diff --git a/.decidim-version b/.decidim-version index 12a91df0e0b30..3edc695dcea5c 100644 --- a/.decidim-version +++ b/.decidim-version @@ -1 +1 @@ -0.26.4 +0.27.2 diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000000..811628826f16e --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ + +open_collective: decidim diff --git a/.github/actions/module-rspec/action.yml b/.github/actions/module-rspec/action.yml index 2ad1e16db6896..bdc49b056afbb 100644 --- a/.github/actions/module-rspec/action.yml +++ b/.github/actions/module-rspec/action.yml @@ -7,14 +7,18 @@ inputs: github_token: description: 'Github token' required: true - ruby-version: + ruby_version: description: 'Ruby Version' - default: "2.7.5" + default: "3.0.2" required: false - node-version: + node_version: description: 'Node version' default: '16.9.1' required: false + processor_count: + description: "Number or parallel jobs to run" + default: "4" + required: false runs: using: "composite" @@ -25,11 +29,11 @@ runs: GITHUB_TOKEN: " ${{ inputs.github_token }}" - uses: ruby/setup-ruby@v1 with: - ruby-version: ${{ inputs.ruby-version }} + ruby-version: ${{ inputs.ruby_version }} bundler-cache: true - uses: actions/setup-node@v1 with: - node-version: ${{ inputs.node-version }} + node-version: ${{ inputs.node_version }} - name: Get npm cache directory path id: npm-cache-dir-path run: echo "::set-output name=dir::$(npm get cache)-${{ inputs.name }}" @@ -56,3 +60,9 @@ runs: name: Scanning Security issues on module working-directory: ${{ inputs.name }} shell: "bash" + - run: bundle exec rake parallel:create parallel:migrate + name: Parallel tests + shell: "bash" + working-directory: ./spec/decidim_dummy_app/ + env: + PARALLEL_TEST_PROCESSORS: " ${{ inputs.processor_count }}" diff --git a/.github/config.yml b/.github/config.yml new file mode 100644 index 0000000000000..cf7b595d5a5b9 --- /dev/null +++ b/.github/config.yml @@ -0,0 +1,14 @@ +# Configuration for request-info - https://github.com/behaviorbot/request-info +# +requestInfoReplyComment: > + It seems like you didn't give us much information about what you're trying to do here. + We would appreciate it if you could provide us with more info about this issue/PR! + +checkIssueTemplate: true + +checkPullRequestTemplate: true + +requestInfoOn: + pullRequest: true + issue: true + diff --git a/.github/stale.yml b/.github/stale.yml index d93c65225aa99..add96c6074f9d 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,7 +1,7 @@ # Number of days of inactivity before an issue becomes stale daysUntilStale: 60 # Number of days of inactivity before a stale issue is closed -daysUntilClose: 7 +daysUntilClose: false # Ignore issues in a project exemptProjects: true # Ignore issues in a milestone @@ -14,8 +14,12 @@ exemptLabels: - "type: bug" # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. @carolromero & @andreslucena feel free to chime in. + Thank you for your contribution. This issue has been automatically marked + as stale because it has not had recent activity. + + Is this still relevant? If so, what is blocking it? Is there anything you + can do to help move it forward? + + @carolromero & @andreslucena feel free to chime in. # Comment to post when closing a stale issue. Set to `false` to disable closeComment: false diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 9b735bb9a522e..7570018e38779 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -20,7 +20,7 @@ Individual workflows with changes: working-directory: ${{ env.DECIDIM_MODULE }} ``` -- `ci_comments.yml`: Runs tests for the JS files. Tests must run from the project root folder. You'll need to install NodeJS and the JS dependencies: +- `ci_javascript.yml`: Runs tests for the JS files. Tests must run from the project root folder. You'll need to install NodeJS and the JS dependencies: ```yml - uses: actions/setup-node@master @@ -32,8 +32,15 @@ Individual workflows with changes: name: Test JS files ``` -- Proposals specs are split in three workflows: +- Some specs are split in three workflows, so if we need to retry this particular workflow we don't need to retry all the module suite. For instance proposals: - `ci_proposals_system_admin.yml`: Runs the system specs for the admin section - `ci_proposals_system_public.yml`: Runs the system specs for the public section - `ci_proposals_unit_tests.yml`: Runs the unit tests + +- `ci_performance_metrics_monitoring.yml`: Runs Lighthouse metrics expectations against the app to detect any performance regression. The expectations can be found in `lighthouse_budget.json`, where a time is defined for each metric: + + - [First Contentful Paint](https://web.dev/first-contentful-paint/): 2 seconds + - [Speed Index](https://web.dev/speed-index/): 4 seconds + - [Time to Interactive](https://web.dev/interactive/): 5 seconds + - [Largest Contentful Paint](https://web.dev/lcp/): 2.5 seconds diff --git a/.github/workflows/ci_accountability.yml b/.github/workflows/ci_accountability.yml index 5b9916af2b891..ce4c56daedd8e 100644 --- a/.github/workflows/ci_accountability.yml +++ b/.github/workflows/ci_accountability.yml @@ -23,9 +23,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-accountability + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -61,7 +62,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_admin.yml b/.github/workflows/ci_admin.yml index 2851d6f87c63c..c9b344e1fe998 100644 --- a/.github/workflows/ci_admin.yml +++ b/.github/workflows/ci_admin.yml @@ -18,9 +18,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-admin + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -52,7 +53,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec --exclude-pattern 'spec/system/**/*_spec.rb' + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec['spec\/(?!system)'] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_admin_system_1.yml b/.github/workflows/ci_admin_system.yml similarity index 85% rename from .github/workflows/ci_admin_system_1.yml rename to .github/workflows/ci_admin_system.yml index 260b6342b38b3..5c5a1cd14b10d 100644 --- a/.github/workflows/ci_admin_system_1.yml +++ b/.github/workflows/ci_admin_system.yml @@ -1,4 +1,4 @@ -name: "[CI] Admin (system tests 1)" +name: "[CI] Admin (system tests)" on: push: branches: @@ -18,9 +18,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-admin + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -56,11 +57,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: | - count=$(ls spec/system/*_spec.rb | wc -l | tr -d ' ') - half=$(expr $count / 2) - list_of_files=$(ls spec/system/*_spec.rb | sed -n "1,$(echo $half)p" | xargs) - bundle exec rspec $list_of_files + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec[^spec/system] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_api.yml b/.github/workflows/ci_api.yml index b74bc376cba6d..5ce7bf4506d06 100644 --- a/.github/workflows/ci_api.yml +++ b/.github/workflows/ci_api.yml @@ -19,9 +19,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-api + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -53,7 +54,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_assemblies.yml b/.github/workflows/ci_assemblies.yml index 2b1cfdebcf777..4c7c8a0defbba 100644 --- a/.github/workflows/ci_assemblies.yml +++ b/.github/workflows/ci_assemblies.yml @@ -18,9 +18,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-assemblies + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -56,7 +57,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_blogs.yml b/.github/workflows/ci_blogs.yml index 325afedc45462..3930887bded1e 100644 --- a/.github/workflows/ci_blogs.yml +++ b/.github/workflows/ci_blogs.yml @@ -21,9 +21,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-blogs + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -59,7 +60,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_budgets.yml b/.github/workflows/ci_budgets.yml index d42cb042f9bf9..ec5ac83370458 100644 --- a/.github/workflows/ci_budgets.yml +++ b/.github/workflows/ci_budgets.yml @@ -20,9 +20,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-budgets + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -58,7 +59,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_comments.yml b/.github/workflows/ci_comments.yml index cae48432a1f4c..9a50851a1a397 100644 --- a/.github/workflows/ci_comments.yml +++ b/.github/workflows/ci_comments.yml @@ -18,9 +18,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-comments + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -56,7 +57,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_conferences.yml b/.github/workflows/ci_conferences.yml index d424f7220c616..4fc4e87865af8 100644 --- a/.github/workflows/ci_conferences.yml +++ b/.github/workflows/ci_conferences.yml @@ -19,9 +19,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-conferences + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -57,7 +58,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_consultations.yml b/.github/workflows/ci_consultations.yml index 4824fc15a8f5b..001d35e9bd129 100644 --- a/.github/workflows/ci_consultations.yml +++ b/.github/workflows/ci_consultations.yml @@ -19,9 +19,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-consultations + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -57,7 +58,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_core_lib.yml b/.github/workflows/ci_core_lib.yml index f2b5e5766eab0..869e961e4676c 100644 --- a/.github/workflows/ci_core_lib.yml +++ b/.github/workflows/ci_core_lib.yml @@ -14,12 +14,14 @@ on: - "decidim-api/**" - "decidim-core/**" - "decidim-dev/**" + - "packages/**" env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-core + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -51,7 +53,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec spec/lib + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec[^spec/lib] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_core_system.yml b/.github/workflows/ci_core_system.yml index 7f8a56f6bb8d0..28d20e6d3fedf 100644 --- a/.github/workflows/ci_core_system.yml +++ b/.github/workflows/ci_core_system.yml @@ -17,9 +17,11 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-core + PARALLEL_TEST_PROCESSORS: 2 + DECIDIM_SERVICE_WORKER_ENABLED: true jobs: main: @@ -55,11 +57,17 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec spec/system + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: | + sudo Xvfb -ac $DISPLAY -screen 0 1920x1084x24 > /dev/null 2>&1 & # optional + bundle exec rake parallel:spec[^spec/system] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: SIMPLECOV: "true" + DISPLAY: ":99" - run: ./.github/upload_coverage.sh $DECIDIM_MODULE $GITHUB_EVENT_PATH name: Upload coverage - uses: actions/upload-artifact@v2 diff --git a/.github/workflows/ci_admin_system_2.yml b/.github/workflows/ci_core_system_ssl.yml similarity index 68% rename from .github/workflows/ci_admin_system_2.yml rename to .github/workflows/ci_core_system_ssl.yml index 4fea30c920bee..e466f1c2ef91b 100644 --- a/.github/workflows/ci_admin_system_2.yml +++ b/.github/workflows/ci_core_system_ssl.yml @@ -1,4 +1,4 @@ -name: "[CI] Admin (system tests 2)" +name: "[CI] Core (system specs SSL)" on: push: branches: @@ -11,16 +11,17 @@ on: paths: - "*" - ".github/**" - - "decidim-admin/**" - "decidim-core/**" - "decidim-dev/**" - - "decidim-participatory_processes/**" env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 - DECIDIM_MODULE: decidim-admin + DECIDIM_MODULE: decidim-core + PARALLEL_TEST_PROCESSORS: 2 + DECIDIM_SERVICE_WORKER_ENABLED: true + TEST_SSL: true jobs: main: @@ -39,11 +40,15 @@ jobs: --health-retries 5 env: POSTGRES_PASSWORD: postgres + validator: + image: ghcr.io/validator/validator:latest + ports: ["8888:8888"] env: DATABASE_USERNAME: postgres DATABASE_PASSWORD: postgres DATABASE_HOST: localhost RUBYOPT: '-W:no-deprecated' + VALIDATOR_HTML_URI: http://localhost:8888/ steps: - uses: actions/checkout@v2.0.0 with: @@ -52,15 +57,17 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} - run: | - count=$(ls spec/system/*_spec.rb | wc -l | tr -d ' ') - half=$(expr $count / 2) - list_of_files=$(ls spec/system/*_spec.rb | sed -n "$(expr $half + 1), $(echo $count)p" | xargs) - bundle exec rspec $list_of_files + sudo Xvfb -ac $DISPLAY -screen 0 1920x1084x24 > /dev/null 2>&1 & # optional + bundle exec rake parallel:spec[spec/system/data_consent/organization_spec.rb] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: SIMPLECOV: "true" + DISPLAY: ":99" - run: ./.github/upload_coverage.sh $DECIDIM_MODULE $GITHUB_EVENT_PATH name: Upload coverage - uses: actions/upload-artifact@v2 diff --git a/.github/workflows/ci_core_unit.yml b/.github/workflows/ci_core_unit.yml index 6364021bb915d..d194825824ecf 100644 --- a/.github/workflows/ci_core_unit.yml +++ b/.github/workflows/ci_core_unit.yml @@ -17,9 +17,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-core + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -51,7 +52,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec --exclude-pattern 'spec/{system,lib}/**/*_spec.rb' + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec['spec\/(?!(system|lib))'] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_debates.yml b/.github/workflows/ci_debates.yml index 2e68aa6acae7b..3809e47a53f95 100644 --- a/.github/workflows/ci_debates.yml +++ b/.github/workflows/ci_debates.yml @@ -19,9 +19,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-debates + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -57,7 +58,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_dev_system.yml b/.github/workflows/ci_dev_system.yml index 9b63b096d3bc0..7b3071bf22c6a 100644 --- a/.github/workflows/ci_dev_system.yml +++ b/.github/workflows/ci_dev_system.yml @@ -16,9 +16,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-dev + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -50,6 +51,9 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} - run: bundle exec rspec spec/system name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} diff --git a/.github/workflows/ci_elections_system_admin_1.yml b/.github/workflows/ci_elections_system_admin.yml similarity index 89% rename from .github/workflows/ci_elections_system_admin_1.yml rename to .github/workflows/ci_elections_system_admin.yml index db42892332694..8b52f892a4769 100644 --- a/.github/workflows/ci_elections_system_admin_1.yml +++ b/.github/workflows/ci_elections_system_admin.yml @@ -1,4 +1,4 @@ -name: "[CI] Elections (system admin 1)" +name: "[CI] Elections (system admin)" on: push: branches: @@ -21,9 +21,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-elections + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -46,7 +47,7 @@ jobs: image: ghcr.io/validator/validator:latest ports: ["8888:8888"] bulletin_board: - image: codegram/decidim-bulletin-board:0.22.3 + image: decidim/decidim-bulletin-board:0.23.0 ports: ["8000:8000"] env: DATABASE_URL: postgresql://postgres:postgres@postgres/bb @@ -71,11 +72,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: | - count=$(ls spec/system/admin/*_spec.rb | wc -l | tr -d ' ') - half=$(expr $count / 2) - list_of_files=$(ls spec/system/admin/*_spec.rb | sed -n "1,$(echo $half)p" | xargs) - bundle exec rspec $list_of_files + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec[^spec/system/admin] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_elections_system_admin_2.yml b/.github/workflows/ci_elections_system_admin_2.yml deleted file mode 100644 index 9e00e1479709f..0000000000000 --- a/.github/workflows/ci_elections_system_admin_2.yml +++ /dev/null @@ -1,86 +0,0 @@ -name: "[CI] Elections (system admin 2)" -on: - push: - branches: - - develop - - release/* - - "*-stable" - pull_request: - branches-ignore: - - "chore/l10n*" - paths: - - "*" - - ".github/**" - - "decidim-admin/**" - - "decidim-bulletin_board/**" - - "decidim-core/**" - - "decidim-dev/**" - - "decidim-elections/**" - - "decidim-forms/**" - - "decidim-proposals/**" - -env: - CI: "true" - RUBY_VERSION: 2.7.5 - NODE_VERSION: 16.9.1 - DECIDIM_MODULE: decidim-elections - -jobs: - main: - name: Tests - runs-on: ubuntu-latest - if: "!startsWith(github.head_ref, 'chore/l10n')" - timeout-minutes: 60 - services: - postgres: - image: postgres:11 - ports: ["5432:5432"] - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - env: - POSTGRES_PASSWORD: postgres - bulletin_board: - image: codegram/decidim-bulletin-board:0.22.3 - ports: ["8000:8000"] - env: - DATABASE_URL: postgresql://postgres:postgres@postgres/bb - RAILS_ENV: test - SEED: 1 - IDENTIFICATION_PRIVATE_KEY: '{"kty":"RSA","n":"zMXsZpYPKkDlSmezX898y7zNOaJ7ENIN4kj4UhQ95Vm4HlgTpIs2VMMsO0eqynMaOR_G1mXdqbpbaJtXijBe4V8323QwGm6WVAa71E7pDXa5g6-uo5f8GePitN0YER9y2yNQN4uTaNzJiWV2uLBUYfMdj3SIif31YwLULHAOj3B_oleFK8coE_Qr3NzATcYBmsqE8AR4NljxTO6KDmP1SLdf5GBOBhOAIFbnL_Kpj2xkm7MS3hjMVKpiRhqA1UgX5oKZ8ixBv46fNJF0pBsHi3fHNjK9oZzgdx_AI-YFpdE_40-8bh_g9sWzxacqOM2-MdQLHbvRPEVltO3E8tr6I5YWrylcP7l9VD8OJeqjq2qFYHnGYdmLoD2XuXmI9EuBvSb9H4-qcartxZSIQCimKib_fxZvgrG1FSRRhK6YpvIdGv4-G2zfCCRsC4XD80TYI2bf-oYCoy7eU3_eVHFMV2yg4p1Wnuw2Vgq0edPL_bKaV9JvGx7F-U5juxNN0WZR9LzbPl4ReejzN95lyHgbj0nTH_u3bSpZmgJrQF-PwdnPcG46deVjJgUeosrlC4lQxVrRz0GL58BuFunnz2uYDBDrcJCiG60EbdkAFHjOcXU4wrUWATin7je_aqdBXhSnkTafcJAMvL7Y2Ld7vDge8nLqjAVlAi5am3rN0kqKT6M","e":"AQAB","kid":"a8e86f02ca27e1861bfc49e2a9a4614ca9068f8efdb6d42d19d3aab0eb2a31be"}' - DISABLE_DATABASE_ENVIRONMENT_CHECK: 1 - RAILS_SERVE_STATIC_FILES: enabled - DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL: true - env: - DATABASE_USERNAME: postgres - DATABASE_PASSWORD: postgres - DATABASE_HOST: localhost - RUBYOPT: "-W:no-deprecated" - ELECTIONS_BULLETIN_BOARD_SERVER: http://localhost:8000/api - steps: - - uses: actions/checkout@v2.0.0 - with: - fetch-depth: 1 - - uses: ./.github/actions/module-rspec - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - name: ${{ env.DECIDIM_MODULE }} - - run: | - count=$(ls spec/system/admin/*_spec.rb | wc -l | tr -d ' ') - half=$(expr $count / 2) - list_of_files=$(ls spec/system/admin/*_spec.rb | sed -n "$(expr $half + 1), $(echo $count)p" | xargs) - bundle exec rspec $list_of_files - name: RSpec - working-directory: ${{ env.DECIDIM_MODULE }} - env: - SIMPLECOV: "true" - - run: ./.github/upload_coverage.sh decidim-elections-system-admin $GITHUB_EVENT_PATH - name: Upload coverage - - uses: actions/upload-artifact@v2 - if: always() - with: - name: screenshots - path: ./spec/decidim_dummy_app/tmp/screenshots - if-no-files-found: ignore diff --git a/.github/workflows/ci_elections_system_public.yml b/.github/workflows/ci_elections_system_public.yml index b3ee2724f3c2f..428ff0300d953 100644 --- a/.github/workflows/ci_elections_system_public.yml +++ b/.github/workflows/ci_elections_system_public.yml @@ -21,9 +21,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-elections + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -46,7 +47,7 @@ jobs: image: ghcr.io/validator/validator:latest ports: ["8888:8888"] bulletin_board: - image: codegram/decidim-bulletin-board:0.22.3 + image: decidim/decidim-bulletin-board:0.23.0 ports: ["8000:8000"] env: DATABASE_URL: postgresql://postgres:postgres@postgres/bb @@ -71,6 +72,9 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} - run: bundle exec rspec spec/system/ --exclude-pattern 'spec/system/admin/**/*_spec.rb' name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} diff --git a/.github/workflows/ci_elections_unit_tests.yml b/.github/workflows/ci_elections_unit_tests.yml index fc10cc94236d9..aefa45bb7d55e 100644 --- a/.github/workflows/ci_elections_unit_tests.yml +++ b/.github/workflows/ci_elections_unit_tests.yml @@ -21,9 +21,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-elections + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -43,7 +44,7 @@ jobs: env: POSTGRES_PASSWORD: postgres bulletin_board: - image: codegram/decidim-bulletin-board:0.22.3 + image: decidim/decidim-bulletin-board:0.23.0 ports: ["8000:8000"] env: DATABASE_URL: postgresql://postgres:postgres@postgres/bb @@ -67,7 +68,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec --exclude-pattern 'spec/system/**/*_spec.rb' + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec['spec\/(?!system)'] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_forms.yml b/.github/workflows/ci_forms.yml index 607012f7d2e02..7cbd8187ea0a4 100644 --- a/.github/workflows/ci_forms.yml +++ b/.github/workflows/ci_forms.yml @@ -18,9 +18,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-forms + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -52,7 +53,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_generators.yml b/.github/workflows/ci_generators.yml index ce4a8c3ba456b..7a95dd99803e8 100644 --- a/.github/workflows/ci_generators.yml +++ b/.github/workflows/ci_generators.yml @@ -16,9 +16,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-generators + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -73,7 +74,7 @@ jobs: - run: bundle exec brakeman --rails6 --force-scan . name: Scanning Security issues on module working-directory: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_initiatives.yml b/.github/workflows/ci_initiatives.yml index 2280c67b736ab..0a33a016e7af2 100644 --- a/.github/workflows/ci_initiatives.yml +++ b/.github/workflows/ci_initiatives.yml @@ -20,9 +20,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-initiatives + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -54,7 +55,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec --exclude-pattern 'spec/system/**/*_spec.rb' + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec['spec\/(?!system)'] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_initiatives_system_admin.yml b/.github/workflows/ci_initiatives_system_admin.yml index 53c81faafdbcb..abe78ea7534e3 100644 --- a/.github/workflows/ci_initiatives_system_admin.yml +++ b/.github/workflows/ci_initiatives_system_admin.yml @@ -20,9 +20,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-initiatives + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -58,7 +59,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec spec/system/admin + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec[^spec/system/admin] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_initiatives_system_public.yml b/.github/workflows/ci_initiatives_system_public.yml index e0a6648b2259a..85a253035ee00 100644 --- a/.github/workflows/ci_initiatives_system_public.yml +++ b/.github/workflows/ci_initiatives_system_public.yml @@ -20,9 +20,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-initiatives + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -58,7 +59,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec spec/system/ --exclude-pattern 'spec/system/admin/**/*_spec.rb' + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec['spec\/system\/(?!admin)'] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_javascript.yml b/.github/workflows/ci_javascript.yml new file mode 100644 index 0000000000000..ae91bcfe1561b --- /dev/null +++ b/.github/workflows/ci_javascript.yml @@ -0,0 +1,54 @@ +name: "[CI] Javascript" +on: + push: + branches: + - develop + - release/* + - "*-stable" + pull_request: + branches-ignore: + - "chore/l10n*" + paths: + - "*" + - ".github/**" + - "decidim-admin/**" + - "decidim-comments/**" + - "decidim-core/**" + - "decidim-dev/**" + +env: + CI: "true" + NODE_VERSION: 16.9.1 + +jobs: + main: + name: Tests + runs-on: ubuntu-20.04 + if: "!startsWith(github.head_ref, 'chore/l10n')" + timeout-minutes: 60 + steps: + - uses: rokroskar/workflow-run-cleanup-action@v0.3.3 + if: "github.ref != 'refs/heads/develop'" + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + - uses: actions/checkout@v2.0.0 + with: + fetch-depth: 1 + - uses: actions/setup-node@v1 + with: + node-version: ${{ env.NODE_VERSION }} + - name: Get npm cache directory path + id: npm-cache-dir-path + run: echo "::set-output name=dir::$(npm get cache)-javascript" + - uses: actions/cache@v2 + id: npm-cache + with: + path: ${{ steps.npm-cache-dir-path.outputs.dir }} + key: npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + npm- + - name: Install JS dependencies + run: npm ci + - run: npm run test + name: Test JS files + diff --git a/.github/workflows/ci_main.yml b/.github/workflows/ci_main.yml index 36ef1772f1fe8..89ea508233caa 100644 --- a/.github/workflows/ci_main.yml +++ b/.github/workflows/ci_main.yml @@ -11,7 +11,7 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 jobs: diff --git a/.github/workflows/ci_meetings_system_admin.yml b/.github/workflows/ci_meetings_system_admin.yml index 11ba9ff9f01c9..fa7ddb061574c 100644 --- a/.github/workflows/ci_meetings_system_admin.yml +++ b/.github/workflows/ci_meetings_system_admin.yml @@ -21,9 +21,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-meetings + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -59,7 +60,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec spec/system/admin + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec[^spec/system/admin] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_meetings_system_public_1.yml b/.github/workflows/ci_meetings_system_public.yml similarity index 85% rename from .github/workflows/ci_meetings_system_public_1.yml rename to .github/workflows/ci_meetings_system_public.yml index ba7aaf643db14..b9467b576bca5 100644 --- a/.github/workflows/ci_meetings_system_public_1.yml +++ b/.github/workflows/ci_meetings_system_public.yml @@ -1,4 +1,4 @@ -name: "[CI] Meetings (system public 1)" +name: "[CI] Meetings (system public)" on: push: branches: @@ -21,9 +21,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-meetings + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -59,11 +60,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: | - count=$(ls spec/system/*_spec.rb | wc -l | tr -d ' ') - half=$(expr $count / 2) - list_of_files=$(ls spec/system/*_spec.rb | sed -n "1,$(echo $half)p" | xargs) - bundle exec rspec $list_of_files + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec['spec\/system\/(?!admin)'] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_meetings_system_public_2.yml b/.github/workflows/ci_meetings_system_public_2.yml deleted file mode 100644 index 3e7e08bfa6007..0000000000000 --- a/.github/workflows/ci_meetings_system_public_2.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: "[CI] Meetings (system public 2)" -on: - push: - branches: - - develop - - release/* - - "*-stable" - pull_request: - branches-ignore: - - "chore/l10n*" - paths: - - "*" - - ".github/**" - - "decidim-admin/**" - - "decidim-assemblies/**" - - "decidim-core/**" - - "decidim-dev/**" - - "decidim-forms/**" - - "decidim-meetings/**" - - "decidim-participatory_processes/**" - -env: - CI: "true" - RUBY_VERSION: 2.7.5 - NODE_VERSION: 16.9.1 - DECIDIM_MODULE: decidim-meetings - -jobs: - main: - name: Tests - runs-on: ubuntu-latest - if: "!startsWith(github.head_ref, 'chore/l10n')" - timeout-minutes: 60 - services: - postgres: - image: postgres:11 - ports: ["5432:5432"] - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - env: - POSTGRES_PASSWORD: postgres - env: - DATABASE_USERNAME: postgres - DATABASE_PASSWORD: postgres - DATABASE_HOST: localhost - RUBYOPT: '-W:no-deprecated' - steps: - - uses: actions/checkout@v2.0.0 - with: - fetch-depth: 1 - - uses: ./.github/actions/module-rspec - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - name: ${{ env.DECIDIM_MODULE }} - - run: | - count=$(ls spec/system/*_spec.rb | wc -l | tr -d ' ') - half=$(expr $count / 2) - list_of_files=$(ls spec/system/*_spec.rb | sed -n "$(expr $half + 1), $(echo $count)p" | xargs) - bundle exec rspec $list_of_files - name: RSpec - working-directory: ${{ env.DECIDIM_MODULE }} - env: - SIMPLECOV: "true" - - run: ./.github/upload_coverage.sh decidim-meetings-system-public $GITHUB_EVENT_PATH - name: Upload coverage - - uses: actions/upload-artifact@v2 - if: always() - with: - name: screenshots - path: ./spec/decidim_dummy_app/tmp/screenshots - if-no-files-found: ignore diff --git a/.github/workflows/ci_meetings_unit_tests.yml b/.github/workflows/ci_meetings_unit_tests.yml index 65223a0fb1712..4d28ca30f931e 100644 --- a/.github/workflows/ci_meetings_unit_tests.yml +++ b/.github/workflows/ci_meetings_unit_tests.yml @@ -21,9 +21,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-meetings + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -55,7 +56,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec --exclude-pattern 'spec/system/**/*_spec.rb' + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec['spec\/(?!system)'] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_pages.yml b/.github/workflows/ci_pages.yml index dfe045b831392..9ebd6919d9ee8 100644 --- a/.github/workflows/ci_pages.yml +++ b/.github/workflows/ci_pages.yml @@ -18,9 +18,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-pages + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -56,7 +57,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_participatory_processes.yml b/.github/workflows/ci_participatory_processes.yml index c7fb39309078c..8ef0118a59292 100644 --- a/.github/workflows/ci_participatory_processes.yml +++ b/.github/workflows/ci_participatory_processes.yml @@ -19,9 +19,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-participatory_processes + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -57,7 +58,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_performance_metrics_monitoring.yml b/.github/workflows/ci_performance_metrics_monitoring.yml new file mode 100644 index 0000000000000..98903e6363f80 --- /dev/null +++ b/.github/workflows/ci_performance_metrics_monitoring.yml @@ -0,0 +1,92 @@ +name: "[CI] Performance Metrics monitoring" +on: + push: + branches: + - develop + - release/* + - "*-stable" + pull_request: + branches-ignore: + - "chore/l10n*" + paths: + - "*" + - ".github/**" + - "decidim-api/**" + - "decidim-core/**" + - "decidim-dev/**" + +env: + CI: "true" + SIMPLECOV: "true" + RUBY_VERSION: 3.0.2 + NODE_VERSION: 16.9.1 + RAILS_ENV: development + +jobs: + main: + name: Tests + runs-on: ubuntu-20.04 + if: "!startsWith(github.head_ref, 'chore/l10n')" + timeout-minutes: 60 + services: + postgres: + image: postgres:11 + ports: ["5432:5432"] + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + env: + POSTGRES_PASSWORD: postgres + env: + DATABASE_USERNAME: postgres + DATABASE_PASSWORD: postgres + DATABASE_HOST: localhost + RUBYOPT: '-W:no-deprecated' + steps: + - uses: rokroskar/workflow-run-cleanup-action@v0.3.3 + if: "github.ref != 'refs/heads/develop'" + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + - 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@v1 + with: + node-version: ${{ env.NODE_VERSION }} + - name: Get npm cache directory path + id: npm-cache-dir-path + run: echo "::set-output name=dir::$(npm get cache)-${{ env.DECIDIM_MODULE }}" + - uses: actions/cache@v2 + id: npm-cache + with: + path: ${{ steps.npm-cache-dir-path.outputs.dir }} + key: npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + npm- + - run: bundle exec rake development_app + name: Create development app + - run: bundle exec rails assets:precompile + name: Precompile assets + working-directory: ./development_app/ + - run: bundle exec rails decidim:lighthouse:prepare_urls + name: Setup lighthouse urls + working-directory: ./development_app/ + - run: bundle exec rails dev:cache + name: Activate Rails cache + working-directory: ./development_app/ + - run: bundle exec rails server -b localhost -d + name: Run Rails server + working-directory: ./development_app/ + - name: Audit URLs using Lighthouse + uses: treosh/lighthouse-ci-action@v8 + with: + runs: 3 # run more than once to warm up the application + uploadArtifacts: true + budgetPath: ./.github/workflows/lighthouse_budget.json # test performance budgets + temporaryPublicStorage: true diff --git a/.github/workflows/ci_proposals_system_admin.yml b/.github/workflows/ci_proposals_system_admin.yml index 50717bb43a7a6..064b6a3353598 100644 --- a/.github/workflows/ci_proposals_system_admin.yml +++ b/.github/workflows/ci_proposals_system_admin.yml @@ -23,9 +23,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-proposals + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -61,7 +62,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec spec/system/admin + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec[^spec/system/admin] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_proposals_system_public_1.yml b/.github/workflows/ci_proposals_system_public.yml similarity index 85% rename from .github/workflows/ci_proposals_system_public_1.yml rename to .github/workflows/ci_proposals_system_public.yml index d551f91fe0186..791cc31a09355 100644 --- a/.github/workflows/ci_proposals_system_public_1.yml +++ b/.github/workflows/ci_proposals_system_public.yml @@ -1,4 +1,4 @@ -name: "[CI] Proposals (system public 1)" +name: "[CI] Proposals (system public)" on: push: branches: @@ -23,9 +23,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-proposals + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -61,11 +62,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: | - count=$(ls spec/system/*_spec.rb | wc -l | tr -d ' ') - half=$(expr $count / 2) - list_of_files=$(ls spec/system/*_spec.rb | sed -n "1,$(echo $half)p" | xargs) - bundle exec rspec $list_of_files + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec['spec\/system\/(?!admin)'] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_proposals_system_public_2.yml b/.github/workflows/ci_proposals_system_public_2.yml deleted file mode 100644 index 616d06902c8b0..0000000000000 --- a/.github/workflows/ci_proposals_system_public_2.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: "[CI] Proposals (system public2)" -on: - push: - branches: - - develop - - release/* - - "*-stable" - pull_request: - branches-ignore: - - "chore/l10n*" - paths: - - "*" - - ".github/**" - - "decidim-admin/**" - - "decidim-assemblies/**" - - "decidim-budgets/**" - - "decidim-comments/**" - - "decidim-core/**" - - "decidim-dev/**" - - "decidim-meetings/**" - - "decidim-participatory_processes/**" - - "decidim-proposals/**" - -env: - CI: "true" - RUBY_VERSION: 2.7.5 - NODE_VERSION: 16.9.1 - DECIDIM_MODULE: decidim-proposals - -jobs: - main: - name: Tests - runs-on: ubuntu-latest - if: "!startsWith(github.head_ref, 'chore/l10n')" - timeout-minutes: 60 - services: - postgres: - image: postgres:11 - ports: ["5432:5432"] - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - env: - POSTGRES_PASSWORD: postgres - env: - DATABASE_USERNAME: postgres - DATABASE_PASSWORD: postgres - DATABASE_HOST: localhost - RUBYOPT: '-W:no-deprecated' - steps: - - uses: actions/checkout@v2.0.0 - with: - fetch-depth: 1 - - uses: ./.github/actions/module-rspec - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - name: ${{ env.DECIDIM_MODULE }} - - run: | - count=$(ls spec/system/*_spec.rb | wc -l | tr -d ' ') - half=$(expr $count / 2) - list_of_files=$(ls spec/system/*_spec.rb | sed -n "$(expr $half + 1), $(echo $count)p" | xargs) - bundle exec rspec $list_of_files - name: RSpec - working-directory: ${{ env.DECIDIM_MODULE }} - env: - SIMPLECOV: "true" - - run: ./.github/upload_coverage.sh decidim-proposals-system-public $GITHUB_EVENT_PATH - name: Upload coverage - - uses: actions/upload-artifact@v2 - if: always() - with: - name: screenshots - path: ./spec/decidim_dummy_app/tmp/screenshots - if-no-files-found: ignore diff --git a/.github/workflows/ci_proposals_unit_tests.yml b/.github/workflows/ci_proposals_unit_tests.yml index 31cc0d03148cb..486cd74810bce 100644 --- a/.github/workflows/ci_proposals_unit_tests.yml +++ b/.github/workflows/ci_proposals_unit_tests.yml @@ -23,9 +23,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-proposals + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -57,7 +58,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec --exclude-pattern 'spec/system/**/*_spec.rb' + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec['spec\/(?!system)'] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_sortitions.yml b/.github/workflows/ci_sortitions.yml index d3723609188fb..3442e204f1e02 100644 --- a/.github/workflows/ci_sortitions.yml +++ b/.github/workflows/ci_sortitions.yml @@ -20,9 +20,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-sortitions + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -58,7 +59,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_surveys.yml b/.github/workflows/ci_surveys.yml index 17f34a2303087..21114ded733bc 100644 --- a/.github/workflows/ci_surveys.yml +++ b/.github/workflows/ci_surveys.yml @@ -21,9 +21,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-surveys + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -59,7 +60,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_system.yml b/.github/workflows/ci_system.yml index e4b464a31a492..947eecbd38ec7 100644 --- a/.github/workflows/ci_system.yml +++ b/.github/workflows/ci_system.yml @@ -17,9 +17,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-system + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -55,7 +56,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_templates.yml b/.github/workflows/ci_templates.yml index c8dd390a95df8..2f8b43b17185a 100644 --- a/.github/workflows/ci_templates.yml +++ b/.github/workflows/ci_templates.yml @@ -20,9 +20,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-templates + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -58,7 +59,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_verifications.yml b/.github/workflows/ci_verifications.yml index a62bc1b42b7df..b0baf13a49cbb 100644 --- a/.github/workflows/ci_verifications.yml +++ b/.github/workflows/ci_verifications.yml @@ -18,9 +18,10 @@ on: env: CI: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-verifications + PARALLEL_TEST_PROCESSORS: 2 jobs: main: @@ -56,7 +57,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} name: ${{ env.DECIDIM_MODULE }} - - run: bundle exec rspec + processor_count: ${{ env.PARALLEL_TEST_PROCESSORS }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/lighthouse_budget.json b/.github/workflows/lighthouse_budget.json new file mode 100644 index 0000000000000..1c67544218853 --- /dev/null +++ b/.github/workflows/lighthouse_budget.json @@ -0,0 +1,23 @@ +[ + { + "path": "/*", + "timings": [ + { + "metric": "first-contentful-paint", + "budget": 2000 + }, + { + "metric": "speed-index", + "budget": 4000 + }, + { + "metric": "interactive", + "budget": 5000 + }, + { + "metric": "largest-contentful-paint", + "budget": 2500 + } + ] + } +] diff --git a/.github/workflows/lint_code.yml b/.github/workflows/lint_code.yml index 78f4f048bc1b3..eb830c43e247e 100644 --- a/.github/workflows/lint_code.yml +++ b/.github/workflows/lint_code.yml @@ -12,7 +12,7 @@ on: env: CI: "true" SIMPLECOV: "true" - RUBY_VERSION: 2.7.5 + RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 jobs: diff --git a/.gitignore b/.gitignore index 6fead199957f3..f274592e37ce0 100644 --- a/.gitignore +++ b/.gitignore @@ -32,5 +32,7 @@ public/decidim-packs tmp # webpack packs output decidim-packs +# inner package-lock files inside the packages/ folder +packages/**/package-lock.json temporary_changelog.md diff --git a/.lighthouserc.json b/.lighthouserc.json new file mode 100644 index 0000000000000..bff6072848ded --- /dev/null +++ b/.lighthouserc.json @@ -0,0 +1,15 @@ +{ + "_comment": "This configuration is used by .github/workflows/ci_metrics_monitoring.yml workflow", + "ci": { + "collect": { + "_comment": "url is empty because is filled dynamically in CI execution", + "url": [], + "settings": { + "chromeFlags": "--disable-gpu --no-sandbox", + "throttlingMethod": "devtools", + "preset": "desktop" + } + } + } +} + diff --git a/.rubocop-disabled.yml b/.rubocop-disabled.yml new file mode 100644 index 0000000000000..de7949f88de4a --- /dev/null +++ b/.rubocop-disabled.yml @@ -0,0 +1,11 @@ +Style/OpenStructUse: + Enabled: false + +Gemspec/RequireMFA: + Enabled: false + +Naming/MemoizedInstanceVariableName: + Enabled: false + +RSpec/VerifiedDoubleReference: + Enabled: false diff --git a/.rubocop.yml b/.rubocop.yml index 870c0b9fff2d6..0975cd3a003af 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,3 +1,4 @@ inherit_from: - .rubocop_ruby.yml - .rubocop_rails.yml + - .rubocop-disabled.yml diff --git a/.rubocop_ruby.yml b/.rubocop_ruby.yml index 299a4ada0d7d2..657b02344b045 100644 --- a/.rubocop_ruby.yml +++ b/.rubocop_ruby.yml @@ -13,11 +13,13 @@ AllCops: - "**/Gemfile" - "**/Rakefile" Exclude: + - "**/node_modules/**/*" - "**/vendor/**/*" - "development_app/**/*" - "decidim_app-design/node_modules/**/*" - "spec/decidim_dummy_app/**/*" - "node_modules/**/*" + - "decidim-initiatives/lib/gem_overrides/origami/date.rb" # Default formatter will be used if no -f/--format option is given. DefaultFormatter: progress # Cop names are not displayed in offense messages by default. Change behavior @@ -68,12 +70,12 @@ AllCops: # If a value is specified for TargetRubyVersion then it is used. # Else if .ruby-version exists and it contains an MRI version it is used. # Otherwise we fallback to the oldest officially supported Ruby version (2.0). - TargetRubyVersion: 2.7 + TargetRubyVersion: 3.0 - RSpec: - Patterns: - - "(?:^|/)spec/" - - "(?:^|/)test/" +# RSpec: +# Patterns: +# - "(?:^|/)spec/" +# - "(?:^|/)test/" # Indent private/protected/public as deep as method definitions Layout/AccessModifierIndentation: @@ -1269,10 +1271,11 @@ RSpec/NamedSubject: Enabled: false RSpec/RepeatedExampleGroupDescription: - Enabled: false + Enabled: true RSpec/RepeatedExampleGroupBody: - Enabled: false + Enabled: true + RSpec/VerifiedDoubles: Enabled: false diff --git a/.ruby-version b/.ruby-version index a603bb50a29e3..b50214693056f 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.5 +3.0.2 diff --git a/.simplecov b/.simplecov index 76114887f8c90..fbd58ab7f2dd5 100644 --- a/.simplecov +++ b/.simplecov @@ -7,7 +7,7 @@ if ENV["SIMPLECOV"] SimpleCov.start do # `ENGINE_ROOT` holds the name of the engine we're testing. # This brings us to the main Decidim folder. - root File.expand_path("..", ENV["ENGINE_ROOT"]) + root File.expand_path("..", ENV.fetch("ENGINE_ROOT", nil)) # We make sure we track all Ruby files, to avoid skipping unrequired files # We need to include the `../` section, otherwise it only tracks files from the diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d1e730d0c264..c204f5054f504 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,5 @@ # Change Log - -## [Unreleased](https://github.com/decidim/decidim/tree/HEAD) - -Nothing. - -## [0.26.4](https://github.com/decidim/decidim/tree/v0.26.4) +## [0.27.2](https://github.com/decidim/decidim/tree/0.27.2) ### Added @@ -16,60 +11,61 @@ Nothing. ### Fixed -- **decidim-core**: Backport 'Prevent the account edit route through Devise' to v0.26 [\#9932](https://github.com/decidim/decidim/pull/9932) -- **decidim-participatory processes**: Backport 'Fix unpublished processes shown in the group process count' to v0.26 [\#9934](https://github.com/decidim/decidim/pull/9934) -- **decidim-admin**: Backport 'Fix global moderation types not translated' to v0.26 [\#9937](https://github.com/decidim/decidim/pull/9937) -- **decidim-admin**: Backport 'Fix updating organization settings in case there were errors' to v0.26 [\#9938](https://github.com/decidim/decidim/pull/9938) -- **decidim-budgets**, **decidim-core**, **decidim-elections**, **decidim-proposals**: Backport 'Do not import resources multiple times' to v0.26 [\#9942](https://github.com/decidim/decidim/pull/9942) -- **decidim-forms**, **decidim-surveys**: Backport 'Fix form answer attachments breaking the answer view' to v0.26 [\#9945](https://github.com/decidim/decidim/pull/9945) -- **decidim-comments**: Backport 'Fix "disappearing" underscores with comments' to v0.26 [\#9949](https://github.com/decidim/decidim/pull/9949) -- **decidim-admin**, **decidim-core**: Backport 'Fix editor content saving when the content has only one video' to v0.26 [\#9951](https://github.com/decidim/decidim/pull/9951) -- **decidim-proposals**: Backport 'Fix collaborative drafts page when there are errors on the form' to v0.26 [\#9955](https://github.com/decidim/decidim/pull/9955) -- **decidim-debates**: Backport 'Fix the finite value on the debate form when editing an existing debate' to v0.26 [\#9957](https://github.com/decidim/decidim/pull/9957) -- **decidim-pages**: Backport 'Fix exporting and importing a page component' to v0.26 [\#9959](https://github.com/decidim/decidim/pull/9959) -- **decidim-participatory processes**: Backport 'Fix importing participatory process from legacy format' to v0.26 [\#9964](https://github.com/decidim/decidim/pull/9964) -- **decidim-assemblies**, **decidim-core**, **decidim-participatory processes**: Backport 'Fix duplicate stats on home page and participatory space main page' to v0.26 [\#9966](https://github.com/decidim/decidim/pull/9966) -- **decidim-budgets**, **decidim-core**, **decidim-proposals**, **decidim-templates**: Backport 'Address Crowdin feedback' to v0.26 [\#9970](https://github.com/decidim/decidim/pull/9970) -- **decidim-core**: Backport 'Limit invitation redirects only to paths within the application' to v0.26 [\#9973](https://github.com/decidim/decidim/pull/9973) -- **decidim-initiatives**: Backport 'Fix initiative sign if the authorization metadata is set to `nil`' to v0.26 [\#9981](https://github.com/decidim/decidim/pull/9981) -- **decidim-initiatives**: Backport 'Add missing i18n key in Initiatives' to v0.26 [\#9983](https://github.com/decidim/decidim/pull/9983) -- **decidim-core**: Backport 'Fix correct resource linking for amendments' to v0.26 [\#9988](https://github.com/decidim/decidim/pull/9988) -- **decidim-core**: Backport 'Fix user sign up with invalid name' to v0.26 [\#9991](https://github.com/decidim/decidim/pull/9991) -- **decidim-initiatives**: Backport 'Make initiatives order translatable' to v0.26 [\#9995](https://github.com/decidim/decidim/pull/9995) -- **decidim-core**: Backport 'Make ToS agreement translatable' to v0.26 [\#9997](https://github.com/decidim/decidim/pull/9997) -- **decidim-debates**: Backport 'Make Scopes field in debates translatable' to v0.26 [\#9999](https://github.com/decidim/decidim/pull/9999) -- **decidim-core**: Backport 'Remove invitations badge' to v0.26 [\#10001](https://github.com/decidim/decidim/pull/10001) -- **decidim-conferences**: Backport 'Fix conference invitations' to v0.26 [\#10004](https://github.com/decidim/decidim/pull/10004) -- **decidim-admin**, **decidim-core**: Backport 'Fix preserving bold text in the rich text editor when pasting content' to v0.26 [\#9962](https://github.com/decidim/decidim/pull/9962) -- **decidim-admin**, **decidim-assemblies**, **decidim-initiatives**, **decidim-participatory processes**, **decidim-verifications**: Backport 'Add missing active actions on admin navigation menu' to v0.26 [\#9993](https://github.com/decidim/decidim/pull/9993) -- **decidim-core**: Backport 'Fix disappearing sub-lists in rich text editors' to v0.26 [\#9968](https://github.com/decidim/decidim/pull/9968) -- **decidim-elections**: Backport 'Define the component import routes, permissions and controller at votings' to v0.26 [\#9977](https://github.com/decidim/decidim/pull/9977) -- **decidim-core**, **decidim-proposals**: Backport 'Fix proposal etiquette and length validator with base64 images' to v0.26 [\#10010](https://github.com/decidim/decidim/pull/10010) -- **decidim-core**, **decidim-debates**, **decidim-meetings**, **decidim-proposals**: Backport 'Refactor cell titles' to v0.26 [\#10041](https://github.com/decidim/decidim/pull/10041) -- **decidim-admin**, **decidim-comments**: Backport 'Fix moderations for comments that are mapped to deleted resources' to v0.26 [\#9941](https://github.com/decidim/decidim/pull/9941) -- **decidim-comments**, **decidim-core**, **decidim-verifications**: Backport 'Fix user related absolute URLs' to v0.26 [\#9947](https://github.com/decidim/decidim/pull/9947) -- **decidim-core**: Backport 'Fix duplicate user activity records when public spaces have private users' to v0.26 [\#9979](https://github.com/decidim/decidim/pull/9979) -- **decidim-meetings**: Backport 'Refactor the meeting list item title display' to v0.26 [\#10047](https://github.com/decidim/decidim/pull/10047) -- **decidim-accountability**, **decidim-admin**, **decidim-proposals**: Backport 'Reformat CSV help for import files on Accountability and Proposals' to v0.26 [\#10055](https://github.com/decidim/decidim/pull/10055) -- **decidim-system**: Backport 'Fix organization SMTP password not saved (became blank) in system panel' to v0.26 [\#10053](https://github.com/decidim/decidim/pull/10053) -- **decidim-budgets**, **decidim-elections**, **decidim-proposals**, **decidim-sortitions**: Backport 'Fix usages of `reorder` and `paginate`' to v0.26 [\#10051](https://github.com/decidim/decidim/pull/10051) -- **decidim-admin**: Backport 'Show only ToS acceptance when admin hasn't accepted it' to v0.26 [\#10057](https://github.com/decidim/decidim/pull/10057) -- **decidim-debates**, **decidim-meetings**, **decidim-proposals**: Backport 'Refactor admin listing titles' to v0.26 [\#10049](https://github.com/decidim/decidim/pull/10049) -- **decidim-core**: Backport 'Fix date/time formats at component forms' to v0.26 [\#9953](https://github.com/decidim/decidim/pull/9953) +- **decidim-core**: Backport 'Fix: The i18n locales selector is showing a dropdown with 3 languages' to v0.27 [\#10087](https://github.com/decidim/decidim/pull/10087) +- **decidim-core**: Backport 'Remove unecessary line in push notifications spec' to v0.27 [\#10088](https://github.com/decidim/decidim/pull/10088) +- Backport 'Lock GitHub actions to Ubuntu 20.04 due to OpenSSL 3.0 issues' to v0.27 [\#10225](https://github.com/decidim/decidim/pull/10225) +- **decidim-core**: Add date format to Conversation [\#10224](https://github.com/decidim/decidim/pull/10224) +- **decidim-core**: Backport 'Allow blocking a UserGroup' to v0.27 [\#10255](https://github.com/decidim/decidim/pull/10255) +- **decidim-admin**, **decidim-assemblies**, **decidim-elections**, **decidim-initiatives**, **decidim-pages**, **decidim-participatory processes**: Backport 'Fix wrong capitalization in i18n values and add missing keys' to v0.27 [\#10256](https://github.com/decidim/decidim/pull/10256) +- **decidim-api**, **decidim-core**: Backport 'Fix machine translations at the API' to v0.27 [\#10257](https://github.com/decidim/decidim/pull/10257) +- **decidim-budgets**: Backport 'Correct the "voted for this" string in the budgets component' to v0.27 [\#10258](https://github.com/decidim/decidim/pull/10258) +- **decidim-conferences**, **decidim-core**: Backport 'Fix translations missing on admin log' to v0.27 [\#10259](https://github.com/decidim/decidim/pull/10259) +- **decidim-core**: Backport 'Fix push notifications URL method' to v0.27 [\#10262](https://github.com/decidim/decidim/pull/10262) +- **decidim-conferences**: Backport 'Add correct call for conference speaker' to v0.27 [\#10260](https://github.com/decidim/decidim/pull/10260) +- **decidim-meetings**: Backport 'Fix missing fields on duplicate meetings functionality' to v0.27 [\#10261](https://github.com/decidim/decidim/pull/10261) +- **decidim-core**: Backport 'Fix resource_icon with component or manifest nil' to v0.27 [\#10263](https://github.com/decidim/decidim/pull/10263) +- **decidim-budgets**, **decidim-core**, **decidim-debates**, **decidim-meetings**, **decidim-proposals**, **decidim-sortitions**: Backport 'Fix filter URL not updated with the text search input' to v0.27 [\#10264](https://github.com/decidim/decidim/pull/10264) +- **decidim-core**: Backport 'Add missing logs for UserGroup block and unblock actions' to v0.27 [\#10266](https://github.com/decidim/decidim/pull/10266) +- **decidim-admin**, **decidim-core**: Backport 'Don't show the 'unreport' action when user is blocked' to v0.27 [\#10267](https://github.com/decidim/decidim/pull/10267) +- **decidim-admin**, **decidim-core**: Backport 'Fix bug when blocking two UserGroups' to v0.27 [\#10269](https://github.com/decidim/decidim/pull/10269) +- **decidim-core**: Backport 'Add order by in linked_participatory_space_resources' to v0.27 [\#10270](https://github.com/decidim/decidim/pull/10270) +- **decidim-blogs**: Backport 'Move i18n attribute key of Post's body' to v0.27 [\#10265](https://github.com/decidim/decidim/pull/10265) +- **decidim-core**: Backport 'Fix dependency resolver trying to fetch gem paths from lazy specifications' to v0.27 [\#10272](https://github.com/decidim/decidim/pull/10272) +- **decidim-core**: Backport 'Fix double parentheses in the titled upload modal with existing attachment' to v0.27 [\#10273](https://github.com/decidim/decidim/pull/10273) +- **decidim-proposals**: Backport 'Removed "disabled" status from proposals' main categories' to v0.27 [\#10274](https://github.com/decidim/decidim/pull/10274) +- **decidim-core**: Backport 'Improve link handling of the redirect engine' to v0.27 [\#10276](https://github.com/decidim/decidim/pull/10276) +- **decidim-core**: Backport 'Fix pipeline asset absolute URLs' to v0.27 [\#10275](https://github.com/decidim/decidim/pull/10275) +- **decidim-accountability**, **decidim-initiatives**, **decidim-participatory processes**: Backport 'Added missing localizations' to v0.27 [\#10278](https://github.com/decidim/decidim/pull/10278) +- **decidim-blogs**: Backport 'Remove unused permissions on Blogs' to v0.27 [\#10268](https://github.com/decidim/decidim/pull/10268) +- **decidim-initiatives**: Backport 'Respect "rich text editor" setting in Initiatives' to v0.27 [\#10271](https://github.com/decidim/decidim/pull/10271) +- **decidim-proposals**: Backport 'Prevent sending proposal create event until is commited' to v0.27 [\#10279](https://github.com/decidim/decidim/pull/10279) +- **decidim-initiatives**: Backport 'Fix initiatives count in initiatives index page' to v0.27 [\#10280](https://github.com/decidim/decidim/pull/10280) +- **decidim-core**: Backport 'User's group endorsement no longer disappears after personal endorsement removed' to v0.27 [\#10281](https://github.com/decidim/decidim/pull/10281) +- **decidim-core**: Backport 'Fix bug regarding user group moderation action logs' to v0.27 [\#10254](https://github.com/decidim/decidim/pull/10254) +- **decidim-assemblies**, **decidim-conferences**, **decidim-participatory processes**: Backport 'Do not display unpublished spaces in linked spaces' to v0.27 [\#10346](https://github.com/decidim/decidim/pull/10346) +- **decidim-assemblies**, **decidim-meetings**: Backport 'Display Published meetings in Assembly cell' to v0.27 [\#10340](https://github.com/decidim/decidim/pull/10340) +- **decidim-core**: Backport 'Uploading files - Explanation %{attribute} not translate' to v0.27 [\#10348](https://github.com/decidim/decidim/pull/10348) +- **decidim-admin**, **decidim-core**: Backport 'Fix newsletters unwanted CSS and 404 page on preview' to v0.27 [\#10354](https://github.com/decidim/decidim/pull/10354) +- **decidim-admin**: Backport 'A Valuator should not be able to access Global Moderation' to v0.27 [\#10350](https://github.com/decidim/decidim/pull/10350) +- **decidim-core**: Backport 'Fix an edge case with the attribute object forms with arrays/enums' (#10218) to v0.27 [\#10358](https://github.com/decidim/decidim/pull/10358) +- **decidim-initiatives**: Backport 'Fixing some typos in the english translations' to v0.27 [\#10361](https://github.com/decidim/decidim/pull/10361) ### Removed Nothing. +### Developer improvements + +- Backport 'Remove unecessary line in push notifications spec' to v0.27 [\#10088](https://github.com/decidim/decidim/pull/10088) + ### Internal -- Backport 'Fix importing a page component without a body' to v0.26 [\#10023](https://github.com/decidim/decidim/pull/10023) +- Backport 'Lock GitHub actions to Ubuntu 20.04 due to OpenSSL 3.0 issues' to v0.27 [\#10225](https://github.com/decidim/decidim/pull/10225) -### Developer improvements +### Unsorted -Nothing. -## [0.26.3](https://github.com/decidim/decidim/tree/v0.26.3) +## [0.27.1](https://github.com/decidim/decidim/tree/0.27.1) ### Added @@ -81,547 +77,870 @@ Nothing. ### Fixed -- **decidim-core**: Backport 'Fix / Expose createMapController properly to let overriding' to v0.26 [\#9520](https://github.com/decidim/decidim/pull/9520) -- **decidim-elections**: Backport 'Capture unhandled errors from JS promises and inform the user' to v0.26 [\#9521](https://github.com/decidim/decidim/pull/9521) -- **decidim-elections**: Backport 'Remove description from questions in elections' to v0.26 [\#9522](https://github.com/decidim/decidim/pull/9522) -- **decidim-initiatives**: Backport 'Return 404 when there isn't an initiative' to v0.26 [\#9523](https://github.com/decidim/decidim/pull/9523) -- **decidim-forms**, **decidim-meetings**, **decidim-surveys**: Backport 'Fix rollback questionnaire answer when file is invalid' to v0.26 [\#9524](https://github.com/decidim/decidim/pull/9524) -- **decidim-elections**: Backport 'Make sure component is published when starting an election' to v0.26 [\#9525](https://github.com/decidim/decidim/pull/9525) -- **decidim-core**, **decidim-meetings**, **decidim-proposals**: Backport 'Fix email subject when resource title has special characters' to v0.26 [\#9526](https://github.com/decidim/decidim/pull/9526) -- **decidim-core**: Backport 'Prevent users to validate nicknames/emails taken by user groups' to v0.26 [\#9527](https://github.com/decidim/decidim/pull/9527) -- **decidim-elections**: Backport 'Fix hardcoded hour in election dashboard' to v0.26 [\#9528](https://github.com/decidim/decidim/pull/9528) -- **decidim-comments**, **decidim-core**: Backport 'Fix long word breaking on comments and cards' to v0.26 [\#9529](https://github.com/decidim/decidim/pull/9529) -- **decidim-assemblies**, **decidim-conferences**, **decidim-consultations**, **decidim-core**, **decidim-elections**, **decidim-initiatives**, **decidim-participatory processes**: Backport 'Fix background-image URLs with weird characters' to v0.26 [\#9531](https://github.com/decidim/decidim/pull/9531) -- **decidim-assemblies**, **decidim-conferences**, **decidim-elections**: Backport 'Fix cache hash on Hightlighted spaces' to v0.26 [\#9536](https://github.com/decidim/decidim/pull/9536) -- **decidim-accountability**: Backport 'Add short format to result date' to v0.26 [\#9540](https://github.com/decidim/decidim/pull/9540) -- **decidim-elections**: Backport 'Advertise users if BB connection is lost in trustees/admin zones' to v0.26 [\#9535](https://github.com/decidim/decidim/pull/9535) -- **decidim-core**: Backport 'Fix email subject when participatory space title is present' to v0.26 [\#9573](https://github.com/decidim/decidim/pull/9573) -- **decidim-conferences**: Backport 'Fix published conferences order' to v0.26 [\#9688](https://github.com/decidim/decidim/pull/9688) -- **decidim-comments**: Backport 'Fix creation notification when editing a comment ' to v0.26 [\#9690](https://github.com/decidim/decidim/pull/9690) -- **decidim-elections**: Backport 'Remove margin-bottom on votings navigation' to v0.26 [\#9692](https://github.com/decidim/decidim/pull/9692) -- **decidim-initiatives**: Backport 'Use public link on initiatives mailer' to v0.26 [\#9694](https://github.com/decidim/decidim/pull/9694) -- **decidim-accountability**: Backport 'Disallow creating grandchildren results' to v0.26 [\#9698](https://github.com/decidim/decidim/pull/9698) -- **decidim-forms**, **decidim-meetings**: Backport 'Prevent showing announcement on meetings registrations' to v0.26 [\#9700](https://github.com/decidim/decidim/pull/9700) -- **decidim-initiatives**: Backport 'Fix for initiative mailer when promoting committee is disabled' to v0.26 [\#9696](https://github.com/decidim/decidim/pull/9696) -- **decidim-elections**: Backport 'Improve steps election check page with census' to v0.26 [\#9702](https://github.com/decidim/decidim/pull/9702) -- **decidim-core**: Backport 'Fix translated attributes field type change' to v0.26 [\#9704](https://github.com/decidim/decidim/pull/9704) -- **decidim-core**: Backport 'Prevent missing ActionLog entries to break the application' to v0.26 [\#9706](https://github.com/decidim/decidim/pull/9706) -- **decidim-proposals**: Backport 'Fix publish event on official proposals' to v0.26 [\#9708](https://github.com/decidim/decidim/pull/9708) -- **decidim-admin**, **decidim-proposals**: Backport 'Add help text for proposals' 'publish answers immediately' setting ' to v0.26 [\#9712](https://github.com/decidim/decidim/pull/9712) -- **decidim-conferences**: Backport 'Return 404 when there isn't a valid component in program' to v0.26 [\#9717](https://github.com/decidim/decidim/pull/9717) -- **decidim-budgets**: Backport 'Fix budgets seeds on non development apps' to v0.26 [\#9719](https://github.com/decidim/decidim/pull/9719) -- **decidim-core**: Backport 'Fix creating automatic nicknames when taken by user_groups' to v0.26 [\#9721](https://github.com/decidim/decidim/pull/9721) -- **decidim-debates**: Backport 'Fix resource endorsed notification with Debates' to v0.26 [\#9723](https://github.com/decidim/decidim/pull/9723) -- **decidim-meetings**: Backport 'Fix agenda_item association with agenda' to v0.26 [\#9728](https://github.com/decidim/decidim/pull/9728) -- **decidim-verifications**: Backport 'Fix absolute urls on 'managed user error' event' to v0.26 [\#9730](https://github.com/decidim/decidim/pull/9730) -- **decidim-core**: Backport 'Fix mobile notifications switch component overlaps' to v0.26 [\#9732](https://github.com/decidim/decidim/pull/9732) -- **decidim-core**: Backport 'Fix blocked user nickname and avatar in user presenter' to v0.26 [\#9741](https://github.com/decidim/decidim/pull/9741) -- **decidim-admin**: Backport 'Fix form error overlap with character counter in the admin panel' to v0.26 [\#9749](https://github.com/decidim/decidim/pull/9749) -- **decidim-core**: Backport 'Fix the endorsement permissions' to v0.26 [\#9734](https://github.com/decidim/decidim/pull/9734) -- **decidim-meetings**: Backport 'Fix order when filtering Meetings' to v0.26 [\#9751](https://github.com/decidim/decidim/pull/9751) -- **decidim-proposals**: Backport 'Fix redundant notification on comments with linked proposals' to v0.26 [\#9746](https://github.com/decidim/decidim/pull/9746) -- **decidim-core**: Backport 'Make the HERE Map display in the currently selected language' to v0.26 [\#9714](https://github.com/decidim/decidim/pull/9714) -- **decidim-admin**, **decidim-forms**: Backport 'Fix admin language selector with more than 4 locales' to v0.26 [\#9710](https://github.com/decidim/decidim/pull/9710) -- **decidim-meetings**: Backport 'Ignore participatory spaces without models in meetings visible_for scope' to v0.26 [\#9794](https://github.com/decidim/decidim/pull/9794) -- **decidim-admin**: Backport 'Fix leaking emails on admin user search controller' to 0.26 [\#9797](https://github.com/decidim/decidim/pull/9797) -- **decidim-assemblies**, **decidim-participatory processes**: Backport 'Fix import of images on spaces' to v0.26 [\#9803](https://github.com/decidim/decidim/pull/9803) -- **decidim-core**: Backport 'Fix hashtags not recognized at the beginning of the string' to v0.26 [\#9811](https://github.com/decidim/decidim/pull/9811) -- **decidim-accountability**, **decidim-core**, **decidim-debates**, **decidim-initiatives**, **decidim-meetings**, **decidim-proposals**: Backport 'Fix version pages showing a HTTP 500 error when the version does not exist' to v0.26 [\#9809](https://github.com/decidim/decidim/pull/9809) -- **decidim-core**: Backport 'Fix hidden error messages on the registration form' to v0.26 [\#9813](https://github.com/decidim/decidim/pull/9813) -- **decidim-core**: Backport 'Fix multitenant organizations stats cache' to v0.26 [\#9807](https://github.com/decidim/decidim/pull/9807) -- **decidim-admin**, **decidim-initiatives**: Backport 'Fix initiatives components' to v0.26 [\#9825](https://github.com/decidim/decidim/pull/9825) -- Backport 'Fix doorkeeper initialization after 5.6.0 release' to v0.26 [\#9788](https://github.com/decidim/decidim/pull/9788) +- **decidim-participatory processes**: Backport 'Fix unpublished processes shown in the group process count' to v0.27 [\#9935](https://github.com/decidim/decidim/pull/9935) +- **decidim-admin**: Backport 'Fix global moderation types not translated' to v0.27 [\#9936](https://github.com/decidim/decidim/pull/9936) +- **decidim-admin**: Backport 'Fix updating organization settings in case there were errors' to v0.27 [\#9939](https://github.com/decidim/decidim/pull/9939) +- **decidim-budgets**, **decidim-core**, **decidim-elections**, **decidim-proposals**: Backport 'Do not import resources multiple times' to v0.27 [\#9943](https://github.com/decidim/decidim/pull/9943) +- **decidim-forms**, **decidim-surveys**: Backport 'Fix form answer attachments breaking the answer view' to v0.27 [\#9944](https://github.com/decidim/decidim/pull/9944) +- **decidim-comments**, **decidim-core**, **decidim-verifications**: Backport 'Fix user related absolute URLs' to v0.27 [\#9946](https://github.com/decidim/decidim/pull/9946) +- **decidim-comments**: Backport 'Fix "disappearing" underscores with comments' to v0.27 [\#9948](https://github.com/decidim/decidim/pull/9948) +- **decidim-admin**, **decidim-core**: Backport 'Fix editor content saving when the content has only one video' to v0.27 [\#9950](https://github.com/decidim/decidim/pull/9950) +- **decidim-core**: Backport 'Fix date/time formats at component forms' to v0.27 [\#9952](https://github.com/decidim/decidim/pull/9952) +- **decidim-proposals**: Backport 'Fix collaborative drafts page when there are errors on the form' to v0.27 [\#9954](https://github.com/decidim/decidim/pull/9954) +- **decidim-debates**: Backport 'Fix the finite value on the debate form when editing an existing debate' to v0.27 [\#9956](https://github.com/decidim/decidim/pull/9956) +- **decidim-pages**: Backport 'Fix exporting and importing a page component' to v0.27 [\#9958](https://github.com/decidim/decidim/pull/9958) +- **decidim-core**: Backport 'Fix webpacker crashes on missing icons' to v0.27 [\#9960](https://github.com/decidim/decidim/pull/9960) +- **decidim-participatory processes**: Backport 'Fix importing participatory process from legacy format' to v0.27 [\#9963](https://github.com/decidim/decidim/pull/9963) +- **decidim-assemblies**, **decidim-core**, **decidim-participatory processes**: Backport 'Fix duplicate stats on home page and participatory space main page' to v0.27 [\#9965](https://github.com/decidim/decidim/pull/9965) +- **decidim-budgets**, **decidim-core**, **decidim-proposals**, **decidim-templates**: Backport 'Address Crowdin feedback' to v0.27 [\#9969](https://github.com/decidim/decidim/pull/9969) +- **decidim-core**, **decidim-proposals**: Backport 'Fix cryptic file validation errors' to v0.27 [\#9971](https://github.com/decidim/decidim/pull/9971) +- **decidim-core**: Backport 'Limit invitation redirects only to paths within the application' to v0.27 [\#9972](https://github.com/decidim/decidim/pull/9972) +- **decidim-admin**, **decidim-assemblies**, **decidim-participatory processes**: Backport 'Add malformed file errors when CSV reading fails' to v0.27 [\#9974](https://github.com/decidim/decidim/pull/9974) +- **decidim-elections**: Backport 'Define the component import routes, permissions and controller at votings' to v0.27 [\#9976](https://github.com/decidim/decidim/pull/9976) +- **decidim-core**: Backport 'Fix duplicate user activity records when public spaces have private users' to v0.27 [\#9978](https://github.com/decidim/decidim/pull/9978) +- **decidim-initiatives**: Backport 'Fix initiative sign if the authorization metadata is set to `nil`' to v0.27 [\#9980](https://github.com/decidim/decidim/pull/9980) +- **decidim-initiatives**: Backport 'Add missing i18n key in Initiatives' to v0.27 [\#9982](https://github.com/decidim/decidim/pull/9982) +- **decidim-comments**: Backport 'Fix commenting field disabled when polling new comments' to v0.27 [\#9986](https://github.com/decidim/decidim/pull/9986) +- **decidim-core**: Backport 'Fix correct resource linking for amendments' to v0.27 [\#9987](https://github.com/decidim/decidim/pull/9987) +- **decidim-core**: Backport 'Fix last activity page showing recently updated records' to v0.27 [\#9989](https://github.com/decidim/decidim/pull/9989) +- **decidim-core**: Backport 'Fix user sign up with invalid name' to v0.27 [\#9990](https://github.com/decidim/decidim/pull/9990) +- **decidim-core**: Backport 'Fix user sign up with invalid name' to v0.27 [\#9990](https://github.com/decidim/decidim/pull/9990) +- **decidim-admin**, **decidim-assemblies**, **decidim-initiatives**, **decidim-participatory processes**, **decidim-verifications**: Backport 'Add missing active actions on admin navigation menu' to v0.27 [\#9992](https://github.com/decidim/decidim/pull/9992) +- **decidim-admin**, **decidim-assemblies**, **decidim-initiatives**, **decidim-participatory processes**, **decidim-verifications**: Backport 'Add missing active actions on admin navigation menu' to v0.27 [\#9992](https://github.com/decidim/decidim/pull/9992) +- **decidim-admin**, **decidim-assemblies**, **decidim-initiatives**, **decidim-participatory processes**, **decidim-verifications**: Backport 'Add missing active actions on admin navigation menu' to v0.27 [\#9992](https://github.com/decidim/decidim/pull/9992) +- **decidim-initiatives**: Backport 'Make initiatives order translatable' to v0.27 [\#9994](https://github.com/decidim/decidim/pull/9994) +- **decidim-core**: Backport 'Make ToS agreement translatable' to v0.27 [\#9996](https://github.com/decidim/decidim/pull/9996) +- **decidim-debates**: Backport 'Make Scopes field in debates translatable' to v0.27 [\#9998](https://github.com/decidim/decidim/pull/9998) +- **decidim-core**: Backport 'Remove invitations badge' to v0.27 [\#10000](https://github.com/decidim/decidim/pull/10000) +- **decidim-conferences**: Backport 'Fix conference invitations' to v0.27 [\#10003](https://github.com/decidim/decidim/pull/10003) +- **decidim-admin**, **decidim-core**: Backport 'Fix preserving bold text in the rich text editor when pasting content' to v0.27 [\#9961](https://github.com/decidim/decidim/pull/9961) +- **decidim-core**, **decidim-proposals**: Backport 'Fix proposal etiquette and length validator with base64 images' to v0.27 [\#10009](https://github.com/decidim/decidim/pull/10009) +- **decidim-core**: Backport 'Fix disappearing sub-lists in rich text editors' to v0.27 [\#9967](https://github.com/decidim/decidim/pull/9967) +- **decidim-meetings**, **decidim-proposals**: Backport 'Fix invalid rendering of meeting and proposal body texts' to v0.27 [\#10002](https://github.com/decidim/decidim/pull/10002) +- **decidim-core**, **decidim-debates**, **decidim-meetings**, **decidim-proposals**: Backport 'Refactor cell titles' to v0.27 [\#10040](https://github.com/decidim/decidim/pull/10040) +- **decidim-admin**, **decidim-comments**: Backport 'Fix moderations for comments that are mapped to deleted resources' to v0.27 [\#9940](https://github.com/decidim/decidim/pull/9940) +- **decidim-meetings**: Backport 'Refactor the meeting list item title display' to v0.27 [\#10046](https://github.com/decidim/decidim/pull/10046) +- **decidim-system**: Backport 'Fix organization SMTP password not saved (became blank) in system panel' to v0.27 [\#10052](https://github.com/decidim/decidim/pull/10052) +- **decidim-accountability**, **decidim-admin**, **decidim-proposals**: Backport 'Reformat CSV help for import files on Accountability and Proposals' to v0.27 [\#10054](https://github.com/decidim/decidim/pull/10054) +- **decidim-budgets**, **decidim-elections**, **decidim-proposals**, **decidim-sortitions**: Backport 'Fix usages of `reorder` and `paginate`' to v0.27 [\#10050](https://github.com/decidim/decidim/pull/10050) +- **decidim-admin**: Backport 'Show only ToS acceptance when admin hasn't accepted it' to v0.27 [\#10056](https://github.com/decidim/decidim/pull/10056) +- **decidim-participatory processes**: Backport 'Fix usages of sanitize helper methods for editable content provided by admins' to v0.27 [\#10058](https://github.com/decidim/decidim/pull/10058) +- **decidim-debates**, **decidim-meetings**, **decidim-proposals**: Backport 'Refactor admin listing titles' to v0.27 [\#10048](https://github.com/decidim/decidim/pull/10048) ### Removed Nothing. +### Developer improvements + +Nothing. + ### Internal -- Backport 'Fix invalid translation in spec' to v0.26 [\#9435](https://github.com/decidim/decidim/pull/9435) -- Backport 'Remove the description field from the elections component seeds' to v0.26 [\#9553](https://github.com/decidim/decidim/pull/9553) -- Fix API GraphiQL system spec for 0.26 with newer ChromeDriver [\#9556](https://github.com/decidim/decidim/pull/9556) -- Backport 'Update `rokroskar/workflow-run-cleanup-action` GitHub action to v0.3.3' to v0.26 [\#9829](https://github.com/decidim/decidim/pull/9829) -- Backport 'Split parallel test coverage reports into their own folders' to v0.26 [\#9819](https://github.com/decidim/decidim/pull/9819) -- Backport 'Improve release process' to v0.26 [\#9864](https://github.com/decidim/decidim/pull/9864) +- **decidim-dev**: Backport 'Ignore the problematics HTML validation checks with hidden inputs' to v0.27 [\#10025](https://github.com/decidim/decidim/pull/10025) +- Backport 'Bump versions on install docs' to v0.27 [\#10008](https://github.com/decidim/decidim/pull/10008) +- **decidim-assemblies**: Backport 'Fix importing a page component without a body' to v0.27 [\#10029](https://github.com/decidim/decidim/pull/10029) -### Developer improvements +## [0.27.0](https://github.com/decidim/decidim/tree/0.27.0) -Nothing. +### Detailed changes -## [0.26.2](https://github.com/decidim/decidim/tree/v0.26.2) +#### Added -### Added +Nothing. + +#### Changed Nothing. -### Changed +#### Fixed Nothing. -### Fixed +#### Removed -- **decidim-comments**, **decidim-core**, **decidim-meetings**: Backport "Fix timeout in comment view and during meetings" to v0.26 [\#9091](https://github.com/decidim/decidim/pull/9091) -- **decidim-core**: Backport "Dont add external link container inside editor" to v0.26 [\#9108](https://github.com/decidim/decidim/pull/9108) -- **decidim-core**: Backport "Add base URI to meta image URLs" to v0.26 [\#9153](https://github.com/decidim/decidim/pull/9153) -- **decidim-initiatives**: Backport "Remove 'edit link' in topbar for initiative's authors" to v0.26 [\#9239](https://github.com/decidim/decidim/pull/9239) -- **decidim-elections**: Backport 'Clarify message to user when checking census' to v0.26 [\#9240](https://github.com/decidim/decidim/pull/9240) -- **decidim-participatory processes**: Backport 'Fix processes count in processes group title cell' to v0.26 [\#9242](https://github.com/decidim/decidim/pull/9242) -- **decidim-elections**: Backport 'Improve wording when casting your vote' to v0.26 [\#9243](https://github.com/decidim/decidim/pull/9243) -- **decidim-proposals**: Backport 'Add 'not answered' as a possible answer in proposals' to v0.26 [\#9246](https://github.com/decidim/decidim/pull/9246) -- **decidim-meetings**: Backport 'Fix meetings minutes migration' to v0.26 [\#9247](https://github.com/decidim/decidim/pull/9247) -- **decidim-assemblies**, **decidim-proposals**: Backport "Fix absolute urls on 'assembly member' and 'collaborative drafts' events" to v0.26 [\#9248](https://github.com/decidim/decidim/pull/9248) -- **decidim-accountability**, **decidim-consultations**: Backport 'Fix components navbar in consultations mobile ' to v0.26 [\#9249](https://github.com/decidim/decidim/pull/9249) -- **decidim-meetings**: Backport 'Move modal to body and fix condition' to v0.26 [\#9250](https://github.com/decidim/decidim/pull/9250) -- **decidim-meetings**: Backport 'Do not send upcoming meeting notification for hidden or withdrawn meetings' to v0.26 [\#9251](https://github.com/decidim/decidim/pull/9251) -- **decidim-core**: Backport 'Show only current organization in verification conflicts with multitenants' to v0.26 [\#9252](https://github.com/decidim/decidim/pull/9252) -- **decidim-elections**: Backport 'Send email to newly added trustees' to v0.26 [\#9253](https://github.com/decidim/decidim/pull/9253) -- **decidim-meetings**: Backport 'Fix registration type field highlighted in admin meeting creation form' to v0.26 [\#9254](https://github.com/decidim/decidim/pull/9254) -- **decidim-surveys**: Backport 'Fix contradictory form errors on survey form' to v0.26 [\#9257](https://github.com/decidim/decidim/pull/9257) -- **decidim-initiatives**: Backport 'Add edit and delete actions in InitiativeType admin table' to v0.26 [\#9260](https://github.com/decidim/decidim/pull/9260) -- **decidim-surveys**: Backport 'Clarify unregistered answers on surveys behavior' to v0.26 [\#9261](https://github.com/decidim/decidim/pull/9261) -- **decidim-elections**: Backport 'Fix voting with single election' to v0.26 [\#9262](https://github.com/decidim/decidim/pull/9262) -- **decidim-initiatives**: Backport 'Fix initiative print link, margin, and organization logo' to v0.26 [\#9263](https://github.com/decidim/decidim/pull/9263) -- **decidim-elections**: Backport 'Remove show more button on elections' to v0.26 [\#9264](https://github.com/decidim/decidim/pull/9264) -- **decidim-surveys**: Backport 'Fix survey activity log entries' to v0.26 [\#9265](https://github.com/decidim/decidim/pull/9265) -- **decidim-budgets**: Backport 'Remove beforeunload confirmation panel from the budgets voting' to v0.26 [\#9266](https://github.com/decidim/decidim/pull/9266) -- **decidim-admin**, **decidim-elections**: Backport 'Fix newsletters and Decidim Votings' to v0.26 [\#9258](https://github.com/decidim/decidim/pull/9258) -- **decidim-core**: Backport 'Fix notifications where resources are missing' to v0.26 [\#9256](https://github.com/decidim/decidim/pull/9256) -- **decidim-core**: Backport 'Enforce password validation rules on 'Forgot your password?' form' to v0.26 [\#9245](https://github.com/decidim/decidim/pull/9245) -- **decidim-core**: Backport 'Fix displaying blocked users in account follow pages' to v0.26 [\#9255](https://github.com/decidim/decidim/pull/9255) -- **decidim-core**: Backport 'Fix Leaflet trying to load "infinite amount of tiles"' to v0.26 [\#9269](https://github.com/decidim/decidim/pull/9269) -- **decidim-system**: Backport 'Enforce password validation rules on system admins' to v0.26 [\#9259](https://github.com/decidim/decidim/pull/9259) -- **decidim-meetings**: Backport 'Remove presenters in the meetings admin backoffice' to v0.26 [\#9323](https://github.com/decidim/decidim/pull/9323) -- **decidim-elections**: Backport 'Correctly show trustees and votings menu' to v0.26 [\#9324](https://github.com/decidim/decidim/pull/9324) -- **decidim-core**: Backport 'Fix hashtag parsing on URLs with fragments' to v0.26 [\#9326](https://github.com/decidim/decidim/pull/9326) -- **decidim-comments**, **decidim-core**: Backport 'Add missing events locales' to v0.26 [\#9327](https://github.com/decidim/decidim/pull/9327) -- **decidim-conferences**: Backport 'Make conference's partners logos always mandatory' to v0.26 [\#9328](https://github.com/decidim/decidim/pull/9328) -- **decidim-admin**: Backport 'Fix margin around warning message in colour settings' to v0.26 [\#9329](https://github.com/decidim/decidim/pull/9329) -- **decidim-elections**: Backport 'Hide more information link when there's no description on an election' to v0.26 [\#9331](https://github.com/decidim/decidim/pull/9331) -- **decidim-admin**, **decidim-assemblies**, **decidim-budgets**, **decidim-core**, **decidim-elections**, **decidim-meetings**, **decidim-pages**, **decidim-proposals**: Backport 'Apply crowdin feedback' to v0.26 [\#9333](https://github.com/decidim/decidim/pull/9333) -- **decidim-comments**, **decidim-core**: Backport 'Don't show deleted resources in last activities ' to v0.26 [\#9330](https://github.com/decidim/decidim/pull/9330) -- **decidim-elections**: Backport 'Fix election label translations' to v0.26 [\#9343](https://github.com/decidim/decidim/pull/9343) -- **decidim-verifications**: Backport 'Allow to renew expired verifications (if renewable)' to v0.26 [\#9344](https://github.com/decidim/decidim/pull/9344) -- **decidim-elections**: Backport 'Add error message when adding question and election has started' to v0.26 [\#9404](https://github.com/decidim/decidim/pull/9404) -- **decidim-core**: Backport 'Fix user interests' to v0.26 [\#9406](https://github.com/decidim/decidim/pull/9406) -- **decidim-elections**: Backport 'Fix regular expression on census check' to v0.26 [\#9408](https://github.com/decidim/decidim/pull/9408) -- **decidim-elections**: Backport 'Enforce YYYYmmdd format in birthdate when uploading census' to v0.26 [\#9410](https://github.com/decidim/decidim/pull/9410) -- **decidim-consultations**: Backport 'Return 404 when there isn't a question' to v0.26 [\#9414](https://github.com/decidim/decidim/pull/9414) -- **decidim-consultations**: Backport 'Return 404 when there isn't a consultation' to v0.26 [\#9413](https://github.com/decidim/decidim/pull/9413) -- **decidim-elections**: Backport 'Return 404 when there isn't a voting in elections_log' to v0.26 [\#9415](https://github.com/decidim/decidim/pull/9415) -- **decidim-proposals**: Backport 'Fix proposals creation with Participatory Texts ' to v0.26 [\#9416](https://github.com/decidim/decidim/pull/9416) -- **decidim-elections**: Backport 'Fix ActionLog when a ballot style is deleted' to v0.26 [\#9411](https://github.com/decidim/decidim/pull/9411) -- **decidim-elections**: Backport 'Only show that the code can be requested via SMS if its true' to v0.26 [\#9409](https://github.com/decidim/decidim/pull/9409) -- **decidim-budgets**, **decidim-proposals**: Backport 'Add missing translation keys proposals import and proposals picker' to v0.26 [\#9412](https://github.com/decidim/decidim/pull/9412) -- **decidim-elections**: Backport 'Fix HTML safe content in election voting' to v0.26 [\#9405](https://github.com/decidim/decidim/pull/9405) -- **decidim-core**: Backport 'Fix for internal links not displaying on page title' to v0.26 [\#9407](https://github.com/decidim/decidim/pull/9407) +Nothing. -### Removed +#### Developer improvements Nothing. -### Internal +## [0.27.0.rc2](https://github.com/decidim/decidim/tree/0.27.0.rc2) -- Backport 'Fix generators specs target branch' to v0.26 [\#9290](https://github.com/decidim/decidim/pull/9290) +### Detailed changes -### Developer improvements +#### Added Nothing. -## [0.26.1](https://github.com/decidim/decidim/tree/v0.26.1) +#### Changed -### Added +Nothing. + +#### Fixed + +- **decidim-assemblies**, **decidim-conferences**, **decidim-consultations**, **decidim-core**, **decidim-elections**, **decidim-initiatives**, **decidim-participatory processes**: Backport 'Fix background-image URLs with weird characters' to v0.27 [\#9495](https://github.com/decidim/decidim/pull/9495) +- **decidim-comments**, **decidim-core**: Backport 'Fix long word breaking on comments and cards' to v0.27 [\#9530](https://github.com/decidim/decidim/pull/9530) +- **decidim-core**: Backport 'Fix nested attributes model mapping' to v0.27 [\#9532](https://github.com/decidim/decidim/pull/9532) +- **decidim-initiatives**: Backport 'Add the rexml gem as a requirement for Ruby 3.0.0+ compatibility' to v0.27 [\#9533](https://github.com/decidim/decidim/pull/9533) +- **decidim-elections**: Backport 'Advertise users if BB connection is lost in trustees/admin zones' to v0.27 [\#9534](https://github.com/decidim/decidim/pull/9534) +- **decidim-assemblies**, **decidim-conferences**, **decidim-elections**: Backport 'Fix cache hash on Hightlighted spaces' to v0.27 [\#9537](https://github.com/decidim/decidim/pull/9537) +- **decidim-core**: Backport 'Fix email subject when participatory space title is present' to v0.27 [\#9538](https://github.com/decidim/decidim/pull/9538) +- **decidim-accountability**: Backport 'Add short format to result date' to v0.27 [\#9541](https://github.com/decidim/decidim/pull/9541) +- **decidim-conferences**: Backport 'Fix published conferences order' to v0.27 [\#9687](https://github.com/decidim/decidim/pull/9687) +- **decidim-comments**: Backport 'Fix creation notification when editing a comment ' to v0.27 [\#9689](https://github.com/decidim/decidim/pull/9689) +- **decidim-elections**: Backport 'Remove margin-bottom on votings navigation' to v0.27 [\#9691](https://github.com/decidim/decidim/pull/9691) +- **decidim-initiatives**: Backport 'Use public link on initiatives mailer' to v0.27 [\#9693](https://github.com/decidim/decidim/pull/9693) +- **decidim-accountability**: Backport 'Disallow creating grandchildren results' to v0.27 [\#9697](https://github.com/decidim/decidim/pull/9697) +- **decidim-forms**, **decidim-meetings**: Backport 'Prevent showing announcement on meetings registrations' to v0.27 [\#9699](https://github.com/decidim/decidim/pull/9699) +- **decidim-initiatives**: Backport 'Fix for initiative mailer when promoting committee is disabled' to v0.27 [\#9695](https://github.com/decidim/decidim/pull/9695) +- **decidim-elections**: Backport 'Improve steps election check page with census' to v0.27 [\#9701](https://github.com/decidim/decidim/pull/9701) +- **decidim-core**: Backport 'Fix translated attributes field type change' to v0.27 [\#9703](https://github.com/decidim/decidim/pull/9703) +- **decidim-core**: Backport 'Prevent missing ActionLog entries to break the application' to v0.27 [\#9705](https://github.com/decidim/decidim/pull/9705) +- **decidim-proposals**: Backport 'Fix publish event on official proposals' to v0.27 [\#9707](https://github.com/decidim/decidim/pull/9707) +- **decidim-admin**, **decidim-proposals**: Backport 'Add help text for proposals' 'publish answers immediately' setting ' to v0.27 [\#9711](https://github.com/decidim/decidim/pull/9711) +- **decidim-conferences**: Backport 'Return 404 when there isn't a valid component in program' to v0.27 [\#9716](https://github.com/decidim/decidim/pull/9716) +- **decidim-budgets**: Backport 'Fix budgets seeds on non development apps' to v0.27 [\#9718](https://github.com/decidim/decidim/pull/9718) +- **decidim-core**: Backport 'Fix creating automatic nicknames when taken by user_groups' to v0.27 [\#9720](https://github.com/decidim/decidim/pull/9720) +- **decidim-debates**: Backport 'Fix resource endorsed notification with Debates' to v0.27 [\#9722](https://github.com/decidim/decidim/pull/9722) +- **decidim-core**: Backport 'Set push notifications in user locale' to v0.27 [\#9724](https://github.com/decidim/decidim/pull/9724) +- **decidim-elections**: Backport 'Improve census importing process in elections/votings space' to v0.27 [\#9725](https://github.com/decidim/decidim/pull/9725) +- **decidim-core**: Backport 'Strip tags keeping entity characters' to v0.27 [\#9726](https://github.com/decidim/decidim/pull/9726) +- **decidim-meetings**: Backport 'Fix agenda_item association with agenda' to v0.27 [\#9727](https://github.com/decidim/decidim/pull/9727) +- **decidim-verifications**: Backport 'Fix absolute urls on 'managed user error' event' to v0.27 [\#9729](https://github.com/decidim/decidim/pull/9729) +- **decidim-core**: Backport 'Fix mobile notifications switch component overlaps' to v0.27 [\#9731](https://github.com/decidim/decidim/pull/9731) +- **decidim-core**: Backport 'Fix account update without password change' to v0.27 [\#9735](https://github.com/decidim/decidim/pull/9735) +- **decidim-meetings**: Backport 'Fix order when filtering Meetings' to v0.27 [\#9737](https://github.com/decidim/decidim/pull/9737) +- **decidim-admin**: Backport 'Fix admin autocomplete when a locale is defined in the URL' to v0.27 [\#9738](https://github.com/decidim/decidim/pull/9738) +- **decidim-core**: Backport 'Fix blocked user nickname and avatar in user presenter' to v0.27 [\#9740](https://github.com/decidim/decidim/pull/9740) +- **decidim-core**: Backport 'Change the custom public port ENV variable name to HTTP_PORT' to v0.27 [\#9747](https://github.com/decidim/decidim/pull/9747) +- **decidim-admin**: Backport 'Fix form error overlap with character counter in the admin panel' to v0.27 [\#9748](https://github.com/decidim/decidim/pull/9748) +- **decidim-core**: Backport 'Fix the endorsement permissions' to v0.27 [\#9733](https://github.com/decidim/decidim/pull/9733) +- **decidim-core**: Backport 'Fix PWA install prompt keeps appearing more than once' to v0.27 [\#9744](https://github.com/decidim/decidim/pull/9744) +- **decidim-core**: Backport 'Fix issues with daily and weekly notifications' to v0.27 [\#9739](https://github.com/decidim/decidim/pull/9739) +- **decidim-proposals**: Backport 'Fix redundant notification on comments with linked proposals' to v0.27 [\#9745](https://github.com/decidim/decidim/pull/9745) +- **decidim-generators**: Backport 'Add missing queue close_meeting_reminder to sidekiq configuration' to v0.27 [\#9715](https://github.com/decidim/decidim/pull/9715) +- **decidim-core**: Backport 'Make the HERE Map display in the currently selected language' to v0.27 [\#9713](https://github.com/decidim/decidim/pull/9713) +- **decidim-admin**, **decidim-forms**: Backport 'Fix admin language selector with more than 4 locales' to v0.27 [\#9709](https://github.com/decidim/decidim/pull/9709) +- **decidim-core**, **decidim-dev**, **decidim-generators**: Backport 'Fix data consent expiry' to v0.27 [\#9742](https://github.com/decidim/decidim/pull/9742) +- **decidim-core**: Backport 'Fix uninitialized constant errors with custom set of modules' to v0.27 [\#9743](https://github.com/decidim/decidim/pull/9743) +- **decidim-meetings**: Backport 'Ignore participatory spaces without models in meetings visible_for scope' to v0.27 [\#9795](https://github.com/decidim/decidim/pull/9795) +- **decidim-admin**: Backport 'Fix leaking emails on admin user search controller' to 0.27 [\#9796](https://github.com/decidim/decidim/pull/9796) +- **decidim-core**: Backport 'Fix order of last activities' to v0.27 [\#9802](https://github.com/decidim/decidim/pull/9802) +- **decidim-conferences**: Backport 'Fix conference speaker avatars' to v0.27 [\#9823](https://github.com/decidim/decidim/pull/9823) +- **decidim-core**: Backport 'Prevent the account edit route through Devise' to v0.27 [\#9806](https://github.com/decidim/decidim/pull/9806) +- **decidim-accountability**, **decidim-core**, **decidim-debates**, **decidim-initiatives**, **decidim-meetings**, **decidim-proposals**: Backport 'Fix version pages showing a HTTP 500 error when the version does not exist' to v0.27 [\#9810](https://github.com/decidim/decidim/pull/9810) +- **decidim-core**: Backport 'Fix hashtags not recognized at the beginning of the string' to v0.27 [\#9812](https://github.com/decidim/decidim/pull/9812) +- **decidim-comments**: Backport 'Fix posting comments before the initial load has run' to v0.27 [\#9815](https://github.com/decidim/decidim/pull/9815) +- **decidim-core**: Backport 'Fix hidden error messages on the registration form' to v0.27 [\#9814](https://github.com/decidim/decidim/pull/9814) +- **decidim-core**: Backport 'Fix multitenant organizations stats cache' to v0.27 [\#9808](https://github.com/decidim/decidim/pull/9808) +- **decidim-core**: Backport 'Fix character counter for the WYSIWYG editor' to v0.27 [\#9816](https://github.com/decidim/decidim/pull/9816) +- **decidim-admin**, **decidim-initiatives**: Backport 'Fix initiatives components' to v0.27 [\#9824](https://github.com/decidim/decidim/pull/9824) +- **decidim-core**, **decidim-meetings**: Backport 'Fix iframe disabling producing invalid HTML' to v0.27 [\#9805](https://github.com/decidim/decidim/pull/9805) +- **decidim-assemblies**, **decidim-participatory processes**: Backport 'Fix import of images on spaces' to v0.27 [\#9804](https://github.com/decidim/decidim/pull/9804) +- **decidim-core**: Backport 'Fix doorkeeper initialization after 5.6.0 release' to v0.27 [\#9787](https://github.com/decidim/decidim/pull/9787) + +#### Removed Nothing. -### Changed +#### Developer improvements Nothing. -### Fixed +## [0.27.0.rc1](https://github.com/decidim/decidim/tree/0.27.0.rc1) -- **decidim-meetings**: Backport "Fix the meetings export to also include unpublished meetings" to v0.26 [\#8939](https://github.com/decidim/decidim/pull/8939) -- **decidim-system**, **decidim-verifications**: Backport "Fix verification report with multitenants" to v0.26 [\#8940](https://github.com/decidim/decidim/pull/8940) -- **decidim-core**: Backport "Fix officialized user event missing translations" to v0.26 [\#8942](https://github.com/decidim/decidim/pull/8942) -- **decidim-verifications**: Backport "Fix email for verification conflict with managed users" to v0.26 [\#8945](https://github.com/decidim/decidim/pull/8945) -- **decidim-core**: Backport "Fix profile notifications" to v0.26 [\#8949](https://github.com/decidim/decidim/pull/8949) -- **decidim-assemblies**, **decidim-budgets**, **decidim-comments**, **decidim-consultations**, **decidim-core**, **decidim-elections**, **decidim-forms**, **decidim-initiatives**, **decidim-participatory processes**, **decidim-proposals**: Backport several accessibility fixes to v0.26 [\#8950](https://github.com/decidim/decidim/pull/8950) -- **decidim-core**: Backport "Add missing 'Locale' string in i18n in account page" to v0.26 [\#8980](https://github.com/decidim/decidim/pull/8980) -- **decidim-meetings**: Backport "Truncate the meetings card description" to v0.26 [\#8979](https://github.com/decidim/decidim/pull/8979) -- **decidim-proposals**: Backport "Fix proposals' cards with big images" to v0.26 [\#8978](https://github.com/decidim/decidim/pull/8978) -- **decidim-initiatives**: Backport "Fix link to docs in initiatives admin" to v0.26 [\#8975](https://github.com/decidim/decidim/pull/8975) -- **decidim-comments**: Backport "Fix budget hard dependency and caching flag issues in comments" to v0.26 [\#8973](https://github.com/decidim/decidim/pull/8973) -- **decidim-participatory processes**: Backport "Fix processes creation form with stats, metrics and announcements" to v0.26 [\#8977](https://github.com/decidim/decidim/pull/8977) -- **decidim-initiatives**: Backport "Show signatures in answered initiatives" to v0.26 [\#8991](https://github.com/decidim/decidim/pull/8991) -- **decidim-core**: Backport "Add missing reveal__title classes" to v0.26 [\#8999](https://github.com/decidim/decidim/pull/8999) -- **decidim-core**: Backport "Remove the label from the dropdown menu opener" to v0.26 [\#9002](https://github.com/decidim/decidim/pull/9002) -- **decidim-core**: Backport "Fix mobile nav keyboard focus" to v0.26 [\#9001](https://github.com/decidim/decidim/pull/9001) -- **decidim-core**: Backport "Fix main navigation aria-current attribute" to v0.26 [\#9000](https://github.com/decidim/decidim/pull/9000) -- **decidim-core**: Backport "Show character counter when replying to message" to v0.26 [\#9003](https://github.com/decidim/decidim/pull/9003) -- **decidim-core**: Backport "Fix character counter with emoji picker close to maximum characters" to v0.26 [\#9012](https://github.com/decidim/decidim/pull/9012) -- **decidim-api**, **decidim-assemblies**, **decidim-conferences**, **decidim-consultations**, **decidim-initiatives**, **decidim-meetings**, **decidim-participatory processes**, **decidim-proposals**: Backport "Fix API when meetings have proposal linking disabled" to v0.26 [\#8992](https://github.com/decidim/decidim/pull/8992) -- **decidim-core**: Backport "Fix Devise flash messages translation" to v0.26 [\#9043](https://github.com/decidim/decidim/pull/9043) -- **decidim-core**: Backport "Disable new conversation next button when no users selected" to v0.26 [\#9054](https://github.com/decidim/decidim/pull/9054) -- **decidim-initiatives**: Backport "Fix initiatives signatures issues" to v0.26 [\#8974](https://github.com/decidim/decidim/pull/8974) -- **decidim-blogs**, **decidim-core**, **decidim-debates**, **decidim-proposals**: Backport "Fix for endorsed_by with other user group's member" to v0.26 [\#9062](https://github.com/decidim/decidim/pull/9062) -- **decidim-proposals**: Backport "Fix footer actions caching on proposals' card" to v0.26 [\#9063](https://github.com/decidim/decidim/pull/9063) -- **decidim-admin**: Backport "Add missing 'Locale' string in i18n in selective newsletter" to v0.26 [\#9064](https://github.com/decidim/decidim/pull/9064) -- **decidim-core**: Backport "Fix social share button sharing" to v0.26 [\#9065](https://github.com/decidim/decidim/pull/9065) -- **decidim-meetings**: Backport "Use published meetings scope on processes landing and proposal's form" to v0.26 [\#9066](https://github.com/decidim/decidim/pull/9066) -- **decidim-core**: Backport "Require omniauth/rails_csrf_protection explicitly" to v0.26 [\#9067](https://github.com/decidim/decidim/pull/9067) -- **decidim-core**, **decidim-proposals**: Backport "Fix amendable events title" to v0.26 [\#9079](https://github.com/decidim/decidim/pull/9079) -- **decidim-proposals**: Backport "Create admin log records when proposals are imported from a file" to v0.26 [\#9077](https://github.com/decidim/decidim/pull/9077) -- **decidim-comments**, **decidim-core**, **decidim-proposals**: Backport "Add noreferrer and ugc to links" to v0.26 [\#9078](https://github.com/decidim/decidim/pull/9078) -- **decidim-meetings**: Backport "Fix submit in meetings admin form" to v0.26 [\#9076](https://github.com/decidim/decidim/pull/9076) -- **decidim-core**: Backport "Fix session cookie SameSite policy" to v0.26 [\#9059](https://github.com/decidim/decidim/pull/9059) -- **decidim-budgets**, **decidim-core**, **decidim-debates**, **decidim-meetings**, **decidim-proposals**: Backport "Fix cache URLs on cards" to v0.26 [\#9074](https://github.com/decidim/decidim/pull/9074) -- **decidim-assemblies**, **decidim-conferences**, **decidim-consultations**, **decidim-core**, **decidim-initiatives**, **decidim-participatory processes**: Backport "Fix Twitter hashtag search when it starts with a number" to v0.26 [\#9075](https://github.com/decidim/decidim/pull/9075) +### 1. Upgrade notes -### Removed +As usual, we recommend that you have a full backup, of the database, application code and static files. -Nothing. +To update, follow these steps: -### Internal +#### 1.1. Update your Gemfile -- Backport "Fix ActionMailer preview loading" to v0.26 [\#8963](https://github.com/decidim/decidim/pull/8963) -- Backport "Fix flaky spec in meetings multi-date selectors" to v0.26 [\#8976](https://github.com/decidim/decidim/pull/8976) -- Backport "Local HTML validator for the CI" to v0.26 [\#9004](https://github.com/decidim/decidim/pull/9004) -- Backport "Fix API when meetings have proposal linking disabled" to v0.26 [\#8992](https://github.com/decidim/decidim/pull/8992) +```ruby +gem "decidim", "0.27.0.rc1" +gem "decidim-dev", "0.27.0.rc1" +``` -### Developer improvements +#### 1.2. Run these commands -- Backport "Fix Devise configs that depend on Decidim configs" to v0.26 [\#9022](https://github.com/decidim/decidim/pull/9022) -- Backport "Fix Faker address country code in seeds" to v0.26 [\#9046](https://github.com/decidim/decidim/pull/9046) +```console +bundle update decidim +bin/rails decidim:upgrade +bin/rails db:migrate +``` -## [0.26.0](https://github.com/decidim/decidim/tree/v0.26.0) +#### 1.3. Follow the steps and commands detailed in these notes -### Added +### 2. General notes -Nothing. +#### 2.1. Ruby update to 3.0 -### Changed +We have updated the Ruby version to 3.0.2. Upgrading to this version will require either to install the Ruby Version on your host, or change the decidim docker image to use ruby:3.0.2. -- **decidim-comments**: Backport "Show hidden comments replies" to v0.26 [\#8868](https://github.com/decidim/decidim/pull/8868) +You can read more about this change on PR [\#8452](https://github.com/decidim/decidim/pull/8452). -### Fixed +#### 2.2. Rails update to 6.1 -- **decidim-proposals**: Backport "Fix geocoding NaN values" to v0.26 [\#8778](https://github.com/decidim/decidim/pull/8778) -- **decidim-core**: Backport "Add 'nofollow noopener' rel to the profile personal URL" to v0.26 [\#8780](https://github.com/decidim/decidim/pull/8780) -- **decidim-generators**: Backport "Add .keep file to empty directory to include on git committing" to v0.26 [\#8788](https://github.com/decidim/decidim/pull/8788) -- **decidim-core**: Backport "Fix avatar upload validation errors are displayed twice" to v0.26 [\#8798](https://github.com/decidim/decidim/pull/8798) -- **decidim-meetings**: Backport "Fix displaying hidden meetings in homepage's 'upcoming meetings' content block" to v0.26 [\#8819](https://github.com/decidim/decidim/pull/8819) -- **decidim-participatory processes**: Backport "Fix characters not encoded in highlighted participatory processes groups title" to v0.26 [\#8824](https://github.com/decidim/decidim/pull/8824) -- **decidim-comments**: Backport "Fix displaying hidden related resources" to v0.26 [\#8835](https://github.com/decidim/decidim/pull/8835) -- **decidim-generators**: Backport "Add natively a .keep file to empty directory to include on git committing" to v0.26 [\#8836](https://github.com/decidim/decidim/pull/8836) -- **decidim-consultations**, **decidim-core**, **decidim-elections**: Backport "Fix report moderation for all the spaces" to v0.26 [\#8841](https://github.com/decidim/decidim/pull/8841) -- **decidim-meetings**, **decidim-participatory processes**: Backport "Fix displaying hidden meetings in show process page" to v0.26 [\#8843](https://github.com/decidim/decidim/pull/8843) -- **decidim-meetings**: Backport "Fix displaying hidden resources in global search" to v0.26 [\#8850](https://github.com/decidim/decidim/pull/8850) -- **decidim-core**: Backport "Fix activity cell disappearing author images" to v0.26 [\#8848](https://github.com/decidim/decidim/pull/8848) -- **decidim-initiatives**: Backport "Fix scope validation on initiative's creation" to v0.26 [\#8857](https://github.com/decidim/decidim/pull/8857) -- **decidim-accountability**: Backport "Fix accountability categories' colors" to v0.26 [\#8858](https://github.com/decidim/decidim/pull/8858) -- **decidim-debates**: Backport "Remove actions from debates' cards" to v0.26 [\#8861](https://github.com/decidim/decidim/pull/8861) -- **decidim-assemblies**: Backport "Fix assemblies title when there are unpublished children" to v0.26 [\#8860](https://github.com/decidim/decidim/pull/8860) -- **decidim-core**: Backport "Fix cache_hash generation in AuthorCell" to v0.26 [\#8862](https://github.com/decidim/decidim/pull/8862) -- **decidim-meetings**, **decidim-participatory processes**: Backport "Fix displaying hidden meetings in processes group's 'upcoming meetings' content block" to v0.26 [\#8864](https://github.com/decidim/decidim/pull/8864) -- **decidim-assemblies**, **decidim-conferences**, **decidim-consultations**, **decidim-proposals**: Backport "Fix notifications when there is a note proposal in other spaces than processes" to v0.26 [\#8865](https://github.com/decidim/decidim/pull/8865) -- **decidim-proposals**: Backport "Fix answered proposals display" to v0.26 [\#8863](https://github.com/decidim/decidim/pull/8863) -- **decidim-comments**: Backport "Show hidden comments replies" to v0.26 [\#8868](https://github.com/decidim/decidim/pull/8868) -- **decidim-meetings**: Backport "Fix meetings iframe embed code" to v0.26 [\#8884](https://github.com/decidim/decidim/pull/8884) +We have updated the Ruby on Rails version to 6.1. This will be done automatically when doing the `bundle update`. If you had any code customization you'll probably need to take this into account and update your code. Some important aspects to mention: -### Removed +- ActionMailer - Change default queue name of the deliver (:mailers) job to be the job adapter's default (:default) +- ActiveSupport - Remove deprecated fallback to I18n.default_locale when config.i18n.fallbacks is empty. This change should be transparent for all the Decidim users that have configured the `Decidim.default_locale` +- If you are using Spring, it is highly suggested to add the following line at the top of your application's `config/spring.rb` (especially if you are seeing the following messages in the console `ERROR: directory is already being watched!`): -Nothing. +```ruby +require "decidim/spring" +``` -### Internal +You can read more about this change on PR [\#8411](https://github.com/decidim/decidim/pull/8411). -- Backport "Fix flaky test in UpdateAssemblyMember" to v0.26 [\#8803](https://github.com/decidim/decidim/pull/8803) +#### 2.3. Data consent change (aka "cookie consent") -### Developer improvements +Local data consent management has been updated, generally also referred to as "cookie consent". Supported data consent categories are essential, preferences, analytics and marketing. -Nothing. +This feature is many times referred to as "cookie consent" due to historic reasons but in Decidim we prefer to call it "data consent" because this can also include other data stored in the user's browser using its APIs, such as data added to LocalStorage. -## [0.26.0.rc2](https://github.com/decidim/decidim/tree/v0.26.0.rc2) +As many non-technical people are still more familiar with the "cookie" terminology, the user interface talks only about "Cookie consent" to make it easier to understand for non-technical participants. -### Added +Iframe HTML elements that are added with the editor or meeting forms are disabled until data consent is given for all data categories. Scripts that require local data to be stored in the user's browser could be added as follows: -Nothing. -#### Moderated content can now be removed from search index -PR [\#8811](https://github.com/decidim/decidim/pull/8811) is addressing an issue when the moderated resources are not removed from the general search index. +```html + +``` -This will automatically work for new moderated resources. For already existing ones, we have introduced a new task that will remove the moderated content from being displayed in search: +Note that you need to define the `type="text/plain"` for the script that adds local data to the user's browser in order to prevent the script from being executed before data consent is given. You should also define the metadata for all the local data that you or your 3rd party scripts are adding to the user's browser. -```ruby +Mind that we also changed the data consent cookie from "decidim-cc" to "decidim-consent" by default. You can change it on your initializer, or update your legal notice accordingly. + +Learn more about [Data consent at Decidim Documentation](https://docs.decidim.org/en/customize/data_consent). You can read more about this change on PR [\#9271](https://github.com/decidim/decidim/pull/9271). + +#### 2.4. Configuration via Environment Variables + +We've modified the default installation to configure most of the application through Environment Variables. For existing installations we recommend that you migrate to this new model so its easier to configure your applications. + +As an example, after migrating to this, if you want to enable a setting, you'll need to: + +a. Set the correct Environment Variable +b. Restart the server + +Until now the flow could be something like: + +a. Change your initializer +b. Commit to git +c. Push to git server +d. Deploy to the server +e. Restart the server + +For migrating: + +1. Backup your `config/secrets.yml` and `config/initializers/decidim.rb` +1. Generate a new decidim app and copy your generated files +1. Migrate your old settings to the new Environment Variables. + +Learn more about [Environment Variables at Decidim Documentation](https://docs.decidim.org/en/configure/environment_variables/). You can read more about this change on PR [\#8725](https://github.com/decidim/decidim/pull/8725). + +#### 2.5. GraphQL API documentation change + +We've replaced the `graphql-docs` npm package with gem. You shouldn't need to do anything as this will be handled automatically. + +The static documentation will be rendered into the `app/views/static/api/docs` directory, which is being refreshed automatically when you run `bin/rails decidim:upgrade`. + +You can read more about this change on PR [\#8631](https://github.com/decidim/decidim/pull/8631). + +#### 2.6. Custom icons new uploader + +We now only allow PNG images at Favicon so we can provide higher quality versions to mobile devices. + +You can read more about this change on PR [\#8645](https://github.com/decidim/decidim/pull/8645). + +#### 2.7. Strong password rules for admin users + +For extra security, there are new password rules for administrator users which are enabled by default. This means that: + +- This will force the current administrators to change their passwords after 90 days has passed from the previous login. +- For development/testing/staging environments this also means that the default user passwords have changed to `decidim123456789` to match the minimum length rules for admins. +- For consistency reasons, regular users password has also been changed with the seed data. + +The relevant [Environment Variables](https://docs.decidim.org/en/configure/environment_variables/) are: + +| Name | Value | Default value | +| -------- | -------- | -------- | +| DECIDIM_ADMIN_PASSWORD_STRONG | Enable strong password rules for admin users. | true | +| DECIDIM_ADMIN_PASSWORD_EXPIRATION_DAYS | Defines how many days admin passwords are valid before they need to be reset. | 90 | +| DECIDIM_ADMIN_PASSWORD_REPETITION_TIMES | Defines how many previous passwords are compared against new admin user passwords. | 5 | +| DECIDIM_ADMIN_PASSWORD_MIN_LENGTH | The minimum character length for admin user passwords. | 15 | + +You can read more about this change on PR [\#9347](https://github.com/decidim/decidim/pull/9347). + +#### 2.8 Service workers + +For the Progressive Web Application related features, like Push Notifications and Add To Home Screen, you'll need to update your webpack configuration: + +```console +bin/rails decidim:webpacker:install +``` + +You'll need to also add these to your .gitignore: + +```gitignore +public/sw.js +public/sw.js.map +``` + +These files will be generated by the asset compilation task in your production server. Most of the time this should be handled automatically by your deployment process (like Capistrano or Heroku). In case that you need to run that manually, this is the command: + +```console +bin/rails assets:precompile +``` + +In your development environment this should be happening automatically behind the scenes or if you are running the `./bin/webpack-dev-server` manually, during the recompilation process. + +### 3. One time actions + +These are one time actions that need to be done after the code is updated in the production database. + +#### 3.1. Moderated content can now be removed from search index + +We have fixed a bug where moderated resources weren't removed from the general search index. This will automatically work for new moderated resources. For already existing ones, we have introduced a new task that will remove the moderated content from being displayed in search: + +```console bin/rails decidim:upgrade:moderation:remove_from_search ``` -#### Default Decidim app fully configurable via ENV vars +You can read more about this change on PR [\#8811](https://github.com/decidim/decidim/pull/8811). -### Changed +#### 3.2. New Comments statistics structure -Nothing. +We've fixed the stastics of comments in participatory spaces. You'll need to run the task: -### Fixed +```console +bin/rails decidim_comments:update_participatory_process_in_comments +``` -- **decidim-meetings**: Backport "Fix for preview unpublished meetings by admin user" to v0.26 [\#8724](https://github.com/decidim/decidim/pull/8724) -- **decidim-comments**: Backport "Adds emojis when user edits a comment" to v0.26 [\#8743](https://github.com/decidim/decidim/pull/8743) -- **decidim-core**: Backport "Properly mark sender and recipient in Conversation" to v0.26 [\#8746](https://github.com/decidim/decidim/pull/8746) -- **decidim-participatory processes**: Backport "Fix order by weight in processes groups' processes content block" to v0.26 [\#8771](https://github.com/decidim/decidim/pull/8771) -- **decidim-core**: Backport "Don't display blocked users in mentions" to v0.26 [\#8770](https://github.com/decidim/decidim/pull/8770) +You can read more about this change on PR [\#8012](https://github.com/decidim/decidim/pull/8012). -### Removed +#### 3.3. Push Notifications -Nothing. +We've implemented Push Notifications for improving the engagement with the platform. To configure it: -### Internal +##### 3.3.1. Generate the VAPID keys by running the command -- Backport "Revert the i18n-tasks initialization syntax" to v0.26 [\#8696](https://github.com/decidim/decidim/pull/8696) -- Backport "Lock graphql version to 1.12 minor" to v0.26 [\#8695](https://github.com/decidim/decidim/pull/8695) -- Disable codeclimate's stylelint [\#8711](https://github.com/decidim/decidim/pull/8711) +```console +bin/rails decidim:pwa:generate_vapid_keys +``` -### Developer improvements +##### 3.3.2. Copy them to your [Environment Variables](https://docs.decidim.org/en/configure/environment_variables/) file -- Backport "Fix webpacker generator for modules" to v0.26 [\#8750](https://github.com/decidim/decidim/pull/8750) +The relevant [Environment Variables](https://docs.decidim.org/en/configure/environment_variables/) are: -## [0.26.0.rc1](https://github.com/decidim/decidim/tree/v0.26.0.rc1) +| Name | Value | Default value | +| -------- | -------- | -------- | +| VAPID_PUBLIC_KEY | VAPID public key that will be used to sign the Push API requests. | | +| VAPID_PRIVATE_KEY | VAPID private key that will be used to sign the Push API requests. | | -### Migration notes -#### Register assets paths -To prevent Zeitwerk from trying to autoload classes from the `app/packs` folder, it's necesary to register these paths for each module and for the application using the method `Decidim.register_assets_path` on initializers. This is explained in the webpacker migration guides for [applications](https://github.com/decidim/decidim/blob/develop/docs/modules/develop/pages/guide_migrate_webpacker_app.adoc#help-decidim-to-know-the-applications-assets-folder) and [modules](https://github.com/decidim/decidim/blob/develop/docs/modules/develop/pages/guide_migrate_webpacker_module.adoc#help-decidim-to-know-the-modules-assets-folder)), and was implemented in [\#8449](https://github.com/decidim/decidim/pull/8449). +These will be printed to the console when you run the command instructed in the previous step. -#### Unconfirmed access disabled by default -As per [\#8233](https://github.com/decidim/decidim/pull/8233), by default all participants must confirm their email account to sign in. Implementors can change this setting as a [initializer configuration](https://docs.decidim.org/en/configure/initializer/#_unconfirmed_access_for_users): +You can read more about this change on PR [\#8774](https://github.com/decidim/decidim/pull/8774). -```ruby -Decidim.configure do |config| - config.unconfirmed_access_for = 2.days -end +#### 3.4. Categories' description is deprecated + +The `description` field in the categories admin forms has been removed (this applies to any participatory space using categories). For now it's still available in the database, so you can extract it with the following command: + +```console +bin/rails runner -e production 'Decidim::Category.pluck(:id, :name, :description).map { |row| puts row.join(";") }' ``` -#### User workflows change to prevent user enumeration attacks +In the next version (v0.28.0) it will be fully removed from the database. -Until now it was possible to see if an email account was registered in Decidim, by using features like "Forgot your password", as the response changed if the email existed ("`You will receive an email with instructions on how to reset your password in a few minutes`") that's different to a non-existing user account ("`could not be found. Did you sign up previously?`"). This allows User Enumration attacks, where a malicious actor can check if anyone has an acount in the platform. As per [\#8537](https://github.com/decidim/decidim/pull/8537), anyone has the same answer always "`If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes`". +You can read more about this change on PR [\#8617](https://github.com/decidim/decidim/pull/8617). -#### Blocked user in global search +#### 3.5. Global search user by nickname -PR [\#8658](https://github.com/decidim/decidim/pull/8658) Blocked users are present in global search, to update the search and make them disappear, Run in a rails console or create a migration with: +We've added the ability to search for a user by nickname. You'll need to update the existing search index by running this in (be aware that it could take a while if your database has a lot of Users!): -```ruby - Decidim::User.find_each(&:try_update_index_for_search_resource) +```console +bin/rails runner -e production 'Decidim::User.find_each { |u| puts "Processing user #{u.id}" ; u.try_update_index_for_search_resource }' ``` -Please be aware that it could take a while if your database has a lot of Users. +You can read more about this change on PR [\#8658](https://github.com/decidim/decidim/pull/8658). -#### Fix statistics in Comments +#### 3.6. Add CORS policy for dynamic file uploads -As per [#8012](https://github.com/decidim/decidim/pull/8012), for fixing statistic in comments. There's a rake task that you need to run: +This release allows Decidim users to upload files to Decidim dynamically from their browsers. If you are using any external file storage providers, such as Amazon S3, Google Cloud Storage or Azure Storage, you need to configure a CORS policy for these service providers to make the uploads work for the end users. If you are using the default configurations with a local file storage, you don't have to do any extra configuration to make this work. -```ruby -rake decidim_comments:update_participatory_process_in_comments +To configure the CORS policy for each 3rd party service, please refer to the [Active Storage section](https://docs.decidim.org/en/services/activestorage.html) of the documentation. + +You can read more about this change on PR [\#8681](https://github.com/decidim/decidim/pull/8681). + +### 4. Scheduled tasks + +Implementers need to configure these changes it in your scheduler task system in the production server. We give the examples with `crontab`, although alternatively you could use `whenever` gem or the scheduled jobs of your hosting provider. + +#### 4.1. Reminders for participants + +We have added the possibility to send reminders for some actions, like pending budgets orders or user generated meetings that weren't closed. + +```console +# Generate reminders +4 0 * * * cd /home/user/decidim_application && RAILS_ENV=production bundle exec rake decidim:reminders:all +``` + +You can read more about this change on PR [\#8621](https://github.com/decidim/decidim/pull/8621). + +#### 4.2. Mail Notifications digest + +Participants can configure if they want to receive notifications in real-time (one email by any action that they're notified to), or a daily or weekly notifications digest (a highlight with some of the notifications). + +```console +# Send notification mail digest daily +5 0 * * * cd /home/user/decidim_application && RAILS_ENV=production bundle exec rake decidim:mailers:notifications_digest_daily + +# Send notification mail digest weekly on saturdays +5 0 * * 6 cd /home/user/decidim_application && RAILS_ENV=production bundle exec rake decidim:mailers:notifications_digest_weekly ``` -#### Base64 images migration +You can read more about this change on PR [\#8833](https://github.com/decidim/decidim/pull/8833). -As per [\#8250](https://github.com/decidim/decidim/pull/8250), we've replaced the default base64 editor images attachment with the use of ActiveStorage attachments. This PR also adds a task to parse all editor contents and replace existing base64 images with attachments. The task parses all the attributes which can be edited from admin using the WYSIWYG editor. The task requires an argument with the email of an admin used to create EditorImage instances. To run this task execute: +#### 4.3. Rename data portability to download your data +"Data portability" has been renamed to "Download you data". As this was a scheduled task that was already configured you'll need to change it. Where you had: + +```console +# Remove expired data portability files +0 0 * * * cd /home/user/decidim_application && RAILS_ENV=production bundle exec rake decidim:delete_data_portability_files ``` -rails decidim:active_storage_migrations:migrate_inline_images_to_active_storage[admin_email] + +Changes to: + +```console +# Remove expired download your data files +0 0 * * * cd /home/user/decidim_application && RAILS_ENV=production bundle exec rake decidim:delete_download_your_data_files ``` -### Added +You can read more about this change on PR [\#9196](https://github.com/decidim/decidim/pull/9196). -- **decidim-budgets**: Port decidim-budgets improvements from AjuntamentdeBarcelona/decidim [\#8249](https://github.com/decidim/decidim/pull/8249) -- **decidim-elections**: Improve evote admin logs [\#8263](https://github.com/decidim/decidim/pull/8263) -- **decidim-blogs**, **decidim-meetings**: Add card images to meetings and blog posts [\#8276](https://github.com/decidim/decidim/pull/8276) -- **decidim-admin**: Align UI groups filtering with the rest of decidim [\#8105](https://github.com/decidim/decidim/pull/8105) -- **decidim-admin**, **decidim-proposals**: Improve error messages in admin panel [\#8193](https://github.com/decidim/decidim/pull/8193) -- **decidim-elections**: Allow to mark trustees as missing [\#8314](https://github.com/decidim/decidim/pull/8314) -- **decidim-admin**: Add sorting to private participants in a participatory space [\#8242](https://github.com/decidim/decidim/pull/8242) -- **decidim-comments**: Improve control of comments in meetings and debates [\#8027](https://github.com/decidim/decidim/pull/8027) -- **decidim-proposals**: Offer a way to see all proposals in withdrawn proposal list [\#8251](https://github.com/decidim/decidim/pull/8251) -- **decidim-admin**, **decidim-proposals**: Configurable default order for proposals [\#8295](https://github.com/decidim/decidim/pull/8295) -- **decidim-assemblies**: Filter assemblies by assembly type in admin [\#7153](https://github.com/decidim/decidim/pull/7153) -- **decidim-assemblies**: Non participant assembly members avatar [\#8277](https://github.com/decidim/decidim/pull/8277) -- **decidim-core**: Add image file upload in QuillJS editor [\#8250](https://github.com/decidim/decidim/pull/8250) -- **decidim-meetings**: Make meeting report editable by the author in front-end [\#8209](https://github.com/decidim/decidim/pull/8209) -- **decidim-core**: Improve dialog accessibility [\#8294](https://github.com/decidim/decidim/pull/8294) -- **decidim-meetings**: Ability for users to withdraw their meetings [\#8248](https://github.com/decidim/decidim/pull/8248) -- **decidim-admin**: Add colors accessibility warning in admin Appearance [\#8354](https://github.com/decidim/decidim/pull/8354) -- **decidim-proposals**: Import proposal answers [\#8271](https://github.com/decidim/decidim/pull/8271) -- **decidim-core**: Add more actions in QuillJS toolbar [\#8120](https://github.com/decidim/decidim/pull/8120) -- **decidim-meetings**: Add more filter options to directory meetings page [\#8333](https://github.com/decidim/decidim/pull/8333) -- **decidim-assemblies**, **decidim-conferences**, **decidim-participatory processes**: Add filters for Participatory process admins section [\#8106](https://github.com/decidim/decidim/pull/8106) -- **decidim-budgets**: Show modal when user is trying to leave with pending vote [\#8387](https://github.com/decidim/decidim/pull/8387) -- **decidim-meetings**: Meetings iframe visibility [\#8307](https://github.com/decidim/decidim/pull/8307) -- **decidim-budgets**: Add search, filters and sorting to admin panel budget projects [\#8592](https://github.com/decidim/decidim/pull/8592) -- **decidim-core**: Describe the notifications' time with words [\#8564](https://github.com/decidim/decidim/pull/8564) -- **decidim-comments**, **decidim-core**: Add link to comments in Notifications [\#8607](https://github.com/decidim/decidim/pull/8607) -- **decidim-comments**, **decidim-core**: Add full content of comments in notifications [\#8581](https://github.com/decidim/decidim/pull/8581) -- **decidim-core**: Change colors on mobile navigation bar [\#8628](https://github.com/decidim/decidim/pull/8628) -- **decidim-core**, **decidim-proposals**: Add author to proposals in notifications [\#8603](https://github.com/decidim/decidim/pull/8603) -- **decidim-comments**, **decidim-core**, **decidim-meetings**, **decidim-proposals**: Allow participants to receive translated content by email [\#8174](https://github.com/decidim/decidim/pull/8174) -- **decidim-admin**: Add search, filters, pagination and sorting to moderated users [\#8620](https://github.com/decidim/decidim/pull/8620) -- **decidim-surveys**: Add "title and description" in surveys [\#8588](https://github.com/decidim/decidim/pull/8588) +### 5. Changes in APIs -### Changed +#### 5.1. Javascript load at the bottom of the pages -- **decidim-elections**: Validate census CSV headers [\#8264](https://github.com/decidim/decidim/pull/8264) -- **decidim-meetings**: Improve Attendees count error handling on frontend [\#8238](https://github.com/decidim/decidim/pull/8238) -- **decidim-core**: Disable unconfirmed access by default [\#8233](https://github.com/decidim/decidim/pull/8233) -- **decidim-meetings**: Rename 'upcoming events' content block to 'upcoming meetings' [\#8412](https://github.com/decidim/decidim/pull/8412) -- **decidim-core**: Change user workflows to prevent user enumeration attacks [\#8537](https://github.com/decidim/decidim/pull/8537) +For improving performance and load times, we've moved javascript snippets to the bottom of `body` sections. -### Fixed +If you are redefining Decidim layout, using partials including javascript packs, or have the "HTML snippet" option enabled, you might need to review them. -- **decidim-accountability**: Fix accountability notifications proposal title [\#8240](https://github.com/decidim/decidim/pull/8240) -- **decidim-elections**: Remove white spaces in Census [\#8262](https://github.com/decidim/decidim/pull/8262) -- **decidim-debates**, **decidim-meetings**, **decidim-proposals**: Fix characters not encoded in title [\#8253](https://github.com/decidim/decidim/pull/8253) -- **decidim-proposals**: Fix flaky test on proposals splitting [\#8302](https://github.com/decidim/decidim/pull/8302) -- **decidim-core**: Fix invalid i18n values for diff changeset [\#8299](https://github.com/decidim/decidim/pull/8299) -- **decidim-meetings**: Fix live? missing method delegation in online_meeting cell [\#8241](https://github.com/decidim/decidim/pull/8241) -- **decidim-comments**: Fix statistics in Comments [\#8012](https://github.com/decidim/decidim/pull/8012) -- **decidim-budgets**: Fix some explore budgets specs [\#8303](https://github.com/decidim/decidim/pull/8303) -- **decidim-core**: Fix missing icons after CORS [\#8290](https://github.com/decidim/decidim/pull/8290) -- **decidim-core**: Remove unnecessary spacer from external link indicator [\#8291](https://github.com/decidim/decidim/pull/8291) -- **decidim-core**: [CVE-2021-22942] Possible Open Redirect in Host Authorization Middleware [\#8265](https://github.com/decidim/decidim/pull/8265) -- **decidim-debates**: Fix "last comment by" when commenter is a user group [\#8279](https://github.com/decidim/decidim/pull/8279) -- **decidim-proposals**: Similar proposal functionality breaks when the machine translation is enabled. [\#8098](https://github.com/decidim/decidim/pull/8098) -- **decidim-core**: Fix regex that parses users and groups references inside content. [\#8297](https://github.com/decidim/decidim/pull/8297) -- **decidim-assemblies**: Fix birthday attribute type in Assembly Members [\#8311](https://github.com/decidim/decidim/pull/8311) -- **decidim-comments**: Fix issues with dynamic comments polling [\#8317](https://github.com/decidim/decidim/pull/8317) -- **decidim-assemblies**: Fix "Edit" and "View public page" in Assembly Members [\#8312](https://github.com/decidim/decidim/pull/8312) -- **decidim-comments**: Fix "View all comments" link in single comment page [\#8308](https://github.com/decidim/decidim/pull/8308) -- **decidim-budgets**: Fix dont allow budget exceeding in project view [\#8261](https://github.com/decidim/decidim/pull/8261) -- **decidim-debates**: Fix title meta tag for debates [\#8323](https://github.com/decidim/decidim/pull/8323) -- **decidim-proposals**: Fix UserAnswersSerializer for CSV exports [\#8329](https://github.com/decidim/decidim/pull/8329) -- **decidim-admin**: Do not block registered users with InviteUserAgain [\#8268](https://github.com/decidim/decidim/pull/8268) -- **decidim-conferences**: Fix error when accessing the meetings of a conference with speakers related [\#8369](https://github.com/decidim/decidim/pull/8369) -- **decidim-conferences**: Fix details on conference speakers: affiliation order, personal URL link, seeds and more info link [\#8378](https://github.com/decidim/decidim/pull/8378) -- **decidim-meetings**: Define localized fields in Decidim::Meetings:DiffRenderer [\#8381](https://github.com/decidim/decidim/pull/8381) -- **decidim-core**: Include only public entities in the following page [\#8361](https://github.com/decidim/decidim/pull/8361) -- **decidim-proposals**: Any user can access proposal's pages representing the "create a proposal" steps [\#8390](https://github.com/decidim/decidim/pull/8390) -- **decidim-core**: Fix localized faker with single locale [\#8394](https://github.com/decidim/decidim/pull/8394) -- **decidim-core**: Fix user activity page error message with missing username [\#8403](https://github.com/decidim/decidim/pull/8403) -- **decidim-core**: Fix conversation with deleted account [\#8409](https://github.com/decidim/decidim/pull/8409) -- **decidim-core**: Fix javascript exception when geocoding proposals is disabled [\#8413](https://github.com/decidim/decidim/pull/8413) -- **decidim-blogs**: Add missing translations [\#8426](https://github.com/decidim/decidim/pull/8426) -- **decidim-comments**: Refresh comments component after updating [\#8362](https://github.com/decidim/decidim/pull/8362) -- **decidim-core**: Fix webpacker issue when using zeitwerk [\#8444](https://github.com/decidim/decidim/pull/8444) -- **decidim-core**: Improve Zeitwerk assets paths to ignore [\#8449](https://github.com/decidim/decidim/pull/8449) -- **decidim-surveys**: Fix notification after creating survey [\#8463](https://github.com/decidim/decidim/pull/8463) -- **decidim-budgets**, **decidim-comments**: Fix comment's get link in project view [\#8450](https://github.com/decidim/decidim/pull/8450) -- **decidim-elections**: Fix report missing trustee admin log entry [\#8468](https://github.com/decidim/decidim/pull/8468) -- **decidim-system**: Add `pptx` in allowed_file_extensions (of admin) [\#8502](https://github.com/decidim/decidim/pull/8502) -- **decidim-core**: Fix 404 link in 'how to participate' home content block [\#8513](https://github.com/decidim/decidim/pull/8513) -- **decidim-meetings**: Fix meetings with multiple dates [\#8497](https://github.com/decidim/decidim/pull/8497) -- **decidim-core**: Fix pt-BR issue [\#8523](https://github.com/decidim/decidim/pull/8523) -- **decidim-generators**: Freezing webpacker to RC.5 until RC.7 is fixed [\#8531](https://github.com/decidim/decidim/pull/8531) -- **decidim-conferences**: Fix conference speakers when there isn't any avatar [\#8520](https://github.com/decidim/decidim/pull/8520) -- **decidim-assemblies**, **decidim-participatory processes**: Fix the copy of components weights in participatory processes and assemblies [\#8498](https://github.com/decidim/decidim/pull/8498) -- **decidim-meetings**: Fix meetings input when rich text editor is disabled [\#8534](https://github.com/decidim/decidim/pull/8534) -- **decidim-meetings**: Fix showing created meetings in 'my public profile' [\#8519](https://github.com/decidim/decidim/pull/8519) -- **decidim-meetings**, **decidim-proposals**: Fix various proposal picker issues when there are thousands of proposals [\#8558](https://github.com/decidim/decidim/pull/8558) -- **decidim-core**: Remove border on all the fieldsets [\#8561](https://github.com/decidim/decidim/pull/8561) -- **decidim-initiatives**: Remove wrong in initiatives header [\#8563](https://github.com/decidim/decidim/pull/8563) -- **decidim-core**: Fix CSS layout wrapper top padding [\#8562](https://github.com/decidim/decidim/pull/8562) -- **decidim-forms**, **decidim-surveys**: Fix duplicated answers in surveys [\#8560](https://github.com/decidim/decidim/pull/8560) -- **decidim-meetings**: Fix the meeting copy functionality [\#8430](https://github.com/decidim/decidim/pull/8430) -- **decidim-core**: Move social login buttons to the top of the login modal [\#8574](https://github.com/decidim/decidim/pull/8574) -- **decidim-comments**, **decidim-meetings**: Fix HTML injection in comments and meeting's description [\#8511](https://github.com/decidim/decidim/pull/8511) -- **decidim-core**: Fix avatar thumbnail in participants' profile [\#8577](https://github.com/decidim/decidim/pull/8577) -- **decidim-core**: Rename index to avoid conflicts with decidim_awesome module migrations [\#8613](https://github.com/decidim/decidim/pull/8613) -- **decidim-core**: Fix group mentions in notifications [\#8598](https://github.com/decidim/decidim/pull/8598) -- **decidim-forms**, **decidim-surveys**: Fix surveys exports with free text in multiple option [\#8582](https://github.com/decidim/decidim/pull/8582) -- **decidim-core**: Fix reply to a conversation with deleted participants [\#8635](https://github.com/decidim/decidim/pull/8635) -- **decidim-admin**, **decidim-debates**, **decidim-proposals**: Fix consistency in creation actions phrasing: "Participants can create XXX" [\#8650](https://github.com/decidim/decidim/pull/8650) -- **decidim-core**: Fix wrong display of deleted accounts in conversations [\#8641](https://github.com/decidim/decidim/pull/8641) -- **decidim-core**: Fix cache key on ActivityCell [\#8654](https://github.com/decidim/decidim/pull/8654) -- **decidim-participatory processes**: Fix participatory groups leaks on other organizations/tenants [\#8651](https://github.com/decidim/decidim/pull/8651) -- **decidim-core**: Fix blocked users appear in search [\#8658](https://github.com/decidim/decidim/pull/8658) -- **decidim-meetings**: Don't start poll meetings component when DOM elements are not present [\#8676](https://github.com/decidim/decidim/pull/8676) -- **decidim-initiatives**, **decidim-proposals**: Fix initiative attachments [\#7452](https://github.com/decidim/decidim/pull/7452) -- **decidim-assemblies**: Fix performance issues on assemblies page when having many private users [\#8509](https://github.com/decidim/decidim/pull/8509) -- **decidim-proposals**: Add location data to proposals export and import [\#8679](https://github.com/decidim/decidim/pull/8679) -- **decidim-meetings**: Fix meetings form embed type visibility [\#8602](https://github.com/decidim/decidim/pull/8602) -- **decidim-meetings**: Do not send upcoming meeting events notification for past events [\#8665](https://github.com/decidim/decidim/pull/8665) +Also, you can no longer call jQuery or any other library in your views directly. For example the following snippet won't work: -### Removed +```javascript + +``` -- **decidim-proposals**: Remove "Allow card image" setting from Proposals [\#8281](https://github.com/decidim/decidim/pull/8281) -- **decidim-assemblies**: Remove designation_mode field from Assembly Members [\#8310](https://github.com/decidim/decidim/pull/8310) -- **decidim-participatory processes**: Remove admin show page in Participatory Process Groups [\#8313](https://github.com/decidim/decidim/pull/8313) +Instead of that, you should encapsulate it in a `content_for(:js_content)` block, that will render the snippet +right after javascript bundles have been loaded. + +```javascript +<% content_for(:js_content) do %> + +<% end %> +``` -### Developer improvements +You can read more about this change on PR [\#9156](https://github.com/decidim/decidim/pull/9156). -- Fix Luxembourgish locale [\#8270](https://github.com/decidim/decidim/pull/8270) -- Fix ARIA roles for dialogs and tooltips [\#8293](https://github.com/decidim/decidim/pull/8293) -- Add selectors on edit_form_fields [\#8353](https://github.com/decidim/decidim/pull/8353) -- Fix HTTPOnly and secure flag on the cookie acceptance cookie [\#8358](https://github.com/decidim/decidim/pull/8358) -- Add Brakeman to GitHub Actions for improving security [\#6832](https://github.com/decidim/decidim/pull/6832) -- Disallow redirection to the host when performing redirect_back [\#8296](https://github.com/decidim/decidim/pull/8296) -- Improve performance on the serializers by using includes, query counter [\#8278](https://github.com/decidim/decidim/pull/8278) -- Enforce redirects to include the organization host [\#8385](https://github.com/decidim/decidim/pull/8385) -- Fix issues with the session/environment security configs [\#8360](https://github.com/decidim/decidim/pull/8360) -- Improve extendability on some controllers [\#8398](https://github.com/decidim/decidim/pull/8398) -- Add avatar eager logging to UserEntityFinder #8416 [\#8417](https://github.com/decidim/decidim/pull/8417) -- Increase text contrast in current phase of a participatory process [\#8422](https://github.com/decidim/decidim/pull/8422) -- Fix CVE-2021-41136 (HTTP Request Smuggling in puma) [\#8431](https://github.com/decidim/decidim/pull/8431) -- Remove anchored dependency [\#8453](https://github.com/decidim/decidim/pull/8453) -- Fix pt-BR issue [\#8523](https://github.com/decidim/decidim/pull/8523) -- Add rendered view instrumentation information [\#8530](https://github.com/decidim/decidim/pull/8530) -- Optimize open data exporter for large amount of data [\#8503](https://github.com/decidim/decidim/pull/8503) -- Add cache key separator to cache_hash [\#8559](https://github.com/decidim/decidim/pull/8559) -- Improve generation of the opendata export [\#8593](https://github.com/decidim/decidim/pull/8593) -- Add several cache keys to cells [\#8566](https://github.com/decidim/decidim/pull/8566) -- Update password strength check [\#8455](https://github.com/decidim/decidim/pull/8455) -- Remove etherpad-lite dependency [\#8541](https://github.com/decidim/decidim/pull/8541) -- Fix Rack::Attack initializer custom parameter configuration [\#8643](https://github.com/decidim/decidim/pull/8643) +#### 5.2. Dynamic attachment uploads -### Internal +We've changed the way file uploads work in Decidim. Files are now dynamically uploaded inside the modal so we can give the user immediate feedback on validation. If you didn't have any customization involving file uploads you can ignore this. + +There are now two different types of file fields: titled and untitled. Titled file fields related to ```Decidim::Attachment``` internally. + +**To update your module** you probably have to update forms and commands related to upload field (also views should be updated in case of titled attachments). After successful a upload and submitting a form, request params should contain signed_id of [ActiveStorage::Blob](https://api.rubyonrails.org/classes/ActiveStorage/Blob.html) which you need to find the blob at the backend. Some examples: + +- To update view with titled file field see example: [edit_form_fields.html.erb](https://github.com/decidim/decidim/pull/8681/files#diff-17a22480fdfa3d439edcb26eb0a1a52bed5521d61ba36e0cc6ca83e838f03e9b) +- To update untitled form example: [import_form.rb](https://github.com/decidim/decidim/pull/8681/files#diff-5ce71b5873906c6f8919f4bc1f8c330bd97e8757760705a66c789f375eb743c1) +- To update untitled command example: [update_account.rb](https://github.com/decidim/decidim/pull/8681/files#diff-ed1274f76cd0ac1d5b223648dcdae670c2127c7dffa0d38540c1536a86f36abb) -- Fix dependencies locks after 0.26.0.dev bump [\#8247](https://github.com/decidim/decidim/pull/8247) -- Add modules recommendations in documentation [\#8218](https://github.com/decidim/decidim/pull/8218) -- Fix webpacker dependency lock [\#8272](https://github.com/decidim/decidim/pull/8272) -- Improve README with examples [\#8244](https://github.com/decidim/decidim/pull/8244) -- Update foundation-sites to 6.7.0 for better Dart Sass compatibility [\#8273](https://github.com/decidim/decidim/pull/8273) -- Fix NPM packages versioning during release process [\#8280](https://github.com/decidim/decidim/pull/8280) -- Add 'Lint PR title' workflow to CI [\#8285](https://github.com/decidim/decidim/pull/8285) -- Don't trigger PR linting on pushes, only on PRs [\#8304](https://github.com/decidim/decidim/pull/8304) -- Prevent root package.json to be treated as a package [\#8315](https://github.com/decidim/decidim/pull/8315) -- Fix CSS validation tests caused by a bug on the validation service [\#8322](https://github.com/decidim/decidim/pull/8322) -- **decidim-core**: Remove npm decidim packages with dependencies from other decidim packages [\#8330](https://github.com/decidim/decidim/pull/8330) -- **decidim-core**: Fix problems introduced by #8330 [\#8341](https://github.com/decidim/decidim/pull/8341) -- Update Node and NPM version [\#8343](https://github.com/decidim/decidim/pull/8343) -- Remove hack for CSS validation [\#8326](https://github.com/decidim/decidim/pull/8326) -- Update docs in migrating to webpacker [\#8349](https://github.com/decidim/decidim/pull/8349) -- **decidim-comments**: Ignore errors during comments migration task [\#8351](https://github.com/decidim/decidim/pull/8351) -- **decidim-meetings**: Fix published and title in seeded meetings [\#8359](https://github.com/decidim/decidim/pull/8359) -- **decidim-core**: Fix SQL to make version display faster [\#8393](https://github.com/decidim/decidim/pull/8393) -- Remove GraphQL deprecated API call [\#8432](https://github.com/decidim/decidim/pull/8432) -- **decidim-generators**: Fixing generator webpacker issues [\#8427](https://github.com/decidim/decidim/pull/8427) -- **decidim-generators**: Fix railties requirements on created applications [\#8415](https://github.com/decidim/decidim/pull/8415) -- **decidim-core**: Update omniauth gem and dependencies [\#8388](https://github.com/decidim/decidim/pull/8388) -- Document how to enable machine translations on organization [\#8458](https://github.com/decidim/decidim/pull/8458) -- **decidim-dev**: Improves manual installation documentation [\#8508](https://github.com/decidim/decidim/pull/8508) -- Update the i18n-tasks initialization syntax [\#8544](https://github.com/decidim/decidim/pull/8544) -- Documentation: improve develop section [\#8553](https://github.com/decidim/decidim/pull/8553) -- Change default window size in Capybara configuration [\#8576](https://github.com/decidim/decidim/pull/8576) -- Fix security instructions [\#8587](https://github.com/decidim/decidim/pull/8587) -- Temporarily ignore CSS validation issue in CI [\#8597](https://github.com/decidim/decidim/pull/8597) -- Update nokogiri to 1.12.5 [\#8609](https://github.com/decidim/decidim/pull/8609) -- Update paper_trail to 12.1 [\#8608](https://github.com/decidim/decidim/pull/8608) -- Update ruby to 2.7.5 [\#8629](https://github.com/decidim/decidim/pull/8629) -- Remove truncato dependency [\#8507](https://github.com/decidim/decidim/pull/8507) -- Change figaro to rbenv-vars in "manual installation" documentation [\#8575](https://github.com/decidim/decidim/pull/8575) -- Add instructions PostgreSQL configuration in development app [\#8618](https://github.com/decidim/decidim/pull/8618) -- Fix etherpad doc reference in initializer [\#8632](https://github.com/decidim/decidim/pull/8632) -- Clarifies git branches conventions in doc [\#8644](https://github.com/decidim/decidim/pull/8644) -- Fix changelog link [\#8671](https://github.com/decidim/decidim/pull/8671) -- Enable simplecov only for rspec step [\#8674](https://github.com/decidim/decidim/pull/8674) -- **decidim-dev**: Improve machine translation documentation and comments [\#8668](https://github.com/decidim/decidim/pull/8668) -- Split the workflows files for CI [\#8675](https://github.com/decidim/decidim/pull/8675) -- DRY GitHub workflows with composite actions [\#8677](https://github.com/decidim/decidim/pull/8677) -- Change Gitter to Matrix.org in documentation [\#8466](https://github.com/decidim/decidim/pull/8466) +Learn more about [Direct Uploads at Rails Documentation](https://edgeguides.rubyonrails.org/active_storage_overview.html#direct-uploads). You can read more about this change on PR [\#8681](https://github.com/decidim/decidim/pull/8681). + +Module developers should also notice that when using `<%= form.upload :file %>` in your views, these fields are now automatically converted to dynamic upload fields. Regarding this, you will need to do a couple of changes in your code: + +1. In your form classes, specify the attribute type as `Decidim::Attributes::Blob`, e.g. `attribute :file, Decidim::Attributes::Blob` +1. In your system tests, you might have previously used something like `attach_file(:your_form_file, file_fixture("your-test-file.xyz"))` to attach your file. Change these to `dynamically_attach_file(:your_form_file, file_fixture("your-test-file.xyz"))` in order to let the test helper handle the attachment for you as it has a few steps. +1. In other tests (such as commands, controllers, etc.), you might have previously used something like `fixture_file_upload(file_fixture("your-test-file.xyz"), "text/plain")`. This will not work anymore after you do the changes in the forms as they now expect either blobs or blob signed ID references. To fix this, replace these with `upload_test_file(Rack::Test::UploadedFile.new(file_fixture("your-test-file.xyz"), "text/plain"))`. +1. If you need to process files locally within your form classes or commands, you need to include the `Decidim::ProcessesFileLocally` concern and use the method it provides `process_file_locally(blob)` to get local access to the files that may be stored at 3rd party file storages. The method takes the ActiveStorage Blob as an argument and yields the path to the local file for the provided block argument. + +#### 5.3. `Decidim::Form`s no longer use `Rectify::Form` and `Virtus` should be no longer used + +If you don't have any customization involving Forms or `Virtus` you can ignore this. + +As per [\#8669](https://github.com/decidim/decidim/pull/8669), your `Decidim::Form`s will no longer use `Rectify::Form` or `Virtus.model` attributes because `Virtus` is discontinued and Decidim is loosening the dependency on the `virtus` gem. Instead, the attributes implementation is now based on [`ActiveModel::Attributes`](https://api.rubyonrails.org/classes/ActiveModel/Attributes/ClassMethods.html) with an integration layer within Decidim that aims to provide as much backwards compatibility as possible with the `Virtus.model` attributes that were previously used. + +For most cases, no changes in the code should be needed but there are specific differences with the implementation which may require changes in the 3rd party code as well. Both `Rectify::Form` and `Virtus` will be still available in the core (through the `rectify` gem) but you should migrate away from them as soon as possible as they may be removed in future versions of Decidim. + +There are specific things that you need to change regarding your Form or `Virtus.model` classes when migrating to `Decidim::AttributeObject`: + +- Change all instances of `YourForm < Rectify::Form` to `YourForm < Decidim::Form`. It should be very rare to find any classes in your code that inherit directly from `Rectify::Form` but in case you have used that, replace those references with `Decidim::Form`. +- Change all instances of `include Virtus.model` to `include Decidim::AttributeObject::Model`. +- For all file objects that may be of type `String` or `ActionDispatch::Http::UploadedFile`, remove the `String` type casting from these attributes as otherwise the uploaded file objects would be converted to strings. In other words, change all `attribute :uploaded_image, String` definitions within the forms to `attribute :uploaded_image` which allows them to be of any type. +- Change all `attribute :attr_name, Hash` to `attribute :attr_name, Hash[Symbol => ExpectedType]` where `ExpectedType` is the type you are expecting the hash values to be. The new layer will default the hash key types to `Symbol` and hash value types to `Object` (= any type). The Virtus Hash attribute did not force any default types for these. It should be preferred to use the actual expected type for the values instead of `Object` (= any type) to make your code more robust and less buggy. +- Change all `attribute :attr_name, Array` to `attribute :attr_name, Array[ExpectedType]` where `ExpectedType` is the type you are expecting the array values to be. It should be preferred to use the actual expected type for the values instead of `Object` (= any type) to make your code more robust and less buggy. +- The original form attribute values are no longer available through the `@attr_name` instance variables within the Form or `Virtus.model` classes. Instead, change all these references to `@attributes["attr_name"].value` in case you want to fetch the original value of the attribute without using its accessor method. Another way is to provide an alias for the original attribute method before overriding it. If you have not overridden the original attribute accessor, simply remove the `@` character in front of the attribute name to fetch the attribute value using the original accessor method. +- When calling the `attributes` method of the model/form classes, use strings to refer to the attribute names, not symbols as you might have done with `Virtus` or `Rectify::Form`. Change all `model.attributes[:attr_name]` method calls to `model.attributes["attr_name"]`. +- When calling `model.attributes.slice(...)`, you also need to use strings to refer to the attribute keys. Change all instances of `model.attributes.slice(:attr1, :attr2)` to `model.attributes.slice("attr1", "attr2")` +- If you had overridden any of the [`Rectify::Form` methods](https://github.com/andypike/rectify/blob/v0.13.0/lib/rectify/form.rb) within your form classes, remove those overrides. For example, you might have overridden the `form_attributes_valid?` method which no longer does anything. Instead, define a custom validation in order to add extra validations to your forms. +- Very rarely, when defining a an attribute of type `Rails::Engine`, you need to change `attribute :attr_name, Rails::Engine` to `attribute :attr_name, Rails::Engine, **{}`. This is because we want to preserve the method signature against `ActiveModel::Attributes` for the `attribute` class method intead of the legacy `Virtus.model`. There is a limitation in the Ruby language that if the method has default values for the previous arguments and defines keyword arguments, the last argument will always receive a `respond_to?(:to_hash)` call to it which doesn't work for `Rails::Engine` (you can try it out in the Rails console by calling `Rails::Engine.respond_to?(:to_hash)`). +- Test all your form and command classes thoroughly to notice any differences between the two implementations. The new layer is a bit more "robust" with some of the type castings, so some things may break during the migration in case you have relied on some of the oversights within `Virtus`. + +#### 5.4. `Rectify::Presenter` deprecated + +PR [\#8758](https://github.com/decidim/decidim/pull/8758) is deprecating the implementation of `Rectify::Presenter` in favour of `SimpleDelegator` + +#### 5.5. Searchlight removal + +The `searchlight` gem has been removed in favor of Ransack as of [\#8748](https://github.com/decidim/decidim/pull/8748) in order to standardize all searches within Decidim around a single way of performing searches. Ransack was selected as the preferred search backend because it is better maintained and has a larger community of developers around it compared to Searchlight. + +Ransack provides a search API that produces the search queries semi-automatically against the available database columns and ActiveRecord scopes made available for the Ransack searches while Searchlight used to require to write all the search logic manually in the search classes. Due to the inner workings of the Ransack gem and for consistency reasons, the following changes have been made for the search filtering: + +- For search scopes that are doing more than matching against a specific column in the database or require special programming logic during the searches, there is a new scope convention introduced with the `with_*` and `with_any_*` scope names. The `with_*` convention should be used when providing a search scope that searches against one key, such as `with_category(1)` and the `with_any_*` convention should be used when providing a search scope that searches against one or multiple keys, such as `with_any_category(1, 2, 3)`. + - An example of such scope is `with_any_category` provided by the `HasCategory` concern which searches against the provided category IDs or any sub-category of those category IDs. You can find all the introduced (or changed) scopes by searching for `scope :with_` within the Decidim codebase. + - With Searchlight, these search parameters were provided e.g. as `category_id` which was then used to perform the explained search query manually in the ResourceSearch class which is now used for a different purpose. As the search now happens through Ransack and the ActiveRecord scopes, these parameters have been renamed to better explain what they do. With Ransack, matching e.g. against the `category_id_eq` key would mean that the search is done against this specific column in the record's database table and only searching for the provided search input (and not e.g. the parent categories in the category case). +- The origin scopes provided by `Decidim::Authorable` and `Decidim::Coauthorable` have been renamed with the `with_` prefix as explained above. +- All the filtering key changes have been reflected to the participant filtering views (`_filters.html.erb` in most modules) as well as the controller methods `default_filter_params` where applicable. +- The `default_filter_params` method within the participant-facing controllers now defines all the parameters that are allowed in the search queries and only these parameters are passed to the Ransack search. This limitation is made in order to protect the participant views from providing more searching options through the URL parameters than they are supposed to provide. In the past, the `Searchlight::Search` classes took care of utilizing only the allowed parameters but Ransacker does not have any middle-layer that would do the same, which is why the limitation is done at the controller side. +- The `search_collection` method now defines the base collection used for the searches within the filtering controllers. In previous versions, there used to be a method that defined a `search_klass` method that defined the `Searchlight::Search` class to be used as the basis for the search. Now, the `search_collection` defines the base collection instead against which the Ransack search is run. + +3rd party developers that have developed their own modules or customizations for the core controllers or filtering views, should revisit their customizations and make sure they reflect these changes made for the controllers or filtering views. It is suggested to remove the customizations related to the filtering views/controllers and re-do from scratch what needs to be customized in order to ensure full compatibility with the changed filtering APIs. In case you had created your own `Searchlight::Search` (or `ResourceSearch`) classes, you should scrap those and start over using Ransack. + +More information on using Ransack can be found from the [Ransack documentation](https://github.com/activerecord-hackery/ransack). You can find examples for filtering in the core filtering views and controllers. + +Related changes include: + +- **decidim-core**: The `Decidim::ActivitySearch` class has been rewritten as `Decidim::PublicActivities` which is now a `Rectify::Query` class instead of `Searchlight::Search` class due to the removal of Searchlight at [\#8748](https://github.com/decidim/decidim/pull/8748). +- **decidim-core**: The `Decidim::ResourceSearch` class now inherits from `Ransack::Search` instead of `Searchlight::Search` as of [\#8748](https://github.com/decidim/decidim/pull/8748). The new `ResourceSearch` class provides extra search functionality for contextual searches that require context information in addition to the search parameters, such as current user or current component. It has barely anything to do with the `ResourceSearch` class in the previous versions which contained much more logic. Please review all your search classes that were inheriting from this class. You should migrate your search filtering to Ransack. +- **decidim-debates**, **decidim-initiatives**, **decidim-meetings**: The resource search classes `Decidim::Debates::DebateSearch`, `Decidim::Intitatives::InitiativeSearch` and `Decidim::Meetings::MeetingSearch` are rewritten for the Ransack searches due to Searchlight removal at [\#8748](https://github.com/decidim/decidim/pull/8748). The role of these classes is now to pass contextual information to the searches, such as the current user. All other search filtering should happen directly through Ransack. +- **decidim-meetings**: The `visible_meetings_for` scope for the `Meeting` model has been renamed to `visible_for` in [\#8748](https://github.com/decidim/decidim/pull/8748) for consistency. +- **decidim-core**: The `official_origin`, `participants_origin`, `user_group_origin` and `meeting_origin` scopes for the `Decidim::Authorable` and `Decidim::Coauthorable` concerns have been changed to `with_official_origin`, `with_participants_origin`, `with_user_group_origin` and `with_meeting_origin` respectively in [\#8748](https://github.com/decidim/decidim/pull/8748) for consistency. See the Searchlight removal change notes for reasoning. +- **decidim-core**: Nicknames are now differents case insensitively, a rake task has been created to check every nickname and modify them if some are similar (Launch it with "bundle exec rake decidim:upgrade:fix_nickname_uniqueness"). Routing and mentions has been made case insensitive for every tab in profiles. + +### Detailed changes + +#### Added + +- **decidim-core**: Implement service workers and custom offline fallback page [\#8594](https://github.com/decidim/decidim/pull/8594) +- **decidim-core**: Add emojis to Conversations [\#8735](https://github.com/decidim/decidim/pull/8735) +- **decidim-budgets**, **decidim-core**: Add reminders for pending orders in budgets [\#8621](https://github.com/decidim/decidim/pull/8621) +- **decidim-core**: Add favicon pwa uploader and icons in manifest [\#8645](https://github.com/decidim/decidim/pull/8645) +- **decidim-core**: Allow users to be searched by nickname [\#8663](https://github.com/decidim/decidim/pull/8663) +- **decidim-core**: Add items to set a splash screen [\#8649](https://github.com/decidim/decidim/pull/8649) +- **decidim-core**: Add VAPID keys' generator for webpush notifications [\#8738](https://github.com/decidim/decidim/pull/8738) +- **decidim-core**: Add anchors on the homepage [\#8756](https://github.com/decidim/decidim/pull/8756) +- **decidim-admin**, **decidim-assemblies**, **decidim-participatory processes**: Add a privacy warning on non-transparent private spaces [\#8753](https://github.com/decidim/decidim/pull/8753) +- **decidim-core**: Show the Add2HomeScreen option in compatible browsers [\#8736](https://github.com/decidim/decidim/pull/8736) +- **decidim-assemblies**: Allow assembly admins administer children assemblies [\#8773](https://github.com/decidim/decidim/pull/8773) +- **decidim-core**: Dynamic attachment uploads [\#8681](https://github.com/decidim/decidim/pull/8681) +- **decidim-participatory processes**: Create process types to allow filtering Processes by them [\#8583](https://github.com/decidim/decidim/pull/8583) +- **decidim-core**: Accessible character counter for screen readers [\#9009](https://github.com/decidim/decidim/pull/9009) +- **decidim-budgets**, **decidim-core**: Show users own voting activity [\#8914](https://github.com/decidim/decidim/pull/8914) +- **decidim-core**: Add autocomplete attribute to Devise fields [\#9038](https://github.com/decidim/decidim/pull/9038) +- **decidim-core**: Allow admins to disable email notifications for reported users [\#9072](https://github.com/decidim/decidim/pull/9072) +- **decidim-meetings**: Add reminders for publishing reports to meeting authors [\#8757](https://github.com/decidim/decidim/pull/8757) +- **decidim-meetings**: Export calendar improvements [\#9035](https://github.com/decidim/decidim/pull/9035) +- **decidim-core**: Remove all the private participants from a participatory space [\#8866](https://github.com/decidim/decidim/pull/8866) +- **decidim-core**: Performance: replace moment by dayjs [\#9161](https://github.com/decidim/decidim/pull/9161) +- **decidim-assemblies**, **decidim-conferences**, **decidim-core**, **decidim-meetings**, **decidim-participatory processes**: Homepage optimization: tune images' caches and query includes [\#9145](https://github.com/decidim/decidim/pull/9145) +- **decidim-accountability**, **decidim-assemblies**, **decidim-conferences**, **decidim-core**, **decidim-elections**, **decidim-meetings**, **decidim-proposals**: Cache highlighted resources for components cells [\#9143](https://github.com/decidim/decidim/pull/9143) +- **decidim-core**: Can resend and cancel email confirmation [\#8996](https://github.com/decidim/decidim/pull/8996) +- **decidim-core**: Performance optimization: load JavaScript at page's bottom [\#9156](https://github.com/decidim/decidim/pull/9156) +- **decidim-meetings**: Configure online meetings embedded services with ENV vars [\#9219](https://github.com/decidim/decidim/pull/9219) +- **decidim-elections**: Add an option to hide the "Can I vote?" page [\#9191](https://github.com/decidim/decidim/pull/9191) +- **decidim-core**: Add autocomplete in user account [\#9217](https://github.com/decidim/decidim/pull/9217) +- **decidim-budgets**: Bulk actions for budgeting projects in admin panel [\#8986](https://github.com/decidim/decidim/pull/8986) +- **decidim-comments**: Load comments with ajax [\#9144](https://github.com/decidim/decidim/pull/9144) +- **decidim-admin**, **decidim-participatory processes**: Add admin log when importing, exporting and duplicating a process [\#9244](https://github.com/decidim/decidim/pull/9244) +- **decidim-core**: Mail notifications digest [\#8833](https://github.com/decidim/decidim/pull/8833) +- **decidim-core**: Send push notifications to client [\#8774](https://github.com/decidim/decidim/pull/8774) +- **decidim-admin**, **decidim-core**: Add admin log when updating component or its permissions [\#9270](https://github.com/decidim/decidim/pull/9270) +- **decidim-admin**, **decidim-core**: Add admin log when creating, updating or deleting attachment collections [\#9276](https://github.com/decidim/decidim/pull/9276) +- **decidim-initiatives**: Add admin log when creating, updating or deleting initiative types [\#9310](https://github.com/decidim/decidim/pull/9310) +- **decidim-admin**: Add admin log when creating, updating or deleting scope types [\#9312](https://github.com/decidim/decidim/pull/9312) +- **decidim-accountability**: Add admin log when creating, updating or deleting accountability's status [\#9320](https://github.com/decidim/decidim/pull/9320) +- **decidim-admin**, **decidim-assemblies**: Add admin log when duplicating, exporting or importing assemblies [\#9338](https://github.com/decidim/decidim/pull/9338) +- **decidim-admin**: Add admin log when creating, updating or deleting area types [\#9316](https://github.com/decidim/decidim/pull/9316) +- **decidim-accountability**, **decidim-admin**: Add admin log when creating, updating or deleting accountability's timeline entries [\#9321](https://github.com/decidim/decidim/pull/9321) +- **decidim-admin**, **decidim-core**: Add admin log when creating, updating or deleting attachments [\#9282](https://github.com/decidim/decidim/pull/9282) +- **decidim-core**: Group creator can leave group [\#9315](https://github.com/decidim/decidim/pull/9315) +- **decidim-meetings**: Short URLs to fix long export calendar URLs [\#9383](https://github.com/decidim/decidim/pull/9383) +- **decidim-core**: Accept and reject cookies [\#9271](https://github.com/decidim/decidim/pull/9271) +- **decidim-admin**: Add admin log when creating, updating or deleting categories [\#9317](https://github.com/decidim/decidim/pull/9317) +- **decidim-admin**: Add admin log when updating external domains or help sections [\#9339](https://github.com/decidim/decidim/pull/9339) +- **decidim-templates**: Add admin log when creating, deleting, duplicating and updating templates [\#9363](https://github.com/decidim/decidim/pull/9363) +- **decidim-forms**: Add admin log when updating survey questionnaire [\#9385](https://github.com/decidim/decidim/pull/9385) +- **decidim-meetings**: Add admin log when updating the meeting questionnaire [\#9273](https://github.com/decidim/decidim/pull/9273) +- **decidim-admin**, **decidim-core**: Add admin log when exporting a component [\#9390](https://github.com/decidim/decidim/pull/9390) +- **decidim-blogs**: Add admin log when creating, updating and deleting blog posts [\#9386](https://github.com/decidim/decidim/pull/9386) +- **decidim-comments**, **decidim-initiatives**: Add configuration option for initiative type to deactivate comments [\#9318](https://github.com/decidim/decidim/pull/9318) +- **decidim-initiatives**: Add order setting to initiatives [\#9377](https://github.com/decidim/decidim/pull/9377) +- **decidim-api**, **decidim-blogs**: Add official blog posts [\#9429](https://github.com/decidim/decidim/pull/9429) +- **decidim-core**: External link improvements [\#9402](https://github.com/decidim/decidim/pull/9402) +- **decidim-admin**, **decidim-core**: Strong passwords for admins [\#9347](https://github.com/decidim/decidim/pull/9347) +- **decidim-budgets**: Add geocoding to budgets projects [\#9280](https://github.com/decidim/decidim/pull/9280) + +#### Changed + +- **decidim-admin**: Change default sort order on admin moderations [\#8667](https://github.com/decidim/decidim/pull/8667) +- **decidim-debates**, **decidim-meetings**, **decidim-proposals**: Replace 'citizens' terminology with 'participants' [\#8697](https://github.com/decidim/decidim/pull/8697) +- **decidim-core**, **decidim-elections**, **decidim-initiatives**, **decidim-proposals**, **decidim-system**, **decidim-verifications**: Change to a inclusive language: replace he/she/his/her with they/their [\#8684](https://github.com/decidim/decidim/pull/8684) +- **decidim-generators**: Make Decidim fully configurable via ENV vars [\#8725](https://github.com/decidim/decidim/pull/8725) +- **decidim-core**: Replace Decidim mentions in UI with 'the platform' [\#8827](https://github.com/decidim/decidim/pull/8827) +- **decidim-admin**: Clarify the locales on the list of admins [\#8838](https://github.com/decidim/decidim/pull/8838) +- **decidim-core**: Display friendly report reason and details in moderation emails [\#8840](https://github.com/decidim/decidim/pull/8840) +- **decidim-comments**: Show hidden comments replies [\#8828](https://github.com/decidim/decidim/pull/8828) +- **decidim-generators**: Make Decidim fully configurable via ENV vars part II [\#8990](https://github.com/decidim/decidim/pull/8990) +- Reduce d3 bundle size [\#9034](https://github.com/decidim/decidim/pull/9034) +- **decidim-elections**: Add help text when verifying your vote [\#9190](https://github.com/decidim/decidim/pull/9190) +- **decidim-accountability**: Add timeline entry title in Accountability projects [\#9127](https://github.com/decidim/decidim/pull/9127) +- **decidim-core**: Rename data portability to download your data [\#9196](https://github.com/decidim/decidim/pull/9196) +- **decidim-elections**: Better wording when verifying an offline voter [\#9357](https://github.com/decidim/decidim/pull/9357) +- **decidim-initiatives**: Add signature collection period title in header [\#9314](https://github.com/decidim/decidim/pull/9314) + +#### Fixed + +- **decidim-admin**, **decidim-assemblies**, **decidim-budgets**, **decidim-conferences**, **decidim-consultations**, **decidim-core**, **decidim-elections**, **decidim-forms**, **decidim-initiatives**, **decidim-meetings**, **decidim-participatory processes**, **decidim-proposals**: Fix deprecation warnings from rails 6.1 update (#8610) [\#8610](https://github.com/decidim/decidim/pull/8610) +- **decidim-core**: Remove 'required field' explanation from conversation textearea [\#8701](https://github.com/decidim/decidim/pull/8701) +- **decidim-core**: Fix some non-localized user emails [\#8719](https://github.com/decidim/decidim/pull/8719) +- **decidim-meetings**: Fix for preview unpublished meetings by admin user [\#8713](https://github.com/decidim/decidim/pull/8713) +- **decidim-participatory processes**: Fix order by weight in processes groups' processes content block [\#8734](https://github.com/decidim/decidim/pull/8734) +- **decidim-admin**, **decidim-core**: Change scope picker button to disabled when necessary [\#8733](https://github.com/decidim/decidim/pull/8733) +- **decidim-comments**: Add emojis when user edits a comment [\#8731](https://github.com/decidim/decidim/pull/8731) +- **decidim-admin**, **decidim-meetings**, **decidim-proposals**: Fix reporting a proposal when author is a meeting [\#8737](https://github.com/decidim/decidim/pull/8737) +- **decidim-core**: Don't display blocked users in mentions [\#8687](https://github.com/decidim/decidim/pull/8687) +- **decidim-core**: Properly mark sender and recipient in Conversation [\#8742](https://github.com/decidim/decidim/pull/8742) +- **decidim-proposals**: Fix geocoding NaN values [\#8762](https://github.com/decidim/decidim/pull/8762) +- **decidim-core**: Add "nofollow noopener" rel to the profile personal URL [\#8779](https://github.com/decidim/decidim/pull/8779) +- **decidim-generators**: Add .keep file to empty directory to include on git committing [\#8786](https://github.com/decidim/decidim/pull/8786) +- **decidim-core**: Fix reminder manifest, replace virtus with attribute object [\#8785](https://github.com/decidim/decidim/pull/8785) +- **decidim-core**: Fix avatar upload validation errors are displayed twice [\#8794](https://github.com/decidim/decidim/pull/8794) +- **decidim-meetings**: Fix displaying hidden meetings in homepage's "upcoming meetings" content block [\#8809](https://github.com/decidim/decidim/pull/8809) +- **decidim-meetings**, **decidim-participatory processes**: Fix displaying hidden meetings in processes group's "upcoming meetings" content block [\#8818](https://github.com/decidim/decidim/pull/8818) +- **decidim-participatory processes**: Fix characters not encoded in highlighted participatory process group title [\#8820](https://github.com/decidim/decidim/pull/8820) +- **decidim-initiatives**: Fix scope validation on initiative's creation [\#8755](https://github.com/decidim/decidim/pull/8755) +- **decidim-generators**: Add natively a .keep file to empty directory to include on git committing [\#8830](https://github.com/decidim/decidim/pull/8830) +- **decidim-core**, **decidim-meetings**, **decidim-proposals**: Fix displaying hidden related resources [\#8812](https://github.com/decidim/decidim/pull/8812) +- **decidim-consultations**, **decidim-core**, **decidim-elections**: Fix report moderation for all the spaces [\#8813](https://github.com/decidim/decidim/pull/8813) +- **decidim-meetings**, **decidim-participatory processes**: Fix displaying hidden meetings in show process page [\#8823](https://github.com/decidim/decidim/pull/8823) +- **decidim-accountability**: Fix accountability text search [\#8831](https://github.com/decidim/decidim/pull/8831) +- **decidim-assemblies**, **decidim-conferences**, **decidim-consultations**, **decidim-proposals**: Fix notifications when there is a note proposal in other spaces than processes [\#8822](https://github.com/decidim/decidim/pull/8822) +- **decidim-core**: Fix activity cell disappearing author images [\#8826](https://github.com/decidim/decidim/pull/8826) +- **decidim-accountability**: Fix accountability categories' colors [\#8844](https://github.com/decidim/decidim/pull/8844) +- **decidim-meetings**: Fix displaying hidden resources in global search [\#8811](https://github.com/decidim/decidim/pull/8811) +- **decidim-assemblies**: Fix assemblies title when there are unpublished children [\#8855](https://github.com/decidim/decidim/pull/8855) +- **decidim-debates**: Remove actions from debates' cards [\#8854](https://github.com/decidim/decidim/pull/8854) +- **decidim-core**: Fix cache_hash generation in AuthorCell [\#8852](https://github.com/decidim/decidim/pull/8852) +- **decidim-proposals**: Fix answered proposals display [\#8851](https://github.com/decidim/decidim/pull/8851) +- **decidim-comments**: Show hidden comments replies [\#8828](https://github.com/decidim/decidim/pull/8828) +- **decidim-meetings**: Fix meetings iframe embed code [\#8875](https://github.com/decidim/decidim/pull/8875) +- **decidim-core**: Fix the way the results are displayed in search page [\#8873](https://github.com/decidim/decidim/pull/8873) +- **decidim-meetings**: Fix display warning message in meetings [\#8872](https://github.com/decidim/decidim/pull/8872) +- **decidim-core**: Translate the remove recipient button correctly for new conversation [\#8894](https://github.com/decidim/decidim/pull/8894) +- **decidim-core**: Fix diff mode selector accessibility [\#8879](https://github.com/decidim/decidim/pull/8879) +- **decidim-core**: Add a unique title to the new group page [\#8882](https://github.com/decidim/decidim/pull/8882) +- **decidim-core**: Fix illogical heading order for the versions list [\#8880](https://github.com/decidim/decidim/pull/8880) +- **decidim-core**: Improve logo link aria label [\#8878](https://github.com/decidim/decidim/pull/8878) +- **decidim-core**: Add the "choose language" string in all locales to the language chooser [\#8883](https://github.com/decidim/decidim/pull/8883) +- **decidim-core**: Change the correct element type for the change password button [\#8890](https://github.com/decidim/decidim/pull/8890) +- **decidim-budgets**: Fix duplicate ID on the budgets index page [\#8908](https://github.com/decidim/decidim/pull/8908) +- **decidim-core**: Fix accessibility issue related to the documents collection toggle [\#8907](https://github.com/decidim/decidim/pull/8907) +- **decidim-participatory processes**: Fix heading order in the process steps page [\#8906](https://github.com/decidim/decidim/pull/8906) +- **decidim-elections**: Fix illogical heading orders in the elections component [\#8905](https://github.com/decidim/decidim/pull/8905) +- **decidim-forms**: Fix the form questionnaires heading orders [\#8903](https://github.com/decidim/decidim/pull/8903) +- **decidim-budgets**: Fix the illogical heading orders with the budget component views [\#8904](https://github.com/decidim/decidim/pull/8904) +- **decidim-core**: Fix the component index views heading order for the subtitle change [\#8902](https://github.com/decidim/decidim/pull/8902) +- **decidim-comments**: Fix comments heading order [\#8876](https://github.com/decidim/decidim/pull/8876) +- **decidim-proposals**: Fix display withdraw warning message in proposals [\#8870](https://github.com/decidim/decidim/pull/8870) +- **decidim-core**: Make the button link font weight consistent with normal links [\#8891](https://github.com/decidim/decidim/pull/8891) +- **decidim-proposals**: Fix illogical heading order for a single proposal [\#8877](https://github.com/decidim/decidim/pull/8877) +- **decidim-core**: Fix the HTML diff mode accessibility [\#8915](https://github.com/decidim/decidim/pull/8915) +- **decidim-assemblies**, **decidim-core**, **decidim-initiatives**, **decidim-participatory processes**: Change the participatory space header's subtitle element to a `

` to fix heading order issues [\#8901](https://github.com/decidim/decidim/pull/8901) +- **decidim-comments**: Fix Foundation Abide errors for Rails remote (AJAX) forms [\#8889](https://github.com/decidim/decidim/pull/8889) +- **decidim-core**: Fix logical heading order for the endorsers list [\#8892](https://github.com/decidim/decidim/pull/8892) +- **decidim-comments**, **decidim-core**: Fix emoji picker hiding Foundation Abide form errors [\#8886](https://github.com/decidim/decidim/pull/8886) +- **decidim-comments**: Fix budget hard dependency and caching flag issues in comments [\#8899](https://github.com/decidim/decidim/pull/8899) +- **decidim-core**: Fix diff mode selector roles and tabindexes [\#8912](https://github.com/decidim/decidim/pull/8912) +- **decidim-consultations**: Fix heading order in the consultation question page [\#8920](https://github.com/decidim/decidim/pull/8920) +- **decidim-meetings**: Fix the meetings export to also include unpublished meetings [\#8874](https://github.com/decidim/decidim/pull/8874) +- **decidim-initiatives**: Fix initiatives signatures issues [\#8448](https://github.com/decidim/decidim/pull/8448) +- **decidim-initiatives**: Fix link to docs in initiatives admin [\#8921](https://github.com/decidim/decidim/pull/8921) +- **decidim-core**: Fix translatable presence validator for hyphenated locales [\#8795](https://github.com/decidim/decidim/pull/8795) +- **decidim-participatory processes**: Fix processes creation form with stats, metrics and announcements [\#8925](https://github.com/decidim/decidim/pull/8925) +- **decidim-system**, **decidim-verifications**: Fix verification report with multitenants: notify it only to admins of that organization [\#8929](https://github.com/decidim/decidim/pull/8929) +- **decidim-core**: Fix officialized user event missing translations [\#8927](https://github.com/decidim/decidim/pull/8927) +- **decidim-verifications**: Fix email for verification conflict with managed users [\#8926](https://github.com/decidim/decidim/pull/8926) +- **decidim-core**: Fix profile notifications [\#8943](https://github.com/decidim/decidim/pull/8943) +- **decidim-elections**: Add a subtitle to votings page [\#8919](https://github.com/decidim/decidim/pull/8919) +- **decidim-assemblies**, **decidim-participatory processes**: Add a subtitle to assemblies and processes pages [\#8918](https://github.com/decidim/decidim/pull/8918) +- **decidim-meetings**: Truncate the meetings card description [\#8954](https://github.com/decidim/decidim/pull/8954) +- **decidim-proposals**: Fix proposals' cards with big images [\#8952](https://github.com/decidim/decidim/pull/8952) +- **decidim-core**: Add missing reveal__title classes [\#8958](https://github.com/decidim/decidim/pull/8958) +- **decidim-core**: Fix multiple mentions correct focus on element (recipient) removal [\#8959](https://github.com/decidim/decidim/pull/8959) +- **decidim-core**: Add missing 'Locale' string in i18n in account page [\#8969](https://github.com/decidim/decidim/pull/8969) +- **decidim-core**: Fix main navigation aria-current attribute [\#8968](https://github.com/decidim/decidim/pull/8968) +- **decidim-core**: Fix mobile nav keyboard focus [\#8962](https://github.com/decidim/decidim/pull/8962) +- **decidim-core**: Remove the label from the dropdown menu opener [\#8972](https://github.com/decidim/decidim/pull/8972) +- **decidim-blogs**, **decidim-core**, **decidim-debates**, **decidim-proposals**: Fix for endorsed_by with other user group's member [\#8967](https://github.com/decidim/decidim/pull/8967) +- **decidim-proposals**: Fix footer actions caching on proposals' card [\#8987](https://github.com/decidim/decidim/pull/8987) +- **decidim-initiatives**: Show signatures in answered initiatives [\#8747](https://github.com/decidim/decidim/pull/8747) +- **decidim-api**, **decidim-meetings**, **decidim-proposals**: Fix API when meetings have proposal linking disabled [\#8971](https://github.com/decidim/decidim/pull/8971) +- **decidim-meetings**, **decidim-proposals**: Fix proposals seeds after reordering of modules loading [\#8993](https://github.com/decidim/decidim/pull/8993) +- **decidim-core**: Show character counter when replying to message [\#8922](https://github.com/decidim/decidim/pull/8922) +- **decidim-core**: Fix character counter with emoji picker close to maximum characters [\#8916](https://github.com/decidim/decidim/pull/8916) +- **decidim-budgets**, **decidim-core**, **decidim-debates**, **decidim-meetings**, **decidim-proposals**: Fix cache URLs on cards [\#8988](https://github.com/decidim/decidim/pull/8988) +- **decidim-core**: Fix submit form with enter when there are attachments [\#9019](https://github.com/decidim/decidim/pull/9019) +- **decidim-core**: Fix Devise flash messages translation [\#9025](https://github.com/decidim/decidim/pull/9025) +- **decidim-admin**: Add missing 'Locale' string in i18n in selective newsletter [\#9037](https://github.com/decidim/decidim/pull/9037) +- **decidim-core**: Disable new conversation next button when no users selected [\#9024](https://github.com/decidim/decidim/pull/9024) +- **decidim-core**: Fix social share button sharing (`Can't find variable: SocialShareButton` console error) [\#9041](https://github.com/decidim/decidim/pull/9041) +- **decidim-meetings**: Use published meetings scope on processes landing and proposal's form [\#9023](https://github.com/decidim/decidim/pull/9023) +- **decidim-core**: Require omniauth/rails_csrf_protection explicitly [\#9053](https://github.com/decidim/decidim/pull/9053) +- **decidim-core**: Fix session cookie SameSite policy [\#9051](https://github.com/decidim/decidim/pull/9051) +- **decidim-conferences**: Fix conference partner logo is not optional on create [\#9045](https://github.com/decidim/decidim/pull/9045) +- **decidim-comments**, **decidim-core**, **decidim-proposals**: Add noreferrer and ugc to links [\#9047](https://github.com/decidim/decidim/pull/9047) +- **decidim-proposals**: Create admin log records when proposals are imported from a file [\#9006](https://github.com/decidim/decidim/pull/9006) +- **decidim-meetings**: Remove presenters in the meetings admin backoffice [\#9052](https://github.com/decidim/decidim/pull/9052) +- **decidim-meetings**: Fix submit in meetings admin form [\#9061](https://github.com/decidim/decidim/pull/9061) +- **decidim-core**, **decidim-proposals**: Fix amendable events title [\#9050](https://github.com/decidim/decidim/pull/9050) +- **decidim-assemblies**, **decidim-conferences**, **decidim-consultations**, **decidim-core**, **decidim-initiatives**, **decidim-participatory processes**: Fix Twitter hashtag search when it starts with a number [\#9039](https://github.com/decidim/decidim/pull/9039) +- **decidim-initiatives**: Remove 'edit link' in topbar for initiative's authors [\#8997](https://github.com/decidim/decidim/pull/8997) +- **decidim-comments**, **decidim-core**, **decidim-meetings**: Fix timeout in comment view and during meetings [\#9070](https://github.com/decidim/decidim/pull/9070) +- **decidim-core**: Dont add external link container inside editor [\#9095](https://github.com/decidim/decidim/pull/9095) +- **decidim-core**, **decidim-dev**: VAPID key generator availabe in core [\#9107](https://github.com/decidim/decidim/pull/9107) +- **decidim-assemblies**: Allow assembly admins to manage components in child assemblies [\#8955](https://github.com/decidim/decidim/pull/8955) +- **decidim-core**: Add base URI to meta image URLs [\#9125](https://github.com/decidim/decidim/pull/9125) +- **decidim-elections**: Clarify message to user when checking census [\#9112](https://github.com/decidim/decidim/pull/9112) +- **decidim-elections**: Fix attachments when called from Cells [\#9136](https://github.com/decidim/decidim/pull/9136) +- **decidim-participatory processes**: Fix processes count in processes group title cell [\#9087](https://github.com/decidim/decidim/pull/9087) +- **decidim-meetings**: Do not send upcoming meeting notification for hidden or withdrawn meetings [\#9134](https://github.com/decidim/decidim/pull/9134) +- **decidim-elections**: Improve wording when casting your vote [\#9098](https://github.com/decidim/decidim/pull/9098) +- **decidim-core**: Prevent race condition between prevenTimeout and show modal [\#9092](https://github.com/decidim/decidim/pull/9092) +- **decidim-generators**: Fix app generator when creating a development_app [\#9142](https://github.com/decidim/decidim/pull/9142) +- **decidim-meetings**: Fix meetings minutes migration [\#9148](https://github.com/decidim/decidim/pull/9148) +- **decidim-core**: Enforce password validation rules on 'Forgot your password?' form [\#9090](https://github.com/decidim/decidim/pull/9090) +- **decidim-proposals**: Add 'not answered' as a possible answer in proposals [\#9021](https://github.com/decidim/decidim/pull/9021) +- **decidim-budgets**: Fix vote reminder email urls [\#9152](https://github.com/decidim/decidim/pull/9152) +- **decidim-meetings**: Move modal to body and fix condition [\#9158](https://github.com/decidim/decidim/pull/9158) +- **decidim-assemblies**, **decidim-proposals**: Fix absolute urls on 'create assembly member' and proposals' 'collaborative drafts' events [\#9146](https://github.com/decidim/decidim/pull/9146) +- **decidim-accountability**, **decidim-consultations**: Fix components navbar in consultations mobile [\#9155](https://github.com/decidim/decidim/pull/9155) +- **decidim-core**: Show only current organization in verification conflicts with multitenants [\#9033](https://github.com/decidim/decidim/pull/9033) +- **decidim-elections**: Send email to newly added trustees [\#9100](https://github.com/decidim/decidim/pull/9100) +- **decidim-meetings**: Fix registration type field highlighted in admin meeting creation form [\#9160](https://github.com/decidim/decidim/pull/9160) +- **decidim-core**: Fix displaying blocked users in account follow pages [\#9164](https://github.com/decidim/decidim/pull/9164) +- **decidim-core**: Separate validation messages for image dimensions and size [\#9165](https://github.com/decidim/decidim/pull/9165) +- **decidim-core**: Fix notifications where resources are missing [\#9183](https://github.com/decidim/decidim/pull/9183) +- **decidim-core**: Fix encoding organization name in A2HS [\#9184](https://github.com/decidim/decidim/pull/9184) +- **decidim-surveys**: Fix contradictory form errors on survey form [\#9186](https://github.com/decidim/decidim/pull/9186) +- **decidim-admin**, **decidim-elections**: Fix newsletters and Decidim Votings [\#9188](https://github.com/decidim/decidim/pull/9188) +- **decidim-meetings**: Fix typo in meeting's copy calendar string [\#9193](https://github.com/decidim/decidim/pull/9193) +- **decidim-initiatives**: Fix typo and improves copy in initiatives admin [\#9194](https://github.com/decidim/decidim/pull/9194) +- **decidim-system**: Enforce password validation rules on system admins [\#9207](https://github.com/decidim/decidim/pull/9207) +- **decidim-initiatives**: Add edit and delete actions in InitiativeType admin table [\#9151](https://github.com/decidim/decidim/pull/9151) +- **decidim-surveys**: Clarify unregistered answers on surveys behavior [\#9205](https://github.com/decidim/decidim/pull/9205) +- **decidim-elections**: Fix voting with single election [\#9097](https://github.com/decidim/decidim/pull/9097) +- **decidim-admin**: Fix invalid translation call [\#9218](https://github.com/decidim/decidim/pull/9218) +- **decidim-initiatives**: Fix initiative print link, margin, and organization logo [\#9162](https://github.com/decidim/decidim/pull/9162) +- **decidim-elections**: Fix election label translations [\#9102](https://github.com/decidim/decidim/pull/9102) +- **decidim-elections**: Remove show more button on elections [\#9103](https://github.com/decidim/decidim/pull/9103) +- **decidim-surveys**: Fix survey activity log entries [\#9173](https://github.com/decidim/decidim/pull/9173) +- **decidim-core**: Fix dynamic validation and title change for titled attachments [\#9175](https://github.com/decidim/decidim/pull/9175) +- **decidim-budgets**: Remove beforeunload confirmation panel from the budgets voting [\#9224](https://github.com/decidim/decidim/pull/9224) +- **decidim-core**: Fix nicknames uniqueness with different cases [\#8792](https://github.com/decidim/decidim/pull/8792) +- **decidim-core**: Fix Leaflet trying to load "infinite amount of tiles" [\#9233](https://github.com/decidim/decidim/pull/9233) +- **decidim-verifications**: Allow to renew expired verifications (if renewable) [\#8192](https://github.com/decidim/decidim/pull/8192) +- **decidim-elections**: Correctly show trustees and votings menu [\#9192](https://github.com/decidim/decidim/pull/9192) +- **decidim-core**: Fix hashtag parsing on URLs with fragments [\#9221](https://github.com/decidim/decidim/pull/9221) +- **decidim-comments**, **decidim-core**: Add missing events locales [\#9199](https://github.com/decidim/decidim/pull/9199) +- **decidim-conferences**: Make conference's partners logos always mandatory [\#9214](https://github.com/decidim/decidim/pull/9214) +- **decidim-admin**: Fix margin around warning message in colour settings [\#9278](https://github.com/decidim/decidim/pull/9278) +- **decidim-comments**, **decidim-core**: Don't show deleted resources in last activities [\#9293](https://github.com/decidim/decidim/pull/9293) +- **decidim-elections**: Hide more information link when there's no description on an election [\#9099](https://github.com/decidim/decidim/pull/9099) +- **decidim-admin**: Fix local storage protocol options for uploaders [\#9285](https://github.com/decidim/decidim/pull/9285) +- **decidim-admin**, **decidim-assemblies**, **decidim-budgets**, **decidim-core**, **decidim-elections**, **decidim-meetings**, **decidim-pages**, **decidim-proposals**: Apply crowdin feedback [\#9301](https://github.com/decidim/decidim/pull/9301) +- **decidim-participatory processes**: Update file validation for process import [\#9236](https://github.com/decidim/decidim/pull/9236) +- **decidim-core**: Fix user interests [\#9225](https://github.com/decidim/decidim/pull/9225) +- **decidim-elections**: Add error message when adding question and election has started [\#9189](https://github.com/decidim/decidim/pull/9189) +- **decidim-elections**: Fix HTML safe content in election voting [\#9210](https://github.com/decidim/decidim/pull/9210) +- **decidim-elections**: Fix ActionLog when a ballot style is deleted [\#9355](https://github.com/decidim/decidim/pull/9355) +- **decidim-elections**: Enforce YYYYmmdd format in birthdate when uploading census [\#9354](https://github.com/decidim/decidim/pull/9354) +- **decidim-elections**: Only show that the code can be requested via SMS if its true [\#9353](https://github.com/decidim/decidim/pull/9353) +- **decidim-meetings**: Short URLs to fix long export calendar URLs [\#9383](https://github.com/decidim/decidim/pull/9383) +- **decidim-core**: Fix for internal links not displaying on page title [\#9228](https://github.com/decidim/decidim/pull/9228) +- **decidim-elections**: Fix regular expression on census check [\#9352](https://github.com/decidim/decidim/pull/9352) +- **decidim-budgets**, **decidim-proposals**: Add missing translation keys proposals import and proposals picker [\#9359](https://github.com/decidim/decidim/pull/9359) +- **decidim-consultations**: Return 404 when there isn't a consultation [\#9374](https://github.com/decidim/decidim/pull/9374) +- **decidim-consultations**: Return 404 when there isn't a question [\#9375](https://github.com/decidim/decidim/pull/9375) +- **decidim-elections**: Return 404 when there isn't a voting in elections_log [\#9376](https://github.com/decidim/decidim/pull/9376) +- **decidim-proposals**: Fix proposals creation with Participatory Texts [\#9381](https://github.com/decidim/decidim/pull/9381) +- **decidim-forms**, **decidim-meetings**, **decidim-surveys**: Fix rollback questionnaire answer when file is invalid [\#9361](https://github.com/decidim/decidim/pull/9361) +- **decidim-core**: Create tempfile when Active Storage service doesn't implement path_for method [\#9362](https://github.com/decidim/decidim/pull/9362) +- **decidim-core**: Fix / Expose createMapController properly to let overriding [\#9425](https://github.com/decidim/decidim/pull/9425) +- **decidim-elections**: Capture unhandled errors from JS promises and inform the user [\#9430](https://github.com/decidim/decidim/pull/9430) +- **decidim-elections**: Make sure component is published when starting an election [\#9358](https://github.com/decidim/decidim/pull/9358) +- **decidim-elections**: Remove description from questions in elections [\#9401](https://github.com/decidim/decidim/pull/9401) +- **decidim-initiatives**: Return 404 when there isn't an initiative [\#9427](https://github.com/decidim/decidim/pull/9427) +- **decidim-core**, **decidim-meetings**, **decidim-proposals**: Fix email subject when resource title has special characters [\#9392](https://github.com/decidim/decidim/pull/9392) +- **decidim-core**, **decidim-generators**: Fix service worker cache in development environment [\#9424](https://github.com/decidim/decidim/pull/9424) +- **decidim-core**: Prevent users to validate nicknames/emails taken by user groups (#9452) [\#9452](https://github.com/decidim/decidim/pull/9452) +- **decidim-elections**: Fix hardcoded hour in election dashboard (#9465) [\#9465](https://github.com/decidim/decidim/pull/9465) + +#### Removed + +- **decidim-meetings**: Clean meetings form with registrations [\#8500](https://github.com/decidim/decidim/pull/8500) +- **decidim-core**: Remove 'required field' explanation from conversation textearea [\#8701](https://github.com/decidim/decidim/pull/8701) +- **decidim-admin**, **decidim-assemblies**, **decidim-conferences**, **decidim-participatory processes**: Remove category description [\#8617](https://github.com/decidim/decidim/pull/8617) +- **decidim-core**: The `rectify` gem has been removed from the stack as of [\#9101](https://github.com/decidim/decidim/pull/9101). If you are a library developer, replace any `Rectify::Query` with `Decidim::Query`, replace any `Rectify::Command` with `Decidim::Command`. Replace any `Rectify::Presenter` with `SimpleDelegator` (Already deprecated in [\#8758](https://github.com/decidim/decidim/pull/8758)) +- **decidim-core**: The `searchlight` gem has been removed in favor of Ransach as of [\#8748](https://github.com/decidim/decidim/pull/8748). Please review the **Changed** notes regarding the required changes. Please review all your search classes that were inheriting from `Searchlight::Search`. You should migrate your search filtering to Ransack. +- **decidim-core**: The `search_params` and `default_search_params` methods within the participant-facing controllers are now removed in favor of using `filter_params` and `default_filter_params` as of [\#8748](https://github.com/decidim/decidim/pull/8748). The duplicate methods were redundant after the Ransack migration which is why they were removed. In case you had overridden these methods in your controllers, they no longer do anything. In case you were calling these methods before, you will now receive a `NoMethodError` because they are removed. Please use `filter_params` and `default_filter_params` instead. +- **decidim-accountability**, **decidim-assemblies**, **decidim-budgets**, **decidim-consultations**, **decidim-core**, **decidim-elections**, **decidim-initiatives**, **decidim-participatory_processes**, **decidim-proposals**, **decidim-sortitions**: The search service classes inheriting from `Searchlight::Search` that are no longer necessary due to the Ransack migration have been removed in all modules as of [\#8748](https://github.com/decidim/decidim/pull/8748). This includes `Decidim::Accountability::ResultSearch`, `Decidim::Assemblies::AssemblySearch`, `Decidim::Budgets::ProjectSearch`, `Decidim::Consultations::ConsultationSearch`, `Decidim::HomeActivitySearch`, `Decidim::ParticipatorySpaceSearch`, `Decidim::Elections::ElectionsSearch`, `Decidim::Votings::VotingSearch`, `Decidim::Meetings::Directory::MeetingSearch`, `Decidim::ParticipatoryProcesses::ParticipatoryProcessesSearch`, `Decidim::Proposals::CollaborativeDraftSearch`, `Decidim::Proposals::ProposalSearch` and `Decidim::Sortitions::SortitionSearch`. + +#### Developer improvements + +- Replace graphql-docs npm package with gem [\#8631](https://github.com/decidim/decidim/pull/8631) +- Migrate from `Virtus` to `ActiveModel::Attributes` (and get rid of `Rectify::Form`) [\#8669](https://github.com/decidim/decidim/pull/8669) +- Replace various autocomplete solutions [\#8524](https://github.com/decidim/decidim/pull/8524) +- Fix webpacker generator for modules [\#8715](https://github.com/decidim/decidim/pull/8715) +- Add parallel_tests for test suite in CI [\#8678](https://github.com/decidim/decidim/pull/8678) +- Replace `searchlight` with `ransack` which is already a core dependency [\#8748](https://github.com/decidim/decidim/pull/8748) +- Update docs in Webpacker app migration [\#8881](https://github.com/decidim/decidim/pull/8881) +- Move VAPID keys generators to core [\#8923](https://github.com/decidim/decidim/pull/8923) +- Update docs in Webpacker app migration (part II) [\#8911](https://github.com/decidim/decidim/pull/8911) +- Fix Devise configs that depend on Decidim configs [\#9014](https://github.com/decidim/decidim/pull/9014) +- Update rails to 6.1 [\#8411](https://github.com/decidim/decidim/pull/8411) +- Add useful error for custom-authorizations development [\#8834](https://github.com/decidim/decidim/pull/8834) +- Prevent Faker Address country_code from raising RetryLimitExceeded [\#9036](https://github.com/decidim/decidim/pull/9036) +- Fix Spring errors with Rails 6.1 [\#9032](https://github.com/decidim/decidim/pull/9032) +- Disable webpack-dev-server overlay [\#9082](https://github.com/decidim/decidim/pull/9082) +- Make frontend development 10-12x faster (compile SCSS through sass-embedded) [\#9081](https://github.com/decidim/decidim/pull/9081) +- Fix webpacker configuration when sass-loader is not available [\#9149](https://github.com/decidim/decidim/pull/9149) +- Remove Rectify Gem dependency [\#9101](https://github.com/decidim/decidim/pull/9101) +- Fix webpacker thread safety [\#9203](https://github.com/decidim/decidim/pull/9203) +- Fix budget amounts in project seeds [\#9174](https://github.com/decidim/decidim/pull/9174) +- Update ruby to 3.0 [\#8452](https://github.com/decidim/decidim/pull/8452) +- Remove unused helper method from UserInterestsController [\#9237](https://github.com/decidim/decidim/pull/9237) +- Light refactor for fetching admins [\#9287](https://github.com/decidim/decidim/pull/9287) +- Fix local storage protocol options for uploaders [\#9285](https://github.com/decidim/decidim/pull/9285) +- Add empty database (aka no seed) installation manual [\#9349](https://github.com/decidim/decidim/pull/9349) +- Bump letter_opener_web from 1.3 to 2.0 [\#9395](https://github.com/decidim/decidim/pull/9395) +- Change docs to use decidim_system:create_admin command [\#9372](https://github.com/decidim/decidim/pull/9372) +- Add documentation for logic customization [\#9325](https://github.com/decidim/decidim/pull/9325) +- External link improvements [\#9402](https://github.com/decidim/decidim/pull/9402) +- Improve asset routing logic [\#9403](https://github.com/decidim/decidim/pull/9403) +- Remove the threads limit from the Capybara Puma server [\#9422](https://github.com/decidim/decidim/pull/9422) ## Previous versions -Please check [release/0.25-stable](https://github.com/decidim/decidim/blob/release/0.25-stable/CHANGELOG.md) for previous changes. +Please check [release/0.26-stable](https://github.com/decidim/decidim/blob/release/0.26-stable/CHANGELOG.md) for previous changes. diff --git a/Gemfile b/Gemfile index 36a8274c232ce..f04324cbe98e2 100644 --- a/Gemfile +++ b/Gemfile @@ -13,29 +13,24 @@ gem "decidim-templates", path: "." gem "bootsnap", "~> 1.4" -gem "foundation_rails_helper", git: "https://github.com/sgruhier/foundation_rails_helper.git" -gem "puma", ">= 5.5.1" +gem "puma", ">= 5.6.2" gem "faker", "~> 2.14" group :development, :test do gem "byebug", "~> 11.0", platform: :mri - # Use latest simplecov from master until next version of simplecov is - # released (greather than 0.18.5) - # See https://github.com/decidim/decidim/issues/6230 - gem "simplecov", "~> 0.19.0" - gem "decidim-dev", path: "." - gem "brakeman", "~> 5.1" + gem "brakeman", "~> 5.2" + gem "parallel_tests", "~> 3.7" end group :development do - gem "letter_opener_web", "~> 1.3" + gem "letter_opener_web", "~> 2.0" gem "listen", "~> 3.1" gem "rubocop-faker" gem "spring", "~> 2.0" gem "spring-watcher-listen", "~> 2.0" - gem "web-console", "4.0.4" + gem "web-console", "~> 4.2" end diff --git a/Gemfile.lock b/Gemfile.lock index 3ed050bce7ec3..9169869252e4e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,72 +1,62 @@ -GIT - remote: https://github.com/sgruhier/foundation_rails_helper.git - revision: 45709e28f567b2e619a06091eb63d4f050f861d8 - specs: - foundation_rails_helper (3.0.0) - actionpack (>= 4.1, < 7.0) - activemodel (>= 4.1, < 7.0) - activesupport (>= 4.1, < 7.0) - railties (>= 4.1, < 7.0) - PATH remote: . specs: - decidim (0.26.4) - decidim-accountability (= 0.26.4) - decidim-admin (= 0.26.4) - decidim-api (= 0.26.4) - decidim-assemblies (= 0.26.4) - decidim-blogs (= 0.26.4) - decidim-budgets (= 0.26.4) - decidim-comments (= 0.26.4) - decidim-core (= 0.26.4) - decidim-debates (= 0.26.4) - decidim-forms (= 0.26.4) - decidim-generators (= 0.26.4) - decidim-meetings (= 0.26.4) - decidim-pages (= 0.26.4) - decidim-participatory_processes (= 0.26.4) - decidim-proposals (= 0.26.4) - decidim-sortitions (= 0.26.4) - decidim-surveys (= 0.26.4) - decidim-system (= 0.26.4) - decidim-templates (= 0.26.4) - decidim-verifications (= 0.26.4) - decidim-accountability (0.26.4) - decidim-comments (= 0.26.4) - decidim-core (= 0.26.4) - decidim-admin (0.26.4) + decidim (0.27.2) + decidim-accountability (= 0.27.2) + decidim-admin (= 0.27.2) + decidim-api (= 0.27.2) + decidim-assemblies (= 0.27.2) + decidim-blogs (= 0.27.2) + decidim-budgets (= 0.27.2) + decidim-comments (= 0.27.2) + decidim-core (= 0.27.2) + decidim-debates (= 0.27.2) + decidim-forms (= 0.27.2) + decidim-generators (= 0.27.2) + decidim-meetings (= 0.27.2) + decidim-pages (= 0.27.2) + decidim-participatory_processes (= 0.27.2) + decidim-proposals (= 0.27.2) + decidim-sortitions (= 0.27.2) + decidim-surveys (= 0.27.2) + decidim-system (= 0.27.2) + decidim-templates (= 0.27.2) + decidim-verifications (= 0.27.2) + decidim-accountability (0.27.2) + decidim-comments (= 0.27.2) + decidim-core (= 0.27.2) + decidim-admin (0.27.2) active_link_to (~> 1.0) - decidim-core (= 0.26.4) + decidim-core (= 0.27.2) devise (~> 4.7) devise-i18n (~> 1.2) devise_invitable (~> 2.0) - decidim-api (0.26.4) + decidim-api (0.27.2) graphql (~> 1.12, < 1.13) + graphql-docs (~> 2.1.0) rack-cors (~> 1.0) + decidim-assemblies (0.27.2) + decidim-core (= 0.27.2) + decidim-blogs (0.27.2) + decidim-admin (= 0.27.2) + decidim-comments (= 0.27.2) + decidim-core (= 0.27.2) + decidim-budgets (0.27.2) + decidim-comments (= 0.27.2) + decidim-core (= 0.27.2) + decidim-comments (0.27.2) + decidim-core (= 0.27.2) redcarpet (~> 3.5, >= 3.5.1) - decidim-assemblies (0.26.4) - decidim-core (= 0.26.4) - decidim-blogs (0.26.4) - decidim-admin (= 0.26.4) - decidim-comments (= 0.26.4) - decidim-core (= 0.26.4) - decidim-budgets (0.26.4) - decidim-comments (= 0.26.4) - decidim-core (= 0.26.4) - decidim-comments (0.26.4) - decidim-core (= 0.26.4) - redcarpet (~> 3.5, >= 3.5.1) - decidim-conferences (0.26.4) - decidim-core (= 0.26.4) - decidim-meetings (= 0.26.4) + decidim-conferences (0.27.2) + decidim-core (= 0.27.2) + decidim-meetings (= 0.27.2) wicked_pdf (~> 2.1) wkhtmltopdf-binary (~> 0.12) - decidim-consultations (0.26.4) - decidim-admin (= 0.26.4) - decidim-comments (= 0.26.4) - decidim-core (= 0.26.4) - decidim-core (0.26.4) + decidim-consultations (0.27.2) + decidim-admin (= 0.27.2) + decidim-comments (= 0.27.2) + decidim-core (= 0.27.2) + decidim-core (0.27.2) active_link_to (~> 1.0) acts_as_list (~> 0.9) batch-loader (~> 1.2) @@ -75,17 +65,17 @@ PATH cells-erb (~> 0.1.0) cells-rails (~> 0.1.3) charlock_holmes (~> 0.7) - date_validator (~> 0.9.0) - decidim-api (= 0.26.4) + date_validator (~> 0.12.0) + decidim-api (= 0.27.2) devise (~> 4.7) devise-i18n (~> 1.2) diffy (~> 3.3) doorkeeper (~> 5.1) doorkeeper-i18n (~> 4.0) - file_validators (~> 2.1) + file_validators (~> 3.0) fog-local (~> 0.6) - foundation_rails_helper - geocoder (~> 1.7.5) + foundation_rails_helper (~> 4.0) + geocoder (~> 1.8) hashdiff (>= 0.4.0, < 2.0.0) invisible_captcha (~> 0.12) kaminari (~> 1.2, >= 1.2.1) @@ -104,144 +94,145 @@ PATH premailer-rails (~> 1.10) rack (~> 2.2, >= 2.2.3) rack-attack (~> 6.0) - rails (~> 6.0.4) + rails (~> 6.1.0) rails-i18n (~> 6.0) ransack (~> 2.4.1) - rectify (~> 0.13.0) redis (~> 4.1) request_store (~> 1.5.0) rubyXL (~> 3.4) rubyzip (~> 2.0) - searchlight (~> 4.1) seven_zip_ruby (~> 1.3) social-share-button (~> 1.2, >= 1.2.1) valid_email2 (~> 2.1) webpacker (= 6.0.0.rc.5) + webpush (~> 1.1) wisper (~> 2.0) - decidim-debates (0.26.4) - decidim-comments (= 0.26.4) - decidim-core (= 0.26.4) - decidim-dev (0.26.4) + decidim-debates (0.27.2) + decidim-comments (= 0.27.2) + decidim-core (= 0.27.2) + decidim-dev (0.27.2) axe-core-rspec (~> 4.1.0) byebug (~> 11.0) capybara (~> 3.24) db-query-matchers (~> 0.10.0) - decidim (= 0.26.4) + decidim (= 0.27.2) erb_lint (~> 0.0.35) factory_bot_rails (~> 4.8) i18n-tasks (~> 0.9.18) mdl (~> 0.5) - nokogiri (~> 1.12) + nokogiri (~> 1.13) + parallel_tests (~> 3.7) puma (~> 5.0) rails-controller-testing (~> 1.0) - rspec-cells (~> 0.3.4) + rspec-cells (~> 0.3.7) rspec-html-matchers (~> 0.9.1) rspec-rails (~> 4.0) rspec-retry (~> 0.6.2) rspec_junit_formatter (~> 0.3.0) - rubocop (~> 0.92.0) - rubocop-rails (~> 2.8) - rubocop-rspec (= 1.43.2) - selenium-webdriver (~> 3.142) - simplecov (~> 0.19.0) - simplecov-cobertura (~> 1.3.1) - system_test_html_screenshots (~> 0.2) + rubocop (~> 1.28.0) + rubocop-rails (~> 2.14) + rubocop-rspec (~> 2.10) + selenium-webdriver (~> 4.1.0) + simplecov (~> 0.21.0) + simplecov-cobertura (~> 2.1.0) w3c_rspec_validators (~> 0.3.0) webmock (~> 3.6) wisper-rspec (~> 1.0) - decidim-elections (0.26.4) - decidim-bulletin_board (= 0.22.3) - decidim-core (= 0.26.4) - decidim-forms (= 0.26.4) - decidim-proposals (= 0.26.4) + decidim-elections (0.27.2) + decidim-bulletin_board (= 0.23) + decidim-core (= 0.27.2) + decidim-forms (= 0.27.2) + decidim-proposals (= 0.27.2) rack-attack (~> 6.0) - voting_schemes-dummy (= 0.22.3) - voting_schemes-electionguard (= 0.22.3) - decidim-forms (0.26.4) - decidim-core (= 0.26.4) + voting_schemes-dummy (= 0.23) + voting_schemes-electionguard (= 0.23) + decidim-forms (0.27.2) + decidim-core (= 0.27.2) wicked_pdf (~> 2.1) wkhtmltopdf-binary (~> 0.12) - decidim-generators (0.26.4) - decidim-core (= 0.26.4) - decidim-initiatives (0.26.4) - decidim-admin (= 0.26.4) - decidim-comments (= 0.26.4) - decidim-core (= 0.26.4) - decidim-verifications (= 0.26.4) + decidim-generators (0.27.2) + decidim-core (= 0.27.2) + decidim-initiatives (0.27.2) + decidim-admin (= 0.27.2) + decidim-comments (= 0.27.2) + decidim-core (= 0.27.2) + decidim-verifications (= 0.27.2) origami (~> 2.1) - virtus-multiparams (~> 0.1) + rexml (~> 3.2.5) wicked (~> 1.3) wicked_pdf (~> 2.1) wkhtmltopdf-binary (~> 0.12) - decidim-meetings (0.26.4) - decidim-core (= 0.26.4) - decidim-forms (= 0.26.4) + decidim-meetings (0.27.2) + decidim-core (= 0.27.2) + decidim-forms (= 0.27.2) icalendar (~> 2.5) - decidim-pages (0.26.4) - decidim-core (= 0.26.4) - decidim-participatory_processes (0.26.4) - decidim-core (= 0.26.4) - decidim-proposals (0.26.4) - decidim-comments (= 0.26.4) - decidim-core (= 0.26.4) - doc2text (~> 0.4.4) + decidim-pages (0.27.2) + decidim-core (= 0.27.2) + decidim-participatory_processes (0.27.2) + decidim-core (= 0.27.2) + decidim-proposals (0.27.2) + decidim-comments (= 0.27.2) + decidim-core (= 0.27.2) + doc2text (~> 0.4.5) redcarpet (~> 3.5, >= 3.5.1) - decidim-sortitions (0.26.4) - decidim-admin (= 0.26.4) - decidim-comments (= 0.26.4) - decidim-core (= 0.26.4) - decidim-proposals (= 0.26.4) - decidim-surveys (0.26.4) - decidim-core (= 0.26.4) - decidim-forms (= 0.26.4) - decidim-templates (= 0.26.4) - decidim-system (0.26.4) + decidim-sortitions (0.27.2) + decidim-admin (= 0.27.2) + decidim-comments (= 0.27.2) + decidim-core (= 0.27.2) + decidim-proposals (= 0.27.2) + decidim-surveys (0.27.2) + decidim-core (= 0.27.2) + decidim-forms (= 0.27.2) + decidim-templates (= 0.27.2) + decidim-system (0.27.2) active_link_to (~> 1.0) - decidim-core (= 0.26.4) + decidim-core (= 0.27.2) devise (~> 4.7) devise-i18n (~> 1.2) devise_invitable (~> 2.0) - decidim-templates (0.26.4) - decidim-core (= 0.26.4) - decidim-forms (= 0.26.4) - decidim-verifications (0.26.4) - decidim-core (= 0.26.4) + decidim-templates (0.27.2) + decidim-core (= 0.27.2) + decidim-forms (= 0.27.2) + decidim-verifications (0.27.2) + decidim-core (= 0.27.2) GEM remote: https://rubygems.org/ specs: - actioncable (6.0.4.1) - actionpack (= 6.0.4.1) + actioncable (6.1.6) + actionpack (= 6.1.6) + activesupport (= 6.1.6) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.4.1) - actionpack (= 6.0.4.1) - activejob (= 6.0.4.1) - activerecord (= 6.0.4.1) - activestorage (= 6.0.4.1) - activesupport (= 6.0.4.1) + actionmailbox (6.1.6) + actionpack (= 6.1.6) + activejob (= 6.1.6) + activerecord (= 6.1.6) + activestorage (= 6.1.6) + activesupport (= 6.1.6) mail (>= 2.7.1) - actionmailer (6.0.4.1) - actionpack (= 6.0.4.1) - actionview (= 6.0.4.1) - activejob (= 6.0.4.1) + actionmailer (6.1.6) + actionpack (= 6.1.6) + actionview (= 6.1.6) + activejob (= 6.1.6) + activesupport (= 6.1.6) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.4.1) - actionview (= 6.0.4.1) - activesupport (= 6.0.4.1) - rack (~> 2.0, >= 2.0.8) + actionpack (6.1.6) + actionview (= 6.1.6) + activesupport (= 6.1.6) + rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.4.1) - actionpack (= 6.0.4.1) - activerecord (= 6.0.4.1) - activestorage (= 6.0.4.1) - activesupport (= 6.0.4.1) + actiontext (6.1.6) + actionpack (= 6.1.6) + activerecord (= 6.1.6) + activestorage (= 6.1.6) + activesupport (= 6.1.6) nokogiri (>= 1.8.5) - actionview (6.0.4.1) - activesupport (= 6.0.4.1) + actionview (6.1.6) + activesupport (= 6.1.6) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) @@ -249,25 +240,27 @@ GEM active_link_to (1.0.5) actionpack addressable - activejob (6.0.4.1) - activesupport (= 6.0.4.1) + activejob (6.1.6) + activesupport (= 6.1.6) globalid (>= 0.3.6) - activemodel (6.0.4.1) - activesupport (= 6.0.4.1) - activerecord (6.0.4.1) - activemodel (= 6.0.4.1) - activesupport (= 6.0.4.1) - activestorage (6.0.4.1) - actionpack (= 6.0.4.1) - activejob (= 6.0.4.1) - activerecord (= 6.0.4.1) - marcel (~> 1.0.0) - activesupport (6.0.4.1) + activemodel (6.1.6) + activesupport (= 6.1.6) + activerecord (6.1.6) + activemodel (= 6.1.6) + activesupport (= 6.1.6) + activestorage (6.1.6) + actionpack (= 6.1.6) + activejob (= 6.1.6) + activerecord (= 6.1.6) + activesupport (= 6.1.6) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (6.1.6) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) acts_as_list (0.9.19) activerecord (>= 3.0) addressable (2.8.0) @@ -295,9 +288,9 @@ GEM parser (>= 2.4) smart_properties bindex (0.8.1) - bootsnap (1.7.5) - msgpack (~> 1.0) - brakeman (5.1.1) + bootsnap (1.10.3) + msgpack (~> 1.2) + brakeman (5.2.2) browser (2.7.1) builder (3.2.4) byebug (11.1.3) @@ -310,7 +303,7 @@ GEM rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - carrierwave (2.2.2) + carrierwave (2.2.3) activemodel (>= 5.0.0) activesupport (>= 5.0.0) addressable (~> 2.6) @@ -332,7 +325,7 @@ GEM charlock_holmes (0.7.7) chef-utils (18.0.172) concurrent-ruby - childprocess (3.0.0) + childprocess (4.1.0) coercible (1.0.0) descendants_tracker (~> 0.0.1) coffee-rails (5.0.0) @@ -343,21 +336,22 @@ GEM execjs coffee-script-source (1.12.2) colorize (0.8.1) - concurrent-ruby (1.1.9) + commonmarker (0.23.6) + concurrent-ruby (1.1.10) crack (0.4.5) rexml crass (1.0.6) - css_parser (1.12.0) + css_parser (1.14.0) addressable - date_validator (0.9.0) - activemodel - activesupport + date_validator (0.12.0) + activemodel (>= 3) + activesupport (>= 3) db-query-matchers (0.10.0) activesupport (>= 4.0, < 7) rspec (~> 3.0) - decidim-bulletin_board (0.22.3) + decidim-bulletin_board (0.23.0) byebug (~> 11.0) - graphlient (~> 0.4.0) + graphlient (~> 0.5.0) jwt (~> 2.2.2) rails (~> 6.0, >= 5.0.0) wisper (~> 2.0.0) @@ -374,20 +368,19 @@ GEM warden (~> 1.2.3) devise-i18n (1.10.2) devise (>= 4.8.0) - devise_invitable (2.0.6) + devise_invitable (2.0.7) actionmailer (>= 5.0) devise (>= 4.6) diff-lcs (1.5.0) diffy (3.4.2) - doc2text (0.4.4) - nokogiri (>= 1.12.5, < 1.13.0) + doc2text (0.4.5) + nokogiri (>= 1.13.2, < 1.14.0) rubyzip (~> 2.3.0) docile (1.4.0) - doorkeeper (5.6.0) + doorkeeper (5.6.4) railties (>= 5) doorkeeper-i18n (4.0.1) dumb_delegator (1.0.0) - equalizer (0.0.11) erb_lint (0.0.37) activesupport better_html (~> 1.0.7) @@ -399,14 +392,17 @@ GEM erbse (0.1.4) temple erubi (1.10.0) - excon (0.93.1) + escape_utils (1.3.0) + excon (0.99.0) execjs (2.8.1) + extended-markdown-filter (0.7.0) + html-pipeline (~> 2.9) factory_bot (4.11.1) activesupport (>= 3.0.0) factory_bot_rails (4.11.1) factory_bot (~> 4.11.1) railties (>= 3.0.0) - faker (2.18.0) + faker (2.19.0) i18n (>= 1.6, < 2) faraday (1.10.2) faraday-em_http (~> 1.0) @@ -433,8 +429,8 @@ GEM faraday-retry (1.0.3) faraday_middleware (1.2.0) faraday (~> 1.0) - ffi (1.15.1) - file_validators (2.3.0) + ffi (1.15.5) + file_validators (3.0.0) activemodel (>= 3.2) mime-types (>= 1.0) fog-core (2.3.0) @@ -445,10 +441,16 @@ GEM fog-local (0.8.0) fog-core (>= 1.27, < 3.0) formatador (1.1.0) - geocoder (1.7.5) - globalid (0.5.2) + foundation_rails_helper (4.0.1) + actionpack (>= 4.1, < 7.1) + activemodel (>= 4.1, < 7.1) + activesupport (>= 4.1, < 7.1) + railties (>= 4.1, < 7.1) + gemoji (3.0.1) + geocoder (1.8.1) + globalid (1.0.0) activesupport (>= 5.0) - graphlient (0.4.0) + graphlient (0.5.0) faraday (>= 1.0) faraday_middleware graphql-client @@ -456,12 +458,24 @@ GEM graphql-client (0.18.0) activesupport (>= 3.0) graphql + graphql-docs (2.1.0) + commonmarker (~> 0.16) + escape_utils (~> 1.2) + extended-markdown-filter (~> 0.4) + gemoji (~> 3.0) + graphql (~> 1.12) + html-pipeline (~> 2.9) + sass (~> 3.4) hashdiff (1.0.1) hashie (5.0.0) - highline (2.0.3) + highline (2.1.0) + hkdf (0.3.0) + html-pipeline (2.14.3) + activesupport (>= 2) + nokogiri (>= 1.4) html_tokenizer (0.0.7) htmlentities (4.3.4) - i18n (1.8.11) + i18n (1.10.0) concurrent-ruby (~> 1.0) i18n-tasks (0.9.37) activesupport (>= 4.0.2) @@ -482,7 +496,7 @@ GEM ruby-vips (>= 2.0.17, < 3) invisible_captcha (0.13.0) rails (>= 3.2.0) - json (2.6.2) + json (2.6.3) jwt (2.2.3) kaminari (1.2.2) activesupport (>= 4.1.0) @@ -502,13 +516,14 @@ GEM kramdown (~> 2.0) launchy (2.5.0) addressable (~> 2.7) - letter_opener (1.7.0) - launchy (~> 2.2) - letter_opener_web (1.4.0) - actionmailer (>= 3.2) - letter_opener (~> 1.0) - railties (>= 3.2) - listen (3.5.1) + letter_opener (1.8.1) + launchy (>= 2.2, < 3) + letter_opener_web (2.0.0) + actionmailer (>= 5.2) + letter_opener (~> 1.7) + railties (>= 5.2) + rexml + listen (3.7.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) loofah (2.3.1) @@ -528,22 +543,26 @@ GEM mime-types (3.4.1) mime-types-data (~> 3.2015) mime-types-data (3.2022.0105) - mini_magick (4.11.0) - mini_mime (1.1.1) - mini_portile2 (2.6.1) - minitest (5.14.4) + mini_magick (4.12.0) + mini_mime (1.1.2) + mini_portile2 (2.8.0) + minitest (5.15.0) mixlib-cli (2.1.8) mixlib-config (3.0.27) tomlrb mixlib-shellout (3.2.7) chef-utils - msgpack (1.4.2) + msgpack (1.4.5) multi_xml (0.6.0) multipart-post (2.2.3) mustache (1.1.1) + net-protocol (0.2.1) + timeout + net-smtp (0.3.3) + net-protocol nio4r (2.5.8) - nokogiri (1.12.5) - mini_portile2 (~> 2.6.1) + nokogiri (1.13.6) + mini_portile2 (~> 2.8.0) racc (~> 1.4) oauth (1.1.0) oauth-tty (~> 1.0, >= 1.0.1) @@ -558,7 +577,7 @@ GEM rack (>= 1.2, < 4) snaky_hash (~> 2.0) version_gem (~> 1.1) - omniauth (2.1.0) + omniauth (2.1.1) hashie (>= 3.4.6) rack (>= 2.2.3) rack-protection @@ -587,49 +606,52 @@ GEM paper_trail (12.3.0) activerecord (>= 5.2) request_store (~> 1.1) - parallel (1.20.1) - parser (3.0.2.0) + parallel (1.22.1) + parallel_tests (3.7.3) + parallel + parser (3.1.2.0) ast (~> 2.4.1) pg (1.1.4) pg_search (2.3.6) activerecord (>= 5.2) activesupport (>= 5.2) - premailer (1.18.0) + premailer (1.19.0) addressable css_parser (>= 1.12.0) htmlentities (>= 4.0.0) - premailer-rails (1.11.1) + premailer-rails (1.12.0) actionmailer (>= 3) + net-smtp premailer (~> 1.7, >= 1.7.9) - public_suffix (4.0.6) - puma (5.5.2) + public_suffix (4.0.7) + puma (5.6.4) nio4r (~> 2.0) racc (1.6.0) - rack (2.2.3) + rack (2.2.3.1) rack-attack (6.6.1) rack (>= 1.0, < 3) rack-cors (1.1.1) rack (>= 2.0.0) - rack-protection (3.0.2) + rack-protection (3.0.5) rack - rack-proxy (0.7.4) + rack-proxy (0.7.6) rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (6.0.4.1) - actioncable (= 6.0.4.1) - actionmailbox (= 6.0.4.1) - actionmailer (= 6.0.4.1) - actionpack (= 6.0.4.1) - actiontext (= 6.0.4.1) - actionview (= 6.0.4.1) - activejob (= 6.0.4.1) - activemodel (= 6.0.4.1) - activerecord (= 6.0.4.1) - activestorage (= 6.0.4.1) - activesupport (= 6.0.4.1) - bundler (>= 1.3.0) - railties (= 6.0.4.1) + rails (6.1.6) + actioncable (= 6.1.6) + actionmailbox (= 6.1.6) + actionmailer (= 6.1.6) + actionpack (= 6.1.6) + actiontext (= 6.1.6) + actionview (= 6.1.6) + activejob (= 6.1.6) + activemodel (= 6.1.6) + activerecord (= 6.1.6) + activestorage (= 6.1.6) + activesupport (= 6.1.6) + bundler (>= 1.15.0) + railties (= 6.1.6) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -643,35 +665,29 @@ GEM rails-i18n (6.0.0) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 7) - railties (6.0.4.1) - actionpack (= 6.0.4.1) - activesupport (= 6.0.4.1) + railties (6.1.6) + actionpack (= 6.1.6) + activesupport (= 6.1.6) method_source - rake (>= 0.8.7) - thor (>= 0.20.3, < 2.0) - rainbow (3.0.0) + rake (>= 12.2) + thor (~> 1.0) + rainbow (3.1.1) rake (13.0.6) ransack (2.4.2) activerecord (>= 5.2.4) activesupport (>= 5.2.4) i18n - rb-fsevent (0.11.0) + rb-fsevent (0.11.1) rb-inotify (0.10.1) ffi (~> 1.0) - rectify (0.13.0) - activemodel (>= 4.1.0) - activerecord (>= 4.1.0) - activesupport (>= 4.1.0) - virtus (~> 1.0.5) - wisper (>= 1.6.1) - redcarpet (3.5.1) + redcarpet (3.6.0) redis (4.8.0) - regexp_parser (2.1.1) + regexp_parser (2.3.1) request_store (1.5.1) rack (>= 1.4) - responders (3.0.1) - actionpack (>= 5.0) - railties (>= 5.0) + responders (3.1.0) + actionpack (>= 5.2) + railties (>= 5.2) rexml (3.2.5) rspec (3.12.0) rspec-core (~> 3.12.0) @@ -680,15 +696,15 @@ GEM rspec-cells (0.3.8) cells (>= 4.0.0, < 6.0.0) rspec-rails (>= 3.0.0, < 6.1.0) - rspec-core (3.12.0) + rspec-core (3.12.1) rspec-support (~> 3.12.0) - rspec-expectations (3.12.0) + rspec-expectations (3.12.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) rspec-html-matchers (0.9.4) nokogiri (~> 1) rspec (>= 3.0.0.a, < 4) - rspec-mocks (3.12.0) + rspec-mocks (3.12.3) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) rspec-rails (4.1.2) @@ -704,26 +720,26 @@ GEM rspec-support (3.12.0) rspec_junit_formatter (0.3.0) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.92.0) + rubocop (1.28.2) parallel (~> 1.10) - parser (>= 2.7.1.5) + parser (>= 3.1.0.0) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.7) + regexp_parser (>= 1.8, < 3.0) rexml - rubocop-ast (>= 0.5.0) + rubocop-ast (>= 1.17.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (1.5.0) - parser (>= 3.0.1.1) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.17.0) + parser (>= 3.1.1.0) rubocop-faker (1.1.0) faker (>= 2.12.0) rubocop (>= 0.82.0) - rubocop-rails (2.9.1) + rubocop-rails (2.15.2) activesupport (>= 4.2.0) rack (>= 1.1) - rubocop (>= 0.90.0, < 2.0) - rubocop-rspec (1.43.2) - rubocop (~> 0.87) + rubocop (>= 1.7.0, < 2.0) + rubocop-rspec (2.11.1) + rubocop (~> 1.19) ruby-progressbar (1.11.0) ruby-vips (2.1.4) ffi (~> 1.12) @@ -732,18 +748,26 @@ GEM nokogiri (>= 1.10.8) rubyzip (>= 1.3.0) rubyzip (2.3.2) - searchlight (4.1.0) - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + selenium-webdriver (4.1.0) + childprocess (>= 0.5, < 5.0) + rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2) semantic_range (3.0.0) seven_zip_ruby (1.3.0) - simplecov (0.19.1) + simplecov (0.21.2) docile (~> 1.1) simplecov-html (~> 0.11) - simplecov-cobertura (1.3.1) - simplecov (~> 0.8) + simplecov_json_formatter (~> 0.1) + simplecov-cobertura (2.1.0) + rexml + simplecov (~> 0.19) simplecov-html (0.12.3) + simplecov_json_formatter (0.1.4) smart_properties (1.17.0) snaky_hash (2.0.1) hashie @@ -762,33 +786,29 @@ GEM activesupport (>= 5.2) sprockets (>= 3.0.0) ssrf_filter (1.1.1) - system_test_html_screenshots (0.2.0) - actionpack (>= 5.2, < 6.1.a) - temple (0.9.1) + temple (0.10.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) - thor (1.1.0) + thor (1.2.1) thread_safe (0.3.6) tilt (2.0.11) + timeout (0.3.1) tomlrb (2.0.3) - tzinfo (1.2.9) - thread_safe (~> 0.1) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) uber (0.1.0) - unicode-display_width (1.8.0) + unicode-display_width (2.1.0) valid_email2 (2.3.1) activemodel (>= 3.2) mail (~> 2.5) version_gem (1.1.1) - virtus (1.0.5) + virtus (2.0.0) axiom-types (~> 0.1) coercible (~> 1.0) descendants_tracker (~> 0.0, >= 0.0.3) - equalizer (~> 0.0, >= 0.0.9) - virtus-multiparams (0.1.1) - virtus (~> 1.0) - voting_schemes-dummy (0.22.3) + voting_schemes-dummy (0.23.0) rails (>= 5.0.0) - voting_schemes-electionguard (0.22.3) + voting_schemes-electionguard (0.23.0) rails (>= 5.0.0) w3c_rspec_validators (0.3.0) rails @@ -800,7 +820,7 @@ GEM rexml (~> 3.2) warden (1.2.9) rack (>= 2.0.9) - web-console (4.0.4) + web-console (4.2.0) actionview (>= 6.0.0) activemodel (>= 6.0.0) bindex (>= 0.4.0) @@ -814,6 +834,9 @@ GEM rack-proxy (>= 0.6.1) railties (>= 5.2) semantic_range (>= 2.3.0) + webpush (1.1.0) + hkdf (~> 0.2) + jwt (~> 2.0) websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) @@ -823,17 +846,17 @@ GEM activesupport wisper (2.0.1) wisper-rspec (1.1.0) - wkhtmltopdf-binary (0.12.6.5) + wkhtmltopdf-binary (0.12.6.6) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.5.1) + zeitwerk (2.5.4) PLATFORMS ruby DEPENDENCIES bootsnap (~> 1.4) - brakeman (~> 5.1) + brakeman (~> 5.2) byebug (~> 11.0) decidim! decidim-conferences! @@ -843,18 +866,17 @@ DEPENDENCIES decidim-initiatives! decidim-templates! faker (~> 2.14) - foundation_rails_helper! - letter_opener_web (~> 1.3) + letter_opener_web (~> 2.0) listen (~> 3.1) - puma (>= 5.5.1) + parallel_tests (~> 3.7) + puma (>= 5.6.2) rubocop-faker - simplecov (~> 0.19.0) spring (~> 2.0) spring-watcher-listen (~> 2.0) - web-console (= 4.0.4) + web-console (~> 4.2) RUBY VERSION - ruby 2.7.5p203 + ruby 3.0.2p107 BUNDLED WITH - 2.3.5 + 2.3.20 diff --git a/README.adoc b/README.adoc index af2273591ef9c..7720f92965286 100644 --- a/README.adoc +++ b/README.adoc @@ -1,5 +1,3 @@ -D:doctype: book - image::https://cdn.rawgit.com/decidim/decidim/develop/logo.svg[Decidim Logo,400] The participatory democracy framework. @@ -9,7 +7,7 @@ Free Open-Source participatory democracy, citizen participation and open governm ____ https://decidim.org[Decidim] is a participatory democracy framework, written in Ruby on Rails, originally developed for the Barcelona City government online and offline participation website. -Installing these libraries will provide you a generator and gems to help you develop web applications like the ones found on <> or like http://staging.decidim.codegram.com[our demo application]. +Installing these libraries will provide you a generator and gems to help you develop web applications like the ones found on <> or like https://try.decidim.org[our demo application]. All members of the Decidim community agree with http://www.decidim.org/contract/[Decidim Social Contract or Code of Democratic Guarantees]. @@ -19,38 +17,7 @@ image:https://img.shields.io/gem/v/decidim.svg[Gem,link=https://rubygems.org/gem Code quality -image:https://codecov.io/gh/decidim/decidim/branch/develop/graph/badge.svg[codecov,link=https://codecov.io/gh/decidim/decidim] image:https://api.codeclimate.com/v1/badges/ad8fa445086e491486b6/maintainability[Maintainability,link=https://codeclimate.com/github/decidim/decidim/maintainability] image:https://d322cqt584bo4o.cloudfront.net/decidim/localized.svg[Crowdin,link=https://crowdin.com/project/decidim] image:http://inch-ci.org/github/decidim/decidim.svg?branch=develop[Inline docs,link=http://inch-ci.org/github/decidim/decidim] image:https://rocketvalidator.com/badges/a11y_issues.svg?url=http://staging.decidim.codegram.com/[Accessibility issues,link=https://rocketvalidator.com/badges/link?url=http://staging.decidim.codegram.com/&report=a11y] image:https://rocketvalidator.com/badges/html_issues.svg?url=http://staging.decidim.codegram.com/[HTML issues,link=https://rocketvalidator.com/badges/link?url=http://staging.decidim.codegram.com/&report=html] - -Test suite - -+++

+++++++++See all++++++ -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Accountability/develop.svg?label=%5BCI%5D%20Accountability[Accountability,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Api/develop.svg?label=%5BCI%5D%20Api[Api,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Assemblies/develop.svg?label=%5BCI%5D%20Assemblies[Assemblies,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Blogs/develop.svg?label=%5BCI%5D%20Blogs[Blogs,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Budgets/develop.svg?label=%5BCI%5D%20Budgets[Budgets,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Comments/develop.svg?label=%5BCI%5D%20Comments[Comments,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Conferences/develop.svg?label=%5BCI%5D%20Conferences[Conferences,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Consultations/develop.svg?label=%5BCI%5D%20Consultations[Consultations,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Core/develop.svg?label=%5BCI%5D%20Core[Core,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Debates/develop.svg?label=%5BCI%5D%20Debates[Debates,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Forms/develop.svg?label=%5BCI%5D%20Forms[Forms,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Generators/develop.svg?label=%5BCI%5D%20Generators[Generators,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Initiatives/develop.svg?label=%5BCI%5D%20Initiatives[Initiatives,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Main%20folder/develop.svg?label=%5BCI%5D%20Main[Main,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Meetings/develop.svg?label=%5BCI%5D%20Meetings[Meetings,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Pages/develop.svg?label=%5BCI%5D%20Pages[Pages,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Participatory%20processes/develop.svg?label=%5BCI%5D%20Participatory%20processes[Participatory processes,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Proposals%20(system%20admin)/develop.svg?label=%5BCI%5D%20Proposals%20(system%20admin)[Proposals (system admin),link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Proposals%20(system%20public)/develop.svg?label=%5BCI%5D%20Proposals%20(system%20public)[Proposals (system admin),link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Proposals%20(unit%20tests)/develop.svg?label=%5BCI%5D%20Proposals%20(unit%20tests)[Proposals (unit tests),link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Sortitions/develop.svg?label=%5BCI%5D%20Sortitions[Sortitions,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Surveys/develop.svg?label=%5BCI%5D%20Surveys[Surveys,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20System/develop.svg?label=%5BCI%5D%20System[System,link=https://github.com/decidim/decidim/actions] -image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20Verifications/develop.svg?label=%5BCI%5D%20Verifications[Verifications,link=https://github.com/decidim/decidim/actions] -+++
+++ - -''' +image:https://codecov.io/gh/decidim/decidim/branch/develop/graph/badge.svg[codecov,link=https://codecov.io/gh/decidim/decidim] image:https://api.codeclimate.com/v1/badges/ad8fa445086e491486b6/maintainability[Maintainability,link=https://codeclimate.com/github/decidim/decidim/maintainability] image:https://d322cqt584bo4o.cloudfront.net/decidim/localized.svg[Crowdin,link=https://crowdin.com/project/decidim] = What do you need to do? @@ -58,7 +25,11 @@ image:https://img.shields.io/github/workflow/status/decidim/decidim/%5BCI%5D%20V - <> - <> - <> -- <> +- <> +- <> +- <> +- <> +- <> ''' @@ -115,3 +86,7 @@ Security is very important to us. If you have any issue regarding security, please disclose the information responsibly by sending an email to security [at] decidim [dot] org and not by creating a github/metadecidim issue. We appreciate your effort to make Decidim more secure. See xref:SECURITY.adoc[full security policy]. + +== Donations + +If you want to support the project, consider making a donation through our https://opencollective.com/decidim[OpenCollective profile]. diff --git a/SECURITY.adoc b/SECURITY.adoc index 5976fd090631a..a6b5326ba586d 100644 --- a/SECURITY.adoc +++ b/SECURITY.adoc @@ -7,10 +7,10 @@ Until we have the version 1.0 we support only the last minor and major version w |=== | Version | Supported -| 0.25.x +| 0.26.x | :white_check_mark: -| \<= 0.24 +| \<= 0.25 | :x: |=== diff --git a/babel.config.json b/babel.config.json index e5811e1aec20c..551d4bec5e5db 100644 --- a/babel.config.json +++ b/babel.config.json @@ -20,11 +20,9 @@ "corejs": false } ], - [ - "@babel/plugin-transform-regenerator", - { - "async": false - } - ] + [ "@babel/plugin-transform-regenerator", { "async": false }], + [ "@babel/plugin-proposal-private-property-in-object", { "loose": true }], + ["@babel/plugin-proposal-private-methods", { "loose": true }], + ["@babel/plugin-proposal-class-properties", { "loose": true }] ] } diff --git a/bin/changelog_generator b/bin/changelog_generator index 860b00feb55fc..e2f828b5c2075 100755 --- a/bin/changelog_generator +++ b/bin/changelog_generator @@ -4,171 +4,204 @@ require "json" require "ruby-progressbar" -# rubocop:disable Style/GlobalVars +class EmptyTokenError < RuntimeError + def full_message + <<~HELP + Decidim's changelog generator. -$github_token = ARGV[0] -$since_sha = ARGV[1] || "HEAD~5" + ## Example -if $github_token.nil? || $github_token == "--help" - puts <<~HELP - Decidim's changelog generator. + bin/changelog_generator - ## Example + ## Params - bin/changelog_generator + The can be obtained from https://github.com/settings/tokens/new + You'll need to create one with `public_repo` access. - ## Params + The is the git commit SHA from which to consider the changes. It's + usually the last commit that modified the `.decidim_version` file. - The can be obtained from https://github.com/settings/tokens/new - You'll need to create one with `public_repo` access. + ## Explanation - The is the git commit SHA from which to consider the changes. It's - usually the last commit that modified the `.decidim_version` file. + This script will generate the sections needed for the changelog, using the + labels of the merged PRs as a source of truth. It will add a section at the + end, "Unsorted", with the list of PRs that couldn't be classified. - ## Explanation + It ignores any Crowdin PR. + HELP + end +end - This script will generate the sections needed for the changelog, using the - labels of the merged PRs as a source of truth. It will add a section at the - end, "Unsorted", with the list of PRs that couldn't be classified. +class ChangeLogGenerator + TYPES = { + "Added" => { + label: "type: feature", + skip_modules: false + }, + "Changed" => { + label: "type: change", + skip_modules: false + }, + "Fixed" => { + label: "type: fix", + skip_modules: false + }, + "Removed" => { + label: "type: removal", + skip_modules: false + }, + "Developer improvements" => { + label: "target: developer-experience", + skip_modules: true + }, + "Internal" => { + label: "type: internal", + skip_modules: false + } + }.freeze + + def initialize(github_token, since_sha) + @github_token = github_token + @since_sha = since_sha + @output_file = [] + @handled_ids = [] + + @progress_bar = ProgressBar.create(title: "PRs", total: list_of_commits.count) + end - It ignores any Crowdin PR. - HELP + def run + raise EmptyTokenError if github_token.nil? || github_token == "--help" - exit 1 -end + TYPES.each do |type_title, type_data| + type_prs = prs.select do |_commit_title, data| + next unless data -list_of_commits = `git log #{$since_sha}..HEAD --oneline`.split("\n").reverse + data[:type].include?(type_data[:label]) + end -$output_file = [] -$progressbar = ProgressBar.create(title: "PRs", total: list_of_commits.count) + output "### #{type_title}" + output "" -def crowdin?(commit) - !commit.match(/New Crowdin updates/).nil? -end + if type_prs.any? + type_prs.each do |_pr_title, data| + process_single_pr(data, type_data) + end + else + output "Nothing." + end -def get_pr_id(commit) - id = commit.scan(/#\d+/).last - return unless id + output "" + end - id.delete_prefix("#") -end + process_unsorted_prs + write_data_file! + end -def get_pr_data(commit) - $progressbar.increment + private - id = get_pr_id(commit) - return nil unless id + def write_data_file! + File.write("temporary_changelog.md", @output_file.join("\n")) + puts "Written file: temporary_changelog.md" + end - data = get_data_for_pr(id) - labels = data["labels"].map { |l| l["name"] }.sort - title = data["title"] + def process_single_pr(data, type_data) + modules_list = data[:modules].map { |l| "**decidim-#{l.delete_prefix("module: ")}**" } + id = data[:id] + title = data[:title] - { - id: id, - title: title, - labels: labels, - type: labels.select { |l| l.match(/^type: /) || l == "target: developer-experience" }, - modules: labels.select { |l| l.match(/^module: /) } - } -end + @handled_ids << id -def get_data_for_pr(id) - uri = "https://api.github.com/repos/decidim/decidim/issues/#{id}" - response = `curl -s -H "Authorization: token #{$github_token}" "#{uri}"` - JSON.parse(response) -end + if type_data[:skip_modules] || modules_list.empty? + output "- #{title} #{pr_link(id)}" + else + output "- #{modules_list.join(", ")}: #{title} #{pr_link(id)}" + end + end -def pr_link(id) - # We need to do this so that it generates the expected Markdown format. - # String interpolation messes with the format. - "[#{"\\#" + id.to_s}](https://github.com/decidim/decidim/pull/#{id})" # rubocop:disable Style/StringConcatenation -end + def process_unsorted_prs + return unless unsorted_prs.any? -def output(str) - $output_file << str -end + output "### Unsorted" + output "" -handled_ids = [] + unsorted_prs.map do |title, data| + pr_data = data || {} + output "- #{title} #{pr_link(pr_data[:id])} || #{data}" + end + end -prs = list_of_commits.inject({}) do |acc, commit| - next acc if crowdin?(commit) + def unsorted_prs + @unsorted_prs ||= prs.reject do |_commit_title, data| + pr_data = data || {} - acc.update(commit => get_pr_data(commit)) -end + @handled_ids.include?(pr_data[:id]) + end + end + + attr_reader :github_token, :since_sha + + def prs + @prs ||= list_of_commits.inject({}) do |acc, commit| + next acc if crowdin?(commit) -types = { - "Added" => { - label: "type: feature", - skip_modules: false - }, - "Changed" => { - label: "type: change", - skip_modules: false - }, - "Fixed" => { - label: "type: fix", - skip_modules: false - }, - "Removed" => { - label: "type: removal", - skip_modules: false - }, - "Internal" => { - label: "type: internal", - skip_modules: true - }, - "Developer improvements" => { - label: "target: developer-experience", - skip_modules: true - } -} - -types.each do |type_title, type_data| - type_prs = prs.select do |_commit_title, data| - next unless data - - data[:type].include?(type_data[:label]) + acc.update(commit => get_pr_data(commit)) + end end - output "### #{type_title}" - output "" + def list_of_commits + @list_of_commits ||= `git log #{since_sha}..HEAD --oneline`.split("\n").reverse + end - if type_prs.any? - type_prs.each do |_pr_title, data| - modules_list = data[:modules].map { |l| "**decidim-#{l.delete_prefix("module: ")}**" } - id = data[:id] - title = data[:title] + def crowdin?(commit) + !commit.match(/New Crowdin updates/).nil? + end - handled_ids << id + def get_pr_id(commit) + id = commit.scan(/#\d+/).last + return unless id - if type_data[:skip_modules] || modules_list.empty? - output "- #{title} #{pr_link(id)}" - else - output "- #{modules_list.join(", ")}: #{title} #{pr_link(id)}" - end - end - else - output "Nothing." + id.delete_prefix("#") end - output "" -end + def get_pr_data(commit) + @progress_bar.increment -unsorted_prs = prs.reject do |_commit_title, data| - pr_data = data || {} + id = get_pr_id(commit) + return nil unless id - handled_ids.include?(pr_data[:id]) -end + data = get_data_for_pr(id) + labels = data["labels"].map { |l| l["name"] }.sort + title = data["title"] + + { + id: id, + title: title, + labels: labels, + type: labels.select { |l| l.match(/^type: /) || l == "target: developer-experience" }, + modules: labels.select { |l| l.match(/^module: /) } + } + end -if unsorted_prs.any? - output "### Unsorted" - output "" + def get_data_for_pr(id) + uri = "https://api.github.com/repos/decidim/decidim/issues/#{id}" + response = `curl -s -H "Authorization: token #{github_token}" "#{uri}"` + JSON.parse(response) + end + + def pr_link(id) + # We need to do this so that it generates the expected Markdown format. + # String interpolation messes with the format. + "[#{"\\#" + id.to_s}](https://github.com/decidim/decidim/pull/#{id})" # rubocop:disable Style/StringConcatenation + end - unsorted_prs.map do |title, data| - pr_data = data || {} - output "- #{title} #{pr_link(pr_data[:id])} || #{data}" + def output(str) + @output_file << str end end -File.write("temporary_changelog.md", $output_file.join("\n")) -# rubocop:enable Style/GlobalVars +begin + ChangeLogGenerator.new(ARGV[0], ARGV[1] || "HEAD~5").run +rescue EmptyTokenError => e + puts e.full_message + exit 1 +end diff --git a/bin/rspec b/bin/rspec index 50d5ccf425ed3..a6e61fc541f0e 100755 --- a/bin/rspec +++ b/bin/rspec @@ -17,7 +17,7 @@ if ARGV[0] other_parts = argument_parts[1..-1] - new_args = [!other_parts.empty? ? other_parts.join("/") : nil, *ARGV[1..-1]].compact + new_args = [other_parts.empty? ? nil : other_parts.join("/"), *ARGV[1..-1]].compact ARGV.replace(new_args) end diff --git a/codecov.yml b/codecov.yml index 822796e9636a0..70b8ad488a139 100644 --- a/codecov.yml +++ b/codecov.yml @@ -6,6 +6,7 @@ ignore: - "decidim-*/lib/decidim/**/participatory_space.rb" coverage: status: + patch: false project: default: threshold: 0.1% diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 2d6367dcd2106..3a3148116c0ca 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -65,6 +65,7 @@ search: ## %w(*.jpg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less *.yml *.json) exclude: - decidim-dev/lib/decidim/dev/assets/iso-8859-15.md + - decidim-dev/lib/decidim/dev/assets/import_participatory_space_private_users_iso8859-1.csv - decidim-comments/app/assets/javascripts/decidim/comments/bundle.js - decidim-comments/app/assets/javascripts/decidim/comments/bundle.js.map - "*.jpeg" @@ -109,6 +110,7 @@ ignore_missing: - decidim.budgets.projects_helper.current_rule_explanation.* - decidim.budgets.projects_helper.current_rule_description.* - decidim.debates.debate_m.footer.commented_time_ago + - explanation # Consider these keys used: ignore_unused: @@ -132,6 +134,7 @@ ignore_unused: - decidim.forms.errors.* - decidim.forms.file_help.* - decidim.forms.user_answers_serializer.* + - decidim.forms.admin_log.questionnaire.update - decidim.proposals.answers.* - decidim.proposals.collaborative_drafts.show.see_other_versions - decidim.proposals.collaborative_drafts.wizard_aside.back @@ -296,7 +299,7 @@ ignore_unused: - decidim.elections.trustee_zone.trustees.show.identification_keys.upload_error.* - decidim.elections.feedback.answer.* - decidim.elections.trustee_zone.elections.key_ceremony_steps.keys.* - - decidim.elections.trustee_zone.elections.tally_steps.keys.* + - decidim.elections.trustee_zone.elections.tally_started_steps.keys.* - decidim.votings.admin_log.* - decidim.votings.admin.content_blocks.landing_page.* - decidim.votings.census.admin.census.new.file_help.* @@ -317,6 +320,9 @@ ignore_unused: - decidim.assemblies.admin.assembly_members.form.explanation - decidim.assemblies.admin.assembly_members.form.image_guide - decidim.assemblies.admin.assembly_members.form.non_user_avatar_help + - decidim.blogs.admin_log.* + - decidim.templates.admin_log.* + - decidim.forms.upload_help.explanation ## Exclude these keys from the `i18n-tasks eq-base' report: # ignore_eq_base: diff --git a/decidim-accountability/app/cells/decidim/accountability/highlighted_results_for_component_cell.rb b/decidim-accountability/app/cells/decidim/accountability/highlighted_results_for_component_cell.rb index dba15a314a849..96a4e5fc2aded 100644 --- a/decidim-accountability/app/cells/decidim/accountability/highlighted_results_for_component_cell.rb +++ b/decidim-accountability/app/cells/decidim/accountability/highlighted_results_for_component_cell.rb @@ -21,7 +21,7 @@ def show private def results - @results ||= Decidim::Accountability::Result.where(component: model).order_randomly(rand * 2 - 1) + @results ||= Decidim::Accountability::Result.where(component: model).order_randomly((rand * 2) - 1) end def results_to_render @@ -31,6 +31,18 @@ def results_to_render def results_count @results_count ||= results.count end + + def cache_hash + hash = [] + hash << "decidim/accountability/highlighted_results_for_component" + hash << results.cache_key_with_version + hash << I18n.locale.to_s + hash.join(Decidim.cache_key_separator) + end + + def cache_expiry_time + 10.minutes + end end end end diff --git a/decidim-accountability/app/commands/decidim/accountability/admin/create_imported_result.rb b/decidim-accountability/app/commands/decidim/accountability/admin/create_imported_result.rb index 72334d1608257..73f4dcd47ee63 100644 --- a/decidim-accountability/app/commands/decidim/accountability/admin/create_imported_result.rb +++ b/decidim-accountability/app/commands/decidim/accountability/admin/create_imported_result.rb @@ -5,7 +5,7 @@ module Accountability module Admin # This command is executed when the user creates a Result from the admin # panel. - class CreateImportedResult < Rectify::Command + class CreateImportedResult < Decidim::Command def initialize(form, parent_id = nil) @form = form @parent_id = parent_id diff --git a/decidim-accountability/app/commands/decidim/accountability/admin/create_result.rb b/decidim-accountability/app/commands/decidim/accountability/admin/create_result.rb index b7be58e3039db..2f17ab9c3adb3 100644 --- a/decidim-accountability/app/commands/decidim/accountability/admin/create_result.rb +++ b/decidim-accountability/app/commands/decidim/accountability/admin/create_result.rb @@ -5,7 +5,7 @@ module Accountability module Admin # This command is executed when the user creates a Result from the admin # panel. - class CreateResult < Rectify::Command + class CreateResult < Decidim::Command def initialize(form) @form = form end diff --git a/decidim-accountability/app/commands/decidim/accountability/admin/create_status.rb b/decidim-accountability/app/commands/decidim/accountability/admin/create_status.rb index 66759635eb6fc..e976bd33a09e1 100644 --- a/decidim-accountability/app/commands/decidim/accountability/admin/create_status.rb +++ b/decidim-accountability/app/commands/decidim/accountability/admin/create_status.rb @@ -5,9 +5,10 @@ module Accountability module Admin # This command is executed when the user creates a Status from the admin # panel. - class CreateStatus < Rectify::Command - def initialize(form) + class CreateStatus < Decidim::Command + def initialize(form, user) @form = form + @user = user end # Creates the status if valid. @@ -28,7 +29,9 @@ def call attr_reader :status def create_status - @status = Status.create!( + @status = Decidim.traceability.create!( + Status, + @user, component: @form.current_component, key: @form.key, name: @form.name, diff --git a/decidim-accountability/app/commands/decidim/accountability/admin/create_timeline_entry.rb b/decidim-accountability/app/commands/decidim/accountability/admin/create_timeline_entry.rb index 7def45b2d973a..8cc2c26d88a69 100644 --- a/decidim-accountability/app/commands/decidim/accountability/admin/create_timeline_entry.rb +++ b/decidim-accountability/app/commands/decidim/accountability/admin/create_timeline_entry.rb @@ -5,9 +5,10 @@ module Accountability module Admin # This command is executed when the user creates a TimelineEntry # for a Result from the admin panel. - class CreateTimelineEntry < Rectify::Command - def initialize(form) + class CreateTimelineEntry < Decidim::Command + def initialize(form, user) @form = form + @user = user end # Creates the timeline_entry if valid. @@ -28,7 +29,9 @@ def call attr_reader :timeline_entry, :form def create_timeline_entry - @timeline_entry = TimelineEntry.create!( + @timeline_entry = Decidim.traceability.create!( + TimelineEntry, + @user, decidim_accountability_result_id: form.decidim_accountability_result_id, entry_date: form.entry_date, title: form.title, diff --git a/decidim-accountability/app/commands/decidim/accountability/admin/destroy_result.rb b/decidim-accountability/app/commands/decidim/accountability/admin/destroy_result.rb index fc570baa66324..7dc3850967b8c 100644 --- a/decidim-accountability/app/commands/decidim/accountability/admin/destroy_result.rb +++ b/decidim-accountability/app/commands/decidim/accountability/admin/destroy_result.rb @@ -5,7 +5,7 @@ module Accountability module Admin # This command is executed when the user destroys a Result from the admin # panel. - class DestroyResult < Rectify::Command + class DestroyResult < Decidim::Command # Initializes an UpdateResult Command. # # result - The current instance of the result to be destroyed. diff --git a/decidim-accountability/app/commands/decidim/accountability/admin/update_imported_result.rb b/decidim-accountability/app/commands/decidim/accountability/admin/update_imported_result.rb index 28a896dace13c..0b041f269b8c6 100644 --- a/decidim-accountability/app/commands/decidim/accountability/admin/update_imported_result.rb +++ b/decidim-accountability/app/commands/decidim/accountability/admin/update_imported_result.rb @@ -5,7 +5,7 @@ module Accountability module Admin # This command is executed when the user changes a Result from the admin # panel. - class UpdateImportedResult < Rectify::Command + class UpdateImportedResult < Decidim::Command # Initializes an UpdateResult Command. # # form - The form from which to get the data. diff --git a/decidim-accountability/app/commands/decidim/accountability/admin/update_result.rb b/decidim-accountability/app/commands/decidim/accountability/admin/update_result.rb index 3ec5eb79aebc1..23f6fb1daa3b9 100644 --- a/decidim-accountability/app/commands/decidim/accountability/admin/update_result.rb +++ b/decidim-accountability/app/commands/decidim/accountability/admin/update_result.rb @@ -5,7 +5,7 @@ module Accountability module Admin # This command is executed when the user changes a Result from the admin # panel. - class UpdateResult < Rectify::Command + class UpdateResult < Decidim::Command # Initializes an UpdateResult Command. # # form - The form from which to get the data. diff --git a/decidim-accountability/app/commands/decidim/accountability/admin/update_status.rb b/decidim-accountability/app/commands/decidim/accountability/admin/update_status.rb index b778f14dc98b6..d013d8f453527 100644 --- a/decidim-accountability/app/commands/decidim/accountability/admin/update_status.rb +++ b/decidim-accountability/app/commands/decidim/accountability/admin/update_status.rb @@ -5,14 +5,15 @@ module Accountability module Admin # This command is executed when the user changes a Result from the admin # panel. - class UpdateStatus < Rectify::Command + class UpdateStatus < Decidim::Command # Initializes an UpdateStatus Command. # # form - The form from which to get the data. # status - The current instance of the status to be updated. - def initialize(form, status) + def initialize(form, status, user) @form = form @status = status + @user = user end # Updates the status if valid. @@ -33,7 +34,9 @@ def call attr_reader :status, :form def update_status - status.update!( + Decidim.traceability.update!( + status, + @user, key: @form.key, name: @form.name, description: @form.description, diff --git a/decidim-accountability/app/commands/decidim/accountability/admin/update_timeline_entry.rb b/decidim-accountability/app/commands/decidim/accountability/admin/update_timeline_entry.rb index 1feee2a24cb3c..6a787db870138 100644 --- a/decidim-accountability/app/commands/decidim/accountability/admin/update_timeline_entry.rb +++ b/decidim-accountability/app/commands/decidim/accountability/admin/update_timeline_entry.rb @@ -5,14 +5,15 @@ module Accountability module Admin # This command is executed when the user changes a Result from the admin # panel. - class UpdateTimelineEntry < Rectify::Command + class UpdateTimelineEntry < Decidim::Command # Initializes an UpdateTimelineEntry Command. # # form - The form from which to get the data. # timeline_entry - The current instance of the timeline_entry to be updated. - def initialize(form, timeline_entry) + def initialize(form, timeline_entry, user) @form = form @timeline_entry = timeline_entry + @user = user end # Updates the timeline_entry if valid. @@ -33,7 +34,9 @@ def call attr_reader :timeline_entry, :form def update_timeline_entry - timeline_entry.update!( + Decidim.traceability.update!( + timeline_entry, + @user, entry_date: form.entry_date, title: form.title, description: form.description diff --git a/decidim-accountability/app/controllers/decidim/accountability/admin/statuses_controller.rb b/decidim-accountability/app/controllers/decidim/accountability/admin/statuses_controller.rb index d9fb24bd2efac..996fc4cda109e 100644 --- a/decidim-accountability/app/controllers/decidim/accountability/admin/statuses_controller.rb +++ b/decidim-accountability/app/controllers/decidim/accountability/admin/statuses_controller.rb @@ -18,7 +18,7 @@ def create @form = form(StatusForm).from_params(params) - CreateStatus.call(@form) do + CreateStatus.call(@form, current_user) do on(:ok) do flash[:notice] = I18n.t("statuses.create.success", scope: "decidim.accountability.admin") redirect_to statuses_path @@ -42,7 +42,7 @@ def update @form = form(StatusForm).from_params(params) - UpdateStatus.call(@form, status) do + UpdateStatus.call(@form, status, current_user) do on(:ok) do flash[:notice] = I18n.t("statuses.update.success", scope: "decidim.accountability.admin") redirect_to statuses_path @@ -58,7 +58,9 @@ def update def destroy enforce_permission_to :destroy, :status, status: status - status.destroy! + Decidim.traceability.perform_action!("delete", status, current_user) do + status.destroy! + end flash[:notice] = I18n.t("statuses.destroy.success", scope: "decidim.accountability.admin") diff --git a/decidim-accountability/app/controllers/decidim/accountability/admin/timeline_entries_controller.rb b/decidim-accountability/app/controllers/decidim/accountability/admin/timeline_entries_controller.rb index c9778d07cbdb8..0b6fe64e2e3e6 100644 --- a/decidim-accountability/app/controllers/decidim/accountability/admin/timeline_entries_controller.rb +++ b/decidim-accountability/app/controllers/decidim/accountability/admin/timeline_entries_controller.rb @@ -19,7 +19,7 @@ def create @form = form(TimelineEntryForm).from_params(params) @form.decidim_accountability_result_id = params[:result_id] - CreateTimelineEntry.call(@form) do + CreateTimelineEntry.call(@form, current_user) do on(:ok) do flash[:notice] = I18n.t("timeline_entries.create.success", scope: "decidim.accountability.admin") redirect_to result_timeline_entries_path(params[:result_id]) @@ -43,7 +43,7 @@ def update @form = form(TimelineEntryForm).from_params(params) - UpdateTimelineEntry.call(@form, timeline_entry) do + UpdateTimelineEntry.call(@form, timeline_entry, current_user) do on(:ok) do flash[:notice] = I18n.t("timeline_entries.update.success", scope: "decidim.accountability.admin") redirect_to result_timeline_entries_path(params[:result_id]) @@ -59,7 +59,9 @@ def update def destroy enforce_permission_to :destroy, :timeline_entry, timeline_entry: timeline_entry - timeline_entry.destroy! + Decidim.traceability.perform_action!("delete", timeline_entry, current_user) do + timeline_entry.destroy! + end flash[:notice] = I18n.t("timeline_entries.destroy.success", scope: "decidim.accountability.admin") diff --git a/decidim-accountability/app/controllers/decidim/accountability/results_controller.rb b/decidim-accountability/app/controllers/decidim/accountability/results_controller.rb index e3eebb3b72461..d666bd396cfca 100644 --- a/decidim-accountability/app/controllers/decidim/accountability/results_controller.rb +++ b/decidim-accountability/app/controllers/decidim/accountability/results_controller.rb @@ -17,30 +17,30 @@ def show private def results - parent_id = params[:parent_id].presence - @results ||= search.results.where(parent_id: parent_id).page(params[:page]).per(12) + @results ||= begin + parent_id = params[:parent_id].presence + search.result.where( + parent_id: [parent_id] + Result.where(parent_id: parent_id).pluck(:id) + ).page(params[:page]).per(12) + end end def result - @result ||= Result.includes(:timeline_entries).where(component: current_component).find(params[:id]) + @result ||= search_collection.includes(:timeline_entries).find_by(id: params[:id]) end - def search_klass - ResultSearch + def search_collection + Result.where(component: current_component) end def default_filter_params { - search_text: "", - scope_id: "", - category_id: "" + search_text_cont: "", + with_scope: "", + with_category: "" } end - def context_params - { component: current_component, organization: current_organization } - end - def first_class_categories @first_class_categories ||= current_participatory_space.categories.first_class end diff --git a/decidim-accountability/app/forms/decidim/accountability/admin/result_form.rb b/decidim-accountability/app/forms/decidim/accountability/admin/result_form.rb index a8a38c1d0f8fa..3ea263cedf000 100644 --- a/decidim-accountability/app/forms/decidim/accountability/admin/result_form.rb +++ b/decidim-accountability/app/forms/decidim/accountability/admin/result_form.rb @@ -59,14 +59,14 @@ def projects # # Returns a Decidim::Scope def scope - @scope ||= @decidim_scope_id ? current_component.scopes.find_by(id: @decidim_scope_id) : current_component.scope + @scope ||= @attributes["decidim_scope_id"].value ? current_component.scopes.find_by(id: @attributes["decidim_scope_id"].value) : current_component.scope end # Scope identifier # # Returns the scope identifier related to the result def decidim_scope_id - @decidim_scope_id || scope&.id + super || scope&.id end def category diff --git a/decidim-accountability/app/helpers/decidim/accountability/breadcrumb_helper.rb b/decidim-accountability/app/helpers/decidim/accountability/breadcrumb_helper.rb index 837f724e5a417..018f1cbaecf42 100644 --- a/decidim-accountability/app/helpers/decidim/accountability/breadcrumb_helper.rb +++ b/decidim-accountability/app/helpers/decidim/accountability/breadcrumb_helper.rb @@ -10,7 +10,7 @@ def stats_calculator end def current_scope - params[:filter][:scope_id] if params[:filter] + params[:filter][:with_scope] if params[:filter] end def progress_calculator(scope_id, category_id) @@ -18,7 +18,7 @@ def progress_calculator(scope_id, category_id) end def category - return if (category_id = params.dig(:filter, :category_id)).blank? + return if (category_id = params.dig(:filter, :with_category)).blank? @category ||= current_participatory_space.categories.find(category_id.is_a?(Array) ? category_id.first : category_id) end diff --git a/decidim-accountability/app/models/decidim/accountability/result.rb b/decidim-accountability/app/models/decidim/accountability/result.rb index 5d6b5875eb51e..b44bca63ff500 100644 --- a/decidim-accountability/app/models/decidim/accountability/result.rb +++ b/decidim-accountability/app/models/decidim/accountability/result.rb @@ -15,10 +15,11 @@ class Result < Accountability::ApplicationRecord include Decidim::Comments::CommentableWithComponent include Decidim::Traceable include Decidim::Loggable - include Decidim::DataPortability + include Decidim::DownloadYourData include Decidim::Randomable include Decidim::Searchable include Decidim::TranslatableResource + include Decidim::FilterableResource component_manifest_name "accountability" @@ -81,14 +82,17 @@ def allow_resource_permissions? true end + def self.ransackable_scopes(_auth_object = nil) + [:with_category, :with_scope] + end + ransacker :id_string do Arel.sql(%{cast("decidim_accountability_results"."id" as text)}) end - # Allow ransacker to search for a key in a hstore column (`title`.`en`) - ransacker :title do |parent| - Arel::Nodes::InfixOperation.new("->>", parent.table[:title], Arel::Nodes.build_quoted(I18n.locale.to_s)) - end + # Create i18n ransackers for :title and :description. + # Create the :search_text ransacker alias for searching from both of these. + ransacker_i18n_multi :search_text, [:title, :description] private diff --git a/decidim-accountability/app/models/decidim/accountability/status.rb b/decidim-accountability/app/models/decidim/accountability/status.rb index f72d575fada3f..b1f26ee23077c 100644 --- a/decidim-accountability/app/models/decidim/accountability/status.rb +++ b/decidim-accountability/app/models/decidim/accountability/status.rb @@ -7,6 +7,8 @@ module Accountability class Status < Accountability::ApplicationRecord include Decidim::HasComponent include Decidim::TranslatableResource + include Decidim::FilterableResource + include Decidim::Traceable component_manifest_name "accountability" @@ -18,8 +20,10 @@ class Status < Accountability::ApplicationRecord validates :name, presence: true # Allow ransacker to search for a key in a hstore column (`name`.`en`) - ransacker :name do |parent| - Arel::Nodes::InfixOperation.new("->>", parent.table[:name], Arel::Nodes.build_quoted(I18n.locale.to_s)) + ransacker_i18n :name + + def self.log_presenter_class_for(_log) + Decidim::Accountability::AdminLog::StatusPresenter end end end diff --git a/decidim-accountability/app/models/decidim/accountability/timeline_entry.rb b/decidim-accountability/app/models/decidim/accountability/timeline_entry.rb index 90be57c3e430b..ba1ce22ce2d20 100644 --- a/decidim-accountability/app/models/decidim/accountability/timeline_entry.rb +++ b/decidim-accountability/app/models/decidim/accountability/timeline_entry.rb @@ -6,10 +6,15 @@ module Accountability # It stores a date, and localized description. class TimelineEntry < Accountability::ApplicationRecord include Decidim::TranslatableResource + include Decidim::Traceable translatable_fields :title translatable_fields :description belongs_to :result, foreign_key: "decidim_accountability_result_id", class_name: "Decidim::Accountability::Result", inverse_of: :timeline_entries + + def self.log_presenter_class_for(_log) + Decidim::Accountability::AdminLog::TimelineEntryPresenter + end end end end diff --git a/decidim-accountability/app/presenters/decidim/accountability/admin_log/status_presenter.rb b/decidim-accountability/app/presenters/decidim/accountability/admin_log/status_presenter.rb new file mode 100644 index 0000000000000..7d3de7c21b356 --- /dev/null +++ b/decidim-accountability/app/presenters/decidim/accountability/admin_log/status_presenter.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module Decidim + module Accountability + module AdminLog + # This class holds the logic to present a `Decidim::Accountability::Status` + # for the `AdminLog` log. + # + # Usage should be automatic and you shouldn't need to call this class + # directly, but here's an example: + # + # action_log = Decidim::ActionLog.last + # view_helpers # => this comes from the views + # StatusPresenter.new(action_log, view_helpers).present + class StatusPresenter < Decidim::Log::BasePresenter + private + + def action_string + case action + when "create", "delete", "update" + "decidim.accountability.admin_log.status.#{action}" + else + super + end + end + + def diff_fields_mapping + { + key: :string, + name: :i18n, + description: :i18n, + progress: :integer + } + end + end + end + end +end diff --git a/decidim-accountability/app/presenters/decidim/accountability/admin_log/timeline_entry_presenter.rb b/decidim-accountability/app/presenters/decidim/accountability/admin_log/timeline_entry_presenter.rb new file mode 100644 index 0000000000000..4597d21eb0d41 --- /dev/null +++ b/decidim-accountability/app/presenters/decidim/accountability/admin_log/timeline_entry_presenter.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module Decidim + module Accountability + module AdminLog + # This class holds the logic to present a `Decidim::Accountability::TimelineEntry` + # for the `AdminLog` log. + # + # Usage should be automatic and you shouldn't need to call this class + # directly, but here's an example: + # + # action_log = Decidim::ActionLog.last + # view_helpers # => this comes from the views + # TimelineEntryPresenter.new(action_log, view_helpers).present + class TimelineEntryPresenter < Decidim::Log::BasePresenter + private + + def action_string + case action + when "create", "delete", "update" + "decidim.accountability.admin_log.timeline_entry.#{action}" + else + super + end + end + + def diff_fields_mapping + { + entry_date: :date, + description: :i18n, + title: :i18n + } + end + end + end + end +end diff --git a/decidim-accountability/app/services/decidim/accountability/result_search.rb b/decidim-accountability/app/services/decidim/accountability/result_search.rb deleted file mode 100644 index e5a63decc32ed..0000000000000 --- a/decidim-accountability/app/services/decidim/accountability/result_search.rb +++ /dev/null @@ -1,48 +0,0 @@ -# frozen_string_literal: true - -module Decidim - module Accountability - # This class handles search and filtering of results. Needs a - # `current_component` param with a `Decidim::Component` in order to - # find the results. - class ResultSearch < ResourceSearch - text_search_fields :title, :description - - # Public: Initializes the service. - # - # options - A hash of options to modify the search. These options will be - # converted to methods by SearchLight so they can be used on filter - # methods. (Default {}) - # * component - A Decidim::Component to get the results from. - # * organization - A Decidim::Organization object. - # * parent_id - The parent ID of the result. The value is forced to false to force - # the filter execution when the value is nil - # * deep_search - Whether to perform the search on all children levels or just the - # first one. True by default. - def initialize(options = {}) - options = options.dup - options[:deep_search] = true if options[:deep_search].nil? - options[:parent_id] = "root" if options[:parent_id].nil? - super(Result.all, options) - end - - # Handle parent_id filter - def search_parent_id - parent_id = options[:parent_id] - parent_id = nil if parent_id == "root" - - if options[:deep_search] - query.where(parent_id: [parent_id] + children_ids(parent_id)) - else - query.where(parent_id: parent_id) - end - end - - private - - def children_ids(parent_id) - Result.where(parent_id: parent_id).pluck(:id) - end - end - end -end diff --git a/decidim-accountability/app/services/decidim/accountability/results_calculator.rb b/decidim-accountability/app/services/decidim/accountability/results_calculator.rb index 67225a60ec23e..fd86ac4faf85d 100644 --- a/decidim-accountability/app/services/decidim/accountability/results_calculator.rb +++ b/decidim-accountability/app/services/decidim/accountability/results_calculator.rb @@ -22,12 +22,16 @@ def progress attr_reader :component, :scope_id, :category_id def results - @results ||= ResultSearch.new( - component: component, - scope_id: scope_id, - category_id: category_id, - deep_search: false - ).results + @results ||= begin + query = Result.where( + parent_id: nil, + component: component + ) + query = query.with_any_scope(scope_id) if scope_id + query = query.with_any_category(category_id) if category_id + + query + end end end end diff --git a/decidim-accountability/app/views/decidim/accountability/admin/timeline_entries/index.html.erb b/decidim-accountability/app/views/decidim/accountability/admin/timeline_entries/index.html.erb index 268e715b55486..c76972622c904 100644 --- a/decidim-accountability/app/views/decidim/accountability/admin/timeline_entries/index.html.erb +++ b/decidim-accountability/app/views/decidim/accountability/admin/timeline_entries/index.html.erb @@ -20,7 +20,7 @@ <% timeline_entries.each do |timeline_entry| %> - <%= timeline_entry.entry_date %>
+ <%= l timeline_entry.entry_date, format: :decidim_short %>
<%= translated_attribute(timeline_entry.title) %> <% if allowed_to? :update, :timeline_entry, timeline_entry: timeline_entry %> diff --git a/decidim-accountability/app/views/decidim/accountability/results/_home_categories.html.erb b/decidim-accountability/app/views/decidim/accountability/results/_home_categories.html.erb index e2b8837e119b4..b82b0f04e6f10 100644 --- a/decidim-accountability/app/views/decidim/accountability/results/_home_categories.html.erb +++ b/decidim-accountability/app/views/decidim/accountability/results/_home_categories.html.erb @@ -26,7 +26,7 @@

- <%= link_to translated_attribute(category.name),results_path(filter: { category_id: category, scope_id: current_scope }) %>

+ <%= link_to translated_attribute(category.name),results_path(filter: { with_category: category, with_scope: current_scope }) %>

<% if component_settings.display_progress_enabled? && progress_calculator(current_scope, category.id).present? %>
@@ -51,7 +51,7 @@
<% category.subcategories.each do |subcategory| %> <% if (subcategory_results_count = count_calculator(current_scope, subcategory.id)) > 0 %> - <%= link_to results_path(filter: { category_id: subcategory, scope_id: current_scope }), class: "medium-4 columns end card__link card__link--block" do %> + <%= link_to results_path(filter: { with_category: subcategory, with_scope: current_scope }), class: "medium-4 columns end card__link card__link--block" do %>
<%= translated_attribute(subcategory.name) %> diff --git a/decidim-accountability/app/views/decidim/accountability/results/_nav_breadcrumb.html.erb b/decidim-accountability/app/views/decidim/accountability/results/_nav_breadcrumb.html.erb index 0b873d3519bd5..3853fe4dff040 100644 --- a/decidim-accountability/app/views/decidim/accountability/results/_nav_breadcrumb.html.erb +++ b/decidim-accountability/app/views/decidim/accountability/results/_nav_breadcrumb.html.erb @@ -7,7 +7,7 @@ <% if category.present? && category.parent.present? %> >
- <%= link_to translated_attribute(category.parent.name), results_path(filter: { category_id: category.parent_id, scope_id: current_scope }) %> + <%= link_to translated_attribute(category.parent.name), results_path(filter: { with_category: category.parent_id, with_scope: current_scope }) %> <% if component_settings.display_progress_enabled? %> <%= display_percentage progress_calculator(current_scope, category.parent_id) %> <% end %> @@ -17,7 +17,7 @@ <% if category.present? %> >
- <%= link_to translated_attribute(category.name), results_path(filter: { category_id: category.id, scope_id: current_scope }) %> + <%= link_to translated_attribute(category.name), results_path(filter: { with_category: category.id, with_scope: current_scope }) %> <% if component_settings.display_progress_enabled? %> <%= display_percentage progress_calculator(current_scope, category.id) %> <% end %> @@ -27,7 +27,7 @@ <% if result && result.parent.present? %> >
- <%= link_to translated_attribute(result.parent.title), result_path(result.parent, filter: { scope_id: current_scope }) %> + <%= link_to translated_attribute(result.parent.title), result_path(result.parent, filter: { with_category: current_scope }) %> <% if component_settings.display_progress_enabled? %> <%= display_percentage result.parent.progress %> <% end %> diff --git a/decidim-accountability/app/views/decidim/accountability/results/_results_leaf.html.erb b/decidim-accountability/app/views/decidim/accountability/results/_results_leaf.html.erb index 5a3408b8b47c5..891cce27b5649 100644 --- a/decidim-accountability/app/views/decidim/accountability/results/_results_leaf.html.erb +++ b/decidim-accountability/app/views/decidim/accountability/results/_results_leaf.html.erb @@ -42,6 +42,6 @@
<% end %>
- <%= decidim_paginate results, order_start_time: params[:order_start_time], scope_id: params[:scope_id] %> + <%= decidim_paginate results, order_start_time: params[:order_start_time], with_scope: params.dig(:filter, :with_scope) %>
diff --git a/decidim-accountability/app/views/decidim/accountability/results/_results_parent.html.erb b/decidim-accountability/app/views/decidim/accountability/results/_results_parent.html.erb index 72d4e82b3196d..26cc24c8b3e44 100644 --- a/decidim-accountability/app/views/decidim/accountability/results/_results_parent.html.erb +++ b/decidim-accountability/app/views/decidim/accountability/results/_results_parent.html.erb @@ -27,6 +27,6 @@
<% end %>
- <%= decidim_paginate results, order_start_time: params[:order_start_time], scope_id: params[:scope_id] %> + <%= decidim_paginate results, order_start_time: params[:order_start_time], with_scope: params.dig(:filter, :with_scope) %>
diff --git a/decidim-accountability/app/views/decidim/accountability/results/_scope_filters.html.erb b/decidim-accountability/app/views/decidim/accountability/results/_scope_filters.html.erb index c2fe194eda2a0..39eceb8a615fa 100644 --- a/decidim-accountability/app/views/decidim/accountability/results/_scope_filters.html.erb +++ b/decidim-accountability/app/views/decidim/accountability/results/_scope_filters.html.erb @@ -4,7 +4,7 @@
  • > - <%= link_to url_for(filter: { category_id: category.try(:id) }) do %> + <%= link_to url_for(filter: { with_category: category.try(:id) }) do %> <%= Decidim::Scope.model_name.human(count: 2) %> <%= t("results.filters.all", scope: "decidim.accountability") %> <% end %> @@ -12,7 +12,7 @@ <% if current_participatory_space.scope %>
  • > - <%= link_to url_for(filter: { scope_id: current_participatory_space.scope.id, category_id: category.try(:id) }) do %> + <%= link_to url_for(filter: { with_scope: current_participatory_space.scope.id, with_category: category.try(:id) }) do %> <%= Decidim::Scope.model_name.human(count: 1) %> <%= translated_attribute(current_participatory_space.scope.name) %> <% end %> @@ -20,7 +20,7 @@ <% end %> <% current_participatory_space.subscopes.each do |scope| %>
  • > - <%= link_to url_for(filter: { scope_id: scope.id, category_id: category.try(:id) }) do %> + <%= link_to url_for(filter: { with_scope: scope.id, with_category: category.try(:id) }) do %> <%= Decidim::Scope.model_name.human(count: 1) %> <%= translated_attribute(scope.name) %> <% end %> diff --git a/decidim-accountability/app/views/decidim/accountability/results/_search.html.erb b/decidim-accountability/app/views/decidim/accountability/results/_search.html.erb index dc03a8a627476..3b06737b6fbf9 100644 --- a/decidim-accountability/app/views/decidim/accountability/results/_search.html.erb +++ b/decidim-accountability/app/views/decidim/accountability/results/_search.html.erb @@ -1,7 +1,7 @@ <%= form_tag results_path, method: :get do %>
  • Créer les Status pour les résultats que vous voulez ajouter
  • Créer au moins un résultat manuellement via ce panneau admin avant d'utiliser l'import, pour mieux comprendre le format et ce que vous devrez compléter.
  • %{link_export_csv}
  • -
  • Appliquer les changement localement. Vous ne pouvez changer que les colonnes suivantes du CSV: +
  • Faites les changements directement sur le fichier. Vous ne pouvez changer que les colonnes suivantes du CSV:
    • category/id: ID de la catégorie
    • -
    • scope/id: ID du périmètre d'application
    • -
    • parent/id: ID du parent (pour résultat liés). Optionel
    • +
    • scope/id: ID du secteur
    • +
    • parent/id: ID du résultat parent (résultat liés). Facultatif
    • title/en: Titre en anglais. Cela dépend de la configuration des langues sur votre plateforme.
    • description/en: Description en anglais. Cela dépend de la configuration des langues sur votre plateforme.
    • start_date: date à partir de laquelle le résultat est mis en Å“uvre (format AAAA-MM-JJ)
    • end_date: date à laquelle se termine la mise en Å“uvre du résultat (format AAAA-MM-JJ)
    • -
    • status/id: ID du status de ce résultat
    • -
    • progress: Pourcentage (de 0 à 100) de l'exécution
    • -
    • proposals_ids: IDs des propositions liées (séparés par une virgule). C'est automatiquement converti en proposal_url
    • +
    • status/id: ID du statut de ce résultat
    • +
    • progress: Pourcentage d'exécution (de 0 à 100)
    • +
    • proposals_ids: IDs des propositions liées (séparés par une virgule). Ces ID seront automatiquement converti en proposal_url
  • @@ -141,6 +143,14 @@ fr-CA: create: "%{user_name} a créé la réalisation %{resource_name} dans %{space_name}" delete: "%{user_name} a supprimé la réalisation %{resource_name} dans %{space_name}" update: "%{user_name} a mis à jour la réalisation %{resource_name} dans %{space_name}" + status: + create: "%{user_name} a créé le statut %{resource_name}" + delete: "%{user_name} a supprimé le statut %{resource_name}" + update: "%{user_name} a mis à jour le statut %{resource_name}" + timeline_entry: + create: "%{user_name} a créé l'étape d'évolution de la réalisation %{resource_name}" + delete: "%{user_name} a supprimé l'étape d'évolution de la réalisation %{resource_name}" + update: "%{user_name} a mis à jour l'étape d'évolution de la réalisation %{resource_name}" value_types: parent_presenter: not_found: 'Le parent n''a pas été trouvé dans la base de données (ID: %{id})' @@ -178,8 +188,8 @@ fr-CA: progress: Avancement timeline_entry: fields: - description: Description entry_date: Date + title: Titre result_m: executed: Exécuté view: Voir diff --git a/decidim-accountability/config/locales/fr.yml b/decidim-accountability/config/locales/fr.yml index 338b7546cd957..905894b977252 100644 --- a/decidim-accountability/config/locales/fr.yml +++ b/decidim-accountability/config/locales/fr.yml @@ -1,3 +1,4 @@ +--- fr: activemodel: attributes: @@ -21,6 +22,7 @@ fr: timeline_entry: description: Description entry_date: Date + title: Titre models: decidim/accountability/proposal_linked_event: Proposition incluse dans une réalisation decidim/accountability/result_progress_updated_event: Résultat du progrès mis à jour @@ -56,18 +58,18 @@ fr:
  • Créer les Status pour les résultats que vous voulez ajouter
  • Créer au moins un résultat manuellement via ce panneau admin avant d'utiliser l'import, pour mieux comprendre le format et ce que vous devrez compléter.
  • %{link_export_csv}
  • -
  • Appliquer les changement localement. Vous ne pouvez changer que les colonnes suivantes du CSV: +
  • Faites les changements directement sur le fichier. Vous ne pouvez changer que les colonnes suivantes du CSV:
    • category/id: ID de la catégorie
    • -
    • scope/id: ID du périmètre d'application
    • -
    • parent/id: ID du parent (pour résultat liés). Optionel
    • +
    • scope/id: ID du secteur
    • +
    • parent/id: ID du résultat parent (résultat liés). Facultatif
    • title/en: Titre en anglais. Cela dépend de la configuration des langues sur votre plateforme.
    • description/en: Description en anglais. Cela dépend de la configuration des langues sur votre plateforme.
    • start_date: date à partir de laquelle le résultat est mis en Å“uvre (format AAAA-MM-JJ)
    • end_date: date à laquelle se termine la mise en Å“uvre du résultat (format AAAA-MM-JJ)
    • -
    • status/id: ID du status de ce résultat
    • -
    • progress: Pourcentage (de 0 à 100) de l'exécution
    • -
    • proposals_ids: IDs des propositions liées (séparés par une virgule). C'est automatiquement converti en proposal_url
    • +
    • status/id: ID du statut de ce résultat
    • +
    • progress: Pourcentage d'exécution (de 0 à 100)
    • +
    • proposals_ids: IDs des propositions liées (séparés par une virgule). Ces ID seront automatiquement converti en proposal_url
  • @@ -141,6 +143,14 @@ fr: create: "%{user_name} a créé la réalisation %{resource_name} dans %{space_name}" delete: "%{user_name} a supprimé la réalisation %{resource_name} dans %{space_name}" update: "%{user_name} a mis à jour la réalisation %{resource_name} dans %{space_name}" + status: + create: "%{user_name} a créé le statut %{resource_name}" + delete: "%{user_name} a supprimé le statut %{resource_name}" + update: "%{user_name} a mis à jour le statut %{resource_name}" + timeline_entry: + create: "%{user_name} a créé l'étape d'évolution de la réalisation %{resource_name}" + delete: "%{user_name} a supprimé l'étape d'évolution de la réalisation %{resource_name}" + update: "%{user_name} a mis à jour l'étape d'évolution de la réalisation %{resource_name}" value_types: parent_presenter: not_found: 'Le parent n''a pas été trouvé dans la base de données (ID: %{id})' @@ -178,8 +188,8 @@ fr: progress: Avancement timeline_entry: fields: - description: Description entry_date: Date + title: Titre result_m: executed: Exécuté view: Voir diff --git a/decidim-accountability/config/locales/ga-IE.yml b/decidim-accountability/config/locales/ga-IE.yml index e8978232894ee..de2fe52fd551b 100644 --- a/decidim-accountability/config/locales/ga-IE.yml +++ b/decidim-accountability/config/locales/ga-IE.yml @@ -1,3 +1,4 @@ +--- ga: activemodel: attributes: diff --git a/decidim-accountability/config/locales/gl.yml b/decidim-accountability/config/locales/gl.yml index bc0bbddaeb0b4..11b32d3caecc9 100644 --- a/decidim-accountability/config/locales/gl.yml +++ b/decidim-accountability/config/locales/gl.yml @@ -1,3 +1,4 @@ +--- gl: activemodel: attributes: @@ -156,7 +157,6 @@ gl: progress: Progreso timeline_entry: fields: - description: Descrición entry_date: Data result_m: executed: Executado diff --git a/decidim-accountability/config/locales/hu.yml b/decidim-accountability/config/locales/hu.yml index a1519c9223b83..bd16ba0c428cf 100644 --- a/decidim-accountability/config/locales/hu.yml +++ b/decidim-accountability/config/locales/hu.yml @@ -1,3 +1,4 @@ +--- hu: activemodel: attributes: @@ -21,6 +22,7 @@ hu: timeline_entry: description: Leírás entry_date: Dátum + title: Cím models: decidim/accountability/proposal_linked_event: Az eredményhez kapcsolódó javaslat decidim/accountability/result_progress_updated_event: Az eredmények frissítve @@ -119,6 +121,14 @@ hu: create: "%{user_name} által létrehozott eredmény: %{resource_name} (itt: %{space_name})" delete: "%{user_name} törölte a(z) %{resource_name} eredményt innen: %{space_name}" update: "%{user_name} frissítette a(z) %{resource_name} eredmény itt: %{space_name}" + status: + create: "%{user_name} létrehozta a(z) %{resource_name} állapotot" + delete: "%{user_name} törölte a(z) %{resource_name} állapotot" + update: "%{user_name} frissítette a(z) %{resource_name} állapotot" + timeline_entry: + create: "%{user_name} létrehozta az %{resource_name} idÅ‘vonal bejegyzést" + delete: "%{user_name} törölte a(z) %{resource_name} idÅ‘vonal bejegyzést" + update: "%{user_name} frissítette a %{resource_name} idÅ‘vonal bejegyzést" value_types: parent_presenter: not_found: 'Nem található az adatbázisban (ID: %{id})' @@ -156,8 +166,8 @@ hu: progress: Folyamat timeline_entry: fields: - description: Leírás entry_date: Dátum + title: Cím result_m: executed: Végrehajtva view: Nézet diff --git a/decidim-accountability/config/locales/id-ID.yml b/decidim-accountability/config/locales/id-ID.yml index 6003c48adb398..aa6f0bbb71917 100644 --- a/decidim-accountability/config/locales/id-ID.yml +++ b/decidim-accountability/config/locales/id-ID.yml @@ -1,3 +1,4 @@ +--- id: activemodel: attributes: @@ -128,7 +129,6 @@ id: progress: Kemajuan timeline_entry: fields: - description: Deskripsi entry_date: Tanggal results: count: diff --git a/decidim-accountability/config/locales/is-IS.yml b/decidim-accountability/config/locales/is-IS.yml index 7d9e5c9c40560..41048dd15656d 100644 --- a/decidim-accountability/config/locales/is-IS.yml +++ b/decidim-accountability/config/locales/is-IS.yml @@ -1,4 +1,5 @@ -is-IS: +--- +is: activemodel: attributes: result: @@ -144,7 +145,6 @@ is-IS: progress: Framfarir timeline_entry: fields: - description: Lýsing entry_date: Dagsetning result_m: executed: Framkvæmt diff --git a/decidim-accountability/config/locales/it.yml b/decidim-accountability/config/locales/it.yml index ff6a5b520b19d..496f459249198 100644 --- a/decidim-accountability/config/locales/it.yml +++ b/decidim-accountability/config/locales/it.yml @@ -1,3 +1,4 @@ +--- it: activemodel: attributes: @@ -156,7 +157,6 @@ it: progress: Avanzamento timeline_entry: fields: - description: Descrizione entry_date: Data result_m: executed: Eseguito diff --git a/decidim-accountability/config/locales/ja.yml b/decidim-accountability/config/locales/ja.yml index 8de5ddeca41e0..d305f5a59e5de 100644 --- a/decidim-accountability/config/locales/ja.yml +++ b/decidim-accountability/config/locales/ja.yml @@ -1,3 +1,4 @@ +--- ja: activemodel: attributes: @@ -21,6 +22,7 @@ ja: timeline_entry: description: 説明 entry_date: 日付 + title: タイトル models: decidim/accountability/proposal_linked_event: çµæžœã«æ案をå«ã‚ã¾ã™ decidim/accountability/result_progress_updated_event: çµæžœã®é€²æ—状æ³ãŒæ›´æ–°ã•ã‚Œã¾ã—㟠@@ -47,7 +49,29 @@ ja: results: çµæžœ import_results: new: + download_export: CSVå½¢å¼ã§ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã‚’ダウンロード import: インãƒãƒ¼ãƒˆ + info: | +

    以下ã®æ‰‹é †ã‚’ãŠå‹§ã‚ã—ã¾ã™:

    +
      +
    1. 追加ã—ãŸã„çµæžœã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚’作æˆã™ã‚‹
    2. +
    3. インãƒãƒ¼ãƒˆã‚’使用ã™ã‚‹å‰ã«ã€ã“ã®ç®¡ç†ãƒ‘ãƒãƒ«ã‹ã‚‰å°‘ãªãã¨ã‚‚1ã¤ã®çµæžœã‚’手動ã§ä½œæˆã—ã€ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã¨å¿…è¦äº‹é …をよりよãç†è§£ã§ãるよã†ã«ã—ã¦ãã ã•ã„。
    4. +
    5. %{link_export_csv}
    6. +
    7. ローカルã§å¤‰æ›´ã—ã¾ã™ã€‚変更ã§ãã‚‹ã®ã¯ã€CSVã®ä»¥ä¸‹ã®åˆ—ã®ã¿ã§ã™: +
        +
      • category/id: カテゴリã®ID
      • +
      • scope/id: スコープã®ID
      • +
      • parent/id: 関連ã™ã‚‹çµæžœã®è¦ªID. (オプション)
      • +
      • title/en: 英語ã®ã‚¿ã‚¤ãƒˆãƒ« ã“ã‚Œã¯ãƒ—ラットフォームã®è¨€èªžè¨­å®šã«ä¾å­˜ã—ã¾ã™.
      • +
      • description/en: 英語ã®èª¬æ˜Ž. ã“ã‚Œã¯ãƒ—ラットフォームã®è¨€èªžè¨­å®šã«ä¾å­˜ã—ã¾ã™.
      • +
      • start_date: çµæžœã®å®Ÿè¡Œé–‹å§‹æ—¥ (YYYY-MM-DDå½¢å¼)
      • +
      • end_date: çµæžœã®å®Ÿè¡Œçµ‚了日 (YYYY-MM-DDå½¢å¼)
      • +
      • status/id: çµæžœã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ID
      • +
      • progress: 進行ã®ãƒ‘ーセンテージ(0 〜 100)
      • +
      • proposals_ids: 関連ã™ã‚‹æ案ã®å†…部ID(カンマ区切り). 自動的ã«proposal_urlã«å¤‰æ›ã•ã‚Œã¾ã™
      • +
      +
    8. +
    title: CSVã‹ã‚‰çµæžœã‚’インãƒãƒ¼ãƒˆ imports: create: @@ -118,6 +142,14 @@ ja: create: "%{user_name} ãŒçµæžœ %{resource_name} ã‚’ %{space_name} ã«ä½œæˆã—ã¾ã—ãŸ" delete: "%{user_name} ㌠%{resource_name} ã®çµæžœ %{space_name} を削除ã—ã¾ã—ãŸ" update: "%{user_name} ã®çµæžœ %{resource_name} ã‚’ %{space_name} ã«æ›´æ–°ã—ã¾ã—ãŸ" + status: + create: "%{user_name} ㌠%{resource_name} ステータスを作æˆã—ã¾ã—ãŸ" + delete: "%{user_name} ㌠%{resource_name} ステータスを削除ã—ã¾ã—ãŸ" + update: "%{user_name} ㌠%{resource_name} ステータスを更新ã—ã¾ã—ãŸ" + timeline_entry: + create: "%{user_name} ㌠%{resource_name} タイムラインエントリを作æˆã—ã¾ã—ãŸ" + delete: "%{user_name} ㌠%{resource_name} タイムラインエントリを削除ã—ã¾ã—ãŸ" + update: "%{user_name} ㌠%{resource_name} タイムラインエントリを更新ã—ã¾ã—ãŸ" value_types: parent_presenter: not_found: '親ãŒãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ä¸Šã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—㟠(ID: %{id})' @@ -155,8 +187,8 @@ ja: progress: 進æ—çŠ¶æ³ timeline_entry: fields: - description: 説明 entry_date: 日付 + title: タイトル result_m: executed: 実行日時 view: 表示 diff --git a/decidim-accountability/config/locales/ka-GE.yml b/decidim-accountability/config/locales/ka-GE.yml new file mode 100644 index 0000000000000..57a95cb04703c --- /dev/null +++ b/decidim-accountability/config/locales/ka-GE.yml @@ -0,0 +1 @@ +ka: diff --git a/decidim-accountability/config/locales/lb.yml b/decidim-accountability/config/locales/lb.yml index 37a2d7b06c705..37bddea6bf7c8 100644 --- a/decidim-accountability/config/locales/lb.yml +++ b/decidim-accountability/config/locales/lb.yml @@ -1,3 +1,4 @@ +--- lb: activemodel: attributes: @@ -156,7 +157,6 @@ lb: progress: Fortschritt timeline_entry: fields: - description: Beschreiwung entry_date: Datum result_m: executed: Ausgeführt diff --git a/decidim-accountability/config/locales/lt.yml b/decidim-accountability/config/locales/lt.yml index 9ef24d7061a69..8b1f0dece2f9a 100644 --- a/decidim-accountability/config/locales/lt.yml +++ b/decidim-accountability/config/locales/lt.yml @@ -1,3 +1,4 @@ +--- lt: activemodel: attributes: @@ -21,6 +22,7 @@ lt: timeline_entry: description: ApraÅ¡ymas entry_date: Data + title: Pavadinimas models: decidim/accountability/proposal_linked_event: PasiÅ«lymas įtrauktas į rezultatÄ… decidim/accountability/result_progress_updated_event: Rezultato progresas atnaujintas @@ -121,6 +123,14 @@ lt: create: "%{user_name} sukÅ«rÄ— rezultatÄ… %{resource_name} erdvÄ—je %{space_name}" delete: "%{user_name} paÅ¡alino %{resource_name} rezultatÄ… erdvÄ—je %{space_name}" update: "%{user_name} atnaujino rezultatÄ… %{resource_name} erdvÄ—je %{space_name}" + status: + create: "%{user_name} sukÅ«rÄ— %{resource_name} bÅ«senÄ…" + delete: "%{user_name} paÅ¡alino %{resource_name} bÅ«senÄ…" + update: "%{user_name} atnaujino %{resource_name} bÅ«senÄ…" + timeline_entry: + create: "%{user_name} sukÅ«rÄ— %{resource_name} laiko juostos įraÅ¡Ä…" + delete: "%{user_name} paÅ¡alino %{resource_name} laiko juostos įraÅ¡Ä…" + update: "%{user_name} atnaujino %{resource_name} laiko juostos įraÅ¡Ä…" value_types: parent_presenter: not_found: 'Motininis elementas duomenų bazÄ—je nerastas (ID: %{id})' @@ -158,8 +168,8 @@ lt: progress: Progresas timeline_entry: fields: - description: ApraÅ¡ymas entry_date: Data + title: Pavadinimas result_m: executed: Ä®vykdyta view: Rodymas diff --git a/decidim-accountability/config/locales/lv.yml b/decidim-accountability/config/locales/lv.yml index aac3223a752d1..cf45ffb071b4f 100644 --- a/decidim-accountability/config/locales/lv.yml +++ b/decidim-accountability/config/locales/lv.yml @@ -1,3 +1,4 @@ +--- lv: activemodel: attributes: @@ -141,7 +142,6 @@ lv: name: Nosaukums timeline_entry: fields: - description: Apraksts entry_date: Datums results: count: diff --git a/decidim-accountability/config/locales/nl.yml b/decidim-accountability/config/locales/nl.yml index 322f457b33179..91f0ebdf8062f 100644 --- a/decidim-accountability/config/locales/nl.yml +++ b/decidim-accountability/config/locales/nl.yml @@ -1,3 +1,4 @@ +--- nl: activemodel: attributes: @@ -21,6 +22,7 @@ nl: timeline_entry: description: Beschrijving entry_date: Datum + title: Titel models: decidim/accountability/proposal_linked_event: Voorstel opgenomen in een resultaat decidim/accountability/result_progress_updated_event: Resultaat voortgang bijgewerkt @@ -119,6 +121,14 @@ nl: create: "%{user_name} heeft het resultaat %{resource_name} gemaakt in %{space_name}" delete: "%{user_name} verwijderde het resultaat %{resource_name} in %{space_name}" update: "%{user_name} bijgewerkt resultaat %{resource_name} in %{space_name}" + status: + create: "%{user_name} heeft %{resource_name} status aangemaakt" + delete: "%{user_name} heeft %{resource_name} status verwijderd" + update: "%{user_name} heeft %{resource_name} status bijgewerkt" + timeline_entry: + create: "%{user_name} heeft timeline entry %{resource_name} aangemaakt" + delete: "%{user_name} heeft timeline entry %{resource_name} verwijderd" + update: "%{user_name} heeft timeline entry %{resource_name} bijgewerkt" value_types: parent_presenter: not_found: 'Het bovenliggende element is niet gevonden in de database (ID: %{id})' @@ -156,8 +166,8 @@ nl: progress: Vooruitgang timeline_entry: fields: - description: Beschrijving entry_date: Datum + title: Titel result_m: executed: Uitgevoerd view: Bekijk diff --git a/decidim-accountability/config/locales/no.yml b/decidim-accountability/config/locales/no.yml index b187deceecde9..4aa6979e8a271 100644 --- a/decidim-accountability/config/locales/no.yml +++ b/decidim-accountability/config/locales/no.yml @@ -1,3 +1,4 @@ +--- "no": activemodel: attributes: @@ -21,6 +22,7 @@ timeline_entry: description: Beskrivelse entry_date: Dato + title: Tittel models: decidim/accountability/proposal_linked_event: Forslag inkludert i et resultat decidim/accountability/result_progress_updated_event: Resultat fremgang oppdatert @@ -119,6 +121,14 @@ create: "%{user_name} opprettet resultat %{resource_name} i %{space_name}" delete: "%{user_name} slettet %{resource_name} resultatet i %{space_name}" update: "%{user_name} oppdaterte rusultat%{resource_name} i %{space_name}" + status: + create: "%{user_name} har opprettet statusen %{resource_name}" + delete: "%{user_name} slettet statusen %{resource_name}" + update: "%{user_name} oppdaterte statusen %{resource_name}" + timeline_entry: + create: "%{user_name} opprettet %{resource_name} i tidslinjen" + delete: "%{user_name} slettet %{resource_name} i tidslinjen" + update: "%{user_name} oppdaterte %{resource_name} i tidslinjen" value_types: parent_presenter: not_found: 'Overordnede ble ikke funnet i databasen (ID: %{id})' @@ -156,8 +166,8 @@ progress: Framgang timeline_entry: fields: - description: Beskrivelse entry_date: Dato + title: Tittel result_m: executed: Utført view: Vis diff --git a/decidim-accountability/config/locales/pl.yml b/decidim-accountability/config/locales/pl.yml index 4428cafb69fb9..8fb48080c12cf 100644 --- a/decidim-accountability/config/locales/pl.yml +++ b/decidim-accountability/config/locales/pl.yml @@ -1,3 +1,4 @@ +--- pl: activemodel: attributes: @@ -21,6 +22,7 @@ pl: timeline_entry: description: Opis entry_date: Data + title: TytuÅ‚ models: decidim/accountability/proposal_linked_event: Propozycja zawarta w wyniku decidim/accountability/result_progress_updated_event: Aktualizacja postÄ™pu wyników @@ -122,6 +124,14 @@ pl: create: "%{user_name} utworzyÅ‚(a) wynik %{resource_name} w %{space_name}" delete: "%{user_name} usunÄ…Å‚/usunęła wynik %{resource_name} z %{space_name}" update: "%{user_name} zaktualizowaÅ‚(a) wynik %{resource_name} w %{space_name}" + status: + create: "%{user_name} utworzyÅ‚ status %{resource_name}" + delete: "%{user_name} usunÄ…Å‚ %{resource_name} status" + update: "%{user_name} zaktualizowaÅ‚ %{resource_name} status" + timeline_entry: + create: "%{user_name} utworzyÅ‚ wpis linii czasu %{resource_name}" + delete: "%{user_name} usunÄ…Å‚ wpis linii czasu %{resource_name}" + update: "%{user_name} zaktualizowaÅ‚ wpis linii czasu %{resource_name}" value_types: parent_presenter: not_found: 'Nie znaleziono elementu nadrzÄ™dnego w bazie danych (ID: %{id})' @@ -159,8 +169,8 @@ pl: progress: PostÄ™p timeline_entry: fields: - description: Opis entry_date: Data + title: TytuÅ‚ result_m: executed: Wykonane view: Zobacz diff --git a/decidim-accountability/config/locales/pt-BR.yml b/decidim-accountability/config/locales/pt-BR.yml index 8dbbad22378ba..4d3d283a7e404 100644 --- a/decidim-accountability/config/locales/pt-BR.yml +++ b/decidim-accountability/config/locales/pt-BR.yml @@ -1,3 +1,4 @@ +--- pt-BR: activemodel: attributes: @@ -21,6 +22,7 @@ pt-BR: timeline_entry: description: Descrição entry_date: Encontro + title: Título models: decidim/accountability/proposal_linked_event: Proposta incluída em um resultado decidim/accountability/result_progress_updated_event: Progresso do resultado atualizado @@ -157,8 +159,8 @@ pt-BR: progress: Progresso timeline_entry: fields: - description: Descrição entry_date: Data + title: Título result_m: executed: Executado view: Visualizar diff --git a/decidim-accountability/config/locales/pt.yml b/decidim-accountability/config/locales/pt.yml index de881e94778ea..4b8e0c1571eaa 100644 --- a/decidim-accountability/config/locales/pt.yml +++ b/decidim-accountability/config/locales/pt.yml @@ -1,3 +1,4 @@ +--- pt: activemodel: attributes: @@ -156,7 +157,6 @@ pt: progress: Progresso timeline_entry: fields: - description: Descrição entry_date: Data result_m: executed: Executado diff --git a/decidim-accountability/config/locales/ro-RO.yml b/decidim-accountability/config/locales/ro-RO.yml index 9c354f76552c6..feae0ce67ccb9 100644 --- a/decidim-accountability/config/locales/ro-RO.yml +++ b/decidim-accountability/config/locales/ro-RO.yml @@ -1,3 +1,4 @@ +--- ro: activemodel: attributes: @@ -12,7 +13,7 @@ ro: proposals: Propuneri incluse start_date: Data de început title: Titlu - updated_at: Actualizat la + updated_at: Ultima actualizare status: description: Descriere key: Cheie @@ -21,6 +22,7 @@ ro: timeline_entry: description: Descriere entry_date: Data + title: Titlu models: decidim/accountability/proposal_linked_event: Propunere inclusă în rezultat decidim/accountability/result_progress_updated_event: Progresul rezultatului actualizat @@ -35,7 +37,7 @@ ro: actions: attachment_collections: Dosare attachments: AtaÈ™amente - confirm_destroy: Sigur doreÈ™ti să È™tergi acest %{name}? + confirm_destroy: SunteÈ›i sigur că doriÈ›i să È™tergeÈ›i %{name}? destroy: Ștergere edit: Editare import_csv: Importă CSV @@ -49,11 +51,12 @@ ro: results: Rezultate import_results: new: + download_export: DescarcaÈ›i Export cu format CSV import: Importă title: ImportaÈ›i rezultate de la CSV imports: create: - success: FiÅŸierul a început importul. VeÅ£i primi un e-mail în următoarele câteva minute cu rezultatul importului + success: FiÈ™ierul a început importul. VeÈ›i primi un e-mail în următoarele câteva minute cu rezultatul importului models: result: name: Rezultat @@ -120,6 +123,12 @@ ro: create: "%{user_name} a creat %{resource_name} în %{space_name}" delete: "%{user_name} a È™ters %{resource_name} în %{space_name}" update: "%{user_name} a actualizat %{resource_name} în %{space_name}" + status: + update: "%{user_name} a actualizat starea %{resource_name}" + timeline_entry: + create: "%{user_name} a creat intrarea de cronologie pentru %{resource_name}" + delete: "%{user_name} a È™ters intrarea de cronologie pentru %{resource_name}" + update: "%{user_name} a actualizat intrarea de cronologie pentru %{resource_name}" value_types: parent_presenter: not_found: 'Elementul-părinte nu a fost găsit în baza de date (ID: %{id})' @@ -157,8 +166,8 @@ ro: progress: Progres timeline_entry: fields: - description: Descriere entry_date: Dată + title: Titlu result_m: executed: Executat view: Vizualizare @@ -224,12 +233,12 @@ ro: events: accountability: proposal_linked: - email_intro: 'Propunerea "%{proposal_title}" a fost inclusă într-un rezultat. O puteÅ£i vedea de pe această pagină:' + email_intro: 'Propunerea "%{proposal_title}" a fost inclusă într-un rezultat. O puteÈ›i vedea de pe această pagină:' email_outro: Ai primit această notificare deoarece urmăreÈ™ti „%{proposal_title}â€. PoÈ›i anula aceste notificări de la link-ul anterior. email_subject: O actualizare la %{proposal_title} notification_title: Propunerea %{proposal_title} a fost inclusă în rezultatul %{resource_title}. result_progress_updated: - email_intro: 'Rezultatul "%{resource_title}", care include propunerea "%{proposal_title}", este acum %{progress}% complet. ÃŽl puteÅ£i vedea de pe această pagină:' + email_intro: 'Rezultatul "%{resource_title}", care include propunerea "%{proposal_title}", este acum %{progress}% complet. ÃŽl puteÈ›i vedea de pe această pagină:' email_outro: Ai primit această notificare deoarece urmăreÈ™ti „%{proposal_title}†și această propunere este inclusă în rezultatul „%{resource_title}â€. PoÈ›i înceta să primeÈ™ti notificări urmând link-ul anterior. email_subject: O actualizare la progresul %{resource_title} notification_title: Rezultatul %{resource_title}, care include propunerea %{proposal_title}, este acum %{progress}% complet. diff --git a/decidim-accountability/config/locales/ru.yml b/decidim-accountability/config/locales/ru.yml index e326a2e6a0602..c75064b790696 100644 --- a/decidim-accountability/config/locales/ru.yml +++ b/decidim-accountability/config/locales/ru.yml @@ -1,3 +1,4 @@ +--- ru: activemodel: attributes: @@ -131,7 +132,6 @@ ru: progress: Продвижение timeline_entry: fields: - description: ОпиÑание entry_date: Дата results: count: diff --git a/decidim-accountability/config/locales/si-LK.yml b/decidim-accountability/config/locales/si-LK.yml index 1b7b24d2d73c1..620b1f12cb083 100644 --- a/decidim-accountability/config/locales/si-LK.yml +++ b/decidim-accountability/config/locales/si-LK.yml @@ -1,3 +1,4 @@ +--- si: activemodel: attributes: @@ -56,7 +57,6 @@ si: models: timeline_entry: fields: - description: සවිස්තරය entry_date: දිනය results: show: diff --git a/decidim-accountability/config/locales/sk.yml b/decidim-accountability/config/locales/sk.yml index 0765bcbe9b15e..49cd6ca2e75a0 100644 --- a/decidim-accountability/config/locales/sk.yml +++ b/decidim-accountability/config/locales/sk.yml @@ -1,3 +1,4 @@ +--- sk: activemodel: attributes: @@ -151,7 +152,6 @@ sk: progress: Postup timeline_entry: fields: - description: Popis entry_date: Dátum result_m: view: ZobraziÅ¥ diff --git a/decidim-accountability/config/locales/sl.yml b/decidim-accountability/config/locales/sl.yml index c6309d71815f1..1eeb6707cde2a 100644 --- a/decidim-accountability/config/locales/sl.yml +++ b/decidim-accountability/config/locales/sl.yml @@ -1,3 +1,4 @@ +--- sl: activemodel: attributes: @@ -96,7 +97,6 @@ sl: progress: Napredek timeline_entry: fields: - description: Opis entry_date: Datum results: filters: diff --git a/decidim-accountability/config/locales/sr-CS.yml b/decidim-accountability/config/locales/sr-CS.yml index 89a064154ad13..1243ad749ed5a 100644 --- a/decidim-accountability/config/locales/sr-CS.yml +++ b/decidim-accountability/config/locales/sr-CS.yml @@ -1,3 +1,4 @@ +--- sr: activemodel: attributes: @@ -130,7 +131,6 @@ sr: progress: Napredak timeline_entry: fields: - description: Opis entry_date: Datum results: count: diff --git a/decidim-accountability/config/locales/sv.yml b/decidim-accountability/config/locales/sv.yml index 1dd8592457bab..eec01767793b7 100644 --- a/decidim-accountability/config/locales/sv.yml +++ b/decidim-accountability/config/locales/sv.yml @@ -1,3 +1,4 @@ +--- sv: activemodel: attributes: @@ -21,6 +22,7 @@ sv: timeline_entry: description: Beskrivning entry_date: Datum + title: Titel models: decidim/accountability/proposal_linked_event: Förslag som ingÃ¥r i ett resultat decidim/accountability/result_progress_updated_event: Uppdaterat resultatutvecklingen @@ -48,7 +50,29 @@ sv: results: Resultat import_results: new: + download_export: Ladda ner exporten som CSV import: Importera + info: | +

    Vi rekommenderar att du följer dessa steg:

    +
      +
    1. Skapa statusarna för de resultat som du vill lägga till
    2. +
    3. Skapa minst ett resultat manuellt via denna administratörspanel innan du använder Import, för att få en bättre förståelse för formatet och vad du behöver fylla i.
    4. +
    5. %{link_export_csv}
    6. +
    7. Genomför ändringarna lokalt. Du kan endast ändra följande kolumner i CSV-filen: +
        +
      • category/id: ID för kategorin
      • +
      • scope/id: ID för tillämpningsomrÃ¥det
      • +
      • parent/id: ID för överordnad (för relaterade resultat). Alternativ
      • +
      • title/I18N: Titel pÃ¥ X sprÃ¥k
      • +
      • description/I18N: Beskrivning av X sprÃ¥k
      • +
      • start_date: datum dÃ¥ resultatet börjar genomföras (format Ã…Ã…Ã…Ã…-MM-DD)
      • +
      • end_date: datum dÃ¥ resultatet slutar genomföras (format Ã…Ã…Ã…Ã…-MM-DD)
      • +
      • status/id: ID för statusen för detta resultat
      • +
      • progress: Procent (frÃ¥n 0 till 100) av genomförandet
      • +
      • proposals_ids:internt ID för relaterade förslag (kommaseparerade). Omvandlas automatiskt till proposal_url
      • +
      +
    8. +
    title: Importera resultat från CSV imports: create: @@ -119,6 +143,14 @@ sv: create: "%{user_name} skapade resultatet %{resource_name} i %{space_name}" delete: "%{user_name} raderade resultatet %{resource_name} i %{space_name}" update: "%{user_name} uppdaterade resultatet %{resource_name} i %{space_name}" + status: + create: "%{user_name} skapade statusen %{resource_name}" + delete: "%{user_name} raderade statusen %{resource_name}" + update: "%{user_name} uppdaterade statusen %{resource_name}" + timeline_entry: + create: "%{user_name} skapade steget %{resource_name} för tidslinjen" + delete: "%{user_name} raderade steget %{resource_name} i tidslinjen" + update: "%{user_name} uppdaterade steget %{resource_name} i tidslinjen" value_types: parent_presenter: not_found: 'Föräldraposten hittades inte i databasen (ID: %{id})' @@ -156,8 +188,8 @@ sv: progress: Behandling timeline_entry: fields: - description: Beskrivning entry_date: Datum + title: Titel result_m: executed: Utfört view: Visa diff --git a/decidim-accountability/config/locales/tr-TR.yml b/decidim-accountability/config/locales/tr-TR.yml index 98753197f080b..f623dbfc93814 100644 --- a/decidim-accountability/config/locales/tr-TR.yml +++ b/decidim-accountability/config/locales/tr-TR.yml @@ -1,3 +1,4 @@ +--- tr: activemodel: attributes: @@ -21,6 +22,7 @@ tr: timeline_entry: description: Açıklama entry_date: tarih + title: Başlik / Unvani models: decidim/accountability/proposal_linked_event: Teklif bir sonuca dahil edildi decidim/accountability/result_progress_updated_event: Sonuç ilerlemesi güncellendi @@ -32,6 +34,8 @@ tr: decidim: accountability: actions: + attachment_collections: Klasörler + attachments: Ekler confirm_destroy: Bu %{name}silmek istediğinize emin misiniz? destroy: silmek edit: Düzenle @@ -46,7 +50,29 @@ tr: results: Sonuçlar import_results: new: + download_export: ' İhracat i CSV formatında indirin ' import: İçe aktar + info: | +

    bu adımları uygulamanızı öneririz

    +

      +
    1. +
    2. fikir_önerisi:ilgılı tekliflerin dahili kimliği(virgüle ayrılmış ). Otomatik olarak biçimine dönüşüyorproposal_url +
    3. +
+ + title: Sonuçları CSV'den içe aktar imports: create: @@ -154,7 +180,6 @@ tr: progress: Ä°lerleme timeline_entry: fields: - description: Açıklama entry_date: tarih result_m: executed: Yürütüldü diff --git a/decidim-accountability/config/locales/uk.yml b/decidim-accountability/config/locales/uk.yml index 7820ee5f9a368..dd62dc26c6b0b 100644 --- a/decidim-accountability/config/locales/uk.yml +++ b/decidim-accountability/config/locales/uk.yml @@ -1,3 +1,4 @@ +--- uk: activemodel: attributes: @@ -128,7 +129,6 @@ uk: progress: Перебіг timeline_entry: fields: - description: ÐžÐ¿Ð¸Ñ entry_date: Дата results: count: diff --git a/decidim-accountability/config/locales/zh-CN.yml b/decidim-accountability/config/locales/zh-CN.yml index 8c7472b1b0196..f7e36b78d2292 100644 --- a/decidim-accountability/config/locales/zh-CN.yml +++ b/decidim-accountability/config/locales/zh-CN.yml @@ -1,3 +1,4 @@ +--- zh-CN: activemodel: attributes: @@ -143,7 +144,6 @@ zh-CN: progress: 进展情况 timeline_entry: fields: - description: æè¿° entry_date: 日期 results: count: diff --git a/decidim-accountability/db/migrate/20220331150008_add_title_to_timeline_entries.rb b/decidim-accountability/db/migrate/20220331150008_add_title_to_timeline_entries.rb index 082e29b91f56d..c0fd23a4dc4e3 100644 --- a/decidim-accountability/db/migrate/20220331150008_add_title_to_timeline_entries.rb +++ b/decidim-accountability/db/migrate/20220331150008_add_title_to_timeline_entries.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class AddTitleToTimelineEntries < ActiveRecord::Migration[6.0] +class AddTitleToTimelineEntries < ActiveRecord::Migration[6.1] def change add_column :decidim_accountability_timeline_entries, :title, :jsonb end diff --git a/decidim-accountability/db/migrate/20220331150155_move_legacy_description_to_title_of_timeline_entries.rb b/decidim-accountability/db/migrate/20220331150155_move_legacy_description_to_title_of_timeline_entries.rb index 1eacf57a97b55..253617a3e7b5b 100644 --- a/decidim-accountability/db/migrate/20220331150155_move_legacy_description_to_title_of_timeline_entries.rb +++ b/decidim-accountability/db/migrate/20220331150155_move_legacy_description_to_title_of_timeline_entries.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class MoveLegacyDescriptionToTitleOfTimelineEntries < ActiveRecord::Migration[6.0] +class MoveLegacyDescriptionToTitleOfTimelineEntries < ActiveRecord::Migration[6.1] class TimelineEntry < ApplicationRecord self.table_name = :decidim_accountability_timeline_entries end diff --git a/decidim-accountability/decidim-accountability.gemspec b/decidim-accountability/decidim-accountability.gemspec index d09dd9272e8a7..24180b091044b 100644 --- a/decidim-accountability/decidim-accountability.gemspec +++ b/decidim-accountability/decidim-accountability.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |s| s.email = ["josepjaume@gmail.com", "mrc2407@gmail.com", "oriolgual@gmail.com"] s.license = "AGPL-3.0" s.homepage = "https://github.com/decidim/decidim" - s.required_ruby_version = ">= 2.7" + s.required_ruby_version = ">= 3.0" s.name = "decidim-accountability" s.summary = "Decidim accountability module" diff --git a/decidim-accountability/lib/decidim/accountability/version.rb b/decidim-accountability/lib/decidim/accountability/version.rb index d9902d7879b53..d29995caad330 100644 --- a/decidim-accountability/lib/decidim/accountability/version.rb +++ b/decidim-accountability/lib/decidim/accountability/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds decidim-accountability version. module Accountability def self.version - "0.26.4" + "0.27.2" end end end diff --git a/decidim-accountability/spec/cells/decidim/accountability/result_m_cell_spec.rb b/decidim-accountability/spec/cells/decidim/accountability/result_m_cell_spec.rb index cf02eb1a7465f..5225ff4f49a15 100644 --- a/decidim-accountability/spec/cells/decidim/accountability/result_m_cell_spec.rb +++ b/decidim-accountability/spec/cells/decidim/accountability/result_m_cell_spec.rb @@ -24,7 +24,7 @@ module Decidim::Accountability expect(subject).to have_css(".card--result") end - it "renders the start and end time " do + it "renders the start and end time" do result_start = I18n.l(start_date.to_date, format: :decidim_short) result_end = I18n.l(end_date.to_date, format: :decidim_short) diff --git a/decidim-accountability/spec/commands/admin/create_status_spec.rb b/decidim-accountability/spec/commands/admin/create_status_spec.rb index 81658d525c91a..e8f2fcb86f1d4 100644 --- a/decidim-accountability/spec/commands/admin/create_status_spec.rb +++ b/decidim-accountability/spec/commands/admin/create_status_spec.rb @@ -4,9 +4,10 @@ module Decidim::Accountability describe Admin::CreateStatus do - subject { described_class.new(form) } + subject { described_class.new(form, user) } let(:organization) { create :organization, available_locales: [:en] } + let(:user) { create(:user, organization: organization) } let(:participatory_process) { create :participatory_process, organization: organization } let(:current_component) { create :component, manifest_name: "accountability", participatory_space: participatory_process } @@ -61,6 +62,18 @@ module Decidim::Accountability subject.call expect(status.progress).to eq progress end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:create, Decidim::Accountability::Status, user, {}) + .and_call_original + + expect { subject.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("create") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-accountability/spec/commands/admin/create_timeline_entry_spec.rb b/decidim-accountability/spec/commands/admin/create_timeline_entry_spec.rb index 6431a0c2fb8a3..bd8f82a7e5417 100644 --- a/decidim-accountability/spec/commands/admin/create_timeline_entry_spec.rb +++ b/decidim-accountability/spec/commands/admin/create_timeline_entry_spec.rb @@ -4,9 +4,10 @@ module Decidim::Accountability describe Admin::CreateTimelineEntry do - subject { described_class.new(form) } + subject { described_class.new(form, user) } let(:organization) { create :organization, available_locales: [:en] } + let(:user) { create :user, organization: organization } let(:participatory_process) { create :participatory_process, organization: organization } let(:current_component) { create :accountability_component, participatory_space: participatory_process } let(:result) { create :result, component: current_component } @@ -60,6 +61,18 @@ module Decidim::Accountability subject.call expect(timeline_entry.result).to eq(result) end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:create, Decidim::Accountability::TimelineEntry, user, {}) + .and_call_original + + expect { subject.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("create") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-accountability/spec/commands/admin/update_status_spec.rb b/decidim-accountability/spec/commands/admin/update_status_spec.rb index e5b21743698b2..a0216777c0638 100644 --- a/decidim-accountability/spec/commands/admin/update_status_spec.rb +++ b/decidim-accountability/spec/commands/admin/update_status_spec.rb @@ -4,9 +4,10 @@ module Decidim::Accountability describe Admin::UpdateStatus do - subject { described_class.new(form, status) } + subject { described_class.new(form, status, user) } let(:organization) { create :organization, available_locales: [:en] } + let(:user) { create :user, organization: organization } let(:participatory_process) { create :participatory_process, organization: organization } let(:current_component) { create :accountability_component, participatory_space: participatory_process } @@ -56,6 +57,18 @@ module Decidim::Accountability subject.call expect(status.progress).to eq progress end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:update, status, user, {}) + .and_call_original + + expect { subject.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("update") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-accountability/spec/commands/admin/update_timeline_entry_spec.rb b/decidim-accountability/spec/commands/admin/update_timeline_entry_spec.rb index 47d4f57596c78..cbe8e2f62108e 100644 --- a/decidim-accountability/spec/commands/admin/update_timeline_entry_spec.rb +++ b/decidim-accountability/spec/commands/admin/update_timeline_entry_spec.rb @@ -4,9 +4,10 @@ module Decidim::Accountability describe Admin::UpdateTimelineEntry do - subject { described_class.new(form, timeline_entry) } + subject { described_class.new(form, timeline_entry, user) } let(:organization) { create :organization, available_locales: [:en] } + let(:user) { create :user, organization: organization } let(:participatory_process) { create :participatory_process, organization: organization } let(:current_component) { create :accountability_component, participatory_space: participatory_process } let(:result) { create :result, component: current_component } @@ -45,6 +46,18 @@ module Decidim::Accountability subject.call expect(translated(timeline_entry.description)).to eq description end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:update, Decidim::Accountability::TimelineEntry, user, {}) + .and_call_original + + expect { subject.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("update") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-accountability/spec/mailers/import_mailer_spec.rb b/decidim-accountability/spec/mailers/import_mailer_spec.rb index 5e044b95cd47b..861a50f05f43c 100644 --- a/decidim-accountability/spec/mailers/import_mailer_spec.rb +++ b/decidim-accountability/spec/mailers/import_mailer_spec.rb @@ -13,9 +13,9 @@ module Accountability let(:participatory_process) { create :participatory_process, organization: organization } let(:current_component) { create :accountability_component, participatory_space: participatory_process, id: 16 } let!(:category) { create :category, id: 16, participatory_space: current_component.participatory_space } - let!(:status_6) { create :status, id: 6, component: current_component } - let!(:status_7) { create :status, id: 7, component: current_component } - let!(:status_8) { create :status, id: 8, component: current_component } + let!(:status6) { create :status, id: 6, component: current_component } + let!(:status7) { create :status, id: 7, component: current_component } + let!(:status8) { create :status, id: 8, component: current_component } let(:valid_csv) { File.read("spec/fixtures/valid_result.csv") } let(:invalid_csv) { File.read("spec/fixtures/invalid_result.csv") } diff --git a/decidim-accountability/spec/permissions/decidim/accountability/admin/permissions_spec.rb b/decidim-accountability/spec/permissions/decidim/accountability/admin/permissions_spec.rb index 0c1ee17c03212..818ac227d1341 100644 --- a/decidim-accountability/spec/permissions/decidim/accountability/admin/permissions_spec.rb +++ b/decidim-accountability/spec/permissions/decidim/accountability/admin/permissions_spec.rb @@ -13,7 +13,7 @@ end let(:extra_context) { {} } let(:accountability_component) { create :accountability_component } - let(:permission_action) { Decidim::PermissionAction.new(action) } + let(:permission_action) { Decidim::PermissionAction.new(**action) } shared_examples "crud permissions" do describe "create" do @@ -21,7 +21,7 @@ { scope: :admin, action: :create, subject: action_subject } end - it { is_expected.to eq true } + it { is_expected.to be true } end describe "update" do @@ -30,7 +30,7 @@ end context "when the resource is present" do - it { is_expected.to eq true } + it { is_expected.to be true } end context "when the resource is not present" do @@ -46,7 +46,7 @@ end context "when the resource is present" do - it { is_expected.to eq true } + it { is_expected.to be true } end context "when the resource is not present" do diff --git a/decidim-accountability/spec/permissions/decidim/accountability/permissions_spec.rb b/decidim-accountability/spec/permissions/decidim/accountability/permissions_spec.rb index 635286cf5cedc..f72e80058bce0 100644 --- a/decidim-accountability/spec/permissions/decidim/accountability/permissions_spec.rb +++ b/decidim-accountability/spec/permissions/decidim/accountability/permissions_spec.rb @@ -12,7 +12,7 @@ } end let(:accountability_component) { create :accountability_component } - let(:permission_action) { Decidim::PermissionAction.new(action) } + let(:permission_action) { Decidim::PermissionAction.new(**action) } context "when scope is admin" do let(:action) do diff --git a/decidim-accountability/spec/requests/result_search_spec.rb b/decidim-accountability/spec/requests/result_search_spec.rb new file mode 100644 index 0000000000000..053024d84b9c3 --- /dev/null +++ b/decidim-accountability/spec/requests/result_search_spec.rb @@ -0,0 +1,109 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "Result search", type: :request do + include Decidim::ComponentPathHelper + + let(:component) { create :accountability_component } + let(:participatory_space) { component.participatory_space } + let(:parent_id) { nil } + let(:filter_params) { {} } + + let!(:result1) do + create( + :result, + title: Decidim::Faker::Localized.literal("A doggo in the title"), + component: component, + parent: nil, + category: create(:category, participatory_space: participatory_space) + ) + end + let!(:result2) do + create( + :result, + description: Decidim::Faker::Localized.literal("There is a doggo in the office"), + component: component, + parent: result1, + category: create(:category, participatory_space: participatory_space) + ) + end + let!(:result3) do + create( + :result, + component: component, + parent: result2, + category: create(:category, participatory_space: participatory_space) + ) + end + let!(:result4) do + create( + :result, + component: component, + parent: nil, + category: create(:category, participatory_space: participatory_space) + ) + end + + let(:request_path) { main_component_path(component) } + + before do + get( + request_path, + params: { parent_id: parent_id, filter: filter_params }, + headers: { "HOST" => component.organization.host } + ) + end + + describe "home" do + subject { response.body } + + it "displays all categories that have top-level results" do + expect(subject).to include(translated(result1.category.name)) + expect(subject).to include(translated(result4.category.name)) + end + + it "does not display the categories that only have sub-results" do + expect(subject).not_to include(translated(result2.category.name)) + expect(subject).not_to include(translated(result3.category.name)) + end + end + + describe "results" do + subject { assigns(:results) } + + let(:request_path) { "#{main_component_path(component)}/results" } + + context "when deep searching" do + context "when the parent_id is nil" do + it "returns the search on all results" do + expect(subject).to match_array [result1, result2, result4] + end + end + + context "when the parent_id is result1" do + let(:parent_id) { result1.id } + + it "returns the search on the children of result" do + expect(subject).to match_array [result2, result3] + end + end + + context "when the parent_id is result2" do + let(:parent_id) { result2.id } + + it "returns the search on the children of result" do + expect(subject).to match_array [result3] + end + end + end + + context "when searching by text" do + let(:filter_params) { { search_text_cont: "doggo" } } + + it "returns the search results matching the word in title or description" do + expect(subject).to match_array [result1, result2] + end + end + end +end diff --git a/decidim-accountability/spec/services/decidim/accountability/diff_renderer_spec.rb b/decidim-accountability/spec/services/decidim/accountability/diff_renderer_spec.rb index 10b3803f98e22..23b2831255c33 100644 --- a/decidim-accountability/spec/services/decidim/accountability/diff_renderer_spec.rb +++ b/decidim-accountability/spec/services/decidim/accountability/diff_renderer_spec.rb @@ -41,7 +41,7 @@ start_date: :date, title_en: :i18n } - types = subject.map { |attribute, data| [attribute.to_sym, data[:type]] }.to_h + types = subject.to_h { |attribute, data| [attribute.to_sym, data[:type]] } expect(types).to eq expected_types end @@ -52,7 +52,7 @@ start_date: "Start date", title_en: "Title (English)" } - labels = subject.map { |attribute, data| [attribute.to_sym, data[:label]] }.to_h + labels = subject.to_h { |attribute, data| [attribute.to_sym, data[:label]] } expect(labels).to eq expected_labels end @@ -76,7 +76,7 @@ start_date: "Start date", title_en: "Title (English)" } - labels = subject.map { |attribute, data| [attribute.to_sym, data[:label]] }.to_h + labels = subject.to_h { |attribute, data| [attribute.to_sym, data[:label]] } expect(labels).to eq expected_labels end end diff --git a/decidim-accountability/spec/services/decidim/accountability/result_search_spec.rb b/decidim-accountability/spec/services/decidim/accountability/result_search_spec.rb deleted file mode 100644 index 71f9ab47772aa..0000000000000 --- a/decidim-accountability/spec/services/decidim/accountability/result_search_spec.rb +++ /dev/null @@ -1,90 +0,0 @@ -# frozen_string_literal: true - -require "spec_helper" - -module Decidim::Accountability - describe ResultSearch do - subject { described_class.new(params).results } - - let(:component) { create :accountability_component } - let(:participatory_space) { component.participatory_space } - let(:default_params) do - { component: component, deep_search: true } - end - let(:params) { default_params } - - it_behaves_like "a resource search", :result - it_behaves_like "a resource search with scopes", :result - it_behaves_like "a resource search with categories", :result - - describe "filters" do - let!(:result1) do - create( - :result, - component: component, - parent: nil - ) - end - let!(:result2) do - create( - :result, - component: component, - parent: result1 - ) - end - let!(:result3) do - create( - :result, - component: component, - parent: result2 - ) - end - - describe "parent_id" do - context "when deep searching" do - context "when the parent_id is nil" do - let(:params) { default_params.merge(parent_id: nil) } - - it "returns the search on all results" do - expect(subject).to match_array [result1, result2] - end - end - - context "when the parent_id is result1" do - let(:params) { default_params.merge(parent_id: result1.id) } - - it "returns the search on the children of result" do - expect(subject).to match_array [result2, result3] - end - end - - context "when the parent_id is result2" do - let(:params) { default_params.merge(parent_id: result2.id) } - - it "returns the search on the children of result" do - expect(subject).to match_array [result3] - end - end - end - - context "when not deep searching" do - context "when the parent_id is nil" do - let(:params) { default_params.merge(parent_id: nil, deep_search: false) } - - it "returns the search on the result without parent" do - expect(subject).to match_array [result1] - end - end - - context "when the parent_id is result1" do - let(:params) { default_params.merge(parent_id: result1.id, deep_search: false) } - - it "returns the search on the children of result" do - expect(subject).to match_array [result2] - end - end - end - end - end - end -end diff --git a/decidim-accountability/spec/services/decidim/accountability/results_csv_importer_spec.rb b/decidim-accountability/spec/services/decidim/accountability/results_csv_importer_spec.rb index fc81c7e65e1b6..1ba273c618983 100644 --- a/decidim-accountability/spec/services/decidim/accountability/results_csv_importer_spec.rb +++ b/decidim-accountability/spec/services/decidim/accountability/results_csv_importer_spec.rb @@ -11,9 +11,9 @@ let(:participatory_process) { create :participatory_process, organization: organization } let(:current_component) { create :accountability_component, participatory_space: participatory_process, id: 16 } let!(:category) { create :category, id: 16, participatory_space: current_component.participatory_space } - let!(:status_6) { create :status, id: 6, component: current_component } - let!(:status_7) { create :status, id: 7, component: current_component } - let!(:status_8) { create :status, id: 8, component: current_component } + let!(:status6) { create :status, id: 6, component: current_component } + let!(:status7) { create :status, id: 7, component: current_component } + let!(:status8) { create :status, id: 8, component: current_component } let(:valid_csv) { File.read("spec/fixtures/valid_result.csv") } let(:invalid_csv) { File.read("spec/fixtures/invalid_result.csv") } @@ -28,7 +28,7 @@ end context "when results exist" do - let!(:result1) { create :result, component: current_component, progress: 0, id: 69, status: status_6 } + let!(:result1) { create :result, component: current_component, progress: 0, id: 69, status: status6 } it "Update the result1 progress attribute" do subject.import! diff --git a/decidim-accountability/spec/services/decidim/accountability/searchable_result_resource_spec.rb b/decidim-accountability/spec/services/decidim/accountability/searchable_result_resource_spec.rb index d6cf677c2ba88..d4abe3f549a41 100644 --- a/decidim-accountability/spec/services/decidim/accountability/searchable_result_resource_spec.rb +++ b/decidim-accountability/spec/services/decidim/accountability/searchable_result_resource_spec.rb @@ -16,7 +16,7 @@ module Decidim component: current_component, scope: scope1, title: Decidim::Faker::Localized.name, - description: description_1 + description: description1 ) end diff --git a/decidim-accountability/spec/system/admin/admin_orders_results_spec.rb b/decidim-accountability/spec/system/admin/admin_orders_results_spec.rb index ba0459c212eab..2956973357278 100644 --- a/decidim-accountability/spec/system/admin/admin_orders_results_spec.rb +++ b/decidim-accountability/spec/system/admin/admin_orders_results_spec.rb @@ -10,12 +10,12 @@ name: { "ca" => "Scope2", "en" => "Scope3" }), component: current_component, category: create(:category, participatory_space: participatory_space), - created_at: Time.current - 2.days), + created_at: 2.days.ago), create(:result, scope: create(:scope, organization: component.organization, name: { "ca" => "Scope3", "en" => "Scope1" }), component: current_component, category: create(:category, participatory_space: participatory_space), - created_at: Time.current - 1.day), + created_at: 1.day.ago), create(:result, scope: create(:scope, organization: component.organization, name: { "ca" => "Scope1", "en" => "Scope2" }), component: current_component, diff --git a/decidim-accountability/spec/system/explore_results_spec.rb b/decidim-accountability/spec/system/explore_results_spec.rb index 8dbbc8a7e09f0..193a41ca4ed83 100644 --- a/decidim-accountability/spec/system/explore_results_spec.rb +++ b/decidim-accountability/spec/system/explore_results_spec.rb @@ -18,16 +18,32 @@ before do component.update(settings: { scopes_enabled: true }) + visit path end describe "home" do + let!(:other_category) { create :category, participatory_space: participatory_space } + let!(:other_scope) { create :scope, organization: organization } + + let(:subcategory) { create :subcategory, parent: category } + let(:other_subcategory) { create :subcategory, parent: other_category } + let(:path) { decidim_participatory_process_accountability.root_path(participatory_process_slug: participatory_process.slug, component_id: component.id) } + before do + # Add scopes and categories for the results to test they work correctly + results[0..2].each { |r| r.update!(category: subcategory, scope: scope) } + results[3..-1].each { |r| r.update!(category: other_subcategory, scope: other_scope) } + + # Revisit the path to load updated results + visit path + end + it "shows categories and subcategories with results" do participatory_process.categories.each do |category| - results_count = Decidim::Accountability::ResultsCalculator.new(component, nil, category.id).count - expect(page).to have_content(translated(category.name)) if !category.subcategories.empty? || results_count.positive? + category_count = Decidim::Accountability::ResultsCalculator.new(component, nil, category.id).count + expect(page).to have_content(translated(category.name)) if category_count.positive? end end @@ -48,6 +64,64 @@ expect(page).to have_no_selector(".progress-figure") end end + + context "with a scope" do + before do + within "ul.tags.tags--action" do + click_link translated(scope.name) + end + end + + it "shows current scope active" do + within "ul.tags.tags--action li.active" do + expect(page).to have_content(translated(scope.name)) + end + end + + it "shows only the categories with results matching the current scope" do + participatory_process.categories.each do |category| + category_count = Decidim::Accountability::ResultsCalculator.new(component, scope.id, category.id).count + if category_count.positive? + expect(page).to have_content(translated(category.name)) + else + expect(page).not_to have_content(translated(category.name)) + end + end + end + end + + context "when searching" do + let!(:matching_result1) do + create( + :result, + title: Decidim::Faker::Localized.literal("A doggo in the title"), + component: component + ) + end + let!(:matching_result2) do + create( + :result, + title: Decidim::Faker::Localized.literal("Other matching result"), + description: Decidim::Faker::Localized.literal("There is a doggo in the office"), + component: component + ) + end + + it "displays the correct search results" do + fill_in :filter_search_text_cont, with: "doggo" + within "form .filters__search" do + find("*[type=submit]").click + end + + expect(page).to have_content("2 RESULTS") + expect(page).to have_content(translated(matching_result1.title)) + expect(page).to have_content(translated(matching_result2.title)) + + results.each do |result| + expect(page).not_to have_content(translated(result.title)) + end + end + end end describe "index" do @@ -74,7 +148,7 @@ let(:path) do decidim_participatory_process_accountability.results_path( - participatory_process_slug: participatory_process.slug, component_id: component.id, filter: { category_id: category.id, scope_id: scope.id } + participatory_process_slug: participatory_process.slug, component_id: component.id, filter: { with_category: category.id, with_scope: scope.id } ) end diff --git a/decidim-admin/app/cells/decidim/admin/attachments_privacy_warning/show.erb b/decidim-admin/app/cells/decidim/admin/attachments_privacy_warning/show.erb new file mode 100644 index 0000000000000..bd873c6c9d574 --- /dev/null +++ b/decidim-admin/app/cells/decidim/admin/attachments_privacy_warning/show.erb @@ -0,0 +1,3 @@ +<% if private_space? && !(transparent_space?) %> +
<%= t("decidim.admin.attachments_privacy_warning.message") %>
+<% end %> diff --git a/decidim-admin/app/cells/decidim/admin/attachments_privacy_warning_cell.rb b/decidim-admin/app/cells/decidim/admin/attachments_privacy_warning_cell.rb new file mode 100644 index 0000000000000..722ce4c4a8387 --- /dev/null +++ b/decidim-admin/app/cells/decidim/admin/attachments_privacy_warning_cell.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Decidim + module Admin + class AttachmentsPrivacyWarningCell < Decidim::ViewModel + delegate :current_participatory_space, to: :controller + + private + + def private_space? + current_participatory_space.private_space if current_participatory_space.respond_to?(:private_space) + end + + def transparent_space? + current_participatory_space.is_transparent if current_participatory_space.respond_to?(:is_transparent) + end + end + end +end diff --git a/decidim-admin/app/commands/decidim/admin/block_user.rb b/decidim-admin/app/commands/decidim/admin/block_user.rb index e734500a81cfd..e16bb986a3424 100644 --- a/decidim-admin/app/commands/decidim/admin/block_user.rb +++ b/decidim-admin/app/commands/decidim/admin/block_user.rb @@ -2,7 +2,7 @@ module Decidim module Admin - class BlockUser < Rectify::Command + class BlockUser < Decidim::Command # Public: Initializes the command. # # form - BlockUserForm diff --git a/decidim-admin/app/commands/decidim/admin/close_session_managed_user.rb b/decidim-admin/app/commands/decidim/admin/close_session_managed_user.rb index cfaccb6d871d5..9220561513393 100644 --- a/decidim-admin/app/commands/decidim/admin/close_session_managed_user.rb +++ b/decidim-admin/app/commands/decidim/admin/close_session_managed_user.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic to close a current impersonation session. - class CloseSessionManagedUser < Rectify::Command + class CloseSessionManagedUser < Decidim::Command # Public: Initializes the command. # # user - The user impersonated. diff --git a/decidim-admin/app/commands/decidim/admin/create_area.rb b/decidim-admin/app/commands/decidim/admin/create_area.rb index a5d8d88f685ae..d8801ef38c8a3 100644 --- a/decidim-admin/app/commands/decidim/admin/create_area.rb +++ b/decidim-admin/app/commands/decidim/admin/create_area.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when creating an area - class CreateArea < Rectify::Command + class CreateArea < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/decidim-admin/app/commands/decidim/admin/create_area_type.rb b/decidim-admin/app/commands/decidim/admin/create_area_type.rb index 13076fc61c0be..872e2139323b4 100644 --- a/decidim-admin/app/commands/decidim/admin/create_area_type.rb +++ b/decidim-admin/app/commands/decidim/admin/create_area_type.rb @@ -3,12 +3,13 @@ module Decidim module Admin # A command with all the business logic when creating an area type. - class CreateAreaType < Rectify::Command + class CreateAreaType < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. - def initialize(form) + def initialize(form, user) @form = form + @user = user end # Executes the command. Broadcasts these events: @@ -29,7 +30,9 @@ def call attr_reader :form def create_area_type - AreaType.create!( + Decidim.traceability.create!( + AreaType, + @user, name: form.name, organization: form.organization, plural: form.plural diff --git a/decidim-admin/app/commands/decidim/admin/create_attachment.rb b/decidim-admin/app/commands/decidim/admin/create_attachment.rb index a7530dc97ebe9..785025af52d35 100644 --- a/decidim-admin/app/commands/decidim/admin/create_attachment.rb +++ b/decidim-admin/app/commands/decidim/admin/create_attachment.rb @@ -4,14 +4,15 @@ module Decidim module Admin # A command with all the business logic to add an attachment to a # participatory process. - class CreateAttachment < Rectify::Command + class CreateAttachment < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. # attached_to - The ActiveRecord::Base that will hold the attachment - def initialize(form, attached_to) + def initialize(form, attached_to, user) @form = form @attached_to = attached_to + @user = user end # Executes the command. Broadcasts these events: @@ -26,9 +27,12 @@ def call build_attachment if @attachment.valid? - @attachment.save! - notify_followers - broadcast(:ok) + Decidim.traceability.perform_action!(:create, Decidim::Attachment, @user) do + @attachment.save! + notify_followers + broadcast(:ok) + @attachment + end else @form.errors.add :file, @attachment.errors[:file] if @attachment.errors.has_key? :file broadcast(:invalid) @@ -47,7 +51,7 @@ def build_attachment weight: form.weight, attachment_collection: form.attachment_collection, file: form.file, # Define attached_to before this - content_type: form.file.content_type + content_type: blob(form.file).content_type ) end @@ -61,6 +65,10 @@ def notify_followers followers: @attachment.attached_to.followers ) end + + def blob(signed_id) + ActiveStorage::Blob.find_signed(signed_id) + end end end end diff --git a/decidim-admin/app/commands/decidim/admin/create_attachment_collection.rb b/decidim-admin/app/commands/decidim/admin/create_attachment_collection.rb index 72fb2a148a421..88baba63e8346 100644 --- a/decidim-admin/app/commands/decidim/admin/create_attachment_collection.rb +++ b/decidim-admin/app/commands/decidim/admin/create_attachment_collection.rb @@ -4,14 +4,15 @@ module Decidim module Admin # A command with all the business logic to add an attachment collection # to a participatory space. - class CreateAttachmentCollection < Rectify::Command + class CreateAttachmentCollection < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. # collection_for - The ActiveRecord::Base that will hold the collection - def initialize(form, collection_for) + def initialize(form, collection_for, user) @form = form @collection_for = collection_for + @user = user end # Executes the command. Broadcasts these events: @@ -32,12 +33,20 @@ def call attr_reader :form def create_attachment_collection - AttachmentCollection.create!( + Decidim.traceability.create!( + AttachmentCollection, + @user, + attributes + ) + end + + def attributes + { name: form.name, weight: form.weight, description: form.description, collection_for: @collection_for - ) + } end end end diff --git a/decidim-admin/app/commands/decidim/admin/create_category.rb b/decidim-admin/app/commands/decidim/admin/create_category.rb index 2e5658ab781c6..581b29f1f5e1c 100644 --- a/decidim-admin/app/commands/decidim/admin/create_category.rb +++ b/decidim-admin/app/commands/decidim/admin/create_category.rb @@ -4,15 +4,16 @@ module Decidim module Admin # A command with all the business logic to create a new category in the # system. - class CreateCategory < Rectify::Command + class CreateCategory < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. # participatory_space - The participatory space that will hold the # category - def initialize(form, participatory_space) + def initialize(form, participatory_space, user) @form = form @participatory_space = participatory_space + @user = user end # Executes the command. Broadcasts these events: @@ -33,10 +34,11 @@ def call attr_reader :form def create_category - Category.create!( + Decidim.traceability.create!( + Category, + @user, name: form.name, weight: form.weight, - description: form.description, parent_id: form.parent_id, participatory_space: @participatory_space ) diff --git a/decidim-admin/app/commands/decidim/admin/create_component.rb b/decidim-admin/app/commands/decidim/admin/create_component.rb index cff14a49efb61..64522a88750dc 100644 --- a/decidim-admin/app/commands/decidim/admin/create_component.rb +++ b/decidim-admin/app/commands/decidim/admin/create_component.rb @@ -3,7 +3,7 @@ module Decidim module Admin # This command gets called when a component is created from the admin panel. - class CreateComponent < Rectify::Command + class CreateComponent < Decidim::Command attr_reader :form, :manifest, :participatory_space # Public: Initializes the command. diff --git a/decidim-admin/app/commands/decidim/admin/create_import.rb b/decidim-admin/app/commands/decidim/admin/create_import.rb index 732c78dbd2bd5..ba6f8f69a1842 100644 --- a/decidim-admin/app/commands/decidim/admin/create_import.rb +++ b/decidim-admin/app/commands/decidim/admin/create_import.rb @@ -2,7 +2,7 @@ module Decidim module Admin - class CreateImport < Rectify::Command + class CreateImport < Decidim::Command def initialize(form) @form = form end @@ -14,13 +14,12 @@ def call transaction do form.importer.import! - return broadcast(:ok, imported_data) + broadcast(:ok, imported_data) rescue StandardError + # Something went wrong with import/finish + broadcast(:invalid) raise ActiveRecord::Rollback end - - # Something went wrong with import/finish - broadcast(:invalid) end attr_reader :form diff --git a/decidim-admin/app/commands/decidim/admin/create_import_example.rb b/decidim-admin/app/commands/decidim/admin/create_import_example.rb index f10dc0e714f85..7a41982f161c6 100644 --- a/decidim-admin/app/commands/decidim/admin/create_import_example.rb +++ b/decidim-admin/app/commands/decidim/admin/create_import_example.rb @@ -2,7 +2,7 @@ module Decidim module Admin - class CreateImportExample < Rectify::Command + class CreateImportExample < Decidim::Command def initialize(form) @form = form end diff --git a/decidim-admin/app/commands/decidim/admin/create_newsletter.rb b/decidim-admin/app/commands/decidim/admin/create_newsletter.rb index 973570ce44766..de80dedeef7e1 100644 --- a/decidim-admin/app/commands/decidim/admin/create_newsletter.rb +++ b/decidim-admin/app/commands/decidim/admin/create_newsletter.rb @@ -4,7 +4,7 @@ module Decidim module Admin # Creates a newsletter and assigns the right author and # organization. - class CreateNewsletter < Rectify::Command + class CreateNewsletter < Decidim::Command # Initializes the command. # # form - The source fo data for this newsletter. diff --git a/decidim-admin/app/commands/decidim/admin/create_participatory_space_private_user.rb b/decidim-admin/app/commands/decidim/admin/create_participatory_space_private_user.rb index f438ad6262057..21c4f5a5d4be9 100644 --- a/decidim-admin/app/commands/decidim/admin/create_participatory_space_private_user.rb +++ b/decidim-admin/app/commands/decidim/admin/create_participatory_space_private_user.rb @@ -4,7 +4,7 @@ module Decidim module Admin # A command with all the business logic when creating a new participatory space # private user in the system. - class CreateParticipatorySpacePrivateUser < Rectify::Command + class CreateParticipatorySpacePrivateUser < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/decidim-admin/app/commands/decidim/admin/create_scope.rb b/decidim-admin/app/commands/decidim/admin/create_scope.rb index 0fa9aad5adda7..60cacb724dc34 100644 --- a/decidim-admin/app/commands/decidim/admin/create_scope.rb +++ b/decidim-admin/app/commands/decidim/admin/create_scope.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when creating a static scope. - class CreateScope < Rectify::Command + class CreateScope < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/decidim-admin/app/commands/decidim/admin/create_scope_type.rb b/decidim-admin/app/commands/decidim/admin/create_scope_type.rb index a92c351fd7310..eef4079ccc339 100644 --- a/decidim-admin/app/commands/decidim/admin/create_scope_type.rb +++ b/decidim-admin/app/commands/decidim/admin/create_scope_type.rb @@ -3,12 +3,13 @@ module Decidim module Admin # A command with all the business logic when creating a scope type. - class CreateScopeType < Rectify::Command + class CreateScopeType < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. - def initialize(form) + def initialize(form, user) @form = form + @user = user end # Executes the command. Broadcasts these events: @@ -29,7 +30,9 @@ def call attr_reader :form def create_scope_type - ScopeType.create!( + Decidim.traceability.create!( + ScopeType, + @user, name: form.name, organization: form.organization, plural: form.plural diff --git a/decidim-admin/app/commands/decidim/admin/create_static_page.rb b/decidim-admin/app/commands/decidim/admin/create_static_page.rb index a0970d2ef17a9..94d831085d19c 100644 --- a/decidim-admin/app/commands/decidim/admin/create_static_page.rb +++ b/decidim-admin/app/commands/decidim/admin/create_static_page.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when creating a static page. - class CreateStaticPage < Rectify::Command + class CreateStaticPage < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/decidim-admin/app/commands/decidim/admin/create_static_page_topic.rb b/decidim-admin/app/commands/decidim/admin/create_static_page_topic.rb index 93ad0295791e4..6a639efc58193 100644 --- a/decidim-admin/app/commands/decidim/admin/create_static_page_topic.rb +++ b/decidim-admin/app/commands/decidim/admin/create_static_page_topic.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when creating a static page topic. - class CreateStaticPageTopic < Rectify::Command + class CreateStaticPageTopic < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/decidim-admin/app/commands/decidim/admin/deliver_newsletter.rb b/decidim-admin/app/commands/decidim/admin/deliver_newsletter.rb index db8e1ca7ef475..04530b9983803 100644 --- a/decidim-admin/app/commands/decidim/admin/deliver_newsletter.rb +++ b/decidim-admin/app/commands/decidim/admin/deliver_newsletter.rb @@ -3,7 +3,7 @@ module Decidim module Admin # Delivers the newsletter to its recipients. - class DeliverNewsletter < Rectify::Command + class DeliverNewsletter < Decidim::Command # Initializes the command. # # newsletter - The newsletter to deliver. @@ -16,12 +16,12 @@ def initialize(newsletter, form, user) end def call - @newsletter.with_lock do - return broadcast(:invalid) if @form.send_to_all_users && !@user.admin? - return broadcast(:invalid) unless @form.valid? - return broadcast(:invalid) if @newsletter.sent? - return broadcast(:no_recipients) if recipients.blank? + return broadcast(:invalid) if @form.send_to_all_users && !@user.admin? + return broadcast(:invalid) unless @form.valid? + return broadcast(:invalid) if @newsletter.sent? + return broadcast(:no_recipients) if recipients.blank? + @newsletter.with_lock do send_newsletter! end diff --git a/decidim-admin/app/commands/decidim/admin/destroy_area.rb b/decidim-admin/app/commands/decidim/admin/destroy_area.rb index 3db686ded7a56..56e9ca8c78838 100644 --- a/decidim-admin/app/commands/decidim/admin/destroy_area.rb +++ b/decidim-admin/app/commands/decidim/admin/destroy_area.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic to destroy an area. - class DestroyArea < Rectify::Command + class DestroyArea < Decidim::Command # Public: Initializes the command. # # area - The area to destroy diff --git a/decidim-admin/app/commands/decidim/admin/destroy_category.rb b/decidim-admin/app/commands/decidim/admin/destroy_category.rb index 86586fb5c804b..f5c198fa19a36 100644 --- a/decidim-admin/app/commands/decidim/admin/destroy_category.rb +++ b/decidim-admin/app/commands/decidim/admin/destroy_category.rb @@ -4,12 +4,13 @@ module Decidim module Admin # A command with all the business logic to destroy a category in the # system. - class DestroyCategory < Rectify::Command + class DestroyCategory < Decidim::Command # Public: Initializes the command. # # category - A Category that will be destroyed - def initialize(category) + def initialize(category, user) @category = category + @user = user end # Executes the command. Broadcasts these events: @@ -30,7 +31,9 @@ def call attr_reader :category def destroy_category - category.destroy! + Decidim.traceability.perform_action!(:delete, category, @user) do + category.destroy! + end end end end diff --git a/decidim-admin/app/commands/decidim/admin/destroy_component.rb b/decidim-admin/app/commands/decidim/admin/destroy_component.rb index 013eb57af4fe2..87a3c87369588 100644 --- a/decidim-admin/app/commands/decidim/admin/destroy_component.rb +++ b/decidim-admin/app/commands/decidim/admin/destroy_component.rb @@ -3,7 +3,7 @@ module Decidim module Admin # This command deals with destroying a Component from the admin panel. - class DestroyComponent < Rectify::Command + class DestroyComponent < Decidim::Command # Public: Initializes the command. # # component - The Component to be destroyed. diff --git a/decidim-admin/app/commands/decidim/admin/destroy_newsletter.rb b/decidim-admin/app/commands/decidim/admin/destroy_newsletter.rb index 45932496ac888..f24986ef79bf6 100644 --- a/decidim-admin/app/commands/decidim/admin/destroy_newsletter.rb +++ b/decidim-admin/app/commands/decidim/admin/destroy_newsletter.rb @@ -3,7 +3,7 @@ module Decidim module Admin # This command deals with destroying a newsletter from the admin panel. - class DestroyNewsletter < Rectify::Command + class DestroyNewsletter < Decidim::Command # Public: Initializes the command. # # newsletter - The Newsletter to be destroyed. diff --git a/decidim-admin/app/commands/decidim/admin/destroy_participatory_space_private_user.rb b/decidim-admin/app/commands/decidim/admin/destroy_participatory_space_private_user.rb index 2f9f79367491a..bdd02dc71ac0b 100644 --- a/decidim-admin/app/commands/decidim/admin/destroy_participatory_space_private_user.rb +++ b/decidim-admin/app/commands/decidim/admin/destroy_participatory_space_private_user.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic to destroy a participatory space private user. - class DestroyParticipatorySpacePrivateUser < Rectify::Command + class DestroyParticipatorySpacePrivateUser < Decidim::Command # Public: Initializes the command. # # participatory_space_private_user - The participatory space private user to destroy diff --git a/decidim-admin/app/commands/decidim/admin/destroy_scope.rb b/decidim-admin/app/commands/decidim/admin/destroy_scope.rb index 1987bf554a42c..e3d343ad239fa 100644 --- a/decidim-admin/app/commands/decidim/admin/destroy_scope.rb +++ b/decidim-admin/app/commands/decidim/admin/destroy_scope.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic to destroy a scope. - class DestroyScope < Rectify::Command + class DestroyScope < Decidim::Command # Public: Initializes the command. # # scope - The Scope to destroy diff --git a/decidim-admin/app/commands/decidim/admin/destroy_share_token.rb b/decidim-admin/app/commands/decidim/admin/destroy_share_token.rb index 38bc1e5d7a0a8..6042d1f5ec858 100644 --- a/decidim-admin/app/commands/decidim/admin/destroy_share_token.rb +++ b/decidim-admin/app/commands/decidim/admin/destroy_share_token.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic to destroy a share token. - class DestroyShareToken < Rectify::Command + class DestroyShareToken < Decidim::Command # Public: Initializes the command. # # share_token - The share_token to destroy diff --git a/decidim-admin/app/commands/decidim/admin/destroy_static_page.rb b/decidim-admin/app/commands/decidim/admin/destroy_static_page.rb index 4da697d9ee1c4..f437aef00ce53 100644 --- a/decidim-admin/app/commands/decidim/admin/destroy_static_page.rb +++ b/decidim-admin/app/commands/decidim/admin/destroy_static_page.rb @@ -3,7 +3,7 @@ module Decidim module Admin # This command deals with destroying a StaticPage from the admin panel. - class DestroyStaticPage < Rectify::Command + class DestroyStaticPage < Decidim::Command # Public: Initializes the command. # # page - The StaticPage to be destroyed. diff --git a/decidim-admin/app/commands/decidim/admin/destroy_static_page_topic.rb b/decidim-admin/app/commands/decidim/admin/destroy_static_page_topic.rb index c3f680ea8fa9b..842499e442cdf 100644 --- a/decidim-admin/app/commands/decidim/admin/destroy_static_page_topic.rb +++ b/decidim-admin/app/commands/decidim/admin/destroy_static_page_topic.rb @@ -3,7 +3,7 @@ module Decidim module Admin # This command deals with destroying a StaticPageTopic from the admin panel. - class DestroyStaticPageTopic < Rectify::Command + class DestroyStaticPageTopic < Decidim::Command # Public: Initializes the command. # # page - The StaticPageTopic to be destroyed. diff --git a/decidim-admin/app/commands/decidim/admin/hide_resource.rb b/decidim-admin/app/commands/decidim/admin/hide_resource.rb index 6fcbf46ff3541..dc5cd0c2eccf9 100644 --- a/decidim-admin/app/commands/decidim/admin/hide_resource.rb +++ b/decidim-admin/app/commands/decidim/admin/hide_resource.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when a user hides a resource. - class HideResource < Rectify::Command + class HideResource < Decidim::Command # Public: Initializes the command. # # reportable - A Decidim::Reportable @@ -60,7 +60,7 @@ def send_hide_notification_to_author affected_users: @reportable.try(:authors) || [@reportable.try(:normalized_author)] } - Decidim::EventsManager.publish(data) + Decidim::EventsManager.publish(**data) end def report_reasons diff --git a/decidim-admin/app/commands/decidim/admin/impersonate_user.rb b/decidim-admin/app/commands/decidim/admin/impersonate_user.rb index 9e9318dea2ffd..4634d57e89de7 100644 --- a/decidim-admin/app/commands/decidim/admin/impersonate_user.rb +++ b/decidim-admin/app/commands/decidim/admin/impersonate_user.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic to impersonate a managed user. - class ImpersonateUser < Rectify::Command + class ImpersonateUser < Decidim::Command # Public: Initializes the command. # # form - The form with the authorization info diff --git a/decidim-admin/app/commands/decidim/admin/invite_admin.rb b/decidim-admin/app/commands/decidim/admin/invite_admin.rb index da41b728784f7..c8920971b8529 100644 --- a/decidim-admin/app/commands/decidim/admin/invite_admin.rb +++ b/decidim-admin/app/commands/decidim/admin/invite_admin.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command to invite an admin. - class InviteAdmin < Rectify::Command + class InviteAdmin < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/decidim-admin/app/commands/decidim/admin/officialize_user.rb b/decidim-admin/app/commands/decidim/admin/officialize_user.rb index 3cbb12b19b577..8af3c5d41e1f3 100644 --- a/decidim-admin/app/commands/decidim/admin/officialize_user.rb +++ b/decidim-admin/app/commands/decidim/admin/officialize_user.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when officializing a user. - class OfficializeUser < Rectify::Command + class OfficializeUser < Decidim::Command # Public: Initializes the command. # # form - The officialization form. diff --git a/decidim-admin/app/commands/decidim/admin/process_participatory_space_private_user_import_csv.rb b/decidim-admin/app/commands/decidim/admin/process_participatory_space_private_user_import_csv.rb index 7939ad825ae44..0896ba8578edb 100644 --- a/decidim-admin/app/commands/decidim/admin/process_participatory_space_private_user_import_csv.rb +++ b/decidim-admin/app/commands/decidim/admin/process_participatory_space_private_user_import_csv.rb @@ -4,7 +4,9 @@ module Decidim module Admin - class ProcessParticipatorySpacePrivateUserImportCsv < Rectify::Command + class ProcessParticipatorySpacePrivateUserImportCsv < Decidim::Command + include Decidim::ProcessesFileLocally + # Public: Initializes the command. # # form - the form object containing the uploaded file @@ -32,8 +34,10 @@ def call private def process_csv - CSV.foreach(@form.file.path, encoding: "BOM|UTF-8") do |email, user_name| - ImportParticipatorySpacePrivateUserCsvJob.perform_later(email, user_name, @private_users_to, @current_user) if email.present? && user_name.present? + process_file_locally(@form.file) do |file_path| + CSV.foreach(file_path, encoding: "BOM|UTF-8") do |email, user_name| + ImportParticipatorySpacePrivateUserCsvJob.perform_later(email, user_name, @private_users_to, @current_user) if email.present? && user_name.present? + end end end end diff --git a/decidim-admin/app/commands/decidim/admin/process_user_group_verification_csv.rb b/decidim-admin/app/commands/decidim/admin/process_user_group_verification_csv.rb index 957c6223f6788..49bdc6960ee94 100644 --- a/decidim-admin/app/commands/decidim/admin/process_user_group_verification_csv.rb +++ b/decidim-admin/app/commands/decidim/admin/process_user_group_verification_csv.rb @@ -6,7 +6,9 @@ module Decidim module Admin # A command with all the business logic when processing the CSV to verify # user groups. - class ProcessUserGroupVerificationCsv < Rectify::Command + class ProcessUserGroupVerificationCsv < Decidim::Command + include Decidim::ProcessesFileLocally + # Public: Initializes the command. # # form - the form object containing the uploaded file @@ -33,9 +35,11 @@ def process_csv verifier = @form.current_user organization = @form.current_organization - CSV.foreach(@form.file.path) do |row| - email = row[0] - VerifyUserGroupFromCsvJob.perform_later(email, verifier, organization) if email.present? + process_file_locally(@form.file) do |file_path| + CSV.foreach(file_path) do |row| + email = row[0] + VerifyUserGroupFromCsvJob.perform_later(email, verifier, organization) if email.present? + end end end end diff --git a/decidim-admin/app/commands/decidim/admin/promote_managed_user.rb b/decidim-admin/app/commands/decidim/admin/promote_managed_user.rb index be600aea77fe7..b395efd6067c0 100644 --- a/decidim-admin/app/commands/decidim/admin/promote_managed_user.rb +++ b/decidim-admin/app/commands/decidim/admin/promote_managed_user.rb @@ -7,7 +7,7 @@ module Admin # Managed users can be promoted to standard users. It means they # will be invited to the application and will lose the managed flag # so the user cannot be impersonated anymore. - class PromoteManagedUser < Rectify::Command + class PromoteManagedUser < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/decidim-admin/app/commands/decidim/admin/publish_component.rb b/decidim-admin/app/commands/decidim/admin/publish_component.rb index 0b70b564d424a..de18bb2dd9f1e 100644 --- a/decidim-admin/app/commands/decidim/admin/publish_component.rb +++ b/decidim-admin/app/commands/decidim/admin/publish_component.rb @@ -3,7 +3,7 @@ module Decidim module Admin # This command gets called when a component is published from the admin panel. - class PublishComponent < Rectify::Command + class PublishComponent < Decidim::Command # Public: Initializes the command. # # component - The component to publish. diff --git a/decidim-admin/app/commands/decidim/admin/reject_user_group.rb b/decidim-admin/app/commands/decidim/admin/reject_user_group.rb index d73996edad685..6ca740c685218 100644 --- a/decidim-admin/app/commands/decidim/admin/reject_user_group.rb +++ b/decidim-admin/app/commands/decidim/admin/reject_user_group.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when rejecting a user_group. - class RejectUserGroup < Rectify::Command + class RejectUserGroup < Decidim::Command # Public: Initializes the command. # # user_group - The user_group to reject diff --git a/decidim-admin/app/commands/decidim/admin/remove_admin.rb b/decidim-admin/app/commands/decidim/admin/remove_admin.rb index 6f694d8a98448..ff0bef932f0db 100644 --- a/decidim-admin/app/commands/decidim/admin/remove_admin.rb +++ b/decidim-admin/app/commands/decidim/admin/remove_admin.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command to remove the admin privilege to an user. - class RemoveAdmin < Rectify::Command + class RemoveAdmin < Decidim::Command # Public: Initializes the command. # # user - the user that will no longer be an admin diff --git a/decidim-admin/app/commands/decidim/admin/reorder_content_blocks.rb b/decidim-admin/app/commands/decidim/admin/reorder_content_blocks.rb index a9422ae79f7d7..3cb5017d34fe9 100644 --- a/decidim-admin/app/commands/decidim/admin/reorder_content_blocks.rb +++ b/decidim-admin/app/commands/decidim/admin/reorder_content_blocks.rb @@ -4,7 +4,7 @@ module Decidim module Admin # A command that reorders a collection of content blocks. It also creates # the ones that might be missing. - class ReorderContentBlocks < Rectify::Command + class ReorderContentBlocks < Decidim::Command # Public: Initializes the command. # # organization - the Organization where the content blocks reside diff --git a/decidim-admin/app/commands/decidim/admin/transfer_user.rb b/decidim-admin/app/commands/decidim/admin/transfer_user.rb index 6771c864d3d01..1cbc559408044 100644 --- a/decidim-admin/app/commands/decidim/admin/transfer_user.rb +++ b/decidim-admin/app/commands/decidim/admin/transfer_user.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic to transfer a managed user. - class TransferUser < Rectify::Command + class TransferUser < Decidim::Command # Public: Initializes the command. # # form diff --git a/decidim-admin/app/commands/decidim/admin/unblock_user.rb b/decidim-admin/app/commands/decidim/admin/unblock_user.rb index 021183ddfbece..80cc01464d311 100644 --- a/decidim-admin/app/commands/decidim/admin/unblock_user.rb +++ b/decidim-admin/app/commands/decidim/admin/unblock_user.rb @@ -2,7 +2,7 @@ module Decidim module Admin - class UnblockUser < Rectify::Command + class UnblockUser < Decidim::Command # Public: Initializes the command. # # blocked_user - the user that is unblocked @@ -39,7 +39,7 @@ def unblock! @blocked_user.blocked = false @blocked_user.blocked_at = nil @blocked_user.block_id = nil - @blocked_user.name = @blocked_user.user_name + @blocked_user.name = @blocked_user.extended_data["user_name"] @blocked_user.save! end end diff --git a/decidim-admin/app/commands/decidim/admin/unhide_resource.rb b/decidim-admin/app/commands/decidim/admin/unhide_resource.rb index 0d0f498442926..a98d6c6b464d2 100644 --- a/decidim-admin/app/commands/decidim/admin/unhide_resource.rb +++ b/decidim-admin/app/commands/decidim/admin/unhide_resource.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when a user hides a resource. - class UnhideResource < Rectify::Command + class UnhideResource < Decidim::Command # Public: Initializes the command. # # reportable - A Decidim::Reportable diff --git a/decidim-admin/app/commands/decidim/admin/unofficialize_user.rb b/decidim-admin/app/commands/decidim/admin/unofficialize_user.rb index a24232d6cf958..bad5fd843b467 100644 --- a/decidim-admin/app/commands/decidim/admin/unofficialize_user.rb +++ b/decidim-admin/app/commands/decidim/admin/unofficialize_user.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when unofficializing a user. - class UnofficializeUser < Rectify::Command + class UnofficializeUser < Decidim::Command # Public: Initializes the command. # # user - The user to be unofficialized. diff --git a/decidim-admin/app/commands/decidim/admin/unpublish_component.rb b/decidim-admin/app/commands/decidim/admin/unpublish_component.rb index 840378d984aee..a2761103a3558 100644 --- a/decidim-admin/app/commands/decidim/admin/unpublish_component.rb +++ b/decidim-admin/app/commands/decidim/admin/unpublish_component.rb @@ -3,7 +3,7 @@ module Decidim module Admin # This command gets called when a component is unpublished from the admin panel. - class UnpublishComponent < Rectify::Command + class UnpublishComponent < Decidim::Command # Public: Initializes the command. # # component - The component to unpublish. diff --git a/decidim-admin/app/commands/decidim/admin/unreport_resource.rb b/decidim-admin/app/commands/decidim/admin/unreport_resource.rb index 0bfcec4623d3b..27fe8f8128ff7 100644 --- a/decidim-admin/app/commands/decidim/admin/unreport_resource.rb +++ b/decidim-admin/app/commands/decidim/admin/unreport_resource.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when a user unreports a resource. - class UnreportResource < Rectify::Command + class UnreportResource < Decidim::Command # Public: Initializes the command. # # reportable - A Decidim::Reportable diff --git a/decidim-admin/app/commands/decidim/admin/unreport_user.rb b/decidim-admin/app/commands/decidim/admin/unreport_user.rb index 7f38fa417e200..028e4cce026ce 100644 --- a/decidim-admin/app/commands/decidim/admin/unreport_user.rb +++ b/decidim-admin/app/commands/decidim/admin/unreport_user.rb @@ -2,7 +2,7 @@ module Decidim module Admin - class UnreportUser < Rectify::Command + class UnreportUser < Decidim::Command # Public: Initializes the command. # # reportable - A Decidim::User - The user reported diff --git a/decidim-admin/app/commands/decidim/admin/update_area.rb b/decidim-admin/app/commands/decidim/admin/update_area.rb index b5a83c4740865..0a4a0d8c9cc62 100644 --- a/decidim-admin/app/commands/decidim/admin/update_area.rb +++ b/decidim-admin/app/commands/decidim/admin/update_area.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when updating an area. - class UpdateArea < Rectify::Command + class UpdateArea < Decidim::Command # Public: Initializes the command. # # area - The Area to update diff --git a/decidim-admin/app/commands/decidim/admin/update_area_type.rb b/decidim-admin/app/commands/decidim/admin/update_area_type.rb index 6b94bd7b2c489..3c655e5e5b716 100644 --- a/decidim-admin/app/commands/decidim/admin/update_area_type.rb +++ b/decidim-admin/app/commands/decidim/admin/update_area_type.rb @@ -3,14 +3,15 @@ module Decidim module Admin # A command with all the business logic when updating an area type. - class UpdateAreaType < Rectify::Command + class UpdateAreaType < Decidim::Command # Public: Initializes the command. # # area_type - The AreaType to update # form - A form object with the params. - def initialize(area_type, form) + def initialize(area_type, form, user) @area_type = area_type @form = form + @user = user end # Executes the command. Broadcasts these events: @@ -31,7 +32,11 @@ def call attr_reader :form def update_area_type - @area_type.update!(attributes) + Decidim.traceability.update!( + @area_type, + @user, + attributes + ) end def attributes diff --git a/decidim-admin/app/commands/decidim/admin/update_attachment.rb b/decidim-admin/app/commands/decidim/admin/update_attachment.rb index b4a80e2110029..1b056806b1adf 100644 --- a/decidim-admin/app/commands/decidim/admin/update_attachment.rb +++ b/decidim-admin/app/commands/decidim/admin/update_attachment.rb @@ -4,7 +4,7 @@ module Decidim module Admin # A command with all the business logic to update an attachment from a # participatory process. - class UpdateAttachment < Rectify::Command + class UpdateAttachment < Decidim::Command include ::Decidim::AttachmentAttributesMethods attr_reader :attachment @@ -13,9 +13,10 @@ class UpdateAttachment < Rectify::Command # # attachment - the Attachment to update # form - A form object with the params. - def initialize(attachment, form) + def initialize(attachment, form, user) @attachment = attachment @form = form + @user = user end # Executes the command. Broadcasts these events: @@ -36,7 +37,7 @@ def call attr_reader :form def update_attachment - attachment.update!(attributes) + Decidim.traceability.update!(@attachment, @user, attributes) end def attributes diff --git a/decidim-admin/app/commands/decidim/admin/update_attachment_collection.rb b/decidim-admin/app/commands/decidim/admin/update_attachment_collection.rb index 325c6798c4cd7..17e27163513e3 100644 --- a/decidim-admin/app/commands/decidim/admin/update_attachment_collection.rb +++ b/decidim-admin/app/commands/decidim/admin/update_attachment_collection.rb @@ -3,14 +3,15 @@ module Decidim module Admin # A command with all the business logic when updating an attachment collection. - class UpdateAttachmentCollection < Rectify::Command + class UpdateAttachmentCollection < Decidim::Command # Public: Initializes the command. # # attachment_collection - The AttachmentCollection to update # form - A form object with the params. - def initialize(attachment_collection, form) + def initialize(attachment_collection, form, user) @attachment_collection = attachment_collection @form = form + @user = user end # Executes the command. Broadcasts these events: @@ -31,7 +32,11 @@ def call attr_reader :form def update_attachment_collection - @attachment_collection.update!(attributes) + Decidim.traceability.update!( + @attachment_collection, + @user, + attributes + ) end def attributes diff --git a/decidim-admin/app/commands/decidim/admin/update_category.rb b/decidim-admin/app/commands/decidim/admin/update_category.rb index f80988df780c8..3fca9e9286eaa 100644 --- a/decidim-admin/app/commands/decidim/admin/update_category.rb +++ b/decidim-admin/app/commands/decidim/admin/update_category.rb @@ -4,16 +4,17 @@ module Decidim module Admin # A command with all the business logic when updating a category in the # system. - class UpdateCategory < Rectify::Command + class UpdateCategory < Decidim::Command attr_reader :category # Public: Initializes the command. # # category - the Category to update # form - A form object with the params. - def initialize(category, form) + def initialize(category, form, user) @category = category @form = form + @user = user end # Executes the command. Broadcasts these events: @@ -34,15 +35,18 @@ def call attr_reader :form def update_category - category.update!(attributes) + Decidim.traceability.update!( + category, + @user, + attributes + ) end def attributes { name: form.name, weight: form.weight, - parent_id: form.parent_id, - description: form.description + parent_id: form.parent_id } end end diff --git a/decidim-admin/app/commands/decidim/admin/update_component.rb b/decidim-admin/app/commands/decidim/admin/update_component.rb index 975bf993626e1..f011fb8545713 100644 --- a/decidim-admin/app/commands/decidim/admin/update_component.rb +++ b/decidim-admin/app/commands/decidim/admin/update_component.rb @@ -3,17 +3,18 @@ module Decidim module Admin # This command gets called when a component is created from the admin panel. - class UpdateComponent < Rectify::Command + class UpdateComponent < Decidim::Command attr_reader :form, :component, :previous_settings # Public: Initializes the command. # # form - The form from which the data in this component comes from. # component - The component to update. - def initialize(form, component) + def initialize(form, component, user) @manifest = component.manifest @form = form @component = component + @user = user end # Public: Creates the Component. @@ -22,9 +23,11 @@ def initialize(form, component) def call return broadcast(:invalid) if form.invalid? - transaction do - update_component - run_hooks + Decidim.traceability.perform_action!("update", @component, @user) do + transaction do + update_component + run_hooks + end end broadcast(:ok, settings_changed?, previous_settings, current_settings) diff --git a/decidim-admin/app/commands/decidim/admin/update_component_permissions.rb b/decidim-admin/app/commands/decidim/admin/update_component_permissions.rb index a9bf17af92585..e98321a3d1369 100644 --- a/decidim-admin/app/commands/decidim/admin/update_component_permissions.rb +++ b/decidim-admin/app/commands/decidim/admin/update_component_permissions.rb @@ -4,16 +4,17 @@ module Decidim module Admin # This command gets called when permissions for a component are updated # in the admin panel. - class UpdateComponentPermissions < Rectify::Command + class UpdateComponentPermissions < Decidim::Command # Public: Initializes the command. # # form - The form from which the data in this component comes from. # component - The component to update. # resource - The resource to update. - def initialize(form, component, resource) + def initialize(form, component, resource, user) @form = form @component = component @resource = resource + @user = user end # Public: Sets the permissions for a component. @@ -22,9 +23,11 @@ def initialize(form, component, resource) def call return broadcast(:invalid) unless form.valid? - transaction do - update_permissions - run_hooks + Decidim.traceability.perform_action!("update_permissions", @component, @user) do + transaction do + update_permissions + run_hooks + end end broadcast(:ok) @@ -45,7 +48,7 @@ def update_permissions handlers_content = {} selected_handlers(value).each do |handler_key| - opts = value.authorization_handlers_options[handler_key.to_sym] + opts = value.authorization_handlers_options[handler_key.to_s] handlers_content[handler_key] = opts ? { options: opts } : {} end diff --git a/decidim-admin/app/commands/decidim/admin/update_content_block.rb b/decidim-admin/app/commands/decidim/admin/update_content_block.rb index 09403f51e9a42..fae2ccdb1ed88 100644 --- a/decidim-admin/app/commands/decidim/admin/update_content_block.rb +++ b/decidim-admin/app/commands/decidim/admin/update_content_block.rb @@ -4,7 +4,7 @@ module Decidim module Admin # This command gets called when a content block is updated from the admin # panel. - class UpdateContentBlock < Rectify::Command + class UpdateContentBlock < Decidim::Command attr_reader :form, :content_block, :scope # Public: Initializes the command. diff --git a/decidim-admin/app/commands/decidim/admin/update_external_domain_whitelist.rb b/decidim-admin/app/commands/decidim/admin/update_external_domain_whitelist.rb index 7b1a0f0312038..f1f571ca5c043 100644 --- a/decidim-admin/app/commands/decidim/admin/update_external_domain_whitelist.rb +++ b/decidim-admin/app/commands/decidim/admin/update_external_domain_whitelist.rb @@ -2,18 +2,21 @@ module Decidim module Admin - class UpdateExternalDomainWhitelist < Rectify::Command + class UpdateExternalDomainWhitelist < Decidim::Command attr_reader :form, :organization - def initialize(form, organization) + def initialize(form, organization, user) @form = form @organization = organization + @user = user end def call return broadcast(:invalid) if form.invalid? - save_domains! + Decidim.traceability.perform_action!("update_external_domain", @organization, @user) do + save_domains! + end broadcast(:ok) end diff --git a/decidim-admin/app/commands/decidim/admin/update_help_sections.rb b/decidim-admin/app/commands/decidim/admin/update_help_sections.rb index e50a4387a754a..3aafc5f232cd7 100644 --- a/decidim-admin/app/commands/decidim/admin/update_help_sections.rb +++ b/decidim-admin/app/commands/decidim/admin/update_help_sections.rb @@ -4,10 +4,11 @@ module Decidim module Admin # This command gets called when a content block is updated from the admin # panel. - class UpdateHelpSections < Rectify::Command - def initialize(form, organization) + class UpdateHelpSections < Decidim::Command + def initialize(form, organization, user) @form = form @organization = organization + @user = user end def call @@ -15,12 +16,25 @@ def call ActiveRecord::Base.transaction do @form.sections.each do |section| - ContextualHelpSection.set_content(@organization, section.id, section.content) + next unless content_has_changed?(section) + + Decidim.traceability.perform_action!("update", ContextualHelpSection, @user, { "resource" => { "title" => section.id.humanize } }) do + ContextualHelpSection.set_content(@organization, section.id, section.content) + ContextualHelpSection.find_by(organization: @organization, section_id: section.id) + end end end broadcast(:ok) end + + private + + def content_has_changed?(section) + return if ContextualHelpSection.find_by(organization: @organization, section_id: section.id).nil? && section.content.compact_blank.blank? + + section.content != ContextualHelpSection.find_content(@organization, section.id).except("machine_translations") + end end end end diff --git a/decidim-admin/app/commands/decidim/admin/update_newsletter.rb b/decidim-admin/app/commands/decidim/admin/update_newsletter.rb index 3c67fe24ffcb6..d21818e4f7ff8 100644 --- a/decidim-admin/app/commands/decidim/admin/update_newsletter.rb +++ b/decidim-admin/app/commands/decidim/admin/update_newsletter.rb @@ -3,7 +3,7 @@ module Decidim module Admin # Updates the newsletter given form data. - class UpdateNewsletter < Rectify::Command + class UpdateNewsletter < Decidim::Command # Initializes the command. # # newsletter - The Newsletter to update. diff --git a/decidim-admin/app/commands/decidim/admin/update_organization.rb b/decidim-admin/app/commands/decidim/admin/update_organization.rb index 8d4e6199f2a97..9ad3e34ea9030 100644 --- a/decidim-admin/app/commands/decidim/admin/update_organization.rb +++ b/decidim-admin/app/commands/decidim/admin/update_organization.rb @@ -4,7 +4,7 @@ module Decidim module Admin # A command with all the business logic for updating the current # organization. - class UpdateOrganization < Rectify::Command + class UpdateOrganization < Decidim::Command # Public: Initializes the command. # # organization - The Organization that will be updated. diff --git a/decidim-admin/app/commands/decidim/admin/update_organization_appearance.rb b/decidim-admin/app/commands/decidim/admin/update_organization_appearance.rb index c0c043bf910ab..e73fcb84cf8bc 100644 --- a/decidim-admin/app/commands/decidim/admin/update_organization_appearance.rb +++ b/decidim-admin/app/commands/decidim/admin/update_organization_appearance.rb @@ -4,7 +4,7 @@ module Decidim module Admin # A command with all the business logic for updating the current # organization appearance. - class UpdateOrganizationAppearance < Rectify::Command + class UpdateOrganizationAppearance < Decidim::Command include ::Decidim::AttachmentAttributesMethods # Public: Initializes the command. diff --git a/decidim-admin/app/commands/decidim/admin/update_organization_tos_version.rb b/decidim-admin/app/commands/decidim/admin/update_organization_tos_version.rb index ca661d88ef60b..0d5941d56f99b 100644 --- a/decidim-admin/app/commands/decidim/admin/update_organization_tos_version.rb +++ b/decidim-admin/app/commands/decidim/admin/update_organization_tos_version.rb @@ -4,7 +4,7 @@ module Decidim module Admin # A command with the business logic for updating the current # organization tos_version attribute. - class UpdateOrganizationTosVersion < Rectify::Command + class UpdateOrganizationTosVersion < Decidim::Command # Public: Initializes the command. # # organization - The Organization that will be updated. diff --git a/decidim-admin/app/commands/decidim/admin/update_resource_permissions.rb b/decidim-admin/app/commands/decidim/admin/update_resource_permissions.rb index faa01150e318b..145714887d5b4 100644 --- a/decidim-admin/app/commands/decidim/admin/update_resource_permissions.rb +++ b/decidim-admin/app/commands/decidim/admin/update_resource_permissions.rb @@ -4,7 +4,7 @@ module Decidim module Admin # This command gets called when permissions for a resource not related with # a component are updated in the admin panel. - class UpdateResourcePermissions < Rectify::Command + class UpdateResourcePermissions < Decidim::Command # Public: Initializes the command. # # form - The form from which the data in this resource comes from. @@ -40,7 +40,7 @@ def configured_permissions def update_permissions permissions = configured_permissions.inject({}) do |result, (key, value)| handlers_content = selected_handlers(value).inject({}) do |handlers_content_result, handler_key| - opts = value.authorization_handlers_options[handler_key.to_sym] + opts = value.authorization_handlers_options[handler_key.to_s] handlers_content_result.update(handler_key => opts ? { options: opts } : {}) end diff --git a/decidim-admin/app/commands/decidim/admin/update_scope.rb b/decidim-admin/app/commands/decidim/admin/update_scope.rb index d1d35b9348ee9..795b65c607745 100644 --- a/decidim-admin/app/commands/decidim/admin/update_scope.rb +++ b/decidim-admin/app/commands/decidim/admin/update_scope.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when updating a scope. - class UpdateScope < Rectify::Command + class UpdateScope < Decidim::Command # Public: Initializes the command. # # scope - The Scope to update diff --git a/decidim-admin/app/commands/decidim/admin/update_scope_type.rb b/decidim-admin/app/commands/decidim/admin/update_scope_type.rb index 48ae773b7bad0..21ac9dbfb75d9 100644 --- a/decidim-admin/app/commands/decidim/admin/update_scope_type.rb +++ b/decidim-admin/app/commands/decidim/admin/update_scope_type.rb @@ -3,14 +3,15 @@ module Decidim module Admin # A command with all the business logic when updating a scope type. - class UpdateScopeType < Rectify::Command + class UpdateScopeType < Decidim::Command # Public: Initializes the command. # # scope_type - The ScopeType to update # form - A form object with the params. - def initialize(scope_type, form) + def initialize(scope_type, form, user) @scope_type = scope_type @form = form + @user = user end # Executes the command. Broadcasts these events: @@ -31,7 +32,11 @@ def call attr_reader :form def update_scope_type - @scope_type.update!(attributes) + Decidim.traceability.update!( + @scope_type, + @user, + attributes + ) end def attributes diff --git a/decidim-admin/app/commands/decidim/admin/update_static_page.rb b/decidim-admin/app/commands/decidim/admin/update_static_page.rb index f1fa45f22b98a..f9472fa735a21 100644 --- a/decidim-admin/app/commands/decidim/admin/update_static_page.rb +++ b/decidim-admin/app/commands/decidim/admin/update_static_page.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when updating a static page. - class UpdateStaticPage < Rectify::Command + class UpdateStaticPage < Decidim::Command # Public: Initializes the command. # # page - The StaticPage to update diff --git a/decidim-admin/app/commands/decidim/admin/update_static_page_topic.rb b/decidim-admin/app/commands/decidim/admin/update_static_page_topic.rb index fc88753f3379b..30f42dbade10b 100644 --- a/decidim-admin/app/commands/decidim/admin/update_static_page_topic.rb +++ b/decidim-admin/app/commands/decidim/admin/update_static_page_topic.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when updating a static page topic. - class UpdateStaticPageTopic < Rectify::Command + class UpdateStaticPageTopic < Decidim::Command # Public: Initializes the command. # # page - The StaticPageTopic to update diff --git a/decidim-admin/app/commands/decidim/admin/update_user_groups.rb b/decidim-admin/app/commands/decidim/admin/update_user_groups.rb index cea8ec4eb886c..667e8b3d4a290 100644 --- a/decidim-admin/app/commands/decidim/admin/update_user_groups.rb +++ b/decidim-admin/app/commands/decidim/admin/update_user_groups.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when updating a usergroup. - class UpdateUserGroups < Rectify::Command + class UpdateUserGroups < Decidim::Command # Public: Initializes the command. # # scope - The Scope to update diff --git a/decidim-admin/app/commands/decidim/admin/verify_user_group.rb b/decidim-admin/app/commands/decidim/admin/verify_user_group.rb index 4c68d3f910298..e97c47e81f333 100644 --- a/decidim-admin/app/commands/decidim/admin/verify_user_group.rb +++ b/decidim-admin/app/commands/decidim/admin/verify_user_group.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A command with all the business logic when verifying a user_group. - class VerifyUserGroup < Rectify::Command + class VerifyUserGroup < Decidim::Command # Public: Initializes the command. # # user_group - The user_group to verify diff --git a/decidim-admin/app/controllers/concerns/decidim/admin/filterable.rb b/decidim-admin/app/controllers/concerns/decidim/admin/filterable.rb index a0e0a677f67c4..f462d1fbcf15f 100644 --- a/decidim-admin/app/controllers/concerns/decidim/admin/filterable.rb +++ b/decidim-admin/app/controllers/concerns/decidim/admin/filterable.rb @@ -31,7 +31,7 @@ module Filterable delegate :scopes, to: :current_organization def query - @query ||= base_query.ransack(ransack_params) + @query ||= base_query.ransack(ransack_params, search_context: :admin, auth_object: current_user) end private diff --git a/decidim-admin/app/controllers/concerns/decidim/admin/participatory_space_export.rb b/decidim-admin/app/controllers/concerns/decidim/admin/participatory_space_export.rb index 1ae5086f94744..0012b968149f1 100644 --- a/decidim-admin/app/controllers/concerns/decidim/admin/participatory_space_export.rb +++ b/decidim-admin/app/controllers/concerns/decidim/admin/participatory_space_export.rb @@ -11,7 +11,9 @@ module ParticipatorySpaceExport def create enforce_permission_to :create, :export_space, participatory_space: exportable_space - ExportParticipatorySpaceJob.perform_later(current_user, exportable_space, manifest_name, default_format) + Decidim.traceability.perform_action!("export", exportable_space, current_user) do + ExportParticipatorySpaceJob.perform_later(current_user, exportable_space, manifest_name, default_format) + end flash[:notice] = t("decidim.admin.exports.notice") diff --git a/decidim-admin/app/controllers/decidim/admin/application_controller.rb b/decidim-admin/app/controllers/decidim/admin/application_controller.rb index 1863ac08fae58..512c674ebd06d 100644 --- a/decidim-admin/app/controllers/decidim/admin/application_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/application_controller.rb @@ -6,6 +6,7 @@ module Admin class ApplicationController < ::DecidimController include NeedsOrganization include NeedsPermission + include NeedsPasswordChange include NeedsSnippets include FormFactory include LocaleSwitcher diff --git a/decidim-admin/app/controllers/decidim/admin/area_types_controller.rb b/decidim-admin/app/controllers/decidim/admin/area_types_controller.rb index 0f30eadfc003f..076ac24e5774a 100644 --- a/decidim-admin/app/controllers/decidim/admin/area_types_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/area_types_controller.rb @@ -21,7 +21,7 @@ def create enforce_permission_to :create, :area_type @form = form(AreaTypeForm).from_params(params) - CreateAreaType.call(@form) do + CreateAreaType.call(@form, current_user) do on(:ok) do flash[:notice] = I18n.t("area_types.create.success", scope: "decidim.admin") redirect_to area_types_path @@ -43,7 +43,7 @@ def update enforce_permission_to :update, :area_type, area_type: area_type @form = form(AreaTypeForm).from_params(params) - UpdateAreaType.call(area_type, @form) do + UpdateAreaType.call(area_type, @form, current_user) do on(:ok) do flash[:notice] = I18n.t("area_types.update.success", scope: "decidim.admin") redirect_to area_types_path @@ -58,7 +58,10 @@ def update def destroy enforce_permission_to :destroy, :area_type, area_type: area_type - area_type.destroy! + + Decidim.traceability.perform_action!("delete", area_type, current_user) do + area_type.destroy! + end flash[:notice] = I18n.t("area_types.destroy.success", scope: "decidim.admin") diff --git a/decidim-admin/app/controllers/decidim/admin/block_user_controller.rb b/decidim-admin/app/controllers/decidim/admin/block_user_controller.rb index e9554bd4e2b1e..4f3a282c21715 100644 --- a/decidim-admin/app/controllers/decidim/admin/block_user_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/block_user_controller.rb @@ -21,7 +21,7 @@ def create BlockUser.call(@form) do on(:ok) do flash[:notice] = I18n.t("officializations.block.success", scope: "decidim.admin") - redirect_to officializations_path(q: { name_or_nickname_or_email_cont: user.name }), notice: notice + redirect_to moderated_users_path(blocked: true) end on(:invalid) do @@ -44,13 +44,13 @@ def destroy end end - redirect_to officializations_path(q: { name_or_nickname_or_email_cont: user.name }), notice: notice + redirect_to moderated_users_path(blocked: false) end private def user - @user ||= Decidim::User.find_by( + @user ||= Decidim::UserBaseEntity.find_by( id: params[:user_id], organization: current_organization ) diff --git a/decidim-admin/app/controllers/decidim/admin/categories_controller.rb b/decidim-admin/app/controllers/decidim/admin/categories_controller.rb index fbb7148c819e3..91fc880ccb648 100644 --- a/decidim-admin/app/controllers/decidim/admin/categories_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/categories_controller.rb @@ -21,7 +21,7 @@ def create enforce_permission_to :create, :category @form = form(CategoryForm).from_params(params, current_participatory_space: current_participatory_space) - CreateCategory.call(@form, current_participatory_space) do + CreateCategory.call(@form, current_participatory_space, current_user) do on(:ok) do flash[:notice] = I18n.t("categories.create.success", scope: "decidim.admin") redirect_to categories_path(current_participatory_space) @@ -45,7 +45,7 @@ def update enforce_permission_to :update, :category, category: @category @form = form(CategoryForm).from_params(params, current_participatory_space: current_participatory_space) - UpdateCategory.call(@category, @form) do + UpdateCategory.call(@category, @form, current_user) do on(:ok) do flash[:notice] = I18n.t("categories.update.success", scope: "decidim.admin") redirect_to categories_path(current_participatory_space) @@ -67,7 +67,7 @@ def destroy @category = collection.find(params[:id]) enforce_permission_to :destroy, :category, category: @category - DestroyCategory.call(@category) do + DestroyCategory.call(@category, current_user) do on(:ok) do flash[:notice] = I18n.t("categories.destroy.success", scope: "decidim.admin") end diff --git a/decidim-admin/app/controllers/decidim/admin/component_permissions_controller.rb b/decidim-admin/app/controllers/decidim/admin/component_permissions_controller.rb index 2ba502e6bc574..5ec9c72d4b00a 100644 --- a/decidim-admin/app/controllers/decidim/admin/component_permissions_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/component_permissions_controller.rb @@ -20,7 +20,7 @@ def update enforce_permission_to :update, :component, component: component @permissions_form = PermissionsForm.from_params(params) - UpdateComponentPermissions.call(@permissions_form, component, resource) do + UpdateComponentPermissions.call(@permissions_form, component, resource, current_user) do on(:ok) do flash[:notice] = t("component_permissions.update.success", scope: "decidim.admin") redirect_to return_path diff --git a/decidim-admin/app/controllers/decidim/admin/components/base_controller.rb b/decidim-admin/app/controllers/decidim/admin/components/base_controller.rb index 2e3313fddfa67..66f5129f662c6 100644 --- a/decidim-admin/app/controllers/decidim/admin/components/base_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/components/base_controller.rb @@ -15,6 +15,7 @@ class BaseController < Decidim::Admin::ApplicationController helper Decidim::ResourceHelper helper Decidim::Admin::ExportsHelper helper Decidim::Admin::ImportsHelper + helper Decidim::Admin::RemindersHelper helper Decidim::Admin::BulkActionsHelper helper Decidim::Admin::ResourcePermissionsHelper diff --git a/decidim-admin/app/controllers/decidim/admin/components_controller.rb b/decidim-admin/app/controllers/decidim/admin/components_controller.rb index da6a071e112f7..09b7134477bfa 100644 --- a/decidim-admin/app/controllers/decidim/admin/components_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/components_controller.rb @@ -58,7 +58,7 @@ def update @form = form(@component.form_class).from_params(component_params) enforce_permission_to :update, :component, component: @component - UpdateComponent.call(@form, @component) do + UpdateComponent.call(@form, @component, current_user) do on(:ok) do |settings_changed, previous_settings, current_settings| handle_component_settings_change(previous_settings, current_settings) if settings_changed diff --git a/decidim-admin/app/controllers/decidim/admin/concerns/has_attachment_collections.rb b/decidim-admin/app/controllers/decidim/admin/concerns/has_attachment_collections.rb index 6e3bd70a84ed0..f9374e796ef56 100644 --- a/decidim-admin/app/controllers/decidim/admin/concerns/has_attachment_collections.rb +++ b/decidim-admin/app/controllers/decidim/admin/concerns/has_attachment_collections.rb @@ -31,7 +31,7 @@ def create enforce_permission_to :create, :attachment_collection @form = form(AttachmentCollectionForm).from_params(params, collection_for: collection_for) - CreateAttachmentCollection.call(@form, collection_for) do + CreateAttachmentCollection.call(@form, collection_for, current_user) do on(:ok) do flash[:notice] = I18n.t("attachment_collections.create.success", scope: "decidim.admin") redirect_to action: :index @@ -56,7 +56,7 @@ def update enforce_permission_to :update, :attachment_collection, attachment_collection: @attachment_collection @form = form(AttachmentCollectionForm).from_params(params, collection_for: collection_for) - UpdateAttachmentCollection.call(@attachment_collection, @form) do + UpdateAttachmentCollection.call(@attachment_collection, @form, current_user) do on(:ok) do flash[:notice] = I18n.t("attachment_collections.update.success", scope: "decidim.admin") redirect_to action: :index @@ -78,7 +78,10 @@ def show def destroy @attachment_collection = collection.find(params[:id]) enforce_permission_to :destroy, :attachment_collection, attachment_collection: @attachment_collection - @attachment_collection.destroy! + + Decidim.traceability.perform_action!("delete", @attachment_collection, current_user) do + @attachment_collection.destroy! + end flash[:notice] = I18n.t("attachment_collections.destroy.success", scope: "decidim.admin") diff --git a/decidim-admin/app/controllers/decidim/admin/concerns/has_attachments.rb b/decidim-admin/app/controllers/decidim/admin/concerns/has_attachments.rb index 98089b682118b..71d01c3628d56 100644 --- a/decidim-admin/app/controllers/decidim/admin/concerns/has_attachments.rb +++ b/decidim-admin/app/controllers/decidim/admin/concerns/has_attachments.rb @@ -31,7 +31,7 @@ def create enforce_permission_to :create, :attachment, attached_to: attached_to @form = form(::Decidim::Admin::AttachmentForm).from_params(params, attached_to: attached_to) - CreateAttachment.call(@form, attached_to) do + CreateAttachment.call(@form, attached_to, current_user) do on(:ok) do flash[:notice] = I18n.t("attachments.create.success", scope: "decidim.admin") redirect_to action: :index @@ -56,7 +56,7 @@ def update enforce_permission_to :update, :attachment, attachment: attachment @form = form(::Decidim::Admin::AttachmentForm).from_params(attachment_params, attached_to: attached_to) - UpdateAttachment.call(@attachment, @form) do + UpdateAttachment.call(@attachment, @form, current_user) do on(:ok) do flash[:notice] = I18n.t("attachments.update.success", scope: "decidim.admin") redirect_to action: :index @@ -78,7 +78,10 @@ def show def destroy @attachment = collection.find(params[:id]) enforce_permission_to :destroy, :attachment, attachment: attachment - @attachment.destroy! + + Decidim.traceability.perform_action!("delete", @attachment, current_user) do + @attachment.destroy! + end flash[:notice] = I18n.t("attachments.destroy.success", scope: "decidim.admin") diff --git a/decidim-admin/app/controllers/decidim/admin/concerns/has_private_users_csv_import.rb b/decidim-admin/app/controllers/decidim/admin/concerns/has_private_users_csv_import.rb index 1538fae9061ed..ba85559e2d84b 100644 --- a/decidim-admin/app/controllers/decidim/admin/concerns/has_private_users_csv_import.rb +++ b/decidim-admin/app/controllers/decidim/admin/concerns/has_private_users_csv_import.rb @@ -18,6 +18,7 @@ module HasPrivateUsersCsvImport def new enforce_permission_to :csv_import, :space_private_user @form = form(ParticipatorySpacePrivateUserCsvImportForm).from_params({}, privatable_to: privatable_to) + @count = Decidim::ParticipatorySpacePrivateUser.by_participatory_space(privatable_to).count render template: "decidim/admin/participatory_space_private_users_csv_imports/new" end @@ -38,6 +39,12 @@ def create end end + def destroy_all + enforce_permission_to :csv_import, :space_private_user + Decidim::ParticipatorySpacePrivateUser.by_participatory_space(privatable_to).delete_all + redirect_to new_participatory_space_private_users_csv_imports_path + end + # Public: Returns a String or Object that will be passed to `redirect_to` after # importing private users. By default it redirects to the privatable_to. # diff --git a/decidim-admin/app/controllers/decidim/admin/dashboard_controller.rb b/decidim-admin/app/controllers/decidim/admin/dashboard_controller.rb index 9402a0c3c4864..f3112ebebf7b6 100644 --- a/decidim-admin/app/controllers/decidim/admin/dashboard_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/dashboard_controller.rb @@ -27,7 +27,8 @@ def latest_action_logs def metrics_presenter @metrics_presenter ||= Decidim::Admin::DashboardMetricChartsPresenter.new( summary: true, - organization: current_organization + organization: current_organization, + view_context: view_context ) end @@ -37,10 +38,10 @@ def users_counter last_month = Time.zone.today.prev_month { - total_admins_last_24: users_count(last_day, true), + total_admins_last_day: users_count(last_day, true), total_admins_last_week: users_count(last_week, true), total_admins_last_month: users_count(last_month, true), - total_participants_last_24: users_count(last_day, false), + total_participants_last_day: users_count(last_day, false), total_participants_last_week: users_count(last_week, false), total_participants_last_month: users_count(last_month, false) } diff --git a/decidim-admin/app/controllers/decidim/admin/exports_controller.rb b/decidim-admin/app/controllers/decidim/admin/exports_controller.rb index b669293837fcc..069df07976239 100644 --- a/decidim-admin/app/controllers/decidim/admin/exports_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/exports_controller.rb @@ -9,7 +9,10 @@ class ExportsController < Decidim::Admin::ApplicationController def create enforce_permission_to :export, :component_data, component: component name = params[:id] - ExportJob.perform_later(current_user, component, name, params[:format] || default_format, params[:resource_id].presence) + + Decidim.traceability.perform_action!("export_component", component, current_user, { name: name, format: params[:format] || default_format }) do + ExportJob.perform_later(current_user, component, name, params[:format] || default_format, params[:resource_id].presence) + end flash[:notice] = t("decidim.admin.exports.notice") diff --git a/decidim-admin/app/controllers/decidim/admin/help_sections_controller.rb b/decidim-admin/app/controllers/decidim/admin/help_sections_controller.rb index a55185867ade8..f16c9d6268c70 100644 --- a/decidim-admin/app/controllers/decidim/admin/help_sections_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/help_sections_controller.rb @@ -25,7 +25,7 @@ def update params[:help_sections] ) - UpdateHelpSections.call(@form, current_organization) do + UpdateHelpSections.call(@form, current_organization, current_user) do on(:ok) do flash[:notice] = t("help_sections.success", scope: "decidim.admin") redirect_to action: :show diff --git a/decidim-admin/app/controllers/decidim/admin/metrics_controller.rb b/decidim-admin/app/controllers/decidim/admin/metrics_controller.rb index ae57abb8a67dc..8fc6154509869 100644 --- a/decidim-admin/app/controllers/decidim/admin/metrics_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/metrics_controller.rb @@ -14,7 +14,8 @@ def index def metrics_presenter @metrics_presenter ||= Decidim::Admin::DashboardMetricChartsPresenter.new( summary: false, - organization: current_organization + organization: current_organization, + view_context: view_context ) end end diff --git a/decidim-admin/app/controllers/decidim/admin/moderations_controller.rb b/decidim-admin/app/controllers/decidim/admin/moderations_controller.rb index 048f46a2307c2..b7cb95b2f7df6 100644 --- a/decidim-admin/app/controllers/decidim/admin/moderations_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/moderations_controller.rb @@ -67,16 +67,18 @@ def unhide private + def ransack_params + query_params[:q] || { s: "created_at desc" } + end + # Private: This method is used by the `Filterable` concern as the base query # without applying filtering and/or sorting options. def collection - @collection ||= begin - if params[:hidden] - participatory_space_moderations.hidden - else - participatory_space_moderations.not_hidden - end - end + @collection ||= if params[:hidden] + participatory_space_moderations.hidden + else + participatory_space_moderations.not_hidden + end end # Private: Returns a collection of `Moderation` filtered and/or sorted by diff --git a/decidim-admin/app/controllers/decidim/admin/newsletter_templates_controller.rb b/decidim-admin/app/controllers/decidim/admin/newsletter_templates_controller.rb index fb3bc271df601..ec717d5f41a67 100644 --- a/decidim-admin/app/controllers/decidim/admin/newsletter_templates_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/newsletter_templates_controller.rb @@ -15,7 +15,7 @@ def index def show; end def preview - email = NewsletterMailer.newsletter(current_user, fake_newsletter) + email = NewsletterMailer.newsletter(current_user, fake_newsletter, preview: true) Premailer::Rails::Hook.perform(email) render html: email.html_part.body.decoded.html_safe end diff --git a/decidim-admin/app/controllers/decidim/admin/newsletters_controller.rb b/decidim-admin/app/controllers/decidim/admin/newsletters_controller.rb index 8ffbc5f9e9701..0c157ac40660b 100644 --- a/decidim-admin/app/controllers/decidim/admin/newsletters_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/newsletters_controller.rb @@ -28,7 +28,7 @@ def show def preview enforce_permission_to :read, :newsletter, newsletter: newsletter - email = NewsletterMailer.newsletter(current_user, newsletter) + email = NewsletterMailer.newsletter(current_user, newsletter, preview: true) Premailer::Rails::Hook.perform(email) render html: email.html_part.body.decoded.html_safe end diff --git a/decidim-admin/app/controllers/decidim/admin/organization_external_domain_whitelist_controller.rb b/decidim-admin/app/controllers/decidim/admin/organization_external_domain_whitelist_controller.rb index 1bc833673808b..da541cb443697 100644 --- a/decidim-admin/app/controllers/decidim/admin/organization_external_domain_whitelist_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/organization_external_domain_whitelist_controller.rb @@ -16,7 +16,7 @@ def update enforce_permission_to :update, :organization, organization: current_organization @form = form(OrganizationExternalDomainWhitelistForm).from_params(params) - UpdateExternalDomainWhitelist.call(@form, current_organization) do + UpdateExternalDomainWhitelist.call(@form, current_organization, current_user) do on(:ok) do flash[:notice] = t("domain_whitelist.update.success", scope: "decidim.admin") redirect_to edit_organization_external_domain_whitelist_path diff --git a/decidim-admin/app/controllers/decidim/admin/reminders_controller.rb b/decidim-admin/app/controllers/decidim/admin/reminders_controller.rb new file mode 100644 index 0000000000000..57b5065810788 --- /dev/null +++ b/decidim-admin/app/controllers/decidim/admin/reminders_controller.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +module Decidim + module Admin + class RemindersController < Admin::ApplicationController + include Decidim::ComponentPathHelper + + helper_method :reminder_manifest + + def new + enforce_permission_to :create, :reminder + + @form = reminder_form_from_params(name: reminder_manifest.name) + render :new + end + + def create + enforce_permission_to :create, :reminder + + @form = reminder_form_from_params(params) + + command_class.call(@form) do + on(:ok) do |reminders_queued| + flash[:notice] = t("decidim.admin.reminders.create.success", count: reminders_queued) + redirect_to manage_component_path(current_component) + end + + on(:invalid) do + flash.now[:alert] = t("decidim.admin.reminders.create.error") + render :new + end + end + end + + private + + def reminder_form_from_params(params) + form(reminder_manifest.form_class).from_params( + params, + current_component: current_component + ) + end + + def reminder_manifest + @reminder_manifest ||= Decidim.reminders_registry.for(reminder_name) + end + + def reminder_name + params[:name] + end + + def command_class + reminder_manifest.command_class + end + + def current_component + @current_component ||= current_participatory_space.components.find(params[:component_id]) + end + end + end +end diff --git a/decidim-admin/app/controllers/decidim/admin/resource_permissions_controller.rb b/decidim-admin/app/controllers/decidim/admin/resource_permissions_controller.rb index 28a9cca29803b..8a496f9cf419b 100644 --- a/decidim-admin/app/controllers/decidim/admin/resource_permissions_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/resource_permissions_controller.rb @@ -47,8 +47,8 @@ def resource_symbol def permission_forms actions.inject({}) do |result, action| form = PermissionForm.new( - authorization_handlers: authorizations_for(action), - authorizations_handlers_options: options_for(action) + authorization_handlers: authorizations_for(action).keys, + authorization_handlers_options: options_for(action) ) result.update(action => form) diff --git a/decidim-admin/app/controllers/decidim/admin/scope_types_controller.rb b/decidim-admin/app/controllers/decidim/admin/scope_types_controller.rb index d1d8ec4fa18c3..dbbf09921ccc4 100644 --- a/decidim-admin/app/controllers/decidim/admin/scope_types_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/scope_types_controller.rb @@ -21,7 +21,7 @@ def create enforce_permission_to :create, :scope_type @form = form(ScopeTypeForm).from_params(params) - CreateScopeType.call(@form) do + CreateScopeType.call(@form, current_user) do on(:ok) do flash[:notice] = I18n.t("scope_types.create.success", scope: "decidim.admin") redirect_to scope_types_path @@ -43,7 +43,7 @@ def update enforce_permission_to :update, :scope_type, scope_type: scope_type @form = form(ScopeTypeForm).from_params(params) - UpdateScopeType.call(scope_type, @form) do + UpdateScopeType.call(scope_type, @form, current_user) do on(:ok) do flash[:notice] = I18n.t("scope_types.update.success", scope: "decidim.admin") redirect_to scope_types_path @@ -58,7 +58,10 @@ def update def destroy enforce_permission_to :destroy, :scope_type, scope_type: scope_type - scope_type.destroy! + + Decidim.traceability.perform_action!("delete", scope_type, current_user) do + scope_type.destroy! + end flash[:notice] = I18n.t("scope_types.destroy.success", scope: "decidim.admin") diff --git a/decidim-admin/app/controllers/decidim/admin/static_pages_controller.rb b/decidim-admin/app/controllers/decidim/admin/static_pages_controller.rb index 4966283313470..21976e00938ec 100644 --- a/decidim-admin/app/controllers/decidim/admin/static_pages_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/static_pages_controller.rb @@ -82,13 +82,7 @@ def form_params form_params = params.to_unsafe_hash form_params["static_page"] ||= {} form_params["static_page"]["organization"] = current_organization - form_params["static_page"]["allow_public_access"] ||= begin - if page - page.allow_public_access - else - false - end - end + form_params["static_page"]["allow_public_access"] ||= page ? page.allow_public_access : false return form_params unless page diff --git a/decidim-admin/app/forms/decidim/admin/block_user_form.rb b/decidim-admin/app/forms/decidim/admin/block_user_form.rb index 451ffcac30e5a..f43e92fa8b7e2 100644 --- a/decidim-admin/app/forms/decidim/admin/block_user_form.rb +++ b/decidim-admin/app/forms/decidim/admin/block_user_form.rb @@ -2,7 +2,7 @@ module Decidim module Admin - # A form object used to officialize users from the admin dashboard. + # A form object used to block users or user groups on the admin dashboard. class BlockUserForm < Form attribute :user_id, Integer attribute :justification, String @@ -15,7 +15,7 @@ def map_model(user) end def user - @user ||= Decidim::User.find_by( + @user ||= Decidim::UserBaseEntity.find_by( id: user_id, organization: current_organization ) diff --git a/decidim-admin/app/forms/decidim/admin/category_form.rb b/decidim-admin/app/forms/decidim/admin/category_form.rb index 7819ace8f3162..597b4716126ee 100644 --- a/decidim-admin/app/forms/decidim/admin/category_form.rb +++ b/decidim-admin/app/forms/decidim/admin/category_form.rb @@ -9,12 +9,11 @@ class CategoryForm < Form translatable_attribute :name, String attribute :weight, Integer, default: 0 - translatable_attribute :description, String attribute :parent_id, Integer mimic :category - validates :name, :description, translatable_presence: true + validates :name, translatable_presence: true validates :parent_id, inclusion: { in: :parent_categories_ids }, allow_blank: true delegate :current_participatory_space, to: :context, prefix: false diff --git a/decidim-admin/app/forms/decidim/admin/component_form.rb b/decidim-admin/app/forms/decidim/admin/component_form.rb index 8ad8cd2f62fde..aabd19fc23574 100644 --- a/decidim-admin/app/forms/decidim/admin/component_form.rb +++ b/decidim-admin/app/forms/decidim/admin/component_form.rb @@ -21,10 +21,12 @@ class ComponentForm < Decidim::Form attribute :settings, Object attribute :default_step_settings, Object - attribute :step_settings, Hash[String => Object] + attribute(:step_settings, { String => Object }) attribute :share_tokens, Array[ShareToken] + validate :validate_settings, :validate_step_settings + def settings? settings.manifest.attributes.any? end @@ -39,13 +41,20 @@ def map_model(model) private - # Overwrites Rectify::Form#form_attributes_valid? to validate nested `step_settings` attributes. - def form_attributes_valid? - return false unless errors.empty? && settings_errors_empty? # Preserves errors from custom validation methods + def validate_settings + return unless errors.empty? && settings_errors_empty? # Preserves errors from custom validation methods + + attributes.each do |key, value| + next unless value.respond_to?(:valid?) + + errors.add(key, :invalid) unless value.valid? + end + end + + def validate_step_settings + return unless step_settings.respond_to?(:attributes) - attributes_that_respond_to(:valid?).concat( - step_settings.each_value.select { |attribute| attribute.respond_to?(:valid?) } - ).all?(&:valid?) + errors.add(:step_settings, :invalid) unless step_settings.attributes.values.all? { |v| !v.respond_to?(:valid?) || v.valid? } end def settings_errors_empty? diff --git a/decidim-admin/app/forms/decidim/admin/import_example_form.rb b/decidim-admin/app/forms/decidim/admin/import_example_form.rb index bcece5da6b487..fb56a41b7fea6 100644 --- a/decidim-admin/app/forms/decidim/admin/import_example_form.rb +++ b/decidim-admin/app/forms/decidim/admin/import_example_form.rb @@ -35,11 +35,7 @@ def example_data end def reader - @reader ||= begin - return unless reader_klass - - reader_klass.new("/dev/null") - end + @reader ||= reader_klass ? reader_klass.new("/dev/null") : nil end def reader_klass diff --git a/decidim-admin/app/forms/decidim/admin/import_form.rb b/decidim-admin/app/forms/decidim/admin/import_form.rb index 6181657402f85..5ab5f44803e59 100644 --- a/decidim-admin/app/forms/decidim/admin/import_form.rb +++ b/decidim-admin/app/forms/decidim/admin/import_form.rb @@ -5,9 +5,10 @@ module Admin class ImportForm < Form ACCEPTED_MIME_TYPES = Decidim::Admin::Import::Readers::ACCEPTED_MIME_TYPES include Decidim::HasUploadValidations + include Decidim::ProcessesFileLocally attribute :name, String - attribute :file + attribute :file, Decidim::Attributes::Blob validates :file, presence: true validates :name, presence: true @@ -16,7 +17,7 @@ class ImportForm < Form validate :verify_import, if: -> { file.present? && accepted_mime_type? && !importer.invalid_file? } def importer - @importer ||= importer_for(file_path, mime_type) + @importer ||= importer_for(file, mime_type) end private @@ -44,15 +45,11 @@ def check_invalid_file def verify_import return if importer.verify - importer.errors.each do |_col, message| - errors.add(:file, message) + importer.errors.each do |error| + errors.add(:file, error.message) end end - def file_path - file&.path - end - def mime_type file&.content_type end @@ -61,9 +58,9 @@ def creator_class manifest.creator end - def importer_for(filepath, mime_type) + def importer_for(path, mime_type) Import::ImporterFactory.build( - filepath, + path, mime_type, context: importer_context, creator: creator_class diff --git a/decidim-admin/app/forms/decidim/admin/managed_user_promotion_form.rb b/decidim-admin/app/forms/decidim/admin/managed_user_promotion_form.rb index 5ead30aaf6d11..d6fdc01a0277b 100644 --- a/decidim-admin/app/forms/decidim/admin/managed_user_promotion_form.rb +++ b/decidim-admin/app/forms/decidim/admin/managed_user_promotion_form.rb @@ -7,7 +7,7 @@ module Admin class ManagedUserPromotionForm < Form attribute :email, String - validates :email, presence: true, 'valid_email_2/email': { disposable: true } + validates :email, presence: true, "valid_email_2/email": { disposable: true } validate :unique_email private diff --git a/decidim-admin/app/forms/decidim/admin/participatory_space_private_user_csv_import_form.rb b/decidim-admin/app/forms/decidim/admin/participatory_space_private_user_csv_import_form.rb index 9cf8fd11d1fe5..94a3ba9d00919 100644 --- a/decidim-admin/app/forms/decidim/admin/participatory_space_private_user_csv_import_form.rb +++ b/decidim-admin/app/forms/decidim/admin/participatory_space_private_user_csv_import_form.rb @@ -8,20 +8,25 @@ module Admin # class ParticipatorySpacePrivateUserCsvImportForm < Form include Decidim::HasUploadValidations + include Decidim::ProcessesFileLocally - attribute :file + attribute :file, Decidim::Attributes::Blob attribute :user_name, String attribute :email, String - validates :file, presence: true + validates :file, presence: true, file_content_type: { allow: ["text/csv"] } validate :validate_csv def validate_csv return if file.blank? - CSV.foreach(file.path) do |_email, user_name| - errors.add(:user_name, :invalid) unless user_name.match?(UserBaseEntity::REGEXP_NAME) + process_file_locally(file) do |file_path| + CSV.foreach(file_path, encoding: "BOM|UTF-8") do |_email, user_name| + errors.add(:user_name, :invalid) unless user_name.match?(UserBaseEntity::REGEXP_NAME) + end end + rescue CSV::MalformedCSVError + errors.add(:file, :malformed) end end end diff --git a/decidim-admin/app/forms/decidim/admin/permission_form.rb b/decidim-admin/app/forms/decidim/admin/permission_form.rb index cf3e75febf591..bc1daf32956b9 100644 --- a/decidim-admin/app/forms/decidim/admin/permission_form.rb +++ b/decidim-admin/app/forms/decidim/admin/permission_form.rb @@ -4,15 +4,21 @@ module Decidim module Admin # This form handles permissions for a particular action in the admin panel. class PermissionForm < Form - attribute :authorization_handlers, Hash - attribute :authorization_handlers_options, Hash + attribute :authorization_handlers, Array[String] + attribute(:authorization_handlers_options, { String => Object }) + + def authorization_handlers + handlers = super || [] + + handlers.index_with { |name| { "options" => authorization_handler_options(name) } } + end def authorization_handlers_names authorization_handlers.keys.map(&:to_s) end def authorization_handler_options(handler_name) - find_handler(handler_name)&.dig("options") || {} + authorization_handlers_options&.dig(handler_name.to_s) || {} end def manifest(handler_name) @@ -33,11 +39,6 @@ def options_attributes(handler_name) def options_manifest(handler_name) manifest(handler_name).options end - - def find_handler(handler_name) - authorization_handlers[handler_name.to_s] || - authorization_handlers[handler_name.to_sym] - end end end end diff --git a/decidim-admin/app/forms/decidim/admin/permissions_form.rb b/decidim-admin/app/forms/decidim/admin/permissions_form.rb index 8094f3de9ec40..e4d9b6837fa6e 100644 --- a/decidim-admin/app/forms/decidim/admin/permissions_form.rb +++ b/decidim-admin/app/forms/decidim/admin/permissions_form.rb @@ -7,16 +7,7 @@ module Admin class PermissionsForm < Form mimic :component_permissions - attribute :permissions, Hash[String => PermissionForm] - - private - - # Overriding Rectify::Form#form_attributes_valid? to preserve errors from custom method validations. - def form_attributes_valid? - return false unless errors.empty? && permissions.each_value.map(&:errors).all?(&:empty?) - - super && permissions.values.all?(&:valid?) - end + attribute(:permissions, { String => PermissionForm }) end end end diff --git a/decidim-admin/app/forms/decidim/admin/user_group_csv_verification_form.rb b/decidim-admin/app/forms/decidim/admin/user_group_csv_verification_form.rb index 208314ec5b04f..25d2add0ce8c8 100644 --- a/decidim-admin/app/forms/decidim/admin/user_group_csv_verification_form.rb +++ b/decidim-admin/app/forms/decidim/admin/user_group_csv_verification_form.rb @@ -6,10 +6,20 @@ module Admin # class UserGroupCsvVerificationForm < Form include Decidim::HasUploadValidations + include Decidim::ProcessesFileLocally - attribute :file + attribute :file, Decidim::Attributes::Blob - validates :file, presence: true + validates :file, presence: true, file_content_type: { allow: ["text/csv"] } + validate :validate_csv, unless: ->(f) { f.file.blank? } + + def validate_csv + process_file_locally(file) do |file_path| + CSV.open(file_path, &:readline) + end + rescue CSV::MalformedCSVError + errors.add(:file, :malformed) + end end end end diff --git a/decidim-admin/app/helpers/decidim/admin/bulk_actions_helper.rb b/decidim-admin/app/helpers/decidim/admin/bulk_actions_helper.rb index a71ec2694802c..1c37e77664e57 100644 --- a/decidim-admin/app/helpers/decidim/admin/bulk_actions_helper.rb +++ b/decidim-admin/app/helpers/decidim/admin/bulk_actions_helper.rb @@ -3,10 +3,6 @@ module Decidim module Admin module BulkActionsHelper - def proposal_find(id) - Decidim::Proposals::Proposal.find(id) - end - # Public: Generates a select field with the categories. Only leaf categories can be set as selected. # # categories - A collection of categories. @@ -14,9 +10,8 @@ def proposal_find(id) # Returns a String. def bulk_categories_select(collection) categories = bulk_categories_for_select collection - disabled = bulk_disabled_categories_for collection prompt = t("decidim.proposals.admin.proposals.index.change_category") - select(:category, :id, options_for_select(categories, selected: [], disabled: disabled), prompt: prompt) + select(:category, :id, options_for_select(categories, selected: []), prompt: prompt) end def bulk_categories_for_select(scope) @@ -39,10 +34,6 @@ def bulk_categories_for_select(scope) end end - def bulk_disabled_categories_for(scope) - scope.first_class.joins(:subcategories).pluck(:id) - end - # Public: Generates a select field with the components. # # siblings - A collection of components. diff --git a/decidim-admin/app/helpers/decidim/admin/moderations/reports_helper.rb b/decidim-admin/app/helpers/decidim/admin/moderations/reports_helper.rb index b91df789ccd73..1df398f1d3df9 100644 --- a/decidim-admin/app/helpers/decidim/admin/moderations/reports_helper.rb +++ b/decidim-admin/app/helpers/decidim/admin/moderations/reports_helper.rb @@ -6,22 +6,31 @@ module Moderations # This module includes helpers to show moderation reports in admin module ReportsHelper include Decidim::Messaging::ConversationHelper + include Decidim::ResourceHelper + include Decidim::TranslationsHelper # Public: Returns the reportable's author names separated by commas. def reportable_author_name(reportable) reportable_authors = reportable.try(:authors) || [reportable.try(:normalized_author)] content_tag :ul, class: "reportable-authors" do reportable_authors.select(&:present?).map do |author| - if author.is_a? User + case author + when User content_tag :li do link_to current_or_new_conversation_path_with(author), target: "_blank", rel: "noopener" do "#{author.name} #{icon "envelope-closed"}".html_safe end end + when Decidim::Meetings::Meeting + content_tag :li do + link_to resource_locator(author).path, target: "_blank", rel: "noopener" do + translated_attribute(author.title) + end + end else content_tag(:li, author.name) end - end.join("").html_safe + end.join.html_safe end end diff --git a/decidim-admin/app/helpers/decidim/admin/reminders_helper.rb b/decidim-admin/app/helpers/decidim/admin/reminders_helper.rb new file mode 100644 index 0000000000000..8963daf4f8394 --- /dev/null +++ b/decidim-admin/app/helpers/decidim/admin/reminders_helper.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Decidim + module Admin + module RemindersHelper + # Route to the correct reminder for a component. + def admin_reminders_path(component, options = {}) + EngineRouter.admin_proxy(component.participatory_space).new_component_reminder_path(options.merge(component_id: component)) + end + end + end +end diff --git a/decidim-admin/app/models/decidim/admin/fake_newsletter.rb b/decidim-admin/app/models/decidim/admin/fake_newsletter.rb index a3f89abbac614..3ed865f9f38d7 100644 --- a/decidim-admin/app/models/decidim/admin/fake_newsletter.rb +++ b/decidim-admin/app/models/decidim/admin/fake_newsletter.rb @@ -41,6 +41,26 @@ def sent_at nil end + def draft? + true + end + + def url(**_) + "#" + end + + def notifications_settings_url(**_) + "#" + end + + def unsubscribe_newsletters_url(**_) + "#" + end + + def organization_official_url + "#" + end + private attr_reader :organization, :manifest diff --git a/decidim-admin/app/packs/entrypoints/decidim_admin.js b/decidim-admin/app/packs/entrypoints/decidim_admin.js index 98e1bbc937461..602396fe70952 100644 --- a/decidim-admin/app/packs/entrypoints/decidim_admin.js +++ b/decidim-admin/app/packs/entrypoints/decidim_admin.js @@ -10,7 +10,6 @@ import Rails from "@rails/ujs" import "foundation-sites" import "src/decidim/vendor/foundation-datepicker" import "src/decidim/foundation_datepicker_locales" -import "jquery.autocomplete" import "jquery-serializejson" import "src/decidim/admin/tab_focus" @@ -34,6 +33,8 @@ import "src/decidim/ajax_modals" import "src/decidim/admin/officializations" import "src/decidim/session_timeouter" import "src/decidim/slug_form" +import "src/decidim/direct_uploads/upload_field" +import "src/decidim/admin/admin_autocomplete" // CSS import "entrypoints/decidim_admin.scss"; diff --git a/decidim-admin/app/packs/src/decidim/admin/admin_autocomplete.js b/decidim-admin/app/packs/src/decidim/admin/admin_autocomplete.js new file mode 100644 index 0000000000000..ef75c0bf18c63 --- /dev/null +++ b/decidim-admin/app/packs/src/decidim/admin/admin_autocomplete.js @@ -0,0 +1,86 @@ +import AutoComplete from "src/decidim/autocomplete"; + +/** + * This function can be used to create an autocomplete input automatically + * from the following kind of div: + *
+ * + * The data-autocomplete attribute should contain the following configuration + * as an encoded JSON, which is used to generate the AutoComplete options: + * - name: assembly_member[user_id], + * - options: [], + * - placeholder: "Select a participant", + * - searchURL: "http://..." + * - selected: "", + * + * @param {HTMLElement} el The element to generate the autocomplete for. + * @returns {AutoComplete} An instance of the AutoComplete class. + */ +const autoConfigure = (el) => { + const config = JSON.parse(el.dataset.autocomplete); + const searchUrl = new URL(config.searchURL); + const textInput = document.createElement("input"); + textInput.type = "text"; + textInput.className = "autocomplete-input"; + el.appendChild(textInput); + let mode = config.mode || "sticky" + let selected = null; + if (config.selected) { + switch (mode) { + case "multi": + selected = config.selected.map((item) => ( + { + key: "label", + value: { + value: item.value, + label: item.label + } + } + )); + break; + case "sticky": + selected = { key: "label", value: config.options[config.options.length - 1] }; + break; + default: + selected = config.selected; + } + } + + const dataSource = (query, callback) => { + const params = new URLSearchParams({ + ...Object.fromEntries(searchUrl.searchParams), + term: query + }); + fetch(`${searchUrl.origin}${searchUrl.pathname}?${params.toString()}`, { + method: "GET", + headers: { "Content-Type": "application/json" } + }).then((response) => response.json()).then((data) => { + callback(data) + }); + }; + + const ac = new AutoComplete(textInput, { + name: config.name, + placeholder: config.placeholder, + selected: selected, + mode: mode, + searchPrompt: true, + searchPromptText: config.searchPromptText, + threshold: 3, + dataMatchKeys: ["label"], + dataSource + }); + + return ac; +} + +$(() => { + const $autocompleteDiv = $("[data-autocomplete]"); + if ($autocompleteDiv.length < 1) { + return; + } + + $autocompleteDiv.each((_index, element) => { + autoConfigure(element); + }) +}) diff --git a/decidim-admin/app/packs/src/decidim/admin/application.js b/decidim-admin/app/packs/src/decidim/admin/application.js index e0dcba5669137..233f92b362f3c 100644 --- a/decidim-admin/app/packs/src/decidim/admin/application.js +++ b/decidim-admin/app/packs/src/decidim/admin/application.js @@ -1,13 +1,10 @@ /* eslint-disable no-invalid-this */ -import * as React from "react"; -import * as ReactDOM from "react-dom"; import toggleNav from "src/decidim/admin/toggle_nav" import createSortList from "src/decidim/admin/sort_list.component" import createQuillEditor from "src/decidim/editor" import formDatePicker from "src/decidim/form_datepicker" import DataPicker from "src/decidim/data_picker" -import Autocomplete from "src/decidim/admin/autocomplete.component"; import FormFilterComponent from "src/decidim/form_filter" import Configuration from "src/decidim/configuration" import InputCharacterCounter from "src/decidim/input_character_counter" @@ -18,17 +15,6 @@ window.Decidim.managedUsersForm = managedUsersForm window.Decidim.config = new Configuration() window.Decidim.InputCharacterCounter = InputCharacterCounter; -const renderAutocompleteSelects = (nodeSelector) => { - window.$(nodeSelector).each((index, node) => { - const props = { ...window.$(node).data("autocomplete") }; - - ReactDOM.render( - React.createElement(Autocomplete, props), - node - ); - }); -}; - $(() => { window.theDataPicker = new DataPicker($(".data-picker")); @@ -36,8 +22,6 @@ $(() => { toggleNav(); - renderAutocompleteSelects('[data-plugin="autocomplete"]'); - createSortList("#steps tbody", { placeholder: $(' ')[0], onSortUpdate: ($children) => { diff --git a/decidim-admin/app/packs/src/decidim/admin/autocomplete.component.js b/decidim-admin/app/packs/src/decidim/admin/autocomplete.component.js deleted file mode 100644 index 1a8051d965fa9..0000000000000 --- a/decidim-admin/app/packs/src/decidim/admin/autocomplete.component.js +++ /dev/null @@ -1,146 +0,0 @@ -/* eslint no-unused-vars: 0 */ -/* eslint consistent-return: 0 */ - -import axios from "axios"; -import * as React from "react"; -import { Async as AsyncSelect } from "react-select"; -import "react-select/scss/default.scss"; -import PropTypes from "prop-types"; - -export class Autocomplete extends React.Component { - constructor(props) { - super(props); - - this.minCharactersToSearch = 3; - - this.handleChange = (selectedOption) => { - this.setState({ selectedOption }); - if (this.props.changeURL) { - axios.get(this.props.changeURL, { - headers: { - Accept: "text/javascript" - }, - withCredentials: true, - params: { - id: selectedOption.value - } - }). - then((response) => { - const script = document.createElement("script"); - script.type = "text/javascript"; - script.innerHTML = response.data; - document.getElementsByTagName("head")[0].appendChild(script); - }). - catch((error) => { - if (axios.isCancel(error)) { - // console.log("Request canceled", error.message); - } - else { - // - } - }); - } - }; - - this.filterOptions = (options, filter, excludeOptions) => { - // Do no filtering, just return all options because - // we return a filtered set from server - return options; - }; - - this.onInputChange = (query) => { - if (query.length < this.minCharactersToSearch) { - this.setState({ noResultsText: this.props.searchPromptText }); - } - else { - this.setState({ noResultsText: this.props.noResultsText }); - } - }; - - this.loadOptions = (query, callback) => { - const lowerQuery = query.toLowerCase(); - - if (this.cancelTokenSource) { - this.cancelTokenSource.cancel(); - } - - if (lowerQuery.length < this.minCharactersToSearch) { - return callback(null, { options: [], complete: false }); - } - - this.cancelTokenSource = axios.CancelToken.source(); - axios.get(this.props.searchURL, { - cancelToken: this.cancelTokenSource.token, - headers: { - Accept: "application/json" - }, - withCredentials: true, - params: { - term: lowerQuery - } - }). - then((response) => { - // CAREFUL! Only set complete to true when there are no more options, - // or more specific queries will not be sent to the server. - return callback(null, { options: response.data, complete: true }); - }). - catch((error) => { - if (!axios.isCancel(error)) { - return callback(error, { options: [], complete: false }); - } - }); - }; - - this.state = { - options: props.options, - selectedOption: props.selected, - searchPromptText: props.searchPromptText, - noResultsText: props.noResultsText - }; - } - - render() { - const { autoload, name, placeholder } = this.props; - const { selectedOption, options, searchPromptText, noResultsText } = this.state; - - return ( - React.createElement("div", { className: "autocomplete-field" }, - React.createElement(AsyncSelect, { - cache: false, - name: name, - value: selectedOption, - options: options, - placeholder: placeholder, - searchPromptText: searchPromptText, - noResultsText: noResultsText, - onChange: this.handleChange, - onInputChange: this.onInputChange, - loadOptions: this.loadOptions, - filterOptions: this.filterOptions, - autoload: autoload, - removeSelected: true, - escapeClearsValue: false, - onCloseResetsInput: false - }) - ) - ); - } -} - -Autocomplete.defaultProps = { - autoload: false -}; - -Autocomplete.propTypes = { - changeURL: PropTypes.string, - searchPromptText: PropTypes.string, - noResultsText: PropTypes.string, - searchURL: PropTypes.string, - selected: PropTypes.string, - options: PropTypes.array, - autoload: PropTypes.bool, - name: PropTypes.string, - placeholder: PropTypes.string -} - -export default Autocomplete; diff --git a/decidim-admin/app/packs/src/decidim/admin/autocomplete.component.test.js b/decidim-admin/app/packs/src/decidim/admin/autocomplete.component.test.js deleted file mode 100644 index 897d1625cbb6e..0000000000000 --- a/decidim-admin/app/packs/src/decidim/admin/autocomplete.component.test.js +++ /dev/null @@ -1,19 +0,0 @@ -import { shallow } from "enzyme"; -import * as React from "react"; -import Autocomplete from "./autocomplete.component"; - -describe("", () => { - const name = "custom[name]"; - const selected = ""; - const options = []; - const placeholder = "Pick a value"; - const noResultsText = "No results found"; - const searchPromptText = "Type to search"; - const searchURL = "/some/url"; - const changeURL = "/some/other/url"; - - it("renders a div of Select", () => { - const wrapper = shallow(); - expect(wrapper.find(".autocomplete-field").exists()).toBeTruthy(); - }); -}); diff --git a/decidim-admin/app/packs/stylesheets/decidim/admin/_decidim.scss b/decidim-admin/app/packs/stylesheets/decidim/admin/_decidim.scss index 095692f42a048..049874f8addaf 100755 --- a/decidim-admin/app/packs/stylesheets/decidim/admin/_decidim.scss +++ b/decidim-admin/app/packs/stylesheets/decidim/admin/_decidim.scss @@ -17,7 +17,6 @@ @import "stylesheets/decidim/admin/modules/modules"; @import "stylesheets/decidim/admin/plugins/jquery.auto-complete"; @import "stylesheets/decidim/admin/components/accordion"; -@import "stylesheets/decidim/admin/components/autocomplete_select.component"; @import "stylesheets/decidim/admin/components/dropdown-menu"; @import "stylesheets/decidim/admin/components/sortable"; @import "stylesheets/decidim/vizzs"; diff --git a/decidim-admin/app/packs/stylesheets/decidim/admin/components/_autocomplete_select.component.scss b/decidim-admin/app/packs/stylesheets/decidim/admin/components/_autocomplete_select.component.scss deleted file mode 100644 index f1f962128396b..0000000000000 --- a/decidim-admin/app/packs/stylesheets/decidim/admin/components/_autocomplete_select.component.scss +++ /dev/null @@ -1,19 +0,0 @@ -.autocomplete-field{ - margin-bottom: 1.5rem; - - .Select{ - .Select-control, - .Select-input, - .Select-placeholder, - &.Select--single > .Select-control .Select-value{ - height: 3rem; - line-height: 3rem; - } - } -} - -.autocomplete-field--results-inline{ - .Select-menu-outer{ - position: relative; - } -} diff --git a/decidim-admin/app/packs/stylesheets/decidim/admin/extra/_quill.scss b/decidim-admin/app/packs/stylesheets/decidim/admin/extra/_quill.scss index 8c1edf137457e..df4a60e6e7989 100644 --- a/decidim-admin/app/packs/stylesheets/decidim/admin/extra/_quill.scss +++ b/decidim-admin/app/packs/stylesheets/decidim/admin/extra/_quill.scss @@ -3,3 +3,10 @@ background: #eee; } } + +.editor-container{ + ul, + ol{ + margin-bottom: 1rem; + } +} diff --git a/decidim-admin/app/packs/stylesheets/decidim/admin/modules/_autocomplete.scss b/decidim-admin/app/packs/stylesheets/decidim/admin/modules/_autocomplete.scss new file mode 100644 index 0000000000000..4c780a63d3f15 --- /dev/null +++ b/decidim-admin/app/packs/stylesheets/decidim/admin/modules/_autocomplete.scss @@ -0,0 +1,5 @@ +@import "stylesheets/decidim/modules/autocomplete"; + +.autoComplete_wrapper{ + margin-bottom: 1.5rem; +} diff --git a/decidim-admin/app/packs/stylesheets/decidim/admin/modules/_modules.scss b/decidim-admin/app/packs/stylesheets/decidim/admin/modules/_modules.scss index 9d43d857829ce..30155f9a49aa8 100644 --- a/decidim-admin/app/packs/stylesheets/decidim/admin/modules/_modules.scss +++ b/decidim-admin/app/packs/stylesheets/decidim/admin/modules/_modules.scss @@ -4,6 +4,7 @@ @import "stylesheets/decidim/admin/modules/buttons"; @import "stylesheets/decidim/admin/modules/forms"; @import "stylesheets/decidim/admin/modules/tabs"; +@import "stylesheets/decidim/admin/modules/autocomplete"; //General layout @import "stylesheets/decidim/admin/modules/layout"; @@ -30,6 +31,7 @@ @import "stylesheets/decidim/admin/modules/draggable-list"; @import "stylesheets/decidim/admin/modules/loading-spinner"; @import "stylesheets/decidim/admin/modules/reveal"; +@import "stylesheets/decidim/admin/modules/upload_modal"; // mentions__container @import "stylesheets/decidim/modules/tags"; diff --git a/decidim-admin/app/packs/stylesheets/decidim/admin/modules/_upload_modal.scss b/decidim-admin/app/packs/stylesheets/decidim/admin/modules/_upload_modal.scss new file mode 100644 index 0000000000000..0111366babae9 --- /dev/null +++ b/decidim-admin/app/packs/stylesheets/decidim/admin/modules/_upload_modal.scss @@ -0,0 +1,42 @@ +@import "stylesheets/decidim/modules/upload_modal"; + +.upload-modal{ + button{ + cursor: pointer; + } + + .upload-items{ + .upload-item-first-row{ + display: flex; + + .file-name-span{ + flex: 4 1 0; + } + + .title-container{ + flex: 3.5 1 0; + } + } + + .upload-item-second-row{ + display: flex; + + .progress-bar-wrapper{ + flex: 4 1 0; + margin-right: 1rem; + + .progress-bar-border{ + border: 1px solid map-get($foundation-palette, primary); + + .progress-bar{ + background-color: map-get($foundation-palette, primary); + } + } + } + + .remove-upload-item{ + flex: 1 1 0; + } + } + } +} diff --git a/decidim-admin/app/permissions/decidim/admin/permissions.rb b/decidim-admin/app/permissions/decidim/admin/permissions.rb index a5c4812e68e34..0ce409b22b969 100644 --- a/decidim-admin/app/permissions/decidim/admin/permissions.rb +++ b/decidim-admin/app/permissions/decidim/admin/permissions.rb @@ -29,7 +29,7 @@ def permissions read_admin_dashboard_action? apply_newsletter_permissions_for_admin! - allow! if permission_action.subject == :global_moderation && admin_terms_accepted? + apply_global_moderations_permission_for_admin! if user.admin? && admin_terms_accepted? allow! if read_admin_log_action? @@ -58,6 +58,7 @@ def permissions allow! if permission_action.subject == :static_page_topic allow! if permission_action.subject == :help_sections allow! if permission_action.subject == :share_token + allow! if permission_action.subject == :reminder end permission_action @@ -78,6 +79,23 @@ def read_admin_dashboard_action? toggle_allow(user.admin? || space_allows_admin_access_to_current_action?) end + def apply_global_moderations_permission_for_admin! + return unless admin_terms_accepted? + return unless permission_action.subject == :global_moderation + return allow! if user.admin? + + return allow! if Decidim.participatory_space_manifests.flat_map.any? do |manifest| + Decidim + .find_participatory_space_manifest(manifest.name) + .participatory_spaces + .call(user.organization)&.any? do |space| + space.respond_to?(:user_roles) && space.user_roles(:admin).where(user: user).or(space.user_roles(:moderator).where(user: user)).any? + end + end + + disallow! + end + def apply_newsletter_permissions_for_admin! return unless admin_terms_accepted? return unless permission_action.subject == :newsletter diff --git a/decidim-admin/app/presenters/decidim/admin/dashboard_metric_charts_presenter.rb b/decidim-admin/app/presenters/decidim/admin/dashboard_metric_charts_presenter.rb index 883259bbb8830..694a9cd01cb0f 100644 --- a/decidim-admin/app/presenters/decidim/admin/dashboard_metric_charts_presenter.rb +++ b/decidim-admin/app/presenters/decidim/admin/dashboard_metric_charts_presenter.rb @@ -3,7 +3,9 @@ module Decidim module Admin class DashboardMetricChartsPresenter < Decidim::MetricChartsPresenter - attribute :summary, Boolean + def summary? + __getobj__.fetch(:summary) + end def render_not_highlighted(metrics) safe_join( diff --git a/decidim-admin/app/queries/decidim/admin/active_users_counter.rb b/decidim-admin/app/queries/decidim/admin/active_users_counter.rb index 04285ed2d7f0e..111cb5dc02dc0 100644 --- a/decidim-admin/app/queries/decidim/admin/active_users_counter.rb +++ b/decidim-admin/app/queries/decidim/admin/active_users_counter.rb @@ -3,7 +3,7 @@ module Decidim module Admin # Counts active users making a distinction between whether they are admins or participants - class ActiveUsersCounter < Rectify::Query + class ActiveUsersCounter < Decidim::Query # Initializes the class. # # @param organization [Organization] Current organization diff --git a/decidim-admin/app/queries/decidim/admin/newsletter_recipients.rb b/decidim-admin/app/queries/decidim/admin/newsletter_recipients.rb index a2b8e21f78689..5bbff6f024a01 100644 --- a/decidim-admin/app/queries/decidim/admin/newsletter_recipients.rb +++ b/decidim-admin/app/queries/decidim/admin/newsletter_recipients.rb @@ -4,7 +4,7 @@ module Decidim module Admin # A class used to find the recipients of the # Newsletter depending on the params of the form - class NewsletterRecipients < Rectify::Query + class NewsletterRecipients < Decidim::Query # Syntactic sugar to initialize the class and return the queried objects. # # form - params to filter the query @@ -56,7 +56,7 @@ def spaces if type.ids.include?("all") object_class.where(organization: @organization) else - object_class.where(id: type.ids.reject(&:blank?)) + object_class.where(id: type.ids.compact_blank) end end.flatten.compact end diff --git a/decidim-admin/app/queries/decidim/admin/user_filter.rb b/decidim-admin/app/queries/decidim/admin/user_filter.rb index 9ff69a2207942..b196f70048578 100644 --- a/decidim-admin/app/queries/decidim/admin/user_filter.rb +++ b/decidim-admin/app/queries/decidim/admin/user_filter.rb @@ -4,7 +4,7 @@ module Decidim module Admin # A class used to filter users by whitelisted scope or searches on their # name - class UserFilter < Rectify::Query + class UserFilter < Decidim::Query WHITELISTED_STATE_SCOPES = %w( officialized not_officialized diff --git a/decidim-admin/app/queries/decidim/admin/user_groups_evaluation.rb b/decidim-admin/app/queries/decidim/admin/user_groups_evaluation.rb index 222b231ab2847..608415466f270 100644 --- a/decidim-admin/app/queries/decidim/admin/user_groups_evaluation.rb +++ b/decidim-admin/app/queries/decidim/admin/user_groups_evaluation.rb @@ -3,7 +3,7 @@ module Decidim module Admin # A class used to find the UserGroup's by their evaluation state. - class UserGroupsEvaluation < Rectify::Query + class UserGroupsEvaluation < Decidim::Query # Syntactic sugar to initialize the class and return the queried objects. # # user_groups - the initial User Group relation that needs to be filtered. diff --git a/decidim-admin/app/views/decidim/admin/attachments/index.html.erb b/decidim-admin/app/views/decidim/admin/attachments/index.html.erb index eb422969377a0..e85aa7c28aebc 100644 --- a/decidim-admin/app/views/decidim/admin/attachments/index.html.erb +++ b/decidim-admin/app/views/decidim/admin/attachments/index.html.erb @@ -9,6 +9,7 @@
+ <%= cell("decidim/admin/attachments_privacy_warning", attached_to.attachments) %> <% if attached_to.attachments.any? %>
diff --git a/decidim-admin/app/views/decidim/admin/categories/_form.html.erb b/decidim-admin/app/views/decidim/admin/categories/_form.html.erb index b5db23134d1a4..351c6da42efc9 100644 --- a/decidim-admin/app/views/decidim/admin/categories/_form.html.erb +++ b/decidim-admin/app/views/decidim/admin/categories/_form.html.erb @@ -12,10 +12,6 @@ <%= form.number_field :weight %> -
- <%= form.translated :editor, :description %> -
-
<%= form.label :parent_id %> <%= select :category, :parent_id, @form.parent_categories.collect { |c| [c.name[current_organization.default_locale], c.id] }, include_blank: true %> diff --git a/decidim-admin/app/views/decidim/admin/categories/show.html.erb b/decidim-admin/app/views/decidim/admin/categories/show.html.erb index 5ee8a3ba0f6d7..a1d97207dd96a 100644 --- a/decidim-admin/app/views/decidim/admin/categories/show.html.erb +++ b/decidim-admin/app/views/decidim/admin/categories/show.html.erb @@ -8,6 +8,5 @@
<%= display_for @category, - :name, - :description %> + :name %>
diff --git a/decidim-admin/app/views/decidim/admin/moderated_users/index.html.erb b/decidim-admin/app/views/decidim/admin/moderated_users/index.html.erb index d4f180e80ea3d..d76ff812e4db7 100644 --- a/decidim-admin/app/views/decidim/admin/moderated_users/index.html.erb +++ b/decidim-admin/app/views/decidim/admin/moderated_users/index.html.erb @@ -60,7 +60,7 @@
- + - +
- <% if allowed_to?(:unreport, :moderate_users) %> + <% if !moderation.user.blocked? && allowed_to?(:unreport, :moderate_users) %> <%= icon_link_to "action-undo", ignore_moderated_user_path(id: moderation), t(".actions.unreport"), class: "action-icon--unreport", method: :put %> <% end %> <% if allowed_to?(:block, :moderate_users) %> diff --git a/decidim-admin/app/views/decidim/admin/organization_appearance/form/_images.html.erb b/decidim-admin/app/views/decidim/admin/organization_appearance/form/_images.html.erb index 9ea95d472ba86..8170cda569553 100644 --- a/decidim-admin/app/views/decidim/admin/organization_appearance/form/_images.html.erb +++ b/decidim-admin/app/views/decidim/admin/organization_appearance/form/_images.html.erb @@ -14,7 +14,8 @@ <%= form.upload( :favicon, dimensions_info: current_organization.attached_uploader(:favicon).dimensions_info, - extension_allowlist: current_organization.attached_uploader(:favicon).extension_allowlist + extension_allowlist: current_organization.attached_uploader(:favicon).extension_allowlist, + help_i18n_scope: "decidim.forms.file_help.icon" ) %> @@ -22,7 +23,7 @@ <%= form.upload( :logo, dimensions_info: current_organization.attached_uploader(:logo).dimensions_info, - extension_allowlist: current_organization.attached_uploader(:favicon).extension_allowlist + extension_allowlist: current_organization.attached_uploader(:logo).extension_allowlist ) %> @@ -30,7 +31,7 @@ <%= form.upload( :official_img_header, dimensions_info: current_organization.attached_uploader(:official_img_header).dimensions_info, - extension_allowlist: current_organization.attached_uploader(:favicon).extension_allowlist + extension_allowlist: current_organization.attached_uploader(:official_img_header).extension_allowlist ) %> @@ -38,7 +39,7 @@ <%= form.upload( :official_img_footer, dimensions_info: current_organization.attached_uploader(:official_img_footer).dimensions_info, - extension_allowlist: current_organization.attached_uploader(:favicon).extension_allowlist + extension_allowlist: current_organization.attached_uploader(:official_img_footer).extension_allowlist ) %> diff --git a/decidim-admin/app/views/decidim/admin/participatory_space_private_users/index.html.erb b/decidim-admin/app/views/decidim/admin/participatory_space_private_users/index.html.erb index 78378ca138a13..34c8314e16f9b 100644 --- a/decidim-admin/app/views/decidim/admin/participatory_space_private_users/index.html.erb +++ b/decidim-admin/app/views/decidim/admin/participatory_space_private_users/index.html.erb @@ -3,7 +3,7 @@

<%= t(".title") %> <% if allowed_to? :create, :space_private_user %> - <%= link_to t(".import_via_csv"), new_participatory_space_private_users_csv_import_path, class: "button tiny button--title import" %> + <%= link_to t(".import_via_csv"), new_participatory_space_private_users_csv_imports_path, class: "button tiny button--title import" %> <%= link_to t("actions.participatory_space_private_user.new", scope: "decidim.admin"), url_for(action: :new), class: "button tiny button--title new" %> <% end %>

diff --git a/decidim-admin/app/views/decidim/admin/participatory_space_private_users_csv_imports/new.html.erb b/decidim-admin/app/views/decidim/admin/participatory_space_private_users_csv_imports/new.html.erb index 80416e46d4446..4799dfd6708cf 100644 --- a/decidim-admin/app/views/decidim/admin/participatory_space_private_users_csv_imports/new.html.erb +++ b/decidim-admin/app/views/decidim/admin/participatory_space_private_users_csv_imports/new.html.erb @@ -1,3 +1,22 @@ +
+
+

+ <%= t(".destroy.title") %> +

+
+
+ <% if @count != 0 %> +

<%= t(".destroy.explanation", count: @count) %>

+ <%= link_to t(".destroy.button"), + destroy_all_participatory_space_private_users_csv_imports_path, + method: :delete, + class: "button alert", + data: { confirm: t(".destroy.confirm") } %> + <% else %> +

<%= t(".destroy.empty") %>

+ <% end %> +
+

@@ -5,7 +24,7 @@

- <%= decidim_form_for(@form, url: participatory_space_private_users_csv_import_path, html: { class: "form" }) do |form| %> + <%= decidim_form_for(@form, url: participatory_space_private_users_csv_imports_path, html: { class: "form" }) do |form| %>

<%= t(".explanation") %>

<%= form.upload :file, optional: false %> diff --git a/decidim-admin/app/views/decidim/admin/reminders/new.html.erb b/decidim-admin/app/views/decidim/admin/reminders/new.html.erb new file mode 100644 index 0000000000000..f85d88d57cb30 --- /dev/null +++ b/decidim-admin/app/views/decidim/admin/reminders/new.html.erb @@ -0,0 +1,21 @@ +<%= decidim_form_for(@form, url: component_reminders_path(name: reminder_manifest.name), class: "form grid-container") do |form| %> +
+
+

+ <%= reminder_manifest.message(:title, count: @form.try(:reminder_amount)) %> +

+
+
+
+
+

<%= reminder_manifest.message(:description) %>

+
+
+
+
+ <%= form.submit t(".submit") %> +
+
+
+
+<% end %> diff --git a/decidim-admin/app/views/decidim/admin/shared/_gallery.html.erb b/decidim-admin/app/views/decidim/admin/shared/_gallery.html.erb index 8740c1be3ce0f..79f40bcf7cb0a 100644 --- a/decidim-admin/app/views/decidim/admin/shared/_gallery.html.erb +++ b/decidim-admin/app/views/decidim/admin/shared/_gallery.html.erb @@ -15,7 +15,12 @@ <% end %>
- <%= form.file_field :add_photos, multiple: true, label: t(".add_images") %> + <%= form.attachment :photos, + multiple: true, + label: t(".add_images"), + button_label: t(".add_images"), + button_edit_label: t(".edit_images"), + help_i18n_scope: "decidim.forms.file_help.image" %>
diff --git a/decidim-proposals/app/views/decidim/proposals/admin/proposals/_js-callout.html.erb b/decidim-admin/app/views/decidim/admin/shared/_js-callout.html.erb similarity index 100% rename from decidim-proposals/app/views/decidim/proposals/admin/proposals/_js-callout.html.erb rename to decidim-admin/app/views/decidim/admin/shared/_js-callout.html.erb diff --git a/decidim-admin/app/views/decidim/admin/users_statistics/_users_count.html.erb b/decidim-admin/app/views/decidim/admin/users_statistics/_users_count.html.erb index 175cfcdcedf49..59d822931c36d 100644 --- a/decidim-admin/app/views/decidim/admin/users_statistics/_users_count.html.erb +++ b/decidim-admin/app/views/decidim/admin/users_statistics/_users_count.html.erb @@ -24,13 +24,13 @@
<%= t(".participants") %> <%= result[:total_participants_last_month] %> <%= result[:total_participants_last_week] %><%= result[:total_participants_last_24] %><%= result[:total_participants_last_day] %>
<%= t(".admins") %> <%= result[:total_admins_last_month] %> <%= result[:total_admins_last_week] %><%= result[:total_admins_last_24] %><%= result[:total_admins_last_day] %>
diff --git a/decidim-admin/app/views/layouts/decidim/admin/_application.html.erb b/decidim-admin/app/views/layouts/decidim/admin/_application.html.erb index 353cbe54c2f34..026ede429911b 100644 --- a/decidim-admin/app/views/layouts/decidim/admin/_application.html.erb +++ b/decidim-admin/app/views/layouts/decidim/admin/_application.html.erb @@ -29,5 +29,7 @@ <%= render partial: "decidim/shared/confirm_modal" %> <%= render partial: "layouts/decidim/admin/js_configuration" %> <%= render partial: "layouts/decidim/cors" if Decidim.cors_enabled %> + + <%= snippets.display(:foot) %> diff --git a/decidim-admin/config/locales/ar.yml b/decidim-admin/config/locales/ar.yml index 20007e1e69fee..6b727c5c07542 100644 --- a/decidim-admin/config/locales/ar.yml +++ b/decidim-admin/config/locales/ar.yml @@ -1,3 +1,4 @@ +--- ar: activemodel: attributes: @@ -10,34 +11,41 @@ ar: organization: المنظمة plural: صيغة الجمع attachment: - attachment_collection_id: المجلد + attachment_collection_id: الحاÙظة description: الوص٠file: مل٠title: المÙرÙÙ‚ أو اسم الصورة + weight: موضع الطلب attachment_collection: description: الوص٠name: اسم + weight: موضع الطلب category: description: الوص٠name: اسم - parent_id: الأبوين + parent_id: الأصل + weight: موضع الطلب component: name: اسم - published_at: نشرت ÙÙŠ + published_at: نشر ÙÙŠ weight: موضع الطلب - id: هوية شخصية + external_domain: + value: القيمة + help_section: + content: المحتوى + id: المعر٠ID import: - user_group_id: إنشاء واردات Ùƒ + user_group_id: إنشاء الاستيرادات Ùƒ newsletter: - body: المحتوى + body: النص subject: الموضوع organization: admin_terms_of_use_body: نص شروط الاستخدام للمدير alert_color: تنبيه available_authorizations: التراخيص المتاحة badges_enabled: تمكين الشارات - comments_max_length: الحد الأقصى لطول التعليقات (اترك 0 لاستعمال للقيمة الاÙتراضية) - cta_button_path: دعوة إلى العمل مسار زر + comments_max_length: الحد الأقصى لطول التعليقات (اترك 0 لاستعمال القيمة الاÙتراضية) + cta_button_path: مسار زر دعوة إلى العمل call to action cta_button_text: نص زر Call To Action customize_welcome_notification: تخصيص إشعار الترحيب default_locale: اللغة الاÙتراضية @@ -153,7 +161,7 @@ ar: reject: رÙض share: مشاركة user: - new: مستخدم جديد + new: مدير جديد verify: التحقق admin_terms_of_use: accept: @@ -309,7 +317,7 @@ ar: dashboard: show: view_more_logs: عرض المزيد من السجلات - welcome: مرحبًا بكم ÙÙŠ لوحة إدارة Decidim. + welcome: أهلا بك على اللوح الإداري. domain_whitelist: form: domain_too_short: نطاق الدومين قصير جداً @@ -743,8 +751,17 @@ ar: create: invalid: حدثت مشكلة ÙÙŠ قراءة مل٠CSV. new: + destroy: + button: حذ٠جميع المشاركين الخاصين + confirm: هل أنت متأكد من أنك تريد حذ٠جميع المشاركين الخاصين؟ لا يمكن التراجع عن هذا الإجراء، ولن تتمكن من استرجاعهم. + empty: ليس لديك أي مشاركين خاصين. + explanation: لديك %{count} مشاركين خاصين. + title: حذ٠جميع المشاركين الخاصين title: حمّل مل٠CSV الخاص بك upload: حمّل + reminders: + new: + submit: إرسال resource_permissions: edit: submit: خضع @@ -789,6 +806,7 @@ ar: shared: gallery: delete_image: احذ٠الصورة + edit_images: تعديل الصورة static_page_topics: create: error: كانت هناك مشكلة ÙÙŠ إنشاء موضوع جديد. @@ -846,7 +864,7 @@ ar: static_pages: صÙحات statistics: النشاط user_groups: المجموعات - users: المشاركون + users: المدراء user_group: csv_verify: invalid: حدثت مشكلة ÙÙŠ قراءة مل٠CSV. @@ -882,7 +900,7 @@ ar: role: وظيÙØ© new: create: دعا - title: دعوة مشارك كمسؤول + title: دعوة مدير جديد users_statistics: users_count: admins: المدراء @@ -928,7 +946,7 @@ ar: report_count: عد reportable_type: النوع reported_content_url: تم الإبلاغ عن عنوان URL للمحتوى - reports: تقارير + reports: التقارير visit_url: زيارة العنوان الشبكي report: fields: @@ -941,8 +959,6 @@ ar: layouts: decidim: admin: - global_moderations: - title: Ù…Ùشر٠عام newsletters: title: النشرات الإخبارية settings: diff --git a/decidim-admin/config/locales/bg.yml b/decidim-admin/config/locales/bg.yml index 08457d22cd6b6..1c71e1142cb7f 100644 --- a/decidim-admin/config/locales/bg.yml +++ b/decidim-admin/config/locales/bg.yml @@ -1,3 +1,4 @@ +--- bg: activemodel: attributes: diff --git a/decidim-admin/config/locales/ca.yml b/decidim-admin/config/locales/ca.yml index 1808f2e23cfec..a6f3a91918f19 100644 --- a/decidim-admin/config/locales/ca.yml +++ b/decidim-admin/config/locales/ca.yml @@ -1,3 +1,4 @@ +--- ca: activemodel: attributes: @@ -14,17 +15,24 @@ ca: description: Descripció file: Arxiu title: Nom de l'adjunt o imatge + weight: Ordre de posició attachment_collection: description: Descripció name: Nom + weight: Ordre de posició category: description: Descripció name: Nom parent_id: Pare + weight: Ordre de posició component: name: Nom published_at: Publicat el weight: Ordre de posició + external_domain: + value: Valor + help_section: + content: Contingut id: ID import: user_group_id: Importar com @@ -92,6 +100,9 @@ ca: welcome_notification_body: Cos de la notificació de benvinguda welcome_notification_subject: Assumpte de la notificació de benvinguda youtube_handler: Nom d'usuària de YouTube + participatory_space_private_user: + email: Correu electrònic + name: Nom scope: code: Codi name: Nom @@ -113,6 +124,7 @@ ca: show_in_footer: Mostra al peu de pàgina slug: Nom curt d'URL title: Títol + topic_id: Assumpte weight: Ordre de posició static_page_topic: description: Descripció @@ -133,6 +145,14 @@ ca: allowed_file_content_types: Fitxer d'imatge no vàlid official_img_header: allowed_file_content_types: Fitxer d'imatge no vàlid + participatory_space_private_user_csv_import: + attributes: + file: + malformed: Arxiu d'importació mal formatat, si us plau, llegeix les instruccions curosament i assegura't que l'arxiu està codificat en UTF-8. + user_group_csv_verification: + attributes: + file: + malformed: Arxiu d'importació mal formatat, si us plau, llegeix les instruccions curosament i assegura't que l'arxiu està codificat en UTF-8. new_import: attributes: file: @@ -177,7 +197,7 @@ ca: reject: Rebutjar share: Compartir user: - new: Nou usuari + new: Nova administradora verify: Verificar admin_terms_of_use: accept: @@ -260,6 +280,8 @@ ca: update: error: S'ha produït un error en actualitzar aquest adjunt. success: Adjunt actualitzat correctament. + attachments_privacy_warning: + message: Tingues cura quan treballis amb adjunts en un espai privat. Qualsevol participant pot compartir aquest document amb tercers. autocomplete: no_results: No s'han trobat resultats search_prompt: Escriu com a mínim tres caràcters per cercar @@ -342,7 +364,7 @@ ca: dashboard: show: view_more_logs: Veure més registres - welcome: Benvinguda al tauler d'administració de Decidim. + welcome: Benvinguda al Tauler d'Aministració. domain_whitelist: form: domain_too_short: El domini és massa curt @@ -704,7 +726,7 @@ ca: select_recipients_to_deliver: all_spaces: Totes all_users_help: Envia el butlletí a tots els usuaris confimats. - confirm_deliver: Estàs segura que vols enviar aquest butlletí? Aquesta acció no es pot desfer. + confirm_deliver: Segur que vols enviar aquest butlletí? Aquesta acció no es pot desfer. deliver: Enviar butlletí followers_help: Envia el butlletí a tots els usuaris confirmats que segueixin qualsevol dels espais participatius seleccionats a la llista. none: Cap @@ -816,7 +838,7 @@ ca: inactive_content_blocks: Blocs de contingut inactiu organization_homepage_content_blocks: edit: - update: Actualitza + update: Actualitzar participatory_space_private_users: create: error: S'ha produït un error en afegir una participant privada a aquest espai de participació. @@ -835,9 +857,23 @@ ca: invalid: S'ha produït un error en llegir el fitxer CSV. success: Arxiu CSV carregat correctament, s'està enviant un missatge de correu electrònic d'invitació als participants. Pot tardar una mica. new: + destroy: + button: Esborrar totes les participants privades + confirm: Segur que vols esborrar totes les participants privades? Aquesta acció no es pot desfer, no podràs recuperar-les. + empty: No hi ha participants privades. + explanation: Hi ha %{count} participant/s privada/ades. + title: Esborrar les participants privades explanation: 'Carrega el teu arxiu CSV. Ha de tenir dues columnes amb l''adreça de correu electrònic a la primera columna i el nom a la segona (adreça electrònica, nom) dels usuaris que vulguis afegir a l''espai de participació, sense capçaleres. Evita emprar caràcter invàlids com `<>?%&^*#@()[]=+:;"{}\|` al nom d''usuari.' title: Puja el fitxer CSV upload: Carrega + reminders: + create: + error: Hi ha hagut un problema en crear els recordatoris. + success: + one: "Es recordarà a %{count} usuària." + other: "Es recordarà a %{count} usuàries." + new: + submit: Envia resource_permissions: edit: submit: Enviar @@ -895,6 +931,7 @@ ca: gallery: add_images: Afegir imatges delete_image: Esborrar la imatge + edit_images: Editar imatges gallery_legend: Afegir una galeria d'imatges (opcional) static_page_topics: create: @@ -955,7 +992,7 @@ ca: static_pages: Pàgines statistics: Activitat user_groups: Grups - users: Participants + users: Administradores user_group: csv_verify: invalid: S'ha produït un error en llegir el fitxer CSV. @@ -991,7 +1028,7 @@ ca: role: Rol new: create: Convidar - title: Convidar una participant com a administradora + title: Convidar una nova administradora users_statistics: users_count: admins: Administradores @@ -1039,14 +1076,14 @@ ca: moderation: fields: created_at: Data de creació - deleted_resource: Elimina el recurs + deleted_resource: Recurs eliminat hidden_at: Data d'ocultació participatory_space: Espai de participació report_count: Recompte reportable_id: ID reportable_type: Tipus reported_content_url: URL contingut del contingut reportat - reports: Denúncies + reports: Informes visit_url: Visiteu l'URL report: fields: diff --git a/decidim-admin/config/locales/cs.yml b/decidim-admin/config/locales/cs.yml index 525065ab8dc90..21019203ef48e 100644 --- a/decidim-admin/config/locales/cs.yml +++ b/decidim-admin/config/locales/cs.yml @@ -1,3 +1,4 @@ +--- cs: activemodel: attributes: @@ -14,17 +15,24 @@ cs: description: Popis file: Soubor title: Název přílohy nebo obrázku + weight: Pozice v Å™azení attachment_collection: description: Popis name: Název + weight: Pozice v Å™azení category: description: Popis name: Název parent_id: NadÅ™azená + weight: Pozice v Å™azení component: name: Název published_at: Publikováno v weight: Pozice v Å™azení + external_domain: + value: Hodnota + help_section: + content: Obsah id: ID import: user_group_id: VytvoÅ™it importy jako @@ -92,6 +100,9 @@ cs: welcome_notification_body: TÄ›lo uvítacího oznámení welcome_notification_subject: PÅ™edmÄ›t uvítacího oznámení youtube_handler: YouTube handler + participatory_space_private_user: + email: E-mail + name: Název scope: code: Kód name: Název @@ -113,6 +124,7 @@ cs: show_in_footer: Zobrazit v zápatí slug: URL slug title: Titul + topic_id: Téma weight: Pozice v Å™azení static_page_topic: description: Popis @@ -133,6 +145,14 @@ cs: allowed_file_content_types: Neplatný soubor s obrázkem official_img_header: allowed_file_content_types: Neplatný soubor s obrázkem + participatory_space_private_user_csv_import: + attributes: + file: + malformed: Chybný importní soubor, pÅ™eÄtÄ›te si pozornÄ› pokyny a ujistÄ›te se, že soubor je kódovaný UTF-8. + user_group_csv_verification: + attributes: + file: + malformed: Chybný importní soubor, pÅ™eÄtÄ›te si pozornÄ› pokyny a ujistÄ›te se, že soubor je kódovaný UTF-8. new_import: attributes: file: @@ -177,13 +197,14 @@ cs: reject: Odmítnout share: Sdílet user: - new: Nový uživatel + new: Nový administrátor verify: Ověřit admin_terms_of_use: accept: error: PÅ™i pÅ™ijímání správcovských podmínek použití doÅ¡lo k chybÄ›. success: SkvÄ›lé! PÅ™ijali jste administrátorské podmínky použití. actions: + accept: Souhlasím s podmínkami are_you_sure: Opravdu chcete odmítnout Podmínky použití pro správce? refuse: Odmítnout administrátorské podmínky title: Souhlasit s podmínkami používání @@ -259,6 +280,8 @@ cs: update: error: PÅ™i aktualizaci této přílohy doÅ¡lo k chybÄ›. success: Příloha byla úspěšnÄ› aktualizována. + attachments_privacy_warning: + message: BuÄte opatrní pÅ™i práci s přílohami v soukromém prostoru. Každý úÄastník by mohl sdílet tento dokument s ostatními. autocomplete: no_results: Nenalezeny žádné výsledky search_prompt: Zadejte nejménÄ› tÅ™i znaky, které chcete vyhledat @@ -341,7 +364,7 @@ cs: dashboard: show: view_more_logs: Zobrazit další protokoly - welcome: Vítejte v administrátorském panelu Decidim. + welcome: Vítejte v Admin panelu. domain_whitelist: form: domain_too_short: Doména je příliÅ¡ krátká @@ -842,9 +865,25 @@ cs: invalid: PÅ™i Ätení souboru CSV doÅ¡lo k chybÄ›. success: CSV soubor byl úspěšnÄ› nahrán, posíláme e-maily na úÄastníky. To může trvat nÄ›jakou dobu. new: + destroy: + button: Odstranit vÅ¡echny soukromé úÄastníky + confirm: Jste si jisti, že chcete odstranit vÅ¡echny soukromé úÄastníky? Tuto akci nelze vrátit zpÄ›t, nebudete je moci obnovit. + empty: Nemáte žádné soukromé úÄastníky. + explanation: Máte %{count} soukromých úÄastníků. + title: Odstranit soukromé úÄastníky explanation: 'Nahrajte soubor CSV. Musí mít dva sloupce s e-mailem v prvním sloupci souboru a jméno v posledním sloupci souboru (e-mail, jméno) uživatelů, které chcete pÅ™idat do participaÄního prostoru, bez záhlaví. VyhnÄ›te se používání neplatných znaků jako `<>?%&^*#@()[]=+:;"{}\|` v uživatelském jménÄ›.' title: Nahrajte Váš CSV soubor upload: Nahrát + reminders: + create: + error: PÅ™i vytváření pÅ™ipomenutí doÅ¡lo k chybÄ›. + success: + one: "%{count} uživatel bude upozornÄ›n." + few: "%{count} uživatelé budou upozornÄ›ni." + many: "%{count} uživatelů bude upozornÄ›no." + other: "%{count} uživatelů bude upozornÄ›no." + new: + submit: Odeslat resource_permissions: edit: submit: PÅ™edložit @@ -902,6 +941,7 @@ cs: gallery: add_images: PÅ™idat obrázky delete_image: Odstranit obrázek + edit_images: Upravit obrázky gallery_legend: PÅ™idat galerii obrázků (volitelné) static_page_topics: create: @@ -962,7 +1002,7 @@ cs: static_pages: Stránky statistics: Aktivita user_groups: Skupiny - users: ÚÄastníci + users: AdministrátoÅ™i user_group: csv_verify: invalid: PÅ™i Ätení souboru CSV doÅ¡lo k chybÄ›. @@ -998,7 +1038,7 @@ cs: role: Role new: create: Pozvat - title: Pozvat úÄastníka jako administrátora + title: Pozvat nového administrátora users_statistics: users_count: admins: AdministrátoÅ™i @@ -1045,7 +1085,7 @@ cs: models: moderation: fields: - created_at: Datum vytvoÅ™ení + created_at: Datum vzniku deleted_resource: Smazaný dokument hidden_at: Skryté u participatory_space: Participativní prostor @@ -1053,7 +1093,7 @@ cs: reportable_id: ID reportable_type: Typ reported_content_url: Oznámená adresa URL obsahu - reports: Zprávy + reports: Hlášení visit_url: NavÅ¡tívit URL report: fields: diff --git a/decidim-admin/config/locales/de.yml b/decidim-admin/config/locales/de.yml index 84f2292310b20..6e51d62f0e34b 100644 --- a/decidim-admin/config/locales/de.yml +++ b/decidim-admin/config/locales/de.yml @@ -1,3 +1,4 @@ +--- de: activemodel: attributes: @@ -14,17 +15,24 @@ de: description: Beschreibung file: Datei title: Anhang oder Bildname + weight: Reihenfolge attachment_collection: description: Beschreibung name: Name + weight: Reihenfolge category: description: Beschreibung name: Name parent_id: Ãœbergeordnete Kategorie + weight: Reihenfolge component: name: Name published_at: Veröffentlicht unter - weight: Bestellposition + weight: Reihenfolge + external_domain: + value: Wert + help_section: + content: Inhalt id: ID import: user_group_id: Importierte Inhalte erstellen als @@ -92,6 +100,9 @@ de: welcome_notification_body: Text der Willkommens-Benachrichtigung welcome_notification_subject: Betreff der Willkommens-Benachrichtigung youtube_handler: YouTube-Handler + participatory_space_private_user: + email: E-Mail + name: Name scope: code: Code name: Name @@ -113,12 +124,13 @@ de: show_in_footer: In der Fußzeile anzeigen slug: URL-Block title: Titel - weight: Bestellposition + topic_id: Thema + weight: Reihenfolge static_page_topic: description: Beschreibung show_in_footer: In der Fußzeile anzeigen title: Titel - weight: Bestellposition + weight: Reihenfolge user_group_csv_verification: file: Datei errors: @@ -177,7 +189,7 @@ de: reject: Ablehnen share: Teilen user: - new: Neuer Benutzer + new: Neuer Administrator verify: Ãœberprüfen admin_terms_of_use: accept: @@ -259,6 +271,8 @@ de: update: error: Beim Aktualisieren dieses Anhangs ist ein Fehler aufgetreten. success: Anhang wurde erfolgreich aktualisiert. + attachments_privacy_warning: + message: Seien Sie vorsichtig, wenn Sie mit Anhängen in einem privaten Raum arbeiten. Jeder Teilnehmer kann dieses Dokument mit anderen teilen. autocomplete: no_results: keine Ergebnisse gefunden search_prompt: Geben Sie mindestens drei Zeichen ein, um zu suchen @@ -341,7 +355,7 @@ de: dashboard: show: view_more_logs: Weitere Protokolle anzeigen - welcome: Willkommen im Decidim Admin Panel. + welcome: Willkommen beim Admin-Panel von Decidim. domain_whitelist: form: domain_too_short: Domain zu kurz @@ -834,9 +848,23 @@ de: invalid: Beim Lesen der CSV-Datei ist ein Fehler aufgetreten. success: CSV-Datei wurde erfolgreich hochgeladen, wir senden eine Einladungs-E-Mail an die Teilnehmer. Dies kann eine Weile dauern. new: + destroy: + button: Alle private Teilnehmende auswählen + confirm: Sind Sie sicher, dass Sie alle private Teilnehmende entfernen möchten? Diese Aktion kann nicht rückgängig gemacht werden. Sie werden sie nicht wiederherstellen können. + empty: Sie haben keine private Teilnehmende. + explanation: Sie haben %{count} private Teilnehmende. + title: Alle private Teilnehmende entfernen explanation: 'Laden Sie Ihre CSV-Datei hoch. Diese muss zwei Spalten haben ohne Kopfzeile, mit E-Mail in der ersten Spalte der Datei und Namen in der letzten Spalte der Datei (E-Mail, Name) in Bezug auf die Benutzer, die Sie dem Beteiligungsbereich hinzufügen möchten. Vermeiden sie ungültige Zeichen wie `<>?%&^*#@()[]=+:;"{}\|` im Namen des Nutzers zu verwenden.' title: CSV-Datei hochladen upload: Hochladen + reminders: + create: + error: Beim Erstellen dieser Erinnerungen ist ein Problem aufgetreten. + success: + one: "%{count} Benutzer wird erinnert." + other: "%{count} Benutzer werden erinnert." + new: + submit: Senden resource_permissions: edit: submit: einreichen @@ -894,6 +922,7 @@ de: gallery: add_images: Bilder hinzufügen delete_image: Bild löschen + edit_images: Bilder bearbeiten gallery_legend: Bildergalerie hinzufügen (Optional) static_page_topics: create: @@ -954,7 +983,7 @@ de: static_pages: Seiten statistics: Aktivität user_groups: Benutzergruppen - users: Teilnehmer + users: Administratoren user_group: csv_verify: invalid: Beim Lesen der CSV-Datei ist ein Fehler aufgetreten. @@ -990,7 +1019,7 @@ de: role: Rolle new: create: Einladen - title: Benutzer als Administrator einladen + title: Neuen Administrator einladen users_statistics: users_count: admins: Admins diff --git a/decidim-admin/config/locales/el.yml b/decidim-admin/config/locales/el.yml index bde77ee9ad119..c68699e1ba5b6 100644 --- a/decidim-admin/config/locales/el.yml +++ b/decidim-admin/config/locales/el.yml @@ -1,3 +1,4 @@ +--- el: activemodel: attributes: @@ -171,8 +172,6 @@ el: permissions: Δικαιώματα reject: ΑπόÏÏιψη share: Κοινοποίηση - user: - new: Îέος χÏήστης verify: Επαλήθευση admin_terms_of_use: accept: @@ -336,7 +335,6 @@ el: dashboard: show: view_more_logs: ΠÏοβολή πεÏισσότεÏων αÏχείων καταγÏαφής - welcome: Καλώς οÏίσατε στον Πίνακα διαχειÏιστή Decidim. domain_whitelist: form: domain_too_short: Î Î¿Î»Ï ÏƒÏντομος τομέας @@ -904,7 +902,6 @@ el: static_pages: Σελίδες statistics: ΔÏαστηÏιότητα user_groups: Ομάδες - users: Συμμετέχοντες user_group: csv_verify: invalid: ΥπήÏξε ένα Ï€Ïόβλημα κατά την ανάγνωση του αÏχείου CSV. @@ -940,7 +937,6 @@ el: role: Ρόλος new: create: ΠÏόσκληση - title: ΠÏοσκαλέστε τον συμμετέχοντα ως διαχειÏιστή users_statistics: users_count: admins: ΔιαχειÏιστές diff --git a/decidim-admin/config/locales/en.yml b/decidim-admin/config/locales/en.yml index 13273e64c03b0..d2e1bb1bc6f35 100644 --- a/decidim-admin/config/locales/en.yml +++ b/decidim-admin/config/locales/en.yml @@ -15,17 +15,24 @@ en: description: Description file: File title: Attachment or image name + weight: Order position attachment_collection: description: Description name: Name + weight: Order position category: description: Description name: Name parent_id: Parent + weight: Order position component: name: Name published_at: Published at weight: Order position + external_domain: + value: Value + help_section: + content: Content id: ID import: user_group_id: Create imports as @@ -93,6 +100,9 @@ en: welcome_notification_body: Welcome notification body welcome_notification_subject: Welcome notification subject youtube_handler: YouTube handler + participatory_space_private_user: + email: Email + name: Name scope: code: Code name: Name @@ -114,6 +124,7 @@ en: show_in_footer: Show in the footer slug: URL slug title: Title + topic_id: Topic weight: Order position static_page_topic: description: Description @@ -134,6 +145,14 @@ en: allowed_file_content_types: Invalid image file official_img_header: allowed_file_content_types: Invalid image file + participatory_space_private_user_csv_import: + attributes: + file: + malformed: Malformed import file, please read through the instructions carefully and make sure the file is UTF-8 encoded. + user_group_csv_verification: + attributes: + file: + malformed: Malformed import file, please read through the instructions carefully and make sure the file is UTF-8 encoded. new_import: attributes: file: @@ -178,7 +197,7 @@ en: reject: Reject share: Share user: - new: New user + new: New admin verify: Verify admin_terms_of_use: accept: @@ -261,6 +280,8 @@ en: update: error: There was a problem updating this attachment. success: Attachment updated successfully. + attachments_privacy_warning: + message: Be careful when working with attachments in a private space. Any participant could share this document to others. autocomplete: no_results: No results found search_prompt: Type at least three characters to search @@ -343,7 +364,7 @@ en: dashboard: show: view_more_logs: View more logs - welcome: Welcome to the Decidim Admin Panel. + welcome: Welcome to the Admin Panel. domain_whitelist: form: domain_too_short: Domain too short @@ -836,9 +857,23 @@ en: invalid: There was a problem reading the CSV file. success: CSV file uploaded successfully, we're sending an invitation email to participants. This might take a while. new: + destroy: + button: Delete all private participants + confirm: Are you sure you want to delete all private participants? This action can't be undone, you will not be able to recover them. + empty: You have no private participants. + explanation: You have %{count} private participants. + title: Delete private participants explanation: Upload your CSV file. It must have two columns with email in the first column of the file and name in the last column of the file (email, name) of the users that you want to add to the participatory space, without headers. Avoid using invalid chars like `<>?%&^*#@()[]=+:;"{}\|` in user name. title: Upload your CSV file upload: Upload + reminders: + create: + error: There was a problem creating reminders. + success: + one: "%{count} user will be reminded." + other: "%{count} users will be reminded." + new: + submit: Send resource_permissions: edit: submit: Submit @@ -896,6 +931,7 @@ en: gallery: add_images: Add images delete_image: Delete Image + edit_images: Edit images gallery_legend: Add an image gallery (Optional) static_page_topics: create: @@ -956,7 +992,7 @@ en: static_pages: Pages statistics: Activity user_groups: Groups - users: Participants + users: Administrators user_group: csv_verify: invalid: There was a problem reading the CSV file. @@ -992,7 +1028,7 @@ en: role: Role new: create: Invite - title: Invite participant as administrator + title: Invite new administrator users_statistics: users_count: admins: Admins diff --git a/decidim-admin/config/locales/eo.yml b/decidim-admin/config/locales/eo.yml index cf517f589830e..225eda575ff9e 100644 --- a/decidim-admin/config/locales/eo.yml +++ b/decidim-admin/config/locales/eo.yml @@ -1,3 +1,4 @@ +--- eo: activemodel: attributes: diff --git a/decidim-admin/config/locales/es-MX.yml b/decidim-admin/config/locales/es-MX.yml index da6aa3f2bcaac..6057274c8bed2 100644 --- a/decidim-admin/config/locales/es-MX.yml +++ b/decidim-admin/config/locales/es-MX.yml @@ -1,3 +1,4 @@ +--- es-MX: activemodel: attributes: @@ -14,17 +15,24 @@ es-MX: description: Descripción file: Archivo title: Nombre del adjunto o imagen + weight: Orden de posición attachment_collection: description: Descripción name: Nombre + weight: Orden de posición category: description: Descripción name: Nombre parent_id: Superior + weight: Orden de posición component: name: Nombre published_at: Publicado en weight: Orden de posición + external_domain: + value: Valor + help_section: + content: Contenido id: ID import: user_group_id: Importar como @@ -92,6 +100,9 @@ es-MX: welcome_notification_body: Cuerpo del mensaje de notificación de bienvenida welcome_notification_subject: Asunto del mensaje de notificación de bienvenida youtube_handler: Nombre de YouTube + participatory_space_private_user: + email: Correo electrónico + name: Nombre scope: code: Código name: Nombre @@ -113,6 +124,7 @@ es-MX: show_in_footer: Mostrar en el pie de página slug: Texto corto de URL title: Título + topic_id: Asunto weight: Orden de posición static_page_topic: description: Descripción @@ -133,6 +145,14 @@ es-MX: allowed_file_content_types: Archivo de imagen no válido official_img_header: allowed_file_content_types: Archivo de imagen no válido + participatory_space_private_user_csv_import: + attributes: + file: + malformed: Archivo de importación mal formateado, por favor lea las instrucciones cuidadosamente y asegúrese de que el archivo está codificado en UTF-8. + user_group_csv_verification: + attributes: + file: + malformed: Archivo de importación mal formateado, por favor lea las instrucciones cuidadosamente y asegúrese de que el archivo está codificado en UTF-8. new_import: attributes: file: @@ -177,7 +197,7 @@ es-MX: reject: Rechazar share: Compartir user: - new: Nuevo ususario + new: Nueva administradora verify: Verificar admin_terms_of_use: accept: @@ -260,6 +280,8 @@ es-MX: update: error: Se ha producido un error al actualizar este archivo adjunto. success: Adjunto actualizado correctamente. + attachments_privacy_warning: + message: Tenga cuidado al trabajar con archivos adjuntos en un espacio privado. Cualquier participante podría compartir este documento a otras personas. autocomplete: no_results: No se han encontrado resultados search_prompt: Escriba al menos tres caracteres para buscar @@ -342,7 +364,7 @@ es-MX: dashboard: show: view_more_logs: Ver más registros - welcome: Bienvenido al panel de administración de Decidim. + welcome: Bienvenida al panel de administración. domain_whitelist: form: domain_too_short: Dominio demasiado corto @@ -835,9 +857,23 @@ es-MX: invalid: Se produjo un error al leer el archivo CSV. success: Archivo CSV subido correctamente, estamos enviando un correo electrónico de invitación a las participantes. Esto puede tardar un tiempo. new: + destroy: + button: Borrar todas las participantes privadas + confirm: '¿Estás segura que quieres eliminar todas las participantes privadas? Esta acción no se puede deshacer, no podrás recupararlas.' + empty: No hay participantes privadas. + explanation: Hay %{count} participante/s privada/s. + title: Borrar las participantes privadas explanation: 'Sube tu archivo CSV. Debe tener dos columnas con correo electrónico en la primera columna del archivo y el nombre en la última columna del archivo (correo electrónico, nombre) de los usuarios que deseas añadir al espacio participativo, sin encabezados. Evitar usar caracteres no válidos como `<>?%&^*#@()[]=+:;"{}\|` en el nombre de usuario.' title: Sube tu archivo CSV upload: Subir + reminders: + create: + error: Se ha producido un error al crear los recordatorios. + success: + one: "%{count} usuaria será recordada." + other: "%{count} usuarias serán recordadas." + new: + submit: Enviar resource_permissions: edit: submit: Enviar @@ -895,6 +931,7 @@ es-MX: gallery: add_images: Añadir imágenes delete_image: Borrar la imagen + edit_images: Editar imagenes gallery_legend: Añadir una galería de imágenes (opccional) static_page_topics: create: @@ -955,7 +992,7 @@ es-MX: static_pages: Páginas statistics: Actividad user_groups: Grupos de usuarios - users: Participantes + users: Administradoras user_group: csv_verify: invalid: Se produjo un error al leer el archivo CSV. @@ -991,7 +1028,7 @@ es-MX: role: Rol new: create: Invitar - title: Invitar a un usuario como administrador + title: Invitar nueva administradora users_statistics: users_count: admins: Administradores @@ -1039,14 +1076,14 @@ es-MX: moderation: fields: created_at: Fecha de creación - deleted_resource: Eliminar recurso + deleted_resource: Recurso eliminado hidden_at: Fecha de ocultación participatory_space: Espacio participativo report_count: Recuento reportable_id: ID reportable_type: Tipo reported_content_url: URL del contenido reportado - reports: Denuncias + reports: Informes visit_url: Visita la URL report: fields: diff --git a/decidim-admin/config/locales/es-PY.yml b/decidim-admin/config/locales/es-PY.yml index 83f1c8f6fd3c1..ee6e59316fb7d 100644 --- a/decidim-admin/config/locales/es-PY.yml +++ b/decidim-admin/config/locales/es-PY.yml @@ -1,3 +1,4 @@ +--- es-PY: activemodel: attributes: @@ -14,17 +15,24 @@ es-PY: description: Descripción file: Archivo title: Nombre del adjunto o imagen + weight: Orden de posición attachment_collection: description: Descripción name: Nombre + weight: Orden de posición category: description: Descripción name: Nombre parent_id: Superior + weight: Orden de posición component: name: Nombre published_at: Publicado en weight: Orden de posición + external_domain: + value: Valor + help_section: + content: Contenido id: ID import: user_group_id: Importar como @@ -92,6 +100,9 @@ es-PY: welcome_notification_body: Cuerpo del mensaje de notificación de bienvenida welcome_notification_subject: Asunto del mensaje de notificación de bienvenida youtube_handler: Nombre de YouTube + participatory_space_private_user: + email: Correo electrónico + name: Nombre scope: code: Código name: Nombre @@ -113,6 +124,7 @@ es-PY: show_in_footer: Mostrar en el pie de página slug: Texto corto de URL title: Título + topic_id: Asunto weight: Orden de posición static_page_topic: description: Descripción @@ -133,6 +145,14 @@ es-PY: allowed_file_content_types: Archivo de imagen no válido official_img_header: allowed_file_content_types: Archivo de imagen no válido + participatory_space_private_user_csv_import: + attributes: + file: + malformed: Archivo de importación mal formateado, por favor lea las instrucciones cuidadosamente y asegúrese de que el archivo está codificado en UTF-8. + user_group_csv_verification: + attributes: + file: + malformed: Archivo de importación mal formateado, por favor lea las instrucciones cuidadosamente y asegúrese de que el archivo está codificado en UTF-8. new_import: attributes: file: @@ -177,7 +197,7 @@ es-PY: reject: Rechazar share: Compartir user: - new: Nuevo ususario + new: Nueva administradora verify: Verificar admin_terms_of_use: accept: @@ -260,6 +280,8 @@ es-PY: update: error: Se ha producido un error al actualizar este archivo adjunto. success: Adjunto actualizado correctamente. + attachments_privacy_warning: + message: Por favor ten cuidado al trabajar con archivos adjuntos en un espacio privado. Cualquier participante puede compartir este documento con otras. autocomplete: no_results: No se han encontrado resultados search_prompt: Escriba al menos tres caracteres para buscar @@ -342,7 +364,7 @@ es-PY: dashboard: show: view_more_logs: Ver más registros - welcome: Bienvenido al panel de administración de Decidim. + welcome: Bienvenida al panel de administración. domain_whitelist: form: domain_too_short: Dominio demasiado corto @@ -835,9 +857,23 @@ es-PY: invalid: Se produjo un error al leer el archivo CSV. success: Archivo CSV subido correctamente, estamos enviando un correo electrónico de invitación a las participantes. Esto puede tardar un tiempo. new: + destroy: + button: Borrar todas las participantes privadas + confirm: '¿Estás segura que quieres eliminar todas las participantes privadas? Esta acción no se puede deshacer, no podrás recupararlas.' + empty: No hay participantes privadas. + explanation: Hay %{count} participante/s privada/s. + title: Borrar las participantes privadas explanation: 'Sube tu archivo CSV. Debe tener dos columnas con correo electrónico en la primera columna del archivo y el nombre en la última columna del archivo (correo electrónico, nombre) de los usuarios que deseas añadir al espacio participativo, sin encabezados. Evitar usar caracteres no válidos como `<>?%&^*#@()[]=+:;"{}\|` en el nombre de usuario.' title: Sube tu archivo CSV upload: Subir + reminders: + create: + error: Se ha producido un error al crear los recordatorios. + success: + one: "%{count} usuaria será recordada." + other: "%{count} usuarias serán recordadas." + new: + submit: Enviar resource_permissions: edit: submit: Enviar @@ -895,6 +931,7 @@ es-PY: gallery: add_images: Añadir imágenes delete_image: Borrar la imagen + edit_images: Editar imagenes gallery_legend: Añadir una galería de imágenes (opccional) static_page_topics: create: @@ -955,7 +992,7 @@ es-PY: static_pages: Páginas statistics: Actividad user_groups: Grupos de usuarios - users: Participantes + users: Administradoras user_group: csv_verify: invalid: Se produjo un error al leer el archivo CSV. @@ -991,7 +1028,7 @@ es-PY: role: Rol new: create: Invitar - title: Invitar a un usuario como administrador + title: Invitar nueva administradora users_statistics: users_count: admins: Administradores @@ -1039,14 +1076,14 @@ es-PY: moderation: fields: created_at: Fecha de creación - deleted_resource: Eliminar recurso + deleted_resource: Recurso eliminado hidden_at: Fecha de ocultación participatory_space: Espacio participativo report_count: Recuento reportable_id: ID reportable_type: Tipo reported_content_url: URL del contenido reportado - reports: Denuncias + reports: Informes visit_url: Visita la URL report: fields: diff --git a/decidim-admin/config/locales/es.yml b/decidim-admin/config/locales/es.yml index 3e67d46362234..5fb3844ed74bf 100644 --- a/decidim-admin/config/locales/es.yml +++ b/decidim-admin/config/locales/es.yml @@ -1,3 +1,4 @@ +--- es: activemodel: attributes: @@ -14,17 +15,24 @@ es: description: Descripción file: Archivo title: Nombre del adjunto o imagen + weight: Orden de posición attachment_collection: description: Descripción name: Nombre + weight: Orden de posición category: description: Descripción name: Nombre parent_id: Superior + weight: Orden de posición component: name: Nombre published_at: Publicado en weight: Orden de posición + external_domain: + value: Valor + help_section: + content: Contenido id: ID import: user_group_id: Importar como @@ -92,6 +100,9 @@ es: welcome_notification_body: Cuerpo del mensaje de notificación de bienvenida welcome_notification_subject: Asunto del mensaje de notificación de bienvenida youtube_handler: Nombre de YouTube + participatory_space_private_user: + email: Correo electrónico + name: Nombre scope: code: Código name: Nombre @@ -113,6 +124,7 @@ es: show_in_footer: Mostrar en el pie de página slug: Texto corto de URL title: Título + topic_id: Asunto weight: Orden de posición static_page_topic: description: Descripción @@ -133,6 +145,14 @@ es: allowed_file_content_types: Archivo de imagen no válido official_img_header: allowed_file_content_types: Archivo de imagen no válido + participatory_space_private_user_csv_import: + attributes: + file: + malformed: Archivo de importación mal formateado, por favor lea las instrucciones cuidadosamente y asegúrese de que el archivo está codificado en UTF-8. + user_group_csv_verification: + attributes: + file: + malformed: Archivo de importación mal formateado, por favor lea las instrucciones cuidadosamente y asegúrese de que el archivo está codificado en UTF-8. new_import: attributes: file: @@ -177,7 +197,7 @@ es: reject: Rechazar share: Compartir user: - new: Nuevo ususario + new: Nueva administradora verify: Verificar admin_terms_of_use: accept: @@ -260,6 +280,8 @@ es: update: error: Se ha producido un error al actualizar este adjunto. success: Adjunto actualizado correctamente. + attachments_privacy_warning: + message: Por favor ten cuidado al trabajar con archivos adjuntos en un espacio privado. Cualquier participante puede compartir este documento con otras. autocomplete: no_results: No se han encontrado resultados search_prompt: Escriba al menos tres caracteres para buscar @@ -342,7 +364,7 @@ es: dashboard: show: view_more_logs: Ver más registros - welcome: Bienvenida al panel de administración de Decidim. + welcome: Bienvenida al panel de administración. domain_whitelist: form: domain_too_short: Dominio demasiado corto @@ -689,7 +711,7 @@ es: all: todos all_users: 'Todos los usuarios ' and: 'y ' - confirm_delete: '¿Estás seguro de que quieres eliminar este boletín?' + confirm_delete: '¿Seguro que quieres eliminar este boletín?' followers: 'seguidores ' has_been_sent_to: 'Se ha enviado a: ' no_scopes: Sin ámbitos @@ -704,7 +726,7 @@ es: select_recipients_to_deliver: all_spaces: Todos all_users_help: Envía el boletín de noticias a todos las participantes confirmadas. - confirm_deliver: '¿Estás segura de que quieres enviar este boletín? Esta acción no se puede deshacer.' + confirm_deliver: '¿Seguro que quieres enviar este boletín? Esta acción no se puede deshacer.' deliver: Enviar boletín followers_help: Envía el boletín de noticias a todas las participantes confirmadas que sigan cualquier espacio participativo seleccionado en la lista. none: Ninguno @@ -835,9 +857,23 @@ es: invalid: Se produjo un error al leer el archivo CSV. success: Archivo CSV subido correctamente, estamos enviando un correo electrónico de invitación a las participantes. Esto puede tardar un tiempo. new: + destroy: + button: Borrar todas las participantes privadas + confirm: '¿Seguro que quieres eliminar todas las participantes privadas? Esta acción no se puede deshacer, no podrás recuperarlas.' + empty: No hay participantes privadas. + explanation: Hay %{count} participante/s privada/s. + title: Borrar las participantes privadas explanation: 'Sube tu archivo CSV. Debe tener dos columnas con correo electrónico en la primera columna del archivo y el nombre en la última columna del archivo (correo electrónico, nombre) de los usuarios que deseas añadir al espacio participativo, sin encabezados. Evitar usar caracteres no válidos como `<>?%&^*#@()[]=+:;"{}\|` en el nombre de usuario.' title: Sube tu archivo CSV upload: Subir + reminders: + create: + error: Se ha producido un error al crear los recordatorios. + success: + one: "%{count} usuaria será recordada." + other: "%{count} usuarias serán recordadas." + new: + submit: Enviar resource_permissions: edit: submit: Enviar @@ -895,6 +931,7 @@ es: gallery: add_images: Añadir imágenes delete_image: Borrar la imagen + edit_images: Editar imagenes gallery_legend: Añadir una galería de imágenes (opcional) static_page_topics: create: @@ -955,7 +992,7 @@ es: static_pages: Páginas statistics: Actividad user_groups: Grupos - users: Participantes + users: Administradoras user_group: csv_verify: invalid: Se produjo un error al leer el archivo CSV. @@ -991,7 +1028,7 @@ es: role: Rol new: create: Invitar - title: Invitar a la participante como administradora + title: Invitar nueva administradora users_statistics: users_count: admins: Administradoras @@ -1039,14 +1076,14 @@ es: moderation: fields: created_at: Fecha de creación - deleted_resource: Eliminar recurso + deleted_resource: Recurso eliminado hidden_at: Fecha de ocultación participatory_space: Espacio participativo report_count: Recuento reportable_id: ID reportable_type: Tipo reported_content_url: URL del contenido reportado - reports: Denuncias + reports: Informes visit_url: Visita la URL report: fields: diff --git a/decidim-admin/config/locales/eu.yml b/decidim-admin/config/locales/eu.yml index 0425ecd5e81d7..d462beefe1787 100644 --- a/decidim-admin/config/locales/eu.yml +++ b/decidim-admin/config/locales/eu.yml @@ -1,3 +1,4 @@ +--- eu: activemodel: attributes: @@ -14,17 +15,24 @@ eu: description: Descripción file: Fitxategia title: Erantsitakoaren edo irudiaren izena + weight: Kokapenaren hurrenkera attachment_collection: description: Deskribapena name: Izena + weight: Kokapenaren hurrenkera category: description: Descripción name: Izena parent_id: Nagusia + weight: Kokapenaren hurrenkera component: name: Izena published_at: Argitaratu at weight: Kokapenaren hurrenkera + external_domain: + value: Balioa + help_section: + content: Edukia id: NAN import: user_group_id: Inportatu hau bezala @@ -92,6 +100,9 @@ eu: welcome_notification_body: Ongietorri-jakinarazpenaren mezuaren atala welcome_notification_subject: Ongietorri-jakinarazpenaren mezuaren gaia youtube_handler: YouTube kudeatzailea + participatory_space_private_user: + email: Helbide elektronikoa + name: Izena scope: code: Kodea name: Izena @@ -113,6 +124,7 @@ eu: show_in_footer: Erakutsi orri-oinean slug: URL laburra title: Titulua + topic_id: Gaia weight: Kokapenaren hurrenkera static_page_topic: description: Deskribapena @@ -123,12 +135,24 @@ eu: file: file errors: models: + newsletter: + attributes: + base: + at_least_one_space: Aukeratu parte hartzeko espazio bat gutxienez organization: attributes: official_img_footer: allowed_file_content_types: Irudi fitxategi baliogabea official_img_header: allowed_file_content_types: Irudi fitxategi baliogabea + participatory_space_private_user_csv_import: + attributes: + file: + malformed: Fitxategia akastuna da. Irakurri arretaz jarraibideak eta ziurtatu fitxategia UTF-8an kodifikatuta dagoela. + user_group_csv_verification: + attributes: + file: + malformed: Fitxategia akastuna da. Irakurri arretaz jarraibideak eta ziurtatu fitxategia UTF-8an kodifikatuta dagoela. new_import: attributes: file: @@ -173,7 +197,7 @@ eu: reject: Ukatu share: Partekatu user: - new: Beste erabiltzaile bat + new: Administratzaile berria verify: Egiaztatu admin_terms_of_use: accept: @@ -197,7 +221,7 @@ eu: success: Area mota behar bezala suntsitu da edit: title: Editatu eremu mota - update: Eguneratzearen + update: Onartu new: create: Sortu eremu mota title: Area mota berria @@ -213,7 +237,7 @@ eu: success: Area behar bezala suntsitu da edit: title: Editatu eremua - update: Eguneratzearen + update: Onartu new: create: Sortu eremua title: Area berria @@ -229,7 +253,7 @@ eu: success: Karpeta ondo suntsitu da. edit: title: Editatu karpeta - update: Eguneratzearen + update: Onartu index: attachment_collection_used: Karpeta hau ezin da ezabatu erabiltzen ari delako. attachment_collections_title: Eranskinen karpetak @@ -256,6 +280,8 @@ eu: update: error: Errorea gertatu da fitxategi erantsi bat eguneratzean. success: Fitxategi erantsia zuzen eguneratu da. + attachments_privacy_warning: + message: Kontuz ibili fitxategi erantsiekin espazio pribatu batean lan egiten duzunean, edozein parte-hartzailek parteka dezake dokumentu hau beste pertsona batzuekin. autocomplete: no_results: Ez da emaitzarik aurkitu search_prompt: Idatzi bilaketak gutxienez hiru karaktere @@ -297,7 +323,7 @@ eu: success: Osagaia zuzen ezabatu da. edit: title: Editatu osagaia - update: Eguneratzearen + update: Onartu form: default_step_settings: Urratsen ezarpen lehenetsiak global_settings: Ezarpen globalak @@ -338,7 +364,6 @@ eu: dashboard: show: view_more_logs: Ikusi gehiago erregistroak - welcome: Ongi etorri Decidim Admin Panelera. domain_whitelist: form: domain_too_short: Domeinu laburregia @@ -426,7 +451,7 @@ eu: help_sections: error: Errore bat gertatu da laguntza-atalak eguneratuz form: - save: Save + save: Gorde success: Laguntza atalak behar bezala eguneratu dira impersonatable_users: index: @@ -466,6 +491,9 @@ eu: data_errors: duplicate_headers: detail: Mesedez, egiaztatu fitxategiak behin bakarrik eskatzen diren zutabeak edo goiburuak dituela. + message: + one: Bikoiztu zutabeak %{columns}. + other: Bikoiztu %{columns} zutabe. invalid_indexes: lines: detail: "\nEgiaztatu erregistro horiek formatu zuzena dutela eta baliozko erregistroak dituztela." @@ -511,7 +539,7 @@ eu: moderation: Moderazio globalak newsletters: Buletinak participants: Parte-hartzaileak - reported_users: Erabiltzaile erreportatuak + reported_users: Erabiltzaile informatuak scope_types: Esparru motak scopes: Esparruak settings: Ezarpenak @@ -610,7 +638,7 @@ eu: nickname: Ezizena reason: Arrazoia reports: Salaketa kopurua - title: Erreportatutako erabiltzaileen zerrenda + title: Informatutako erabiltzaileen zerrenda report: reasons: does_not_belong: Ez da bidezkoa @@ -794,7 +822,7 @@ eu: inactive_content_blocks: Eduki eduki gabeko blokeak organization_homepage_content_blocks: edit: - update: Eguneratu + update: Onartu participatory_space_private_users: create: error: Errore bat gertatu da partaidetza espazio honen erabiltzaile pribatua gehitzean. @@ -933,7 +961,6 @@ eu: static_pages: Orriak statistics: Jarduera user_groups: Erabiltzaile-taldeak - users: Parte-hartzaileak user_group: csv_verify: invalid: Errore bat gertatu da CSV fitxategia irakurtzean. @@ -969,7 +996,6 @@ eu: role: Rola new: create: Gonbit egin - title: Gonbit egin erabiltzaile bati administratzaile gisa users_statistics: users_count: admins: Administratzaileak @@ -1020,9 +1046,10 @@ eu: hidden_at: Ezkutatze-data participatory_space: Parte hartzeko esparrua report_count: Zenbaketa + reportable_id: ID reportable_type: Mota reported_content_url: Emandako edukiaren URLa - reports: Salaketak + reports: Txostenak visit_url: Bisitatu URLa report: fields: diff --git a/decidim-admin/config/locales/fi-plain.yml b/decidim-admin/config/locales/fi-plain.yml index 689a379b4fba0..3a51880a4db7a 100644 --- a/decidim-admin/config/locales/fi-plain.yml +++ b/decidim-admin/config/locales/fi-plain.yml @@ -1,3 +1,4 @@ +--- fi-pl: activemodel: attributes: @@ -14,17 +15,24 @@ fi-pl: description: Kuvaus file: Tiedosto title: Liitetiedoston tai kuvan nimi + weight: Järjestysnumero attachment_collection: description: Kuvaus name: Nimi + weight: Järjestysnumero category: description: Kuvaus name: Nimi parent_id: Yläaihepiiri + weight: Järjestysnumero component: name: Nimi published_at: Julkaistu osoitteessa weight: Järjestysnumero + external_domain: + value: Arvo + help_section: + content: Sisältö id: ID import: user_group_id: Tuo käyttäjänä @@ -92,6 +100,9 @@ fi-pl: welcome_notification_body: Tervetuloilmoituksen runko welcome_notification_subject: Tervetuloilmoituksen otsikko youtube_handler: YouTube-käsittelijä + participatory_space_private_user: + email: Sähköpostiosoite + name: Nimi scope: code: Koodi name: Nimi @@ -113,6 +124,7 @@ fi-pl: show_in_footer: Näytä alatunnisteessa slug: URL-tunniste title: Otsikko + topic_id: Aihe weight: Järjestysnumero static_page_topic: description: Kuvaus @@ -133,6 +145,14 @@ fi-pl: allowed_file_content_types: Virheellinen kuvatiedosto official_img_header: allowed_file_content_types: Virheellinen kuvatiedosto + participatory_space_private_user_csv_import: + attributes: + file: + malformed: Virheellinen tuontitiedosto, lue ohjeet huolellisesti ja varmista, että tiedosto on UTF-8 muodossa. + user_group_csv_verification: + attributes: + file: + malformed: Virheellinen tuontitiedosto, lue ohjeet huolellisesti ja varmista, että tiedosto on UTF-8 muodossa. new_import: attributes: file: @@ -177,7 +197,7 @@ fi-pl: reject: Hylkää share: Jaa user: - new: Uusi käyttäjä + new: Uusi hallintakäyttäjä verify: Vahvista admin_terms_of_use: accept: @@ -260,6 +280,8 @@ fi-pl: update: error: Tämän liitteen päivityksessä tapahtui virhe. success: Liite luotu onnistuneesti. + attachments_privacy_warning: + message: Ole varovainen, kun työskentelet liitetiedostojen kanssa yksityisessä tilassa. Kuka tahansa osallistuja voi jakaa tämän asiakirjan muille. autocomplete: no_results: Ei tuloksia search_prompt: Kirjoita vähintään kolme merkkiä hakuun @@ -342,7 +364,7 @@ fi-pl: dashboard: show: view_more_logs: Näytä lisää lokitietoja - welcome: Tervetuloa Decidimin hallintapaneeliin. + welcome: Tervetuloa hallintapaneeliin. domain_whitelist: form: domain_too_short: Verkkotunnus on liian lyhyt @@ -835,9 +857,23 @@ fi-pl: invalid: CSV-tiedoston käsittelyssä tapahtui virhe. success: CSV-tiedosto ladattu onnistuneesti. Lähetämme kutsusähköpostin osallistujille. Tämä voi kestää hetken. new: + destroy: + button: Poista kaikki yksityiset osallistujat + confirm: Oletko varma, että haluat poistaa kaikki yksityiset osallistujat? Tätä toimintoa ei voi peruuttaa ja poistettuja osallistujia ei voi palauttaa. + empty: Tässä osallistumistilassa ei ole yksityisiä osallistujia. + explanation: Tässä osallistumistilassa on %{count} yksityistä osallistujaa. + title: Poista kaikki yksityiset osallistujat explanation: 'Lataa CSV-tiedosto osallistumistilan käyttäjistä. Tiedostossa on oltava kaksi saraketta tuotaville käyttäjille ilman sarakeotsikoita: sähköpostiosoitteet ensimmäisessä ja nimi toisessa sarakkeessa (sähköposti, nimi). Vältä erikoismerkkejä nimessä, kuten `<>?%&^*#@()[]=+:;"{}\|`.' title: Lataa CSV-tiedosto upload: Lataa + reminders: + create: + error: Muistutusten luonti epäonnistui. + success: + one: "%{count} käyttäjää muistutetaan." + other: "%{count} käyttäjää muistutetaan." + new: + submit: Lähetä resource_permissions: edit: submit: Lähetä @@ -895,6 +931,7 @@ fi-pl: gallery: add_images: Lisää kuvia delete_image: Poista kuva + edit_images: Muokkaa kuvia gallery_legend: Lisää kuvagalleria (valinnainen) static_page_topics: create: @@ -955,7 +992,7 @@ fi-pl: static_pages: Sivut statistics: Toiminta user_groups: Käyttäjäryhmät - users: Osallistujat + users: Hallintakäyttäjät user_group: csv_verify: invalid: CSV-tiedoston käsittelyssä tapahtui virhe. @@ -991,7 +1028,7 @@ fi-pl: role: Rooli new: create: Kutsu - title: Kutsu käyttäjä hallinnoijaksi + title: Luo uusi hallintakäyttäjä users_statistics: users_count: admins: Ylläpitäjät @@ -1038,7 +1075,7 @@ fi-pl: models: moderation: fields: - created_at: Luonnin ajankohta + created_at: Luontipäivämäärä deleted_resource: Poistettu tietue hidden_at: Piilotuksen ajankohta participatory_space: Osallistumistila @@ -1046,7 +1083,7 @@ fi-pl: reportable_id: ID reportable_type: Tyyppi reported_content_url: Raportoidun sisällön URL - reports: Raportit + reports: Ilmoitukset visit_url: Vieraile URL-osoitteessa report: fields: diff --git a/decidim-admin/config/locales/fi.yml b/decidim-admin/config/locales/fi.yml index 1ce09f917594d..cd7f808dc57af 100644 --- a/decidim-admin/config/locales/fi.yml +++ b/decidim-admin/config/locales/fi.yml @@ -1,3 +1,4 @@ +--- fi: activemodel: attributes: @@ -14,17 +15,24 @@ fi: description: Kuvaus file: Tiedosto title: Liitetiedoston tai kuvan nimi + weight: Järjestysnumero attachment_collection: description: Kuvaus name: Nimi + weight: Järjestysnumero category: description: Kuvaus name: Nimi parent_id: Yläaihepiiri + weight: Järjestysnumero component: name: Nimi published_at: Julkaistu osoitteessa weight: Järjestysnumero + external_domain: + value: Arvo + help_section: + content: Sisältö id: ID import: user_group_id: Tuo käyttäjänä @@ -92,6 +100,9 @@ fi: welcome_notification_body: Tervetuloilmoituksen runko welcome_notification_subject: Tervetuloilmoituksen otsikko youtube_handler: YouTube-käsittelijä + participatory_space_private_user: + email: Sähköpostiosoite + name: Nimi scope: code: Koodi name: Nimi @@ -113,6 +124,7 @@ fi: show_in_footer: Näytä alatunnisteessa slug: URL-tunniste title: Otsikko + topic_id: Aihe weight: Järjestysnumero static_page_topic: description: Kuvaus @@ -133,6 +145,14 @@ fi: allowed_file_content_types: Virheellinen kuvatiedosto official_img_header: allowed_file_content_types: Virheellinen kuvatiedosto + participatory_space_private_user_csv_import: + attributes: + file: + malformed: Virheellinen tuontitiedosto, lue ohjeet huolellisesti ja varmista, että tiedosto on UTF-8 muodossa. + user_group_csv_verification: + attributes: + file: + malformed: Virheellinen tuontitiedosto, lue ohjeet huolellisesti ja varmista, että tiedosto on UTF-8 muodossa. new_import: attributes: file: @@ -177,7 +197,7 @@ fi: reject: Hylkää share: Jaa user: - new: Uusi käyttäjä + new: Uusi hallintakäyttäjä verify: Vahvista admin_terms_of_use: accept: @@ -260,6 +280,8 @@ fi: update: error: Liitteen päivitys epäonnistui. success: Liitteen luonti onnistui. + attachments_privacy_warning: + message: Ole varovainen, kun työskentelet liitetiedostojen kanssa yksityisessä tilassa. Kuka tahansa osallistuja voi jakaa tämän asiakirjan muille. autocomplete: no_results: Ei tuloksia search_prompt: Kirjoita vähintään kolme merkkiä hakuun @@ -342,7 +364,7 @@ fi: dashboard: show: view_more_logs: Näytä lisää lokitietoja - welcome: Tervetuloa Decidimin hallintapaneeliin. + welcome: Tervetuloa hallintapaneeliin. domain_whitelist: form: domain_too_short: Verkkotunnus on liian lyhyt @@ -812,8 +834,8 @@ fi: title: Sallittujen ulkoisten verkkotunnusten lista organization_homepage: edit: - active_content_blocks: Aktiiviset sisältöblokit - inactive_content_blocks: Ei-aktiiviset sisältöblokit + active_content_blocks: Aktiiviset sisältölohkot + inactive_content_blocks: Käytöstä poistetut sisältölohkot organization_homepage_content_blocks: edit: update: Päivitä @@ -835,9 +857,23 @@ fi: invalid: CSV-tiedoston käsittely epäonnistui. success: CSV-tiedosto ladattu onnistuneesti. Lähetämme kutsusähköpostin osallistujille. Tämä voi kestää hetken. new: + destroy: + button: Poista kaikki yksityiset osallistujat + confirm: Oletko varma, että haluat poistaa kaikki yksityiset osallistujat? Tätä toimintoa ei voi peruuttaa ja poistettuja osallistujia ei voi palauttaa. + empty: Tässä osallistumistilassa ei ole yksityisiä osallistujia. + explanation: Tässä osallistumistilassa on %{count} yksityistä osallistujaa. + title: Poista kaikki yksityiset osallistujat explanation: 'Lataa CSV-tiedosto osallistumistilan käyttäjistä. Tiedostossa on oltava kaksi saraketta tuotaville käyttäjille ilman sarakeotsikoita: sähköpostiosoitteet ensimmäisessä ja nimi toisessa sarakkeessa (sähköposti, nimi). Vältä erikoismerkkejä nimessä, kuten `<>?%&^*#@()[]=+:;"{}\|`.' title: Lataa CSV-tiedosto upload: Lataa + reminders: + create: + error: Muistutusten luonti epäonnistui. + success: + one: "%{count} käyttäjää muistutetaan." + other: "%{count} käyttäjää muistutetaan." + new: + submit: Lähetä resource_permissions: edit: submit: Lähetä @@ -895,6 +931,7 @@ fi: gallery: add_images: Lisää kuvia delete_image: Poista kuva + edit_images: Muokkaa kuvia gallery_legend: Lisää kuvagalleria (valinnainen) static_page_topics: create: @@ -955,7 +992,7 @@ fi: static_pages: Sivut statistics: Toiminta user_groups: Käyttäjäryhmät - users: Osallistujat + users: Hallintakäyttäjät user_group: csv_verify: invalid: CSV-tiedoston käsittely epäonnistui. @@ -991,7 +1028,7 @@ fi: role: Rooli new: create: Kutsu - title: Kutsu käyttäjä hallinnointikäyttäjäksi + title: Luo uusi hallintakäyttäjä users_statistics: users_count: admins: Ylläpitäjät @@ -1038,7 +1075,7 @@ fi: models: moderation: fields: - created_at: Luonnin ajankohta + created_at: Luontipäivämäärä deleted_resource: Poistettu tietue hidden_at: Piilotuksen ajankohta participatory_space: Osallistumistila @@ -1046,7 +1083,7 @@ fi: reportable_id: ID reportable_type: Tyyppi reported_content_url: Raportoidun sisällön URL - reports: Raportit + reports: Ilmoitukset visit_url: Vieraile URL-osoitteessa report: fields: diff --git a/decidim-admin/config/locales/fr-CA.yml b/decidim-admin/config/locales/fr-CA.yml index a8a2180f142bb..0c51ed67de7d7 100644 --- a/decidim-admin/config/locales/fr-CA.yml +++ b/decidim-admin/config/locales/fr-CA.yml @@ -1,3 +1,4 @@ +--- fr-CA: activemodel: attributes: @@ -14,17 +15,24 @@ fr-CA: description: Description file: Fichier title: Nom de la pièce jointe ou de l'image + weight: Rang d'affichage attachment_collection: description: Description name: Titre + weight: Rang d'affichage category: description: Description name: Titre parent_id: Parent + weight: Rang d'affichage component: name: Titre published_at: Publiée à weight: Rang + external_domain: + value: Valeur + help_section: + content: Contenu id: ID import: user_group_id: Créer des imports en tant que @@ -92,6 +100,9 @@ fr-CA: welcome_notification_body: Corps du mail de bienvenue welcome_notification_subject: Objet du mail de bienvenue youtube_handler: Gestionnaire YouTube + participatory_space_private_user: + email: Email + name: Nom scope: code: Code name: Titre @@ -113,6 +124,7 @@ fr-CA: show_in_footer: Montrer dans le pied de page slug: Identifiant title: Titre + topic_id: Sujet weight: Rang static_page_topic: description: La description @@ -133,6 +145,14 @@ fr-CA: allowed_file_content_types: Fichier image invalide official_img_header: allowed_file_content_types: Fichier image invalide + participatory_space_private_user_csv_import: + attributes: + file: + malformed: Fichier d'importation mal formé, veuillez lire attentivement les instructions et assurez-vous que le fichier est encodé en UTF-8. + user_group_csv_verification: + attributes: + file: + malformed: Fichier d'importation mal formé, veuillez lire attentivement les instructions et assurez-vous que le fichier est encodé en UTF-8. new_import: attributes: file: @@ -177,7 +197,7 @@ fr-CA: reject: Rejeter share: Partager user: - new: Nouvel utilisateur + new: Nouvel administrateur verify: Vérifier admin_terms_of_use: accept: @@ -260,6 +280,8 @@ fr-CA: update: error: Une erreur s'est produite lors de la mise à jour de ce document lié. success: Document lié mis à jour avec succès. + attachments_privacy_warning: + message: Soyez prudent lorsque vous travaillez avec des pièces jointes dans un espace privé. Tout participant pourrait partager ce document à d'autres. autocomplete: no_results: Aucun résultat trouvé search_prompt: Renseignez au moins trois caractères pour lancer la recherche @@ -342,7 +364,7 @@ fr-CA: dashboard: show: view_more_logs: Afficher plus - welcome: Bienvenue dans l'espace d'administration de Decidim. + welcome: Bienvenue dans l'espace d'administration. domain_whitelist: form: domain_too_short: Le nom de domaine est trop court @@ -835,9 +857,23 @@ fr-CA: invalid: Une erreur s'est produite lors de la lecture du fichier CSV. success: Fichier CSV a été transféré avec succès, nous envoyons un courriel d'invitation aux participants. Cela peut prendre un certain temps. new: + destroy: + button: Supprimer tous les utilisateurs privés + confirm: Êtes-vous sûr de vouloir supprimer tous les utilisateurs privés ? Cette action ne peut pas être annulée, vous ne pourrez pas les récupérer. + empty: Vous n'avez aucun utilisateur privé. + explanation: Vous avez %{count} utilisateurs privés. + title: Supprimer les utilisateurs privés explanation: 'Téléchargez votre fichier CSV. Il doit avoir deux colonnes avec dans la première colonne les emails, et dans la deuxième colonne les noms (email, nom) des utilisateurs que vous souhaitez ajouter à l''espace participatif, sans en-tête. Évitez les caractères spéciaux comme `<>?%&^*#@()[]=+:;"{}\|` dans les noms des utilisateurs.' title: Téléchargez votre fichier CSV upload: Télécharger + reminders: + create: + error: Il y a eu un problème lors de la création des rappels. + success: + one: "%{count} utilisateur recevra un rappel." + other: "%{count} utilisateurs recevront un rappel." + new: + submit: Envoyer resource_permissions: edit: submit: Soumettre @@ -895,6 +931,7 @@ fr-CA: gallery: add_images: Ajouter des images delete_image: Supprimer l'image + edit_images: Modifier les images gallery_legend: Ajouter une galerie d'images (facultatif) static_page_topics: create: @@ -955,7 +992,7 @@ fr-CA: static_pages: Pages statistics: Activité user_groups: Groupes d'utilisateurs - users: Participants + users: Administrateurs user_group: csv_verify: invalid: Une erreur s'est produite lors de la lecture du fichier CSV. @@ -991,7 +1028,7 @@ fr-CA: role: Rôle new: create: Inviter - title: Inviter l'utilisateur en tant qu'administrateur + title: Inviter un nouvel administrateur users_statistics: users_count: admins: Administrateurs @@ -1046,7 +1083,7 @@ fr-CA: reportable_id: ID reportable_type: Type reported_content_url: URL - reports: Motif + reports: Signalements visit_url: Visitez l'URL report: fields: diff --git a/decidim-admin/config/locales/fr.yml b/decidim-admin/config/locales/fr.yml index 75e8c0dbffba0..bcaa30c5a9faa 100644 --- a/decidim-admin/config/locales/fr.yml +++ b/decidim-admin/config/locales/fr.yml @@ -1,3 +1,4 @@ +--- fr: activemodel: attributes: @@ -14,17 +15,24 @@ fr: description: Description file: Fichier title: Nom de la pièce jointe ou de l'image + weight: Rang d'affichage attachment_collection: description: Description name: Titre + weight: Rang d'affichage category: description: Description name: Titre parent_id: Parent + weight: Rang d'affichage component: name: Titre published_at: Publiée à weight: Rang d'affichage + external_domain: + value: Valeur + help_section: + content: Contenu id: ID import: user_group_id: Créer des imports en tant que @@ -92,6 +100,9 @@ fr: welcome_notification_body: Corps du mail de bienvenue welcome_notification_subject: Objet du mail de bienvenue youtube_handler: Gestionnaire YouTube + participatory_space_private_user: + email: Email + name: Nom scope: code: Code name: Titre @@ -113,6 +124,7 @@ fr: show_in_footer: Montrer dans le pied de page slug: Identifiant title: Titre + topic_id: Sujet weight: Rang d'affichage static_page_topic: description: La description @@ -133,6 +145,14 @@ fr: allowed_file_content_types: Fichier image invalide official_img_header: allowed_file_content_types: Fichier image invalide + participatory_space_private_user_csv_import: + attributes: + file: + malformed: Fichier d'importation mal formé, veuillez lire attentivement les instructions et assurez-vous que le fichier est encodé en UTF-8. + user_group_csv_verification: + attributes: + file: + malformed: Fichier d'importation mal formé, veuillez lire attentivement les instructions et assurez-vous que le fichier est encodé en UTF-8. new_import: attributes: file: @@ -177,7 +197,7 @@ fr: reject: Rejeter share: Partager user: - new: Nouvel utilisateur + new: Nouvel administrateur verify: Vérifier admin_terms_of_use: accept: @@ -260,6 +280,8 @@ fr: update: error: Une erreur s'est produite lors de la mise à jour de ce document lié. success: Document lié mis à jour avec succès. + attachments_privacy_warning: + message: Soyez prudent lorsque vous travaillez avec des pièces jointes dans un espace privé. Tout participant pourrait partager ce document à d'autres. autocomplete: no_results: Aucun résultat trouvé search_prompt: Renseignez au moins trois caractères pour lancer la recherche @@ -342,7 +364,7 @@ fr: dashboard: show: view_more_logs: Afficher plus - welcome: Bienvenue dans l'espace d'administration de Decidim. + welcome: Bienvenue dans l'espace d'administration. domain_whitelist: form: domain_too_short: Le nom de domaine est trop court @@ -835,9 +857,23 @@ fr: invalid: Une erreur s'est produite lors de la lecture du fichier CSV. success: Fichier CSV a été transféré avec succès, nous envoyons un courriel d'invitation aux participants. Cela peut prendre un certain temps. new: + destroy: + button: Supprimer tous les utilisateurs privés + confirm: Êtes-vous sûr de vouloir supprimer tous les utilisateurs privés ? Cette action ne peut pas être annulée, vous ne pourrez pas les récupérer. + empty: Vous n'avez aucun utilisateur privé. + explanation: Vous avez %{count} utilisateurs privés. + title: Supprimer les utilisateurs privés explanation: 'Téléchargez votre fichier CSV. Il doit avoir deux colonnes avec dans la première colonne les emails, et dans la deuxième colonne les noms (email, nom) des utilisateurs que vous souhaitez ajouter à l''espace participatif, sans en-tête. Évitez les caractères spéciaux comme `<>?%&^*#@()[]=+:;"{}\|` dans les noms des utilisateurs.' title: Téléchargez votre fichier CSV upload: Télécharger + reminders: + create: + error: Il y a eu un problème lors de la création des rappels. + success: + one: "%{count} utilisateur recevra un rappel." + other: "%{count} utilisateurs recevront un rappel." + new: + submit: Envoyer resource_permissions: edit: submit: Soumettre @@ -895,6 +931,7 @@ fr: gallery: add_images: Ajouter des images delete_image: Supprimer l'image + edit_images: Modifier les images gallery_legend: Ajouter une galerie d'images (facultatif) static_page_topics: create: @@ -955,7 +992,7 @@ fr: static_pages: Pages statistics: Activité user_groups: Groupes d'utilisateurs - users: Participants + users: Administrateurs user_group: csv_verify: invalid: Une erreur s'est produite lors de la lecture du fichier CSV. @@ -991,7 +1028,7 @@ fr: role: Rôle new: create: Inviter - title: Inviter l'utilisateur en tant qu'administrateur + title: Inviter un nouvel administrateur users_statistics: users_count: admins: Administrateurs @@ -1046,7 +1083,7 @@ fr: reportable_id: ID reportable_type: Type reported_content_url: URL - reports: Motif + reports: Signalements visit_url: Visitez l'URL report: fields: diff --git a/decidim-admin/config/locales/ga-IE.yml b/decidim-admin/config/locales/ga-IE.yml index 45baa997932d6..bc0f4e6872b6d 100644 --- a/decidim-admin/config/locales/ga-IE.yml +++ b/decidim-admin/config/locales/ga-IE.yml @@ -1,3 +1,4 @@ +--- ga: activemodel: attributes: diff --git a/decidim-admin/config/locales/gl.yml b/decidim-admin/config/locales/gl.yml index d69bb61d9dc1f..4f34f040f9050 100644 --- a/decidim-admin/config/locales/gl.yml +++ b/decidim-admin/config/locales/gl.yml @@ -1,3 +1,4 @@ +--- gl: activemodel: attributes: @@ -172,7 +173,7 @@ gl: reject: Rexeitar share: Compartir user: - new: Novo usuario + new: Novo administrador verify: Verifique admin_terms_of_use: accept: @@ -251,6 +252,8 @@ gl: update: error: Produciuse un erro ao actualizar este anexo. success: Adxunto actualizado correctamente. + attachments_privacy_warning: + message: Ten coidado ao traballar con ficheiros anexos nun espazo privado. Calquera participante podería compartir este documento con outra xente. autocomplete: no_results: Non se atoparon resultados search_prompt: Escriba polo menos tres caracteres para buscar @@ -331,7 +334,7 @@ gl: dashboard: show: view_more_logs: Ver máis rexistros - welcome: Benvido ao Panel de administración de decisións. + welcome: Benvido/a ao panel de administración. domain_whitelist: form: domain_too_short: Dominio curto de máis @@ -815,6 +818,14 @@ gl: explanation: 'Sube o teu ficheiro CSV. Ten de ter dúas columnas co correo electrónico na primeira e o nome na última (correo, nome) dos usuarios que desexes engadir ao espazo de participación, sen cabeceiras. Evita empregar os seguintes caracteres `<>?%&^*#@()[]=+:;"{}\|` no nome de usuario.' title: Sube o teu ficheiro CSV upload: Subir + reminders: + create: + error: Produciuse un problema ao crear os recordatorios. + success: + one: "Lembrarase a %{count} usuario." + other: "Lembrarase a %{count} usuarios." + new: + submit: Enviar resource_permissions: edit: submit: Enviar @@ -872,6 +883,7 @@ gl: gallery: add_images: Engadir imaxes delete_image: Eliminar imaxe + edit_images: Editar imaxes gallery_legend: Engadir unha galería de imaxes (opcional) static_page_topics: create: @@ -932,7 +944,7 @@ gl: static_pages: Páxinas statistics: Actividade user_groups: Grupos de usuarios - users: Participantes + users: Administradores user_group: csv_verify: invalid: Produciuse un erro ao ler o ficheiro CSV. @@ -968,7 +980,7 @@ gl: role: Rol new: create: Invitar - title: Convidar ao usuario como administrador + title: Convidar a un novo administrador users_statistics: users_count: admins: Administradores diff --git a/decidim-admin/config/locales/hu.yml b/decidim-admin/config/locales/hu.yml index 051a6815c1e84..661909c5d4d31 100644 --- a/decidim-admin/config/locales/hu.yml +++ b/decidim-admin/config/locales/hu.yml @@ -1,3 +1,4 @@ +--- hu: activemodel: attributes: @@ -177,7 +178,7 @@ hu: reject: Elutasít share: Megosztás user: - new: Új felhasználó + new: Új adminisztrátor verify: EllenÅ‘rzés admin_terms_of_use: accept: @@ -259,6 +260,8 @@ hu: update: error: Hiba történt a melléklet frissítése során. success: Melléklet frissítése sikeres. + attachments_privacy_warning: + message: Legyen óvatos a mellékletek kezelése során. Bármely résztvevÅ‘ megoszthatja a dokumentumokat bárkivel. autocomplete: no_results: Nincs találat search_prompt: Legalább három karakter szükséges a kereséshez @@ -341,7 +344,7 @@ hu: dashboard: show: view_more_logs: További naplók megtekintése - welcome: Ãœdvözöljük a Decidim Admin Panelben. + welcome: Ãœdvözölünk az Admin Panelben. domain_whitelist: form: domain_too_short: Túl rövid domain @@ -831,9 +834,23 @@ hu: invalid: Hiba történt a CSV fájl olvasásában. success: A CSV-fájl sikeresen feltöltÅ‘dött, meghívó e-mailt küldünk a résztvevÅ‘knek. Ez eltarthat egy ideig. new: + destroy: + button: Az összes privát felhasználó törlése + confirm: Biztosan törölni akarja az összes privát felhasználót? Ezt a műveletet nem tudja visszavonni, vagy a felhasználókat késÅ‘bb helyreállítani. + empty: Nincsenek privát résztvevÅ‘k. + explanation: '%{count} privát résztvevÅ‘je van.' + title: Privát felhasználók törlése explanation: 'Töltse fel a CSV-fájlt. Két oszlopnak kell lennie, e-mail címmel a fájl elsÅ‘ oszlopában, és a fájl utolsó oszlopában (e-mail, név) azoknak a felhasználóknak az adataival, akiket fel akar venni a részvételi térbe, fejlécek nélkül. Kerülje az olyan érvénytelen karakterek használatát, mint a `<>?%&^*#@()[]=+:;"{}\|` a felhasználónévben.' title: Töltse fel a CSV fájlod upload: Feltölt + reminders: + create: + error: Hiba történt a bejegyzés létrehozása során. + success: + one: "%{count} felhasználó emlékeztetÅ‘t fog kapni." + other: "%{count} felhasználó emlékeztetÅ‘t fog kapni." + new: + submit: Küldés resource_permissions: edit: submit: Beküldés @@ -891,6 +908,7 @@ hu: gallery: add_images: Képek hozzáadása delete_image: Kép törlése + edit_images: Kép szerkesztése gallery_legend: Képgaléria hozzáadása (opcionális) static_page_topics: create: @@ -951,7 +969,7 @@ hu: static_pages: Oldalak statistics: Tevékenység user_groups: Csoportok - users: RésztvevÅ‘k + users: Adminisztrátorok user_group: csv_verify: invalid: Hiba történt a CSV fájl olvasásában. @@ -987,7 +1005,7 @@ hu: role: Szerep new: create: Meghívás - title: A résztvevÅ‘ meghívása rendszergazdaként + title: Új adminisztrátor létrehozása users_statistics: users_count: admins: Adminok diff --git a/decidim-admin/config/locales/id-ID.yml b/decidim-admin/config/locales/id-ID.yml index 6e041418cc7cb..62effdca1819d 100644 --- a/decidim-admin/config/locales/id-ID.yml +++ b/decidim-admin/config/locales/id-ID.yml @@ -1,3 +1,4 @@ +--- id: activemodel: attributes: @@ -245,7 +246,6 @@ id: dashboard: show: view_more_logs: Lihat lebih banyak log - welcome: Selamat datang di Panel Admin Decidim. exports: export_as: "%{name} sebagai %{export_format}" notice: Ekspor Anda sedang dalam proses. Anda akan menerima email setelah selesai. @@ -597,7 +597,6 @@ id: scopes: Scopes static_pages: Halaman user_groups: Grup Pengguna - users: Peserta user_group: csv_verify: invalid: Ada kesalahan saat membaca file CSV. @@ -633,7 +632,6 @@ id: role: Peran new: create: Undang - title: Undang pengguna sebagai administrator users_statistics: users_count: admins: Admin @@ -661,10 +659,10 @@ id: models: moderation: fields: + created_at: Tanggal pembuatan hidden_at: Tersembunyi di report_count: Menghitung reported_content_url: URL konten yang dilaporkan - reports: Laporan visit_url: Kunjungi URL errors: messages: diff --git a/decidim-admin/config/locales/is-IS.yml b/decidim-admin/config/locales/is-IS.yml index 6fee5d3efc480..7a2f298af3009 100644 --- a/decidim-admin/config/locales/is-IS.yml +++ b/decidim-admin/config/locales/is-IS.yml @@ -1,4 +1,5 @@ -is-IS: +--- +is: activemodel: attributes: area: @@ -140,8 +141,6 @@ is-IS: permissions: Heimildir reject: Hafna share: Deila - user: - new: Nýr notandi verify: Staðfestu area_types: create: @@ -251,7 +250,6 @@ is-IS: dashboard: show: view_more_logs: Skoða fleiri logs - welcome: Velkomin á Decidim Admin Panel. exports: export_as: "%{name} sem %{export_format}" notice: Útflutningur þinn er í gangi. Þú færð tölvupóst þegar það er lokið. @@ -445,6 +443,9 @@ is-IS: homepage_highlighted_content_banner_title: Hápunktur efni borði images: layout_appearance_title: Breyta útliti útlits + organization_homepage_content_blocks: + edit: + update: Uppfæra participatory_space_private_users: new: create: Búa til @@ -533,10 +534,10 @@ is-IS: models: moderation: fields: + created_at: Sköpunardegi hidden_at: Falinn á report_count: Telja reported_content_url: Tilkynnt efni vefslóð - reports: Skýrslur visit_url: Heimsókn vefslóð errors: messages: diff --git a/decidim-admin/config/locales/it.yml b/decidim-admin/config/locales/it.yml index 133f38d72fe7b..a515fdb26ffa6 100644 --- a/decidim-admin/config/locales/it.yml +++ b/decidim-admin/config/locales/it.yml @@ -1,3 +1,4 @@ +--- it: activemodel: attributes: @@ -171,8 +172,6 @@ it: permissions: Permessi reject: Rifiuta share: Condividi - user: - new: Nuovo utente verify: Verifica admin_terms_of_use: accept: @@ -336,7 +335,6 @@ it: dashboard: show: view_more_logs: Visualizza più registri - welcome: Benvenuti nel pannello di amministrazione di Decidim. domain_whitelist: form: domain_too_short: Dominio troppo corto @@ -774,7 +772,7 @@ it: inactive_content_blocks: Blocchi di contenuto inattivo organization_homepage_content_blocks: edit: - update: Aggiornare + update: Aggiorna participatory_space_private_users: create: error: Si è verificato un errore durante l'aggiunta di un utente privato per questo spazio partecipativo. @@ -796,6 +794,11 @@ it: explanation: 'Carica il file CSV. Il file deve contenere due colonne (e-mail e nome) senza intestazioni: nella prima sono elencati gli indirizzi e-mail degli utenti che si desidera aggiungere allo spazio partecipativo, nella seconda i loro nomi. Evita di usare caratteri non validi come `<>?%&^*#@()[]=+:;"{}\|` nella colonna dei nomi.' title: Carica il tuo file CSV upload: Carica File + reminders: + create: + error: Si è verificato un errore durante la creazione dei promemoria. + new: + submit: Invia resource_permissions: edit: submit: Invia @@ -913,7 +916,6 @@ it: static_pages: Pagine statistics: Attività user_groups: Gruppi di utenti - users: Partecipanti user_group: csv_verify: invalid: Si è verificato un errore durante la lettura del file CSV. @@ -949,7 +951,6 @@ it: role: Ruolo new: create: Invita - title: Invita l'utente in qualità di amministratrice/tore users_statistics: users_count: admins: Amministratori diff --git a/decidim-admin/config/locales/ja.yml b/decidim-admin/config/locales/ja.yml index 78f1c2cfee2a8..6fb265e8e58d7 100644 --- a/decidim-admin/config/locales/ja.yml +++ b/decidim-admin/config/locales/ja.yml @@ -1,3 +1,4 @@ +--- ja: activemodel: attributes: @@ -14,17 +15,24 @@ ja: description: 説明 file: ファイル title: 添付ファイルã¾ãŸã¯ç”»åƒå + weight: 並ã³é †ã®ä½ç½® attachment_collection: description: 説明 name: åå‰ + weight: 並ã³é †ã®ä½ç½® category: description: 説明 name: åå‰ parent_id: 親 + weight: 並ã³é †ã®ä½ç½® component: name: åå‰ published_at: 公開日時 weight: 順番ã®ä½ç½® + external_domain: + value: 値 + help_section: + content: 内容 id: ID import: user_group_id: インãƒãƒ¼ãƒˆã‚’ä½œæˆ @@ -92,6 +100,9 @@ ja: welcome_notification_body: ウェルカム通知本文 welcome_notification_subject: ウェルカム通知ã®ä»¶å youtube_handler: YouTube ãƒãƒ³ãƒ‰ãƒ©ãƒ¼ + participatory_space_private_user: + email: Eメールアドレス + name: åå‰ scope: code: コード name: åå‰ @@ -113,6 +124,7 @@ ja: show_in_footer: フッターã«è¡¨ç¤º slug: URL スラグ title: タイトル + topic_id: トピック weight: 順番ã®ä½ç½® static_page_topic: description: 説明 @@ -133,6 +145,14 @@ ja: allowed_file_content_types: 無効ãªç”»åƒãƒ•ã‚¡ã‚¤ãƒ« official_img_header: allowed_file_content_types: 無効ãªç”»åƒãƒ•ã‚¡ã‚¤ãƒ« + participatory_space_private_user_csv_import: + attributes: + file: + malformed: インãƒãƒ¼ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã®å½¢å¼ãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“。手順を見直ã—ã¦ã€ãƒ•ã‚¡ã‚¤ãƒ«ãŒUTF-8ã§ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。 + user_group_csv_verification: + attributes: + file: + malformed: インãƒãƒ¼ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã®å½¢å¼ãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“。手順を見直ã—ã¦ã€ãƒ•ã‚¡ã‚¤ãƒ«ãŒUTF-8ã§ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。 new_import: attributes: file: @@ -177,13 +197,14 @@ ja: reject: æ‹’å¦ share: 共有 user: - new: æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ + new: æ–°ã—ã„管ç†è€… verify: 確èªã™ã‚‹ admin_terms_of_use: accept: error: 管ç†è€…å‘ã‘利用è¦ç´„ã«åŒæ„中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ success: ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€ç®¡ç†è€…å‘ã‘利用è¦ç´„ã«åŒæ„ã—ã¾ã—ãŸã€‚ actions: + accept: 利用è¦ç´„ã«åŒæ„ã—ã¾ã™ are_you_sure: 管ç†è€…å‘ã‘利用è¦ç´„を削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ refuse: åŒæ„ã—ãªã„ title: 利用è¦ç´„ã«åŒæ„ã™ã‚‹ @@ -259,6 +280,8 @@ ja: update: error: ã“ã®æ·»ä»˜ãƒ•ã‚¡ã‚¤ãƒ«ã‚’更新中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ success: 添付ファイルãŒæ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚ + attachments_privacy_warning: + message: プライベートスペースã§æ·»ä»˜ãƒ•ã‚¡ã‚¤ãƒ«ã‚’扱ã†å ´åˆã¯æ³¨æ„ã—ã¦ãã ã•ã„.ã™ã¹ã¦ã®å‚加者ãŒã“ã®æ–‡æ›¸ã‚’ä»–ã®äººã¨å…±æœ‰ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ï¼Ž autocomplete: no_results: çµæžœãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—㟠search_prompt: 検索ã™ã‚‹ã«ã¯å°‘ãªãã¨ã‚‚3文字を入力ã—ã¦ãã ã•ã„ @@ -341,7 +364,7 @@ ja: dashboard: show: view_more_logs: ã‚‚ã£ã¨ãƒ­ã‚°ã‚’見る - welcome: Decidim 管ç†ç”»é¢ã¸ã‚ˆã†ã“ã。 + welcome: 管ç†ç”»é¢ã¸ã‚ˆã†ã“ã。 domain_whitelist: form: domain_too_short: ドメインãŒçŸ­ã™ãŽã¾ã™ @@ -830,9 +853,22 @@ ja: invalid: CSVファイルã®èª­ã¿è¾¼ã¿ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ success: CSVファイルãŒæ­£å¸¸ã«ã‚¢ãƒƒãƒ—ロードã•ã‚Œã¾ã—ãŸã€‚出席者ã«æ‹›å¾…メールをé€ä¿¡ã—ã¾ã™ã€‚時間ãŒã‹ã‹ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ new: + destroy: + button: ã™ã¹ã¦ã®ãƒ—ライベートå‚加者を削除 + confirm: ã™ã¹ã¦ã®ãƒ—ライベートå‚加者を削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿã“ã®æ“作ã¯å…ƒã«æˆ»ã›ãšã€å‰Šé™¤ã—ãŸãƒ‡ãƒ¼ã‚¿ã‚’復元ã§ãã¾ã›ã‚“。 + empty: プライベートã®å‚加者ã¯ã„ã¾ã›ã‚“。 + explanation: '%{count} 人ã®ãƒ—ライベートå‚加者ãŒã„ã¾ã™ã€‚' + title: プライベートå‚加者を削除 explanation: 'CSV ファイルをアップロードã—ã¾ã™ã€‚ファイル㯠1列目ã«é›»å­ãƒ¡ãƒ¼ãƒ«ã€2列目ã«åå‰ã‚’æŒã¤å½¢å¼ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™(email, name)。 ユーザーåã« `<>?%&^*#@()[]=+:;"{}\|`ã®ã‚ˆã†ãªç„¡åŠ¹ãªæ–‡å­—を使用ã—ãªã„ã§ãã ã•ã„。' title: CSVファイルをアップロード upload: アップロード + reminders: + create: + error: リマインダー作æˆä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ + success: + other: "%{count} ユーザーã«é€šçŸ¥ã•ã‚Œã¾ã™ã€‚" + new: + submit: é€ä¿¡ resource_permissions: edit: submit: é€ä¿¡ @@ -890,6 +926,7 @@ ja: gallery: add_images: ç”»åƒã‚’追加 delete_image: ç”»åƒã‚’削除 + edit_images: ç”»åƒã‚’編集 gallery_legend: ç”»åƒã‚®ãƒ£ãƒ©ãƒªãƒ¼ã‚’追加 (オプション) static_page_topics: create: @@ -950,7 +987,7 @@ ja: static_pages: ページ statistics: アクティビティ user_groups: グループ - users: å‚加者 + users: 管ç†è€… user_group: csv_verify: invalid: CSVファイルã®èª­ã¿è¾¼ã¿ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ @@ -986,7 +1023,7 @@ ja: role: ロール new: create: 招待 - title: 管ç†è€…ã¨ã—ã¦å‚加者を招待 + title: æ–°ã—ã„管ç†è€…を招待ã™ã‚‹ users_statistics: users_count: admins: 管ç†è€… @@ -1041,7 +1078,7 @@ ja: reportable_id: ID reportable_type: 種別 reported_content_url: 報告ã•ã‚ŒãŸã‚³ãƒ³ãƒ†ãƒ³ãƒ„ URL - reports: レãƒãƒ¼ãƒˆ + reports: 報告 visit_url: URL ã‚’å‚ç…§ report: fields: diff --git a/decidim-admin/config/locales/ka-GE.yml b/decidim-admin/config/locales/ka-GE.yml new file mode 100644 index 0000000000000..57a95cb04703c --- /dev/null +++ b/decidim-admin/config/locales/ka-GE.yml @@ -0,0 +1 @@ +ka: diff --git a/decidim-admin/config/locales/lb.yml b/decidim-admin/config/locales/lb.yml index eb59b47ebd642..c9d6aa7f26f08 100644 --- a/decidim-admin/config/locales/lb.yml +++ b/decidim-admin/config/locales/lb.yml @@ -1,3 +1,4 @@ +--- lb: activemodel: attributes: @@ -171,8 +172,6 @@ lb: permissions: Berechtigungen reject: Ablehnen share: Teilen - user: - new: Neuer Benutzer verify: Ãœberprüfen admin_terms_of_use: accept: @@ -336,7 +335,6 @@ lb: dashboard: show: view_more_logs: Weitere Protokolle anzeigen - welcome: Willkommen im Decidim Admin Panel. domain_whitelist: form: domain_too_short: Domain zu kurz @@ -911,7 +909,6 @@ lb: static_pages: Seiten statistics: Aktivität user_groups: Benutzergruppen - users: Teilnehmer user_group: csv_verify: invalid: Beim Lesen der CSV-Datei ist ein Fehler aufgetreten. @@ -947,7 +944,6 @@ lb: role: Rolle new: create: Einladen - title: Benutzer als Administrator einladen users_statistics: users_count: admins: Admins diff --git a/decidim-admin/config/locales/lt.yml b/decidim-admin/config/locales/lt.yml index 1b21e90a07894..168194f576a7b 100644 --- a/decidim-admin/config/locales/lt.yml +++ b/decidim-admin/config/locales/lt.yml @@ -1,3 +1,4 @@ +--- lt: activemodel: attributes: @@ -177,7 +178,7 @@ lt: reject: Atmesti share: Dalintis user: - new: Naujas naudotojas + new: Naujas administratorius verify: Patikrinti admin_terms_of_use: accept: @@ -259,6 +260,8 @@ lt: update: error: Atnaujinant šį priedÄ… iÅ¡kilo problema. success: Priedas atnaujintas. + attachments_privacy_warning: + message: ElkitÄ—s atsargiai su priedais privaÄiose aplinkose. Bet koks dalyvis gali pasidalinti dokumentais su kitais. autocomplete: no_results: Rezultatų nerasta search_prompt: Ä®veskite bent tris raides paieÅ¡kai pradÄ—ti @@ -341,7 +344,7 @@ lt: dashboard: show: view_more_logs: PeržiÅ«rÄ—ti daugiau ataskaitų - welcome: '„Decidim“ administratoriaus sritis.' + welcome: Sveiki atvykÄ™ į administratorių puslapį. domain_whitelist: form: domain_too_short: Domenas per trumpas @@ -842,9 +845,25 @@ lt: invalid: Skaitant CSV rinkmenÄ… iÅ¡kilo problema. success: CSV dokumentas įkeltas sÄ—kmingai, dalyviai kvieÄiami e. laiÅ¡ku - tai gali užtrukti. new: + destroy: + button: IÅ¡trinti visus privaÄius dalyvius + confirm: Ar tikrai norite iÅ¡trinti visus privaÄius dalyvius? Atlikus šį veiksmÄ… nebebus įmanoma sugražinti Å¡ių dalyvių į platformÄ…. + empty: Neturite privaÄių dalyvių. + explanation: Turite %{count} privaÄių dalyvių. + title: IÅ¡trinti privaÄius dalyvius explanation: 'Ä®kelkite CSV dokumentÄ…. Jis turi turÄ—ti du stulpelius su naudotojų el. paÅ¡tu pirmajame ir vardu paskutiniÄ…jame. Dokumente neturÄ—tų bÅ«ti laukų pavadinimų ir Å¡ių simbolių naudotojų varduose "<>?%&^*#@()[]=+:;"{}\|".' title: Ä®kelkite CSV dokumentÄ… upload: Ä®kelti + reminders: + create: + error: Kuriant priminimus iÅ¡kilo problema. + success: + one: "%{count} naudotojui bus priminta." + few: "%{count} naudotojams bus priminta." + many: "%{count} naudotojų bus priminta." + other: "%{count} naudotojams bus priminta." + new: + submit: Siųsti resource_permissions: edit: submit: Pateikti @@ -902,6 +921,7 @@ lt: gallery: add_images: PridÄ—ti paveikslÄ—lių delete_image: PaÅ¡alinti paveikslÄ—lį + edit_images: Redaguoti paveikslÄ—lį gallery_legend: PridÄ—ti paveikslÄ—lių galerijÄ… (Neprivaloma) static_page_topics: create: @@ -962,7 +982,7 @@ lt: static_pages: Puslapiai statistics: Veikla user_groups: GrupÄ—s - users: Dalyviai + users: Administratoriai user_group: csv_verify: invalid: Skaitant CSV rinkmenÄ… iÅ¡kilo problema. @@ -998,7 +1018,7 @@ lt: role: RolÄ— new: create: Pakviesti - title: Kviesti dalyvį kaip administratorių + title: Pakviesti naujÄ… administratorių users_statistics: users_count: admins: Administratoriai diff --git a/decidim-admin/config/locales/lv.yml b/decidim-admin/config/locales/lv.yml index c87065a03c5ee..e5db5eccbe9fe 100644 --- a/decidim-admin/config/locales/lv.yml +++ b/decidim-admin/config/locales/lv.yml @@ -1,3 +1,4 @@ +--- lv: activemodel: attributes: @@ -262,7 +263,6 @@ lv: dashboard: show: view_more_logs: SkatÄ«t vairÄk ierakstu - welcome: Laipni lÅ«dzam Decidim administratora panelÄ«. exports: export_as: "%{name} kÄ %{export_format}" notice: PaÅ¡laik notiek jÅ«su eksportÄ“Å¡ana. JÅ«s saņemsiet e-pastu, kad tÄ bÅ«s pabeigta. @@ -681,7 +681,6 @@ lv: static_pages: Lapas statistics: AktivitÄte user_groups: Grupas - users: DalÄ«bnieki user_group: csv_verify: invalid: CSV faila lasÄ«Å¡anas laikÄ radÄs problÄ“ma. @@ -717,7 +716,6 @@ lv: role: Loma new: create: UzaicinÄt - title: UzaicinÄt dalÄ«bnieku par administratoru users_statistics: users_count: admins: Administratori @@ -749,10 +747,10 @@ lv: models: moderation: fields: + created_at: Izveides datums hidden_at: PaslÄ“pts plkst. report_count: Skaits reported_content_url: PaziņotÄ satura URL - reports: Ziņojumi visit_url: ApmeklÄ“t URL errors: messages: diff --git a/decidim-admin/config/locales/nl.yml b/decidim-admin/config/locales/nl.yml index ad1350d735f3a..38585c64d87d4 100644 --- a/decidim-admin/config/locales/nl.yml +++ b/decidim-admin/config/locales/nl.yml @@ -1,3 +1,4 @@ +--- nl: activemodel: attributes: @@ -177,7 +178,7 @@ nl: reject: Weigeren share: Deel user: - new: Nieuwe gebruiker + new: Nieuwe admin verify: Verifiëren admin_terms_of_use: accept: @@ -259,6 +260,8 @@ nl: update: error: Er is een fout opgetreden bij het bijwerken van deze bijlage. success: Bijlage is succesvol bijgewerkt. + attachments_privacy_warning: + message: Wees voorzichtig bij het werken met bijlagen in een privéruimte. Elke deelnemer kan dit document delen met anderen. autocomplete: no_results: geen resultaten gevonden search_prompt: Typ minimaal drie tekens om te zoeken @@ -341,7 +344,7 @@ nl: dashboard: show: view_more_logs: Bekijk meer logs - welcome: Welkom bij het Decidim Admin Panel. + welcome: Welkom bij de beheerder omgeving. domain_whitelist: form: domain_too_short: Domein te kort @@ -834,9 +837,23 @@ nl: invalid: Er is een fout opgetreden bij het lezen van het CSV-bestand. success: Het CSV-bestand is succesvol geüploaded. We sturen een uitnodigingsmail naar de deelnemers. Dit kan even duren. new: + destroy: + button: Verwijder alle privé deelnemers + confirm: Weet je zeker dat je alle privédeelnemers wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt, je kan ze achteraf niet herstellen. + empty: Je hebt geen privé deelnemers. + explanation: Je hebt %{count} privédeelnemers. + title: Verwijder privé deelnemer explanation: 'Upload het CSV-bestand zonder headers. Het moet uit twee kolommen bestaan, met het e-mailadres in de eerste kolom en de naam in de laatste kolom van de gebruikers die je wil toevoegen aan de participatieve ruimte (e-mail, naam). Vermijd tekens als `<>?%&^*#@()[]=+:;"{}\|` in de namen.' title: Upload het CSV-bestand upload: Upload + reminders: + create: + error: Er is een probleem opgetreden bij het maken van herinneringen. + success: + one: "%{count} gebruiker zal een herinnering krijgen." + other: "%{count} gebruikers zullen een herinnering krijgen." + new: + submit: Verzenden resource_permissions: edit: submit: Bevestigen @@ -894,6 +911,7 @@ nl: gallery: add_images: Afbeeldingen toevoegen delete_image: Afbeelding verwijderen + edit_images: Bewerk afbeeldingen gallery_legend: Voeg een afbeeldingsgalerij toe (optioneel) static_page_topics: create: @@ -954,7 +972,7 @@ nl: static_pages: Pagina's statistics: Activiteit user_groups: groepen - users: Deelnemers + users: Beheerders user_group: csv_verify: invalid: Er is een fout opgetreden bij het lezen van het CSV-bestand. @@ -990,7 +1008,7 @@ nl: role: Rol new: create: Nodig uit - title: Nodig deelnemer uit als beheerder + title: Nodig gebruiker uit als beheerder users_statistics: users_count: admins: Admins @@ -1044,7 +1062,7 @@ nl: reportable_id: ID reportable_type: Type reported_content_url: Gerapporteerde inhouds-URL - reports: Meldingen + reports: Rapporten visit_url: Bezoek URL report: fields: diff --git a/decidim-admin/config/locales/no.yml b/decidim-admin/config/locales/no.yml index 2cd66e1bcbacf..cfb1f85918601 100644 --- a/decidim-admin/config/locales/no.yml +++ b/decidim-admin/config/locales/no.yml @@ -1,3 +1,4 @@ +--- "no": activemodel: attributes: @@ -177,7 +178,7 @@ reject: Avvis share: Del user: - new: Ny bruker + new: Ny admin verify: Verifiser admin_terms_of_use: accept: @@ -259,6 +260,8 @@ update: error: Det oppsto et problem med Ã¥ oppdatere dette vedlegget. success: Vedlegg ble oppdatert. + attachments_privacy_warning: + message: Vær forsiktig nÃ¥r du arbeider med vedlegg i et privat rom. Alle deltakere kan dele dette dokumentet med andre. autocomplete: no_results: Ingen resultat funnet search_prompt: Skriv minst tre tegn for Ã¥ søke @@ -341,7 +344,7 @@ dashboard: show: view_more_logs: Vis flere logger - welcome: Velkommen til Decidim administrator Panel. + welcome: Velkommen til Admin-panelet. domain_whitelist: form: domain_too_short: Domene er for kort @@ -834,9 +837,23 @@ invalid: Det oppstod et problem med Ã¥ lese CSV-filen. success: CSV fil lastet opp. Vi sender en invitasjons email til deltakerne. Dette kan ta en stund. new: + destroy: + button: Slett alle private deltakere + confirm: Er du sikker pÃ¥ at du vil slette alle private deltakere? Denne handlingen kan ikke angres, du vil ikke kunne gjenopprette dem. + empty: Du har ingen private deltakere. + explanation: Du har %{count} private deltakere. + title: Slett private deltakere explanation: 'Last opp din CSV-fil. Det mÃ¥ være to kolonner uten overskrifter, e-post i den første kolonnen og navn i den siste kolonnen (e-post, navn) til brukerne du vil legge til i det deltakende rommet. UnngÃ¥ Ã¥ bruke ugyldige tegn som `<>?%&^*#@()[]=+:;"{}\″` med brukernavn.' title: Last opp din CSV fil upload: Last opp + reminders: + create: + error: Det oppsto et problem med Ã¥ opprette pÃ¥minnelser. + success: + one: "%{count} bruker vil bli pÃ¥minnet." + other: "%{count} brukere vil bli pÃ¥minnet." + new: + submit: Send resource_permissions: edit: submit: Send inn @@ -894,6 +911,7 @@ gallery: add_images: Legg til bilder delete_image: Slett bilde + edit_images: Rediger bilder gallery_legend: Legg til et bildegalleri (valgfritt) static_page_topics: create: @@ -954,7 +972,7 @@ static_pages: Sider statistics: Aktivitet user_groups: Grupper - users: Deltakere + users: Administratorer user_group: csv_verify: invalid: Det oppstod et problem med Ã¥ lese CSV-filen. @@ -990,7 +1008,7 @@ role: Rolle new: create: Inviter - title: Inviter deltaker som administrator + title: Inviter ny administrator users_statistics: users_count: admins: Adminer diff --git a/decidim-admin/config/locales/pl.yml b/decidim-admin/config/locales/pl.yml index ea63ddbbb5b7f..e795272bfcf9f 100644 --- a/decidim-admin/config/locales/pl.yml +++ b/decidim-admin/config/locales/pl.yml @@ -1,3 +1,4 @@ +--- pl: activemodel: attributes: @@ -340,7 +341,7 @@ pl: dashboard: show: view_more_logs: Zobacz wiÄ™cej logów - welcome: Witamy w panelu administracyjnym Decidim. + welcome: Witamy w Panelu Administracyjnym. domain_whitelist: form: domain_too_short: Domena jest zbyt krótka @@ -841,9 +842,22 @@ pl: invalid: WystÄ…piÅ‚ bÅ‚Ä…d podczas odczytu pliku CSV. success: Plik CSV zostaÅ‚ pomyÅ›lnie wgrany, wysyÅ‚amy e-mail z zaproszeniem do uczestników. To może zająć chwilÄ™. new: + destroy: + button: UsuÅ„ wszystkich prywatnych uczestników + title: UsuÅ„ prywatnych uczestników explanation: 'PrzeÅ›lij swój plik CSV. Plik musi skÅ‚adać siÄ™ z dwóch kolumn: w pierwszej kolumnie adresy e-mail, w drugiej kolumnie imiona (adres e-mail, imiÄ™) użytkowników, których chcesz dodać do przestrzeni partycypacyjnej; bez nagłówków. Unikaj używania niepoprawnych znaków takich jak `<>?%&^*#@()[]=+:;"{}\|` w imieniu użytkownika.' title: PrzeÅ›lij swój plik CSV upload: PrzeÅ›lij + reminders: + create: + error: WystÄ…piÅ‚ bÅ‚Ä…d podczas tworzenia przypomnieÅ„. + success: + one: "%{count} użytkownik otrzyma przypomnienie." + few: "%{count} użytkowników otrzyma przypomnienie." + many: "%{count} użytkowników otrzyma przypomnienie." + other: "%{count} użytkowników otrzyma przypomnienie." + new: + submit: WyÅ›lij resource_permissions: edit: submit: Zatwierdź @@ -901,6 +915,7 @@ pl: gallery: add_images: Dodaj obrazy delete_image: UsuÅ„ obraz + edit_images: Edytuj obrazy gallery_legend: Dodaj galeriÄ™ obrazów (opcjonalnie) static_page_topics: create: @@ -961,7 +976,7 @@ pl: static_pages: Strony statistics: Aktywność user_groups: Grupy użytkowników - users: Użytkownicy + users: Administratorzy user_group: csv_verify: invalid: WystÄ…piÅ‚ bÅ‚Ä…d podczas odczytu pliku CSV. @@ -997,7 +1012,7 @@ pl: role: Rola new: create: ZaproÅ› - title: ZaproÅ› użytkownika jako administratora + title: ZaproÅ› nowego administratora users_statistics: users_count: admins: Administratorzy diff --git a/decidim-admin/config/locales/pt-BR.yml b/decidim-admin/config/locales/pt-BR.yml index d17a28a27dacf..e8d0e06efcdef 100644 --- a/decidim-admin/config/locales/pt-BR.yml +++ b/decidim-admin/config/locales/pt-BR.yml @@ -1,3 +1,4 @@ +--- pt-BR: activemodel: attributes: @@ -170,8 +171,6 @@ pt-BR: permissions: Permissões reject: Negar share: Compartilhar - user: - new: Novo usuário verify: Verificar admin_terms_of_use: accept: @@ -330,7 +329,6 @@ pt-BR: dashboard: show: view_more_logs: Ver mais registros - welcome: Bem-vindo ao Decidim Admin Panel. domain_whitelist: form: domain_too_short: Domínio muito curto @@ -898,7 +896,6 @@ pt-BR: static_pages: Páginas statistics: Atividade user_groups: Grupos de usuários - users: Participantes user_group: csv_verify: invalid: Ocorreu um erro ao ler o arquivo CSV. @@ -934,7 +931,6 @@ pt-BR: role: Cargo new: create: Convite - title: Convide o usuário como administrador users_statistics: users_count: admins: Admins @@ -997,7 +993,7 @@ pt-BR: decidim: admin: global_moderations: - title: Moderações globais + title: Moderadores globais newsletters: title: Boletins informativos settings: diff --git a/decidim-admin/config/locales/pt.yml b/decidim-admin/config/locales/pt.yml index bb7170174fa23..6363519fbdea7 100644 --- a/decidim-admin/config/locales/pt.yml +++ b/decidim-admin/config/locales/pt.yml @@ -1,3 +1,4 @@ +--- pt: activemodel: attributes: @@ -171,8 +172,6 @@ pt: permissions: Permissões reject: Rejeitar share: Partilhar - user: - new: Novo utilizador verify: Verificar admin_terms_of_use: accept: @@ -336,7 +335,6 @@ pt: dashboard: show: view_more_logs: Ver mais registos - welcome: Bem-vindo ao Painel de Administração de Decidim. domain_whitelist: form: domain_too_short: Domínio demasiado curto @@ -913,7 +911,6 @@ pt: static_pages: Páginas statistics: Atividade user_groups: Grupos - users: Participantes user_group: csv_verify: invalid: Ocorreu um problema ao ler o ficheiro CSV. @@ -949,7 +946,6 @@ pt: role: Função new: create: Convidar - title: Convidar o(a) participante como administrador(a) users_statistics: users_count: admins: Administradores diff --git a/decidim-admin/config/locales/ro-RO.yml b/decidim-admin/config/locales/ro-RO.yml index acccb31b9b33b..57981c9a587c6 100644 --- a/decidim-admin/config/locales/ro-RO.yml +++ b/decidim-admin/config/locales/ro-RO.yml @@ -1,3 +1,4 @@ +--- ro: activemodel: attributes: @@ -14,17 +15,24 @@ ro: description: Descriere file: FiÅŸier title: Numele fiÈ™ierului sau al imaginii ataÈ™ate + weight: PoziÈ›ie attachment_collection: description: Descriere name: Nume + weight: PoziÈ›ie category: description: Descriere name: Nume parent_id: Categoria mamă + weight: PoziÈ›ie component: name: Nume published_at: Publicat în - weight: Ordinea în poziÈ›ionare + weight: PoziÈ›ie + external_domain: + value: Valoare + help_section: + content: ConÈ›inut id: ID import: user_group_id: Creează importuri ca @@ -92,6 +100,9 @@ ro: welcome_notification_body: ConÈ›inutul notificării de bun venit welcome_notification_subject: Subiectul notificării de bun venit youtube_handler: Responsabil YouTube + participatory_space_private_user: + email: E-mail + name: Nume scope: code: Cod name: Nume @@ -113,12 +124,13 @@ ro: show_in_footer: AfiÈ™ează în subsol slug: URL slug title: Titlu - weight: Ordinea în poziÈ›ionare + topic_id: Subiect + weight: PoziÈ›ie static_page_topic: description: Descriere show_in_footer: AfiÈ™ează în subsol title: Titlu - weight: Ordinea în poziÈ›ionare + weight: PoziÈ›ie user_group_csv_verification: file: FiÅŸier errors: @@ -133,6 +145,14 @@ ro: allowed_file_content_types: FiÈ™ier invalid official_img_header: allowed_file_content_types: FiÈ™ier invalid + participatory_space_private_user_csv_import: + attributes: + file: + malformed: FiÅŸier de import malformat, vă rugăm să citiÅ£i instrucÅ£iunile cu atenÅ£ie ÅŸi asiguraÅ£i-vă că fiÅŸierul este codificat UTF-8. + user_group_csv_verification: + attributes: + file: + malformed: FiÅŸier de import malformat, vă rugăm să citiÅ£i instrucÅ£iunile cu atenÅ£ie ÅŸi asiguraÅ£i-vă că fiÅŸierul este codificat UTF-8. new_import: attributes: file: @@ -177,7 +197,7 @@ ro: reject: Respinge share: Distribuie user: - new: Utilizator nou + new: Administrator nou verify: Verifică admin_terms_of_use: accept: @@ -260,6 +280,8 @@ ro: update: error: A apărut o eroare la actualizarea acestui ataÈ™ament. success: AtaÈ™amentul a fost actualizat cu succes. + attachments_privacy_warning: + message: FiÈ›i precaut atunci când lucraÈ›i cu ataÈ™amente într-un spaÈ›iu privat. Orice participant poate distribui acest document altora. autocomplete: no_results: Nu a fost găsit niciun rezultat search_prompt: TastaÈ›i cel puÈ›in trei caractere pentru a căuta @@ -342,7 +364,7 @@ ro: dashboard: show: view_more_logs: AfiÈ™ează mai multe înregistrări - welcome: Bine aÈ›i venit în Panoul de administrare Decidim. + welcome: Bine aÈ›i venit în Panoul de administrare. domain_whitelist: form: domain_too_short: Domeniul e prea scurt @@ -839,9 +861,24 @@ ro: invalid: A apărut o problemă la citirea fiÈ™ierului CSV. success: FiÈ™ier-ul CSV a fost încărcat cu succes, trimitem un e-mail de invitaÈ›ie participanÈ›ilor. Acest lucru ar putea dura puÈ›in timp. new: + destroy: + button: Șterge toÈ›i participanÈ›ii privaÈ›i + confirm: SunteÈ›i sigur că doriÈ›i să È™tergeÈ›i toÈ›i participanÈ›ii privaÈ›i? Această acÈ›iune nu poate fi anulată, È™i nu îi veÈ›i putea recupera. + empty: Nu aveÈ›i niciun participant privat. + explanation: AveÈ›i %{count} participanÈ›i privaÈ›i. + title: Ștergere participanÈ›i privaÈ›i explanation: 'ÃŽncărcă fiÅŸierul tău CSV. Trebuie să aibă două coloane cu e-mail în prima coloană a fiÈ™ierului È™i numele în ultima coloană (e-mail, numele) pentru utilizatorii pe care doriÅ£i să îi adăugaÅ£i în spaÅ£iul participativ, fără antet. Evită folosirea caracterelor invalide, cum ar fi `<>?%&^*#@()[]=+:;"{}\ ` în numele utilizatorului.' title: ÃŽncarcă fiÈ™ierul tău CSV upload: ÃŽncarcă + reminders: + create: + error: A apărut o eroare la crearea de memento-uri. + success: + one: "I se va reaminti utilizatorului." + few: "Se va reaminti celor %{count} utilizatori." + other: "Se va reaminti celor %{count} utilizatori." + new: + submit: Trimite resource_permissions: edit: submit: Trimite @@ -899,6 +936,7 @@ ro: gallery: add_images: Adaugă imagini delete_image: Șterge imaginea + edit_images: Editare imagini gallery_legend: Adaugă o galerie de imagini (opÈ›ional) static_page_topics: create: @@ -959,7 +997,7 @@ ro: static_pages: Pagini statistics: Activitate user_groups: Grupuri - users: ParticipanÈ›i + users: Administratori user_group: csv_verify: invalid: A apărut o problemă la citirea fiÈ™ierului CSV. @@ -995,7 +1033,7 @@ ro: role: Rol new: create: Invită - title: Invită participantul ca administrator + title: Invită un administrator nou users_statistics: users_count: admins: Administratori @@ -1047,6 +1085,7 @@ ro: hidden_at: Ascuns la participatory_space: SpaÈ›iu participativ report_count: Număr + reportable_id: ID reportable_type: Tip reported_content_url: URL-ul conÈ›inutului raportat reports: Rapoarte @@ -1063,7 +1102,7 @@ ro: decidim: admin: global_moderations: - title: Moderare globală + title: Moderări globale newsletters: title: Buletine informative settings: diff --git a/decidim-admin/config/locales/ru.yml b/decidim-admin/config/locales/ru.yml index eeec00789b2ca..131090ed32947 100644 --- a/decidim-admin/config/locales/ru.yml +++ b/decidim-admin/config/locales/ru.yml @@ -1,3 +1,4 @@ +--- ru: activemodel: attributes: @@ -249,7 +250,6 @@ ru: dashboard: show: view_more_logs: ПроÑмотреть другие журналы - welcome: Добро пожаловать в админ-панель ДеÑидим! exports: export_as: "%{name} как %{export_format}" notice: Идет Ñохранение в виде файла. Ð’Ñ‹ получите Ñлектронное пиÑьмо, когда оно будет завершено. @@ -501,6 +501,9 @@ ru: edit: active_content_blocks: Блоки дейÑтвующего Ñодержимого inactive_content_blocks: Блоки недейÑтвующего Ñодержимого + organization_homepage_content_blocks: + edit: + update: Обновить participatory_space_private_users: create: error: При попытке добавить чаÑтного учаÑтника в Ñто проÑтранÑтво ÑоучаÑÑ‚Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð¾ÑˆÐ»Ð° ошибка. @@ -575,7 +578,6 @@ ru: scopes: Охваты static_pages: Страницы user_groups: Группы учаÑтников - users: УчаÑтники user_group: reject: invalid: При отказе от Ñтой группы учаÑтников произошла ошибка. @@ -606,7 +608,6 @@ ru: role: Роль new: create: ПриглаÑить - title: ПриглаÑить учаÑтника в качеÑтве админиÑтратора users_statistics: users_count: admins: ÐдминиÑтраторы @@ -634,10 +635,10 @@ ru: models: moderation: fields: + created_at: Дата ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ hidden_at: 'Скрыто:' report_count: КоличеÑтво reported_content_url: Веб-Ð°Ð´Ñ€ÐµÑ Ð¾Ð±Ð¶Ð°Ð»Ð¾Ð²Ð°Ð½Ð½Ð¾Ð³Ð¾ Ñодержимого - reports: Жалобы visit_url: ПоÑетите веб-Ð°Ð´Ñ€ÐµÑ errors: messages: diff --git a/decidim-admin/config/locales/sk.yml b/decidim-admin/config/locales/sk.yml index 2d23aa3e93ec5..e96dbeab7be07 100644 --- a/decidim-admin/config/locales/sk.yml +++ b/decidim-admin/config/locales/sk.yml @@ -1,3 +1,4 @@ +--- sk: activemodel: attributes: @@ -264,7 +265,6 @@ sk: dashboard: show: view_more_logs: ZobraziÅ¥ viac logov - welcome: Vitajte v Administrátorskom Paneli Decidim. exports: export_as: "%{name} ako %{export_format}" notice: Váš export práve prebieha. Obdržíte e-mail po dokonÄení. @@ -688,7 +688,6 @@ sk: static_pages: Stránky statistics: Aktivita user_groups: Skupiny - users: ÚÄastníci user_group: csv_verify: invalid: Vyskytol sa problém s Äítaním súboru CSV. @@ -724,7 +723,6 @@ sk: role: Rola new: create: PozvaÅ¥ - title: PozvaÅ¥ úÄastníka ako administrátora users_statistics: users_count: admins: Administrátori @@ -756,10 +754,10 @@ sk: models: moderation: fields: + created_at: Dátum vytvorenia hidden_at: Skryté report_count: PoÄet reported_content_url: NahlásiÅ¥ URL obsahu - reports: Nahlásenia visit_url: NavÅ¡tíviÅ¥ URL errors: messages: diff --git a/decidim-admin/config/locales/sl.yml b/decidim-admin/config/locales/sl.yml index c533b0a0af289..ab8ac6ba48c26 100644 --- a/decidim-admin/config/locales/sl.yml +++ b/decidim-admin/config/locales/sl.yml @@ -1,3 +1,4 @@ +--- sl: activemodel: attributes: diff --git a/decidim-admin/config/locales/sr-CS.yml b/decidim-admin/config/locales/sr-CS.yml index c5428be3316a1..d048c1575068c 100644 --- a/decidim-admin/config/locales/sr-CS.yml +++ b/decidim-admin/config/locales/sr-CS.yml @@ -1,3 +1,4 @@ +--- sr: activemodel: attributes: @@ -264,7 +265,6 @@ sr: dashboard: show: view_more_logs: Pogledaj joÅ¡ zapisa iz evidencije - welcome: DobroÅ¡li u Decidim Admin Panel. exports: export_as: "%{name} kao %{export_format}" notice: VaÅ¡ prenos podataka je u toku. Dobićete e-mail poruku kada bude zavrÅ¡en. @@ -556,6 +556,9 @@ sr: images: preview: Pregled omnipresent_banner_appearance_title: Izmeni sveprisutni baner + organization_homepage_content_blocks: + edit: + update: Ažuriraj shared: gallery: add_images: Dodaj slike @@ -564,10 +567,14 @@ sr: titles: metrics: Metrika statistics: Aktivnost - users: UÄesnici users_statistics: users_count: last_day: Poslednji dan last_month: Poslednji mesec last_week: Poslednje nedelje no_users_count_statistics_yet: JoÅ¡ nema statistike o broju korisnika + moderations: + models: + moderation: + fields: + created_at: Datum kreiranja diff --git a/decidim-admin/config/locales/sv.yml b/decidim-admin/config/locales/sv.yml index 74504efb3b08b..e1888698366da 100644 --- a/decidim-admin/config/locales/sv.yml +++ b/decidim-admin/config/locales/sv.yml @@ -1,3 +1,4 @@ +--- sv: activemodel: attributes: @@ -14,17 +15,24 @@ sv: description: Beskrivning file: Fil title: Bilaga eller bildnamn + weight: Ordning attachment_collection: description: Beskrivning name: Namn + weight: Ordning category: description: Beskrivning name: Namn parent_id: Överordnad + weight: Ordning component: name: Namn published_at: Publicerad - weight: Vikt + weight: Ordning + external_domain: + value: Värde + help_section: + content: InnehÃ¥ll id: ID import: user_group_id: Skapa import som @@ -92,6 +100,9 @@ sv: welcome_notification_body: Välkomstmeddelandets brödtext welcome_notification_subject: Välkomstmeddelandets ämnesrad youtube_handler: YouTube-hanterare + participatory_space_private_user: + email: E-post + name: Namn scope: code: Kod name: Namn @@ -113,12 +124,13 @@ sv: show_in_footer: Visa i sidfoten slug: URL slug title: Titel - weight: Vikt + topic_id: Ämne + weight: Ordning static_page_topic: description: Beskrivning show_in_footer: Visa i sidfoten title: Titel - weight: Vikt + weight: Ordning user_group_csv_verification: file: Fil errors: @@ -133,6 +145,14 @@ sv: allowed_file_content_types: Ogiltig bildfil official_img_header: allowed_file_content_types: Ogiltig bildfil + participatory_space_private_user_csv_import: + attributes: + file: + malformed: Fel format, läs igenom instruktionerna noga och se till att filen är UTF-8 kodad. + user_group_csv_verification: + attributes: + file: + malformed: Fel format, läs igenom instruktionerna noga och se till att filen är UTF-8 kodad. new_import: attributes: file: @@ -184,6 +204,7 @@ sv: error: Ett fel inträffade när användarvillkoren för administratörer skulle godkännas. success: Du har godkänt användarvillkoren för administratörer. actions: + accept: Jag godkänner villkoren are_you_sure: Är du säker pÃ¥ att du vill avvisa administratörsvillkoren? refuse: Avvisa villkoren för administratörer title: Godkänn användarvillkoren @@ -259,6 +280,8 @@ sv: update: error: Det gick inte att uppdatera bilagan. success: Bilagan har uppdaterats. + attachments_privacy_warning: + message: Var försiktig när du arbetar med bilagor i ett privat utrymme. En deltagare skulle kunna dela detta dokument utanför plattformen. autocomplete: no_results: Hittade inga resultat search_prompt: Sök genom att skriva minst tre tecken @@ -341,7 +364,7 @@ sv: dashboard: show: view_more_logs: Visa fler loggar - welcome: Välkommen till Decidims adminpanel. + welcome: Välkommen till Adminpanelen. domain_whitelist: form: domain_too_short: Domänen är för kort @@ -834,9 +857,23 @@ sv: invalid: Det gick inte att läsa CSV-filen. success: CSV-filen har skickats in och vi skickar inbjudningar via e-brev till deltagarna. Det kan ta en stund. new: + destroy: + button: Radera alla privata deltagare + confirm: Är du säker pÃ¥ att du vill radera alla privata deltagare? Den här Ã¥tgärden kan inte Ã¥ngras. + empty: Det finns inga privata deltagare. + explanation: Det finns %{count} privata deltagare. + title: Radera privata deltagare explanation: 'Skicka in din CSV-fil. Den mÃ¥ste ha tvÃ¥ kolumner över de användare som du vill lägga till deltagarutrymmet, utan rubriker, med e-postadressen i den första kolumnen i filen och namnet i den sista kolumnen i filen (e-post, namn). Undvik olämpliga karaktärer som `<>?%&^*#@()[]=+:;"{}\|` i användarnamn.' title: Skicka CSV-fil upload: Skicka + reminders: + create: + error: Det gick inte att skapa pÃ¥minnelser. + success: + one: "%{count} användare kommer pÃ¥minnas." + other: "%{count} användare kommer pÃ¥minnas." + new: + submit: Skicka resource_permissions: edit: submit: Skicka in @@ -894,6 +931,7 @@ sv: gallery: add_images: Lägg till bilder delete_image: Ta bort bild + edit_images: Redigera bilder gallery_legend: Lägg till ett bildgalleri (Frivilligt) static_page_topics: create: @@ -954,7 +992,7 @@ sv: static_pages: Sidor statistics: Aktivitet user_groups: Grupper - users: Deltagare + users: Administratörer user_group: csv_verify: invalid: Det gick inte att läsa CSV-filen. @@ -990,7 +1028,7 @@ sv: role: Roll new: create: Bjud in - title: Bjud in användaren som administratör + title: Bjud in ny administratör users_statistics: users_count: admins: Administratörer @@ -1038,6 +1076,7 @@ sv: moderation: fields: created_at: Skapandedatum + deleted_resource: Borttagen resurs hidden_at: Dold participatory_space: Deltagarutrymme report_count: Antal diff --git a/decidim-admin/config/locales/tr-TR.yml b/decidim-admin/config/locales/tr-TR.yml index f390458dcbd53..bf2521bdebdaa 100644 --- a/decidim-admin/config/locales/tr-TR.yml +++ b/decidim-admin/config/locales/tr-TR.yml @@ -1,3 +1,4 @@ +--- tr: activemodel: attributes: @@ -77,6 +78,8 @@ tr: welcome_notification_body: Karşılama bildirimi gövdesi welcome_notification_subject: Karşılama bildirimi konusu youtube_handler: YouTube iÅŸleyici + participatory_space_private_user: + name: Adı scope: code: kod name: isim @@ -295,7 +298,6 @@ tr: dashboard: show: view_more_logs: Daha fazla günlükleri görüntüle - welcome: Decidim Yönetici Paneline hoÅŸ geldiniz. exports: export_as: "%{name} olarak %{export_format}" formats: @@ -800,7 +802,6 @@ tr: static_pages: Sayfalar statistics: Aktivite user_groups: Kullanıcı Grupları - users: Katılımcılar user_group: csv_verify: invalid: CSV dosyasını okurken bir hata oluÅŸtu. @@ -836,7 +837,6 @@ tr: role: Rol new: create: Davet et - title: Kullanıcıyı yönetici olarak davet et users_statistics: users_count: admins: Yöneticiler diff --git a/decidim-admin/config/locales/uk.yml b/decidim-admin/config/locales/uk.yml index 03ce9fbee6c89..ecbb03056a41d 100644 --- a/decidim-admin/config/locales/uk.yml +++ b/decidim-admin/config/locales/uk.yml @@ -1,3 +1,4 @@ +--- uk: activemodel: attributes: @@ -223,7 +224,6 @@ uk: dashboard: show: view_more_logs: ПереглÑнути інші журнали - welcome: ЛаÑкаво проÑимо до адмін-панелі ДеÑідім! exports: export_as: "%{name} Ñк %{export_format}" notice: Зараз відбуваєтьÑÑ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ñƒ виглÑді файлу. Ви отримаєте електронного лиÑта піÑÐ»Ñ Ð¹Ð¾Ð³Ð¾ завершеннÑ. @@ -457,6 +457,9 @@ uk: edit: active_content_blocks: Блоки діючого вміÑту inactive_content_blocks: Блоки недіючого вміÑту + organization_homepage_content_blocks: + edit: + update: Оновити participatory_space_private_users: create: error: При Ñпробі додати приватного учаÑника до цього проÑтору ÑпівучаÑÑ‚Ñ– ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. @@ -557,7 +560,6 @@ uk: role: Роль new: create: ЗапроÑити - title: ЗапроÑити учаÑника в ÑкоÑÑ‚Ñ– адмініÑтратора users_statistics: users_count: admins: ÐдмініÑтратори @@ -579,10 +581,10 @@ uk: models: moderation: fields: + created_at: Дата ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ hidden_at: 'Приховано:' report_count: КількіÑÑ‚ÑŒ reported_content_url: Веб-адреÑа оÑкарженого вміÑту - reports: Скарги visit_url: Відвідайте веб-адреÑу errors: messages: diff --git a/decidim-admin/config/locales/val-ES.yml b/decidim-admin/config/locales/val-ES.yml index ab90a2c7f0dea..a6d764b061962 100644 --- a/decidim-admin/config/locales/val-ES.yml +++ b/decidim-admin/config/locales/val-ES.yml @@ -1,3 +1,4 @@ +--- val: decidim: admin: diff --git a/decidim-admin/config/locales/zh-CN.yml b/decidim-admin/config/locales/zh-CN.yml index b2dcb4d13f165..55c07da3f4b47 100644 --- a/decidim-admin/config/locales/zh-CN.yml +++ b/decidim-admin/config/locales/zh-CN.yml @@ -1,3 +1,4 @@ +--- zh-CN: activemodel: attributes: @@ -273,7 +274,6 @@ zh-CN: dashboard: show: view_more_logs: 查看更多日志 - welcome: 欢迎æ¥åˆ°Decidim管ç†é¢æ¿ exports: export_as: "%{name} 为 %{export_format}" formats: @@ -731,7 +731,6 @@ zh-CN: static_pages: 页 次 statistics: 活动 user_groups: 群組 - users: å‚加者 user_group: csv_verify: invalid: 读å–CSV文件时出现问题。 @@ -767,7 +766,6 @@ zh-CN: role: 作用 new: create: 邀请 - title: 邀请å‚与者作为管ç†å‘˜ users_statistics: users_count: admins: 管ç†å‘˜ @@ -799,10 +797,10 @@ zh-CN: models: moderation: fields: + created_at: 创建日期 hidden_at: éšè—于 report_count: 计数 reported_content_url: 报告的内容 URL - reports: 报告 visit_url: 访问 URL errors: messages: diff --git a/decidim-admin/decidim-admin.gemspec b/decidim-admin/decidim-admin.gemspec index eb1c6d3c0146e..60a7519adda15 100644 --- a/decidim-admin/decidim-admin.gemspec +++ b/decidim-admin/decidim-admin.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |s| s.email = ["josepjaume@gmail.com", "mrc2407@gmail.com", "oriolgual@gmail.com"] s.license = "AGPL-3.0" s.homepage = "https://github.com/decidim/decidim" - s.required_ruby_version = ">= 2.7" + s.required_ruby_version = ">= 3.0" s.name = "decidim-admin" s.summary = "Decidim organization administration" diff --git a/decidim-admin/lib/decidim/admin/engine.rb b/decidim-admin/lib/decidim/admin/engine.rb index 2f3b8f6fe9c19..7d9399cff7e97 100644 --- a/decidim-admin/lib/decidim/admin/engine.rb +++ b/decidim-admin/lib/decidim/admin/engine.rb @@ -7,7 +7,6 @@ require "devise-i18n" require "decidim/core" require "foundation_rails_helper" -require "rectify" require "doorkeeper" require "doorkeeper-i18n" require "hashdiff" diff --git a/decidim-admin/lib/decidim/admin/import/importer.rb b/decidim-admin/lib/decidim/admin/import/importer.rb index 0f60544075eae..4881ac13f6119 100644 --- a/decidim-admin/lib/decidim/admin/import/importer.rb +++ b/decidim-admin/lib/decidim/admin/import/importer.rb @@ -10,6 +10,8 @@ module Import # You can also use the ImporterFactory class to create an Importer # instance. class Importer + include Decidim::ProcessesFileLocally + delegate :errors, to: :verifier # Public: Initializes an Importer. @@ -72,15 +74,15 @@ def collection_data return @collection_data if @collection_data @collection_data = [] - reader.new(file).read_rows do |rowdata, index| - if index.zero? - @data_headers = rowdata.map { |d| d.to_s.to_sym } - else - @collection_data << Hash[ - rowdata.each_with_index.map do |val, ind| + process_file_locally(file) do |file_path| + reader.new(file_path).read_rows do |rowdata, index| + if index.zero? + @data_headers = rowdata.map { |d| d.to_s.to_sym } + else + @collection_data << rowdata.each_with_index.to_h do |val, ind| [@data_headers[ind], val] end - ] + end end end diff --git a/decidim-admin/lib/decidim/admin/import/readers/json.rb b/decidim-admin/lib/decidim/admin/import/readers/json.rb index f2eea98d1d169..b7a02db7d84b1 100644 --- a/decidim-admin/lib/decidim/admin/import/readers/json.rb +++ b/decidim-admin/lib/decidim/admin/import/readers/json.rb @@ -39,7 +39,7 @@ def example_file(data) columns = data.shift json_data = data.map do |row| deep_hash( - columns.each_with_index.map { |col, ind| [col, row[ind]] }.to_h + columns.each_with_index.to_h { |col, ind| [col, row[ind]] } ) end diff --git a/decidim-admin/lib/decidim/admin/test/commands/create_attachment_collection_examples.rb b/decidim-admin/lib/decidim/admin/test/commands/create_attachment_collection_examples.rb index 30267d1ec69f4..72a9f821dfb10 100644 --- a/decidim-admin/lib/decidim/admin/test/commands/create_attachment_collection_examples.rb +++ b/decidim-admin/lib/decidim/admin/test/commands/create_attachment_collection_examples.rb @@ -7,6 +7,7 @@ module Admin shared_examples_for "CreateAttachmentCollection command" do describe "call" do let(:organization) { create(:organization) } + let(:user) { create(:user, organization: organization) } let(:form_params) do { "attachment_collection" => { @@ -27,11 +28,11 @@ module Admin current_organization: organization ) end - let(:command) { described_class.new(form, collection_for) } + let(:command) { described_class.new(form, collection_for, user) } describe "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do @@ -55,6 +56,18 @@ module Admin command.call end.to change(collection_for.attachment_collections, :count).by(1) end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:create, Decidim::AttachmentCollection, user, {}) + .and_call_original + + expect { command.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("create") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-admin/lib/decidim/admin/test/commands/create_category_examples.rb b/decidim-admin/lib/decidim/admin/test/commands/create_category_examples.rb index 699fb0921c974..1916a5941292c 100644 --- a/decidim-admin/lib/decidim/admin/test/commands/create_category_examples.rb +++ b/decidim-admin/lib/decidim/admin/test/commands/create_category_examples.rb @@ -7,15 +7,13 @@ module Admin shared_examples_for "CreateCategory command" do describe "call" do let(:organization) { create(:organization) } + let(:user) { create(:user, organization: organization) } let(:form_params) do { "category" => { "name_en" => Decidim::Faker::Localized.paragraph(sentence_count: 3), "name_es" => Decidim::Faker::Localized.paragraph(sentence_count: 3), - "name_ca" => Decidim::Faker::Localized.paragraph(sentence_count: 3), - "description_en" => Decidim::Faker::Localized.paragraph(sentence_count: 3), - "description_es" => Decidim::Faker::Localized.paragraph(sentence_count: 3), - "description_ca" => Decidim::Faker::Localized.paragraph(sentence_count: 3) + "name_ca" => Decidim::Faker::Localized.paragraph(sentence_count: 3) } } end @@ -27,11 +25,11 @@ module Admin current_organization: organization ) end - let(:command) { described_class.new(form, participatory_space) } + let(:command) { described_class.new(form, participatory_space, user) } describe "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do @@ -55,6 +53,18 @@ module Admin command.call end.to change(participatory_space.categories, :count).by(1) end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:create, Decidim::Category, user, {}) + .and_call_original + + expect { command.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("create") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-admin/lib/decidim/admin/test/commands/destroy_category_examples.rb b/decidim-admin/lib/decidim/admin/test/commands/destroy_category_examples.rb index eba22d911a8b5..f369262777db6 100644 --- a/decidim-admin/lib/decidim/admin/test/commands/destroy_category_examples.rb +++ b/decidim-admin/lib/decidim/admin/test/commands/destroy_category_examples.rb @@ -7,8 +7,9 @@ module Admin shared_examples_for "DestroyCategory command" do describe "call" do let(:organization) { create(:organization) } + let(:user) { create(:user, organization: organization) } let(:category) { create(:category, participatory_space: participatory_space) } - let(:command) { described_class.new(category) } + let(:command) { described_class.new(category, user) } describe "when the category is not present" do let(:category) { nil } @@ -28,6 +29,21 @@ module Admin end end + context "when the category is a subcategory" do + let!(:parent_category) { create :category, participatory_space: participatory_space } + + before do + category.parent = parent_category + end + + it "destroy the category" do + category + expect do + command.call + end.to change(Category, :count).by(-1) + end + end + describe "when the data is valid" do it "broadcasts ok" do expect { command.call }.to broadcast(:ok) @@ -39,6 +55,18 @@ module Admin command.call end.to change(Category, :count).by(-1) end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:delete, category, user) + .and_call_original + + expect { command.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("delete") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-admin/lib/decidim/admin/test/commands/update_attachment_collection_examples.rb b/decidim-admin/lib/decidim/admin/test/commands/update_attachment_collection_examples.rb index 9992183850481..46415c5c1f181 100644 --- a/decidim-admin/lib/decidim/admin/test/commands/update_attachment_collection_examples.rb +++ b/decidim-admin/lib/decidim/admin/test/commands/update_attachment_collection_examples.rb @@ -7,6 +7,7 @@ module Admin shared_examples_for "UpdateAttachmentCollection command" do describe "call" do let(:organization) { create(:organization) } + let(:user) { create(:user, organization: organization) } let(:attachment_collection) { create(:attachment_collection, collection_for: collection_for) } let(:form_params) do { @@ -28,11 +29,11 @@ module Admin current_organization: organization ) end - let(:command) { described_class.new(attachment_collection, form) } + let(:command) { described_class.new(attachment_collection, form, user) } describe "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do @@ -58,6 +59,18 @@ module Admin expect(translated(attachment_collection.name)).to eq("New title") end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:update, Decidim::AttachmentCollection, user, {}) + .and_call_original + + expect { command.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("update") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-admin/lib/decidim/admin/test/commands/update_category_examples.rb b/decidim-admin/lib/decidim/admin/test/commands/update_category_examples.rb index 2eb18ee44f632..8dc24c0787e73 100644 --- a/decidim-admin/lib/decidim/admin/test/commands/update_category_examples.rb +++ b/decidim-admin/lib/decidim/admin/test/commands/update_category_examples.rb @@ -7,16 +7,14 @@ module Admin shared_examples_for "UpdateCategory command" do describe "call" do let(:organization) { create(:organization) } + let(:user) { create(:user, organization: organization) } let(:category) { create(:category, participatory_space: participatory_space) } let(:form_params) do { "category" => { "name_en" => "New title", "name_es" => "Title", - "name_ca" => "Title", - "description_en" => "Description", - "description_es" => "Description", - "description_ca" => "Description" + "name_ca" => "Title" } } end @@ -28,11 +26,11 @@ module Admin current_organization: organization ) end - let(:command) { described_class.new(category, form) } + let(:command) { described_class.new(category, form, user) } describe "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do @@ -58,6 +56,18 @@ module Admin expect(translated(category.name)).to eq("New title") end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:update, Decidim::Category, user, {}) + .and_call_original + + expect { command.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("update") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-admin/lib/decidim/admin/test/filters_participatory_space_user_roles_examples.rb b/decidim-admin/lib/decidim/admin/test/filters_participatory_space_user_roles_examples.rb index a8e11319f204b..e2329325e0ae6 100644 --- a/decidim-admin/lib/decidim/admin/test/filters_participatory_space_user_roles_examples.rb +++ b/decidim-admin/lib/decidim/admin/test/filters_participatory_space_user_roles_examples.rb @@ -99,7 +99,7 @@ apply_filter("Invite accepted", "Yes") within ".stack tbody" do - expect(page).to have_content(invited_user_2.name) + expect(page).to have_content(invited_user2.name) expect(page).to have_css("tr", count: 1) end end @@ -110,7 +110,7 @@ apply_filter("Invite accepted", "No") within ".stack tbody" do - expect(page).to have_content(invited_user_1.name) + expect(page).to have_content(invited_user1.name) expect(page).to have_css("tr", count: 1) end end @@ -123,7 +123,7 @@ apply_filter("Ever logged in", "Yes") within ".stack tbody" do - expect(page).to have_content(invited_user_2.name) + expect(page).to have_content(invited_user2.name) expect(page).to have_css("tr", count: 1) end end @@ -134,7 +134,7 @@ apply_filter("Ever logged in", "No") within ".stack tbody" do - expect(page).to have_content(invited_user_1.name) + expect(page).to have_content(invited_user1.name) expect(page).to have_css("tr", count: 1) end end diff --git a/decidim-admin/lib/decidim/admin/test/filters_participatory_space_users_examples.rb b/decidim-admin/lib/decidim/admin/test/filters_participatory_space_users_examples.rb index cba5701f747ea..3df25dc1c1c1f 100644 --- a/decidim-admin/lib/decidim/admin/test/filters_participatory_space_users_examples.rb +++ b/decidim-admin/lib/decidim/admin/test/filters_participatory_space_users_examples.rb @@ -7,7 +7,7 @@ apply_filter("Invitation sent", "Not sent") within ".stack tbody" do - expect(page).to have_content(invited_user_2.name) + expect(page).to have_content(invited_user2.name) expect(page).to have_css("tr", count: 1) end end @@ -18,7 +18,7 @@ apply_filter("Invitation sent", "Sent") within ".stack tbody" do - expect(page).to have_content(invited_user_1.name) + expect(page).to have_content(invited_user1.name) expect(page).to have_css("tr", count: 1) end end @@ -31,7 +31,7 @@ apply_filter("Invitation accepted", "Not accepted") within ".stack tbody" do - expect(page).to have_content(invited_user_2.name) + expect(page).to have_content(invited_user2.name) expect(page).to have_css("tr", count: 1) end end @@ -42,7 +42,7 @@ apply_filter("Invitation accepted", "Accepted") within ".stack tbody" do - expect(page).to have_content(invited_user_1.name) + expect(page).to have_content(invited_user1.name) expect(page).to have_css("tr", count: 1) end end diff --git a/decidim-admin/lib/decidim/admin/test/forms/category_form_examples.rb b/decidim-admin/lib/decidim/admin/test/forms/category_form_examples.rb index 4225429f8fa90..1d8c24dfae8a5 100644 --- a/decidim-admin/lib/decidim/admin/test/forms/category_form_examples.rb +++ b/decidim-admin/lib/decidim/admin/test/forms/category_form_examples.rb @@ -21,13 +21,6 @@ module Admin ca: "Nom" } end - let(:description) do - { - en: "Description", - es: "Descripción", - ca: "Descripció" - } - end let(:parent_id) { nil } let(:attributes) do { @@ -35,10 +28,7 @@ module Admin "name_en" => name[:en], "name_es" => name[:es], "name_ca" => name[:ca], - "parent_id" => parent_id, - "description_en" => description[:en], - "description_es" => description[:es], - "description_ca" => description[:ca] + "parent_id" => parent_id } } end @@ -59,16 +49,6 @@ module Admin it { is_expected.to be_invalid } end - context "when some language in description is missing" do - let(:description) do - { - ca: "Descripció" - } - end - - it { is_expected.to be_invalid } - end - context "when the parent_id is set" do let!(:category) { create :category, participatory_space: participatory_space } diff --git a/decidim-admin/lib/decidim/admin/test/manage_attachments_examples.rb b/decidim-admin/lib/decidim/admin/test/manage_attachments_examples.rb index b71f15db85f60..9c32901e56b00 100644 --- a/decidim-admin/lib/decidim/admin/test/manage_attachments_examples.rb +++ b/decidim-admin/lib/decidim/admin/test/manage_attachments_examples.rb @@ -48,8 +48,11 @@ es: "Este documento contiene información importante", ca: "Aquest document conté informació important" ) + end + + dynamically_attach_file(:attachment_file, Decidim::Dev.asset("Exampledocument.pdf")) - attach_file :attachment_file, Decidim::Dev.asset("Exampledocument.pdf") + within ".new_attachment" do find("*[type=submit]").click end @@ -81,7 +84,11 @@ ) select translated(attachment_collection.name, locale: :en), from: "attachment_attachment_collection_id" - attach_file :attachment_file, Decidim::Dev.asset("Exampledocument.pdf") + end + + dynamically_attach_file(:attachment_file, Decidim::Dev.asset("Exampledocument.pdf")) + + within ".new_attachment" do find("*[type=submit]").click end diff --git a/decidim-admin/lib/decidim/admin/test/manage_categories_examples.rb b/decidim-admin/lib/decidim/admin/test/manage_categories_examples.rb index 1770f81562722..6a5c9d2e25a20 100644 --- a/decidim-admin/lib/decidim/admin/test/manage_categories_examples.rb +++ b/decidim-admin/lib/decidim/admin/test/manage_categories_examples.rb @@ -14,9 +14,6 @@ expect(page).to have_selector("input#category_name_en[value='#{translated(category.name, locale: :en)}']") expect(page).to have_selector("input#category_weight[value='#{category.weight}']") - within ".editor .editor-container" do - expect(page).to have_content(strip_tags(translated(category.description, locale: :en))) - end expect(page).to have_selector("select#category_parent_id") end @@ -32,13 +29,6 @@ es: "Mi categoría", ca: "La meva categoria" ) - fill_in_i18n_editor( - :category_description, - "#category-description-tabs", - en: "Description", - es: "Descripción", - ca: "Descripció" - ) find("*[type=submit]").click end diff --git a/decidim-admin/lib/decidim/admin/test/manage_component_permissions_examples.rb b/decidim-admin/lib/decidim/admin/test/manage_component_permissions_examples.rb index 14d9c03ad45d7..b0cbcfeb6072a 100644 --- a/decidim-admin/lib/decidim/admin/test/manage_component_permissions_examples.rb +++ b/decidim-admin/lib/decidim/admin/test/manage_component_permissions_examples.rb @@ -52,9 +52,7 @@ context "when failing to set permissions" do before do - # rubocop:disable RSpec/AnyInstance allow_any_instance_of(Decidim::Admin::PermissionsForm).to receive(:valid?).and_return(false) - # rubocop:enable RSpec/AnyInstance within ".component-#{component.id}" do click_link "Permissions" end diff --git a/decidim-admin/lib/decidim/admin/test/manage_moderations_examples.rb b/decidim-admin/lib/decidim/admin/test/manage_moderations_examples.rb index d91128f9c19e5..90362d13085fb 100644 --- a/decidim-admin/lib/decidim/admin/test/manage_moderations_examples.rb +++ b/decidim-admin/lib/decidim/admin/test/manage_moderations_examples.rb @@ -1,5 +1,31 @@ # frozen_string_literal: true +shared_examples "sorted moderations" do + let!(:moderations) do + reportables.first(reportables.length - 1).map do |reportable| + moderation = create(:moderation, reportable: reportable, report_count: 1, reported_content: reportable.reported_searchable_content_text) + create(:report, moderation: moderation) + moderation + end + end + let!(:moderation) { moderations.first } + let(:moderations_link_text) { "Moderations" } + + before do + visit participatory_space_path + click_link moderations_link_text + end + + it "sorts the most recent first" do + within ".pagination" do + click_link "Last" + end + all("tbody tr").each_with_index do |row, _index| + expect(row.find("td:first-child")).to have_content(reportables.first.id) + end + end +end + shared_examples "manage moderations" do let!(:moderations) do reportables.first(reportables.length - 1).map do |reportable| @@ -146,11 +172,17 @@ end context "when listing hidden resources" do - it "user can review them" do + before do within ".card-title" do click_link "Hidden" end + end + it "user can't unreport them" do + expect(page).not_to have_css(".action-icon--unreport") + end + + it "user can review them" do hidden_moderations.each do |moderation| within "tr[data-id=\"#{moderation.id}\"]" do expect(page).to have_css("a[href='#{moderation.reportable.reported_content_url}']") diff --git a/decidim-admin/lib/decidim/admin/version.rb b/decidim-admin/lib/decidim/admin/version.rb index 7210b1ec5b77c..9bf37895124da 100644 --- a/decidim-admin/lib/decidim/admin/version.rb +++ b/decidim-admin/lib/decidim/admin/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-admin version. module Admin def self.version - "0.26.4" + "0.27.2" end end end diff --git a/decidim-admin/spec/commands/decidim/admin/block_user_spec.rb b/decidim-admin/spec/commands/decidim/admin/block_user_spec.rb index 23a48c243db20..aa0b8603acd6b 100644 --- a/decidim-admin/spec/commands/decidim/admin/block_user_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/block_user_spec.rb @@ -8,68 +8,83 @@ module Decidim::Admin let(:organization) { create :organization } let(:current_user) { create :user, :admin, organization: organization } - let(:user_to_block) { create :user, :managed, name: "Testingname", organization: organization } let(:justification) { "justification for blocking the user" } let(:user_block) { create :justification, :user, :current_user } - context "when the form is valid" do - let(:form) do - double( - user: user_to_block, - current_user: current_user, - justification: :justification, - valid?: true - ) - end + shared_examples "blocking user or group form" do + context "when the form is valid" do + let(:form) do + double( + user: user_to_block, + current_user: current_user, + justification: :justification, + valid?: true + ) + end - it "broadcasts ok" do - expect { subject.call }.to broadcast(:ok, user_to_block) - end + it "broadcasts ok" do + expect { subject.call }.to broadcast(:ok, user_to_block) + end - it "user is notified" do - subject.call - expect(Decidim::BlockUserJob).to have_been_enqueued.on_queue("block_user") - end + it "user is notified" do + subject.call + expect(Decidim::BlockUserJob).to have_been_enqueued.on_queue("block_user") + end - it "user is updated" do - subject.call - expect(form.user.blocked).to be(true) - expect(form.user.extended_data["user_name"]).to eq("Testingname") - expect(form.user.name).to eq("Blocked user") - end + it "user is updated" do + subject.call + expect(form.user.blocked).to be(true) + expect(form.user.extended_data["user_name"]).to eq(user_name) + expect(form.user.name).to eq("Blocked user") + end + + it "original username is stored in the action log entry's resource title" do + subject.call + log = Decidim::ActionLog.last + expect(log.resource).to eq(form.user) + expect(log.extra["resource"]["title"]).to eq(user_name) + end - it "original username is stored in the action log entry's resource title" do - subject.call - log = Decidim::ActionLog.last - expect(log.resource).to eq(form.user) - expect(log.extra["resource"]["title"]).to eq("Testingname") + it "tracks the changes" do + expect(Decidim.traceability).to receive(:perform_action!).with("block", + user_to_block, + current_user, + extra: { + reportable_type: form.user.class.name, + current_justification: form.justification + }, + resource: { + title: form.user.name + }) + subject.call + end end - it "tracks the changes" do - expect(Decidim.traceability).to receive(:perform_action!).with("block", - user_to_block, - current_user, - extra: { - reportable_type: form.user.class.name, - current_justification: form.justification - }, - resource: { - title: form.user.name - }) - subject.call + context "when the form is not ok" do + let(:form) do + double( + valid?: false + ) + end + + it "broadcasts invalid" do + expect { subject.call }.to broadcast(:invalid) + end end end - context "when the form is not ok" do - let(:form) do - double( - valid?: false - ) - end + context "with a user" do + let(:user_to_block) { create :user, name: user_name, organization: organization } + let(:user_name) { "Testing user" } - it "broadcasts invalid" do - expect { subject.call }.to broadcast(:invalid) - end + it_behaves_like "blocking user or group form" + end + + context "with a user group" do + let(:user_to_block) { create :user_group, name: user_name, organization: organization } + let(:user_name) { "Testing user group" } + + it_behaves_like "blocking user or group form" end end end diff --git a/decidim-admin/spec/commands/decidim/admin/create_area_type_spec.rb b/decidim-admin/spec/commands/decidim/admin/create_area_type_spec.rb index 7069cb89a55d7..31582a50f0cdf 100644 --- a/decidim-admin/spec/commands/decidim/admin/create_area_type_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/create_area_type_spec.rb @@ -4,9 +4,10 @@ module Decidim::Admin describe CreateAreaType do - subject { described_class.new(form) } + subject { described_class.new(form, user) } let(:organization) { create :organization } + let(:user) { create(:user, organization: organization) } let(:name) { Decidim::Faker::Localized.literal("territorial") } let(:plural) { Decidim::Faker::Localized.literal("territorials") } @@ -36,6 +37,18 @@ module Decidim::Admin it "creates a new scope type for the organization" do expect { subject.call }.to change { organization.area_types.count }.by(1) end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:create, Decidim::AreaType, user, {}) + .and_call_original + + expect { subject.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("create") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-admin/spec/commands/decidim/admin/create_attachment_spec.rb b/decidim-admin/spec/commands/decidim/admin/create_attachment_spec.rb index e2e336488c064..7fb7dbe2b0117 100644 --- a/decidim-admin/spec/commands/decidim/admin/create_attachment_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/create_attachment_spec.rb @@ -4,8 +4,8 @@ module Decidim::Admin describe CreateAttachment do - subject { described_class.call(form, attached_to) } - + subject { described_class.call(form, attached_to, user) } + let(:user) { create(:user) } let(:form) do instance_double( AttachmentForm, @@ -24,12 +24,7 @@ module Decidim::Admin weight: 0 ) end - let(:file) do - Rack::Test::UploadedFile.new( - Decidim::Dev.test_file("city.jpeg", "image/jpeg"), - "image/jpeg" - ) - end + let(:file) { upload_test_file(Decidim::Dev.test_file("city.jpeg", "image/jpeg")) } let(:attached_to) { create(:participatory_process) } describe "when valid" do @@ -60,6 +55,18 @@ module Decidim::Admin subject end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:create, Decidim::Attachment, user) + .and_call_original + + expect { subject }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("create") + expect(action_log.version).to be_present + end end describe "when invalid" do diff --git a/decidim-admin/spec/commands/decidim/admin/create_component_spec.rb b/decidim-admin/spec/commands/decidim/admin/create_component_spec.rb index 411a633f6f58f..f271c48cba378 100644 --- a/decidim-admin/spec/commands/decidim/admin/create_component_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/create_component_spec.rb @@ -22,19 +22,19 @@ module Decidim::Admin manifest: manifest, participatory_space: participatory_process, settings: { - dummy_global_attribute_1: true, - dummy_global_attribute_2: false + dummy_global_attribute1: true, + dummy_global_attribute2: false }, default_step_settings: { step.id.to_s => { - dummy_step_attribute_1: true, - dummy_step_attribute_2: false + dummy_step_attribute1: true, + dummy_step_attribute2: false } }, step_settings: { step.id.to_s => { - dummy_step_attribute_1: true, - dummy_step_attribute_2: false + dummy_step_attribute1: true, + dummy_step_attribute2: false } } ) @@ -55,13 +55,13 @@ module Decidim::Admin expect(participatory_process.components).not_to be_empty component = participatory_process.components.first - expect(component.settings.dummy_global_attribute_1).to eq(true) - expect(component.settings.dummy_global_attribute_2).to eq(false) + expect(component.settings.dummy_global_attribute1).to be(true) + expect(component.settings.dummy_global_attribute2).to be(false) expect(component.weight).to eq 2 step_settings = component.step_settings[step.id.to_s] - expect(step_settings.dummy_step_attribute_1).to eq(true) - expect(step_settings.dummy_step_attribute_2).to eq(false) + expect(step_settings.dummy_step_attribute1).to be(true) + expect(step_settings.dummy_step_attribute2).to be(false) end it "traces the action", versioning: true do diff --git a/decidim-admin/spec/commands/decidim/admin/create_import_spec.rb b/decidim-admin/spec/commands/decidim/admin/create_import_spec.rb index 0e19e4116c2a1..056cf359b9e9f 100644 --- a/decidim-admin/spec/commands/decidim/admin/create_import_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/create_import_spec.rb @@ -10,7 +10,7 @@ module Decidim::Admin let(:organization) { create(:organization) } let(:participatory_space) { create(:participatory_process, organization: organization) } let!(:component) { create(:dummy_component, organization: organization) } - let(:file) { Decidim::Dev.test_file("verify_user_groups.csv", "text/csv") } + let(:file) { upload_test_file(Decidim::Dev.test_file("verify_user_groups.csv", "text/csv")) } let(:form) do Decidim::Admin::ImportForm.from_params( diff --git a/decidim-admin/spec/commands/decidim/admin/create_newsletter_spec.rb b/decidim-admin/spec/commands/decidim/admin/create_newsletter_spec.rb index fb3d2b98672ff..3c785ec0930da 100644 --- a/decidim-admin/spec/commands/decidim/admin/create_newsletter_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/create_newsletter_spec.rb @@ -75,7 +75,7 @@ module Decidim::Admin expect(newsletter.author).to eq(user) expect(newsletter.organization).to eq(organization) expect(newsletter.subject.deep_stringify_keys).to eq(form.subject.deep_stringify_keys) - expect(newsletter.sent?).to eq(false) + expect(newsletter.sent?).to be(false) expect(newsletter.template).to be_present expect(newsletter.template.settings.body.stringify_keys).to eq(newsletter_body.stringify_keys.except("machine_translations")) end diff --git a/decidim-admin/spec/commands/create_participatory_space_private_user_spec.rb b/decidim-admin/spec/commands/decidim/admin/create_participatory_space_private_user_spec.rb similarity index 97% rename from decidim-admin/spec/commands/create_participatory_space_private_user_spec.rb rename to decidim-admin/spec/commands/decidim/admin/create_participatory_space_private_user_spec.rb index 64f21442ad40b..604ef8aba2f9c 100644 --- a/decidim-admin/spec/commands/create_participatory_space_private_user_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/create_participatory_space_private_user_spec.rb @@ -15,10 +15,12 @@ module Decidim::Admin let(:form) do double( invalid?: invalid, + delete_current_private_participants?: delete, email: email, name: name ) end + let(:delete) { false } let(:invalid) { false } context "when the form is not valid" do diff --git a/decidim-admin/spec/commands/decidim/admin/create_scope_type_spec.rb b/decidim-admin/spec/commands/decidim/admin/create_scope_type_spec.rb index efd39e43804cd..3ffc29562e5b1 100644 --- a/decidim-admin/spec/commands/decidim/admin/create_scope_type_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/create_scope_type_spec.rb @@ -4,9 +4,10 @@ module Decidim::Admin describe CreateScopeType do - subject { described_class.new(form) } + subject { described_class.new(form, user) } let(:organization) { create :organization } + let(:user) { create(:user, organization: organization) } let(:name) { Decidim::Faker::Localized.literal("province") } let(:plural) { Decidim::Faker::Localized.literal("provinces") } @@ -36,6 +37,18 @@ module Decidim::Admin it "creates a new scope type for the organization" do expect { subject.call }.to change { organization.scope_types.count }.by(1) end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:create, Decidim::ScopeType, user, {}) + .and_call_original + + expect { subject.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("create") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-admin/spec/commands/decidim/admin/create_static_page_spec.rb b/decidim-admin/spec/commands/decidim/admin/create_static_page_spec.rb index cc10ba07992c5..2a16040e2e39a 100644 --- a/decidim-admin/spec/commands/decidim/admin/create_static_page_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/create_static_page_spec.rb @@ -16,7 +16,7 @@ module Decidim::Admin describe "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do diff --git a/decidim-admin/spec/commands/decidim/admin/deliver_newsletter_spec.rb b/decidim-admin/spec/commands/decidim/admin/deliver_newsletter_spec.rb index 75acd38203527..3d7129b732a0e 100644 --- a/decidim-admin/spec/commands/decidim/admin/deliver_newsletter_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/deliver_newsletter_spec.rb @@ -106,11 +106,11 @@ def user_localized_body(user) context "when interests match the selected scopes" do let!(:deliverable_users) do - create_list(:user, rand(2..9), :confirmed, organization: organization, newsletter_notifications_at: Time.current, extended_data: { "interested_scopes": scopes.first.id }) + create_list(:user, rand(2..9), :confirmed, organization: organization, newsletter_notifications_at: Time.current, extended_data: { interested_scopes: scopes.first.id }) end let!(:undeliverable_users) do - create_list(:user, rand(2..9), :confirmed, organization: organization, newsletter_notifications_at: Time.current, extended_data: { "interested_scopes": scopes.last.id }) + create_list(:user, rand(2..9), :confirmed, organization: organization, newsletter_notifications_at: Time.current, extended_data: { interested_scopes: scopes.last.id }) end it_behaves_like "selective newsletter" @@ -119,7 +119,7 @@ def user_localized_body(user) context "when interest do not match the selected scopes" do let(:user_interest) { create(:scope, organization: organization) } let!(:deliverable_users) do - create_list(:user, rand(2..9), :confirmed, organization: organization, newsletter_notifications_at: Time.current, extended_data: { "interested_scopes": user_interest.id }) + create_list(:user, rand(2..9), :confirmed, organization: organization, newsletter_notifications_at: Time.current, extended_data: { interested_scopes: user_interest.id }) end it "is not valid" do @@ -132,7 +132,7 @@ def user_localized_body(user) context "when sending to followers" do let(:send_to_followers) { true } - context "when no spaces selected " do + context "when no spaces selected" do it "is not valid" do expect { command.call }.to broadcast(:invalid) end @@ -180,7 +180,7 @@ def user_localized_body(user) context "when sending to participants" do let(:send_to_participants) { true } - context "when no spaces selected " do + context "when no spaces selected" do it "is not valid" do expect { command.call }.to broadcast(:invalid) end diff --git a/decidim-admin/spec/commands/decidim/admin/destroy_component_spec.rb b/decidim-admin/spec/commands/decidim/admin/destroy_component_spec.rb index ceac6a68d2a9e..69feb59b50452 100644 --- a/decidim-admin/spec/commands/decidim/admin/destroy_component_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/destroy_component_spec.rb @@ -37,9 +37,9 @@ module Decidim::Admin subject.call - component = results[:component] - expect(component.id).to eq(component.id) - expect(component).not_to be_persisted + result_component = results[:component] + expect(result_component.id).to eq(component.id) + expect(result_component).not_to be_persisted end end end diff --git a/decidim-admin/spec/commands/decidim/admin/impersonate_user_spec.rb b/decidim-admin/spec/commands/decidim/admin/impersonate_user_spec.rb index a928d5b05055d..e15aa92affbac 100644 --- a/decidim-admin/spec/commands/decidim/admin/impersonate_user_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/impersonate_user_spec.rb @@ -46,13 +46,13 @@ module Decidim::Admin it "creates a impersonation log" do expect do subject.call - end.to change { Decidim::ImpersonationLog.count }.by(1) + end.to change(Decidim::ImpersonationLog, :count).by(1) end it "creates a action log" do expect do subject.call - end.to change { Decidim::ActionLog.count }.by(1) + end.to change(Decidim::ActionLog, :count).by(1) end it "expires the impersonation session automatically" do @@ -77,7 +77,7 @@ module Decidim::Admin it "creates a action log with reason" do expect do subject.call - end.to change { Decidim::ActionLog.count }.by(1) + end.to change(Decidim::ActionLog, :count).by(1) expect(Decidim::ActionLog.last.action).to eq("manage") end diff --git a/decidim-admin/spec/commands/decidim/admin/process_participatory_space_private_user_import_csv_spec.rb b/decidim-admin/spec/commands/decidim/admin/process_participatory_space_private_user_import_csv_spec.rb index ee14e8becd8e8..b9906ab3a181f 100644 --- a/decidim-admin/spec/commands/decidim/admin/process_participatory_space_private_user_import_csv_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/process_participatory_space_private_user_import_csv_spec.rb @@ -9,7 +9,7 @@ module Decidim::Admin let(:current_user) { create(:user, :admin, organization: organization) } let(:organization) { create(:organization) } let(:private_users_to) { create :participatory_process, organization: organization } - let(:file) { File.new Decidim::Dev.asset("import_participatory_space_private_users.csv") } + let(:file) { upload_test_file(Decidim::Dev.test_file("import_participatory_space_private_users.csv", "text/csv"), return_blob: true) } let(:validity) { true } let(:form) do @@ -37,7 +37,7 @@ module Decidim::Admin end context "when the CSV file has BOM" do - let(:file) { File.new Decidim::Dev.asset("import_participatory_space_private_users_with_bom.csv") } + let(:file) { upload_test_file(Decidim::Dev.test_file("import_participatory_space_private_users_with_bom.csv", "text/csv"), return_blob: true) } let(:email) { "my_user@example.org" } it "broadcasts ok" do diff --git a/decidim-admin/spec/commands/decidim/admin/process_user_group_verification_csv_spec.rb b/decidim-admin/spec/commands/decidim/admin/process_user_group_verification_csv_spec.rb index 46ca463f416bd..e39f6cd86da29 100644 --- a/decidim-admin/spec/commands/decidim/admin/process_user_group_verification_csv_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/process_user_group_verification_csv_spec.rb @@ -8,7 +8,7 @@ module Decidim::Admin let(:user) { create(:user, :admin, organization: organization) } let(:organization) { create(:organization) } - let(:file) { File.new Decidim::Dev.asset("verify_user_groups.csv") } + let(:file) { upload_test_file(Decidim::Dev.test_file("verify_user_groups.csv", "text/csv"), return_blob: true) } let(:validity) { true } let(:form) do diff --git a/decidim-admin/spec/commands/decidim/admin/promote_managed_user_spec.rb b/decidim-admin/spec/commands/decidim/admin/promote_managed_user_spec.rb index 6d50544248fe3..b8b8c5e9e6484 100644 --- a/decidim-admin/spec/commands/decidim/admin/promote_managed_user_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/promote_managed_user_spec.rb @@ -47,7 +47,7 @@ module Decidim::Admin context "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do diff --git a/decidim-admin/spec/commands/decidim/admin/reject_user_group_spec.rb b/decidim-admin/spec/commands/decidim/admin/reject_user_group_spec.rb index ee4e25a3d8e07..5ec64ff8738af 100644 --- a/decidim-admin/spec/commands/decidim/admin/reject_user_group_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/reject_user_group_spec.rb @@ -16,7 +16,7 @@ module Decidim::Admin let(:invalid) { true } it "broadcast invalid in return" do - expect(user_group).to receive(:valid?).and_return(false) + allow(user_group).to receive(:valid?).and_return(false) expect { subject.call }.to broadcast(:invalid) expect(user_group.rejected_at).to be_nil @@ -49,7 +49,7 @@ module Decidim::Admin let(:invalid) { true } it "broadcast invalid in return and do not clean verified_at" do - expect(user_group).to receive(:valid?).and_return(false) + allow(user_group).to receive(:valid?).and_return(false) expect { subject.call }.to broadcast(:invalid) expect(user_group.verified_at).not_to be_nil diff --git a/decidim-admin/spec/commands/decidim/admin/reorder_content_blocks_spec.rb b/decidim-admin/spec/commands/decidim/admin/reorder_content_blocks_spec.rb index 3924423d3e163..2d4a900ce052f 100644 --- a/decidim-admin/spec/commands/decidim/admin/reorder_content_blocks_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/reorder_content_blocks_spec.rb @@ -95,7 +95,7 @@ module Decidim::Admin expect(published_block2.weight).to eq 1 expect(unpublished_block.weight).to eq 2 - expect(published_block1.weight).to eq nil + expect(published_block1.weight).to be_nil end it "unpublishes a published block that disappears from the order" do diff --git a/decidim-admin/spec/commands/decidim/admin/transfer_user_spec.rb b/decidim-admin/spec/commands/decidim/admin/transfer_user_spec.rb index 35941c5a4384c..08ae506caebf6 100644 --- a/decidim-admin/spec/commands/decidim/admin/transfer_user_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/transfer_user_spec.rb @@ -42,18 +42,18 @@ module Decidim::Admin end end - context "when user is missing" do - let(:current_user) {} + context "when user is missing" do + let(:current_user) { nil } it "broadcasts invalid" do expect { subject.call }.to broadcast(:invalid) end end - context "when solve conflict succeeds " do + context "when solve conflict succeeds" do it "mark conflict as solved" do subject.call - expect(conflict.reload.solved).to eq(true) + expect(conflict.reload.solved).to be(true) end it "update email" do diff --git a/decidim-admin/spec/commands/decidim/admin/unblock_user_spec.rb b/decidim-admin/spec/commands/decidim/admin/unblock_user_spec.rb index 08e58fd5215ce..90bf1aca19122 100644 --- a/decidim-admin/spec/commands/decidim/admin/unblock_user_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/unblock_user_spec.rb @@ -6,41 +6,57 @@ module Decidim::Admin describe UnblockUser do subject { described_class.new(user_to_unblock, current_user) } + let(:extended_data) { { user_name: user_name } } let(:current_user) { create :user, :admin } - let(:user_to_unblock) { create :user, :managed, blocked: true, name: "Testingname" } - context "when the blocking is valid" do - it "broadcasts ok" do - expect { subject.call }.to broadcast(:ok) - end + shared_examples "unblocking a user or group" do + context "when the blocking is valid" do + it "broadcasts ok" do + expect { subject.call }.to broadcast(:ok) + end + + it "user is updated" do + subject.call + expect(user_to_unblock.blocked).to be(false) + expect(user_to_unblock.name).to eq(user_name) + expect(user_to_unblock.blocked_at).to be_nil + expect(user_to_unblock.block_id).to be_nil + end - it "user is updated" do - subject.call - expect(user_to_unblock.blocked).to be(false) - expect(user_to_unblock.name).to eq("Testingname") - expect(user_to_unblock.blocked_at).to be_nil - expect(user_to_unblock.block_id).to be_nil + it "tracks the changes" do + expect(Decidim.traceability).to receive(:perform_action!) + .with( + "unblock", + user_to_unblock, + current_user, + extra: { + reportable_type: user_to_unblock.class.name + } + ) + subject.call + end end - it "tracks the changes" do - expect(Decidim.traceability).to receive(:perform_action!) - .with( - "unblock", - user_to_unblock, - current_user, - extra: { - reportable_type: user_to_unblock.class.name - } - ) - subject.call + context "when the suspension is not valid" do + it "broadcasts invalid" do + allow(user_to_unblock).to receive(:blocked?).and_return(false) + expect { subject.call }.to broadcast(:invalid) + end end end - context "when the suspension is not valid" do - it "broadcasts invalid" do - allow(user_to_unblock).to receive(:blocked?).and_return(false) - expect { subject.call }.to broadcast(:invalid) - end + context "with a user" do + let(:user_to_unblock) { create :user, :blocked, extended_data: extended_data } + let(:user_name) { "Testing user" } + + it_behaves_like "unblocking a user or group" + end + + context "with a user group" do + let(:user_to_unblock) { create :user_group, :blocked, extended_data: extended_data } + let(:user_name) { "Testing user group" } + + it_behaves_like "unblocking a user or group" end end end diff --git a/decidim-admin/spec/commands/decidim/admin/unreport_resource_spec.rb b/decidim-admin/spec/commands/decidim/admin/unreport_resource_spec.rb index d2672adb616e5..2fb2422a8653f 100644 --- a/decidim-admin/spec/commands/decidim/admin/unreport_resource_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/unreport_resource_spec.rb @@ -17,7 +17,7 @@ module Decidim::Admin it "deletes the moderation" do command.call - expect(reportable.reload.moderation).to be(nil) + expect(reportable.reload.moderation).to be_nil end it "traces the action", versioning: true do diff --git a/decidim-admin/spec/commands/decidim/admin/unreport_user_spec.rb b/decidim-admin/spec/commands/decidim/admin/unreport_user_spec.rb index dfb3242232a1e..fdfb012582e67 100644 --- a/decidim-admin/spec/commands/decidim/admin/unreport_user_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/unreport_user_spec.rb @@ -17,7 +17,7 @@ module Decidim::Admin it "deletes the moderation" do command.call - expect(reportable.reload.user_moderation).to be(nil) + expect(reportable.reload.user_moderation).to be_nil end it "traces the action", versioning: true do diff --git a/decidim-admin/spec/commands/decidim/admin/update_area_type_spec.rb b/decidim-admin/spec/commands/decidim/admin/update_area_type_spec.rb index b2e27fe0d3877..670d6ad4d5f9c 100644 --- a/decidim-admin/spec/commands/decidim/admin/update_area_type_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/update_area_type_spec.rb @@ -4,9 +4,10 @@ module Decidim::Admin describe UpdateAreaType do - subject { described_class.new(area_type, form) } + subject { described_class.new(area_type, form, user) } let(:organization) { create :organization } + let(:user) { create(:user, organization: organization) } let(:area_type) { create :area_type, organization: organization } let(:name) { Decidim::Faker::Localized.literal("new name") } let(:plural) { Decidim::Faker::Localized.literal("new names") } @@ -41,6 +42,18 @@ module Decidim::Admin it "updates the plural of the scope" do expect(translated(area_type.plural)).to eq("new names") end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:update, area_type, user, {}) + .and_call_original + + expect { subject.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("update") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-admin/spec/commands/decidim/admin/update_attachment_spec.rb b/decidim-admin/spec/commands/decidim/admin/update_attachment_spec.rb new file mode 100644 index 0000000000000..54b2c7e11f195 --- /dev/null +++ b/decidim-admin/spec/commands/decidim/admin/update_attachment_spec.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim::Admin + describe UpdateAttachment do + let!(:participatory_process) { create(:participatory_process) } + let!(:attachment) { create(:attachment, attached_to: participatory_process) } + let!(:user) { create(:user) } + + let(:form) do + instance_double( + AttachmentForm, + title: { + en: "An image", + ca: "Una imatge", + es: "Una imagen" + }, + description: { + en: "A city", + ca: "Una ciutat", + es: "Una ciudad" + }, + file: file, + attachment_collection: nil, + weight: 2 + ) + end + let(:file) { upload_test_file(Decidim::Dev.test_file("city.jpeg", "image/jpeg")) } + + describe "when valid" do + before do + allow(form).to receive(:invalid?).and_return(false) + end + + it "broadcasts :ok and updates the attachment" do + expect do + described_class.call(attachment, form, user) + end.to broadcast(:ok) + + expect(attachment["title"]["en"]).to eq("An image") + expect(attachment.weight).to eq(2) + end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:update, attachment, user, {}) + .and_call_original + + expect { described_class.call(attachment, form, user) }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("update") + expect(action_log.version).to be_present + end + end + + describe "when invalid" do + before do + allow(form).to receive(:invalid?).and_return(true) + end + + it "does not update the component" do + expect do + described_class.call(attachment, form, user) + end.to broadcast(:invalid) + + attachment.reload + expect(attachment.title["en"]).not_to eq("An image") + end + end + end +end diff --git a/decidim-admin/spec/commands/decidim/admin/update_component_permissions_spec.rb b/decidim-admin/spec/commands/decidim/admin/update_component_permissions_spec.rb index 3208f91e43e76..588af51f5fcc6 100644 --- a/decidim-admin/spec/commands/decidim/admin/update_component_permissions_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/update_component_permissions_spec.rb @@ -4,10 +4,11 @@ module Decidim::Admin describe UpdateComponentPermissions do - subject(:command) { described_class.call(form, component, resource) } + subject(:command) { described_class.call(form, component, resource, user) } let(:organization) { create(:organization, available_authorizations: ["dummy"]) } let(:participatory_process) { create(:participatory_process, :with_steps, organization: organization) } + let(:user) { create(:user, organization: organization) } let(:component) do create( @@ -45,7 +46,7 @@ module Decidim::Admin dummy: { options: { "perry" => "mason" } } }, authorization_handlers_names: ["dummy"], - authorization_handlers_options: { dummy: { "perry" => "mason" } } + authorization_handlers_options: { "dummy" => { "perry" => "mason" } } ) } ) @@ -87,6 +88,18 @@ module Decidim::Admin expect(component.permissions).to eq(expected_permissions) end + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with("update_permissions", Decidim::Component, user) + .and_call_original + + expect { subject }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("update_permissions") + expect(action_log.version).to be_present + end + context "when receives a resource" do let(:resource) { create(:dummy_resource, component: component) } let(:expected_permissions) { component.permissions.merge(changing_permissions) } diff --git a/decidim-admin/spec/commands/decidim/admin/update_component_spec.rb b/decidim-admin/spec/commands/decidim/admin/update_component_spec.rb index 9e501e71fe350..e8e320c79ff77 100644 --- a/decidim-admin/spec/commands/decidim/admin/update_component_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/update_component_spec.rb @@ -8,6 +8,7 @@ module Decidim::Admin let(:step) { participatory_process.steps.first } let!(:component) { create(:component, :with_one_step, participatory_space: participatory_process) } let(:manifest) { component.manifest } + let(:user) { create :user } let(:form) do instance_double( @@ -21,21 +22,21 @@ module Decidim::Admin invalid?: !valid, valid?: valid, settings: { - dummy_global_attribute_1: true, - dummy_global_attribute_2: false, + dummy_global_attribute1: true, + dummy_global_attribute2: false, readonly_attribute: false }, default_step_settings: { step.id.to_s => { - dummy_step_attribute_1: true, - dummy_step_attribute_2: false, + dummy_step_attribute1: true, + dummy_step_attribute2: false, readonly_step_attribute: false } }, step_settings: { step.id.to_s => { - dummy_step_attribute_1: true, - dummy_step_attribute_2: false, + dummy_step_attribute1: true, + dummy_step_attribute2: false, readonly_step_attribute: false } } @@ -47,19 +48,19 @@ module Decidim::Admin it "broadcasts :ok and updates the component (except the readonly attribute)" do expect do - described_class.call(form, component) + described_class.call(form, component, user) end.to broadcast(:ok) expect(component["name"]["en"]).to eq("My component") expect(component.weight).to eq(3) - expect(component.settings.dummy_global_attribute_1).to eq(true) - expect(component.settings.dummy_global_attribute_2).to eq(false) - expect(component.settings.readonly_attribute).to eq(true) + expect(component.settings.dummy_global_attribute1).to be(true) + expect(component.settings.dummy_global_attribute2).to be(false) + expect(component.settings.readonly_attribute).to be(true) step_settings = component.step_settings[step.id.to_s] - expect(step_settings.dummy_step_attribute_1).to eq(true) - expect(step_settings.dummy_step_attribute_2).to eq(false) - expect(step_settings.readonly_step_attribute).to eq(true) + expect(step_settings.dummy_step_attribute1).to be(true) + expect(step_settings.dummy_step_attribute2).to be(false) + expect(step_settings.readonly_step_attribute).to be(true) end it "fires the hooks" do @@ -69,7 +70,7 @@ module Decidim::Admin results[:component] = component end - described_class.call(form, component) + described_class.call(form, component, user) component = results[:component] expect(component.name["en"]).to eq("My component") @@ -78,7 +79,7 @@ module Decidim::Admin it "broadcasts the previous and current settings" do expect do - described_class.call(form, component) + described_class.call(form, component, user) end.to broadcast( :ok, true, @@ -93,6 +94,18 @@ module Decidim::Admin ) ) end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with("update", Decidim::Component, user) + .and_call_original + + expect { described_class.call(form, component, user) }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("update") + expect(action_log.version).to be_present + end end describe "when invalid" do @@ -100,7 +113,7 @@ module Decidim::Admin it "does not update the component" do expect do - described_class.call(form, component) + described_class.call(form, component, user) end.to broadcast(:invalid) component.reload diff --git a/decidim-admin/spec/commands/decidim/admin/update_content_block_spec.rb b/decidim-admin/spec/commands/decidim/admin/update_content_block_spec.rb index 06bc7198468a3..5845fa8c9ffaa 100644 --- a/decidim-admin/spec/commands/decidim/admin/update_content_block_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/update_content_block_spec.rb @@ -14,7 +14,7 @@ module Decidim::Admin } end let(:uploaded_image) do - ActiveStorage::Blob.create_after_upload!( + ActiveStorage::Blob.create_and_upload!( io: File.open(Decidim::Dev.asset("city.jpeg")), filename: "city.jpeg", content_type: "image/jpeg" @@ -54,7 +54,7 @@ module Decidim::Admin it "updates the content block settings" do subject.call content_block.reload - expect(content_block.settings.welcome_text[:en]).to eq("My text") + expect(content_block.settings.welcome_text["en"]).to eq("My text") end context "when the image does not exist" do @@ -71,7 +71,7 @@ module Decidim::Admin context "when the image exists" do let(:original_image) do - ActiveStorage::Blob.create_after_upload!( + ActiveStorage::Blob.create_and_upload!( io: File.open(Decidim::Dev.asset("city.jpeg")), filename: "city.jpeg", content_type: "image/jpeg" diff --git a/decidim-admin/spec/commands/decidim/admin/update_external_domain_whitelist_spec.rb b/decidim-admin/spec/commands/decidim/admin/update_external_domain_whitelist_spec.rb index 4ac612ebac96b..de956ab3f6115 100644 --- a/decidim-admin/spec/commands/decidim/admin/update_external_domain_whitelist_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/update_external_domain_whitelist_spec.rb @@ -5,12 +5,13 @@ module Decidim::Admin describe UpdateExternalDomainWhitelist do let(:organization) { create(:organization, external_domain_whitelist: []) } + let(:user) { create(:user, organization: organization) } let(:form) { Decidim::Admin::OrganizationExternalDomainWhitelistForm.from_params(attributes) } - let(:command) { described_class.new(form, organization) } + let(:command) { described_class.new(form, organization, user) } let(:domains) { ["erabaki.pamplona.es", "osallistu.hel.fi", "codefor.fr"] } let(:attributes) do { - "external_domains": { + external_domains: { "1613404734167" => { "value" => domains[0], "id" => "", "position" => "0", "deleted" => "false" }, "1613404734172" => { "value" => domains[1], "id" => "", "position" => "1", "deleted" => "false" }, "1613404734961" => { "value" => domains[2], "id" => "", "position" => "2", "deleted" => "false" } @@ -32,6 +33,18 @@ module Decidim::Admin expect(organization.external_domain_whitelist).to include(domains[2]) expect(organization.external_domain_whitelist.length).to eq(3) end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with("update_external_domain", organization, user) + .and_call_original + + expect { command.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("update_external_domain") + expect(action_log.version).to be_present + end end describe "when the form is not valid" do diff --git a/decidim-admin/spec/commands/decidim/admin/update_help_sections_spec.rb b/decidim-admin/spec/commands/decidim/admin/update_help_sections_spec.rb new file mode 100644 index 0000000000000..53d93b3c38741 --- /dev/null +++ b/decidim-admin/spec/commands/decidim/admin/update_help_sections_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim::Admin + describe UpdateHelpSections do + let(:organization) { create(:organization, external_domain_whitelist: []) } + let(:user) { create(:user, organization: organization) } + let(:form) { Decidim::Admin::HelpSectionsForm.from_params(attributes) } + let(:command) { described_class.new(form, organization, user) } + let(:attributes) do + { + sections: { + 1 => { "id" => "assembly", "content" => { en: "Repelle" } } + } + } + end + + describe "when the form is valid" do + it "broadcasts ok" do + expect { command.call }.to broadcast(:ok) + end + + it "update help sections" do + command.call + expect(Decidim::ContextualHelpSection.find_by("section_id" => "assembly").content).to eq({ "en" => "Repelle" }) + end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with("update", Decidim::ContextualHelpSection, user, { "resource" => { "title" => "Assembly" } }) + .and_call_original + + expect { command.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("update") + expect(action_log.version).to be_present + end + end + + describe "when the form is not valid" do + before do + allow(form).to receive(:valid?).and_return(false) + end + + it "broadcasts invalid" do + expect { command.call }.to broadcast(:invalid) + end + + it "doesn't update help sections" do + expect(Decidim::ContextualHelpSection.find_by("id" => "assembly")).to be_nil + end + end + end +end diff --git a/decidim-admin/spec/commands/decidim/admin/update_newsletter_spec.rb b/decidim-admin/spec/commands/decidim/admin/update_newsletter_spec.rb index 2d55f6d000302..1d04a15521e60 100644 --- a/decidim-admin/spec/commands/decidim/admin/update_newsletter_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/update_newsletter_spec.rb @@ -65,7 +65,7 @@ module Decidim::Admin expect(newsletter.author).to eq(user) expect(newsletter.subject.except("machine_translations")).to eq(form.subject.deep_stringify_keys.except("machine_translations")) - expect(newsletter.sent?).to eq(false) + expect(newsletter.sent?).to be(false) expect(newsletter.template).to be_present expect(newsletter.template.settings.body.stringify_keys).to eq(newsletter_body.stringify_keys.except("machine_translations")) end diff --git a/decidim-admin/spec/commands/decidim/admin/update_organization_appearance_spec.rb b/decidim-admin/spec/commands/decidim/admin/update_organization_appearance_spec.rb index e6a1af936d8f8..1280921c6a7a4 100644 --- a/decidim-admin/spec/commands/decidim/admin/update_organization_appearance_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/update_organization_appearance_spec.rb @@ -15,7 +15,7 @@ module Decidim::Admin description_ca: "La meva descripció", enable_omnipresent_banner: false, header_snippets: '', - favicon: fixture_file_upload(File.new(Decidim::Dev.asset("icon.png"))) + favicon: upload_test_file(Decidim::Dev.test_file("city.jpeg", "image/jpeg")) } } end @@ -32,7 +32,7 @@ module Decidim::Admin describe "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do @@ -49,10 +49,10 @@ module Decidim::Admin describe "when the organization is not valid" do before do - expect(form).to receive(:invalid?).and_return(false) + allow(form).to receive(:invalid?).and_return(false) expect(organization).to receive(:valid?).at_least(:once).and_return(false) - organization.errors.add(:official_img_header, "Image too big") - organization.errors.add(:official_img_footer, "Image too big") + organization.errors.add(:official_img_header, "File resolution is too large") + organization.errors.add(:official_img_footer, "File resolution is too large") end it "broadcasts invalid" do diff --git a/decidim-admin/spec/commands/decidim/admin/update_organization_spec.rb b/decidim-admin/spec/commands/decidim/admin/update_organization_spec.rb index d1d5e0878d027..7d6ff0464104b 100644 --- a/decidim-admin/spec/commands/decidim/admin/update_organization_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/update_organization_spec.rb @@ -17,7 +17,7 @@ module Decidim::Admin badges_enabled: true, user_groups_enabled: true, send_welcome_notification: false, - admin_terms_of_use_body: { "en": Faker::Lorem.paragraph }, + admin_terms_of_use_body: { en: Faker::Lorem.paragraph }, rich_text_editor_in_public_views: true, machine_translation_display_priority: "translation", enable_machine_translations: true @@ -37,7 +37,7 @@ module Decidim::Admin describe "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do @@ -75,8 +75,8 @@ module Decidim::Admin organization.reload expect(organization.name).to eq("My super organization") - expect(organization.rich_text_editor_in_public_views).to eq(true) - expect(organization.enable_machine_translations).to eq(true) + expect(organization.rich_text_editor_in_public_views).to be(true) + expect(organization.enable_machine_translations).to be(true) end end end diff --git a/decidim-admin/spec/commands/decidim/admin/update_scope_type_spec.rb b/decidim-admin/spec/commands/decidim/admin/update_scope_type_spec.rb index f4810d606058d..a15deb66bb5f7 100644 --- a/decidim-admin/spec/commands/decidim/admin/update_scope_type_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/update_scope_type_spec.rb @@ -4,9 +4,10 @@ module Decidim::Admin describe UpdateScopeType do - subject { described_class.new(scope_type, form) } + subject { described_class.new(scope_type, form, user) } let(:organization) { create :organization } + let(:user) { create(:user, organization: organization) } let(:scope_type) { create :scope_type, organization: organization } let(:name) { Decidim::Faker::Localized.literal("new name") } let(:plural) { Decidim::Faker::Localized.literal("new names") } @@ -41,6 +42,18 @@ module Decidim::Admin it "updates the plural of the scope" do expect(translated(scope_type.plural)).to eq("new names") end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with(:update, scope_type, user, {}) + .and_call_original + + expect { subject.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("update") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-admin/spec/commands/decidim/admin/update_static_page_spec.rb b/decidim-admin/spec/commands/decidim/admin/update_static_page_spec.rb index 434a255bda284..0579c3ee0b837 100644 --- a/decidim-admin/spec/commands/decidim/admin/update_static_page_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/update_static_page_spec.rb @@ -20,7 +20,7 @@ module Decidim::Admin describe "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do @@ -58,7 +58,7 @@ module Decidim::Admin page.reload expect(page.slug).to eq("new-slug") - expect(page.allow_public_access).to eq(true) + expect(page.allow_public_access).to be(true) end end end diff --git a/decidim-admin/spec/commands/decidim/admin/verify_user_group_spec.rb b/decidim-admin/spec/commands/decidim/admin/verify_user_group_spec.rb index 7088b49110dab..0a21d4f6c04fd 100644 --- a/decidim-admin/spec/commands/decidim/admin/verify_user_group_spec.rb +++ b/decidim-admin/spec/commands/decidim/admin/verify_user_group_spec.rb @@ -17,7 +17,7 @@ module Decidim::Admin let(:invalid) { true } it "broadcasts invalid in return" do - expect(user_group).to receive(:valid?).and_return(false) + allow(user_group).to receive(:valid?).and_return(false) expect { subject.call }.to broadcast(:invalid) expect(user_group.rejected_at).to be_nil @@ -50,7 +50,7 @@ module Decidim::Admin let(:invalid) { true } it "broadcasts invalid in return and do not clean rejected_at" do - expect(user_group).to receive(:valid?).and_return(false) + allow(user_group).to receive(:valid?).and_return(false) expect { subject.call }.to broadcast(:invalid) expect(user_group.rejected_at).not_to be_nil diff --git a/decidim-admin/spec/controllers/block_user_controller_spec.rb b/decidim-admin/spec/controllers/block_user_controller_spec.rb index aff59a870748b..3b550ec201056 100644 --- a/decidim-admin/spec/controllers/block_user_controller_spec.rb +++ b/decidim-admin/spec/controllers/block_user_controller_spec.rb @@ -16,77 +16,101 @@ module Admin end describe "unblock" do - let!(:user) { create(:user, :blocked, :confirmed, organization: organization, nickname: "some_nickname") } + shared_examples "unblocking a user or group" do + context "when having a user" do + it "flashes a notice message" do + delete :destroy, params: { user_id: user.id } + + expect(flash[:notice]).to be_present + expect(user.reload.blocked?).to be(false) + end + end - context "when having a user" do - it "flashes a notice message" do - delete :destroy, params: { user_id: user.id } + context "when the user is not blocked" do + before do + user.blocked = false + user.save! + end - expect(flash[:notice]).to be_present - expect(user.reload.blocked?).to be(false) - end - end + it "flashes an alert message" do + delete :destroy, params: { user_id: user.id } - context "when the user is not blocked" do - before do - user.blocked = false - user.save! + expect(flash[:alert]).to be_present + expect(user.reload.blocked?).to be(false) + end end - it "flashes an alert message" do - delete :destroy, params: { user_id: user.id } + context "when current user is not an admin" do + before do + current_user.admin = false + current_user.save! + end + + it "the user remains blocked" do + delete :destroy, params: { user_id: user.id } - expect(flash[:alert]).to be_present - expect(user.reload.blocked?).to be(false) + expect(user.reload.blocked?).to be(true) + end end end - context "when current user is not an admin" do - before do - current_user.admin = false - current_user.save! - end + context "when its a user" do + let!(:user) { create(:user, :blocked, :confirmed, organization: organization, nickname: "some_nickname") } + + it_behaves_like "unblocking a user or group" + end - it "the user remains blocked" do - delete :destroy, params: { user_id: user.id } + context "when its a user group" do + let!(:user) { create(:user_group, :blocked, :confirmed, organization: organization, nickname: "another_nickname") } - expect(user.reload.blocked?).to be(true) - end + it_behaves_like "unblocking a user or group" end end describe "block" do - let!(:user) { create(:user, :confirmed, organization: organization, nickname: "some_nickname") } + shared_examples "blocking a user or group" do + context "when having a user" do + it "flashes a notice message" do + put :create, params: { user_id: user.id, justification: ::Faker::Lorem.sentence(word_count: 12) } + + expect(flash[:notice]).to be_present + expect(user.reload.blocked?).to be(true) + end + end - context "when having a user" do - it "flashes a notice message" do - put :create, params: { user_id: user.id, justification: ::Faker::Lorem.sentence(word_count: 12) } + context "when form is invalid" do + it "flashes an alert message" do + put :create, params: { user_id: user.id, justification: nil } - expect(flash[:notice]).to be_present - expect(user.reload.blocked?).to be(true) + expect(flash[:alert]).to be_present + expect(user.reload.blocked?).to be(false) + end end - end - context "when form is invalid" do - it "flashes an alert message" do - put :create, params: { user_id: user.id, justification: nil } + context "when current user is not an admin" do + before do + current_user.admin = false + current_user.save! + end - expect(flash[:alert]).to be_present - expect(user.reload.blocked?).to be(false) + it "the user remains unblocked" do + put :create, params: { user_id: user.id, justification: ::Faker::Lorem.sentence(word_count: 12) } + + expect(user.reload.blocked?).to be(false) + end end end - context "when current user is not an admin" do - before do - current_user.admin = false - current_user.save! - end + context "when its a user" do + let!(:user) { create(:user, :confirmed, organization: organization, nickname: "some_nickname") } - it "the user remains unblocked" do - put :create, params: { user_id: user.id, justification: ::Faker::Lorem.sentence(word_count: 12) } + it_behaves_like "blocking a user or group" + end - expect(user.reload.blocked?).to be(false) - end + context "when its a user group" do + let!(:user) { create(:user_group, :confirmed, organization: organization, nickname: "another_nickname") } + + it_behaves_like "blocking a user or group" end end end diff --git a/decidim-admin/spec/controllers/concerns/impersonate_users_spec.rb b/decidim-admin/spec/controllers/concerns/impersonate_users_spec.rb index ca1444e57c783..e4b5103430409 100644 --- a/decidim-admin/spec/controllers/concerns/impersonate_users_spec.rb +++ b/decidim-admin/spec/controllers/concerns/impersonate_users_spec.rb @@ -27,17 +27,17 @@ class ImpersonateFakeController < Decidim::Admin::ApplicationController request.set_header k, [Mime[:js], Mime[:html], Mime[:xml], "text/xml", "*/*"].join(", ") end allow(controller).to receive(:request).and_return(request) - expect(controller.send(:check_impersonation_log_expired)).to eq(nil) + expect(controller.send(:check_impersonation_log_expired)).to be_nil end it "returns nil on non HTML responses" do request.set_header "HTTP_ACCEPT", [Mime[:js], Mime[:xml]].join(",") allow(controller).to receive(:request).and_return(request) - expect(controller.send(:check_impersonation_log_expired)).to eq(nil) + expect(controller.send(:check_impersonation_log_expired)).to be_nil end it "redirects when impersonated session is expired" do - expect(controller.send(:check_impersonation_log_expired)).to eq(nil) + expect(controller.send(:check_impersonation_log_expired)).to be_nil request.set_header "HTTP_ACCEPT", [Mime[:html], "text/html"].join(",") allow(controller).to receive(:real_user).and_return(user) diff --git a/decidim-admin/spec/controllers/static_pages_controller_spec.rb b/decidim-admin/spec/controllers/static_pages_controller_spec.rb index 5ec750041037a..2f18b3da21bad 100644 --- a/decidim-admin/spec/controllers/static_pages_controller_spec.rb +++ b/decidim-admin/spec/controllers/static_pages_controller_spec.rb @@ -26,7 +26,7 @@ module Admin it "assigns the default value for the allow_public_access" do post :create, params: {} - expect(assigns(:form).allow_public_access).to eq(false) + expect(assigns(:form).allow_public_access).to be(false) end end @@ -34,13 +34,13 @@ module Admin it "does not overwrite it when unchecked" do put :create, params: { static_page: { allow_public_access: "0" } }.with_indifferent_access - expect(assigns(:form).allow_public_access).to eq(false) + expect(assigns(:form).allow_public_access).to be(false) end it "does not overwrite it when checked" do post :create, params: { static_page: { allow_public_access: "1" } }.with_indifferent_access - expect(assigns(:form).allow_public_access).to eq(true) + expect(assigns(:form).allow_public_access).to be(true) end end end @@ -75,14 +75,14 @@ module Admin page.update!(allow_public_access: true) put :update, params: { id: page.id }.with_indifferent_access - expect(assigns(:form).allow_public_access).to eq(true) + expect(assigns(:form).allow_public_access).to be(true) end it "injects it to the form when set to false" do page.update!(allow_public_access: false) put :update, params: { id: page.id }.with_indifferent_access - expect(assigns(:form).allow_public_access).to eq(false) + expect(assigns(:form).allow_public_access).to be(false) end end @@ -91,14 +91,14 @@ module Admin page.update!(allow_public_access: true) put :update, params: { id: page.id, static_page: { allow_public_access: "0" } }.with_indifferent_access - expect(assigns(:form).allow_public_access).to eq(false) + expect(assigns(:form).allow_public_access).to be(false) end it "does not overwrite it when checked" do page.update!(allow_public_access: false) put :update, params: { id: page.id, static_page: { allow_public_access: "1" } }.with_indifferent_access - expect(assigns(:form).allow_public_access).to eq(true) + expect(assigns(:form).allow_public_access).to be(true) end end end diff --git a/decidim-admin/spec/forms/block_user_form_spec.rb b/decidim-admin/spec/forms/block_user_form_spec.rb index aff2a65afa4bd..2759ba3c11147 100644 --- a/decidim-admin/spec/forms/block_user_form_spec.rb +++ b/decidim-admin/spec/forms/block_user_form_spec.rb @@ -6,52 +6,63 @@ module Decidim module Admin describe BlockUserForm do let(:organization) { create(:organization) } - - let(:user) { create(:user, organization: organization) } - let(:justification) { "" } - describe "from a model" do - subject do - described_class.from_model( - user - ).with_context( - current_organization: organization - ) - end + shared_examples "blocking a user or group" do + describe "from a model" do + subject do + described_class.from_model( + user + ).with_context( + current_organization: organization + ) + end - context "when justification form is empty" do - it { is_expected.not_to be_valid } + context "when justification form is empty" do + it { is_expected.not_to be_valid } + end end - end - describe "from params" do - subject do - described_class.from_params( - justification: justification, user_id: user.id - ).with_context( - current_organization: organization - ) - end + describe "from params" do + subject do + described_class.from_params( + justification: justification, user_id: user.id + ).with_context( + current_organization: organization + ) + end - context "when justification has the correct length" do - let(:justification) { "Not TOS compliant." } + context "when justification has the correct length" do + let(:justification) { "Not TOS compliant." } - it { is_expected.to be_valid } - end + it { is_expected.to be_valid } + end - context "when justification is too short" do - let(:justification) { "Not TOS." } + context "when justification is too short" do + let(:justification) { "Not TOS." } - it { is_expected.not_to be_valid } - end + it { is_expected.not_to be_valid } + end - context "when the user does not exist" do - let(:user_id) { 9999 } + context "when the user does not exist" do + let(:user_id) { 9999 } - it { is_expected.not_to be_valid } + it { is_expected.not_to be_valid } + end end end + + context "with a user" do + let(:user) { create(:user, organization: organization) } + + it_behaves_like "blocking a user or group" + end + + context "with a user group" do + let(:user) { create(:user_group, organization: organization) } + + it_behaves_like "blocking a user or group" + end end end end diff --git a/decidim-admin/spec/forms/decidim/admin/import_form_spec.rb b/decidim-admin/spec/forms/decidim/admin/import_form_spec.rb index f596758fec30c..347d49d14bf3c 100644 --- a/decidim-admin/spec/forms/decidim/admin/import_form_spec.rb +++ b/decidim-admin/spec/forms/decidim/admin/import_form_spec.rb @@ -10,7 +10,7 @@ module Admin let(:organization) { create(:organization) } let!(:component) { create(:dummy_component, organization: organization) } let(:user) { create(:user, :confirmed, :admin, organization: organization) } - let(:file) { Decidim::Dev.test_file("import_proposals.csv", "text/csv") } + let(:file) { upload_test_file(Decidim::Dev.test_file("import_proposals.csv", "text/csv")) } let(:name) { "dummies" } let(:params) { { file: file, name: name } } @@ -28,17 +28,17 @@ module Admin end context "when content type is not accepted" do - let(:file) { Decidim::Dev.test_file("city.jpeg", "image/jpeg") } + let(:file) { upload_test_file(Decidim::Dev.test_file("city.jpeg", "image/jpeg")) } it { is_expected.not_to be_valid } end context "when the file is not a valid file" do - let(:file) { Decidim::Dev.test_file("Exampledocument.pdf", Decidim::Admin::Import::Readers::XLSX::MIME_TYPE) } + let(:file) { upload_test_file(Decidim::Dev.test_file("Exampledocument.pdf", Decidim::Admin::Import::Readers::XLSX::MIME_TYPE)) } it "reports invalid and adds the correct error for the file field" do expect(subject).not_to be_valid - expect(subject.errors[:file]).to include("Invalid file provided, please check that the file is correctly formatted") + expect(subject.errors[:file]).to include("Invalid mime type") end end end diff --git a/decidim-admin/spec/forms/decidim/admin/transfer_user_form_spec.rb b/decidim-admin/spec/forms/decidim/admin/transfer_user_form_spec.rb index 43879b707bbfe..b5f3554aba958 100644 --- a/decidim-admin/spec/forms/decidim/admin/transfer_user_form_spec.rb +++ b/decidim-admin/spec/forms/decidim/admin/transfer_user_form_spec.rb @@ -34,13 +34,13 @@ module Admin end context "when no current_user is passed" do - let(:current_user) {} + let(:current_user) { nil } it { is_expected.to be_invalid } end context "when no conflict is passed" do - let(:conflict) {} + let(:conflict) { nil } it { is_expected.to be_invalid } end diff --git a/decidim-admin/spec/forms/managed_user_promotion_form_spec.rb b/decidim-admin/spec/forms/managed_user_promotion_form_spec.rb index 8cd35f44ee9ab..28feba9e5ceb8 100644 --- a/decidim-admin/spec/forms/managed_user_promotion_form_spec.rb +++ b/decidim-admin/spec/forms/managed_user_promotion_form_spec.rb @@ -29,7 +29,7 @@ module Admin end context "when email is missing" do - let(:email) {} + let(:email) { nil } it { is_expected.to be_invalid } end diff --git a/decidim-admin/spec/forms/organization_appearance_form_spec.rb b/decidim-admin/spec/forms/organization_appearance_form_spec.rb index 48243aa066084..3375ec983bb1b 100644 --- a/decidim-admin/spec/forms/organization_appearance_form_spec.rb +++ b/decidim-admin/spec/forms/organization_appearance_form_spec.rb @@ -101,7 +101,7 @@ module Admin let(:highlighted_content_banner_action_title) { Decidim::Faker::Localized.sentence(word_count: 2) } let(:highlighted_content_banner_action_subtitle) { Decidim::Faker::Localized.sentence(word_count: 2) } let(:highlighted_content_banner_action_url) { ::Faker::Internet.url } - let(:highlighted_content_banner_image) { Decidim::Dev.test_file("city.jpeg", "image/jpeg") } + let(:highlighted_content_banner_image) { upload_test_file(Decidim::Dev.test_file("city.jpeg", "image/jpeg")) } it { is_expected.to be_valid } @@ -130,12 +130,12 @@ module Admin end context "and highlighted_content_banner_image is blank" do - let(:highlighted_content_banner_image) { "" } + let(:highlighted_content_banner_image) { nil } it { is_expected.not_to be_valid } context "and the organization already has an image set" do - let(:organization) { create :organization, highlighted_content_banner_image: Decidim::Dev.test_file("city.jpeg", "image/jpeg") } + let(:organization) { create :organization, highlighted_content_banner_image: upload_test_file(Decidim::Dev.test_file("city.jpeg", "image/jpeg")) } let(:highlighted_content_banner_image) { nil } it { is_expected.to be_valid } diff --git a/decidim-admin/spec/forms/participatory_space_private_user_csv_import_form_spec.rb b/decidim-admin/spec/forms/participatory_space_private_user_csv_import_form_spec.rb index 43a12338c1716..914efc6edfdac 100644 --- a/decidim-admin/spec/forms/participatory_space_private_user_csv_import_form_spec.rb +++ b/decidim-admin/spec/forms/participatory_space_private_user_csv_import_form_spec.rb @@ -22,7 +22,7 @@ module Admin "file" => file } end - let(:file) { File.new Decidim::Dev.asset("import_participatory_space_private_users.csv") } + let(:file) { upload_test_file(Decidim::Dev.asset("import_participatory_space_private_users.csv")) } context "when everything is OK" do it { is_expected.to be_valid } @@ -35,10 +35,21 @@ module Admin end context "when user name contains invalid chars" do - let(:file) { File.new Decidim::Dev.asset("import_participatory_space_private_users_nok.csv") } + let(:file) { upload_test_file(Decidim::Dev.asset("import_participatory_space_private_users_nok.csv")) } it { is_expected.to be_invalid } end + + context "when the provided file is encoded with incorrect character set" do + let(:file) { upload_test_file(Decidim::Dev.asset("import_participatory_space_private_users_iso8859-1.csv")) } + + it { is_expected.to be_invalid } + + it "adds the correct error" do + subject.valid? + expect(subject.errors[:file].join).to eq("Malformed import file, please read through the instructions carefully and make sure the file is UTF-8 encoded.") + end + end end end end diff --git a/decidim-admin/spec/forms/participatory_space_private_user_form_spec.rb b/decidim-admin/spec/forms/participatory_space_private_user_form_spec.rb index 1aea18c934585..96c3fdd7df1a8 100644 --- a/decidim-admin/spec/forms/participatory_space_private_user_form_spec.rb +++ b/decidim-admin/spec/forms/participatory_space_private_user_form_spec.rb @@ -23,7 +23,7 @@ module Admin end context "when email is missing" do - let(:email) {} + let(:email) { nil } it { is_expected.to be_invalid } end diff --git a/decidim-admin/spec/forms/static_page_form_spec.rb b/decidim-admin/spec/forms/static_page_form_spec.rb index 839f57bf9c6b7..5508f2010f613 100644 --- a/decidim-admin/spec/forms/static_page_form_spec.rb +++ b/decidim-admin/spec/forms/static_page_form_spec.rb @@ -152,7 +152,7 @@ module Admin describe "#control_public_access?" do context "when organization does not require authentication" do it "returns false" do - expect(subject.control_public_access?).to eq(false) + expect(subject.control_public_access?).to be(false) end end @@ -160,7 +160,7 @@ module Admin let(:organization) { create(:organization, force_users_to_authenticate_before_access_organization: true) } it "returns true" do - expect(subject.control_public_access?).to eq(true) + expect(subject.control_public_access?).to be(true) end end end diff --git a/decidim-admin/spec/forms/user_group_csv_verification_form_spec.rb b/decidim-admin/spec/forms/user_group_csv_verification_form_spec.rb index 6b9144d57962c..a53f63ccea64e 100644 --- a/decidim-admin/spec/forms/user_group_csv_verification_form_spec.rb +++ b/decidim-admin/spec/forms/user_group_csv_verification_form_spec.rb @@ -12,7 +12,7 @@ module Admin "file" => file } end - let(:file) { File.new Decidim::Dev.asset("verify_user_groups.csv") } + let(:file) { upload_test_file(Decidim::Dev.test_file("verify_user_groups.csv", "text/csv"), return_blob: true) } context "when everything is OK" do it { is_expected.to be_valid } @@ -23,6 +23,17 @@ module Admin it { is_expected.to be_invalid } end + + context "when the provided file is encoded with incorrect character set" do + let(:file) { upload_test_file(Decidim::Dev.asset("import_participatory_space_private_users_iso8859-1.csv")) } + + it { is_expected.to be_invalid } + + it "adds the correct error" do + subject.valid? + expect(subject.errors[:file].join).to eq("Malformed import file, please read through the instructions carefully and make sure the file is UTF-8 encoded.") + end + end end end end diff --git a/decidim-admin/spec/helpers/aria_selected_link_to_helper_spec.rb b/decidim-admin/spec/helpers/aria_selected_link_to_helper_spec.rb index d81b27557d74c..0582c96ccbc4a 100644 --- a/decidim-admin/spec/helpers/aria_selected_link_to_helper_spec.rb +++ b/decidim-admin/spec/helpers/aria_selected_link_to_helper_spec.rb @@ -21,9 +21,9 @@ module Admin end end - context "when it's ponting to the current path" do + context "when it's pointing to the current path" do before do - expect(helper) + allow(helper) .to receive(:is_active_link?) .and_return true end @@ -33,9 +33,9 @@ module Admin end end - context "when it's ponting to the current path" do + context "when it isn't pointing to the current path" do before do - expect(helper) + allow(helper) .to receive(:is_active_link?) .and_return false end diff --git a/decidim-admin/spec/helpers/moderations/reports_helper_spec.rb b/decidim-admin/spec/helpers/moderations/reports_helper_spec.rb new file mode 100644 index 0000000000000..ca79a347d20d8 --- /dev/null +++ b/decidim-admin/spec/helpers/moderations/reports_helper_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require "spec_helper" +require "decidim/proposals/test/factories" + +module Decidim + module Admin + module Moderations + describe ReportsHelper do + subject do + Nokogiri::HTML( + helper.reportable_author_name(reportable) + ) + end + + before do + allow(helper).to receive(:current_or_new_conversation_path_with).and_return("/conversations/1") + end + + context "with different reportable authors types" do + describe "when it's a dummy resource author" do + let(:reportable) { create(:dummy_resource, title: { "en" => "

Dummy
Title

" }) } + + it "returns the author's name" do + expect(helper.reportable_author_name(reportable)).to include("reportable-authors") + expect(helper.reportable_author_name(reportable)).to include(reportable.author.name) + end + end + + describe "when it's a user author" do + let!(:proposal) { create(:proposal) } + let(:reportable) { proposal } + + it "returns the user's name" do + expect(helper.reportable_author_name(reportable)).to include("reportable-authors") + expect(helper.reportable_author_name(reportable)).to include(reportable.authors.first.name) + end + end + + describe "when it's a meeting author" do + let!(:proposal) { create(:proposal, :official_meeting) } + let(:reportable) { proposal } + + it "returns the meeting's title" do + expect(helper.reportable_author_name(reportable)).to include("reportable-authors") + expect(helper.reportable_author_name(reportable)).to include(translated_attribute(reportable.authors.first.title)) + end + end + end + end + end + end +end diff --git a/decidim-admin/spec/helpers/settings_helper_spec.rb b/decidim-admin/spec/helpers/settings_helper_spec.rb index df1f51f89bbb7..f6ab35eaf803b 100644 --- a/decidim-admin/spec/helpers/settings_helper_spec.rb +++ b/decidim-admin/spec/helpers/settings_helper_spec.rb @@ -148,7 +148,7 @@ def render_input let(:type) { :scope } it "is supported" do - expect(form).to receive(:scopes_picker).with(:test, checkboxes_on_top: true) + expect(form).to receive(:scopes_picker).with(:test, { checkboxes_on_top: true }) render_input end end diff --git a/decidim-admin/spec/lib/admin/form_builder_spec.rb b/decidim-admin/spec/lib/admin/form_builder_spec.rb index f577eba4ea820..4b647b42627f2 100644 --- a/decidim-admin/spec/lib/admin/form_builder_spec.rb +++ b/decidim-admin/spec/lib/admin/form_builder_spec.rb @@ -5,9 +5,9 @@ module Decidim describe Admin::FormBuilder do - let(:subject) { Nokogiri::HTML(output) } + subject { Nokogiri::HTML(output) } - let(:helper) { Class.new(ActionView::Base).new(ActionView::LookupContext.new(nil)) } + let(:helper) { Class.new(ActionView::Base).new(ActionView::LookupContext.new(ActionController::Base.view_paths), {}, []) } let(:available_locales) { %w(ca en de-CH) } let(:resource) do @@ -17,7 +17,7 @@ def self.model_name end include ActiveModel::Model - include Virtus.model + include Decidim::AttributeObject::Model attribute :category_id, Integer end.new diff --git a/decidim-admin/spec/lib/decidim/admin/import/creator_spec.rb b/decidim-admin/spec/lib/decidim/admin/import/creator_spec.rb index 4008d6f7b43fb..0bdb43761a3d9 100644 --- a/decidim-admin/spec/lib/decidim/admin/import/creator_spec.rb +++ b/decidim-admin/spec/lib/decidim/admin/import/creator_spec.rb @@ -4,7 +4,7 @@ module Decidim::Admin::Import describe Creator do - let(:subject) { described_class.new(unknown_resource) } + subject { described_class.new(unknown_resource) } let(:unknown_resource) { { field: "foo" } } it "cant finish without implementation for a resource" do diff --git a/decidim-admin/spec/lib/decidim/admin/import/readers/base_spec.rb b/decidim-admin/spec/lib/decidim/admin/import/readers/base_spec.rb index c7e6dff8643f2..89cae037bf71c 100644 --- a/decidim-admin/spec/lib/decidim/admin/import/readers/base_spec.rb +++ b/decidim-admin/spec/lib/decidim/admin/import/readers/base_spec.rb @@ -4,7 +4,7 @@ module Decidim::Admin::Import::Readers describe Base do - let(:subject) { described_class.new(file) } + subject { described_class.new(file) } let(:file) { Decidim::Dev.test_file("Exampledocument.pdf", "application/pdf") } describe "#read_rows" do diff --git a/decidim-admin/spec/lib/decidim/admin/import/readers/csv_spec.rb b/decidim-admin/spec/lib/decidim/admin/import/readers/csv_spec.rb index 29162e4fee039..a8b0c08655564 100644 --- a/decidim-admin/spec/lib/decidim/admin/import/readers/csv_spec.rb +++ b/decidim-admin/spec/lib/decidim/admin/import/readers/csv_spec.rb @@ -4,7 +4,7 @@ module Decidim::Admin::Import::Readers describe CSV do - let(:subject) { described_class.new(file) } + subject { described_class.new(file) } let(:csv_data) do <<~CSV id;title;detail @@ -18,9 +18,7 @@ module Decidim::Admin::Import::Readers end let(:file) do path = Rails.application.root.join("tmp/test_csv.csv") - File.open(path, "w") do |f| - f.write(csv_data) - end + File.write(path, csv_data) path end diff --git a/decidim-admin/spec/lib/decidim/admin/import/readers/json_spec.rb b/decidim-admin/spec/lib/decidim/admin/import/readers/json_spec.rb index bcc851cad4579..76a3bb80114c5 100644 --- a/decidim-admin/spec/lib/decidim/admin/import/readers/json_spec.rb +++ b/decidim-admin/spec/lib/decidim/admin/import/readers/json_spec.rb @@ -4,7 +4,7 @@ module Decidim::Admin::Import::Readers describe JSON do - let(:subject) { described_class.new(file) } + subject { described_class.new(file) } let(:json_data) do <<~JSON [ @@ -31,9 +31,7 @@ module Decidim::Admin::Import::Readers end let(:file) do path = Rails.application.root.join("tmp/test_json.json") - File.open(path, "w") do |f| - f.write(json_data) - end + File.write(path, json_data) path end diff --git a/decidim-admin/spec/lib/decidim/admin/import/readers/xlsx_spec.rb b/decidim-admin/spec/lib/decidim/admin/import/readers/xlsx_spec.rb index cd2b8c385b50b..192a0e7849394 100644 --- a/decidim-admin/spec/lib/decidim/admin/import/readers/xlsx_spec.rb +++ b/decidim-admin/spec/lib/decidim/admin/import/readers/xlsx_spec.rb @@ -4,7 +4,7 @@ module Decidim::Admin::Import::Readers describe XLSX do - let(:subject) { described_class.new(file) } + subject { described_class.new(file) } let(:file) { Decidim::Dev.test_file("test_excel.xlsx", Decidim::Admin::Import::Readers::XLSX::MIME_TYPE) } describe "#read_rows" do diff --git a/decidim-admin/spec/models/decidim/admin/fake_newsletter_spec.rb b/decidim-admin/spec/models/decidim/admin/fake_newsletter_spec.rb index e99d6ab6f4e22..5796f0c9fb492 100644 --- a/decidim-admin/spec/models/decidim/admin/fake_newsletter_spec.rb +++ b/decidim-admin/spec/models/decidim/admin/fake_newsletter_spec.rb @@ -3,8 +3,9 @@ require "spec_helper" describe Decidim::Admin::FakeNewsletter do - subject { described_class.new(organization, manifest) } + subject { newsletter } + let(:newsletter) { described_class.new(organization, manifest) } let(:organization) { create :organization } let(:manifest) do Decidim @@ -32,4 +33,28 @@ expect(subject.template.settings.body).to include("Dummy text for body") end end + + describe "#url" do + subject { newsletter.url } + + it { is_expected.to eq("#") } + end + + describe "#notifications_settings_url" do + subject { newsletter.notifications_settings_url } + + it { is_expected.to eq("#") } + end + + describe "#unsubscribe_newsletters_url" do + subject { newsletter.unsubscribe_newsletters_url } + + it { is_expected.to eq("#") } + end + + describe "#organization_official_url" do + subject { newsletter.organization_official_url } + + it { is_expected.to eq("#") } + end end diff --git a/decidim-admin/spec/permissions/decidim/admin/permissions_spec.rb b/decidim-admin/spec/permissions/decidim/admin/permissions_spec.rb index b28910e37bdfe..1c1e2a5b61ca2 100644 --- a/decidim-admin/spec/permissions/decidim/admin/permissions_spec.rb +++ b/decidim-admin/spec/permissions/decidim/admin/permissions_spec.rb @@ -8,7 +8,7 @@ let(:user) { build :user, :admin, organization: organization } let(:organization) { build :organization } let(:context) { {} } - let(:permission_action) { Decidim::PermissionAction.new(action) } + let(:permission_action) { Decidim::PermissionAction.new(**action) } let(:registrations_enabled) { true } let(:action) do { scope: :admin, action: action_name, subject: action_subject } @@ -43,12 +43,12 @@ { scope: :public, action: :read, subject: :admin_dashboard } end - it { is_expected.to eq true } + it { is_expected.to be true } context "when user is a user manager" do let(:user) { build :user, :user_manager } - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -58,7 +58,7 @@ context "when user is not present" do let(:user) { nil } - it { is_expected.to eq false } + it { is_expected.to be false } end context "when user is a user manager" do @@ -90,7 +90,7 @@ let(:action_name) { :read } let(:action_subject) { :admin_dashboard } - it { is_expected.to eq true } + it { is_expected.to be true } end describe "admin logs" do @@ -101,7 +101,7 @@ context "when reading" do let(:action_name) { :read } - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -125,7 +125,7 @@ context "when reading" do let(:action_name) { :read } - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -137,7 +137,7 @@ context "when updating" do let(:action_name) { :update } - it { is_expected.to eq true } + it { is_expected.to be true } context "when page is not present" do let(:page) { nil } @@ -162,12 +162,12 @@ context "when page is not default" do let(:page) { build :static_page } - it { is_expected.to eq true } + it { is_expected.to be true } end end context "when any other action" do - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -179,7 +179,7 @@ let(:action_subject) { :share_token } context "when any action" do - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -191,7 +191,7 @@ let(:action_name) { :update } context "when user belongs to organization" do - it { is_expected.to eq true } + it { is_expected.to be true } end context "when user does not belong to organization" do @@ -222,7 +222,7 @@ context "when organization available authorizations are empty" do let(:authorizations) { [] } - it { is_expected.to eq false } + it { is_expected.to be false } end context "when organization available authorizations are not empty" do @@ -235,7 +235,7 @@ end context "when any other action" do - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -248,7 +248,7 @@ let(:action_name) { :destroy } context "when destroying another user" do - it { is_expected.to eq true } + it { is_expected.to be true } end context "when destroying itself" do @@ -277,7 +277,7 @@ end context "when there are no active impersonation logs" do - it { is_expected.to eq true } + it { is_expected.to be true } end end end @@ -315,14 +315,14 @@ end context "when there are no active impersonation logs" do - it { is_expected.to eq true } + it { is_expected.to be true } end end context "when show their email" do let(:action_name) { :show_email } - it { is_expected.to eq true } + it { is_expected.to be true } context "when user is not an admin" do let(:user) { build :user, organization: organization } @@ -332,14 +332,14 @@ end context "when any other action" do - it { is_expected.to eq true } + it { is_expected.to be true } end end shared_examples "can perform any action for" do |action_subject_name| let(:action_subject) { action_subject_name } - it { is_expected.to eq true } + it { is_expected.to be true } end it_behaves_like "can perform any action for", :category diff --git a/decidim-admin/spec/permissions/decidim/admin/user_manager_permissions_spec.rb b/decidim-admin/spec/permissions/decidim/admin/user_manager_permissions_spec.rb index b5e8ee007e4d4..773234b137d36 100644 --- a/decidim-admin/spec/permissions/decidim/admin/user_manager_permissions_spec.rb +++ b/decidim-admin/spec/permissions/decidim/admin/user_manager_permissions_spec.rb @@ -8,7 +8,7 @@ let(:user) { build :user, :user_manager, organization: organization } let(:organization) { build :organization } let(:context) { {} } - let(:permission_action) { Decidim::PermissionAction.new(action) } + let(:permission_action) { Decidim::PermissionAction.new(**action) } let(:space_permissions) { instance_double(Decidim::ParticipatoryProcesses::Permissions, allowed?: space_allows) } let(:registrations_enabled) { true } let(:action) do @@ -25,7 +25,7 @@ let(:action_name) { :read } let(:action_subject) { :admin_dashboard } - it { is_expected.to eq true } + it { is_expected.to be true } end describe "managed users" do @@ -50,12 +50,12 @@ context "when organization available authorizations are not empty" do let(:authorizations) { [:foo] } - it { is_expected.to eq true } + it { is_expected.to be true } end end context "when any other action" do - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -68,7 +68,7 @@ let(:action_name) { :destroy } context "when destroying another user" do - it { is_expected.to eq true } + it { is_expected.to be true } end context "when destroying itself" do @@ -97,7 +97,7 @@ end context "when there are no active impersonation logs" do - it { is_expected.to eq true } + it { is_expected.to be true } end end end @@ -135,12 +135,12 @@ end context "when there are no active impersonation logs" do - it { is_expected.to eq true } + it { is_expected.to be true } end end context "when any other action" do - it { is_expected.to eq true } + it { is_expected.to be true } end end end diff --git a/decidim-admin/spec/presenters/decidim/admin/dashboard_metric_charts_presenter_spec.rb b/decidim-admin/spec/presenters/decidim/admin/dashboard_metric_charts_presenter_spec.rb index 1f8b96c3eb309..d11adddd792f6 100644 --- a/decidim-admin/spec/presenters/decidim/admin/dashboard_metric_charts_presenter_spec.rb +++ b/decidim-admin/spec/presenters/decidim/admin/dashboard_metric_charts_presenter_spec.rb @@ -3,7 +3,7 @@ require "spec_helper" describe Decidim::Admin::DashboardMetricChartsPresenter do - subject { described_class.new(organization: organization, summary: summary) } + subject { described_class.new(organization: organization, summary: summary, view_context: ActionController::Base.new.view_context) } let(:organization) { create :organization } let(:summary) { false } diff --git a/decidim-admin/spec/queries/active_users_counter_spec.rb b/decidim-admin/spec/queries/active_users_counter_spec.rb index d43e2a0e88865..4e790170b2a6a 100644 --- a/decidim-admin/spec/queries/active_users_counter_spec.rb +++ b/decidim-admin/spec/queries/active_users_counter_spec.rb @@ -30,7 +30,7 @@ module Decidim::Admin end it "returns 0 matches" do - query = described_class.new(parameters) + query = described_class.new(**parameters) expect(query.count).to eq(0) end @@ -60,12 +60,12 @@ module Decidim::Admin let(:result) do { - total_admins_last_24: described_class.new(parameters_last_day_admin).query.count, - total_admins_last_week: described_class.new(parameters_last_week_admin).query.count, - total_admins_last_month: described_class.new(parameters_last_month_admin).query.count, - total_participants_last_24: described_class.new(parameters_last_day_participants).query.count, - total_participants_last_week: described_class.new(parameters_last_week_participants).query.count, - total_participants_last_month: described_class.new(parameters_last_month_participants).query.count + total_admins_last_day: described_class.new(**parameters_last_day_admin).query.count, + total_admins_last_week: described_class.new(**parameters_last_week_admin).query.count, + total_admins_last_month: described_class.new(**parameters_last_month_admin).query.count, + total_participants_last_day: described_class.new(**parameters_last_day_participants).query.count, + total_participants_last_week: described_class.new(**parameters_last_week_participants).query.count, + total_participants_last_month: described_class.new(**parameters_last_month_participants).query.count } end @@ -74,7 +74,7 @@ module Decidim::Admin end it "counts total admins logged last 24 hours - 10" do - expect(result[:total_admins_last_24]).to eq(10) + expect(result[:total_admins_last_day]).to eq(10) end it "counts total admins logged last week - 14" do @@ -86,7 +86,7 @@ module Decidim::Admin end it "counts total participants logged last 24 hours - 7" do - expect(result[:total_participants_last_24]).to eq(7) + expect(result[:total_participants_last_day]).to eq(7) end it "counts total participants logged last week - 12" do diff --git a/decidim-admin/spec/shared/manage_impersonations_examples.rb b/decidim-admin/spec/shared/manage_impersonations_examples.rb index 27c0230dc2263..d82d322ea2d66 100644 --- a/decidim-admin/spec/shared/manage_impersonations_examples.rb +++ b/decidim-admin/spec/shared/manage_impersonations_examples.rb @@ -125,7 +125,7 @@ expect(Decidim::Admin::ExpireImpersonationJob).to have_been_enqueued.with(impersonated_user, user) travel Decidim::ImpersonationLog::SESSION_TIME_IN_MINUTES.minutes / 2 visit current_path - travel Decidim::ImpersonationLog::SESSION_TIME_IN_MINUTES.minutes / 2 + 1.second + travel (Decidim::ImpersonationLog::SESSION_TIME_IN_MINUTES.minutes / 2) + 1.second visit current_path expect(page).to have_content("expired") expect(page).to have_link("Impersonate") @@ -255,8 +255,8 @@ visit last_email_link within "form.new_user" do - fill_in :invitation_user_password, with: "decidim123456" - fill_in :invitation_user_password_confirmation, with: "decidim123456" + fill_in :invitation_user_password, with: "decidim123456789" + fill_in :invitation_user_password_confirmation, with: "decidim123456789" check :invitation_user_tos_agreement find("*[type=submit]").click end diff --git a/decidim-admin/spec/system/admin_invite_spec.rb b/decidim-admin/spec/system/admin_invite_spec.rb index 7ac45f63e04dc..848f272e13108 100644 --- a/decidim-admin/spec/system/admin_invite_spec.rb +++ b/decidim-admin/spec/system/admin_invite_spec.rb @@ -42,8 +42,8 @@ within "form.new_user" do fill_in :invitation_user_nickname, with: "caballo_loco" - fill_in :invitation_user_password, with: "decidim123456" - fill_in :invitation_user_password_confirmation, with: "decidim123456" + fill_in :invitation_user_password, with: "decidim123456789" + fill_in :invitation_user_password_confirmation, with: "decidim123456789" check :invitation_user_tos_agreement find("*[type=submit]").click end diff --git a/decidim-admin/spec/system/admin_manage_moderated_users_spec.rb b/decidim-admin/spec/system/admin_manage_moderated_users_spec.rb index 790186fd85c59..73c070d192202 100644 --- a/decidim-admin/spec/system/admin_manage_moderated_users_spec.rb +++ b/decidim-admin/spec/system/admin_manage_moderated_users_spec.rb @@ -110,6 +110,10 @@ visit decidim_admin.moderated_users_path(blocked: true) end + it "user can't unreport them" do + expect(page).not_to have_css(".action-icon--unreport") + end + context "when filtering by report reason" do it_behaves_like "a filtered collection", options: "Report reason", filter: "Spam" do let(:in_filter) { first_user.nickname } diff --git a/decidim-admin/spec/system/admin_manages_global_moderations_spec.rb b/decidim-admin/spec/system/admin_manages_global_moderations_spec.rb index a9e00d2306577..5d6698316051e 100644 --- a/decidim-admin/spec/system/admin_manages_global_moderations_spec.rb +++ b/decidim-admin/spec/system/admin_manages_global_moderations_spec.rb @@ -26,4 +26,9 @@ it_behaves_like "manage moderations" do let(:moderations_link_text) { "Global moderations" } end + + it_behaves_like "sorted moderations" do + let!(:reportables) { create_list(:dummy_resource, 17, component: current_component) } + let(:moderations_link_text) { "Global moderations" } + end end diff --git a/decidim-admin/spec/system/admin_manages_newsletter_templates_spec.rb b/decidim-admin/spec/system/admin_manages_newsletter_templates_spec.rb index a90b4b1306880..e4e58cc8f92f1 100644 --- a/decidim-admin/spec/system/admin_manages_newsletter_templates_spec.rb +++ b/decidim-admin/spec/system/admin_manages_newsletter_templates_spec.rb @@ -59,4 +59,18 @@ expect(page).to have_content("New newsletter") end end + + describe "previewing a newsletter template iframe" do + shared_examples "working newsletter template iframe" do |template_id| + it "changes the footer links correctly" do + visit decidim_admin.preview_newsletter_template_path(template_id) + expect(page).to have_link("notifications page", href: "#") + expect(page).to have_link("Unsubscribe", href: "#") + expect(page).to have_link(organization.name, href: "#", count: 2) + end + end + + it_behaves_like "working newsletter template iframe", :basic_only_text + it_behaves_like "working newsletter template iframe", :image_text_cta + end end diff --git a/decidim-admin/spec/system/admin_manages_newsletters_spec.rb b/decidim-admin/spec/system/admin_manages_newsletters_spec.rb index e012e73871d52..7c6812b2ca86c 100644 --- a/decidim-admin/spec/system/admin_manages_newsletters_spec.rb +++ b/decidim-admin/spec/system/admin_manages_newsletters_spec.rb @@ -75,12 +75,11 @@ es: "Hola, %{name}! Contenido relevante.", ca: "Hola, %{name}! Contingut rellevant." ) + end - attach_file( - "Main image", - Decidim::Dev.asset("city2.jpeg") - ) + dynamically_attach_file(:newsletter_images_main_image, Decidim::Dev.asset("city2.jpeg")) + within ".new_newsletter" do find("*[type=submit]").click end diff --git a/decidim-admin/spec/system/admin_manages_organization_appearance_spec.rb b/decidim-admin/spec/system/admin_manages_organization_appearance_spec.rb index b163053d7f8a9..3e47d1c2f6b7d 100644 --- a/decidim-admin/spec/system/admin_manages_organization_appearance_spec.rb +++ b/decidim-admin/spec/system/admin_manages_organization_appearance_spec.rb @@ -47,10 +47,12 @@ fill_in "Official organization URL", with: "http://www.example.com" - attach_file "Logo", Decidim::Dev.asset("city2.jpeg") - attach_file "Icon", Decidim::Dev.asset("city3.jpeg") - attach_file "Official logo header", Decidim::Dev.asset("city2.jpeg") - attach_file "Official logo footer", Decidim::Dev.asset("city3.jpeg") + dynamically_attach_file(:organization_logo, Decidim::Dev.asset("city2.jpeg")) + dynamically_attach_file(:organization_favicon, Decidim::Dev.asset("logo.png"), remove_before: true) do + expect(page).to have_content("Has to be a square image") + end + dynamically_attach_file(:organization_official_img_header, Decidim::Dev.asset("city2.jpeg"), remove_before: true) + dynamically_attach_file(:organization_official_img_footer, Decidim::Dev.asset("city3.jpeg"), remove_before: true) fill_in :organization_theme_color, with: "#a0a0a0" diff --git a/decidim-admin/spec/system/admin_manages_organization_homepage_spec.rb b/decidim-admin/spec/system/admin_manages_organization_homepage_spec.rb index 12441f2c9692d..1c2b9bcf49a00 100644 --- a/decidim-admin/spec/system/admin_manages_organization_homepage_spec.rb +++ b/decidim-admin/spec/system/admin_manages_organization_homepage_spec.rb @@ -46,10 +46,7 @@ it "updates the images of the content block" do visit decidim_admin.edit_organization_homepage_content_block_path(:hero) - attach_file( - :content_block_images_background_image, - Decidim::Dev.asset("city2.jpeg") - ) + dynamically_attach_file(:content_block_images_background_image, Decidim::Dev.asset("city2.jpeg")) click_button "Update" visit decidim.root_path diff --git a/decidim-admin/spec/system/admin_manages_organization_spec.rb b/decidim-admin/spec/system/admin_manages_organization_spec.rb index fa6d22104b99b..715e7fe7b21d2 100644 --- a/decidim-admin/spec/system/admin_manages_organization_spec.rb +++ b/decidim-admin/spec/system/admin_manages_organization_spec.rb @@ -62,21 +62,21 @@ end it "deletes paragraph changes pressing backspace" do - find('div[contenteditable="true"].ql-editor').send_keys "ef", [:enter], "gh", [:backspace], [:backspace], [:backspace], [:backspace] + find('div[contenteditable="true"].ql-editor').native.send_keys "ef", [:enter], "gh", [:backspace], [:backspace], [:backspace], [:backspace] expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq("

e

".gsub("\n", "")) end it "deletes linebreaks when pressing backspace" do - find('div[contenteditable="true"].ql-editor').send_keys "a", [:left], [:enter], [:shift, :enter], [:backspace], [:backspace] + find('div[contenteditable="true"].ql-editor').native.send_keys "a", [:left], [:enter], [:shift, :enter], [:backspace], [:backspace] expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq("

a

".gsub("\n", "")) end it "creates and deletes linebreaks with enter, shift+enter and backspace" do - find('div[contenteditable="true"].ql-editor').send_keys "acd", [:left], [:left], [:enter], [:shift, :enter], [:shift, :enter], "b", [:left], [:backspace], [:backspace] + find('div[contenteditable="true"].ql-editor').native.send_keys "acd", [:left], [:left], [:enter], [:shift, :enter], [:shift, :enter], "b", [:left], [:backspace], [:backspace] expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq("

abcd

".gsub("\n", "")) @@ -169,14 +169,14 @@ end it "creates single br tag" do - find('div[contenteditable="true"].ql-editor').send_keys([:left, :left, :left, :left, :left], [:shift, :enter]) + find('div[contenteditable="true"].ql-editor').native.send_keys([:left, :left, :left, :left, :left], [:shift, :enter]) expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq('

foo

link

') end it "doesnt create br tag inside a tag" do - find('div[contenteditable="true"].ql-editor').send_keys([:left, :left, :left, :left], [:shift, :enter]) + find('div[contenteditable="true"].ql-editor').native.send_keys([:left, :left, :left, :left], [:shift, :enter]) expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq('

foo

link

') @@ -202,7 +202,7 @@ end it "is still editable" do - find('div[contenteditable="true"].ql-editor').send_keys(Array.new(15) { :backspace }, "bar baz") + find('div[contenteditable="true"].ql-editor').native.send_keys(Array.new(15) { :backspace }, "bar baz") click_button "Update" expect(page).to have_content("Organization updated successfully") expect(find( @@ -229,16 +229,16 @@ end it "renders new br tags inside the editor" do - find('div[contenteditable="true"].ql-editor').send_keys [:enter], "Here shift+enter makes line change:", [:shift, :enter], "instead of new paragraph!" + find('div[contenteditable="true"].ql-editor').native.send_keys [:enter], "Here shift+enter makes line change:", [:shift, :enter], "instead of new paragraph!" expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq("#{terms_content}

Here shift+enter makes line change:
instead of new paragraph!

".gsub("\n", "")) end it "makes smartbreak (
) when pressing ⎠button" do - find('div[contenteditable="true"].ql-editor').send_keys [:enter], "foo" + find('div[contenteditable="true"].ql-editor').native.send_keys [:enter], "foo" click_button("âŽ") - find('div[contenteditable="true"].ql-editor').send_keys "bar" + find('div[contenteditable="true"].ql-editor').native.send_keys "bar" expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq("#{terms_content}

foo
bar

".gsub("\n", "")) @@ -246,16 +246,25 @@ describe "editor history" do it "has undo" do - find('div[contenteditable="true"].ql-editor').send_keys("foo", [:shift, :enter], "bar", [:control, "z"], [:control, "z"], - [:control, "z"], [:control, "z"], [:control, "z"], [:control, "z"], - [:control, "z"]) + find('div[contenteditable="true"].ql-editor').native.send_keys( + "foo", + [:shift, :enter], + "bar", + [:control, "z"], + [:control, "z"], + [:control, "z"], + [:control, "z"], + [:control, "z"], + [:control, "z"], + [:control, "z"] + ) expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq(terms_content.gsub("\n", "")) end it "has redo" do - find('div[contenteditable="true"].ql-editor').send_keys [:shift, :enter], "X", [:control, "z"], [:control, :shift, "z"] + find('div[contenteditable="true"].ql-editor').native.send_keys [:shift, :enter], "X", [:control, "z"], [:control, :shift, "z"] expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq("

Paragraph

Some
text
here

Another paragraph
X

".gsub("\n", "")) @@ -282,63 +291,63 @@ end it "renders new list item" do - find('div[contenteditable="true"].ql-editor').send_keys [:enter], "List item 4" + find('div[contenteditable="true"].ql-editor').native.send_keys [:enter], "List item 4" expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq("

Paragraph

  • List item 1
  • List item 2
  • List item 3
  • List item 4
".gsub("\n", "")) end it "ends the list when pressing enter twice and starts new paragraph" do - find('div[contenteditable="true"].ql-editor').send_keys [:enter, :enter], "Another paragraph" + find('div[contenteditable="true"].ql-editor').native.send_keys [:enter, :enter], "Another paragraph" expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq("#{terms_content}

Another paragraph

".gsub("\n", "")) end it "deletes empty list item when pressing backspace and starts new paragraph" do - find('div[contenteditable="true"].ql-editor').send_keys [:enter, :backspace], "Another paragraph" + find('div[contenteditable="true"].ql-editor').native.send_keys [:enter, :backspace], "Another paragraph" expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq("#{terms_content}

Another paragraph

".gsub("\n", "")) end it "deletes linebreaks (and smartbreaks) using the backspace" do - find('div[contenteditable="true"].ql-editor').send_keys [:enter, :enter, :enter, :backspace, :backspace] + find('div[contenteditable="true"].ql-editor').native.send_keys [:enter, :enter, :enter, :backspace, :backspace] expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq(terms_content.to_s.gsub("\n", "")) end it "keeps right curson position when using the backspace" do - find('div[contenteditable="true"].ql-editor').send_keys [:enter, "bc", :left, :left, :enter, :backspace, :backspace, "a"] + find('div[contenteditable="true"].ql-editor').native.send_keys [:enter, "bc", :left, :left, :enter, :backspace, :backspace, "a"] expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq("

Paragraph

  • List item 1
  • List item 2
  • List item 3
  • abc
".to_s.gsub("\n", "")) end it "keeps right format when using the backspace" do - find('div[contenteditable="true"].ql-editor').send_keys [:enter, :backspace, "abc", :left, :left, :left, :backspace] + find('div[contenteditable="true"].ql-editor').native.send_keys [:enter, :backspace, "abc", :left, :left, :left, :backspace] expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq("

Paragraph

  • List item 1
  • List item 2
  • List item 3abc
".to_s.gsub("\n", "")) end it "keeps right cursor position when using backspace after empty list item" do - find('div[contenteditable="true"].ql-editor').send_keys [:enter, "bcd", :left, :left, :left, :enter, :backspace, :enter, :enter, :backspace, :backspace, :backspace, "a"] + find('div[contenteditable="true"].ql-editor').native.send_keys [:enter, "bcd", :left, :left, :left, :enter, :backspace, :enter, :enter, :backspace, :backspace, :backspace, "a"] expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq("

Paragraph

  • List item 1
  • List item 2
  • List item 3
  • abcd
".to_s.gsub("\n", "")) end it "keeps right cursor position when using backspace after list item with text" do - find('div[contenteditable="true"].ql-editor').send_keys [:enter, "acd", :left, :left, :enter, :backspace, :enter, :enter, :backspace, :backspace, :backspace, "b"] + find('div[contenteditable="true"].ql-editor').native.send_keys [:enter, "acd", :left, :left, :enter, :backspace, :enter, :enter, :backspace, :backspace, :backspace, "b"] expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq("

Paragraph

  • List item 1
  • List item 2
  • List item 3
  • abcd
".to_s.gsub("\n", "")) end it "doesnt delete characters below when pressing backspace" do - find('div[contenteditable="true"].ql-editor').send_keys [:up, :up, :up, :home, :enter, :enter, :enter, :backspace, :backspace, :backspace] + find('div[contenteditable="true"].ql-editor').native.send_keys [:up, :up, :up, :home, :enter, :enter, :enter, :backspace, :backspace, :backspace] expect(find( "#organization-admin_terms_of_use_body-tabs-admin_terms_of_use_body-panel-0 .editor .ql-editor" )["innerHTML"]).to eq(terms_content.to_s.gsub("\n", "")) diff --git a/decidim-admin/spec/system/admin_passwords_spec.rb b/decidim-admin/spec/system/admin_passwords_spec.rb new file mode 100644 index 0000000000000..ae30015001e13 --- /dev/null +++ b/decidim-admin/spec/system/admin_passwords_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe "Admin passwords", type: :system do + let(:organization) { create(:organization) } + let(:user) { create(:user, :confirmed, :admin, password: password, password_updated_at: password_updated_at, organization: organization) } + let(:password) { "decidim123456789" } + let(:new_password) { "decidim987654321" } + let(:password_updated_at) { nil } + + before do + switch_to_host(organization.host) + visit decidim.root_path + end + + context "when admin has not updated their password" do + let(:password_updated_at) { nil } + + it "can update password successfully" do + manual_login(user.email, password) + expect(page).to have_content("Admin users need to change their password every 90 days") + expect(page).to have_content("Password change") + fill_in :password_user_password, with: new_password + fill_in :password_user_password_confirmation, with: new_password + click_button "Change my password" + expect(page).to have_css(".callout.success") + expect(page).to have_content("Password successfully updated") + expect(user.reload.password_updated_at).to be_between(2.seconds.ago, Time.current) + end + + it "cannot dismiss password change" do + manual_login(user.email, password) + expect(page).to have_content("Password change") + click_link "user-menu-control" + click_link "Admin dashboard" + expect(page).to have_content("You need to change your password in order to proceed further") + expect(page).to have_content("Password change") + expect(page).to have_current_path(decidim.change_password_path) + end + + context "when user is in different path" do + before do + visit decidim_admin.root_path + end + + it "redirects to original path after password update" do + manual_login(user.email, password) + expect(page).to have_content("Password change") + fill_in :password_user_password, with: new_password + fill_in :password_user_password_confirmation, with: new_password + click_button "Change my password" + expect(page).to have_css(".callout.success") + expect(page).to have_current_path(decidim_admin.root_path) + end + end + end + + context "when users password is expired" do + let(:password_updated_at) { 91.days.ago } + + it "redirects to edit password view" do + manual_login(user.email, password) + expect(page).to have_content("Password change") + end + end + + def manual_login(email, password) + click_link "Sign In" + fill_in :session_user_email, with: email + fill_in :session_user_password, with: password + click_button "Log in" + end +end diff --git a/decidim-admin/spec/system/admin_verifies_user_groups_via_csv_spec.rb b/decidim-admin/spec/system/admin_verifies_user_groups_via_csv_spec.rb index af5adb4fb68b5..ccb3b5b323dda 100644 --- a/decidim-admin/spec/system/admin_verifies_user_groups_via_csv_spec.rb +++ b/decidim-admin/spec/system/admin_verifies_user_groups_via_csv_spec.rb @@ -32,7 +32,7 @@ # The CSV has headers, we're testing we ignore them expect(Decidim::Admin::VerifyUserGroupFromCsvJob).to receive(:perform_later).once.ordered.with("Email", user, organization) expect(Decidim::Admin::VerifyUserGroupFromCsvJob).to receive(:perform_later).once.ordered.with(user_group.email, user, organization) - attach_file "File", Decidim::Dev.asset("verify_user_groups.csv") + dynamically_attach_file(:user_group_csv_verification_file, Decidim::Dev.asset("verify_user_groups.csv")) perform_enqueued_jobs { click_button "Upload" } expect(page).to have_content("CSV file uploaded successfully") diff --git a/decidim-admin/spec/system/autocomplete/multiselect_spec.rb b/decidim-admin/spec/system/autocomplete/multiselect_spec.rb new file mode 100644 index 0000000000000..16957bb73ccca --- /dev/null +++ b/decidim-admin/spec/system/autocomplete/multiselect_spec.rb @@ -0,0 +1,156 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe "Autocomplete multiselect", type: :system do + let(:organization) { create(:organization) } + let(:user) { create(:user, :admin, :confirmed, organization: organization) } + let(:path) { URI.parse(decidim_admin.user_entities_organization_url).path } + let(:url) { "http://#{organization.host}:#{Capybara.current_session.server.port}#{path}" } + let(:selected) { '""' } + + before do + final_html = html_document + Rails.application.routes.draw do + mount Decidim::Core::Engine => "/" + get "test_multiselect", to: ->(_) { [200, {}, [final_html]] } + end + switch_to_host(organization.host) + login_as user, scope: :user + end + + after do + expect_no_js_errors + + Rails.application.reload_routes! + end + + context "when view has div that defines autocomplete multiselect" do + let(:autocomplete_multifield_select) do + %( +
+
+ ) + end + + let(:html_head) { "" } + let(:html_document) do + head_extra = html_head + body_extra = autocomplete_multifield_select + template.instance_eval do + <<~HTML.strip + + + + Autocomplete multiselect Test + #{stylesheet_pack_tag "decidim_admin"} + #{javascript_pack_tag "decidim_admin"} + #{head_extra} + + +

Hello world

+ + #{body_extra} +
+ + + HTML + end + end + let(:template_class) do + Class.new(ActionView::Base) do + # empty class + end + end + let(:template) { template_class.new(ActionView::LookupContext.new(ActionController::Base.view_paths), {}, []) } + + before do + visit "/test_multiselect" + end + + describe "render autocomplete wrapper with text input" do + it "shows multiselect" do + within ".autoComplete_wrapper" do + expect(page).to have_selector("input[type='text']", wait: 2) + end + end + end + + context "when there is participants" do + let!(:participant) { create(:user, :confirmed, organization: organization, name: "Andrea Kuhlman") } + let!(:participant2) { create(:user, :confirmed, organization: organization, name: "Jenae Walsh") } + let!(:participant3) { create(:user, :confirmed, organization: organization, name: "John Connor") } + + describe "select one participant" do + it "shows selected participant and creates hidden input" do + find("input[type='text']").fill_in with: participant.name.slice(0..2) + find(".autoComplete_wrapper ul#autoComplete_list_1 li", match: :first, wait: 2).click + expect(page).to have_content(participant.name) + hidden_input = find("input[type='hidden']", visible: false) + expect(hidden_input.value).to eq(participant.id.to_s) + text_input = find("input[type='text']") + expect(text_input.value).to eq("") + end + + context "when the URL has extra parameters in it" do + let(:url) { "http://#{organization.host}:#{Capybara.current_session.server.port}#{path}?locale=ca" } + + it "shows selected participant" do + find("input[type='text']").fill_in with: participant.name.slice(0..2) + find(".autoComplete_wrapper ul#autoComplete_list_1 li", match: :first, wait: 2).click + expect(page).to have_content(participant.name) + end + end + end + + describe "remove selected item" do + it "selects and removes item" do + autocomplete_select participant.name, from: :user_id + expect(page).to have_content(participant.name) + expect(page).to have_selector(%(input[value="#{participant.id}"]), visible: :hidden) + find(".clear-multi-selection").click + expect(page).not_to have_content(participant.name) + expect(page).not_to have_selector(%(input[value="#{participant.id}"]), visible: :hidden) + end + end + + describe "select multiple participants" do + it "shows selected participants and creates hidden inputs" do + autocomplete_select participant.name, from: :user_id + autocomplete_select participant2.name, from: :user_id + expect(page).to have_content(participant.name) + expect(page).to have_content(participant2.name) + expect(page).not_to have_content(participant3.name) + expect(page).to have_selector(%(input[value="#{participant.id}"]), visible: :hidden) + expect(page).to have_selector(%(input[value="#{participant2.id}"]), visible: :hidden) + expect(page).not_to have_selector(%(input[value="#{participant3.id}"]), visible: :hidden) + end + end + + describe "preselected values" do + let(:selected) { %([{"value": "#{participant2.id}", "label": "#{participant2.name}"}, {"value": "#{participant3.id}", "label": "#{participant3.name}"}]) } + + it "shows preselected value" do + expect(page).not_to have_content(participant.name) + expect(page).to have_content(participant2.name) + expect(page).to have_content(participant3.name) + expect(page).not_to have_selector(%(input[value="#{participant.id}"]), visible: :hidden) + expect(page).to have_selector(%(input[value="#{participant2.id}"]), visible: :hidden) + expect(page).to have_selector(%(input[value="#{participant3.id}"]), visible: :hidden) + end + end + end + end +end diff --git a/decidim-admin/spec/system/participatory_space_private_user_import_via_csv_spec.rb b/decidim-admin/spec/system/participatory_space_private_user_import_via_csv_spec.rb new file mode 100644 index 0000000000000..ff9f4a6a9ca42 --- /dev/null +++ b/decidim-admin/spec/system/participatory_space_private_user_import_via_csv_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe "Admin manages participatory space private users via csv import", type: :system do + let(:organization) { create(:organization) } + + let!(:user) { create(:user, :admin, :confirmed, organization: organization) } + let(:assembly) { create(:assembly, organization: organization) } + + before do + switch_to_host(organization.host) + login_as user, scope: :user + visit decidim_admin_assemblies.edit_assembly_path(assembly) + find("a[href*='participatory_space_private_users']").click + find("a[href*='csv_import'").click + end + + it "show the form to add some private users via csv" do + expect(page).to have_content("Upload your CSV file") + end + + context "when there are no existing users" do + it "doesn't propose to delete" do + expect(page).to have_content("You have no private participants.") + end + end + + context "when there are existing users" do + before do + create_list :assembly_private_user, 3, privatable_to: assembly, user: create(:user, organization: assembly.organization) + visit current_path + end + + it "propose to delete" do + expect(page).to have_selector(".alert") + end + + it "ask you for confirmation and delete existing users" do + find(".alert").click + + expect(page).to have_content("Are you sure you want to delete all private participants?") + + find("a.button[data-confirm-ok]").click + + expect(page).to have_content("You have no private participants") + end + end +end diff --git a/decidim-admin/spec/system/space_admin_manages_global_moderations_spec.rb b/decidim-admin/spec/system/space_admin_manages_global_moderations_spec.rb index ae649d11cf31b..86e61519a5edc 100644 --- a/decidim-admin/spec/system/space_admin_manages_global_moderations_spec.rb +++ b/decidim-admin/spec/system/space_admin_manages_global_moderations_spec.rb @@ -83,6 +83,11 @@ it_behaves_like "manage moderations" do let(:moderations_link_text) { "Global moderations" } end + + it_behaves_like "sorted moderations" do + let!(:reportables) { create_list(:dummy_resource, 17, component: current_component) } + let(:moderations_link_text) { "Global moderations" } + end end context "when the user can manage a space without moderations" do diff --git a/decidim-admin/spec/system/space_moderator_manages_global_moderations_spec.rb b/decidim-admin/spec/system/space_moderator_manages_global_moderations_spec.rb index d0f5d440af3a2..8350bb1d65fd8 100644 --- a/decidim-admin/spec/system/space_moderator_manages_global_moderations_spec.rb +++ b/decidim-admin/spec/system/space_moderator_manages_global_moderations_spec.rb @@ -51,6 +51,11 @@ it_behaves_like "manage moderations" do let(:moderations_link_text) { "Global moderations" } end + + it_behaves_like "sorted moderations" do + let!(:reportables) { create_list(:dummy_resource, 17, component: current_component) } + let(:moderations_link_text) { "Global moderations" } + end end context "when the user can manage a space without moderations" do diff --git a/decidim-api/app/controllers/decidim/api/documentation_controller.rb b/decidim-api/app/controllers/decidim/api/documentation_controller.rb index c30f47a8d87f6..13c62141f0d8d 100644 --- a/decidim-api/app/controllers/decidim/api/documentation_controller.rb +++ b/decidim-api/app/controllers/decidim/api/documentation_controller.rb @@ -6,6 +6,27 @@ module Api # the Schema to be executed, later returning the response as JSON. class DocumentationController < Api::ApplicationController layout "decidim/api/documentation" + + helper_method :static_api_docs_content + before_action :set_cache_headers + + private + + def static_api_docs_content + render_to_string(File.join("static", "api", "docs", *safe_content_path, "index"), layout: false) + end + + def safe_content_path + return "" unless params[:path] + + params[:path].split("/").excluding("..", ".") + end + + def set_cache_headers + response.headers["Cache-Control"] = "no-cache, no-store" + response.headers["Pragma"] = "no-cache" + response.headers["Expires"] = "Mon, 01 Jan 1990 00:00:00 GMT" + end end end end diff --git a/decidim-api/app/helpers/decidim/api/application_helper.rb b/decidim-api/app/helpers/decidim/api/application_helper.rb deleted file mode 100644 index 9665d38871331..0000000000000 --- a/decidim-api/app/helpers/decidim/api/application_helper.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -require "redcarpet" - -module Decidim - module Api - # Custom helpers, scoped to the api engine. - # - module ApplicationHelper - def render_doc(file) - md_render File.read(File.join(File.dirname(__FILE__), "../../../../docs", "#{file}.md")) - end - - def md_render(text) - text = Redcarpet::Markdown.new(markdown, autolink: true, tables: true, fenced_code_blocks: true).render(text) - text.html_safe - end - - def markdown - @markdown ||= Redcarpet::Render::HTML.new - end - end - end -end diff --git a/decidim-api/app/packs/entrypoints/decidim_api_docs.js b/decidim-api/app/packs/entrypoints/decidim_api_docs.js index 30d7cc3d2857d..b3672b91c6524 100644 --- a/decidim-api/app/packs/entrypoints/decidim_api_docs.js +++ b/decidim-api/app/packs/entrypoints/decidim_api_docs.js @@ -1,26 +1 @@ -/* eslint-disable react/jsx-no-undef */ - -import jQuery from "jquery" -import { render } from "react-dom" -import { GraphQLDocs } from "graphql-docs" -import "stylesheets/decidim/api/docs.scss" - -const fetcherFactory = (path) => { - return (query) => { - return jQuery.ajax({ - url: path, - data: JSON.stringify({ query }), - method: "POST", - contentType: "application/json", - dataType: "json" - }); - }; -} - -window.renderDocumentation = (path) => { - render( - , - document.getElementById("documentation"), - ); -}; - +import "entrypoints/decidim_api_docs.scss"; diff --git a/decidim-api/app/packs/entrypoints/decidim_api_docs.scss b/decidim-api/app/packs/entrypoints/decidim_api_docs.scss new file mode 100644 index 0000000000000..b049a87bea612 --- /dev/null +++ b/decidim-api/app/packs/entrypoints/decidim_api_docs.scss @@ -0,0 +1,1318 @@ +body{ + max-width: 1200px; +} + +.version{ + display: inline-block; + font-size: .8rem; + margin-right: 1rem; + padding: 3px 7px; + background: #f33; + border-radius: 10px; + margin-top: 5px; + color: white; +} + +ol, +ul{ + list-style: none; + padding-left: 15px; +} + +blockquote, +q{ + quotes: none; +} + +blockquote::before, +blockquote::after, +q::before, +q::after{ + content: ''; + content: none; +} + +table{ + border-collapse: collapse; + border-spacing: 0; +} + +body{ + font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-size: 16px; + font-weight: 400; + color: #444; +} + +em{ + font-style: italic; +} + +#sidebar{ + background-color: #fff; + position: fixed; + z-index: 2; + top: 0; + left: 0; + bottom: 0; + width: 250px; + padding: 0; + overflow-x: hidden; + overflow-y: scroll; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: none; + border-right: 1px solid #eee; + font-size: 16px; + line-height: 1.1em; +} + +#sidebar::-webkit-scrollbar{ + width: 0 !important; +} + +#sidebar li{ + margin-bottom: .6em; +} + +#sidebar a{ + color: #444; + text-decoration: none; +} + +#sidebar a:hover{ + color: #de4f4f; +} + +#sidebar a.current{ + color: #de4f4f; +} + +#sidebar a.H2{ + font-weight: bold; +} + +#sidebar .categories > li > p{ + margin-top: 1.5em; + border-top: 1px solid #eee; + text-transform: uppercase; + padding-top: 1.2em; + margin-bottom: 1em; + color: #999; + font-size: .8em; +} + +#sidebar .sub-menu{ + padding-left: 20px; + margin: .6em 0; + font-size: 14px; +} + +#sidebar .sub-menu .active{ + position: relative; + color: #de4f4f; +} + +#sidebar .sub-menu .active::before{ + content: ""; + position: absolute; + top: 2px; + left: -15px; + display: inline-block; + width: 0; + height: 0; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-left: 6px solid #de4f4f; +} + +#sidebar-mobile{ + display: none; + margin-bottom: 20px; +} + +#sidebar-mobile .search-box{ + width: 200px; + margin-bottom: 20px; +} + +.content{ + padding: 20px 30px; + max-width: 760px; + margin-left: 300px; + -webkit-text-size-adjust: 100%; +} + +.content em{ + font-style: italic; +} + +.content h1{ + margin: 15px 0; + line-height: 1.4em; + font-size: 2em; + margin-top: 0; + margin-bottom: 30px; +} + +.content h2{ + margin: 15px 0; + line-height: 1.4em; + font-size: 1.5em; + margin-top: 30px; + padding-bottom: 10px; + border-bottom: 1px solid #eee; + position: relative; +} + +.content h2 .anchor{ + opacity: 0; + position: absolute; + font-size: 16px; + top: 2px; + left: -21px; +} + +.content h2:hover .anchor{ + opacity: 1; +} + +.content h3{ + margin: 15px 0; + line-height: 1.4em; + font-size: 1.2em; + margin-top: 30px; + position: relative; +} + +.content h3 .anchor{ + opacity: 0; + position: absolute; + font-size: 16px; + top: 2px; + left: -21px; +} + +.content h3:hover .anchor{ + opacity: 1; +} + +.content h4{ + margin: 15px 0; + line-height: 1.4em; +} + +.content h5{ + margin: 15px 0; + line-height: 1.4em; +} + +.content h6{ + margin: 15px 0; + line-height: 1.4em; +} + +.content p{ + margin: 15px 0; + line-height: 1.4em; +} + +.content ul{ + margin: 15px 0; + line-height: 1.4em; + padding-left: 1.5em; + list-style-type: disc; +} + +.content ul li{ + margin-bottom: 5px; +} + +.content ol{ + margin: 15px 0; + line-height: 1.4em; + padding-left: 1.5em; + list-style-type: decimal; +} + +.content ol li{ + margin-bottom: 5px; +} + +.content figure{ + margin: 15px 0; + line-height: 1.4em; +} + +.content a{ + color: #de4f4f; +} + +.content img{ + max-width: 100%; +} + +.content code{ + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + font-size: .8em; + line-height: 1.6em; + padding: 1px 4px; + background-color: #eee; + margin: 0 2px; +} + +.content blockquote{ + padding-left: 1.3em; + border-left: #eee solid .2em; + font-style: italic; +} + +.content blockquote.warning{ + border-color: #f00; + color: #f00; +} + +.content dl{ + margin-left: 1.5em; +} + +.content dl dt .name{ + font-family: monospace; +} + +.content dl dt .type{ + margin-left: .5em; +} + +.content dl dd{ + margin-left: 1.5em; +} + +.content .edit-discuss-links{ + margin-top: -25px; + margin-bottom: 40px; +} + +.content table{ + margin-top: 10px; +} + +.content table th{ + text-align: left; + padding: 0 25px; +} + +.content table thead th:first-child{ + padding: 0; +} + +.content table td p{ + padding: 0 25px; +} + +.content pre{ + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + line-height: 1.6em; + margin: 20px 0; + overflow-x: auto; + position: relative; + padding: 20px 30px; +} + +.content pre table{ + width: 100%; + border-collapse: collapse; + padding: 0; + margin: 0; +} + +.content pre tr{ + width: 100%; + border-collapse: collapse; + padding: 0; + margin: 0; +} + +.content pre td{ + width: 100%; + border-collapse: collapse; + padding: 0; + margin: 0; +} + +.content pre code{ + background-color: #272822; + padding: 0; + margin: 0; +} + +.content pre .gutter{ + user-select: none; + width: 1.5em; + padding-right: 30px; +} + +.content .highlight.html .code::after{ + position: absolute; + top: 0; + right: 0; + color: #ccc; + text-align: right; + font-size: .75em; + padding: 5px 10px 0; + letter-spacing: 1.5px; + line-height: 15px; + height: 15px; + font-weight: 600; +} + +.content .highlight.js .code::after{ + position: absolute; + top: 0; + right: 0; + color: #ccc; + text-align: right; + font-size: .75em; + padding: 5px 10px 0; + letter-spacing: 1.5px; + line-height: 15px; + height: 15px; + font-weight: 600; +} + +.content .highlight.bash .code::after{ + position: absolute; + top: 0; + right: 0; + color: #ccc; + text-align: right; + font-size: .75em; + padding: 5px 10px 0; + letter-spacing: 1.5px; + line-height: 15px; + height: 15px; + font-weight: 600; +} + +.content .highlight.css .code::after{ + position: absolute; + top: 0; + right: 0; + color: #ccc; + text-align: right; + font-size: .75em; + padding: 5px 10px 0; + letter-spacing: 1.5px; + line-height: 15px; + height: 15px; + font-weight: 600; +} + +.content .highlight.jsx .code::after{ + position: absolute; + top: 0; + right: 0; + color: #ccc; + text-align: right; + font-size: .75em; + padding: 5px 10px 0; + letter-spacing: 1.5px; + line-height: 15px; + height: 15px; + font-weight: 600; +} + +.content .highlight.html.html .code::after{ + content: 'HTML'; +} + +.content .highlight.js.html .code::after{ + content: 'HTML'; +} + +.content .highlight.bash.html .code::after{ + content: 'HTML'; +} + +.content .highlight.css.html .code::after{ + content: 'HTML'; +} + +.content .highlight.jsx.html .code::after{ + content: 'HTML'; +} + +.content .highlight.html.js .code::after{ + content: 'JS'; +} + +.content .highlight.js.js .code::after{ + content: 'JS'; +} + +.content .highlight.bash.js .code::after{ + content: 'JS'; +} + +.content .highlight.css.js .code::after{ + content: 'JS'; +} + +.content .highlight.jsx.js .code::after{ + content: 'JS'; +} + +.content .highlight.html.bash .code::after{ + content: 'Shell'; +} + +.content .highlight.js.bash .code::after{ + content: 'Shell'; +} + +.content .highlight.bash.bash .code::after{ + content: 'Shell'; +} + +.content .highlight.css.bash .code::after{ + content: 'Shell'; +} + +.content .highlight.jsx.bash .code::after{ + content: 'Shell'; +} + +.content .highlight.html.css .code::after{ + content: 'CSS'; +} + +.content .highlight.js.css .code::after{ + content: 'CSS'; +} + +.content .highlight.bash.css .code::after{ + content: 'CSS'; +} + +.content .highlight.css.css .code::after{ + content: 'CSS'; +} + +.content .highlight.jsx.css .code::after{ + content: 'CSS'; +} + +.content .highlight.html.jsx .code::after{ + content: 'JSX'; +} + +.content .highlight.js.jsx .code::after{ + content: 'JSX'; +} + +.content .highlight.bash.jsx .code::after{ + content: 'JSX'; +} + +.content .highlight.css.jsx .code::after{ + content: 'JSX'; +} + +.content .highlight.jsx.jsx .code::after{ + content: 'JSX'; +} + +.content > table{ + width: 100%; + margin: 20px 0; +} + +.content > table tr{ + border-top: 1px solid #eee; +} + +.content > table tr:nth-child(2n){ + background-color: #f8f8f8; +} + +.content > table th{ + padding: 12px 13px; + border: 1px solid #eee; + vertical-align: middle; + text-align: left; +} + +.content > table td{ + border: 1px solid #eee; + vertical-align: middle; + padding: 6px 13px; + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + font-size: .8em; + line-height: 1.6em; +} + +.content .bottom-nav{ + height: 44px; + margin: 30px 0 25px; + border-bottom: 1px solid #eee; + padding-bottom: 25px; +} + +.content .bottom-nav a{ + margin: 0 5px; +} + +.content .edit-link{ + text-align: center; +} + +.content .edit-link a{ + color: #aaa; +} + +.content .edit-link a::before{ + content: ''; + display: inline-block; + width: 16px; + height: 16px; + background-size: 16px; + opacity: .3; + margin-right: 8px; + position: relative; + top: 2px; +} + +.content .field-name{ + font-weight: bold; +} + +.content .field-entry{ + margin-bottom: 4rem; +} + +.content .description-wrapper > p{ + padding-left: 1rem; + margin-bottom: 1rem; +} + +#mobile-header{ + z-index: 3; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 20px; + display: none; +} + +#mobile-header .menu-button{ + color: #333; + position: absolute; + top: 0; + right: 20px; + height: 24px; + font-size: 40px; + cursor: pointer; + opacity: .4; +} + +@media screen and (max-width: 560px){ + body{ + font-size: 14px; + } + + body.sidebar-open #sidebar{ + transform: translate3d(0, 0, 0); + } + + body.sidebar-open #mobile-shade{ + opacity: 1; + pointer-events: auto; + } + + .content{ + margin-left: 0; + } + + #mobile-header{ + display: block; + } + + #mobile-shade{ + display: block; + } + + #sidebar-mobile{ + display: block; + } + + #wrap{ + padding-top: 40px; + padding-left: 0; + } + + #sidebar{ + top: 0; + left: 0; + border-right: none; + box-shadow: 0 0 4px rgba(0, 0, 0, .25); + transition: transform .3s ease; + transform: translate3d(-120%, 0, 0); + display: block; + } +} + +.api{ + background: #fafafa; +} + +.api h3{ + padding: 5px 10px; +} + +.api h3.api-title{ + margin: 0; + overflow: auto; +} + +.api h4{ + font-weight: normal; + font-style: italic; + margin-bottom: .25em; + text-decoration: underline; + margin-left: 20px; +} + +.api dl{ + margin-top: .25em; +} + +.api dl.args{ + margin-left: 40px; +} + +.api dl.constants{ + margin-left: 20px; +} + +.api dt{ + margin-top: 1em; +} + +.api dt .name{ + font-weight: bold; +} + +.api dt .type{ + margin-left: 15px; + font-size: .9em; + font-weight: 200; + color: #000; +} + +.api dd{ + margin-bottom: 1em; + margin-left: 0; +} + +.api .desc{ + margin: 1em; +} + +.api pre{ + margin-right: 10px; +} + +h3.api-title{ + padding: 5px 10px; + margin-top: 2em; +} + +.api-title .locus{ + float: right; + font-weight: normal; + padding-right: 5px; + font-style: italic; +} + +.api-title .subtext{ + font-size: 11px; + text-align: left; + clear: both; + display: block; + font-weight: normal; +} + +.api-title .subtext > code{ + font-size: 11px; + margin-right: 12px; +} + +.api-title .src-code{ + color: #20338a !important; + border-bottom: none !important; +} + +.gutter pre{ + color: #999; +} + +pre{ + color: #525252; +} + +pre .function .keyword{ + color: #0092db; +} + +pre .constant{ + color: #0092db; +} + +pre .keyword{ + color: #e96900; +} + +pre .attribute{ + color: #e96900; +} + +pre .number{ + color: #ae81ff; +} + +pre .literal{ + color: #ae81ff; +} + +pre .tag{ + color: #2973b7; +} + +pre .tag .title{ + color: #2973b7; +} + +pre .tag .value{ + color: #90a959; +} + +pre .change{ + color: #2973b7; +} + +pre .winutils{ + color: #2973b7; +} + +pre .flow{ + color: #2973b7; +} + +pre .lisp .title{ + color: #2973b7; +} + +pre .clojure .built_in{ + color: #2973b7; +} + +pre .nginx .title{ + color: #2973b7; +} + +pre .tex .special{ + color: #2973b7; +} + +pre .tex .command{ + color: #90a959; +} + +pre .tex .formula{ + color: #b3b3b3; + opacity: .5; +} + +pre .class .title{ + color: #4077bf; +} + +pre .symbol{ + color: #90a959; +} + +pre .symbol .string{ + color: #90a959; +} + +pre .value{ + color: #90a959; +} + +pre .regexp{ + color: #90a959; +} + +pre .title{ + color: #a6e22e; +} + +pre .string{ + color: #90a959; +} + +pre .subst{ + color: #90a959; +} + +pre .haskell .type{ + color: #90a959; +} + +pre .preprocessor{ + color: #90a959; +} + +pre .ruby .class .parent{ + color: #90a959; +} + +pre .built_in{ + color: #90a959; +} + +pre .sql .aggregate{ + color: #90a959; +} + +pre .django .template_tag{ + color: #90a959; +} + +pre .django .variable{ + color: #90a959; +} + +pre .django .filter .argument{ + color: #90a959; +} + +pre .smalltalk .class{ + color: #90a959; +} + +pre .smalltalk .localvars{ + color: #90a959; +} + +pre .smalltalk .array{ + color: #90a959; +} + +pre .javadoc{ + color: #90a959; +} + +pre .attr_selector{ + color: #90a959; +} + +pre .pseudo{ + color: #90a959; +} + +pre .addition{ + color: #90a959; +} + +pre .stream{ + color: #90a959; +} + +pre .envvar{ + color: #90a959; +} + +pre .apache .tag{ + color: #90a959; +} + +pre .apache .cbracket{ + color: #90a959; +} + +pre .apache .sqbracket{ + color: #b3b3b3; +} + +pre .prompt{ + color: #90a959; +} + +pre .comment{ + color: #b3b3b3; +} + +pre .java .annotation{ + color: #b3b3b3; +} + +pre .python .decorator{ + color: #b3b3b3; +} + +pre .template_comment{ + color: #b3b3b3; +} + +pre .pi{ + color: #b3b3b3; +} + +pre .doctype{ + color: #b3b3b3; +} + +pre .deletion{ + color: #b3b3b3; +} + +pre .shebang{ + color: #b3b3b3; +} + +pre .coffeescript .javascript{ + opacity: .5; +} + +pre .javascript .xml{ + opacity: .5; +} + +pre .xml .javascript{ + opacity: .5; +} + +pre .xml .vbscript{ + opacity: .5; +} + +pre .xml .css{ + opacity: .5; +} + +pre .xml .cdata{ + opacity: .5; +} + +.highlight .hll{ + background-color: #49483e; +} + +pre{ + background: #272822; + color: #f8f8f2; +} + +.highlight .c{ + color: #75715e; +} + +/* Comment */ +.highlight .err{ + color: #960050; + background-color: #1e0010; +} + +/* Error */ +.highlight .k{ + color: #66d9ef; +} + +/* Keyword */ +.highlight .l{ + color: #ae81ff; +} + +/* Literal */ +.highlight .n{ + color: #f8f8f2; +} + +/* Name */ +.highlight .o{ + color: #f92672; +} + +/* Operator */ +.highlight .p{ + color: #f8f8f2; +} + +/* Punctuation */ +.highlight .cm{ + color: #75715e; +} + +/* Comment.Multiline */ +.highlight .cp{ + color: #75715e; +} + +/* Comment.Preproc */ +.highlight .c1{ + color: #75715e; +} + +/* Comment.Single */ +.highlight .cs{ + color: #75715e; +} + +/* Comment.Special */ +.highlight .ge{ + font-style: italic; +} + +/* Generic.Emph */ +.highlight .gs{ + font-weight: bold; +} + +/* Generic.Strong */ +.highlight .kc{ + color: #66d9ef; +} + +/* Keyword.Constant */ +.highlight .kd{ + color: #66d9ef; +} + +/* Keyword.Declaration */ +.highlight .kn{ + color: #f92672; +} + +/* Keyword.Namespace */ +.highlight .kp{ + color: #66d9ef; +} + +/* Keyword.Pseudo */ +.highlight .kr{ + color: #66d9ef; +} + +/* Keyword.Reserved */ +.highlight .kt{ + color: #66d9ef; +} + +/* Keyword.Type */ +.highlight .ld{ + color: #e6db74; +} + +/* Literal.Date */ +.highlight .m{ + color: #ae81ff; +} + +/* Literal.Number */ +.highlight .s{ + color: #e6db74; +} + +/* Literal.String */ +.highlight .na{ + color: #a6e22e; +} + +/* Name.Attribute */ +.highlight .nb{ + color: #f8f8f2; +} + +/* Name.Builtin */ +.highlight .nc{ + color: #a6e22e; +} + +/* Name.Class */ +.highlight .no{ + color: #66d9ef; +} + +/* Name.Constant */ +.highlight .nd{ + color: #a6e22e; +} + +/* Name.Decorator */ +.highlight .ni{ + color: #f8f8f2; +} + +/* Name.Entity */ +.highlight .ne{ + color: #a6e22e; +} + +/* Name.Exception */ +.highlight .nf{ + color: #a6e22e; +} + +/* Name.Function */ +.highlight .nl{ + color: #f8f8f2; +} + +/* Name.Label */ +.highlight .nn{ + color: #f8f8f2; +} + +/* Name.Namespace */ +.highlight .nx{ + color: #a6e22e; +} + +/* Name.Other */ +.highlight .py{ + color: #f8f8f2; +} + +/* Name.Property */ +.highlight .nt{ + color: #f92672; +} + +/* Name.Tag */ +.highlight .nv{ + color: #f8f8f2; +} + +/* Name.Variable */ +.highlight .ow{ + color: #f92672; +} + +/* Operator.Word */ +.highlight .w{ + color: #f8f8f2; +} + +/* Text.Whitespace */ +.highlight .mf{ + color: #ae81ff; +} + +/* Literal.Number.Float */ +.highlight .mh{ + color: #ae81ff; +} + +/* Literal.Number.Hex */ +.highlight .mi{ + color: #ae81ff; +} + +/* Literal.Number.Integer */ +.highlight .mo{ + color: #ae81ff; +} + +/* Literal.Number.Oct */ +.highlight .sb{ + color: #e6db74; +} + +/* Literal.String.Backtick */ +.highlight .sc{ + color: #e6db74; +} + +/* Literal.String.Char */ +.highlight .sd{ + color: #e6db74; +} + +/* Literal.String.Doc */ +.highlight .s2{ + color: #e6db74; +} + +/* Literal.String.Double */ +.highlight .se{ + color: #ae81ff; +} + +/* Literal.String.Escape */ +.highlight .sh{ + color: #e6db74; +} + +/* Literal.String.Heredoc */ +.highlight .si{ + color: #e6db74; +} + +/* Literal.String.Interpol */ +.highlight .sx{ + color: #e6db74; +} + +/* Literal.String.Other */ +.highlight .sr{ + color: #e6db74; +} + +/* Literal.String.Regex */ +.highlight .s1{ + color: #e6db74; +} + +/* Literal.String.Single */ +.highlight .ss{ + color: #e6db74; +} + +/* Literal.String.Symbol */ +.highlight .bp{ + color: #f8f8f2; +} + +/* Name.Builtin.Pseudo */ +.highlight .vc{ + color: #f8f8f2; +} + +/* Name.Variable.Class */ +.highlight .vg{ + color: #f8f8f2; +} + +/* Name.Variable.Global */ +.highlight .vi{ + color: #f8f8f2; +} + +/* Name.Variable.Instance */ +.highlight .il{ + color: #ae81ff; +} + +/* Literal.Number.Integer.Long */ +.deprecation-notice{ + padding-left: 5px; + border-left: 2px solid #e8400d; + background: #fdf2ec; +} + +.deprecation-notice span{ + font-weight: bold; +} diff --git a/decidim-api/app/packs/stylesheets/decidim/api/docs.scss b/decidim-api/app/packs/stylesheets/decidim/api/docs.scss deleted file mode 100644 index 4909010a04f52..0000000000000 --- a/decidim-api/app/packs/stylesheets/decidim/api/docs.scss +++ /dev/null @@ -1,61 +0,0 @@ -body{ - max-width: 1200px; -} - -.intro, -.info{ - margin-left: 270px; - color: #333; -} - -.info{ - li{ - margin-bottom: 1rem; - } - - h3{ - margin-top: 2em; - } -} - -.version{ - display: inline-block; - font-size: .8rem; - margin-right: 1rem; - padding: 3px 7px; - background: #f33; - border-radius: 10px; - margin-top: 5px; - color: white; -} - -@media only screen and (max-width: 767px){ - .intro, - .info{ - margin: 10px; - } -} - -code{ - font-size: .8em; - background: #ddd; - padding: .1em; -} - -pre{ - padding: .5rem; - background: #f0f0f0; - border: 1px solid #e8e8e8; - - code{ - background: none; - } -} - -blockquote{ - border-left: 3px solid burlywood; - padding: .1em 0 .1em 1rem; - margin: 1rem 0; - background: #f9f7f5; - width: 100%; -} diff --git a/decidim-api/app/views/decidim/api/documentation/graphql_docs_template.html.erb b/decidim-api/app/views/decidim/api/documentation/graphql_docs_template.html.erb new file mode 100644 index 0000000000000..2c59ad0724d6a --- /dev/null +++ b/decidim-api/app/views/decidim/api/documentation/graphql_docs_template.html.erb @@ -0,0 +1,7 @@ +
<%= contents %>
+ + + +
+ ☰ +
diff --git a/decidim-api/app/views/decidim/api/documentation/show.html.erb b/decidim-api/app/views/decidim/api/documentation/show.html.erb index c4d36d9e4de6f..a6367c1a8fbaf 100644 --- a/decidim-api/app/views/decidim/api/documentation/show.html.erb +++ b/decidim-api/app/views/decidim/api/documentation/show.html.erb @@ -1,5 +1,4 @@ - -
+
Decidim <%= Decidim.version %>

<%= current_organization.name %> API documentation

@@ -8,12 +7,4 @@ <% end %>
-
- <%= render_doc("usage") %> -
- -
- - +<%= static_api_docs_content %> diff --git a/decidim-api/app/views/decidim/api/graphiql/show.html.erb b/decidim-api/app/views/decidim/api/graphiql/show.html.erb index a03cd0f42f3dc..1d22d745cd930 100644 --- a/decidim-api/app/views/decidim/api/graphiql/show.html.erb +++ b/decidim-api/app/views/decidim/api/graphiql/show.html.erb @@ -3,13 +3,14 @@ <%= Decidim::GraphiQL::Rails.config.title || "Decidim API" %> <%= stylesheet_pack_tag("decidim_api_graphiql") %> - <%= javascript_pack_tag("decidim_api_graphiql", defer: false) %>
Loading...
+ <%= javascript_pack_tag "decidim_api_graphiql", defer: false %> + <% js_configs = { graphql_endpoint: graphql_endpoint_path, @@ -17,6 +18,7 @@ request_headers: JSON.pretty_generate(Decidim::GraphiQL::Rails.config.resolve_headers(self)) } %> + diff --git a/decidim-api/app/views/layouts/decidim/api/documentation.html.erb b/decidim-api/app/views/layouts/decidim/api/documentation.html.erb index ab3e2a42dacd4..29eba32fa7fd8 100644 --- a/decidim-api/app/views/layouts/decidim/api/documentation.html.erb +++ b/decidim-api/app/views/layouts/decidim/api/documentation.html.erb @@ -1,10 +1,7 @@ <%= current_organization.name %> - API Documentation - <%= javascript_pack_tag "decidim_api_docs", defer: false %> - <%= stylesheet_pack_tag "decidim_api_docs" %> - + <%= stylesheet_pack_tag("decidim_api_docs") %> <%= yield %> diff --git a/decidim-api/config/routes.rb b/decidim-api/config/routes.rb index 1fb6e0abf77f6..af5227afa2d76 100644 --- a/decidim-api/config/routes.rb +++ b/decidim-api/config/routes.rb @@ -3,6 +3,7 @@ Decidim::Api::Engine.routes.draw do get "/graphiql", to: "graphiql#show", graphql_path: "/api", as: :graphiql get "/docs", to: "documentation#show", as: :documentation + get "/docs/*path", to: "documentation#show" get "/", to: redirect("/api/docs") post "/" => "queries#create", as: :root end diff --git a/decidim-api/decidim-api.gemspec b/decidim-api/decidim-api.gemspec index 05bc16f44bb7b..b195937bfd0c0 100644 --- a/decidim-api/decidim-api.gemspec +++ b/decidim-api/decidim-api.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |s| s.email = ["josepjaume@gmail.com", "mrc2407@gmail.com", "oriolgual@gmail.com"] s.license = "AGPL-3.0" s.homepage = "https://github.com/decidim/decidim" - s.required_ruby_version = ">= 2.7" + s.required_ruby_version = ">= 3.0" s.name = "decidim-api" s.summary = "Decidim API module" @@ -21,9 +21,8 @@ Gem::Specification.new do |s| s.files = Dir["{app,config,db,lib,vendor,docs}/**/*", "Rakefile", "README.md"] s.add_dependency "graphql", "~> 1.12", "< 1.13" + s.add_dependency "graphql-docs", "~> 2.1.0" s.add_dependency "rack-cors", "~> 1.0" - s.add_dependency "redcarpet", "~> 3.5", ">= 3.5.1" - s.add_development_dependency "decidim-comments", Decidim::Api.version s.add_development_dependency "decidim-core", Decidim::Api.version s.add_development_dependency "decidim-dev", Decidim::Api.version diff --git a/decidim-api/lib/decidim/api.rb b/decidim-api/lib/decidim/api.rb index f2dd160b6be2b..455c8759a6289 100644 --- a/decidim-api/lib/decidim/api.rb +++ b/decidim-api/lib/decidim/api.rb @@ -7,6 +7,23 @@ module Decidim # This module holds all business logic related to exposing a Public API for # decidim. module Api + include ActiveSupport::Configurable + + # defines the schema max_per_page to configure GraphQL pagination + config_accessor :schema_max_per_page do + 50 + end + + # defines the schema max_complexity to configure GraphQL query complexity + config_accessor :schema_max_complexity do + 5000 + end + + # defines the schema max_depth to configure GraphQL query max_depth + config_accessor :schema_max_depth do + 15 + end + # This declares all the types an interface or union can resolve to. This needs # to be done in order to be able to have them found. This is a shortcoming of # graphql-ruby and the way it deals with loading types, in combination with diff --git a/decidim-api/lib/decidim/api/schema.rb b/decidim-api/lib/decidim/api/schema.rb index b1d0a4d09d211..8a0905419bece 100644 --- a/decidim-api/lib/decidim/api/schema.rb +++ b/decidim-api/lib/decidim/api/schema.rb @@ -7,9 +7,9 @@ class Schema < GraphQL::Schema mutation(MutationType) query(QueryType) - default_max_page_size 50 - max_depth 15 - max_complexity 300 + default_max_page_size Decidim::Api.schema_max_per_page + max_depth Decidim::Api.schema_max_depth + max_complexity Decidim::Api.schema_max_complexity orphan_types(Api.orphan_types) end diff --git a/decidim-api/lib/decidim/api/test/component_context.rb b/decidim-api/lib/decidim/api/test/component_context.rb index 7be4f3ab470d4..836e436d8b327 100644 --- a/decidim-api/lib/decidim/api/test/component_context.rb +++ b/decidim-api/lib/decidim/api/test/component_context.rb @@ -12,8 +12,8 @@ let(:participatory_process) { create :participatory_process, organization: current_organization } let(:category) { create(:category, participatory_space: participatory_process) } - let(:component_type) {} - let(:component_fragment) {} + let(:component_type) { nil } + let(:component_fragment) { nil } let(:participatory_process_query) do %( diff --git a/decidim-api/lib/decidim/api/version.rb b/decidim-api/lib/decidim/api/version.rb index 166afaf06f8bf..851b590300393 100644 --- a/decidim-api/lib/decidim/api/version.rb +++ b/decidim-api/lib/decidim/api/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-api version. module Api def self.version - "0.26.4" + "0.27.2" end end end diff --git a/decidim-api/lib/tasks/decidim_api_docs.rake b/decidim-api/lib/tasks/decidim_api_docs.rake new file mode 100644 index 0000000000000..c588a406885c1 --- /dev/null +++ b/decidim-api/lib/tasks/decidim_api_docs.rake @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require "graphql-docs" + +namespace :decidim_api do + desc "Generates the API docs files" + task generate_docs: :environment do + output_dir = clear_previous_docs + + GraphQLDocs.build( + schema: Decidim::Api::Schema, + output_dir: output_dir, + base_url: "/api/docs", + landing_pages: { + index: File.expand_path("../../docs/usage.md", __dir__) + }, + templates: { + default: File.expand_path("../../app/views/decidim/api/documentation/graphql_docs_template.html.erb", __dir__) + } + ) + + clear_cache_folder + end + + def clear_previous_docs + output_dir = Rails.application.root.join("app", "views", "static", "api", "docs") + FileUtils.rm_rf(output_dir) + output_dir + end + + def clear_cache_folder + FileUtils.rm_rf(Rails.application.root.join(".sass-cache")) + end +end diff --git a/decidim-api/spec/system/documentation_spec.rb b/decidim-api/spec/system/documentation_spec.rb index 34044349a3687..24b998f9abad0 100644 --- a/decidim-api/spec/system/documentation_spec.rb +++ b/decidim-api/spec/system/documentation_spec.rb @@ -16,10 +16,7 @@ within "h1" do expect(page).to have_content(organization.name) end - - within ".info" do - expect(page).to have_content("ABOUT THE GRAPHQL API") - end + expect(page).to have_content("About the GraphQL API") end end end diff --git a/decidim-api/spec/tasks/decidim_api_generate_docs_spec.rb b/decidim-api/spec/tasks/decidim_api_generate_docs_spec.rb new file mode 100644 index 0000000000000..66d02470eadd8 --- /dev/null +++ b/decidim-api/spec/tasks/decidim_api_generate_docs_spec.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe "rake decidim_api:generate_docs", type: :task do + it "creates the static docs files" do + static = Rails.root.join("app/views/static/api/docs") + FileUtils.rm_rf(static) + + task.execute + + index = File.read("#{static}/index.html") + expect(index).to include("About the GraphQL API") + expect(index).to include("GraphQL Reference") + end +end diff --git a/decidim-assemblies/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies/show.erb b/decidim-assemblies/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies/show.erb index 1b3245c1082a0..5a9c581055cf4 100644 --- a/decidim-assemblies/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies/show.erb +++ b/decidim-assemblies/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies/show.erb @@ -1,4 +1,4 @@ -
+

<%= t("active_assemblies", scope: i18n_scope) %>

diff --git a/decidim-assemblies/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies_cell.rb b/decidim-assemblies/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies_cell.rb index b315b4af02dfa..58648dd2f50e1 100644 --- a/decidim-assemblies/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies_cell.rb +++ b/decidim-assemblies/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies_cell.rb @@ -6,10 +6,6 @@ module ContentBlocks class HighlightedAssembliesCell < Decidim::ViewModel delegate :current_user, to: :controller - cache :show, expires_in: 10.minutes, if: :perform_caching? do - cache_hash - end - def show render if highlighted_assemblies.any? end @@ -22,6 +18,7 @@ def highlighted_assemblies @highlighted_assemblies ||= OrganizationPrioritizedAssemblies .new(current_organization, current_user) .query + .with_attached_hero_image .includes([:organization]) .limit(max_results) end diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/copy_assembly.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/copy_assembly.rb index 5a2be22ba6d97..ccd96e1b7a7e4 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/copy_assembly.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/copy_assembly.rb @@ -5,14 +5,15 @@ module Assemblies module Admin # A command with all the business logic when copying a new participatory # assembly in the system. - class CopyAssembly < Rectify::Command + class CopyAssembly < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. # assembly - An assembly we want to duplicate - def initialize(form, assembly) + def initialize(form, assembly, user) @form = form @assembly = assembly + @user = user end # Executes the command. Broadcasts these events: @@ -24,11 +25,13 @@ def initialize(form, assembly) def call return broadcast(:invalid) if form.invalid? - Assembly.transaction do - copy_assembly - copy_assembly_attachments - copy_assembly_categories if @form.copy_categories? - copy_assembly_components if @form.copy_components? + Decidim.traceability.perform_action!("duplicate", @assembly, @user) do + Assembly.transaction do + copy_assembly + copy_assembly_attachments + copy_assembly_categories if @form.copy_categories? + copy_assembly_components if @form.copy_components? + end end broadcast(:ok, @copied_assembly) diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/create_assemblies_type.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/create_assemblies_type.rb index 0cecb70b6e689..a9cc966d4a549 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/create_assemblies_type.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/create_assemblies_type.rb @@ -5,7 +5,7 @@ module Assemblies module Admin # A command with all the business logic when creating a new assembly # type in the system. - class CreateAssembliesType < Rectify::Command + class CreateAssembliesType < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/create_assembly.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/create_assembly.rb index a1425fc13c62b..4e918840d4a69 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/create_assembly.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/create_assembly.rb @@ -5,7 +5,7 @@ module Assemblies module Admin # A command with all the business logic when creating a new participatory # assembly in the system. - class CreateAssembly < Rectify::Command + class CreateAssembly < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/create_assembly_member.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/create_assembly_member.rb index 9f440cfba8e74..c51416b2b9eba 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/create_assembly_member.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/create_assembly_member.rb @@ -5,7 +5,7 @@ module Assemblies module Admin # A command with all the business logic when creating a new assembly # member in the system. - class CreateAssemblyMember < Rectify::Command + class CreateAssemblyMember < Decidim::Command include ::Decidim::AttachmentAttributesMethods # Public: Initializes the command. @@ -53,16 +53,16 @@ def assembly_member_with_attributes def assembly_member_attributes form.attributes.slice( - :full_name, - :gender, - :birthday, - :birthplace, - :ceased_date, - :designation_date, - :position, - :position_other, - :weight - ).merge( + "full_name", + "gender", + "birthday", + "birthplace", + "ceased_date", + "designation_date", + "position", + "position_other", + "weight" + ).symbolize_keys.merge( assembly: assembly, user: form.user ).merge( @@ -99,7 +99,7 @@ def notify_assembly_member_about_new_membership resource: assembly, followers: followers } - Decidim::EventsManager.publish(data) + Decidim::EventsManager.publish(**data) end end end diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/destroy_assemblies_type.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/destroy_assemblies_type.rb index c85aa4a5df42d..5b6a2b3020a86 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/destroy_assemblies_type.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/destroy_assemblies_type.rb @@ -5,7 +5,7 @@ module Assemblies module Admin # A command with all the business logic when destroying an assembly # type in the system. - class DestroyAssembliesType < Rectify::Command + class DestroyAssembliesType < Decidim::Command # Public: Initializes the command. # # assemblies_type - the AssemblyMember to destroy diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/destroy_assembly_admin.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/destroy_assembly_admin.rb index 256ca47ba9892..a0edcb6296aaf 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/destroy_assembly_admin.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/destroy_assembly_admin.rb @@ -5,7 +5,7 @@ module Assemblies module Admin # A command with all the business logic when destroying an assembly # admin in the system. - class DestroyAssemblyAdmin < Rectify::Command + class DestroyAssemblyAdmin < Decidim::Command # Public: Initializes the command. # # role - the AssemblyUserRole to destroy diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/destroy_assembly_member.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/destroy_assembly_member.rb index 1381e54acd61f..e7291d4edc832 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/destroy_assembly_member.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/destroy_assembly_member.rb @@ -5,7 +5,7 @@ module Assemblies module Admin # A command with all the business logic when destroying an assembly # member in the system. - class DestroyAssemblyMember < Rectify::Command + class DestroyAssemblyMember < Decidim::Command # Public: Initializes the command. # # assembly_member - the AssemblyMember to destroy diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/import_assembly.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/import_assembly.rb index f62e72b8736c9..ff83f3668738e 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/import_assembly.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/import_assembly.rb @@ -5,13 +5,14 @@ module Assemblies module Admin # A command with all the business logic to import a new assembly # in the system. - class ImportAssembly < Rectify::Command + class ImportAssembly < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. # assembly - An assembly we want to duplicate - def initialize(form) + def initialize(form, user) @form = form + @user = user end # Executes the command. Broadcasts these events: @@ -38,11 +39,14 @@ def call def import_assembly importer = Decidim::Assemblies::AssemblyImporter.new(form.current_organization, form.current_user) assemblies.each do |original_assembly| - @imported_assembly = importer.import(original_assembly, form.current_user, title: form.title, slug: form.slug) - importer.import_assemblies_type(original_assembly["decidim_assemblies_type_id"]) - importer.import_categories(original_assembly["assembly_categories"]) if form.import_categories? - importer.import_folders_and_attachments(original_assembly["attachments"]) if form.import_attachments? - importer.import_components(original_assembly["components"]) if form.import_components? + Decidim.traceability.perform_action!("import", Assembly, @user) do + @imported_assembly = importer.import(original_assembly, form.current_user, title: form.title, slug: form.slug) + importer.import_assemblies_type(original_assembly["decidim_assemblies_type_id"]) + importer.import_categories(original_assembly["assembly_categories"]) if form.import_categories? + importer.import_folders_and_attachments(original_assembly["attachments"]) if form.import_attachments? + importer.import_components(original_assembly["components"]) if form.import_components? + @imported_assembly + end end end diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/notify_role_assigned_to_assembly.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/notify_role_assigned_to_assembly.rb index 79920fe6d4395..67b5e57f8da59 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/notify_role_assigned_to_assembly.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/notify_role_assigned_to_assembly.rb @@ -4,7 +4,7 @@ module Decidim module Assemblies module Admin # A command to notify users when a role is assigned for an assembly - class NotifyRoleAssignedToAssembly < Rectify::Command + class NotifyRoleAssignedToAssembly < Decidim::Command def send_notification(user) Decidim::EventsManager.publish( event: "decidim.events.assembly.role_assigned", diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/publish_assembly.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/publish_assembly.rb index 19bef137b6f06..958cac1fb25c4 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/publish_assembly.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/publish_assembly.rb @@ -4,7 +4,7 @@ module Decidim module Assemblies module Admin # A command that sets an assembly as published. - class PublishAssembly < Rectify::Command + class PublishAssembly < Decidim::Command # Public: Initializes the command. # # assembly - A Assembly that will be published diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/unpublish_assembly.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/unpublish_assembly.rb index 39a82e832ed55..a16348d4ae227 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/unpublish_assembly.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/unpublish_assembly.rb @@ -4,7 +4,7 @@ module Decidim module Assemblies module Admin # A command that sets an assembly as unpublished. - class UnpublishAssembly < Rectify::Command + class UnpublishAssembly < Decidim::Command # Public: Initializes the command. # # assembly - A Assembly that will be published diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assemblies_setting.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assemblies_setting.rb index c4de83c575635..6946d2ba526c1 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assemblies_setting.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assemblies_setting.rb @@ -5,7 +5,7 @@ module Assemblies module Admin # A command with all the business logic when updating assemblies # settings in admin area. - class UpdateAssembliesSetting < Rectify::Command + class UpdateAssembliesSetting < Decidim::Command # Public: Initializes the command. # # assemblies_setting - A assemblies_setting object to update. diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assemblies_type.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assemblies_type.rb index 235155fed53aa..99a0b82700932 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assemblies_type.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assemblies_type.rb @@ -5,7 +5,7 @@ module Assemblies module Admin # A command with all the business logic when updating a new assembly # type in the system. - class UpdateAssembliesType < Rectify::Command + class UpdateAssembliesType < Decidim::Command # Public: Initializes the command. # # assemblies_type - A assemblies_type object to update. diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assembly.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assembly.rb index edf72b961458e..efded9588411f 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assembly.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assembly.rb @@ -5,7 +5,7 @@ module Assemblies module Admin # A command with all the business logic when creating a new participatory # assembly in the system. - class UpdateAssembly < Rectify::Command + class UpdateAssembly < Decidim::Command include ::Decidim::AttachmentAttributesMethods # Public: Initializes the command. diff --git a/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assembly_member.rb b/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assembly_member.rb index ee590e0665906..e7769aba69a25 100644 --- a/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assembly_member.rb +++ b/decidim-assemblies/app/commands/decidim/assemblies/admin/update_assembly_member.rb @@ -5,7 +5,7 @@ module Assemblies module Admin # A command with all the business logic when updating an assembly # member in the system. - class UpdateAssemblyMember < Rectify::Command + class UpdateAssemblyMember < Decidim::Command include ::Decidim::AttachmentAttributesMethods # Public: Initializes the command. @@ -51,16 +51,16 @@ def call def attributes form.attributes.slice( - :full_name, - :gender, - :birthday, - :birthplace, - :ceased_date, - :designation_date, - :position, - :position_other, - :weight - ).merge( + "full_name", + "gender", + "birthday", + "birthplace", + "ceased_date", + "designation_date", + "position", + "position_other", + "weight" + ).symbolize_keys.merge( user: form.user ).merge( attachment_attributes(:non_user_avatar) diff --git a/decidim-assemblies/app/controllers/decidim/assemblies/admin/assembly_copies_controller.rb b/decidim-assemblies/app/controllers/decidim/assemblies/admin/assembly_copies_controller.rb index 06975e1259ac2..7e93c4aefb749 100644 --- a/decidim-assemblies/app/controllers/decidim/assemblies/admin/assembly_copies_controller.rb +++ b/decidim-assemblies/app/controllers/decidim/assemblies/admin/assembly_copies_controller.rb @@ -17,7 +17,7 @@ def create enforce_permission_to :create, :assembly @form = form(AssemblyCopyForm).from_params(params) - CopyAssembly.call(@form, current_assembly) do + CopyAssembly.call(@form, current_assembly, current_user) do on(:ok) do flash[:notice] = I18n.t("assemblies_copies.create.success", scope: "decidim.admin") redirect_to assemblies_path(parent_id: current_assembly.parent_id) diff --git a/decidim-assemblies/app/controllers/decidim/assemblies/admin/assembly_imports_controller.rb b/decidim-assemblies/app/controllers/decidim/assemblies/admin/assembly_imports_controller.rb index 88d24de88ebac..3e62738e92cef 100644 --- a/decidim-assemblies/app/controllers/decidim/assemblies/admin/assembly_imports_controller.rb +++ b/decidim-assemblies/app/controllers/decidim/assemblies/admin/assembly_imports_controller.rb @@ -13,7 +13,7 @@ def create enforce_permission_to :import, :assembly @form = form(AssemblyImportForm).from_params(params) - ImportAssembly.call(@form) do + ImportAssembly.call(@form, current_user) do on(:ok) do flash[:notice] = I18n.t("assembly_imports.create.success", scope: "decidim.admin") redirect_to assemblies_path diff --git a/decidim-assemblies/app/controllers/decidim/assemblies/admin/reminders_controller.rb b/decidim-assemblies/app/controllers/decidim/assemblies/admin/reminders_controller.rb new file mode 100644 index 0000000000000..4c28446e1d7d1 --- /dev/null +++ b/decidim-assemblies/app/controllers/decidim/assemblies/admin/reminders_controller.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Decidim + module Assemblies + module Admin + # This controller allows to send reminders. + # It is targeted for customizations for reminder things that lives under + # an assembly. + class RemindersController < Decidim::Admin::RemindersController + include Concerns::AssemblyAdmin + end + end + end +end diff --git a/decidim-assemblies/app/controllers/decidim/assemblies/assemblies_controller.rb b/decidim-assemblies/app/controllers/decidim/assemblies/assemblies_controller.rb index 610f81317da33..9461b986f548f 100644 --- a/decidim-assemblies/app/controllers/decidim/assemblies/assemblies_controller.rb +++ b/decidim-assemblies/app/controllers/decidim/assemblies/assemblies_controller.rb @@ -48,15 +48,15 @@ def show private - def search_klass - AssemblySearch + def search_collection + Assembly.where(organization: current_organization).published.visible_for(current_user) end def default_filter_params { - scope_id: nil, - area_id: nil, - type_id: nil + with_scope: nil, + with_area: nil, + type_id_eq: nil } end @@ -77,7 +77,7 @@ def promoted_assemblies end def parent_assemblies - search.results.parent_assemblies.order(weight: :asc, promoted: :desc) + search.result.parent_assemblies.order(weight: :asc, promoted: :desc) end def stats diff --git a/decidim-assemblies/app/events/decidim/role_assigned_to_assembly_event.rb b/decidim-assemblies/app/events/decidim/role_assigned_to_assembly_event.rb index ecbed338b6565..065b2e705f3d3 100644 --- a/decidim-assemblies/app/events/decidim/role_assigned_to_assembly_event.rb +++ b/decidim-assemblies/app/events/decidim/role_assigned_to_assembly_event.rb @@ -6,7 +6,7 @@ class RoleAssignedToAssemblyEvent < Decidim::Events::SimpleEvent include Decidim::Events::AuthorEvent def notification_title - I18n.t("notification_title", i18n_options).html_safe + I18n.t("notification_title", **i18n_options).html_safe end def i18n_role diff --git a/decidim-assemblies/app/forms/decidim/assemblies/admin/assembly_import_form.rb b/decidim-assemblies/app/forms/decidim/assemblies/admin/assembly_import_form.rb index 6787d8d959874..df546bc03a33b 100644 --- a/decidim-assemblies/app/forms/decidim/assemblies/admin/assembly_import_form.rb +++ b/decidim-assemblies/app/forms/decidim/assemblies/admin/assembly_import_form.rb @@ -30,10 +30,9 @@ class AssemblyImportForm < Form attribute :import_categories, Boolean, default: true attribute :import_attachments, Boolean, default: true attribute :import_components, Boolean, default: true - attribute :document - - validates :document, presence: true + attribute :document, Decidim::Attributes::Blob + validates :document, file_content_type: { allow: ACCEPTED_TYPES.values } validates :slug, presence: true, format: { with: Decidim::Assembly.slug_format } validates :title, translatable_presence: true validate :slug_uniqueness @@ -41,7 +40,7 @@ class AssemblyImportForm < Form validate :document_type_must_be_valid, if: :document def document_text - @document_text ||= document&.read + @document_text ||= document&.download end def document_type_must_be_valid @@ -60,9 +59,9 @@ def document_type end def i18n_invalid_document_type_text - I18n.t("invalid_document_type", + I18n.t("allowed_file_content_types", scope: "activemodel.errors.models.assembly.attributes.document", - valid_mime_types: i18n_valid_mime_types_text) + types: i18n_valid_mime_types_text) end def i18n_valid_mime_types_text diff --git a/decidim-assemblies/app/helpers/decidim/assemblies/filter_assemblies_helper.rb b/decidim-assemblies/app/helpers/decidim/assemblies/filter_assemblies_helper.rb index ee7e655bf8bad..d5fbe6d883ddc 100644 --- a/decidim-assemblies/app/helpers/decidim/assemblies/filter_assemblies_helper.rb +++ b/decidim-assemblies/app/helpers/decidim/assemblies/filter_assemblies_helper.rb @@ -7,7 +7,9 @@ module Assemblies # `filter` returns a Filter object from Decidim::FilterResource module FilterAssembliesHelper def available_filters - @available_filters ||= [t("all", scope: "decidim.assemblies.filter")] + organization_assembly_types + return if organization_assembly_types.blank? + + [t("all", scope: "decidim.assemblies.filter")] + organization_assembly_types end def filter_link(type_id) @@ -16,9 +18,9 @@ def filter_link(type_id) .url_helpers .assemblies_path( filter: { - scope_id: filter.scope_id, - area_id: filter.area_id, - type_id: type_id + with_scope: filter.with_scope, + with_area: filter.with_area, + type_id_eq: type_id } ) end @@ -28,14 +30,16 @@ def help_text end def current_filter_name - type = AssembliesType.find_by(id: filter.type_id) + type = AssembliesType.find_by(id: filter_params[:type_id_eq]) return translated_attribute type.title if type t("all", scope: "decidim.assemblies.filter") end def organization_assembly_types - AssembliesType.where(organization: current_organization)&.map { |type| [translated_attribute(type.title), type.id] } + @organization_assembly_types ||= AssembliesType.where(organization: current_organization).joins(:assemblies).where( + decidim_assemblies: { id: search.result.unscope(where: :decidim_assemblies_type_id).parent_assemblies } + ).distinct&.map { |type| [translated_attribute(type.title), type.id] } end end end diff --git a/decidim-assemblies/app/models/decidim/assembly.rb b/decidim-assemblies/app/models/decidim/assembly.rb index abd90d9b8e03c..1c261d4d4b13e 100644 --- a/decidim-assemblies/app/models/decidim/assembly.rb +++ b/decidim-assemblies/app/models/decidim/assembly.rb @@ -34,6 +34,8 @@ class Assembly < ApplicationRecord include Decidim::Searchable include Decidim::HasUploadValidations include Decidim::TranslatableResource + include Decidim::HasArea + include Decidim::FilterableResource SOCIAL_HANDLERS = [:twitter, :facebook, :instagram, :youtube, :github].freeze CREATED_BY = %w(city_council public others).freeze @@ -146,7 +148,7 @@ def closed? end def user_roles(role_name = nil) - roles = Decidim::AssemblyUserRole.where(assembly: self) + roles = Decidim::AssemblyUserRole.where(assembly: self_and_ancestors) return roles if role_name.blank? roles.where(role: role_name) @@ -156,6 +158,10 @@ def attachment_context :admin end + def self.ransackable_scopes(_auth_object = nil) + [:with_area, :with_scope] + end + private # When an assembly changes their parent, we need to update the parents_path attribute @@ -208,8 +214,8 @@ def update_children_paths # rubocop:enable Rails/SkipsModelValidations # Allow ransacker to search for a key in a hstore column (`title`.`en`) - ransacker :title do |parent| - Arel::Nodes::InfixOperation.new("->>", parent.table[:title], Arel::Nodes.build_quoted(I18n.locale.to_s)) - end + ransacker_i18n :title + + ransack_alias :type_id, :decidim_assemblies_type_id end end diff --git a/decidim-assemblies/app/packs/src/decidim/assemblies/orgchart.js b/decidim-assemblies/app/packs/src/decidim/assemblies/orgchart.js index 4d0b7259d85cc..6f7e6d67a81cc 100644 --- a/decidim-assemblies/app/packs/src/decidim/assemblies/orgchart.js +++ b/decidim-assemblies/app/packs/src/decidim/assemblies/orgchart.js @@ -2,10 +2,13 @@ /* eslint dot-location: ["error", "property"], no-negated-condition: "error" */ /* eslint no-unused-expressions: ["error", { "allowTernary": true }] */ /* eslint no-unused-vars: 0 */ -/* global d3 */ -import * as d3 from "d3" -import renderChart from "src/decidim/vizzs/renders" +import { select, selectAll, event } from "d3-selection"; +import { max } from "d3-array"; +import { hierarchy } from "d3-hierarchy"; +import { forceManyBody, forceCollide, forceCenter, forceX, forceY, forceSimulation, forceLink } from "d3-force"; +import { drag } from "d3-drag"; +import { json } from "d3-fetch"; // lib const renderOrgCharts = () => { @@ -54,11 +57,11 @@ const renderOrgCharts = () => { let updateData let collapse, expand let filter - let hierarchy = {} + let _hierarchy = {} // main chart object - let main = function (selection) { - selection.each(function scope() { + let main = function (_selection) { + _selection.each(function scope() { // calculated properties let calc = {} @@ -68,12 +71,12 @@ const renderOrgCharts = () => { calc.chartHeight = attrs.svgHeight - attrs.marginBottom - calc.chartTopMargin // ########################## HIERARCHY STUFF ######################### - hierarchy.root = d3.hierarchy(attrs.data.root) + _hierarchy.root = hierarchy(attrs.data.root) // ########################### BEHAVIORS ######################### let behaviors = {} - // behaviors.zoom = d3.zoom().scaleExtent([0.75, 100, 8]).on("zoom", zoomed) - behaviors.drag = d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended) + // behaviors.zoom = zoom().scaleExtent([0.75, 100, 8]).on("zoom", zoomed) + behaviors.drag = drag().on("start", dragstarted).on("drag", dragged).on("end", dragended) // ########################### LAYOUTS ######################### let layouts = {} @@ -83,24 +86,24 @@ const renderOrgCharts = () => { // ########################### FORCE STUFF ######################### let force = {} - force.link = d3.forceLink().id((d) => d.id) - force.charge = d3.forceManyBody().strength(-240) - force.center = d3.forceCenter(calc.chartWidth / 2, calc.chartHeight / 2) + force.link = forceLink().id((d) => d.id) + force.charge = forceManyBody().strength(-240) + force.center = forceCenter(calc.chartWidth / 2, calc.chartHeight / 2) // prevent collide - force.collide = d3.forceCollide().radius((d) => { + force.collide = forceCollide().radius((d) => { // Creates an invented radius based on element measures: diagonal = 2 * radius = sqrt(width^2, height^2) let base = (d.bbox || {}).width + (attrs.nodeGutter.x * 2) let height = (d.bbox || {}).height + (attrs.nodeGutter.y * 2) let diagonal = Math.sqrt(Math.pow(base, 2) + Math.pow(height, 2)) let fakeRadius = (diagonal / 2) - // return d3.max([attrs.nodeDistance * 3, fakeRadius]) + // return max([attrs.nodeDistance * 3, fakeRadius]) return fakeRadius * 1.5 }) // manually set x positions (which is calculated using custom radial layout) - force.x = d3.forceX() + force.x = forceX() .strength(0.5) .x(function (d) { @@ -115,8 +118,8 @@ const renderOrgCharts = () => { return projectCircle(d.proportion, (d.depth - 1) * attrs.distance)[0] }) - // manually set y positions (which is calculated using d3.cluster) - force.y = d3.forceY() + // manually set y positions (which is calculated using cluster) + force.y = forceY() .strength(0.5) .y(function (d) { @@ -134,7 +137,7 @@ const renderOrgCharts = () => { // --------------------------------- INITIALISE FORCE SIMULATION ---------------------------- // get based on top parameter simulation - force.simulation = d3.forceSimulation() + force.simulation = forceSimulation() .force("link", force.link) .force("charge", force.charge) .force("center", force.center) @@ -145,7 +148,7 @@ const renderOrgCharts = () => { // ########################### HIERARCHY STUFF ######################### // flatten root - let arr = flatten(hierarchy.root) + let arr = flatten(_hierarchy.root) // hide members based on their depth arr.forEach((d) => { @@ -163,25 +166,25 @@ const renderOrgCharts = () => { // #################################### DRAWINGS ####################### // drawing containers - let container = d3.select(this) + let container = select(this) // add svg - let svg = container.patternify({ tag: "svg", selector: "svg-chart-container" }) + let svg = patternify(container, { tag: "svg", selector: "svg-chart-container" }) .attr("width", attrs.svgWidth) .attr("height", attrs.svgHeight) // .call(behaviors.zoom) // add container g element - let chart = svg.patternify({ tag: "g", selector: "chart" }) + let chart = patternify(svg, { tag: "g", selector: "chart" }) .attr("transform", `translate(${calc.chartLeftMargin},${calc.chartTopMargin})`) // ################################ Chart Content Drawing ################################## // link wrapper - let linksWrapper = chart.patternify({ tag: "g", selector: "links-wrapper" }) + let linksWrapper = patternify(chart, { tag: "g", selector: "links-wrapper" }) // node wrapper - let nodesWrapper = chart.patternify({ tag: "g", selector: "nodes-wrapper" }) + let nodesWrapper = patternify(chart, { tag: "g", selector: "nodes-wrapper" }) let links, nodes // reusable function which updates visual based on data change @@ -194,14 +197,14 @@ const renderOrgCharts = () => { (clickedNode) ? $btnReset.removeClass("invisible") : $btnReset.addClass("invisible") // set xy and proportion properties with custom radial layout - layouts.radial(hierarchy.root) + layouts.radial(_hierarchy.root) // nodes and links array - let nodesArr = flatten(hierarchy.root, true) + let nodesArr = flatten(_hierarchy.root, true) .orderBy((d) => d.depth) .filter((d) => !d.hidden) - let linksArr = hierarchy.root.links() + let linksArr = _hierarchy.root.links() .filter((d) => !d.source.hidden) .filter((d) => !d.target.hidden) @@ -274,7 +277,7 @@ const renderOrgCharts = () => { .attr("class", "as-text") .attr("dx", (d) => d.bbox.x + d.bbox.width + attrs.nodeGutter.x) .attr("dy", attrs.childrenIndicatorRadius + 3) - .text((d) => d3.max([(d.children || {}).length, (d._children || {}).length])) + .text((d) => max([(d.children || {}).length, (d._children || {}).length])) // merge node groups and style it nodes = enteredNodes.merge(nodes) @@ -291,7 +294,7 @@ const renderOrgCharts = () => { // zoom handler // function zoomed() { // // get transform event - // let transform = d3.event.transform + // let transform = event.transform // attrs.lastTransform = transform // // // apply transform event props to the wrapper @@ -330,8 +333,8 @@ const renderOrgCharts = () => { // handle dragging event function dragged(d) { // make dragged node fixed - d.fx = d3.event.x - d.fy = d3.event.y + d.fx = event.x + d.fy = event.y } // -------------------- handle drag end event --------------- @@ -342,7 +345,7 @@ const renderOrgCharts = () => { // -------------------------- node mouse hover handler --------------- function nodeMouseEnter(d) { // get links - let _links = hierarchy.root.links() + let _links = _hierarchy.root.links() // get hovered node connected links let connectedLinks = _links.filter((l) => l.source.id === d.id || l.target.id === d.id) @@ -438,7 +441,7 @@ const renderOrgCharts = () => { // } function freeNodes() { - d3.selectAll(".node").each((n) => { + selectAll(".node").each((n) => { n.fx = null n.fy = null }) @@ -507,18 +510,18 @@ const renderOrgCharts = () => { } // ----------- PROTOTYEPE FUNCTIONS ---------------------- - d3.selection.prototype.patternify = function (_params) { + function patternify(node, _params) { let selector = _params.selector let elementTag = _params.tag let _data = _params.data || [selector] // pattern in action - let selection = this.selectAll(`.${selector}`).data(_data) - selection.exit().remove() - selection = selection.enter().append(elementTag).merge(selection) - selection.attr("class", selector) + let _selection = node.selectAll(`.${selector}`).data(_data) + _selection.exit().remove() + _selection = _selection.enter().append(elementTag).merge(_selection) + _selection.attr("class", selector) - return selection + return _selection } // custom radial layout @@ -527,8 +530,8 @@ const renderOrgCharts = () => { recurse(root, 0, 1) - function recurse(node, min, max) { - node.proportion = (max + min) / 2 + function recurse(node, min, _max) { + node.proportion = (_max + min) / 2 if (!node.x) { // if node has parent, match entered node positions to it's parent @@ -550,7 +553,7 @@ const renderOrgCharts = () => { // recursively do the same for children if (node.children) { - let offset = (max - min) / node.children.length + let offset = (_max - min) / node.children.length node.children.forEach(function (child, i) { let newMin = min + (offset * i) let newMax = newMin + offset @@ -624,7 +627,7 @@ const renderOrgCharts = () => { // run visual main.run = function () { - d3.selectAll(attrs.container) + selectAll(attrs.container) .call(main) return main } @@ -643,7 +646,7 @@ const renderOrgCharts = () => { main.reset = function () { - hierarchy.root.children.forEach((e) => collapse(e, true)) + _hierarchy.root.children.forEach((e) => collapse(e, true)) main.run() return main @@ -659,7 +662,7 @@ const renderOrgCharts = () => { let width = $container.width() let height = width / (16 / 9) - d3.json($container.data("url")).then((data) => { + json($container.data("url")).then((data) => { // Make a fake previous node if the data entry is not hierarchical if (data instanceof Array) { fake = true @@ -691,5 +694,8 @@ const renderOrgCharts = () => { } $(() => { - renderChart(renderOrgCharts); + renderOrgCharts() + $(document).on("change.zf.tabs", () => { + renderOrgCharts() + }); }) diff --git a/decidim-assemblies/app/permissions/decidim/assemblies/permissions.rb b/decidim-assemblies/app/permissions/decidim/assemblies/permissions.rb index 24e6d9a4efee2..c74cb0dab5655 100644 --- a/decidim-assemblies/app/permissions/decidim/assemblies/permissions.rb +++ b/decidim-assemblies/app/permissions/decidim/assemblies/permissions.rb @@ -32,6 +32,8 @@ def permissions user_can_list_assembly_list? user_can_read_current_assembly? user_can_create_assembly? + user_can_export_assembly? + user_can_copy_assembly? user_can_read_assemblies_setting? # org admins and space admins can do everything in the admin section @@ -71,6 +73,12 @@ def admin_user? user.admin? || (assembly ? can_manage_assembly?(role: :admin) : has_manageable_assemblies?) end + # It's an admin assembly when assembly exists and the user is allowed to + # manage the current assembly. + def admin_assembly? + assembly.present? && assembly_admin_allowed_assemblies.include?(assembly) + end + # Checks if it has any manageable assembly, with any possible role. def has_manageable_assemblies?(role: :any) return unless user @@ -88,7 +96,11 @@ def can_manage_assembly?(role: :any) # Returns a collection of assemblies where the given user has the # specific role privilege. def assemblies_with_role_privileges(role) - Decidim::Assemblies::AssembliesWithUserRole.for(user, role) + if role == :admin + assembly_admin_allowed_assemblies + else + Decidim::Assemblies::AssembliesWithUserRole.for(user, role) + end end def public_list_assemblies_action? @@ -151,12 +163,26 @@ def user_can_read_admin_dashboard? allow! if user.admin? || has_manageable_assemblies? end - # Only organization admins can create a assembly + # Only organization admins and assemblies admins can create a assembly def user_can_create_assembly? return unless permission_action.action == :create && permission_action.subject == :assembly - toggle_allow(user.admin?) + toggle_allow(user.admin? || admin_assembly? || user_role == "admin") + end + + def user_can_export_assembly? + return unless permission_action.action == :export && + permission_action.subject == :assembly + + toggle_allow(user.admin? || admin_assembly?) + end + + def user_can_copy_assembly? + return unless permission_action.action == :copy && + permission_action.subject == :assembly + + toggle_allow(user.admin? || admin_assembly?) end def user_can_read_assemblies_setting? @@ -185,10 +211,9 @@ def user_can_list_assembly_list? end def allowed_list_of_assemblies? - assemblies = AssembliesWithUserRole.for(user) - parent_assemblies = assemblies.flat_map { |assembly| [assembly.id] + assembly.ancestors.pluck(:id) } + parent_assemblies = assembly_admin_allowed_assemblies.flat_map { |assembly| [assembly.id] + assembly.ancestors.pluck(:id) } - allowed_list_of_assemblies = Decidim::Assembly.where(id: assemblies + parent_assemblies) + allowed_list_of_assemblies = Decidim::Assembly.where(id: assembly_admin_allowed_assemblies + parent_assemblies) allowed_list_of_assemblies.uniq.member?(assembly) end @@ -196,7 +221,7 @@ def user_can_read_current_assembly? return unless read_assembly_list_permission_action? return if permission_action.subject == :assembly_list - toggle_allow(user.admin? || can_manage_assembly?) + toggle_allow(user.admin? || can_manage_assembly? || admin_assembly?) end # A moderator needs to be able to read the assembly they are assigned to, @@ -223,13 +248,10 @@ def valuator_action? end # Process admins can perform everything *inside* that assembly. They cannot - # create a assembly or perform actions on assembly groups or other - # assemblies. + # perform actions on assembly groups or other assemblies. def assembly_admin_action? return unless can_manage_assembly?(role: :admin) return if user.admin? - return disallow! if permission_action.action == :create && - permission_action.subject == :assembly is_allowed = [ :attachment, @@ -279,6 +301,18 @@ def read_assembly_list_permission_action? def assembly @assembly ||= context.fetch(:current_participatory_space, nil) || context.fetch(:assembly, nil) end + + def user_role + assembly_user_role = Decidim::AssemblyUserRole.find_by(decidim_user_id: user.id) + assembly_user_role.present? ? assembly_user_role.role : :any + end + + def assembly_admin_allowed_assemblies + assemblies = AssembliesWithUserRole.for(user, :admin) + child_assemblies = assemblies.flat_map { |assembly| [assembly.id] + assembly.children.pluck(:id) } + + Decidim::Assembly.where(id: assemblies + child_assemblies) + end end end end diff --git a/decidim-assemblies/app/presenters/decidim/assemblies/admin_log/assembly_presenter.rb b/decidim-assemblies/app/presenters/decidim/assemblies/admin_log/assembly_presenter.rb index e7b3a1c07440a..aa648f4e8f7df 100644 --- a/decidim-assemblies/app/presenters/decidim/assemblies/admin_log/assembly_presenter.rb +++ b/decidim-assemblies/app/presenters/decidim/assemblies/admin_log/assembly_presenter.rb @@ -63,7 +63,7 @@ def i18n_labels_scope def action_string case action - when "create", "publish", "unpublish", "update" + when "create", "publish", "unpublish", "update", "duplicate", "export", "import" "decidim.admin_log.assembly.#{action}" else super diff --git a/decidim-assemblies/app/presenters/decidim/assemblies/assembly_stats_presenter.rb b/decidim-assemblies/app/presenters/decidim/assemblies/assembly_stats_presenter.rb index 69c7f33ff5bda..dec3a45a36223 100644 --- a/decidim-assemblies/app/presenters/decidim/assemblies/assembly_stats_presenter.rb +++ b/decidim-assemblies/app/presenters/decidim/assemblies/assembly_stats_presenter.rb @@ -4,9 +4,12 @@ module Decidim module Assemblies # A presenter to render statistics in an Assembly. class AssemblyStatsPresenter < Decidim::StatsPresenter - attribute :assembly, Decidim::Assembly include Decidim::IconHelper + def assembly + __getobj__.fetch(:assembly) + end + # Public: returns a collection of stats (Hash) for the Assembly Home. def collection highlighted_stats = assembly_participants_stats diff --git a/decidim-assemblies/app/presenters/decidim/assembly_member_presenter.rb b/decidim-assemblies/app/presenters/decidim/assembly_member_presenter.rb index 5abe7bc32674d..e5f3a50c1f0ad 100644 --- a/decidim-assemblies/app/presenters/decidim/assembly_member_presenter.rb +++ b/decidim-assemblies/app/presenters/decidim/assembly_member_presenter.rb @@ -46,11 +46,9 @@ def non_user_avatar private def user - @user ||= begin - if (user = __getobj__.user.presence) - Decidim::UserPresenter.new(user) - end - end + @user ||= if (user = __getobj__.user.presence) + Decidim::UserPresenter.new(user) + end end end end diff --git a/decidim-assemblies/app/queries/decidim/assemblies/admin/admin_users.rb b/decidim-assemblies/app/queries/decidim/assemblies/admin/admin_users.rb index 09f39b3b8cd11..db82cc1a21b34 100644 --- a/decidim-assemblies/app/queries/decidim/assemblies/admin/admin_users.rb +++ b/decidim-assemblies/app/queries/decidim/assemblies/admin/admin_users.rb @@ -4,7 +4,7 @@ module Decidim module Assemblies module Admin # A class used to find the admins for an assembly or an organization assemblies. - class AdminUsers < Rectify::Query + class AdminUsers < Decidim::Query # Syntactic sugar to initialize the class and return the queried objects. # # assembly - an assembly that needs to find its assembly admins diff --git a/decidim-assemblies/app/queries/decidim/assemblies/admin/assembly_members.rb b/decidim-assemblies/app/queries/decidim/assemblies/admin/assembly_members.rb index 556e844abc484..ec7ddf89ec9b2 100644 --- a/decidim-assemblies/app/queries/decidim/assemblies/admin/assembly_members.rb +++ b/decidim-assemblies/app/queries/decidim/assemblies/admin/assembly_members.rb @@ -4,7 +4,7 @@ module Decidim module Assemblies module Admin # A class used to find the AssemblyMembers's by their status status. - class AssemblyMembers < Rectify::Query + class AssemblyMembers < Decidim::Query # Syntactic sugar to initialize the class and return the queried objects. # # assembly_members - the initial AssemblyMember relation that needs to be filtered. diff --git a/decidim-assemblies/app/queries/decidim/assemblies/assemblies_with_user_role.rb b/decidim-assemblies/app/queries/decidim/assemblies/assemblies_with_user_role.rb index fdbe060b0f5d9..2a5fda2470751 100644 --- a/decidim-assemblies/app/queries/decidim/assemblies/assemblies_with_user_role.rb +++ b/decidim-assemblies/app/queries/decidim/assemblies/assemblies_with_user_role.rb @@ -4,7 +4,7 @@ module Decidim module Assemblies # A class used to find the Assemblies that the given user has # the specific role privilege. - class AssembliesWithUserRole < Rectify::Query + class AssembliesWithUserRole < Decidim::Query # Syntactic sugar to initialize the class and return the queried objects. # # user - a User that needs to find which assemblies can manage diff --git a/decidim-assemblies/app/queries/decidim/assemblies/filtered_assemblies.rb b/decidim-assemblies/app/queries/decidim/assemblies/filtered_assemblies.rb index b1f28fc5e7a70..efbc8082e9cb1 100644 --- a/decidim-assemblies/app/queries/decidim/assemblies/filtered_assemblies.rb +++ b/decidim-assemblies/app/queries/decidim/assemblies/filtered_assemblies.rb @@ -3,7 +3,7 @@ module Decidim module Assemblies # This query filters assemblies by type. - class FilteredAssemblies < Rectify::Query + class FilteredAssemblies < Decidim::Query def initialize(filter) @filter = filter end diff --git a/decidim-assemblies/app/queries/decidim/assemblies/organization_assemblies.rb b/decidim-assemblies/app/queries/decidim/assemblies/organization_assemblies.rb index 0253c78df09a0..10710cd3c5aea 100644 --- a/decidim-assemblies/app/queries/decidim/assemblies/organization_assemblies.rb +++ b/decidim-assemblies/app/queries/decidim/assemblies/organization_assemblies.rb @@ -3,7 +3,7 @@ module Decidim module Assemblies # This query class filters all assemblies given an organization. - class OrganizationAssemblies < Rectify::Query + class OrganizationAssemblies < Decidim::Query def initialize(organization) @organization = organization end diff --git a/decidim-assemblies/app/queries/decidim/assemblies/organization_prioritized_assemblies.rb b/decidim-assemblies/app/queries/decidim/assemblies/organization_prioritized_assemblies.rb index 2b2d8e61f1460..e4e593d7d535b 100644 --- a/decidim-assemblies/app/queries/decidim/assemblies/organization_prioritized_assemblies.rb +++ b/decidim-assemblies/app/queries/decidim/assemblies/organization_prioritized_assemblies.rb @@ -4,14 +4,14 @@ module Decidim module Assemblies # This query class filters public assemblies given an organization in a # meaningful prioritized order. - class OrganizationPrioritizedAssemblies < Rectify::Query + class OrganizationPrioritizedAssemblies < Decidim::Query def initialize(organization, user = nil) @organization = organization @user = user end def query - Rectify::Query.merge( + Decidim::Query.merge( OrganizationPublishedAssemblies.new(@organization, @user), PrioritizedAssemblies.new ).query diff --git a/decidim-assemblies/app/queries/decidim/assemblies/organization_published_assemblies.rb b/decidim-assemblies/app/queries/decidim/assemblies/organization_published_assemblies.rb index 7298aab81b8c1..c2fcc02996bfb 100644 --- a/decidim-assemblies/app/queries/decidim/assemblies/organization_published_assemblies.rb +++ b/decidim-assemblies/app/queries/decidim/assemblies/organization_published_assemblies.rb @@ -3,14 +3,14 @@ module Decidim module Assemblies # This query class filters published assemblies given an organization. - class OrganizationPublishedAssemblies < Rectify::Query + class OrganizationPublishedAssemblies < Decidim::Query def initialize(organization, user = nil) @organization = organization @user = user end def query - Rectify::Query.merge( + Decidim::Query.merge( OrganizationAssemblies.new(@organization), PublishedAssemblies.new, VisibleAssemblies.new(@user) diff --git a/decidim-assemblies/app/queries/decidim/assemblies/parent_assemblies.rb b/decidim-assemblies/app/queries/decidim/assemblies/parent_assemblies.rb index 93701b6ffa421..56c5e5b998b86 100644 --- a/decidim-assemblies/app/queries/decidim/assemblies/parent_assemblies.rb +++ b/decidim-assemblies/app/queries/decidim/assemblies/parent_assemblies.rb @@ -3,7 +3,7 @@ module Decidim module Assemblies # This query filters assemblies so only parent assemblies are returned. - class ParentAssemblies < Rectify::Query + class ParentAssemblies < Decidim::Query def query Decidim::Assembly.where(parent: nil) end diff --git a/decidim-assemblies/app/queries/decidim/assemblies/parent_assemblies_for_select.rb b/decidim-assemblies/app/queries/decidim/assemblies/parent_assemblies_for_select.rb index 9aeec63116cc2..185ab87e14dc7 100644 --- a/decidim-assemblies/app/queries/decidim/assemblies/parent_assemblies_for_select.rb +++ b/decidim-assemblies/app/queries/decidim/assemblies/parent_assemblies_for_select.rb @@ -3,7 +3,7 @@ module Decidim module Assemblies # This query filters assemblies that can be assigned as parents for an assembly. - class ParentAssembliesForSelect < Rectify::Query + class ParentAssembliesForSelect < Decidim::Query # Syntactic sugar to initialize the class and return the queried objects. def self.for(organization, assembly) new(organization, assembly).query diff --git a/decidim-assemblies/app/queries/decidim/assemblies/prioritized_assemblies.rb b/decidim-assemblies/app/queries/decidim/assemblies/prioritized_assemblies.rb index 43f6e21e32c38..cb2c868066b53 100644 --- a/decidim-assemblies/app/queries/decidim/assemblies/prioritized_assemblies.rb +++ b/decidim-assemblies/app/queries/decidim/assemblies/prioritized_assemblies.rb @@ -4,7 +4,7 @@ module Decidim module Assemblies # This query orders assemblies by importance, prioritizing promoted # assemblies. - class PrioritizedAssemblies < Rectify::Query + class PrioritizedAssemblies < Decidim::Query def query Decidim::Assembly.order(promoted: :desc) end diff --git a/decidim-assemblies/app/queries/decidim/assemblies/promoted_assemblies.rb b/decidim-assemblies/app/queries/decidim/assemblies/promoted_assemblies.rb index 46422276eedb3..8e82a0fc2e4d6 100644 --- a/decidim-assemblies/app/queries/decidim/assemblies/promoted_assemblies.rb +++ b/decidim-assemblies/app/queries/decidim/assemblies/promoted_assemblies.rb @@ -3,7 +3,7 @@ module Decidim module Assemblies # This query filters assemblies so only promoted ones are returned. - class PromotedAssemblies < Rectify::Query + class PromotedAssemblies < Decidim::Query def query Decidim::Assembly.promoted end diff --git a/decidim-assemblies/app/queries/decidim/assemblies/published_assemblies.rb b/decidim-assemblies/app/queries/decidim/assemblies/published_assemblies.rb index fc59590a8c587..30b27b58b0a52 100644 --- a/decidim-assemblies/app/queries/decidim/assemblies/published_assemblies.rb +++ b/decidim-assemblies/app/queries/decidim/assemblies/published_assemblies.rb @@ -3,7 +3,7 @@ module Decidim module Assemblies # This query filters published assemblies only. - class PublishedAssemblies < Rectify::Query + class PublishedAssemblies < Decidim::Query def query Decidim::Assembly.published end diff --git a/decidim-assemblies/app/queries/decidim/assemblies/visible_assemblies.rb b/decidim-assemblies/app/queries/decidim/assemblies/visible_assemblies.rb index b96bfacb8015d..b158466d58482 100644 --- a/decidim-assemblies/app/queries/decidim/assemblies/visible_assemblies.rb +++ b/decidim-assemblies/app/queries/decidim/assemblies/visible_assemblies.rb @@ -3,7 +3,7 @@ module Decidim module Assemblies # This query class filters assemblies given a current_user. - class VisibleAssemblies < Rectify::Query + class VisibleAssemblies < Decidim::Query def initialize(user) @user = user end diff --git a/decidim-assemblies/app/serializers/decidim/assemblies/assembly_importer.rb b/decidim-assemblies/app/serializers/decidim/assemblies/assembly_importer.rb index 9888e72a7fe1c..d91e21b0eeee3 100644 --- a/decidim-assemblies/app/serializers/decidim/assemblies/assembly_importer.rb +++ b/decidim-assemblies/app/serializers/decidim/assemblies/assembly_importer.rb @@ -108,7 +108,7 @@ def import_folders_and_attachments(attachments) attachments["files"].map do |file| next unless remote_file_exists?(file["remote_file_url"]) - file_tmp = URI.open(file["remote_file_url"]) + file_tmp = URI.parse(file["remote_file_url"]).open Decidim.traceability.perform_action!("create", Attachment, @user) do attachment = Attachment.new( diff --git a/decidim-assemblies/app/services/decidim/assemblies/assembly_search.rb b/decidim-assemblies/app/services/decidim/assemblies/assembly_search.rb deleted file mode 100644 index 514fefa6a5cdd..0000000000000 --- a/decidim-assemblies/app/services/decidim/assemblies/assembly_search.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -module Decidim - module Assemblies - # Service that encapsulates all logic related to filtering assemblies. - class AssemblySearch < ParticipatorySpaceSearch - def initialize(options = {}) - super(Assembly.all, options) - end - - def search_type_id - return query if type_id.blank? - - query.where(decidim_assemblies_type_id: type_id) - end - end - end -end diff --git a/decidim-assemblies/app/views/decidim/assemblies/_filter_by_type.html.erb b/decidim-assemblies/app/views/decidim/assemblies/_filter_by_type.html.erb index 7047c06299738..2c11820ca79b1 100644 --- a/decidim-assemblies/app/views/decidim/assemblies/_filter_by_type.html.erb +++ b/decidim-assemblies/app/views/decidim/assemblies/_filter_by_type.html.erb @@ -1,5 +1,5 @@
- <% if available_filters.any? %> + <% if available_filters.present? %> -<%= javascript_pack_tag "decidim_assemblies" %> +<% content_for :js_content do %> + <%= javascript_pack_tag "decidim_assemblies" %> +<% end %> diff --git a/decidim-assemblies/config/locales/ar.yml b/decidim-assemblies/config/locales/ar.yml index abc21eea8fb43..e730c6f429fbb 100644 --- a/decidim-assemblies/config/locales/ar.yml +++ b/decidim-assemblies/config/locales/ar.yml @@ -1,3 +1,4 @@ +--- ar: activemodel: attributes: @@ -252,7 +253,6 @@ ar: duration_help: إذا كانت مدة هذه الجمعية محدودة ØŒ Ùحدد تاريخ الانتهاء. خلا٠ذلك ØŒ سو٠يظهر على أنه غير مسمى. filters: مرشحات images: الصور - included_at_help: حدد التاريخ الذي تمت Ùيه إضاÙØ© هذه الجمعية إلى Decidim. ليس بالضرورة أن يكون هو Ù†Ùسه تاريخ الإنشاء. metadata: البيانات الوصÙية other: آخر select_a_created_by: حدد تم إنشاؤها بواسطة diff --git a/decidim-assemblies/config/locales/bg.yml b/decidim-assemblies/config/locales/bg.yml index f9a37bd8c4203..6958f690a4b80 100644 --- a/decidim-assemblies/config/locales/bg.yml +++ b/decidim-assemblies/config/locales/bg.yml @@ -1,3 +1,4 @@ +--- bg: activemodel: attributes: diff --git a/decidim-assemblies/config/locales/ca.yml b/decidim-assemblies/config/locales/ca.yml index 76bf43086277b..f988e5452eeb2 100644 --- a/decidim-assemblies/config/locales/ca.yml +++ b/decidim-assemblies/config/locales/ca.yml @@ -1,9 +1,13 @@ +--- ca: activemodel: attributes: assemblies_setting: enable_organization_chart: Habilitar organigrama + assemblies_type: + title: Títol assembly: + announcement: Avís area_id: Àrea assembly_type: Tipus d'assemblea assembly_type_other: Altre tipus d'assemblea @@ -22,12 +26,16 @@ ca: decidim_scope_id: Àmbit description: Descripció developer_group: Grup promotor + document: Document domain: Domini duration: Durada facebook: Facebook github: GitHub hashtag: Hashtag hero_image: Imatge de portada + import_attachments: Importar arxius adjunts + import_categories: Importar categories + import_components: Importar components included_at: Inclòs a instagram: Instagram internal_organisation: Organització interna @@ -64,6 +72,7 @@ ca: non_user_avatar: Avatar position: Posició user_id: Participant o grup + weight: Ordre de posició assembly_user_role: email: Correu electrònic name: Nom @@ -73,7 +82,7 @@ ca: assembly: attributes: document: - invalid_document_type: 'Tipus de document invàlid. Els formats que s''accepten són: %{valid_mime_types}' + allowed_file_content_types: 'Tipus de document no vàlid. Només s''accepten arxius amb les següents extensions: %{types}' activerecord: models: decidim/assembly: @@ -242,6 +251,9 @@ ca: admin_log: assembly: create: "%{user_name} ha creat l'assemblea %{resource_name}" + duplicate: "%{user_name} ha duplicat la assemblea %{resource_name}" + export: "%{user_name} ha exportat l'assemblea %{resource_name}" + import: "%{user_name} ha importat l'assemblea %{resource_name}" publish: "%{user_name} ha publicat l'assemblea %{resource_name}" unpublish: "%{user_name} ha despublicat l'assemblea %{resource_name}" update: "%{user_name} ha actualitzat l'assemblea %{resource_name}" @@ -270,7 +282,7 @@ ca: duration_help: Si la durada d'aquesta assemblea és limitada, selecciona la data de finalització. En cas contrari, apareixerà com a indefinida. filters: Filtres images: Imatges - included_at_help: Selecciona la data en què es va afegir aquest assemblea a Decidim. No necessàriament ha de ser la mateixa que la data de creació. + included_at_help: Selecciona la data en què es va afegir aquesta assemblea a la plataforma. No necessàriament ha de ser la mateixa que la data de creació. metadata: Metadades other: Altre select_a_created_by: Selecciona una creadora diff --git a/decidim-assemblies/config/locales/cs.yml b/decidim-assemblies/config/locales/cs.yml index 22b8a62185956..f92908813e1d1 100644 --- a/decidim-assemblies/config/locales/cs.yml +++ b/decidim-assemblies/config/locales/cs.yml @@ -1,9 +1,13 @@ +--- cs: activemodel: attributes: assemblies_setting: enable_organization_chart: Povolit schéma organizace + assemblies_type: + title: Název assembly: + announcement: Oznámení area_id: Oblast assembly_type: Typ shromáždÄ›ní assembly_type_other: Typ shromáždÄ›ní ostatní @@ -22,12 +26,16 @@ cs: decidim_scope_id: Oblast působnosti description: Popis developer_group: Skupina promotérů + document: Dokument domain: Doména duration: Doba trvání facebook: Facebook github: GitHub hashtag: Hashtag hero_image: Obrázek na hlavní stránce + import_attachments: Importovat přílohy + import_categories: Importovat kategorie + import_components: Importovat komponenty included_at: Zahrnuty v instagram: Instagram internal_organisation: VnitÅ™ní organizace @@ -64,6 +72,7 @@ cs: non_user_avatar: Avatar position: Pozice user_id: Uživatel + weight: Pozice v Å™azení assembly_user_role: email: E-mail name: Název @@ -73,7 +82,7 @@ cs: assembly: attributes: document: - invalid_document_type: 'Neplatný typ dokumentu. PÅ™ijatelné formáty jsou: %{valid_mime_types}' + allowed_file_content_types: 'Neplatný typ dokumentu. Jsou povoleny pouze soubory s následujícími příponami: %{types}' activerecord: models: decidim/assembly: @@ -248,6 +257,9 @@ cs: admin_log: assembly: create: "%{user_name} vytvoÅ™il %{resource_name} shromáždÄ›ní" + duplicate: "%{user_name} zkopíroval shromáždÄ›ní %{resource_name}" + export: "%{user_name} exportoval shromáždÄ›ní %{resource_name}" + import: "%{user_name} importoval shromáždÄ›ní %{resource_name}" publish: "%{user_name} publikoval %{resource_name} shromáždÄ›ní" unpublish: "%{user_name} odebral %{resource_name} shromáždÄ›ní" update: "%{user_name} aktualizoval shromáždÄ›ní %{resource_name}" @@ -276,7 +288,7 @@ cs: duration_help: Pokud je doba trvání tohoto shromáždÄ›ní omezená, zvolte koneÄné datum, jinak se objeví jako neurÄitá. filters: Filtry images: Obrázky - included_at_help: Vyberte datum, kdy bylo toto shromáždÄ›ní pÅ™idáno do aplikace Decidim. Nemusí to být nutnÄ› stejné jako datum vytvoÅ™ení. + included_at_help: Vyberte datum, kdy byla tato sestava pÅ™idána na platformu. Nemusí být nutnÄ› stejné jako datum vytvoÅ™ení. metadata: Metadata other: Ostatní select_a_created_by: Vybrat vytvoÅ™eno od diff --git a/decidim-assemblies/config/locales/de.yml b/decidim-assemblies/config/locales/de.yml index fa185dc1b119e..a3293a297ee3f 100644 --- a/decidim-assemblies/config/locales/de.yml +++ b/decidim-assemblies/config/locales/de.yml @@ -1,3 +1,4 @@ +--- de: activemodel: attributes: @@ -52,7 +53,7 @@ de: target: Wer nimmt teil? title: Titel twitter: Twitter - weight: Bestellposition + weight: Reihenfolge youtube: Youtube assembly_member: birthday: Geburtstag @@ -64,6 +65,7 @@ de: non_user_avatar: Profilbild position: Position user_id: User + weight: Reihenfolge assembly_user_role: email: Email name: Name @@ -73,7 +75,7 @@ de: assembly: attributes: document: - invalid_document_type: 'Ungültiger Dokumenttyp. Zulässige Formate sind: %{valid_mime_types}' + allowed_file_content_types: 'Ungültiger Dokumententyp. Nur Dateien mit folgenden Erweiterungen sind erlaubt: %{types}' activerecord: models: decidim/assembly: @@ -242,6 +244,9 @@ de: admin_log: assembly: create: "%{user_name} hat das Gremium %{resource_name} erstellt" + duplicate: "%{user_name} hat das Gremium %{resource_name} aktualisiert" + export: "%{user_name} hat das Gremium %{resource_name} exportiert" + import: "%{user_name} hat das Gremium %{resource_name} importiert" publish: "%{user_name} hat das Gremium %{resource_name} veröffentlicht" unpublish: "%{user_name} hat das Gremium %{resource_name} auf \"unveröffentlicht\" gesetzt" update: "%{user_name} hat das Gremium %{resource_name} aktualisiert" @@ -270,7 +275,7 @@ de: duration_help: Wenn die Dauer dieser Assembly begrenzt ist, wählen Sie das Enddatum aus. Andernfalls wird es als unbestimmt angezeigt. filters: Filter images: Bilder - included_at_help: Wählen Sie das Datum aus, an dem diese Baugruppe zu Decidim hinzugefügt wurde. Es muss nicht unbedingt mit dem Erstellungsdatum identisch sein. + included_at_help: Wählen Sie das Datum aus, an dem dieses Gremium zu Decidim hinzugefügt wurde. Es muss nicht unbedingt mit dem Erstellungsdatum identisch sein. metadata: Metadaten other: Andere select_a_created_by: Wählen Sie eine erstellt von aus diff --git a/decidim-assemblies/config/locales/el.yml b/decidim-assemblies/config/locales/el.yml index 82b85c820f051..59514d115040b 100644 --- a/decidim-assemblies/config/locales/el.yml +++ b/decidim-assemblies/config/locales/el.yml @@ -1,3 +1,4 @@ +--- el: activemodel: attributes: @@ -67,12 +68,6 @@ el: email: Email name: Όνομα role: Ρόλος - errors: - models: - assembly: - attributes: - document: - invalid_document_type: 'Μη έγκυÏος Ï„Ïπος εγγÏάφου. Οι αποδεκτές μοÏφές είναι: %{valid_mime_types}' activerecord: models: decidim/assembly: @@ -266,7 +261,6 @@ el: duration_help: Εάν η διάÏκεια αυτής της συνέλευσης είναι πεÏιοÏισμένη, επιλέξτε την ημεÏομηνία λήξης. ΔιαφοÏετικά, θα εμφανίζεται ως απεÏιόÏιστη. filters: ΦίλτÏα images: Εικόνες - included_at_help: Επιλέξτε την ημεÏομηνία Ï€Ïοσθήκης αυτής της συνέλευσης στο Decidim. Δεν χÏειάζεται απαÏαίτητα να είναι ίδια με την ημεÏομηνία δημιουÏγίας. metadata: Μεταδεδομένα other: Άλλο select_a_created_by: Επιλέξτε «ΔημιουÏγήθηκε από» diff --git a/decidim-assemblies/config/locales/en.yml b/decidim-assemblies/config/locales/en.yml index b425f6d76c31b..4409e78b27a4e 100644 --- a/decidim-assemblies/config/locales/en.yml +++ b/decidim-assemblies/config/locales/en.yml @@ -4,7 +4,10 @@ en: attributes: assemblies_setting: enable_organization_chart: Enable organization chart + assemblies_type: + title: Title assembly: + announcement: Announcement area_id: Area assembly_type: Assembly type assembly_type_other: Assembly type other @@ -23,12 +26,16 @@ en: decidim_scope_id: Scope description: Description developer_group: Promoter group + document: Document domain: Domain duration: Duration facebook: Facebook github: GitHub hashtag: Hashtag hero_image: Home image + import_attachments: Import attachments + import_categories: Import categories + import_components: Import components included_at: Included at instagram: Instagram internal_organisation: Internal organisation @@ -65,6 +72,7 @@ en: non_user_avatar: Avatar position: Position user_id: User or group + weight: Order position assembly_user_role: email: Email name: Name @@ -74,7 +82,7 @@ en: assembly: attributes: document: - invalid_document_type: 'Invalid document type. Accepted formats are: %{valid_mime_types}' + allowed_file_content_types: 'Invalid document type. Only files with the following extensions are allowed: %{types}' activerecord: models: decidim/assembly: @@ -243,6 +251,9 @@ en: admin_log: assembly: create: "%{user_name} created the %{resource_name} assembly" + duplicate: "%{user_name} duplicated the %{resource_name} assembly" + export: "%{user_name} exported the %{resource_name} assembly" + import: "%{user_name} imported the %{resource_name} assembly" publish: "%{user_name} published the %{resource_name} assembly" unpublish: "%{user_name} unpublished the %{resource_name} assembly" update: "%{user_name} updated the %{resource_name} assembly" @@ -271,7 +282,7 @@ en: duration_help: If the duration of this assembly is limited, select the end date. Otherwise, it will appear as indefinite. filters: Filters images: Images - included_at_help: Select the date when this assembly was added to Decidim. It does not necessarily have to be the same as the creation date. + included_at_help: Select the date when this assembly was added to the platform. It does not necessarily have to be the same as the creation date. metadata: Metadata other: Other select_a_created_by: Select a created by diff --git a/decidim-assemblies/config/locales/es-MX.yml b/decidim-assemblies/config/locales/es-MX.yml index dd85c3865f6b8..dfb5f4cf68fb9 100644 --- a/decidim-assemblies/config/locales/es-MX.yml +++ b/decidim-assemblies/config/locales/es-MX.yml @@ -1,9 +1,13 @@ +--- es-MX: activemodel: attributes: assemblies_setting: enable_organization_chart: Habilitar organigrama + assemblies_type: + title: Título assembly: + announcement: Aviso area_id: Ãrea assembly_type: Tipo de montaje assembly_type_other: Tipo de montaje otro @@ -22,12 +26,16 @@ es-MX: decidim_scope_id: Ãmbito description: Descripción developer_group: Grupo promotor + document: Documento domain: Dominio duration: Duración facebook: Facebook github: GitHub hashtag: Hashtag hero_image: Imagen de portada + import_attachments: Importar archivos adjuntos + import_categories: Importar categorias + import_components: Importar componentes included_at: Incluido en instagram: Instagram internal_organisation: Organización interna @@ -64,6 +72,7 @@ es-MX: non_user_avatar: Avatar position: Posición user_id: Usuaria + weight: Orden de posición assembly_user_role: email: Correo electrónico name: Nombre @@ -73,7 +82,7 @@ es-MX: assembly: attributes: document: - invalid_document_type: 'Tipo de documento invalido. Los formatos que se aceptan son: %{valid_mime_types}' + allowed_file_content_types: 'Tipo de documento no válido. Sólo se permiten archivos con las siguientes extensiones: %{types}' activerecord: models: decidim/assembly: @@ -242,6 +251,9 @@ es-MX: admin_log: assembly: create: "%{user_name} creó la asamblea %{resource_name}" + duplicate: "%{user_name} duplicó la asamblea %{resource_name}" + export: "%{user_name} exportó la asamblea %{resource_name}" + import: "%{user_name} importó la asamblea %{resource_name}" publish: "%{user_name} publicó la asamblea %{resource_name}" unpublish: "%{user_name} despublicó la asamblea %{resource_name}" update: "%{user_name} actualizó la asamblea %{resource_name}" @@ -270,7 +282,7 @@ es-MX: duration_help: Si la duración de esta asamblea es limitada, selecciona la fecha de finalización. De lo contrario, aparecerá como indefinida. filters: Filtros images: Imágenes - included_at_help: Selecciona la fecha en que se agregó este ensamblaje a Decidim. No necesariamente tiene que ser la misma que la fecha de creación. + included_at_help: Selecciona la fecha en la que se añadió esta asamblea a la plataforma. No es necesario que sea la misma que la fecha de creación. metadata: Metadatos other: Otro select_a_created_by: Selecciona creada por diff --git a/decidim-assemblies/config/locales/es-PY.yml b/decidim-assemblies/config/locales/es-PY.yml index 7956cb840c527..83b00be5e457f 100644 --- a/decidim-assemblies/config/locales/es-PY.yml +++ b/decidim-assemblies/config/locales/es-PY.yml @@ -1,9 +1,13 @@ +--- es-PY: activemodel: attributes: assemblies_setting: enable_organization_chart: Habilitar organigrama + assemblies_type: + title: Título assembly: + announcement: Aviso area_id: Ãrea assembly_type: Tipo de montaje assembly_type_other: Tipo de montaje otro @@ -22,12 +26,16 @@ es-PY: decidim_scope_id: Ãmbito description: Descripción developer_group: Grupo promotor + document: Documento domain: Dominio duration: Duración facebook: Facebook github: GitHub hashtag: Hashtag hero_image: Imagen de portada + import_attachments: Importar archivos adjuntos + import_categories: Importar categorias + import_components: Importar componentes included_at: Incluido en instagram: Instagram internal_organisation: Organización interna @@ -64,6 +72,7 @@ es-PY: non_user_avatar: Avatar position: Posición user_id: Usuaria + weight: Orden de posición assembly_user_role: email: Correo electrónico name: Nombre @@ -73,7 +82,7 @@ es-PY: assembly: attributes: document: - invalid_document_type: 'Tipo de documento invalido. Los formatos que se aceptan son: %{valid_mime_types}' + allowed_file_content_types: 'Tipo de documento no válido. Sólo se permiten archivos con las siguientes extensiones: %{types}' activerecord: models: decidim/assembly: @@ -242,6 +251,9 @@ es-PY: admin_log: assembly: create: "%{user_name} creó la asamblea %{resource_name}" + duplicate: "%{user_name} ha duplicado la asamblea %{resource_name}" + export: "%{user_name} ha exportado la asamblea %{resource_name}" + import: "%{user_name} ha importado la asamblea %{resource_name}" publish: "%{user_name} publicó la asamblea %{resource_name}" unpublish: "%{user_name} despublicó la asamblea %{resource_name}" update: "%{user_name} actualizó la asamblea %{resource_name}" @@ -270,7 +282,7 @@ es-PY: duration_help: Si la duración de esta asamblea es limitada, selecciona la fecha de finalización. De lo contrario, aparecerá como indefinida. filters: Filtros images: Imágenes - included_at_help: Selecciona la fecha en que se agregó este ensamblaje a Decidim. No necesariamente tiene que ser la misma que la fecha de creación. + included_at_help: Selecciona la fecha en la que se añadió esta asamblea a la plataforma. No necesariamente tiene que ser la misma que la fecha de creación. metadata: Metadatos other: Otro select_a_created_by: Selecciona creada por diff --git a/decidim-assemblies/config/locales/es.yml b/decidim-assemblies/config/locales/es.yml index 0c60b05c9e2a7..eed5a58fbe5e8 100644 --- a/decidim-assemblies/config/locales/es.yml +++ b/decidim-assemblies/config/locales/es.yml @@ -1,9 +1,13 @@ +--- es: activemodel: attributes: assemblies_setting: enable_organization_chart: Habilitar organigrama + assemblies_type: + title: Título assembly: + announcement: Aviso area_id: Ãrea assembly_type: Tipo de asamblea assembly_type_other: Otro tipo de asamblea @@ -22,12 +26,16 @@ es: decidim_scope_id: Ãmbito description: Descripción developer_group: Grupo promotor + document: Documento domain: Dominio duration: Duración facebook: Facebook github: GitHub hashtag: Hashtag hero_image: Imagen de portada + import_attachments: Importar archivos adjuntos + import_categories: Importar categorias + import_components: Importar componentes included_at: Incluido en instagram: Instagram internal_organisation: Organización interna @@ -64,6 +72,7 @@ es: non_user_avatar: Avatar position: Posición user_id: Participante o grupo + weight: Orden de posición assembly_user_role: email: Correo electrónico name: Nombre @@ -73,7 +82,7 @@ es: assembly: attributes: document: - invalid_document_type: 'Tipo de documento inválido. Los formatos que se aceptan son: %{valid_mime_types}' + allowed_file_content_types: 'Tipo de documento no válido. Sólo se permiten archivos con las siguientes extensiones: %{types}' activerecord: models: decidim/assembly: @@ -242,6 +251,9 @@ es: admin_log: assembly: create: "%{user_name} creó la asamblea %{resource_name}" + duplicate: "%{user_name} ha duplicado la asamblea %{resource_name}" + export: "%{user_name} ha exportado la asamblea %{resource_name}" + import: "%{user_name} ha importado la asamblea %{resource_name}" publish: "%{user_name} publicó la asamblea %{resource_name}" unpublish: "%{user_name} despublicó la asamblea %{resource_name}" update: "%{user_name} actualizó la asamblea %{resource_name}" @@ -270,7 +282,7 @@ es: duration_help: Si la duración de esta asamblea es limitada, selecciona la fecha de finalización. De lo contrario, aparecerá como indefinida. filters: Filtros images: Imágenes - included_at_help: Selecciona la fecha en que se agregó esta asamblea a Decidim. No necesariamente tiene que ser la misma que la fecha de creación. + included_at_help: Selecciona la fecha en la que se añadió esta asamblea a la plataforma. No necesariamente tiene que ser la misma que la fecha de creación. metadata: Metadatos other: Otro select_a_created_by: Selecciona una creadora diff --git a/decidim-assemblies/config/locales/eu.yml b/decidim-assemblies/config/locales/eu.yml index 4cbaaea08fdf6..4388199537d3f 100644 --- a/decidim-assemblies/config/locales/eu.yml +++ b/decidim-assemblies/config/locales/eu.yml @@ -1,11 +1,12 @@ +--- eu: activemodel: attributes: assemblies_setting: enable_organization_chart: Gaitu organigrama assembly: - area_id: Area - assembly_type: Muntatze-mota + area_id: Arloa + assembly_type: Batzar mota assembly_type_other: Batzar mota beste banner_image: Bannerra closing_date: Amaiera data @@ -22,6 +23,7 @@ eu: decidim_scope_id: esparrua description: Deskribapena developer_group: Sustatzailearen taldea + document: Dokumentua domain: Domeinua duration: Iraupena facebook: Facebook @@ -66,18 +68,18 @@ eu: user_id: Parte-hartzailea edo taldea assembly_user_role: email: Emaila - name: izena + name: Izena role: Role errors: models: assembly: attributes: document: - invalid_document_type: 'Dokumentu-mota baliogabea da. Formatu hauek onartzen dira: %{valid_mime_types}' + allowed_file_content_types: 'Dokumentu mota hau ez da onartzen. Honako hauek onartzen dira: %{types}' activerecord: models: decidim/assembly: - one: Batzar + one: Batzarra other: Batzar decidim/assembly_member: one: Batzar kidea @@ -149,12 +151,12 @@ eu: success: Kidea muntaia honekin batera ezabatu da. edit: title: Eguneratu muntaia kidea. - update: eguneratzearen + update: Eguneratu index: - assembly_members_title: Batzar kideak + assembly_members_title: Batzarraen kideak new: create: Sortu - title: Batzar berria kide. + title: Batzarkide berria. update: error: Errore bat gertatu da kidea bistaratzeko muntaia honetarako. success: Batzar hau behar bezala eguneratu da. @@ -173,7 +175,7 @@ eu: success: Erabiltzailea behar bezala kendu da muntaia honetatik. edit: title: Eguneratu muntaia erabiltzailea. - update: eguneratzearen + update: Eguneratu index: assembly_admins_title: Batzar erabiltzaileak new: @@ -217,22 +219,22 @@ eu: fields: ceased_date: Data amaitua designation_date: Deuseztapen data - full_name: izena + full_name: Izena position: Kargua name: kidea positions: other: Beste president: Lehendakaria - secretary: idazkari + secretary: Idazkaritza vice_president: Lehendakariordea assembly_user_role: fields: - email: Emaila - name: izena - role: Role + email: Helbide elektronikoa + name: Izena + role: Rola name: Batzar Erabiltzailea roles: - admin: Administrator + admin: Administratzailea collaborator: Kolaboratzaile moderator: Moderatzaile valuator: Ebaluatzailea @@ -270,7 +272,6 @@ eu: duration_help: Muntaia honen iraupena mugatua bada, hautatu amaiera-data. Bestela, mugagabea izango da. filters: iragazkiak images: Irudiak - included_at_help: Hautatu muntaia hau Decidim-era gehitu denean. Ez du derrigorrez sorkuntzako data izan behar. metadata: Metadata other: Beste select_a_created_by: Aukeratu egilea by egilea diff --git a/decidim-assemblies/config/locales/fi-plain.yml b/decidim-assemblies/config/locales/fi-plain.yml index 0b3ec44020de0..8f49e02d1e552 100644 --- a/decidim-assemblies/config/locales/fi-plain.yml +++ b/decidim-assemblies/config/locales/fi-plain.yml @@ -1,9 +1,13 @@ +--- fi-pl: activemodel: attributes: assemblies_setting: enable_organization_chart: Ota organisaatiokaavio käyttöön + assemblies_type: + title: Otsikko assembly: + announcement: Ilmoitus area_id: Alue assembly_type: Ryhmän tyyppi assembly_type_other: Muu ryhmän tyyppi @@ -22,12 +26,16 @@ fi-pl: decidim_scope_id: Teema description: Kuvaus developer_group: Perustajaryhmä + document: Asiakirja domain: Toimintaympäristö duration: Kesto facebook: Facebook github: GitHub hashtag: Aihetunniste (hashtag) hero_image: Etusivun kuva + import_attachments: Tuo liitteitä + import_categories: Tuo aihepiirejä + import_components: Tuo komponentteja included_at: Mukana osoitteessa instagram: Instagram internal_organisation: Sisäinen organisaatio @@ -64,6 +72,7 @@ fi-pl: non_user_avatar: Avatar position: Asema user_id: Käyttäjä tai ryhmä + weight: Järjestysnumero assembly_user_role: email: Sähköposti name: Nimi @@ -73,7 +82,7 @@ fi-pl: assembly: attributes: document: - invalid_document_type: 'Virheellinen asiakirjan muoto. Hyväksytyt tiedostomuodot ovat: %{valid_mime_types}' + allowed_file_content_types: 'Virheellinen tiedostomuoto. Ainoastaan seuraavat tiedostomuodot on sallittu: %{types}' activerecord: models: decidim/assembly: @@ -242,6 +251,9 @@ fi-pl: admin_log: assembly: create: "%{user_name} loi %{resource_name} ryhmän" + duplicate: "%{user_name} kopioi ryhmän %{resource_name}" + export: "%{user_name} vei ryhmän %{resource_name}" + import: "%{user_name} toi ryhmän %{resource_name}" publish: "%{user_name} julkaisi %{resource_name} ryhmän" unpublish: "%{user_name} lopetti %{resource_name} ryhmän julkaisemisen" update: "%{user_name} päivitti %{resource_name} ryhmän" @@ -270,7 +282,7 @@ fi-pl: duration_help: Jos ryhmän kesto on rajoitettu, valitse päättymispäivä. Muussa tapauksessa se näkyy määrittelemättömänä. filters: Suodattimet images: kuvat - included_at_help: Valitse päivämäärä, jolloin ryhmä lisättiin Decidimiin. Sen ei välttämättä tarvitse olla sama kuin luomispäivä. + included_at_help: Valitse päivämäärä, jolloin tämä ryhmä lisättiin alustalle. Sen ei välttämättä tarvitse olla sama kuin luontipäivä. metadata: metadata other: muut select_a_created_by: Valitse luoja diff --git a/decidim-assemblies/config/locales/fi.yml b/decidim-assemblies/config/locales/fi.yml index 1a91c87c6517c..eba267336c278 100644 --- a/decidim-assemblies/config/locales/fi.yml +++ b/decidim-assemblies/config/locales/fi.yml @@ -1,9 +1,13 @@ +--- fi: activemodel: attributes: assemblies_setting: enable_organization_chart: Ota organisaatiokaavio käyttöön + assemblies_type: + title: Otsikko assembly: + announcement: Ilmoitus area_id: Alue assembly_type: Ryhmän tyyppi assembly_type_other: Muu ryhmän tyyppi @@ -22,12 +26,16 @@ fi: decidim_scope_id: Teema description: Kuvaus developer_group: Edistäjäryhmä + document: Asiakirja domain: Toimintaympäristö duration: Kesto facebook: Facebook github: GitHub hashtag: Aihetunniste (hashtag) hero_image: Etusivun kuva + import_attachments: Tuo liitteitä + import_categories: Tuo aihepiirejä + import_components: Tuo komponentteja included_at: Lisäysaika instagram: Instagram internal_organisation: Sisäinen organisaatio @@ -64,6 +72,7 @@ fi: non_user_avatar: Avatar position: Asema user_id: Käyttäjä tai ryhmä + weight: Järjestysnumero assembly_user_role: email: Sähköposti name: Nimi @@ -73,7 +82,7 @@ fi: assembly: attributes: document: - invalid_document_type: 'Virheellinen asiakirjan muoto. Hyväksytyt tiedostomuodot ovat: %{valid_mime_types}' + allowed_file_content_types: 'Virheellinen tiedostomuoto. Ainoastaan seuraavat tiedostomuodot on sallittu: %{types}' activerecord: models: decidim/assembly: @@ -242,6 +251,9 @@ fi: admin_log: assembly: create: "%{user_name} loi %{resource_name} ryhmän" + duplicate: "%{user_name} kopioi ryhmän %{resource_name}" + export: "%{user_name} vei ryhmän %{resource_name}" + import: "%{user_name} toi ryhmän %{resource_name}" publish: "%{user_name} julkaisi %{resource_name} ryhmän" unpublish: "%{user_name} lopetti ryhmän %{resource_name} julkaisun" update: "%{user_name} päivitti %{resource_name} ryhmän" @@ -270,7 +282,7 @@ fi: duration_help: Jos ryhmän kesto on rajoitettu, valitse päättymispäivä. Muussa tapauksessa se näkyy määrittelemättömänä. filters: Suodattimet images: Kuvat - included_at_help: Valitse päivämäärä, jolloin ryhmä lisättiin Decidimiin. Sen ei välttämättä tarvitse olla sama kuin luomispäivä. + included_at_help: Valitse päivämäärä, jolloin tämä ryhmä lisättiin alustalle. Sen ei välttämättä tarvitse olla sama kuin luontipäivä. metadata: Metatiedot other: Muut select_a_created_by: Valitse luoja diff --git a/decidim-assemblies/config/locales/fr-CA.yml b/decidim-assemblies/config/locales/fr-CA.yml index 8fc9f31a618dc..01330f7b8073c 100644 --- a/decidim-assemblies/config/locales/fr-CA.yml +++ b/decidim-assemblies/config/locales/fr-CA.yml @@ -1,9 +1,13 @@ +--- fr-CA: activemodel: attributes: assemblies_setting: enable_organization_chart: Activer le schéma d'assemblée + assemblies_type: + title: Titre assembly: + announcement: Message d'annonce area_id: Zone d'application assembly_type: Type d'assemblée assembly_type_other: Autre type d'assemblée @@ -22,12 +26,16 @@ fr-CA: decidim_scope_id: Périmètre d'application description: Description developer_group: Organisateur + document: Document domain: Domaine duration: Durée facebook: Facebook github: GitHub hashtag: Mot-clic hero_image: Image de la page d'accueil + import_attachments: Importer les pièces jointes + import_categories: Importer les catégories + import_components: Importer les fonctionnalités included_at: Intégrée à cette plateforme le instagram: Instagram internal_organisation: Organisation interne @@ -64,6 +72,7 @@ fr-CA: non_user_avatar: Avatar position: Statut user_id: Utilisateur + weight: Rang d'affichage assembly_user_role: email: E-mail name: "Nom\n" @@ -73,7 +82,7 @@ fr-CA: assembly: attributes: document: - invalid_document_type: 'Type de document invalide. Les formats acceptés sont : %{valid_mime_types}' + allowed_file_content_types: 'Type de document invalide. Seuls les fichiers avec les extensions suivantes sont autorisés : %{types}' activerecord: models: decidim/assembly: @@ -242,6 +251,9 @@ fr-CA: admin_log: assembly: create: "%{user_name} a créé l'assemblée %{resource_name}" + duplicate: "%{user_name} a dupliqué l'assemblée %{resource_name}" + export: "%{user_name} a exporté l'assemblée %{resource_name}" + import: "%{user_name} a importé l'assemblée %{resource_name}" publish: "%{user_name} a publié l'assemblée %{resource_name}" unpublish: "%{user_name} a dépublié l'assemblée %{resource_name}" update: "%{user_name} a mis à jour l'assemblée %{resource_name}" @@ -270,7 +282,7 @@ fr-CA: duration_help: Si la durée de cette assemblée est limitée, sélectionnez la date de fin. Sinon sa durée ne sera pas limitée. filters: Filtres images: Images - included_at_help: Sélectionnez la date à laquelle cet assemblée a été ajoutée à Decidim. Elle ne doit pas nécessairement être identique à la date de création. + included_at_help: Sélectionnez la date à laquelle cet assemblée a été ajoutée à la plateforme. Elle ne doit pas nécessairement être identique à la date de création. metadata: Métadonnées other: Autre select_a_created_by: Sélectionnez un créateur diff --git a/decidim-assemblies/config/locales/fr.yml b/decidim-assemblies/config/locales/fr.yml index 29a8040041dd0..a89d350ecf079 100644 --- a/decidim-assemblies/config/locales/fr.yml +++ b/decidim-assemblies/config/locales/fr.yml @@ -1,9 +1,13 @@ +--- fr: activemodel: attributes: assemblies_setting: enable_organization_chart: Activer le schéma d'assemblée + assemblies_type: + title: Titre assembly: + announcement: Message d'annonce area_id: Périmètre d'assemblée assembly_type: Type d'assemblée assembly_type_other: Autre type d'assemblée @@ -22,12 +26,16 @@ fr: decidim_scope_id: Périmètre d'application description: Description developer_group: Organisateur + document: Document domain: Domaine duration: Durée facebook: Facebook github: GitHub hashtag: Hashtag hero_image: Image de la page d'accueil + import_attachments: Importer les pièces jointes + import_categories: Importer les catégories + import_components: Importer les fonctionnalités included_at: Intégrée à cette plateforme le instagram: Instagram internal_organisation: Organisation interne @@ -64,6 +72,7 @@ fr: non_user_avatar: Avatar position: Statut user_id: Utilisateur ou groupe + weight: Rang d'affichage assembly_user_role: email: E-mail name: "Nom\n" @@ -73,7 +82,7 @@ fr: assembly: attributes: document: - invalid_document_type: 'Type de document invalide. Les formats acceptés sont : %{valid_mime_types}' + allowed_file_content_types: 'Type de document invalide. Seuls les fichiers avec les extensions suivantes sont autorisés : %{types}' activerecord: models: decidim/assembly: @@ -242,6 +251,9 @@ fr: admin_log: assembly: create: "%{user_name} a créé l'assemblée %{resource_name}" + duplicate: "%{user_name} a dupliqué l'assemblée %{resource_name}" + export: "%{user_name} a exporté l'assemblée %{resource_name}" + import: "%{user_name} a importé l'assemblée %{resource_name}" publish: "%{user_name} a publié l'assemblée %{resource_name}" unpublish: "%{user_name} a dépublié l'assemblée %{resource_name}" update: "%{user_name} a mis à jour l'assemblée %{resource_name}" @@ -270,7 +282,7 @@ fr: duration_help: Si la durée de cette assemblée est limitée, sélectionnez la date de fin. Sinon sa durée ne sera pas limitée. filters: Filtres images: Images - included_at_help: Sélectionnez la date à laquelle cet assemblée a été ajoutée à Decidim. Elle ne doit pas nécessairement être identique à la date de création. + included_at_help: Sélectionnez la date à laquelle cet assemblée a été ajoutée à la plateforme. Elle ne doit pas nécessairement être identique à la date de création. metadata: Métadonnées other: Autre select_a_created_by: Sélectionnez un créateur diff --git a/decidim-assemblies/config/locales/ga-IE.yml b/decidim-assemblies/config/locales/ga-IE.yml index 30e641f9e2e44..cc406a8bcf827 100644 --- a/decidim-assemblies/config/locales/ga-IE.yml +++ b/decidim-assemblies/config/locales/ga-IE.yml @@ -1,3 +1,4 @@ +--- ga: activemodel: attributes: diff --git a/decidim-assemblies/config/locales/gl.yml b/decidim-assemblies/config/locales/gl.yml index aa3a0c276138b..dce0f67eac78f 100644 --- a/decidim-assemblies/config/locales/gl.yml +++ b/decidim-assemblies/config/locales/gl.yml @@ -1,3 +1,4 @@ +--- gl: activemodel: attributes: @@ -68,12 +69,6 @@ gl: email: Correo electrónico name: Nome role: Rol - errors: - models: - assembly: - attributes: - document: - invalid_document_type: 'Tipo de documento non válido. Formatos aceptados: %{valid_mime_types}' activerecord: models: decidim/assembly: @@ -270,7 +265,7 @@ gl: duration_help: Se a duración deste conxunto é limitada, seleccione a data de finalización. Se non, aparecerá como indefinido. filters: Filtros images: Imaxes - included_at_help: Seleccione a data en que se engadiu este conxunto a Decidim. Non ten que ser necesariamente o mesmo que a data de creación. + included_at_help: Selecciona a data na que engadiches esta xuntanza á plataforma. Non ten por que ser a mesma que a data de creación. metadata: Metadatos other: Outra select_a_created_by: Seleccione un creado por diff --git a/decidim-assemblies/config/locales/hu.yml b/decidim-assemblies/config/locales/hu.yml index fef28e86bacfc..152b952baf693 100644 --- a/decidim-assemblies/config/locales/hu.yml +++ b/decidim-assemblies/config/locales/hu.yml @@ -1,3 +1,4 @@ +--- hu: activemodel: attributes: @@ -68,12 +69,6 @@ hu: email: Email name: Név role: Szerep - errors: - models: - assembly: - attributes: - document: - invalid_document_type: 'Nem megfelelÅ‘ dokument típus. Az elfogadott formátumok: %{valid_mime_types}' activerecord: models: decidim/assembly: @@ -242,6 +237,9 @@ hu: admin_log: assembly: create: "%{user_name} létrehozta a(z) %{resource_name} gyűlést" + duplicate: "%{user_name} duplikálta a(z) %{resource_name} gyűlést" + export: "%{user_name} exportálta a(z) %{resource_name} gyűlést" + import: "%{user_name} importálta a(z) %{resource_name} gyűlést" publish: "%{user_name} közzétette a(z) %{resource_name} gyűlést" unpublish: "%{user_name} visszavonta a(z) %{resource_name} gyűlés közzétételét" update: "%{user_name} frissítette a(z) %{resource_name} gyűlést" @@ -270,7 +268,7 @@ hu: duration_help: Ha a gyűlés idÅ‘tartama korlátozott, válassz befejezÅ‘ dátumot. EllenkezÅ‘ esetben határozatlan idejű lesz. filters: SzűrÅ‘k images: képek - included_at_help: Válaszd ki a dátumot, amikor a gyűlést hozzáadtad a Decidimhez. Nem feltétlenül kell megegyeznie a létrehozás idÅ‘pontjával. + included_at_help: Válassza ki a dátumot, amikor ezt a gyűlést hozzáadták a platformhoz. Nem feltétlenül kell megegyeznie a létrehozás dátumával. metadata: Metaadatok other: Egyéb select_a_created_by: Válassz alapítót diff --git a/decidim-assemblies/config/locales/id-ID.yml b/decidim-assemblies/config/locales/id-ID.yml index 57effaaadc116..43712c8facdc7 100644 --- a/decidim-assemblies/config/locales/id-ID.yml +++ b/decidim-assemblies/config/locales/id-ID.yml @@ -1,3 +1,4 @@ +--- id: activemodel: attributes: @@ -217,7 +218,6 @@ id: duration_help: Jika durasi rakitan ini terbatas, pilih tanggal akhir. Jika tidak, itu akan muncul sebagai tidak terbatas. filters: Filter images: Gambar - included_at_help: Pilih tanggal saat perakitan ini ditambahkan ke Decidim. Tidak harus sama dengan tanggal pembuatan. metadata: Metadata other: Lain select_a_created_by: Pilih yang dibuat oleh diff --git a/decidim-assemblies/config/locales/is-IS.yml b/decidim-assemblies/config/locales/is-IS.yml index b722738cb8ca5..9dca6285d14b7 100644 --- a/decidim-assemblies/config/locales/is-IS.yml +++ b/decidim-assemblies/config/locales/is-IS.yml @@ -1,4 +1,5 @@ -is-IS: +--- +is: activemodel: attributes: assembly: diff --git a/decidim-assemblies/config/locales/it.yml b/decidim-assemblies/config/locales/it.yml index afcd4d06464a5..2fd7d5494cf54 100644 --- a/decidim-assemblies/config/locales/it.yml +++ b/decidim-assemblies/config/locales/it.yml @@ -1,3 +1,4 @@ +--- it: activemodel: attributes: @@ -68,12 +69,6 @@ it: email: E-mail name: Nome role: Ruolo - errors: - models: - assembly: - attributes: - document: - invalid_document_type: 'Tipo di documento non valido. I formati accettati sono: %{valid_mime_types}' activerecord: models: decidim/assembly: @@ -270,7 +265,6 @@ it: duration_help: Se la durata di questa assemblea è limitata, selezionare la data di fine. Altrimenti, apparirà come indefinita. filters: Filtri images: Immagini - included_at_help: Seleziona la data in cui questa assemblea è stata aggiunto a Decidim. Non deve necessariamente essere uguale alla data di creazione. metadata: Metadati other: Altro select_a_created_by: Seleziona un creatore diff --git a/decidim-assemblies/config/locales/ja.yml b/decidim-assemblies/config/locales/ja.yml index f5555d0a12730..5040f961bb91b 100644 --- a/decidim-assemblies/config/locales/ja.yml +++ b/decidim-assemblies/config/locales/ja.yml @@ -1,9 +1,13 @@ +--- ja: activemodel: attributes: assemblies_setting: enable_organization_chart: 組織図を有効化 + assemblies_type: + title: タイトル assembly: + announcement: ãŠçŸ¥ã‚‰ã› area_id: エリア assembly_type: å‚加スペース種別 assembly_type_other: ãã®ä»–(å‚加スペース) @@ -22,12 +26,16 @@ ja: decidim_scope_id: スコープ description: 説明 developer_group: プロモーターグループ + document: ドキュメント domain: ドメイン duration: æŒç¶šæœŸé–“ facebook: Facebook github: GitHub hashtag: ãƒãƒƒã‚·ãƒ¥ã‚¿ã‚° hero_image: ãƒ›ãƒ¼ãƒ ç”»åƒ + import_attachments: 添付ファイルをインãƒãƒ¼ãƒˆ + import_categories: カテゴリをインãƒãƒ¼ãƒˆ + import_components: コンãƒãƒ¼ãƒãƒ³ãƒˆã‚’インãƒãƒ¼ãƒˆ included_at: å«ã¾ã‚ŒãŸæ—¥ instagram: Instagram internal_organisation: 内部組織 @@ -64,6 +72,7 @@ ja: non_user_avatar: ã‚¢ãƒã‚¿ãƒ¼ position: ãƒã‚¸ã‚·ãƒ§ãƒ³ user_id: ユーザー + weight: 並ã³é †ã®ä½ç½® assembly_user_role: email: Eメールアドレス name: åå‰ @@ -73,7 +82,7 @@ ja: assembly: attributes: document: - invalid_document_type: '無効ãªãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã®ç¨®é¡žã§ã™ã€‚承èªã•ã‚ŒãŸãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã¯æ¬¡ã®ã¨ãŠã‚Šã§ã™: %{valid_mime_types}' + allowed_file_content_types: '無効ãªãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚¿ã‚¤ãƒ—ã§ã™ã€‚次ã®æ‹¡å¼µå­ã‚’æŒã¤ãƒ•ã‚¡ã‚¤ãƒ«ã®ã¿è¨±å¯ã•ã‚Œã¾ã™: %{types}' activerecord: models: decidim/assembly: @@ -239,6 +248,9 @@ ja: admin_log: assembly: create: "%{user_name} ㌠%{resource_name} å‚加スペースを作æˆã—ã¾ã—ãŸ" + duplicate: "%{user_name} ㌠%{resource_name} å‚加スペースを複製ã—ã¾ã—ãŸ" + export: "%{user_name} 㯠%{resource_name} å‚加スペースをエクスãƒãƒ¼ãƒˆã—ã¾ã—ãŸ" + import: "%{user_name} ㌠%{resource_name} å‚加スペースをインãƒãƒ¼ãƒˆã—ã¾ã—ãŸ" publish: "%{user_name} ㌠%{resource_name} å‚加スペースを公開ã—ã¾ã—ãŸ" unpublish: "%{user_name} ㌠%{resource_name} å‚加スペースをéžå…¬é–‹ã«ã—ã¾ã—ãŸ" update: "%{user_name} ㌠%{resource_name} å‚加スペースを更新ã—ã¾ã—ãŸ" @@ -267,7 +279,7 @@ ja: duration_help: ã“ã®å‚加スペースã®æŒç¶šæ™‚é–“ãŒé™ã‚‰ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€çµ‚了日をé¸æŠžã—ã¾ã™ã€‚ãれ以外ã®å ´åˆã¯ã€ä¸å®šç¾©ã¨ã—ã¦è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ filters: フィルタ images: ç”»åƒ - included_at_help: ã“ã®å‚加スペースãŒDecidimã«è¿½åŠ ã•ã‚ŒãŸæ—¥ä»˜ã‚’é¸æŠžã—ã¾ã™ã€‚å¿…ãšã—も作æˆæ—¥ã¨åŒã˜ã§ã‚ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。 + included_at_help: ã“ã®å‚加スペースãŒãƒ—ラットフォームã«è¿½åŠ ã•ã‚ŒãŸæ—¥ä»˜ã‚’é¸æŠžã—ã¾ã™ã€‚å¿…ãšã—も作æˆæ—¥ã¨åŒã˜ã§ã‚ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“。 metadata: メタデータ other: ãã®ä»– select_a_created_by: 作æˆè€…ã‚’é¸æŠžã—ã¦ãã ã•ã„ diff --git a/decidim-assemblies/config/locales/ka-GE.yml b/decidim-assemblies/config/locales/ka-GE.yml new file mode 100644 index 0000000000000..57a95cb04703c --- /dev/null +++ b/decidim-assemblies/config/locales/ka-GE.yml @@ -0,0 +1 @@ +ka: diff --git a/decidim-assemblies/config/locales/lb.yml b/decidim-assemblies/config/locales/lb.yml index 7a4acce00badb..35f1f81bd6a24 100644 --- a/decidim-assemblies/config/locales/lb.yml +++ b/decidim-assemblies/config/locales/lb.yml @@ -1,3 +1,4 @@ +--- lb: activemodel: attributes: @@ -68,12 +69,6 @@ lb: email: Email name: Name role: Rolle - errors: - models: - assembly: - attributes: - document: - invalid_document_type: 'Ungültiger Dokumenttyp. Zulässige Formate sind: %{valid_mime_types}' activerecord: models: decidim/assembly: diff --git a/decidim-assemblies/config/locales/lt.yml b/decidim-assemblies/config/locales/lt.yml index c4381fce95fbb..ed3d90cd49199 100644 --- a/decidim-assemblies/config/locales/lt.yml +++ b/decidim-assemblies/config/locales/lt.yml @@ -1,3 +1,4 @@ +--- lt: activemodel: attributes: @@ -68,12 +69,6 @@ lt: email: El. paÅ¡tas name: Vardas role: RolÄ— - errors: - models: - assembly: - attributes: - document: - invalid_document_type: 'Netinkamas dokumento tipas. Priimtini formatai: %{valid_mime_types}' activerecord: models: decidim/assembly: @@ -248,6 +243,9 @@ lt: admin_log: assembly: create: "%{user_name} sukÅ«rÄ— %{resource_name} asamblÄ—jÄ…" + duplicate: "%{user_name} dublikavo %{resource_name} asamblÄ—jÄ…" + export: "%{user_name} eksportavo %{resource_name} asamblÄ—jÄ…" + import: "%{user_name} importavo %{resource_name} asamblÄ—jÄ…" publish: "%{user_name} publikavo %{resource_name} asamblÄ—jÄ…" unpublish: "%{user_name} depublikavo %{resource_name} asamblÄ—jÄ…" update: "%{user_name} atnaujino %{resource_name} asamblÄ—jÄ…" @@ -276,7 +274,7 @@ lt: duration_help: Jei Å¡ios asamblÄ—jos veiklos trukmÄ— ribota, pasirinkite pabaigos datÄ…. PrieÅ¡ingu atveju bus rodoma, kad ji neterminuota. filters: Filtrai images: Vaizdai - included_at_help: Pasirinkite datÄ…, kada Å¡i asamblÄ—ja buvo įtraukta į „Decidim“. Å i data nebÅ«tinai turi sutapti su sukÅ«rimo data. + included_at_help: Pasirinkite datÄ…, kada Å¡i asamblÄ—ja buvo įtraukta į „Decidim“ platformÄ…. Å i data nebÅ«tinai turi sutapti su sukÅ«rimo data. metadata: Metaduomenys other: Kita select_a_created_by: Pasirinkti pagal kÅ«rÄ—jÄ… diff --git a/decidim-assemblies/config/locales/lv.yml b/decidim-assemblies/config/locales/lv.yml index d5d4407c2ac0b..c0b1048c6b5f9 100644 --- a/decidim-assemblies/config/locales/lv.yml +++ b/decidim-assemblies/config/locales/lv.yml @@ -1,3 +1,4 @@ +--- lv: activemodel: attributes: @@ -243,7 +244,6 @@ lv: duration_help: Ja Å¡Ä«s asamblejas ilgums ir ierobežots, izvÄ“lieties beigu datumu. PretÄ“jÄ gadÄ«jumÄ tas parÄdÄ«sies kÄ nenoteikts filters: Filtri images: AttÄ“li - included_at_help: IzvÄ“lieties datumu, kad Å¡Ä« asambleja tika pievienota Decidim. Tam nav noteikti jÄbÅ«t tÄdam paÅ¡am kÄ izveides datumam. metadata: Metadati other: Cits select_a_created_by: IzvÄ“lieties izveidotÄju diff --git a/decidim-assemblies/config/locales/nl.yml b/decidim-assemblies/config/locales/nl.yml index f6d4dc02be292..f3265e133d35a 100644 --- a/decidim-assemblies/config/locales/nl.yml +++ b/decidim-assemblies/config/locales/nl.yml @@ -1,3 +1,4 @@ +--- nl: activemodel: attributes: @@ -68,12 +69,6 @@ nl: email: E-mail name: Naam role: Rol - errors: - models: - assembly: - attributes: - document: - invalid_document_type: 'Ongeldig documenttype. Geaccepteerde formaten zijn: %{valid_mime_types}' activerecord: models: decidim/assembly: @@ -242,6 +237,9 @@ nl: admin_log: assembly: create: "%{user_name} heeft de groep %{resource_name} gemaakt" + duplicate: "%{user_name} heeft de groep %{resource_name} gedupliceerd" + export: "%{user_name} heeft de groep %{resource_name} geëxporteerd" + import: "%{user_name} heeft de groep %{resource_name} geïmporteerd" publish: "%{user_name} heeft de %{resource_name} groep gepubliceerd" unpublish: "%{user_name} heeft de groep %{resource_name} gedepubliceerd" update: "%{user_name} heeft de groep %{resource_name} bijgewerkt" diff --git a/decidim-assemblies/config/locales/no.yml b/decidim-assemblies/config/locales/no.yml index ab6838498df9d..7bc4b79fd7127 100644 --- a/decidim-assemblies/config/locales/no.yml +++ b/decidim-assemblies/config/locales/no.yml @@ -1,3 +1,4 @@ +--- "no": activemodel: attributes: @@ -68,12 +69,6 @@ email: Epost name: Navn role: Rolle - errors: - models: - assembly: - attributes: - document: - invalid_document_type: 'Ugyldig dokumenttype. Godkjente formater er: %{valid_mime_types}' activerecord: models: decidim/assembly: @@ -270,7 +265,6 @@ duration_help: Hvis varigheten av denne forsamlingen er limitert, velg en sluttdato. Hvis ikke, vil den vises som ubestemt. filters: Filter images: Bilder - included_at_help: Velg datoen da denne forsamling ble lagt til Decidim. Dette trenger ikke nødvendigvis Ã¥ være det samme som opprettelsesdatoen. metadata: Metadata other: Annet select_a_created_by: Velg en opprettet av diff --git a/decidim-assemblies/config/locales/pl.yml b/decidim-assemblies/config/locales/pl.yml index 3dcf49ec9e8d1..2e8ca7e1b0549 100644 --- a/decidim-assemblies/config/locales/pl.yml +++ b/decidim-assemblies/config/locales/pl.yml @@ -1,9 +1,11 @@ +--- pl: activemodel: attributes: assemblies_setting: enable_organization_chart: WÅ‚Ä…cz wykres dla organizacji assembly: + announcement: Powiadomienie area_id: Kategoria assembly_type: Typ zespoÅ‚u assembly_type_other: Typ zespoÅ‚u inny @@ -73,7 +75,7 @@ pl: assembly: attributes: document: - invalid_document_type: 'NieprawidÅ‚owy typ dokumentu. Akceptowane formaty to: %{valid_mime_types}' + allowed_file_content_types: 'NieprawidÅ‚owy typ dokumentu. Dozwolone sÄ… tylko pliki z nastÄ™pujÄ…cymi rozszerzeniami: %{types}' activerecord: models: decidim/assembly: @@ -248,6 +250,9 @@ pl: admin_log: assembly: create: "%{user_name} utworzyÅ‚(a) zespół %{resource_name}" + duplicate: "%{user_name} zduplikowaÅ‚(a) zespół %{resource_name}" + export: "%{user_name} wyeksportowaÅ‚(a) zespół %{resource_name}" + import: "%{user_name} zaimportowaÅ‚(a) zespół %{resource_name}" publish: "%{user_name} upubliczniÅ‚(a) zespół %{resource_name}" unpublish: "%{user_name} anulowaÅ‚(a) publikacjÄ™ zespoÅ‚u %{resource_name}" update: "%{user_name} zaktualizowaÅ‚(a) zespół %{resource_name}" @@ -276,7 +281,6 @@ pl: duration_help: JeÅ›li czas trwania tego zespoÅ‚u jest ograniczony, wybierz datÄ™ koÅ„cowÄ…. W przeciwnym razie pojawi siÄ™ jako nieokreÅ›lony. filters: Filtry images: Obrazy - included_at_help: Wybierz datÄ™ dodania tego zespoÅ‚u do Decidim. To niekoniecznie musi być ta sama data co data utworzenia. metadata: Metadane other: Inny select_a_created_by: Wybierz utworzony przez diff --git a/decidim-assemblies/config/locales/pt-BR.yml b/decidim-assemblies/config/locales/pt-BR.yml index 8d3e6012c303f..966d023624d64 100644 --- a/decidim-assemblies/config/locales/pt-BR.yml +++ b/decidim-assemblies/config/locales/pt-BR.yml @@ -1,3 +1,4 @@ +--- pt-BR: activemodel: attributes: @@ -67,12 +68,6 @@ pt-BR: email: E-mail name: Nome role: Cargo - errors: - models: - assembly: - attributes: - document: - invalid_document_type: 'Tipo de documento inválido. Formatos aceitos são: %{valid_mime_types}' activerecord: models: decidim/assembly: @@ -266,7 +261,6 @@ pt-BR: duration_help: Se a duração desse assembly for limitada, selecione a data final. Caso contrário, aparecerá como indefinido. filters: Filtros images: Imagens - included_at_help: Selecione a data em que esta montagem foi adicionada ao Decidim. Não precisa necessariamente ser o mesmo que a data de criação. metadata: Metadados other: De outros select_a_created_by: Selecione um criado por diff --git a/decidim-assemblies/config/locales/pt.yml b/decidim-assemblies/config/locales/pt.yml index 9ea910f8b3d24..9870f842a73ec 100644 --- a/decidim-assemblies/config/locales/pt.yml +++ b/decidim-assemblies/config/locales/pt.yml @@ -1,3 +1,4 @@ +--- pt: activemodel: attributes: @@ -68,12 +69,6 @@ pt: email: E-mail name: Nome role: Função - errors: - models: - assembly: - attributes: - document: - invalid_document_type: 'Tipo de documento inválido. Os formatos aceites são: %{valid_mime_types}' activerecord: models: decidim/assembly: @@ -270,7 +265,6 @@ pt: duration_help: Se a duração desta reunião for limitada, selecione a data final. Caso contrário, aparecerá como indefinida. filters: Filtros images: Imagens - included_at_help: Selecione a data em que esta reunião foi adicionada ao Decidim. Não necessita necessariamente de ser a mesma que a data de criação. metadata: Metadados other: Outros select_a_created_by: Selecione um criado por diff --git a/decidim-assemblies/config/locales/ro-RO.yml b/decidim-assemblies/config/locales/ro-RO.yml index 292a3627a8917..0118fc855099e 100644 --- a/decidim-assemblies/config/locales/ro-RO.yml +++ b/decidim-assemblies/config/locales/ro-RO.yml @@ -1,9 +1,13 @@ +--- ro: activemodel: attributes: assemblies_setting: enable_organization_chart: Activează graficul organizatiei + assemblies_type: + title: Titlu assembly: + announcement: AnunÅ£ area_id: Zonă assembly_type: Tipul grupului de lucru assembly_type_other: Alt tip de grup de lucru @@ -22,12 +26,16 @@ ro: decidim_scope_id: Domeniu description: Descriere developer_group: Grup promotor + document: Document domain: Domeniu duration: Durată facebook: Facebook github: GitHub hashtag: Hashtag hero_image: Imagine pentru pagina principală + import_attachments: Importă ataÈ™amente + import_categories: Importă categorii + import_components: Importă componente included_at: Inclus la instagram: Instagram internal_organisation: Organizare internă @@ -52,7 +60,7 @@ ro: target: Cine participă title: Titlu twitter: Twitter - weight: Ordinea în poziÈ›ionare + weight: PoziÈ›ie youtube: YouTube assembly_member: birthday: Data naÈ™terii @@ -64,6 +72,7 @@ ro: non_user_avatar: Avatar position: PoziÈ›ie user_id: Utilizator sau grup + weight: PoziÈ›ie assembly_user_role: email: E-mail name: Nume @@ -73,7 +82,7 @@ ro: assembly: attributes: document: - invalid_document_type: 'Tip de document invalid. Formatele acceptate sunt: %{valid_mime_types}' + allowed_file_content_types: 'Tip de document invalid. Sunt permise numai fiÈ™iere cu următoarele extensii: %{types}' activerecord: models: decidim/assembly: @@ -245,6 +254,9 @@ ro: admin_log: assembly: create: "%{user_name} a creat grupul de lucru %{resource_name}" + duplicate: "%{user_name} a actualizat adunarea %{resource_name}" + export: "%{user_name} a actualizat adunarea %{resource_name}" + import: "%{user_name} a actualizat adunarea %{resource_name}" publish: "%{user_name} a publicat grupul de lucru %{resource_name}" unpublish: "%{user_name} a anulat publicarea grupului de lucru %{resource_name}" update: "%{user_name} a actualizat grupul de lucru %{resource_name}" @@ -273,7 +285,6 @@ ro: duration_help: ÃŽn cazul în care durata acestui grup de lucru este limitată, selectaÅ£i data de încheiere. ÃŽn caz contrar, va apărea ca nelimitată. filters: Filtre images: Imagini - included_at_help: SelectaÈ›i data la care aceast grup de lucru a fost adăugat în Decidem. Nu trebuie să fie neapărat aceeaÈ™i dată cu data creării. metadata: Metadate other: Altul select_a_created_by: SelectaÈ›i după persoana care a creat diff --git a/decidim-assemblies/config/locales/ru.yml b/decidim-assemblies/config/locales/ru.yml index 49998a1cf24ce..e5dc55d5c44a9 100644 --- a/decidim-assemblies/config/locales/ru.yml +++ b/decidim-assemblies/config/locales/ru.yml @@ -1,3 +1,4 @@ +--- ru: activemodel: attributes: @@ -222,7 +223,6 @@ ru: assemblies: form: duration_help: ЕÑли длительноÑÑ‚ÑŒ Ñтого ÑÐ¾Ð±Ñ€Ð°Ð½Ð¸Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð°, выберите дату окончаниÑ. Ð’ противном Ñлучае оно будет отображатьÑÑ ÐºÐ°Ðº беÑÑрочное. - included_at_help: Выберите дату, когда Ñто Ñобрание было добавлено ​​в ДеÑидим. Она не обÑзательно должна Ñовпадать Ñ Ð´Ð°Ñ‚Ð¾Ð¹ ÑозданиÑ. select_a_created_by: Укажите, кем Ñоздано select_an_area: Выберите учаÑток select_an_assembly_type: Выберите вид ÑÐ¾Ð±Ñ€Ð°Ð½Ð¸Ñ diff --git a/decidim-assemblies/config/locales/sk.yml b/decidim-assemblies/config/locales/sk.yml index beef21bcc966a..e99ed98ba3b01 100644 --- a/decidim-assemblies/config/locales/sk.yml +++ b/decidim-assemblies/config/locales/sk.yml @@ -1,3 +1,4 @@ +--- sk: activemodel: attributes: diff --git a/decidim-assemblies/config/locales/sl.yml b/decidim-assemblies/config/locales/sl.yml index 68adb9b536dc9..0ca54eb745a40 100644 --- a/decidim-assemblies/config/locales/sl.yml +++ b/decidim-assemblies/config/locales/sl.yml @@ -1,3 +1,4 @@ +--- sl: activemodel: attributes: @@ -59,12 +60,6 @@ sl: email: Email name: Ime role: Vloga - errors: - models: - assembly: - attributes: - document: - invalid_document_type: 'Neveljavna vrsta dokumenta. Sprejemljive oblike so: %{valid_mime_types}' activerecord: models: decidim/assembly: diff --git a/decidim-assemblies/config/locales/sr-CS.yml b/decidim-assemblies/config/locales/sr-CS.yml index a033cd2e6a03a..7f88a891e912c 100644 --- a/decidim-assemblies/config/locales/sr-CS.yml +++ b/decidim-assemblies/config/locales/sr-CS.yml @@ -1,3 +1,4 @@ +--- sr: decidim: admin: diff --git a/decidim-assemblies/config/locales/sv.yml b/decidim-assemblies/config/locales/sv.yml index 41c90419ca037..c924d2fd02a28 100644 --- a/decidim-assemblies/config/locales/sv.yml +++ b/decidim-assemblies/config/locales/sv.yml @@ -1,9 +1,13 @@ +--- sv: activemodel: attributes: assemblies_setting: enable_organization_chart: Aktivera organisationskarta + assemblies_type: + title: Titel assembly: + announcement: Meddelande area_id: OmrÃ¥de assembly_type: Typ av grupp assembly_type_other: Annan typ av grupp @@ -22,12 +26,14 @@ sv: decidim_scope_id: OmfÃ¥ng description: Beskrivning developer_group: Kampanjgrupp + document: Dokument domain: Domän duration: Varaktighet facebook: Facebook github: GitHub hashtag: Hashtag hero_image: Hembild + import_attachments: Importera bilagor included_at: Inkluderad vid instagram: Instagram internal_organisation: Intern organisation @@ -52,7 +58,7 @@ sv: target: Vem deltar title: Titel twitter: Twitter - weight: Vikt + weight: Ordning youtube: YouTube assembly_member: birthday: Födelsedag @@ -64,16 +70,11 @@ sv: non_user_avatar: Profilbild position: Befattning user_id: Användare + weight: Ordning assembly_user_role: email: E-post name: Namn role: Roll - errors: - models: - assembly: - attributes: - document: - invalid_document_type: 'Ogiltig dokumenttyp. Godkända format är: %{valid_mime_types}' activerecord: models: decidim/assembly: @@ -270,7 +271,7 @@ sv: duration_help: Om varaktigheten för gruppen är begränsad, välj ett slutdatum. Annars kommer den att visas som permanent. filters: Filter images: Bilder - included_at_help: Markera det datum dÃ¥ gruppen lades till i Decidim. Det behöver inte nödvändigtvis vara detsamma som datumet det skapades. + included_at_help: Markera det datum dÃ¥ gruppen lades till pÃ¥ plattformen. Det behöver inte nödvändigtvis vara detsamma som datumet det skapades. metadata: Metadata other: Annan select_a_created_by: Välj en skapad av diff --git a/decidim-assemblies/config/locales/tr-TR.yml b/decidim-assemblies/config/locales/tr-TR.yml index dc4cd2bc33da4..e8947d31d02ed 100644 --- a/decidim-assemblies/config/locales/tr-TR.yml +++ b/decidim-assemblies/config/locales/tr-TR.yml @@ -1,3 +1,4 @@ +--- tr: activemodel: attributes: @@ -66,12 +67,6 @@ tr: email: E-posta name: Adı role: Rol - errors: - models: - assembly: - attributes: - document: - invalid_document_type: 'Geçersiz belge türü. Kabul edilen biçimler ÅŸunlardır: %{valid_mime_types}' activerecord: models: decidim/assembly: @@ -263,7 +258,6 @@ tr: duration_help: Bu kurulun süresi sınırlıysa, bitiÅŸ tarihini seçin. Aksi takdirde belirsiz görünecektir. filters: Filtreler images: Resimler - included_at_help: Bu kurulun Decidim'e eklendiÄŸi tarihi seçin. Yaratılış tarihi ile aynı olmak zorunda deÄŸildir. metadata: Meta veri other: DiÄŸer select_a_created_by: tarafından oluÅŸturulanı seçin diff --git a/decidim-assemblies/config/locales/uk.yml b/decidim-assemblies/config/locales/uk.yml index af861445c3c2c..466d9278d32ac 100644 --- a/decidim-assemblies/config/locales/uk.yml +++ b/decidim-assemblies/config/locales/uk.yml @@ -1,3 +1,4 @@ +--- uk: activemodel: attributes: @@ -222,7 +223,6 @@ uk: assemblies: form: duration_help: Якщо триваліÑÑ‚ÑŒ цих зборів обмежена, оберіть дату завершеннÑ. Ð’ іншому випадку вони будуть показуватиÑÑ Ñк безÑтрокові. - included_at_help: Оберіть дату, коли ці збори були додані до ДеÑідім. Вона не обов'Ñзково має бути тою Ñамою ж, що Ñ– дата ÑтвореннÑ. select_a_created_by: Вкажіть, ким Ñтворені select_an_area: Оберіть дільницю select_an_assembly_type: Оберіть різновид зборів diff --git a/decidim-assemblies/config/locales/zh-CN.yml b/decidim-assemblies/config/locales/zh-CN.yml index 07ca0b4338f44..100739abf0b1a 100644 --- a/decidim-assemblies/config/locales/zh-CN.yml +++ b/decidim-assemblies/config/locales/zh-CN.yml @@ -1,3 +1,4 @@ +--- zh-CN: activemodel: attributes: @@ -63,12 +64,6 @@ zh-CN: email: 电å­é‚®ä»¶åœ°å€ name: å称 role: 作用 - errors: - models: - assembly: - attributes: - document: - invalid_document_type: '无效的文档类型。接å—çš„æ ¼å¼ä¸ºï¼š %{valid_mime_types}' activerecord: models: decidim/assembly: @@ -257,7 +252,6 @@ zh-CN: duration_help: 如果这个程åºé›†çš„æŒç»­æ—¶é—´æœ‰é™ï¼Œè¯·é€‰æ‹©ç»“æŸæ—¥æœŸã€‚å¦åˆ™ï¼Œå®ƒå°†æ˜¾ç¤ºä¸ºæ— é™æœŸã€‚ filters: 筛选器 images: å›¾åƒ - included_at_help: 选择程åºé›†æ·»åŠ åˆ° Decidim 的日期。它ä¸ä¸€å®šä¸Žåˆ›å»ºæ—¥æœŸç›¸åŒã€‚ metadata: å…ƒæ•°æ® other: 其他 select_a_created_by: 选择创建者: diff --git a/decidim-assemblies/decidim-assemblies.gemspec b/decidim-assemblies/decidim-assemblies.gemspec index 48465524e2b60..5edbc38c488cf 100644 --- a/decidim-assemblies/decidim-assemblies.gemspec +++ b/decidim-assemblies/decidim-assemblies.gemspec @@ -10,7 +10,7 @@ Gem::Specification.new do |s| s.email = ["josepjaume@gmail.com", "mrc2407@gmail.com", "oriolgual@gmail.com"] s.license = "AGPL-3.0" s.homepage = "https://github.com/decidim/decidim" - s.required_ruby_version = ">= 2.7" + s.required_ruby_version = ">= 3.0" s.name = "decidim-assemblies" s.summary = "Decidim assemblies module" @@ -22,4 +22,6 @@ Gem::Specification.new do |s| s.add_development_dependency "decidim-admin", Decidim::Assemblies.version s.add_development_dependency "decidim-dev", Decidim::Assemblies.version + s.add_development_dependency "decidim-meetings", Decidim::Assemblies.version + s.add_development_dependency "decidim-proposals", Decidim::Assemblies.version end diff --git a/decidim-assemblies/lib/decidim/assemblies/admin_engine.rb b/decidim-assemblies/lib/decidim/assemblies/admin_engine.rb index df93295e46c0e..763aeb2342758 100644 --- a/decidim-assemblies/lib/decidim/assemblies/admin_engine.rb +++ b/decidim-assemblies/lib/decidim/assemblies/admin_engine.rb @@ -53,6 +53,7 @@ class AdminEngine < ::Rails::Engine resources :imports, only: [:new, :create] do get :example, on: :collection end + resources :reminders, only: [:new, :create] end resources :moderations do @@ -69,7 +70,9 @@ class AdminEngine < ::Rails::Engine post :resend_invitation, to: "participatory_space_private_users#resend_invitation" end collection do - resource :participatory_space_private_users_csv_import, only: [:new, :create], path: "csv_import" + resource :participatory_space_private_users_csv_imports, only: [:new, :create], path: "csv_import" do + delete :destroy_all + end end end end diff --git a/decidim-assemblies/lib/decidim/assemblies/participatory_space.rb b/decidim-assemblies/lib/decidim/assemblies/participatory_space.rb index 7c705ea3d2de2..4893721d753f0 100644 --- a/decidim-assemblies/lib/decidim/assemblies/participatory_space.rb +++ b/decidim-assemblies/lib/decidim/assemblies/participatory_space.rb @@ -66,13 +66,13 @@ Decidim::Faker::Localized.paragraph(sentence_count: 3) end, organization: organization, - hero_image: ActiveStorage::Blob.create_after_upload!( + hero_image: ActiveStorage::Blob.create_and_upload!( io: File.open(File.join(seeds_root, "city.jpeg")), filename: "hero_image.jpeg", content_type: "image/jpeg", metadata: nil ), # Keep after organization - banner_image: ActiveStorage::Blob.create_after_upload!( + banner_image: ActiveStorage::Blob.create_and_upload!( io: File.open(File.join(seeds_root, "city2.jpeg")), filename: "banner_image.jpeg", content_type: "image/jpeg", @@ -132,8 +132,8 @@ user.update!( name: Faker::Name.name, nickname: Faker::Twitter.unique.screen_name, - password: "decidim123456", - password_confirmation: "decidim123456", + password: "decidim123456789", + password_confirmation: "decidim123456789", organization: organization, confirmed_at: Time.current, locale: I18n.default_locale, @@ -159,13 +159,13 @@ Decidim::Faker::Localized.paragraph(sentence_count: 3) end, organization: organization, - hero_image: ActiveStorage::Blob.create_after_upload!( + hero_image: ActiveStorage::Blob.create_and_upload!( io: File.open(File.join(seeds_root, "city.jpeg")), filename: "hero_image.jpeg", content_type: "image/jpeg", metadata: nil ), # Keep after organization - banner_image: ActiveStorage::Blob.create_after_upload!( + banner_image: ActiveStorage::Blob.create_and_upload!( io: File.open(File.join(seeds_root, "city2.jpeg")), filename: "banner_image.jpeg", content_type: "image/jpeg", @@ -197,7 +197,7 @@ attachment_collection: attachment_collection, attached_to: current_assembly, content_type: "application/pdf", - file: ActiveStorage::Blob.create_after_upload!( + file: ActiveStorage::Blob.create_and_upload!( io: File.open(File.join(seeds_root, "Exampledocument.pdf")), filename: "Exampledocument.pdf", content_type: "application/pdf", @@ -210,7 +210,7 @@ description: Decidim::Faker::Localized.sentence(word_count: 5), attached_to: current_assembly, content_type: "image/jpeg", - file: ActiveStorage::Blob.create_after_upload!( + file: ActiveStorage::Blob.create_and_upload!( io: File.open(File.join(seeds_root, "city.jpeg")), filename: "city.jpeg", content_type: "image/jpeg", @@ -223,7 +223,7 @@ description: Decidim::Faker::Localized.sentence(word_count: 5), attached_to: current_assembly, content_type: "application/pdf", - file: ActiveStorage::Blob.create_after_upload!( + file: ActiveStorage::Blob.create_and_upload!( io: File.open(File.join(seeds_root, "Exampledocument.pdf")), filename: "Exampledocument.pdf", content_type: "application/pdf", diff --git a/decidim-assemblies/lib/decidim/assemblies/test/factories.rb b/decidim-assemblies/lib/decidim/assemblies/test/factories.rb index e71909aa5a435..81ccb2eefd28b 100644 --- a/decidim-assemblies/lib/decidim/assemblies/test/factories.rb +++ b/decidim-assemblies/lib/decidim/assemblies/test/factories.rb @@ -105,6 +105,7 @@ end organization { assembly.organization } + admin_terms_accepted_at { Time.current } after(:create) do |user, evaluator| create :assembly_user_role, @@ -120,6 +121,7 @@ end organization { assembly.organization } + admin_terms_accepted_at { Time.current } after(:create) do |user, evaluator| create :assembly_user_role, @@ -135,6 +137,7 @@ end organization { assembly.organization } + admin_terms_accepted_at { Time.current } after(:create) do |user, evaluator| create :assembly_user_role, @@ -150,6 +153,7 @@ end organization { assembly.organization } + admin_terms_accepted_at { Time.current } after(:create) do |user, evaluator| create :assembly_user_role, diff --git a/decidim-assemblies/lib/decidim/assemblies/version.rb b/decidim-assemblies/lib/decidim/assemblies/version.rb index d8e1bc97ed4f2..2766de9fa9b9f 100644 --- a/decidim-assemblies/lib/decidim/assemblies/version.rb +++ b/decidim-assemblies/lib/decidim/assemblies/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-assemblies version. module Assemblies def self.version - "0.26.4" + "0.27.2" end end end diff --git a/decidim-assemblies/spec/commands/copy_assembly_spec.rb b/decidim-assemblies/spec/commands/copy_assembly_spec.rb index 75c4299f83582..c76ea8346fc6f 100644 --- a/decidim-assemblies/spec/commands/copy_assembly_spec.rb +++ b/decidim-assemblies/spec/commands/copy_assembly_spec.rb @@ -4,9 +4,10 @@ module Decidim::Assemblies describe Admin::CopyAssembly do - subject { described_class.new(form, assembly) } + subject { described_class.new(form, assembly, user) } let(:organization) { create :organization } + let(:user) { create :user, organization: organization } let(:scope) { create :scope, organization: organization } let(:errors) { double.as_null_object } let!(:assembly) { create :assembly } @@ -42,7 +43,7 @@ module Decidim::Assemblies context "when everything is ok" do it "duplicates an assembly" do - expect { subject.call }.to change { Decidim::Assembly.count }.by(1) + expect { subject.call }.to change(Decidim::Assembly, :count).by(1) old_assembly = Decidim::Assembly.first new_assembly = Decidim::Assembly.last @@ -67,13 +68,25 @@ module Decidim::Assemblies it "broadcasts ok" do expect { subject.call }.to broadcast(:ok) end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with("duplicate", Decidim::Assembly, user) + .and_call_original + + expect { subject.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("duplicate") + expect(action_log.version).to be_present + end end context "when copy_categories exists" do let(:copy_categories) { true } it "duplicates a assembly and the categories" do - expect { subject.call }.to change { Decidim::Category.count }.by(1) + expect { subject.call }.to change(Decidim::Category, :count).by(1) expect(Decidim::Category.unscoped.distinct.pluck(:decidim_participatory_space_id).count).to eq 2 old_assembly_category = Decidim::Category.unscoped.first @@ -91,17 +104,17 @@ module Decidim::Assemblies it "duplicates an assembly and the components" do dummy_hook = proc {} component.manifest.on :copy, &dummy_hook - expect(dummy_hook).to receive(:call).with(new_component: an_instance_of(Decidim::Component), old_component: component) + expect(dummy_hook).to receive(:call).with({ new_component: an_instance_of(Decidim::Component), old_component: component }) - expect { subject.call }.to change { Decidim::Component.count }.by(1) + expect { subject.call }.to change(Decidim::Component, :count).by(1) last_assembly = Decidim::Assembly.last last_component = Decidim::Component.all.reorder(:id).last expect(last_component.participatory_space).to eq(last_assembly) expect(last_component.name).to eq(component.name) - expect(last_component.settings.attributes.except(:dummy_global_translatable_text)).to eq(component.settings.attributes.except(:dummy_global_translatable_text)) - expect(last_component.settings.attributes[:dummy_global_translatable_text]).to include(component.settings.attributes[:dummy_global_translatable_text]) + expect(last_component.settings.attributes.except("dummy_global_translatable_text")).to eq(component.settings.attributes.except("dummy_global_translatable_text")) + expect(last_component.settings.attributes["dummy_global_translatable_text"]).to include(component.settings.attributes["dummy_global_translatable_text"]) expect(last_component.step_settings.keys).to eq(component.step_settings.keys) expect(last_component.step_settings.values).to eq(component.step_settings.values) end @@ -121,7 +134,7 @@ module Decidim::Assemblies let!(:assembly) { create :assembly, parent: assembly_parent, organization: organization } it "duplicates an assembly" do - expect { subject.call }.to change { Decidim::Assembly.count }.by(1) + expect { subject.call }.to change(Decidim::Assembly, :count).by(1) old_assembly = Decidim::Assembly.find_by(id: assembly.id) new_assembly = Decidim::Assembly.last diff --git a/decidim-assemblies/spec/commands/create_assemblies_type_spec.rb b/decidim-assemblies/spec/commands/create_assemblies_type_spec.rb index 07741d4d27dbe..818ff735698c9 100644 --- a/decidim-assemblies/spec/commands/create_assemblies_type_spec.rb +++ b/decidim-assemblies/spec/commands/create_assemblies_type_spec.rb @@ -34,7 +34,7 @@ module Decidim::Assemblies end it "creates a new assembly type for the organization" do - expect { subject.call }.to change { Decidim::AssembliesType.count }.by(1) + expect { subject.call }.to change(Decidim::AssembliesType, :count).by(1) end it "traces the action", versioning: true do diff --git a/decidim-assemblies/spec/commands/create_assembly_member_spec.rb b/decidim-assemblies/spec/commands/create_assembly_member_spec.rb index ff38c86b69763..a4aaf3feb9bc4 100644 --- a/decidim-assemblies/spec/commands/create_assembly_member_spec.rb +++ b/decidim-assemblies/spec/commands/create_assembly_member_spec.rb @@ -11,7 +11,7 @@ module Decidim::Assemblies let!(:current_user) { create :user, :confirmed, organization: assembly.organization } let(:existing_user) { false } let(:non_user_avatar) do - ActiveStorage::Blob.create_after_upload!( + ActiveStorage::Blob.create_and_upload!( io: File.open(Decidim::Dev.asset("avatar.jpg")), filename: "avatar.jpeg", content_type: "image/jpeg" @@ -55,7 +55,7 @@ module Decidim::Assemblies context "when image is invalid" do let(:existing_user) { false } let(:non_user_avatar) do - ActiveStorage::Blob.create_after_upload!( + ActiveStorage::Blob.create_and_upload!( io: File.open(Decidim::Dev.asset("invalid.jpeg")), filename: "avatar.jpeg", content_type: "image/jpeg" @@ -73,7 +73,7 @@ module Decidim::Assemblies let(:assembly_member) { Decidim::AssemblyMember.last } it "creates an assembly" do - expect { subject.call }.to change { Decidim::AssemblyMember.count }.by(1) + expect { subject.call }.to change(Decidim::AssemblyMember, :count).by(1) end it "broadcasts ok" do diff --git a/decidim-assemblies/spec/commands/create_assembly_spec.rb b/decidim-assemblies/spec/commands/create_assembly_spec.rb index db46249157e8d..693373d693fa8 100644 --- a/decidim-assemblies/spec/commands/create_assembly_spec.rb +++ b/decidim-assemblies/spec/commands/create_assembly_spec.rb @@ -19,6 +19,8 @@ module Decidim::Assemblies organization: organization ) end + let(:related_process_ids) { [participatory_processes.map(&:id)] } + let(:form) do instance_double( Admin::AssemblyForm, @@ -47,7 +49,7 @@ module Decidim::Assemblies parent: nil, private_space: false, errors: errors, - participatory_processes_ids: participatory_processes.map(&:id), + participatory_processes_ids: related_process_ids, show_statistics: false, purpose_of_action: { en: "purpose of action" }, composition: { en: "composition of internal working groups" }, @@ -87,15 +89,15 @@ module Decidim::Assemblies persisted?: false, valid?: false, errors: { - hero_image: "Image too big", - banner_image: "Image too big" + hero_image: "File resolution is too large", + banner_image: "File resolution is too large" } ).as_null_object end before do allow(Decidim::ActionLogger).to receive(:log).and_return(true) - expect(Decidim::Assembly).to receive(:create).and_return(invalid_assembly) + allow(Decidim::Assembly).to receive(:create).and_return(invalid_assembly) end it "broadcasts invalid" do @@ -103,15 +105,15 @@ module Decidim::Assemblies end it "adds errors to the form" do - expect(errors).to receive(:add).with(:hero_image, "Image too big") - expect(errors).to receive(:add).with(:banner_image, "Image too big") + expect(errors).to receive(:add).with(:hero_image, "File resolution is too large") + expect(errors).to receive(:add).with(:banner_image, "File resolution is too large") subject.call end end context "when the uploaded hero image has too large dimensions" do let(:hero_image) do - ActiveStorage::Blob.create_after_upload!( + ActiveStorage::Blob.create_and_upload!( io: File.open(Decidim::Dev.asset("5000x5000.png")), filename: "5000x5000.png", content_type: "image/png" @@ -137,7 +139,7 @@ module Decidim::Assemblies it "broadcasts invalid" do expect { subject.call }.to broadcast(:invalid) - expect(form.errors.messages[:hero_image]).to contain_exactly(["The image is too big"]) + expect(form.errors.messages[:hero_image]).to contain_exactly("File resolution is too large") end end @@ -145,7 +147,7 @@ module Decidim::Assemblies let(:assembly) { Decidim::Assembly.last } it "creates an assembly" do - expect { subject.call }.to change { Decidim::Assembly.count }.by(1) + expect { subject.call }.to change(Decidim::Assembly, :count).by(1) end it "broadcasts ok" do @@ -180,7 +182,7 @@ module Decidim::Assemblies it "assembly type is null" do subject.call - expect(assembly.assembly_type).to eq(nil) + expect(assembly.assembly_type).to be_nil end end @@ -189,6 +191,33 @@ module Decidim::Assemblies linked_participatory_processes = assembly.linked_participatory_space_resources(:participatory_processes, "included_participatory_processes") expect(linked_participatory_processes).to match_array(participatory_processes) end + + context "when sorting by weight" do + let!(:process_one) { create :participatory_process, organization: organization, weight: 2 } + let!(:process_two) { create :participatory_process, organization: organization, weight: 1 } + let(:related_process_ids) { [process_one.id, process_two.id] } + + it "links processes in right way" do + subject.call + + linked_processes = assembly.linked_participatory_space_resources(:participatory_process, "included_participatory_processes") + expect(linked_processes.first).to eq(process_two) + end + end + + context "when linking draft processes" do + let!(:process_one) { create :participatory_process, :unpublished, organization: organization, weight: 2 } + let!(:process_two) { create :participatory_process, organization: organization, weight: 1 } + let(:related_process_ids) { [process_one.id, process_two.id] } + + it "links processes in right way" do + subject.call + + linked_processes = assembly.linked_participatory_space_resources(:participatory_process, "included_participatory_processes") + expect(linked_processes.size).to eq(1) + expect(linked_processes.first).to eq(process_two) + end + end end end end diff --git a/decidim-assemblies/spec/commands/decidim/assemblies/admin/import_assembly_spec.rb b/decidim-assemblies/spec/commands/decidim/assemblies/admin/import_assembly_spec.rb index 3463942d6dc5e..c37b74ae8b961 100644 --- a/decidim-assemblies/spec/commands/decidim/assemblies/admin/import_assembly_spec.rb +++ b/decidim-assemblies/spec/commands/decidim/assemblies/admin/import_assembly_spec.rb @@ -6,10 +6,11 @@ module Decidim::Assemblies::Admin describe ImportAssembly do include Decidim::ComponentTestHelpers - subject { described_class.new(form) } + subject { described_class.new(form, user) } let(:organization) { create :organization } - let!(:document_file) { IO.read(Decidim::Dev.asset(document_name)) } + let(:user) { create :user, organization: organization } + let!(:document_file) { File.read(Decidim::Dev.asset(document_name)) } let(:form_doc) do instance_double(File, blank?: false) @@ -75,6 +76,17 @@ def stub_calls_to_external_files expect(imported_assembly).not_to be_published expect(imported_assembly.organization).to eq(organization) end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!).twice + .and_call_original + + expect { subject.call }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("import") + expect(action_log.version).to be_present + end end describe "when the form is not valid" do @@ -87,7 +99,7 @@ def stub_calls_to_external_files it "doesn't create any assembly" do expect do subject.call - end.to change(::Decidim::Assembly, :count).by(0) + end.not_to change(::Decidim::Assembly, :count) end end @@ -105,7 +117,7 @@ def stub_calls_to_external_files it "imports an assembly and the categories" do stub_calls_to_external_files - expect { subject.call }.to change { Decidim::Category.count }.by(8) + expect { subject.call }.to change(Decidim::Category, :count).by(8) expect(Decidim::Category.distinct.select(:decidim_participatory_space_id).count).to eq 1 imported_assembly_category = Decidim::Category.first @@ -125,7 +137,7 @@ def stub_calls_to_external_files it "imports a assembly and the collections" do stub_calls_to_external_files - expect { subject.call }.to change { Decidim::AttachmentCollection.count }.by(1) + expect { subject.call }.to change(Decidim::AttachmentCollection, :count).by(1) imported_assembly_collection = Decidim::AttachmentCollection.first expect(imported_assembly_collection.name).to eq("ca" => "deleniti", "en" => "laboriosam", "es" => "quia") expect(imported_assembly_collection.collection_for).to eq(Decidim::Assembly.last) diff --git a/decidim-assemblies/spec/commands/update_assemblies_setting_spec.rb b/decidim-assemblies/spec/commands/update_assemblies_setting_spec.rb index 3f7f87015c76a..58fc1ef8c480b 100644 --- a/decidim-assemblies/spec/commands/update_assemblies_setting_spec.rb +++ b/decidim-assemblies/spec/commands/update_assemblies_setting_spec.rb @@ -28,7 +28,7 @@ module Decidim::Assemblies end context "when the form is valid" do - it "broadcasts ok" do + it "broadcasts ok" do expect { subject.call }.to broadcast(:ok) end diff --git a/decidim-assemblies/spec/commands/update_assembly_admin_spec.rb b/decidim-assemblies/spec/commands/update_assembly_admin_spec.rb index 98f0b24844aae..a682dbdda6268 100644 --- a/decidim-assemblies/spec/commands/update_assembly_admin_spec.rb +++ b/decidim-assemblies/spec/commands/update_assembly_admin_spec.rb @@ -68,7 +68,7 @@ module Decidim::Assemblies it "traces the action", versioning: true do expect(Decidim.traceability) .to receive(:update!) - .with(user_role, current_user, { role: new_role }, resource: hash_including(:title)) + .with(user_role, current_user, { role: new_role }, { resource: hash_including(:title) }) .and_call_original expect { subject.call }.to change(Decidim::ActionLog, :count) diff --git a/decidim-assemblies/spec/commands/update_assembly_member_spec.rb b/decidim-assemblies/spec/commands/update_assembly_member_spec.rb index c7f17d12ccda1..8b5c49755705a 100644 --- a/decidim-assemblies/spec/commands/update_assembly_member_spec.rb +++ b/decidim-assemblies/spec/commands/update_assembly_member_spec.rb @@ -11,13 +11,7 @@ module Decidim::Assemblies let!(:current_user) { create :user, :confirmed, organization: assembly.organization } let(:user) { nil } let(:existing_user) { false } - let(:non_user_avatar) do - ActiveStorage::Blob.create_after_upload!( - io: File.open(Decidim::Dev.asset("avatar.jpg")), - filename: "avatar.jpeg", - content_type: "image/jpeg" - ) - end + let(:non_user_avatar) { upload_test_file(Decidim::Dev.test_file("avatar.jpg", "image/jpeg")) } let(:form_klass) { Admin::AssemblyMemberForm } let(:form_params) do { @@ -55,13 +49,7 @@ module Decidim::Assemblies context "when image is invalid" do let(:existing_user) { false } - let(:non_user_avatar) do - ActiveStorage::Blob.create_after_upload!( - io: File.open(Decidim::Dev.asset("invalid.jpeg")), - filename: "avatar.jpeg", - content_type: "image/jpeg" - ) - end + let(:non_user_avatar) { upload_test_file(Decidim::Dev.asset("invalid.jpeg")) } it "prevents uploading" do expect { subject.call }.not_to raise_error @@ -77,7 +65,7 @@ module Decidim::Assemblies end.to change { assembly_member.reload && assembly_member.full_name }.from(assembly_member.full_name).to("New name") end - it "broadcasts ok" do + it "broadcasts ok" do expect { subject.call }.to broadcast(:ok) end diff --git a/decidim-assemblies/spec/commands/update_assembly_spec.rb b/decidim-assemblies/spec/commands/update_assembly_spec.rb index 07bf550162c38..079113ac7616a 100644 --- a/decidim-assemblies/spec/commands/update_assembly_spec.rb +++ b/decidim-assemblies/spec/commands/update_assembly_spec.rb @@ -91,7 +91,7 @@ module Decidim::Assemblies describe "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do @@ -110,7 +110,7 @@ module Decidim::Assemblies let(:attachment_params) do { banner_image: banner_image.blob, - hero_image: ActiveStorage::Blob.create_after_upload!( + hero_image: ActiveStorage::Blob.create_and_upload!( io: File.open(Decidim::Dev.asset("5000x5000.png")), filename: "5000x5000.png", content_type: "image/png" @@ -120,16 +120,16 @@ module Decidim::Assemblies it "broadcasts invalid" do expect { command.call }.to broadcast(:invalid) - expect(form.errors.messages[:hero_image]).to contain_exactly(["The image is too big"]) + expect(form.errors.messages[:hero_image]).to contain_exactly("File resolution is too large") end end describe "when the assembly is not valid" do before do - expect(form).to receive(:invalid?).and_return(false) + allow(form).to receive(:invalid?).and_return(false) expect(my_assembly).to receive(:valid?).at_least(:once).and_return(false) - my_assembly.errors.add(:hero_image, "Image too big") - my_assembly.errors.add(:banner_image, "Image too big") + my_assembly.errors.add(:hero_image, "File resolution is too large") + my_assembly.errors.add(:banner_image, "File resolution is too large") end it "broadcasts invalid" do @@ -186,7 +186,7 @@ module Decidim::Assemblies it "assembly type is null" do command.call - expect(my_assembly.assembly_type).to eq(nil) + expect(my_assembly.assembly_type).to be_nil end end @@ -243,7 +243,7 @@ module Decidim::Assemblies my_assembly.reload parent_assembly.reload - expect(my_assembly.parent).to be(nil) + expect(my_assembly.parent).to be_nil expect(parent_assembly.children_count).to eq(parent_assembly.children.count) end end diff --git a/decidim-assemblies/spec/controllers/admin/assembly_exports_controller_spec.rb b/decidim-assemblies/spec/controllers/admin/assembly_exports_controller_spec.rb index a5a130d255a28..9a0d2f683f36f 100644 --- a/decidim-assemblies/spec/controllers/admin/assembly_exports_controller_spec.rb +++ b/decidim-assemblies/spec/controllers/admin/assembly_exports_controller_spec.rb @@ -31,6 +31,18 @@ module Admin post(:create, params: params) end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with("export", assembly, user) + .and_call_original + + expect { post(:create, params: params) }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("export") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-assemblies/spec/controllers/exports_controller_spec.rb b/decidim-assemblies/spec/controllers/admin/exports_controller_spec.rb similarity index 75% rename from decidim-assemblies/spec/controllers/exports_controller_spec.rb rename to decidim-assemblies/spec/controllers/admin/exports_controller_spec.rb index d4b60a0a2cce4..d730360c3a3a1 100644 --- a/decidim-assemblies/spec/controllers/exports_controller_spec.rb +++ b/decidim-assemblies/spec/controllers/admin/exports_controller_spec.rb @@ -47,6 +47,18 @@ module Admin end end end + + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:perform_action!) + .with("export_component", component, user, { name: "dummies", format: "json" }) + .and_call_original + + expect { post(:create, params: params) }.to change(Decidim::ActionLog, :count) + action_log = Decidim::ActionLog.last + expect(action_log.action).to eq("export_component") + expect(action_log.version).to be_present + end end end end diff --git a/decidim-assemblies/spec/controllers/admin/imports_controller_spec.rb b/decidim-assemblies/spec/controllers/admin/imports_controller_spec.rb index 448cc7a9ce0d3..acee679f61bbf 100644 --- a/decidim-assemblies/spec/controllers/admin/imports_controller_spec.rb +++ b/decidim-assemblies/spec/controllers/admin/imports_controller_spec.rb @@ -11,13 +11,7 @@ module Admin it_behaves_like "admin imports controller" do let!(:participatory_space) { create :assembly, organization: organization } let(:extra_params) { { assembly_slug: participatory_space.slug } } - - let(:file) do - Rack::Test::UploadedFile.new( - Decidim::Dev.test_file("import_proposals.csv", "text/csv"), - "text/csv" - ) - end + let(:file) { upload_test_file(Decidim::Dev.test_file("import_proposals.csv", "text/csv")) } end end end diff --git a/decidim-assemblies/spec/controllers/assembly_members_controller_spec.rb b/decidim-assemblies/spec/controllers/assembly_members_controller_spec.rb index 12457c1213fc1..c2c5518fb5633 100644 --- a/decidim-assemblies/spec/controllers/assembly_members_controller_spec.rb +++ b/decidim-assemblies/spec/controllers/assembly_members_controller_spec.rb @@ -30,15 +30,15 @@ module Assemblies end context "when assembly has members" do - let!(:member_1) { create(:assembly_member, assembly: assembly) } - let!(:member_2) { create(:assembly_member, assembly: assembly) } + let!(:member1) { create(:assembly_member, assembly: assembly) } + let!(:member2) { create(:assembly_member, assembly: assembly) } let!(:non_member) { create(:assembly_member) } context "when user has permissions" do it "displays list of members" do get :index, params: { assembly_slug: assembly.slug } - expect(controller.helpers.collection).to match_array([member_1, member_2]) + expect(controller.helpers.collection).to match_array([member1, member2]) end end diff --git a/decidim-assemblies/spec/factories.rb b/decidim-assemblies/spec/factories.rb index e793a3cbeef74..13db5e8b4a4b4 100644 --- a/decidim-assemblies/spec/factories.rb +++ b/decidim-assemblies/spec/factories.rb @@ -2,5 +2,6 @@ require "decidim/core/test/factories" require "decidim/proposals/test/factories" +require "decidim/meetings/test/factories" require "decidim/assemblies/test/factories" diff --git a/decidim-assemblies/spec/forms/assembly_form_spec.rb b/decidim-assemblies/spec/forms/assembly_form_spec.rb index ae278a410f488..d94093a065540 100644 --- a/decidim-assemblies/spec/forms/assembly_form_spec.rb +++ b/decidim-assemblies/spec/forms/assembly_form_spec.rb @@ -41,7 +41,7 @@ module Admin } end let(:slug) { "slug" } - let(:attachment) { Decidim::Dev.test_file("city.jpeg", "image/jpeg") } + let(:attachment) { upload_test_file(Decidim::Dev.test_file("city.jpeg", "image/jpeg")) } let(:show_statistics) { true } let(:private_space) { true } let(:purpose_of_action) do @@ -166,30 +166,19 @@ module Admin it { is_expected.to be_valid } end - context "when hero_image is too big" do + context "when attachment (hero_image or banner_image) is too big" do before do organization.settings.tap do |settings| settings.upload.maximum_file_size.default = 5 end - expect(subject.hero_image).to receive(:size).twice.and_return(6.megabytes) - end - - it { is_expected.not_to be_valid } - end - - context "when banner_image is too big" do - before do - organization.settings.tap do |settings| - settings.upload.maximum_file_size.default = 5 - end - expect(subject.banner_image).to receive(:size).twice.and_return(6.megabytes) + ActiveStorage::Blob.find_signed(attachment).update(byte_size: 6.megabytes) end it { is_expected.not_to be_valid } end context "when images are not the expected type" do - let(:attachment) { Decidim::Dev.test_file("Exampledocument.pdf", "application/pdf") } + let(:attachment) { upload_test_file(Decidim::Dev.test_file("Exampledocument.pdf", "application/pdf")) } it { is_expected.not_to be_valid } end diff --git a/decidim-assemblies/spec/forms/assembly_member_form_spec.rb b/decidim-assemblies/spec/forms/assembly_member_form_spec.rb index dfe88496587d5..f83f46e41d46a 100644 --- a/decidim-assemblies/spec/forms/assembly_member_form_spec.rb +++ b/decidim-assemblies/spec/forms/assembly_member_form_spec.rb @@ -20,7 +20,7 @@ module Admin let(:gender) { ::Faker::Lorem.word } let(:position) { Decidim::AssemblyMember::POSITIONS.first } let(:existing_user) { false } - let(:non_user_avatar) { fixture_file_upload(File.open(Decidim::Dev.asset("city.jpeg")), "image/jpeg") } + let(:non_user_avatar) { upload_test_file(Decidim::Dev.test_file("city.jpeg", "image/jpeg")) } let(:user_id) { nil } let(:attributes) do @@ -130,13 +130,13 @@ module Admin context "when the user does not exist" do let(:user_id) { 999_999 } - it { is_expected.to eq(nil) } + it { is_expected.to be_nil } end context "when the user is from another organization" do let(:user_id) { create(:user).id } - it { is_expected.to eq(nil) } + it { is_expected.to be_nil } end end end diff --git a/decidim-assemblies/spec/forms/assembly_user_role_form_spec.rb b/decidim-assemblies/spec/forms/assembly_user_role_form_spec.rb index 3a4835976dffe..d5e305c7802e6 100644 --- a/decidim-assemblies/spec/forms/assembly_user_role_form_spec.rb +++ b/decidim-assemblies/spec/forms/assembly_user_role_form_spec.rb @@ -36,7 +36,7 @@ module Admin end context "when email is missing" do - let(:email) {} + let(:email) { nil } it { is_expected.to be_invalid } end diff --git a/decidim-assemblies/spec/lib/components/assemblies/current_component_spec.rb b/decidim-assemblies/spec/lib/components/assemblies/current_component_spec.rb index 9318cb5047b53..b72d012b5c0e2 100644 --- a/decidim-assemblies/spec/lib/components/assemblies/current_component_spec.rb +++ b/decidim-assemblies/spec/lib/components/assemblies/current_component_spec.rb @@ -6,21 +6,19 @@ module Decidim module Assemblies describe CurrentComponent do let(:request) { double(params: params, env: env) } - let(:subject) { described_class.new(manifest) } let(:params) { {} } let(:manifest) { Decidim.find_component_manifest("dummy") } - let(:organization) do create(:organization) end - let(:current_assembly) { create(:assembly, organization: organization) } let(:other_assembly) { create(:assembly, organization: organization) } - let(:env) do { "decidim.current_organization" => organization } end + subject { described_class.new(manifest) } + context "when the params contain an assembly id" do before do params["assembly_slug"] = current_assembly.id.to_s @@ -28,7 +26,7 @@ module Assemblies context "when the params don't contain a component id" do it "doesn't match" do - expect(subject.matches?(request)).to eq(false) + expect(subject.matches?(request)).to be(false) end end @@ -41,7 +39,7 @@ module Assemblies let(:component) { create(:component, participatory_space: other_assembly) } it "matches" do - expect(subject.matches?(request)).to eq(false) + expect(subject.matches?(request)).to be(false) end end @@ -49,7 +47,7 @@ module Assemblies let(:component) { create(:component, participatory_space: current_assembly) } it "matches" do - expect(subject.matches?(request)).to eq(true) + expect(subject.matches?(request)).to be(true) end end end diff --git a/decidim-assemblies/spec/lib/query_extensions_spec.rb b/decidim-assemblies/spec/lib/query_extensions_spec.rb index 21e2bb572d58f..03dcf1f7e2bc0 100644 --- a/decidim-assemblies/spec/lib/query_extensions_spec.rb +++ b/decidim-assemblies/spec/lib/query_extensions_spec.rb @@ -9,16 +9,16 @@ module Core include_context "with a graphql class type" describe "assembliesTypes" do - let!(:assemblies_type_1) { create(:assemblies_type, organization: current_organization) } - let!(:assemblies_type_2) { create(:assemblies_type, organization: current_organization) } - let!(:assemblies_type_3) { create(:assemblies_type) } + let!(:assemblies_type1) { create(:assemblies_type, organization: current_organization) } + let!(:assemblies_type2) { create(:assemblies_type, organization: current_organization) } + let!(:assemblies_type3) { create(:assemblies_type) } let(:query) { %({ assembliesTypes { id }}) } it "returns all the assembliesType" do - expect(response["assembliesTypes"]).to include("id" => assemblies_type_1.id.to_s) - expect(response["assembliesTypes"]).to include("id" => assemblies_type_2.id.to_s) - expect(response["assembliesTypes"]).not_to include("id" => assemblies_type_3.id.to_s) + expect(response["assembliesTypes"]).to include("id" => assemblies_type1.id.to_s) + expect(response["assembliesTypes"]).to include("id" => assemblies_type2.id.to_s) + expect(response["assembliesTypes"]).not_to include("id" => assemblies_type3.id.to_s) end end diff --git a/decidim-assemblies/spec/permissions/decidim/assemblies/permissions_spec.rb b/decidim-assemblies/spec/permissions/decidim/assemblies/permissions_spec.rb index f14464a86f1bd..19b66fd7e7be4 100644 --- a/decidim-assemblies/spec/permissions/decidim/assemblies/permissions_spec.rb +++ b/decidim-assemblies/spec/permissions/decidim/assemblies/permissions_spec.rb @@ -11,7 +11,7 @@ let(:assemblies_setting) { create :assemblies_setting, organization: organization } let(:assembly) { create :assembly, organization: organization, assembly_type: assembly_type } let(:context) { {} } - let(:permission_action) { Decidim::PermissionAction.new(action) } + let(:permission_action) { Decidim::PermissionAction.new(**action) } let(:assembly_admin) { create :assembly_admin, assembly: assembly } let(:assembly_collaborator) { create :assembly_collaborator, assembly: assembly } let(:assembly_moderator) { create :assembly_moderator, assembly: assembly } @@ -20,11 +20,11 @@ shared_examples "access for role" do |access| case access when true - it { is_expected.to eq true } + it { is_expected.to be true } when :not_set it_behaves_like "permission is not set" else - it { is_expected.to eq false } + it { is_expected.to be false } end end @@ -74,6 +74,23 @@ ) end + context "when accessing global moderation" do + subject { Decidim::Admin::Permissions.new(user, permission_action, context).permissions.allowed? } + + let(:action) do + { scope: :admin, action: :read, subject: :global_moderation } + end + + it_behaves_like( + "access for roles", + org_admin: true, + admin: true, + collaborator: false, + moderator: true, + valuator: false + ) + end + context "when reading a assembly" do let(:action) do { scope: :public, action: :read, subject: :assembly } @@ -83,13 +100,13 @@ context "when the user is an admin" do let(:user) { create :user, :admin } - it { is_expected.to eq true } + it { is_expected.to be true } end context "when the assembly is published" do let(:user) { create :user, organization: organization } - it { is_expected.to eq true } + it { is_expected.to be true } end context "when the assembly is not published" do @@ -97,7 +114,7 @@ let(:assembly) { create :assembly, :unpublished, organization: organization } context "when the user doesn't have access to it" do - it { is_expected.to eq false } + it { is_expected.to be false } end context "when the user has access to it" do @@ -105,7 +122,7 @@ create :assembly_user_role, user: user, assembly: assembly end - it { is_expected.to eq true } + it { is_expected.to be true } end end end @@ -115,7 +132,7 @@ { scope: :public, action: :list, subject: :assembly } end - it { is_expected.to eq true } + it { is_expected.to be true } end context "when listing assembly members" do @@ -123,7 +140,7 @@ { scope: :public, action: :list, subject: :members } end - it { is_expected.to eq true } + it { is_expected.to be true } end context "when any other action" do @@ -269,6 +286,36 @@ { scope: :admin, action: :create, subject: :assembly } end + it_behaves_like( + "access for roles", + org_admin: true, + admin: true, + collaborator: false, + moderator: false, + valuator: false + ) + end + + context "when exporting an assembly" do + let(:action) do + { scope: :admin, action: :export, subject: :assembly } + end + + it_behaves_like( + "access for roles", + org_admin: true, + admin: false, + collaborator: false, + moderator: false, + valuator: false + ) + end + + context "when copying an assembly" do + let(:action) do + { scope: :admin, action: :copy, subject: :assembly } + end + it_behaves_like( "access for roles", org_admin: true, @@ -335,7 +382,7 @@ { scope: :admin, action: :read, subject: :dummy } end - it { is_expected.to eq true } + it { is_expected.to be true } end context "when action is :preview" do @@ -343,7 +390,7 @@ { scope: :admin, action: :preview, subject: :dummy } end - it { is_expected.to eq true } + it { is_expected.to be true } end context "when action is a random one" do @@ -363,7 +410,7 @@ { scope: :admin, action: :create, subject: :assembly } end - it { is_expected.to eq false } + it { is_expected.to be true } end shared_examples "allows any action on subject" do |action_subject| @@ -372,7 +419,7 @@ { scope: :admin, action: :foo, subject: action_subject } end - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -393,7 +440,7 @@ { scope: :admin, action: :create, subject: :assembly } end - it { is_expected.to eq true } + it { is_expected.to be true } end shared_examples "allows any action on subject" do |action_subject| @@ -402,7 +449,7 @@ { scope: :admin, action: :foo, subject: action_subject } end - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -425,7 +472,7 @@ { scope: :admin, action: :index, subject: :assembly_type } end - it { is_expected.to eq true } + it { is_expected.to be true } end context "when action is :create" do @@ -433,7 +480,7 @@ { scope: :admin, action: :create, subject: :assembly_type } end - it { is_expected.to eq true } + it { is_expected.to be true } end context "when action is :edit" do @@ -441,7 +488,7 @@ { scope: :admin, action: :edit, subject: :assembly_type } end - it { is_expected.to eq true } + it { is_expected.to be true } end context "when action is :destroy" do @@ -453,13 +500,13 @@ context "and assembly type has children" do let!(:assembly) { create :assembly, organization: organization, assembly_type: assembly_type } - it { is_expected.to eq false } + it { is_expected.to be false } end context "and assembly type has no children" do let(:assembly) { create :assembly, organization: organization } - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -470,7 +517,7 @@ { scope: :admin, action: :create, subject: :assembly_type } end - it { is_expected.to eq false } + it { is_expected.to be false } end context "when listing assemblies list" do @@ -486,7 +533,7 @@ { scope: :admin, action: :list, subject: :assembly } end - it { is_expected.to eq(true) } + it { is_expected.to be(true) } end context "when the assembly has one ancestor" do @@ -499,7 +546,7 @@ { scope: :admin, action: :list, subject: :assembly } end - it { is_expected.to eq(true) } + it { is_expected.to be(true) } end context "when the assembly has more than one ancestor" do @@ -513,10 +560,10 @@ { scope: :admin, action: :list, subject: :assembly } end - it { is_expected.to eq(true) } + it { is_expected.to be(true) } end - context "when the assembly has one ancestor" do + context "when the assembly has one sucessor" do before do create :assembly_user_role, user: user, assembly: assembly.parent end @@ -526,7 +573,105 @@ { scope: :admin, action: :list, subject: :assembly } end - it { is_expected.to eq(false) } + it { is_expected.to be(true) } + end + end + end + + describe "when acting with assemblies admins and children assemblies" do + let!(:user) { create :assembly_admin, assembly: mother_assembly } + let(:mother_assembly) { create :assembly, parent: assembly, organization: organization, hashtag: "mother" } + let(:child_assembly) { create :assembly, parent: mother_assembly, organization: organization, hashtag: "child" } + + context "when assembly is a grandmother assembly" do + let(:context) { { assembly: assembly } } + + context "and action is :list" do + let(:action) do + { scope: :admin, action: :list, subject: :assembly } + end + + it { is_expected.to be(true) } + end + + context "and action is :export" do + let(:action) do + { scope: :admin, action: :export, subject: :assembly } + end + + it { is_expected.to be(false) } + end + + context "and action is :copy" do + let(:action) do + { scope: :admin, action: :copy, subject: :assembly } + end + + it { is_expected.to be(false) } + end + end + + context "when assembly is a mother assembly" do + let(:context) { { assembly: mother_assembly } } + + context "and action is :list" do + let(:action) do + { scope: :admin, action: :list, subject: :assembly } + end + + it { is_expected.to be(true) } + end + + context "and action is :export" do + let(:action) do + { scope: :admin, action: :export, subject: :assembly } + end + + it { is_expected.to be(true) } + end + + context "and action is :copy" do + let(:action) do + { scope: :admin, action: :copy, subject: :assembly } + end + + it { is_expected.to be(true) } + end + end + + context "when assembly is a child assembly" do + let(:context) { { assembly: child_assembly } } + + context "and action is :list" do + let(:action) do + { scope: :admin, action: :list, subject: :assembly } + end + + it { is_expected.to be(true) } + end + + context "and action is :export" do + let(:action) do + { scope: :admin, action: :export, subject: :assembly } + end + + it { is_expected.to be(true) } + end + + context "and action is :copy" do + let(:action) do + { scope: :admin, action: :copy, subject: :assembly } + end + + it { is_expected.to be(true) } + end + + context "and action is :read the current assembly" do + let(:action) do + { scope: :admin, action: :read, subject: :assembly } + end + + it { is_expected.to be(true) } end end end diff --git a/decidim-assemblies/spec/presenters/decidim/assemblies/assembly_presenter_spec.rb b/decidim-assemblies/spec/presenters/decidim/assemblies/assembly_presenter_spec.rb index c384b5d7870b7..0004a7807393d 100644 --- a/decidim-assemblies/spec/presenters/decidim/assemblies/assembly_presenter_spec.rb +++ b/decidim-assemblies/spec/presenters/decidim/assemblies/assembly_presenter_spec.rb @@ -26,11 +26,11 @@ module Decidim describe "when images are attached" do it "resolves hero_image_url" do - expect(subject.hero_image_url).to eq("http://#{organization_host}#{assembly.attached_uploader(:hero_image).path}") + expect(subject.hero_image_url).to eq("http://#{organization_host}:#{Capybara.server_port}#{assembly.attached_uploader(:hero_image).path}") end it "resolves banner_image_url" do - expect(subject.banner_image_url).to eq("http://#{organization_host}#{assembly.attached_uploader(:banner_image).path}") + expect(subject.banner_image_url).to eq("http://#{organization_host}:#{Capybara.server_port}#{assembly.attached_uploader(:banner_image).path}") end end end diff --git a/decidim-assemblies/spec/presenters/decidim/assembly_member_presenter_spec.rb b/decidim-assemblies/spec/presenters/decidim/assembly_member_presenter_spec.rb index 322cce4e86b88..752aa95708fc8 100644 --- a/decidim-assemblies/spec/presenters/decidim/assembly_member_presenter_spec.rb +++ b/decidim-assemblies/spec/presenters/decidim/assembly_member_presenter_spec.rb @@ -121,7 +121,7 @@ module Decidim context "when a image is attached" do let(:non_user_avatar) do - ActiveStorage::Blob.create_after_upload!( + ActiveStorage::Blob.create_and_upload!( io: File.open(Decidim::Dev.asset("avatar.jpg")), filename: "avatar.jpeg", content_type: "image/jpeg" diff --git a/decidim-assemblies/spec/requests/assembly_search_spec.rb b/decidim-assemblies/spec/requests/assembly_search_spec.rb new file mode 100644 index 0000000000000..8d78fee74b3f0 --- /dev/null +++ b/decidim-assemblies/spec/requests/assembly_search_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "Assembly search", type: :request do + subject { response.body } + + let(:organization) { create(:organization) } + let!(:assembly1) do + create( + :assembly, + organization: organization, + assembly_type: create(:assemblies_type, organization: organization), + area: create(:area, organization: organization), + scope: create(:scope, organization: organization) + ) + end + let!(:assembly2) do + create( + :assembly, + organization: organization, + assembly_type: create(:assemblies_type, organization: organization), + area: create(:area, organization: organization), + scope: create(:scope, organization: organization) + ) + end + + let(:filter_params) { {} } + let(:request_path) { decidim_assemblies.assemblies_path } + + before do + get( + request_path, + params: { filter: filter_params }, + headers: { "HOST" => organization.host } + ) + end + + it "displays all assemblies by default" do + expect(subject).to include(translated(assembly1.title)) + expect(subject).to include(translated(assembly2.title)) + end + + context "when filtering by assembly type" do + let(:filter_params) { { type_id_eq: assembly1.assembly_type.id } } + + it "displays matching assemblies" do + expect(subject).to include(translated(assembly1.title)) + expect(subject).not_to include(translated(assembly2.title)) + end + end + + context "when filtering by area" do + let(:filter_params) { { with_area: assembly1.area.id } } + + it "displays matching assemblies" do + expect(subject).to include(translated(assembly1.title)) + expect(subject).not_to include(translated(assembly2.title)) + end + end + + context "when filtering by scope" do + let(:filter_params) { { with_scope: assembly1.scope.id } } + + it "displays matching assemblies" do + expect(subject).to include(translated(assembly1.title)) + expect(subject).not_to include(translated(assembly2.title)) + end + end +end diff --git a/decidim-assemblies/spec/serializers/decidim/assemblies/assembly_serializer_spec.rb b/decidim-assemblies/spec/serializers/decidim/assemblies/assembly_serializer_spec.rb index 81fe80fd5653e..e1363f2a21feb 100644 --- a/decidim-assemblies/spec/serializers/decidim/assemblies/assembly_serializer_spec.rb +++ b/decidim-assemblies/spec/serializers/decidim/assemblies/assembly_serializer_spec.rb @@ -5,7 +5,8 @@ module Decidim::Assemblies describe AssemblySerializer do let(:resource) { create(:assembly) } - let(:subject) { described_class.new(resource) } + + subject { described_class.new(resource) } describe "#serialize" do it "includes the assembly data" do diff --git a/decidim-assemblies/spec/services/decidim/assemblies/searchable_assembly_resource_spec.rb b/decidim-assemblies/spec/services/decidim/assemblies/searchable_assembly_resource_spec.rb index bf4cb11e805ae..819afb6b00bdf 100644 --- a/decidim-assemblies/spec/services/decidim/assemblies/searchable_assembly_resource_spec.rb +++ b/decidim-assemblies/spec/services/decidim/assemblies/searchable_assembly_resource_spec.rb @@ -14,7 +14,7 @@ module Decidim title: Decidim::Faker::Localized.name, subtitle: Decidim::Faker::Localized.name, short_description: Decidim::Faker::Localized.sentence, - description: description_1, + description: description1, users: [author] ) end @@ -27,7 +27,7 @@ module Decidim title: Decidim::Faker::Localized.name, subtitle: Decidim::Faker::Localized.name, short_description: Decidim::Faker::Localized.sentence, - description: description_2, + description: description2, users: [author] ) end diff --git a/decidim-assemblies/spec/shared/assembly_admin_manage_assembly_components_examples.rb b/decidim-assemblies/spec/shared/assembly_admin_manage_assembly_components_examples.rb new file mode 100644 index 0000000000000..6fe823375b1d7 --- /dev/null +++ b/decidim-assemblies/spec/shared/assembly_admin_manage_assembly_components_examples.rb @@ -0,0 +1,221 @@ +# frozen_string_literal: true + +shared_examples "assembly admin manage assembly components" do + before do + switch_to_host(organization.host) + login_as user, scope: :user + end + + describe "add a component" do + before do + visit decidim_admin_assemblies.components_path(assembly) + + find("button[data-toggle=add-component-dropdown]").click + + within "#add-component-dropdown" do + find(".dummy").click + end + + within ".new_component" do + fill_in_i18n( + :component_name, + "#component-name-tabs", + en: "My component", + ca: "La meva funcionalitat", + es: "Mi funcionalitat" + ) + + within ".global-settings" do + fill_in_i18n_editor( + :component_settings_dummy_global_translatable_text, + "#global-settings-dummy_global_translatable_text-tabs", + en: "Dummy Text" + ) + all("input[type=checkbox]").last.click + end + + within ".default-step-settings" do + fill_in_i18n_editor( + :component_default_step_settings_dummy_step_translatable_text, + "#default-step-settings-dummy_step_translatable_text-tabs", + en: "Dummy Text for Step" + ) + all("input[type=checkbox]").first.click + end + + click_button "Add component" + end + end + + it "is successfully created" do + expect(page).to have_admin_callout("successfully") + expect(page).to have_content("My component") + end + + context "and then edit it" do + before do + within find("tr", text: "My component") do + click_link "Configure" + end + end + + it "successfully displays initial values in the form" do + within ".global-settings" do + expect(all("input[type=checkbox]").last).to be_checked + end + + within ".default-step-settings" do + expect(all("input[type=checkbox]").first).to be_checked + end + end + + it "successfully edits it" do + click_button "Update" + + expect(page).to have_admin_callout("successfully") + end + end + end + + describe "edit a component" do + let(:component_name) do + { + en: "My component", + ca: "La meva funcionalitat", + es: "Mi funcionalitat" + } + end + + let!(:component) do + create(:component, name: component_name, participatory_space: assembly) + end + + before do + visit decidim_admin_assemblies.components_path(assembly) + end + + it "updates the component" do + within ".component-#{component.id}" do + click_link "Configure" + end + + within ".edit_component" do + fill_in_i18n( + :component_name, + "#component-name-tabs", + en: "My updated component", + ca: "La meva funcionalitat actualitzada", + es: "Mi funcionalidad actualizada" + ) + + within ".global-settings" do + all("input[type=checkbox]").last.click + end + + within ".default-step-settings" do + all("input[type=checkbox]").first.click + end + + click_button "Update" + end + + expect(page).to have_admin_callout("successfully") + expect(page).to have_content("My updated component") + + within find("tr", text: "My updated component") do + click_link "Configure" + end + + within ".global-settings" do + expect(all("input[type=checkbox]").last).to be_checked + end + + within ".default-step-settings" do + expect(all("input[type=checkbox]").first).to be_checked + end + end + end + + describe "remove a component" do + let(:component_name) do + { + en: "My component", + ca: "La meva funcionalitat", + es: "Mi funcionalitat" + } + end + + let!(:component) do + create(:component, name: component_name, participatory_space: assembly) + end + + before do + visit decidim_admin_assemblies.components_path(assembly) + end + + it "removes the component" do + within ".component-#{component.id}" do + click_link "Delete" + end + + expect(page).to have_no_content("My component") + end + end + + describe "publish and unpublish a component" do + let!(:component) do + create(:component, participatory_space: assembly, published_at: published_at) + end + + let(:published_at) { nil } + + before do + visit decidim_admin_assemblies.components_path(assembly) + end + + context "when the component is unpublished" do + it "publishes the component" do + within ".component-#{component.id}" do + click_link "Publish" + end + + within ".component-#{component.id}" do + expect(page).to have_css(".action-icon--unpublish") + end + end + + it "notifies its followers" do + follower = create(:user, organization: assembly.organization) + create(:follow, followable: assembly, user: follower) + + within ".component-#{component.id}" do + click_link "Publish" + end + + expect(enqueued_jobs.last[:args]).to include("decidim.events.components.component_published") + end + end + + context "when the component is published" do + let(:published_at) { Time.current } + + it "unpublishes the component" do + within ".component-#{component.id}" do + click_link "Unpublish" + end + + within ".component-#{component.id}" do + expect(page).to have_css(".action-icon--publish") + end + end + end + end + + def participatory_space + assembly + end + + def participatory_space_components_path(participatory_space) + decidim_admin_assemblies.components_path(participatory_space) + end +end diff --git a/decidim-assemblies/spec/shared/manage_assemblies_examples.rb b/decidim-assemblies/spec/shared/manage_assemblies_examples.rb index d678fdf7f193f..d5830b517e005 100644 --- a/decidim-assemblies/spec/shared/manage_assemblies_examples.rb +++ b/decidim-assemblies/spec/shared/manage_assemblies_examples.rb @@ -20,7 +20,7 @@ ca: "El meu nou títol" ) - attach_file :assembly_banner_image, image3_path + dynamically_attach_file(:assembly_banner_image, image3_path, remove_before: true) within ".edit_assembly" do expect(assembly_parent_id_options).not_to include(assembly.id) diff --git a/decidim-assemblies/spec/shared/manage_assembly_members_examples.rb b/decidim-assemblies/spec/shared/manage_assembly_members_examples.rb index 6e3c572751eb5..400def2c49796 100644 --- a/decidim-assemblies/spec/shared/manage_assembly_members_examples.rb +++ b/decidim-assemblies/spec/shared/manage_assembly_members_examples.rb @@ -18,15 +18,17 @@ find(".datepicker-days .active").click within ".new_assembly_member" do - expect(page).to have_content("You should get the consent of the persons before publishing them as a member") - fill_in( :assembly_member_full_name, with: "Daisy O'connor" ) + end - attach_file "Avatar", Decidim::Dev.asset("avatar.jpg") + dynamically_attach_file(:assembly_member_non_user_avatar, Decidim::Dev.asset("avatar.jpg")) do + expect(page).to have_content("You should get the consent of the persons before publishing them as a member") + end + within ".new_assembly_member" do select "President", from: :assembly_member_position find("*[type=submit]").click diff --git a/decidim-assemblies/spec/shared/manage_assembly_private_users_examples.rb b/decidim-assemblies/spec/shared/manage_assembly_private_users_examples.rb index d5f714b38f966..756a7b4a14910 100644 --- a/decidim-assemblies/spec/shared/manage_assembly_private_users_examples.rb +++ b/decidim-assemblies/spec/shared/manage_assembly_private_users_examples.rb @@ -42,7 +42,7 @@ # The CSV has no headers expect(Decidim::Admin::ImportParticipatorySpacePrivateUserCsvJob).to receive(:perform_later).once.ordered.with("my_user@example.org", "My User Name", assembly, user) expect(Decidim::Admin::ImportParticipatorySpacePrivateUserCsvJob).to receive(:perform_later).once.ordered.with("my_private_user@example.org", "My Private User Name", assembly, user) - attach_file "File", Decidim::Dev.asset("import_participatory_space_private_users.csv") + dynamically_attach_file(:participatory_space_private_user_csv_import_file, Decidim::Dev.asset("import_participatory_space_private_users.csv")) perform_enqueued_jobs { click_button "Upload" } expect(page).to have_content("CSV file uploaded successfully") diff --git a/decidim-assemblies/spec/system/admin/admin_filters_assemblies_private_space_users_spec.rb b/decidim-assemblies/spec/system/admin/admin_filters_assemblies_private_space_users_spec.rb index 4eb6845c8a48b..e33f4167c049c 100644 --- a/decidim-assemblies/spec/system/admin/admin_filters_assemblies_private_space_users_spec.rb +++ b/decidim-assemblies/spec/system/admin/admin_filters_assemblies_private_space_users_spec.rb @@ -9,10 +9,10 @@ let!(:user) { create(:user, :admin, :confirmed, organization: organization) } let(:assembly) { create(:assembly, organization: organization) } - let!(:invited_user_1) { create(:user, name: name, organization: organization) } - let!(:invited_private_user_1) { create :assembly_private_user, user: invited_user_1, privatable_to: assembly } - let!(:invited_user_2) { create(:user, email: email, organization: organization) } - let!(:invited_private_user_2) { create :assembly_private_user, user: invited_user_2, privatable_to: assembly } + let!(:invited_user1) { create(:user, name: name, organization: organization) } + let!(:invited_private_user1) { create :assembly_private_user, user: invited_user1, privatable_to: assembly } + let!(:invited_user2) { create(:user, email: email, organization: organization) } + let!(:invited_private_user2) { create :assembly_private_user, user: invited_user2, privatable_to: assembly } let(:name) { "Dummy Name" } let(:email) { "dummy_email@example.org" } @@ -20,7 +20,7 @@ let(:resource_controller) { Decidim::Assemblies::Admin::ParticipatorySpacePrivateUsersController } before do - invited_user_1.update!(invitation_sent_at: Time.current - 1.day, invitation_accepted_at: Time.current) + invited_user1.update!(invitation_sent_at: 1.day.ago, invitation_accepted_at: Time.current) switch_to_host(organization.host) login_as user, scope: :user diff --git a/decidim-assemblies/spec/system/admin/admin_filters_assemblies_user_roles_spec.rb b/decidim-assemblies/spec/system/admin/admin_filters_assemblies_user_roles_spec.rb index 62a921bd43c25..9a53d609ddd27 100644 --- a/decidim-assemblies/spec/system/admin/admin_filters_assemblies_user_roles_spec.rb +++ b/decidim-assemblies/spec/system/admin/admin_filters_assemblies_user_roles_spec.rb @@ -11,11 +11,11 @@ let(:name) { "Dummy Name" } let(:email) { "dummy_email@example.org" } - let!(:invited_user_1) { create(:assembly_valuator, name: name, assembly: assembly) } - let!(:invited_user_2) { create(:assembly_valuator, email: email, assembly: assembly) } + let!(:invited_user1) { create(:assembly_valuator, name: name, assembly: assembly) } + let!(:invited_user2) { create(:assembly_valuator, email: email, assembly: assembly) } before do - invited_user_2.update!(invitation_sent_at: Time.current - 1.day, invitation_accepted_at: Time.current, last_sign_in_at: Time.current) + invited_user2.update!(invitation_sent_at: 1.day.ago, invitation_accepted_at: Time.current, last_sign_in_at: Time.current) switch_to_host(organization.host) login_as admin, scope: :user @@ -36,6 +36,7 @@ let!(:user) do create(:assembly_valuator, name: "ZZZupper user", + email: "zzz@example.org", assembly: assembly, last_sign_in_at: 30.seconds.ago, invitation_accepted_at: Time.current) diff --git a/decidim-assemblies/spec/system/admin/admin_imports_assembly_spec.rb b/decidim-assemblies/spec/system/admin/admin_imports_assembly_spec.rb index af31d427790d0..13c395b142267 100644 --- a/decidim-assemblies/spec/system/admin/admin_imports_assembly_spec.rb +++ b/decidim-assemblies/spec/system/admin/admin_imports_assembly_spec.rb @@ -41,9 +41,9 @@ ca: "Importació de l'asamblea" ) fill_in :assembly_slug, with: "as-import" - attach_file :assembly_document, Decidim::Dev.asset("assemblies.json") end + dynamically_attach_file(:assembly_document, Decidim::Dev.asset("assemblies.json")) click_button "Import" end diff --git a/decidim-assemblies/spec/system/admin/admin_manages_assemblies_spec.rb b/decidim-assemblies/spec/system/admin/admin_manages_assemblies_spec.rb index e9c269267145e..6fc293f713518 100644 --- a/decidim-assemblies/spec/system/admin/admin_manages_assemblies_spec.rb +++ b/decidim-assemblies/spec/system/admin/admin_manages_assemblies_spec.rb @@ -53,9 +53,12 @@ fill_in :assembly_slug, with: "slug" fill_in :assembly_hashtag, with: "#hashtag" fill_in :assembly_weight, with: 1 - attach_file :assembly_hero_image, image1_path - attach_file :assembly_banner_image, image2_path + end + + dynamically_attach_file(:assembly_hero_image, image1_path) + dynamically_attach_file(:assembly_banner_image, image2_path) + within ".new_assembly" do find("*[type=submit]").click end @@ -89,15 +92,15 @@ context "when filtering by assemblies type" do include_context "with filterable context" - let!(:assemblies_type_1) { create(:assemblies_type) } - let!(:assemblies_type_2) { create(:assemblies_type) } + let!(:assemblies_type1) { create(:assemblies_type) } + let!(:assemblies_type2) { create(:assemblies_type) } Decidim::AssembliesType.all.each do |assemblies_type| i18n_assemblies_type = assemblies_type.name[I18n.locale.to_s] context "filtering collection by assemblies_type: #{i18n_assemblies_type}" do - let!(:assembly_1) { create(:assembly, organization: organization, assemblies_type: assemblies_type_1) } - let!(:assembly_2) { create(:assembly, organization: organization, assemblies_type: assemblies_type_2) } + let!(:assembly1) { create(:assembly, organization: organization, assemblies_type: assemblies_type1) } + let!(:assembly2) { create(:assembly, organization: organization, assemblies_type: assemblies_type2) } it_behaves_like "a filtered collection", options: "Assembly type", filter: i18n_assemblies_type do let(:in_filter) { translated(assembly_with_type(type).title) } diff --git a/decidim-assemblies/spec/system/admin/admin_manages_assemblies_with_parent_selector_spec.rb b/decidim-assemblies/spec/system/admin/admin_manages_assemblies_with_parent_selector_spec.rb index 1aa869fc5c850..4fecdfc735be8 100644 --- a/decidim-assemblies/spec/system/admin/admin_manages_assemblies_with_parent_selector_spec.rb +++ b/decidim-assemblies/spec/system/admin/admin_manages_assemblies_with_parent_selector_spec.rb @@ -57,9 +57,12 @@ fill_in :assembly_slug, with: "slug" fill_in :assembly_hashtag, with: "#hashtag" fill_in :assembly_weight, with: 1 - attach_file :assembly_hero_image, image1_path - attach_file :assembly_banner_image, image2_path + end + + dynamically_attach_file(:assembly_hero_image, image1_path) + dynamically_attach_file(:assembly_banner_image, image2_path) + within ".new_assembly" do find("*[type=submit]").click end @@ -116,9 +119,12 @@ fill_in :assembly_slug, with: "slug" fill_in :assembly_hashtag, with: "#hashtag" fill_in :assembly_weight, with: 1 - attach_file :assembly_hero_image, image1_path - attach_file :assembly_banner_image, image2_path + end + + dynamically_attach_file(:assembly_hero_image, image1_path) + dynamically_attach_file(:assembly_banner_image, image2_path) + within ".new_assembly" do find("*[type=submit]").click end diff --git a/decidim-assemblies/spec/system/admin/assembly_admin_accesses_admin_sections_spec.rb b/decidim-assemblies/spec/system/admin/assembly_admin_accesses_admin_sections_spec.rb index 9f17d789840c0..b81b2b9ab82ae 100644 --- a/decidim-assemblies/spec/system/admin/assembly_admin_accesses_admin_sections_spec.rb +++ b/decidim-assemblies/spec/system/admin/assembly_admin_accesses_admin_sections_spec.rb @@ -8,23 +8,55 @@ before do switch_to_host(organization.host) login_as user, scope: :user - visit decidim_admin_assemblies.assemblies_path + end + + context "when is a mother assembly" do + it "can access all sections" do + visit decidim_admin_assemblies.assemblies_path + click_link translated(assembly.title) - click_link translated(assembly.title) + within ".secondary-nav" do + expect(page).to have_content("Info") + expect(page).to have_content("Components") + expect(page).to have_content("Categories") + expect(page).to have_content("Attachments") + expect(page).to have_content("Folders") + expect(page).to have_content("Files") + expect(page).to have_content("Members") + expect(page).to have_content("Assembly admins") + expect(page).to have_content("Private users") + expect(page).to have_content("Moderations") + end + end end - it "can access all sections" do - within ".secondary-nav" do - expect(page).to have_content("Info") - expect(page).to have_content("Components") - expect(page).to have_content("Categories") - expect(page).to have_content("Attachments") - expect(page).to have_content("Folders") - expect(page).to have_content("Files") - expect(page).to have_content("Members") - expect(page).to have_content("Assembly admins") - expect(page).to have_content("Private users") - expect(page).to have_content("Moderations") + context "when is a child assembly" do + let!(:child_assembly) { create :assembly, parent: assembly, organization: organization, hashtag: "child" } + + before do + visit decidim_admin_assemblies.assemblies_path + within find("tr", text: translated(assembly.title)) do + click_link "Assemblies" + end + + click_link translated(child_assembly.title) + end + + it "can access all sections" do + within ".secondary-nav" do + expect(page).to have_content("Info") + expect(page).to have_content("Components") + expect(page).to have_content("Categories") + expect(page).to have_content("Attachments") + expect(page).to have_content("Folders") + expect(page).to have_content("Files") + expect(page).to have_content("Members") + expect(page).to have_content("Assembly admins") + expect(page).to have_content("Private users") + expect(page).to have_content("Moderations") + end end + + it_behaves_like "assembly admin manage assembly components" end end diff --git a/decidim-assemblies/spec/system/admin/assembly_moderator_manages_assembly_moderations_spec.rb b/decidim-assemblies/spec/system/admin/assembly_moderator_manages_assembly_moderations_spec.rb index e95f864e9ffa8..909f7247d3683 100644 --- a/decidim-assemblies/spec/system/admin/assembly_moderator_manages_assembly_moderations_spec.rb +++ b/decidim-assemblies/spec/system/admin/assembly_moderator_manages_assembly_moderations_spec.rb @@ -17,4 +17,8 @@ end it_behaves_like "manage moderations" + + it_behaves_like "sorted moderations" do + let!(:reportables) { create_list(:dummy_resource, 17, component: current_component) } + end end diff --git a/decidim-assemblies/spec/system/assemblies_spec.rb b/decidim-assemblies/spec/system/assemblies_spec.rb index 18b31e2005146..955b7ae0a26d2 100644 --- a/decidim-assemblies/spec/system/assemblies_spec.rb +++ b/decidim-assemblies/spec/system/assemblies_spec.rb @@ -6,12 +6,13 @@ describe "Assemblies", type: :system do let(:organization) { create(:organization) } let(:show_statistics) { true } + let(:base_description) { { en: "Description", ca: "Descripció", es: "Descripción" } } let(:base_assembly) do create( :assembly, :with_type, organization: organization, - description: { en: "Description", ca: "Descripció", es: "Descripción" }, + description: base_description, short_description: { en: "Short description", ca: "Descripció curta", es: "Descripción corta" }, show_statistics: show_statistics ) @@ -156,7 +157,7 @@ let(:target_path) { decidim_assemblies.assembly_path(assembly) } end - context "and requesting the assebly path" do + context "and requesting the assembly path" do before do visit decidim_assemblies.assembly_path(assembly) end @@ -181,6 +182,8 @@ let(:attached_to) { assembly } end + it_behaves_like "has embedded video in description", :base_description + context "when the assembly has some components" do it "shows the components" do within ".process-nav" do @@ -234,6 +237,34 @@ expect(page).to have_selector("#assemblies-grid .row .column:first-child", text: child_assembly.title[:en]) expect(page).to have_selector("#assemblies-grid .row .column:last-child", text: second_child_assembly.title[:en]) end + + context "when child assembly has a meeting" do + let(:meetings_component) { create(:meeting_component, :published, participatory_space: child_assembly) } + + context "with unpublished meeting" do + let!(:meeting) { create(:meeting, :upcoming, component: meetings_component) } + + it "is not displaying the widget" do + visit decidim_assemblies.assembly_path(assembly) + + within("#assemblies-grid") do + expect(page).not_to have_content("Upcoming meeting") + end + end + end + + context "with published meeting" do + let!(:meeting) { create(:meeting, :upcoming, :published, component: meetings_component) } + + it "is displaying the widget" do + visit decidim_assemblies.assembly_path(assembly) + + within("#assemblies-grid") do + expect(page).to have_content("Upcoming meeting") + end + end + end + end end context "when the assembly has children private and transparent assemblies" do diff --git a/decidim-assemblies/spec/system/filter_assemblies_spec.rb b/decidim-assemblies/spec/system/filter_assemblies_spec.rb index fc4cd4371c23d..6f36ec476c8d7 100644 --- a/decidim-assemblies/spec/system/filter_assemblies_spec.rb +++ b/decidim-assemblies/spec/system/filter_assemblies_spec.rb @@ -33,6 +33,20 @@ end end + context "when no assemblies types present" do + let!(:assemblies) { create_list(:assembly, 3, organization: organization) } + + before do + visit decidim_assemblies.assemblies_path + end + + it "doesn't show the assemblies types filter" do + within("#assemblies-filter") do + expect(page).to have_no_content("All types") + end + end + end + context "when filtering parent assemblies by scope" do let!(:scope) { create :scope, organization: organization } let!(:assembly_with_scope) { create(:assembly, scope: scope, organization: organization) } @@ -40,7 +54,7 @@ context "and choosing a scope" do before do - visit decidim_assemblies.assemblies_path(filter: { scope_id: scope.id }) + visit decidim_assemblies.assemblies_path(filter: { with_scope: scope.id }) end it "lists all processes belonging to that scope" do @@ -63,7 +77,7 @@ context "and choosing an area" do before do - select translated(area.name), from: "filter[area_id]" + select translated(area.name), from: "filter[with_area]" end it "lists all processes belonging to that area" do diff --git a/decidim-assemblies/spec/system/private_assemblies_spec.rb b/decidim-assemblies/spec/system/private_assemblies_spec.rb index 04e2b4eee09ab..7db4e698f0914 100644 --- a/decidim-assemblies/spec/system/private_assemblies_spec.rb +++ b/decidim-assemblies/spec/system/private_assemblies_spec.rb @@ -8,15 +8,15 @@ let!(:admin) { create(:user, :admin, :confirmed, organization: organization) } let!(:user) { create :user, :confirmed, organization: organization } let!(:other_user) { create :user, :confirmed, organization: organization } - let!(:other_user_2) { create :user, :confirmed, organization: organization } + let!(:other_user2) { create :user, :confirmed, organization: organization } let!(:assembly_private_user) { create :assembly_private_user, user: other_user, privatable_to: private_assembly } - let!(:assembly_private_user_2) { create :assembly_private_user, user: other_user_2, privatable_to: private_assembly } + let!(:assembly_private_user2) { create :assembly_private_user, user: other_user2, privatable_to: private_assembly } context "when there are private assemblies" do context "and the assembly is transparent" do let!(:private_assembly) { create :assembly, :published, organization: organization, private_space: true, is_transparent: true } - context "and no user is loged in" do + context "and no user is logged in" do before do switch_to_host(organization.host) visit decidim_assemblies.assemblies_path @@ -36,23 +36,40 @@ end end - context "when user is loged in and is not a assembly private user" do - before do - switch_to_host(organization.host) - login_as user, scope: :user - visit decidim_assemblies.assemblies_path - end + context "when user is logged in" do + context "when is not an assembly private user" do + before do + switch_to_host(organization.host) + login_as user, scope: :user + visit decidim_assemblies.assemblies_path + end - it "lists all the assemblies" do - within "#parent-assemblies" do - within "#parent-assemblies h3" do - expect(page).to have_content("2") + it "lists all the assemblies" do + within "#parent-assemblies" do + within "#parent-assemblies h3" do + expect(page).to have_content("2") + end + + expect(page).to have_content(translated(assembly.title, locale: :en)) + expect(page).to have_selector(".card--assembly", count: 2) + + expect(page).to have_content(translated(private_assembly.title, locale: :en)) end + end + end - expect(page).to have_content(translated(assembly.title, locale: :en)) - expect(page).to have_selector(".card--assembly", count: 2) + context "when the user is admin" do + before do + switch_to_host(organization.host) + login_as admin, scope: :user + visit decidim_assemblies.assemblies_path + end - expect(page).to have_content(translated(private_assembly.title, locale: :en)) + it "doesn't show the privacy warning in attachments admin" do + visit decidim_admin_assemblies.assembly_attachments_path(private_assembly) + within "#attachments" do + expect(page).to have_no_content("Any participant could share this document to others") + end end end end @@ -61,13 +78,13 @@ context "when the assembly is not transparent" do let!(:private_assembly) { create :assembly, :published, organization: organization, private_space: true, is_transparent: false } - context "and no user is loged in" do + context "and no user is logged in" do before do switch_to_host(organization.host) visit decidim_assemblies.assemblies_path end - it "lists only the not private assembly" do + it "doesn't list the private assembly" do within "#parent-assemblies" do within "#parent-assemblies h3" do expect(page).to have_content("1") @@ -81,17 +98,15 @@ end end - context "when user is loged in and is not a assembly private user" do - before do - switch_to_host(organization.host) - login_as logged_in_user, scope: :user - visit decidim_assemblies.assemblies_path - end - - context "when the user is admin" do - let(:logged_in_user) { user } + context "when user is logged in and is not an assembly private user" do + context "when the user isn't admin" do + before do + switch_to_host(organization.host) + login_as user, scope: :user + visit decidim_assemblies.assemblies_path + end - it "lists only the not private assembly" do + it "doesn't list the private assembly" do within "#parent-assemblies" do within "#parent-assemblies h3" do expect(page).to have_content("1") @@ -106,7 +121,11 @@ end context "when the user is admin" do - let(:logged_in_user) { admin } + before do + switch_to_host(organization.host) + login_as admin, scope: :user + visit decidim_assemblies.assemblies_path + end it "lists private assemblies" do within "#parent-assemblies" do @@ -126,10 +145,17 @@ expect(page).to have_current_path decidim_assemblies.assembly_path(private_assembly) expect(page).to have_content "This is a private assembly" end + + it "shows the privacy warning in attachments admin" do + visit decidim_admin_assemblies.assembly_attachments_path(private_assembly) + within "#attachments" do + expect(page).to have_content("Any participant could share this document to others") + end + end end end - context "when user is loged in and is assembly private user" do + context "when user is logged in and is an assembly private user" do before do switch_to_host(organization.host) login_as other_user, scope: :user diff --git a/decidim-assemblies/spec/types/assembly_member_type_spec.rb b/decidim-assemblies/spec/types/assembly_member_type_spec.rb index 68c9dcaeaea90..1de20f36c12e9 100644 --- a/decidim-assemblies/spec/types/assembly_member_type_spec.rb +++ b/decidim-assemblies/spec/types/assembly_member_type_spec.rb @@ -38,7 +38,7 @@ module Assemblies let(:query) { "{ user { name } }" } it "returns the user field" do - expect(response["user"]).to be nil + expect(response["user"]).to be_nil end end @@ -102,7 +102,7 @@ module Assemblies let(:query) { "{ ceasedDate }" } it "returns the assembly member ceasedDate" do - expect(response["ceasedDate"]).to be nil + expect(response["ceasedDate"]).to be_nil end end end diff --git a/decidim-assemblies/spec/types/assembly_type_spec.rb b/decidim-assemblies/spec/types/assembly_type_spec.rb index 5509b6e72c70b..c76a86311d078 100644 --- a/decidim-assemblies/spec/types/assembly_type_spec.rb +++ b/decidim-assemblies/spec/types/assembly_type_spec.rb @@ -189,7 +189,7 @@ module Assemblies let(:query) { "{ area { id } }" } it "returns the area field" do - expect(response["area"]).to be nil + expect(response["area"]).to be_nil end end @@ -198,7 +198,7 @@ module Assemblies context "when has no parent" do it "returns the parent" do - expect(response["parent"]).to be nil + expect(response["parent"]).to be_nil end end @@ -258,7 +258,7 @@ module Assemblies let(:query) { "{ assemblyType { id } }" } it "returns the assemblyType field" do - expect(response["assemblyType"]).to be nil + expect(response["assemblyType"]).to be_nil end end diff --git a/decidim-blogs/app/commands/decidim/blogs/admin/create_post.rb b/decidim-blogs/app/commands/decidim/blogs/admin/create_post.rb index 125febfab1aac..9964c3ceb2d14 100644 --- a/decidim-blogs/app/commands/decidim/blogs/admin/create_post.rb +++ b/decidim-blogs/app/commands/decidim/blogs/admin/create_post.rb @@ -5,7 +5,7 @@ module Blogs module Admin # This command is executed when the user creates a Post from the admin # panel. - class CreatePost < Rectify::Command + class CreatePost < Decidim::Command def initialize(form, current_user) @form = form @current_user = current_user diff --git a/decidim-blogs/app/commands/decidim/blogs/admin/update_post.rb b/decidim-blogs/app/commands/decidim/blogs/admin/update_post.rb index 6903f69485717..b7d6bd7c43e27 100644 --- a/decidim-blogs/app/commands/decidim/blogs/admin/update_post.rb +++ b/decidim-blogs/app/commands/decidim/blogs/admin/update_post.rb @@ -5,14 +5,15 @@ module Blogs module Admin # This command is executed when the user changes a Blog from the admin # panel. - class UpdatePost < Rectify::Command + class UpdatePost < Decidim::Command # Initializes a UpdateBlog Command. # # form - The form from which to get the data. # blog - The current instance of the page to be updated. - def initialize(form, post) + def initialize(form, post, user) @form = form @post = post + @user = user end # Updates the blog if valid. @@ -33,7 +34,9 @@ def call attr_reader :form, :post def update_post! - post.update!( + Decidim.traceability.update!( + post, + @user, title: form.title, body: form.body, author: form.author diff --git a/decidim-blogs/app/controllers/decidim/blogs/admin/posts_controller.rb b/decidim-blogs/app/controllers/decidim/blogs/admin/posts_controller.rb index d8c687e46a10f..ff2e2246e3e66 100644 --- a/decidim-blogs/app/controllers/decidim/blogs/admin/posts_controller.rb +++ b/decidim-blogs/app/controllers/decidim/blogs/admin/posts_controller.rb @@ -6,6 +6,7 @@ module Admin # This controller allows the create or update a blog. class PostsController < Admin::ApplicationController helper UserGroupHelper + helper PostsHelper def new enforce_permission_to :create, :blogpost @@ -38,7 +39,7 @@ def update enforce_permission_to :update, :blogpost, blogpost: post @form = form(PostForm).from_params(params, current_component: current_component) - UpdatePost.call(@form, post) do + UpdatePost.call(@form, post, current_user) do on(:ok) do flash[:notice] = I18n.t("posts.update.success", scope: "decidim.blogs.admin") redirect_to posts_path @@ -53,7 +54,10 @@ def update def destroy enforce_permission_to :destroy, :blogpost, blogpost: post - post.destroy! + + Decidim.traceability.perform_action!("delete", post, current_user) do + post.destroy! + end flash[:notice] = I18n.t("posts.destroy.success", scope: "decidim.blogs.admin") diff --git a/decidim-blogs/app/forms/decidim/blogs/admin/post_form.rb b/decidim-blogs/app/forms/decidim/blogs/admin/post_form.rb index ba5e98f864e18..b410a046ac6b3 100644 --- a/decidim-blogs/app/forms/decidim/blogs/admin/post_form.rb +++ b/decidim-blogs/app/forms/decidim/blogs/admin/post_form.rb @@ -10,24 +10,44 @@ class PostForm < Decidim::Form translatable_attribute :title, String translatable_attribute :body, String - attribute :user_group_id, Integer + attribute :decidim_author_id, Integer validates :title, translatable_presence: true validates :body, translatable_presence: true + validate :can_set_author - def map_model(post) - self.user_group_id = post.author.id if post.author.is_a?(Decidim::UserGroup) + def map_model(model) + self.decidim_author_id = nil if model.author.is_a? Decidim::Organization end - def user_group - @user_group ||= Decidim::UserGroup.find_by( + def user_or_group + @user_or_group ||= Decidim::UserBaseEntity.find_by( organization: current_organization, - id: user_group_id.to_i + id: decidim_author_id ) end def author - user_group || current_user + user_or_group || current_organization + end + + private + + def can_set_author + return if author == current_user.organization + return if author == current_user + return if user_groups.include? author + return if author == post&.author + + errors.add(:decidim_author_id, :invalid) + end + + def post + @post ||= Post.find_by(id: id) + end + + def user_groups + @user_groups ||= Decidim::UserGroups::ManageableUserGroups.for(current_user).verified end end end diff --git a/decidim-blogs/app/helpers/decidim/blogs/admin/posts_helper.rb b/decidim-blogs/app/helpers/decidim/blogs/admin/posts_helper.rb index 8b56347cc8e1e..7648b63b6a62a 100644 --- a/decidim-blogs/app/helpers/decidim/blogs/admin/posts_helper.rb +++ b/decidim-blogs/app/helpers/decidim/blogs/admin/posts_helper.rb @@ -18,6 +18,21 @@ def post_description_admin(post, max_length = 100) body = translated_attribute(post.body) CGI.unescapeHTML html_truncate(body, max_length: max_length) end + + def post_author_select_field(form, name, _options = {}) + select_options = [ + [current_organization.name, ""], + [current_user.name, current_user.id] + ] + current_user_groups = Decidim::UserGroups::ManageableUserGroups.for(current_user).verified + + select_options += current_user_groups.map { |g| [g.name, g.id] } if current_organization.user_groups_enabled? && current_user_groups.any? + unless form.object.author.is_a?(Organization) || select_options.pluck(1).include?(form.object.author.id) + select_options << [form.object.author.name, form.object.author.id] + end + + form.select(name, select_options) + end end end end diff --git a/decidim-blogs/app/models/decidim/blogs/post.rb b/decidim-blogs/app/models/decidim/blogs/post.rb index 2967998c54986..c8d89c36e6e5b 100644 --- a/decidim-blogs/app/models/decidim/blogs/post.rb +++ b/decidim-blogs/app/models/decidim/blogs/post.rb @@ -39,6 +39,10 @@ def visible? participatory_space.try(:visible?) && component.try(:published?) end + def self.log_presenter_class_for(_log) + Decidim::Blogs::AdminLog::PostPresenter + end + # Public: Overrides the `comments_have_alignment?` Commentable concern method. def comments_have_alignment? true @@ -55,7 +59,11 @@ def allow_resource_permissions? end def official? - author.nil? + author.is_a?(Decidim::Organization) + end + + def user_group? + author.is_a?(Decidim::UserGroup) end def users_to_notify_on_comment_created diff --git a/decidim-blogs/app/presenters/decidim/blogs/admin_log/post_presenter.rb b/decidim-blogs/app/presenters/decidim/blogs/admin_log/post_presenter.rb new file mode 100644 index 0000000000000..a4706efbbf96f --- /dev/null +++ b/decidim-blogs/app/presenters/decidim/blogs/admin_log/post_presenter.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module Decidim + module Blogs + module AdminLog + # This class holds the logic to present a `Decidim::Blogs::Post` + # for the `AdminLog` log. + # + # Usage should be automatic and you shouldn't need to call this class + # directly, but here's an example: + # + # action_log = Decidim::ActionLog.last + # view_helpers # => this comes from the views + # PostPresenter.new(action_log, view_helpers).present + class PostPresenter < Decidim::Log::BasePresenter + private + + def action_string + case action + when "create", "delete", "update" + "decidim.blogs.admin_log.post.#{action}" + else + super + end + end + + def diff_fields_mapping + { + title: :i18n, + body: :i18n + } + end + end + end + end +end diff --git a/decidim-blogs/app/presenters/decidim/blogs/official_author_presenter.rb b/decidim-blogs/app/presenters/decidim/blogs/official_author_presenter.rb new file mode 100644 index 0000000000000..d54ca370a1822 --- /dev/null +++ b/decidim-blogs/app/presenters/decidim/blogs/official_author_presenter.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Decidim + module Blogs + # + # A dummy presenter to abstract out the author of an official post. + # + class OfficialAuthorPresenter < Decidim::OfficialAuthorPresenter + def name + I18n.t("decidim.blogs.models.post.fields.official_blog_post") + end + end + end +end diff --git a/decidim-blogs/app/presenters/decidim/blogs/post_presenter.rb b/decidim-blogs/app/presenters/decidim/blogs/post_presenter.rb index cf9d8e5ad7245..39c9cf3b1833d 100644 --- a/decidim-blogs/app/presenters/decidim/blogs/post_presenter.rb +++ b/decidim-blogs/app/presenters/decidim/blogs/post_presenter.rb @@ -7,7 +7,13 @@ module Blogs # class PostPresenter < SimpleDelegator def author - @author ||= Decidim::UserPresenter.new(super) + @author ||= if official? + Decidim::Blogs::OfficialAuthorPresenter.new + elsif user_group? + Decidim::UserGroupPresenter.new(super) + else + Decidim::UserPresenter.new(super) + end end end end diff --git a/decidim-blogs/app/views/decidim/blogs/admin/posts/_form.html.erb b/decidim-blogs/app/views/decidim/blogs/admin/posts/_form.html.erb index 22d1978db3af0..f40f9db116f45 100644 --- a/decidim-blogs/app/views/decidim/blogs/admin/posts/_form.html.erb +++ b/decidim-blogs/app/views/decidim/blogs/admin/posts/_form.html.erb @@ -3,16 +3,16 @@

<%= title %>

- <% if current_organization.user_groups_enabled? && Decidim::UserGroups::ManageableUserGroups.for(current_user).verified.any? %> +
- <%= user_group_select_field form, :user_group_id, label: t("decidim.blogs.actions.user_group_id") %> + <%= post_author_select_field form, :decidim_author_id, label: t("decidim.blogs.actions.author_id") %>
- <% end %> +
<%= form.translated :text_field, :title, autofocus: true %>
- <%= form.translated :editor, :body, toolbar: :full, lines: 30, label: t("models.components.body", scope: "decidim.blogs.admin") %> + <%= form.translated :editor, :body, toolbar: :full, lines: 30 %>
diff --git a/decidim-blogs/app/views/decidim/blogs/posts/_posts.html.erb b/decidim-blogs/app/views/decidim/blogs/posts/_posts.html.erb index b29ef1ae3a6ba..7747fa34b0429 100644 --- a/decidim-blogs/app/views/decidim/blogs/posts/_posts.html.erb +++ b/decidim-blogs/app/views/decidim/blogs/posts/_posts.html.erb @@ -12,7 +12,8 @@ <% end %>
- <%= cell "decidim/author", present(post.author), from: post, has_actions: true %> + <% post_presenter = Decidim::Blogs::PostPresenter.new(post) %> + <%= cell "decidim/author", post_presenter.author, from: post, has_actions: true %>
<%= decidim_sanitize_editor post_description(post) %> diff --git a/decidim-blogs/app/views/decidim/blogs/posts/show.html.erb b/decidim-blogs/app/views/decidim/blogs/posts/show.html.erb index f4074e131d476..44fe3ed8fa580 100644 --- a/decidim-blogs/app/views/decidim/blogs/posts/show.html.erb +++ b/decidim-blogs/app/views/decidim/blogs/posts/show.html.erb @@ -23,7 +23,9 @@ <% end %>

<%= translated_attribute post.title %>

- <%= cell "decidim/author", present(post.author), from: post %> + + <% post_presenter = Decidim::Blogs::PostPresenter.new(post) %> + <%= cell "decidim/author", post_presenter.author, from: post %>
<% if show_endorsements_card? %> diff --git a/decidim-blogs/config/locales/ar.yml b/decidim-blogs/config/locales/ar.yml index e6ef3efc24c97..df4f409827646 100644 --- a/decidim-blogs/config/locales/ar.yml +++ b/decidim-blogs/config/locales/ar.yml @@ -1,3 +1,4 @@ +--- ar: activemodel: models: @@ -14,16 +15,14 @@ ar: decidim: blogs: actions: + author_id: إنشاء مشاركة كـ confirm_destroy: هل أنت متأكد أنك تريد حذ٠هذه المشاركة؟ destroy: حذ٠edit: تعديل new: منشور جديد title: Ø£Ùعال - user_group_id: إنشاء مشاركة كـ admin: models: - components: - body: الجسم post: name: بريد posts: @@ -51,7 +50,6 @@ ar: author: مؤل٠body: الجسم created_at: أنشئت ÙÙŠ - title: عنوان posts: show: back: العودة إلى القائمة diff --git a/decidim-blogs/config/locales/bg.yml b/decidim-blogs/config/locales/bg.yml index e7ed14e885d1a..3b89e84a44541 100644 --- a/decidim-blogs/config/locales/bg.yml +++ b/decidim-blogs/config/locales/bg.yml @@ -1,3 +1,4 @@ +--- bg: activemodel: models: diff --git a/decidim-blogs/config/locales/ca.yml b/decidim-blogs/config/locales/ca.yml index 43863a6ecf3a5..db437dcb7d78c 100644 --- a/decidim-blogs/config/locales/ca.yml +++ b/decidim-blogs/config/locales/ca.yml @@ -1,5 +1,12 @@ +--- ca: activemodel: + attributes: + post: + body: Cos del text + decidim_author_id: Autoria + published_at: Hora de publicació + title: Títol models: decidim/blogs/create_post_event: Nova publicació al blog activerecord: @@ -10,16 +17,14 @@ ca: decidim: blogs: actions: - confirm_destroy: Estàs segura que vols eliminar aquesta publicació? + author_id: Crear publicació com + confirm_destroy: Segur que vols eliminar aquesta publicació? destroy: Suprimeix edit: Edita new: Nova publicació title: Accions - user_group_id: Crear publicació com admin: models: - components: - body: Cos post: name: Publicar posts: @@ -39,6 +44,11 @@ ca: update: invalid: S'ha produït un error en guardar la publicació. success: S'ha desat la publicació correctament + admin_log: + post: + create: "%{user_name} ha creat el post %{resource_name} al blog de %{space_name}" + delete: "%{user_name} ha eliminat el post %{resource_name} del blog de %{space_name}" + update: "%{user_name} ha actualitzat el post %{resource_name} en el blog de %{space_name}" last_activity: new_post_at_html: "Nova publicació a %{link}" models: @@ -47,7 +57,8 @@ ca: author: Autora body: Cos created_at: Creat el - title: títol + official_blog_post: Post oficial + title: Títol posts: show: back: Tornar al llistat @@ -60,8 +71,10 @@ ca: components: blogs: actions: + comment: Comentar create: Crear destroy: Esborrar + endorse: Adherir-se update: Actualitzar name: Blog settings: diff --git a/decidim-blogs/config/locales/cs.yml b/decidim-blogs/config/locales/cs.yml index 2b6c4648c2300..2dfdd3d874661 100644 --- a/decidim-blogs/config/locales/cs.yml +++ b/decidim-blogs/config/locales/cs.yml @@ -1,5 +1,12 @@ +--- cs: activemodel: + attributes: + post: + body: TÄ›lo zprávy + decidim_author_id: Autor + published_at: ÄŒas zveÅ™ejnÄ›ní + title: Název models: decidim/blogs/create_post_event: Nový blogový příspÄ›vek activerecord: @@ -12,16 +19,14 @@ cs: decidim: blogs: actions: + author_id: VytvoÅ™it příspÄ›vek jako confirm_destroy: Opravdu chcete tento příspÄ›vek smazat? destroy: Smazat edit: Upravit new: Nový příspÄ›vek title: Akce - user_group_id: VytvoÅ™it příspÄ›vek jako admin: models: - components: - body: TÄ›lo post: name: PříspÄ›vek posts: @@ -41,6 +46,11 @@ cs: update: invalid: PÅ™i ukládání příspÄ›vku doÅ¡lo k chybám. success: PříspÄ›vek byl úspěšnÄ› uložen + admin_log: + post: + create: "%{user_name} vytvoÅ™il příspÄ›vek %{resource_name} v %{space_name}" + delete: "%{user_name} odstranil příspÄ›vek %{resource_name} z %{space_name}" + update: "%{user_name} aktualizoval příspÄ›vek %{resource_name} v %{space_name}" last_activity: new_post_at_html: "Nový příspÄ›vek v %{link}" models: @@ -49,7 +59,8 @@ cs: author: Autor body: TÄ›lo created_at: VytvoÅ™eno v - title: titulek + official_blog_post: Oficiální příspÄ›vek + title: Název posts: show: back: ZpÄ›t na seznam @@ -62,8 +73,10 @@ cs: components: blogs: actions: + comment: Komentář create: VytvoÅ™it destroy: Smazat + endorse: Schválit update: Aktualizovat name: Blog settings: diff --git a/decidim-blogs/config/locales/de.yml b/decidim-blogs/config/locales/de.yml index 7a8ab31eabfeb..ca6848f97a155 100644 --- a/decidim-blogs/config/locales/de.yml +++ b/decidim-blogs/config/locales/de.yml @@ -1,3 +1,4 @@ +--- de: activemodel: models: @@ -10,16 +11,14 @@ de: decidim: blogs: actions: + author_id: Beitrag erstellen als confirm_destroy: Möchten Sie diesen Beitrag wirklich löschen? destroy: Löschen edit: Bearbeiten new: Neuer Beitrag title: Aktionen - user_group_id: Beitrag erstellen als admin: models: - components: - body: Haupttext post: name: Post posts: @@ -39,6 +38,11 @@ de: update: invalid: Beim Speichern des Posts sind Fehler aufgetreten. success: Beitrag wurde erfolgreich gespeichert + admin_log: + post: + create: "%{user_name} hat den Blogpost %{resource_name} in %{space_name} erstellt" + delete: "%{user_name} hat den Blogpost %{resource_name} in %{space_name} gelöscht" + update: "%{user_name} hat den Blogpost %{resource_name} in %{space_name} aktualisiert" last_activity: new_post_at_html: "Neuer Beitrag bei %{link}" models: @@ -47,7 +51,7 @@ de: author: Autor body: Haupttext created_at: Hergestellt in - title: Titel + official_blog_post: Offizieller Post posts: show: back: Zurück zur Liste diff --git a/decidim-blogs/config/locales/el.yml b/decidim-blogs/config/locales/el.yml index 6b9da01312b36..0e8872f9a21c5 100644 --- a/decidim-blogs/config/locales/el.yml +++ b/decidim-blogs/config/locales/el.yml @@ -1,3 +1,4 @@ +--- el: activemodel: models: @@ -10,16 +11,14 @@ el: decidim: blogs: actions: + author_id: ΔημιουÏγία ανάÏτησης ως confirm_destroy: Είστε βέβαιοι ότι θέλετε να διαγÏάψετε αυτήν τη δημοσίευση; destroy: ΔιαγÏαφή edit: ΕπεξεÏγασία new: Îέα δημοσίευση title: ΕνέÏγειες - user_group_id: ΔημιουÏγία ανάÏτησης ως admin: models: - components: - body: Σώμα post: name: Δημοσίευση posts: @@ -47,7 +46,6 @@ el: author: Συντάκτης body: Σώμα created_at: ΔημιουÏγήθηκε στις - title: τίτλος posts: show: back: ΕπιστÏοφή στη λίστα diff --git a/decidim-blogs/config/locales/en.yml b/decidim-blogs/config/locales/en.yml index 297b1debad7b7..37b2105ed540a 100644 --- a/decidim-blogs/config/locales/en.yml +++ b/decidim-blogs/config/locales/en.yml @@ -1,6 +1,12 @@ --- en: activemodel: + attributes: + post: + body: Body + decidim_author_id: Author + published_at: Publish time + title: Title models: decidim/blogs/create_post_event: New blog post activerecord: @@ -11,16 +17,14 @@ en: decidim: blogs: actions: + author_id: Create post as confirm_destroy: Are you sure you want to delete this post? destroy: Delete edit: Edit new: New post title: Actions - user_group_id: Create post as admin: models: - components: - body: Body post: name: Post posts: @@ -40,6 +44,11 @@ en: update: invalid: There was a problem saving the post. success: Post successfully saved + admin_log: + post: + create: "%{user_name} created the %{resource_name} blog post in %{space_name}" + delete: "%{user_name} deleted the %{resource_name} blog post from %{space_name}" + update: "%{user_name} updated the %{resource_name} blog post in %{space_name}" last_activity: new_post_at_html: "New post at %{link}" models: @@ -48,7 +57,8 @@ en: author: Author body: Body created_at: Created at - title: title + official_blog_post: Official post + title: Title posts: show: back: Back to list @@ -61,8 +71,10 @@ en: components: blogs: actions: + comment: Comment create: Create destroy: Delete + endorse: Endorse update: Update name: Blog settings: diff --git a/decidim-blogs/config/locales/es-MX.yml b/decidim-blogs/config/locales/es-MX.yml index cd155a6e03c76..0c4bf97f275e5 100644 --- a/decidim-blogs/config/locales/es-MX.yml +++ b/decidim-blogs/config/locales/es-MX.yml @@ -1,5 +1,12 @@ +--- es-MX: activemodel: + attributes: + post: + body: Cuerpo del texto + decidim_author_id: Autoria + published_at: Hora de publicación + title: Título models: decidim/blogs/create_post_event: Nueva publicación del blog activerecord: @@ -10,16 +17,14 @@ es-MX: decidim: blogs: actions: + author_id: Crear publicación como confirm_destroy: '¿Seguro que quieres eliminar esta publicación?' destroy: Borrar edit: Editar new: Nueva publicación title: Comportamiento - user_group_id: Crear publicación como admin: models: - components: - body: Cuerpo post: name: Enviar posts: @@ -39,6 +44,11 @@ es-MX: update: invalid: Ha habido errores al guardar la publicación. success: Publicación guardada con éxito + admin_log: + post: + create: "%{user_name} creó el post %{resource_name} en el blog de %{space_name}" + delete: "%{user_name} ha eliminado el post %{resource_name} en el blog de %{space_name}" + update: "%{user_name} ha actualizado el post %{resource_name} en el blog de %{space_name}" last_activity: new_post_at_html: "Nueva publicación en %{link}" models: @@ -47,7 +57,8 @@ es-MX: author: Autoría body: Cuerpo created_at: Creado en - title: título + official_blog_post: Post oficial + title: Título posts: show: back: Volver al listado @@ -60,8 +71,10 @@ es-MX: components: blogs: actions: + comment: Comentar create: Crear destroy: Borrar + endorse: Adherirse update: Actualizar name: Blog settings: diff --git a/decidim-blogs/config/locales/es-PY.yml b/decidim-blogs/config/locales/es-PY.yml index 8a4c7a7fa2749..6b8cbf94a75fb 100644 --- a/decidim-blogs/config/locales/es-PY.yml +++ b/decidim-blogs/config/locales/es-PY.yml @@ -1,5 +1,12 @@ +--- es-PY: activemodel: + attributes: + post: + body: Cuerpo del texto + decidim_author_id: Autoria + published_at: Hora de publicación + title: Título models: decidim/blogs/create_post_event: Nueva publicación del blog activerecord: @@ -10,16 +17,14 @@ es-PY: decidim: blogs: actions: + author_id: Crear publicación como confirm_destroy: '¿Seguro que quieres eliminar esta publicación?' destroy: Borrar edit: Editar new: Nueva publicación title: Comportamiento - user_group_id: Crear publicación como admin: models: - components: - body: Cuerpo post: name: Enviar posts: @@ -39,6 +44,11 @@ es-PY: update: invalid: Ha habido errores al guardar la publicación. success: Publicación guardada con éxito + admin_log: + post: + create: "%{user_name} creó el post %{resource_name} en el blog de %{space_name}" + delete: "%{user_name} ha eliminado el post %{resource_name} en el blog de %{space_name}" + update: "%{user_name} ha actualizado el post %{resource_name} en el blog de %{space_name}" last_activity: new_post_at_html: "Nueva publicación en %{link}" models: @@ -47,7 +57,8 @@ es-PY: author: Autoría body: Cuerpo created_at: Creado en - title: título + official_blog_post: Post oficial + title: Título posts: show: back: Volver al listado @@ -60,8 +71,10 @@ es-PY: components: blogs: actions: + comment: Comentar create: Crear destroy: Borrar + endorse: Adherirse update: Actualizar name: Blog settings: diff --git a/decidim-blogs/config/locales/es.yml b/decidim-blogs/config/locales/es.yml index 74510d730da38..254cf4b4026a7 100644 --- a/decidim-blogs/config/locales/es.yml +++ b/decidim-blogs/config/locales/es.yml @@ -1,5 +1,12 @@ +--- es: activemodel: + attributes: + post: + body: Cuerpo del texto + decidim_author_id: Autoria + published_at: Hora de publicación + title: Título models: decidim/blogs/create_post_event: Nueva publicación en el blog activerecord: @@ -10,16 +17,14 @@ es: decidim: blogs: actions: - confirm_destroy: '¿Estás segura que quieres eliminar esta publicación?' + author_id: Crear publicación como + confirm_destroy: '¿Seguro que quieres eliminar esta publicación?' destroy: Borrar edit: Editar new: Nueva publicación title: Acciones - user_group_id: Crear publicación como admin: models: - components: - body: Cuerpo post: name: Publicar posts: @@ -39,6 +44,11 @@ es: update: invalid: Se ha producido un error al guardar la publicación. success: Se ha guardado la publicación correctamente + admin_log: + post: + create: "%{user_name} creó el post %{resource_name} en el blog de %{space_name}" + delete: "%{user_name} ha eliminado el post %{resource_name} en el blog de %{space_name}" + update: "%{user_name} ha actualizado el post %{resource_name} en el blog de %{space_name}" last_activity: new_post_at_html: "Nueva publicación en %{link}" models: @@ -47,7 +57,8 @@ es: author: Autora body: Cuerpo created_at: Creado en - title: título + official_blog_post: Post oficial + title: Título posts: show: back: Volver al listado @@ -60,8 +71,10 @@ es: components: blogs: actions: + comment: Comentar create: Crear destroy: Borrar + endorse: Adherirse update: Actualizar name: Blog settings: diff --git a/decidim-blogs/config/locales/eu.yml b/decidim-blogs/config/locales/eu.yml index 8e5714d118b86..5fdd9da501944 100644 --- a/decidim-blogs/config/locales/eu.yml +++ b/decidim-blogs/config/locales/eu.yml @@ -1,85 +1,98 @@ +--- eu: activemodel: + attributes: + post: + body: Testua + decidim_author_id: Egilea + published_at: Argitaratze data + title: Izena models: decidim/blogs/create_post_event: Blogeko post berria activerecord: models: decidim/blogs/post: - one: Post - other: Mezuak + one: Argitalpena + other: Argitalpenak decidim: blogs: actions: - confirm_destroy: Ziur mezua ezabatu nahi duzula? + author_id: Sortu argitalpena hau bezala + confirm_destroy: Ziur zaude post hau argitalpen ezabatu nahi duzula? destroy: Ezabatu edit: Editatu new: Post berria title: Ekintzak - user_group_id: Sortu argitalpena hau bezala admin: models: - components: - body: Gorputzeko post: - name: Post + name: Argitalpena posts: create: - invalid: Arazo bat izan da post hau sortzeko - success: Mezua ondo sortu da + invalid: Arazo bat izan da sarrera hau sortzeko + success: Argitalpena ondo sortu da destroy: success: Mezua ondo ezabatu da edit: - save: eguneratzearen + save: Eguneratu title: Editatu argitalpena index: - title: Mezuak + title: Argitalpenak new: create: Sortu - title: Sortu mezua + title: Sortu argitalpena update: - invalid: Erroreak gertatu dira mezua gordetzean. - success: Mezua ondo gorde da + invalid: Akatsen bat gertatu da mezua gordetzean. + success: Sarrera ondo gorde da + admin_log: + post: + create: "%{user_name} k %{resource_name} blogeko argitalpena sortu du %{space_name} espazioan" + delete: "%{user_name} k %{resource_name} blogeko argitalpena ezabatu du %{space_name} espazioan" + update: "%{user_name} k %{resource_name} blogeko argitalpena eguneratu egin da %{space_name} espazioan" last_activity: - new_post_at_html: "Post berria %{link}" + new_post_at_html: "Post berria %{link}-ean" models: post: fields: author: Egilea - body: Gorputzeko - created_at: Sortutako at + body: Testua + created_at: Sortze-data + official_blog_post: Blogeko argitalpen ofiziala title: Izenburua posts: show: back: Itzuli zerrendara comments: Iruzkinak - view: ikusi + view: Ikusi sidebar_blog: comments: iruzkinak most_commented_posts: Gehien iruzkinatutako mezu - read_more: Irakurri gehiago + read_more: Geihago irakurri components: blogs: actions: + comment: Iruzkindu create: Sortu destroy: Ezabatu + endorse: Atxiki update: Eguneratu name: Bloga settings: global: - announcement: Anuntzio + announcement: Iragarpena comments_enabled: Iruzkinak gaituta - comments_max_length: Iruzkinen gehieneko luzera (utzi 0 defektuz konfigurazioa mantendu nahi baduzu) + comments_max_length: Iruzkinen gehieneko luzera (utzi 0 lehenetsitako konfigurazioari eutsi nahi badiozu) step: - announcement: Anuntzio + announcement: Iragarpena comments_blocked: Iruzkinak blokeatuta endorsements_blocked: Atxikimenduak blokeatuta endorsements_enabled: Atxikimenduak gaituta events: blogs: post_created: - email_intro: '"%{resource_title}" mezua "%{participatory_space_title}" argitaratzen ari zarela jarraitzen ari zara.' + email_intro: '"%{resource_title}" argitalpena jarraitzen ari zaren "%{participatory_space_title}" espazioan argitaratu da.' email_outro: Jakinarazpena jaso duzu "%{participatory_space_title}" jarraitzen ari zarelako. Aurreko estekan utzi ahal diozu jarraitzeari. - email_subject: '%{participatory_space_title} argitaratutako mezu berria' + email_subject: Argitalpen berria %{participatory_space_title} espazioan notification_title: %{resource_title} posta %{participatory_space_title} argitaratu da statistics: posts_count: Argitalpenak diff --git a/decidim-blogs/config/locales/fi-plain.yml b/decidim-blogs/config/locales/fi-plain.yml index 44d40704da52e..3d6b27f8bb8a3 100644 --- a/decidim-blogs/config/locales/fi-plain.yml +++ b/decidim-blogs/config/locales/fi-plain.yml @@ -1,5 +1,12 @@ +--- fi-pl: activemodel: + attributes: + post: + body: Sisältöteksti + decidim_author_id: Laatija + published_at: Julkaisuaika + title: Otsikko models: decidim/blogs/create_post_event: Uusi blogiartikkeli activerecord: @@ -10,16 +17,14 @@ fi-pl: decidim: blogs: actions: + author_id: Luo artikkeli käyttäjänä confirm_destroy: Haluatko varmasti poistaa tämän artikkelin? destroy: Poista edit: Muokkaa new: Uusi artikkeli title: Toiminnot - user_group_id: Luo artikkeli käyttäjänä admin: models: - components: - body: Leipäteksti post: name: Artikkeli posts: @@ -39,6 +44,11 @@ fi-pl: update: invalid: Artikkelin tallennuksessa tapahtui virheitä. success: Artikkeli tallennettu onnistuneesti + admin_log: + post: + create: "%{user_name} loi blogikirjoituksen %{resource_name} tilassa %{space_name}" + delete: "%{user_name} poisti blogikirjoituksen %{resource_name} tilasta %{space_name}" + update: "%{user_name} päivitti blogikirjoitusta %{resource_name} tilassa %{space_name}" last_activity: new_post_at_html: "Uusi artikkeli osoitteessa %{link}" models: @@ -47,7 +57,8 @@ fi-pl: author: Kirjoittaja body: Leipäteksti created_at: Luotu - title: otsikko + official_blog_post: Virallinen artikkeli + title: Otsikko posts: show: back: Takaisin listaan @@ -60,8 +71,10 @@ fi-pl: components: blogs: actions: + comment: Kommentointi create: Luo destroy: Poista + endorse: Suosittelu update: Päivitä name: Blogi settings: diff --git a/decidim-blogs/config/locales/fi.yml b/decidim-blogs/config/locales/fi.yml index 673bf62924101..72b3cd5087dea 100644 --- a/decidim-blogs/config/locales/fi.yml +++ b/decidim-blogs/config/locales/fi.yml @@ -1,5 +1,12 @@ +--- fi: activemodel: + attributes: + post: + body: Sisältöteksti + decidim_author_id: Laatija + published_at: Julkaisuaika + title: Otsikko models: decidim/blogs/create_post_event: Uusi blogiartikkeli activerecord: @@ -10,16 +17,14 @@ fi: decidim: blogs: actions: + author_id: Luo artikkeli käyttäjänä confirm_destroy: Haluatko varmasti poistaa tämän artikkelin? destroy: Poista edit: Muokkaa new: Uusi artikkeli title: Toiminnot - user_group_id: Luo artikkeli käyttäjänä admin: models: - components: - body: Leipäteksti post: name: Artikkeli posts: @@ -39,6 +44,11 @@ fi: update: invalid: Artikkelin tallennus epäonnistui. success: Artikkeli tallennus onnistui + admin_log: + post: + create: "%{user_name} loi blogikirjoituksen %{resource_name} tilassa %{space_name}" + delete: "%{user_name} poisti blogikirjoituksen %{resource_name} tilasta %{space_name}" + update: "%{user_name} päivitti blogikirjoitusta %{resource_name} tilassa %{space_name}" last_activity: new_post_at_html: "Uusi artikkeli osoitteessa %{link}" models: @@ -47,7 +57,8 @@ fi: author: Laatija body: Leipäteksti created_at: Luotu - title: otsikko + official_blog_post: Virallinen artikkeli + title: Otsikko posts: show: back: Takaisin listaan @@ -60,8 +71,10 @@ fi: components: blogs: actions: + comment: Kommentointi create: Luo destroy: Poista + endorse: Suosittelu update: Päivitä name: Blogi settings: diff --git a/decidim-blogs/config/locales/fr-CA.yml b/decidim-blogs/config/locales/fr-CA.yml index 60dfce02eb653..9ba9ee84e6e62 100644 --- a/decidim-blogs/config/locales/fr-CA.yml +++ b/decidim-blogs/config/locales/fr-CA.yml @@ -1,5 +1,12 @@ +--- fr-CA: activemodel: + attributes: + post: + body: Corps du texte + decidim_author_id: Auteur + published_at: Date de publication + title: Titre models: decidim/blogs/create_post_event: Nouvel article activerecord: @@ -10,16 +17,14 @@ fr-CA: decidim: blogs: actions: + author_id: Créer un article comme confirm_destroy: Êtes-vous certain de vouloir supprimer cet article ? destroy: Supprimer edit: Modifier new: Nouvel article title: Actions - user_group_id: Créer un article comme admin: models: - components: - body: Corps du texte post: name: Publier posts: @@ -39,6 +44,11 @@ fr-CA: update: invalid: Il y a eu des erreurs lors de l'enregistrement de l'article. success: Article enregistré avec succès + admin_log: + post: + create: "%{user_name} a créé l'article de blog %{resource_name} dans %{space_name}" + delete: "%{user_name} a supprimé l'article de blog %{resource_name} dans %{space_name}" + update: "%{user_name} a mis à jour l'article de blog %{resource_name} dans %{space_name}" last_activity: new_post_at_html: "Nouvel article à %{link}" models: @@ -47,7 +57,8 @@ fr-CA: author: Auteur body: Corps du texte created_at: Créé à - title: titre + official_blog_post: Article officiel + title: Titre posts: show: back: Retour à la liste @@ -60,8 +71,10 @@ fr-CA: components: blogs: actions: + comment: Commenter create: Créer destroy: Supprimer + endorse: Soutenir update: Mettre à jour name: Actualités settings: diff --git a/decidim-blogs/config/locales/fr.yml b/decidim-blogs/config/locales/fr.yml index 7afc3749be257..ca3b765fc0c57 100644 --- a/decidim-blogs/config/locales/fr.yml +++ b/decidim-blogs/config/locales/fr.yml @@ -1,5 +1,12 @@ +--- fr: activemodel: + attributes: + post: + body: Corps du texte + decidim_author_id: Auteur + published_at: Date de publication + title: Titre models: decidim/blogs/create_post_event: Nouvel article activerecord: @@ -10,16 +17,14 @@ fr: decidim: blogs: actions: + author_id: Créer un article en tant que confirm_destroy: Êtes-vous certain de vouloir supprimer cet article ? destroy: Supprimer edit: Modifier new: Nouvel article title: Actions - user_group_id: Créer un article en tant que admin: models: - components: - body: Corps du texte post: name: Publier posts: @@ -39,6 +44,11 @@ fr: update: invalid: Il y a eu des erreurs lors de l'enregistrement de l'article. success: Article enregistré avec succès + admin_log: + post: + create: "%{user_name} a créé l'article de blog %{resource_name} dans %{space_name}" + delete: "%{user_name} a supprimé l'article de blog %{resource_name} dans %{space_name}" + update: "%{user_name} a mis à jour l'article de blog %{resource_name} dans %{space_name}" last_activity: new_post_at_html: "Nouvel article à %{link}" models: @@ -47,7 +57,8 @@ fr: author: Auteur body: Corps du texte created_at: Créé à - title: titre + official_blog_post: Article officiel + title: Titre posts: show: back: Retour à la liste @@ -60,8 +71,10 @@ fr: components: blogs: actions: + comment: Commenter create: Créer destroy: Supprimer + endorse: Soutenir update: Mettre à jour name: Actualités settings: diff --git a/decidim-blogs/config/locales/ga-IE.yml b/decidim-blogs/config/locales/ga-IE.yml index 61e3be9df885b..d5a20266867b8 100644 --- a/decidim-blogs/config/locales/ga-IE.yml +++ b/decidim-blogs/config/locales/ga-IE.yml @@ -1,3 +1,4 @@ +--- ga: activerecord: models: @@ -16,8 +17,6 @@ ga: title: Gníomhartha admin: models: - components: - body: Corp post: name: Postáil posts: @@ -34,7 +33,6 @@ ga: fields: author: Údar body: Corp - title: teideal posts: show: comments: Tráchtanna diff --git a/decidim-blogs/config/locales/gl.yml b/decidim-blogs/config/locales/gl.yml index 9b607520d0889..146e7d03cf6cc 100644 --- a/decidim-blogs/config/locales/gl.yml +++ b/decidim-blogs/config/locales/gl.yml @@ -1,3 +1,4 @@ +--- gl: activemodel: models: @@ -10,16 +11,14 @@ gl: decidim: blogs: actions: + author_id: Crear publicación como confirm_destroy: Tes a certeza de querer eliminar esta publicación? destroy: Eliminar edit: Editar new: Nova publicación title: Accións - user_group_id: Crear publicación como admin: models: - components: - body: Corpo post: name: Publicación posts: @@ -47,7 +46,6 @@ gl: author: Autor body: Corpo created_at: Creado o - title: título posts: show: back: Volver á listaxe diff --git a/decidim-blogs/config/locales/hu.yml b/decidim-blogs/config/locales/hu.yml index ced3c553f7eab..530fa7d16565b 100644 --- a/decidim-blogs/config/locales/hu.yml +++ b/decidim-blogs/config/locales/hu.yml @@ -1,3 +1,4 @@ +--- hu: activemodel: models: @@ -10,16 +11,14 @@ hu: decidim: blogs: actions: + author_id: Bejegyzés létrehozása confirm_destroy: Biztos, hogy törlöd ezt a bejegyzést? destroy: Törlés edit: Szerkesztés new: Új bejegyzés title: Műveletek - user_group_id: Bejegyzés létrehozása admin: models: - components: - body: Szöveg post: name: Bejegyzés posts: @@ -39,6 +38,11 @@ hu: update: invalid: Hiba történt a bejegyzés mentése során. success: Bejegyzés mentése sikeres + admin_log: + post: + create: "%{user_name} létrehozta a(z) %{resource_name} blogposztot itt: %{space_name}" + delete: "%{user_name} törölte a(z) %{resource_name} blogposztot itt: %{space_name}" + update: "%{user_name} frissítette a(z) %{resource_name} blogposztot itt: %{space_name}" last_activity: new_post_at_html: "Új hozzászólás %{link}kor" models: @@ -47,7 +51,7 @@ hu: author: SzerzÅ‘ body: Szöveg created_at: 'Létrehozva:' - title: cím + official_blog_post: Hivatalos bejegyzés posts: show: back: Vissza a listához diff --git a/decidim-blogs/config/locales/id-ID.yml b/decidim-blogs/config/locales/id-ID.yml index fbc03d4fb5afa..886f728af35d7 100644 --- a/decidim-blogs/config/locales/id-ID.yml +++ b/decidim-blogs/config/locales/id-ID.yml @@ -1,3 +1,4 @@ +--- id: activemodel: models: @@ -16,8 +17,6 @@ id: title: Tindakan admin: models: - components: - body: Tubuh post: name: Pos posts: @@ -44,7 +43,6 @@ id: author: Penulis body: Tubuh created_at: Dibuat di - title: judul posts: show: view: Melihat diff --git a/decidim-blogs/config/locales/is-IS.yml b/decidim-blogs/config/locales/is-IS.yml index 90148beff76ed..eac143ab540fa 100644 --- a/decidim-blogs/config/locales/is-IS.yml +++ b/decidim-blogs/config/locales/is-IS.yml @@ -1,4 +1,5 @@ -is-IS: +--- +is: decidim: blogs: actions: @@ -8,8 +9,6 @@ is-IS: title: Aðgerðir admin: models: - components: - body: Líkami post: name: Post posts: @@ -30,7 +29,6 @@ is-IS: author: Höfundur body: Líkami created_at: Búið til á - title: titill posts: sidebar_blog: comments: athugasemdir diff --git a/decidim-blogs/config/locales/it.yml b/decidim-blogs/config/locales/it.yml index 3ec1c80954eb3..9a9593c763bdd 100644 --- a/decidim-blogs/config/locales/it.yml +++ b/decidim-blogs/config/locales/it.yml @@ -1,3 +1,4 @@ +--- it: activemodel: models: @@ -10,16 +11,14 @@ it: decidim: blogs: actions: + author_id: Crea post come confirm_destroy: Sei sicuro di voler eliminare questo post? destroy: Elimina edit: Modifica new: Nuovo post title: Azioni - user_group_id: Crea post come admin: models: - components: - body: Corpo post: name: Inviare posts: @@ -47,7 +46,6 @@ it: author: Autore body: Corpo created_at: Creato a - title: titolo posts: show: back: Torna alla lista diff --git a/decidim-blogs/config/locales/ja.yml b/decidim-blogs/config/locales/ja.yml index e011264704f42..1429ac0b2a808 100644 --- a/decidim-blogs/config/locales/ja.yml +++ b/decidim-blogs/config/locales/ja.yml @@ -1,5 +1,12 @@ +--- ja: activemodel: + attributes: + post: + body: 本文 + decidim_author_id: 作æˆè€… + published_at: 公開時刻 + title: タイトル models: decidim/blogs/create_post_event: æ–°ã—ã„ブログ投稿 activerecord: @@ -9,16 +16,14 @@ ja: decidim: blogs: actions: + author_id: 次ã®ã‚ˆã†ã«æŠ•ç¨¿ã‚’ä½œæˆ confirm_destroy: ã“ã®æŠ•ç¨¿ã‚’削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ destroy: 削除 edit: 編集 new: æ–°è¦æŠ•ç¨¿ title: アクション - user_group_id: 次ã®ã‚ˆã†ã«æŠ•ç¨¿ã‚’ä½œæˆ admin: models: - components: - body: 本文 post: name: 投稿 posts: @@ -38,6 +43,11 @@ ja: update: invalid: 投稿ã®ä¿å­˜ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ success: 投稿をä¿å­˜ã—ã¾ã—㟠+ admin_log: + post: + create: "%{user_name} ㌠%{space_name} ã§ãƒ–ログ投稿 %{resource_name} を作æˆã—ã¾ã—ãŸ" + delete: "%{user_name} ãŒãƒ–ログ投稿 %{resource_name} ã‚’ %{space_name} ã‹ã‚‰å‰Šé™¤ã—ã¾ã—ãŸ" + update: "%{user_name} ㌠%{space_name} ã®ãƒ–ログ投稿 %{resource_name} ã‚’æ›´æ–°ã—ã¾ã—ãŸ" last_activity: new_post_at_html: " %{link}ã«æ–°ã—ã„投稿" models: @@ -46,6 +56,7 @@ ja: author: 作æˆè€… body: 本文 created_at: 作æˆæ—¥æ™‚ + official_blog_post: å…¬å¼ãƒã‚¹ãƒˆ title: タイトル posts: show: @@ -59,8 +70,10 @@ ja: components: blogs: actions: + comment: コメント create: ä½œæˆ destroy: 削除 + endorse: オススメ update: æ›´æ–° name: ブログ settings: diff --git a/decidim-blogs/config/locales/ka-GE.yml b/decidim-blogs/config/locales/ka-GE.yml new file mode 100644 index 0000000000000..57a95cb04703c --- /dev/null +++ b/decidim-blogs/config/locales/ka-GE.yml @@ -0,0 +1 @@ +ka: diff --git a/decidim-blogs/config/locales/lb.yml b/decidim-blogs/config/locales/lb.yml index 42d5337c21e2c..5a65b967973e6 100644 --- a/decidim-blogs/config/locales/lb.yml +++ b/decidim-blogs/config/locales/lb.yml @@ -1,3 +1,4 @@ +--- lb: activemodel: models: @@ -10,16 +11,14 @@ lb: decidim: blogs: actions: + author_id: Beitrag erstellen als confirm_destroy: Möchten Sie diesen Beitrag wirklich löschen? destroy: Löschen edit: Bearbeiten new: Neuer Beitrag title: Aktionen - user_group_id: Beitrag erstellen als admin: models: - components: - body: Haupttext post: name: Post posts: @@ -47,7 +46,6 @@ lb: author: Autor body: Haupttext created_at: Hergestellt in - title: Titel posts: show: back: Zurück zur Liste diff --git a/decidim-blogs/config/locales/lt.yml b/decidim-blogs/config/locales/lt.yml index cb5afcbc04b6c..2379ece5b475e 100644 --- a/decidim-blogs/config/locales/lt.yml +++ b/decidim-blogs/config/locales/lt.yml @@ -1,5 +1,9 @@ +--- lt: activemodel: + attributes: + post: + published_at: Paskelbimo laikas models: decidim/blogs/create_post_event: Naujas tinklaraÅ¡Äio įraÅ¡as activerecord: @@ -12,16 +16,14 @@ lt: decidim: blogs: actions: + author_id: Sukurti įraÅ¡Ä… kaip confirm_destroy: Ar tikrai norite iÅ¡trinti šį įraÅ¡Ä…? destroy: IÅ¡trinti edit: Redaguoti new: Naujas įraÅ¡as title: Veiksmai - user_group_id: Sukurti įraÅ¡Ä… kaip admin: models: - components: - body: PagrindinÄ— dalis post: name: Publikacija posts: @@ -41,6 +43,11 @@ lt: update: invalid: IÅ¡saugant šį įraÅ¡Ä… iÅ¡kilo problema. success: Ä®raÅ¡as iÅ¡saugotas + admin_log: + post: + create: "%{user_name} sukÅ«rÄ— %{resource_name} tinklaraÅ¡Äio įraÅ¡Ä… %{space_name}" + delete: "%{user_name} iÅ¡trynÄ— %{resource_name} tinklaraÅ¡Äio įraÅ¡Ä… iÅ¡ %{space_name}" + update: "%{user_name} atnaujino %{resource_name} tinklaraÅ¡Äio įraÅ¡Ä… %{space_name}" last_activity: new_post_at_html: " Naujas įraÅ¡as %{link}" models: @@ -49,7 +56,7 @@ lt: author: AutorÄ—(-ius) body: PagrindinÄ— dalis created_at: Sukurta - title: pavadinimas + official_blog_post: Oficiali publikacija posts: show: back: Grįžti į sÄ…raÅ¡Ä… diff --git a/decidim-blogs/config/locales/lv.yml b/decidim-blogs/config/locales/lv.yml index a487b8729c886..cf1267c54d54f 100644 --- a/decidim-blogs/config/locales/lv.yml +++ b/decidim-blogs/config/locales/lv.yml @@ -1,3 +1,4 @@ +--- lv: activemodel: models: @@ -18,8 +19,6 @@ lv: title: DarbÄ«bas admin: models: - components: - body: Pamatteksts post: name: Ziņa posts: @@ -46,7 +45,6 @@ lv: author: Autors body: Pamatteksts created_at: Izveidots plkst. - title: nosaukums posts: show: back: Atpakaļ uz sarakstu diff --git a/decidim-blogs/config/locales/nl.yml b/decidim-blogs/config/locales/nl.yml index df2c7e6006617..ae5a38d64adbc 100644 --- a/decidim-blogs/config/locales/nl.yml +++ b/decidim-blogs/config/locales/nl.yml @@ -1,3 +1,4 @@ +--- nl: activemodel: models: @@ -10,16 +11,14 @@ nl: decidim: blogs: actions: + author_id: Bericht aanmaken als confirm_destroy: Weet je zeker dat je dit bericht wilt verwijderen? destroy: Verwijder edit: Bewerk new: Nieuwe blogpost title: acties - user_group_id: Bericht aanmaken als admin: models: - components: - body: Tekstgedeelte post: name: Post posts: @@ -39,6 +38,11 @@ nl: update: invalid: Er zijn fouten opgetreden bij het opslaan van deze blogpost. success: Post succesvol opgeslagen + admin_log: + post: + create: "%{user_name} heeft de %{resource_name} blog gemaakt in %{space_name}" + delete: "%{user_name} heeft de %{resource_name} blog verwijderd in %{space_name}" + update: "%{user_name} heeft de %{resource_name} blog bijgewerkt in %{space_name}" last_activity: new_post_at_html: "Nieuw bericht op %{link}" models: @@ -47,7 +51,7 @@ nl: author: Auteur body: Tekstgedeelte created_at: Aangemaakt op - title: titel + official_blog_post: Officiële blogpost posts: show: back: Terug naar het overzicht diff --git a/decidim-blogs/config/locales/no.yml b/decidim-blogs/config/locales/no.yml index c77ff4daec5e1..9018e4b9f749b 100644 --- a/decidim-blogs/config/locales/no.yml +++ b/decidim-blogs/config/locales/no.yml @@ -1,3 +1,4 @@ +--- "no": activemodel: models: @@ -10,16 +11,14 @@ decidim: blogs: actions: + author_id: Opprett innlegg som confirm_destroy: Er du sikker pÃ¥ at du vil slette dette innlegget? destroy: Slett edit: Editar new: Nytt innlegg title: Handlinger - user_group_id: Opprett innlegg som admin: models: - components: - body: Tekst post: name: Innlegg posts: @@ -47,7 +46,6 @@ author: Forfatter body: Tekst created_at: Opprettet pÃ¥ - title: tittel posts: show: back: Tilbake til listen diff --git a/decidim-blogs/config/locales/pl.yml b/decidim-blogs/config/locales/pl.yml index bbb966fd64c58..ede2cf7725e25 100644 --- a/decidim-blogs/config/locales/pl.yml +++ b/decidim-blogs/config/locales/pl.yml @@ -1,3 +1,4 @@ +--- pl: activemodel: models: @@ -12,16 +13,14 @@ pl: decidim: blogs: actions: + author_id: Utwórz wpis jako confirm_destroy: Czy na pewno chcesz usunąć ten wpis? destroy: UsuÅ„ edit: Edytuj new: Nowy wpis title: DziaÅ‚ania - user_group_id: Utwórz wpis jako admin: models: - components: - body: Treść post: name: Wpis posts: @@ -49,7 +48,6 @@ pl: author: Autor body: Treść created_at: Utworzono - title: TytuÅ‚ posts: show: back: Powrót do listy diff --git a/decidim-blogs/config/locales/pt-BR.yml b/decidim-blogs/config/locales/pt-BR.yml index a00ff10230c9c..1ec52c59b0cf5 100644 --- a/decidim-blogs/config/locales/pt-BR.yml +++ b/decidim-blogs/config/locales/pt-BR.yml @@ -1,3 +1,4 @@ +--- pt-BR: activemodel: models: @@ -10,16 +11,14 @@ pt-BR: decidim: blogs: actions: + author_id: Criar publicação como confirm_destroy: Deseja mesmo excluir este post? destroy: Excluir edit: Editar new: Nova postagem title: Ações - user_group_id: Criar publicação como admin: models: - components: - body: Corpo post: name: Postar posts: @@ -47,7 +46,6 @@ pt-BR: author: Autor body: Corpo created_at: Criado em - title: título posts: show: back: Voltar para a lista diff --git a/decidim-blogs/config/locales/pt.yml b/decidim-blogs/config/locales/pt.yml index 3ca46431f5831..7cfc7c690b0e6 100644 --- a/decidim-blogs/config/locales/pt.yml +++ b/decidim-blogs/config/locales/pt.yml @@ -1,3 +1,4 @@ +--- pt: activemodel: models: @@ -10,16 +11,14 @@ pt: decidim: blogs: actions: + author_id: Criar publicação como confirm_destroy: Tem a certeza de que deseja eliminar esta publicação? destroy: Eliminar edit: Editar new: Nova publicação title: Ações - user_group_id: Criar publicação como admin: models: - components: - body: Corpo post: name: Publicação posts: @@ -47,7 +46,6 @@ pt: author: Autor body: Corpo created_at: Criado em - title: título posts: show: back: Retroceder à lista diff --git a/decidim-blogs/config/locales/ro-RO.yml b/decidim-blogs/config/locales/ro-RO.yml index 3ddd7d7ce667f..fead84118295d 100644 --- a/decidim-blogs/config/locales/ro-RO.yml +++ b/decidim-blogs/config/locales/ro-RO.yml @@ -1,5 +1,12 @@ +--- ro: activemodel: + attributes: + post: + body: ConÈ›inut + decidim_author_id: Autor + published_at: Publicat la + title: Titlu models: decidim/blogs/create_post_event: Postare nouă pe blog activerecord: @@ -11,16 +18,14 @@ ro: decidim: blogs: actions: + author_id: Creează postare ca confirm_destroy: Sigur doreÈ™ti să ÅŸtergi această postare? destroy: Șterge edit: Editează new: Postare nouă title: AcÈ›iuni - user_group_id: Creează postare ca admin: models: - components: - body: ConÈ›inut post: name: Postează posts: @@ -40,6 +45,11 @@ ro: update: invalid: A apărut o eroare la salvarea postării. success: Postarea a fost salvată cu succes + admin_log: + post: + create: "%{user_name} a creat postarea de blog %{resource_name} în %{space_name}" + delete: "%{user_name} a È™ters postarea de blog %{resource_name} din %{space_name}" + update: "%{user_name} a actualizat postarea de blog %{resource_name} în %{space_name}" last_activity: new_post_at_html: "Postare nouă la %{link}" models: @@ -48,7 +58,8 @@ ro: author: Autor body: ConÈ›inut created_at: Creat la - title: titlu + official_blog_post: Postare oficială + title: Titlu posts: show: back: ÃŽnapoi la listă @@ -61,8 +72,10 @@ ro: components: blogs: actions: + comment: Comentariu create: Creează destroy: Șterge + endorse: SusÈ›ine update: Actualizează name: Blog settings: diff --git a/decidim-blogs/config/locales/ru.yml b/decidim-blogs/config/locales/ru.yml index a241b036160e3..522c54d7d87f2 100644 --- a/decidim-blogs/config/locales/ru.yml +++ b/decidim-blogs/config/locales/ru.yml @@ -1,3 +1,4 @@ +--- ru: activemodel: models: @@ -19,8 +20,6 @@ ru: title: ДейÑÑ‚Ð²Ð¸Ñ admin: models: - components: - body: ОÑновной текÑÑ‚ post: name: ПоÑÑ‚ posts: @@ -47,7 +46,6 @@ ru: author: Ðвтор body: ОÑновной текÑÑ‚ created_at: 'Создано:' - title: заголовок posts: show: view: ПоÑмотреть diff --git a/decidim-blogs/config/locales/sk.yml b/decidim-blogs/config/locales/sk.yml index f4767670da8c8..33020fc0377da 100644 --- a/decidim-blogs/config/locales/sk.yml +++ b/decidim-blogs/config/locales/sk.yml @@ -1,3 +1,4 @@ +--- sk: activemodel: models: @@ -19,8 +20,6 @@ sk: title: Akcie admin: models: - components: - body: Telo textu post: name: Príspevok posts: @@ -47,7 +46,6 @@ sk: author: Autor body: Telo textu created_at: Vytvorené - title: názov posts: show: back: Späť na zoznam diff --git a/decidim-blogs/config/locales/sl.yml b/decidim-blogs/config/locales/sl.yml index a7ab48022455f..add144188ee05 100644 --- a/decidim-blogs/config/locales/sl.yml +++ b/decidim-blogs/config/locales/sl.yml @@ -1,3 +1,4 @@ +--- sl: decidim: blogs: diff --git a/decidim-blogs/config/locales/sr-CS.yml b/decidim-blogs/config/locales/sr-CS.yml index 7b352b7438174..1da853ddb71fd 100644 --- a/decidim-blogs/config/locales/sr-CS.yml +++ b/decidim-blogs/config/locales/sr-CS.yml @@ -1,3 +1,4 @@ +--- sr: decidim: blogs: diff --git a/decidim-blogs/config/locales/sv.yml b/decidim-blogs/config/locales/sv.yml index 58a2a0867bef2..be92e33e98eeb 100644 --- a/decidim-blogs/config/locales/sv.yml +++ b/decidim-blogs/config/locales/sv.yml @@ -1,5 +1,10 @@ +--- sv: activemodel: + attributes: + post: + decidim_author_id: Författare + title: Titel models: decidim/blogs/create_post_event: Nytt blogginlägg activerecord: @@ -10,16 +15,14 @@ sv: decidim: blogs: actions: + author_id: Skapa inlägg som confirm_destroy: Vill du radera inlägget? destroy: Radera edit: Redigera new: Nytt inlägg title: Ã…tgärder - user_group_id: Skapa inlägg som admin: models: - components: - body: InnehÃ¥ll post: name: Publicera posts: @@ -47,7 +50,8 @@ sv: author: Författare body: InnehÃ¥ll created_at: Skapad - title: titel + official_blog_post: Officiellt inlägg + title: Titel posts: show: back: Tillbaka till listan diff --git a/decidim-blogs/config/locales/tr-TR.yml b/decidim-blogs/config/locales/tr-TR.yml index 9841ab0c43cb0..e07bee4854125 100644 --- a/decidim-blogs/config/locales/tr-TR.yml +++ b/decidim-blogs/config/locales/tr-TR.yml @@ -1,3 +1,4 @@ +--- tr: activemodel: models: @@ -17,8 +18,6 @@ tr: title: Eylemler admin: models: - components: - body: Vücut post: name: posta posts: @@ -46,7 +45,6 @@ tr: author: Yazar body: Vücut created_at: Adresinde düzenlendi - title: BaÅŸlık posts: show: back: Listeye geri dön diff --git a/decidim-blogs/config/locales/uk.yml b/decidim-blogs/config/locales/uk.yml index d2402a0a39fc9..620d5ffa6d222 100644 --- a/decidim-blogs/config/locales/uk.yml +++ b/decidim-blogs/config/locales/uk.yml @@ -1,3 +1,4 @@ +--- uk: activemodel: models: @@ -19,8 +20,6 @@ uk: title: Дії admin: models: - components: - body: ОÑновний текÑÑ‚ post: name: Ð”Ð¾Ð¿Ð¸Ñ posts: @@ -45,7 +44,6 @@ uk: author: Ðвтор body: ОÑновний текÑÑ‚ created_at: 'Створено:' - title: заголовок posts: show: view: ПереглÑнути diff --git a/decidim-blogs/config/locales/zh-CN.yml b/decidim-blogs/config/locales/zh-CN.yml index 3b419067968d3..f77bed17d6fb7 100644 --- a/decidim-blogs/config/locales/zh-CN.yml +++ b/decidim-blogs/config/locales/zh-CN.yml @@ -1,3 +1,4 @@ +--- zh-CN: activemodel: models: @@ -16,8 +17,6 @@ zh-CN: title: 行动 admin: models: - components: - body: 正文内容 post: name: å¸–å­ posts: @@ -44,7 +43,6 @@ zh-CN: author: 作者 body: 正文内容 created_at: 创建于 - title: 标题 posts: show: back: 返回列表 diff --git a/decidim-blogs/decidim-blogs.gemspec b/decidim-blogs/decidim-blogs.gemspec index e2308afbe3654..8a78f812e7026 100644 --- a/decidim-blogs/decidim-blogs.gemspec +++ b/decidim-blogs/decidim-blogs.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |s| s.email = ["isaac.mg@coditramuntana.com"] s.license = "AGPL-3.0" s.homepage = "https://github.com/decidim/decidim" - s.required_ruby_version = ">= 2.7" + s.required_ruby_version = ">= 3.0" s.name = "decidim-blogs" s.summary = "Decidim blogs module" diff --git a/decidim-blogs/lib/decidim/blogs/component.rb b/decidim-blogs/lib/decidim/blogs/component.rb index 74270732199cb..9c249c112be8c 100644 --- a/decidim-blogs/lib/decidim/blogs/component.rb +++ b/decidim-blogs/lib/decidim/blogs/component.rb @@ -36,7 +36,7 @@ component.register_resource(:blogpost) do |resource| resource.model_class_name = "Decidim::Blogs::Post" resource.card = "decidim/blogs/post" - resource.actions = %w(endorse vote amend comment) + resource.actions = %w(endorse comment) resource.searchable = true end @@ -72,8 +72,14 @@ Decidim::Component.create!(params) end - 5.times do - author = Decidim::User.where(organization: component.organization).all.first + 6.times do |n| + author = if n >= 3 + Decidim::User.where(organization: component.organization).order(Arel.sql("RANDOM()")).first + elsif n <= 1 + Decidim::UserGroup.where(organization: component.organization).order(Arel.sql("RANDOM()")).first + else + component.organization + end params = { component: component, diff --git a/decidim-blogs/lib/decidim/blogs/version.rb b/decidim-blogs/lib/decidim/blogs/version.rb index 1593e669e8efa..1726d18b70a20 100644 --- a/decidim-blogs/lib/decidim/blogs/version.rb +++ b/decidim-blogs/lib/decidim/blogs/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-pages version. module Blogs def self.version - "0.26.4" + "0.27.2" end end end diff --git a/decidim-blogs/spec/commands/decidim/blogs/admin/update_post_spec.rb b/decidim-blogs/spec/commands/decidim/blogs/admin/update_post_spec.rb index 9744d9ccb8c41..b492306dc00c4 100644 --- a/decidim-blogs/spec/commands/decidim/blogs/admin/update_post_spec.rb +++ b/decidim-blogs/spec/commands/decidim/blogs/admin/update_post_spec.rb @@ -6,7 +6,7 @@ module Decidim module Blogs module Admin describe UpdatePost do - subject { described_class.new(form, post) } + subject { described_class.new(form, post, current_user) } let(:organization) { create(:organization) } let(:participatory_process) { create :participatory_process, organization: organization } @@ -34,7 +34,7 @@ module Admin end it "doesn't update the post" do - expect(post).not_to receive(:update_attributes!) + expect(post).not_to receive(:update!) subject.call end end @@ -61,6 +61,23 @@ module Admin expect { subject.call }.to change(Decidim::SearchableResource, :count).by_at_least(1) end + it "traces the action", versioning: true do + expect(Decidim.traceability) + .to receive(:update!) + .with(post, current_user, { + title: { en: title }, + body: { en: body }, + author: current_user + }) + .and_call_original + + expect { subject.call }.to change(Decidim::ActionLog, :count) + + action_log = Decidim::ActionLog.last + expect(action_log.version).to be_present + expect(action_log.version.event).to eq "update" + end + context "with a group author" do let(:group) { create(:user_group, :verified, organization: organization) } let(:form) do diff --git a/decidim-blogs/spec/forms/decidim/blogs/admin/post_form_spec.rb b/decidim-blogs/spec/forms/decidim/blogs/admin/post_form_spec.rb index ace889a61e1cf..0e98e42b8364f 100644 --- a/decidim-blogs/spec/forms/decidim/blogs/admin/post_form_spec.rb +++ b/decidim-blogs/spec/forms/decidim/blogs/admin/post_form_spec.rb @@ -8,11 +8,20 @@ module Admin describe PostForm do subject do described_class.from_params(attributes).with_context( - current_organization: current_organization + current_organization: current_organization, + current_user: current_user ) end let(:current_organization) { create(:organization) } + let(:current_user) { create :user, organization: current_organization } + let(:another_user) { create(:user, organization: current_organization) } + let(:user_group) { create(:user_group, :verified, organization: current_organization) } + let(:decidim_author_id) { "" } + let(:component) { create(:post_component, organization: current_organization) } + let(:post) { create(:post, component: component, author: author) } + let(:user_from_another_org) { create(:user) } + let(:post_id) { nil } let(:title) do { @@ -34,7 +43,9 @@ module Admin { "post" => { "title" => title, - "body" => body + "body" => body, + "decidim_author_id" => decidim_author_id, + "id" => post_id } } end @@ -43,24 +54,121 @@ module Admin it { is_expected.to be_valid } end - describe "map_model" do - let(:component) { create(:post_component, organization: current_organization) } - let(:post) { create(:post, component: component, author: author) } - let(:author) { create(:user, organization: current_organization) } + context "when title is missing" do + let(:title) do + { "en" => "" } + end + + it { is_expected.to be_invalid } + end - before do - subject.map_model(post) + context "when body is missing" do + let(:body) do + { "en" => "" } end - it "does not assign the user group for normal users" do - expect(subject.user_group_id).to be_nil + it { is_expected.to be_invalid } + end + + context "when organization is specified" do + let(:decidim_author_id) { current_organization.id } + + it { is_expected.to be_valid } + end + + context "when author is a current_user" do + let(:decidim_author_id) { current_user.id } + + it { is_expected.to be_valid } + + it "assigns current_user as author" do + expect(subject.author).to eq(current_user) + end + end + + context "when the author belongs to different organization" do + let(:decidim_author_id) { user_from_another_org.id } + + it "sets the author to the current_organization" do + expect(subject.author).to eq(current_organization) + end + end + + context "when decidim_author_id is empty" do + it "assigns current_organization as author" do + expect(subject.author).to eq(current_organization) + end + end + + context "when decidim_author_id is user_group" do + let(:decidim_author_id) { user_group.id } + + it "assigns user_group as author" do + expect(subject.author).to eq(user_group) + end + end + + context "when decidim_author_id is another_user from the same organization" do + let(:post_id) { post.id } + let(:author) { current_user } + let(:decidim_author_id) { another_user.id } + + it { is_expected.to be_invalid } + end + + describe "when assigns a model" do + subject do + described_class.from_model(post).with_context( + current_organization: current_organization, + current_user: current_user + ) + end + + let(:author) { current_organization } + + context "when author is an organization" do + it "assigns current_organization.id as decidim_author_id" do + expect(subject.decidim_author_id).to be_nil + end + + it "assigns current_organization as author" do + expect(subject.author).to eq(current_organization) + end end context "when the author is a group" do - let(:author) { create(:user_group, :verified, organization: current_organization) } + let(:author) { user_group } + + it "assigns user_group.id as decidim_author_id" do + expect(subject.decidim_author_id).to eq(user_group.id) + end + + it "assigns user_group as author" do + expect(subject.author).to eq(user_group) + end + end + + context "when the author is the current_user" do + let(:author) { current_user } + + it "assigns current_user.id as decidim_author_id" do + expect(subject.decidim_author_id).to eq(current_user.id) + end + + it "assigns current_user object as author" do + expect(subject.author).to eq(current_user) + end + end + + context "when the author is another user" do + let(:author) { another_user } + + it "assigns another_user.id as decidim_author_id" do + expect(subject.decidim_author_id).to eq(another_user.id) + end - it "assigns the user group ID to the form" do - expect(subject.user_group_id).to eq(author.id) + it "assigns another_user object as author" do + expect(subject.author).to eq(another_user) end end end diff --git a/decidim-blogs/spec/helpers/decidim/blogs/admin/post_helper_spec.rb b/decidim-blogs/spec/helpers/decidim/blogs/admin/post_helper_spec.rb new file mode 100644 index 0000000000000..f3e6b18fcce93 --- /dev/null +++ b/decidim-blogs/spec/helpers/decidim/blogs/admin/post_helper_spec.rb @@ -0,0 +1,118 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim::Blogs::Admin + describe PostsHelper, type: :helper do + describe "#post_author_select_field" do + let(:organization) { create :organization } + let(:user) { create :user, :admin, :confirmed, organization: organization } + let!(:another_user) { create :user, :admin, :confirmed, organization: organization } + let!(:user_group) { create :user_group, :verified, decidim_organization_id: organization.id, users: [user] } + let!(:another_user_group) { create :user_group, :verified, decidim_organization_id: organization.id, users: [another_user] } + let(:name) { "a-select-form-name" } + let(:author) { user } + let(:form) do + double( + object: double(author: author) + ) + end + + let(:all_fields) do + [ + [organization.name, ""], + [user.name, user.id], + [user_group.name, user_group.id] + ] + end + + let(:extra_user_fields) do + [ + [organization.name, ""], + [user.name, user.id], + [user_group.name, user_group.id], + [another_user.name, another_user.id] + ] + end + + let(:extra_group_fields) do + [ + [organization.name, ""], + [user.name, user.id], + [user_group.name, user_group.id], + [another_user_group.name, another_user_group.id] + ] + end + + let(:basic_fields) do + [ + [organization.name, ""], + [user.name, user.id] + ] + end + + let(:groups_enabled) { true } + + before do + allow(helper).to receive(:current_organization).and_return(organization) + allow(helper).to receive(:current_user).and_return(user) + allow(organization).to receive(:user_groups_enabled?).and_return(groups_enabled) + allow(form).to receive(:select) { |_, array| array } + end + + context "when all actors are present" do + it "Returns all types of authors" do + expect(helper.post_author_select_field(form, name)).to eq(all_fields) + end + end + + context "when author is a user's user_group" do + let(:author) { user_group } + + it "Returns all types of authors" do + expect(helper.post_author_select_field(form, name)).to eq(all_fields) + end + end + + context "when organization has no groups_enabled" do + let(:groups_enabled) { false } + + it "Returns organization and user" do + expect(helper.post_author_select_field(form, name)).to eq(basic_fields) + end + + context "when author is a user's user_group" do + let(:author) { user_group } + + it "Returns organization, user and user group" do + expect(helper.post_author_select_field(form, name)).to eq(all_fields) + end + end + end + + context "when author is another user" do + let(:author) { another_user } + + it "Returns all types of authors plus the original author" do + expect(helper.post_author_select_field(form, name)).to eq(extra_user_fields) + end + end + + context "when author is the organization" do + let(:author) { organization } + + it "Returns all types of authors" do + expect(helper.post_author_select_field(form, name)).to eq(all_fields) + end + end + + context "when author is another user_group" do + let(:author) { another_user_group } + + it "Returns all types of authors" do + expect(helper.post_author_select_field(form, name)).to eq(extra_group_fields) + end + end + end + end +end diff --git a/decidim-blogs/spec/permissions/decidim/blog/permissions_spec.rb b/decidim-blogs/spec/permissions/decidim/blog/permissions_spec.rb index 3752dde71d5b1..abf48cd124a70 100644 --- a/decidim-blogs/spec/permissions/decidim/blog/permissions_spec.rb +++ b/decidim-blogs/spec/permissions/decidim/blog/permissions_spec.rb @@ -12,14 +12,14 @@ } end let(:blog_component) { create :post_component } - let(:permission_action) { Decidim::PermissionAction.new(action) } + let(:permission_action) { Decidim::PermissionAction.new(**action) } context "when scope is public" do let(:action) do { scope: :public, action: :foo, subject: :blogpost } end - it { is_expected.to eq true } + it { is_expected.to be true } end context "when scope is admin" do @@ -27,7 +27,7 @@ { scope: :admin, action: :foo, subject: :blogpost } end - it { is_expected.to eq true } + it { is_expected.to be true } end context "when scope is a random one" do diff --git a/decidim-blogs/spec/services/decidim/blogs/searchable_blogpost_resource_spec.rb b/decidim-blogs/spec/services/decidim/blogs/searchable_blogpost_resource_spec.rb index 82d50239affe6..811f59fbdd562 100644 --- a/decidim-blogs/spec/services/decidim/blogs/searchable_blogpost_resource_spec.rb +++ b/decidim-blogs/spec/services/decidim/blogs/searchable_blogpost_resource_spec.rb @@ -15,7 +15,7 @@ module Decidim :post, component: current_component, title: Decidim::Faker::Localized.name, - body: description_1 + body: description1 ) end @@ -68,7 +68,7 @@ module Decidim describe "Search" do context "when searching by resource resource_type" do - let!(:resource_2) do + let!(:resource2) do create( :post, component: current_component, @@ -82,7 +82,7 @@ module Decidim on(:ok) do |results_by_type| results = results_by_type[resource.class.name] expect(results[:count]).to eq 2 - expect(results[:results]).to match_array [resource, resource_2] + expect(results[:results]).to match_array [resource, resource2] end on(:invalid) { raise("Should not happen") } end @@ -93,7 +93,7 @@ module Decidim on(:ok) do |results_by_type| results = results_by_type[resource.class.name] expect(results[:count]).to eq 1 - expect(results[:results]).to eq [resource_2] + expect(results[:results]).to eq [resource2] end on(:invalid) { raise("Should not happen") } end diff --git a/decidim-blogs/spec/shared/manage_posts_examples.rb b/decidim-blogs/spec/shared/manage_posts_examples.rb index c2bdefc7b649a..64c25252dcc2e 100644 --- a/decidim-blogs/spec/shared/manage_posts_examples.rb +++ b/decidim-blogs/spec/shared/manage_posts_examples.rb @@ -7,6 +7,8 @@ end within ".edit_post" do + expect(page).to have_select("post_decidim_author_id", selected: author.name) + fill_in_i18n( :post_title, "#post-title-tabs", @@ -30,6 +32,7 @@ within "table" do expect(page).to have_content("My new title") expect(page).to have_content("Post title 2") + expect(page).to have_content(author.name) end end @@ -91,7 +94,7 @@ it "can set user group as posts author", :slow do find(".card-title a.button").click - select user_group.name, from: "post_user_group_id" + select user_group.name, from: "post_decidim_author_id" fill_in_i18n( :post_title, @@ -129,7 +132,7 @@ end within ".edit_post" do - select user_group.name, from: "post_user_group_id" + select user_group.name, from: "post_decidim_author_id" find("*[type=submit]").click end @@ -140,4 +143,116 @@ end end end + + context "when user is the organization" do + let(:author) { organization } + + it "can set organization as posts author", :slow do + find(".card-title a.button").click + + select organization.name, from: "post_decidim_author_id" + + fill_in_i18n( + :post_title, + "#post-title-tabs", + en: "My post", + es: "Mi post", + ca: "El meu post" + ) + + fill_in_i18n_editor( + :post_body, + "#post-body-tabs", + en: "A description", + es: "Descripción", + ca: "Descripció" + ) + + within ".new_post" do + find("*[type=submit]").click + end + + expect(page).to have_admin_callout("successfully") + + within "table" do + expect(page).to have_content(author.name) + expect(page).to have_content("My post") + expect(page).to have_content("Post title 1") + expect(page).to have_content("Post title 2") + end + end + + it "can update the blog as the organization" do + within find("tr", text: translated(post1.title)) do + click_link "Edit" + end + + within ".edit_post" do + select organization.name, from: "post_decidim_author_id" + find("*[type=submit]").click + end + + expect(page).to have_admin_callout("successfully") + + within find("tr", text: translated(post1.title)) do + expect(page).to have_content(author.name) + end + end + end + + context "when user is current_user" do + let(:author) { user } + + it "can set current_user as posts author", :slow do + find(".card-title a.button").click + + select user.name, from: "post_decidim_author_id" + + fill_in_i18n( + :post_title, + "#post-title-tabs", + en: "My post", + es: "Mi post", + ca: "El meu post" + ) + + fill_in_i18n_editor( + :post_body, + "#post-body-tabs", + en: "A description", + es: "Descripción", + ca: "Descripció" + ) + + within ".new_post" do + find("*[type=submit]").click + end + + expect(page).to have_admin_callout("successfully") + + within "table" do + expect(page).to have_content(author.name) + expect(page).to have_content("My post") + expect(page).to have_content("Post title 1") + expect(page).to have_content("Post title 2") + end + end + + it "can update the blog as the user" do + within find("tr", text: translated(post1.title)) do + click_link "Edit" + end + + within ".edit_post" do + select user.name, from: "post_decidim_author_id" + find("*[type=submit]").click + end + + expect(page).to have_admin_callout("successfully") + + within find("tr", text: translated(post1.title)) do + expect(page).to have_content(author.name) + end + end + end end diff --git a/decidim-blogs/spec/system/admin_manages_posts_spec.rb b/decidim-blogs/spec/system/admin_manages_posts_spec.rb index 2d8087a233f71..e0f62fa95acca 100644 --- a/decidim-blogs/spec/system/admin_manages_posts_spec.rb +++ b/decidim-blogs/spec/system/admin_manages_posts_spec.rb @@ -4,10 +4,21 @@ describe "Admin manages posts", type: :system do let(:manifest_name) { "blogs" } - let!(:post1) { create :post, component: current_component, title: { en: "Post title 1" } } + let!(:post1) { create :post, component: current_component, author: author, title: { en: "Post title 1" } } let!(:post2) { create :post, component: current_component, title: { en: "Post title 2" } } + let(:author) { create :user, organization: organization } include_context "when managing a component as an admin" - it_behaves_like "manage posts" + context "when author is the organization" do + let(:author) { organization } + + it_behaves_like "manage posts" + end + + context "when author is a user" do + let(:author) { create :user, organization: organization } + + it_behaves_like "manage posts" + end end diff --git a/decidim-blogs/spec/system/endorse_posts_spec.rb b/decidim-blogs/spec/system/endorse_posts_spec.rb new file mode 100644 index 0000000000000..cb0a7a18cdcfa --- /dev/null +++ b/decidim-blogs/spec/system/endorse_posts_spec.rb @@ -0,0 +1,107 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe "endorse posts", type: :system do + include_context "with a component" + let(:manifest_name) { "blogs" } + let(:organization) { create(:organization) } + let(:author) { create(:user, :confirmed, name: "Tester", organization: organization) } + let!(:post) { create(:post, component: component, title: { en: "Blog post title" }) } + + before do + sign_in author + visit_component + click_link "Blog post title" + end + + context "when liking the post without belonging to a user group" do + it "likes the post" do + click_button("Endorse") + expect(page).to have_content("ENDORSED") + end + end + + context "when liking the post while being a part of a group" do + let!(:user_group) do + create( + :user_group, + :verified, + name: "Tester's Organization", + nickname: "test_org", + email: "t.mail.org@example.org", + users: [author], + organization: organization + ) + end + + it "opens a modal where you select identity as a user or a group" do + visit page.current_path + click_button("Endorse") + expect(page).to have_content("SELECT IDENTITY") + expect(page).to have_content("Tester's Organization") + expect(page).to have_content("Tester") + end + + def add_likes + click_button "Endorse" + within "#user-identities" do + find("li", text: /\ATester's Organization\z/).click + find("li", text: /\ATester\z/).click + click_button "Done" + end + visit current_path + click_button "Endorse" + end + + context "when both identities picked" do + it "likes the post as a group and a user" do + visit page.current_path + + add_likes + + within "#user-identities" do + expect(page).to have_css(".selected", count: 2) + end + end + end + + context "when like cancelled as a user" do + it "doesn't cancel group like" do + visit page.current_path + + add_likes + find(".selected", match: :first).click + click_button "Done" + visit current_path + click_button "Endorse" + + within "#user-identities" do + expect(page).to have_css(".selected", count: 1) + within ".selected" do + expect(page).to have_content("Tester's Organization") + end + end + end + end + + context "when like cancelled as a group" do + it "doesn't cancel user like" do + visit page.current_path + + add_likes + page.all(".selected")[1].click + click_button "Done" + visit current_path + click_button "Endorse" + + within "#user-identities" do + expect(page).to have_css(".selected", count: 1) + within ".selected" do + expect(page).to have_text("Tester", exact: true) + end + end + end + end + end +end diff --git a/decidim-blogs/spec/system/explore_posts_spec.rb b/decidim-blogs/spec/system/explore_posts_spec.rb index 0c1667fb0fbfc..6035034e431ed 100644 --- a/decidim-blogs/spec/system/explore_posts_spec.rb +++ b/decidim-blogs/spec/system/explore_posts_spec.rb @@ -6,7 +6,7 @@ include_context "with a component" let(:manifest_name) { "blogs" } - let!(:old_post) { create(:post, component: component, created_at: Time.current - 2.days) } + let!(:old_post) { create(:post, component: component, created_at: 2.days.ago) } let!(:new_post) { create(:post, component: component, created_at: Time.current) } let!(:image) { create(:attachment, attached_to: old_post) } @@ -54,12 +54,41 @@ describe "show" do let(:posts_count) { 1 } - let!(:post) { create(:post, component: component) } + let(:author) { organization } + let!(:post) { create(:post, component: component, author: author) } before do visit resource_locator(post).path end + context "when author is an organization" do + it "shows 'Official' as the author" do + within ".author__name" do + expect(page).to have_content("Official") + end + end + end + + context "when author is a user_group" do + let(:author) { create(:user_group, :verified, organization: organization) } + + it "shows user group as the author" do + within ".author__name" do + expect(page).to have_content(author.name) + end + end + end + + context "when author is a user" do + let(:author) { user } + + it "shows user as the author" do + within ".author__name" do + expect(page).to have_content(user.name) + end + end + end + it "show post info" do expect(page).to have_i18n_content(post.title) expect(page).to have_i18n_content(post.body) diff --git a/decidim-blogs/spec/system/process_admin_manages_post_spec.rb b/decidim-blogs/spec/system/process_admin_manages_post_spec.rb index 3b8dbf9b598f8..d01c4f09dd475 100644 --- a/decidim-blogs/spec/system/process_admin_manages_post_spec.rb +++ b/decidim-blogs/spec/system/process_admin_manages_post_spec.rb @@ -4,8 +4,9 @@ describe "Process admin manages post", type: :system do let(:manifest_name) { "blogs" } - let!(:post1) { create :post, component: current_component, title: { en: "Post title 1" } } + let!(:post1) { create :post, component: current_component, author: author, title: { en: "Post title 1" } } let!(:post2) { create :post, component: current_component, title: { en: "Post title 2" } } + let(:author) { create :user, organization: organization } include_context "when managing a component as a process admin" diff --git a/decidim-blogs/spec/types/integration_schema_spec.rb b/decidim-blogs/spec/types/integration_schema_spec.rb index 6d4a5ed9e72c0..8291173c90b35 100644 --- a/decidim-blogs/spec/types/integration_schema_spec.rb +++ b/decidim-blogs/spec/types/integration_schema_spec.rb @@ -160,7 +160,7 @@ let!(:other_post) { create(:post, created_at: 2.weeks.ago, updated_at: 1.week.ago, component: current_component) } let(:edges) { response["participatoryProcess"]["components"].first["posts"]["edges"] } - context "when ordered by " do + context "when ordered by" do context "with createdAt" do let(:criteria) { "order: { createdAt: \"asc\" }" } @@ -219,12 +219,6 @@ it { expect(edges).to eq([{ "node" => { "id" => other_post.id.to_s } }]) } end - - context "with updatedBefore" do - let(:criteria) { "filter: { updatedBefore: \"#{post.created_at.to_date}\" } " } - - it { expect(edges).to eq([{ "node" => { "id" => other_post.id.to_s } }]) } - end end end end diff --git a/decidim-budgets/app/cells/decidim/budgets/order_activity_cell.rb b/decidim-budgets/app/cells/decidim/budgets/order_activity_cell.rb new file mode 100644 index 0000000000000..6c196e173ce4b --- /dev/null +++ b/decidim-budgets/app/cells/decidim/budgets/order_activity_cell.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module Decidim + module Budgets + # A cell to display when actions happen on an order. + class OrderActivityCell < ActivityCell + def title + I18n.t( + "decidim.budgets.last_activity.new_vote_at_html", + link: participatory_space_link + ) + end + + def resource_link_path + resource_locator(budget).path + end + + def resource_link_text + decidim_html_escape(translated_attribute(budget.title)) + end + + private + + def budget + @budget ||= resource.budget + end + end + end +end diff --git a/decidim-budgets/app/commands/decidim/budgets/add_line_item.rb b/decidim-budgets/app/commands/decidim/budgets/add_line_item.rb index 388fc87a78f8f..ee4e78aa7f71e 100644 --- a/decidim-budgets/app/commands/decidim/budgets/add_line_item.rb +++ b/decidim-budgets/app/commands/decidim/budgets/add_line_item.rb @@ -3,7 +3,7 @@ module Decidim module Budgets # A command with all the business to add new line items to orders - class AddLineItem < Rectify::Command + class AddLineItem < Decidim::Command # Public: Initializes the command. # # order - The current order for the user or nil if it is not created yet. @@ -23,11 +23,13 @@ def initialize(current_order, project, current_user) # Returns nothing. def call transaction do - return broadcast(:invalid) if voting_not_enabled? || order.checked_out? || exceeds_budget? + raise ActiveRecord::RecordInvalid if voting_not_enabled? || order.checked_out? || exceeds_budget? add_line_item broadcast(:ok, order) end + rescue ActiveRecord::RecordInvalid + broadcast(:invalid) end private diff --git a/decidim-budgets/app/commands/decidim/budgets/admin/create_budget.rb b/decidim-budgets/app/commands/decidim/budgets/admin/create_budget.rb index fb65ffabfdfac..e344c8dcb3559 100644 --- a/decidim-budgets/app/commands/decidim/budgets/admin/create_budget.rb +++ b/decidim-budgets/app/commands/decidim/budgets/admin/create_budget.rb @@ -5,7 +5,7 @@ module Budgets module Admin # This command is executed when the user creates an Budget # from the admin panel. - class CreateBudget < Rectify::Command + class CreateBudget < Decidim::Command def initialize(form) @form = form end diff --git a/decidim-budgets/app/commands/decidim/budgets/admin/create_order_reminders.rb b/decidim-budgets/app/commands/decidim/budgets/admin/create_order_reminders.rb new file mode 100644 index 0000000000000..e60e94cefb67d --- /dev/null +++ b/decidim-budgets/app/commands/decidim/budgets/admin/create_order_reminders.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +module Decidim + module Budgets + module Admin + # This command is executed when admin sends vote reminders. + class CreateOrderReminders < Decidim::Command + def initialize(form) + @form = form + end + + def call + return broadcast(:invalid) if form.invalid? + return broadcast(:invalid) unless voting_enabled? + return broadcast(:invalid) if voting_ends_soon? + + generator.generate_for(current_component, &alternative_refresh_state) + + broadcast(:ok, generator.reminder_jobs_queued) + end + + private + + attr_reader :form + + def alternative_refresh_state + proc do |reminder| + reminder.records.each do |record| + next if %w(active pending).exclude? record.state + + record.state = begin + if record.remindable.created_at > minimum_time_between_reminders || + (reminder.deliveries.present? && reminder.deliveries.last.created_at > minimum_time_between_reminders) + "pending" + else + "active" + end + end + record.save if record.changed? + end + end + end + + def minimum_time_between_reminders + form.minimum_interval_between_reminders.ago + end + + def generator + @generator ||= Decidim::Budgets::OrderReminderGenerator.new + end + + def current_component + form.current_component + end + + def voting_enabled? + form.voting_enabled? + end + + def voting_ends_soon? + form.voting_ends_soon? + end + end + end + end +end diff --git a/decidim-budgets/app/commands/decidim/budgets/admin/create_project.rb b/decidim-budgets/app/commands/decidim/budgets/admin/create_project.rb index ff3c2e8b9c7a8..e8a4696af77cb 100644 --- a/decidim-budgets/app/commands/decidim/budgets/admin/create_project.rb +++ b/decidim-budgets/app/commands/decidim/budgets/admin/create_project.rb @@ -5,7 +5,7 @@ module Budgets module Admin # This command is executed when the user creates a Project from the admin # panel. - class CreateProject < Rectify::Command + class CreateProject < Decidim::Command include ::Decidim::AttachmentMethods include ::Decidim::GalleryMethods @@ -44,7 +44,10 @@ def create_project! category: form.category, title: form.title, description: form.description, - budget_amount: form.budget_amount + budget_amount: form.budget_amount, + address: form.address, + latitude: form.latitude, + longitude: form.longitude } @project = Decidim.traceability.create!( diff --git a/decidim-budgets/app/commands/decidim/budgets/admin/destroy_budget.rb b/decidim-budgets/app/commands/decidim/budgets/admin/destroy_budget.rb index 8efda0d6b9d4e..6289de3c2c311 100644 --- a/decidim-budgets/app/commands/decidim/budgets/admin/destroy_budget.rb +++ b/decidim-budgets/app/commands/decidim/budgets/admin/destroy_budget.rb @@ -5,7 +5,7 @@ module Budgets module Admin # This command is executed when the user destroys a Budget # from the admin panel. - class DestroyBudget < Rectify::Command + class DestroyBudget < Decidim::Command def initialize(budget, current_user) @budget = budget @current_user = current_user diff --git a/decidim-budgets/app/commands/decidim/budgets/admin/destroy_project.rb b/decidim-budgets/app/commands/decidim/budgets/admin/destroy_project.rb index 75b322d1cee81..f0eaeac0fc0d9 100644 --- a/decidim-budgets/app/commands/decidim/budgets/admin/destroy_project.rb +++ b/decidim-budgets/app/commands/decidim/budgets/admin/destroy_project.rb @@ -5,7 +5,7 @@ module Budgets module Admin # This command is executed when the user deletes a Project from the admin # panel. - class DestroyProject < Rectify::Command + class DestroyProject < Decidim::Command # Initializes an UpdateProject Command. # # project - The current instance of the project to be destroyed. diff --git a/decidim-budgets/app/commands/decidim/budgets/admin/import_proposals_to_budgets.rb b/decidim-budgets/app/commands/decidim/budgets/admin/import_proposals_to_budgets.rb index 97addf67f1c75..350f4923c5b93 100644 --- a/decidim-budgets/app/commands/decidim/budgets/admin/import_proposals_to_budgets.rb +++ b/decidim-budgets/app/commands/decidim/budgets/admin/import_proposals_to_budgets.rb @@ -5,7 +5,7 @@ module Budgets module Admin # A command with all the business logic when an admin imports proposals from # one component to projects of a budget. - class ImportProposalsToBudgets < Rectify::Command + class ImportProposalsToBudgets < Decidim::Command # Public: Initializes the command. # # form - A form object with the params. @@ -48,7 +48,10 @@ def create_project_from_proposal!(original_proposal) description: original_proposal.body, budget_amount: budget_for(original_proposal), category: original_proposal.category, - scope: original_proposal.scope + scope: original_proposal.scope, + address: original_proposal.address, + latitude: original_proposal.latitude, + longitude: original_proposal.longitude } @project = Decidim.traceability.create!( diff --git a/decidim-budgets/app/commands/decidim/budgets/admin/update_budget.rb b/decidim-budgets/app/commands/decidim/budgets/admin/update_budget.rb index ceb060c04802d..316d68753ce50 100644 --- a/decidim-budgets/app/commands/decidim/budgets/admin/update_budget.rb +++ b/decidim-budgets/app/commands/decidim/budgets/admin/update_budget.rb @@ -5,7 +5,7 @@ module Budgets module Admin # This command is executed when the user updates a Budget # from the admin panel. - class UpdateBudget < Rectify::Command + class UpdateBudget < Decidim::Command def initialize(form, budget) @form = form @budget = budget diff --git a/decidim-budgets/app/commands/decidim/budgets/admin/update_project.rb b/decidim-budgets/app/commands/decidim/budgets/admin/update_project.rb index b0dbc5c4750b2..0a6122dff94c7 100644 --- a/decidim-budgets/app/commands/decidim/budgets/admin/update_project.rb +++ b/decidim-budgets/app/commands/decidim/budgets/admin/update_project.rb @@ -5,7 +5,7 @@ module Budgets module Admin # This command is executed when the user changes a Project from the admin # panel. - class UpdateProject < Rectify::Command + class UpdateProject < Decidim::Command include ::Decidim::AttachmentMethods include ::Decidim::GalleryMethods @@ -53,7 +53,10 @@ def update_project title: form.title, description: form.description, budget_amount: form.budget_amount, - selected_at: selected_at + selected_at: selected_at, + address: form.address, + latitude: form.latitude, + longitude: form.longitude ) end diff --git a/decidim-budgets/app/commands/decidim/budgets/admin/update_project_category.rb b/decidim-budgets/app/commands/decidim/budgets/admin/update_project_category.rb new file mode 100644 index 0000000000000..99474a64c9714 --- /dev/null +++ b/decidim-budgets/app/commands/decidim/budgets/admin/update_project_category.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +module Decidim + module Budgets + module Admin + class UpdateProjectCategory < Decidim::Command + include TranslatableAttributes + + # Public: Initializes the command. + # + # category_id - the category id to update + # project_ids - the project ids to update. + def initialize(category_id, project_ids) + @category = Decidim::Category.find_by id: category_id + @project_ids = project_ids + @response = { category_name: "", successful: [], errored: [] } + end + + def call + return broadcast(:invalid_category) if @category.blank? + return broadcast(:invalid_project_ids) if @project_ids.blank? + + @response[:category_name] = @category.translated_name + Project.where(id: @project_ids).find_each do |project| + if @category == project.category + @response[:errored] << translated_attribute(project.title) + else + transaction do + update_project_category project + end + @response[:successful] << translated_attribute(project.title) + end + end + + broadcast(:update_projects_category, @response) + end + + private + + def update_project_category(project) + project.update!( + category: @category + ) + end + end + end + end +end diff --git a/decidim-budgets/app/commands/decidim/budgets/admin/update_project_scope.rb b/decidim-budgets/app/commands/decidim/budgets/admin/update_project_scope.rb new file mode 100644 index 0000000000000..ae32ad5f8bbc7 --- /dev/null +++ b/decidim-budgets/app/commands/decidim/budgets/admin/update_project_scope.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +module Decidim + module Budgets + module Admin + class UpdateProjectScope < Decidim::Command + include TranslatableAttributes + + # Public: Initializes the command. + # + # scope_id - the scope id to update + # project_ids - the project ids to update. + def initialize(scope_id, project_ids) + @scope = ::Decidim::Scope.find_by id: scope_id + @project_ids = project_ids + @response = { scope_name: "", successful: [], errored: [] } + end + + def call + return broadcast(:invalid_scope) if @scope.blank? + return broadcast(:invalid_project_ids) if @project_ids.blank? + + update_projects_scope + + broadcast(:update_projects_scope, @response) + end + + private + + attr_reader :scope, :project_ids + + def update_projects_scope + @response[:scope_name] = translated_attribute(scope.name, scope.organization) + ::Decidim::Budgets::Project.where(id: project_ids).find_each do |project| + if scope == project.scope + @response[:errored] << translated_attribute(project.title) + else + transaction do + update_project_scope project + end + @response[:successful] << translated_attribute(project.title) + end + end + end + + def update_project_scope(project) + project.update!( + scope: scope + ) + end + end + end + end +end diff --git a/decidim-budgets/app/commands/decidim/budgets/admin/update_project_selection.rb b/decidim-budgets/app/commands/decidim/budgets/admin/update_project_selection.rb new file mode 100644 index 0000000000000..57da744d6c98d --- /dev/null +++ b/decidim-budgets/app/commands/decidim/budgets/admin/update_project_selection.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module Decidim + module Budgets + module Admin + class UpdateProjectSelection < Decidim::Command + include TranslatableAttributes + + # Public: Initializes the command. + # + # selection - Defines if projects are selected (for implementation) + # project_ids - the project ids to update. + def initialize(selection, project_ids) + @selection = selection + @project_ids = project_ids + @response = { selection_name: "", successful: [], errored: [] } + end + + def call + return broadcast(:invalid_selection) if @selection.blank? || [true, false, "true", "false"].exclude?(@selection) + return broadcast(:invalid_project_ids) if @project_ids.blank? + + @selection = ActiveModel::Type::Boolean.new.cast(@selection) + + update_projects_selection + + broadcast(:update_projects_selection, @response) + end + + private + + attr_reader :selection, :project_ids + + def update_projects_selection + ::Decidim::Budgets::Project.where(id: project_ids).find_each do |project| + if (selection == false && !project.selected?) || (selection && project.selected?) + @response[:errored] << translated_attribute(project.title) + else + transaction do + update_project_selection project + end + @response[:successful] << translated_attribute(project.title) + end + end + end + + def update_project_selection(project) + selected_at = selection ? Time.current : nil + project.update!( + selected_at: selected_at + ) + end + end + end + end +end diff --git a/decidim-budgets/app/commands/decidim/budgets/cancel_order.rb b/decidim-budgets/app/commands/decidim/budgets/cancel_order.rb index f78a18793fa0e..7251cc5ad4034 100644 --- a/decidim-budgets/app/commands/decidim/budgets/cancel_order.rb +++ b/decidim-budgets/app/commands/decidim/budgets/cancel_order.rb @@ -3,7 +3,7 @@ module Decidim module Budgets # A command with all the business to cancel an order. - class CancelOrder < Rectify::Command + class CancelOrder < Decidim::Command # Public: Initializes the command. # # order - The current order for the user. diff --git a/decidim-budgets/app/commands/decidim/budgets/checkout.rb b/decidim-budgets/app/commands/decidim/budgets/checkout.rb index 73ef6a3c30674..ef47b366c55d9 100644 --- a/decidim-budgets/app/commands/decidim/budgets/checkout.rb +++ b/decidim-budgets/app/commands/decidim/budgets/checkout.rb @@ -3,7 +3,7 @@ module Decidim module Budgets # A command with all the business to checkout. - class Checkout < Rectify::Command + class Checkout < Decidim::Command # Public: Initializes the command. # # order - The current order for the user. @@ -32,8 +32,15 @@ def checkout! @order.with_lock do SendOrderSummaryJob.perform_later(@order) - @order.checked_out_at = Time.current - @order.save + + Decidim.traceability.update!( + @order, + @order.user, + { checked_out_at: Time.current }, + visibility: "private-only" + ) + rescue ActiveRecord::RecordInvalid + false end end end diff --git a/decidim-budgets/app/commands/decidim/budgets/remove_line_item.rb b/decidim-budgets/app/commands/decidim/budgets/remove_line_item.rb index 0a41cc946e31e..015b47edc53df 100644 --- a/decidim-budgets/app/commands/decidim/budgets/remove_line_item.rb +++ b/decidim-budgets/app/commands/decidim/budgets/remove_line_item.rb @@ -3,7 +3,7 @@ module Decidim module Budgets # A command with all the business to add remove line items from orders - class RemoveLineItem < Rectify::Command + class RemoveLineItem < Decidim::Command # Public: Initializes the command. # # order - The current order for the user diff --git a/decidim-budgets/app/controllers/decidim/budgets/admin/projects_controller.rb b/decidim-budgets/app/controllers/decidim/budgets/admin/projects_controller.rb index 6c75ad6ed2e9e..72aecc28793f0 100644 --- a/decidim-budgets/app/controllers/decidim/budgets/admin/projects_controller.rb +++ b/decidim-budgets/app/controllers/decidim/budgets/admin/projects_controller.rb @@ -8,8 +8,9 @@ class ProjectsController < Admin::ApplicationController include Decidim::ApplicationHelper include Decidim::Proposals::Admin::Picker if Decidim::Budgets.enable_proposal_linking include Decidim::Budgets::Admin::Filterable + helper Decidim::Budgets::Admin::ProjectBulkActionsHelper - helper_method :projects, :finished_orders, :pending_orders, :present + helper_method :projects, :finished_orders, :pending_orders, :present, :project_ids def collection @collection ||= budget.projects.page(params[:page]).per(15) @@ -74,6 +75,93 @@ def destroy end end + def update_category + enforce_permission_to :update, :project_category + + ::Decidim::Budgets::Admin::UpdateProjectCategory.call(params[:category][:id], project_ids) do + on(:invalid_category) do + flash.now[:error] = I18n.t( + "projects.update_category.select_a_category", + scope: "decidim.budgets.admin" + ) + end + + on(:invalid_project_ids) do + flash.now[:alert] = I18n.t( + "projects.update_category.select_a_project", + scope: "decidim.budgets.admin" + ) + end + + on(:update_projects_category) do + flash.now[:notice] = update_projects_bulk_response_successful(@response, :category) + flash.now[:alert] = update_projects_bulk_response_errored(@response, :category) + end + end + + respond_to do |format| + format.js { render :update_attribute, locals: { form_selector: "#js-form-recategorize-projects", attribute_selector: "#category_id" } } + end + end + + def update_scope + enforce_permission_to :update, :project_scope + + ::Decidim::Budgets::Admin::UpdateProjectScope.call(params[:scope_id], project_ids) do + on(:invalid_scope) do + flash.now[:error] = t( + "projects.update_scope.select_a_scope", + scope: "decidim.budgets.admin" + ) + end + + on(:invalid_project_ids) do + flash.now[:alert] = t( + "projects.update_scope.select_a_project", + scope: "decidim.budgets.admin" + ) + end + + on(:update_projects_scope) do + flash.now[:notice] = update_projects_bulk_response_successful(@response, :scope) + flash.now[:alert] = update_projects_bulk_response_errored(@response, :scope) + end + end + + respond_to do |format| + format.js { render :update_attribute, locals: { form_selector: "#js-form-scope-change-projects", attribute_selector: "#scope_id" } } + end + end + + def update_selected + enforce_permission_to :update, :project_selected + + ::Decidim::Budgets::Admin::UpdateProjectSelection.call(params.dig(:selected, "value"), project_ids) do + on(:invalid_selection) do + flash.now[:error] = t( + "projects.update_selected.select_a_selection", + scope: "decidim.budgets.admin" + ) + end + + on(:invalid_project_ids) do + flash.now[:alert] = t( + "projects.update_selected.select_a_project", + scope: "decidim.budgets.admin" + ) + end + + on(:update_projects_selection) do + flash.now[:notice] = update_projects_bulk_response_successful(@response, :selected, selection: @selection) + flash.now[:alert] = update_projects_bulk_response_errored(@response, :selected, selection: @selection) + end + end + + respond_to do |format| + format.js { render :update_attribute, locals: { form_selector: "#js-form-change-selected-projects", attribute_selector: "#selected_value" } } + end + end + private def projects @@ -84,6 +172,10 @@ def orders @orders ||= Order.where(budget: budget) end + def project_ids + @project_ids ||= params[:project_ids] + end + def pending_orders orders.pending end @@ -95,6 +187,50 @@ def finished_orders def project @project ||= projects.find(params[:id]) end + + def update_projects_bulk_response_successful(response, subject, extra = {}) + return if response[:successful].blank? + + interpolations = { + subject_name: response[:subject_name], + projects: response[:successful].to_sentence + } + + case subject + when :category + t("projects.update_category.success", scope: "decidim.budgets.admin", **interpolations) + when :scope + t("projects.update_scope.success", scope: "decidim.budgets.admin", **interpolations) + when :selected + if extra[:selection] + t("projects.update_selected.success.selected", scope: "decidim.budgets.admin", **interpolations) + else + t("projects.update_selected.success.unselected", scope: "decidim.budgets.admin", **interpolations) + end + end + end + + def update_projects_bulk_response_errored(response, subject, extra = {}) + return if response[:errored].blank? + + interpolations = { + subject_name: response[:subject_name], + projects: response[:errored].to_sentence + } + + case subject + when :category + t("projects.update_category.invalid", scope: "decidim.budgets.admin", **interpolations) + when :scope + t("projects.update_scope.invalid", scope: "decidim.budgets.admin", **interpolations) + when :selected + if extra[:selection] + t("projects.update_selected.invalid.selected", scope: "decidim.budgets.admin", **interpolations) + else + t("projects.update_selected.invalid.unselected", scope: "decidim.budgets.admin", **interpolations) + end + end + end end end end diff --git a/decidim-budgets/app/controllers/decidim/budgets/projects_controller.rb b/decidim-budgets/app/controllers/decidim/budgets/projects_controller.rb index 7a6ed8283c8f4..6602fc2ec026b 100644 --- a/decidim-budgets/app/controllers/decidim/budgets/projects_controller.rb +++ b/decidim-budgets/app/controllers/decidim/budgets/projects_controller.rb @@ -8,7 +8,7 @@ class ProjectsController < Decidim::Budgets::ApplicationController include NeedsCurrentOrder include Decidim::Budgets::Orderable - helper_method :projects, :project, :budget + helper_method :projects, :project, :budget, :all_geocoded_projects def index raise ActionController::RoutingError, "Not Found" unless budget @@ -28,34 +28,34 @@ def budget def projects return @projects if @projects - @projects = reorder(search.results) + @projects = reorder(search.result) @projects = @projects.page(params[:page]).per(current_component.settings.projects_per_page) end + def all_geocoded_projects + @all_geocoded_projects ||= projects.geocoded + end + def project @project ||= Project.find_by(id: params[:id]) end - def search_klass - ProjectSearch + def search_collection + Project.where(budget: budget).includes([:scope, :component, :attachments, :category]) end def default_filter_params { - search_text: "", - status: default_filter_status_params, - scope_id: default_filter_scope_params, - category_id: default_filter_category_params + search_text_cont: "", + with_any_status: default_filter_status_params, + with_any_scope: default_filter_scope_params, + with_any_category: default_filter_category_params } end def default_filter_status_params voting_finished? ? %w(selected) : %w(all) end - - def context_params - { budget: budget, component: current_component, organization: current_organization } - end end end end diff --git a/decidim-budgets/app/forms/decidim/budgets/admin/budget_form.rb b/decidim-budgets/app/forms/decidim/budgets/admin/budget_form.rb index 16a2892dd7842..57086b4436a91 100644 --- a/decidim-budgets/app/forms/decidim/budgets/admin/budget_form.rb +++ b/decidim-budgets/app/forms/decidim/budgets/admin/budget_form.rb @@ -24,14 +24,14 @@ class BudgetForm < Decidim::Form # # Returns a Decidim::Scope def scope - @scope ||= @decidim_scope_id ? current_component.scopes.find_by(id: @decidim_scope_id) : current_component.scope + @scope ||= @attributes["decidim_scope_id"].value ? current_component.scopes.find_by(id: @attributes["decidim_scope_id"].value) : current_component.scope end # Scope identifier # # Returns the scope identifier related to the meeting def decidim_scope_id - @decidim_scope_id || scope&.id + super || scope&.id end end end diff --git a/decidim-budgets/app/forms/decidim/budgets/admin/order_reminder_form.rb b/decidim-budgets/app/forms/decidim/budgets/admin/order_reminder_form.rb new file mode 100644 index 0000000000000..c4340dd75eaea --- /dev/null +++ b/decidim-budgets/app/forms/decidim/budgets/admin/order_reminder_form.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +module Decidim + module Budgets + module Admin + class OrderReminderForm < Decidim::Form + def reminder_amount + @reminder_amount ||= if !voting_enabled? || voting_ends_soon? + 0 + else + user_ids = [] + unfinished_orders.each do |order| + reminder = Decidim::Reminder.find_by(component: current_component, user: order.user) + if !reminder || (reminder.deliveries.present? && reminder.deliveries.last.created_at < minimum_interval_between_reminders.ago) + user_ids << order.user.id + end + end + user_ids.uniq.count + end + end + + def voting_enabled? + current_component.current_settings.votes == "enabled" + end + + def voting_ends_soon? + return false unless participatory_space.respond_to? :active_step + return false if participatory_space.active_step.blank? + + time_zone = current_organization.time_zone + return false if time_zone.blank? + + end_time = current_component.participatory_space.active_step[:end_date].in_time_zone(time_zone).end_of_day + + 6.hours.from_now >= end_time + end + + def minimum_interval_between_reminders + 24.hours + end + + private + + def minimum_time_before_first_reminder + @minimum_time_before_first_reminder ||= begin + reminder_manifest = Decidim.reminders_registry.for(:orders) + if reminder_manifest.blank? + minimum_interval_between_reminders + else + Array(reminder_manifest.settings.attributes[:reminder_times].default).first + end + end + end + + def participatory_space + @participatory_space ||= current_component.participatory_space + end + + def unfinished_orders + @unfinished_orders ||= Decidim::Budgets::Order.where( + budget: budgets, + checked_out_at: nil, + created_at: Time.zone.at(0)..minimum_time_before_first_reminder.ago + ).select do |order| + order.user.email.present? + end + end + + def budgets + @budgets ||= Decidim::Budgets::Budget.where(component: current_component) + end + end + end + end +end diff --git a/decidim-budgets/app/forms/decidim/budgets/admin/project_form.rb b/decidim-budgets/app/forms/decidim/budgets/admin/project_form.rb index ec140e27261b4..6050865cf7589 100644 --- a/decidim-budgets/app/forms/decidim/budgets/admin/project_form.rb +++ b/decidim-budgets/app/forms/decidim/budgets/admin/project_form.rb @@ -13,6 +13,9 @@ class ProjectForm < Decidim::Form translatable_attribute :title, String translatable_attribute :description, String + attribute :address, String + attribute :latitude, Float + attribute :longitude, Float attribute :budget_amount, Integer attribute :decidim_scope_id, Integer attribute :decidim_category_id, Integer @@ -25,7 +28,7 @@ class ProjectForm < Decidim::Form validates :title, translatable_presence: true validates :description, translatable_presence: true validates :budget_amount, presence: true, numericality: { greater_than: 0 } - + validates :address, geocoding: true, if: ->(form) { form.has_address? && !form.geocoded? } validates :category, presence: true, if: ->(form) { form.decidim_category_id.present? } validates :scope, presence: true, if: ->(form) { form.decidim_scope_id.present? } validates :decidim_scope_id, scope_belongs_to_component: true, if: ->(form) { form.decidim_scope_id.present? } @@ -33,6 +36,7 @@ class ProjectForm < Decidim::Form validate :notify_missing_attachment_if_errored delegate :categories, to: :current_component + alias component current_component def map_model(model) self.proposal_ids = model.linked_resources(:proposals, "included_proposals").pluck(:id) @@ -49,6 +53,18 @@ def proposals &.order(title: :asc) end + def geocoding_enabled? + Decidim::Map.available?(:geocoding) && current_component.settings.geocoding_enabled? + end + + def has_address? + geocoding_enabled? && address.present? + end + + def geocoded? + latitude.present? && longitude.present? + end + # Finds the Budget from the decidim_budgets_budget_id. # # Returns a Decidim::Budgets:Budget @@ -67,14 +83,14 @@ def category # # Returns a Decidim::Scope def scope - @scope ||= @decidim_scope_id ? current_component.scopes.find_by(id: @decidim_scope_id) : current_component.scope + @scope ||= @attributes["decidim_scope_id"].value ? current_component.scopes.find_by(id: @attributes["decidim_scope_id"].value) : current_component.scope end # Scope identifier # # Returns the scope identifier related to the project def decidim_scope_id - @decidim_scope_id || scope&.id + super || scope&.id end private diff --git a/decidim-budgets/app/helpers/decidim/budgets/admin/project_bulk_actions_helper.rb b/decidim-budgets/app/helpers/decidim/budgets/admin/project_bulk_actions_helper.rb new file mode 100644 index 0000000000000..be3a0ab564c35 --- /dev/null +++ b/decidim-budgets/app/helpers/decidim/budgets/admin/project_bulk_actions_helper.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Decidim + module Budgets + module Admin + module ProjectBulkActionsHelper + def bulk_selections + select( + :selected, + :value, + [ + [t("projects.index.select_for_implementation", scope: "decidim.budgets.admin"), true], + [t("projects.index.deselect_implementation", scope: "decidim.budgets.admin"), false] + ] + ) + end + end + end + end +end diff --git a/decidim-budgets/app/helpers/decidim/budgets/projects_helper.rb b/decidim-budgets/app/helpers/decidim/budgets/projects_helper.rb index a41affeff9aa9..b82153d03b8c7 100644 --- a/decidim-budgets/app/helpers/decidim/budgets/projects_helper.rb +++ b/decidim-budgets/app/helpers/decidim/budgets/projects_helper.rb @@ -5,6 +5,8 @@ module Budgets # A helper to render order and budgets actions module ProjectsHelper include ActiveSupport::NumberHelper + include Decidim::ApplicationHelper + include Decidim::MapHelper # Render a budget as a currency # @@ -82,6 +84,32 @@ def current_rule_description t(".vote_threshold_percent_rule.description", minimum_budget: budget_to_currency(current_order.minimum_budget)) end end + + # Serialize a collection of geocoded projects to be used by the dynamic map component + # + # geocoded_projects - A collection of geocoded projects + def projects_data_for_map(geocoded_projects) + geocoded_projects.map do |project| + project_data_for_map(project) + end + end + + def project_data_for_map(project) + project + .slice(:latitude, :longitude, :address) + .merge( + title: decidim_html_escape(translated_attribute(project.title)), + description: html_truncate(decidim_sanitize_editor(translated_attribute(project.description)), length: 100), + icon: icon("project", width: 40, height: 70, remove_icon_class: true), + link: ::Decidim::ResourceLocatorPresenter.new([project.budget, project]).path + ) + end + + def has_position?(project) + return if project.address.blank? + + project.latitude.present? && project.longitude.present? + end end end end diff --git a/decidim-budgets/app/jobs/decidim/budgets/send_vote_reminder_job.rb b/decidim-budgets/app/jobs/decidim/budgets/send_vote_reminder_job.rb new file mode 100644 index 0000000000000..6b33e2f87f180 --- /dev/null +++ b/decidim-budgets/app/jobs/decidim/budgets/send_vote_reminder_job.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Decidim + module Budgets + class SendVoteReminderJob < ApplicationJob + queue_as :vote_reminder + + def perform(reminder) + return if reminder.records.active.blank? + + ::Decidim::ReminderDelivery.create(reminder: reminder) + ::Decidim::Budgets::VoteReminderMailer.vote_reminder(reminder).deliver_now + end + end + end +end diff --git a/decidim-budgets/app/mailers/decidim/budgets/vote_reminder_mailer.rb b/decidim-budgets/app/mailers/decidim/budgets/vote_reminder_mailer.rb new file mode 100644 index 0000000000000..25be9680fb9a8 --- /dev/null +++ b/decidim-budgets/app/mailers/decidim/budgets/vote_reminder_mailer.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module Decidim + module Budgets + class VoteReminderMailer < Decidim::ApplicationMailer + include Decidim::TranslationsHelper + include Decidim::SanitizeHelper + + helper Decidim::TranslationsHelper + + helper_method :routes + + # Send the user an email reminder to finish voting + # + # reminder - the reminder to send. + def vote_reminder(reminder) + @reminder = reminder + @user = reminder.user + with_user(@user) do + @orders = reminder.records.active.map(&:remindable) + @organization = @user.organization + + subject = I18n.t( + "decidim.budgets.vote_reminder_mailer.vote_reminder.email_subject", + count: @orders.count + ) + + mail(to: @user.email, subject: subject) + end + end + + private + + def routes + @routes ||= Decidim::EngineRouter.main_proxy(@reminder.component) + end + end + end +end diff --git a/decidim-budgets/app/models/decidim/budgets/order.rb b/decidim-budgets/app/models/decidim/budgets/order.rb index b7fe7c3601f86..f269bfd01d58b 100644 --- a/decidim-budgets/app/models/decidim/budgets/order.rb +++ b/decidim-budgets/app/models/decidim/budgets/order.rb @@ -5,7 +5,7 @@ module Budgets # The data store for a Order in the Decidim::Budgets component. It is unique for each # user and component and contains a collection of projects class Order < Budgets::ApplicationRecord - include Decidim::DataPortability + include Decidim::DownloadYourData include Decidim::NewsletterParticipant belongs_to :user, class_name: "Decidim::User", foreign_key: "decidim_user_id" @@ -15,7 +15,6 @@ class Order < Budgets::ApplicationRecord has_many :projects, through: :line_items, class_name: "Decidim::Budgets::Project", foreign_key: "decidim_project_id" validates :user, uniqueness: { scope: :budget } - validates :budget, presence: true validate :user_belongs_to_organization # Rules active for the budget threshold and minimum budgets rules. @@ -171,7 +170,7 @@ def self.user_collection(user) end def self.export_serializer - Decidim::Budgets::DataPortabilityBudgetsOrderSerializer + Decidim::Budgets::DownloadYourDataBudgetsOrderSerializer end def self.newsletter_participant_ids(component) diff --git a/decidim-budgets/app/models/decidim/budgets/project.rb b/decidim-budgets/app/models/decidim/budgets/project.rb index 913fbd85a4dce..ea98312c4d6c2 100644 --- a/decidim-budgets/app/models/decidim/budgets/project.rb +++ b/decidim-budgets/app/models/decidim/budgets/project.rb @@ -18,6 +18,7 @@ class Project < Budgets::ApplicationRecord include Decidim::Randomable include Decidim::Searchable include Decidim::TranslatableResource + include Decidim::FilterableResource translatable_fields :title, :description @@ -33,6 +34,10 @@ class Project < Budgets::ApplicationRecord scope :selected, -> { where.not(selected_at: nil) } scope :not_selected, -> { where(selected_at: nil) } + geocoded_by :address + + scope_search_multi :with_any_status, [:selected, :not_selected] + searchable_fields( scope_id: :decidim_scope_id, participatory_space: { component: :participatory_space }, @@ -98,10 +103,9 @@ def attachment_context Arel.sql(%{cast("decidim_budgets_projects"."id" as text)}) end - # Allow ransacker to search for a key in a hstore column (`title`.`en`) - ransacker :title do |parent| - Arel::Nodes::InfixOperation.new("->>", parent.table[:title], Arel::Nodes.build_quoted(I18n.locale.to_s)) - end + # Create i18n ransackers for :title and :description. + # Create the :search_text ransacker alias for searching from both of these. + ransacker_i18n_multi :search_text, [:title, :description] ransacker :selected do Arel.sql(%{("decidim_budgets_projects"."selected_at")::text}) @@ -119,6 +123,10 @@ def attachment_context SQL Arel.sql(query) end + + def self.ransackable_scopes(_auth_object = nil) + [:with_any_status, :with_any_scope, :with_any_category] + end end end end diff --git a/decidim-budgets/app/packs/entrypoints/decidim_budgets_admin.js b/decidim-budgets/app/packs/entrypoints/decidim_budgets_admin.js new file mode 100644 index 0000000000000..a11f4f9a803cd --- /dev/null +++ b/decidim-budgets/app/packs/entrypoints/decidim_budgets_admin.js @@ -0,0 +1 @@ +import "src/decidim/budgets/admin/projects" diff --git a/decidim-budgets/app/packs/src/decidim/budgets/admin/projects.js b/decidim-budgets/app/packs/src/decidim/budgets/admin/projects.js new file mode 100644 index 0000000000000..f76e4dab40a37 --- /dev/null +++ b/decidim-budgets/app/packs/src/decidim/budgets/admin/projects.js @@ -0,0 +1,143 @@ +/* eslint-disable no-invalid-this */ +$(() => { + const selectedResourcesCount = () => { + return $(".table-list .js-check-all-resources:checked").length + } + + const selectedResourcesNotPublishedAnswerCount = () => { + return $(".table-list [data-published-state=false] .js-check-all-resources:checked").length + } + + const selectedResourcesCountUpdate = () => { + const selectedResources = selectedResourcesCount(); + const selectedResourcesNotPublishedAnswer = selectedResourcesNotPublishedAnswerCount(); + + if (selectedResources === 0) { + $("#js-selected-resources-count").text("") + } else { + $("#js-selected-resources-count").text(selectedResources); + } + + if (selectedResources >= 2) { + $('button[data-action="merge-resources"]').parent().show(); + } else { + $('button[data-action="merge-resources"]').parent().hide(); + } + + if (selectedResourcesNotPublishedAnswer > 0) { + $('button[data-action="publish-answers"]').parent().show(); + $("#js-form-publish-answers-number").text(selectedResourcesNotPublishedAnswer); + } else { + $('button[data-action="publish-answers"]').parent().hide(); + } + } + + const showBulkActionsButton = () => { + if (selectedResourcesCount() > 0) { + $("#js-bulk-actions-button").removeClass("hide"); + } + } + + const hideBulkActionsButton = (force = false) => { + if (selectedResourcesCount() === 0 || force === true) { + $("#js-bulk-actions-button").addClass("hide"); + $("#js-bulk-actions-dropdown").removeClass("is-open"); + } + } + + const showOtherActionsButtons = () => { + $("#js-other-actions-wrapper").removeClass("hide"); + } + + const hideOtherActionsButtons = () => { + $("#js-other-actions-wrapper").addClass("hide"); + } + + const hideBulkActionForms = () => { + $(".js-bulk-action-form").addClass("hide"); + } + + if ($("#js-bulk-actions-wrapper").length === 0) { + return; + } + + // Expose functions to make them available in .js.erb templates + window.hideBulkActionForms = hideBulkActionForms; + window.hideBulkActionsButton = hideBulkActionsButton; + window.showOtherActionsButtons = showOtherActionsButtons; + window.selectedResourcesCountUpdate = selectedResourcesCountUpdate; + + + if ($(".js-bulk-action-form").length) { + hideBulkActionForms(); + $("#js-bulk-actions-button").addClass("hide"); + + $("#js-bulk-actions-dropdown ul li button").on("click", (event) => { + event.preventDefault(); + let action = $(event.target).data("action"); + + if (action) { + $(`#js-form-${action}`).on("submit", () => { + $(".layout-content > .callout-wrapper").html(""); + }) + + $(`#js-${action}-actions`).removeClass("hide"); + hideBulkActionsButton(true); + hideOtherActionsButtons(); + } + }) + + // select all checkboxes + $(".js-check-all").on("change", function() { + $(".js-check-all-resources").prop("checked", $(this).prop("checked")); + + if ($(this).prop("checked")) { + $(".js-check-all-resources").closest("tr").addClass("selected"); + showBulkActionsButton(); + } else { + $(".js-check-all-resources").closest("tr").removeClass("selected"); + hideBulkActionsButton(); + } + + selectedResourcesCountUpdate(); + }); + + // resource checkbox change + $(".table-list").on("change", ".js-check-all-resources", function() { + let resourceId = $(this).val() + let checked = $(this).prop("checked") + + // uncheck "select all", if one of the listed checkbox item is unchecked + if ($(this).prop("checked") === false) { + $(".js-check-all").prop("checked", false); + } + // check "select all" if all checkbox resources are checked + if ($(".js-check-all-resources:checked").length === $(".js-check-all-resources").length) { + $(".js-check-all").prop("checked", true); + showBulkActionsButton(); + } + + if ($(this).prop("checked")) { + showBulkActionsButton(); + $(this).closest("tr").addClass("selected"); + } else { + hideBulkActionsButton(); + $(this).closest("tr").removeClass("selected"); + } + + if ($(".js-check-all-resources:checked").length === 0) { + hideBulkActionsButton(); + } + + $(".js-bulk-action-form").find(`.js-resource-id-${resourceId}`).prop("checked", checked); + selectedResourcesCountUpdate(); + }); + + $(".js-cancel-bulk-action").on("click", () => { + hideBulkActionForms() + showBulkActionsButton(); + showOtherActionsButtons(); + }); + } +}); +/* eslint-enable no-invalid-this */ diff --git a/decidim-budgets/app/permissions/decidim/budgets/admin/permissions.rb b/decidim-budgets/app/permissions/decidim/budgets/admin/permissions.rb index 9b1b3423ae6d9..22a92920d9e8c 100644 --- a/decidim-budgets/app/permissions/decidim/budgets/admin/permissions.rb +++ b/decidim-budgets/app/permissions/decidim/budgets/admin/permissions.rb @@ -19,13 +19,18 @@ def permissions end when :project, :projects case permission_action.action - when :create - permission_action.allow! - when :import_proposals + when :create, :import_proposals, :project_category permission_action.allow! when :update, :destroy permission_action.allow! if project.present? end + when :order + case permission_action.action + when :remind + permission_action.allow! + end + when :project_category, :project_scope, :project_selected + permission_action.allow! end permission_action diff --git a/decidim-budgets/app/queries/decidim/budgets/filtered_projects.rb b/decidim-budgets/app/queries/decidim/budgets/filtered_projects.rb index 9caac3178758a..e5b3739fa9e07 100644 --- a/decidim-budgets/app/queries/decidim/budgets/filtered_projects.rb +++ b/decidim-budgets/app/queries/decidim/budgets/filtered_projects.rb @@ -3,7 +3,7 @@ module Decidim module Budgets # A class used to find projects filtered by components and a date range - class FilteredProjects < Rectify::Query + class FilteredProjects < Decidim::Query # Syntactic sugar to initialize the class and return the queried objects. # # components - An array of Decidim::Component diff --git a/decidim-budgets/app/serializers/decidim/budgets/data_portability_budgets_order_serializer.rb b/decidim-budgets/app/serializers/decidim/budgets/download_your_data_budgets_order_serializer.rb similarity index 88% rename from decidim-budgets/app/serializers/decidim/budgets/data_portability_budgets_order_serializer.rb rename to decidim-budgets/app/serializers/decidim/budgets/download_your_data_budgets_order_serializer.rb index b6c452c01e6ba..49e5e44b6f4e1 100644 --- a/decidim-budgets/app/serializers/decidim/budgets/data_portability_budgets_order_serializer.rb +++ b/decidim-budgets/app/serializers/decidim/budgets/download_your_data_budgets_order_serializer.rb @@ -2,13 +2,13 @@ module Decidim module Budgets - class DataPortabilityBudgetsOrderSerializer < Decidim::Exporters::Serializer + class DownloadYourDataBudgetsOrderSerializer < Decidim::Exporters::Serializer # Public: Initializes the serializer with a conversation. def initialize(order) @order = order end - # Serializes a Debate for data portability + # Serializes a Debate for download your data def serialize { id: order.id, diff --git a/decidim-budgets/app/services/decidim/budgets/order_reminder_generator.rb b/decidim-budgets/app/services/decidim/budgets/order_reminder_generator.rb new file mode 100644 index 0000000000000..96deeec39175d --- /dev/null +++ b/decidim-budgets/app/services/decidim/budgets/order_reminder_generator.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +module Decidim + module Budgets + # This class is the generator class which creates and updates order related reminders, + # after reminder is generated it is send to user who have not checked out his/her/their vote. + class OrderReminderGenerator + attr_reader :reminder_jobs_queued + + def initialize + @reminder_manifest = Decidim.reminders_registry.for(:orders) + @reminder_jobs_queued = 0 + end + + # Creates reminders and updates them if they already exists. + def generate + Decidim::Component.where(manifest_name: "budgets").each do |component| + next if component.current_settings.votes != "enabled" + + send_reminders(component) + end + end + + def generate_for(component, &block) + @alternative_refresh_state = block + send_reminders(component) + end + + private + + attr_reader :reminder_manifest + + def send_reminders(component) + budgets = Decidim::Budgets::Budget.where(component: component) + pending_orders = Decidim::Budgets::Order.where(budget: budgets, checked_out_at: nil) + users = Decidim::User.where(id: pending_orders.pluck(:decidim_user_id).uniq) + users.each do |user| + reminder = Decidim::Reminder.find_or_create_by(user: user, component: component) + users_pending_orders = pending_orders.where(user: user) + update_reminder_records(reminder, users_pending_orders) + if reminder.records.active.any? + Decidim::Budgets::SendVoteReminderJob.perform_later(reminder) + @reminder_jobs_queued += 1 + end + end + end + + def update_reminder_records(reminder, users_pending_orders) + clean_checked_out_and_deleted_orders(reminder) + add_pending_orders(reminder, users_pending_orders) + end + + def clean_checked_out_and_deleted_orders(reminder) + reminder.records.each do |record| + if record.remindable.nil? + record.update(state: "deleted") + elsif record.remindable.checked_out_at.present? + record.update(state: "completed") + end + end + end + + def add_pending_orders(reminder, users_pending_orders) + reminder.records << users_pending_orders.map { |order| Decidim::ReminderRecord.find_or_create_by(reminder: reminder, remindable: order) } + return @alternative_refresh_state.call(reminder) if @alternative_refresh_state.present? + + reminder.records.each do |record| + refresh_state(record, reminder.deliveries.length) if %w(active pending).include? record.state + end + end + + def refresh_state(record, delivered_count) + intervals = Array(reminder_manifest.settings.attributes[:reminder_times].default) + return record.update(state: "pending") if delivered_count >= intervals.length + + record.state = intervals[delivered_count].ago > record.remindable.created_at ? "active" : "pending" + record.save if record.changed? + end + + def voting_enabled?(component) + component.current_settings.votes == "enabled" + end + end + end +end diff --git a/decidim-budgets/app/services/decidim/budgets/project_search.rb b/decidim-budgets/app/services/decidim/budgets/project_search.rb deleted file mode 100644 index 3c1d68ec40e12..0000000000000 --- a/decidim-budgets/app/services/decidim/budgets/project_search.rb +++ /dev/null @@ -1,45 +0,0 @@ -# frozen_string_literal: true - -module Decidim - module Budgets - # This class handles search and filtering of projects. Needs a - # `current_component` param with a `Decidim::Component` in order to - # find the projects. - class ProjectSearch < ResourceSearch - text_search_fields :title, :description - - # Public: Initializes the service. - # component - A Decidim::Component to get the projects from. - def initialize(options = {}) - super(Project.all, options) - end - - # Creates the SearchLight base query. - def base_query - raise "Missing budget" unless budget - raise "Missing component" unless component - - @scope.where(budget: budget) - end - - # Returns the random projects for the current page. - def results - Project.where(id: super.pluck(:id)).includes([:scope, :component, :attachments, :category]) - end - - def search_status - return query if status.member?("all") - - apply_scopes(%w(selected not_selected), status) - end - - private - - # Private: Since budget is not used by a search method we need - # to define the method manually. - def budget - options[:budget] - end - end - end -end diff --git a/decidim-budgets/app/views/decidim/budgets/admin/budgets/index.html.erb b/decidim-budgets/app/views/decidim/budgets/admin/budgets/index.html.erb index 3ea474a6a75ef..e251c51136834 100644 --- a/decidim-budgets/app/views/decidim/budgets/admin/budgets/index.html.erb +++ b/decidim-budgets/app/views/decidim/budgets/admin/budgets/index.html.erb @@ -5,6 +5,9 @@ <%= t(".title") %>
+ <% if allowed_to? :remind, :order %> + <%= link_to t("actions.send_voting_reminders", scope: "decidim.budgets"), admin_reminders_path(current_component, name: "orders"), class: "button tiny button--title" %> + <% end %> <% if allowed_to? :export, :budget %> <%= export_dropdown %> <% end %> diff --git a/decidim-budgets/app/views/decidim/budgets/admin/projects/_bulk-actions.html.erb b/decidim-budgets/app/views/decidim/budgets/admin/projects/_bulk-actions.html.erb new file mode 100644 index 0000000000000..65f325038d0fa --- /dev/null +++ b/decidim-budgets/app/views/decidim/budgets/admin/projects/_bulk-actions.html.erb @@ -0,0 +1,13 @@ +
+ <%= render partial: "decidim/budgets/admin/projects/bulk_actions/dropdown" %> + + <%= render partial: "decidim/budgets/admin/projects/bulk_actions/recategorize" %> + <%= render partial: "decidim/budgets/admin/projects/bulk_actions/scope-change" %> + <%= render partial: "decidim/budgets/admin/projects/bulk_actions/change-selected" %> + + <%= link_to t("actions.import", scope: "decidim.budgets", name: t("models.project.name", scope: "decidim.budgets.admin")), new_budget_proposals_import_path(budget), class: "button tiny button--title" if allowed_to? :import_proposals, :project %> + <% if allowed_to? :export, :budget %> + <%= export_dropdown(current_component, budget.id) %> + <% end %> + <%= link_to t("actions.new", scope: "decidim.budgets", name: t("models.project.name", scope: "decidim.budgets.admin")), new_budget_project_path, class: "button tiny button--title new" if allowed_to? :create, :project %> +
diff --git a/decidim-budgets/app/views/decidim/budgets/admin/projects/_form.html.erb b/decidim-budgets/app/views/decidim/budgets/admin/projects/_form.html.erb index aca30797b3d89..868f9dff443ea 100644 --- a/decidim-budgets/app/views/decidim/budgets/admin/projects/_form.html.erb +++ b/decidim-budgets/app/views/decidim/budgets/admin/projects/_form.html.erb @@ -18,6 +18,12 @@ <%= form.number_field :budget_amount %>
+ <% if @form.geocoding_enabled? %> +
+ <%= form.geocoding_field :address %> +
+ <% end %> + <% if current_component.has_subscopes? %>
<%= scopes_picker_field form, :decidim_scope_id, root: budget.scope %> diff --git a/decidim-budgets/app/views/decidim/budgets/admin/projects/_project-tr.html.erb b/decidim-budgets/app/views/decidim/budgets/admin/projects/_project-tr.html.erb new file mode 100644 index 0000000000000..4001430507570 --- /dev/null +++ b/decidim-budgets/app/views/decidim/budgets/admin/projects/_project-tr.html.erb @@ -0,0 +1,50 @@ + + + <%= check_box_tag "project_ids_s[]", project.id, false, class: "js-check-all-resources js-project-list-check js-resource-id-#{project.id}" %>
+ + + <%= project.id %>
+ + + <%= translated_attribute(project.title) %>
+ + + <% if project.category %> + <%= translated_attribute project.category.name %> + <% end %> + + <%= td_resource_scope_for(project.scope) %> + + <%= project.confirmed_orders_count %> + + + <% if project.selected? %> + <%= content_tag :strong, t("projects.index.selected", scope: "decidim.budgets.admin"), class: "text-success" %> + <% else %> + <%= content_tag :span, "x", class: "text-muted" %> + <% end %> + + + <%= icon_link_to "eye", resource_locator([budget, project]).path, t("actions.preview", scope: "decidim.budgets"), target: :blank, class: "action-icon--preview" %> + + <% if allowed_to? :update, :project, project: project %> + <%= icon_link_to "pencil", resource_locator([budget, project]).edit, t("actions.edit", scope: "decidim.budgets"), class: "action-icon--edit" %> + <% end %> + + <% if allowed_to? :update, :project, project: project %> + <%= icon_link_to "folder", project_attachment_collections_path(project), t("actions.attachment_collections", scope: "decidim.budgets"), class: "action-icon--attachment_collections" %> + <% end %> + + <% if allowed_to? :update, :project, project: project %> + <%= icon_link_to "paperclip", project_attachments_path(project), t("actions.attachments", scope: "decidim.budgets"), class: "action-icon--attachments" %> + <% end %> + + <%= resource_permissions_link(project) %> + + <% if allowed_to? :destroy, :project, project: project %> + <%= icon_link_to "circle-x", resource_locator([budget, project]).show, t("actions.destroy", scope: "decidim.budgets"), method: :delete, class: "action-icon--remove", data: { confirm: t("actions.confirm_destroy", scope: "decidim.budgets") } %> + <% else %> + <%= icon "circle-x", class: "action-icon action-icon--disabled", role: "img", aria_label: t("actions.destroy", scope: "decidim.budgets") %> + <% end %> + + diff --git a/decidim-budgets/app/views/decidim/budgets/admin/projects/bulk_actions/_change-selected.html.erb b/decidim-budgets/app/views/decidim/budgets/admin/projects/bulk_actions/_change-selected.html.erb new file mode 100644 index 0000000000000..805a498aa9a23 --- /dev/null +++ b/decidim-budgets/app/views/decidim/budgets/admin/projects/bulk_actions/_change-selected.html.erb @@ -0,0 +1,15 @@ +
+ <%= form_tag(update_selected_budget_projects_path, method: :post, remote: true, id: "js-form-change-selected-projects", class: "flex--cc flex-gap--1") do %> +
+ <% projects.each do |project| %> + <%= check_box_tag "project_ids[]", project.id, false, class: "js-check-all-resources js-resource-id-#{project.id}" %> + <% end %> +
+ + <%= bulk_selections %> + + <%= submit_tag(t("decidim.budgets.admin.projects.index.update"), id: "js-submit-edit-selected", class: "button small button--simple float-left") %> + + + <% end %> +
diff --git a/decidim-budgets/app/views/decidim/budgets/admin/projects/bulk_actions/_dropdown.html.erb b/decidim-budgets/app/views/decidim/budgets/admin/projects/bulk_actions/_dropdown.html.erb new file mode 100644 index 0000000000000..788458e269575 --- /dev/null +++ b/decidim-budgets/app/views/decidim/budgets/admin/projects/bulk_actions/_dropdown.html.erb @@ -0,0 +1,36 @@ +
+ + + +
diff --git a/decidim-budgets/app/views/decidim/budgets/admin/projects/bulk_actions/_recategorize.html.erb b/decidim-budgets/app/views/decidim/budgets/admin/projects/bulk_actions/_recategorize.html.erb new file mode 100644 index 0000000000000..f6397fdf82871 --- /dev/null +++ b/decidim-budgets/app/views/decidim/budgets/admin/projects/bulk_actions/_recategorize.html.erb @@ -0,0 +1,15 @@ +
+ <%= form_tag(update_category_budget_projects_path, method: :post, remote: true, id: "js-form-recategorize-projects", class: "flex--cc flex-gap--1") do %> +
+ <% projects.each do |project| %> + <%= check_box_tag "project_ids[]", project.id, false, class: "js-check-all-resources js-resource-id-#{project.id}" %> + <% end %> +
+ + <%= bulk_categories_select current_component.categories %> + + <%= submit_tag(t("decidim.budgets.admin.projects.index.update"), id: "js-submit-edit-category", class: "button small button--simple float-left") %> + + + <% end %> +
diff --git a/decidim-budgets/app/views/decidim/budgets/admin/projects/bulk_actions/_scope-change.html.erb b/decidim-budgets/app/views/decidim/budgets/admin/projects/bulk_actions/_scope-change.html.erb new file mode 100644 index 0000000000000..44efc6a795831 --- /dev/null +++ b/decidim-budgets/app/views/decidim/budgets/admin/projects/bulk_actions/_scope-change.html.erb @@ -0,0 +1,25 @@ +
+ <%= form_tag(update_scope_budget_projects_path, method: :post, remote: true, id: "js-form-scope-change-projects", class: "flex--cc flex-gap--1") do %> +
+ <% projects.each do |project| %> + <%= check_box_tag "project_ids[]", project.id, false, class: "js-check-all-resources js-resource-id-#{project.id}" %> + <% end %> +
+ + <%= scopes_picker_tag( + :scope_id, + try(:current_participatory_space)&.scope, + field: t("models.project.fields.scope", scope: "decidim.budgets") + ) %> + + <%= submit_tag( + t("decidim.budgets.admin.projects.index.update_scope_button"), + id: "js-submit-scope-change-projects", + class: "button small button--simple float-left" + ) %> + + + <% end %> +
diff --git a/decidim-budgets/app/views/decidim/budgets/admin/projects/index.html.erb b/decidim-budgets/app/views/decidim/budgets/admin/projects/index.html.erb index 10015c8207324..8acb05032aa12 100644 --- a/decidim-budgets/app/views/decidim/budgets/admin/projects/index.html.erb +++ b/decidim-budgets/app/views/decidim/budgets/admin/projects/index.html.erb @@ -4,14 +4,9 @@
<%= link_to translated_attribute(budget.title), budgets_path %> > <%= t(".title") %> + ">
-
- <%= link_to t("actions.import", scope: "decidim.budgets", name: t("models.project.name", scope: "decidim.budgets.admin")), new_budget_proposals_import_path(budget), class: "button tiny button--title" if allowed_to? :import_proposals, :project %> - <% if allowed_to? :export, :budget %> - <%= export_dropdown(current_component, budget.id) %> - <% end %> - <%= link_to t("actions.new", scope: "decidim.budgets", name: t("models.project.name", scope: "decidim.budgets.admin")), new_budget_project_path, class: "button tiny button--title new" if allowed_to? :create, :project %> -
+ <%= render partial: "bulk-actions" %>
@@ -21,6 +16,7 @@ + @@ -32,53 +28,7 @@ <% projects.each do |project| %> - - - - - <%= td_resource_scope_for(project.scope) %> - - - - + <%= render partial: "project-tr", locals: { project: project } %> <% end %>
<%= check_box_tag "projects_bulk", "all", false, class: "js-check-all" %> <%= sort_link(query, :id, t("models.project.fields.id", scope: "decidim.budgets"), default_order: :desc) %> <%= sort_link(query, :title, t("models.project.fields.title", scope: "decidim.budgets")) %> <%= sort_link(query, :category_name, t("models.project.fields.category", scope: "decidim.budgets") ) %>
- <%= project.id %>
-
- <%= translated_attribute(project.title) %>
-
- <% if project.category %> - <%= translated_attribute project.category.name %> - <% end %> - - <%= project.confirmed_orders_count %> - - <% if project.selected? %> - <%= content_tag :strong, t(".selected"), class: "text-success" %> - <% else %> - <%= content_tag :span, "×", class: "text-muted" %> - <% end %> - - <%= icon_link_to "eye", resource_locator([budget, project]).path, t("actions.preview", scope: "decidim.budgets"), target: :blank, class: "action-icon--preview" %> - - <% if allowed_to? :update, :project, project: project %> - <%= icon_link_to "pencil", resource_locator([budget, project]).edit, t("actions.edit", scope: "decidim.budgets"), class: "action-icon--edit" %> - <% end %> - - <% if allowed_to? :update, :project, project: project %> - <%= icon_link_to "folder", project_attachment_collections_path(project), t("actions.attachment_collections", scope: "decidim.budgets"), class: "action-icon--attachment_collections" %> - <% end %> - - <% if allowed_to? :update, :project, project: project %> - <%= icon_link_to "paperclip", project_attachments_path(project), t("actions.attachments", scope: "decidim.budgets"), class: "action-icon--attachments" %> - <% end %> - - <%= resource_permissions_link(project) %> - - <% if allowed_to? :destroy, :project, project: project %> - <%= icon_link_to "circle-x", resource_locator([budget, project]).show, t("actions.destroy", scope: "decidim.budgets"), method: :delete, class: "action-icon--remove", data: { confirm: t("actions.confirm_destroy", scope: "decidim.budgets") } %> - <% else %> - <%= icon "circle-x", class: "action-icon action-icon--disabled", role: "img", aria_label: t("actions.destroy", scope: "decidim.budgets") %> - <% end %> -
@@ -91,3 +41,5 @@ <%= t ".pending_orders" %>: <%= pending_orders.count %>
+ +<%= javascript_pack_tag "decidim_budgets_admin" %> diff --git a/decidim-budgets/app/views/decidim/budgets/admin/projects/update_attribute.js.erb b/decidim-budgets/app/views/decidim/budgets/admin/projects/update_attribute.js.erb new file mode 100644 index 0000000000000..66a833877961a --- /dev/null +++ b/decidim-budgets/app/views/decidim/budgets/admin/projects/update_attribute.js.erb @@ -0,0 +1,26 @@ +<% if flash.now[:error].present? %> + $("<%= form_selector %> <%= attribute_selector %>").addClass("is-invalid-input") + $("<%= escape_javascript(render partial: %q{decidim/admin/shared/js-callout}, locals: { css: %q{alert}, text: flash.now[:error] }) %>").appendTo(".callout-wrapper"); +<% end %> + +<% if flash.now[:alert].present? %> + $("<%= form_selector %> <%= attribute_selector %>").removeClass("is-invalid-input") + $("<%= escape_javascript(render partial: %q{decidim/admin/shared/js-callout}, locals: { css: %q{warning}, text: flash.now[:alert] }) %>").appendTo(".callout-wrapper"); +<% end %> + +<% if flash.now[:notice].present? %> + $("<%= escape_javascript(render partial: %q{decidim/admin/shared/js-callout}, locals: { css: %q{success}, text: flash.now[:notice] }) %>").appendTo(".callout-wrapper"); + + <% project_ids.each do |id| %> + $(".table-list [data-id='<%= id %>']") + .replaceWith("<%= escape_javascript(render partial: %q{project-tr}, locals: { project: Decidim::Budgets::Project.find(id) }) %>"); + <% end %> + + $("<%= form_selector %> <%= attribute_selector %>").removeClass("is-invalid-input") + $(".js-check-all").prop('checked', false); + $(".js-check-all-resources").prop('checked', false); + window.hideBulkActionsButton(); + window.hideBulkActionForms(); + window.showOtherActionsButtons(); + window.selectedResourcesCountUpdate(); +<% end %> diff --git a/decidim-budgets/app/views/decidim/budgets/projects/_filters.html.erb b/decidim-budgets/app/views/decidim/budgets/projects/_filters.html.erb index bc6dea175d27c..b2c3fe1ac9973 100644 --- a/decidim-budgets/app/views/decidim/budgets/projects/_filters.html.erb +++ b/decidim-budgets/app/views/decidim/budgets/projects/_filters.html.erb @@ -4,7 +4,7 @@