diff --git a/.decidim-version b/.decidim-version index 69bf493e50986..e9e87efa685c7 100644 --- a/.decidim-version +++ b/.decidim-version @@ -1 +1 @@ -0.27.5 +0.27.6 \ No newline at end of file diff --git a/.github/actions/module-rspec/action.yml b/.github/actions/module-rspec/action.yml index 47e007bbd92d5..a752fcf51785e 100644 --- a/.github/actions/module-rspec/action.yml +++ b/.github/actions/module-rspec/action.yml @@ -15,10 +15,6 @@ inputs: 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" @@ -75,5 +71,3 @@ runs: name: Parallel tests shell: "bash" working-directory: ./spec/decidim_dummy_app/ - env: - PARALLEL_TEST_PROCESSORS: " ${{ inputs.processor_count }}" diff --git a/.github/workflows/ci_accountability.yml b/.github/workflows/ci_accountability.yml index 485735e59e295..997a1d857bd9f 100644 --- a/.github/workflows/ci_accountability.yml +++ b/.github/workflows/ci_accountability.yml @@ -26,7 +26,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-accountability - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -63,7 +62,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_admin.yml b/.github/workflows/ci_admin.yml index 187f68ec2ac02..429828d8bb8bf 100644 --- a/.github/workflows/ci_admin.yml +++ b/.github/workflows/ci_admin.yml @@ -21,7 +21,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-admin - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -54,7 +53,6 @@ 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 rake parallel:spec['spec\/(?!system)'] diff --git a/.github/workflows/ci_admin_system.yml b/.github/workflows/ci_admin_system.yml index 4efe6c7669108..4a379e7f74a6d 100644 --- a/.github/workflows/ci_admin_system.yml +++ b/.github/workflows/ci_admin_system.yml @@ -21,7 +21,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-admin - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -58,7 +57,6 @@ 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 rake parallel:spec[^spec/system] diff --git a/.github/workflows/ci_api.yml b/.github/workflows/ci_api.yml index 9f3b2b237beb0..df0835444c2bc 100644 --- a/.github/workflows/ci_api.yml +++ b/.github/workflows/ci_api.yml @@ -22,7 +22,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-api - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -55,7 +54,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_assemblies.yml b/.github/workflows/ci_assemblies.yml index 86ea20c782342..792006f7ffb5c 100644 --- a/.github/workflows/ci_assemblies.yml +++ b/.github/workflows/ci_assemblies.yml @@ -21,7 +21,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-assemblies - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -58,7 +57,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_blogs.yml b/.github/workflows/ci_blogs.yml index 1a8e534fc7d30..81a553da91fa2 100644 --- a/.github/workflows/ci_blogs.yml +++ b/.github/workflows/ci_blogs.yml @@ -24,7 +24,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-blogs - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -61,7 +60,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_budgets.yml b/.github/workflows/ci_budgets.yml index db3d55fd9b3bc..a60cc8dd5d84c 100644 --- a/.github/workflows/ci_budgets.yml +++ b/.github/workflows/ci_budgets.yml @@ -23,7 +23,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-budgets - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -60,7 +59,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_comments.yml b/.github/workflows/ci_comments.yml index 3e06894911dd8..ccc8b3dcda52b 100644 --- a/.github/workflows/ci_comments.yml +++ b/.github/workflows/ci_comments.yml @@ -21,7 +21,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-comments - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -58,7 +57,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_conferences.yml b/.github/workflows/ci_conferences.yml index bb226fafeff63..f6fa5a572af2c 100644 --- a/.github/workflows/ci_conferences.yml +++ b/.github/workflows/ci_conferences.yml @@ -22,7 +22,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-conferences - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -59,7 +58,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_consultations.yml b/.github/workflows/ci_consultations.yml index e7e612814ab2f..de73259760a1b 100644 --- a/.github/workflows/ci_consultations.yml +++ b/.github/workflows/ci_consultations.yml @@ -22,7 +22,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-consultations - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -59,7 +58,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_core_lib.yml b/.github/workflows/ci_core_lib.yml index ba801b5efc638..e66f38e37454d 100644 --- a/.github/workflows/ci_core_lib.yml +++ b/.github/workflows/ci_core_lib.yml @@ -21,7 +21,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-core - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -54,7 +53,6 @@ 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 rake parallel:spec[^spec/lib] diff --git a/.github/workflows/ci_core_system.yml b/.github/workflows/ci_core_system.yml index b196977e14a02..bcbd71b932c93 100644 --- a/.github/workflows/ci_core_system.yml +++ b/.github/workflows/ci_core_system.yml @@ -20,7 +20,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-core - PARALLEL_TEST_PROCESSORS: 2 DECIDIM_SERVICE_WORKER_ENABLED: true CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 @@ -58,7 +57,6 @@ 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: | diff --git a/.github/workflows/ci_core_system_ssl.yml b/.github/workflows/ci_core_system_ssl.yml index c76e6e5d46e08..bccb21fa40350 100644 --- a/.github/workflows/ci_core_system_ssl.yml +++ b/.github/workflows/ci_core_system_ssl.yml @@ -19,7 +19,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-core - PARALLEL_TEST_PROCESSORS: 2 DECIDIM_SERVICE_WORKER_ENABLED: true TEST_SSL: true CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 @@ -58,7 +57,6 @@ 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: | diff --git a/.github/workflows/ci_core_tasks.yml b/.github/workflows/ci_core_tasks.yml new file mode 100644 index 0000000000000..128c3ea447121 --- /dev/null +++ b/.github/workflows/ci_core_tasks.yml @@ -0,0 +1,73 @@ +name: "[CI] Core (tasks tests)" +on: + push: + branches: + - develop + - release/* + - "*-stable" + pull_request: + branches-ignore: + - "chore/l10n*" + paths: + - "*" + - ".github/**" + - "decidim-api/**" + - "decidim-core/**" + - "decidim-dev/**" + +env: + CI: "true" + RUBY_VERSION: 3.0.2 + NODE_VERSION: 16.9.1 + DECIDIM_MODULE: decidim-core + CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 + +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: actions/checkout@v2.0.0 + with: + fetch-depth: 1 + - uses: ./.github/actions/module-rspec + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + name: ${{ env.DECIDIM_MODULE }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec['spec/tasks\/(?!decidim_webpacker_tasks.rake)'] + name: RSpec + working-directory: ${{ env.DECIDIM_MODULE }} + env: + SIMPLECOV: "true" + - uses: codecov/codecov-action@v3 + name: Upload coverage + with: + token: ${{ env.CODECOV_TOKEN }} + name: ${{ env.DECIDIM_MODULE }} + flags: ${{ env.DECIDIM_MODULE }} + - 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_core_tasks_webpacker.yml b/.github/workflows/ci_core_tasks_webpacker.yml new file mode 100644 index 0000000000000..cbc749df83438 --- /dev/null +++ b/.github/workflows/ci_core_tasks_webpacker.yml @@ -0,0 +1,73 @@ +name: "[CI] Core (webpacker tasks tests)" +on: + push: + branches: + - develop + - release/* + - "*-stable" + pull_request: + branches-ignore: + - "chore/l10n*" + paths: + - "*" + - ".github/**" + - "decidim-api/**" + - "decidim-core/**" + - "decidim-dev/**" + +env: + CI: "true" + RUBY_VERSION: 3.0.2 + NODE_VERSION: 16.9.1 + DECIDIM_MODULE: decidim-core + CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 + +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: actions/checkout@v2.0.0 + with: + fetch-depth: 1 + - uses: ./.github/actions/module-rspec + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + name: ${{ env.DECIDIM_MODULE }} + ruby_version: ${{ env.RUBY_VERSION }} + node_version: ${{ env.NODE_VERSION }} + - run: bundle exec rake parallel:spec['spec/tasks/decidim_webpacker_tasks.rake'] + name: RSpec + working-directory: ${{ env.DECIDIM_MODULE }} + env: + SIMPLECOV: "true" + - uses: codecov/codecov-action@v3 + name: Upload coverage + with: + token: ${{ env.CODECOV_TOKEN }} + name: ${{ env.DECIDIM_MODULE }} + flags: ${{ env.DECIDIM_MODULE }} + - 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_core_unit.yml b/.github/workflows/ci_core_unit.yml index 6de3373aea1f1..3cfbc72412fa0 100644 --- a/.github/workflows/ci_core_unit.yml +++ b/.github/workflows/ci_core_unit.yml @@ -20,7 +20,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-core - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -53,10 +52,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 rake parallel:spec['spec\/(?!(system|lib))'] + - run: bundle exec rake parallel:spec['spec\/(?!(system|lib|tasks))'] name: RSpec working-directory: ${{ env.DECIDIM_MODULE }} env: diff --git a/.github/workflows/ci_debates.yml b/.github/workflows/ci_debates.yml index 576796dcb84ed..dc28121afe71a 100644 --- a/.github/workflows/ci_debates.yml +++ b/.github/workflows/ci_debates.yml @@ -22,7 +22,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-debates - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -59,7 +58,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_dev_system.yml b/.github/workflows/ci_dev_system.yml index 65b453e39507c..bb915e7d47bc9 100644 --- a/.github/workflows/ci_dev_system.yml +++ b/.github/workflows/ci_dev_system.yml @@ -19,7 +19,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-dev - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -52,7 +51,6 @@ 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 diff --git a/.github/workflows/ci_forms.yml b/.github/workflows/ci_forms.yml index 6d4e971e5c3ab..47fede18288ab 100644 --- a/.github/workflows/ci_forms.yml +++ b/.github/workflows/ci_forms.yml @@ -21,7 +21,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-forms - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -54,7 +53,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_generators.yml b/.github/workflows/ci_generators.yml index 785c9d091b6b7..e65e0d687a707 100644 --- a/.github/workflows/ci_generators.yml +++ b/.github/workflows/ci_generators.yml @@ -19,7 +19,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-generators - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: diff --git a/.github/workflows/ci_initiatives.yml b/.github/workflows/ci_initiatives.yml index 7a0b52011a892..c346fb6e2cafb 100644 --- a/.github/workflows/ci_initiatives.yml +++ b/.github/workflows/ci_initiatives.yml @@ -23,7 +23,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-initiatives - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -56,7 +55,6 @@ 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 rake parallel:spec['spec\/(?!system)'] diff --git a/.github/workflows/ci_initiatives_system_admin.yml b/.github/workflows/ci_initiatives_system_admin.yml index fe14a8ac506a3..d52c288c838e5 100644 --- a/.github/workflows/ci_initiatives_system_admin.yml +++ b/.github/workflows/ci_initiatives_system_admin.yml @@ -23,7 +23,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-initiatives - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -60,7 +59,6 @@ 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 rake parallel:spec[^spec/system/admin] diff --git a/.github/workflows/ci_initiatives_system_public.yml b/.github/workflows/ci_initiatives_system_public.yml index 3b4f024d4b236..464215d9dc544 100644 --- a/.github/workflows/ci_initiatives_system_public.yml +++ b/.github/workflows/ci_initiatives_system_public.yml @@ -23,7 +23,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-initiatives - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -60,7 +59,6 @@ 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 rake parallel:spec['spec\/system\/(?!admin)'] diff --git a/.github/workflows/ci_meetings_system_admin.yml b/.github/workflows/ci_meetings_system_admin.yml index 83f7617a55e92..1589ddf1735a5 100644 --- a/.github/workflows/ci_meetings_system_admin.yml +++ b/.github/workflows/ci_meetings_system_admin.yml @@ -24,7 +24,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-meetings - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -61,7 +60,6 @@ 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 rake parallel:spec[^spec/system/admin] diff --git a/.github/workflows/ci_meetings_system_public.yml b/.github/workflows/ci_meetings_system_public.yml index 67bd4ef52cb60..c92d5ea3dc58d 100644 --- a/.github/workflows/ci_meetings_system_public.yml +++ b/.github/workflows/ci_meetings_system_public.yml @@ -24,7 +24,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-meetings - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -61,7 +60,6 @@ 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 rake parallel:spec['spec\/system\/(?!admin)'] diff --git a/.github/workflows/ci_meetings_unit_tests.yml b/.github/workflows/ci_meetings_unit_tests.yml index b68182bbc30ca..972d14aad0e9b 100644 --- a/.github/workflows/ci_meetings_unit_tests.yml +++ b/.github/workflows/ci_meetings_unit_tests.yml @@ -24,7 +24,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-meetings - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -57,7 +56,6 @@ 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 rake parallel:spec['spec\/(?!system)'] diff --git a/.github/workflows/ci_pages.yml b/.github/workflows/ci_pages.yml index fdfef297ab359..62cef43f99461 100644 --- a/.github/workflows/ci_pages.yml +++ b/.github/workflows/ci_pages.yml @@ -21,7 +21,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-pages - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -58,7 +57,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_participatory_processes.yml b/.github/workflows/ci_participatory_processes.yml index d3c294c038fb2..84c038e5a80da 100644 --- a/.github/workflows/ci_participatory_processes.yml +++ b/.github/workflows/ci_participatory_processes.yml @@ -22,7 +22,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-participatory_processes - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -59,7 +58,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_proposals_system_admin.yml b/.github/workflows/ci_proposals_system_admin.yml index bc5e366f952e0..c2808c9810f5d 100644 --- a/.github/workflows/ci_proposals_system_admin.yml +++ b/.github/workflows/ci_proposals_system_admin.yml @@ -26,7 +26,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-proposals - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -63,7 +62,6 @@ 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 rake parallel:spec[^spec/system/admin] diff --git a/.github/workflows/ci_proposals_system_public.yml b/.github/workflows/ci_proposals_system_public.yml index 6f1838b6dd9eb..e80e67c9c369f 100644 --- a/.github/workflows/ci_proposals_system_public.yml +++ b/.github/workflows/ci_proposals_system_public.yml @@ -26,7 +26,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-proposals - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -63,7 +62,6 @@ 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 rake parallel:spec['spec\/system\/(?!admin)'] diff --git a/.github/workflows/ci_proposals_unit_tests.yml b/.github/workflows/ci_proposals_unit_tests.yml index d5c7bea2b114a..9a641efca0a87 100644 --- a/.github/workflows/ci_proposals_unit_tests.yml +++ b/.github/workflows/ci_proposals_unit_tests.yml @@ -26,7 +26,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-proposals - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -59,7 +58,6 @@ 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 rake parallel:spec['spec\/(?!system)'] diff --git a/.github/workflows/ci_sortitions.yml b/.github/workflows/ci_sortitions.yml index 8d5b26659e4dd..7a00d6bd96ff8 100644 --- a/.github/workflows/ci_sortitions.yml +++ b/.github/workflows/ci_sortitions.yml @@ -23,7 +23,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-sortitions - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -60,7 +59,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_surveys.yml b/.github/workflows/ci_surveys.yml index b316f27fd8d72..ff6b7815d01b6 100644 --- a/.github/workflows/ci_surveys.yml +++ b/.github/workflows/ci_surveys.yml @@ -24,7 +24,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-surveys - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -61,7 +60,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_system.yml b/.github/workflows/ci_system.yml index 5b0c97972b93c..b7c30647a2bd1 100644 --- a/.github/workflows/ci_system.yml +++ b/.github/workflows/ci_system.yml @@ -20,7 +20,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-system - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -57,7 +56,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_templates.yml b/.github/workflows/ci_templates.yml index f352f469613b6..06b1df7415714 100644 --- a/.github/workflows/ci_templates.yml +++ b/.github/workflows/ci_templates.yml @@ -23,7 +23,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-templates - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -60,7 +59,6 @@ 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 rake parallel:spec diff --git a/.github/workflows/ci_verifications.yml b/.github/workflows/ci_verifications.yml index 45c8c9ed87007..142644b8fdc12 100644 --- a/.github/workflows/ci_verifications.yml +++ b/.github/workflows/ci_verifications.yml @@ -21,7 +21,6 @@ env: RUBY_VERSION: 3.0.2 NODE_VERSION: 16.9.1 DECIDIM_MODULE: decidim-verifications - PARALLEL_TEST_PROCESSORS: 2 CODECOV_TOKEN: bc15b944-6b42-420a-b3f9-a5a8fb214326 jobs: @@ -58,7 +57,6 @@ 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 rake parallel:spec diff --git a/CHANGELOG.md b/CHANGELOG.md index 977c8742bd8ac..20057e579f2cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## [0.27.6](https://github.com/decidim/decidim/tree/0.27.6) + ### Upgrade notes #### Verifications documents configurations @@ -50,6 +52,18 @@ en: You can read more about this change on PR [\#12306](https://github.com/decidim/decidim/pull/12306) +#### Allow removal of orphan categories + +A bug was identified that prevented the deletion of categories lacking associated resources. This action is a one-time task that must be performed directly in the production database. + +```console +bin/rails decidim:upgrade:fix_orphan_categorizations +``` + +You can read more about this change on PR [\#12143](https://github.com/decidim/decidim/pull/12143). + +## Detailed changes + ### Added Nothing. @@ -60,7 +74,79 @@ Nothing. ### Fixed -Nothing. +- **decidim-participatory processes**: Fix using CTA image on promoted process group [\#12202](https://github.com/decidim/decidim/pull/12202) +- **decidim-proposals**: Backport 'Add answered_at field in proposals' export' to v0.27 [\#12297](https://github.com/decidim/decidim/pull/12297) +- Backport 'Use git instead of filesystem for releases files' to v0.27 [\#12303](https://github.com/decidim/decidim/pull/12303) +- Backport 'Lock Ruby to Decidim supported version' to v0.27 [\#12299](https://github.com/decidim/decidim/pull/12299) +- **decidim-admin**: Backport 'Fix favicons in admin panel' to v0.27 [\#12315](https://github.com/decidim/decidim/pull/12315) +- **decidim-budgets**: Backport 'Change the selected column in budgets' projects' to v0.27 [\#12296](https://github.com/decidim/decidim/pull/12296) +- **decidim-admin**: Backport 'Add admin permissions for conflicts and logs controllers' to v0.27 [\#12300](https://github.com/decidim/decidim/pull/12300) +- **decidim-core**: Backport 'Allow passing a blob object to `AssetRouter::Storage`' to v0.27 [\#12304](https://github.com/decidim/decidim/pull/12304) +- Backport 'Fix webpack generation on cells specs' to v0.27 [\#12335](https://github.com/decidim/decidim/pull/12335) +- **decidim-proposals**: Backport 'Protect participatory text buttons under authorization' to v0.27 [\#12353](https://github.com/decidim/decidim/pull/12353) +- **decidim-meetings**: Do not display dates for upcoming moderated meetings [\#12295](https://github.com/decidim/decidim/pull/12295) +- **decidim-proposals**: Add participatory text missing attribute [\#12330](https://github.com/decidim/decidim/pull/12330) +- **decidim-core**: Backport 'Properly handle the category name in tags cell' to v0.27 [\#12298](https://github.com/decidim/decidim/pull/12298) +- Pinning chrome version to v119 [\#12420](https://github.com/decidim/decidim/pull/12420) +- Backport 'Fix Proposals bulk action form' to v0.27 [\#12444](https://github.com/decidim/decidim/pull/12444) +- **decidim-elections**: Backport 'Fix voting data migration for AddFollowableCounterCacheToVotings' to v0.27 [\#12443](https://github.com/decidim/decidim/pull/12443) +- Backport 'Fix authorization handler in OmniauthRegistrations' to v0.27 [\#12445](https://github.com/decidim/decidim/pull/12445) +- Backport 'Generate component Gemfile template when releasing' to v0.27 [\#12450](https://github.com/decidim/decidim/pull/12450) +- **decidim-budgets**: Backport 'Pass the budget context to the admin new and edit actions for projects' to v0.27 [\#12448](https://github.com/decidim/decidim/pull/12448) +- **decidim-admin**, **decidim-system**: Backport 'Fix exception when presenting oauth application in admin log' to v0.27 [\#12447](https://github.com/decidim/decidim/pull/12447) +- Backport 'Bump stringio and carrierwave' to v0.27 [\#12449](https://github.com/decidim/decidim/pull/12449) +- **decidim-verifications**: Backport 'Allow apps to configure the document types in the verifications module' to v0.27 [\#12451](https://github.com/decidim/decidim/pull/12451) +- **decidim-dev**: Backport 'Disable shm usage in Capybara' to v0.27 [\#12506](https://github.com/decidim/decidim/pull/12506) +- **decidim-admin**: Backport 'Fix deleted and blocked users display from impersonations participant list' to v0.27 [\#12505](https://github.com/decidim/decidim/pull/12505) +- Backport 'Fix decidim-core and decidim-api dependency tree' to v0.27 [\#12512](https://github.com/decidim/decidim/pull/12512) +- **decidim-api**: Backport 'Add note about the unescaped contents of the GraphQL API' to v0.27 [\#12510](https://github.com/decidim/decidim/pull/12510) +- **decidim-core**: Backport 'Refactor of events specs' to v0.27 [\#12507](https://github.com/decidim/decidim/pull/12507) +- **decidim-core**: Backport 'Refactor of events specs (part 2)' to v0.27 [\#12508](https://github.com/decidim/decidim/pull/12508) +- **decidim-core**: Backport 'Implement push notifications for conversations' messages' to v0.27 [\#12511](https://github.com/decidim/decidim/pull/12511) +- Backport 'Standardize the way resources are being listed ...' to v0.27 [\#12533](https://github.com/decidim/decidim/pull/12533) +- Backport 'Fix decidim-templates usage' to v0.27 [\#12600](https://github.com/decidim/decidim/pull/12600) +- **decidim-admin**: Backport 'Fix images URL in newsletters' to v0.27 [\#12612](https://github.com/decidim/decidim/pull/12612) +- Fix embeds for resources and spaces that shouldn't be embedded [\#12528](https://github.com/decidim/decidim/pull/12528) +- **decidim-comments**: Backport 'Restrict comments replies tree including polymorphism' to v0.27 [\#12305](https://github.com/decidim/decidim/pull/12305) +- Backport 'Patch participatory spaces factories' to v0.27 [\#12647](https://github.com/decidim/decidim/pull/12647) +- Backport 'Patch events on the new format' to v0.27 [\#12648](https://github.com/decidim/decidim/pull/12648) +- Backport 'Patch components and spaces factories' to v0.27 [\#12547](https://github.com/decidim/decidim/pull/12547) +- **decidim-core**: Backport 'Fix user profile current tab' to v0.27 [\#12729](https://github.com/decidim/decidim/pull/12729) +- Backport 'Add description for the decidim:reminders:all task' to v0.27 [\#12733](https://github.com/decidim/decidim/pull/12733) +- Backport 'Add matrix for Decidim/Ruby/Node versions in manual guide' to v0.27 [\#12759](https://github.com/decidim/decidim/pull/12759) +- **decidim-admin**, **decidim-core**, **decidim-generators**: Backport 'Fix bug in welcome notifications when the organization has weird characters' to v0.27 [\#12784](https://github.com/decidim/decidim/pull/12784) +- **decidim-comments**: Backport 'Add votes count to comment caches' to v0.27 [\#12782](https://github.com/decidim/decidim/pull/12782) +- **decidim-budgets**: Backport 'Fix DOM text reinterpreted as HTML in budgets' exit handler' to v0.27 [\#12769](https://github.com/decidim/decidim/pull/12769) +- **decidim-initiatives**: Backport 'Fix potential unsafe external link in initiatives' to v0.27 [\#12780](https://github.com/decidim/decidim/pull/12780) +- **decidim-api**: Backport 'Fix graphiql initial query escaping' to v0.27 [\#12779](https://github.com/decidim/decidim/pull/12779) +- **decidim-core**: Backport 'Fix clear-text storage of sensitive information in omniauth registration' to v0.27 [\#12773](https://github.com/decidim/decidim/pull/12773) +- **decidim-accountability**: Backport 'Remove ComponentInterface from the ResultType in the API' to v0.27 [\#12774](https://github.com/decidim/decidim/pull/12774) +- **decidim-core**: Backport 'Fix flaky spec on join user group command spec' to v0.27 [\#12776](https://github.com/decidim/decidim/pull/12776) +- **decidim-core**: Backport 'Fix flaky spec on endorsements controller' to v0.27 [\#12777](https://github.com/decidim/decidim/pull/12777) +- **decidim-core**: Backport 'Fix overly permissive regular expression range in "has reference" specs' to v0.27 [\#12770](https://github.com/decidim/decidim/pull/12770) +- **decidim-proposals**: Backport 'Add counter cache for proposals' ValuationAssignments' to v0.27 [\#12771](https://github.com/decidim/decidim/pull/12771) +- **decidim-admin**, **decidim-core**: Backport 'Fix API paths when deploying decidim in folder' to v0.27 [\#12775](https://github.com/decidim/decidim/pull/12775) +- **decidim-core**: Backport 'Improve testing on address cell' to v0.27 [\#12788](https://github.com/decidim/decidim/pull/12788) +- **decidim-core**: Backport 'Fix illogical heading order on registration page' to v0.27 [\#12791](https://github.com/decidim/decidim/pull/12791) +- **decidim-proposals**: Backport 'Fix flaky specs in proposals' to v0.27 [\#12795](https://github.com/decidim/decidim/pull/12795) +- **decidim-core**, **decidim-dev**: Backport 'Fix flaky shakapacker compilation' to v0.27 [\#12781](https://github.com/decidim/decidim/pull/12781) +- **decidim-core**: Backport 'Fix performance issue with attribute encryption/decryption' to v0.27 [\#12793](https://github.com/decidim/decidim/pull/12793) +- **decidim-core**: Backport 'Improve premailer HTML parsing' to v0.27 [\#12789](https://github.com/decidim/decidim/pull/12789) +- **decidim-comments**: Backport 'Fix flaky spec on CommentVote model spec' to v0.27 [\#12790](https://github.com/decidim/decidim/pull/12790) +- **decidim-assemblies**, **decidim-conferences**, **decidim-core**, **decidim-initiatives**, **decidim-meetings**, **decidim-participatory processes**: Backport 'Don't add the slug of the space in some links' to v0.27 [\#12792](https://github.com/decidim/decidim/pull/12792) +- Backport 'Fix flaky generator spec with missing `package.json`' to v0.27 [\#12772](https://github.com/decidim/decidim/pull/12772) +- **decidim-core**: Backport 'Fix duplicate ActiveSupport notifications' to v0.27 [\#12801](https://github.com/decidim/decidim/pull/12801) +- **decidim-comments**: Backport 'Improve performance on comment rendering' to v0.27 [\#12799](https://github.com/decidim/decidim/pull/12799) +- **decidim-templates**: Backport 'Skip authenticity token in questionnaire templates' to v0.27 [\#12798](https://github.com/decidim/decidim/pull/12798) +- **decidim-meetings**: Backport 'Fix selection of polls with two answers and single options questions' to v0.27 [\#12803](https://github.com/decidim/decidim/pull/12803) +- Backport 'Add patch_generators task to maintainers' releases instructions' to v0.27 [\#12800](https://github.com/decidim/decidim/pull/12800) +- **decidim-admin**, **decidim-budgets**: Backport 'Do not show scopes column in budgets if there isn't subscopes' to v0.27 [\#12802](https://github.com/decidim/decidim/pull/12802) +- **decidim-core**: Backport 'Show extended information when a new comment is in a digest email' to v0.27 [\#12805](https://github.com/decidim/decidim/pull/12805) +- **decidim-core**: Backport 'Prevent malformed URLs in the general search' to v0.27 [\#12807](https://github.com/decidim/decidim/pull/12807) +- **decidim-budgets**, **decidim-dev**: Backport 'Prevent multiple requests from creating multiple orders at budgets' to v0.27 [\#12804](https://github.com/decidim/decidim/pull/12804) +- **decidim-proposals**: Backport 'Attempt to fix flaky spec on proposals' ammends' to v0.27 [\#12796](https://github.com/decidim/decidim/pull/12796) +- **decidim-core**: Backport 'Update Leaflet and related NPM packages' to v0.27 [\#12794](https://github.com/decidim/decidim/pull/12794) +- **decidim-admin**, **decidim-core**: Backport 'Allow deletion of categories when there are no resources associated' to v0.27 [\#12808](https://github.com/decidim/decidim/pull/12808) ### Removed @@ -68,11 +154,15 @@ Nothing. ### Developer improvements -Nothing. +- Backport 'Improve testing on address cell' to v0.27 [\#12788](https://github.com/decidim/decidim/pull/12788) +- Backport 'Improve premailer HTML parsing' to v0.27 [\#12789](https://github.com/decidim/decidim/pull/12789) ### Internal -Nothing. +- **decidim-elections**: Remove elections pipeline in 0.27 [\#12456](https://github.com/decidim/decidim/pull/12456) +- Backport 'Patch participatory spaces factories' to v0.27 [\#12647](https://github.com/decidim/decidim/pull/12647) +- Backport 'Patch events on the new format' to v0.27 [\#12648](https://github.com/decidim/decidim/pull/12648) +- **decidim-accountability**, **decidim-admin**, **decidim-api**, **decidim-assemblies**, **decidim-blogs**, **decidim-budgets**, **decidim-comments**, **decidim-conferences**, **decidim-consultations**, **decidim-core**, **decidim-debates**, **decidim-dev**, **decidim-elections**, **decidim-forms**, **decidim-generators**, **decidim-initiatives**, **decidim-meetings**, **decidim-pages**, **decidim-participatory processes**, **decidim-proposals**, **decidim-sortitions**, **decidim-surveys**, **decidim-system**, **decidim-templates**, **decidim-verifications**: Bump to v0.27.6 version [\#12814](https://github.com/decidim/decidim/pull/12814) ## [0.27.5](https://github.com/decidim/decidim/tree/0.27.5) diff --git a/Gemfile.lock b/Gemfile.lock index 26a2262127bd2..75b1ebc009035 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,63 +1,63 @@ PATH remote: . specs: - decidim (0.27.5) - decidim-accountability (= 0.27.5) - decidim-admin (= 0.27.5) - decidim-api (= 0.27.5) - decidim-assemblies (= 0.27.5) - decidim-blogs (= 0.27.5) - decidim-budgets (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-debates (= 0.27.5) - decidim-forms (= 0.27.5) - decidim-generators (= 0.27.5) - decidim-meetings (= 0.27.5) - decidim-pages (= 0.27.5) - decidim-participatory_processes (= 0.27.5) - decidim-proposals (= 0.27.5) - decidim-sortitions (= 0.27.5) - decidim-surveys (= 0.27.5) - decidim-system (= 0.27.5) - decidim-templates (= 0.27.5) - decidim-verifications (= 0.27.5) - decidim-accountability (0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-admin (0.27.5) + decidim (0.27.6) + decidim-accountability (= 0.27.6) + decidim-admin (= 0.27.6) + decidim-api (= 0.27.6) + decidim-assemblies (= 0.27.6) + decidim-blogs (= 0.27.6) + decidim-budgets (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-debates (= 0.27.6) + decidim-forms (= 0.27.6) + decidim-generators (= 0.27.6) + decidim-meetings (= 0.27.6) + decidim-pages (= 0.27.6) + decidim-participatory_processes (= 0.27.6) + decidim-proposals (= 0.27.6) + decidim-sortitions (= 0.27.6) + decidim-surveys (= 0.27.6) + decidim-system (= 0.27.6) + decidim-templates (= 0.27.6) + decidim-verifications (= 0.27.6) + decidim-accountability (0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-admin (0.27.6) active_link_to (~> 1.0) - decidim-core (= 0.27.5) + decidim-core (= 0.27.6) devise (~> 4.7) devise-i18n (~> 1.2) devise_invitable (~> 2.0, >= 2.0.9) - decidim-api (0.27.5) - decidim-core (= 0.27.5) + decidim-api (0.27.6) + decidim-core (= 0.27.6) graphql (~> 1.12, < 1.13) graphql-docs (~> 2.1.0) rack-cors (~> 1.0) - decidim-assemblies (0.27.5) - decidim-core (= 0.27.5) - decidim-blogs (0.27.5) - decidim-admin (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-budgets (0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-comments (0.27.5) - decidim-core (= 0.27.5) + decidim-assemblies (0.27.6) + decidim-core (= 0.27.6) + decidim-blogs (0.27.6) + decidim-admin (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-budgets (0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-comments (0.27.6) + decidim-core (= 0.27.6) redcarpet (~> 3.5, >= 3.5.1) - decidim-conferences (0.27.5) - decidim-core (= 0.27.5) - decidim-meetings (= 0.27.5) + decidim-conferences (0.27.6) + decidim-core (= 0.27.6) + decidim-meetings (= 0.27.6) wicked_pdf (~> 2.1) wkhtmltopdf-binary (~> 0.12) - decidim-consultations (0.27.5) - decidim-admin (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-core (0.27.5) + decidim-consultations (0.27.6) + decidim-admin (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-core (0.27.6) active_link_to (~> 1.0) acts_as_list (~> 0.9) batch-loader (~> 1.2) @@ -82,7 +82,6 @@ PATH loofah (~> 2.19.0) mime-types (>= 1.16, < 4.0) mini_magick (~> 4.9) - mustache (~> 1.1.0) omniauth (~> 2.0) omniauth-facebook (~> 5.0) omniauth-google-oauth2 (~> 1.0) @@ -107,15 +106,15 @@ PATH webpacker (= 6.0.0.rc.5) webpush (~> 1.1) wisper (~> 2.0) - decidim-debates (0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-dev (0.27.5) + decidim-debates (0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-dev (0.27.6) axe-core-rspec (~> 4.1.0) byebug (~> 11.0) capybara (~> 3.24) db-query-matchers (~> 0.10.0) - decidim (= 0.27.5) + decidim (= 0.27.6) erb_lint (~> 0.0.35) factory_bot_rails (~> 4.8) i18n-tasks (~> 0.9.18) @@ -138,62 +137,62 @@ PATH w3c_rspec_validators (~> 0.3.0) webmock (~> 3.6) wisper-rspec (~> 1.0) - decidim-elections (0.27.5) + decidim-elections (0.27.6) decidim-bulletin_board (= 0.23) - decidim-core (= 0.27.5) - decidim-forms (= 0.27.5) - decidim-proposals (= 0.27.5) + decidim-core (= 0.27.6) + decidim-forms (= 0.27.6) + decidim-proposals (= 0.27.6) rack-attack (~> 6.0) voting_schemes-dummy (= 0.23) voting_schemes-electionguard (= 0.23) - decidim-forms (0.27.5) - decidim-core (= 0.27.5) + decidim-forms (0.27.6) + decidim-core (= 0.27.6) wicked_pdf (~> 2.1) wkhtmltopdf-binary (~> 0.12) - decidim-generators (0.27.5) - decidim-core (= 0.27.5) - decidim-initiatives (0.27.5) - decidim-admin (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-verifications (= 0.27.5) + decidim-generators (0.27.6) + decidim-core (= 0.27.6) + decidim-initiatives (0.27.6) + decidim-admin (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-verifications (= 0.27.6) origami (~> 2.1) rexml (~> 3.2.5) wicked (~> 1.3) wicked_pdf (~> 2.1) wkhtmltopdf-binary (~> 0.12) - decidim-meetings (0.27.5) - decidim-core (= 0.27.5) - decidim-forms (= 0.27.5) + decidim-meetings (0.27.6) + decidim-core (= 0.27.6) + decidim-forms (= 0.27.6) icalendar (~> 2.5) - decidim-pages (0.27.5) - decidim-core (= 0.27.5) - decidim-participatory_processes (0.27.5) - decidim-core (= 0.27.5) - decidim-proposals (0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) + decidim-pages (0.27.6) + decidim-core (= 0.27.6) + decidim-participatory_processes (0.27.6) + decidim-core (= 0.27.6) + decidim-proposals (0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) doc2text (~> 0.4.5) redcarpet (~> 3.5, >= 3.5.1) - decidim-sortitions (0.27.5) - decidim-admin (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-proposals (= 0.27.5) - decidim-surveys (0.27.5) - decidim-core (= 0.27.5) - decidim-forms (= 0.27.5) - decidim-system (0.27.5) + decidim-sortitions (0.27.6) + decidim-admin (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-proposals (= 0.27.6) + decidim-surveys (0.27.6) + decidim-core (= 0.27.6) + decidim-forms (= 0.27.6) + decidim-system (0.27.6) active_link_to (~> 1.0) - decidim-core (= 0.27.5) + decidim-core (= 0.27.6) devise (~> 4.7) devise-i18n (~> 1.2) devise_invitable (~> 2.0, >= 2.0.9) - decidim-templates (0.27.5) - decidim-core (= 0.27.5) - decidim-forms (= 0.27.5) - decidim-verifications (0.27.5) - decidim-core (= 0.27.5) + decidim-templates (0.27.6) + decidim-core (= 0.27.6) + decidim-forms (= 0.27.6) + decidim-verifications (0.27.6) + decidim-core (= 0.27.6) GEM remote: https://rubygems.org/ @@ -265,7 +264,7 @@ GEM addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) ast (2.4.2) - axe-core-api (4.8.0) + axe-core-api (4.9.0) dumb_delegator virtus axe-core-rspec (4.1.0) @@ -276,8 +275,9 @@ GEM descendants_tracker (~> 0.0.4) ice_nine (~> 0.11.0) thread_safe (~> 0.3, >= 0.3.1) + base64 (0.2.0) batch-loader (1.5.0) - bcrypt (3.1.19) + bcrypt (3.1.20) better_html (1.0.16) actionview (>= 4.0) activesupport (>= 4.0) @@ -286,6 +286,7 @@ GEM html_tokenizer (~> 0.0.6) parser (>= 2.4) smart_properties + bigdecimal (3.1.7) bindex (0.8.1) bootsnap (1.10.3) msgpack (~> 1.2) @@ -293,16 +294,16 @@ GEM browser (2.7.1) builder (3.2.4) byebug (11.1.3) - capybara (3.39.2) + capybara (3.40.0) addressable matrix mini_mime (>= 0.1.3) - nokogiri (~> 1.8) + nokogiri (~> 1.11) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - carrierwave (2.2.5) + carrierwave (2.2.6) activemodel (>= 5.0.0) activesupport (>= 5.0.0) addressable (~> 2.6) @@ -322,7 +323,7 @@ GEM actionpack (>= 5.0) cells (>= 4.1.6, < 5.0.0) charlock_holmes (0.7.7) - chef-utils (18.3.0) + chef-utils (18.4.12) concurrent-ruby childprocess (4.1.0) coercible (1.0.0) @@ -337,10 +338,11 @@ GEM colorize (0.8.1) commonmarker (0.23.10) concurrent-ruby (1.2.3) - crack (0.4.5) + crack (1.0.0) + bigdecimal rexml crass (1.0.6) - css_parser (1.16.0) + css_parser (1.17.1) addressable date (3.3.3) date_validator (0.12.0) @@ -360,7 +362,7 @@ GEM declarative-option (0.1.0) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) - devise (4.9.3) + devise (4.9.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) @@ -371,13 +373,13 @@ GEM devise_invitable (2.0.9) actionmailer (>= 5.0) devise (>= 4.6) - diff-lcs (1.5.0) + diff-lcs (1.5.1) diffy (3.4.2) - doc2text (0.4.6) - nokogiri (>= 1.13.2, < 1.15.0) + doc2text (0.4.7) + nokogiri (>= 1.13.2, < 1.17.0) rubyzip (~> 2.3.0) docile (1.4.0) - doorkeeper (5.6.6) + doorkeeper (5.7.0) railties (>= 5) doorkeeper-i18n (4.0.1) dumb_delegator (1.0.0) @@ -393,7 +395,7 @@ GEM temple erubi (1.12.0) escape_utils (1.3.0) - excon (0.104.0) + excon (0.110.0) execjs (2.9.1) extended-markdown-filter (0.7.0) html-pipeline (~> 2.9) @@ -433,7 +435,7 @@ GEM file_validators (3.0.0) activemodel (>= 3.2) mime-types (>= 1.0) - fog-core (2.3.0) + fog-core (2.4.0) builder excon (~> 0.71) formatador (>= 0.2, < 2.0) @@ -455,7 +457,7 @@ GEM faraday_middleware graphql-client graphql (1.12.24) - graphql-client (0.18.0) + graphql-client (0.19.0) activesupport (>= 3.0) graphql graphql-docs (2.1.0) @@ -466,14 +468,14 @@ GEM graphql (~> 1.12) html-pipeline (~> 2.9) sass (~> 3.4) - hashdiff (1.0.1) + hashdiff (1.1.0) hashie (5.0.0) - highline (2.1.0) + highline (3.0.1) hkdf (0.3.0) html-pipeline (2.14.3) activesupport (>= 2) nokogiri (>= 1.4) - html_tokenizer (0.0.7) + html_tokenizer (0.0.8) htmlentities (4.3.4) i18n (1.14.1) concurrent-ruby (~> 1.0) @@ -487,7 +489,7 @@ GEM rails-i18n rainbow (>= 2.2.2, < 4.0) terminal-table (>= 1.5.1) - icalendar (2.10.0) + icalendar (2.10.1) ice_cube (~> 0.16) ice_cube (0.16.4) ice_nine (0.11.2) @@ -496,7 +498,7 @@ GEM ruby-vips (>= 2.0.17, < 3) invisible_captcha (0.13.0) rails (>= 3.2.0) - json (2.6.3) + json (2.7.2) jwt (2.2.3) kaminari (1.2.2) activesupport (>= 4.1.0) @@ -534,7 +536,7 @@ GEM net-imap net-pop net-smtp - marcel (1.0.2) + marcel (1.0.4) matrix (0.4.2) mdl (0.13.0) kramdown (~> 2.3) @@ -543,9 +545,9 @@ GEM mixlib-config (>= 2.2.1, < 4) mixlib-shellout method_source (1.0.0) - mime-types (3.5.1) + mime-types (3.5.2) mime-types-data (~> 3.2015) - mime-types-data (3.2023.1003) + mime-types-data (3.2024.0305) mini_magick (4.12.0) mini_mime (1.1.5) mini_portile2 (2.8.5) @@ -557,8 +559,7 @@ GEM chef-utils msgpack (1.4.5) multi_xml (0.6.0) - multipart-post (2.3.0) - mustache (1.1.1) + multipart-post (2.4.0) net-imap (0.4.4) date net-protocol @@ -585,17 +586,17 @@ GEM rack (>= 1.2, < 4) snaky_hash (~> 2.0) version_gem (~> 1.1) - omniauth (2.1.1) + omniauth (2.1.2) hashie (>= 3.4.6) rack (>= 2.2.3) rack-protection omniauth-facebook (5.0.0) omniauth-oauth2 (~> 1.2) - omniauth-google-oauth2 (1.1.1) + omniauth-google-oauth2 (1.1.2) jwt (>= 2.0) - oauth2 (~> 2.0.6) + oauth2 (~> 2.0) omniauth (~> 2.0) - omniauth-oauth2 (~> 1.8.0) + omniauth-oauth2 (~> 1.8) omniauth-oauth (1.2.0) oauth omniauth (>= 1.0, < 3) @@ -623,7 +624,7 @@ GEM pg_search (2.3.6) activerecord (>= 5.2) activesupport (>= 5.2) - premailer (1.21.0) + premailer (1.23.0) addressable css_parser (>= 1.12.0) htmlentities (>= 4.0.0) @@ -640,7 +641,8 @@ GEM rack (>= 1.0, < 4) rack-cors (1.1.1) rack (>= 2.0.0) - rack-protection (3.1.0) + rack-protection (3.2.0) + base64 (>= 0.1.0) rack (~> 2.2, >= 2.2.4) rack-proxy (0.7.7) rack @@ -698,24 +700,24 @@ GEM actionpack (>= 5.2) railties (>= 5.2) rexml (3.2.5) - rspec (3.12.0) - rspec-core (~> 3.12.0) - rspec-expectations (~> 3.12.0) - rspec-mocks (~> 3.12.0) - rspec-cells (0.3.8) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-cells (0.3.9) cells (>= 4.0.0, < 6.0.0) - rspec-rails (>= 3.0.0, < 6.1.0) - rspec-core (3.12.2) - rspec-support (~> 3.12.0) - rspec-expectations (3.12.3) + rspec-rails (>= 3.0.0, < 6.2.0) + rspec-core (3.13.0) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) + rspec-support (~> 3.13.0) rspec-html-matchers (0.9.4) nokogiri (~> 1) rspec (>= 3.0.0.a, < 4) - rspec-mocks (3.12.6) + rspec-mocks (3.13.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) + rspec-support (~> 3.13.0) rspec-rails (4.1.2) actionpack (>= 4.2) activesupport (>= 4.2) @@ -726,7 +728,7 @@ GEM rspec-support (~> 3.10) rspec-retry (0.6.2) rspec-core (> 3.3) - rspec-support (3.12.1) + rspec-support (3.13.1) rspec_junit_formatter (0.3.0) rspec-core (>= 2, < 4, != 2.12.0) rubocop (1.28.2) @@ -750,10 +752,10 @@ GEM rubocop-rspec (2.11.1) rubocop (~> 1.19) ruby-progressbar (1.11.0) - ruby-vips (2.2.0) + ruby-vips (2.2.1) ffi (~> 1.12) ruby2_keywords (0.0.5) - rubyXL (3.4.25) + rubyXL (3.4.27) nokogiri (>= 1.10.8) rubyzip (>= 1.3.0) rubyzip (2.3.2) @@ -810,7 +812,7 @@ GEM valid_email2 (2.3.1) activemodel (>= 3.2) mail (~> 2.5) - version_gem (1.1.3) + version_gem (1.1.4) virtus (2.0.0) axiom-types (~> 0.1) coercible (~> 1.0) @@ -834,7 +836,7 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) - webmock (3.19.1) + webmock (3.23.0) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -851,7 +853,7 @@ GEM websocket-extensions (0.1.5) wicked (1.4.0) railties (>= 3.0.7) - wicked_pdf (2.7.0) + wicked_pdf (2.8.0) activesupport wisper (2.0.1) wisper-rspec (1.1.0) diff --git a/decidim-accountability/app/events/decidim/accountability/base_result_event.rb b/decidim-accountability/app/events/decidim/accountability/base_result_event.rb new file mode 100644 index 0000000000000..3f14f856b3e0d --- /dev/null +++ b/decidim-accountability/app/events/decidim/accountability/base_result_event.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Decidim + module Accountability + class BaseResultEvent < Decidim::Events::SimpleEvent + i18n_attributes :proposal_title, :proposal_path + + def resource_text + translated_attribute(resource.description) + end + + def proposal_title + @proposal_title ||= decidim_sanitize_translated(proposal.title) + end + + def proposal_path + @proposal_path ||= Decidim::ResourceLocatorPresenter.new(proposal).path + end + + def proposal + @proposal ||= resource.linked_resources(:proposals, "included_proposals").find_by(id: extra[:proposal_id]) + end + end + end +end diff --git a/decidim-accountability/app/events/decidim/accountability/proposal_linked_event.rb b/decidim-accountability/app/events/decidim/accountability/proposal_linked_event.rb index c4fe40bd24c46..604db909621c9 100644 --- a/decidim-accountability/app/events/decidim/accountability/proposal_linked_event.rb +++ b/decidim-accountability/app/events/decidim/accountability/proposal_linked_event.rb @@ -2,24 +2,7 @@ module Decidim module Accountability - class ProposalLinkedEvent < Decidim::Events::SimpleEvent - i18n_attributes :proposal_title, :proposal_path - - def proposal_path - @proposal_path ||= Decidim::ResourceLocatorPresenter.new(proposal).path - end - - def proposal_title - @proposal_title ||= translated_attribute(proposal.title) - end - - def proposal - @proposal ||= resource.linked_resources(:proposals, "included_proposals").find_by(id: extra[:proposal_id]) - end - - def resource_text - translated_attribute(resource.description) - end + class ProposalLinkedEvent < BaseResultEvent end end end diff --git a/decidim-accountability/app/events/decidim/accountability/result_progress_updated_event.rb b/decidim-accountability/app/events/decidim/accountability/result_progress_updated_event.rb index 3c37a4f0510cb..496cbca93def5 100644 --- a/decidim-accountability/app/events/decidim/accountability/result_progress_updated_event.rb +++ b/decidim-accountability/app/events/decidim/accountability/result_progress_updated_event.rb @@ -2,28 +2,12 @@ module Decidim module Accountability - class ResultProgressUpdatedEvent < Decidim::Events::SimpleEvent - i18n_attributes :proposal_title, :proposal_path, :progress - - def proposal_path - @proposal_path ||= Decidim::ResourceLocatorPresenter.new(proposal).path - end - - def proposal_title - @proposal_title ||= translated_attribute(proposal.title) - end - - def proposal - @proposal ||= resource.linked_resources(:proposals, "included_proposals").find_by(id: extra[:proposal_id]) - end + class ResultProgressUpdatedEvent < BaseResultEvent + i18n_attributes :progress def progress extra[:progress] end - - def resource_text - translated_attribute(resource.description) - end end end end diff --git a/decidim-accountability/app/views/decidim/accountability/results/_home_header.html.erb b/decidim-accountability/app/views/decidim/accountability/results/_home_header.html.erb index a72a9e8a266b4..5a1eff4c59e81 100644 --- a/decidim-accountability/app/views/decidim/accountability/results/_home_header.html.erb +++ b/decidim-accountability/app/views/decidim/accountability/results/_home_header.html.erb @@ -1,7 +1,7 @@
- <%== translated_attribute component_settings.intro %> + <%= decidim_sanitize_admin translated_attribute(component_settings.intro) %>
<% if component_settings.display_progress_enabled? && progress_calculator(current_scope, nil).present? %> diff --git a/decidim-accountability/app/views/decidim/accountability/results/_show_leaf.html.erb b/decidim-accountability/app/views/decidim/accountability/results/_show_leaf.html.erb index e66e8f7c03085..dc28c8abde247 100644 --- a/decidim-accountability/app/views/decidim/accountability/results/_show_leaf.html.erb +++ b/decidim-accountability/app/views/decidim/accountability/results/_show_leaf.html.erb @@ -62,7 +62,7 @@
- <%== translated_attribute result.description %> + <%= decidim_sanitize_admin(translated_attribute(result.description)) %> <%= cell "decidim/tags", result, context: { extra_classes: ["tags--result"] } %>
diff --git a/decidim-accountability/app/views/decidim/accountability/results/_timeline.html.erb b/decidim-accountability/app/views/decidim/accountability/results/_timeline.html.erb index bb45078f2aeb9..b15cd9b82cfb5 100644 --- a/decidim-accountability/app/views/decidim/accountability/results/_timeline.html.erb +++ b/decidim-accountability/app/views/decidim/accountability/results/_timeline.html.erb @@ -18,7 +18,7 @@ <% if translated_attribute(timeline_entry.description).present? %>
- <%== translated_attribute timeline_entry.description %> + <%= decidim_escape_translated(timeline_entry.description) %>
<% end %>
diff --git a/decidim-accountability/app/views/decidim/participatory_spaces/_result.html.erb b/decidim-accountability/app/views/decidim/participatory_spaces/_result.html.erb index 3a4aea23b83f2..aace393c46cd6 100644 --- a/decidim-accountability/app/views/decidim/participatory_spaces/_result.html.erb +++ b/decidim-accountability/app/views/decidim/participatory_spaces/_result.html.erb @@ -3,7 +3,7 @@ <%= link_to resource_locator(result).path, class: "card--list__text card__link card__link--block" do %>

- <%= translated_attribute(result.title) %> + <%= decidim_escape_translated(result.title) %>

@@ -19,7 +19,7 @@ <% if result.status %> <%= t("models.result.fields.status", scope: "decidim.accountability") %> - <%= translated_attribute(result.status.name) %> + <%= decidim_escape_translated(result.status.name) %> <% end %>
<% end %> diff --git a/decidim-accountability/config/locales/ar.yml b/decidim-accountability/config/locales/ar.yml index 292e357a2de69..76d79f8dd1e82 100644 --- a/decidim-accountability/config/locales/ar.yml +++ b/decidim-accountability/config/locales/ar.yml @@ -221,7 +221,7 @@ ar: stats: attendees: الحضور back_to_resource: العودة إلى النتيجة - comments: تعليقات + comments: التعليقات contributions: مساهمات last_edited_by: التعديل الأخير تم بواسطة last_updated_at: آخر تحديث في diff --git a/decidim-accountability/config/locales/bg.yml b/decidim-accountability/config/locales/bg.yml index 3c61732a93308..fad3e6f8ac2a4 100644 --- a/decidim-accountability/config/locales/bg.yml +++ b/decidim-accountability/config/locales/bg.yml @@ -22,6 +22,7 @@ bg: timeline_entry: description: Описание entry_date: Дата + title: Заглавие models: decidim/accountability/proposal_linked_event: Предложение, включено в резултата decidim/accountability/result_progress_updated_event: Напредъкът на резултатите е актуализиран @@ -33,20 +34,45 @@ bg: decidim: accountability: actions: + attachment_collections: Папки + attachments: Прикачени файлове confirm_destroy: Сигурни ли сте, че искате да изтриете това %{name}? destroy: Изтрий edit: Редактирай - import_csv: Импорт CVS + import_csv: Импортиране на CSV new: Ново %{name} preview: Преглед timeline_entries: Развитие на проекта title: Действия admin: exports: + result_comments: Коментари results: Резултати import_results: new: + download_export: Свалете експорта в CSV формат import: Внасяне + info: | +

Препоръчваме ви да следвате следните стъпки:

+
    +
  1. Създайте статусите за резултатите, които искате да добавите
  2. +
  3. Създайте поне един резултат ръчно чрез този административен панел, преди да използвате Импортиране, за да разберете по-добре формата и това, което ще се нуждае от попълване.
  4. +
  5. %{link_export_csv}
  6. +
  7. Направете промените локално. Можете да промените само следните колони в CSV: +
      +
    • category/id: ID за категорията
    • +
    • scope/id: ID за обхвата
    • +
    • parent/id: ID на родителя (за свързани резултати). По избор
    • +
    • title/en: Заглавие на английски език. Това ще зависи от езиковата конфигурация на вашата платформа.
    • +
    • description/en: Описание на английски език. Това ще зависи от езиковата конфигурация на вашата платформа.
    • +
    • начална_дата: дата, когато резултатът започва да се изпълнява (формат ГГГГ-ММ-ДД)
    • +
    • крайна_дата: дата, на която резултатът приключва изпълнението (формат ГГГГ-ММ-ДД)
    • +
    • status/id: ID на статуса за този резултат
    • +
    • напредък: Процент (от 0 до 100) на изпълнението
    • +
    • proposals_ids: вътрешен идентификатор на свързаните предложения (разделени със запетая). Той автоматично се преобразува в proposal_url
    • +
    +
  8. +
title: Импортирай резултати от CSV imports: create: @@ -117,9 +143,22 @@ bg: create: "%{user_name} създаде резултата %{resource_name} в %{space_name}" delete: "%{user_name} изтри резултата %{resource_name} в %{space_name}" update: "%{user_name} обнови резултата %{resource_name} в %{space_name}" + status: + create: "Статусът е създаден" + delete: "Статусът е изтрит" + update: "Статусът е обновен" + timeline_entry: + create: "Създаде запис във времевата линия" + delete: "Изтри запис от времевата линия" + update: "Обнови запис във времевата линия" value_types: parent_presenter: not_found: 'Родителя липсва в базата данни (ID: %{id})' + content_blocks: + highlighted_results: + dates: Дати + results: Резултати + unspecified: Не е посочено import_mailer: import: errors: Грешки @@ -132,8 +171,12 @@ bg: models: result: fields: + category: Категория + created_at: Създаден end_date: Крайна дата + id: ID progress: Напредък + scope: Обхват start_date: Начална дата status: Статус title: Заглавие @@ -146,6 +189,10 @@ bg: timeline_entry: fields: entry_date: Дата + title: Заглавие + result_m: + executed: Изпълнено + view: Изглед results: count: results_count: @@ -176,8 +223,19 @@ bg: votes: Поддръжки timeline: title: Развитие на проекта + admin: + filters: + results: + category_id_eq: + label: Категория + scope_id_eq: + label: Обхват + status_id_eq: + label: Статус components: accountability: + actions: + comment: Коментар name: Отговорност settings: global: @@ -218,3 +276,5 @@ bg: result_project: Проекти, включени в резултата included_proposals: result_proposal: Предложения, включени в резултата + statistics: + results_count: Резултати diff --git a/decidim-accountability/config/locales/ca.yml b/decidim-accountability/config/locales/ca.yml index dd740705070ad..b21b78ea42f80 100644 --- a/decidim-accountability/config/locales/ca.yml +++ b/decidim-accountability/config/locales/ca.yml @@ -260,7 +260,7 @@ ca: notification_title: La proposta %{proposal_title} s'ha inclòs al resultat %{resource_title}. result_progress_updated: email_intro: 'El resultat "%{resource_title}", que inclou la proposta "%{proposal_title}", s''ha completat en un %{progress}%. Pots veure-ho des d''aquesta pàgina:' - email_outro: Has rebut aquesta notificació perquè estàs seguint "%{proposal_title}", i aquesta proposta s'inclou al resultat "%{resource_title}". Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint la proposta "%{proposal_title}", i aquesta s'inclou al resultat "%{resource_title}". Pots deixar de rebre notificacions seguint l'enllaç anterior. email_subject: Una actualització sobre el progrés de %{resource_title} notification_title: El resultat %{resource_title}, que inclou la proposta %{proposal_title}, s'ha completat en un %{progress}%. metrics: diff --git a/decidim-accountability/config/locales/da.yml b/decidim-accountability/config/locales/da.yml index 2799c6e1ac06d..444111335fa08 100644 --- a/decidim-accountability/config/locales/da.yml +++ b/decidim-accountability/config/locales/da.yml @@ -167,7 +167,6 @@ da: stats: attendees: Mødedeltagere back_to_resource: Tilbage til resultater - comments: Kommentarer contributions: Bidrag last_edited_by: Sidst redigeret af last_updated_at: Senest opdateret den diff --git a/decidim-accountability/config/locales/es.yml b/decidim-accountability/config/locales/es.yml index b074263ca8a57..896770a96ef34 100644 --- a/decidim-accountability/config/locales/es.yml +++ b/decidim-accountability/config/locales/es.yml @@ -255,12 +255,12 @@ es: accountability: proposal_linked: email_intro: 'La propuesta "%{proposal_title}" se ha incluido en un resultado. Puedes verlo desde esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo "%{proposal_title}". Puedes dejar de recibir notificaciones siguiendo el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo la propuesta "%{proposal_title}". Puedes dejar de recibir notificaciones siguiendo el enlace anterior. email_subject: Una actualización en %{proposal_title} notification_title: Se ha incluido la propuesta %{proposal_title} en el resultado %{resource_title}. result_progress_updated: email_intro: 'El resultado "%{resource_title}", que incluye la propuesta "%{proposal_title}", está completado al %{progress}%. Puedes verlo desde esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo "%{proposal_title}" y esta propuesta se incluye en el resultado "%{resource_title}". Puedes dejar de recibir notificaciones siguiendo el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo la propuesta "%{proposal_title}" y esta se incluye en el resultado "%{resource_title}". Puedes dejar de recibir notificaciones siguiendo el enlace anterior. email_subject: Una actualización sobre el progreso de %{resource_title} notification_title: El resultado %{resource_title}, que incluye la propuesta %{proposal_title}, ahora está completado al %{progress}%. metrics: diff --git a/decidim-accountability/config/locales/he-IL.yml b/decidim-accountability/config/locales/he-IL.yml new file mode 100644 index 0000000000000..c5edfc3cf1aef --- /dev/null +++ b/decidim-accountability/config/locales/he-IL.yml @@ -0,0 +1,219 @@ +--- +he: + activemodel: + attributes: + result: + decidim_accountability_status_id: סטטוס + decidim_category_id: קטגוריה + decidim_scope_id: היקף + description: תיאור + end_date: תאריך סיום + progress: התקדמות + project_ids: פרויקטים כלולים + proposals: הצעות כלולות + start_date: תאריך התחלה + title: כותרת + updated_at: עודכן ב- + status: + description: תיאור + key: מפתח + name: שם + progress: התקדמות + timeline_entry: + description: תיאור + entry_date: תאריך + title: כותרת + models: + decidim/accountability/proposal_linked_event: הצעה כלולה בתוצאה + decidim/accountability/result_progress_updated_event: התקדמות התוצאה עודכנה + activerecord: + models: + decidim/accountability/result: + one: תוצאה + two: תוצאות + many: תוצאות + other: תוצאות + decidim: + accountability: + actions: + attachment_collections: תיקיות + attachments: צרופות + confirm_destroy: האם את/ה בטוח/ה שברצונך למחוק את {name}? + destroy: מחיקה + edit: עריכה + preview: תצוגה מקדימה + timeline_entries: אבולוציה של הפרויקט + title: פעולות + admin: + exports: + result_comments: תגובות + results: תוצאות + import_results: + new: + download_export: להורדת הייצוא כקובץ CSV + import: ייבוא + models: + result: + name: תוצאה + status: + name: סטטוס + results: + edit: + title: עריכת תוצאה + update: עדכון תוצאה + index: + title: תוצאות + new: + create: יצירת תוצאה + title: תוצאה חדשה + shared: + subnav: + statuses: סטטוסים + statuses: + edit: + title: עריכת סטטוס + update: עדכון סטטוס + index: + title: סטטוסים + new: + create: יצירת סטטוס + title: סטטוס חדש + timeline_entries: + edit: + title: עריכת רשומה + update: עדכן רשומה + index: + title: ערכי ציר הזמן של הפרויקט + new: + create: יצירת רשומה + title: רשומה חדשה + admin_log: + result: + 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})' + content_blocks: + highlighted_results: + results: תוצאות + import_mailer: + import: + errors: שגיאות + row_number: שורה + subject: ייבוא ​​מוצלח של תוצאות + success: ייבוא ​​מוצלח של תוצאות. ניתן לעיין בתוצאות בממשק הניהול. + models: + result: + fields: + category: קטגוריה + created_at: נוצר + end_date: תאריך סיום + id: מספר מזהה + progress: התקדמות + scope: היקף + start_date: תאריך התחלה + status: סטטוס + title: כותרת + status: + fields: + description: תיאור + key: מפתח + name: שם + progress: התקדמות + timeline_entry: + fields: + entry_date: תאריך + title: כותרת + results: + count: + results_count: + one: תוצאה אחת + two: "שתי תוצאות" + many: "%{count} תוצאות" + other: "%{count} תוצאות" + filters: + all: הכל + home: + categories_label: קטגוריות + subcategories_label: תתי קטגוריות + home_header: + global_status: סטטוס ביצוע גלובלי + nav_breadcrumb: + global: ביצוע גלובלי + search: + search: חיפוש פעולה + show: + stats: + attendees: משתתפים.ות + back_to_resource: בחזרה לתוצאות + comments: תגובות + contributions: תרומות + last_edited_by: נערך לאחרונה על-ידי + last_updated_at: עודכן לאחרונה ב + meetings: פגישות + proposals: הצעות + votes: תמיכה + timeline: + title: אבולוציה של הפרויקט + admin: + filters: + results: + category_id_eq: + label: קטגוריה + scope_id_eq: + label: היקף + status_id_eq: + label: סטטוס + components: + accountability: + actions: + comment: תגובה + name: אחריותיות + settings: + global: + categories_label: שם ל"קטגוריות" + comments_enabled: איפשור תגובות + comments_max_length: אורך מקסימלי להערות (השאירו 0 לערך ברירת המחדל) + display_progress_enabled: הצגת התקדמות + heading_leaf_level_results: שם ל"פרויקטים" + heading_parent_level_results: שם ל"תוצאות" + intro: הקדמה + scope_id: היקף + scopes_enabled: היקפים מאופשרים + subcategories_label: שם ל"תתי קטוגריות" + step: + comments_blocked: תגובות חסומות + events: + accountability: + proposal_linked: + email_intro: 'ההצעה "%{proposal_title}" נכללה בתוצאה. ניתן לראות אותה מהעמוד הזה:' + email_outro: קיבלת הודעה זו מכיוון שאת.ה עוקב.ת אחר "%{proposal_title}". ניתן להפסיק לקבל התראות באמצעות הקישור הקודם. + email_subject: עדכון ל-%{proposal_title} + notification_title: ההצעה %{proposal_title} נכללה בתוצאת %{resource_title}. + result_progress_updated: + email_intro: 'התוצאה "%{resource_title}", הכוללת את ההצעה "%{proposal_title}", הושלמה כעת %{progress}%. ניתן לראות את זה מהעמוד הזה:' + email_outro: קיבלת הודעה זו מכיוון שאת.ה עוקב.ת אחר "%{proposal_title}", וההצעה הזו כלולה בתוצאה "%{resource_title}". ניתן להפסיק לקבל התראות באמצעות הקישור הקודם. + email_subject: עדכון ל-%{resource_title} התקדמות + notification_title: התוצאה %{resource_title}, הכוללת את ההצעה %{proposal_title}, היא כעת %{ התקדמות}% הושלמה. + metrics: + results: + description: מספר התוצאות שנוצרו + object: תוצאות + title: תוצאות + resource_links: + included_projects: + result_project: פרויקטים כלולים בתוצאה זו + included_proposals: + result_proposal: הצעות כלולות בתוצאה זו + statistics: + results_count: תוצאות diff --git a/decidim-accountability/config/locales/id-ID.yml b/decidim-accountability/config/locales/id-ID.yml index aa6f0bbb71917..2a63dbd242b57 100644 --- a/decidim-accountability/config/locales/id-ID.yml +++ b/decidim-accountability/config/locales/id-ID.yml @@ -150,7 +150,6 @@ id: stats: attendees: Hadirin back_to_resource: Kembali ke hasil - comments: Komentar contributions: Kontribusi last_edited_by: Terakhir diedit oleh last_updated_at: Terakhir diperbarui pada diff --git a/decidim-accountability/config/locales/it.yml b/decidim-accountability/config/locales/it.yml index 496f459249198..ffe7c9137e902 100644 --- a/decidim-accountability/config/locales/it.yml +++ b/decidim-accountability/config/locales/it.yml @@ -22,6 +22,7 @@ it: timeline_entry: description: Descrizione entry_date: Data + title: Titolo models: decidim/accountability/proposal_linked_event: Proposta inclusa in un risultato decidim/accountability/result_progress_updated_event: Avanzamento dei risultati aggiornato @@ -158,6 +159,7 @@ it: timeline_entry: fields: entry_date: Data + title: Titolo result_m: executed: Eseguito view: Visualizza diff --git a/decidim-accountability/config/locales/lb.yml b/decidim-accountability/config/locales/lb.yml index 37bddea6bf7c8..6457e11ae2d9e 100644 --- a/decidim-accountability/config/locales/lb.yml +++ b/decidim-accountability/config/locales/lb.yml @@ -182,7 +182,7 @@ lb: stats: attendees: Teilnehmer back_to_resource: Gehe zurück zum Ergebnis - comments: Bemerkungen + comments: Kommentarer contributions: Beiträge last_edited_by: Zuletzt bearbeitet von last_updated_at: Zuletzt aktualisiert am diff --git a/decidim-accountability/config/locales/lv.yml b/decidim-accountability/config/locales/lv.yml index cf45ffb071b4f..4cd36e46b73fc 100644 --- a/decidim-accountability/config/locales/lv.yml +++ b/decidim-accountability/config/locales/lv.yml @@ -165,7 +165,6 @@ lv: stats: attendees: Apmeklētāji back_to_resource: Atgriezties pie rezultātiem - comments: Komentāri contributions: Papildinājumi last_edited_by: Pēdējo reizi labojis last_updated_at: Pēdējo reizi atjaunināts plkst. diff --git a/decidim-accountability/config/locales/pt.yml b/decidim-accountability/config/locales/pt.yml index 4b8e0c1571eaa..f6cacd754a579 100644 --- a/decidim-accountability/config/locales/pt.yml +++ b/decidim-accountability/config/locales/pt.yml @@ -22,6 +22,7 @@ pt: timeline_entry: description: Descrição entry_date: Data + 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 diff --git a/decidim-accountability/config/locales/ru.yml b/decidim-accountability/config/locales/ru.yml index c75064b790696..78a64ae223c78 100644 --- a/decidim-accountability/config/locales/ru.yml +++ b/decidim-accountability/config/locales/ru.yml @@ -156,7 +156,6 @@ ru: stats: attendees: Участники back_to_resource: Вернуться к итогу - comments: Комментарии contributions: Внесенные предложения last_edited_by: Последний раз редактировалось last_updated_at: Последнее обновление diff --git a/decidim-accountability/config/locales/si-LK.yml b/decidim-accountability/config/locales/si-LK.yml index 620b1f12cb083..e3f6ee0fd32ed 100644 --- a/decidim-accountability/config/locales/si-LK.yml +++ b/decidim-accountability/config/locales/si-LK.yml @@ -61,4 +61,5 @@ si: results: show: stats: + comments: අදහස් meetings: රැස්වීම් diff --git a/decidim-accountability/config/locales/sk.yml b/decidim-accountability/config/locales/sk.yml index 49cd6ca2e75a0..ca4ce468b13d6 100644 --- a/decidim-accountability/config/locales/sk.yml +++ b/decidim-accountability/config/locales/sk.yml @@ -178,7 +178,6 @@ sk: stats: attendees: Účastníci back_to_resource: Naspať na výsledky - comments: Komentáre contributions: Príspevky last_edited_by: Naposledy editoval last_updated_at: Naposledy aktualizované diff --git a/decidim-accountability/config/locales/sr-CS.yml b/decidim-accountability/config/locales/sr-CS.yml index 1243ad749ed5a..ae5cd02cfb50d 100644 --- a/decidim-accountability/config/locales/sr-CS.yml +++ b/decidim-accountability/config/locales/sr-CS.yml @@ -154,7 +154,6 @@ sr: stats: attendees: Učesnici back_to_resource: Vrati se na rezultat - comments: Komentari contributions: Doprinosi last_edited_by: Poslednji put izmenjeno od strane last_updated_at: Poslеdnji put ažurirano diff --git a/decidim-accountability/config/locales/th-TH.yml b/decidim-accountability/config/locales/th-TH.yml index a4431912a8299..7b29b706083c7 100644 --- a/decidim-accountability/config/locales/th-TH.yml +++ b/decidim-accountability/config/locales/th-TH.yml @@ -1 +1,141 @@ +--- th: + activemodel: + attributes: + result: + decidim_accountability_status_id: สถานะ + decidim_category_id: หมวดหมู่ + decidim_scope_id: ขอบเขต + description: คำอธิบาย + end_date: วันสิ้นสุด + progress: ความคืบหน้า + project_ids: รวมโครงการ + proposals: รวมข้อเสนอ + start_date: วันที่เริ่มต้น + title: ชื่อ + updated_at: อัปเดตที่ + status: + description: คำอธิบาย + key: สำคัญ + name: ชื่อ + progress: ความคืบหน้า + timeline_entry: + description: คำอธิบาย + entry_date: วันที่ + title: ชื่อ + models: + decidim/accountability/proposal_linked_event: ข้อเสนอที่รวมอยู่ในผลลัพธ์ + decidim/accountability/result_progress_updated_event: อัปเดตความคืบหน้าของผลลัพธ์แล้ว + activerecord: + models: + decidim/accountability/result: + other: ผลลัพธ์ + decidim: + accountability: + actions: + attachment_collections: โฟลเดอร์ + attachments: ไฟล์แนบ + confirm_destroy: คุณแน่ใจหรือไม่ว่าต้องการลบ %{name} นี้ + destroy: ลบ + edit: แก้ไข + preview: ดูตัวอย่าง + timeline_entries: วิวัฒนาการของโครงการ + title: การดำเนินการ + admin: + exports: + result_comments: ความคิดเห็น + results: ผลลัพธ์ + import_results: + new: + download_export: ดาวน์โหลดการส่งออกด้วยรูปแบบ CSV + import: นำเข้า + models: + result: + name: ผลลัพธ์ + status: + name: สถานะ + results: + edit: + title: แก้ไขผลลัพธ์ + update: อัพเดทผลครับ + index: + title: ผลลัพธ์ + new: + create: สร้างผลลัพธ์ + title: ผลลัพธ์ใหม่ + shared: + subnav: + statuses: สถานะ + statuses: + edit: + title: แก้ไขสถานะ + update: อัพเดตสถานะ + index: + title: สถานะ + new: + create: Create status + title: สถานะใหม่ + results: + home: + categories_label: หมวดหมู่ + subcategories_label: หมวดหมู่ย่อย + home_header: + global_status: สถานะการดำเนินการทั่วโลก + nav_breadcrumb: + global: การดำเนินการระดับโลก + search: + search: ค้นหาการกระทำ + show: + stats: + back_to_resource: กลับไปหาผลลัพธ์ + comments: ความคิดเห็น + timeline: + title: วิวัฒนาการของโครงการ + admin: + filters: + results: + category_id_eq: + label: หมวดหมู่ + scope_id_eq: + label: ขอบเขต + status_id_eq: + label: สถานะ + components: + accountability: + actions: + comment: ความคิดเห็น + name: ความรับผิดชอบ + settings: + global: + comments_enabled: เปิดใช้งานความคิดเห็นแล้ว + comments_max_length: ความคิดเห็นความยาวสูงสุด (ปล่อยให้ 0 เป็นค่าเริ่มต้น) + display_progress_enabled: แสดงความคืบหน้า + intro: คำแนะนำ + scope_id: ขอบเขต + scopes_enabled: เปิดใช้งานขอบเขตแล้ว + step: + comments_blocked: ความคิดเห็นถูกบล็อก + events: + accountability: + proposal_linked: + email_intro: 'ข้อเสนอ "%{proposal_title}" ถูกรวมไว้ในผลลัพธ์แล้ว คุณสามารถดูได้จากหน้านี้:' + email_outro: คุณได้รับการแจ้งเตือนนี้เนื่องจากคุณกำลังติดตาม "%{proposal_title}" คุณสามารถหยุดรับการแจ้งเตือนได้ตามลิงก์ก่อนหน้า + email_subject: การอัปเดตเป็น %{proposal_title} + notification_title: ข้อเสนอ %{proposal_title} ถูกรวมไว้ในผลลัพธ์ %{resource_title} แล้ว + result_progress_updated: + email_intro: 'ผลลัพธ์ "%{resource_title}" ซึ่งรวมถึงข้อเสนอ "%{proposal_title}" ขณะนี้เสร็จสมบูรณ์แล้ว %{progress}% คุณสามารถดูได้จากหน้านี้:' + email_outro: คุณได้รับการแจ้งเตือนนี้เนื่องจากคุณกำลังติดตาม "%{proposal_title}" และข้อเสนอนี้รวมอยู่ในผลลัพธ์ "%{resource_title}" คุณสามารถหยุดรับการแจ้งเตือนได้ตามลิงก์ก่อนหน้า + email_subject: การอัปเดตความคืบหน้าของ %{resource_title} + notification_title: ผลลัพธ์ %{resource_title} ซึ่งรวมถึงข้อเสนอ %{proposal_title} อยู่ในขณะนี้ %{ ความคืบหน้า}% เสร็จสมบูรณ์ + metrics: + results: + description: จำนวนผลลัพธ์ที่สร้างขึ้น + object: ผลลัพธ์ + title: ผลลัพธ์ + resource_links: + included_projects: + result_project: โครงการที่รวมอยู่ในผลลัพธ์นี้ + included_proposals: + result_proposal: โครงการที่รวมอยู่ในผลลัพธ์นี้ + statistics: + results_count: ผลลัพธ์ diff --git a/decidim-accountability/config/locales/tr-TR.yml b/decidim-accountability/config/locales/tr-TR.yml index f623dbfc93814..57420b8385092 100644 --- a/decidim-accountability/config/locales/tr-TR.yml +++ b/decidim-accountability/config/locales/tr-TR.yml @@ -143,6 +143,14 @@ tr: create: "%{user_name} sonuç yaratmıştır %{resource_name} içinde %{space_name}" delete: "%{user_name} %{resource_name} sonuçtan %{space_name}sildi" update: "%{user_name} güncellenen sonuç %{resource_name} in %{space_name}" + status: + create: "48 / 5.000\nÇeviri sonuçları\nÇeviri sonucu\n%{user_name}, %{resource_name} kaydını oluşturdu" + delete: "%{user_name}, %{resource_name} kaydını sildi" + update: "%{user_name}, %{resource_name} kaydını Güncelledi" + timeline_entry: + create: "%{user_name}, %{resource_name} zaman çizelgesi girişini oluşturdu" + delete: "%{user_name}, %{resource_name} zaman çizelgesi girişini sildi" + update: "%{user_name}, %{resource_name} zaman çizelgesi girişini güncelledi" value_types: parent_presenter: not_found: 'Üst veritabanında bulunamadı (ID: %{id})' @@ -181,6 +189,7 @@ tr: timeline_entry: fields: entry_date: tarih + title: Başlık result_m: executed: Yürütüldü view: Görünüm @@ -225,6 +234,8 @@ tr: label: Durum components: accountability: + actions: + comment: Yorum name: Sorumluluk settings: global: @@ -265,3 +276,5 @@ tr: result_project: Bu sonuca dahil edilen projeler included_proposals: result_proposal: Bu sonuca dahil teklifler + statistics: + results_count: Sonuçlar diff --git a/decidim-accountability/config/locales/uk.yml b/decidim-accountability/config/locales/uk.yml index dd62dc26c6b0b..2b6aa8e566540 100644 --- a/decidim-accountability/config/locales/uk.yml +++ b/decidim-accountability/config/locales/uk.yml @@ -153,7 +153,6 @@ uk: stats: attendees: Учасники back_to_resource: Повернутися до підсумків - comments: Коментарів contributions: Внесені пропозиції last_edited_by: Останній раз редагувалося last_updated_at: Останній раз оновлювалося diff --git a/decidim-accountability/config/locales/zh-CN.yml b/decidim-accountability/config/locales/zh-CN.yml index f7e36b78d2292..f52e12373c273 100644 --- a/decidim-accountability/config/locales/zh-CN.yml +++ b/decidim-accountability/config/locales/zh-CN.yml @@ -165,7 +165,6 @@ zh-CN: stats: attendees: 参与者 back_to_resource: 返回结果 - comments: 评论 contributions: 二. 捐款 last_edited_by: 最后编辑者 last_updated_at: 最后更新于 diff --git a/decidim-accountability/lib/decidim/accountability/test/factories.rb b/decidim-accountability/lib/decidim/accountability/test/factories.rb index 3afc298e19fe6..5adb0642394ee 100644 --- a/decidim-accountability/lib/decidim/accountability/test/factories.rb +++ b/decidim-accountability/lib/decidim/accountability/test/factories.rb @@ -8,16 +8,19 @@ FactoryBot.define do factory :accountability_component, parent: :component do - name { Decidim::Components::Namer.new(participatory_space.organization.available_locales, :accountability).i18n_name } + transient do + skip_injection { false } + end + name { generate_component_name(participatory_space.organization.available_locales, :accountability, skip_injection: skip_injection) } manifest_name { :accountability } - participatory_space { create(:participatory_process, :with_steps, organization: organization) } + participatory_space { create(:participatory_process, :with_steps, organization: organization, skip_injection: skip_injection) } settings do { - intro: Decidim::Faker::Localized.wrapped("

", "

") { generate_localized_title }, - categories_label: Decidim::Faker::Localized.word, - subcategories_label: Decidim::Faker::Localized.word, - heading_parent_level_results: Decidim::Faker::Localized.word, - heading_leaf_level_results: Decidim::Faker::Localized.word, + intro: generate_localized_description(:accountability_component_intro, skip_injection: skip_injection), + categories_label: generate_localized_word(:accountability_component_categories_label, skip_injection: skip_injection), + subcategories_label: generate_localized_word(:accountability_component_subcategories_label, skip_injection: skip_injection), + heading_parent_level_results: generate_localized_word(:accountability_component_heading_parent_level_results, skip_injection: skip_injection), + heading_leaf_level_results: generate_localized_word(:accountability_component_heading_leaf_level_results, skip_injection: skip_injection), scopes_enabled: true, scope_id: participatory_space.scope&.id } @@ -25,27 +28,36 @@ end factory :status, class: "Decidim::Accountability::Status" do - component { create(:accountability_component) } + transient do + skip_injection { false } + end + component { create(:accountability_component, skip_injection: skip_injection) } sequence(:key) { |n| "status_#{n}" } - name { Decidim::Faker::Localized.word } - description { generate_localized_title } + name { generate_localized_word(:status_name, skip_injection: skip_injection) } + description { generate_localized_word(:status_description, skip_injection: skip_injection) } progress { rand(1..100) } end factory :result, class: "Decidim::Accountability::Result" do - component { create(:accountability_component) } - title { generate_localized_title } - description { Decidim::Faker::Localized.wrapped("

", "

") { generate_localized_title } } + transient do + skip_injection { false } + end + component { create(:accountability_component, skip_injection: skip_injection) } + title { generate_localized_title(:result_title, skip_injection: skip_injection) } + description { generate_localized_description(:result_description, skip_injection: skip_injection) } start_date { "12/7/2017" } end_date { "30/9/2017" } - status { create :status, component: component } + status { create :status, component: component, skip_injection: skip_injection } progress { rand(1..100) } end factory :timeline_entry, class: "Decidim::Accountability::TimelineEntry" do - result { create(:result) } + transient do + skip_injection { false } + end + result { create(:result, skip_injection: skip_injection) } entry_date { "12/7/2017" } - title { generate_localized_title } - description { generate_localized_title } + title { generate_localized_title(:timeline_entry_title, skip_injection: skip_injection) } + description { generate_localized_title(:timeline_entry_description, skip_injection: skip_injection) } end end diff --git a/decidim-accountability/lib/decidim/accountability/version.rb b/decidim-accountability/lib/decidim/accountability/version.rb index b864c7197ff39..c8ace659d9016 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.27.5" + "0.27.6" end end end diff --git a/decidim-accountability/lib/decidim/api/result_type.rb b/decidim-accountability/lib/decidim/api/result_type.rb index 5e5fe5b8983f4..4ca5ed8043e9a 100644 --- a/decidim-accountability/lib/decidim/api/result_type.rb +++ b/decidim-accountability/lib/decidim/api/result_type.rb @@ -3,7 +3,6 @@ module Decidim module Accountability class ResultType < Decidim::Api::Types::BaseObject - implements Decidim::Core::ComponentInterface implements Decidim::Core::CategorizableInterface implements Decidim::Comments::CommentableInterface implements Decidim::Core::ScopableInterface diff --git a/decidim-accountability/spec/events/decidim/accountability/proposal_linked_event_spec.rb b/decidim-accountability/spec/events/decidim/accountability/proposal_linked_event_spec.rb index 636bd3bc8ab18..3c6442d75b0ac 100644 --- a/decidim-accountability/spec/events/decidim/accountability/proposal_linked_event_spec.rb +++ b/decidim-accountability/spec/events/decidim/accountability/proposal_linked_event_spec.rb @@ -6,14 +6,14 @@ include_context "when a simple event" let(:event_name) { "decidim.events.accountability.proposal_linked" } - let(:resource) { create(:result) } + let(:resource) { create(:result, title: generate_localized_title(:result_title)) } let(:proposal_component) do create(:component, manifest_name: "proposals", participatory_space: resource.component.participatory_space) end - let(:proposal) { create :proposal, component: proposal_component, title: { en: "My super proposal" } } + let(:proposal) { create :proposal, component: proposal_component } let(:extra) { { proposal_id: proposal.id } } let(:proposal_path) { resource_locator(proposal).path } - let(:proposal_title) { translated(proposal.title) } + let(:proposal_title) { decidim_sanitize_translated(proposal.title) } let(:notification_title) { "The proposal #{proposal_title} has been included in the #{resource_title} result." } let(:email_subject) { "An update to #{proposal_title}" } let(:email_outro) { "You have received this notification because you are following \"#{proposal_title}\". You can stop receiving notifications following the previous link." } @@ -48,18 +48,21 @@ describe "email_subject" do it "is generated correctly" do expect(subject.email_subject).not_to include(proposal.title.to_s) + expect(subject.email_subject).to include(proposal_title) end end describe "email_outro" do it "is generated correctly" do expect(subject.email_outro).not_to include(proposal.title.to_s) + expect(subject.email_outro).to include(proposal_title) end end describe "email_intro" do it "is generated correctly" do expect(subject.email_intro).not_to include(proposal.title.to_s) + expect(subject.email_intro).to include(proposal_title) end end diff --git a/decidim-accountability/spec/events/decidim/accountability/result_progress_updated_event_spec.rb b/decidim-accountability/spec/events/decidim/accountability/result_progress_updated_event_spec.rb index 70bc82f3e5a1b..ad3ce8a1bc502 100644 --- a/decidim-accountability/spec/events/decidim/accountability/result_progress_updated_event_spec.rb +++ b/decidim-accountability/spec/events/decidim/accountability/result_progress_updated_event_spec.rb @@ -6,18 +6,18 @@ include_context "when a simple event" let(:event_name) { "decidim.events.accountability.result_progress_updated" } - let(:resource) { create(:result) } + let(:resource) { create(:result, title: generate_localized_title(:result_title)) } let(:proposal_component) do create(:component, manifest_name: "proposals", participatory_space: resource.component.participatory_space) end - let(:proposal) { create :proposal, component: proposal_component, title: { en: "My super proposal" } } + let(:proposal) { create :proposal, component: proposal_component } let(:extra) { { proposal_id: proposal.id, progress: 95 } } let(:proposal_path) { resource_locator(proposal).path } - let(:proposal_title) { translated(proposal.title) } - let(:email_subject) { "An update to #{translated resource.title} progress" } + let(:proposal_title) { decidim_sanitize_translated(proposal.title) } + let(:email_subject) { "An update to #{resource_title} progress" } let(:notification_title) { "The result #{resource_title}, which includes the proposal #{proposal_title}, is now 95% complete." } - let(:email_outro) { "You have received this notification because you are following \"#{proposal_title}\", and this proposal is included in the result \"#{translated resource.title}\". You can stop receiving notifications following the previous link." } - let(:email_intro) { "The result \"#{translated resource.title}\", which includes the proposal \"#{proposal_title}\", is now 95% complete. You can see it from this page:" } + let(:email_outro) { "You have received this notification because you are following \"#{proposal_title}\", and this proposal is included in the result \"#{resource_title}\". You can stop receiving notifications following the previous link." } + let(:email_intro) { "The result \"#{resource_title}\", which includes the proposal \"#{proposal_title}\", is now 95% complete. You can see it from this page:" } before do resource.link_resources([proposal], "included_proposals") @@ -48,12 +48,14 @@ describe "email_outro" do it "is generated correctly" do expect(subject.email_outro).not_to include(proposal.title.to_s) + expect(subject.email_outro).to include(proposal_title) end end describe "email_intro" do it "is generated correctly" do expect(subject.email_intro).not_to include(proposal.title.to_s) + expect(subject.email_intro).to include(proposal_title) end end diff --git a/decidim-accountability/spec/system/explore_results_spec.rb b/decidim-accountability/spec/system/explore_results_spec.rb index 193a41ca4ed83..8901f773afebb 100644 --- a/decidim-accountability/spec/system/explore_results_spec.rb +++ b/decidim-accountability/spec/system/explore_results_spec.rb @@ -175,7 +175,7 @@ it "shows all result info" do expect(page).to have_i18n_content(result.title) - expect(page).to have_i18n_content(result.description) + expect(page).to have_i18n_content(result.description, strip_tags: true) expect(page).to have_content(result.reference) expect(page).to have_content("#{result.progress.to_i}%") end @@ -321,7 +321,7 @@ it "shows related meetings" do meetings.each do |meeting| expect(page).to have_i18n_content(meeting.title) - expect(page).to have_i18n_content(meeting.description) + expect(page).to have_content(i18n_content(meeting.description, strip_tags: true).strip) end end diff --git a/decidim-accountability/spec/types/integration_schema_spec.rb b/decidim-accountability/spec/types/integration_schema_spec.rb index eb3bb95a8947e..4dff053b070b2 100644 --- a/decidim-accountability/spec/types/integration_schema_spec.rb +++ b/decidim-accountability/spec/types/integration_schema_spec.rb @@ -32,7 +32,6 @@ "hasComments" => result.comment_threads.size.positive?, "id" => result.id.to_s, "parent" => result.parent, - "participatorySpace" => { "id" => result.participatory_space.id.to_s }, "progress" => result.progress.to_f, "reference" => result.reference, "scope" => result.scope, @@ -71,7 +70,7 @@ { "__typename" => "Accountability", "id" => current_component.id.to_s, - "name" => { "translation" => "Accountability" }, + "name" => { "translation" => translated(current_component.name) }, "results" => { "edges" => [ { @@ -123,9 +122,6 @@ parent { id } - participatorySpace { - id - } progress reference scope { @@ -232,9 +228,6 @@ parent { id } - participatorySpace { - id - } progress reference scope { diff --git a/decidim-admin/app/commands/decidim/admin/destroy_category.rb b/decidim-admin/app/commands/decidim/admin/destroy_category.rb index f5c198fa19a36..7fff9db526985 100644 --- a/decidim-admin/app/commands/decidim/admin/destroy_category.rb +++ b/decidim-admin/app/commands/decidim/admin/destroy_category.rb @@ -20,7 +20,7 @@ def initialize(category, user) # # Returns nothing. def call - return broadcast(:invalid) if category.nil? || category.subcategories.any? + return broadcast(:invalid) if category.nil? || category.subcategories.any? || !category.unused? destroy_category broadcast(:ok) diff --git a/decidim-admin/app/controllers/decidim/admin/impersonations_controller.rb b/decidim-admin/app/controllers/decidim/admin/impersonations_controller.rb index edb9948ea5dda..c05d7cd262d7d 100644 --- a/decidim-admin/app/controllers/decidim/admin/impersonations_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/impersonations_controller.rb @@ -82,6 +82,7 @@ def existing_managed_user return nil unless handler.unique_id existing_authorization = Authorization.find_by( + user: User.where(organization: current_organization), name: handler_name, unique_id: handler.unique_id ) diff --git a/decidim-admin/app/controllers/decidim/admin/organization_controller.rb b/decidim-admin/app/controllers/decidim/admin/organization_controller.rb index b5d566b68c723..890023587e863 100644 --- a/decidim-admin/app/controllers/decidim/admin/organization_controller.rb +++ b/decidim-admin/app/controllers/decidim/admin/organization_controller.rb @@ -44,13 +44,16 @@ def search(relation) respond_to do |format| format.json do if (term = params[:term].to_s).present? - query = relation.order(name: :asc) query = if term.start_with?("@") - query.where("nickname ILIKE ?", "#{term.delete("@")}%") + nickname = term.delete("@") + relation.where("nickname ILIKE ?", "#{nickname}%") + .order(Arel.sql(ActiveRecord::Base.sanitize_sql_array("similarity(nickname, '#{nickname}') DESC"))) else - query.where("name ILIKE ?", "%#{term}%").or( - query.where("email ILIKE ?", "%#{term}%") + relation.where("name ILIKE ?", "%#{term}%").or( + relation.where("email ILIKE ?", "%#{term}%") ) + .order(Arel.sql(ActiveRecord::Base.sanitize_sql_array("GREATEST(similarity(name, '#{term}'), similarity(email, '#{term}')) DESC"))) + .order(Arel.sql(ActiveRecord::Base.sanitize_sql_array("(similarity(name, '#{term}') + similarity(email, '#{term}')) / 2 DESC"))) end render json: query.all.collect { |u| { value: u.id, label: "#{u.name} (@#{u.nickname})" } } else diff --git a/decidim-admin/app/events/decidim/resource_hidden_event.rb b/decidim-admin/app/events/decidim/resource_hidden_event.rb index 63a22ad1d6d1c..01260ea9d53fc 100644 --- a/decidim-admin/app/events/decidim/resource_hidden_event.rb +++ b/decidim-admin/app/events/decidim/resource_hidden_event.rb @@ -2,6 +2,8 @@ module Decidim class ResourceHiddenEvent < Decidim::Events::SimpleEvent + include Decidim::ApplicationHelper + i18n_attributes :resource_path, :report_reasons, :resource_type, :resource_content def resource_path @@ -23,7 +25,9 @@ def resource_title end def resource_content - translated_attribute(@resource[@resource.reported_attributes.first]).truncate(100, separator: " ") + text = translated_attribute(@resource[@resource.reported_attributes.first]) + + decidim_sanitize(html_truncate(text, length: 100), strip_tags: true) end def resource_text diff --git a/decidim-admin/app/helpers/decidim/admin/newsletters_helper.rb b/decidim-admin/app/helpers/decidim/admin/newsletters_helper.rb index 0c78d2150aceb..195da0af2bbd4 100644 --- a/decidim-admin/app/helpers/decidim/admin/newsletters_helper.rb +++ b/decidim-admin/app/helpers/decidim/admin/newsletters_helper.rb @@ -74,7 +74,7 @@ def sent_to_spaces(newsletter) else Decidim.find_participatory_space_manifest(type["manifest_name"].to_sym) .participatory_spaces.call(current_organization).where(id: type["ids"]).each do |space| - html += "#{translated_attribute space.title}" + html += "#{decidim_escape_translated space.title}" end end html += "
" diff --git a/decidim-admin/app/mailers/decidim/admin/application_mailer.rb b/decidim-admin/app/mailers/decidim/admin/application_mailer.rb deleted file mode 100644 index 0d1127bd9ccf8..0000000000000 --- a/decidim-admin/app/mailers/decidim/admin/application_mailer.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -module Decidim - module Admin - # Custom application mailer, scoped to the admin mailer. - # - class ApplicationMailer < ActionMailer::Base - default from: Decidim.config.mailer_sender - layout "mailer" - end - end -end diff --git a/decidim-admin/app/views/decidim/admin/categories/index.html.erb b/decidim-admin/app/views/decidim/admin/categories/index.html.erb index 6610948383fc0..44b2d0b6b6fd5 100644 --- a/decidim-admin/app/views/decidim/admin/categories/index.html.erb +++ b/decidim-admin/app/views/decidim/admin/categories/index.html.erb @@ -52,7 +52,13 @@ <% end %> <% if allowed_to? :destroy, :category, category: subcategory %> - <%= icon_link_to "circle-x", category_path(current_participatory_space, subcategory), t("actions.destroy", scope: "decidim.admin"), class: "action-icon--remove", method: :delete, data: { confirm: t("actions.confirm_destroy", scope: "decidim.admin") } %> + <% if subcategory.unused? %> + <%= icon_link_to "circle-x", category_path(current_participatory_space, subcategory), t("actions.destroy", scope: "decidim.admin"), class: "action-icon--remove", method: :delete, data: { confirm: t("actions.confirm_destroy", scope: "decidim.admin") } %> + <% else %> + " data-tooltip="true" data-disable-hover="false"> + <%= icon "delete-bin-line", class: "action-icon action-icon--disabled", role: "img", "aria-hidden": true %> + + <% end %> <% end %> diff --git a/decidim-admin/app/views/decidim/admin/resource_permissions/edit.html.erb b/decidim-admin/app/views/decidim/admin/resource_permissions/edit.html.erb index e519e86152201..40053a15f6900 100644 --- a/decidim-admin/app/views/decidim/admin/resource_permissions/edit.html.erb +++ b/decidim-admin/app/views/decidim/admin/resource_permissions/edit.html.erb @@ -6,9 +6,9 @@ <% if resource %> - <% if resource.is_a?(Decidim::Resourceable) %> - <%= link_to(resource_title(resource), resource_locator(resource).path) %> + <%= link_to(decidim_escape_translated(resource.title).html_safe, resource_locator(resource).path) %> <% else %> - <%= strip_tags resource_title(resource) %> + <%= decidim_escape_translated(resource.title).html_safe %> <% end %> <% end %> diff --git a/decidim-admin/app/views/layouts/decidim/admin/_js_configuration.html.erb b/decidim-admin/app/views/layouts/decidim/admin/_js_configuration.html.erb index 96892c18cbcd3..b28a3ab69612d 100644 --- a/decidim-admin/app/views/layouts/decidim/admin/_js_configuration.html.erb +++ b/decidim-admin/app/views/layouts/decidim/admin/_js_configuration.html.erb @@ -1,5 +1,6 @@ <% js_configs = { + api_path: decidim_api.root_path(locale: nil), icons_path: Decidim.cors_enabled ? "" : asset_pack_path("media/images/icons.svg"), messages: { "selfxssWarning": { diff --git a/decidim-admin/config/locales/bg.yml b/decidim-admin/config/locales/bg.yml index ee079e7f33e6f..66150ae7f432c 100644 --- a/decidim-admin/config/locales/bg.yml +++ b/decidim-admin/config/locales/bg.yml @@ -15,22 +15,34 @@ bg: 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: Създаване на импорта като newsletter: body: Тяло subject: Тема organization: + admin_terms_of_use_body: Съдържание на административните условия за ползване alert_color: Аларма + available_authorizations: Активни оторизации badges_enabled: Включи значките comments_max_length: Максимална дължина на коментарите (Оставете 0 за стойност по подразбиране) cta_button_path: Път на бутона "призив към действие" @@ -39,8 +51,12 @@ bg: default_locale: Език по подразбиране description: Описание enable_omnipresent_banner: Показвай всепоказван банер + enable_participatory_space_filters: Активиране на филтри за пространство за участие facebook_handler: Манипулатор на Facebook favicon: Икона + force_authentication: Принудително оторизиране + force_users_to_authenticate_before_access_organization: Принуждавайте потребителите да се оторизират, преди достъп до организацията + from: Адрес на е-поща на изпращача github_handler: Манипулатор на GitHub header_snippets: Части на HTML заглавката highlight_alternative_color: Подчертаване, алтернативен @@ -52,6 +68,7 @@ bg: highlighted_content_banner_image: Изображение highlighted_content_banner_short_description: Кратко описание highlighted_content_banner_title: Заглавие + host: Хост instagram_handler: Манипулатор на Instagram logo: Лого machine_translation_display_priority: Приоритет за показване на машинен превод @@ -64,19 +81,28 @@ bg: omnipresent_banner_short_description: Кратко описание omnipresent_banner_title: Заглавие omnipresent_banner_url: URL адрес + organization_admin_email: Имейл на администратора на организацията + organization_admin_name: Име на администратора на организацията + organization_locales: Местоположение на организацията primary_color: Основен reference_prefix: Префикс на препратка rich_text_editor_in_public_views: Разреши редактора на rich text за участниците secondary_color: Вторичен + secondary_hosts: Вторични хостове send_welcome_notification: Изпращай приветствия success_color: Успешно time_zone: Часова зона tos_version: Версия на условия за ползване + twitter_handler: X манипулатор user_groups_enabled: Разреши групи + users_registration_mode: Режим на регистрация на потребители warning_color: Предупреждение welcome_notification_body: Тяло на приветствието welcome_notification_subject: Тема на приветствието youtube_handler: Манипулатор на YouTube + participatory_space_private_user: + email: Имейл + name: Име scope: code: Код name: Име @@ -88,39 +114,790 @@ bg: name: Име organization: Организация plural: Множествено число + settings: + scope_id: Обхват static_page: + allow_public_access: Разрешаване на достъп без оторизация changed_notably: Настъпиха значителни промени. content: Съдържание organization: Организация show_in_footer: Покажи в долния колонтитул slug: Съкратен URL title: Заглавие + topic_id: Тема + weight: Нареди позиция static_page_topic: description: Описание show_in_footer: Покажи в долния колонтитул title: Заглавие + weight: Нареди позиция user_group_csv_verification: file: Файл errors: models: + newsletter: + attributes: + base: + at_least_one_space: Изберете поне едно място за участие organization: attributes: official_img_footer: 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: + invalid_file: Предоставен е невалиден файл, моля, проверете дали файлът е правилно форматиран + invalid_mime_type: Невалиден мим формат activerecord: attributes: decidim/static_page: content: Съдържание slug: Съкратен URL title: Заглавие + doorkeeper/application: + authorize_url: Оторизиране на URL адрес + client_id: ID на клиента + client_secret: Клиентска тайна + organization_name: Наименование на организацията + organization_url: URL адрес на организацията + redirect_uri: Пренасочващ URL адрес + site: Уебсайт decidim: admin: + actions: + add: Добавяне + attachment: + new: Нов прикачен файл + attachment_collection: + new: Нова колекция от прикачени файлове + browse: Разглеждане + category: + new: Нова категория + export: Експорт на всички + export-selection: Експорт на селекцията + import: Импортиране + manage: Управление + new: Ново %{name} + newsletter: + new: Нов бюлетин + participatory_space_private_user: + new: Нов частен потребител на пространство за участие + per_page: За страница + permissions: Разрешения + reject: Откажи + share: Сподели + user: + new: Нов администратор + verify: Провери + admin_terms_of_use: + accept: + error: Възникна грешка при приемането на административните условия за ползване. + success: Чудесно! Приехте административните условия за ползване. + actions: + accept: Приемам условията + are_you_sure: Сигурни ли сте, че искате да откажете административните условия за ползване? + refuse: Отхвърляне на административните условия + title: Съгласявам се с правилата и условията за ползване + required_review: + alert: 'Задължително: Прегледайте административните условия за ползване' + callout: Моля, отделете малко време, за да прегледате административните условия за ползване. В противен случай няма да можете да администрирате платформата. + cta: Прегледайте ги сега. + title: Административни условия за ползване + area_types: + create: + error: Възникна проблем при създаването на нов тип област. + success: Типът област е създаден успешно. + destroy: + success: Типът област е премахнат успешно + edit: + title: Редактиране на типа област + update: Актуализация + new: + create: Създаване на тип област + title: Нов тип област + update: + error: Възникна проблем при актуализирането на този тип област. + success: Типът област е актуализиран успешно + areas: + create: + error: Възникна проблем при създаването на нова област. + success: Областта е създадена успешно. + destroy: + has_spaces: Тази зона има зависими пространства. Моля, уверете се, че нито едно пространство за участие не споменава тази област, преди да я изтриете. + success: Областта е премахната успешно + edit: + title: Редактиране на областта + update: Актуализация + new: + create: Създаване на област + title: Нова област + no_areas: Няма области + update: + error: Възникна проблем при актуализирането на тази област. + success: Областта е актуализирана успешно + attachment_collections: + create: + error: Възникна проблем при създаването на нова папка. + success: Папката е създадена успешно. + destroy: + success: Папката е премахната успешно. + edit: + title: Редактиране на папка + update: Актуализация + index: + attachment_collection_used: Тази папка не може да бъде премахната, защото се използва. + attachment_collections_title: Папки с прикачени файлове + new: + create: Създаване + title: Нова папка + update: + error: Възникна проблем при актуализирането на тази папка. + success: Папката беше актуализирана успешно. + attachments: + create: + error: Възникна проблем при създаването на нов прикачен файл. + success: Прикаченият файл беше създаден успешно. + destroy: + success: Прикаченият файл беше премахнат успешно. + edit: + title: Редактиране на прикачения файл + update: Актуализация + index: + attachments_title: Прикачени файлове + new: + create: Създаване на прикачен файл + title: Нов прикачен файл + update: + error: Възникна проблем при актуализирането на този прикачен файл. + success: Прикаченият файл беше актуализиран успешно. + attachments_privacy_warning: + message: Бъдете внимателни, когато работите с прикачени файлове в лично пространство. Всеки участник може да сподели този документ с други. + autocomplete: + no_results: Няма намерени резултати + search_prompt: Въведете поне три символа, за да търсите + block_user: + new: + action: Блокирайте акаунта и изпратете обосновка + description: Блокирането на потребител ще направи акаунта му неизползваем. Можете да предоставите във вашата обосновка всякакви насоки относно начините, по които бихте обмислили деблокирането на потребителя. + justification: Обосновка + title: Блокиране на потребител %{name} + categories: + create: + error: Възникна проблем при създаването на тази категория. + success: Категорията беше създадена успешно. + destroy: + error: Възникна проблем при изтриването на тази категория. Моля, първо изтрийте всички подкатегории, уверете се, че към тази категория не принадлежат други елементи, след което опитайте отново. + success: Категорията беше изтрита успешно. + edit: + title: Редактиране на категория + update: Актуализация + index: + categories_title: Категории + category_used: Тази категория не може да бъде премахната, защото се използва. + new: + create: Създаване на категория + title: Нова категория + update: + error: Възникна проблем при актуализирането на тази категория. + success: Категорията е обновена. + component_permissions: + update: + error: Възникна проблем при актуализирането на разрешенията на този компонент. + success: Разрешенията бяха актуализирани успешно. + components: + create: + error: Възникна проблем при създаването на този компонент. + success: Компонентът беше създаден успешно. + destroy: + error: Възникна проблем при премахването на този компонент. + success: Компонентът беше изтрит успешно. + edit: + title: Редактиране на компонента + update: Актуализация + form: + default_step_settings: Настройки на стъпките по подразбиране + global_settings: Глобални настройки + step_settings: Настройки на стъпките + index: + add: Добавяне на компонент + headers: + actions: Активности + name: Име на компонент + scope: Обхват на компонента + type: Тип на компонента + new: + add: Добавяне на компонент + title: 'Добавяне на компонент: %{name}' + publish: + success: Компонентът беше публикуван успешно. + conflicts: + transfer: + error: Възникна проблем при прехвърлянето на текущия участник към управляван участник. + dashboard: + show: + welcome: Добре дошли в Административния панел. + domain_whitelist: + update: + error: Неуспешно актуализиране на белия списък на домейни + success: Белият списък на домейни е актуализиран успешно + exports: + notice: Заявеното от Вас експортиране е в процес. Ще получите имейл, когато приключи. + filters: + moderated_users: + reports_reason_eq: + values: + does_not_belong: Не принадлежи + offensive: Обидно + spam: Спам + moderations: + reportable_type_string_eq: + label: Тип + officialized_at_null: + label: Състояние + values: + 'false': Официализирано + 'true': Неофициализирано + participatory_space_private_users: + user_invitation_accepted_at_not_null: + label: Поканата е приета + values: + 'false': Не се приема + 'true': Прието + user_invitation_sent_at_not_null: + label: Поканата е изпратена + values: + 'false': Не е изпратено + 'true': Изпратено + private_space_eq: + label: Частни + values: + 'false': Публични + 'true': Частни + published_at_null: + label: Публикувано + values: + 'false': Публикувано + 'true': Непубликувано + scope_id_eq: + label: Обхват + search_label: Търсене + search_placeholder: + name_or_nickname_or_email_cont: Търсене на %{collection} по имейл, име или псевдоним. + report_count_eq: Отчитане на броя + reported_id_string_or_reported_content_cont: Търсете в %{collection} по ID или съдържание, което може да бъде отчетено. + title_cont: Търсене на %{collection} по заглавие. + user_name_or_user_email_cont: Търси в %{collection} по име или имейл. + user_name_or_user_nickname_or_user_email_cont: Търсене на %{collection} по имейл, име или псевдоним. + state_eq: + label: Състояние + values: + all: Всички + pending: Изчакване + rejected: Отхвърлен + verified: Проверен + forms: + file_help: + import: + explanation: 'Указания за файла:' + message_1: Поддържат се CSV, JSON и Excel (.xlsx) файлове + message_2: За CSV файлове разделителят между колоните трябва да е точка и запетая (";") + help_sections: + error: Възникна проблем при актуализирането на помощните раздели + form: + save: Запази + success: Помощните раздели бяха актуализирани успешно + impersonatable_users: + index: + filter: + all: Всички + managed: Управляван(и) + not_managed: Неуправляван(и) + filter_by: Филтрирай по + impersonate: Имитирай + impersonate_new_managed_user: Управление на нов участник + managed: Управляван(и) + name: Име + needs_authorization_warning: Нуждатете се от поне една активирана оторизация за тази организация. + not_managed: Неуправляван(и) + promote: Промотиране + search: Търсене + status: Статус + view_logs: Преглед на регистрите + impersonations: + close_session: + error: Възникна проблем при затварянето на текущата сесия за управление на участника. + success: Текущата сесия за имитиране на потребител беше прекратена успешно. + create: + error: Възникна проблем при управлението на участника. + success: Управляваният участник беше създаден успешно. + form: + authorization_method: Метод на оторизация + name: Име + reason: Причина + new: + impersonate: Имитирай + impersonate_existing_managed_user: Управление на участник „%{name}“ + impersonate_existing_user: Управление на участник „%{name}“ + impersonate_new_managed_user: Управление на нов участник + imports: + and: и + data_errors: + duplicate_headers: + detail: Моля, проверете дали файлът съдържа необходимите колони или заглавки само веднъж. + message: + one: Дублирана колона %{columns}. + other: Дублирани колони %{columns}. + invalid_indexes: + lines: + detail: Моля, проверете дали тези редове са форматирани правилно и съдържат валидни записи. + message: + one: Открих грешка във файла за импортиране на ред %{indexes}. + other: Открити са грешки във файла за импортиране на редове %{indexes}. + records: + detail: Моля, проверете дали тези записи са форматирани правилно и съдържат валидни записи. + message: + one: Намерена е грешка във файла за импортиране на записи с поредни номера %{indexes}. + other: Открити са грешки във файла за импортиране за записи с поредни номера %{indexes}. + missing_headers: + detail: Моля, проверете дали файлът съдържа необходимите колони. + message: + one: Липсваща колона %{columns}. + other: Липсващи колони %{columns}. + error: Възникна проблем по време на импортирането + example_error: Не можа да се създаде пример за дадения тип + new: + accepted_mime_types: + csv: CSV + json: JSON + xlsx: Excel (.xlsx) + actions: + back: Назад + download_example: Изтегляне на пример + download_example_format: Пример като %{name} + file_legend: Добавете файл за импортиране, който ще бъде анализиран. + import: Импортиране + notice: "%{count} %{resource_name} успешно импортирани" + logs: + logs_list: + no_logs_yet: Все още няма регистри + managed_users: + promotion: + error: Възникна проблем при повишаването на управлявания участник. + success: Управляваният участник беше повишен успешно. + promotions: + new: + explanation: Управляваните участници могат да бъдат повишавани до стандартни участници. Това означава, че ще бъдат поканени в приложението и повече няма да можете да ги управлявате. Поканеният участник ще получи имейл, за да приеме поканата Ви. + new_managed_user_promotion: Ново повишение на управляван участник + promote: Повишаване + menu: + admin_log: Регистър на дейността на администраторите + admins: Администратори + appearance: Външен вид + area_types: Типове области + areas: Области + configuration: Конфигурация + external_domain_whitelist: Лист с позволени външни домейни + help_sections: Помощни раздели + homepage: Начална страница + impersonations: Имитация + moderation: Глобални модерации + newsletters: Бюлетин с новости + participants: Участници + reported_users: Докладвани потребители + scope_types: Типове на обхвата + scopes: Обхвати + settings: Настройки + static_pages: Страници + user_groups: Групи + users: Участници + metrics: + metrics: + see_more_metrics: Показване на повече индикатори + models: + area: + fields: + area_type: Тип район + name: Име + area_type: + fields: + name: Име + plural: Множествено число + attachment: + fields: + collection: Папка + content_type: Тип + file_size: Размер + title: Заглавие + name: Прикачен файл + attachment_collection: + name: Папка + category: + name: Категория + impersonation_log: + fields: + admin: Администратор + ended_at: Приключило на + expired_at: Изтекло на + reason: Причина + started_at: Започнало в + user: Участник + newsletter: + fields: + created_at: Създадено на + progress: Прогрес + sent_at: Изпратено в + sent_to: Изпратено до + subject: Относно + name: Бюлетин + participatory_space_private_user: + name: Пространство за участие на частен участник + scope: + fields: + name: Име + scope_type: Тип на обхвата + scope_type: + fields: + name: Име + plural: Множествено число + share_token: + fields: + created_at: Създадено на + expires_at: Изтича на + last_used_at: Последно използвано + times_used: Брой използвания + token: Токен + user: Създадено от + static_page: + fields: + created_at: Създадено на + title: Заглавие + user: + fields: + created_at: Дата на създаване + last_sign_in_at: Дата на последно влизане + newsletter_templates: + show: + use_template: Използване на този шаблон + newsletters: + create: + error: Възникна проблем при създаването на този бюлетин. + success: Бюлетинът беше създаден успешно. Моля, прегледайте го, преди да го изпратите. + deliver: + error: Възникна проблем при доставянето на този бюлетин. + success: Бюлетинът беше доставен успешно. + destroy: + error_already_sent: 'Бюлетинът не може да се премахне: Вече е изпратен.' + success: Бюлетинът беше премахнат успешно. + edit: + save_and_preview: Запази и прегледай + title: Редактирай бюлетин + index: + all: всички + all_users: 'Всички потребители ' + and: 'и ' + confirm_delete: Наистина ли искате да изтриете този бюлетин? + followers: 'последователи ' + has_been_sent_to: 'Беше изпратено до: ' + no_scopes: Няма обхвати + not_sent: Не е изпратено + participants: 'участници ' + segmented_to: 'Сегментирано за %{subject}: ' + subscribed_count: 'Абонирани:' + title: Бюлетини + new: + save: Запази + title: Нов бюлетин + select_recipients_to_deliver: + all_spaces: Всички + all_users_help: Изпраща бюлетина на всички потвърдени потребители. + confirm_deliver: Наистина ли искате да доставите този бюлетин? Това действие не може да бъде отменено. + deliver: Доставяне на бюлетина + followers_help: Изпраща бюлетина до всички потвърдени потребители, които следят някое от избраните пространства за участие в списъка. + none: Няма + participants_help: Изпраща бюлетина до всички потвърдени потребители, които са участвали в някое от избраните пространства за участие в списъка. + recipients_count: Този бюлетин ще бъде изпратен на %{count} потребители. + scopes_help: Изпраща бюлетина на потребителите, които са активирали някой от избраните обхвати в настройките за „Моите интереси“ в профила си. + select_scopes: Филтрирайте по потребители, които са активирали някой от изброените обхвати в настройките за „Моите интереси“ в профила си. + select_spaces: Изберете пространства, за да сегментирате бюлетина + select_users: Изберете до кои потребители искате да изпратите бюлетина + send_to_all_users: Изпращане до всички потребители + send_to_followers: Изпращане до последователите + send_to_participants: Изпращане до участниците + title: Изберете получатели, на които да бъде изпратено + warning: "Внимание: Този бюлетин ще бъде изпратен само на потребители, които са включили Искам да получавам бюлетини в настройките си за известия." + send: + no_recipients: Няма получатели за тази селекция + show: + preview: Преглед + select_recipients_to_deliver: Изберете получатели, на които да бъде доставено + subject: Относно + update: + error: Възникна проблем при актуализирането на този бюлетин. + success: Бюлетинът беше актуализиран успешно. Моля, прегледайте го, преди да го изпратите. + officializations: + block: + error: Възникна грешка при блокиране на участника + success: Участникът беше блокиран успешно + create: + success: Участникът е официализиран успешно + destroy: + success: Официализирането на участника е премахнато успешно + index: + actions: Активности + badge: Бадж + block: Блокиране на потребител + created_at: Създадено на + name: Име + nickname: Псевдоним + not_officialized: Неофициализирано + officialize: Официализиране + officialized: Официализирано + reofficialize: Повторно официализиране + reports: Доклади + show_email: Показване на електронната поща + status: Статус + unblock: Разблокирай Потребител + unofficialize: Премахване на официализирането + new: + badge: Бадж за официализиране + officialize: Официализиране + title: Официализиране на участника „%{name}“ + show_email_modal: + close_modal: Затвори прозореца + description: Ако искате да се свържете директно с участник, можете да щракнете върху бутона „Показване“, за да видите електронната поща. Това действие ще бъде регистрирано. + email_address: Имейл адрес + full_name: Три имена + hidden: скрито + show: Покажи + title: Показване на електронната поща на участника + unblock: + error: Възникна грешка при отблокиране на участника + success: Участникът беше отблокиран успешно + organization: + edit: + title: Редактиране на организацията + update: Актуализация + form: + facebook: Facebook + github: GitHub + instagram: Instagram + rich_text_editor_in_public_views_help: В някои текстови области участниците ще могат да вмъкнат някои HTML тагове с помощта на редактора за обогатен текст. + social_handlers: Социални мрежи + twitter: X + url: URL + youtube: YouTube + update: + error: Възникна проблем при актуализирането на тази организация. + success: Организацията беше актуализирана успешно. organization_appearance: + edit: + update: Актуализация form: colors: colors_title: Цветове на организацията + colors_warning_html: Внимание! Промяната на тези цветове може да наруши контрастите на достъпността. Можете да проверите контраста на Вашия избор с WebAIM Contrast Checker или други подобни инструменти. header_snippets_help: Използвайте това поле, за да добавите нещо в HTML заглавието. Най-често се използва за интеграция на външни услуги, които изискват допълнителни JavaScript или CSS. Освен това, можете да го ползвате за добавяне на допълнителни метатагове в HTML. Обърнете внимание, че ще се визуализира само в публичните страници, но не и в администраторския раздел. + homepage_highlighted_content_banner_title: Банер с подчертано съдържание images: layout_appearance_title: Редактиране външния вид шаблона + preview: Преглед + omnipresent_banner_appearance_title: Редактиране на присъстващия навсякъде банер + organization_external_domain_whitelist: + edit: + update: Актуализация + external_domain: + down: Надолу + external_domain: Външен домейн + remove: Премахни + up: Горе + form: + add: Добави към белия списък + title: Бял списък с външни домейни + organization_homepage_content_blocks: + edit: + update: Актуализация + participatory_space_private_users: + create: + error: Възникна проблем при добавянето на частен участник за това пространство за участие. + success: Достъпът на частния участник до пространството за участие беше създаден успешно. + destroy: + error: Възникна проблем при изтриването на частен участник за това пространство за участие. + success: Достъпът на частния участник до пространството за участие беше премахнат успешно. + index: + import_via_csv: Импортиране чрез CSV + title: Пространство за участие на частен участник + new: + create: Създаване + title: Ново пространство за участие на частен участник. + participatory_space_private_users_csv_imports: + create: + invalid: Възникна проблем при прочитането на CSV файла. + success: Файлът във формат CSV беше качен успешно; изпращаме имейл с покана на участниците. Това може да отнеме известно време. + new: + destroy: + button: Изтрийте всички частни участници + confirm: Сигурни ли сте, че искате да изтриете всички частни участници? Това действие не може да бъде отменено, няма да можете да ги възстановите. + empty: Нямате частни участници. + explanation: Имате %{count} частни участници. + title: Изтрийте частни участници + explanation: 'Качете своя CSV файл. Трябва да има две колони с имейл в първата колона на файла и име в последната колона на файла (имейл, име) на потребителите, които искате да добавите към пространството за участие, без заглавки. Избягвайте използването на невалидни знаци като `<>?%&^*#@()[]=+:;"{}\|` в потребителското име.' + title: Качете своя CSV файл + upload: Качване + reminders: + create: + error: Възникна проблем при създаването на напомняния. + success: + one: "%{count} потребител ще получи напомняне." + other: "%{count} потребители ще получат напомняне." + new: + submit: Изпрати + resource_permissions: + edit: + submit: Подаване + title: Редактирай разрешенията + update: + success: Разрешенията бяха актуализирани успешно. + resources: + index: + headers: + scope: Обхват + scope_types: + create: + error: Възникна проблем при създаването на нов тип обхват. + success: Типът обхват е създаден успешно. + destroy: + success: Типът обхват е премахнат успешно + edit: + title: Редактиране на типа на обхвата + update: Актуализация + new: + create: Създаване на тип обхват + title: Нов тип обхват + update: + error: Възникна проблем при актуализирането на този тип обхват. + success: Типът обхват е актуализиран успешно + scopes: + create: + error: Възникна проблем при създаването на нов обхват. + success: Обхватът беше създаден успешно. + destroy: + success: Обхватът беше премахнат успешно + share_tokens: + share_tokens: + empty: Няма активни маркери + shared: + gallery: + delete_image: Изтриване на изображение + static_page_topics: + destroy: + success: Темата беше премахната успешно + static_pages: + edit: + changed_notably_help: Ако бъде поставена отметка, участниците ще получат известие да приемат новите Правила и условия за ползване. + index: + last_notable_change: Последна значима промяна + topic: + destroy: Премахни темата + empty: Няма страници с тази тема + update: + success: Страницата беше актуализирана успешно + titles: + edit_external_domains: Бял списък с външни домейни + edit_organization_appearance: Редактиране на външния вид на началната страница + impersonatable_users: Управляеми участници + impersonations: Управление на участниците + metrics: Метрики + pages: Страници + panel: Администратор + participants: Участници + scope_types: Типове на обхвата + scopes: Обхвати + static_pages: Страници + statistics: Активност + user_groups: Групи + users: Администратори + user_group: + csv_verify: + invalid: Възникна проблем при прочитането на CSV файла. + success: Файлът във формат CSV беше качен успешно, проверяваме групите, които отговарят на критериите. Това може да отнеме известно време. + reject: + invalid: Възникна проблем с отхвърлянето на тази група. + success: Групата беше отхвърлена успешно + verify: + invalid: Възникна проблем с проверката на тази група. + success: Групата беше проверена успешно + user_groups: + index: + state: + pending: Изчакване + rejected: Отхвърлено + verified: Проверен + verify_via_csv: Проверка чрез CSV + user_groups_csv_verifications: + new: + explanation: Качете своя файл във формат CSV. Трябва да съдържа официалните електронни пощи на групите в организацията Ви в първата колона от файла, без заглавки. Ще бъдат валидирани само групите с потвърдена електронна поща и с адрес на електронната поща във файла във формат CSV. + title: Качете своя CSV файл + upload: Качване + users: + create: + error: Възникна проблем с поканата на този администратор. + success: Участника е поканен успешно. + destroy: + error: Възникна проблем при опита за изтриване на този администратор. + success: Участникът вече не е администратор. + form: + email: Имейл + name: Име + role: Роля + new: + create: Покани + title: Поканете нов администратор + users_statistics: + users_count: + admins: Администратори + last_day: Предният ден + last_month: Миналия месец + last_week: Последната седмица + no_users_count_statistics_yet: Все още няма статистика за броя на потребителите + participants: Участници + forms: + errors: + impersonate_user: + reason: Трябва да предоставите причина, когато управлявате участник, който не е управляван + metrics: + blocked_users: + object: блокирани потребители + title: Блокирани потребители + reported_users: + object: докладвани потребители + title: Докладвани потребители + user_reports: + object: доклади на потребители + moderations: + models: + moderation: + fields: + created_at: Дата на създаване + report_count: Брой + reports: Доклади + layouts: + decidim: + admin: + global_moderations: + title: Глобални модерации + newsletters: + title: Бюлетин с новости + settings: + title: Настройки + users: + title: Участници diff --git a/decidim-admin/config/locales/he-IL.yml b/decidim-admin/config/locales/he-IL.yml new file mode 100644 index 0000000000000..118fac6a0317e --- /dev/null +++ b/decidim-admin/config/locales/he-IL.yml @@ -0,0 +1,53 @@ +--- +he: + activemodel: + attributes: + area: + area_type: סוג איזור + name: שם + organization: ארגון + area_type: + name: שם + organization: ארגון + plural: רבים + attachment: + attachment_collection_id: תיקייה + 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: מספר מזהה + import: + user_group_id: יצירת ייבוא כ + newsletter: + body: גוף + subject: נושא + organization: + alert_color: התראה + available_authorizations: הרשאות זמינות + badges_enabled: אפשר תגיות + comments_max_length: אורך מקסימלי לתגובות (השאירו 0 לערך ברירת המחדל) + decidim: + admin: + newsletters: + select_recipients_to_deliver: + send_to_all_users: שליחה לכל המשתמשים.ות + send_to_followers: שליחה לכל העוקבים.ות + send_to_participants: שליחה למשתתפים.ות diff --git a/decidim-admin/config/locales/lv.yml b/decidim-admin/config/locales/lv.yml index 4ce710521111e..02815ac53ad5b 100644 --- a/decidim-admin/config/locales/lv.yml +++ b/decidim-admin/config/locales/lv.yml @@ -288,6 +288,9 @@ lv: search_placeholder: name_or_nickname_or_email_cont: Meklējiet %{collection} pēc e-pasta adreses, vārda vai segvārda. title_cont: Meklējiet %{collection} pēc nosaukuma. + state_eq: + values: + rejected: Noraidīts help_sections: error: Palīdzības sadaļu atjaunināšanas laikā radās problēma form: diff --git a/decidim-admin/config/locales/no.yml b/decidim-admin/config/locales/no.yml index 796847254a250..515b700d5e0d0 100644 --- a/decidim-admin/config/locales/no.yml +++ b/decidim-admin/config/locales/no.yml @@ -793,6 +793,10 @@ form: add: Legg til i hviteliste title: Hviteliste for eksterne domener + organization_homepage: + edit: + active_content_blocks: Aktive innholdsblokker + inactive_content_blocks: Inaktive innholdsblokker organization_homepage_content_blocks: edit: update: Oppdater diff --git a/decidim-admin/config/locales/sl.yml b/decidim-admin/config/locales/sl.yml index 83bc9f2f670c2..adb6561bf5214 100644 --- a/decidim-admin/config/locales/sl.yml +++ b/decidim-admin/config/locales/sl.yml @@ -127,6 +127,9 @@ sl: filters: scope_id_eq: label: Področje + state_eq: + values: + rejected: Zavrnjen menu: scope_types: Tipi področja scopes: Področja diff --git a/decidim-admin/config/locales/sq-AL.yml b/decidim-admin/config/locales/sq-AL.yml index 9e0121baf81ae..efeca3120497c 100644 --- a/decidim-admin/config/locales/sq-AL.yml +++ b/decidim-admin/config/locales/sq-AL.yml @@ -51,16 +51,83 @@ sq: description: Përshkrimi enable_omnipresent_banner: Shfaq banerin e gjithëpranishëm enable_participatory_space_filters: Aktivizo filtrat e hapësirës së pjesëmarrjes + facebook_handler: Emri i përdoruesit Facebook favicon: Ikona force_authentication: Sforco autentikimin + force_users_to_authenticate_before_access_organization: Detyro përdoruesit të autentikohen para se të aksesojnë organizatën + from: Adresa email e dërguesit + github_handler: Emri i përdoruesit Github highlight_color: Theksim + highlighted_content_banner_image: Imazhi highlighted_content_banner_short_description: Përshkrim i shkurtër highlighted_content_banner_title: Titulli host: Organizatori + instagram_handler: Emri i përdoruesit Instagram + logo: Logo + machine_translation_display_priority: Prioriteti i shfaqjes së përkthimit automatik + machine_translation_display_priority_original: Teksti origjinal i pari + machine_translation_display_priority_translation: Teksti i përkthyer i pari + name: Emri + official_url: Adresa zyrtare e organizatës + omnipresent_banner_short_description: Përshkrim i shkurtër + omnipresent_banner_title: Titulli + omnipresent_banner_url: URL + organization_admin_email: Emaili i adminit të organizatës + organization_admin_name: Emri i adminit të organizatës + organization_locales: Gjuhët e organizatës + primary_color: Ngjyra parësore + rich_text_editor_in_public_views: Aktivizo editorin kompleks për pjesëmarrësit + secondary_color: Ngjyra dytësore + send_welcome_notification: Dërgo njoftim mirëseardhjeje + success_color: Sukses + time_zone: Zona orare + tos_version: Versioni i kushteve të shërbimit + twitter_handler: Emri i përdoruesit X + user_groups_enabled: Aktivizo grupet + users_registration_mode: Mënyra e regjistrimit të përdoruesve + warning_color: Kujdes + welcome_notification_body: Përmbajtja e njoftimit të mirëseardhjes + welcome_notification_subject: Tema e njoftimit të mirëseardhjes + youtube_handler: Emri i përdoruesit Youtube + participatory_space_private_user: + email: Email + name: Emri + scope: + code: Kodi + name: Emri + organization: Organizata + scope_type: + name: Emri + organization: Organizata + plural: Shumësi + static_page: + allow_public_access: Lejo akses të paautentikuar + content: Përmbajtja + organization: Organizata + slug: Slug i adresës URL + title: Titulli + activerecord: + attributes: + decidim/static_page: + content: Përmbajtje + slug: Slug i adresës URL + title: Titulli decidim: admin: + models: + share_token: + fields: + last_used_at: Hera e fundit që u përdor + times_used: Sa herë është përdorur newsletters: select_recipients_to_deliver: send_to_all_users: Dërgo të gjithë përdoruesve send_to_followers: Dërgo ndjekësve send_to_participants: Dërgo pjesëmarrësve + organization: + form: + social_handlers: Rrjetet sociale + organization_appearance: + form: + colors: + colors_title: Ngjyrat e organizatës diff --git a/decidim-admin/config/locales/th-TH.yml b/decidim-admin/config/locales/th-TH.yml index a4431912a8299..55c2e3810d9fa 100644 --- a/decidim-admin/config/locales/th-TH.yml +++ b/decidim-admin/config/locales/th-TH.yml @@ -1 +1,101 @@ +--- th: + activemodel: + attributes: + area: + area_type: ประเภทพื้นที่ + name: ชื่อ + organization: องค์กร + area_type: + name: ชื่อ + organization: องค์กร + plural: พหูพจน์ + attachment: + attachment_collection_id: โฟลเดอร์ + description: คำอธิบาย + file: ไฟล์ + title: ชื่อไฟล์แนบหรือรูปภาพ + weight: ตำแหน่งการสั่งซื้อ + attachment_collection: + description: คำอธิบาย + name: ชื่อ + organization: + machine_translation_display_priority_translation: แปลข้อความก่อน + name: ชื่อ + official_img_footer: ส่วนท้ายของโลโก้อย่างเป็นทางการ + official_url: URL องค์กรอย่างเป็นทางการ + omnipresent_banner_short_description: คำอธิบายสั้น + omnipresent_banner_title: ชื่อ + omnipresent_banner_url: URL + organization_admin_email: อีเมลผู้ดูแลระบบองค์กร + organization_admin_name: อีเมลผู้ดูแลระบบองค์กร + organization_locales: สถานที่ขององค์กร + primary_color: หลัก + reference_prefix: คำนำหน้าอ้างอิง + rich_text_editor_in_public_views: เปิดใช้งานโปรแกรมแก้ไขข้อความแบบ Rich Text สำหรับผู้เข้าร่วม + secondary_color: รอง + secondary_hosts: เจ้าภาพรอง + send_welcome_notification: ส่งการแจ้งเตือนยินดีต้อนรับ + success_color: ความสำเร็จ + time_zone: เขตเวลา + tos_version: เงื่อนไขการให้บริการเวอร์ชัน + twitter_handler: ตัวจัดการเอ็กซ์ + user_groups_enabled: เปิดใช้งานกลุ่ม + users_registration_mode: โหมดการลงทะเบียนผู้ใช้ + warning_color: คำเตือน + welcome_notification_body: ยินดีต้อนรับเนื้อหาการแจ้งเตือน + welcome_notification_subject: ยินดีต้อนรับเรื่องการแจ้งเตือน + youtube_handler: ตัวจัดการ YouTube + participatory_space_private_user: + email: อีเมล + name: ชื่อ + scope: + code: รหัส + name: ชื่อ + organization: องค์กร + parent_id: พ่อแม่ + scope_type: ประเภทขอบเขต + scope_type_id: ประเภทขอบเขต + scope_type: + name: ชื่อ + organization: องค์กร + plural: พหูพจน์ + settings: + scope_id: ขอบเขต + static_page: + allow_public_access: อนุญาตการเข้าถึงโดยไม่ต้องตรวจสอบสิทธิ์ + changed_notably: มีการเปลี่ยนแปลงที่เห็นได้ชัดเจน + content: เนื้อหา + organization: องค์กร + show_in_footer: แสดงในส่วนท้าย + slug: บุ้ง URL + title: ชื่อ + topic_id: หัวข้อ + weight: ตำแหน่งการสั่งซื้อ + static_page_topic: + description: คำอธิบาย + decidim: + admin: + area_types: + edit: + title: แก้ไขประเภทพื้นที่ + update: อัปเดต + new: + create: สร้างประเภทพื้นที่ + title: ประเภทพื้นที่ใหม่ + update: + error: เกิดปัญหาในการอัปเดตประเภทพื้นที่นี้ + areas: + create: + error: เกิดปัญหาในการสร้างพื้นที่ใหม่ + success: สร้างพื้นที่สำเร็จแล้ว + destroy: + has_spaces: พื้นที่นี้มีช่องว่างที่ต้องพึ่งพา โปรดตรวจสอบให้แน่ใจว่าไม่มี Participatory Space อ้างอิงถึงพื้นที่นี้ก่อนที่จะลบออก + edit: + title: แก้ไขพื้นที่ + organization_external_domain_whitelist: + edit: + update: อัปเดต + organization_homepage_content_blocks: + edit: + update: อัปเดต 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 f369262777db6..9b28e08e2f710 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 @@ -19,6 +19,15 @@ module Admin end end + context "when the category is being used by a resource" do + let(:component) { create(:dummy_component, participatory_space: participatory_space) } + let!(:resource) { create(:dummy_resource, component: component, category: category) } + + it "broadcasts invalid" do + expect { command.call }.to broadcast(:invalid) + end + end + context "when the category is not empty" do let!(:subcategory) { create :subcategory, parent: category } diff --git a/decidim-admin/lib/decidim/admin/version.rb b/decidim-admin/lib/decidim/admin/version.rb index d285f98a89d5a..f6f069fbb3259 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.27.5" + "0.27.6" end end end diff --git a/decidim-admin/spec/controllers/impersonations_controller_spec.rb b/decidim-admin/spec/controllers/impersonations_controller_spec.rb index 32c195c84ac66..259d7ba8051ab 100644 --- a/decidim-admin/spec/controllers/impersonations_controller_spec.rb +++ b/decidim-admin/spec/controllers/impersonations_controller_spec.rb @@ -158,6 +158,46 @@ module Admin end end + context "with existing managed user with the same identity in another organization" do + let(:other_organization) do + create( + :organization, + available_authorizations: ["dummy_authorization_handler"] + ) + end + + before do + user = create( + :user, + :managed, + organization: other_organization, + name: managed_user_name + ) + Decidim::Authorization.create!( + user: user, + name: authorization_params[:handler_name], + unique_id: authorization_params[:document_number], + metadata: { + document_number: "9999X", + postal_code: "99999" + } + ) + end + + it_behaves_like "successful authorization" + + it "creates a new managed user" do + post(:create, params: params) + + expect( + Decidim::User.where( + name: managed_user_name, + managed: true + ).count + ).to eq(2) + end + end + context "with existing non-managed user with the same identity" do before do user = create( @@ -190,6 +230,53 @@ module Admin expect(subject).to render_template(:new) end end + + context "with existing non-managed user with the same identity in another organization" do + let(:other_organization) do + create( + :organization, + available_authorizations: ["dummy_authorization_handler"] + ) + end + + before do + user = create( + :user, + organization: other_organization, + name: managed_user_name + ) + Decidim::Authorization.create!( + user: user, + name: authorization_params[:handler_name], + unique_id: authorization_params[:document_number], + metadata: { + document_number: authorization_params[:document_number], + postal_code: "99999" + } + ) + end + + it_behaves_like "successful authorization" + + it "creates a new managed user" do + post(:create, params: params) + + expect( + Decidim::User.where( + organization: organization, + name: managed_user_name, + managed: true + ).count + ).to eq(1) + + expect( + Decidim::User.where( + organization: other_organization, + name: managed_user_name + ).count + ).to eq(1) + end + end end end end diff --git a/decidim-admin/spec/controllers/organizations_controller_spec.rb b/decidim-admin/spec/controllers/organizations_controller_spec.rb index a27c0a3b55d52..cc6adea0df65e 100644 --- a/decidim-admin/spec/controllers/organizations_controller_spec.rb +++ b/decidim-admin/spec/controllers/organizations_controller_spec.rb @@ -9,6 +9,11 @@ module Admin let(:organization) { create :organization } let(:current_user) { create(:user, :admin, :confirmed, organization: organization) } + let(:parsed_response) { JSON.parse(response.body).map(&:symbolize_keys) } + + shared_context "with daisy" do + let!(:daisy) { create(:user, name: "Daisy", nickname: "daisy", organization: organization, email: "daisy@example.org") } + end before do request.env["decidim.current_organization"] = organization @@ -32,9 +37,18 @@ module Admin organization: organization ) end - let(:parsed_response) { JSON.parse(response.body).map(&:symbolize_keys) } context "when searching by name" do + context "when finding by full name" do + include_context "with daisy" + + it "returns the results ordered by similarity" do + get :user_entities, format: :json, params: { term: "Daisy" } + expect(parsed_response.count).to eq(3) + expect(parsed_response.first[:value]).to eq(daisy.id) + end + end + it "returns the id, name and nickname for filtered users and user groups" do get :user_entities, format: :json, params: { term: "daisy" } expect(parsed_response).to include({ value: user.id, label: "#{user.name} (@#{user.nickname})" }) @@ -56,6 +70,16 @@ module Admin expect(parsed_response).not_to include({ value: deleted_user.id, label: "#{deleted_user.name} (@#{deleted_user.nickname})" }) expect(parsed_response).not_to include({ value: managed_user.id, label: "#{managed_user.name} (@#{managed_user.nickname})" }) end + + context "when finding by full nickname" do + include_context "with daisy" + + it "returns the results ordered by similarity" do + get :user_entities, format: :json, params: { term: "@daisy" } + expect(parsed_response.count).to eq(3) + expect(parsed_response.first[:value]).to eq(daisy.id) + end + end end context "when searching by email" do @@ -68,6 +92,16 @@ module Admin expect(parsed_response).not_to include({ value: deleted_user.id, label: "#{deleted_user.name} (@#{deleted_user.nickname})" }) expect(parsed_response).not_to include({ value: managed_user.id, label: "#{managed_user.name} (@#{managed_user.nickname})" }) end + + context "when finding by full email" do + include_context "with daisy" + + it "returns the results ordered by similarity" do + get :user_entities, format: :json, params: { term: "daisy@example.org" } + expect(parsed_response.count).to eq(1) + expect(parsed_response.first[:value]).to eq(daisy.id) + end + end end context "when user is blocked" do @@ -112,8 +146,6 @@ module Admin ) end - let(:parsed_response) { JSON.parse(response.body).map(&:symbolize_keys) } - context "when no search term is provided" do it "returns an empty result set" do get :users, format: :json, params: {} @@ -133,6 +165,15 @@ module Admin get :users, format: :json, params: { term: "daisy" } expect(parsed_response).to eq([{ value: user.id, label: "#{user.name} (@#{user.nickname})" }]) end + + context "when there is more than one result" do + include_context "with daisy" + + it "returns the results ordered by similarity" do + get :users, format: :json, params: { term: "daisy" } + expect(parsed_response).to eq([{ value: daisy.id, label: "#{daisy.name} (@#{daisy.nickname})" }, { value: user.id, label: "#{user.name} (@#{user.nickname})" }]) + end + end end context "when searching by nickname" do @@ -140,6 +181,15 @@ module Admin get :users, format: :json, params: { term: "@daisy" } expect(parsed_response).to eq([{ value: user.id, label: "#{user.name} (@#{user.nickname})" }]) end + + context "when there is more than one result" do + include_context "with daisy" + + it "returns the results ordered by similarity" do + get :users, format: :json, params: { term: "@daisy" } + expect(parsed_response).to eq([{ value: daisy.id, label: "#{daisy.name} (@#{daisy.nickname})" }, { value: user.id, label: "#{user.name} (@#{user.nickname})" }]) + end + end end context "when searching by email" do @@ -147,6 +197,15 @@ module Admin get :users, format: :json, params: { term: user.email } expect(parsed_response).to eq([{ value: user.id, label: "#{user.name} (@#{user.nickname})" }]) end + + context "when there is more than one result" do + include_context "with daisy" + + it "returns the results ordered by similarity" do + get :users, format: :json, params: { term: "daisy@example.org" } + expect(parsed_response).to eq([{ value: daisy.id, label: "#{daisy.name} (@#{daisy.nickname})" }]) + end + end end context "when user is blocked" do diff --git a/decidim-admin/spec/events/decidim/attachment_created_event_spec.rb b/decidim-admin/spec/events/decidim/attachment_created_event_spec.rb index 31ad7a9b98e73..93d8efd353a09 100644 --- a/decidim-admin/spec/events/decidim/attachment_created_event_spec.rb +++ b/decidim-admin/spec/events/decidim/attachment_created_event_spec.rb @@ -8,7 +8,7 @@ let(:event_name) { "decidim.events.attachments.attachment_created" } let(:resource) { create(:attachment) } let(:attached_to_url) { resource_locator(attached_to).url } - let(:resource_title) { attached_to.title["en"] } + let(:resource_title) { decidim_sanitize_translated(attached_to.title) } let(:resource_path) { resource.url } let(:attached_to) { resource.attached_to } let(:email_subject) { "An update to #{resource_title}" } diff --git a/decidim-admin/spec/events/decidim/component_published_event_spec.rb b/decidim-admin/spec/events/decidim/component_published_event_spec.rb index 2f3ba6aa1ed6d..ae7136c3c6310 100644 --- a/decidim-admin/spec/events/decidim/component_published_event_spec.rb +++ b/decidim-admin/spec/events/decidim/component_published_event_spec.rb @@ -11,8 +11,9 @@ let(:resource) { create(:component) } let(:participatory_space) { resource.participatory_space } let(:resource_path) { main_component_path(resource) } - let(:email_subject) { "An update to #{participatory_space_title}" } + let(:email_subject) { "An update to #{decidim_sanitize_translated(participatory_space.title)}" } let(:resource_title) { decidim_sanitize_translated(resource.name) } + let(:participatory_space_title) { decidim_sanitize_translated(participatory_space.title) } let(:email_intro) { "The #{resource_title} component is now active for #{participatory_space_title}. You can see it from this page:" } let(:email_outro) { "You have received this notification because you are following #{participatory_space_title}. You can stop receiving notifications following the previous link." } let(:notification_title) { "The #{resource_title} component is now active for #{participatory_space_title}" } diff --git a/decidim-admin/spec/events/decidim/resource_hidden_event_spec.rb b/decidim-admin/spec/events/decidim/resource_hidden_event_spec.rb index 50728ee523334..7d68456d32dfa 100644 --- a/decidim-admin/spec/events/decidim/resource_hidden_event_spec.rb +++ b/decidim-admin/spec/events/decidim/resource_hidden_event_spec.rb @@ -6,13 +6,14 @@ module Decidim describe ResourceHiddenEvent do include_context "when a simple event" - let(:comment) { create :comment, body: { "en" => "a reported comment" } } - let(:moderation) { create :moderation, reportable: comment } - let(:report) { create :report, moderation: moderation } + let(:comment) { create(:comment, body: generate_localized_description(:comment_body)) } + let(:moderation) { create(:moderation, reportable: comment) } + let(:report) { create(:report, moderation: moderation) } let(:resource) { comment } + let(:resource_text) { "#{decidim_sanitize(translated(resource.body), strip_tags: true)}" } let(:event_name) { "decidim.events.reports.resource_hidden" } let(:extra) { { report_reasons: ["spam"] } } - let(:notification_title) { "An administrator removed your comment because it has been reported as spam.
\na reported comment" } + let(:notification_title) { "An administrator removed your comment because it has been reported as spam.
\n#{resource_text}" } let(:email_subject) { "Your comment has been removed" } let(:email_outro) { "You have received this notification because you are an author of the removed content." } let(:email_intro) { "An administrator removed your comment because it has been reported as spam." } @@ -22,7 +23,7 @@ module Decidim describe "resource_text" do it "is generated correctly" do - expect(subject.resource_text).to include("#{comment.body["en"]}") + expect(subject.resource_text).to include(resource_text) end end end diff --git a/decidim-admin/spec/helpers/moderations/reports_helper_spec.rb b/decidim-admin/spec/helpers/moderations/reports_helper_spec.rb index ca79a347d20d8..467ee04fcdd21 100644 --- a/decidim-admin/spec/helpers/moderations/reports_helper_spec.rb +++ b/decidim-admin/spec/helpers/moderations/reports_helper_spec.rb @@ -42,8 +42,9 @@ module Moderations let(:reportable) { proposal } it "returns the meeting's title" do + meeting_title = ActionView::Base.full_sanitizer.sanitize(translated_attribute(reportable.authors.first.title)) expect(helper.reportable_author_name(reportable)).to include("reportable-authors") - expect(helper.reportable_author_name(reportable)).to include(translated_attribute(reportable.authors.first.title)) + expect(helper.reportable_author_name(reportable)).to include(meeting_title) end end end diff --git a/decidim-api/lib/decidim/api/engine.rb b/decidim-api/lib/decidim/api/engine.rb index 3fd4711571a33..38727a30bf152 100644 --- a/decidim-api/lib/decidim/api/engine.rb +++ b/decidim-api/lib/decidim/api/engine.rb @@ -35,9 +35,9 @@ class Engine < ::Rails::Engine initializer "decidim-api.graphiql" do Decidim::GraphiQL::Rails.config.tap do |config| config.query_params = true - config.initial_query = File.read( - File.join(__dir__, "graphiql-initial-query.txt") - ).html_safe + config.initial_query = ERB::Util.html_escape( + File.read(File.join(__dir__, "graphiql-initial-query.txt")) + ) end end diff --git a/decidim-api/lib/decidim/api/version.rb b/decidim-api/lib/decidim/api/version.rb index b9d1b448a73b7..d7b2b97c25745 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.27.5" + "0.27.6" end end end diff --git a/decidim-assemblies/app/cells/decidim/assemblies/assembly_m_cell.rb b/decidim-assemblies/app/cells/decidim/assemblies/assembly_m_cell.rb index d2e2c0def4e10..c45141df49e82 100644 --- a/decidim-assemblies/app/cells/decidim/assemblies/assembly_m_cell.rb +++ b/decidim-assemblies/app/cells/decidim/assemblies/assembly_m_cell.rb @@ -70,7 +70,7 @@ def has_assembly_type? end def assembly_type - translated_attribute model.assembly_type.title + decidim_sanitize_translated model.assembly_type.title end 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 5a9c581055cf4..325cc383bc7a6 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 @@ -10,7 +10,7 @@
- <%= translated_attribute assembly.title %> + <%= decidim_escape_translated assembly.title %>
<% end %>
diff --git a/decidim-assemblies/app/events/decidim/assemblies/create_assembly_member_event.rb b/decidim-assemblies/app/events/decidim/assemblies/create_assembly_member_event.rb index 1c717bb54f635..bfa320ad335c2 100644 --- a/decidim-assemblies/app/events/decidim/assemblies/create_assembly_member_event.rb +++ b/decidim-assemblies/app/events/decidim/assemblies/create_assembly_member_event.rb @@ -6,7 +6,7 @@ class CreateAssemblyMemberEvent < Decidim::Events::SimpleEvent i18n_attributes :resource_name def resource_name - @resource_name ||= translated_attribute(assembly.title) + @resource_name ||= decidim_sanitize_translated(assembly.title) end def assembly 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 065b2e705f3d3..3920681579d90 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 @@ -2,13 +2,8 @@ module Decidim class RoleAssignedToAssemblyEvent < Decidim::Events::SimpleEvent - include Decidim::Events::NotificationEvent include Decidim::Events::AuthorEvent - def notification_title - I18n.t("notification_title", **i18n_options).html_safe - end - def i18n_role I18n.t(extra["role"], scope: "decidim.admin.models.assembly_user_role.roles", default: extra["role"]) end diff --git a/decidim-assemblies/app/helpers/decidim/assemblies/assemblies_helper.rb b/decidim-assemblies/app/helpers/decidim/assemblies/assemblies_helper.rb index f6a80ef06a139..ba05771552f7a 100644 --- a/decidim-assemblies/app/helpers/decidim/assemblies/assemblies_helper.rb +++ b/decidim-assemblies/app/helpers/decidim/assemblies/assemblies_helper.rb @@ -31,7 +31,7 @@ def participatory_processes_for_assembly(assembly_participatory_processes) def assembly_features(assembly) html = "".html_safe - html += "#{translated_attribute(assembly.title)}: ".html_safe + html += "#{decidim_escape_translated(assembly.title)}: ".html_safe html += t("assemblies.show.private_space", scope: "decidim").to_s.html_safe html += ", #{t("assemblies.show.is_transparent.#{assembly.is_transparent}", scope: "decidim")}".html_safe if assembly.is_transparent? html += " #{decidim_sanitize_editor translated_attribute(assembly.special_features)}".html_safe diff --git a/decidim-assemblies/config/locales/bg.yml b/decidim-assemblies/config/locales/bg.yml index 4fb1019831eed..98b6f080cdc6e 100644 --- a/decidim-assemblies/config/locales/bg.yml +++ b/decidim-assemblies/config/locales/bg.yml @@ -2,11 +2,78 @@ bg: activemodel: attributes: + assemblies_setting: + enable_organization_chart: Активиране на организационна диаграма assembly: area_id: Район assembly_type: Тип събрание assembly_type_other: Друг тип събрание + errors: + models: + assembly: + attributes: + document: + allowed_file_content_types: 'Невалиден файлов формат. Разрешени са само файлове със следните разширения: %{types}' decidim: + admin: + assemblies: + index: + not_published: Не публикувано + assemblies_settings: + update: + error: Възникна проблем при актуализирането на настройките. + success: Настройките са актуализирани успешно. + assembly_members: + edit: + title: Актуализиране на член на събранието. + new: + title: Нов член на събранието. + assembly_user_roles: + edit: + title: Актуализиране на администратора на събранието. + new: + title: Нов администратор на събранието. + menu: + assemblies_settings: Настройки + assemblies_submenu: + info: Информация assemblies: + admin: + assemblies_settings: + form: + title: Настройки за събрания + assembly_imports: + form: + document_legend: Добавяне на документ + assembly_members: + form: + image_guide: За предпочитане използвайте хоризонтално изображение без текст. + index: + filter: + all: Всички + filter_by: Филтрирай по + search: Търсене + pages: + home: + highlighted_assemblies: + assemblies_button_title: Връзка към страницата „Събрания“, на която се показват всички събрания show: area: Район + is_transparent: + 'false': непрозрачно + 'true': прозрачно + read_less: Скрийте + read_more: Прочетете повече + social_networks: Социални мрежи + errors: + messages: + cannot_be_blank: не може да остане празно + layouts: + decidim: + assemblies: + index: + children: 'Събрания: ' + organizational_chart: Организационна диаграма + reset_chart: Начално състояние + assembly_navigation: + assembly_menu_item: Събранието diff --git a/decidim-assemblies/config/locales/he-IL.yml b/decidim-assemblies/config/locales/he-IL.yml new file mode 100644 index 0000000000000..e7feee24b4654 --- /dev/null +++ b/decidim-assemblies/config/locales/he-IL.yml @@ -0,0 +1,110 @@ +--- +he: + activemodel: + attributes: + assemblies_type: + title: כותרת + assembly: + announcement: הכרזה + area_id: אזור + assembly_type: סוג אסיפה + assembly_type_other: סוג אסיפה אחרת + banner_image: תמונת הבאנר + closing_date: תאריך סגירה + closing_date_reason: סיבת תאריך סגירה + composition: הרכב + copy_categories: העתקת קטגוריה + copy_components: העתקת רכיבים + copy_features: העתקת מאפיינים + created_by: נוצר ע"י + created_by_other: נוצר על ידי אחרים + creation_date: תאריך יצירה + decidim_area_id: אזור + decidim_assemblies_type_id: סוג אסיפה + decidim_scope_id: היקף + description: תיאור + developer_group: קבוצת יזמים + document: מסמך + domain: דומיין + duration: משך זמן + facebook: פייסבוק + github: Github + hashtag: תַּג הַקְבָּצָה + hero_image: תמונת ראשית + import_attachments: יבוא צרופות + import_categories: ייבוא קטגוריות + import_components: ייבוא רכיבים + included_at: נכלל ב + instagram: אינסטגרם + internal_organisation: ארגון פנימי + is_transparent: שקוף + local_area: אזור ארגון + meta_scope: מטא נתונים של היקף + parent_id: אסיפה (הורה) + participatory_processes_ids: תהליך השתתפותי מקושר + participatory_scope: מה הוחלט + participatory_structure: איך זה מוחלט + private_space: מרחב פרטי + promoted: הודגש + published_at: פורסם בתאריך + purpose_of_action: מטרת הפעולה + scope_id: היקף + scopes_enabled: היקפים מאופשרים + short_description: תיאור קצר + show_statistics: הצגת סטטיסטיקה + slug: כינוי לקישור + special_features: מאפיינים מיוחדים + decidim: + admin: + assembly_copies: + new: + title: שכפל אסיפה + assembly_imports: + create: + error: הייתה בעיה בייבוא ​​אסיפה זו. + success: אסיפה יובאה בהצלחה. + new: + import: ייבוא + select: בחירת הנתונים לייבוא + title: ייבוא אסיפה + assembly_members: + create: + error: הייתה בעיה בהוספת חבר.ה עבור אסיפה זו. + success: חבר.ה נוצר.ה בהצלחה עבור האסיפה הזו. + destroy: + success: חבר.ה נמחק.ה בהצלחה מאסיפה זו. + edit: + update: עדכון + index: + assembly_members_title: חברי.ות אסיפה + new: + create: יצירה + update: + error: הייתה בעיה בעדכון חבר.ה עבור אסיפה זו. + success: חבר.ה עודכנ.ה בהצלחה עבור אסיפה זו. + assembly_publications: + create: + error: הייתה בעיה בפרסום ​​אסיפה זו. + success: אסיפה פורסמה בהצלחה. + destroy: + error: הייתה בעיה בביטול פרסום ​​אסיפה זו. + success: פרסום האסיפה בוטל בהצלחה. + assembly_user_roles: + create: + error: הייתה בעיה בהוספת מנהל.ת עבור אסיפה זו. + assemblies: + show: + area: אזור + closing_date: תאריך סגירה + composition: הרכב + created_by: נוצר ע"י + creation_date: תאריך יצירה + developer_group: קבוצת יזמים + included_at: נכלל ב + internal_organisation: ארגון פנימי + local_area: אזור ארגון + participatory_scope: מה הוחלט + participatory_structure: איך זה מוחלט + purpose_of_action: מטרת הפעולה + related_participatory_processes: תהליך השתתפותי מקושר + scope: היקף diff --git a/decidim-assemblies/config/locales/id-ID.yml b/decidim-assemblies/config/locales/id-ID.yml index d223024f0f2b2..5dc599d934f27 100644 --- a/decidim-assemblies/config/locales/id-ID.yml +++ b/decidim-assemblies/config/locales/id-ID.yml @@ -303,7 +303,7 @@ id: purpose_of_action: Tujuan tindakan read_less: Baca lebih sedikit read_more: Baca lebih lajut - related_participatory_processes: Proses partisipatif terkait + related_participatory_processes: Proses Partisipatif Terkait scope: Cakupan social_networks: Jaringan sosial target: Yang berpartisipasi diff --git a/decidim-assemblies/config/locales/is-IS.yml b/decidim-assemblies/config/locales/is-IS.yml index ff58d9883ffd4..1d03a4726f084 100644 --- a/decidim-assemblies/config/locales/is-IS.yml +++ b/decidim-assemblies/config/locales/is-IS.yml @@ -233,7 +233,6 @@ is: purpose_of_action: Tilgangur aðgerða read_less: Lesa minna read_more: Lestu meira - related_participatory_processes: Svipaðir þátttakandi ferli scope: Umfang social_networks: Samfélagsmiðlar target: Hver tekur þátt diff --git a/decidim-assemblies/config/locales/lb.yml b/decidim-assemblies/config/locales/lb.yml index 1909c99effc0d..82fc15ebba5c9 100644 --- a/decidim-assemblies/config/locales/lb.yml +++ b/decidim-assemblies/config/locales/lb.yml @@ -309,7 +309,7 @@ lb: purpose_of_action: Zweck der Aktion read_less: Lese weniger read_more: Weiterlesen - related_participatory_processes: Procesos participativos relacionados + related_participatory_processes: Ähnliche Beteiligungsprozesse scope: Umfang social_networks: Soziale Netzwerke target: Wer nimmt teil? diff --git a/decidim-assemblies/config/locales/sk.yml b/decidim-assemblies/config/locales/sk.yml index 4e7daac2a2a1c..656de90eaffbc 100644 --- a/decidim-assemblies/config/locales/sk.yml +++ b/decidim-assemblies/config/locales/sk.yml @@ -158,6 +158,7 @@ sk: participatory_scope: O čom sa rozhoduje participatory_structure: Ako sa o tom rozhoduje purpose_of_action: Cieľ aktivity + related_participatory_processes: Súvisiace participatívne procesy scope: Rozsah target: Kto sa zúčastňuje events: diff --git a/decidim-assemblies/config/locales/sq-AL.yml b/decidim-assemblies/config/locales/sq-AL.yml index 44ddadc95a8f3..543e6c3ff37c4 100644 --- a/decidim-assemblies/config/locales/sq-AL.yml +++ b/decidim-assemblies/config/locales/sq-AL.yml @@ -1 +1,85 @@ +--- sq: + activemodel: + attributes: + assemblies_type: + title: Titulli + assembly: + announcement: Njoftim + area_id: Zona + assembly_type: Lloji i asamblesë + assembly_type_other: Lloji i asamblesë tjetër + closing_date: Data e mbylljes + closing_date_reason: Arsyeja e datës së mbylljes + composition: Përbërja + copy_categories: Kopjo kategoritë + created_by: Krijuar nga + created_by_other: Krijuar nga tjetër + creation_date: Data e krijimit + decidim_area_id: Zona + decidim_assemblies_type_id: Lloji i asamblesë + decidim_scope_id: Qëllimi + description: Përshkrimi + developer_group: Grupi promovues + document: Dokument + domain: Domeini + duration: Kohëzgjatja + facebook: Facebook + github: Github + hashtag: Hashtag + hero_image: Imazhi kryesor + import_attachments: Importoni bashkëngjitjet + import_categories: Importoni kategoritë + import_components: Importoni përbërësit + included_at: Përfshirë në + instagram: Instagram + internal_organisation: Organizatë e brëndshme + is_transparent: Është transparente + local_area: Zona e organizatës + parent_id: Asambleja e përgjithshme + participatory_scope: Çfarë u vendos + participatory_structure: Si u vendos + private_space: Hapësirë private + promoted: Në pah + published_at: Publikuar në + purpose_of_action: Qëllimi i aksionit + scope_id: Qëllimi + scopes_enabled: Fushveprimet e aktivizuara + short_description: Përshkrim i shkurtër + show_statistics: Trego statistikat + slug: Identifikues URL-je + special_features: Karaktersitika të veçanta + subtitle: Nëntitull + target: Kush merr pjesë + title: Titulli + twitter: X + youtube: YouTube + assembly_member: + birthday: Datëlindje + birthplace: Vendi i lindjes + full_name: Emri i plotë + gender: Gjinia + non_user_avatar: Avatar + position: Pozicioni + user_id: Perdorues ose grup + assembly_user_role: + email: Email + name: Emri + role: Roli + decidim: + assemblies: + show: + area: Zona + closing_date: Data e mbylljes + composition: Përbërja + created_by: Krijuar nga + creation_date: Data e krijimit + developer_group: Grupi promovues + included_at: Përfshirë në + internal_organisation: Organizatë e brëndshme + local_area: Zona e organizatës + participatory_scope: Çfarë u vendos + participatory_structure: Si u vendos + purpose_of_action: Qëllimi i aksionit + scope: Qëllimi + target: Kush merr pjesë diff --git a/decidim-assemblies/config/locales/tr-TR.yml b/decidim-assemblies/config/locales/tr-TR.yml index 4839419bf5834..0b9645ce1845a 100644 --- a/decidim-assemblies/config/locales/tr-TR.yml +++ b/decidim-assemblies/config/locales/tr-TR.yml @@ -376,7 +376,7 @@ tr: purpose_of_action: Eylem amacı read_less: Daha az oku read_more: Daha fazla oku - related_participatory_processes: İlgili katılımcı süreçleri + related_participatory_processes: İlgili Katılımcı süreçler scope: kapsam social_networks: Sosyal ağlar target: Katılanlar diff --git a/decidim-assemblies/config/locales/zh-TW.yml b/decidim-assemblies/config/locales/zh-TW.yml index dcda7902b90bf..f4becfdb4b822 100644 --- a/decidim-assemblies/config/locales/zh-TW.yml +++ b/decidim-assemblies/config/locales/zh-TW.yml @@ -383,7 +383,7 @@ zh-TW: purpose_of_action: 行動目的 read_less: 閱讀減少 read_more: 閱讀變多 - related_participatory_processes: 相關參與過程 + related_participatory_processes: 相關參與程序 scope: 範圍 social_networks: 社群網路 social_networks_title: 訪問大會 diff --git a/decidim-assemblies/lib/decidim/assemblies/test/factories.rb b/decidim-assemblies/lib/decidim/assemblies/test/factories.rb index d902430c2acf6..ab69ede02828d 100644 --- a/decidim-assemblies/lib/decidim/assemblies/test/factories.rb +++ b/decidim-assemblies/lib/decidim/assemblies/test/factories.rb @@ -14,7 +14,10 @@ end factory :assemblies_type, class: "Decidim::AssembliesType" do - title { generate_localized_title } + transient do + skip_injection { false } + end + title { generate_localized_title(:assemblies_type_title, skip_injection: skip_injection) } organization end @@ -22,45 +25,45 @@ transient do skip_injection { false } end - title { generate_localized_title } + title { generate_localized_title(:assembly_title, skip_injection: skip_injection) } slug { generate(:assembly_slug) } - subtitle { generate_localized_title } - short_description { Decidim::Faker::Localized.wrapped("

", "

") { generate_localized_title } } - description { Decidim::Faker::Localized.wrapped("

", "

") { generate_localized_title } } + subtitle { generate_localized_title(:assembly_subtitle, skip_injection: skip_injection) } + short_description { generate_localized_description(:assembly_short_description, skip_injection: skip_injection) } + description { generate_localized_description(:assembly_description, skip_injection: skip_injection) } organization hero_image { Decidim::Dev.test_file("city.jpeg", "image/jpeg") } # Keep after organization banner_image { Decidim::Dev.test_file("city2.jpeg", "image/jpeg") } # Keep after organization published_at { Time.current } - meta_scope { Decidim::Faker::Localized.word } - developer_group { generate_localized_title } - local_area { generate_localized_title } - target { generate_localized_title } - participatory_scope { generate_localized_title } - participatory_structure { generate_localized_title } + meta_scope { generate_localized_word(:assembly_meta_scope, skip_injection: skip_injection) } + developer_group { generate_localized_title(:assembly_developer_group, skip_injection: skip_injection) } + local_area { generate_localized_title(:assembly_local_area, skip_injection: skip_injection) } + target { generate_localized_title(:assembly_target, skip_injection: skip_injection) } + participatory_scope { generate_localized_title(:assembly_participatory_scope, skip_injection: skip_injection) } + participatory_structure { generate_localized_title(:assembly_participatory_structure, skip_injection: skip_injection) } show_statistics { true } private_space { false } - purpose_of_action { Decidim::Faker::Localized.wrapped("

", "

") { generate_localized_title } } - composition { Decidim::Faker::Localized.wrapped("

", "

") { generate_localized_title } } + purpose_of_action { generate_localized_description(:assembly_purpose_of_action, skip_injection: skip_injection) } + composition { generate_localized_description(:assembly_composition, skip_injection: skip_injection) } creation_date { 1.month.ago } created_by { "others" } - created_by_other { Decidim::Faker::Localized.word } + created_by_other { generate_localized_word(:assembly_created_by_other, skip_injection: skip_injection) } duration { 2.months.from_now.at_midnight } included_at { 1.month.ago } closing_date { 2.months.from_now.at_midnight } - closing_date_reason { Decidim::Faker::Localized.wrapped("

", "

") { generate_localized_title } } - internal_organisation { Decidim::Faker::Localized.wrapped("

", "

") { generate_localized_title } } + closing_date_reason { generate_localized_description(:assembly_closing_date_reason, skip_injection: skip_injection) } + internal_organisation { generate_localized_description(:assembly_internal_organisation, skip_injection: skip_injection) } is_transparent { true } - special_features { Decidim::Faker::Localized.wrapped("

", "

") { generate_localized_title } } + special_features { generate_localized_description(:assembly_special_features, skip_injection: skip_injection) } twitter_handler { "others" } facebook_handler { "others" } instagram_handler { "others" } youtube_handler { "others" } github_handler { "others" } weight { 1 } - announcement { generate_localized_title } + announcement { generate_localized_title(:assembly_announcement, skip_injection: skip_injection) } trait :with_type do - assembly_type { create :assemblies_type, organization: organization } + assembly_type { create :assemblies_type, organization: organization, skip_injection: skip_injection } end trait :promoted do @@ -76,7 +79,7 @@ end trait :with_parent do - parent { create :assembly, organization: organization } + parent { create :assembly, organization: organization, skip_injection: skip_injection } end trait :public do @@ -97,13 +100,17 @@ end factory :assembly_user_role, class: "Decidim::AssemblyUserRole" do + transient do + skip_injection { false } + end user - assembly { create :assembly, organization: user.organization } + assembly { create :assembly, organization: user.organization, skip_injection: skip_injection } role { "admin" } end factory :assembly_admin, parent: :user, class: "Decidim::User" do transient do + skip_injection { false } assembly { create(:assembly) } end @@ -114,12 +121,14 @@ create :assembly_user_role, user: user, assembly: evaluator.assembly, - role: :admin + role: :admin, + skip_injection: evaluator.skip_injection end end factory :assembly_moderator, parent: :user, class: "Decidim::User" do transient do + skip_injection { false } assembly { create(:assembly) } end @@ -130,12 +139,14 @@ create :assembly_user_role, user: user, assembly: evaluator.assembly, - role: :moderator + role: :moderator, + skip_injection: evaluator.skip_injection end end factory :assembly_collaborator, parent: :user, class: "Decidim::User" do transient do + skip_injection { false } assembly { create(:assembly) } end @@ -146,12 +157,14 @@ create :assembly_user_role, user: user, assembly: evaluator.assembly, + skip_injection: evaluator.skip_injection, role: :collaborator end end factory :assembly_valuator, parent: :user, class: "Decidim::User" do transient do + skip_injection { false } assembly { create(:assembly) } end @@ -162,13 +175,16 @@ create :assembly_user_role, user: user, assembly: evaluator.assembly, - role: :valuator + role: :valuator, + skip_injection: evaluator.skip_injection end end factory :assembly_member, class: "Decidim::AssemblyMember" do - assembly { create(:assembly) } - + transient do + skip_injection { false } + end + assembly { create(:assembly, skip_injection: skip_injection) } full_name { Faker::Name.name } gender { Faker::Lorem.word } birthday { Faker::Date.birthday(min_age: 18, max_age: 65) } @@ -181,7 +197,7 @@ end trait :with_user do - user { create(:user, organization: assembly.organization) } + user { create(:user, organization: assembly.organization, skip_injection: skip_injection) } end end end diff --git a/decidim-assemblies/lib/decidim/assemblies/version.rb b/decidim-assemblies/lib/decidim/assemblies/version.rb index eeaf05eb5cda7..3b3d57e9dde7d 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.27.5" + "0.27.6" end end end diff --git a/decidim-assemblies/spec/events/decidim/assemblies/create_assembly_member_event_spec.rb b/decidim-assemblies/spec/events/decidim/assemblies/create_assembly_member_event_spec.rb index 19782e2e89f64..7b259bb5f9f25 100644 --- a/decidim-assemblies/spec/events/decidim/assemblies/create_assembly_member_event_spec.rb +++ b/decidim-assemblies/spec/events/decidim/assemblies/create_assembly_member_event_spec.rb @@ -3,16 +3,16 @@ require "spec_helper" describe Decidim::Assemblies::CreateAssemblyMemberEvent do - let(:assembly) { create :assembly } - let(:resource) { assembly } + include_context "when a simple event" + + let(:resource) { create(:assembly, title: generate_localized_title(:assembly_title)) } + let(:participatory_space) { resource } let(:event_name) { "decidim.events.assemblies.create_assembly_member" } - let(:assembly_title) { translated(assembly.title) } - let(:email_subject) { "You have been invited to be a member of the #{assembly_title} assembly!" } - let(:email_intro) { %(An admin of the #{assembly_title} assembly has added you as one of its members.) } + let(:email_subject) { "You have been invited to be a member of the #{resource_title} assembly!" } + let(:email_intro) { %(An admin of the #{resource_title} assembly has added you as one of its members.) } let(:email_outro) { %(You have received this notification because you have been invited to an assembly. Check the assembly page to contribute!) } - let(:notification_title) { %(You have been registered as a member of Assembly #{assembly_title}. Check the assembly page to contribute!) } + let(:notification_title) { %(You have been registered as a member of Assembly #{resource_title}. Check the assembly page to contribute!) } - include_context "when a simple event" it_behaves_like "a simple event" it_behaves_like "a simple event email" it_behaves_like "a simple event notification" diff --git a/decidim-assemblies/spec/events/decidim/role_assigned_to_assembly_event_spec.rb b/decidim-assemblies/spec/events/decidim/role_assigned_to_assembly_event_spec.rb index cec0cbc431c46..bdfe4604e7a67 100644 --- a/decidim-assemblies/spec/events/decidim/role_assigned_to_assembly_event_spec.rb +++ b/decidim-assemblies/spec/events/decidim/role_assigned_to_assembly_event_spec.rb @@ -5,14 +5,15 @@ describe Decidim::RoleAssignedToAssemblyEvent do include_context "when a simple event" - let(:resource) { create :assembly, title: { en: "It's my assembly" } } + let(:resource) { create(:assembly, title: generate_localized_title(:assembly_title)) } + let(:participatory_space) { resource } let(:event_name) { "decidim.events.assembly.role_assigned" } let(:role) { create :assembly_user_role, user: user, assembly: resource, role: :admin } let(:extra) { { role: role } } - let(:email_subject) { "You have been assigned as #{role} for \"#{resource.title["en"]}\"." } - let(:email_outro) { "You have received this notification because you are #{role} of the \"#{resource.title["en"]}\" assembly." } - let(:email_intro) { "You have been assigned as #{role} for assembly \"#{resource.title["en"]}\"." } - let(:notification_title) { "You have been assigned as #{role} for assembly #{resource.title["en"]}." } + let(:email_subject) { "You have been assigned as #{role} for \"#{resource_title}\"." } + let(:email_outro) { "You have received this notification because you are #{role} of the \"#{resource_title}\" assembly." } + let(:email_intro) { "You have been assigned as #{role} for assembly \"#{resource_title}\"." } + let(:notification_title) { "You have been assigned as #{role} for assembly #{resource_title}." } it_behaves_like "a simple event" it_behaves_like "a simple event email" diff --git a/decidim-assemblies/spec/presenters/decidim/resource_locator_presenter_spec.rb b/decidim-assemblies/spec/presenters/decidim/resource_locator_presenter_spec.rb new file mode 100644 index 0000000000000..0a225db6ad76f --- /dev/null +++ b/decidim-assemblies/spec/presenters/decidim/resource_locator_presenter_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + describe ResourceLocatorPresenter, type: :helper do + it_behaves_like "generates routes without query strings on slug" do + let(:route_fragment) { "assemblies/#{participatory_space.slug}" } + let(:admin_route_fragment) { "assemblies/#{participatory_space.slug}" } + let(:factory_name) { :assembly } + end + end +end diff --git a/decidim-assemblies/spec/requests/assembly_search_spec.rb b/decidim-assemblies/spec/requests/assembly_search_spec.rb index 4e37580d5a8e2..972dc184cba11 100644 --- a/decidim-assemblies/spec/requests/assembly_search_spec.rb +++ b/decidim-assemblies/spec/requests/assembly_search_spec.rb @@ -37,16 +37,16 @@ end it "displays all assemblies by default" do - expect(subject).to include(translated(assembly1.title)) - expect(subject).to include(translated(assembly2.title)) + expect(subject).to include(decidim_escape_translated(assembly1.title)) + expect(subject).to include(decidim_escape_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)) + expect(subject).to include(decidim_escape_translated(assembly1.title)) + expect(subject).not_to include(decidim_escape_translated(assembly2.title)) end end @@ -54,8 +54,8 @@ 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)) + expect(subject).to include(decidim_escape_translated(assembly1.title)) + expect(subject).not_to include(decidim_escape_translated(assembly2.title)) end end @@ -63,8 +63,8 @@ let(:filter_params) { { with_any_scope: [assembly1.scope.id] } } it "displays matching assemblies" do - expect(subject).to include(translated(assembly1.title)) - expect(subject).not_to include(translated(assembly2.title)) + expect(subject).to include(decidim_escape_translated(assembly1.title)) + expect(subject).not_to include(decidim_escape_translated(assembly2.title)) end end 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 index 6fe823375b1d7..24af4ff99b804 100644 --- a/decidim-assemblies/spec/shared/assembly_admin_manage_assembly_components_examples.rb +++ b/decidim-assemblies/spec/shared/assembly_admin_manage_assembly_components_examples.rb @@ -192,7 +192,16 @@ click_link "Publish" end - expect(enqueued_jobs.last[:args]).to include("decidim.events.components.component_published") + expect(Decidim::EventPublisherJob).to(have_been_enqueued.with( + "decidim.events.components.component_published", { + resource: component, + event_class: "Decidim::ComponentPublishedEvent", + affected_users: [], + followers: [follower], + force_send: false, + extra: {} + } + )) end end diff --git a/decidim-assemblies/spec/shared/manage_assembly_components_examples.rb b/decidim-assemblies/spec/shared/manage_assembly_components_examples.rb index f76958a76662f..c8b2e9a5aa592 100644 --- a/decidim-assemblies/spec/shared/manage_assembly_components_examples.rb +++ b/decidim-assemblies/spec/shared/manage_assembly_components_examples.rb @@ -192,7 +192,16 @@ click_link "Publish" end - expect(enqueued_jobs.last[:args]).to include("decidim.events.components.component_published") + expect(Decidim::EventPublisherJob).to(have_been_enqueued.with( + "decidim.events.components.component_published", { + resource: component, + event_class: "Decidim::ComponentPublishedEvent", + affected_users: [], + followers: [follower], + force_send: false, + extra: {} + } + )) end it_behaves_like "manage component share tokens" diff --git a/decidim-blogs/config/locales/bg.yml b/decidim-blogs/config/locales/bg.yml index 3b89e84a44541..8032d6b8adaa0 100644 --- a/decidim-blogs/config/locales/bg.yml +++ b/decidim-blogs/config/locales/bg.yml @@ -12,3 +12,30 @@ bg: blogs: actions: confirm_destroy: Сигурни ли сте, че желаете да изтриете тази публикация? + admin: + models: + post: + name: Публикация + posts: + create: + invalid: Възникна проблем при създаването на тази публикация + success: Публикацията беше създадена успешно + destroy: + success: Публикацията беше изтрита успешно + update: + success: Публикацията беше запазена успешно + last_activity: + new_post_at_html: "Нова публикация на %{link}" + models: + post: + fields: + created_at: Създадена на + posts: + show: + back: Назад към списъка + comments: Коментари + view: Преглед + sidebar_blog: + comments: коментари + most_commented_posts: Най-коментирани публикации + read_more: Прочетете повече diff --git a/decidim-blogs/config/locales/ca.yml b/decidim-blogs/config/locales/ca.yml index 6fd6091870a2e..3cc64c63a514c 100644 --- a/decidim-blogs/config/locales/ca.yml +++ b/decidim-blogs/config/locales/ca.yml @@ -93,7 +93,7 @@ ca: blogs: post_created: email_intro: La publicació "%{resource_title}" s'ha publicat al "%{participatory_space_title}", el qual segueixes. - email_outro: Has rebut aquesta notificació perquè estàs seguint "%{participatory_space_title}". Pots deixar de seguir-lo des de l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint l'espai "%{participatory_space_title}". Pots deixar de seguir-lo des de l'enllaç anterior. email_subject: Nova publicació publicada a %{participatory_space_title} notification_title: La publicació %{resource_title} ha estat publicada a %{participatory_space_title} statistics: diff --git a/decidim-blogs/config/locales/ga-IE.yml b/decidim-blogs/config/locales/ga-IE.yml index d5a20266867b8..187096b21d52c 100644 --- a/decidim-blogs/config/locales/ga-IE.yml +++ b/decidim-blogs/config/locales/ga-IE.yml @@ -41,6 +41,9 @@ ga: comments: tráchtanna components: blogs: + actions: + comment: Tabhair Trácht + endorse: Formhuinigh name: Blag settings: step: diff --git a/decidim-blogs/config/locales/he-IL.yml b/decidim-blogs/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-blogs/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-blogs/config/locales/it.yml b/decidim-blogs/config/locales/it.yml index 9a9593c763bdd..f0156de1106ce 100644 --- a/decidim-blogs/config/locales/it.yml +++ b/decidim-blogs/config/locales/it.yml @@ -57,6 +57,9 @@ it: read_more: Leggi di più components: blogs: + actions: + comment: Commento + endorse: Appoggia name: blog settings: global: diff --git a/decidim-blogs/config/locales/lb.yml b/decidim-blogs/config/locales/lb.yml index 5a65b967973e6..8410857bab35d 100644 --- a/decidim-blogs/config/locales/lb.yml +++ b/decidim-blogs/config/locales/lb.yml @@ -57,6 +57,9 @@ lb: read_more: Weiterlesen components: blogs: + actions: + comment: Kommentar + endorse: Bestätigen name: Blog settings: global: diff --git a/decidim-blogs/config/locales/pt.yml b/decidim-blogs/config/locales/pt.yml index 7cfc7c690b0e6..ef315d2f4a71f 100644 --- a/decidim-blogs/config/locales/pt.yml +++ b/decidim-blogs/config/locales/pt.yml @@ -57,6 +57,9 @@ pt: read_more: Ler mais components: blogs: + actions: + comment: Comentar + endorse: Apoiar name: Blog settings: global: diff --git a/decidim-blogs/config/locales/sq-AL.yml b/decidim-blogs/config/locales/sq-AL.yml index 44ddadc95a8f3..20a75156d4b0a 100644 --- a/decidim-blogs/config/locales/sq-AL.yml +++ b/decidim-blogs/config/locales/sq-AL.yml @@ -1 +1,80 @@ +--- sq: + activemodel: + attributes: + post: + body: Përmbajtja + decidim_author_id: Autor + published_at: Koha e publikimit + title: Titulli + models: + decidim/blogs/create_post_event: Postim i ri + activerecord: + models: + decidim/blogs/post: + one: Postim + other: Postimet + decidim: + blogs: + actions: + author_id: Krijo postimin si + confirm_destroy: Je i sigurt që dëshiron ta fshish këtë postim? + destroy: Fshij + edit: Përpuno + new: Postim i ri + title: Veprime + admin: + posts: + edit: + save: Përditëso + title: Përpuno postimin + index: + title: Postimet + new: + create: Krijo + title: Krijo postimin + update: + invalid: Ndodhi një problem gjatë krijimit të këtij postimi. + admin_log: + post: + create: "%{user_name} krijoi postimin %{resource_name} në %{space_name}" + delete: "%{user_name} fshiu postimin %{resource_name} nga %{space_name}" + update: "%{user_name} përditësoi postimin %{resource_name} në %{space_name}" + models: + post: + fields: + author: Autor + body: Përmbajtja + official_blog_post: Postimi zyrtar + title: Titulli + posts: + index: + empty: Nuk ka ende postime. + components: + blogs: + actions: + comment: Koment + create: Krijo + destroy: Fshij + endorse: Mirato + update: Përditëso + name: Blog + settings: + global: + announcement: Njoftim + comments_enabled: Komentet janë aktivizuar + comments_max_length: Gjatësia maksimale e komenteve (Lëre 0 për vlerën e paracaktuar) + step: + announcement: Njoftim + comments_blocked: Komentet të bllokuara + endorsements_blocked: Mbështetjet të bllokuara + endorsements_enabled: Mbështetjet të aktivizuara + events: + blogs: + post_created: + email_intro: Postimi "%{resource_title}" është publikuar në "%{participatory_space_title}" që ju po ndiqni. + email_outro: Ju e keni marrë këtë njoftim sepse po ndiqni %{participatory_space_title}. Mund t'i ndaloni njoftimet me anë të linkut të mëparshëm. + email_subject: Postimi i ri i publikuar në %{participatory_space_title} + notification_title: Postimi %{resource_title} është publikuar në %{participatory_space_title} + statistics: + posts_count: Postimet diff --git a/decidim-blogs/lib/decidim/blogs/test/factories.rb b/decidim-blogs/lib/decidim/blogs/test/factories.rb index 5a4f537c62059..5db33b27f4058 100644 --- a/decidim-blogs/lib/decidim/blogs/test/factories.rb +++ b/decidim-blogs/lib/decidim/blogs/test/factories.rb @@ -6,21 +6,32 @@ FactoryBot.define do factory :post_component, parent: :component do - name { Decidim::Components::Namer.new(participatory_space.organization.available_locales, :blogs).i18n_name } + transient do + skip_injection { false } + end + + name { generate_component_name(participatory_space.organization.available_locales, :blogs, skip_injection: skip_injection) } manifest_name { :blogs } - participatory_space { create(:participatory_process, :with_steps, organization: organization) } + participatory_space { create(:participatory_process, :with_steps, skip_injection: skip_injection, organization: organization) } end factory :post, class: "Decidim::Blogs::Post" do - title { generate_localized_title } - body { Decidim::Faker::Localized.wrapped("

", "

") { generate_localized_title } } - component { build(:component, manifest_name: "blogs") } - author { build(:user, :confirmed, organization: component.organization) } + transient do + skip_injection { false } + end + + title { generate_localized_title(:blog_title, skip_injection: skip_injection) } + body { generate_localized_description(:blog_body, skip_injection: skip_injection) } + component { build(:post_component, skip_injection: skip_injection) } + author { build(:user, :confirmed, skip_injection: skip_injection, organization: component.organization) } trait :with_endorsements do - after :create do |post| + after :create do |post, evaluator| 5.times.collect do - create(:endorsement, resource: post, author: build(:user, organization: post.participatory_space.organization)) + create(:endorsement, + resource: post, + skip_injection: evaluator.skip_injection, + author: build(:user, skip_injection: evaluator.skip_injection, organization: post.participatory_space.organization)) end end end diff --git a/decidim-blogs/lib/decidim/blogs/version.rb b/decidim-blogs/lib/decidim/blogs/version.rb index 150109209348e..e73e11274e73c 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.27.5" + "0.27.6" end end end diff --git a/decidim-blogs/spec/events/decidim/blogs/create_post_event_spec.rb b/decidim-blogs/spec/events/decidim/blogs/create_post_event_spec.rb index a981bd33d6db6..4f4f9d40f03ae 100644 --- a/decidim-blogs/spec/events/decidim/blogs/create_post_event_spec.rb +++ b/decidim-blogs/spec/events/decidim/blogs/create_post_event_spec.rb @@ -3,14 +3,15 @@ require "spec_helper" describe Decidim::Blogs::CreatePostEvent do - let(:resource) { create :post } + include_context "when a simple event" + + let(:resource) { create(:post, title: generate_localized_title(:blog_title)) } let(:event_name) { "decidim.events.blogs.post_created" } let(:email_intro) { "The post \"#{resource_title}\" has been published in \"#{participatory_space_title}\" that you are following." } let(:email_outro) { "You have received this notification because you are following \"#{participatory_space_title}\". You can unfollow it from the previous link." } let(:notification_title) { "The post #{resource_title} has been published in #{participatory_space_title}" } let(:email_subject) { "New post published in #{participatory_space_title}" } - include_context "when a simple event" it_behaves_like "a simple event" it_behaves_like "a simple event email" it_behaves_like "a simple event notification" diff --git a/decidim-blogs/spec/events/decidim/resource_endorsed_event_spec.rb b/decidim-blogs/spec/events/decidim/resource_endorsed_event_spec.rb index 2d978f92779ab..adb7feccc428e 100644 --- a/decidim-blogs/spec/events/decidim/resource_endorsed_event_spec.rb +++ b/decidim-blogs/spec/events/decidim/resource_endorsed_event_spec.rb @@ -3,7 +3,7 @@ require "spec_helper" describe Decidim::ResourceEndorsedEvent do - let(:resource) { create :post, title: { en: "My blog post" } } + let(:resource) { create(:post, title: generate_localized_title(:blog_title)) } let(:resource_type) { "Post" } let(:resource_text) { resource.body } diff --git a/decidim-blogs/spec/types/integration_schema_spec.rb b/decidim-blogs/spec/types/integration_schema_spec.rb index 8291173c90b35..c9a7fdbb17c74 100644 --- a/decidim-blogs/spec/types/integration_schema_spec.rb +++ b/decidim-blogs/spec/types/integration_schema_spec.rb @@ -50,7 +50,7 @@ { "__typename" => "Blogs", "id" => current_component.id.to_s, - "name" => { "translation" => "Blog" }, + "name" => { "translation" => translated(current_component.name) }, "posts" => { "edges" => [ { diff --git a/decidim-budgets/app/cells/decidim/budgets/base_cell.rb b/decidim-budgets/app/cells/decidim/budgets/base_cell.rb index c87c297f9adcb..fa60018348532 100644 --- a/decidim-budgets/app/cells/decidim/budgets/base_cell.rb +++ b/decidim-budgets/app/cells/decidim/budgets/base_cell.rb @@ -13,7 +13,7 @@ class BaseCell < Decidim::ViewModel delegate :settings, to: :current_component def budgets_link_list(budgets) - budgets.map { |budget| link_to(translated_attribute(budget.title), resource_locator(budget).path) } + budgets.map { |budget| link_to(decidim_escape_translated(budget.title), resource_locator(budget).path) } .to_sentence .html_safe end diff --git a/decidim-budgets/app/cells/decidim/budgets/budget_list_item/show.erb b/decidim-budgets/app/cells/decidim/budgets/budget_list_item/show.erb index 2cb1828c124af..96ff03e5a1db4 100644 --- a/decidim-budgets/app/cells/decidim/budgets/budget_list_item/show.erb +++ b/decidim-budgets/app/cells/decidim/budgets/budget_list_item/show.erb @@ -2,7 +2,7 @@
<%= link_to budget_path(budget), class: link_class do %>

- <%= translated_attribute(title) %> + <%= decidim_escape_translated(title) %>

<% end %> diff --git a/decidim-budgets/app/cells/decidim/budgets/budgets_list/voted.erb b/decidim-budgets/app/cells/decidim/budgets/budgets_list/voted.erb index 8ff0d6b5dcc41..0b9c4c4c3a434 100644 --- a/decidim-budgets/app/cells/decidim/budgets/budgets_list/voted.erb +++ b/decidim-budgets/app/cells/decidim/budgets/budgets_list/voted.erb @@ -32,7 +32,7 @@ <% voted.each do |budget| %>
  • <%= link_to( - t("cancel_order.more_than_one", scope: i18n_scope, name: translated_attribute(budget.title)), + t("cancel_order.more_than_one", scope: i18n_scope, name: decidim_escape_translated(budget.title)), budget_order_path(budget), method: :delete, class: "cancel-order", diff --git a/decidim-budgets/app/cells/decidim/budgets/project_list_item_cell.rb b/decidim-budgets/app/cells/decidim/budgets/project_list_item_cell.rb index b6a176136bea3..12754df4709a8 100644 --- a/decidim-budgets/app/cells/decidim/budgets/project_list_item_cell.rb +++ b/decidim-budgets/app/cells/decidim/budgets/project_list_item_cell.rb @@ -21,7 +21,7 @@ def resource_path end def resource_title - translated_attribute model.title + decidim_escape_translated model.title end def resource_added? diff --git a/decidim-budgets/app/controllers/decidim/budgets/line_items_controller.rb b/decidim-budgets/app/controllers/decidim/budgets/line_items_controller.rb index d4c6fac6cdd9c..87c707dd32c2c 100644 --- a/decidim-budgets/app/controllers/decidim/budgets/line_items_controller.rb +++ b/decidim-budgets/app/controllers/decidim/budgets/line_items_controller.rb @@ -12,15 +12,21 @@ def create enforce_permission_to :vote, :project, project: project, budget: budget, workflow: current_workflow respond_to do |format| - AddLineItem.call(persisted_current_order, project, current_user) do - on(:ok) do |order| - self.current_order = order - format.html { redirect_back(fallback_location: budget_path(budget)) } - format.js { render "update_budget" } - end - - on(:invalid) do - format.js { render "update_budget", status: :unprocessable_entity } + # Note that the user-specific lock here is important in order to + # prevent multiple simultaneous processes on different machines from + # creating multiple orders for the same user in case the button is + # pressed multiple times. + current_user.with_lock do + AddLineItem.call(persisted_current_order, project, current_user) do + on(:ok) do |order| + self.current_order = order + format.html { redirect_back(fallback_location: budget_path(budget)) } + format.js { render "update_budget" } + end + + on(:invalid) do + format.js { render "update_budget", status: :unprocessable_entity } + end end end end diff --git a/decidim-budgets/app/packs/src/decidim/budgets/exit_handler.js b/decidim-budgets/app/packs/src/decidim/budgets/exit_handler.js index b0c20aa2f434a..88e80e2ab5df5 100644 --- a/decidim-budgets/app/packs/src/decidim/budgets/exit_handler.js +++ b/decidim-budgets/app/packs/src/decidim/budgets/exit_handler.js @@ -65,7 +65,7 @@ $(() => { } $exitLink.attr("href", url); - $exitLink.html(exitLinkText); + $exitLink.text(exitLinkText); $exitNotification.foundation("open"); }; 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 45fd4da31422d..6f776204f6627 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 @@ -27,7 +27,9 @@ <%= t("models.budget.fields.name", scope: "decidim.budgets") %> <%= t("models.budget.fields.total_budget", scope: "decidim.budgets") %> <%= t("models.budget.fields.projects_count", scope: "decidim.budgets") %> - <%= th_resource_scope_label %> + <% if current_component.has_subscopes? %> + <%= th_resource_scope_label %> + <% end %> <%= t("actions.title", scope: "decidim.budgets") %> @@ -43,7 +45,9 @@ <%= link_to budget.projects.count, budget_projects_path(budget) %> - <%= td_resource_scope_for(budget.scope) %> + <% if current_component.has_subscopes? %> + <%= td_resource_scope_for(budget.scope) %> + <% end %> <%= icon_link_to "eye", resource_locator(budget).path, t("actions.preview", scope: "decidim.budgets"), class: "action-icon--preview", target: :blank %> 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 index 39f02d0f17113..b2d11f08da25d 100644 --- 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 @@ -13,7 +13,9 @@ <%= translated_attribute project.category.name %> <% end %> - <%= td_resource_scope_for(project.scope) %> + <% if current_component.has_subscopes? %> + <%= td_resource_scope_for(project.scope) %> + <% end %> <%= project.confirmed_orders_count %> diff --git a/decidim-budgets/app/views/decidim/budgets/admin/projects/edit.html.erb b/decidim-budgets/app/views/decidim/budgets/admin/projects/edit.html.erb index 331184c14c6af..e8e2f6d950289 100644 --- a/decidim-budgets/app/views/decidim/budgets/admin/projects/edit.html.erb +++ b/decidim-budgets/app/views/decidim/budgets/admin/projects/edit.html.erb @@ -1,6 +1,6 @@ <% add_decidim_page_title("#{translated_attribute(budget.title)} - #{t(".title")}") %> <%= decidim_form_for([budget, @form], html: { class: "form edit_project" }) do |f| %> - <%= render partial: "form", object: f, locals: { title: "#{translated_attribute(budget.title)} > #{t(".title")}" } %> + <%= render partial: "form", object: f, locals: { title: "#{decidim_escape_translated(budget.title)} > #{t(".title")}" } %>
    <%= f.submit t(".update") %> 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 9f3a88fcd5fd9..c1f93a16a6ba6 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 @@ -3,7 +3,7 @@

    - <%= link_to translated_attribute(budget.title), budgets_path %> > + <%= link_to decidim_escape_translated(budget.title), budgets_path %> > <%= t(".title") %> ">
    @@ -21,7 +21,9 @@ <%= 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") ) %> - <%= th_scope_sort_link %> + <% if current_component.has_subscopes? %> + <%= th_scope_sort_link %> + <% end %> <%= sort_link(query, :confirmed_orders_count, t("index.confirmed_orders_count")) %> <%= sort_link(query, :selected, t(".selected")) %> <%= t("actions.title", scope: "decidim.budgets") %> diff --git a/decidim-budgets/app/views/decidim/budgets/admin/projects/new.html.erb b/decidim-budgets/app/views/decidim/budgets/admin/projects/new.html.erb index 0131637473c97..78115e25efa08 100644 --- a/decidim-budgets/app/views/decidim/budgets/admin/projects/new.html.erb +++ b/decidim-budgets/app/views/decidim/budgets/admin/projects/new.html.erb @@ -1,6 +1,6 @@ <% add_decidim_page_title("#{translated_attribute(budget.title)} - #{t(".title")}") %> <%= decidim_form_for([budget, @form], html: { class: "form new_project" }) do |f| %> - <%= render partial: "form", object: f, locals: { title: "#{translated_attribute(budget.title)} > #{t(".title")}" } %> + <%= render partial: "form", object: f, locals: { title: "#{decidim_escape_translated(budget.title)} > #{t(".title")}" } %>
    <%= f.submit t(".create") %> diff --git a/decidim-budgets/config/locales/bg.yml b/decidim-budgets/config/locales/bg.yml index f3e54121ea951..7d2271338bcc2 100644 --- a/decidim-budgets/config/locales/bg.yml +++ b/decidim-budgets/config/locales/bg.yml @@ -7,7 +7,123 @@ bg: decidim_scope_id: Сфера decidim: budgets: + actions: + new: Ново %{name} + admin: + budgets: + create: + invalid: Възникна проблем при създаването на този бюджет + success: Бюджетът беше създаден успешно + destroy: + invalid: Възникна проблем при изтриването на този бюджет + success: Бюджетът беше изтрит успешно + update: + invalid: Възникна проблем при актуализирането на този бюджет + success: Бюджетът беше актуализиран успешно + projects: + create: + invalid: Възникна проблем при създаването на този проект + success: Проектът беше създаден успешно + destroy: + success: Проектът беше изтрит успешно + update: + invalid: Възникна проблем при актуализирането на този проект + success: Проектът беше актуализиран успешно + update_category: + select_a_category: Моля, изберете категория + select_a_project: Моля, изберете проект + update_scope: + select_a_project: Моля, изберете проект + select_a_scope: Моля, изберете обхват + update_selected: + select_a_project: Моля, изберете проект + select_a_selection: Моля, изберете състояние на внедряване + proposals_imports: + create: + invalid: Възникна проблем при импортирането на предложенията в проектите + success: "%{number} предложения бяха импортирани успешно в проекти" + new: + title: Импортиране на предложения + budget: + view: Преглед на всички бюджетни проекти + budget_list_item: + voting_finished: Вие гласувахте този бюджет + voting_started: Вие започнахте да гласувате за този бюджет + budgets_list: + finished_message: Завършихте процеса на гласуване. Благодарим Ви за участието! + if_change_opinion: Ако сте размислили, имате възможност + my_budgets: Моите бюджети + voted_on: Гласувахте на %{links} + last_activity: + new_vote_at_html: "Ново бюджетно гласуване на %{link}" + limit_announcement: + cant_vote: Не можете да гласувате за този бюджет. Опитайте с друг бюджет. models: project: fields: scope: Сфера + projects: + budget_excess: + budget_excess: + description: Този проект надвишава максималния бюджет и не може да бъде добавен. Ако искате, можете да изтриете проект, който вече сте избрали, за да може да се гласува отново, според вашите предпочитания. + close: Затвори + description: Този проект надвишава максималния бюджет и не може да бъде добавен. Ако искате, можете да изтриете проект, който вече сте избрали, за да може да се гласува отново, според вашите предпочитания. + budget_summary: + assigned: 'Възложен:' + cancel_order: изтрийте гласа си и започнете отначало + checked_out: + description: Вече сте гласували за бюджета. Ако сте размислили, имате възможност %{cancel_link}. + minimum_projects_rule: + description: За кои проекти смятате, че трябва да осигурим бюджет? Изберете най-малко %{minimum_number} желани от Вас проекта и гласувайте, според предпочитанията си за дефиниране на бюджета. + instruction: "
  • Изберете поне %{minimum_number} желани от Вас проекта и гласувайте, според предпочитанията си за дефиниране на бюджета.
  • " + projects_rule: + description: За какви проекти смятате, че трябва да отделим бюджет? Изберете най-малко %{minimum_number}, но не повече от %{maximum_number} желани от Вас проекта и гласувайте, според предпочитанията си за дефиниране на бюджета. + instruction: "
  • Изберете най-малко %{minimum_number}, но не повече от %{maximum_number} желани от Вас проекта и гласувайте, според предпочитанията си за дефиниране на бюджета.
  • " + projects_rule_maximum_only: + description: За кои проекти смятате, че трябва да осигурим бюджет? Изберете не повече от %{maximum_number} желани от Вас проекта и гласувайте, според предпочитанията си за дефиниране на бюджета. + instruction: "
  • Изберете не повече от %{maximum_number} желани от Вас проекта и гласувайте, според предпочитанията си за дефиниране на бюджета.
  • " + rules: + title: Бюджетни правила + title: Вие решавате бюджета + total_projects: Общ брой гласове + vote_threshold_percent_rule: + description: За кои проекти смятате, че трябва да осигурим бюджет? Присъеденете най-малко %{minimum_budget} към желаните от Вас проекти и гласувайте, според предпочитанията си за дефиниране на бюджета. + instruction: "
  • Присъеденете поне %{minimum_budget} към желаните от вас проекти и гласувайте, според предпочитанията си за дефиниране на бюджета.
  • " + filters_small_view: + filter: Филтър + filter_by: Филтрирай по + unfold: Разгъване + index: + view_project: Преглед на проекта + order_selected_projects: + remove: Премахни + selected_projects: + one: избран проект + other: избрани проекти + view: Преглед + project: + add: Добавяне на проект %{resource_name} към Вашето гласуване + remove: Премахване на проекта %{resource_name} от Вашето гласуване + view: Преглед + project_budget_button: + add: Добавяне към гласуването Ви + add_descriptive: Добавяне на проект %{resource_name} към Вашето гласуване + added: Добавено към Вашето гласуване + added_descriptive: Проектът %{resource_name} е добавен към Вашето гласуване + show: + view_all_projects: Преглед на всички проекти + components: + budgets: + settings: + global: + form: + errors: + budget_voting_rule_only_one: Трябва да бъде активирано само едно правило за гласуване + budget_voting_rule_required: Изисква се едно правило за гласуване + orders: + checkout: + error: Възникна проблем при обработването на Вашия глас + success: Вашият глас е приет успешно + destroy: + error: Възникна проблем при отмяната на гласа Ви + success: Вашият глас беше отменен успешно diff --git a/decidim-budgets/config/locales/ca.yml b/decidim-budgets/config/locales/ca.yml index 28941a1e6aa8f..c4c1a60b07a50 100644 --- a/decidim-budgets/config/locales/ca.yml +++ b/decidim-budgets/config/locales/ca.yml @@ -368,7 +368,7 @@ ca: budgets: budget_published: email_intro: 'Ja està activa la fase %{resource_title} per a %{participatory_space_title}. Pots veure-la des d''aquesta pàgina:' - email_outro: Has rebut aquesta notificació perquè estàs seguint l'espai %{participatory_space_title}. Pots deixar de rebre notificacions a través de l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint l'espai "%{participatory_space_title}". Pots deixar de rebre notificacions a través de l'enllaç anterior. email_subject: El component %{resource_title} ja està actiu per %{participatory_space_title}. notification_title: El pressupost %{resource_title} a %{participatory_space_title} ja està actiu. orders: diff --git a/decidim-budgets/config/locales/es.yml b/decidim-budgets/config/locales/es.yml index d68a1f8af810e..9be6fb7319498 100644 --- a/decidim-budgets/config/locales/es.yml +++ b/decidim-budgets/config/locales/es.yml @@ -368,7 +368,7 @@ es: budgets: budget_published: email_intro: 'Ya está activa la fase %{resource_title} para %{participatory_space_title}. Puedes verla desde esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo %{participatory_space_title}. Puedes dejar de recibir notificaciones siguiendo el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo el espacio "%{participatory_space_title}". Puedes dejar de recibir notificaciones siguiendo el enlace anterior. email_subject: El componente %{resource_title} está ahora activo para %{participatory_space_title}. notification_title: El presupuesto %{resource_title} en %{participatory_space_title} ya está activo. orders: diff --git a/decidim-budgets/config/locales/he-IL.yml b/decidim-budgets/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-budgets/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-budgets/config/locales/sq-AL.yml b/decidim-budgets/config/locales/sq-AL.yml index 44ddadc95a8f3..a980761781955 100644 --- a/decidim-budgets/config/locales/sq-AL.yml +++ b/decidim-budgets/config/locales/sq-AL.yml @@ -1 +1,53 @@ +--- sq: + activemodel: + attributes: + budget: + decidim_scope_id: Fushëveprimi + description: Përshkrimi + title: Titulli + total_budget: Buxheti total + weight: Rendit pozicionet + project: + budget_amount: Shuma buxhetore + decidim_category_id: Kategori + decidim_scope_id: Fushëveprim + description: Përshkrimi + proposal_ids: Propozime të ngjashme + proposals: Propozimet + selected: Përzgjedhur për zbatim + title: Titulli + proposals_import: + scope_id: Fushëveprim + activerecord: + models: + decidim/budgets/project: + one: Projekt + other: Projektet + decidim: + admin: + filters: + projects: + category_id_eq: + label: Kategori + scope_id_eq: + label: Qëllimi + selected_at_null: + label: E përzgjedhur + values: + 'false': Përzgjedhur për zbatim + 'true': Nuk është përzgjedhur për zbatim + budgets: + actions: + attachment_collections: Dosjet + attachments: Bashkëngjitjet + confirm_destroy: A je i sigurt që do ta fshish këtë projekt? + destroy: Fshi + edit: Përpuno + edit_projects: Menaxho projektet + import: Importo propozimet ne projekte + preview: Pamje paraprake + models: + project: + fields: + scope: Fushëveprim diff --git a/decidim-budgets/lib/decidim/budgets/test/factories.rb b/decidim-budgets/lib/decidim/budgets/test/factories.rb index 260e7122aabf3..41abf89f6fc3b 100644 --- a/decidim-budgets/lib/decidim/budgets/test/factories.rb +++ b/decidim-budgets/lib/decidim/budgets/test/factories.rb @@ -8,9 +8,12 @@ FactoryBot.define do factory :budgets_component, parent: :component do - name { Decidim::Components::Namer.new(participatory_space.organization.available_locales, :budgets).i18n_name } + transient do + skip_injection { false } + end + name { generate_component_name(participatory_space.organization.available_locales, :budgets, skip_injection: skip_injection) } manifest_name { :budgets } - participatory_space { create(:participatory_process, :with_steps, organization: organization) } + participatory_space { create(:participatory_process, :with_steps, skip_injection: skip_injection, organization: organization) } trait :with_geocoding_enabled do settings do @@ -109,10 +112,13 @@ end factory :budget, class: "Decidim::Budgets::Budget" do - title { generate_localized_title } - description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + transient do + skip_injection { false } + end + title { generate_localized_title(:budget_title, skip_injection: skip_injection) } + description { generate_localized_description(:budget_description, skip_injection: skip_injection) } total_budget { 100_000_000 } - component { create(:budgets_component) } + component { create(:budgets_component, skip_injection: skip_injection) } trait :with_projects do transient do @@ -120,19 +126,22 @@ end after(:create) do |budget, evaluator| - create_list(:project, evaluator.projects_number, budget: budget) + create_list(:project, evaluator.projects_number, skip_injection: evaluator.skip_injection, budget: budget) end end end factory :project, class: "Decidim::Budgets::Project" do - title { generate_localized_title } - description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + transient do + skip_injection { false } + end + title { generate_localized_title(:project_title, skip_injection: skip_injection) } + description { generate_localized_description(:project_description, skip_injection: skip_injection) } address { "#{Faker::Address.street_name}, #{Faker::Address.city}" } latitude { Faker::Address.latitude } longitude { Faker::Address.longitude } budget_amount { Faker::Number.number(digits: 8) } - budget { create(:budget) } + budget { create(:budget, skip_injection: skip_injection) } trait :selected do selected_at { Time.current } @@ -144,14 +153,17 @@ end after :create do |project, evaluator| - project.attachments = create_list(:attachment, evaluator.photos_number, :with_image, attached_to: project) + project.attachments = create_list(:attachment, evaluator.photos_number, :with_image, attached_to: project, skip_injection: evaluator.skip_injection) end end end factory :order, class: "Decidim::Budgets::Order" do - budget { create(:budget) } - user { create(:user, organization: component.organization) } + transient do + skip_injection { false } + end + budget { create(:budget, skip_injection: skip_injection) } + user { create(:user, organization: component.organization, skip_injection: skip_injection) } trait :with_projects do transient do @@ -160,14 +172,17 @@ after(:create) do |order, evaluator| project_budget = (order.maximum_budget / evaluator.projects_number).to_i - order.projects << create_list(:project, evaluator.projects_number, budget_amount: project_budget, budget: order.budget) + order.projects << create_list(:project, evaluator.projects_number, budget_amount: project_budget, budget: order.budget, skip_injection: evaluator.skip_injection) order.save! end end end factory :line_item, class: "Decidim::Budgets::LineItem" do + transient do + skip_injection { false } + end order - project { create(:project, budget: order.budget) } + project { create(:project, budget: order.budget, skip_injection: skip_injection) } end end diff --git a/decidim-budgets/lib/decidim/budgets/version.rb b/decidim-budgets/lib/decidim/budgets/version.rb index 711b5eef49b0d..b0e7907de0b3e 100644 --- a/decidim-budgets/lib/decidim/budgets/version.rb +++ b/decidim-budgets/lib/decidim/budgets/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-budgets version. module Budgets def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-budgets/spec/requests/line_items_spec.rb b/decidim-budgets/spec/requests/line_items_spec.rb new file mode 100644 index 0000000000000..dfdcb7d398fe3 --- /dev/null +++ b/decidim-budgets/spec/requests/line_items_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "Project search", type: :request do + include Decidim::ComponentPathHelper + + let(:user) { create(:user, :confirmed) } + let(:participatory_space) { create :participatory_process, :with_steps, organization: user.organization } + let(:component) { create(:budgets_component, participatory_space: participatory_space, settings: settings) } + let(:settings) { { vote_threshold_percent: 50 } } + let(:budget) { create(:budget, component: component, total_budget: 100_000) } + let(:project) { create(:project, budget: budget, budget_amount: 60_000) } + + let(:headers) { { "HOST" => participatory_space.organization.host } } + + before do + login_as user, scope: :user + end + + describe "POST create" do + let(:request_path) { Decidim::EngineRouter.main_proxy(component).budget_order_line_item_path(budget) } + + it "creates the order" do + expect do + post(request_path, xhr: true, params: { project_id: project.id }, headers: headers) + end.to change(Decidim::Budgets::Order, :count).by(1) + + expect(response).to have_http_status(:ok) + end + + context "when trying to add the same project twice" do + it "adds it only once" do + post(request_path, xhr: true, params: { project_id: project.id }, headers: headers) + expect(response).to have_http_status(:ok) + + post(request_path, xhr: true, params: { project_id: project.id }, headers: headers) + expect(response).to have_http_status(:unprocessable_entity) + + expect(Decidim::Budgets::Order.count).to eq(1) + expect(Decidim::Budgets::LineItem.count).to eq(1) + end + end + + context "with concurrent requests" do + include_context "with concurrency" + + before do + # Persist the session cookie before the concurrent requests. + get(Decidim::Core::Engine.routes.url_helpers.root_path, headers: headers) + end + + it "only creates a single order" do + expect do + threads = 10.times.map do + Thread.new do + sleep(rand(0.05..0.5)) + + post(request_path, xhr: true, params: { project_id: project.id }, headers: headers) + end + end + # Wait for each thread to finish + threads.each(&:join) + end.not_to raise_error + + expect(Decidim::Budgets::Order.count).to eq(1) + end + end + end +end diff --git a/decidim-budgets/spec/requests/project_search_spec.rb b/decidim-budgets/spec/requests/project_search_spec.rb index 6e290efed9f1b..b5ca9191b5d35 100644 --- a/decidim-budgets/spec/requests/project_search_spec.rb +++ b/decidim-budgets/spec/requests/project_search_spec.rb @@ -59,11 +59,11 @@ it_behaves_like "a resource search with categories", :project it "displays all projects within the budget without any filters" do - expect(subject).to include(translated(project1.title)) - expect(subject).to include(translated(project2.title)) - expect(subject).to include(translated(project3.title)) - expect(subject).not_to include(translated(project4.title)) - expect(subject).not_to include(translated(project5.title)) + expect(subject).to include(decidim_escape_translated(project1.title)) + expect(subject).to include(decidim_escape_translated(project2.title)) + expect(subject).to include(decidim_escape_translated(project3.title)) + expect(subject).not_to include(decidim_escape_translated(project4.title)) + expect(subject).not_to include(decidim_escape_translated(project5.title)) end context "when searching by status" do @@ -73,9 +73,9 @@ let(:status) { ["all"] } it "displays all projects" do - expect(subject).to include(translated(project1.title)) - expect(subject).to include(translated(project2.title)) - expect(subject).to include(translated(project3.title)) + expect(subject).to include(decidim_escape_translated(project1.title)) + expect(subject).to include(decidim_escape_translated(project2.title)) + expect(subject).to include(decidim_escape_translated(project3.title)) end end @@ -83,9 +83,9 @@ let(:status) { ["selected"] } it "displays the selected projects" do - expect(subject).to include(translated(project1.title)) - expect(subject).to include(translated(project2.title)) - expect(subject).not_to include(translated(project3.title)) + expect(subject).to include(decidim_escape_translated(project1.title)) + expect(subject).to include(decidim_escape_translated(project2.title)) + expect(subject).not_to include(decidim_escape_translated(project3.title)) end end @@ -93,9 +93,9 @@ let(:status) { ["not_selected"] } it "displays the selected projects" do - expect(subject).not_to include(translated(project1.title)) - expect(subject).not_to include(translated(project2.title)) - expect(subject).to include(translated(project3.title)) + expect(subject).not_to include(decidim_escape_translated(project1.title)) + expect(subject).not_to include(decidim_escape_translated(project2.title)) + expect(subject).to include(decidim_escape_translated(project3.title)) end end end diff --git a/decidim-budgets/spec/system/admin_manages_budgets_spec.rb b/decidim-budgets/spec/system/admin_manages_budgets_spec.rb index 5ec445ad44b83..3701af4507c3c 100644 --- a/decidim-budgets/spec/system/admin_manages_budgets_spec.rb +++ b/decidim-budgets/spec/system/admin_manages_budgets_spec.rb @@ -121,6 +121,62 @@ end end + describe "when managing a budget with scopes" do + let!(:scopes) { create_list(:subscope, 3, organization: organization, parent: scope) } + let(:scope_id) { scope.id } + let(:participatory_space) { create(:participatory_process, organization: organization, scopes_enabled: scopes_enabled) } + let!(:component) { create(:component, manifest: manifest, settings: { scopes_enabled: scopes_enabled, scope_id: scope_id }, participatory_space: participatory_space) } + let!(:budget) { create(:budget, component: current_component) } + let!(:scope) { create(:scope, organization: organization) } + let(:scopes_enabled) { true } + + before do + visit current_path + end + + context "when the scope has subscopes" do + context "when scopes_enabled is true" do + it "displays the scope column" do + expect(component).to be_scopes_enabled + expect(component).to have_subscopes + expect(page).to have_content("Scope") + end + end + + context "when scopes_enabled is false" do + let(:scopes_enabled) { false } + + it "displays the scope column" do + expect(component).not_to be_scopes_enabled + expect(component).not_to have_subscopes + expect(page).to have_no_content("Scope") + end + end + end + + context "when the scope does not have subscopes" do + let(:scope_id) { scopes.first.id } + + context "when scopes_enabled is true" do + it "hides the scope column" do + expect(component).to be_scopes_enabled + expect(component).not_to have_subscopes + expect(page).to have_no_content("Scope") + end + end + + context "when scopes_enabled is false" do + let(:scopes_enabled) { false } + + it "displays the scope column" do + expect(component).not_to be_scopes_enabled + expect(component).not_to have_subscopes + expect(page).to have_no_content("Scope") + end + end + end + end + describe "component page shows finished and pending orders of all budgets" do context "when component has many budgets with orders" do let(:budget2) { create(:budget, :with_projects, component: current_component) } diff --git a/decidim-budgets/spec/system/admin_manages_projects_spec.rb b/decidim-budgets/spec/system/admin_manages_projects_spec.rb index 67608c50a4129..f45581cbced53 100644 --- a/decidim-budgets/spec/system/admin_manages_projects_spec.rb +++ b/decidim-budgets/spec/system/admin_manages_projects_spec.rb @@ -84,5 +84,14 @@ expect(::Decidim::Budgets::Project.find(project.id).selected_at).to eq(Time.zone.today) expect(::Decidim::Budgets::Project.find(project2.id).selected_at).to eq(Time.zone.today) end + + describe "when managing a project with scopes" do + let!(:project) { create(:project, component: current_component) } + let!(:scope) { create(:scope, organization: current_component.organization) } + + it "does not display subscopes" do + expect(page).to have_no_content(scope.name) + end + end end end diff --git a/decidim-budgets/spec/system/comments_spec.rb b/decidim-budgets/spec/system/comments_spec.rb index 14fc4e339e0e2..bebf0edd9a129 100644 --- a/decidim-budgets/spec/system/comments_spec.rb +++ b/decidim-budgets/spec/system/comments_spec.rb @@ -30,9 +30,9 @@ end within_window(another_window) do - expect(page).to have_content(commentable.title["en"]) - expect(page).to have_content(comments.first.body["en"]) - expect(page).not_to have_content(comments.second.body["en"]) + expect(page).to have_content(translated(commentable.title)) + expect(page).to have_content(decidim_sanitize_translated(comments.first.body)) + expect(page).not_to have_content(decidim_sanitize_translated(comments.second.body)) end end end diff --git a/decidim-budgets/spec/system/explore_budget_notifications_spec.rb b/decidim-budgets/spec/system/explore_budget_notifications_spec.rb index d003ed28d0950..eb9f655fb911e 100644 --- a/decidim-budgets/spec/system/explore_budget_notifications_spec.rb +++ b/decidim-budgets/spec/system/explore_budget_notifications_spec.rb @@ -33,7 +33,7 @@ visit_notifications within "#notifications" do - expect(page).to have_content(translated(project.title)) + expect(page).to have_content(decidim_sanitize_translated(project.title)) end end end diff --git a/decidim-budgets/spec/system/orders_spec.rb b/decidim-budgets/spec/system/orders_spec.rb index a8ef3fbfc4bb1..e6d8715914163 100644 --- a/decidim-budgets/spec/system/orders_spec.rb +++ b/decidim-budgets/spec/system/orders_spec.rb @@ -660,8 +660,8 @@ end it "shows the component" do - expect(page).to have_i18n_content(project.title) - expect(page).to have_i18n_content(project.description) + expect(page).to have_i18n_content(project.title, strip_tags: true) + expect(page).to have_i18n_content(project.description, strip_tags: true) end context "with linked proposals" do diff --git a/decidim-budgets/spec/types/integration_schema_spec.rb b/decidim-budgets/spec/types/integration_schema_spec.rb index ec686b5bc88ad..6d19c0ac9f8fc 100644 --- a/decidim-budgets/spec/types/integration_schema_spec.rb +++ b/decidim-budgets/spec/types/integration_schema_spec.rb @@ -52,7 +52,7 @@ { "__typename" => "Budgets", "id" => current_component.id.to_s, - "name" => { "translation" => "Budgets" }, + "name" => { "translation" => translated(current_component.name) }, "budgets" => { "edges" => [ { diff --git a/decidim-comments/app/cells/decidim/comments/comment_cell.rb b/decidim-comments/app/cells/decidim/comments/comment_cell.rb index a782daea7a14d..c67a9c9b8da11 100644 --- a/decidim-comments/app/cells/decidim/comments/comment_cell.rb +++ b/decidim-comments/app/cells/decidim/comments/comment_cell.rb @@ -47,6 +47,8 @@ def cache_hash hash.push(model.must_render_translation?(current_organization) ? 1 : 0) hash.push(model.authored_by?(current_user) ? 1 : 0) hash.push(model.reported_by?(current_user) ? 1 : 0) + hash.push(model.up_votes_count) + hash.push(model.down_votes_count) hash.push(model.cache_key_with_version) hash.push(model.author.cache_key_with_version) @hash = hash.join(Decidim.cache_key_separator) @@ -146,11 +148,11 @@ def comment_path end def up_votes_count - model.up_votes.count + model.up_votes_count end def down_votes_count - model.down_votes.count + model.down_votes_count end def root_depth @@ -166,11 +168,11 @@ def reloaded? end def voted_up? - model.up_voted_by?(current_user) + @up_voted ||= model.up_voted_by?(current_user) end def voted_down? - model.down_voted_by?(current_user) + @down_voted ||= model.down_voted_by?(current_user) end def nested? diff --git a/decidim-comments/app/models/decidim/comments/comment.rb b/decidim-comments/app/models/decidim/comments/comment.rb index b3fcf0822ebf0..e82c0d7fb774b 100644 --- a/decidim-comments/app/models/decidim/comments/comment.rb +++ b/decidim-comments/app/models/decidim/comments/comment.rb @@ -29,6 +29,7 @@ class Comment < ApplicationRecord translatable_fields :body parent_item_foreign_key :decidim_commentable_id + parent_item_polymorphic_type_key :decidim_commentable_type belongs_to :commentable, foreign_key: "decidim_commentable_id", foreign_type: "decidim_commentable_type", polymorphic: true belongs_to :root_commentable, foreign_key: "decidim_root_commentable_id", foreign_type: "decidim_root_commentable_type", polymorphic: true, touch: true @@ -121,14 +122,14 @@ def users_to_notify_on_comment_created # # Returns a bool value to indicate if the condition is truthy or not def up_voted_by?(user) - up_votes.any? { |vote| vote.author == user } + up_votes.exists?(author: user) end # Public: Check if the user has downvoted the comment # # Returns a bool value to indicate if the condition is truthy or not def down_voted_by?(user) - down_votes.any? { |vote| vote.author == user } + down_votes.exists?(author: user) end # Public: Overrides the `reported_content_url` Reportable concern method. diff --git a/decidim-comments/app/models/decidim/comments/comment_vote.rb b/decidim-comments/app/models/decidim/comments/comment_vote.rb index ae05469bddc21..48324716d2f47 100644 --- a/decidim-comments/app/models/decidim/comments/comment_vote.rb +++ b/decidim-comments/app/models/decidim/comments/comment_vote.rb @@ -14,12 +14,22 @@ class CommentVote < ApplicationRecord validates :weight, inclusion: { in: [-1, 1] } validate :author_and_comment_same_organization + after_create :update_comment_votes_count + after_destroy :update_comment_votes_count + def self.export_serializer Decidim::Comments::CommentVoteSerializer end private + def update_comment_votes_count + up_votes_count = self.class.where(decidim_comment_id: comment.id, weight: 1).count + down_votes_count = self.class.where(decidim_comment_id: comment.id, weight: -1).count + + comment.update(up_votes_count: up_votes_count, down_votes_count: down_votes_count) + end + # Private: check if the comment and the author have the same organization def author_and_comment_same_organization return unless author.present? && comment.present? diff --git a/decidim-comments/config/locales/bg.yml b/decidim-comments/config/locales/bg.yml index 4b19db46b4ab8..1e0f417c279ad 100644 --- a/decidim-comments/config/locales/bg.yml +++ b/decidim-comments/config/locales/bg.yml @@ -5,3 +5,26 @@ bg: decidim/comments/comment_by_followed_user_event: Коментар decidim/comments/comment_created_event: Коментар decidim/comments/reply_created_event: Отговор на коментар + decidim: + comments: + comments: + delete: + error: Коментарът не можа да бъде изтрит. + comments_count: Брой коментари + last_activity: + new_comment_at_html: "Нов коментар на %{link}" + view: Преглед + components: + add_comment_form: + account_message: Влезте с Вашия профил или се регистрирайте, за да добавите коментара си. + form: + form_error: Текстът е задължителен и не може да е по-дълъг от %{length} символа. + comment: + report: + reasons: + does_not_belong: Съдържа незаконни дейности, заплахи за самоубийство, лична информация или нещо друго, което считате, че е неподходящо за %{organization_name}. + comment_thread: + title: Разговор с %{authorName} + errors: + messages: + cannot_have_comments: не може да има коментари diff --git a/decidim-comments/config/locales/ca.yml b/decidim-comments/config/locales/ca.yml index 06cc7f994be7f..f75a8d72ed94a 100644 --- a/decidim-comments/config/locales/ca.yml +++ b/decidim-comments/config/locales/ca.yml @@ -125,27 +125,27 @@ ca: comments: comment_by_followed_user: email_intro: "%{author_name} ha deixat un comentari a %{resource_title}. Podeu llegir-lo en aquesta pàgina:" - email_outro: Has rebut aquesta notificació perquè estàs seguint %{author_name}. Pots deixar de seguir a aquesta participant des de la seva pàgina de perfil. + email_outro: Has rebut aquesta notificació perquè estàs seguint el comentari "%{author_name}". Pots deixar de seguir a aquesta participant des de la seva pàgina de perfil. email_subject: Hi ha un nou comentari de %{author_name} en %{resource_title} notification_title: Hi ha un nou comentari per %{author_name} %{author_nickname} a %{resource_title}. comment_by_followed_user_group: email_intro: '%{author_name} ha deixat un comentari a%{resource_title}. Pots llegir-lo en aquesta pàgina:' - email_outro: Reps aquesta notificació perquè segueixes a %{author_name}. Pots deixar de seguir aquest grup des de la seva pàgina de perfil. + email_outro: Reps aquesta notificació perquè segueixes a "%{author_name}". Pots deixar de seguir aquest grup des de la seva pàgina de perfil. email_subject: Hi ha un nou comentari de %{author_name} en %{resource_title} notification_title: Hi ha un nou comentari per %{author_name} %{author_nickname} a %{resource_title}. comment_created: email_intro: "S'ha comentat %{resource_title}. Pots llegir el comentari d'aquesta pàgina:" - email_outro: Has rebut aquesta notificació perquè estàs seguint "%{resource_title}" o la seva autora. Pots deixar de seguir-la des de l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint el comentari "%{resource_title}" o la seva autora. Pots deixar de seguir-la des de l'enllaç anterior. email_subject: Hi ha un nou comentari de %{author_name} a %{resource_title} notification_title: Hi ha un nou comentari de %{author_name} %{author_nickname} en %{resource_title} comment_downvoted: email_intro: El teu comentari a "%{resource_title}" ha rebut un vot negatiu. Ara té un total de %{upvotes} vots positius i %{downvotes} vots negatius. - email_outro: Has rebut aquesta notificació perquè ets autora d'aquest comentari. + email_outro: Has rebut aquesta notificació perquè vas fer aquest comentari. email_subject: El teu comentari a "%{resource_title}" ha rebut un vot negatiu. notification_title: El teu comentari a "%{resource_title}" ha rebut un vot negatiu. Ara té un total de %{upvotes} vots positius i %{downvotes} vots negatius. comment_upvoted: email_intro: El teu comentari a "%{resource_title}" ha rebut un vot positiu. Ara té un total de %{upvotes} vots positius i %{downvotes} vots negatius. - email_outro: Has rebut aquesta notificació perquè ets autora d'aquest comentari. + email_outro: Has rebut aquesta notificació perquè vas fer aquest comentari. email_subject: El teu comentari a "%{resource_title}" ha rebut un vot positiu. notification_title: El teu comentari a "%{resource_title}" ha rebut un vot positiu. Ara té un total de %{upvotes} vots positius i %{downvotes} vots negatius. reply_created: @@ -155,12 +155,12 @@ ca: notification_title: %{author_name} %{author_nickname} ha respost el teu comentari a %{resource_title} user_group_mentioned: email_intro: Un grup al qual pertanys ha estat esmentat - email_outro: Has rebut aquesta notificació perquè formes part del grup %{group_name} que ha estat esmentat a %{resource_title}. + email_outro: Has rebut aquesta notificació perquè formes part del grup "%{group_name}" que ha estat esmentat a %{resource_title}. email_subject: T'han esmentat a %{resource_title} com a membre de %{group_name} notification_title: %{author_name} %{author_nickname} t'ha esmentat com a membre de %{group_name} %{group_nickname} a %{resource_title} user_mentioned: email_intro: Has estat esmentada - email_outro: Has rebut aquesta notificació perquè has estat esmentada a %{resource_title}. + email_outro: Has rebut aquesta notificació perquè t'han esmentat al comentari "%{resource_title}". email_subject: Has estat esmentada a %{resource_title} notification_title: Has estat esmentada a %{resource_title} per %{author_name} %{author_nickname} metrics: diff --git a/decidim-comments/config/locales/es.yml b/decidim-comments/config/locales/es.yml index c333da146be93..87b2c481a7c9d 100644 --- a/decidim-comments/config/locales/es.yml +++ b/decidim-comments/config/locales/es.yml @@ -125,7 +125,7 @@ es: comments: comment_by_followed_user: email_intro: "%{author_name} ha dejado un comentario en %{resource_title}. Puedes leerlo en esta página:" - email_outro: Has recibido esta notificación porque sigues "%{author_name}". Puedes dejar de seguir a esta participante desde su página de perfil. + email_outro: Has recibido esta notificación porque sigues a "%{author_name}". Puedes dejar de seguir a esta participante desde su página de perfil. email_subject: Hay un nuevo comentario de %{author_name} en %{resource_title} notification_title: Hay un nuevo comentario de %{author_name} %{author_nickname} en %{resource_title}. comment_by_followed_user_group: @@ -135,32 +135,32 @@ es: notification_title: Hay un nuevo comentario de %{author_name} %{author_nickname} en %{resource_title}. comment_created: email_intro: "%{resource_title} ha sido comentado. Puedes leer el comentario en esta página:" - email_outro: Has recibido esta notificación porque está siguiendo "%{resource_title}" o su autora. Puedes dejar de seguirla desde el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo el comentario "%{resource_title}" o a su autora. Puedes dejar de seguirla desde el enlace anterior. email_subject: Hay un nuevo comentario de %{author_name} en %{resource_title} notification_title: Hay un nuevo comentario de %{author_name} %{author_nickname} en %{resource_title} comment_downvoted: email_intro: Tu comentario en "%{resource_title}" ha sido votado negativamente. Ahora tiene un total de %{upvotes} votos positivos y %{downvotes} votos negativos. - email_outro: Has recibido esta notificación porque eres la autora de este comentario. + email_outro: Has recibido esta notificación porque hiciste este comentario. email_subject: Su comentario en "%{resource_title}" ha sido votado negativamente. notification_title: Tu comentario en "%{resource_title}" ha sido votado negativamente. Ahora tiene un total de %{upvotes} votos positivos y %{downvotes} votos negativos. comment_upvoted: email_intro: Tu comentario en "%{resource_title}" ha sido votado postivamente. Ahora tiene un total de %{upvotes} votos positivos y %{downvotes} votos negativos. - email_outro: Has recibido esta notificación porque eres la autora de este comentario. + email_outro: Has recibido esta notificación porque hiciste este comentario. email_subject: Tu comentario en "%{resource_title}" ha sido votado positivamente. notification_title: Tu comentario en "%{resource_title}" ha sido votado positivamente. Ahora tiene un total de %{upvotes} votos positivos y %{downvotes} votos negativos. reply_created: email_intro: "%{author_name} ha respondido a tu comentario en %{resource_title}. Puedes leerlo en esta página:" - email_outro: Has recibido esta notificación porque tu comentario fue respondido. + email_outro: Has recibido esta notificación porque han respondido a tu comentario. email_subject: "%{author_name} ha respondido a tu comentario en %{resource_title}" notification_title: %{author_name} %{author_nickname} ha respondido a tu comentario en %{resource_title} user_group_mentioned: email_intro: Se ha mencionado un grupo al que perteneces - email_outro: Has recibido esta notificación porque formas parte del grupo %{group_name} que ha sido mencionado en %{resource_title}. + email_outro: Has recibido esta notificación porque formas parte del grupo "%{group_name}" que ha sido mencionado en "%{resource_title}". email_subject: Te han mencionado en %{resource_title} como miembro de %{group_name} notification_title: %{author_name} %{author_nickname} te ha mencionado en %{resource_title} como miembro de %{group_name} %{group_nickname} user_mentioned: email_intro: Has sido mencionada - email_outro: Has recibido esta notificación porque has sido mencionada en %{resource_title}. + email_outro: Has recibido esta notificación porque te han mencionado en el comentario "%{resource_title}". email_subject: Has sido mencionada en %{resource_title} notification_title: Has sido mencionada en %{resource_title} por %{author_name} %{author_nickname} metrics: diff --git a/decidim-comments/config/locales/he-IL.yml b/decidim-comments/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-comments/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-comments/config/locales/sq-AL.yml b/decidim-comments/config/locales/sq-AL.yml index 44ddadc95a8f3..5acebda500f73 100644 --- a/decidim-comments/config/locales/sq-AL.yml +++ b/decidim-comments/config/locales/sq-AL.yml @@ -1 +1,39 @@ +--- sq: + decidim: + components: + add_comment_form: + form: + user_group_id: + label: Komento si + opinion: + label: Mendimi jot mbi këtë temë + negative: Negativ + negative_selected: Mendimi jot mbi këtë temë është negativ + neutral: Neutral + neutral_selected: Mendimi jot mbi këtë temë është neutral + positive: Pozitiv + positive_selected: Mendimi jot mbi këtë temë është pozitiv + remaining_characters: "%{count} karaktere të mbetura" + remaining_characters_1: "%{count} karakter i mbetur" + title: Shto komentin tënd + comment: + alignment: + against: Kundër + in_favor: Pro + confirm_destroy: A je i sigurt që do ta fshish këtë koment? + delete: Fshi + deleted_at: Komenti u fshi në datën %{date} + edit: Përpuno + edited: Ndryshuar + hide_replies: Fshih përgjigjet + moderated_at: Komenti u moderua në datën %{date} + reply: Përgjigju + report: + action: Raporto + already_reported: Kjo përmbajtje është raportuar nga të tjerë dhe do rishikohet nga administratorët. + close: Mbyll + description: Përmbajtje e papërshtatshme? + details: Komente të tjera + reasons: + offensive: Përmban racizëm, seksizëm, ofendime, sulme personale, kërcënime me vdekje, shtyrje për vetëvrasje apo forma të tjera të gjuhës së urrejtjes. diff --git a/decidim-comments/db/migrate/20240304092558_add_comment_vote_counter_cache_to_comments.rb b/decidim-comments/db/migrate/20240304092558_add_comment_vote_counter_cache_to_comments.rb new file mode 100644 index 0000000000000..8055094f543f1 --- /dev/null +++ b/decidim-comments/db/migrate/20240304092558_add_comment_vote_counter_cache_to_comments.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class AddCommentVoteCounterCacheToComments < ActiveRecord::Migration[6.1] + def change + add_column :decidim_comments_comments, :up_votes_count, :integer, null: false, default: 0, index: true + add_column :decidim_comments_comments, :down_votes_count, :integer, null: false, default: 0, index: true + + # We cannot use the reset_counters as up_votes and down_votes are scoped associationws + reversible do |dir| + dir.up do + Decidim::Comments::Comment.reset_column_information + Decidim::Comments::Comment.find_each do |record| + # rubocop:disable Rails/SkipsModelValidations + record.class.update_counters(record.id, up_votes_count: record.up_votes.length) + record.class.update_counters(record.id, down_votes_count: record.down_votes.length) + # rubocop:enable Rails/SkipsModelValidations + end + end + end + end +end diff --git a/decidim-comments/lib/decidim/api/comment_type.rb b/decidim-comments/lib/decidim/api/comment_type.rb index acdcbfa5eb01e..2232be67db38c 100644 --- a/decidim-comments/lib/decidim/api/comment_type.rb +++ b/decidim-comments/lib/decidim/api/comment_type.rb @@ -58,7 +58,7 @@ def formatted_created_at end def up_votes - object.up_votes.size + object.up_votes_count end def up_voted @@ -66,7 +66,7 @@ def up_voted end def down_votes - object.down_votes.size + object.down_votes_count end def down_voted diff --git a/decidim-comments/lib/decidim/comments/test/factories.rb b/decidim-comments/lib/decidim/comments/test/factories.rb index dda8423b5df25..5e46a72093991 100644 --- a/decidim-comments/lib/decidim/comments/test/factories.rb +++ b/decidim-comments/lib/decidim/comments/test/factories.rb @@ -4,8 +4,11 @@ FactoryBot.define do factory :comment, class: "Decidim::Comments::Comment" do - author { build(:user, organization: commentable.organization) } - commentable { build(:dummy_resource) } + transient do + skip_injection { false } + end + author { build(:user, organization: commentable.organization, skip_injection: skip_injection) } + commentable { build(:dummy_resource, skip_injection: skip_injection) } root_commentable { commentable } body { Decidim::Faker::Localized.paragraph } participatory_space { commentable.try(:participatory_space) } @@ -25,22 +28,26 @@ end trait :comment_on_comment do - author { build(:user, organization: root_commentable.organization) } + author { build(:user, organization: root_commentable.organization, skip_injection: skip_injection) } commentable do build( :comment, author: author, root_commentable: root_commentable, - commentable: root_commentable + commentable: root_commentable, + skip_injection: skip_injection ) end - root_commentable { build(:dummy_resource) } + root_commentable { build(:dummy_resource, skip_injection: skip_injection) } end end factory :comment_vote, class: "Decidim::Comments::CommentVote" do - comment { build(:comment) } - author { build(:user, organization: comment.organization) } + transient do + skip_injection { false } + end + comment { build(:comment, skip_injection: skip_injection) } + author { build(:user, organization: comment.organization, skip_injection: skip_injection) } weight { [-1, 1].sample } trait :up_vote do diff --git a/decidim-comments/lib/decidim/comments/test/shared_examples/comment_event.rb b/decidim-comments/lib/decidim/comments/test/shared_examples/comment_event.rb index 0b97df767bc58..3b69bff6409e7 100644 --- a/decidim-comments/lib/decidim/comments/test/shared_examples/comment_event.rb +++ b/decidim-comments/lib/decidim/comments/test/shared_examples/comment_event.rb @@ -16,7 +16,7 @@ let(:comment_author_name) { decidim_html_escape comment.author.name } let(:extra) { { comment_id: comment.id } } - let(:resource_title) { decidim_html_escape(translated(resource.title)) } + let(:resource_title) { decidim_sanitize_translated(resource.title) } let(:user_group) do user_group = create(:user_group, :verified, organization: organization, users: [comment_author]) comment.update!(user_group: user_group) diff --git a/decidim-comments/lib/decidim/comments/test/shared_examples/comment_voted_event.rb b/decidim-comments/lib/decidim/comments/test/shared_examples/comment_voted_event.rb index 74822712afc13..88c279ed234a7 100644 --- a/decidim-comments/lib/decidim/comments/test/shared_examples/comment_voted_event.rb +++ b/decidim-comments/lib/decidim/comments/test/shared_examples/comment_voted_event.rb @@ -12,7 +12,7 @@ let(:comment_vote_author) { comment_vote.author } let(:extra) { { comment_id: comment.id, author_id: comment_vote_author.id, weight: weight, downvotes: 100, upvotes: 999 } } - let(:resource_title) { decidim_html_escape(translated(resource.title)) } + let(:resource_title) { decidim_sanitize_translated(resource.title) } let(:resource_text) { subject.resource_text } let(:verb) { weight.positive? ? "upvoted" : "downvoted" } diff --git a/decidim-comments/lib/decidim/comments/version.rb b/decidim-comments/lib/decidim/comments/version.rb index 521ee69d5d8aa..3cb23ffa203cb 100644 --- a/decidim-comments/lib/decidim/comments/version.rb +++ b/decidim-comments/lib/decidim/comments/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-comments version. module Comments def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-comments/spec/events/decidim/comments/comment_downvoted_event_spec.rb b/decidim-comments/spec/events/decidim/comments/comment_downvoted_event_spec.rb index f1a19b0e9472e..c2adc43b59689 100644 --- a/decidim-comments/spec/events/decidim/comments/comment_downvoted_event_spec.rb +++ b/decidim-comments/spec/events/decidim/comments/comment_downvoted_event_spec.rb @@ -10,8 +10,8 @@ it_behaves_like "a comment voted event" do let(:parent_comment) { create(:comment) } let(:comment) { create :comment, commentable: parent_comment, root_commentable: parent_comment.root_commentable } - let(:resource_title) { decidim_html_escape(translated(resource.commentable.title)) } let(:resource_path) { resource_locator(resource.commentable).path } + let(:resource_title) { decidim_sanitize_translated(parent_comment.root_commentable.title) } end end @@ -19,7 +19,6 @@ it_behaves_like "a comment voted event" do let(:resource) { comment.commentable } let(:comment) { create :comment } - let(:resource_title) { decidim_html_escape(translated(resource.title)) } it_behaves_like "a translated comment event" do let(:translatable) { false } diff --git a/decidim-comments/spec/events/decidim/comments/comment_upvoted_event_spec.rb b/decidim-comments/spec/events/decidim/comments/comment_upvoted_event_spec.rb index 6d1632cf8569a..8a0f35d7201f3 100644 --- a/decidim-comments/spec/events/decidim/comments/comment_upvoted_event_spec.rb +++ b/decidim-comments/spec/events/decidim/comments/comment_upvoted_event_spec.rb @@ -10,8 +10,8 @@ it_behaves_like "a comment voted event" do let(:parent_comment) { create(:comment) } let(:comment) { create :comment, commentable: parent_comment, root_commentable: parent_comment.root_commentable } - let(:resource_title) { decidim_html_escape(translated(resource.commentable.title)) } let(:resource_path) { resource_locator(resource.commentable).path } + let(:resource_title) { decidim_sanitize_translated(parent_comment.root_commentable.title) } end end @@ -19,7 +19,6 @@ it_behaves_like "a comment voted event" do let(:resource) { comment.commentable } let(:comment) { create :comment } - let(:resource_title) { decidim_html_escape(translated(resource.title)) } it_behaves_like "a translated comment event" do let(:translatable) { false } diff --git a/decidim-comments/spec/events/decidim/comments/reply_created_event_spec.rb b/decidim-comments/spec/events/decidim/comments/reply_created_event_spec.rb index d175d3f2a4bf0..509a336b74d3d 100644 --- a/decidim-comments/spec/events/decidim/comments/reply_created_event_spec.rb +++ b/decidim-comments/spec/events/decidim/comments/reply_created_event_spec.rb @@ -8,10 +8,10 @@ let(:comment) { create :comment, commentable: parent_comment, root_commentable: parent_comment.root_commentable } let(:parent_comment) { create :comment } let(:resource) { comment.root_commentable } - let(:email_subject) { "#{comment_author_name} has replied your comment in #{translated resource.title}" } + let(:email_subject) { "#{comment_author_name} has replied your comment in #{resource_title}" } let(:email_intro) { "#{comment_author_name} has replied your comment in #{resource_title}. You can read it in this page:" } let(:email_outro) { "You have received this notification because your comment was replied." } - let(:notification_title) { "#{comment_author_name} @#{comment_author.nickname} has replied your comment in #{translated resource.title}" } + let(:notification_title) { "#{comment_author_name} @#{comment_author.nickname} has replied your comment in #{resource_title}" } it_behaves_like "a simple event email" it_behaves_like "a simple event notification" diff --git a/decidim-comments/spec/events/decidim/comments/user_group_mentioned_event_spec.rb b/decidim-comments/spec/events/decidim/comments/user_group_mentioned_event_spec.rb index 766cd00ba48a2..b61fe2cde605b 100644 --- a/decidim-comments/spec/events/decidim/comments/user_group_mentioned_event_spec.rb +++ b/decidim-comments/spec/events/decidim/comments/user_group_mentioned_event_spec.rb @@ -24,9 +24,9 @@ let(:parsed_body) { Decidim::ContentProcessor.parse("Comment mentioning some user group, @#{group.nickname}", current_organization: organization) } let(:parsed_ca_body) { Decidim::ContentProcessor.parse("Un commentaire pour @#{group.nickname}", current_organization: organization) } let(:body) { { en: parsed_body.rewrite, machine_translations: { ca: parsed_ca_body.rewrite } } } - let(:email_subject) { "You have been mentioned in #{html_escape(translated(resource.title))} as a member of #{html_escape(group.name)}" } + let(:email_subject) { "You have been mentioned in #{resource_title} as a member of #{html_escape(group.name)}" } let(:email_intro) { "A group you belong to has been mentioned" } - let(:email_outro) { "You have received this notification because you are a member of the group #{html_escape(group.name)} that has been mentioned in #{html_escape(translated(resource.title))}." } + let(:email_outro) { "You have received this notification because you are a member of the group #{html_escape(group.name)} that has been mentioned in #{resource_title}." } it_behaves_like "a comment event" it_behaves_like "a simple event email" @@ -61,7 +61,7 @@ describe "notification_title" do it "is generated correctly" do expect(subject.notification_title) - .to include("You have been mentioned in #{html_escape(translated(resource.title))}") + .to include("You have been mentioned in #{resource_title}") expect(subject.notification_title) .to include(" as a member of #{html_escape(group.name)} @#{group.nickname}") diff --git a/decidim-comments/spec/events/decidim/comments/user_mentioned_event_spec.rb b/decidim-comments/spec/events/decidim/comments/user_mentioned_event_spec.rb index addfb894df2b6..b77eb0d2bee8c 100644 --- a/decidim-comments/spec/events/decidim/comments/user_mentioned_event_spec.rb +++ b/decidim-comments/spec/events/decidim/comments/user_mentioned_event_spec.rb @@ -22,10 +22,10 @@ let(:author) { create :user, organization: organization } let!(:comment) { create :comment, body: body, author: author, commentable: commentable } let(:user) { create :user, organization: organization, locale: "ca" } - let(:notification_title) { "You have been mentioned in #{translated resource.title} by #{author.name} @#{author.nickname}" } - let(:email_subject) { "You have been mentioned in #{translated resource.title}" } + let(:notification_title) { "You have been mentioned in #{resource_title} by #{author.name} @#{author.nickname}" } + let(:email_subject) { "You have been mentioned in #{resource_title}" } let(:email_intro) { "You have been mentioned" } - let(:email_outro) { "You have received this notification because you have been mentioned in #{translated resource.title}." } + let(:email_outro) { "You have received this notification because you have been mentioned in #{resource_title}." } it_behaves_like "a comment event" it_behaves_like "a simple event email" diff --git a/decidim-comments/spec/models/comment_spec.rb b/decidim-comments/spec/models/comment_spec.rb index a5bc0e7e14b5a..3b277e3e12b55 100644 --- a/decidim-comments/spec/models/comment_spec.rb +++ b/decidim-comments/spec/models/comment_spec.rb @@ -47,10 +47,12 @@ module Comments it "has a up_votes association returning comment votes with weight 1" do expect(comment.up_votes.count).to eq(1) + expect(comment.up_votes_count).to eq(1) end it "has a down_votes association returning comment votes with weight -1" do expect(comment.down_votes.count).to eq(1) + expect(comment.down_votes_count).to eq(1) end it "has an associated participatory_process" do diff --git a/decidim-comments/spec/models/comment_vote_spec.rb b/decidim-comments/spec/models/comment_vote_spec.rb index 9eaba3ddbdda5..1230f253bd712 100644 --- a/decidim-comments/spec/models/comment_vote_spec.rb +++ b/decidim-comments/spec/models/comment_vote_spec.rb @@ -42,6 +42,24 @@ module Comments comment_vote = build(:comment_vote, comment: comment, author: author) expect(comment_vote).to be_invalid end + + context "when it is a downvote" do + let!(:comment_vote) { create(:comment_vote, comment: comment, author: author, weight: -1) } + + it "updates the comment votes count after creation" do + expect(comment.up_votes_count).to eq(0) + expect(comment.down_votes_count).to eq(1) + end + end + + context "when it is an upvote" do + let!(:comment_vote) { create(:comment_vote, comment: comment, author: author, weight: 1) } + + it "updates the comment votes count after creation" do + expect(comment.up_votes_count).to eq(1) + expect(comment.down_votes_count).to eq(0) + end + end end end end diff --git a/decidim-conferences/app/cells/decidim/conferences/conference_address/show.erb b/decidim-conferences/app/cells/decidim/conferences/conference_address/show.erb index f71461b96c5fa..fb88cecb64803 100644 --- a/decidim-conferences/app/cells/decidim/conferences/conference_address/show.erb +++ b/decidim-conferences/app/cells/decidim/conferences/conference_address/show.erb @@ -1,11 +1,11 @@
    <% if model.respond_to? :location %>
    - <%= translated_attribute model.location %>
    + <%= decidim_escape_translated model.location %>
    <% end %>
    <%= model.address %>
    <% if model.respond_to? :location_hints %> -
    <%= translated_attribute model.location_hints %>
    +
    <%= decidim_escape_translated model.location_hints %>
    <% end %>
    diff --git a/decidim-conferences/app/cells/decidim/conferences/conference_m_cell.rb b/decidim-conferences/app/cells/decidim/conferences/conference_m_cell.rb index c6b7b5480cd42..04086a184ff1c 100644 --- a/decidim-conferences/app/cells/decidim/conferences/conference_m_cell.rb +++ b/decidim-conferences/app/cells/decidim/conferences/conference_m_cell.rb @@ -14,10 +14,6 @@ def current_participatory_space private - def title - decidim_html_escape(super) - end - def has_image? true end diff --git a/decidim-conferences/app/cells/decidim/conferences/conference_speaker_cell.rb b/decidim-conferences/app/cells/decidim/conferences/conference_speaker_cell.rb index 4aa2c8e019690..67416f7ab7eb1 100644 --- a/decidim-conferences/app/cells/decidim/conferences/conference_speaker_cell.rb +++ b/decidim-conferences/app/cells/decidim/conferences/conference_speaker_cell.rb @@ -60,7 +60,7 @@ def affiliation def short_bio return unless model.short_bio.presence - translated_attribute model.short_bio + decidim_escape_translated model.short_bio end def twitter_handle diff --git a/decidim-conferences/app/cells/decidim/conferences/content_blocks/highlighted_conferences/show.erb b/decidim-conferences/app/cells/decidim/conferences/content_blocks/highlighted_conferences/show.erb index 77d9b6534fd78..a36e4d1f2324e 100644 --- a/decidim-conferences/app/cells/decidim/conferences/content_blocks/highlighted_conferences/show.erb +++ b/decidim-conferences/app/cells/decidim/conferences/content_blocks/highlighted_conferences/show.erb @@ -10,7 +10,7 @@
    - <%= translated_attribute conference.title %> + <%= decidim_escape_translated conference.title %>
    <% end %>
    diff --git a/decidim-conferences/app/events/decidim/conferences/conference_registration_notification_event.rb b/decidim-conferences/app/events/decidim/conferences/conference_registration_notification_event.rb index 78f645c322752..5e53d34a6f3f7 100644 --- a/decidim-conferences/app/events/decidim/conferences/conference_registration_notification_event.rb +++ b/decidim-conferences/app/events/decidim/conferences/conference_registration_notification_event.rb @@ -4,6 +4,7 @@ module Decidim module Conferences class ConferenceRegistrationNotificationEvent < Decidim::Events::BaseEvent include Decidim::Events::NotificationEvent + include Decidim::SanitizeHelper def notification_title I18n.t("notification_title", **i18n_options).html_safe @@ -12,10 +13,19 @@ def notification_title def i18n_options { resource_title: resource_title, + resource_path: resource_path, resource_url: resource_url, scope: event_name } end + + def resource_title + return unless resource + + title = decidim_sanitize_translated(resource.title) + + Decidim::ContentProcessor.render_without_format(title, links: false).html_safe + end end end end diff --git a/decidim-conferences/app/views/decidim/conferences/conference_program/_program_meeting.html.erb b/decidim-conferences/app/views/decidim/conferences/conference_program/_program_meeting.html.erb index ad8ed6ef8a848..12551faaaa3ba 100644 --- a/decidim-conferences/app/views/decidim/conferences/conference_program/_program_meeting.html.erb +++ b/decidim-conferences/app/views/decidim/conferences/conference_program/_program_meeting.html.erb @@ -3,7 +3,7 @@ <%= start_time.to_s(:time) %> - <%= end_time.to_s(:time) %>

    - <%= link_to present(meeting).title, resource_locator(meeting).path %> + <%= link_to decidim_sanitize(present(meeting).title), resource_locator(meeting).path %>
    diff --git a/decidim-conferences/config/locales/bg.yml b/decidim-conferences/config/locales/bg.yml index b024f8164a24a..4a1a346480a7b 100644 --- a/decidim-conferences/config/locales/bg.yml +++ b/decidim-conferences/config/locales/bg.yml @@ -6,3 +6,87 @@ bg: assemblies_ids: Свързани събрания banner_image: Банер изображение consultations_ids: Свързани консултации + errors: + models: + conference_registration_invite: + attributes: + email: + already_invited: На този имейл вече е изпратена покана + decidim: + admin: + actions: + new_conference: Нова конференция + conferences: + index: + not_published: Не публикувано + menu: + conferences_submenu: + info: Информация + conferences: + admin: + conference_invites: + index: + filter: + accepted: Прието + all: Всички + rejected: Отхвърлен + filter_by: Филтрирай по + new: + explanation: Участникът ще бъде поканен да се присъедини към конференция. Дори имейлът му да не е регистриран, той също ще бъде поканен в организацията. + conference: + show: + free: Свободно + conference_program: + program_meeting: + content: Съдържание + streaming: Стриймване + show: + day: Ден + conference_registrations: + create: + unauthorized: Трябва да влезете в акаунта си, преди да се регистрирате за конференцията. + decline_invitation: + unauthorized: Трябва да влезете в акаунта си, преди да откажете поканата. + conference_speaker_cell: + twitter_handle: + go_to_twitter: Към Twitter + conferences: + show: + make_conference_registration: 'Регистрирайте се за конференцията:' + mailer: + conference_registration_mailer: + confirmation: + subject: Регистрацията Ви за конференцията е потвърдена + pending_validation: + subject: Регистрацията Ви за конференцията очаква потвърждение + pages: + home: + highlighted_conferences: + active_conferences: Активни конференции + conferences_button_title: Връзка към страницата „Конференции“, на която се показват всички конференции + photo: + image: + attributes: + alt: Медийно изображение + show: + close_modal: Затвори прозореца + photo: Изображение + photos_list: + show: + related_photos: Изображения + shared: + conference_user_login: + already_account: Имате ли вече профил в CivilPower? + new_user: Нов потребител? + sign_in: Влезте в профила си, за да се регистрирате за конференцията + sign_up: Създайте си профил в CivilPower, за да се регистрирате за конференцията + show: + related_consultations: Свързани консултации + log: + value_types: + conference_presenter: + not_found: 'Конференцията не бе намерена в базата данни (Идент. №: %{id})' + layouts: + decidim: + conferences_nav: + conference_menu_item: Информация diff --git a/decidim-conferences/config/locales/ca.yml b/decidim-conferences/config/locales/ca.yml index fd2fa87117e7a..3c96849d85326 100644 --- a/decidim-conferences/config/locales/ca.yml +++ b/decidim-conferences/config/locales/ca.yml @@ -546,7 +546,7 @@ ca: notification_title: La teva inscripció a jornada %{resource_title} està pendent de confirmació. conference_registrations_over_percentage: email_intro: Les places ocupades per a la jornada "%{resource_title}" superen el %{percentage}%. - email_outro: Has rebut aquesta notificació perquè ets administradora de l'espai participatiu de la jornada. + email_outro: Has rebut aquesta notificació perquè administres l'espai participatiu de la jornada. email_subject: Les places ocupades per a la jornada "%{resource_title}" superen el %{percentage}% notification_title: Les places ocupades per a la jornada %{resource_title} superen el %{percentage}%. conference_updated: diff --git a/decidim-conferences/config/locales/he-IL.yml b/decidim-conferences/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-conferences/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-conferences/lib/decidim/conferences/test/factories.rb b/decidim-conferences/lib/decidim/conferences/test/factories.rb index 6af3b7db5a1b6..c9507c5fc70dd 100644 --- a/decidim-conferences/lib/decidim/conferences/test/factories.rb +++ b/decidim-conferences/lib/decidim/conferences/test/factories.rb @@ -10,12 +10,15 @@ end factory :conference, class: "Decidim::Conference" do - title { generate_localized_title } + transient do + skip_injection { false } + end + title { generate_localized_title(:conference_title, skip_injection: skip_injection) } slug { generate(:conference_slug) } - slogan { generate_localized_title } - short_description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } - description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } - objectives { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + slogan { generate_localized_title(:conference_slogan, skip_injection: skip_injection) } + short_description { generate_localized_description(:conference_short_description, skip_injection: skip_injection) } + description { generate_localized_description(:conference_description, skip_injection: skip_injection) } + objectives { generate_localized_description(:conference_objectives, skip_injection: skip_injection) } organization hero_image { Decidim::Dev.test_file("city.jpeg", "image/jpeg") } # Keep after organization banner_image { Decidim::Dev.test_file("city2.jpeg", "image/jpeg") } # Keep after organization @@ -24,7 +27,7 @@ show_statistics { true } start_date { 1.month.ago } end_date { 1.month.ago + 3.days } - registration_terms { generate_localized_title } + registration_terms { generate_localized_title(:conference_registration_terms, skip_injection: skip_injection) } trait :promoted do promoted { true } @@ -47,14 +50,18 @@ end factory :conference_user_role, class: "Decidim::ConferenceUserRole" do + transient do + skip_injection { false } + end user - conference { create :conference, organization: user.organization } + conference { create :conference, organization: user.organization, skip_injection: skip_injection } role { "admin" } end factory :conference_admin, parent: :user, class: "Decidim::User" do transient do - conference { create(:conference) } + skip_injection { false } + conference { create(:conference, skip_injection: skip_injection) } end organization { conference.organization } @@ -64,13 +71,15 @@ create :conference_user_role, user: user, conference: evaluator.conference, - role: :admin + role: :admin, + skip_injection: evaluator.skip_injection end end factory :conference_moderator, parent: :user, class: "Decidim::User" do transient do - conference { create(:conference) } + skip_injection { false } + conference { create(:conference, skip_injection: skip_injection) } end organization { conference.organization } @@ -80,13 +89,15 @@ create :conference_user_role, user: user, conference: evaluator.conference, - role: :moderator + role: :moderator, + skip_injection: evaluator.skip_injection end end factory :conference_collaborator, parent: :user, class: "Decidim::User" do transient do - conference { create(:conference) } + skip_injection { false } + conference { create(:conference, skip_injection: skip_injection) } end organization { conference.organization } @@ -96,13 +107,15 @@ create :conference_user_role, user: user, conference: evaluator.conference, - role: :collaborator + role: :collaborator, + skip_injection: evaluator.skip_injection end end factory :conference_valuator, parent: :user, class: "Decidim::User" do transient do - conference { create(:conference) } + skip_injection { false } + conference { create(:conference, skip_injection: skip_injection) } end organization { conference.organization } @@ -112,17 +125,21 @@ create :conference_user_role, user: user, conference: evaluator.conference, - role: :valuator + role: :valuator, + skip_injection: evaluator.skip_injection end end factory :conference_speaker, class: "Decidim::ConferenceSpeaker" do - conference { create(:conference) } + transient do + skip_injection { false } + end + conference { create(:conference, skip_injection: skip_injection) } full_name { Faker::Name.name } position { Decidim::Faker::Localized.word } affiliation { Decidim::Faker::Localized.word } - short_bio { generate_localized_title } + short_bio { generate_localized_title(:conference_speaker_short_bio, skip_injection: skip_injection) } twitter_handle { Faker::Internet.user_name } personal_url { Faker::Internet.url } @@ -131,58 +148,66 @@ end trait :with_user do - user { create(:user, organization: conference.organization) } + user { create(:user, organization: conference.organization, skip_injection: skip_injection) } end trait :with_meeting do transient do - meetings_component { create(:meetings_component, participatory_space: conference.participatory_space) } + meetings_component { create(:meetings_component, participatory_space: conference.participatory_space, skip_injection: skip_injection) } end after :build do |conference_speaker, evaluator| conference_speaker.conference_speaker_conference_meetings << build(:conference_speaker_conference_meeting, meetings_component: evaluator.meetings_component, - conference_speaker: conference_speaker) + conference_speaker: conference_speaker, + skip_injection: evaluator.skip_injection) end end end factory :conference_speaker_conference_meeting, class: "Decidim::ConferenceSpeakerConferenceMeeting" do transient do - conference { create(:conference) } - meetings_component { create(:meetings_component, participatory_space: conference.participatory_space) } + skip_injection { false } + conference { create(:conference, skip_injection: skip_injection) } + meetings_component { create(:meetings_component, skip_injection: skip_injection, participatory_space: conference.participatory_space) } end - conference_meeting { create(:conference_meeting, :published, conference: conference, component: meetings_component) } - conference_speaker { create(:conference_speaker, conference: conference) } + conference_meeting { create(:conference_meeting, :published, conference: conference, skip_injection: skip_injection, component: meetings_component) } + conference_speaker { create(:conference_speaker, conference: conference, skip_injection: skip_injection) } end factory :conference_meeting_registration_type, class: "Decidim::Conferences::ConferenceMeetingRegistrationType" do transient do - conference { create(:conference) } + skip_injection { false } + conference { create(:conference, skip_injection: skip_injection) } end conference_meeting - registration_type { build(:registration_type, conference: conference) } + registration_type { build(:registration_type, conference: conference, skip_injection: skip_injection) } end factory :conference_meeting, parent: :meeting, class: "Decidim::ConferenceMeeting" do transient do - conference { create(:conference) } + skip_injection { false } + conference { create(:conference, skip_injection: skip_injection) } end after :build do |conference_meeting, evaluator| conference_meeting.conference_meeting_registration_types << build(:conference_meeting_registration_type, conference_meeting: conference_meeting, - conference: evaluator.conference) + conference: evaluator.conference, + skip_injection: evaluator.skip_injection) end end factory :registration_type, class: "Decidim::Conferences::RegistrationType" do + transient do + skip_injection { false } + end conference - title { generate_localized_title } - description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + title { generate_localized_title(:registration_type_title, skip_injection: skip_injection) } + description { generate_localized_description(:registration_type_description, skip_injection: skip_injection) } published_at { Time.current } price { Faker::Number.between(from: 1, to: 300) } weight { Faker::Number.between(from: 1, to: 10) } @@ -197,6 +222,9 @@ end factory :conference_registration, class: "Decidim::Conferences::ConferenceRegistration" do + transient do + skip_injection { false } + end conference user registration_type @@ -212,6 +240,9 @@ end factory :conference_invite, class: "Decidim::Conferences::ConferenceInvite" do + transient do + skip_injection { false } + end conference user sent_at { 1.day.ago } @@ -229,6 +260,9 @@ end factory :partner, class: "Decidim::Conferences::Partner" do + transient do + skip_injection { false } + end conference name { Faker::Name.name } @@ -247,8 +281,11 @@ end factory :media_link, class: "Decidim::Conferences::MediaLink" do + transient do + skip_injection { false } + end conference - title { generate_localized_title } + title { generate_localized_title(:media_link_title, skip_injection: skip_injection) } weight { Faker::Number.between(from: 1, to: 10) } link { Faker::Internet.url } date { 1.month.ago } diff --git a/decidim-conferences/lib/decidim/conferences/version.rb b/decidim-conferences/lib/decidim/conferences/version.rb index b5cadeee9bae0..dc8a33bb86586 100644 --- a/decidim-conferences/lib/decidim/conferences/version.rb +++ b/decidim-conferences/lib/decidim/conferences/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-conferences version. module Conferences def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-conferences/spec/commands/join_conference_spec.rb b/decidim-conferences/spec/commands/join_conference_spec.rb index 4675ea48ee53c..ce8769c2289e1 100644 --- a/decidim-conferences/spec/commands/join_conference_spec.rb +++ b/decidim-conferences/spec/commands/join_conference_spec.rb @@ -52,7 +52,7 @@ module Decidim::Conferences email = last_email expect(email.subject).to include("pending") - expect(email.body.encoded).to include(translated(registration_type.title)) + expect(email.text_part.body.to_s.split.join(" ")).to include(translated(registration_type.title)) end it "sends a notification to the user with the pending validation" do diff --git a/decidim-conferences/spec/events/decidim/conferences/conference_registration_notification_event_spec.rb b/decidim-conferences/spec/events/decidim/conferences/conference_registration_notification_event_spec.rb new file mode 100644 index 0000000000000..6665ce6c10a82 --- /dev/null +++ b/decidim-conferences/spec/events/decidim/conferences/conference_registration_notification_event_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe Decidim::Conferences::ConferenceRegistrationNotificationEvent do + let(:resource) { create(:conference) } + let(:event_name) { "decidim.events.conferences.conference_registration_validation_pending" } + let(:user) { create(:user, organization: organization) } + + include_context "when a simple event" do + let(:participatory_space) { resource } + end + + describe "notification_title" do + it "includes the subject" do + expect(subject.notification_title).to include("Your registration for the conference #{participatory_space_title} is pending to be confirmed.") + end + end +end diff --git a/decidim-conferences/spec/events/decidim/conferences/conference_registrations_enabled_event_spec.rb b/decidim-conferences/spec/events/decidim/conferences/conference_registrations_enabled_event_spec.rb index 146b9136d92aa..6cb8eca3340bd 100644 --- a/decidim-conferences/spec/events/decidim/conferences/conference_registrations_enabled_event_spec.rb +++ b/decidim-conferences/spec/events/decidim/conferences/conference_registrations_enabled_event_spec.rb @@ -3,9 +3,11 @@ require "spec_helper" describe Decidim::Conferences::ConferenceRegistrationsEnabledEvent do - let(:resource) { create :conference } + include_context "when a simple event" + + let(:resource) { create(:conference, title: generate_localized_title(:conference_title)) } + let(:participatory_space) { resource } let(:event_name) { "decidim.events.conferences.registrations_enabled" } - include_context "when a simple event" it_behaves_like "a simple event" end diff --git a/decidim-conferences/spec/events/decidim/conferences/conference_registrations_over_percentage_event_spec.rb b/decidim-conferences/spec/events/decidim/conferences/conference_registrations_over_percentage_event_spec.rb index 84cae96bd2fa4..1c764a9783891 100644 --- a/decidim-conferences/spec/events/decidim/conferences/conference_registrations_over_percentage_event_spec.rb +++ b/decidim-conferences/spec/events/decidim/conferences/conference_registrations_over_percentage_event_spec.rb @@ -5,7 +5,8 @@ describe Decidim::Conferences::ConferenceRegistrationsOverPercentageEvent do include_context "when a simple event" - let(:resource) { create :conference } + let(:resource) { create(:conference, title: generate_localized_title(:conference_title)) } + let(:participatory_space) { resource } let(:event_name) { "decidim.events.conferences.conference_registrations_over_percentage" } let(:extra) { { percentage: 1.1 } } diff --git a/decidim-conferences/spec/events/decidim/conferences/conference_role_assigned_event_spec.rb b/decidim-conferences/spec/events/decidim/conferences/conference_role_assigned_event_spec.rb index 7e7de900948a6..ffd92f6498843 100644 --- a/decidim-conferences/spec/events/decidim/conferences/conference_role_assigned_event_spec.rb +++ b/decidim-conferences/spec/events/decidim/conferences/conference_role_assigned_event_spec.rb @@ -5,14 +5,15 @@ describe Decidim::Conferences::ConferenceRoleAssignedEvent do include_context "when a simple event" - let(:resource) { create :conference, title: { en: "It's my conference" } } + let(:resource) { create(:conference, title: generate_localized_title(:conference_title)) } + let(:participatory_space) { resource } let(:event_name) { "decidim.events.conferences.role_assigned" } let(:role) { create :conference_user_role, user: user, conference: resource, role: :admin } let(:extra) { { role: role } } - let(:email_subject) { "You have been assigned as #{role} for \"#{resource.title["en"]}\"." } - let(:email_outro) { "You have received this notification because you are #{role} of the \"#{resource.title["en"]}\" conference." } - let(:email_intro) { "You have been assigned as #{role} for conference \"#{resource.title["en"]}\"." } - let(:notification_title) { "You have been assigned as #{role} for conference #{resource.title["en"]}." } + let(:email_subject) { "You have been assigned as #{role} for \"#{resource_title}\"." } + let(:email_outro) { "You have received this notification because you are #{role} of the \"#{resource_title}\" conference." } + let(:email_intro) { "You have been assigned as #{role} for conference \"#{resource_title}\"." } + let(:notification_title) { "You have been assigned as #{role} for conference #{resource_title}." } it_behaves_like "a simple event" it_behaves_like "a simple event email" diff --git a/decidim-conferences/spec/events/decidim/conferences/upcoming_conference_event_spec.rb b/decidim-conferences/spec/events/decidim/conferences/upcoming_conference_event_spec.rb index cd7145bcc919d..576de05e1e5ef 100644 --- a/decidim-conferences/spec/events/decidim/conferences/upcoming_conference_event_spec.rb +++ b/decidim-conferences/spec/events/decidim/conferences/upcoming_conference_event_spec.rb @@ -3,9 +3,11 @@ require "spec_helper" describe Decidim::Conferences::UpcomingConferenceEvent do - let(:resource) { create :conference } + include_context "when a simple event" + + let(:resource) { create(:conference, title: generate_localized_title(:conference_title)) } + let(:participatory_space) { resource } let(:event_name) { "decidim.events.conferences.upcoming_conference" } - include_context "when a simple event" it_behaves_like "a simple event" end diff --git a/decidim-conferences/spec/events/decidim/conferences/update_conference_event_spec.rb b/decidim-conferences/spec/events/decidim/conferences/update_conference_event_spec.rb index f15d6eed2d28a..72dad15105677 100644 --- a/decidim-conferences/spec/events/decidim/conferences/update_conference_event_spec.rb +++ b/decidim-conferences/spec/events/decidim/conferences/update_conference_event_spec.rb @@ -3,9 +3,11 @@ require "spec_helper" describe Decidim::Conferences::UpdateConferenceEvent do - let(:resource) { create :conference } + include_context "when a simple event" + + let(:resource) { create(:conference, title: generate_localized_title(:conference_title)) } + let(:participatory_space) { resource } let(:event_name) { "decidim.events.conferences.conference_updated" } - include_context "when a simple event" it_behaves_like "a simple event" end diff --git a/decidim-conferences/spec/presenters/decidim/resource_locator_presenter_spec.rb b/decidim-conferences/spec/presenters/decidim/resource_locator_presenter_spec.rb new file mode 100644 index 0000000000000..5d99da4ad9ad0 --- /dev/null +++ b/decidim-conferences/spec/presenters/decidim/resource_locator_presenter_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + describe ResourceLocatorPresenter, type: :helper do + it_behaves_like "generates routes without query strings on slug" do + let(:route_fragment) { "conferences/#{participatory_space.slug}" } + let(:admin_route_fragment) { "conferences/#{participatory_space.slug}" } + let(:factory_name) { :conference } + end + end +end diff --git a/decidim-conferences/spec/services/decidim/conferences/searchable_conferences_resource_spec.rb b/decidim-conferences/spec/services/decidim/conferences/searchable_conferences_resource_spec.rb index b7e6412c892f0..1aa55e5871ff3 100644 --- a/decidim-conferences/spec/services/decidim/conferences/searchable_conferences_resource_spec.rb +++ b/decidim-conferences/spec/services/decidim/conferences/searchable_conferences_resource_spec.rb @@ -37,7 +37,7 @@ module Decidim d += I18n.transliterate(translated(space.objectives, locale: locale)) { "content_a" => I18n.transliterate(translated(space.title, locale: locale)), - "content_b" => I18n.transliterate(translated(space.slogan, locale: locale)), + "content_b" => I18n.transliterate(strip_tags(translated(space.slogan, locale: locale))), "content_c" => I18n.transliterate(translated(space.short_description, locale: locale)), "content_d" => d } diff --git a/decidim-conferences/spec/shared/manage_conference_components_examples.rb b/decidim-conferences/spec/shared/manage_conference_components_examples.rb index 90c434b8a6a6b..80ad3d9b91280 100644 --- a/decidim-conferences/spec/shared/manage_conference_components_examples.rb +++ b/decidim-conferences/spec/shared/manage_conference_components_examples.rb @@ -192,7 +192,16 @@ click_link "Publish" end - expect(enqueued_jobs.last[:args]).to include("decidim.events.components.component_published") + expect(Decidim::EventPublisherJob).to(have_been_enqueued.with( + "decidim.events.components.component_published", { + resource: component, + event_class: "Decidim::ComponentPublishedEvent", + affected_users: [], + followers: [follower], + force_send: false, + extra: {} + } + )) end it_behaves_like "manage component share tokens" diff --git a/decidim-conferences/spec/system/conference_program_spec.rb b/decidim-conferences/spec/system/conference_program_spec.rb index c6a44a76ec381..85337204b615b 100644 --- a/decidim-conferences/spec/system/conference_program_spec.rb +++ b/decidim-conferences/spec/system/conference_program_spec.rb @@ -62,7 +62,7 @@ expect(page).to have_selector(".programme-title", count: 3) meetings.each do |meeting| - expect(page).to have_content(Decidim::ConferenceMeetingPresenter.new(meeting).title) + expect(page).to have_content(ActionView::Base.full_sanitizer.sanitize(Decidim::ConferenceMeetingPresenter.new(meeting).title)) end end end diff --git a/decidim-consultations/config/locales/bg.yml b/decidim-consultations/config/locales/bg.yml index d0e375da96f10..e301e5694d7ac 100644 --- a/decidim-consultations/config/locales/bg.yml +++ b/decidim-consultations/config/locales/bg.yml @@ -1 +1,21 @@ +--- bg: + activerecord: + errors: + models: + decidim/consultations/vote: + attributes: + question: + invalid_num_votes: Броят на гласовете е невалиден + decidim: + admin: + consultations: + deprecation_warning: Модулът за консултации ще бъде отхвърлен в близко бъдеще. Работим върху следващата криптографски защитена версия, наречена Гласувания. + question_configuration: + disable_external_voting: Моля, деактивирайте външното гласуване за разширени конфигурации + consultations: + last_activity: + new_question_at_html: "Нов въпрос в(ъв) %{link}" + question_votes: + create: + error: Възникна проблем с гласуването по въпроса diff --git a/decidim-consultations/config/locales/he-IL.yml b/decidim-consultations/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-consultations/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-consultations/lib/decidim/consultations/version.rb b/decidim-consultations/lib/decidim/consultations/version.rb index 593b3cba5e8fd..a908fff3db09d 100644 --- a/decidim-consultations/lib/decidim/consultations/version.rb +++ b/decidim-consultations/lib/decidim/consultations/version.rb @@ -3,7 +3,7 @@ module Decidim module Consultations def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-core/app/cells/decidim/activity_cell.rb b/decidim-core/app/cells/decidim/activity_cell.rb index 11493bb7eac49..17abc071d3c51 100644 --- a/decidim-core/app/cells/decidim/activity_cell.rb +++ b/decidim-core/app/cells/decidim/activity_cell.rb @@ -38,9 +38,9 @@ def title case resource_title when String - resource_title + decidim_html_escape(resource_title) when Hash - translated_attribute(resource_title) + decidim_escape_translated(resource_title) end end diff --git a/decidim-core/app/cells/decidim/card_cell.rb b/decidim-core/app/cells/decidim/card_cell.rb index 01d167a5c1399..2f78a855208de 100644 --- a/decidim-core/app/cells/decidim/card_cell.rb +++ b/decidim-core/app/cells/decidim/card_cell.rb @@ -28,11 +28,11 @@ def resource_cell end def title - model.try(:title) || model.try(:name) || "" + decidim_escape_translated(model.try(:title) || model.try(:name) || "") end def body - model.try(:body) || model.try(:about) || "" + decidim_escape_translated(model.try(:body) || model.try(:about) || "") end def resource_manifest diff --git a/decidim-core/app/cells/decidim/card_m/top.erb b/decidim-core/app/cells/decidim/card_m/top.erb index d3912b9f85d2a..c89cfc195bfcb 100644 --- a/decidim-core/app/cells/decidim/card_m/top.erb +++ b/decidim-core/app/cells/decidim/card_m/top.erb @@ -1,7 +1,7 @@
    <% if render_space? %>
    - <%= searchable_resource_human_name(model.participatory_space.class, count: 1) %>: <%= link_to translated_attribute(model.participatory_space.title), Decidim::ResourceLocatorPresenter.new(model.participatory_space).path, class: "card__link text-ellipsis" %> + <%= searchable_resource_human_name(model.participatory_space.class, count: 1) %>: <%= link_to decidim_escape_translated(model.participatory_space.title), Decidim::ResourceLocatorPresenter.new(model.participatory_space).path, class: "card__link text-ellipsis" %>
    <% end %>
    diff --git a/decidim-core/app/cells/decidim/card_m_cell.rb b/decidim-core/app/cells/decidim/card_m_cell.rb index 423c3bb3fb4ce..c1290e332ff99 100644 --- a/decidim-core/app/cells/decidim/card_m_cell.rb +++ b/decidim-core/app/cells/decidim/card_m_cell.rb @@ -57,7 +57,7 @@ def label end def title - decidim_html_escape(translated_attribute(model.title)) + decidim_escape_translated(model.title) end def description diff --git a/decidim-core/app/cells/decidim/user_profile_cell.rb b/decidim-core/app/cells/decidim/user_profile_cell.rb index 880370bfbb37e..21af754c40411 100644 --- a/decidim-core/app/cells/decidim/user_profile_cell.rb +++ b/decidim-core/app/cells/decidim/user_profile_cell.rb @@ -29,7 +29,7 @@ def resource_path delegate :badge, to: :presented_resource def description - html_truncate(decidim_html_escape(user.about.to_s), length: 100) + html_truncate(decidim_escape_translated(user.about), length: 100) end def avatar diff --git a/decidim-core/app/commands/decidim/create_omniauth_registration.rb b/decidim-core/app/commands/decidim/create_omniauth_registration.rb index 60fedb6ce473f..fe09315474547 100644 --- a/decidim-core/app/commands/decidim/create_omniauth_registration.rb +++ b/decidim-core/app/commands/decidim/create_omniauth_registration.rb @@ -57,14 +57,12 @@ def create_or_find_user # to be marked confirmed. @user.skip_confirmation! if !@user.confirmed? && @user.email == verified_email else - generated_password = SecureRandom.hex - @user.email = (verified_email || form.email) @user.name = form.name @user.nickname = form.normalized_nickname @user.newsletter_notifications_at = nil - @user.password = generated_password - @user.password_confirmation = generated_password + @user.password = SecureRandom.hex + @user.password_confirmation = @user.password if form.avatar_url.present? url = URI.parse(form.avatar_url) filename = File.basename(url.path) diff --git a/decidim-core/app/controllers/concerns/decidim/force_authentication.rb b/decidim-core/app/controllers/concerns/decidim/force_authentication.rb index 7c57a645ecf25..b23e979540a22 100644 --- a/decidim-core/app/controllers/concerns/decidim/force_authentication.rb +++ b/decidim-core/app/controllers/concerns/decidim/force_authentication.rb @@ -17,7 +17,7 @@ module ForceAuthentication # Breaks the request lifecycle, if user is not authenticated. # Otherwise returns. def ensure_authenticated! - return true unless current_organization.force_users_to_authenticate_before_access_organization + return true unless current_organization&.force_users_to_authenticate_before_access_organization # Next stop: Let's check whether auth is ok unless user_signed_in? diff --git a/decidim-core/app/controllers/concerns/decidim/paginable.rb b/decidim-core/app/controllers/concerns/decidim/paginable.rb index 05cb8847fcd24..f6c7453745bd6 100644 --- a/decidim-core/app/controllers/concerns/decidim/paginable.rb +++ b/decidim-core/app/controllers/concerns/decidim/paginable.rb @@ -19,7 +19,7 @@ def paginate(resources) def per_page if OPTIONS.include?(params[:per_page]) - params[:per_page] + params[:per_page].to_i elsif params[:per_page] sorted = OPTIONS.sort params[:per_page].to_i.clamp(sorted.first, sorted.last) diff --git a/decidim-core/app/controllers/concerns/decidim/use_organization_time_zone.rb b/decidim-core/app/controllers/concerns/decidim/use_organization_time_zone.rb index 13ba69e616c3a..9089d0c45851c 100644 --- a/decidim-core/app/controllers/concerns/decidim/use_organization_time_zone.rb +++ b/decidim-core/app/controllers/concerns/decidim/use_organization_time_zone.rb @@ -25,7 +25,7 @@ def use_organization_time_zone(&action) # # Returns a String. def organization_time_zone - @organization_time_zone ||= current_user&.time_zone.presence || current_organization.time_zone + @organization_time_zone ||= current_user&.time_zone.presence || current_organization&.time_zone end end end diff --git a/decidim-core/app/controllers/decidim/links_controller.rb b/decidim-core/app/controllers/decidim/links_controller.rb index 05d686838f399..6455d19df1d8b 100644 --- a/decidim-core/app/controllers/decidim/links_controller.rb +++ b/decidim-core/app/controllers/decidim/links_controller.rb @@ -35,7 +35,19 @@ def parse_url end def external_url - @external_url ||= URI.parse(URI::Parser.new.escape(params[:external_url])) + @external_url ||= URI.parse(escape_url(params[:external_url])) + end + + def escape_url(external_url) + before_fragment, fragment = external_url.split("#", 2) + escaped_before_fragment = URI::Parser.new.escape(before_fragment) + + if fragment + escaped_fragment = URI::Parser.new.escape(fragment) + "#{escaped_before_fragment}##{escaped_fragment}" + else + escaped_before_fragment + end end end end diff --git a/decidim-core/app/events/decidim/welcome_notification_event.rb b/decidim-core/app/events/decidim/welcome_notification_event.rb index fa742f35fceb8..261f780868066 100644 --- a/decidim-core/app/events/decidim/welcome_notification_event.rb +++ b/decidim-core/app/events/decidim/welcome_notification_event.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "mustache" - module Decidim class WelcomeNotificationEvent < Decidim::Events::BaseEvent include Decidim::Events::EmailEvent @@ -46,13 +44,12 @@ def resource_title private def interpolate(template) - Mustache.render( - template.to_s, - organization: organization.name, - name: user.name, - help_url: url_helpers.pages_url(host: organization.host), - badges_url: url_helpers.gamification_badges_url(host: organization.host) - ).html_safe + template + .gsub("{{name}}", user.name) + .gsub("{{organization}}", organization.name) + .gsub("{{help_url}}", url_helpers.pages_url(host: organization.host)) + .gsub("{{badges_url}}", url_helpers.gamification_badges_url(host: organization.host)) + .html_safe end end end diff --git a/decidim-core/app/helpers/decidim/cells_paginate_helper.rb b/decidim-core/app/helpers/decidim/cells_paginate_helper.rb index 9d8b258024233..f36c8a263fc31 100644 --- a/decidim-core/app/helpers/decidim/cells_paginate_helper.rb +++ b/decidim-core/app/helpers/decidim/cells_paginate_helper.rb @@ -14,7 +14,7 @@ def paginate(scope, **options, &block) end def per_page - params[:per_page] || Decidim::Paginable::OPTIONS.first + params[:per_page].to_i || Decidim::Paginable::OPTIONS.first end end end diff --git a/decidim-core/app/helpers/decidim/resource_helper.rb b/decidim-core/app/helpers/decidim/resource_helper.rb index 6c63bdfec259d..a1852c19f9bb7 100644 --- a/decidim-core/app/helpers/decidim/resource_helper.rb +++ b/decidim-core/app/helpers/decidim/resource_helper.rb @@ -75,7 +75,7 @@ def resource_locator(resource) # Returns a descriptive title for the resource def resource_title(resource) title = resource.try(:title) || resource.try(:name) || resource.try(:subject) || "#{resource.model_name.human} ##{resource.id}" - title = translated_attribute(title) if title.is_a?(Hash) + title = decidim_escape_translated(title) if title.is_a?(Hash) title end end diff --git a/decidim-core/app/helpers/decidim/user_profile_helper.rb b/decidim-core/app/helpers/decidim/user_profile_helper.rb index f69d31b3dd556..19d2b1ab97803 100644 --- a/decidim-core/app/helpers/decidim/user_profile_helper.rb +++ b/decidim-core/app/helpers/decidim/user_profile_helper.rb @@ -14,9 +14,14 @@ module UserProfileHelper # # Returns a String with the menu tab. def user_profile_tab(text, link, options = {}) - active = is_active_link?(link, (options[:aria_link_type] || :inclusive)) + aria = {} + cls = %w(tabs-title) + if is_active_link?(link, (options[:aria_link_type] || :inclusive)) + cls << "is-active" + aria[:current] = "page" + end - content_tag(:li, class: "tabs-title#{active ? " is-active" : nil}") do + content_tag(:li, class: cls.join(" "), aria: aria) do link_to(text, link, options) end end diff --git a/decidim-core/app/mailers/decidim/application_mailer.rb b/decidim-core/app/mailers/decidim/application_mailer.rb index 253ab2173c9b3..f334811eec2a3 100644 --- a/decidim-core/app/mailers/decidim/application_mailer.rb +++ b/decidim-core/app/mailers/decidim/application_mailer.rb @@ -7,23 +7,57 @@ class ApplicationMailer < ActionMailer::Base include LocalisedMailer include MultitenantAssetHost after_action :set_smtp + after_action :set_from default from: Decidim.config.mailer_sender layout "decidim/mailer" private + attr_reader :organization + def set_smtp - return if @organization.nil? || @organization.smtp_settings.blank? + return if organization.nil? || organization.smtp_settings.blank? - mail.from = @organization.smtp_settings["from"].presence || mail.from mail.reply_to = mail.reply_to || Decidim.config.mailer_reply mail.delivery_method.settings.merge!( - address: @organization.smtp_settings["address"], - port: @organization.smtp_settings["port"], - user_name: @organization.smtp_settings["user_name"], - password: Decidim::AttributeEncryptor.decrypt(@organization.smtp_settings["encrypted_password"]) + address: organization.smtp_settings["address"], + port: organization.smtp_settings["port"], + user_name: organization.smtp_settings["user_name"], + password: Decidim::AttributeEncryptor.decrypt(organization.smtp_settings["encrypted_password"]) ) { |_k, o, v| v.presence || o }.compact_blank! end + + def set_from + return if organization.nil? + return if already_defined_name_in_mail?(mail.from.first) + + mail.from = sender + end + + def sender + return Decidim.config.mailer_sender if return_mailer_sender? + return default_sender if organization.smtp_settings.blank? + return default_sender if organization.smtp_settings["from"].nil? + return default_sender if organization.smtp_settings["from"].empty? + + smtp_settings_from = organization.smtp_settings["from"] + return smtp_settings_from if already_defined_name_in_mail?(smtp_settings_from) + + email_address_with_name(smtp_settings_from, organization.name) + end + + def default_sender + email_address_with_name(Decidim.config.mailer_sender, organization.name) + end + + def already_defined_name_in_mail?(mail_address) + # if there is an space, there is already a name in the address + mail_address.match?(/ /) + end + + def return_mailer_sender? + already_defined_name_in_mail?(Decidim.config.mailer_sender) && organization.smtp_settings.present? + end end end diff --git a/decidim-core/app/packs/src/decidim/input_hashtags.js b/decidim-core/app/packs/src/decidim/input_hashtags.js index 5397f650798bf..e457c84bb41f3 100644 --- a/decidim-core/app/packs/src/decidim/input_hashtags.js +++ b/decidim-core/app/packs/src/decidim/input_hashtags.js @@ -26,7 +26,7 @@ $(() => { /* eslint no-use-before-define: ["error", { "variables": false }]*/ let remoteSearch = function(text, cb) { - $.post("/api", {query: `{hashtags(name:"${text}") {name}}`}). + $.post(window.Decidim.config.get("api_path"), {query: `{hashtags(name:"${text}") {name}}`}). then((response) => { let data = response.data.hashtags || {}; diff --git a/decidim-core/app/packs/src/decidim/input_mentions.js b/decidim-core/app/packs/src/decidim/input_mentions.js index a02c949747aea..a377399996354 100644 --- a/decidim-core/app/packs/src/decidim/input_mentions.js +++ b/decidim-core/app/packs/src/decidim/input_mentions.js @@ -42,7 +42,7 @@ $(() => { /* eslint no-use-before-define: ["error", { "variables": false }]*/ let remoteSearch = function(text, cb) { let query = `{users(filter:{wildcard:"${text}"}){nickname,name,avatarUrl,__typename,...on UserGroup{membersCount}}}`; - $.post("/api", {query: query}). + $.post(window.Decidim.config.get("api_path"), {query: query}). then((response) => { let data = response.data.users || {}; cb(data) diff --git a/decidim-core/app/packs/src/decidim/input_multiple_mentions.js b/decidim-core/app/packs/src/decidim/input_multiple_mentions.js index defa47391e76f..3e92e2c0d473a 100644 --- a/decidim-core/app/packs/src/decidim/input_multiple_mentions.js +++ b/decidim-core/app/packs/src/decidim/input_multiple_mentions.js @@ -42,7 +42,7 @@ $(() => { const autoComplete = new AutoComplete($searchInput[0], { dataMatchKeys: ["name", "nickname"], dataSource: (query, callback) => { - $.post("/api", { + $.post(window.Decidim.config.get("api_path"), { "query": ` { users(filter:{wildcard:"${query}",excludeIds:[]}) diff --git a/decidim-core/app/packs/src/decidim/vizzs/index.js b/decidim-core/app/packs/src/decidim/vizzs/index.js index 0f1c570d422ae..d00e11065b723 100644 --- a/decidim-core/app/packs/src/decidim/vizzs/index.js +++ b/decidim-core/app/packs/src/decidim/vizzs/index.js @@ -19,7 +19,7 @@ $(() => { metricsParams.spaceId = $("#metrics #metrics-space_id").val() || null; } - const fetch = (metrics) => $.post("/api", query(metrics)); + const fetch = (metrics) => $.post(window.Decidim.config.get("api_path"), query(metrics)); const downloadMetricData = (event) => { event.preventDefault(); diff --git a/decidim-core/app/packs/stylesheets/decidim/plugins/leaflet.scss b/decidim-core/app/packs/stylesheets/decidim/plugins/leaflet.scss index 06f8a3a8a78e4..ead8b05b53137 100644 --- a/decidim-core/app/packs/stylesheets/decidim/plugins/leaflet.scss +++ b/decidim-core/app/packs/stylesheets/decidim/plugins/leaflet.scss @@ -22,8 +22,6 @@ .leaflet-tile, .leaflet-marker-icon, .leaflet-marker-shadow{ - -webkit-user-select: none; - -moz-user-select: none; user-select: none; -webkit-user-drag: none; } @@ -45,34 +43,53 @@ display: block; } -/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */ +/* .leaflet-container svg: reset svg max-width declaration shipped in Joomla! (joomla.org) 3.x */ /* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */ -.leaflet-container .leaflet-overlay-pane svg, +.leaflet-container .leaflet-overlay-pane svg{ + max-width: none !important; + max-height: none !important; +} + .leaflet-container .leaflet-marker-pane img, .leaflet-container .leaflet-shadow-pane img, .leaflet-container .leaflet-tile-pane img, -.leaflet-container img.leaflet-image-layer{ +.leaflet-container img.leaflet-image-layer, +.leaflet-container .leaflet-tile{ max-width: none !important; + max-height: none !important; + width: auto; + padding: 0; +} + +.leaflet-container img.leaflet-tile{ + /* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */ + mix-blend-mode: plus-lighter; } .leaflet-container.leaflet-touch-zoom{ - -ms-touch-action: pan-x pan-y; touch-action: pan-x pan-y; } .leaflet-container.leaflet-touch-drag{ - -ms-touch-action: pinch-zoom; + /* Fallback for FF which does not support pinch-zoom */ + touch-action: none; touch-action: pinch-zoom; } .leaflet-container.leaflet-touch-drag.leaflet-touch-zoom{ - -ms-touch-action: none; touch-action: none; } +.leaflet-container{ + -webkit-tap-highlight-color: transparent; +} + +.leaflet-container a{ + -webkit-tap-highlight-color: rgba(51, 181, 229, .4); +} + .leaflet-tile{ - filter: inherit; visibility: hidden; } @@ -83,7 +100,6 @@ .leaflet-zoom-box{ width: 0; height: 0; - -moz-box-sizing: border-box; box-sizing: border-box; z-index: 800; } @@ -94,27 +110,40 @@ user-select: none; } -.leaflet-pane{ z-index: 400; } +.leaflet-pane{ + z-index: 400; +} -.leaflet-tile-pane{ z-index: 200; } -.leaflet-overlay-pane{ z-index: 400; } -.leaflet-shadow-pane{ z-index: 500; } -.leaflet-marker-pane{ z-index: 600; } -.leaflet-tooltip-pane{ z-index: 650; } -.leaflet-popup-pane{ z-index: 700; } +.leaflet-tile-pane{ + z-index: 200; +} -.leaflet-map-pane canvas{ z-index: 100; } -.leaflet-map-pane svg{ z-index: 200; } +.leaflet-overlay-pane{ + z-index: 400; +} -.leaflet-vml-shape{ - width: 1px; - height: 1px; +.leaflet-shadow-pane{ + z-index: 500; } -.lvml{ - behavior: url(#default#VML); - display: inline-block; - position: absolute; +.leaflet-marker-pane{ + z-index: 600; +} + +.leaflet-tooltip-pane{ + z-index: 650; +} + +.leaflet-popup-pane{ + z-index: 700; +} + +.leaflet-map-pane canvas{ + z-index: 100; +} + +.leaflet-map-pane svg{ + z-index: 200; } /* control positioning */ @@ -122,7 +151,6 @@ .leaflet-control{ position: relative; z-index: 800; - pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ pointer-events: auto; } @@ -176,15 +204,8 @@ /* zoom and fade animations */ -.leaflet-fade-anim .leaflet-tile{ - will-change: opacity; -} - .leaflet-fade-anim .leaflet-popup{ opacity: 0; - -webkit-transition: opacity .2s linear; - -moz-transition: opacity .2s linear; - -o-transition: opacity .2s linear; transition: opacity .2s linear; } @@ -193,8 +214,6 @@ } .leaflet-zoom-animated{ - -webkit-transform-origin: 0 0; - -ms-transform-origin: 0 0; transform-origin: 0 0; } @@ -203,17 +222,11 @@ } .leaflet-zoom-anim .leaflet-zoom-animated{ - -webkit-transition: -webkit-transform .25s cubic-bezier(0, 0, .25, 1); - -moz-transition: -moz-transform .25s cubic-bezier(0, 0, .25, 1); - -o-transition: -o-transform .25s cubic-bezier(0, 0, .25, 1); transition: transform .25s cubic-bezier(0, 0, .25, 1); } .leaflet-zoom-anim .leaflet-tile, .leaflet-pan-anim .leaflet-tile{ - -webkit-transition: none; - -moz-transition: none; - -o-transition: none; transition: none; } @@ -228,8 +241,7 @@ } .leaflet-grab{ - cursor: -webkit-grab; - cursor: -moz-grab; + cursor: grab; } .leaflet-crosshair, @@ -245,9 +257,7 @@ .leaflet-dragging .leaflet-grab, .leaflet-dragging .leaflet-grab .leaflet-interactive, .leaflet-dragging .leaflet-marker-draggable{ - cursor: move; - cursor: -webkit-grabbing; - cursor: -moz-grabbing; + cursor: grabbing; } /* marker & overlays interactivity */ @@ -262,7 +272,6 @@ .leaflet-marker-icon.leaflet-interactive, .leaflet-image-layer.leaflet-interactive, .leaflet-pane > svg path.leaflet-interactive{ - pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ pointer-events: auto; } @@ -277,10 +286,6 @@ color: #0078a8; } -.leaflet-container a.leaflet-active{ - outline: 2px solid orange; -} - .leaflet-zoom-box{ border: 2px dotted #38f; background: rgba(255, 255, 255, .5); @@ -288,7 +293,10 @@ /* general typography */ .leaflet-container{ - font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; + font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; + font-size: 12px; + font-size: .75rem; + line-height: 1.5; } /* general toolbar styles */ @@ -318,7 +326,8 @@ display: block; } -.leaflet-bar a:hover{ +.leaflet-bar a:hover, +.leaflet-bar a:focus{ background-color: #f4f4f4; } @@ -345,24 +354,27 @@ line-height: 30px; } +.leaflet-touch .leaflet-bar a:first-child{ + border-top-left-radius: 2px; + border-top-right-radius: 2px; +} + +.leaflet-touch .leaflet-bar a:last-child{ + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; +} + /* zoom control */ .leaflet-control-zoom-in, .leaflet-control-zoom-out{ - font: bold 18px 'Lucida Console', Monaco, monospace; + font: bold 18px "Lucida Console", Monaco, monospace; text-indent: 1px; } -.leaflet-control-zoom-out{ - font-size: 20px; -} - -.leaflet-touch .leaflet-control-zoom-in{ - font-size: 22px; -} - +.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out{ - font-size: 24px; + font-size: 22px; } /* layers control */ @@ -399,6 +411,12 @@ position: relative; } +.leaflet-control-layers-list{ + border: 0; + margin: 0; + padding: 0; +} + .leaflet-control-layers-expanded{ padding: 6px 10px 6px 6px; color: #333; @@ -406,7 +424,7 @@ } .leaflet-control-layers-scrollbar{ - overflow-y: scroll; + overflow: hidden scroll; padding-right: 5px; } @@ -418,6 +436,8 @@ .leaflet-control-layers label{ display: block; + font-size: 13px; + font-size: 1.08333em; } .leaflet-control-layers-separator{ @@ -443,19 +463,24 @@ .leaflet-control-scale-line{ padding: 0 5px; color: #333; + line-height: 1.4; } .leaflet-control-attribution a{ text-decoration: none; } -.leaflet-control-attribution a:hover{ +.leaflet-control-attribution a:hover, +.leaflet-control-attribution a:focus{ text-decoration: underline; } -.leaflet-container .leaflet-control-attribution, -.leaflet-container .leaflet-control-scale{ - font-size: 11px; +.leaflet-attribution-flag{ + display: inline !important; + vertical-align: baseline !important; + width: 1em; + height: .6669em; + margin-right: .277em; } .leaflet-left .leaflet-control-scale{ @@ -471,13 +496,10 @@ border-top: none; line-height: 1.1; padding: 2px 5px 1px; - font-size: 11px; white-space: nowrap; - overflow: hidden; - -moz-box-sizing: border-box; box-sizing: border-box; - background: #fff; background: rgba(255, 255, 255, .5); + text-shadow: 1px 1px #fff; } .leaflet-control-scale-line:not(:first-child){ @@ -517,8 +539,11 @@ } .leaflet-popup-content{ - margin: 13px 19px; - line-height: 1.4; + margin: 13px 24px 13px 20px; + line-height: 1.3; + font-size: 13px; + font-size: 1.08333em; + min-height: 1px; } .leaflet-popup-content p{ @@ -530,6 +555,7 @@ height: 20px; position: absolute; left: 50%; + margin-top: -1px; margin-left: -20px; overflow: hidden; pointer-events: none; @@ -540,10 +566,7 @@ height: 17px; padding: 1px; margin: -10px auto 0; - -webkit-transform: rotate(45deg); - -moz-transform: rotate(45deg); - -ms-transform: rotate(45deg); - -o-transform: rotate(45deg); + pointer-events: auto; transform: rotate(45deg); } @@ -558,48 +581,23 @@ position: absolute; top: 0; right: 0; - padding: 4px 4px 0 0; border: none; text-align: center; - width: 18px; - height: 14px; + width: 24px; + height: 24px; font: 16px/14px Tahoma, Verdana, sans-serif; - color: #c3c3c3; + color: #757575; text-decoration: none; - font-weight: bold; background: transparent; } -.leaflet-container a.leaflet-popup-close-button:hover{ - color: #999; +.leaflet-container a.leaflet-popup-close-button:hover, +.leaflet-container a.leaflet-popup-close-button:focus{ + color: #585858; } .leaflet-popup-scrolled{ overflow: auto; - border-bottom: 1px solid #ddd; - border-top: 1px solid #ddd; -} - -.leaflet-oldie .leaflet-popup-content-wrapper{ - zoom: 1; -} - -.leaflet-oldie .leaflet-popup-tip{ - width: 24px; - margin: 0 auto; - -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; - filter: progid:dximagetransform.microsoft.matrix(M11=.70710678, M12=.70710678, M21=-.70710678, M22=.70710678); -} - -.leaflet-oldie .leaflet-popup-tip-container{ - margin-top: -1px; -} - -.leaflet-oldie .leaflet-control-zoom, -.leaflet-oldie .leaflet-control-layers, -.leaflet-oldie .leaflet-popup-content-wrapper, -.leaflet-oldie .leaflet-popup-tip{ - border: 1px solid #999; } /* div icon */ @@ -620,15 +618,12 @@ border-radius: 3px; color: #222; white-space: nowrap; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; user-select: none; pointer-events: none; box-shadow: 0 1px 3px rgba(0, 0, 0, .4); } -.leaflet-tooltip.leaflet-clickable{ +.leaflet-tooltip.leaflet-interactive{ cursor: pointer; pointer-events: auto; } @@ -698,3 +693,12 @@ margin-left: -12px; border-right-color: #fff; } + +/* Printing */ + +@media print{ + /* Prevent printers from removing background-images of controls. */ + .leaflet-control{ + -webkit-print-color-adjust: exact; + } +} diff --git a/decidim-core/app/presenters/decidim/notification_to_mailer_presenter.rb b/decidim-core/app/presenters/decidim/notification_to_mailer_presenter.rb index 94cb556d569c2..e81415fb4809b 100644 --- a/decidim-core/app/presenters/decidim/notification_to_mailer_presenter.rb +++ b/decidim-core/app/presenters/decidim/notification_to_mailer_presenter.rb @@ -7,11 +7,16 @@ module Decidim class NotificationToMailerPresenter < SimpleDelegator include Decidim::TranslatableAttributes + EXTENDED_NOTIFICATIONS_CLASSES = [ + "Decidim::Comments::CommentCreatedEvent" + ].freeze + delegate :url_helpers, to: "Decidim::Core::Engine.routes" delegate :resource_title, to: :event delegate :resource_url, to: :event delegate :email_intro, to: :event delegate :resource_path, to: :event + delegate :safe_resource_text, to: :event def date_time if frequency == :daily @@ -21,6 +26,10 @@ def date_time end end + def show_extended_information? + EXTENDED_NOTIFICATIONS_CLASSES.include?(event_class) + end + private def event diff --git a/decidim-core/app/services/decidim/events_manager.rb b/decidim-core/app/services/decidim/events_manager.rb index ec90853657306..7417e3f7f3c9f 100644 --- a/decidim-core/app/services/decidim/events_manager.rb +++ b/decidim-core/app/services/decidim/events_manager.rb @@ -46,5 +46,11 @@ def self.publish(event:, resource:, event_class: Decidim::Events::BaseEvent, aff def self.subscribe(event, &block) ActiveSupport::Notifications.subscribe(event, &block) end + + def self.subscribe_events! + subscribe(/^decidim\.events\./) do |event_name, data| + EventPublisherJob.perform_later(event_name, data) + end + end end end diff --git a/decidim-core/app/views/decidim/devise/registrations/new.html.erb b/decidim-core/app/views/decidim/devise/registrations/new.html.erb index 4de2e89375bb8..9a328c6c659f7 100644 --- a/decidim-core/app/views/decidim/devise/registrations/new.html.erb +++ b/decidim-core/app/views/decidim/devise/registrations/new.html.erb @@ -60,7 +60,7 @@
    -

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

    +

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

    <%= strip_tags(translated_attribute(terms_and_conditions_page.content)) %> @@ -74,7 +74,7 @@

    -

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

    +

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

    <%= f.check_box :newsletter, label: t(".newsletter"), checked: @form.newsletter %>
    diff --git a/decidim-core/app/views/decidim/links/new.html.erb b/decidim-core/app/views/decidim/links/new.html.erb index 7944fa0a9913f..d1e0dd2af6c3c 100644 --- a/decidim-core/app/views/decidim/links/new.html.erb +++ b/decidim-core/app/views/decidim/links/new.html.erb @@ -1,3 +1,5 @@ +<% add_decidim_page_title t("decidim.links.warning.title") %> +
  • - <%= translated_attribute(model.body) %> + <%= decidim_escape_translated(model.body) %>
    (<%= t(model.question_type, scope: "decidim.forms.question_types") %>) diff --git a/decidim-forms/config/locales/bg.yml b/decidim-forms/config/locales/bg.yml index 778c0f37d1302..930bc556ee13d 100644 --- a/decidim-forms/config/locales/bg.yml +++ b/decidim-forms/config/locales/bg.yml @@ -7,8 +7,19 @@ bg: question: max_choices: Максимален брой възможности question_type: Тип + errors: + models: + questionnaire: + request_invalid: Възникна грешка при обработката на заявката. Моля, опитайте отново decidim: forms: + errors: + answer: + body: Основният текст не може да бъде празен + questionnaires: + show: + answer_questionnaire: + anonymous_user_message: Влезте в профила си или се регистрирайте, за да попълните отговорите си във формуляра. step_navigation: show: are_you_sure: Това действие не може да се отмени и Вие не можете да редактирате отговорите си. Сигурни ли сте? diff --git a/decidim-forms/config/locales/he-IL.yml b/decidim-forms/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-forms/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-forms/lib/decidim/forms/test/factories.rb b/decidim-forms/lib/decidim/forms/test/factories.rb index fbbede5908bf1..85f73bf82fce5 100644 --- a/decidim-forms/lib/decidim/forms/test/factories.rb +++ b/decidim-forms/lib/decidim/forms/test/factories.rb @@ -5,37 +5,37 @@ FactoryBot.define do factory :questionnaire, class: "Decidim::Forms::Questionnaire" do - title { generate_localized_title } - description do - Decidim::Faker::Localized.wrapped("

    ", "

    ") do - generate_localized_title - end + transient do + skip_injection { false } end - tos { generate_localized_title } - questionnaire_for { build(:participatory_process) } + title { generate_localized_title(:questionnaire_title, skip_injection: skip_injection) } + description { generate_localized_description(:questionnaire_description, skip_injection: skip_injection) } + tos { generate_localized_title(:questionnaire_tos, skip_injection: skip_injection) } + questionnaire_for { build(:participatory_process, skip_injection: skip_injection) } salt { SecureRandom.hex(32) } trait :with_questions do questions do position = 0 qs = %w(short_answer long_answer).collect do |text_question_type| - q = build(:questionnaire_question, question_type: text_question_type, position: position) + q = build(:questionnaire_question, question_type: text_question_type, position: position, skip_injection: skip_injection) position += 1 q end - qs << build(:questionnaire_question, :with_answer_options, question_type: :single_option, position: position) + qs << build(:questionnaire_question, :with_answer_options, question_type: :single_option, position: position, skip_injection: skip_injection) qs end end trait :with_all_questions do - after(:build) do |questionaire, _evaluator| + after(:build) do |questionaire, evaluator| position = 0 %w(short_answer long_answer).collect do |text_question_type| q = create(:questionnaire_question, question_type: text_question_type, position: position, - questionnaire: questionaire) + questionnaire: questionaire, + skip_injection: evaluator.skip_injection) position += 1 questionaire.questions << q end @@ -44,7 +44,8 @@ q = create(:questionnaire_question, :with_answer_options, question_type: option_question_type, position: position, - questionnaire: questionaire) + questionnaire: questionaire, + skip_injection: evaluator.skip_injection) q.display_conditions.build( condition_question: questionaire.questions[q.position - 1], question: q, @@ -60,7 +61,8 @@ question_type: matrix_question_type, position: position, body: generate_localized_title, - questionnaire: questionaire) + questionnaire: questionaire, + skip_injection: evaluator.skip_injection) q.display_conditions.build( condition_question: questionaire.questions[q.position - 1], question: q, @@ -82,16 +84,13 @@ factory :questionnaire_question, class: "Decidim::Forms::Question" do transient do + skip_injection { false } options { [] } rows { [] } end - body { generate_localized_title } - description do - Decidim::Faker::Localized.wrapped("

    ", "

    ") do - generate_localized_title - end - end + body { generate_localized_title(:questionnaire_question_body, skip_injection: skip_injection) } + description { generate_localized_description(:questionnaire_question_description, skip_injection: skip_injection) } mandatory { false } position { 0 } question_type { Decidim::Forms::Question::TYPES.first } @@ -119,13 +118,13 @@ trait :with_answer_options do answer_options do - Array.new(3).collect { build(:answer_option) } + Array.new(3).collect { build(:answer_option, skip_injection: skip_injection) } end end trait :conditioned do display_conditions do - Array.new(3).collect { build(:display_condition) } + Array.new(3).collect { build(:display_condition, skip_injection: skip_injection) } end end @@ -139,22 +138,28 @@ end factory :answer, class: "Decidim::Forms::Answer" do + transient do + skip_injection { false } + end body { "hola" } questionnaire - question { create(:questionnaire_question, questionnaire: questionnaire) } - user { create(:user, organization: questionnaire.questionnaire_for.organization) } + question { create(:questionnaire_question, questionnaire: questionnaire, skip_injection: skip_injection) } + user { create(:user, organization: questionnaire.questionnaire_for.organization, skip_injection: skip_injection) } session_token { Digest::MD5.hexdigest(user.id.to_s) } trait :with_attachments do - after(:create) do |answer, _evaluator| - create :attachment, :with_image, attached_to: answer - create :attachment, :with_pdf, attached_to: answer + after(:create) do |answer, evaluator| + create :attachment, :with_image, attached_to: answer, skip_injection: evaluator.skip_injection + create :attachment, :with_pdf, attached_to: answer, skip_injection: evaluator.skip_injection end end end factory :answer_option, class: "Decidim::Forms::AnswerOption" do - question { create(:questionnaire_question) } + transient do + skip_injection { false } + end + question { create(:questionnaire_question, skip_injection: skip_injection) } body { generate_localized_title } free_text { false } @@ -168,31 +173,40 @@ end factory :answer_choice, class: "Decidim::Forms::AnswerChoice" do + transient do + skip_injection { false } + end answer - answer_option { create(:answer_option, question: answer.question) } - matrix_row { create(:question_matrix_row, question: answer.question) } + answer_option { create(:answer_option, question: answer.question, skip_injection: skip_injection) } + matrix_row { create(:question_matrix_row, question: answer.question, skip_injection: skip_injection) } end factory :question_matrix_row, class: "Decidim::Forms::QuestionMatrixRow" do - question { create(:questionnaire_question) } + transient do + skip_injection { false } + end + question { create(:questionnaire_question, skip_injection: skip_injection) } body { generate_localized_title } position { 0 } end factory :display_condition, class: "Decidim::Forms::DisplayCondition" do - condition_question { create(:questionnaire_question) } - question { create(:questionnaire_question, position: 1) } + transient do + skip_injection { false } + end + condition_question { create(:questionnaire_question, skip_injection: skip_injection) } + question { create(:questionnaire_question, position: 1, skip_injection: skip_injection) } condition_type { :answered } mandatory { true } trait :equal do condition_type { :equal } - answer_option { create(:answer_option, question: condition_question) } + answer_option { create(:answer_option, question: condition_question, skip_injection: skip_injection) } end trait :match do condition_type { :match } - condition_value { generate_localized_title } + condition_value { generate_localized_title(:condition_value, skip_injection: skip_injection) } end end end diff --git a/decidim-forms/lib/decidim/forms/test/shared_examples/has_questionnaire.rb b/decidim-forms/lib/decidim/forms/test/shared_examples/has_questionnaire.rb index f25e59027a9bf..5ba8547b09b2b 100644 --- a/decidim-forms/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +++ b/decidim-forms/lib/decidim/forms/test/shared_examples/has_questionnaire.rb @@ -8,7 +8,7 @@ visit questionnaire_public_path expect(page).to have_i18n_content(questionnaire.title, upcase: true) - expect(page).to have_i18n_content(questionnaire.description) + expect(page).to have_i18n_content(questionnaire.description, strip_tags: true) expect(page).not_to have_css(".form.answer-questionnaire") @@ -29,7 +29,7 @@ visit questionnaire_public_path expect(page).to have_i18n_content(questionnaire.title, upcase: true) - expect(page).to have_i18n_content(questionnaire.description) + expect(page).to have_i18n_content(questionnaire.description, strip_tags: true) fill_in question.body["en"], with: "My first answer" diff --git a/decidim-forms/lib/decidim/forms/version.rb b/decidim-forms/lib/decidim/forms/version.rb index 9773c11cd75fd..b36dd710e58db 100644 --- a/decidim-forms/lib/decidim/forms/version.rb +++ b/decidim-forms/lib/decidim/forms/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-forms version. module Forms def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-generators/Gemfile.lock b/decidim-generators/Gemfile.lock index fb56e8d4cf49c..bf09d0646be6a 100644 --- a/decidim-generators/Gemfile.lock +++ b/decidim-generators/Gemfile.lock @@ -1,63 +1,63 @@ PATH remote: .. specs: - decidim (0.27.5) - decidim-accountability (= 0.27.5) - decidim-admin (= 0.27.5) - decidim-api (= 0.27.5) - decidim-assemblies (= 0.27.5) - decidim-blogs (= 0.27.5) - decidim-budgets (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-debates (= 0.27.5) - decidim-forms (= 0.27.5) - decidim-generators (= 0.27.5) - decidim-meetings (= 0.27.5) - decidim-pages (= 0.27.5) - decidim-participatory_processes (= 0.27.5) - decidim-proposals (= 0.27.5) - decidim-sortitions (= 0.27.5) - decidim-surveys (= 0.27.5) - decidim-system (= 0.27.5) - decidim-templates (= 0.27.5) - decidim-verifications (= 0.27.5) - decidim-accountability (0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-admin (0.27.5) + decidim (0.27.6) + decidim-accountability (= 0.27.6) + decidim-admin (= 0.27.6) + decidim-api (= 0.27.6) + decidim-assemblies (= 0.27.6) + decidim-blogs (= 0.27.6) + decidim-budgets (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-debates (= 0.27.6) + decidim-forms (= 0.27.6) + decidim-generators (= 0.27.6) + decidim-meetings (= 0.27.6) + decidim-pages (= 0.27.6) + decidim-participatory_processes (= 0.27.6) + decidim-proposals (= 0.27.6) + decidim-sortitions (= 0.27.6) + decidim-surveys (= 0.27.6) + decidim-system (= 0.27.6) + decidim-templates (= 0.27.6) + decidim-verifications (= 0.27.6) + decidim-accountability (0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-admin (0.27.6) active_link_to (~> 1.0) - decidim-core (= 0.27.5) + decidim-core (= 0.27.6) devise (~> 4.7) devise-i18n (~> 1.2) devise_invitable (~> 2.0, >= 2.0.9) - decidim-api (0.27.5) - decidim-core (= 0.27.5) + decidim-api (0.27.6) + decidim-core (= 0.27.6) graphql (~> 1.12, < 1.13) graphql-docs (~> 2.1.0) rack-cors (~> 1.0) - decidim-assemblies (0.27.5) - decidim-core (= 0.27.5) - decidim-blogs (0.27.5) - decidim-admin (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-budgets (0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-comments (0.27.5) - decidim-core (= 0.27.5) + decidim-assemblies (0.27.6) + decidim-core (= 0.27.6) + decidim-blogs (0.27.6) + decidim-admin (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-budgets (0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-comments (0.27.6) + decidim-core (= 0.27.6) redcarpet (~> 3.5, >= 3.5.1) - decidim-conferences (0.27.5) - decidim-core (= 0.27.5) - decidim-meetings (= 0.27.5) + decidim-conferences (0.27.6) + decidim-core (= 0.27.6) + decidim-meetings (= 0.27.6) wicked_pdf (~> 2.1) wkhtmltopdf-binary (~> 0.12) - decidim-consultations (0.27.5) - decidim-admin (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-core (0.27.5) + decidim-consultations (0.27.6) + decidim-admin (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-core (0.27.6) active_link_to (~> 1.0) acts_as_list (~> 0.9) batch-loader (~> 1.2) @@ -82,7 +82,6 @@ PATH loofah (~> 2.19.0) mime-types (>= 1.16, < 4.0) mini_magick (~> 4.9) - mustache (~> 1.1.0) omniauth (~> 2.0) omniauth-facebook (~> 5.0) omniauth-google-oauth2 (~> 1.0) @@ -107,15 +106,15 @@ PATH webpacker (= 6.0.0.rc.5) webpush (~> 1.1) wisper (~> 2.0) - decidim-debates (0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-dev (0.27.5) + decidim-debates (0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-dev (0.27.6) axe-core-rspec (~> 4.1.0) byebug (~> 11.0) capybara (~> 3.24) db-query-matchers (~> 0.10.0) - decidim (= 0.27.5) + decidim (= 0.27.6) erb_lint (~> 0.0.35) factory_bot_rails (~> 4.8) i18n-tasks (~> 0.9.18) @@ -138,62 +137,62 @@ PATH w3c_rspec_validators (~> 0.3.0) webmock (~> 3.6) wisper-rspec (~> 1.0) - decidim-elections (0.27.5) + decidim-elections (0.27.6) decidim-bulletin_board (= 0.23) - decidim-core (= 0.27.5) - decidim-forms (= 0.27.5) - decidim-proposals (= 0.27.5) + decidim-core (= 0.27.6) + decidim-forms (= 0.27.6) + decidim-proposals (= 0.27.6) rack-attack (~> 6.0) voting_schemes-dummy (= 0.23) voting_schemes-electionguard (= 0.23) - decidim-forms (0.27.5) - decidim-core (= 0.27.5) + decidim-forms (0.27.6) + decidim-core (= 0.27.6) wicked_pdf (~> 2.1) wkhtmltopdf-binary (~> 0.12) - decidim-generators (0.27.5) - decidim-core (= 0.27.5) - decidim-initiatives (0.27.5) - decidim-admin (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-verifications (= 0.27.5) + decidim-generators (0.27.6) + decidim-core (= 0.27.6) + decidim-initiatives (0.27.6) + decidim-admin (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-verifications (= 0.27.6) origami (~> 2.1) rexml (~> 3.2.5) wicked (~> 1.3) wicked_pdf (~> 2.1) wkhtmltopdf-binary (~> 0.12) - decidim-meetings (0.27.5) - decidim-core (= 0.27.5) - decidim-forms (= 0.27.5) + decidim-meetings (0.27.6) + decidim-core (= 0.27.6) + decidim-forms (= 0.27.6) icalendar (~> 2.5) - decidim-pages (0.27.5) - decidim-core (= 0.27.5) - decidim-participatory_processes (0.27.5) - decidim-core (= 0.27.5) - decidim-proposals (0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) + decidim-pages (0.27.6) + decidim-core (= 0.27.6) + decidim-participatory_processes (0.27.6) + decidim-core (= 0.27.6) + decidim-proposals (0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) doc2text (~> 0.4.5) redcarpet (~> 3.5, >= 3.5.1) - decidim-sortitions (0.27.5) - decidim-admin (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-proposals (= 0.27.5) - decidim-surveys (0.27.5) - decidim-core (= 0.27.5) - decidim-forms (= 0.27.5) - decidim-system (0.27.5) + decidim-sortitions (0.27.6) + decidim-admin (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-proposals (= 0.27.6) + decidim-surveys (0.27.6) + decidim-core (= 0.27.6) + decidim-forms (= 0.27.6) + decidim-system (0.27.6) active_link_to (~> 1.0) - decidim-core (= 0.27.5) + decidim-core (= 0.27.6) devise (~> 4.7) devise-i18n (~> 1.2) devise_invitable (~> 2.0, >= 2.0.9) - decidim-templates (0.27.5) - decidim-core (= 0.27.5) - decidim-forms (= 0.27.5) - decidim-verifications (0.27.5) - decidim-core (= 0.27.5) + decidim-templates (0.27.6) + decidim-core (= 0.27.6) + decidim-forms (= 0.27.6) + decidim-verifications (0.27.6) + decidim-core (= 0.27.6) GEM remote: https://rubygems.org/ @@ -265,7 +264,7 @@ GEM addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) ast (2.4.2) - axe-core-api (4.8.0) + axe-core-api (4.9.0) dumb_delegator virtus axe-core-rspec (4.1.0) @@ -287,6 +286,7 @@ GEM html_tokenizer (~> 0.0.6) parser (>= 2.4) smart_properties + bigdecimal (3.1.7) bindex (0.8.1) bootsnap (1.10.3) msgpack (~> 1.2) @@ -294,16 +294,16 @@ GEM browser (2.7.1) builder (3.2.4) byebug (11.1.3) - capybara (3.39.2) + capybara (3.40.0) addressable matrix mini_mime (>= 0.1.3) - nokogiri (~> 1.8) + nokogiri (~> 1.11) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - carrierwave (2.2.5) + carrierwave (2.2.6) activemodel (>= 5.0.0) activesupport (>= 5.0.0) addressable (~> 2.6) @@ -323,7 +323,7 @@ GEM actionpack (>= 5.0) cells (>= 4.1.6, < 5.0.0) charlock_holmes (0.7.7) - chef-utils (18.3.0) + chef-utils (18.4.12) concurrent-ruby childprocess (4.1.0) coercible (1.0.0) @@ -338,10 +338,11 @@ GEM colorize (0.8.1) commonmarker (0.23.10) concurrent-ruby (1.2.3) - crack (0.4.5) + crack (1.0.0) + bigdecimal rexml crass (1.0.6) - css_parser (1.16.0) + css_parser (1.17.1) addressable date (3.3.4) date_validator (0.12.0) @@ -361,7 +362,7 @@ GEM declarative-option (0.1.0) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) - devise (4.9.3) + devise (4.9.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) @@ -372,13 +373,13 @@ GEM devise_invitable (2.0.9) actionmailer (>= 5.0) devise (>= 4.6) - diff-lcs (1.5.0) + diff-lcs (1.5.1) diffy (3.4.2) doc2text (0.4.7) nokogiri (>= 1.13.2, < 1.17.0) rubyzip (~> 2.3.0) docile (1.4.0) - doorkeeper (5.6.8) + doorkeeper (5.7.0) railties (>= 5) doorkeeper-i18n (4.0.1) dumb_delegator (1.0.0) @@ -394,7 +395,7 @@ GEM temple erubi (1.12.0) escape_utils (1.3.0) - excon (0.109.0) + excon (0.110.0) execjs (2.9.1) extended-markdown-filter (0.7.0) html-pipeline (~> 2.9) @@ -456,7 +457,7 @@ GEM faraday_middleware graphql-client graphql (1.12.24) - graphql-client (0.18.0) + graphql-client (0.19.0) activesupport (>= 3.0) graphql graphql-docs (2.1.0) @@ -469,12 +470,12 @@ GEM sass (~> 3.4) hashdiff (1.1.0) hashie (5.0.0) - highline (2.1.0) + highline (3.0.1) hkdf (0.3.0) html-pipeline (2.14.3) activesupport (>= 2) nokogiri (>= 1.4) - html_tokenizer (0.0.7) + html_tokenizer (0.0.8) htmlentities (4.3.4) i18n (1.14.1) concurrent-ruby (~> 1.0) @@ -497,7 +498,7 @@ GEM ruby-vips (>= 2.0.17, < 3) invisible_captcha (0.13.0) rails (>= 3.2.0) - json (2.7.1) + json (2.7.2) jwt (2.2.3) kaminari (1.2.2) activesupport (>= 4.1.0) @@ -535,7 +536,7 @@ GEM net-imap net-pop net-smtp - marcel (1.0.2) + marcel (1.0.4) matrix (0.4.2) mdl (0.13.0) kramdown (~> 2.3) @@ -546,7 +547,7 @@ GEM method_source (1.0.0) mime-types (3.5.2) mime-types-data (~> 3.2015) - mime-types-data (3.2024.0206) + mime-types-data (3.2024.0305) mini_magick (4.12.0) mini_mime (1.1.5) mini_portile2 (2.8.5) @@ -559,7 +560,6 @@ GEM msgpack (1.4.5) multi_xml (0.6.0) multipart-post (2.4.0) - mustache (1.1.1) net-imap (0.4.10) date net-protocol @@ -592,11 +592,11 @@ GEM rack-protection omniauth-facebook (5.0.0) omniauth-oauth2 (~> 1.2) - omniauth-google-oauth2 (1.1.1) + omniauth-google-oauth2 (1.1.2) jwt (>= 2.0) - oauth2 (~> 2.0.6) + oauth2 (~> 2.0) omniauth (~> 2.0) - omniauth-oauth2 (~> 1.8.0) + omniauth-oauth2 (~> 1.8) omniauth-oauth (1.2.0) oauth omniauth (>= 1.0, < 3) @@ -618,14 +618,14 @@ GEM parallel (1.24.0) parallel_tests (3.13.0) parallel - parser (3.2.2.4) + parser (3.3.1.0) ast (~> 2.4.1) racc pg (1.1.4) pg_search (2.3.6) activerecord (>= 5.2) activesupport (>= 5.2) - premailer (1.22.0) + premailer (1.23.0) addressable css_parser (>= 1.12.0) htmlentities (>= 4.0.0) @@ -694,31 +694,31 @@ GEM ffi (~> 1.0) redcarpet (3.6.0) redis (4.8.1) - regexp_parser (2.8.3) + regexp_parser (2.9.0) request_store (1.5.1) rack (>= 1.4) responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) rexml (3.2.5) - rspec (3.12.0) - rspec-core (~> 3.12.0) - rspec-expectations (~> 3.12.0) - rspec-mocks (~> 3.12.0) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) rspec-cells (0.3.9) cells (>= 4.0.0, < 6.0.0) rspec-rails (>= 3.0.0, < 6.2.0) - rspec-core (3.12.2) - rspec-support (~> 3.12.0) - rspec-expectations (3.12.3) + rspec-core (3.13.0) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) + rspec-support (~> 3.13.0) rspec-html-matchers (0.9.4) nokogiri (~> 1) rspec (>= 3.0.0.a, < 4) - rspec-mocks (3.12.6) + rspec-mocks (3.13.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) + rspec-support (~> 3.13.0) rspec-rails (4.1.2) actionpack (>= 4.2) activesupport (>= 4.2) @@ -729,7 +729,7 @@ GEM rspec-support (~> 3.10) rspec-retry (0.6.2) rspec-core (> 3.3) - rspec-support (3.12.1) + rspec-support (3.13.1) rspec_junit_formatter (0.3.0) rspec-core (>= 2, < 4, != 2.12.0) rubocop (1.28.2) @@ -741,8 +741,8 @@ GEM rubocop-ast (>= 1.17.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.30.0) - parser (>= 3.2.1.0) + rubocop-ast (1.31.3) + parser (>= 3.3.1.0) rubocop-rails (2.15.2) activesupport (>= 4.2.0) rack (>= 1.1) @@ -750,10 +750,10 @@ GEM rubocop-rspec (2.11.1) rubocop (~> 1.19) ruby-progressbar (1.13.0) - ruby-vips (2.2.0) + ruby-vips (2.2.1) ffi (~> 1.12) ruby2_keywords (0.0.5) - rubyXL (3.4.25) + rubyXL (3.4.27) nokogiri (>= 1.10.8) rubyzip (>= 1.3.0) rubyzip (2.3.2) @@ -810,7 +810,7 @@ GEM valid_email2 (2.3.1) activemodel (>= 3.2) mail (~> 2.5) - version_gem (1.1.3) + version_gem (1.1.4) virtus (2.0.0) axiom-types (~> 0.1) coercible (~> 1.0) @@ -834,7 +834,7 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) - webmock (3.19.1) + webmock (3.23.0) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) diff --git a/decidim-generators/lib/decidim/generators/version.rb b/decidim-generators/lib/decidim/generators/version.rb index b98b011d418cc..4172ce98460ca 100644 --- a/decidim-generators/lib/decidim/generators/version.rb +++ b/decidim-generators/lib/decidim/generators/version.rb @@ -4,7 +4,7 @@ module Decidim module Generators def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-initiatives/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives/show.erb b/decidim-initiatives/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives/show.erb index 27cc156e31c5a..fcb9df7c1d1f6 100644 --- a/decidim-initiatives/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives/show.erb +++ b/decidim-initiatives/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives/show.erb @@ -8,9 +8,9 @@ <%= link_to decidim_initiatives.initiative_path(initiative), class: "card card--initiative card--mini" do %> - <%= translated_attribute initiative.title %> + <%= decidim_escape_translated initiative.title %>
    - <%= decidim_html_escape(translated_attribute(initiative.title)) %> + <%= decidim_escape_translated(initiative.title) %>
    <% end %>
  • diff --git a/decidim-initiatives/app/events/decidim/initiatives/admin/initiative_sent_to_technical_validation_event.rb b/decidim-initiatives/app/events/decidim/initiatives/admin/initiative_sent_to_technical_validation_event.rb index 348e8b920c203..a04dd58489741 100644 --- a/decidim-initiatives/app/events/decidim/initiatives/admin/initiative_sent_to_technical_validation_event.rb +++ b/decidim-initiatives/app/events/decidim/initiatives/admin/initiative_sent_to_technical_validation_event.rb @@ -13,7 +13,7 @@ def admin_initiative_path end def admin_initiative_url - decidim_admin_initiatives.edit_initiative_url(resource, resource.mounted_params) + EngineRouter.admin_proxy(resource).edit_initiative_url(resource) end end end diff --git a/decidim-initiatives/app/events/decidim/initiatives/approve_membership_request_event.rb b/decidim-initiatives/app/events/decidim/initiatives/approve_membership_request_event.rb index 933614f89a099..99ea618d18fc9 100644 --- a/decidim-initiatives/app/events/decidim/initiatives/approve_membership_request_event.rb +++ b/decidim-initiatives/app/events/decidim/initiatives/approve_membership_request_event.rb @@ -2,10 +2,7 @@ module Decidim module Initiatives - class ApproveMembershipRequestEvent < Decidim::Events::BaseEvent - include Decidim::Events::EmailEvent - include Decidim::Events::NotificationEvent - + class ApproveMembershipRequestEvent < Decidim::Events::SimpleEvent def email_subject I18n.t( "decidim.initiatives.events.approve_membership_request.email_subject", diff --git a/decidim-initiatives/app/events/decidim/initiatives/create_initiative_event.rb b/decidim-initiatives/app/events/decidim/initiatives/create_initiative_event.rb index 13adcf98f6295..9ac5185ca3c8c 100644 --- a/decidim-initiatives/app/events/decidim/initiatives/create_initiative_event.rb +++ b/decidim-initiatives/app/events/decidim/initiatives/create_initiative_event.rb @@ -2,10 +2,7 @@ module Decidim module Initiatives - class CreateInitiativeEvent < Decidim::Events::BaseEvent - include Decidim::Events::EmailEvent - include Decidim::Events::NotificationEvent - + class CreateInitiativeEvent < Decidim::Events::SimpleEvent def email_subject I18n.t( "decidim.initiatives.events.create_initiative_event.email_subject", diff --git a/decidim-initiatives/app/events/decidim/initiatives/initiative_sent_to_technical_validation_event.rb b/decidim-initiatives/app/events/decidim/initiatives/initiative_sent_to_technical_validation_event.rb index 3d9bdfc690a40..5f59f91e0a7e2 100644 --- a/decidim-initiatives/app/events/decidim/initiatives/initiative_sent_to_technical_validation_event.rb +++ b/decidim-initiatives/app/events/decidim/initiatives/initiative_sent_to_technical_validation_event.rb @@ -12,7 +12,7 @@ def admin_initiative_path end def admin_initiative_url - decidim_admin_initiatives.edit_initiative_url(resource, resource.mounted_params) + EngineRouter.admin_proxy(resource).edit_initiative_url(resource) end end end diff --git a/decidim-initiatives/app/events/decidim/initiatives/revoke_membership_request_event.rb b/decidim-initiatives/app/events/decidim/initiatives/revoke_membership_request_event.rb index 68d36ef297ff1..2e4272939eb40 100644 --- a/decidim-initiatives/app/events/decidim/initiatives/revoke_membership_request_event.rb +++ b/decidim-initiatives/app/events/decidim/initiatives/revoke_membership_request_event.rb @@ -2,10 +2,7 @@ module Decidim module Initiatives - class RevokeMembershipRequestEvent < Decidim::Events::BaseEvent - include Decidim::Events::EmailEvent - include Decidim::Events::NotificationEvent - + class RevokeMembershipRequestEvent < Decidim::Events::SimpleEvent def email_subject I18n.t( "decidim.initiatives.events.revoke_membership_request.email_subject", diff --git a/decidim-initiatives/app/events/decidim/initiatives/spawn_committee_request_event.rb b/decidim-initiatives/app/events/decidim/initiatives/spawn_committee_request_event.rb index e82fddf6e6415..68ccc2560a51f 100644 --- a/decidim-initiatives/app/events/decidim/initiatives/spawn_committee_request_event.rb +++ b/decidim-initiatives/app/events/decidim/initiatives/spawn_committee_request_event.rb @@ -2,10 +2,7 @@ module Decidim module Initiatives - class SpawnCommitteeRequestEvent < Decidim::Events::BaseEvent - include Decidim::Events::EmailEvent - include Decidim::Events::NotificationEvent - + class SpawnCommitteeRequestEvent < Decidim::Events::SimpleEvent def email_subject I18n.t( "decidim.initiatives.events.spawn_committee_request_event.email_subject", diff --git a/decidim-initiatives/app/helpers/decidim/initiatives/application_helper.rb b/decidim-initiatives/app/helpers/decidim/initiatives/application_helper.rb index 9032d134e979a..b382650287a88 100644 --- a/decidim-initiatives/app/helpers/decidim/initiatives/application_helper.rb +++ b/decidim-initiatives/app/helpers/decidim/initiatives/application_helper.rb @@ -56,7 +56,7 @@ def scope_children_to_tree(scope) def filter_types_values types_values = Decidim::InitiativesType.where(organization: current_organization).map do |type| TreeNode.new( - TreePoint.new(type.id.to_s, type.title[I18n.locale.to_s]) + TreePoint.new(type.id.to_s, decidim_escape_translated(type.title)) ) end diff --git a/decidim-initiatives/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb b/decidim-initiatives/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb index dba0adbb7c5c5..e5df0f606d89d 100644 --- a/decidim-initiatives/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb +++ b/decidim-initiatives/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb @@ -36,7 +36,7 @@
    " id="<%= "initiativeType#{type.id}" %>">

    <%= translated_attribute(type.title) %>

    - <%= raw translated_attribute type.description %> + <%= decidim_escape_translated(type.description) %>

    <%= decidim_form_for(@form, url: next_wizard_path, method: :put, html: { id: "new_initiative_#{type.id}", class: "form select-initiative_type-form" }) do |f| %> diff --git a/decidim-initiatives/app/views/decidim/initiatives/initiatives/_result.html.erb b/decidim-initiatives/app/views/decidim/initiatives/initiatives/_result.html.erb index 951da3be99d92..533ba3f1dc068 100644 --- a/decidim-initiatives/app/views/decidim/initiatives/initiatives/_result.html.erb +++ b/decidim-initiatives/app/views/decidim/initiatives/initiatives/_result.html.erb @@ -5,9 +5,9 @@
    <%= t("decidim.initiatives.initiatives.result.answer_title") %>:

    <% if initiative.answer_url.present? %> - + <%= link_to initiative.answer_url, target: "_blank", rel: "noopener noreferrer" do %> <%= decidim_sanitize_editor translated_attribute initiative.answer %> - + <% end %> <% else %> <%= decidim_sanitize_editor translated_attribute initiative.answer %> <% end %> diff --git a/decidim-initiatives/app/views/decidim/initiatives/initiatives/_tags.html.erb b/decidim-initiatives/app/views/decidim/initiatives/initiatives/_tags.html.erb index 5eb30c27eecb8..4b3695cc5b44e 100644 --- a/decidim-initiatives/app/views/decidim/initiatives/initiatives/_tags.html.erb +++ b/decidim-initiatives/app/views/decidim/initiatives/initiatives/_tags.html.erb @@ -1,7 +1,7 @@

    diff --git a/decidim-initiatives/config/locales/bg.yml b/decidim-initiatives/config/locales/bg.yml index 4677627d29d26..6fd792ebb8371 100644 --- a/decidim-initiatives/config/locales/bg.yml +++ b/decidim-initiatives/config/locales/bg.yml @@ -6,9 +6,152 @@ bg: decidim_user_group_id: Автор description: Описание offline_votes: Лични подписи + errors: + models: + initiative: + attributes: + attachment: + title: Заглавието не трябва да бъде празно + activerecord: + models: + decidim/initiative: + one: Инициатива + other: Инициативи decidim: + admin: + initiatives_settings: + update: + error: Възникна грешка + success: Настройките на инициативите са актуализирани успешно + gamification: + badges: + initiatives: + description_own: Публикували сте %{score} инициативи. + unearned_another: Този участник все още няма публикувани инициативи. initiatives: + admin: + committee_requests: + index: + invite_to_committee_help: Споделете този линк, за да поканите други участници в промоторския комитет + no_members_yet: Няма участници в промоторския комитет + initiatives: + edit: + success: Инициативата е изпратена за техническа валидация + update: + error: Възникна грешка + success: Инициативата беше актуализирана успешно + initiatives_type_scopes: + create: + error: Възникна грешка + success: Създаден е нов обхват за дадения тип инициатива + destroy: + success: Обхватът беше премахнат успешно + edit: + destroy: Изтрий + update: + error: Възникна грешка + success: Обхватът беше актуализиран успешно + initiatives_types: + create: + error: Възникна грешка + success: Успешно е създаден нов тип инициатива + destroy: + success: Типът инициатива беше премахнат успешно + edit: + destroy: Изтрий + update: + error: Възникна грешка + success: Типът инициатива беше актуализиран успешно application_helper: filter_state_values: closed: Затворен open: Отворен + committee_requests: + new: + help_text: На път сте да заявите членство в промоторския комитет на тази инициатива + create_initiative: + fill_data: + decidim_user_group_id_help: Не е възможно да се промени авторството на инициативата след създаването и. + finish_help: + access_reminder: Можете да достъпите инициативите си чрез филтъра %{link} на страницата Инициативи. + previous_form: + help: В какво се състои инициативата? Напишете заглавието и описанието. Препоръчваме кратко заглавие и описание, което да включва предложеното решение. + show_similar_initiatives: + compare_help: Ако някоя от следните инициативи е подобна на Вашата, препоръчваме да се подпишете в нея. Така ще има повече възможности за осъществяването на предложението Ви. + continue: Моята инициатива е различна + form: + delete_attachment: Изтрий + index: + uninitialized: Инициативите все още не са конфигурирани от администратор + initiative_signatures: + fill_personal_data: + date_select: + day: Ден + month: Месец + year: Година + help: Моля, попълнете личните си данни в следните полета, за да подпишете инициативата + sms_phone_number: + help: Попълнете потвърдения си телефонен номер във формуляра, за да заявите вашия код за потвърждение + initiative_votes: + create: + invalid: Предоставената информация за подписване на инициативата не е валидна + success_html: Поздравления! Подписахте успешно инициативата %{title} + sms_code: + invalid: Кодът Ви за потвърждение не съвпада с нашия. Моля, проверете отново съобщението, което Ви изпратихме със SMS. + initiatives: + author: + deleted: Изтрито + committee_members: + invite_to_committee_help: Споделете този линк, за да поканите други участници в промоторския комитет + no_members_yet: Няма участници в промоторския комитет + filters: + search: Търсене + filters_small_view: + close_modal: Затвори прозореца + filter: Филтър + filter_by: Филтрирай по + unfold: Разгъване + index_header: + not_authorized: + authorizations_page: Преглед на оторизациите + close: Затвори + explanation: Трябва да преминете проверка, за да създадете нова инициатива. + title: Изисква се оторизация + result: + answer_title: На тази инициатива е отговорено + show: + any_vote_method: За тази гражданска инициатива се събират подписи както онлайн, така и лично. + follow_description: Получавайте известия, когато има новини за тази инициатива + offline_method: За тази гражданска инициатива се събират подписи само лично. + print: Отпечатай инициативата + vote_cabin: + supports_required: "Необходими са %{total_supports} подписа" + votes_count: + most_popular_initiative: Най-популярна инициатива + need_more_votes: Има нужда от повече подписи + signature_interval: + title: Период за събиране на подписи + update: + error: Възникна грешка + success: Инициативата беше актуализирана успешно + versions: + shared: + back_to_resource: Връщане назад към инициативата + layouts: + decidim: + initiative_creation_header: + previous_form: Начало + show_similar_initiatives: Сравнете + step: Стъпка %{current} от общо %{total} + title: Създаване на нова инициатива + initiative_header: + initiative_menu_item: Инициатива + initiative_signature_creation_header: + finished: Подписът на инициативата е създаден + see_steps: вижте стъпките + select_identity: Изберете идентичност + step: Стъпка %{current} от общо %{total} + initiatives: + initiative: + check: Прегледайте + check_and_support: Прегледайте и се подпишете diff --git a/decidim-initiatives/config/locales/ca.yml b/decidim-initiatives/config/locales/ca.yml index 43d01d912e3a6..94b0735c9b1a6 100644 --- a/decidim-initiatives/config/locales/ca.yml +++ b/decidim-initiatives/config/locales/ca.yml @@ -153,33 +153,33 @@ ca: admin: initiative_sent_to_technical_validation: email_intro: La iniciativa "%{resource_title}" s'ha enviat a validació tècnica. Comprova-ho a través del taullel d'administració - email_outro: Has rebut aquesta notificació perquè ets una de les administradores de la plataforma. + email_outro: Has rebut aquesta notificació perquè admnistres la plataforma. email_subject: La iniciativa %{resource_title} ha sol·licitat validació tècnica. notification_title: La iniciativa "%{resource_title}" s'ha enviat a validació tècnica. Comprova-ho a través del taullel d'administració initiative_extended: email_intro: La data de finalització de recollida de signatures per a la iniciativa %{resource_title} s'ha ampliat! - email_outro: Has rebut aquesta notificació perquè estàs seguint %{resource_title}. Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint la iniciativa "%{resource_title}". Pots deixar de rebre notificacions seguint l'enllaç anterior. email_subject: S'ha ampliat la data de finalització de la recollida de signatura de la iniciativa! notification_title: El termini de recollida de signatures per a la iniciativa %{resource_title} s'ha ampliat. initiative_sent_to_technical_validation: email_intro: La iniciativa "%{resource_title}" s'ha enviat a validació tècnica. Comprova-ho a través del taulell d'administració - email_outro: Has rebut aquesta notificació perquè ets una de les administradores de la plataforma. + email_outro: Has rebut aquesta notificació perquè admnistres la plataforma. email_subject: La iniciativa %{resource_title} ha sol·licitat validació tècnica. notification_title: La iniciativa "%{resource_title}" s'ha enviat a validació tècnica. Comprova-ho a través del taullel d'administració milestone_completed: affected_user: email_intro: La teva iniciativa %{resource_title} ha aconseguit un %{percentage}% de les signatures necessàries! - email_outro: Has rebut aquesta notificació perquè ets l'autora de la iniciativa %{resource_title}. + email_outro: Has rebut aquesta notificació perquè promous la iniciativa "%{resource_title}". email_subject: S'ha completat una nova fita! notification_title: La teva iniciativa %{resource_title} ha aconseguit el %{percentage}% de les signatures. follower: email_intro: La iniciativa %{resource_title} ha aconseguit el %{percentage}% de les signatures! - email_outro: Has rebut aquesta notificació perquè estàs seguint %{resource_title}. Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint la inciativa "%{resource_title}". Pots deixar de rebre notificacions seguint l'enllaç anterior. email_subject: S'ha completat una nova fita! notification_title: La iniciativa %{resource_title} ha aconseguit el %{percentage}% de les signatures. support_threshold_reached: email_intro: La iniciativa %{resource_title} ha arribat al llindar de signatures - email_outro: Has rebut aquesta notificació perquè ets una de les administradores de la plataforma. + email_outro: Has rebut aquesta notificació perquè admnistres la plataforma. email_subject: Llindar de signatures aconseguit notification_title: La iniciativa %{resource_title} ha arribat al llindar de signatures gamification: @@ -416,27 +416,27 @@ ca: events: approve_membership_request: email_intro: "%{author_nickname} ha acceptat la teva sol·licitud per formar part de la comissió promotora de la iniciativa %{resource_title}." - email_outro: 'Has rebut aquesta notificació perquè has sol·licitat formar part de la iniciativa %{resource_title}' + email_outro: 'Has rebut aquesta notificació perquè has sol·licitat formar part de la iniciativa: "%{resource_title}"' email_subject: "%{author_nickname} ha acceptat la teva sol·licitud per formar part de la comissió promotora" notification_title: %{author_nickname} ha acceptat la teva sol·licitud per formar part de la comissió promotora per la següent iniciativa %{resource_title}. create_initiative_event: email_intro: "%{author_name} %{author_nickname}, a qui segueixes, ha creat una nova iniciativa. Comprova-la i contribueix:" - email_outro: Has rebut aquesta notificació perquè estàs seguint %{author_nickname}. Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint a "%{author_nickname}". Pots deixar de rebre notificacions seguint l'enllaç anterior. email_subject: Nova iniciativa de %{author_nickname} notification_title: La iniciativa %{resource_title} va ser creada per %{author_name} %{author_nickname}. endorse_initiative_event: email_intro: "%{author_name} %{author_nickname}, a qui segueixes, ha donat suport a la següent iniciativa. Potser vols contribuir a la conversa:" - email_outro: Has rebut aquesta notificació perquè estàs seguint %{author_nickname}. Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint a "%{author_nickname}". Pots deixar de rebre notificacions seguint l'enllaç anterior. email_subject: Iniciativa adherida per %{author_nickname} notification_title: La iniciativa %{resource_title} va ser adherida per %{author_name} %{author_nickname}. revoke_membership_request: email_intro: "%{author_nickname} ha rebutjat la teva sol·licitud per formar part de la comissió promotora per la iniciativa %{resource_title}." - email_outro: 'Has rebut aquesta notificació perquè has sol·licitat formar part de la iniciativa %{resource_title}.' + email_outro: 'Has rebut aquesta notificació perquè has sol·licitat formar part de la iniciativa: "%{resource_title}".' email_subject: "%{author_nickname} ha rebutjat la teva sol·licitud per formar part de la comissió promotora" notification_title: %{author_nickname} ha rebutjat la teva sol·licitud per formar part de la comissió promotora per la següent iniciativa %{resource_title}. spawn_committee_request_event: email_intro: "%{applicant_nickname} ha sol·licitat formar part de la comissió promotora de la teva iniciativa %{resource_title}. Per a acceptar o rebutjar la sol·licitud, vés al formulari d'edició de la teva iniciativa." - email_outro: 'Has rebut aquesta notificació perquè ets l''autora de la iniciativa %{resource_title}' + email_outro: 'Has rebut aquesta notificació perquè promous la iniciativa: "%{resource_title}"' email_subject: "%{applicant_nickname} vol unir-se a la teva iniciativa" notification_title: %{applicant_nickname} ha sol·licitat formar part de la comissió promotora de la teva iniciativa %{resource_title}. Per acceptar-ho o rebutjar-ho fes clic aquí. form: diff --git a/decidim-initiatives/config/locales/es.yml b/decidim-initiatives/config/locales/es.yml index 0ee915b29397d..5d4fca1f63995 100644 --- a/decidim-initiatives/config/locales/es.yml +++ b/decidim-initiatives/config/locales/es.yml @@ -153,33 +153,33 @@ es: admin: initiative_sent_to_technical_validation: email_intro: La iniciativa "%{resource_title}" ha sido enviada a validación técnica. Compruébalo a través del panel de administración - email_outro: Has recibido esta notificación porque eres una de las administradoras de la plataforma. + email_outro: Has recibido esta notificación porque administras la plataforma. email_subject: La iniciativa %{resource_title} ha solicitado validación técnica. notification_title: La iniciativa "%{resource_title}" ha sido enviada a validación técnica. Compruébalo a través del panel de administración initiative_extended: email_intro: '¡El plazo de finalización de la iniciativa %{resource_title} se ha ampliado!' - email_outro: Has recibido esta notificación porque está siguiendo %{resource_title}. Puedes dejar de recibir notificaciones siguiendo el enlace anterior. + email_outro: Has recibido esta notificación porque está siguiendo la iniciactiva "%{resource_title}". Puedes dejar de recibir notificaciones siguiendo el enlace anterior. email_subject: '¡Ampliado el términio de recogida de firmas para esta iniciativa!' notification_title: El plazo de recogida de firmas para la iniciativa %{resource_title} se ha ampliado. initiative_sent_to_technical_validation: email_intro: La iniciativa "%{resource_title}" ha sido enviada a la validación técnica. Compruébala en el panel de administración - email_outro: Has recibido esta notificación porque eres una administradora de la plataforma. + email_outro: Has recibido esta notificación porque administras la plataforma. email_subject: La iniciativa "%{resource_title}" fue enviada a validación técnica. notification_title: La iniciativa "%{resource_title}" ha sido enviada a validación técnica. Compruébalo en el panel de administración milestone_completed: affected_user: email_intro: '¡Tu iniciativa %{resource_title} ha conseguido el %{percentage}% de las firmas necesarias!' - email_outro: Has recibido esta notificación porque eres la autora de la iniciativa %{resource_title}. + email_outro: Has recibido esta notificación porque promueves la iniciativa "%{resource_title}". email_subject: '¡Nuevo hito completado!' notification_title: Tu iniciativa %{resource_title} ha conseguido el %{percentage}% de firmas. follower: email_intro: '¡La iniciativa %{resource_title} ha logrado el %{percentage}% de firmas!' - email_outro: Has recibido esta notificación porque estás siguiendo a %{resource_title}. Puedes dejar de recibir notificaciones siguiendo el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo la iniciativa "%{resource_title}". Puedes dejar de recibir notificaciones siguiendo el enlace anterior. email_subject: '¡Nuevo hito completado!' notification_title: La iniciativa %{resource_title} ha logrado el %{percentage}% de las firmas. support_threshold_reached: email_intro: La iniciativa %{resource_title} ha alcanzado el umbral de firmas - email_outro: Has recibido esta notificación porque eres una de las administradoras de la plataforma. + email_outro: Has recibido esta notificación porque administras la plataforma. email_subject: Umbral de firmas alcanzado notification_title: La iniciativa %{resource_title} ha alcanzado el umbral de firmas gamification: @@ -431,12 +431,12 @@ es: notification_title: La iniciativa %{resource_title} fue adherida por %{author_name} %{author_nickname}. revoke_membership_request: email_intro: "%{author_nickname} rechazó tu solicitud para formar parte del comité promotor de la siguiente iniciativa %{resource_title}." - email_outro: 'Has recibido esta notificación porque has solicitado unirte a esta iniciativa: %{resource_title}.' + email_outro: 'Has recibido esta notificación porque has solicitado unirte a esta iniciativa: "%{resource_title}".' email_subject: "%{author_nickname} rechazó tu solicitud para unirte al comité promotor" notification_title: %{author_nickname} rechazó tu solicitud para formar parte del comité promotor de la siguiente iniciativa %{resource_title}. spawn_committee_request_event: email_intro: "%{applicant_nickname} ha solicitado unirse al comité promotor de tu iniciativa %{resource_title}. Para aceptar o rechazar la solicitud, ve al formulario de edición de tu iniciativa." - email_outro: 'Has recibido esta notificación porque eres la autora de la iniciativa %{resource_title}' + email_outro: 'Has recibido esta notificación porque promueves esta iniciativa: "%{resource_title}"' email_subject: "%{applicant_nickname} quiere unirse a tu iniciativa" notification_title: %{applicant_nickname} ha solicitado unirse al comité promotor de tu iniciativa %{resource_title}. Para aceptar o rechazar la solicitud haz clic aquí. form: diff --git a/decidim-initiatives/config/locales/he-IL.yml b/decidim-initiatives/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-initiatives/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-initiatives/config/locales/pl.yml b/decidim-initiatives/config/locales/pl.yml index 529f9b8ae34a2..3e3d46780ae35 100644 --- a/decidim-initiatives/config/locales/pl.yml +++ b/decidim-initiatives/config/locales/pl.yml @@ -3,8 +3,13 @@ pl: activemodel: attributes: initiative: + answer: Odpowiedź + answer_url: Adres URL odpowiedzi + area_id: Obszar + decidim_scope_id: Zakres decidim_user_group_id: Autor description: Opis + hashtag: Hashtag offline_votes: Podpisy na piśmie offline_votes_for_scope: Podpisy dla %{scope_name} scope_id: Zakres @@ -17,14 +22,18 @@ pl: online: Online state: Stan title: Tytuł + type_id: Typ initiatives_committee_member: user: Członek Komisji + initiatives_settings: + initiatives_order: Kolejność initiatives_type: area_enabled: Pozwól autorom na wybór kategorii dla ich inicjatyw attachments_enabled: Pozwól na załączniki banner_image: Baner child_scope_threshold_enabled: Włącz podpisy dla elementów podrzędnych collect_user_extra_fields: Zbierz dane osobowe użytkowników przy zbiórce podpisów + comments_enabled: Włącz komentarze custom_signature_end_date_enabled: Pozwól autorom na wybór końca okresu zbierania podpisów description: Opis document_number_authorization_handler: Zezwolenie na weryfikację numeru dokumentu przy zbiórce podpisów @@ -33,9 +42,13 @@ pl: online_signature_enabled: Pozwól na podpisy online only_global_scope_enabled: Pozwól tylko na tworzenie inicjatyw o zasięgu globalnym promoting_committee_enabled: Włącz komitet organizacyjny + signature_type: Typ podpisu title: Tytuł undo_online_signatures_enabled: Pozwól użytkownikom na wycofanie ich podpisów online validate_sms_code_on_votes: Dodaj krok weryfikacji kodem SMS przy zbiórce podpisów + initiatives_type_scope: + decidim_scopes_id: Zakresy + supports_required: Wymagane wsparcie initiatives_vote: date_of_birth: Data urodzenia document_number: Numer dokumentu @@ -101,6 +114,7 @@ pl: components: Komponenty information: Informacja initiatives: Inicjatywy + initiatives_settings: Ustawienia initiatives_types: Typy inicjatyw moderations: Moderacja models: @@ -252,6 +266,16 @@ pl: update: error: Wystąpił błąd success: Inicjatywa została zaktualizowana + initiatives_settings: + edit: + update: Aktualizuj + form: + comments: Najczęściej komentowane + date: Najnowsze + publication_date: Ostatnio opublikowane + random: Losowo + signatures: Najczęściej podpisane + title: Ustawienia dla inicjatyw initiatives_type_scopes: create: error: Wystąpił błąd diff --git a/decidim-initiatives/lib/decidim/initiatives/test/factories.rb b/decidim-initiatives/lib/decidim/initiatives/test/factories.rb index 6d785dff40a57..7b28aea94fd6b 100644 --- a/decidim-initiatives/lib/decidim/initiatives/test/factories.rb +++ b/decidim-initiatives/lib/decidim/initiatives/test/factories.rb @@ -5,8 +5,11 @@ FactoryBot.define do factory :initiatives_type, class: "Decidim::InitiativesType" do - title { generate_localized_title } - description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + transient do + skip_injection { false } + end + title { generate_localized_title(:initiatives_type_title, skip_injection: skip_injection) } + description { generate_localized_description(:initiatives_type_description, skip_injection: skip_injection) } organization # Keep banner_image after organization banner_image do @@ -82,7 +85,7 @@ trait :with_user_extra_fields_collection do collect_user_extra_fields { true } - extra_fields_legal_information { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + extra_fields_legal_information { generate_localized_description(:initiatives_type_extra_fields_legal_information, skip_injection: skip_injection) } document_number_authorization_handler { "dummy_authorization_handler" } end @@ -100,20 +103,26 @@ end factory :initiatives_type_scope, class: "Decidim::InitiativesTypeScope" do - type { create(:initiatives_type) } - scope { create(:scope, organization: type.organization) } + transient do + skip_injection { false } + end + type { create(:initiatives_type, skip_injection: skip_injection) } + scope { create(:scope, organization: type.organization, skip_injection: skip_injection) } supports_required { 1000 } trait :with_user_extra_fields_collection do - type { create(:initiatives_type, :with_user_extra_fields_collection) } + type { create(:initiatives_type, :with_user_extra_fields_collection, skip_injection: skip_injection) } end end factory :initiative, class: "Decidim::Initiative" do - title { generate_localized_title } - description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + transient do + skip_injection { false } + end + title { generate_localized_title(:initiative_title, skip_injection: skip_injection) } + description { generate_localized_description(:initiative_description, skip_injection: skip_injection) } organization - author { create(:user, :confirmed, organization: organization) } + author { create(:user, :confirmed, organization: organization, skip_injection: skip_injection) } published_at { Time.current } state { "published" } signature_type { "online" } @@ -121,15 +130,15 @@ signature_end_date { Date.current + 120.days } scoped_type do - create(:initiatives_type_scope, - type: create(:initiatives_type, organization: organization, signature_type: signature_type)) + create(:initiatives_type_scope, skip_injection: skip_injection, + type: create(:initiatives_type, organization: organization, signature_type: signature_type, skip_injection: skip_injection)) end - after(:create) do |initiative| + after(:create) do |initiative, evaluator| if initiative.author.is_a?(Decidim::User) && Decidim::Authorization.where(user: initiative.author).where.not(granted_at: nil).none? - create(:authorization, user: initiative.author, granted_at: Time.now.utc) + create(:authorization, user: initiative.author, granted_at: Time.now.utc, skip_injection: evaluator.skip_injection) end - create_list(:initiatives_committee_member, 3, initiative: initiative) + create_list(:initiatives_committee_member, 3, initiative: initiative, skip_injection: evaluator.skip_injection) end trait :created do @@ -198,13 +207,13 @@ trait :with_user_extra_fields_collection do scoped_type do - create(:initiatives_type_scope, - type: create(:initiatives_type, :with_user_extra_fields_collection, organization: organization)) + create(:initiatives_type_scope, skip_injection: skip_injection, + type: create(:initiatives_type, :with_user_extra_fields_collection, organization: organization, skip_injection: skip_injection)) end end trait :with_area do - area { create(:area, organization: organization) } + area { create(:area, organization: organization, skip_injection: skip_injection) } end trait :with_documents do @@ -217,7 +226,8 @@ initiative.attachments << create( :attachment, :with_pdf, - attached_to: initiative + attached_to: initiative, + skip_injection: evaluator.skip_injection ) end end @@ -233,7 +243,8 @@ initiative.attachments << create( :attachment, :with_image, - attached_to: initiative + attached_to: initiative, + skip_injection: evaluator.skip_injection ) end end @@ -241,8 +252,11 @@ end factory :initiative_user_vote, class: "Decidim::InitiativesVote" do - initiative { create(:initiative) } - author { create(:user, :confirmed, organization: initiative.organization) } + transient do + skip_injection { false } + end + initiative { create(:initiative, skip_injection: skip_injection) } + author { create(:user, :confirmed, organization: initiative.organization, skip_injection: skip_injection) } hash_id { SecureRandom.uuid } scope { initiative.scope } after(:create) do |vote| @@ -251,17 +265,23 @@ end factory :organization_user_vote, class: "Decidim::InitiativesVote" do - initiative { create(:initiative) } - author { create(:user, :confirmed, organization: initiative.organization) } - decidim_user_group_id { create(:user_group).id } - after(:create) do |support| - create(:user_group_membership, user: support.author, user_group: Decidim::UserGroup.find(support.decidim_user_group_id)) + transient do + skip_injection { false } + end + initiative { create(:initiative, skip_injection: skip_injection) } + author { create(:user, :confirmed, organization: initiative.organization, skip_injection: skip_injection) } + decidim_user_group_id { create(:user_group, skip_injection: skip_injection).id } + after(:create) do |support, evaluator| + create(:user_group_membership, user: support.author, user_group: Decidim::UserGroup.find(support.decidim_user_group_id), skip_injection: evaluator.skip_injection) end end factory :initiatives_committee_member, class: "Decidim::InitiativesCommitteeMember" do - initiative { create(:initiative) } - user { create(:user, :confirmed, organization: initiative.organization) } + transient do + skip_injection { false } + end + initiative { create(:initiative, skip_injection: skip_injection) } + user { create(:user, :confirmed, organization: initiative.organization, skip_injection: skip_injection) } state { "accepted" } trait :accepted do @@ -278,6 +298,9 @@ end factory :initiatives_settings, class: "Decidim::InitiativesSettings" do + transient do + skip_injection { false } + end initiatives_order { "random" } organization diff --git a/decidim-initiatives/lib/decidim/initiatives/version.rb b/decidim-initiatives/lib/decidim/initiatives/version.rb index c9e1c01fd7a85..9f9db2813572c 100644 --- a/decidim-initiatives/lib/decidim/initiatives/version.rb +++ b/decidim-initiatives/lib/decidim/initiatives/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-initiatives version. module Initiatives def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-initiatives/spec/cells/decidim/initiatives_votes/vote_cell_spec.rb b/decidim-initiatives/spec/cells/decidim/initiatives_votes/vote_cell_spec.rb index 2c29518147f2c..8a3552855bbb5 100644 --- a/decidim-initiatives/spec/cells/decidim/initiatives_votes/vote_cell_spec.rb +++ b/decidim-initiatives/spec/cells/decidim/initiatives_votes/vote_cell_spec.rb @@ -25,7 +25,7 @@ context "when rendering" do it "shows title and identifier of initiative" do expect(subject).to have_content(vote.initiative.title[:en]) - expect(subject).to have_content(translated(vote.initiative.title, locale: :en)) + expect(subject).to have_content(decidim_sanitize_translated(vote.initiative.title)) end it "shows decrypted data" do diff --git a/decidim-initiatives/spec/events/decidim/initiatives/admin/initiative_sent_to_technical_validation_event_spec.rb b/decidim-initiatives/spec/events/decidim/initiatives/admin/initiative_sent_to_technical_validation_event_spec.rb index 54fde99186bc4..48c3c8532afea 100644 --- a/decidim-initiatives/spec/events/decidim/initiatives/admin/initiative_sent_to_technical_validation_event_spec.rb +++ b/decidim-initiatives/spec/events/decidim/initiatives/admin/initiative_sent_to_technical_validation_event_spec.rb @@ -3,17 +3,18 @@ require "spec_helper" describe Decidim::Initiatives::Admin::InitiativeSentToTechnicalValidationEvent do - let(:resource) { create :initiative } + include_context "when a simple event" + + let(:resource) { create :initiative, title: generate_localized_title(:initiative_title) } + let(:participatory_space) { resource } let(:event_name) { "decidim.events.initiatives.admin.initiative_sent_to_technical_validation" } - let(:admin_initiative_path) { "/admin/initiatives/#{resource.slug}/edit?initiative_slug=#{resource.slug}" } - let(:admin_initiative_url) { "http://#{organization.host}#{admin_initiative_path}" } - let!(:initiative_title) { decidim_html_escape(resource_title) } - let(:email_subject) { "Initiative \"#{decidim_sanitize(resource_title)}\" was sent to technical validation." } - let(:email_intro) { %(The initiative "#{initiative_title}" has been sent to technical validation. Check it out at the admin panel) } + let(:admin_initiative_path) { "/admin/initiatives/#{resource.slug}/edit" } + let(:admin_initiative_url) { "http://#{organization.host}:#{Capybara.server_port}#{admin_initiative_path}" } + let(:email_subject) { "Initiative \"#{resource_title}\" was sent to technical validation." } + let(:email_intro) { %(The initiative "#{resource_title}" has been sent to technical validation. Check it out at the admin panel) } let(:email_outro) { "You have received this notification because you are an admin of the platform." } - let(:notification_title) { %(The initiative "#{initiative_title}" has been sent to technical validation. Check it out at the admin panel) } + let(:notification_title) { %(The initiative "#{resource_title}" has been sent to technical validation. Check it out at the admin panel) } - include_context "when a simple event" it_behaves_like "a simple event" it_behaves_like "a simple event email" it_behaves_like "a simple event notification" diff --git a/decidim-initiatives/spec/events/decidim/initiatives/admin/support_threshold_reached_event_spec.rb b/decidim-initiatives/spec/events/decidim/initiatives/admin/support_threshold_reached_event_spec.rb index 43e31f7df97e7..817160268ad99 100644 --- a/decidim-initiatives/spec/events/decidim/initiatives/admin/support_threshold_reached_event_spec.rb +++ b/decidim-initiatives/spec/events/decidim/initiatives/admin/support_threshold_reached_event_spec.rb @@ -6,15 +6,12 @@ include_context "when a simple event" let(:event_name) { "decidim.events.initiatives.support_threshold_reached" } - let(:resource) { initiative } - - let(:initiative) { create :initiative } - let(:participatory_space) { initiative } - let(:initiative_title) { decidim_html_escape(translated(initiative.title)) } + let(:resource) { create :initiative, title: generate_localized_title(:initiative_title) } + let(:participatory_space) { resource } let(:email_subject) { "Signatures threshold reached" } - let(:email_intro) { "The initiative #{initiative_title} has reached the signatures threshold" } + let(:email_intro) { "The initiative #{resource_title} has reached the signatures threshold" } let(:email_outro) { "You have received this notification because you are an admin of the platform." } - let(:notification_title) { "The #{initiative_title} initiative has reached the signatures threshold" } + let(:notification_title) { "The #{resource_title} initiative has reached the signatures threshold" } it_behaves_like "a simple event" it_behaves_like "a simple event email" diff --git a/decidim-initiatives/spec/events/decidim/initiatives/approve_membership_request_event_spec.rb b/decidim-initiatives/spec/events/decidim/initiatives/approve_membership_request_event_spec.rb index 3ecdda1770912..c01ea388d763f 100644 --- a/decidim-initiatives/spec/events/decidim/initiatives/approve_membership_request_event_spec.rb +++ b/decidim-initiatives/spec/events/decidim/initiatives/approve_membership_request_event_spec.rb @@ -3,25 +3,19 @@ require "spec_helper" describe Decidim::Initiatives::ApproveMembershipRequestEvent do - subject do - described_class.new( - resource: initiative, - event_name: event_name, - user: [membership_request.user], - user_role: :affected_user, - extra: { author: author } - ) - end + include_context "when a simple event" + let(:user_role) { :affected_user } + let(:extra) { { author: author } } let(:event_name) { "decidim.events.initiatives.approve_membership_request" } - let(:organization) { create(:organization) } - let!(:initiative) { create(:initiative, :created, organization: organization) } - let(:author) { initiative.author } + let!(:resource) { create(:initiative, :created, title: generate_localized_title(:initiative_title)) } + let(:participatory_space) { resource } + + let(:author) { resource.author } let(:author_profile_url) { Decidim::UserPresenter.new(author).profile_url } let(:author_nickname) { Decidim::UserPresenter.new(author).nickname } - let(:membership_request) { create(:initiatives_committee_member, initiative: initiative, state: "requested") } - let(:resource_url) { resource_locator(initiative).url } - let(:resource_title) { translated(initiative.title) } + let(:user) { create(:initiatives_committee_member, initiative: resource, state: "requested").user } + let(:resource_url) { resource_locator(resource).url } let(:email_subject) { "#{author_nickname} accepted your application to the promoter committee" } let(:email_intro) { "#{author_nickname} accepted your application to be part of the promoter committee for the initiative #{resource_title}." } let(:email_outro) { "You received this notification because you applied to this initiative: #{resource_title}" } @@ -39,6 +33,7 @@ end end + it_behaves_like "a simple event" it_behaves_like "a simple event email" it_behaves_like "a simple event notification" end diff --git a/decidim-initiatives/spec/events/decidim/initiatives/create_initiative_event_spec.rb b/decidim-initiatives/spec/events/decidim/initiatives/create_initiative_event_spec.rb index 7dea2baf5ff80..7ebeb87a7b5db 100644 --- a/decidim-initiatives/spec/events/decidim/initiatives/create_initiative_event_spec.rb +++ b/decidim-initiatives/spec/events/decidim/initiatives/create_initiative_event_spec.rb @@ -4,19 +4,21 @@ describe Decidim::Initiatives::CreateInitiativeEvent do subject do - described_class.new(resource: initiative, event_name: event_name, user: user, extra: {}) + described_class.new(resource: resource, event_name: event_name, user: user, extra: {}) end - let(:organization) { initiative.organization } - let(:initiative) { create :initiative } - let(:initiative_author) { initiative.author } + include_context "when a simple event" + + let(:organization) { resource.organization } + let(:resource) { create :initiative, title: generate_localized_title(:initiative_title) } + let(:initiative_author) { resource.author } let(:event_name) { "decidim.events.initiatives.initiative_created" } let(:user) { create :user, organization: organization } - let(:resource_path) { resource_locator(initiative).path } + let(:resource_path) { resource_locator(resource).path } let(:email_subject) { "New initiative by @#{initiative_author.nickname}" } let(:email_intro) { "#{initiative_author.name} @#{initiative_author.nickname}, who you are following, has created a new initiative, check it out and contribute:" } let(:email_outro) { "You have received this notification because you are following @#{initiative_author.nickname}. You can stop receiving notifications following the previous link." } - let(:notification_title) { "The #{initiative.title["en"]} initiative was created by #{initiative_author.name} @#{initiative_author.nickname}." } + let(:notification_title) { "The #{resource_title} initiative was created by #{initiative_author.name} @#{initiative_author.nickname}." } it_behaves_like "a simple event email" it_behaves_like "a simple event notification" diff --git a/decidim-initiatives/spec/events/decidim/initiatives/endorse_initiative_event_spec.rb b/decidim-initiatives/spec/events/decidim/initiatives/endorse_initiative_event_spec.rb index 2026ad0f4b6a2..00f045006f2f0 100644 --- a/decidim-initiatives/spec/events/decidim/initiatives/endorse_initiative_event_spec.rb +++ b/decidim-initiatives/spec/events/decidim/initiatives/endorse_initiative_event_spec.rb @@ -6,21 +6,24 @@ include Decidim::SanitizeHelper subject do - described_class.new(resource: initiative, event_name: event_name, user: user, extra: {}) + described_class.new(resource: resource, event_name: event_name, user: user, extra: {}) end - let(:organization) { initiative.organization } - let(:initiative) { create :initiative } - let(:initiative_author) { initiative.author } + include_context "when a simple event" + + include Decidim::TranslationsHelper + + let(:organization) { resource.organization } + let(:resource) { create(:initiative) } + let(:initiative_author) { resource.author } let(:event_name) { "decidim.events.initiatives.initiative_endorsed" } let(:user) { create :user, organization: organization } - let(:resource_path) { resource_locator(initiative).path } + let(:resource_path) { resource_locator(resource).path } let(:email_subject) { "Initiative endorsed by @#{initiative_author.nickname}" } let(:email_intro) { "#{initiative_author.name} @#{initiative_author.nickname}, who you are following, has endorsed the following initiative, maybe you want to contribute to the conversation:" } let(:email_outro) { "You have received this notification because you are following @#{initiative_author.nickname}. You can stop receiving notifications following the previous link." } - let(:intiative_title) { decidim_html_escape(translated(initiative.title)) } let(:notification_title) { <<-EOTITLE.squish } - The #{intiative_title} initiative was endorsed by + The #{resource_title} initiative was endorsed by #{initiative_author.name} @#{initiative_author.nickname}. EOTITLE diff --git a/decidim-initiatives/spec/events/decidim/initiatives/extend_initiative_event_spec.rb b/decidim-initiatives/spec/events/decidim/initiatives/extend_initiative_event_spec.rb index 676e35c1b561b..4181def77bde6 100644 --- a/decidim-initiatives/spec/events/decidim/initiatives/extend_initiative_event_spec.rb +++ b/decidim-initiatives/spec/events/decidim/initiatives/extend_initiative_event_spec.rb @@ -6,10 +6,8 @@ include_context "when a simple event" let(:event_name) { "decidim.events.initiatives.initiative_extended" } - let(:resource) { initiative } - - let(:initiative) { create :initiative } - let(:participatory_space) { initiative } + let(:resource) { create :initiative, title: generate_localized_title(:initiative_title) } + let(:participatory_space) { resource } it_behaves_like "a simple event" diff --git a/decidim-initiatives/spec/events/decidim/initiatives/initiative_sent_to_technical_validation_event_spec.rb b/decidim-initiatives/spec/events/decidim/initiatives/initiative_sent_to_technical_validation_event_spec.rb index 8c5ae5591e8c9..775a42736c6b7 100644 --- a/decidim-initiatives/spec/events/decidim/initiatives/initiative_sent_to_technical_validation_event_spec.rb +++ b/decidim-initiatives/spec/events/decidim/initiatives/initiative_sent_to_technical_validation_event_spec.rb @@ -3,16 +3,18 @@ require "spec_helper" describe Decidim::Initiatives::InitiativeSentToTechnicalValidationEvent do - let(:resource) { create :initiative } + include_context "when a simple event" + + let(:resource) { create :initiative, title: generate_localized_title(:initiative_title) } + let(:participatory_space) { resource } let(:event_name) { "decidim.events.initiatives.initiative_sent_to_technical_validation" } - let(:admin_initiative_path) { "/admin/initiatives/#{resource.slug}/edit?initiative_slug=#{resource.slug}" } - let(:admin_initiative_url) { "http://#{organization.host}#{admin_initiative_path}" } - let(:email_subject) { "Initiative \"#{decidim_sanitize(resource_title)}\" was sent to technical validation." } + let(:admin_initiative_path) { "/admin/initiatives/#{resource.slug}/edit" } + let(:admin_initiative_url) { "http://#{organization.host}:#{Capybara.server_port}#{admin_initiative_path}" } + let(:email_subject) { "Initiative \"#{resource_title}\" was sent to technical validation." } let(:email_outro) { "You have received this notification because you are an admin of the platform." } - let(:email_intro) { %(The initiative "#{decidim_html_escape(resource_title)}" has been sent to technical validation. Check it out at the admin panel) } - let(:notification_title) { %(The initiative "#{decidim_html_escape(resource_title)}" has been sent to technical validation. Check it out at the admin panel) } + let(:email_intro) { %(The initiative "#{resource_title}" has been sent to technical validation. Check it out at the admin panel) } + let(:notification_title) { %(The initiative "#{resource_title}" has been sent to technical validation. Check it out at the admin panel) } - include_context "when a simple event" it_behaves_like "a simple event" it_behaves_like "a simple event email" it_behaves_like "a simple event notification" diff --git a/decidim-initiatives/spec/events/decidim/initiatives/milestone_completed_event_spec.rb b/decidim-initiatives/spec/events/decidim/initiatives/milestone_completed_event_spec.rb index 13f8438e39934..3c4e5470508f0 100644 --- a/decidim-initiatives/spec/events/decidim/initiatives/milestone_completed_event_spec.rb +++ b/decidim-initiatives/spec/events/decidim/initiatives/milestone_completed_event_spec.rb @@ -6,11 +6,9 @@ include_context "when a simple event" let(:event_name) { "decidim.events.initiatives.milestone_completed" } - let(:resource) { initiative } - - let(:initiative) { create :initiative } + let(:resource) { create :initiative, title: generate_localized_title(:initiative_title) } let(:extra) { { percentage: 75 } } - let(:participatory_space) { initiative } + let(:participatory_space) { resource } it_behaves_like "a simple event" diff --git a/decidim-initiatives/spec/events/decidim/initiatives/revoke_membership_request_event_spec.rb b/decidim-initiatives/spec/events/decidim/initiatives/revoke_membership_request_event_spec.rb index f4903566abb1c..29f2e00b55240 100644 --- a/decidim-initiatives/spec/events/decidim/initiatives/revoke_membership_request_event_spec.rb +++ b/decidim-initiatives/spec/events/decidim/initiatives/revoke_membership_request_event_spec.rb @@ -3,25 +3,18 @@ require "spec_helper" describe Decidim::Initiatives::RevokeMembershipRequestEvent do - subject do - described_class.new( - resource: initiative, - event_name: event_name, - user: [membership_request.user], - user_role: :affected_user, - extra: { author: author } - ) - end + include_context "when a simple event" + let(:user_role) { :affected_user } + let(:extra) { { author: author } } let(:event_name) { "decidim.events.initiatives.approve_membership_request" } let(:organization) { create(:organization) } - let!(:initiative) { create(:initiative, :created, organization: organization) } - let(:author) { initiative.author } + let!(:resource) { create(:initiative, :created, organization: organization) } + let(:author) { resource.author } let(:author_profile_url) { Decidim::UserPresenter.new(author).profile_url } let(:author_nickname) { Decidim::UserPresenter.new(author).nickname } - let(:membership_request) { create(:initiatives_committee_member, initiative: initiative, state: "requested") } - let(:resource_url) { resource_locator(initiative).url } - let(:resource_title) { translated(initiative.title) } + let(:user) { create(:initiatives_committee_member, initiative: resource, state: "requested").user } + let(:resource_url) { resource_locator(resource).url } let(:email_subject) { "#{author_nickname} rejected your application to the promoter committee" } let(:email_intro) { "#{author_nickname} rejected your application to be part of the promoter committee for the following initiative #{resource_title}." } let(:email_outro) { "You received this notification because you applied to this initiative: #{resource_title}." } diff --git a/decidim-initiatives/spec/events/decidim/initiatives/spawn_committee_request_event_spec.rb b/decidim-initiatives/spec/events/decidim/initiatives/spawn_committee_request_event_spec.rb index 6a104a6f3291b..eaf0eb15227a0 100644 --- a/decidim-initiatives/spec/events/decidim/initiatives/spawn_committee_request_event_spec.rb +++ b/decidim-initiatives/spec/events/decidim/initiatives/spawn_committee_request_event_spec.rb @@ -3,24 +3,18 @@ require "spec_helper" describe Decidim::Initiatives::SpawnCommitteeRequestEvent do - subject do - described_class.new( - resource: initiative, - event_name: event_name, - user: [initiative.author], - user_role: :affected_user, - extra: { applicant: applicant } - ) - end + include_context "when a simple event" - let(:organization) { initiative.organization } - let(:initiative) { create :initiative } + let(:user_role) { :affected_user } + let(:extra) { { applicant: applicant } } + let(:user) { resource.author } + let(:organization) { resource.organization } + let(:resource) { create(:initiative) } let(:event_name) { "decidim.events.initiatives.initiative_created" } let(:applicant) { create :user, organization: organization } let(:applicant_profile_url) { Decidim::UserPresenter.new(applicant).profile_url } let(:applicant_nickname) { Decidim::UserPresenter.new(applicant).nickname } - let(:resource_url) { resource_locator(initiative).url } - let(:resource_title) { translated(initiative.title) } + let(:resource_url) { resource_locator(resource).url } let(:email_subject) { "#{applicant_nickname} wants to join your initiative" } let(:email_intro) { "#{applicant_nickname} applied for the promoter committee of your initiative #{resource_title}. To accept or reject the application, go to the edit form of your initiative." } let(:email_outro) { "You received this notification because you are the author of this initiative: #{resource_title}" } diff --git a/decidim-initiatives/spec/mailers/decidim/initiatives/initiatives_mailer_spec.rb b/decidim-initiatives/spec/mailers/decidim/initiatives/initiatives_mailer_spec.rb index cde0b0f0ee7ae..d244ebfe5ea66 100644 --- a/decidim-initiatives/spec/mailers/decidim/initiatives/initiatives_mailer_spec.rb +++ b/decidim-initiatives/spec/mailers/decidim/initiatives/initiatives_mailer_spec.rb @@ -15,12 +15,12 @@ module Initiatives context "when the promoting committee is enabled" do it "renders the headers" do - expect(mail.subject).to eq("Your initiative '#{initiative.title["en"]}' has been created") + expect(mail.subject).to eq("Your initiative '#{translated(initiative.title)}' has been created") expect(mail.to).to eq([initiative.author.email]) end it "renders the body" do - expect(mail.body.encoded).to match(initiative.title["en"]) + expect(mail.body.encoded).to include(decidim_escape_translated(initiative.title)) end it "renders the promoter committee help" do @@ -40,7 +40,7 @@ module Initiatives end it "renders the body" do - expect(mail.body.encoded).to match(initiative.title["en"]) + expect(mail.body.encoded).to include(decidim_html_escape(translated(initiative.title))) end it "doesn't render the promoter committee help" do @@ -63,7 +63,7 @@ module Initiatives end it "renders the body" do - expect(mail.body).to match("The initiative #{initiative.title["en"]} has changed its status to: #{I18n.t(initiative.state, scope: "decidim.initiatives.admin_states")}") + expect(mail.body).to include("The initiative #{decidim_sanitize_translated(initiative.title)} has changed its status to: #{I18n.t(initiative.state, scope: "decidim.initiatives.admin_states")}") end end @@ -76,7 +76,7 @@ module Initiatives end it "renders the body" do - expect(mail.body.encoded).to match(initiative.title["en"]) + expect(mail.body.encoded).to include(decidim_sanitize_translated(initiative.title)) end end end diff --git a/decidim-initiatives/spec/presenters/decidim/resource_locator_presenter_spec.rb b/decidim-initiatives/spec/presenters/decidim/resource_locator_presenter_spec.rb new file mode 100644 index 0000000000000..1d2d39d047915 --- /dev/null +++ b/decidim-initiatives/spec/presenters/decidim/resource_locator_presenter_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + describe ResourceLocatorPresenter, type: :helper do + it_behaves_like "generates routes without query strings on slug" do + let(:route_fragment) { "initiatives/#{participatory_space.slug}" } + let(:admin_route_fragment) { "initiatives/#{participatory_space.slug}" } + let(:factory_name) { :initiative } + end + end +end diff --git a/decidim-initiatives/spec/requests/initiative_search_spec.rb b/decidim-initiatives/spec/requests/initiative_search_spec.rb index 6902320e57ac9..2677f28110ea0 100644 --- a/decidim-initiatives/spec/requests/initiative_search_spec.rb +++ b/decidim-initiatives/spec/requests/initiative_search_spec.rb @@ -45,21 +45,21 @@ end it "displays all published open initiatives by default" do - expect(subject).to include(translated(initiative1.title)) - expect(subject).to include(translated(initiative2.title)) - expect(subject).to include(translated(initiative3.title)) - expect(subject).to include(translated(area1_initiative.title)) - expect(subject).to include(translated(area2_initiative.title)) - expect(subject).to include(translated(user1_initiative.title)) - expect(subject).to include(translated(user2_initiative.title)) - expect(subject).to include(translated(group1_initiative.title)) - expect(subject).to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).not_to include(translated(accepted_initiative.title)) - expect(subject).not_to include(translated(rejected_initiative.title)) - expect(subject).not_to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).to include(decidim_escape_translated(initiative1.title)) + expect(subject).to include(decidim_escape_translated(initiative2.title)) + expect(subject).to include(decidim_escape_translated(initiative3.title)) + expect(subject).to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end context "when filtering by text" do @@ -67,42 +67,42 @@ let(:search_text) { "doggo" } it "displays the initiatives containing the search in the title or the body or the author name or nickname" do - expect(subject).to include(translated(initiative1.title)) - expect(subject).to include(translated(initiative2.title)) - expect(subject).not_to include(translated(initiative3.title)) - expect(subject).not_to include(translated(area1_initiative.title)) - expect(subject).not_to include(translated(area2_initiative.title)) - expect(subject).to include(translated(user1_initiative.title)) - expect(subject).to include(translated(user2_initiative.title)) - expect(subject).to include(translated(group1_initiative.title)) - expect(subject).to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).not_to include(translated(accepted_initiative.title)) - expect(subject).not_to include(translated(rejected_initiative.title)) - expect(subject).not_to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).to include(decidim_escape_translated(initiative1.title)) + expect(subject).to include(decidim_escape_translated(initiative2.title)) + expect(subject).not_to include(decidim_escape_translated(initiative3.title)) + expect(subject).not_to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end context "and the search_text is an initiative id" do let(:search_text) { initiative1.id.to_s } it "returns the initiative with the searched id" do - expect(subject).to include(translated(initiative1.title)) - expect(subject).not_to include(translated(initiative2.title)) - expect(subject).not_to include(translated(initiative3.title)) - expect(subject).not_to include(translated(area1_initiative.title)) - expect(subject).not_to include(translated(area2_initiative.title)) - expect(subject).not_to include(translated(user1_initiative.title)) - expect(subject).not_to include(translated(user2_initiative.title)) - expect(subject).not_to include(translated(group1_initiative.title)) - expect(subject).not_to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).not_to include(translated(accepted_initiative.title)) - expect(subject).not_to include(translated(rejected_initiative.title)) - expect(subject).not_to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).to include(decidim_escape_translated(initiative1.title)) + expect(subject).not_to include(decidim_escape_translated(initiative2.title)) + expect(subject).not_to include(decidim_escape_translated(initiative3.title)) + expect(subject).not_to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end end end @@ -114,21 +114,21 @@ let(:state) { %w(open) } it "displays only open initiatives" do - expect(subject).to include(translated(initiative1.title)) - expect(subject).to include(translated(initiative2.title)) - expect(subject).to include(translated(initiative3.title)) - expect(subject).to include(translated(area1_initiative.title)) - expect(subject).to include(translated(area2_initiative.title)) - expect(subject).to include(translated(user1_initiative.title)) - expect(subject).to include(translated(user2_initiative.title)) - expect(subject).to include(translated(group1_initiative.title)) - expect(subject).to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).not_to include(translated(accepted_initiative.title)) - expect(subject).not_to include(translated(rejected_initiative.title)) - expect(subject).not_to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).to include(decidim_escape_translated(initiative1.title)) + expect(subject).to include(decidim_escape_translated(initiative2.title)) + expect(subject).to include(decidim_escape_translated(initiative3.title)) + expect(subject).to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end end @@ -136,21 +136,21 @@ let(:state) { %w(closed) } it "displays only closed initiatives" do - expect(subject).not_to include(translated(initiative1.title)) - expect(subject).not_to include(translated(initiative2.title)) - expect(subject).not_to include(translated(initiative3.title)) - expect(subject).not_to include(translated(area1_initiative.title)) - expect(subject).not_to include(translated(area2_initiative.title)) - expect(subject).not_to include(translated(user1_initiative.title)) - expect(subject).not_to include(translated(user2_initiative.title)) - expect(subject).not_to include(translated(group1_initiative.title)) - expect(subject).not_to include(translated(group2_initiative.title)) - expect(subject).to include(translated(closed_initiative.title)) - expect(subject).to include(translated(accepted_initiative.title)) - expect(subject).to include(translated(rejected_initiative.title)) - expect(subject).to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(initiative1.title)) + expect(subject).not_to include(decidim_escape_translated(initiative2.title)) + expect(subject).not_to include(decidim_escape_translated(initiative3.title)) + expect(subject).not_to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end end @@ -158,21 +158,21 @@ let(:state) { %w(accepted) } it "returns only accepted initiatives" do - expect(subject).not_to include(translated(initiative1.title)) - expect(subject).not_to include(translated(initiative2.title)) - expect(subject).not_to include(translated(initiative3.title)) - expect(subject).not_to include(translated(area1_initiative.title)) - expect(subject).not_to include(translated(area2_initiative.title)) - expect(subject).not_to include(translated(user1_initiative.title)) - expect(subject).not_to include(translated(user2_initiative.title)) - expect(subject).not_to include(translated(group1_initiative.title)) - expect(subject).not_to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).to include(translated(accepted_initiative.title)) - expect(subject).not_to include(translated(rejected_initiative.title)) - expect(subject).not_to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(initiative1.title)) + expect(subject).not_to include(decidim_escape_translated(initiative2.title)) + expect(subject).not_to include(decidim_escape_translated(initiative3.title)) + expect(subject).not_to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end end @@ -180,21 +180,21 @@ let(:state) { %w(rejected) } it "returns only rejected initiatives" do - expect(subject).not_to include(translated(initiative1.title)) - expect(subject).not_to include(translated(initiative2.title)) - expect(subject).not_to include(translated(initiative3.title)) - expect(subject).not_to include(translated(area1_initiative.title)) - expect(subject).not_to include(translated(area2_initiative.title)) - expect(subject).not_to include(translated(user1_initiative.title)) - expect(subject).not_to include(translated(user2_initiative.title)) - expect(subject).not_to include(translated(group1_initiative.title)) - expect(subject).not_to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).not_to include(translated(accepted_initiative.title)) - expect(subject).to include(translated(rejected_initiative.title)) - expect(subject).to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(initiative1.title)) + expect(subject).not_to include(decidim_escape_translated(initiative2.title)) + expect(subject).not_to include(decidim_escape_translated(initiative3.title)) + expect(subject).not_to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end end @@ -202,21 +202,21 @@ let(:state) { %w(answered) } it "returns only answered initiatives" do - expect(subject).not_to include(translated(initiative1.title)) - expect(subject).not_to include(translated(initiative2.title)) - expect(subject).not_to include(translated(initiative3.title)) - expect(subject).not_to include(translated(area1_initiative.title)) - expect(subject).not_to include(translated(area2_initiative.title)) - expect(subject).not_to include(translated(user1_initiative.title)) - expect(subject).not_to include(translated(user2_initiative.title)) - expect(subject).not_to include(translated(group1_initiative.title)) - expect(subject).not_to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).not_to include(translated(accepted_initiative.title)) - expect(subject).not_to include(translated(rejected_initiative.title)) - expect(subject).to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(initiative1.title)) + expect(subject).not_to include(decidim_escape_translated(initiative2.title)) + expect(subject).not_to include(decidim_escape_translated(initiative3.title)) + expect(subject).not_to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end end @@ -224,21 +224,21 @@ let(:state) { %w(open closed) } it "displays only closed initiatives" do - expect(subject).to include(translated(initiative1.title)) - expect(subject).to include(translated(initiative2.title)) - expect(subject).to include(translated(initiative3.title)) - expect(subject).to include(translated(area1_initiative.title)) - expect(subject).to include(translated(area2_initiative.title)) - expect(subject).to include(translated(user1_initiative.title)) - expect(subject).to include(translated(user2_initiative.title)) - expect(subject).to include(translated(group1_initiative.title)) - expect(subject).to include(translated(group2_initiative.title)) - expect(subject).to include(translated(closed_initiative.title)) - expect(subject).to include(translated(accepted_initiative.title)) - expect(subject).to include(translated(rejected_initiative.title)) - expect(subject).to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).to include(decidim_escape_translated(initiative1.title)) + expect(subject).to include(decidim_escape_translated(initiative2.title)) + expect(subject).to include(decidim_escape_translated(initiative3.title)) + expect(subject).to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end end end @@ -250,21 +250,21 @@ let(:scope_id) { [scoped_type1.scope.id] } it "displays initiatives by scope" do - expect(subject).to include(translated(initiative1.title)) - expect(subject).not_to include(translated(initiative2.title)) - expect(subject).not_to include(translated(initiative3.title)) - expect(subject).not_to include(translated(area1_initiative.title)) - expect(subject).not_to include(translated(area2_initiative.title)) - expect(subject).not_to include(translated(user1_initiative.title)) - expect(subject).not_to include(translated(user2_initiative.title)) - expect(subject).not_to include(translated(group1_initiative.title)) - expect(subject).not_to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).not_to include(translated(accepted_initiative.title)) - expect(subject).not_to include(translated(rejected_initiative.title)) - expect(subject).not_to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).to include(decidim_escape_translated(initiative1.title)) + expect(subject).not_to include(decidim_escape_translated(initiative2.title)) + expect(subject).not_to include(decidim_escape_translated(initiative3.title)) + expect(subject).not_to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end end @@ -272,21 +272,21 @@ let(:scope_id) { [scoped_type2.scope.id, scoped_type1.scope.id] } it "displays initiatives by scope" do - expect(subject).to include(translated(initiative1.title)) - expect(subject).to include(translated(initiative2.title)) - expect(subject).not_to include(translated(initiative3.title)) - expect(subject).not_to include(translated(area1_initiative.title)) - expect(subject).not_to include(translated(area2_initiative.title)) - expect(subject).not_to include(translated(user1_initiative.title)) - expect(subject).not_to include(translated(user2_initiative.title)) - expect(subject).not_to include(translated(group1_initiative.title)) - expect(subject).not_to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).not_to include(translated(accepted_initiative.title)) - expect(subject).not_to include(translated(rejected_initiative.title)) - expect(subject).not_to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).to include(decidim_escape_translated(initiative1.title)) + expect(subject).to include(decidim_escape_translated(initiative2.title)) + expect(subject).not_to include(decidim_escape_translated(initiative3.title)) + expect(subject).not_to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end end end @@ -308,21 +308,21 @@ let(:author) { "any" } it "displays all initiatives except the created ones" do - expect(subject).to include(translated(initiative1.title)) - expect(subject).to include(translated(initiative2.title)) - expect(subject).to include(translated(initiative3.title)) - expect(subject).to include(translated(area1_initiative.title)) - expect(subject).to include(translated(area2_initiative.title)) - expect(subject).to include(translated(user1_initiative.title)) - expect(subject).to include(translated(user2_initiative.title)) - expect(subject).to include(translated(group1_initiative.title)) - expect(subject).to include(translated(group2_initiative.title)) - expect(subject).to include(translated(closed_initiative.title)) - expect(subject).to include(translated(accepted_initiative.title)) - expect(subject).to include(translated(rejected_initiative.title)) - expect(subject).to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).to include(decidim_escape_translated(initiative1.title)) + expect(subject).to include(decidim_escape_translated(initiative2.title)) + expect(subject).to include(decidim_escape_translated(initiative3.title)) + expect(subject).to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end end @@ -330,21 +330,21 @@ let(:author) { "myself" } it "contains only initiatives of the author, including their created upcoming initiative" do - expect(subject).not_to include(translated(initiative1.title)) - expect(subject).not_to include(translated(initiative2.title)) - expect(subject).not_to include(translated(initiative3.title)) - expect(subject).not_to include(translated(area1_initiative.title)) - expect(subject).not_to include(translated(area2_initiative.title)) - expect(subject).to include(translated(user1_initiative.title)) - expect(subject).not_to include(translated(user2_initiative.title)) - expect(subject).not_to include(translated(group1_initiative.title)) - expect(subject).not_to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).not_to include(translated(accepted_initiative.title)) - expect(subject).not_to include(translated(rejected_initiative.title)) - expect(subject).not_to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).to include(translated(user1_created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(initiative1.title)) + expect(subject).not_to include(decidim_escape_translated(initiative2.title)) + expect(subject).not_to include(decidim_escape_translated(initiative3.title)) + expect(subject).not_to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).to include(decidim_escape_translated(user1_created_initiative.title)) end end end @@ -354,42 +354,42 @@ let(:type_id) { [initiative1.type.id] } it "displays initiatives of correct type" do - expect(subject).to include(translated(initiative1.title)) - expect(subject).not_to include(translated(initiative2.title)) - expect(subject).not_to include(translated(initiative3.title)) - expect(subject).not_to include(translated(area1_initiative.title)) - expect(subject).not_to include(translated(area2_initiative.title)) - expect(subject).not_to include(translated(user1_initiative.title)) - expect(subject).not_to include(translated(user2_initiative.title)) - expect(subject).not_to include(translated(group1_initiative.title)) - expect(subject).not_to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).not_to include(translated(accepted_initiative.title)) - expect(subject).not_to include(translated(rejected_initiative.title)) - expect(subject).not_to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).to include(decidim_escape_translated(initiative1.title)) + expect(subject).not_to include(decidim_escape_translated(initiative2.title)) + expect(subject).not_to include(decidim_escape_translated(initiative3.title)) + expect(subject).not_to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end context "and providing multiple types" do let(:type_id) { [initiative1.type.id, initiative2.type.id] } it "displays initiatives of correct type" do - expect(subject).to include(translated(initiative1.title)) - expect(subject).to include(translated(initiative2.title)) - expect(subject).not_to include(translated(initiative3.title)) - expect(subject).not_to include(translated(area1_initiative.title)) - expect(subject).not_to include(translated(area2_initiative.title)) - expect(subject).not_to include(translated(user1_initiative.title)) - expect(subject).not_to include(translated(user2_initiative.title)) - expect(subject).not_to include(translated(group1_initiative.title)) - expect(subject).not_to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).not_to include(translated(accepted_initiative.title)) - expect(subject).not_to include(translated(rejected_initiative.title)) - expect(subject).not_to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).to include(decidim_escape_translated(initiative1.title)) + expect(subject).to include(decidim_escape_translated(initiative2.title)) + expect(subject).not_to include(decidim_escape_translated(initiative3.title)) + expect(subject).not_to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end end end @@ -401,21 +401,21 @@ let(:area_id) { [area1.id.to_s] } it "displays initiatives by area" do - expect(subject).not_to include(translated(initiative1.title)) - expect(subject).not_to include(translated(initiative2.title)) - expect(subject).not_to include(translated(initiative3.title)) - expect(subject).to include(translated(area1_initiative.title)) - expect(subject).not_to include(translated(area2_initiative.title)) - expect(subject).not_to include(translated(user1_initiative.title)) - expect(subject).not_to include(translated(user2_initiative.title)) - expect(subject).not_to include(translated(group1_initiative.title)) - expect(subject).not_to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).not_to include(translated(accepted_initiative.title)) - expect(subject).not_to include(translated(rejected_initiative.title)) - expect(subject).not_to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(initiative1.title)) + expect(subject).not_to include(decidim_escape_translated(initiative2.title)) + expect(subject).not_to include(decidim_escape_translated(initiative3.title)) + expect(subject).to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end end @@ -423,21 +423,21 @@ let(:area_id) { [area1.id.to_s, area2.id.to_s] } it "displays initiatives by area" do - expect(subject).not_to include(translated(initiative1.title)) - expect(subject).not_to include(translated(initiative2.title)) - expect(subject).not_to include(translated(initiative3.title)) - expect(subject).to include(translated(area1_initiative.title)) - expect(subject).to include(translated(area2_initiative.title)) - expect(subject).not_to include(translated(user1_initiative.title)) - expect(subject).not_to include(translated(user2_initiative.title)) - expect(subject).not_to include(translated(group1_initiative.title)) - expect(subject).not_to include(translated(group2_initiative.title)) - expect(subject).not_to include(translated(closed_initiative.title)) - expect(subject).not_to include(translated(accepted_initiative.title)) - expect(subject).not_to include(translated(rejected_initiative.title)) - expect(subject).not_to include(translated(answered_rejected_initiative.title)) - expect(subject).not_to include(translated(created_initiative.title)) - expect(subject).not_to include(translated(user1_created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(initiative1.title)) + expect(subject).not_to include(decidim_escape_translated(initiative2.title)) + expect(subject).not_to include(decidim_escape_translated(initiative3.title)) + expect(subject).to include(decidim_escape_translated(area1_initiative.title)) + expect(subject).to include(decidim_escape_translated(area2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group1_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(group2_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(closed_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(accepted_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(answered_rejected_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(created_initiative.title)) + expect(subject).not_to include(decidim_escape_translated(user1_created_initiative.title)) end end end diff --git a/decidim-meetings/app/cells/decidim/meetings/meeting_s_cell.rb b/decidim-meetings/app/cells/decidim/meetings/meeting_s_cell.rb index 409c3793866c7..682cc8ab44a0a 100644 --- a/decidim-meetings/app/cells/decidim/meetings/meeting_s_cell.rb +++ b/decidim-meetings/app/cells/decidim/meetings/meeting_s_cell.rb @@ -14,7 +14,7 @@ def participatory_space_class_name end def participatory_space_title - translated_attribute model.component.participatory_space.title + decidim_escape_translated model.component.participatory_space.title end def participatory_space_path diff --git a/decidim-meetings/app/helpers/decidim/meetings/directory/application_helper.rb b/decidim-meetings/app/helpers/decidim/meetings/directory/application_helper.rb index f4cdd42a25492..78bb132d28936 100644 --- a/decidim-meetings/app/helpers/decidim/meetings/directory/application_helper.rb +++ b/decidim-meetings/app/helpers/decidim/meetings/directory/application_helper.rb @@ -92,7 +92,7 @@ def directory_filter_categories_values key_point = current_participatory_space.class.name.gsub("::", "__") + current_participatory_space.id.to_s TreeNode.new( - TreePoint.new(key_point, translated_attribute(current_participatory_space.title, current_organization)), + TreePoint.new(key_point, decidim_escape_translated(current_participatory_space.title)), categories_values ) end diff --git a/decidim-meetings/app/packs/src/decidim/meetings/poll.component.js b/decidim-meetings/app/packs/src/decidim/meetings/poll.component.js index 87017ed910997..b34d35b5b5fc1 100644 --- a/decidim-meetings/app/packs/src/decidim/meetings/poll.component.js +++ b/decidim-meetings/app/packs/src/decidim/meetings/poll.component.js @@ -1,5 +1,8 @@ /* eslint id-length: ["error", { "exceptions": ["$"] }] */ +import createOptionAttachedInputs from "src/decidim/forms/option_attached_inputs.component" +import createMaxChoicesAlertComponent from "src/decidim/forms/max_choices_alert.component" + /** * A plain Javascript component that handles questions from polls in meetings: * - fetches them via Ajax @@ -75,6 +78,7 @@ export default class PollComponent { this._updateCounter(); this._setQuestionsState(this.$element); this._pollQuestions(); + this._addValidations(); }); } @@ -163,4 +167,27 @@ export default class PollComponent { this.$counter.html(`(${questionsCount})`); } } + + _addValidations() { + $(".js-radio-button-collection, .js-check-box-collection").each((idx, el) => { + createOptionAttachedInputs({ + wrapperField: $(el), + controllerFieldSelector: "input[type=radio], input[type=checkbox]", + dependentInputSelector: "input[type=text], input[type=hidden]" + }); + }); + + $.unique($(".js-check-box-collection").parents(".answer")).each((idx, el) => { + const maxChoices = $(el).data("max-choices"); + if (maxChoices) { + createMaxChoicesAlertComponent({ + wrapperField: $(el), + controllerFieldSelector: "input[type=checkbox]", + controllerCollectionSelector: ".js-check-box-collection", + alertElement: $(el).find(".max-choices-alert"), + maxChoices: maxChoices + }); + } + }); + } } diff --git a/decidim-meetings/app/services/decidim/meetings/close_meeting_reminder_generator.rb b/decidim-meetings/app/services/decidim/meetings/close_meeting_reminder_generator.rb index 7a1224084e687..7a470d470eab0 100644 --- a/decidim-meetings/app/services/decidim/meetings/close_meeting_reminder_generator.rb +++ b/decidim-meetings/app/services/decidim/meetings/close_meeting_reminder_generator.rb @@ -38,11 +38,9 @@ def finder_query(component_id, interval) def send_reminders(component) intervals = Array(reminder_manifest.settings.attributes[:reminder_times].default) - space_admins = Decidim::ParticipatoryProcessUserRole.where(decidim_participatory_process_id: component.participatory_space_id, role: "admin").collect(&:user) - space_admins = (global_admins + space_admins).uniq intervals.each do |interval| finder_query(component.id, interval).find_each do |meeting| - authors = meeting.official? ? space_admins : [meeting.author] + authors = meeting.official? ? space_admins(component) : [meeting.author] authors.each do |author| send_notif = author.notification_settings.fetch("close_meeting_reminder", "1") next unless send_notif == "1" @@ -60,8 +58,16 @@ def send_reminders(component) end end - def global_admins - @global_admins ||= Decidim::User.where(admin: true).all + def space_admins(component) + @space_admins ||= begin + space_admins = if component.participatory_space.respond_to?(:user_roles) + component.participatory_space.user_roles(:admin).collect(&:user) + else + [] + end + global_admins = component.organization.admins + (global_admins + space_admins).uniq + end end end end diff --git a/decidim-meetings/app/views/decidim/meetings/admin/agenda/_form.html.erb b/decidim-meetings/app/views/decidim/meetings/admin/agenda/_form.html.erb index 9013d3fddbd3e..c7e5e74f8c97c 100644 --- a/decidim-meetings/app/views/decidim/meetings/admin/agenda/_form.html.erb +++ b/decidim-meetings/app/views/decidim/meetings/admin/agenda/_form.html.erb @@ -3,7 +3,7 @@

    - <%= present(@meeting).title %>  <%= icon "arrow-right" %> <%= title %> + <%= present(@meeting).title(html_escape: true) %>  <%= icon "arrow-right" %> <%= title %>

    diff --git a/decidim-meetings/app/views/decidim/meetings/layouts/live_event.html.erb b/decidim-meetings/app/views/decidim/meetings/layouts/live_event.html.erb index 6aa142ec43009..56527e10b8a40 100644 --- a/decidim-meetings/app/views/decidim/meetings/layouts/live_event.html.erb +++ b/decidim-meetings/app/views/decidim/meetings/layouts/live_event.html.erb @@ -24,7 +24,7 @@ <% end %>
    - <%= current_organization.name %> / <%= present(meeting).title(links: true) %> + <%= current_organization.name %> / <%= present(meeting).title(links: true, html_escape: true) %>
    diff --git a/decidim-meetings/app/views/decidim/meetings/meetings/_meeting_agenda.html.erb b/decidim-meetings/app/views/decidim/meetings/meetings/_meeting_agenda.html.erb index e028dea85c705..c893ea103b542 100644 --- a/decidim-meetings/app/views/decidim/meetings/meetings/_meeting_agenda.html.erb +++ b/decidim-meetings/app/views/decidim/meetings/meetings/_meeting_agenda.html.erb @@ -11,7 +11,7 @@ <%= display_duration_agenda_items(agenda_item.id, index, agenda_items_times) %>
    -

    <%= translated_attribute(agenda_item.description).html_safe %>

    +

    <%= decidim_sanitize_translated(agenda_item.description).html_safe %>

    <% if agenda_item.agenda_item_children.presence %> <% parent_start_time = agenda_items_times[index][:start_time] %> @@ -22,7 +22,7 @@ <%= translated_attribute(agenda_item_child.title) %>  <%= display_duration_agenda_items(agenda_item_child.id, index_child, agenda_item_children_times) %> -

    <%= translated_attribute(agenda_item_child.description).html_safe %>

    +

    <%= decidim_sanitize_translated(agenda_item_child.description).html_safe %>

    <% end %> <% end %> <% end %> diff --git a/decidim-meetings/app/views/decidim/meetings/polls/answers/_multiple_option.html.erb b/decidim-meetings/app/views/decidim/meetings/polls/answers/_multiple_option.html.erb index 892579f79abdf..16141c4c125b9 100644 --- a/decidim-meetings/app/views/decidim/meetings/polls/answers/_multiple_option.html.erb +++ b/decidim-meetings/app/views/decidim/meetings/polls/answers/_multiple_option.html.erb @@ -1,13 +1,17 @@ -<% question.answer_options.each_with_index do |answer_option, idx| %> - <% choice = answer.choices.find { |choice| choice.decidim_answer_option_id == answer_option.id } if answer %> +
    + <% question.answer_options.each_with_index do |answer_option, idx| %> + <% choice = answer.choices.find { |choice| choice.decidim_answer_option_id == answer_option.id } if answer %> - <%= label_tag do %> - <%= check_box_tag "answer[choices][#{idx}][body]", - translated_attribute(answer_option.body), - choice.present?, disabled: disabled %> +
    + <%= label_tag do %> + <%= check_box_tag "answer[choices][#{idx}][body]", + translated_attribute(answer_option.body), + choice.present?, disabled: disabled %> - <%= translated_attribute(answer_option.body) %> + <%= translated_attribute(answer_option.body) %> - <%= hidden_field_tag "answer[choices][#{idx}][answer_option_id]", answer_option.id, disabled: disabled %> + <%= hidden_field_tag "answer[choices][#{idx}][answer_option_id]", answer_option.id, disabled: disabled %> + <% end %> +
    <% end %> -<% end %> +
    diff --git a/decidim-meetings/app/views/decidim/meetings/polls/answers/_single_option.html.erb b/decidim-meetings/app/views/decidim/meetings/polls/answers/_single_option.html.erb index 33faa49313e95..a82bec96084f0 100644 --- a/decidim-meetings/app/views/decidim/meetings/polls/answers/_single_option.html.erb +++ b/decidim-meetings/app/views/decidim/meetings/polls/answers/_single_option.html.erb @@ -4,16 +4,16 @@ <% choice_id = "#{field_id}_choices_#{idx}" %> <%= label_tag "#{choice_id}_body" do %> - <%= radio_button_tag "answer[choices][#{idx}][body]", - translated_attribute(answer_option.body), - answer_option.id == choice.try(:decidim_answer_option_id), - id: "#{choice_id}_body", disabled: disabled %> + <%= radio_button_tag "answer[choices][#{question.id}][body]", + translated_attribute(answer_option.body), + answer_option.id == choice.try(:decidim_answer_option_id), + id: "#{choice_id}_body", disabled: disabled %> <%= translated_attribute(answer_option.body) %> - <%= hidden_field_tag "answer[choices][#{idx}][answer_option_id]", - answer_option.id, - id: "#{choice_id}_answer_option", - disabled: disabled %> + <%= hidden_field_tag "answer[choices][#{question.id}][answer_option_id]", + answer_option.id, + id: "#{choice_id}_answer_option", + disabled: disabled %> <% end %> <% end %> diff --git a/decidim-meetings/app/views/decidim/meetings/polls/questions/_published_question.html.erb b/decidim-meetings/app/views/decidim/meetings/polls/questions/_published_question.html.erb index 79dc93a76f16e..511900a21304d 100644 --- a/decidim-meetings/app/views/decidim/meetings/polls/questions/_published_question.html.erb +++ b/decidim-meetings/app/views/decidim/meetings/polls/questions/_published_question.html.erb @@ -6,12 +6,12 @@ <% @form = form || Decidim::Meetings::AnswerForm.new(question_id: question.id, current_user: current_user) %> <%= decidim_form_for(@form, url: meeting_polls_answers_path(meeting), method: :post, remote: true, html: { class: "form answer-questionnaire" }, data: { "safe-path" => meeting_live_event_path(meeting) }) do |form| %>
    + <%= t(".max_choices_alert") %> + <%= render partial: "decidim/meetings/polls/answers/#{question.question_type}", locals: { answer: @form.answer, question: question, answer_form: form, disabled: question.answered_by?(current_user), field_id: question.id } %> <%= form.hidden_field :question_id %> - <%= t(".max_choices_alert") %> - <% @form.errors.full_messages.each do |msg| %> <%= msg %> <% end %> diff --git a/decidim-meetings/config/locales/bg.yml b/decidim-meetings/config/locales/bg.yml index 5280465c0bd32..640523059f4fc 100644 --- a/decidim-meetings/config/locales/bg.yml +++ b/decidim-meetings/config/locales/bg.yml @@ -1,6 +1,34 @@ --- bg: + activemodel: + errors: + models: + meeting: + attributes: + iframe_embed_type: + not_embeddable: Този URL адрес не може да бъде вграден в страница за среща или събитие на живо + meeting_agenda: + attributes: + base: + too_many_minutes: Продължителността на точките надвишава продължителността на срещата с(ъс) %{count} минути + too_many_minutes_child: Продължителността на подточките надвишава продължителността на точката от дневния ред „%{parent_title}“ с(ъс) %{count} минути + meeting_registration_invite: + attributes: + email: + already_invited: На този имейл вече е изпратена покана decidim: + admin: + meeting_copies: + new: + select: Изберете кои данни искате да дублирате + forms: + meetings: + attendees_count_help_text: Не забравяйте да включите общия брой присъстващи на вашата среща, независимо дали те присъстват лично, онлайн или хибридно. + gamification: + badges: + attended_meetings: + unearned_another: Този участник все още не е присъствал на нито една среща. + unearned_own: Все още не сте присъствали на нито една среща. meetings: actions: invalid_destroy: @@ -8,9 +36,86 @@ bg: one: 'Срещата не може да бъде премахната, понеже има %{count} участник свързан с нея:' other: 'Срещата не може да бъде премахната, понеже има %{count} участника свързани с нея:' admin: + agenda: + create: + invalid: Възникна проблем при създаването на този дневен ред + success: Дневният ред беше създаден успешно + update: + invalid: Възникна проблем при актуализирането на този дневен ред + success: Дневният ред беше актуализиран успешно + invites: + index: + filter_by: Филтрирай по + registrations_disabled: Не можете да поканите присъстващи, защото регистрациите са изключени. meetings: + close: + invalid: Възникна проблем при закриването на тази среща + success: Срещата беше закрита успешно + create: + invalid: Възникна проблем при създаването на тази среща destroy: invalid: proposals_count: one: Срещата не може да бъде премахната, понеже има %{count} участник свързан с нея other: Срещата не може да бъде премахната, понеже има %{count} участника свързани с нея + form: + disclaimer: 'Отказ от отговорност: Използвайки външна система за регистрация, вие сте наясно, че организаторите на %{organization} не носят отговорност за данните, предоставени от потребителите на външната услуга.' + publish: + invalid: Възникна проблем при публикуването на тази среща + success: Срещата беше публикувана успешно + unpublish: + invalid: Възникна проблем при отмяната на публикуването на тази среща + success: Публикуването на срещата беше успешно отменено + update: + invalid: Възникна проблем при актуализирането на тази среща + success: Срещата беше актуализирана успешно + meetings_poll: + update: + invalid: Възникна проблем при актуализирането на тази анкета за среща + success: Анкетата за среща бе актуализирана успешно + registrations: + form: + reserved_slots_help: Оставете 0, ако не разполагате с резервирани места + calendar_modal: + close_window: Затвори прозореца + copy_calendar_url_explanation: Моля, обърнете внимание, че експортирате селекция от срещи, тъй като има активни филтри. Ако искате да ги експортирате всички, първо нулирайте всички филтри. + content_blocks: + upcoming_meetings: + view_all_meetings: Виж всички + last_activity: + meeting_updated_at_html: "Срещата беше актуализирана на: %{link}" + new_meeting_at_html: "Нова среща на %{link}" + meeting: + not_allowed: Нямате разрешение да разглеждате тази среща + meetings: + calendar_modal: + close_window: Затвори прозореца + filters_small_view: + close_modal: Затвори прозореца + filter: Филтър + filter_by: Филтрирай по + unfold: Разгъване + form: + disclaimer: 'Отказ от отговорност: Използвайки външна система за регистрация, вие сте наясно, че организаторите на %{organization} не носят отговорност за данните, предоставени от потребителите на външната услуга.' + meeting_minutes: + related_information: Свързана информация + meetings: + no_meetings_warning: Няма срещи, които да съответстват на критериите Ви за търсене, или няма насрочени срещи. + show: + back: Обратно към списъка + view: Преглед + meetings_map: + view_meeting: Преглед на срещата + public_participants_list: + attending_participants: Присъстващи участници + registrations: + create: + success: Присъединихте се успешно към срещата. Тъй като се регистрирахте за тази среща, ще бъдете уведомявани за всички нейни актуализации. + versions: + back_to_resource: Връщане назад към срещата + withdraw: + error: Възникна грешка при оттеглянето на срещата + success: Срещата е оттеглена успешно + participatory_spaces: + highlighted_meetings: + see_all: Виж всички срещи (%{count}) diff --git a/decidim-meetings/config/locales/ca.yml b/decidim-meetings/config/locales/ca.yml index 91c1000cfdf91..6cbc89e8f7292 100644 --- a/decidim-meetings/config/locales/ca.yml +++ b/decidim-meetings/config/locales/ca.yml @@ -165,14 +165,14 @@ ca: meeting_created: button_text: Inscriu-te a la trobada email_intro: S'ha afegit la trobada "%{resource_title}" a l'espai "%{participatory_space_title}" que estàs seguint. - email_outro: Has rebut aquesta notificació perquè estàs seguint "%{participatory_space_title}". Pots deixar de seguir-lo des de l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint l'espai "%{participatory_space_title}". Pots deixar de seguir-lo des de l'enllaç anterior. email_subject: Nova trobada afegida a %{participatory_space_title} notification_title: S'ha afegit la trobada %{resource_title} a %{participatory_space_title} meeting_registration_confirmed: notification_title: S'ha confirmat el teu registre per a la trobada %{resource_title}. El teu codi de registre és %{registration_code}. meeting_registrations_over_percentage: email_intro: Les inscripcions per la trobada "%{resource_title}" superen el %{percentage}%. - email_outro: Has rebut aquesta notificació perquè ets administradora de l'espai participatiu de la trobada. + email_outro: Has rebut aquesta notificació perquè administres l'espai participatiu de la trobada. email_subject: Les inscripcions per la trobada "%{resource_title}" superen el %{percentage}% notification_title: Les inscripcions per la trobada %{resource_title} superen el %{percentage}%. meeting_updated: @@ -419,7 +419,7 @@ ca: body: La trobada "%{meeting_title}" està pendent de tancar-se. Si us plau, afegiu un informe de la reunió fent servir el botó "Tancar trobada". greetings: Hola,
    %{organization_name}
    %{organization_url} hello: Hola %{username}, - subject: Ara pots tancar la trobada amb un informe a la plataforma %{organization_name} + subject: Està pendent tancar la trobada amb un informe a la plataforma %{organization_name} conference_venues: Seus de les jornades content_blocks: upcoming_meetings: @@ -663,7 +663,7 @@ ca: participatory_spaces: highlighted_meetings: past_meetings: Trobades anteriors - see_all: Veure tots (%{count}) + see_all: Veure totes (%{count}) upcoming_meetings: Properes trobades upcoming_meeting_for_card: upcoming_meeting: Propera trobada diff --git a/decidim-meetings/config/locales/es.yml b/decidim-meetings/config/locales/es.yml index 23a4021142d4a..5efca7994af8b 100644 --- a/decidim-meetings/config/locales/es.yml +++ b/decidim-meetings/config/locales/es.yml @@ -154,7 +154,7 @@ es: meeting_closed: affected_user: email_intro: 'Tu encuentro "%{resource_title}" se ha cerrado. Puedes leer las conclusiones desde su página:' - email_outro: Has recibido esta notificación porque has organizaco el encuentro "%{resource_title}". + email_outro: Has recibido esta notificación porque organizaste el encuentro "%{resource_title}". email_subject: Se ha cerrado el encuentro "%{resource_title}" notification_title: El encuentro %{resource_title} ha sido cerrada. follower: @@ -165,14 +165,14 @@ es: meeting_created: button_text: Inscribirse en el encuentro email_intro: Se ha añadido el encuentro "%{resource_title}" al espacio "%{participatory_space_title}" que estás siguiendo. - email_outro: Has recibido esta notificación porque sigues "%{participatory_space_title}". Puedes dejar de seguirlo en el enlace anterior. + email_outro: Has recibido esta notificación porque sigues el espacio "%{participatory_space_title}". Puedes dejar de seguirlo en el enlace anterior. email_subject: Nuevo encuentro añadido en %{participatory_space_title} notification_title: Se ha añadido el encuentro %{resource_title} en %{participatory_space_title} meeting_registration_confirmed: notification_title: Tu inscripción al encuentro %{resource_title} ha sido confirmada. Tu código de registro es %{registration_code}. meeting_registrations_over_percentage: email_intro: Las inscripciones para el encuentro "%{resource_title}" superan el %{percentage}%. - email_outro: Has recibido esta notificación porque eres administradora del espacio participativo del encuentro. + email_outro: Has recibido esta notificación porque administras el espacio participativo del encuentro. email_subject: Las inscripciones para el encuentro "%{resource_title}" superan el %{percentage}% notification_title: Las inscripciones para el encuentro %{resource_title} superan el %{percentage}%. meeting_updated: @@ -419,7 +419,7 @@ es: body: El encuentro "%{meeting_title}" está pendiente de cerrarse. Por favor, agrega un informe de la reunión usando el botón "Cerrar encuentro". greetings: Hola,
    %{organization_name}
    %{organization_url} hello: Hola %{username}, - subject: Ahora puedes cerrar el encuentro con un informe en la plataforma %{organization_name} + subject: Está pendiente cerrar el encuentro con un informe en la plataforma %{organization_name} conference_venues: Sedes de las jornadas content_blocks: upcoming_meetings: diff --git a/decidim-meetings/config/locales/he-IL.yml b/decidim-meetings/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-meetings/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-meetings/config/locales/pl.yml b/decidim-meetings/config/locales/pl.yml index 58ced97daff73..9d71948cecc1a 100644 --- a/decidim-meetings/config/locales/pl.yml +++ b/decidim-meetings/config/locales/pl.yml @@ -28,21 +28,37 @@ pl: organizer_gid: Utwórz jako organizer_id: Organizator private_meeting: Prywatne spotkanie + registration_email_custom_content: Niestandardowa treści rejestracyjnego e-maila registration_form_enabled: Włączono formularz rejestracyjny registration_terms: Warunki rejestracji + registration_type: Typ rejestracji registration_url: Adres URL rejestracji registrations_enabled: Rejestracje włączone + reserved_slots: Zastrzeżone miejsca na to spotkanie + start_time: Godzina rozpoczęcia title: Tytuł transparent: Transparentny type_of_meeting: Typ + meeting_agenda: + title: Tytuł + visible: Widoczna meeting_agenda_items: + description: Opis duration: Czas trwania + title: Tytuł + meeting_registration_invite: + email: E-mail + name: Nazwa + validate_registration_code: + code: Kod errors: models: meeting: attributes: iframe_embed_type: not_embeddable: Ten adres URL nie może być osadzony na stronie spotkania lub wydarzenia na żywo + online_meeting_url: + url_format: Adres URL musi być prawidłowy meeting_agenda: attributes: base: @@ -85,16 +101,27 @@ pl: closed_at_present: label: Państwo values: + 'false': Otwarte 'true': Zamknięte is_upcoming_true: label: Data + values: + 'false': Przeszłe + 'true': Nadchodzące + scope_id_eq: + label: Zakres with_any_origin: + label: Źródło values: + official: Oficjalny + participants: Uczestnik user_group: Grupy użytkowników with_any_type: label: Rodzaj spotkania values: + hybrid: Hybrydowe in_person: Osobiste + online: Online meeting_copies: create: error: Wystąpił błąd podczas duplikowania tego spotkania. @@ -106,6 +133,7 @@ pl: components: meetings: actions: + comment: Skomentuj join: Dołącz name: Spotkania settings: @@ -261,7 +289,9 @@ pl: select_user: Wybierz użytkownika index: filter: + accepted: Zaakceptowano all: Wszystkie + rejected: Odrzucono sent: Wysłano filter_by: Filtruj według invite_attendee: Zaproś uczestnika @@ -574,11 +604,21 @@ pl: questions: closed_question: question_results: Wyniki wyborów + index_admin: + edit: Edytuj w panelu administratora + question: Pytanie + received_answer: otrzymana odpowiedź + received_answers: otrzymane odpowiedzi + results: Wyniki + send: Wyślij + sent: Wysłano published_question: max_choices_alert: Wybrano zbyt wiele opcji question: Pytanie question_replied: Odpowiedziano na pytanie reply_question: Odpowiedz na pytanie + public_participants_list: + attending_participants: Uczestnicy biorący udział read_more: "(zobacz więcej)" registration_mailer: confirmation: @@ -606,6 +646,7 @@ pl: types: private_meeting: Prywatne spotkanie transparent: Transparentne + withdraw: Wycofany versions: back_to_resource: Wróć do spotkania withdraw: diff --git a/decidim-meetings/lib/decidim/meetings/test/factories.rb b/decidim-meetings/lib/decidim/meetings/test/factories.rb index dfc722c3e6e11..75d723b6f6108 100644 --- a/decidim-meetings/lib/decidim/meetings/test/factories.rb +++ b/decidim-meetings/lib/decidim/meetings/test/factories.rb @@ -6,9 +6,12 @@ FactoryBot.define do factory :meeting_component, parent: :component do - name { Decidim::Components::Namer.new(participatory_space.organization.available_locales, :meetings).i18n_name } + transient do + skip_injection { false } + end + name { generate_component_name(participatory_space.organization.available_locales, :meetings, skip_injection: skip_injection) } manifest_name { :meetings } - participatory_space { create(:participatory_process, :with_steps, organization: organization) } + participatory_space { create(:participatory_process, :with_steps, organization: organization, skip_injection: skip_injection) } trait :with_creation_enabled do settings do @@ -20,10 +23,14 @@ end factory :meeting, class: "Decidim::Meetings::Meeting" do - title { generate_localized_title } - description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } - location { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } - location_hints { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + transient do + skip_injection { false } + end + + title { generate_localized_title(:meeting_title, skip_injection: skip_injection) } + description { generate_localized_description(:meeting_description, skip_injection: skip_injection) } + location { generate_localized_description(:meeting_location, skip_injection: skip_injection) } + location_hints { generate_localized_description(:meeting_location_hints, skip_injection: skip_injection) } address { Faker::Lorem.sentence(word_count: 3) } latitude { Faker::Address.latitude } longitude { Faker::Address.longitude } @@ -33,10 +40,10 @@ transparent { true } questionnaire { build(:questionnaire) } registration_form_enabled { true } - registration_terms { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + registration_terms { generate_localized_description(:meeting_registration_terms, skip_injection: skip_injection) } registration_type { :on_this_platform } type_of_meeting { :in_person } - component { build(:component, manifest_name: "meetings") } + component { build(:meeting_component) } iframe_access_level { :all } iframe_embed_type { :none } @@ -71,7 +78,7 @@ end trait :not_official do - author { create(:user, organization: component.organization) if component } + author { create(:user, organization: component.organization, skip_injection: skip_injection) if component } end trait :with_services do @@ -82,7 +89,7 @@ end after(:build) do |meeting, evaluator| - meeting.services = evaluator.services || build_list(:service, 2, meeting: meeting) + meeting.services = evaluator.services || build_list(:service, 2, meeting: meeting, skip_injection: evaluator.skip_injection) end end @@ -90,15 +97,15 @@ trait :user_group_author do author do - create(:user, organization: component.organization) if component + create(:user, organization: component.organization, skip_injection: skip_injection) if component end user_group do - create(:user_group, :verified, organization: component.organization, users: [author]) if component + create(:user_group, :verified, organization: component.organization, users: [author], skip_injection: skip_injection) if component end end trait :closed do - closing_report { generate_localized_title } + closing_report { generate_localized_title(:meeting_closing_report, skip_injection: skip_injection) } attendees_count { rand(50) } contributions_count { rand(50) } attending_organizations { Array.new(3) { Faker::TvShows::GameOfThrones.house }.join(", ") } @@ -117,7 +124,7 @@ registrations_enabled { true } available_slots { 10 } reserved_slots { 4 } - registration_terms { generate_localized_title } + registration_terms { generate_localized_title(:meeting_registration_terms, skip_injection: skip_injection) } end trait :past do @@ -170,41 +177,53 @@ end factory :registration, class: "Decidim::Meetings::Registration" do + transient do + skip_injection { false } + end meeting user end factory :agenda, class: "Decidim::Meetings::Agenda" do + transient do + skip_injection { false } + end meeting - title { generate_localized_title } + title { generate_localized_title(:meeting_agenda_title, skip_injection: skip_injection) } visible { true } trait :with_agenda_items do - after(:create) do |agenda, _evaluator| - create_list(:agenda_item, 2, :with_children, agenda: agenda) + after(:create) do |agenda, evaluator| + create_list(:agenda_item, 2, :with_children, agenda: agenda, skip_injection: evaluator.skip_injection) end end end factory :agenda_item, class: "Decidim::Meetings::AgendaItem" do + transient do + skip_injection { false } + end agenda - title { generate_localized_title } - description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + title { generate_localized_title(:meeting_agenda_item_title, skip_injection: skip_injection) } + description { generate_localized_description(:meeting_agenda_item_description, skip_injection: skip_injection) } duration { 15 } position { 0 } trait :with_parent do - parent { create(:agenda_item, agenda: agenda) } + parent { create(:agenda_item, agenda: agenda, skip_injection: skip_injection) } end trait :with_children do after(:create) do |agenda_item, evaluator| - create_list(:agenda_item, 2, parent: agenda_item, agenda: evaluator.agenda) + create_list(:agenda_item, 2, parent: agenda_item, agenda: evaluator.agenda, skip_injection: evaluator.skip_injection) end end end factory :invite, class: "Decidim::Meetings::Invite" do + transient do + skip_injection { false } + end meeting user sent_at { 1.day.ago } @@ -221,31 +240,41 @@ end factory :service, class: "Decidim::Meetings::Service" do + transient do + skip_injection { false } + end meeting - title { generate_localized_title } - description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + title { generate_localized_title(:meeting_service_title, skip_injection: skip_injection) } + description { generate_localized_description(:meeting_service_description, skip_injection: skip_injection) } end factory :poll, class: "Decidim::Meetings::Poll" do + transient do + skip_injection { false } + end meeting end factory :meetings_poll_questionnaire, class: "Decidim::Meetings::Questionnaire" do - questionnaire_for { build(:poll) } + transient do + skip_injection { false } + end + questionnaire_for { build(:poll, skip_injection: skip_injection) } end factory :meetings_poll_question, class: "Decidim::Meetings::Question" do transient do + skip_injection { false } options { [] } end - body { generate_localized_title } + body { generate_localized_title(:meeting_poll_question_body, skip_injection: skip_injection) } position { 0 } status { 0 } question_type { Decidim::Meetings::Question::QUESTION_TYPES.first } questionnaire factory: :meetings_poll_questionnaire answer_options do - Array.new(3).collect { build(:meetings_poll_answer_option, question: nil) } + Array.new(3).collect { build(:meetings_poll_answer_option, question: nil, skip_injection: skip_injection) } end trait :unpublished do @@ -262,18 +291,27 @@ end factory :meetings_poll_answer, class: "Decidim::Meetings::Answer" do + transient do + skip_injection { false } + end questionnaire factory: :meetings_poll_questionnaire - question { create(:meetings_poll_question, questionnaire: questionnaire) } - user { create(:user, organization: questionnaire.questionnaire_for.organization) } + question { create(:meetings_poll_question, questionnaire: questionnaire, skip_injection: skip_injection) } + user { create(:user, organization: questionnaire.questionnaire_for.organization, skip_injection: skip_injection) } end factory :meetings_poll_answer_option, class: "Decidim::Meetings::AnswerOption" do - question { create(:meetings_poll_question) } + transient do + skip_injection { false } + end + question { create(:meetings_poll_question, skip_injection: skip_injection) } body { generate_localized_title } end factory :meetings_poll_answer_choice, class: "Decidim::Meetings::AnswerChoice" do + transient do + skip_injection { false } + end answer factory: :meetings_poll_answer - answer_option { create(:meetings_poll_answer_option, question: answer.question) } + answer_option { create(:meetings_poll_answer_option, question: answer.question, skip_injection: skip_injection) } end end diff --git a/decidim-meetings/lib/decidim/meetings/version.rb b/decidim-meetings/lib/decidim/meetings/version.rb index 97c9df0f01b1f..73d9fec2cde37 100644 --- a/decidim-meetings/lib/decidim/meetings/version.rb +++ b/decidim-meetings/lib/decidim/meetings/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-meetings version. module Meetings def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-meetings/spec/cells/decidim/meetings/meeting_highlighted_list_item_cell_spec.rb b/decidim-meetings/spec/cells/decidim/meetings/meeting_highlighted_list_item_cell_spec.rb index 03628480cfe62..ae42ef368bc85 100644 --- a/decidim-meetings/spec/cells/decidim/meetings/meeting_highlighted_list_item_cell_spec.rb +++ b/decidim-meetings/spec/cells/decidim/meetings/meeting_highlighted_list_item_cell_spec.rb @@ -18,15 +18,8 @@ module Decidim::Meetings end context "when title contains special html entities" do - let!(:original_title) { meeting.title["en"] } - - before do - meeting.update!(title: { en: "#{original_title} &'<" }) - meeting.reload - end - it "escapes them correctly" do - expect(subject.to_s).to include("<strong>#{original_title}</strong> &'<") + expect(subject.to_s).to include(decidim_escape_translated(meeting.title).gsub(""", "\"")) end end end diff --git a/decidim-meetings/spec/cells/decidim/meetings/meeting_list_item_cell_spec.rb b/decidim-meetings/spec/cells/decidim/meetings/meeting_list_item_cell_spec.rb index 79ec0adbb1f88..ae5c30d7cb3a9 100644 --- a/decidim-meetings/spec/cells/decidim/meetings/meeting_list_item_cell_spec.rb +++ b/decidim-meetings/spec/cells/decidim/meetings/meeting_list_item_cell_spec.rb @@ -16,15 +16,8 @@ module Decidim::Meetings end context "when title contains special html entities" do - let!(:original_title) { meeting.title["en"] } - - before do - meeting.update!(title: { en: "#{original_title} &'<" }) - meeting.reload - end - it "escapes them correctly" do - expect(subject.to_s).to include("<strong>#{original_title}</strong> &'<") + expect(subject.to_s).to include(decidim_escape_translated(meeting.title).gsub(""", "\"")) end end end diff --git a/decidim-meetings/spec/cells/decidim/meetings/meeting_m_cell_spec.rb b/decidim-meetings/spec/cells/decidim/meetings/meeting_m_cell_spec.rb index 998d02ec2b1dd..a9ccc59e8f7bf 100644 --- a/decidim-meetings/spec/cells/decidim/meetings/meeting_m_cell_spec.rb +++ b/decidim-meetings/spec/cells/decidim/meetings/meeting_m_cell_spec.rb @@ -50,17 +50,11 @@ module Decidim::Meetings context "when title contains special html entities" do let(:show_space) { true } - before do - @original_title = meeting.title["en"] - meeting.update!(title: { en: "#{meeting.title["en"]} &'<" }) - meeting.reload - end - it "escapes them correctly" do - expect(the_cell.title).to eq("#{@original_title} &'<") + expect(the_cell.title).to eq(decidim_escape_translated(meeting.title)) # as the `cell` test helper wraps content in a Capybara artifact that already converts html entities # we should compare with the expected visual result, as we were checking the DOM instead of the html - expect(cell_html).to have_content("#{@original_title} &'<") + expect(cell_html).to have_content(translated(meeting.title)) end end end diff --git a/decidim-meetings/spec/presenters/decidim/meetings/admin_log/invite_presenter_spec.rb b/decidim-meetings/spec/presenters/decidim/meetings/admin_log/invite_presenter_spec.rb index 33357a2ba34b8..b71e703a0e30b 100644 --- a/decidim-meetings/spec/presenters/decidim/meetings/admin_log/invite_presenter_spec.rb +++ b/decidim-meetings/spec/presenters/decidim/meetings/admin_log/invite_presenter_spec.rb @@ -20,13 +20,13 @@ module Decidim::Meetings::AdminLog it "renders the invite information" do user = action_log.user inviter = "#{user.name}" - space = "#{translated(participatory_space.title)}" + space = "#{decidim_escape_translated(participatory_space.title)}" action_string = "#{inviter} invited #{invite.user.name} to join meeting on the #{space} space" expect(subject).to include action_string end end - context "when invite doesn't exist anymore" do + context "when invite does not exist anymore" do before do invite.destroy action_log.reload diff --git a/decidim-meetings/spec/requests/meeting_directory_search_spec.rb b/decidim-meetings/spec/requests/meeting_directory_search_spec.rb index 246f1ecefb427..2c3ecd2230557 100644 --- a/decidim-meetings/spec/requests/meeting_directory_search_spec.rb +++ b/decidim-meetings/spec/requests/meeting_directory_search_spec.rb @@ -34,11 +34,11 @@ end it "displays all meetings without any filters" do - expect(subject).to include(translated(meeting1.title)) - expect(subject).to include(translated(meeting2.title)) - expect(subject).to include(translated(meeting3.title)) - expect(subject).to include(translated(meeting4.title)) - expect(subject).to include(translated(meeting5.title)) + expect(subject).to include(decidim_escape_translated(meeting1.title)) + expect(subject).to include(decidim_escape_translated(meeting2.title)) + expect(subject).to include(decidim_escape_translated(meeting3.title)) + expect(subject).to include(decidim_escape_translated(meeting4.title)) + expect(subject).to include(decidim_escape_translated(meeting5.title)) end context "when filtering by category" do @@ -48,11 +48,11 @@ let(:category_ids) { nil } it "displays all resources" do - expect(subject).to include(translated(meeting1.title)) - expect(subject).to include(translated(meeting2.title)) - expect(subject).to include(translated(meeting3.title)) - expect(subject).to include(translated(meeting4.title)) - expect(subject).to include(translated(meeting5.title)) + expect(subject).to include(decidim_escape_translated(meeting1.title)) + expect(subject).to include(decidim_escape_translated(meeting2.title)) + expect(subject).to include(decidim_escape_translated(meeting3.title)) + expect(subject).to include(decidim_escape_translated(meeting4.title)) + expect(subject).to include(decidim_escape_translated(meeting5.title)) end end @@ -60,11 +60,11 @@ let(:category_ids) { [category2.id] } it "displays only resources for that category and its children" do - expect(subject).not_to include(translated(meeting1.title)) - expect(subject).not_to include(translated(meeting2.title)) - expect(subject).to include(translated(meeting3.title)) - expect(subject).to include(translated(meeting4.title)) - expect(subject).not_to include(translated(meeting5.title)) + expect(subject).not_to include(decidim_escape_translated(meeting1.title)) + expect(subject).not_to include(decidim_escape_translated(meeting2.title)) + expect(subject).to include(decidim_escape_translated(meeting3.title)) + expect(subject).to include(decidim_escape_translated(meeting4.title)) + expect(subject).not_to include(decidim_escape_translated(meeting5.title)) end end @@ -72,11 +72,11 @@ let(:category_ids) { [child_category.id] } it "displays only resources for that category" do - expect(subject).not_to include(translated(meeting1.title)) - expect(subject).not_to include(translated(meeting2.title)) - expect(subject).not_to include(translated(meeting3.title)) - expect(subject).to include(translated(meeting4.title)) - expect(subject).not_to include(translated(meeting5.title)) + expect(subject).not_to include(decidim_escape_translated(meeting1.title)) + expect(subject).not_to include(decidim_escape_translated(meeting2.title)) + expect(subject).not_to include(decidim_escape_translated(meeting3.title)) + expect(subject).to include(decidim_escape_translated(meeting4.title)) + expect(subject).not_to include(decidim_escape_translated(meeting5.title)) end end @@ -85,11 +85,11 @@ let(:category_ids) { [value] } it "displays only resources for that participatory_process - all categories and sub-categories" do - expect(subject).not_to include(translated(meeting1.title)) - expect(subject).to include(translated(meeting2.title)) - expect(subject).to include(translated(meeting3.title)) - expect(subject).to include(translated(meeting4.title)) - expect(subject).not_to include(translated(meeting5.title)) + expect(subject).not_to include(decidim_escape_translated(meeting1.title)) + expect(subject).to include(decidim_escape_translated(meeting2.title)) + expect(subject).to include(decidim_escape_translated(meeting3.title)) + expect(subject).to include(decidim_escape_translated(meeting4.title)) + expect(subject).not_to include(decidim_escape_translated(meeting5.title)) end end @@ -97,11 +97,11 @@ let(:category_ids) { ["without"] } it "returns resources without a category" do - expect(subject).to include(translated(meeting1.title)) - expect(subject).not_to include(translated(meeting2.title)) - expect(subject).not_to include(translated(meeting3.title)) - expect(subject).not_to include(translated(meeting4.title)) - expect(subject).to include(translated(meeting5.title)) + expect(subject).to include(decidim_escape_translated(meeting1.title)) + expect(subject).not_to include(decidim_escape_translated(meeting2.title)) + expect(subject).not_to include(decidim_escape_translated(meeting3.title)) + expect(subject).not_to include(decidim_escape_translated(meeting4.title)) + expect(subject).to include(decidim_escape_translated(meeting5.title)) end end @@ -109,11 +109,11 @@ let(:category_ids) { ["without", category1.id] } it "returns resources without a category and with the selected category" do - expect(subject).to include(translated(meeting1.title)) - expect(subject).to include(translated(meeting2.title)) - expect(subject).not_to include(translated(meeting3.title)) - expect(subject).not_to include(translated(meeting4.title)) - expect(subject).to include(translated(meeting5.title)) + expect(subject).to include(decidim_escape_translated(meeting1.title)) + expect(subject).to include(decidim_escape_translated(meeting2.title)) + expect(subject).not_to include(decidim_escape_translated(meeting3.title)) + expect(subject).not_to include(decidim_escape_translated(meeting4.title)) + expect(subject).to include(decidim_escape_translated(meeting5.title)) end end end diff --git a/decidim-meetings/spec/requests/meeting_search_spec.rb b/decidim-meetings/spec/requests/meeting_search_spec.rb index 6ad586376c1d2..1360123d1b716 100644 --- a/decidim-meetings/spec/requests/meeting_search_spec.rb +++ b/decidim-meetings/spec/requests/meeting_search_spec.rb @@ -73,10 +73,10 @@ it_behaves_like "a resource search with origin", :published_meeting it "displays all meetings without any filters" do - expect(subject).to include(translated(meeting1.title)) - expect(subject).to include(translated(meeting2.title)) - expect(subject).not_to include(translated(meeting3.title)) - expect(subject).not_to include(translated(meeting4.title)) + expect(subject).to include(decidim_escape_translated(meeting1.title)) + expect(subject).to include(decidim_escape_translated(meeting2.title)) + expect(subject).not_to include(decidim_escape_translated(meeting3.title)) + expect(subject).not_to include(decidim_escape_translated(meeting4.title)) end context "when searching by date" do @@ -97,11 +97,11 @@ let(:date) { ["upcoming"] } it "only returns that are scheduled in the future" do - expect(subject).to include(translated(meeting1.title)) - expect(subject).to include(translated(meeting2.title)) - expect(subject).not_to include(translated(meeting3.title)) - expect(subject).not_to include(translated(meeting4.title)) - expect(subject).not_to include(translated(past_meeting.title)) + expect(subject).to include(decidim_escape_translated(meeting1.title)) + expect(subject).to include(decidim_escape_translated(meeting2.title)) + expect(subject).not_to include(decidim_escape_translated(meeting3.title)) + expect(subject).not_to include(decidim_escape_translated(meeting4.title)) + expect(subject).not_to include(decidim_escape_translated(past_meeting.title)) end end @@ -109,11 +109,11 @@ let(:date) { ["past"] } it "only returns meetings that were scheduled in the past" do - expect(subject).not_to include(translated(meeting1.title)) - expect(subject).not_to include(translated(meeting2.title)) - expect(subject).not_to include(translated(meeting3.title)) - expect(subject).not_to include(translated(meeting4.title)) - expect(subject).to include(translated(past_meeting.title)) + expect(subject).not_to include(decidim_escape_translated(meeting1.title)) + expect(subject).not_to include(decidim_escape_translated(meeting2.title)) + expect(subject).not_to include(decidim_escape_translated(meeting3.title)) + expect(subject).not_to include(decidim_escape_translated(meeting4.title)) + expect(subject).to include(decidim_escape_translated(past_meeting.title)) end end end @@ -125,10 +125,10 @@ let(:availability) { "withdrawn" } it "only returns meetings that are withdrawn" do - expect(subject).not_to include(translated(meeting1.title)) - expect(subject).not_to include(translated(meeting2.title)) - expect(subject).not_to include(translated(meeting3.title)) - expect(subject).to include(translated(meeting4.title)) + expect(subject).not_to include(decidim_escape_translated(meeting1.title)) + expect(subject).not_to include(decidim_escape_translated(meeting2.title)) + expect(subject).not_to include(decidim_escape_translated(meeting3.title)) + expect(subject).to include(decidim_escape_translated(meeting4.title)) end end @@ -136,10 +136,10 @@ let(:availability) { nil } it "only returns meetings that are not withdrawn" do - expect(subject).to include(translated(meeting1.title)) - expect(subject).to include(translated(meeting2.title)) - expect(subject).not_to include(translated(meeting3.title)) - expect(subject).not_to include(translated(meeting4.title)) + expect(subject).to include(decidim_escape_translated(meeting1.title)) + expect(subject).to include(decidim_escape_translated(meeting2.title)) + expect(subject).not_to include(decidim_escape_translated(meeting3.title)) + expect(subject).not_to include(decidim_escape_translated(meeting4.title)) end end end @@ -148,10 +148,10 @@ let(:filter_params) { { search_text_cont: "TestCheck" } } it "show only the meeting containing the search_text" do - expect(subject).to include(translated(meeting1.title)) - expect(subject).not_to include(translated(meeting2.title)) - expect(subject).not_to include(translated(meeting3.title)) - expect(subject).not_to include(translated(meeting4.title)) + expect(subject).to include(decidim_escape_translated(meeting1.title)) + expect(subject).not_to include(decidim_escape_translated(meeting2.title)) + expect(subject).not_to include(decidim_escape_translated(meeting3.title)) + expect(subject).not_to include(decidim_escape_translated(meeting4.title)) end end @@ -176,8 +176,8 @@ let(:type) { ["online"] } it "only lists online meetings" do - expect(subject).to include(translated(online_meeting.title)) - expect(subject).not_to include(translated(in_person_meeting.title)) + expect(subject).to include(decidim_escape_translated(online_meeting.title)) + expect(subject).not_to include(decidim_escape_translated(in_person_meeting.title)) end end @@ -185,8 +185,8 @@ let(:type) { ["in_person"] } it "only lists online meetings" do - expect(subject).to include(translated(in_person_meeting.title)) - expect(subject).not_to include(translated(online_meeting.title)) + expect(subject).to include(decidim_escape_translated(in_person_meeting.title)) + expect(subject).not_to include(decidim_escape_translated(online_meeting.title)) end end end @@ -208,8 +208,8 @@ let(:activity) { "all" } it "returns all the meetings" do - expect(subject).to include(translated(meeting1.title)) - expect(subject).to include(translated(meeting2.title)) + expect(subject).to include(decidim_escape_translated(meeting1.title)) + expect(subject).to include(decidim_escape_translated(meeting2.title)) end end @@ -217,8 +217,8 @@ let(:activity) { "my_meetings" } it "returns only the meeting created by the current user" do - expect(subject).to include(translated(meeting1.title)) - expect(subject).not_to include(translated(meeting2.title)) + expect(subject).to include(decidim_escape_translated(meeting1.title)) + expect(subject).not_to include(decidim_escape_translated(meeting2.title)) end end end diff --git a/decidim-meetings/spec/services/calendar/component_calendar_spec.rb b/decidim-meetings/spec/services/calendar/component_calendar_spec.rb index a5cb89dd10842..f4193b60d682d 100644 --- a/decidim-meetings/spec/services/calendar/component_calendar_spec.rb +++ b/decidim-meetings/spec/services/calendar/component_calendar_spec.rb @@ -6,12 +6,13 @@ module Decidim::Meetings::Calendar describe ComponentCalendar do subject { described_class.for(component) } - let!(:meeting) { create :meeting, :published } + let(:title) { Decidim::Faker::Localized.localized { " #{generate(:title)}" } } + let!(:meeting) { create :meeting, :published, title: title } let!(:component) { meeting.component } - let!(:another_meeting) { create :meeting, :published, component: component } - let!(:external_meeting) { create :meeting } - let!(:unpublished_meeting) { create :meeting, component: component } - let!(:withdrawn_meeting) { create :meeting, :published, :withdrawn } + let!(:another_meeting) { create(:meeting, :published, component: component, title: Decidim::Faker::Localized.localized { generate(:title) }) } + let!(:external_meeting) { create(:meeting, title: Decidim::Faker::Localized.localized { generate(:title) }) } + let!(:unpublished_meeting) { create(:meeting, component: component, title: Decidim::Faker::Localized.localized { generate(:title) }) } + let!(:withdrawn_meeting) { create(:meeting, :published, :withdrawn, title: Decidim::Faker::Localized.localized { generate(:title) }) } describe "#calendar" do it "renders a full calendar" do @@ -55,7 +56,7 @@ module Decidim::Meetings::Calendar let!(:filters) { { "with_any_origin" => ["", "official"], "with_any_type" => ["", "online"] } } context "when no meetings returned" do - let!(:online_meeting) { create :meeting, :published, :not_official, :online, component: component } + let!(:online_meeting) { create :meeting, :published, :not_official, :online, component: component, title: title } it "returns a nil value" do expect(subject).to be_nil @@ -63,7 +64,7 @@ module Decidim::Meetings::Calendar end context "when having meetings returned" do - let!(:online_meeting) { create :meeting, :published, :official, :online, component: component } + let!(:online_meeting) { create :meeting, :published, :official, :online, component: component, title: Decidim::Faker::Localized.localized { generate(:title) } } it "renders the meetings of the given component based on filters" do expect(subject).to include(online_meeting.title["en"]) diff --git a/decidim-meetings/spec/services/calendar/meeting_calendar_spec.rb b/decidim-meetings/spec/services/calendar/meeting_calendar_spec.rb index c41dd96dc6f7a..38f13b2ed10de 100644 --- a/decidim-meetings/spec/services/calendar/meeting_calendar_spec.rb +++ b/decidim-meetings/spec/services/calendar/meeting_calendar_spec.rb @@ -5,9 +5,8 @@ module Decidim::Meetings::Calendar describe MeetingCalendar do subject { described_class.for(meeting) } - - let!(:meeting) { create :meeting } - let!(:another_meeting) { create :meeting } + let!(:meeting) { create(:meeting, title: Decidim::Faker::Localized.localized { " #{generate(:title)}" }) } + let!(:another_meeting) { create(:meeting, title: Decidim::Faker::Localized.localized { " #{generate(:title)}" }) } describe "#calendar" do it "renders a full calendar" do diff --git a/decidim-meetings/spec/services/calendar/organization_calendar_spec.rb b/decidim-meetings/spec/services/calendar/organization_calendar_spec.rb index eedd11b2abb16..6d2500020f520 100644 --- a/decidim-meetings/spec/services/calendar/organization_calendar_spec.rb +++ b/decidim-meetings/spec/services/calendar/organization_calendar_spec.rb @@ -6,12 +6,12 @@ module Decidim::Meetings::Calendar describe OrganizationCalendar do subject { described_class.for(organization) } - let!(:meeting) { create :meeting, :published } + let!(:meeting) { create :meeting, :published, title: Decidim::Faker::Localized.localized { " meeting title" } } let!(:component) { meeting.component } let!(:component2) { create :meeting_component, participatory_space: component.participatory_space } let!(:organization) { component.organization } - let!(:another_meeting) { create :meeting, :published, component: component2 } - let!(:external_meeting) { create :meeting } + let!(:another_meeting) { create :meeting, :published, component: component2, title: Decidim::Faker::Localized.localized { " another meeting title" } } + let!(:external_meeting) { create :meeting, title: Decidim::Faker::Localized.localized { " external meeting title" } } describe "#calendar" do it "renders a full calendar" do @@ -48,9 +48,9 @@ module Decidim::Meetings::Calendar describe "#filters" do subject { described_class.for(organization, filters) } - let(:online_meeting) { create :meeting, :official, :online, component: component } - let(:online_meeting2) { create :meeting, :not_official, :online, component: component2 } - let!(:withdrawn_meeting) { create :meeting, :published, :withdrawn, component: component2 } + let(:online_meeting) { create :meeting, :official, :online, component: component, title: Decidim::Faker::Localized.localized { " online meeting title" } } + let(:online_meeting2) { create :meeting, :not_official, :online, component: component2, title: Decidim::Faker::Localized.localized { " online meeting 2 " } } + let!(:withdrawn_meeting) { create :meeting, :published, :withdrawn, component: component2, title: Decidim::Faker::Localized.localized { " withdrawn meeting title" } } let!(:filters) { { "with_any_origin" => ["", "official"], "with_any_type" => ["", "online"] } } context "when no meetings returned" do diff --git a/decidim-meetings/spec/services/decidim/meetings/close_meeting_reminder_generator_spec.rb b/decidim-meetings/spec/services/decidim/meetings/close_meeting_reminder_generator_spec.rb index e8dfa9f4eee80..a28d3e2c6345f 100644 --- a/decidim-meetings/spec/services/decidim/meetings/close_meeting_reminder_generator_spec.rb +++ b/decidim-meetings/spec/services/decidim/meetings/close_meeting_reminder_generator_spec.rb @@ -17,10 +17,11 @@ module Decidim::Meetings end let(:intervals) { [3.days, 7.days] } let(:organization) { create(:organization) } - let(:participatory_process) { create(:participatory_process, organization: organization) } - let!(:component) { create(:component, :published, manifest_name: "meetings", participatory_space: participatory_process) } + let(:participatory_space) { create(:participatory_process, organization: organization) } + let!(:component) { create(:component, :published, manifest_name: "meetings", participatory_space: participatory_space) } let(:user) { create(:user, :admin, organization: organization, email: "user@example.org") } let!(:meeting) { create(:meeting, :published, component: component, author: user, start_time: start_time, end_time: end_time, closed_at: closed_at) } + let(:closed_at) { nil } before do @@ -42,12 +43,49 @@ module Decidim::Meetings end end - context "and the meeting is not closed" do + context "and the user meeting is not closed" do + it "sends reminder" do + expect(Decidim::Meetings::SendCloseMeetingReminderJob).to receive(:perform_later) + + expect { subject.generate }.to change(Decidim::Reminder, :count).by(1) + end + end + + context "and the official meeting is not closed" do + let(:other_organization) { create(:organization) } + let!(:user) { create(:user, :admin, organization: organization, email: "user@example.org") } + let!(:other_admin) { create(:user, :admin, organization: other_organization, email: "user@example.org") } + let!(:meeting) { create(:meeting, :published, :official, component: component, start_time: start_time, end_time: end_time, closed_at: closed_at) } + it "sends reminder" do expect(Decidim::Meetings::SendCloseMeetingReminderJob).to receive(:perform_later) expect { subject.generate }.to change(Decidim::Reminder, :count).by(1) end + + context "and there are space admins" do + context "and space admin is Participatory Process" do + let(:participatory_space) { create(:participatory_process, organization: organization) } + let!(:process_admin) { create(:process_admin, participatory_process: participatory_space) } + + it "sends reminder" do + expect(Decidim::Meetings::SendCloseMeetingReminderJob).to receive(:perform_later).twice + + expect { subject.generate }.to change(Decidim::Reminder, :count).by(2) + end + end + + context "and space admin is Assembly" do + let(:participatory_space) { create(:assembly, organization: organization) } + let!(:process_admin) { create(:assembly_admin, assembly: participatory_space) } + + it "sends reminder" do + expect(Decidim::Meetings::SendCloseMeetingReminderJob).to receive(:perform_later).twice + + expect { subject.generate }.to change(Decidim::Reminder, :count).by(2) + end + end + end end end diff --git a/decidim-meetings/spec/system/explore_meetings_spec.rb b/decidim-meetings/spec/system/explore_meetings_spec.rb index cb54c60a2a537..0dd273ffeb627 100644 --- a/decidim-meetings/spec/system/explore_meetings_spec.rb +++ b/decidim-meetings/spec/system/explore_meetings_spec.rb @@ -478,9 +478,9 @@ it "shows all meeting info" do expect(page).to have_i18n_content(meeting.title) - expect(page).to have_i18n_content(meeting.description) - expect(page).to have_i18n_content(meeting.location) - expect(page).to have_i18n_content(meeting.location_hints) + expect(page).to have_i18n_content(meeting.description, strip_tags: true) + expect(page).to have_i18n_content(meeting.location, strip_tags: true) + expect(page).to have_i18n_content(meeting.location_hints, strip_tags: true) expect(page).to have_content(meeting.address) expect(page).to have_content(meeting.reference) @@ -594,7 +594,7 @@ it "shows the closing report" do visit_component click_link translated(meeting.title) - expect(page).to have_i18n_content(meeting.closing_report) + expect(page).to have_i18n_content(meeting.closing_report, strip_tags: true) within ".definition-data" do expect(page).to have_content("ATTENDEES COUNT\n#{meeting.attendees_count}") diff --git a/decidim-meetings/spec/system/live_meeting_answer_questions_spec.rb b/decidim-meetings/spec/system/live_meeting_answer_questions_spec.rb index 0130fd5bbed09..bd20e11cb2ccc 100644 --- a/decidim-meetings/spec/system/live_meeting_answer_questions_spec.rb +++ b/decidim-meetings/spec/system/live_meeting_answer_questions_spec.rb @@ -62,7 +62,7 @@ end context "when questions are published" do - let!(:question_multiple_option) { create(:meetings_poll_question, :published, questionnaire: questionnaire, body: body_multiple_option_question, question_type: "multiple_option") } + let!(:question_multiple_option) { create(:meetings_poll_question, :published, questionnaire: questionnaire, body: body_multiple_option_question, question_type: "multiple_option", max_choices: 2) } let!(:question_single_option) { create(:meetings_poll_question, :published, questionnaire: questionnaire, body: body_single_option_question, question_type: "single_option") } before do @@ -78,6 +78,30 @@ expect(page).to have_content("Question replied") end + + it "does not allow selecting two single options" do + click_button "Questions (2)" + find("details[data-question='#{question_single_option.id}']").click + + choose question_single_option.answer_options.first.body["en"] + choose question_single_option.answer_options.second.body["en"] + answers = all("details[data-question='#{question_single_option.id}'] input[type='radio']") + + expect(answers[0]["checked"]).to be_falsy + expect(answers[1]["checked"]).to be_truthy + expect(answers[2]["checked"]).to be_falsy + end + + it "does not allow selecting more than the maximum choices for multiple options" do + click_button "Questions (2)" + open_first_question + + check question_multiple_option.answer_options.first.body["en"] + check question_multiple_option.answer_options.second.body["en"] + check question_multiple_option.answer_options.third.body["en"] + + expect(page).to have_content("There are too many choices selected") + end end context "when questions are closed" do diff --git a/decidim-meetings/spec/system/meeting_registrations_spec.rb b/decidim-meetings/spec/system/meeting_registrations_spec.rb index 433d36e6f54c1..045f80ccf6646 100644 --- a/decidim-meetings/spec/system/meeting_registrations_spec.rb +++ b/decidim-meetings/spec/system/meeting_registrations_spec.rb @@ -61,7 +61,7 @@ def questionnaire_public_path visit questionnaire_public_path expect(page).to have_i18n_content(questionnaire.title, upcase: true) - expect(page).to have_i18n_content(questionnaire.description) + expect(page).to have_i18n_content(questionnaire.description, strip_tags: true) expect(page).to have_no_i18n_content(question.body) @@ -98,7 +98,7 @@ def questionnaire_public_path visit questionnaire_public_path expect(page).to have_i18n_content(questionnaire.title, upcase: true) - expect(page).to have_i18n_content(questionnaire.description) + expect(page).to have_i18n_content(questionnaire.description, strip_tags: true) expect(page).to have_no_i18n_content(question.body) @@ -153,7 +153,7 @@ def questionnaire_public_path visit questionnaire_public_path expect(page).to have_i18n_content(questionnaire.title, upcase: true) - expect(page).to have_i18n_content(questionnaire.description) + expect(page).to have_i18n_content(questionnaire.description, strip_tags: true) expect(page).not_to have_css(".form.answer-questionnaire") @@ -309,7 +309,7 @@ def questionnaire_public_path visit questionnaire_public_path expect(page).to have_i18n_content(questionnaire.title, upcase: true) - expect(page).to have_i18n_content(questionnaire.description) + expect(page).to have_i18n_content(questionnaire.description, strip_tags: true) expect(page).to have_content "Show my attendance publicly" expect(page).to have_field("public_participation", checked: false) @@ -483,7 +483,7 @@ def questionnaire_public_path visit questionnaire_public_path expect(page).to have_i18n_content(questionnaire.title, upcase: true) - expect(page).to have_i18n_content(questionnaire.description) + expect(page).to have_i18n_content(questionnaire.description, strip_tags: true) expect(page).to have_no_i18n_content(question.body) diff --git a/decidim-meetings/spec/system/participatory_processes_view_hooks_spec.rb b/decidim-meetings/spec/system/participatory_processes_view_hooks_spec.rb index 9a6b092fa5ba8..fce8efc7725b7 100644 --- a/decidim-meetings/spec/system/participatory_processes_view_hooks_spec.rb +++ b/decidim-meetings/spec/system/participatory_processes_view_hooks_spec.rb @@ -17,10 +17,10 @@ visit resource_locator(participatory_process).path expect(page).to have_css(".past_meetings .card--list__item", count: 3) - expect(page).not_to have_content(/#{translated(moderated_meeting.title)}/i) + expect(page).to have_no_content(/#{translated(moderated_meeting.title)}/i) past_meetings.sort_by { |m| [m.end_time, m.start_time] }.last(3).each do |meeting| - expect(page).to have_content(/#{translated(meeting.title)}/i) + expect(page).to have_content(translated(meeting.title)) end end end @@ -38,7 +38,7 @@ expect(page).not_to have_content(/#{translated(moderated_meeting.title)}/i) upcoming_meetings.sort_by { |m| [m.start_time, m.end_time] }.first(3).each do |meeting| - expect(page).to have_content(/#{translated(meeting.title)}/i) + expect(page).to have_content(translated(meeting.title)) end end end @@ -58,11 +58,11 @@ expect(page).not_to have_css(".past_meetings") past_meetings.each do |meeting| - expect(page).not_to have_content(/#{translated(meeting.title)}/i) + expect(page).not_to have_content(translated(meeting.title)) end upcoming_meetings.sort_by { |m| [m.start_time, m.end_time] }.first(3).each do |meeting| - expect(page).to have_content(/#{translated(meeting.title)}/i) + expect(page).to have_content(translated(meeting.title)) end end end diff --git a/decidim-meetings/spec/types/integration_schema_spec.rb b/decidim-meetings/spec/types/integration_schema_spec.rb index 9b6976d6f3b91..11108c3be2ce0 100644 --- a/decidim-meetings/spec/types/integration_schema_spec.rb +++ b/decidim-meetings/spec/types/integration_schema_spec.rb @@ -72,7 +72,7 @@ { "__typename" => "Meetings", "id" => current_component.id.to_s, - "name" => { "translation" => "Meetings" }, + "name" => { "translation" => translated(current_component.name) }, "meetings" => { "edges" => [ { diff --git a/decidim-pages/config/locales/bg.yml b/decidim-pages/config/locales/bg.yml index cc3180509c795..5d76b343f3a52 100644 --- a/decidim-pages/config/locales/bg.yml +++ b/decidim-pages/config/locales/bg.yml @@ -29,3 +29,8 @@ bg: update: invalid: Възникна проблем при запазване на страницата. success: Страницата е успешно съхранена. + home: + hero: + participate_title: Участвайте в процесите на платформата + sub_hero: + register_title: Регистрирайте се, за да си създадете акаунт diff --git a/decidim-pages/config/locales/he-IL.yml b/decidim-pages/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-pages/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-pages/lib/decidim/pages/version.rb b/decidim-pages/lib/decidim/pages/version.rb index df0039df141e4..41c6fc511f8d6 100644 --- a/decidim-pages/lib/decidim/pages/version.rb +++ b/decidim-pages/lib/decidim/pages/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-pages version. module Pages def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-participatory_processes/app/cells/decidim/participatory_process_groups/content_blocks/title/show.erb b/decidim-participatory_processes/app/cells/decidim/participatory_process_groups/content_blocks/title/show.erb index 44f6ef6555c4b..c66838a80e8ef 100644 --- a/decidim-participatory_processes/app/cells/decidim/participatory_process_groups/content_blocks/title/show.erb +++ b/decidim-participatory_processes/app/cells/decidim/participatory_process_groups/content_blocks/title/show.erb @@ -1,5 +1,5 @@
    -

    <%= translated_attribute(participatory_process_group.title) %>

    +

    <%= decidim_escape_translated(participatory_process_group.title) %>

    <%= decidim_sanitize_editor_admin translated_attribute(participatory_process_group.description) %> diff --git a/decidim-participatory_processes/app/cells/decidim/participatory_processes/process_group_m_cell.rb b/decidim-participatory_processes/app/cells/decidim/participatory_processes/process_group_m_cell.rb index a7371c82723aa..88c1f98cb3a60 100644 --- a/decidim-participatory_processes/app/cells/decidim/participatory_processes/process_group_m_cell.rb +++ b/decidim-participatory_processes/app/cells/decidim/participatory_processes/process_group_m_cell.rb @@ -16,7 +16,7 @@ def resource_image_path end def title - translated_attribute model.title + decidim_escape_translated model.title end def resource_path diff --git a/decidim-participatory_processes/config/locales/bg.yml b/decidim-participatory_processes/config/locales/bg.yml index 1cbca58772a13..c48a8b353cd56 100644 --- a/decidim-participatory_processes/config/locales/bg.yml +++ b/decidim-participatory_processes/config/locales/bg.yml @@ -19,8 +19,74 @@ bg: local_area: Район на организацията meta_scope: Метаданни сфера decidim: + admin: + actions: + filter: + all_processes: Показване на всички процеси + process_groups: Групи процеси + models: + participatory_process: + fields: + promoted: Акцентирано + participatory_process_group_landing_page: + edit: + active_content_blocks: Активни блокове със съдържание + inactive_content_blocks: Неактивни блокове със съдържание + participatory_process_steps: + destroy: + error: + active_step: Не може да изтриете активна фаза. + last_step: Не може да изтриете последната фаза от процеса. + participatory_processes: + index: + not_published: Не публикувано + log: + value_types: + participatory_process_type_presenter: + not_found: 'Типът на процеса не бе намерен в базата данни (Идент. №: %{id})' + participatory_process: + show: + related_assemblies: Свързани събрания + participatory_process_groups: + content_blocks: + title: + name: Заглавие, описание и хаштаг + participatory_process_steps: + index: + title: Фази на процес за участие participatory_processes: + pages: + home: + highlighted_processes: + active_step: Активна фаза + more_information: Още информация + participate: Участвайте + participate_in: Участие в процеса %{resource_name} + processes_button_title: Връзка към страницата „Процеси“, на която се показват всички процеси + participatory_processes: + filters: + explanations: + no_active: Няма активни процеси + no_active_nor_upcoming: Няма активни или предстоящи процеси + index: + loading: Зареждане на резултати... show: area: Район + dates: Дати developer_group: Група за популяризиране end_date: Крайна дата + unspecified: Неопределено + layouts: + decidim: + participatory_process_widgets: + show: + active_step: Активна фаза + participatory_processes: + participatory_process: + active_step: 'Текуща фаза:' + promoted_process: + active_step: 'Текуща фаза:' + process_header_steps: + step: Фаза %{current} от общо %{total} + process_navigation: + process_menu_item: Процесът diff --git a/decidim-participatory_processes/config/locales/ca.yml b/decidim-participatory_processes/config/locales/ca.yml index c4b0cf0955bf7..2301a85b23dd7 100644 --- a/decidim-participatory_processes/config/locales/ca.yml +++ b/decidim-participatory_processes/config/locales/ca.yml @@ -337,12 +337,12 @@ ca: notification_title: Se t'ha assignat el rol de %{role} al procés participatiu %{resource_title}. step_activated: email_intro: 'Ja està activa la fase %{resource_title} per a %{participatory_space_title}. Pots veure-ho des d''aquesta pàgina:' - email_outro: Has rebut aquesta notificació perquè estàs seguint %{participatory_space_title}. Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint l'espai "%{participatory_space_title}". Pots deixar de rebre notificacions seguint l'enllaç anterior. email_subject: Una actualització a %{participatory_space_title} notification_title: Ja està activa la fase %{resource_title} per a %{participatory_space_title} step_changed: email_intro: 'S''han actualitzat les dates de la fase %{resource_title} a %{participatory_space_title}. Pots veure-ho des d''aquesta pàgina:' - email_outro: Has rebut aquesta notificació perquè estàs seguint %{participatory_space_title}. Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint l'espai "%{participatory_space_title}". Pots deixar de rebre notificacions seguint l'enllaç anterior. email_subject: Una actualització a %{participatory_space_title} notification_title: Les dates de la fase %{resource_title} a %{participatory_space_title} s'han actualitzat. help: diff --git a/decidim-participatory_processes/config/locales/es.yml b/decidim-participatory_processes/config/locales/es.yml index 93b7be9260e9a..c0d41cd52f78e 100644 --- a/decidim-participatory_processes/config/locales/es.yml +++ b/decidim-participatory_processes/config/locales/es.yml @@ -337,7 +337,7 @@ es: notification_title: Se te ha asignado el rol de %{role} en el proceso participativo %{resource_title}. step_activated: email_intro: 'Ya está activa la fase %{resource_title} para %{participatory_space_title}. Puedes verla desde esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo %{participatory_space_title}. Puedes dejar de recibir notificaciones siguiendo el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo el espacio "%{participatory_space_title}". Puedes dejar de recibir notificaciones siguiendo el enlace anterior. email_subject: Una actualización en %{participatory_space_title} notification_title: Ya está activa la fase %{resource_title} para %{participatory_space_title} step_changed: diff --git a/decidim-participatory_processes/config/locales/he-IL.yml b/decidim-participatory_processes/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-participatory_processes/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-participatory_processes/config/locales/lb.yml b/decidim-participatory_processes/config/locales/lb.yml index 48c31bce4d9e1..544a286736ae9 100644 --- a/decidim-participatory_processes/config/locales/lb.yml +++ b/decidim-participatory_processes/config/locales/lb.yml @@ -72,6 +72,9 @@ lb: decidim/participatory_process_group: one: Prozessgruppe other: Prozessgruppen + decidim/participatory_process_step: + one: Etapp + other: Phasen decidim: admin: actions: @@ -169,14 +172,64 @@ lb: update: error: Beim Aktualisieren dieser partizipativen Prozessgruppe ist ein Fehler aufgetreten. success: Partizipative Prozessgruppe wurde erfolgreich aktualisiert. + participatory_process_imports: + create: + error: Beim Importieren dieses Beteiligungsprozesses ist ein Fehler aufgetreten. + success: Beteiligungsprozess wurde erfolgreich importiert. + new: + import: Import + select: Wählen Sie aus, welche Daten Sie importieren möchten + title: Beteiligungsprozess importieren + participatory_process_publications: + create: + error: Bei der Veröffentlichung dieses Beteiligungsprozesses ist ein Fehler aufgetreten. + success: Partizipativer Prozess erfolgreich veröffentlicht. + destroy: + error: Beim Aufheben der Veröffentlichung dieses Beteiligungsprozesses ist ein Fehler aufgetreten. + success: Partizipativer Prozess wurde nicht veröffentlicht. + participatory_process_step_activations: + create: + error: Beim Aktivieren dieses partizipativen Prozessschritts ist ein Fehler aufgetreten. + success: Partizipativer Prozessschritt erfolgreich aktiviert. participatory_process_steps: + create: + error: Beim Erstellen eines neuen partizipativen Prozessschritts ist ein Fehler aufgetreten. + success: Partizipativer Prozessschritt erfolgreich erstellt. + default_title: Aféierung destroy: error: active_step: Der aktive Schritt kann nicht gelöscht werden. last_step: Der letzte Schritt eines Beteiligungsprozesses kann nicht gelöscht werden. + success: Participatory-Prozessschritt erfolgreich gelöscht. + edit: + title: Beteiligungsschritt bearbeiten + update: Aktualiséieren + index: + steps_title: Phasen + new: + create: Erstellen + title: Neuer partizipativer Prozessschritt + ordering: + error: Beim Neuanordnen dieser partizipativen Prozessschritte ist ein Fehler aufgetreten. + update: + error: Beim Aktualisieren dieses partizipativen Prozessschritts ist ein Fehler aufgetreten. + success: Partizipativer Prozessschritt erfolgreich aktualisiert. participatory_process_types: form: title: Titel + participatory_process_user_roles: + create: + error: Beim Hinzufügen eines Benutzers für diesen partizipativen Prozess ist ein Fehler aufgetreten. + success: Benutzer hat diesen partizipativen Prozess erfolgreich hinzugefügt. + destroy: + success: Der Benutzer wurde erfolgreich aus diesem partizipativen Prozess entfernt. + edit: + title: Administrator des Beteiligungsprozesses aktualisieren + update: Aktualiséieren + index: + process_admins_title: Partizipative Prozessbenutzer + new: + create: Erstellen titles: participatory_process_groups: Prozessgruppen participatory_processes: Bedeelegungsprozesser @@ -257,6 +310,25 @@ lb: show: title: Prozessgruppen participatory_processes: + admin: + participatory_process_groups: + form: + title: Allgemeine Information + participatory_processes: + form: + other: Andere + related_processes: Ähnliche Beteiligungsprozesse + scope_type_max_depth_help: Beschränken Sie die Bereichs-Filtertiefe; der Filter zeigt nur Ergebnisse von Allgemein bis zum ausgewählten Bereichstyp an. + select_an_area: Wählen Sie einen Bereich aus + select_process_group: Wählen Sie eine Prozessgruppe aus + title: Allgemeine Information + content_blocks: + highlighted_processes: + name: Hervorgehobene Beteiligungsprozesse + index: + title: Bedeelegungsprozesser + last_activity: + new_participatory_process: Neuer partizipativer Prozess pages: home: highlighted_processes: @@ -264,11 +336,25 @@ lb: more_information: weider Informatiounen participate: Matmaachen participate_in: Am Prozess %{resource_name} teilnehmen + participatory_process_steps: + index: + back_to_process: Zurück zur Prozessseite participatory_processes: filters: + counters: + active: + one: 1 aktiver Beteiligungsprozess + other: "%{count} Beteiligungsprozesse" explanations: no_active: Keine aktiven Prozesse no_active_nor_upcoming: Keine aktiven oder zukünftigen Beteiligungsprozesse + no_active_nor_upcoming_callout: Es gibt keine aktiven oder zukünftigen Beteiligungsprozesse. Hier ist eine Liste der vergangenen. + names: + active: Aktiv + all: All + past: Vergaangenes + upcoming: Demnächst stattfannend + see: Sehen index: loading: Ergebnisse werden geladen... show: diff --git a/decidim-participatory_processes/config/locales/pl.yml b/decidim-participatory_processes/config/locales/pl.yml index 98ef3f4d0f945..1a16eec3c4d50 100644 --- a/decidim-participatory_processes/config/locales/pl.yml +++ b/decidim-participatory_processes/config/locales/pl.yml @@ -12,15 +12,22 @@ pl: decidim_area_id: Kategoria description: Opis developer_group: Grupa inicjatorów + document: Dokument domain: Domena end_date: Data zakończenia hashtag: Hashtag hero_image: Obraz główny + import_attachments: Importuj załączniki + import_categories: Importuj kategorie + import_components: Importuj komponenty + import_steps: Importuj kroki local_area: Obszar organizacji meta_scope: Zakres metadanych participatory_process_group_id: Grupa procesów + participatory_process_type_id: Typ procesów participatory_scope: Zaproponowano participatory_structure: Jak decydowano + private_space: Proces prywatny promoted: Promowany published_at: Opublikowano related_process_ids: Powiązane procesy @@ -57,10 +64,18 @@ pl: short_description: Krótki opis start_date: Data rozpoczęcia title: Tytuł + participatory_process_type: + title: Tytuł participatory_process_user_role: email: Adres e-mail name: Imię role: Rola + errors: + models: + participatory_process: + attributes: + document: + allowed_file_content_types: 'Nieprawidłowy typ dokumentu. Dozwolone są tylko pliki z następującymi rozszerzeniami: %{types}' models: decidim/participatory_process_step_activated_event: Aktualny etap decidim/participatory_process_step_changed_event: Zmieniono etap @@ -108,6 +123,7 @@ pl: participatory_process_groups_submenu: info: Informacje landing_page: Strona startowa + participatory_process_types: Typy procesu participatory_processes: Procesy participatory_processes_submenu: attachment_collections: Foldery @@ -139,6 +155,11 @@ pl: start_date: Data rozpoczęcia title: Tytuł name: Etap procesu partycypacyjnego + participatory_process_type: + fields: + created_at: Utworzono + title: Tytuł + name: Typ procesu participatory_process_user_role: fields: email: Adres e-mail @@ -470,6 +491,7 @@ pl: no_active: Brak aktualnych procesów no_active_nor_upcoming: Brak aktualnych i nadchodzących procesów no_active_nor_upcoming_callout: Nie ma aktualnych ani nadchodzących procesów. Oto lista poprzednich procesów. + filter_by: Pokaż names: active: Aktualne all: Wszystko @@ -478,6 +500,8 @@ pl: see: Zobacz index: loading: Ładowanie wyników... + show: + title: O tym procesie show: area: Kategoria belongs_to_group: Ten proces należy do diff --git a/decidim-participatory_processes/lib/decidim/participatory_processes/test/factories.rb b/decidim-participatory_processes/lib/decidim/participatory_processes/test/factories.rb index 6157e254bb6c9..f273c0b1c6a57 100644 --- a/decidim-participatory_processes/lib/decidim/participatory_processes/test/factories.rb +++ b/decidim-participatory_processes/lib/decidim/participatory_processes/test/factories.rb @@ -14,23 +14,23 @@ transient do skip_injection { false } end - title { generate_localized_title } + title { generate_localized_title(:participatory_process_title, skip_injection: skip_injection) } slug { generate(:participatory_process_slug) } - subtitle { generate_localized_title } + subtitle { generate_localized_title(:participatory_process_subtitle, skip_injection: skip_injection) } weight { 1 } - short_description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } - description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + short_description { generate_localized_description(:participatory_process_short_description, skip_injection: skip_injection) } + description { generate_localized_description(:participatory_process_description, skip_injection: skip_injection) } organization hero_image { Decidim::Dev.test_file("city.jpeg", "image/jpeg") } # Keep after organization banner_image { Decidim::Dev.test_file("city2.jpeg", "image/jpeg") } # Keep after organization published_at { Time.current } - meta_scope { Decidim::Faker::Localized.word } - developer_group { generate_localized_title } - local_area { generate_localized_title } - target { generate_localized_title } - participatory_scope { generate_localized_title } - participatory_structure { generate_localized_title } - announcement { generate_localized_title } + meta_scope { generate_localized_word(:participatory_process_meta_scope, skip_injection: skip_injection) } + developer_group { generate_localized_title(:participatory_process_developer_group, skip_injection: skip_injection) } + local_area { generate_localized_title(:participatory_process_local_area, skip_injection: skip_injection) } + target { generate_localized_title(:participatory_process_target, skip_injection: skip_injection) } + participatory_scope { generate_localized_title(:participatory_process_participatory_scope, skip_injection: skip_injection) } + participatory_structure { generate_localized_title(:participatory_process_participatory_structure, skip_injection: skip_injection) } + announcement { generate_localized_title(:participatory_process_announcement, skip_injection: skip_injection) } show_metrics { true } show_statistics { true } private_space { false } @@ -61,6 +61,7 @@ create(:participatory_process_step, active: true, end_date: evaluator.current_step_ends, + skip_injection: evaluator.skip_injection, participatory_process: participatory_process) participatory_process.reload participatory_process.steps.reload @@ -89,26 +90,30 @@ end factory :participatory_process_group, class: "Decidim::ParticipatoryProcessGroup" do - title { generate_localized_title } - description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + transient do + skip_injection { false } + end + title { generate_localized_title(:participatory_process_group_title, skip_injection: skip_injection) } + description { generate_localized_description(:participatory_process_group_description, skip_injection: skip_injection) } hero_image { Decidim::Dev.test_file("city.jpeg", "image/jpeg") } organization hashtag { Faker::Internet.slug } group_url { Faker::Internet.url } - developer_group { generate_localized_title } - local_area { generate_localized_title } + developer_group { generate_localized_title(:participatory_process_group_developer_group, skip_injection: skip_injection) } + local_area { generate_localized_title(:participatory_process_group_local_area, skip_injection: skip_injection) } meta_scope { Decidim::Faker::Localized.word } - target { generate_localized_title } - participatory_scope { generate_localized_title } - participatory_structure { generate_localized_title } + target { generate_localized_title(:participatory_process_group_target, skip_injection: skip_injection) } + participatory_scope { generate_localized_title(:participatory_process_group_participatory_scope, skip_injection: skip_injection) } + participatory_structure { generate_localized_title(:participatory_process_group_participatory_structure, skip_injection: skip_injection) } trait :promoted do promoted { true } end trait :with_participatory_processes do - after(:create) do |participatory_process_group| - create_list(:participatory_process, 2, :published, organization: participatory_process_group.organization, participatory_process_group: participatory_process_group) + after(:create) do |participatory_process_group, evaluator| + create_list(:participatory_process, 2, :published, organization: participatory_process_group.organization, participatory_process_group: participatory_process_group, + skip_injection: evaluator.skip_injection) end end end @@ -117,8 +122,8 @@ transient do skip_injection { false } end - title { generate_localized_title } - description { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } + title { generate_localized_title(:participatory_process_step_title, skip_injection: skip_injection) } + description { generate_localized_description(:participatory_process_step_description, skip_injection: skip_injection) } start_date { 1.month.ago } end_date { 2.months.from_now } position { nil } @@ -135,25 +140,31 @@ end factory :participatory_process_type, class: "Decidim::ParticipatoryProcessType" do - title { generate_localized_title } + transient do + skip_injection { false } + end + title { generate_localized_title(:participatory_process_type_title, skip_injection: skip_injection) } organization trait :with_active_participatory_processes do - after(:create) do |participatory_process_type| - create_list(:participatory_process, 2, :active, :published, organization: participatory_process_type.organization, participatory_process_type: participatory_process_type) + after(:create) do |participatory_process_type, evaluator| + create_list(:participatory_process, 2, :active, :published, organization: participatory_process_type.organization, participatory_process_type: participatory_process_type, + skip_injection: evaluator.skip_injection) end end trait :with_past_participatory_processes do - after(:create) do |participatory_process_type| - create_list(:participatory_process, 2, :past, :published, organization: participatory_process_type.organization, participatory_process_type: participatory_process_type) + after(:create) do |participatory_process_type, evaluator| + create_list(:participatory_process, 2, :past, :published, organization: participatory_process_type.organization, participatory_process_type: participatory_process_type, + skip_injection: evaluator.skip_injection) end end end factory :process_admin, parent: :user, class: "Decidim::User" do transient do - participatory_process { create(:participatory_process) } + skip_injection { false } + participatory_process { create(:participatory_process, skip_injection: skip_injection) } end organization { participatory_process.organization } @@ -163,13 +174,14 @@ create :participatory_process_user_role, user: user, participatory_process: evaluator.participatory_process, - role: :admin + role: :admin, skip_injection: evaluator.skip_injection end end factory :process_collaborator, parent: :user, class: "Decidim::User" do transient do - participatory_process { create(:participatory_process) } + skip_injection { false } + participatory_process { create(:participatory_process, skip_injection: skip_injection) } end organization { participatory_process.organization } @@ -179,13 +191,14 @@ create :participatory_process_user_role, user: user, participatory_process: evaluator.participatory_process, - role: :collaborator + role: :collaborator, skip_injection: evaluator.skip_injection end end factory :process_moderator, parent: :user, class: "Decidim::User" do transient do - participatory_process { create(:participatory_process) } + skip_injection { false } + participatory_process { create(:participatory_process, skip_injection: skip_injection) } end organization { participatory_process.organization } @@ -195,13 +208,14 @@ create :participatory_process_user_role, user: user, participatory_process: evaluator.participatory_process, - role: :moderator + role: :moderator, skip_injection: evaluator.skip_injection end end factory :process_valuator, parent: :user, class: "Decidim::User" do transient do - participatory_process { create(:participatory_process) } + skip_injection { false } + participatory_process { create(:participatory_process, skip_injection: skip_injection) } end organization { participatory_process.organization } @@ -211,13 +225,16 @@ create :participatory_process_user_role, user: user, participatory_process: evaluator.participatory_process, - role: :valuator + role: :valuator, skip_injection: evaluator.skip_injection end end factory :participatory_process_user_role, class: "Decidim::ParticipatoryProcessUserRole" do + transient do + skip_injection { false } + end user - participatory_process { create :participatory_process, organization: user.organization } + participatory_process { create :participatory_process, organization: user.organization, skip_injection: skip_injection } role { "admin" } end end diff --git a/decidim-participatory_processes/lib/decidim/participatory_processes/version.rb b/decidim-participatory_processes/lib/decidim/participatory_processes/version.rb index 1f0950d608856..f8bef1603efaa 100644 --- a/decidim-participatory_processes/lib/decidim/participatory_processes/version.rb +++ b/decidim-participatory_processes/lib/decidim/participatory_processes/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-participatory_processes version. module ParticipatoryProcesses def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-participatory_processes/spec/events/decidim/participatory_process_role_assigned_event_spec.rb b/decidim-participatory_processes/spec/events/decidim/participatory_process_role_assigned_event_spec.rb index 2bdfff0016e7c..bc898579db835 100644 --- a/decidim-participatory_processes/spec/events/decidim/participatory_process_role_assigned_event_spec.rb +++ b/decidim-participatory_processes/spec/events/decidim/participatory_process_role_assigned_event_spec.rb @@ -6,13 +6,14 @@ include_context "when a simple event" let(:resource) { create :participatory_process } + let(:participatory_space) { resource } let(:event_name) { "decidim.events.participatory_process.role_assigned" } - let(:role) { create :participatory_process_user_role, user: user, participatory_process: resource, role: :admin } + let(:role) { create(:participatory_process_user_role, user: user, participatory_process: resource, role: :admin) } let(:extra) { { role: role } } - let(:email_subject) { "You have been assigned as #{role} for \"#{resource.title["en"]}\"." } - let(:email_outro) { "You have received this notification because you are #{role} of the \"#{resource.title["en"]}\" participatory process." } - let(:email_intro) { "You have been assigned as #{role} for participatory process \"#{resource.title["en"]}\"." } - let(:notification_title) { "You have been assigned as #{role} for participatory process #{resource.title["en"]}." } + let(:email_subject) { "You have been assigned as #{role} for \"#{resource_title}\"." } + let(:email_outro) { "You have received this notification because you are #{role} of the \"#{resource_title}\" participatory process." } + let(:email_intro) { "You have been assigned as #{role} for participatory process \"#{resource_title}\"." } + let(:notification_title) { "You have been assigned as #{role} for participatory process #{resource_title}." } it_behaves_like "a simple event" it_behaves_like "a simple event email" diff --git a/decidim-participatory_processes/spec/events/decidim/participatory_process_step_activated_event_spec.rb b/decidim-participatory_processes/spec/events/decidim/participatory_process_step_activated_event_spec.rb index 0ea3d00ba0669..2e584d3868314 100644 --- a/decidim-participatory_processes/spec/events/decidim/participatory_process_step_activated_event_spec.rb +++ b/decidim-participatory_processes/spec/events/decidim/participatory_process_step_activated_event_spec.rb @@ -23,7 +23,8 @@ ) end - let(:email_subject) { "An update to #{participatory_space_title}" } + let(:resource_title) { decidim_sanitize_translated(resource.title) } + let(:email_subject) { "An update to #{decidim_sanitize_translated(participatory_space.title)}" } let(:email_intro) { "The #{resource_title} phase is now active for #{participatory_space_title}. You can see it from this page:" } let(:email_outro) { "You have received this notification because you are following #{participatory_space_title}. You can stop receiving notifications following the previous link." } let(:notification_title) { "The #{resource_title} phase is now active for #{participatory_space_title}" } diff --git a/decidim-participatory_processes/spec/events/decidim/participatory_process_step_changed_event_spec.rb b/decidim-participatory_processes/spec/events/decidim/participatory_process_step_changed_event_spec.rb index 849a7f8b63ba6..675019a6cf2e3 100644 --- a/decidim-participatory_processes/spec/events/decidim/participatory_process_step_changed_event_spec.rb +++ b/decidim-participatory_processes/spec/events/decidim/participatory_process_step_changed_event_spec.rb @@ -23,7 +23,7 @@ ) end - let(:email_subject) { "An update to #{participatory_space_title}" } + let(:email_subject) { "An update to #{decidim_sanitize_translated(participatory_space.title)}" } let(:email_intro) { "The dates for the #{resource_title} phase at #{participatory_space_title} have been updated. You can see it from this page:" } let(:email_outro) { "You have received this notification because you are following #{participatory_space_title}. You can stop receiving notifications following the previous link." } let(:notification_title) { "The dates for the #{resource_title} phase at #{participatory_space_title} have been updated." } diff --git a/decidim-participatory_processes/spec/presenters/decidim/resource_locator_presenter_spec.rb b/decidim-participatory_processes/spec/presenters/decidim/resource_locator_presenter_spec.rb new file mode 100644 index 0000000000000..abecff65dbb29 --- /dev/null +++ b/decidim-participatory_processes/spec/presenters/decidim/resource_locator_presenter_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + describe ResourceLocatorPresenter, type: :helper do + it_behaves_like "generates routes without query strings on slug" do + let(:route_fragment) { "processes/#{participatory_space.slug}" } + let(:admin_route_fragment) { "participatory_processes/#{participatory_space.slug}" } + let(:factory_name) { :participatory_process } + end + end +end diff --git a/decidim-participatory_processes/spec/requests/participatory_process_search_spec.rb b/decidim-participatory_processes/spec/requests/participatory_process_search_spec.rb index 69f4943b03393..fcc5eb0115170 100644 --- a/decidim-participatory_processes/spec/requests/participatory_process_search_spec.rb +++ b/decidim-participatory_processes/spec/requests/participatory_process_search_spec.rb @@ -47,18 +47,18 @@ end it "displays all public active processes by default" do - expect(subject).to include(translated(process1.title)) - expect(subject).to include(translated(process2.title)) - expect(subject).not_to include(translated(past_process.title)) - expect(subject).not_to include(translated(upcoming_process.title)) + expect(subject).to include(decidim_escape_translated(process1.title)) + expect(subject).to include(decidim_escape_translated(process2.title)) + expect(subject).not_to include(decidim_escape_translated(past_process.title)) + expect(subject).not_to include(decidim_escape_translated(upcoming_process.title)) end context "when filtering by area" do let(:filter_params) { { with_area: process1.area.id } } it "displays matching assemblies" do - expect(subject).to include(translated(process1.title)) - expect(subject).not_to include(translated(process2.title)) + expect(subject).to include(decidim_escape_translated(process1.title)) + expect(subject).not_to include(decidim_escape_translated(process2.title)) end end @@ -66,8 +66,8 @@ let(:filter_params) { { with_any_scope: [process1.scope.id] } } it "displays matching assemblies" do - expect(subject).to include(translated(process1.title)) - expect(subject).not_to include(translated(process2.title)) + expect(subject).to include(decidim_escape_translated(process1.title)) + expect(subject).not_to include(decidim_escape_translated(process2.title)) end end @@ -78,10 +78,10 @@ let(:date) { "active" } it "displays all active processes" do - expect(subject).to include(translated(process1.title)) - expect(subject).to include(translated(process2.title)) - expect(subject).not_to include(translated(past_process.title)) - expect(subject).not_to include(translated(upcoming_process.title)) + expect(subject).to include(decidim_escape_translated(process1.title)) + expect(subject).to include(decidim_escape_translated(process2.title)) + expect(subject).not_to include(decidim_escape_translated(past_process.title)) + expect(subject).not_to include(decidim_escape_translated(upcoming_process.title)) end end @@ -89,10 +89,10 @@ let(:date) { "past" } it "displays the past process" do - expect(subject).not_to include(translated(process1.title)) - expect(subject).not_to include(translated(process2.title)) - expect(subject).to include(translated(past_process.title)) - expect(subject).not_to include(translated(upcoming_process.title)) + expect(subject).not_to include(decidim_escape_translated(process1.title)) + expect(subject).not_to include(decidim_escape_translated(process2.title)) + expect(subject).to include(decidim_escape_translated(past_process.title)) + expect(subject).not_to include(decidim_escape_translated(upcoming_process.title)) end end @@ -100,10 +100,10 @@ let(:date) { "upcoming" } it "displays the upcoming process" do - expect(subject).not_to include(translated(process1.title)) - expect(subject).not_to include(translated(process2.title)) - expect(subject).not_to include(translated(past_process.title)) - expect(subject).to include(translated(upcoming_process.title)) + expect(subject).not_to include(decidim_escape_translated(process1.title)) + expect(subject).not_to include(decidim_escape_translated(process2.title)) + expect(subject).not_to include(decidim_escape_translated(past_process.title)) + expect(subject).to include(decidim_escape_translated(upcoming_process.title)) end end @@ -111,10 +111,10 @@ let(:date) { "all" } it "displays all public processes" do - expect(subject).to include(translated(process1.title)) - expect(subject).to include(translated(process2.title)) - expect(subject).to include(translated(past_process.title)) - expect(subject).to include(translated(upcoming_process.title)) + expect(subject).to include(decidim_escape_translated(process1.title)) + expect(subject).to include(decidim_escape_translated(process2.title)) + expect(subject).to include(decidim_escape_translated(past_process.title)) + expect(subject).to include(decidim_escape_translated(upcoming_process.title)) end end @@ -123,10 +123,10 @@ let(:dom) { Nokogiri::HTML(subject) } it "displays all public processes" do - expect(subject).to include(translated(process1.title)) - expect(subject).to include(translated(process2.title)) - expect(subject).to include(translated(past_process.title)) - expect(subject).to include(translated(upcoming_process.title)) + expect(subject).to include(decidim_escape_translated(process1.title)) + expect(subject).to include(decidim_escape_translated(process2.title)) + expect(subject).to include(decidim_escape_translated(past_process.title)) + expect(subject).to include(decidim_escape_translated(upcoming_process.title)) end it "does not cause any display issues" do diff --git a/decidim-participatory_processes/spec/shared/manage_process_components_examples.rb b/decidim-participatory_processes/spec/shared/manage_process_components_examples.rb index 8213272090ca8..8901da23e0dc7 100644 --- a/decidim-participatory_processes/spec/shared/manage_process_components_examples.rb +++ b/decidim-participatory_processes/spec/shared/manage_process_components_examples.rb @@ -319,7 +319,16 @@ click_link "Publish" end - expect(enqueued_jobs.last[:args]).to include("decidim.events.components.component_published") + expect(Decidim::EventPublisherJob).to(have_been_enqueued.with( + "decidim.events.components.component_published", { + resource: component, + event_class: "Decidim::ComponentPublishedEvent", + affected_users: [], + followers: [follower], + force_send: false, + extra: {} + } + )) end it_behaves_like "manage component share tokens" diff --git a/decidim-participatory_processes/spec/system/participatory_process_groups_spec.rb b/decidim-participatory_processes/spec/system/participatory_process_groups_spec.rb index 2802d754cf5e5..44d7f55e8091b 100644 --- a/decidim-participatory_processes/spec/system/participatory_process_groups_spec.rb +++ b/decidim-participatory_processes/spec/system/participatory_process_groups_spec.rb @@ -83,7 +83,7 @@ end it "shows the description" do - expect(page).to have_i18n_content(participatory_process_group.description) + expect(page).to have_i18n_content(participatory_process_group.description, strip_tags: true) end it "shows the meta scope name" do @@ -120,10 +120,10 @@ it "shows metadata attributes" do within "#participatory_process_group-metadata" do - expect(page).to have_i18n_content(participatory_process_group.developer_group) - expect(page).to have_i18n_content(participatory_process_group.target) - expect(page).to have_i18n_content(participatory_process_group.participatory_scope) - expect(page).to have_i18n_content(participatory_process_group.participatory_structure) + expect(page).to have_i18n_content(participatory_process_group.developer_group, strip_tags: true) + expect(page).to have_i18n_content(participatory_process_group.target, strip_tags: true) + expect(page).to have_i18n_content(participatory_process_group.participatory_scope, strip_tags: true) + expect(page).to have_i18n_content(participatory_process_group.participatory_structure, strip_tags: true) end end end diff --git a/decidim-participatory_processes/spec/system/participatory_process_steps_spec.rb b/decidim-participatory_processes/spec/system/participatory_process_steps_spec.rb index 31fff91640c0f..8526cf9c93c9c 100644 --- a/decidim-participatory_processes/spec/system/participatory_process_steps_spec.rb +++ b/decidim-participatory_processes/spec/system/participatory_process_steps_spec.rb @@ -37,7 +37,7 @@ expect(page).to have_css(".timeline__item", count: 3) steps.each do |step| - expect(page).to have_content(/#{translated(step.title)}/i) + expect(page).to have_content(translated(step.title)) end end diff --git a/decidim-proposals/app/helpers/decidim/proposals/application_helper.rb b/decidim-proposals/app/helpers/decidim/proposals/application_helper.rb index 2ea1de6f66fe7..d985182eaa98a 100644 --- a/decidim-proposals/app/helpers/decidim/proposals/application_helper.rb +++ b/decidim-proposals/app/helpers/decidim/proposals/application_helper.rb @@ -121,7 +121,7 @@ def form_has_address? end def show_voting_rules? - return false unless votes_enabled? + return false if !votes_enabled? || current_settings.votes_blocked? return true if vote_limit_enabled? return true if threshold_per_proposal_enabled? diff --git a/decidim-proposals/app/models/decidim/proposals/proposal.rb b/decidim-proposals/app/models/decidim/proposals/proposal.rb index 2a376a7f3ac13..e548702577723 100644 --- a/decidim-proposals/app/models/decidim/proposals/proposal.rb +++ b/decidim-proposals/app/models/decidim/proposals/proposal.rb @@ -96,11 +96,11 @@ class Proposal < Proposals::ApplicationRecord } scope :sort_by_valuation_assignments_count_asc, lambda { - order(Arel.sql("#{sort_by_valuation_assignments_count_nulls_last_query} ASC NULLS FIRST").to_s) + order(valuation_assignments_count: :asc) } scope :sort_by_valuation_assignments_count_desc, lambda { - order(Arel.sql("#{sort_by_valuation_assignments_count_nulls_last_query} DESC NULLS LAST").to_s) + order(valuation_assignments_count: :desc) } scope_search_multi :with_any_state, [:accepted, :rejected, :evaluating, :state_not_published] @@ -333,18 +333,6 @@ def self.ransack(params = {}, options = {}) ProposalSearch.new(self, params, options) end - # Defines the base query so that ransack can actually sort by this value - def self.sort_by_valuation_assignments_count_nulls_last_query - <<-SQL.squish - ( - SELECT COUNT(decidim_proposals_valuation_assignments.id) - FROM decidim_proposals_valuation_assignments - WHERE decidim_proposals_valuation_assignments.decidim_proposal_id = decidim_proposals_proposals.id - GROUP BY decidim_proposals_valuation_assignments.decidim_proposal_id - ) - SQL - end - # method to filter by assigned valuator role ID def self.valuator_role_ids_has(value) query = <<-SQL.squish diff --git a/decidim-proposals/app/models/decidim/proposals/valuation_assignment.rb b/decidim-proposals/app/models/decidim/proposals/valuation_assignment.rb index dcf9ccda990af..ac7cf5f37a3ad 100644 --- a/decidim-proposals/app/models/decidim/proposals/valuation_assignment.rb +++ b/decidim-proposals/app/models/decidim/proposals/valuation_assignment.rb @@ -9,7 +9,8 @@ class ValuationAssignment < ApplicationRecord include Decidim::Traceable include Decidim::Loggable - belongs_to :proposal, foreign_key: "decidim_proposal_id", class_name: "Decidim::Proposals::Proposal" + belongs_to :proposal, foreign_key: "decidim_proposal_id", class_name: "Decidim::Proposals::Proposal", + counter_cache: true belongs_to :valuator_role, polymorphic: true def self.log_presenter_class_for(_log) diff --git a/decidim-proposals/app/views/decidim/proposals/admin/proposals/_form.html.erb b/decidim-proposals/app/views/decidim/proposals/admin/proposals/_form.html.erb index 304fa5194399c..c328ee82c9db0 100644 --- a/decidim-proposals/app/views/decidim/proposals/admin/proposals/_form.html.erb +++ b/decidim-proposals/app/views/decidim/proposals/admin/proposals/_form.html.erb @@ -44,7 +44,7 @@
    <%= form.select :meeting_id, - options_for_select(@form.meetings&.map { |meeting| [present(meeting).title, meeting.id] }, selected: meetings_as_authors_selected ), + options_for_select(@form.meetings&.map { |meeting| [present(meeting).title(html_escape: true), meeting.id] }, selected: meetings_as_authors_selected ), { include_blank: true, label: t(".select_a_meeting") }, { multiple: false, class: "chosen-select" } %>
    diff --git a/decidim-proposals/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb b/decidim-proposals/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb index bd153f2faf79a..cbaafe51fa3de 100644 --- a/decidim-proposals/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +++ b/decidim-proposals/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb @@ -53,7 +53,7 @@ - <%= proposal.valuation_assignments.count %> + <%= proposal.valuation_assignments.size %> diff --git a/decidim-proposals/app/views/decidim/proposals/admin/proposals/show.html.erb b/decidim-proposals/app/views/decidim/proposals/admin/proposals/show.html.erb index 4fe1e2a304685..b1081eb7d0a91 100644 --- a/decidim-proposals/app/views/decidim/proposals/admin/proposals/show.html.erb +++ b/decidim-proposals/app/views/decidim/proposals/admin/proposals/show.html.erb @@ -107,7 +107,7 @@ <% proposal_meetings.each do |meeting| %> <% presented_meeting = present(meeting) %>
  • - <%= link_to presented_meeting.title, presented_meeting.profile_path %> + <%= link_to decidim_escape_translated(meeting.title).html_safe, presented_meeting.profile_path %>
  • <% end %> diff --git a/decidim-proposals/config/locales/ar.yml b/decidim-proposals/config/locales/ar.yml index 0d69f40d2c501..5f40165b7904f 100644 --- a/decidim-proposals/config/locales/ar.yml +++ b/decidim-proposals/config/locales/ar.yml @@ -191,7 +191,6 @@ ar: proposal_wizard_step_1_help_text: اقتراح الاقتراح "إنشاء" نص مساعدة الخطوة proposal_wizard_step_2_help_text: اقتراح الاقتراح "قارن" نص خطوة المساعدة proposal_wizard_step_3_help_text: نص اقتراح "إكمال" تعليمات نص المعالج - proposal_wizard_step_4_help_text: اقتراح الاقتراح "نشر" نص تعليمات الخطوة resources_permissions_enabled: يمكن تعيين أذونات الإجراءات لكل اقتراح scope_id: نطاق scopes_enabled: النطاقات مفعلة @@ -989,7 +988,7 @@ ar: step_1: إنشاء اقتراحك step_2: قارن step_3: إكمال - step_4: انشر اقتراحك + step_4: نشر اقتراحك step_of: الخطوة %{current_step_num} من %{total_steps} title: خطوات إنشاء الاقتراحات proposals_picker: diff --git a/decidim-proposals/config/locales/bg.yml b/decidim-proposals/config/locales/bg.yml index 22dd9ef66d930..3cfefef9aa163 100644 --- a/decidim-proposals/config/locales/bg.yml +++ b/decidim-proposals/config/locales/bg.yml @@ -8,9 +8,12 @@ bg: category_id: Категория decidim_scope_id: Сфера has_address: Има адрес + scope_id: Обхват state: Състояние title: Заглавие user_group_id: Създай съвместна чернова като + import_participatory_text: + document: Текстов документ за участие proposal: address: Адрес answer: Отговор @@ -20,23 +23,32 @@ bg: category_id: Категория decidim_scope_id: Сфера has_address: Има адрес + scope_id: Обхват state: Състояние suggested_hashtags: Предложени хаштагове title: Заглавие user_group_id: Създай предложение като proposal_answer: answer: Отговор + cost: Разход + cost_report: Доклад за разходите + execution_period: Период на изпълнение proposals_copy: copy_proposals: Разбирам, че това ще вмъкне всички предложения от избрания компонент към текущия и това действие не е обратимо. origin_component_id: Компонент, от който да се копират предложенията proposals_import: import_proposals: Копиране на предложения + keep_answers: Запазете състоянието и отговорите keep_authors: Запази автора на оригинала valuation_assignment: admin_log: valuator_role_id: Име на проверяващ errors: models: + participatory_text: + attributes: + document: + allowed_file_content_types: 'Невалиден файлов формат. Позволени са само файлове със следните разширения: %{types}' proposal: attributes: add_documents: @@ -48,6 +60,16 @@ bg: identical: И заглавието не може да е еднакво title: identical: И основния текст не може да е еднакъв + proposals_merge: + attributes: + base: + not_official: Не са официални + supported: Получили са подкрепа или одобрения + proposals_split: + attributes: + base: + not_official: Не са официални + supported: Получили са подкрепа или одобрения models: decidim/proposals/accepted_proposal_event: Предложението е прието decidim/proposals/admin/update_proposal_category_event: Категорията на предложението е променена @@ -77,8 +99,28 @@ bg: admin: filters: proposals: + category_id_eq: + label: Категория + is_emendation_true: + label: Тип + values: + 'false': Предложения + 'true': Изменения + scope_id_eq: + label: Обхват + state_eq: + label: Състояние + values: + accepted: Прието + evaluating: Оценяване + published: Публикувано + rejected: Отхвърлено + validating: Техническа проверка + withdrawn: Оттеглено state_null: label: Състояние + values: + 'true': Не отговорено valuator_role_ids_has: label: Прикрепено към проверяващ search_placeholder: @@ -87,9 +129,11 @@ bg: proposals: actions: amend: Промяна + comment: Коментар create: Създай endorse: Одобри vote: Поддръжка + vote_comment: Оцени коментара withdraw: Оттегляне name: Предложения settings: @@ -102,6 +146,18 @@ bg: can_accumulate_supports_beyond_threshold: Може да събира поддръжка над прага collaborative_drafts_enabled: Съвместните чернови са разрешени comments_enabled: Коментарите са разрешени + comments_max_length: Максимална дължина на коментарите (Оставете 0 за стойност по подразбиране) + default_sort_order: Сортиране на предложения по подразбиране + default_sort_order_help: '"По подразбиране" означава, че ако подрепата е активирана, предложенията ще се показват сортирани по произволен ред, а ако подкрепата е блокирана, тогава те ще бъдат сортирани по най-подкрепяни.' + default_sort_order_options: + default: По подразбиране + most_commented: Най-коментирани + most_endorsed: Най-препоръчвани + most_followed: Най-следвани + most_voted: Най-подкрепяни + random: Произволно + recent: Скорошни + with_more_authors: С повече автори geocoding_enabled: Координатите са разрешени minimum_votes_per_user: Минимална поддръжка за потребител new_proposal_body_template: Шаблон за основен текст на предложение @@ -112,13 +168,19 @@ bg: participatory_texts_enabled_readonly: Тази настройка не е активна, ако има съществуващи предложения. Моля, създайте нов компонент „Предложения“, ако желаете да активирате тази функция или изчистете всички внесени предложения в менюто „Текст на участници“, ако искате да я деактивирате. proposal_answering_enabled: Отговора на предложение е разрешен proposal_edit_before_minutes: Предложенията могат да бъдат редактирани от авторите преди да минат толкова минути + proposal_edit_time: Редактиране на предложение + proposal_edit_time_choices: + infinite: Разрешаване на редактиране на предложения за безкраен период от време + limited: Позволете редактиране на предложения в рамките на определен период от време proposal_length: Максимална дължина на основния текст на предложението proposal_limit: Максимален брой предложения на участник proposal_wizard_step_1_help_text: Текст на помощника за стъпка "Създай" proposal_wizard_step_2_help_text: Текст на помощника за стъпка "Сравни" proposal_wizard_step_3_help_text: Текст на помощника за стъпка "Завърши" - proposal_wizard_step_4_help_text: Текст на помощника за стъпка "Публикувай" + proposal_wizard_step_4_help_text: Помощен текст на стъпка "Публикуване" на съветника за предложения resources_permissions_enabled: Позволените действия могат да се задават за всяко предложение + scope_id: Обхват + scopes_enabled: Обхватите са активирани threshold_per_proposal: Праг за предложенията vote_limit: Максимален брой поддръжки на участник step: @@ -137,10 +199,24 @@ bg: answers_with_costs: Активиране на "тежест" за отговорите на предложение automatic_hashtags: Добавени са хаштагове на всички предложения comments_blocked: Коментарите са блокирани + creation_enabled: Участниците могат да създават предложения + creation_enabled_readonly: Тази настройка е деактивирана, когато активирате функцията "Текстове за участие". За да качите предложения като текст за участие, щракнете върху бутона "Текстове за участие" и следвайте инструкциите. + default_sort_order: Сортиране на предложения по подразбиране + default_sort_order_help: '"По подразбиране" означава, че ако подрепата е активирана, предложенията ще се показват сортирани по произволен ред, а ако подкрепата е блокирана, тогава те ще бъдат сортирани по най-подкрепяни.' + default_sort_order_options: + default: По подразбиране + most_commented: Най-коментирани + most_endorsed: Най-препоръчвани + most_followed: Най-следвани + most_voted: Най-подкрепяни + random: Произволно + recent: Скорошни + with_more_authors: С повече автори endorsements_blocked: Одобряване забранено endorsements_enabled: Одобряване разрешено proposal_answering_enabled: Отговора на предложение е разрешен publish_answers_immediately: Публикувай отговорите на предложения незабавно + publish_answers_immediately_help_html: 'Имайте предвид, че ако отговаряте на някои предложения, без това активиране, ще трябва да ги публикувате ръчно, като ги изберете и използвате действието за публикуване. За повече информация как работи това вижте страницата с документация за отговорите на предложенията.' suggested_hashtags: Предлагай хаштаг на участниците когато създават предложения votes_blocked: Поддържането блокирано votes_enabled: Поддържането разрешено @@ -154,21 +230,33 @@ bg: email_subject: Някой е направил бележка в предложението %{resource_title}. notification_title: Някой е направил бележка в предложението %{resource_title}. Вижте я в администраторския панел collaborative_draft_access_accepted: + email_intro: '%{requester_name} получи достъп като сътрудник в съвместната чернова %{resource_title}.' + email_outro: Получихте известие, защото сте сътрудник в %{resource_title}. email_subject: "%{requester_name} получи достъп като сътрудник в %{resource_title}." notification_title: %{requester_name} %{requester_nickname} получи достъп като сътрудник в съвместната чернова %{resource_title}. collaborative_draft_access_rejected: + email_intro: '%{requester_name} е отхвърлен като сътрудник в съвместната чернова %{resource_title}.' + email_outro: Получихте известие, защото сте сътрудник в %{resource_title}. email_subject: "%{requester_name} е отхвърлен като сътрудник в съвместната чернова %{resource_title}." notification_title: %{requester_name} %{requester_nickname} е отхвърлен като сътрудник в съвместната чернова %{resource_title}. collaborative_draft_access_requested: + email_intro: '%{requester_name} заяви достъп като сътрудник. Можете да приемете или отхвърлите от сраницата на колективната чернова %{resource_title}.' + email_outro: Получихте известие, защото сте сътрудник в %{resource_title}. email_subject: "%{requester_name} заяви достъп като сътрудник в %{resource_title}." notification_title: %{requester_name} %{requester_nickname} заяви достъп като сътрудник в колективната чернова %{resource_title}. Моля, приемете или отхвърлете заявката. collaborative_draft_access_requester_accepted: + email_intro: Получихте достъп като сътрудник в колективната чернова %{resource_title}. + email_outro: Получихте известие, защото заявихте да бъдете сътрудник в %{resource_title}. email_subject: Приет сте като сътрудник в %{resource_title}. notification_title: Получихте достъп като сътрудник в колективната чернова %{resource_title}. collaborative_draft_access_requester_rejected: + email_intro: Отказан Ви е достъп като сътрудник в колективната чернова %{resource_title}. + email_outro: Получихте известие, защото заявихте да бъдете сътрудник в %{resource_title}. email_subject: Отхвърлен сте като сътрудник в %{resource_title}. notification_title: Отказан Ви е достъп като сътрудник в колективната чернова %{resource_title}. collaborative_draft_withdrawn: + email_intro: %{author_name} %{author_nickname} оттегли колективната чернова %{resource_title}. + email_outro: Получихте известие, защото сте сътрудник в %{resource_title}. email_subject: "%{author_name} %{author_nickname} оттегли колективната чернова %{resource_title}." notification_title: %{author_name} %{author_nickname} оттегли колективната чернова %{resource_title}. creation_enabled: @@ -189,6 +277,7 @@ bg: notification_title: Вашето предложение %{resource_title} е одобрено. follower: email_intro: 'Предложението "%{resource_title}" е одобрено. Прочетете отговора на страницата:' + email_outro: Получавате това известие, защото следвате "%{resource_title}". Може да премахнете следването чрез предната връзка. email_subject: Предложение, което следвате е одобрено notification_title: Предложението %{resource_title} беше одобрено. proposal_evaluating: @@ -199,6 +288,7 @@ bg: notification_title: Вашето предложение %{resource_title} се разглежда. follower: email_intro: 'Предложението "%{resource_title}" се разглежда в момента. Прочетете отговора на страницата:' + email_outro: Получавате това известие, защото следвате "%{resource_title}". Може да премахнете следването чрез предната връзка. email_subject: Предложение, което следвате се разглежда notification_title: Предложението %{resource_title} се разглежда. proposal_mentioned: @@ -214,23 +304,534 @@ bg: proposal_published_for_space: email_intro: Предложението "%{resource_title}" беше добавено в "%{participatory_space_title}", което следвате. email_outro: Получавате това известие, защото следвате "%{participatory_space_title}". Може да прекратите известията чрез предната връзка. + email_subject: Ново предложение „%{resource_title}“ беше добавено в(ъв) %{participatory_space_title} + notification_title: Предложениетоl %{resource_title} е добавено към %{participatory_space_title} от %{author} + notification_title_official: Официалното предложение %{resource_title} е добавено към %{participatory_space_title} proposal_rejected: affected_user: + email_intro: 'Вашето предложение "%{resource_title}" беше отхвърлено. Можете да прочетете отговора на тази страница:' email_outro: Получавате това известие, защото сте автор на %{resource_title}". + email_subject: Вашето предложение беше отхвърлено + notification_title: Вашето предложение %{resource_title} беше отхвърлено. + follower: + email_intro: 'Предложението „%{resource_title}“ беше отхвърлено. Можете да прочетете отговора на тази страница:' + email_outro: Получавате това известие, защото следвате "%{resource_title}". Може да премахнете следването чрез предната връзка. + email_subject: Предложение, което следвате, беше отхвърлено + notification_title: Предложението %{resource_title} беше отхвърлено. + proposal_update_category: + email_intro: 'Администратор актуализира категорията на Вашето предложение „%{resource_title}“. Вижте повече на тази страница:' + email_outro: Получавате това известие, защото сте авторът на предложението. + email_subject: Категорията на предложението %{resource_title} беше актуализирана + notification_title: Категорията на предложението %{resource_title} беше актуализирана от администратор. + proposal_update_scope: + email_intro: 'Администратор актуализира обхвата на Вашето предложение „%{resource_title}“. Вижте повече на тази страница:' + email_outro: Получавате това известие, защото сте авторът на предложението. + email_subject: Обхватът на предложението %{resource_title} беше актуализиран + notification_title: Обхватът на предложението %{resource_title} беше актуализиран от администратор. + voting_enabled: + email_intro: 'Можете да подкрепяте нови предложения в(ъв) %{participatory_space_title}! Започнете да участвате на следната страница:' + email_outro: Получавате това известие, защото следвате %{participatory_space_title}. Може да прекратите известията чрез предходния линк. + email_subject: Предоставянето на подкрепа за предложения започна за %{participatory_space_title} + notification_title: Вече можете да започнете да подкрепяте предложения в(ъв) %{participatory_space_title} + gamification: + badges: + accepted_proposals: + conditions: + - Изберете пространството за участие, което ви интересува, с подаване на активни предложения + - Опитайте се да правите предложения, които могат да бъдат изпълнени. По този начин е по-вероятно те да бъдат приети. + description: Тази значка се дава, когато участвате активно с нови предложения и те са приети. + description_another: Този участник има %{score} приети предложения. + description_own: Имате %{score} приети предложения. + name: Приети предложения + next_level_in: Нужни са Ви още %{score} приети предложения, за да достигнете следващото ниво! + unearned_another: Все още не е прието нито едно предложение на този участник. + unearned_own: Все нямате прието предложение. + proposal_votes: + conditions: + - Разгледайте и прекарайте известно време, за да се запознаете с предложенията на други хора + - Подкрепете предложенията, които харесвате или намирате за интересни + description: Тази значка се предоставя, когато подкрепяте предложения на други хора. + description_another: Този участник е подкрепил %{score} предложения. + description_own: Подкрепили сте %{score} предложения. + name: Подкрепяния на предложение + next_level_in: Подкрепете още %{score} предложения, за да достигнете следващото ниво! + unearned_another: Този участник все още не е подкрепил нито едно предложение. + unearned_own: Все още не сте подкрепили нито едно предложение. + proposals: + conditions: + - Изберете пространството за участие, което ви интересува, с подаване на активни предложения + - Създайте ноео предложение + description: Тази значка се предоставя, когато участвате активно с нови предложения. + description_another: Този участник е създал %{score} предложения. + description_own: Създали сте %{score} предложения. + name: Предложения + next_level_in: Създайте още %{score} предложения, за да достигнете следващото ниво! + unearned_another: Този участник все още не е създал нито едно предложение. + unearned_own: Все още не сте създали нито едно предложение. + metrics: + accepted_proposals: + description: Брой на приетите предложения + object: предложения + title: Приети предложения + endorsements: + description: Брой одобрения на предложения + object: одобрения + title: Одобрения + proposals: + description: Брой предложения + object: предложения + title: Предложения + votes: + description: Брой на подкрепяния за предложения + object: подкрепа + title: Подкрепа + participatory_spaces: + highlighted_proposals: + see_all: Виж всички предложения (%{count}) proposals: + actions: + answer_proposal: Отговор на предложение + edit_proposal: Редактиране на предложение + import: Импортиране на предложения от друг компонент + new: Ново предложение + participatory_texts: Текстове на участници + show: Показване на предложението + title: Активности admin: + actions: + preview: Преглед + exports: + proposal_comments: Коментари + proposals: Предложения imports: + help: + answers: | + Документът за импортиране трябва да съдържа следните имена на колони в случай на CSV или Excel файлове или имена на ключове в случай на JSON файлове: +
      +
    • id: ID на предложението за отговор
    • +
    • състояние: Едно от „прието“, „оценява“ или „отхвърлено“
    • +
    • answer/en: Отговор на английски език. Това ще зависи от езиковата конфигурация на вашата платформа.
    • +
    + proposals: | + Файлът трябва да има следните имена на колони в случай на CSV или Excel файлове или имена на ключове в случай на JSON файлове: +
      +
    • title/en: Заглавие на английски език. Това ще зависи от езиковата конфигурация на вашата платформа.
    • +
    • body/en: Основен текст на английски език. Това ще зависи от езиковата конфигурация на вашата платформа.
    • +
    • scope/id: ID за обхвата
    • +
    • category/id: ID за категорията
    • +
    + label: + answers: Импортиране на отговори от файл + proposals: Импортиране на предложения от файл + resources: + answers: + one: отговор на предложение + other: отговори на предложение + proposals: + one: предложение + other: предложения title: + answers: Импортиране на отговори на предложения proposals: Копиране на предложения + models: + proposal: + name: Предложение + participatory_texts: + bulk-actions: + are_you_sure: Наистина ли искате да отхвърлите цялата чернова на текста за участие? + discard_all: Отхвърли всички + import_doc: Импортиране на документ + discard: + success: Всички чернови на текстове за участие бяха отхвърлени. + import: + invalid: Формулярът е невалиден! + invalid_file: Файлът съдържа грешка, моля, опитайте да редактирате съдържанието на файла и го качете повторно. + success: Поздравления, следните раздели бяха преобразувани в предложения. Вече можете да ги прегледате и да ги коригирате, преди да ги публикувате. + index: + info_1: Следните раздели бяха преобразувани в предложения. Вече можете да ги прегледате и да ги коригирате, преди да ги публикувате. + publish_document: Публикуване на Документ + save_draft: Запазване на чернова + title: Преглед на текста за участие + new_import: + accepted_mime_types: + md: Маркиране + odt: ODT + bottom_hint: "(Ще имате възможност да прегледате и сортирате секциите с документи)" + document_legend: 'Добавете документ с големина до 2 Mb, като всеки раздел до 3 нива надолу в структурата ще бъде анализиран в „Предложения“. Поддържаните формати са: %{valid_mime_types}' + title: Добави документ + upload_document: Качване на документ + publish: + invalid: Неуспешно публикуване на предложения + success: Всички предложения бяха публикувани + sections: + article: "Член" + section: "Раздел: %{title}" + sub-section: "Подраздел: %{title}" + update: + success: Текстът за участие беше актуализиран успешно. + proposal_answers: + form: + accepted: Прието + answer_proposal: Отговор + evaluating: Оценяване + not_answered: Не отговорено + rejected: Отхвърлено + title: Отговор на предложение %{title} + proposal_notes: + create: + error: Възникна проблем при създаването на тази бележка за предложението + success: Бележката за предложението беше създадена успешно + form: + note: Бележка + submit: Подаване + leave_your_note: Оставете Вашата бележка + title: Лични бележки proposals: + answer: + invalid: Възникна проблем при отговарянето на това предложение + success: Отговорихте успешно на предложението + create: + invalid: Възникна проблем при създаването на това предложение + success: Предложението беше създадено успешно + edit: + title: Актуализиране на предложението + update: Актуализация + form: + attachment_legend: "(Незадължително) Добавяне на прикачен файл" + created_in_meeting: Това предложение е резултат от среща + delete_attachment: Изтриване на прикачен файл + select_a_category: Изберете категория + select_a_meeting: Избор на среща + index: + actions: Активности + assign_to_valuator: Възлагане на оценител + assign_to_valuator_button: Възлагане + cancel: Отказ + change_category: Промяна на категория + change_scope: Промяна на обхвата + merge: Сливане в едно ново + merge_button: Сливане + publish: Публикувай + publish_answers: Публикуване на отговори + select_component: Избери компонент + selected: избрани + split: Разделяне на предложения + split_button: Разделяне + title: Предложения + unassign_from_valuator: Отнемане възложеното на оценителя + unassign_from_valuator_button: Отнемане на възложеното + update: Актуализация + update_scope_button: Актуализиране на обхвата + new: + create: Създаване + title: Създаване на предложение + publish_answers: + number_of_proposals: Отговорите на %{number} предложения ще бъдат публикувани. + select_a_proposal: Моля, изберете предложение show: + amendments_count: Брой изменения + assigned_valuators: Присъеденени оценители + authors: Автори + body: Основен текст + comments_count: Брой коментари + comments_negative_count: Против + comments_neutral_count: Неутрален + comments_positive_count: Подкрепям + created_at: Дата на създаване + documents: Документи + endorsements_count: Брой препоръки + endorsements_ranking: Класиране по препоръки + endorsers: Препоръчали + link: Връзка + n_more_endorsers: + one: и още 1 + other: и още %{count} + photos: Снимки proposals: Предложения + ranking: "%{ranking} от %{total}" + related_meetings: Свързани срещи + remove_assignment: Премахване на възлагане + remove_assignment_confirmation: Наистина ли искате да премахнете оценителя от това предложение? + valuators: Оценители + votes_count: Брой подкрепяния + votes_ranking: Класиране по подкрепяния + update_category: + invalid: 'Тези предложения вече имат категорията %{subject_name}: %{proposals}.' + select_a_category: Моля, изберете категория + select_a_proposal: Моля, изберете предложение + success: 'Предложенията бяха актуализирани успешно в категорията %{subject_name}: %{proposals}.' + update_scope: + invalid: 'Тези предложения вече имат обхват %{subject_name}: %{proposals}.' + select_a_proposal: Моля, изберете предложение + select_a_scope: Моля, изберете обхват + success: 'Предложенията бяха актуализирани успешно в обхвата %{subject_name}: %{proposals}.' proposals_imports: + create: + invalid: Възникна проблем при импортирането на предложенията + success: "%{number} предложения бяха импортирани успешно" new: + create: Импортиране на предложения + no_components: Няма други компоненти на предложения в това пространство за участие, от които да се импортират предложенията. + select_component: Моля, изберете компонент + select_states: Проверете състоянието на предложенията за импортиране title: Копиране на предложения + proposals_merges: + create: + invalid: 'Възникна проблем при обединяването на избраните предложения, заради някои от тези:' + success: Предложенията бяха обединени успешно в ново предложение. + proposals_splits: + create: + invalid: 'Възникна проблем при сливането на избраните предложения, заради някои от тези:' + success: Предложенията бяха разделени успешно в нови предложения. + valuation_assignments: + create: + invalid: Възникна грешка при възлагането на предложенията на оценител + success: Предложенията бяха възложени успешно на оценител + delete: + invalid: Възникна грешка при отмяна на възлагането на предложения към оценител + success: Оценителят бе успешно премахнат от предложенията + admin_log: + proposal: + answer: "%{user_name} отговори на предложението %{resource_name} в пространството %{space_name}" + create: "%{user_name} създаде предложението %{resource_name} в пространството %{space_name} като официално предложение" + publish_answer: "%{user_name} публикува отговора на предложението %{resource_name} в пространството %{space_name}" + update: "%{user_name} актуализира официалното предложение %{resource_name} в пространството %{space_name}" + proposal_note: + create: "%{user_name} остави частна бележка в предложението %{resource_name} в пространството %{space_name}" + valuation_assignment: + create: "%{user_name} възложи предложението %{resource_name} на оценител" + delete: "%{user_name} премахна възлагането на предложението %{proposal_title} на оценител" + answers: + accepted: Прието + evaluating: Оценяване + not_answered: Не отговорено + rejected: Отхвърлено + withdrawn: Оттеглено + application_helper: + filter_category_values: + all: Всички + filter_origin_values: + all: Всички + meetings: Срещи + official: Официално + participants: Участници + user_groups: Групи + filter_scope_values: + all: Всички + filter_state_values: + accepted: Прието + all: Всички + evaluating: Оценяване + not_answered: Не отговорено + rejected: Отхвърлено + filter_type_values: + all: Всички + amendments: Изменения + proposals: Предложения + collaborative_drafts: + collaborative_draft: + publish: + error: Възникна проблем при публикуването на съвместната чернова. + irreversible_action_modal: + body: След като черновата бъде публикувана като предложение, тя повече няма да може да се редактира. За предложението няма да могат да се приемат нови автори или добавки. + cancel: Отказ + ok: Публикувай като предложение + title: Следното действие е необратимо + success: Съвместната чернова беше публикувана успешно като предложение. + view_collaborative_draft: Преглед на съвместна чернова + withdraw: + error: Възникна проблем при затварянето на съвместната чернова. + irreversible_action_modal: + body: След като черновата бъде затворена, тя повече няма да може да се редактира. За черновата няма да могат да се приемат нови автори или добавки. + cancel: Отказ + ok: Оттегляне на съвместната чернова + title: Следното действие е необратимо + success: Съвместната чернова беше оттеглена успешно. + count: + drafts_count: + one: "Съвместна чернова" + other: "Съвместни чернови" + create: + error: Възникна проблем при създаването на тази съвместна чернова. + success: Съвместната чернова беше създадена успешно. + edit: + attachment_legend: "(Незадължително) Добавяне на прикачен файл" + back: Назад + select_a_category: Моля, изберете категория + send: Изпрати + title: Редактиране на съвместната чернова + filters: + all: Всички + amendment: Изменения + category: Категория + open: Отворен + published: Публикувано + related_to: Свързано с + scope: Обхват + search: Търсене + state: Статус + withdrawn: Оттеглено + filters_small_view: + close_modal: Затвори прозореца + filter: Филтър + filter_by: Филтрирай по + unfold: Разгъване + new: + add_file: Добави файл + edit_file: Редактирай файл + send: Продължи + new_collaborative_draft_button: + new_collaborative_draft: Нова съвместна чернова + orders: + label: 'Подреждане на черновите по:' + most_contributed: Най-допринесли + random: Произволно + recent: Скорошни + requests: + accepted_request: + error: Неуспешно приемане като сътрудник, моля, опитайте отново по-късно. + success: "@%{user} беше приет(а) успешно като сътрудник" + access_requested: + error: Заявката Ви не беше изпълнена успешно, моля, опитайте отново по-късно. + success: Вашата заявка за сътрудничество беше изпратена успешно + collaboration_requests: + accept_request: Приеми + reject_request: Отхвърли + title: Заявки за сътрудничество + rejected_request: + error: Неуспешно отхвърляне като сътрудник, моля, опитайте отново по-късно. + success: "@%{user} беше отхвърлен(а) успешно като сътрудник" + show: + back: Назад + edit: Редактиране на съвместната чернова + final_proposal: окончателно предложение + final_proposal_help_text: Тази чернова е завършена. Вижте окончателното предложение + hidden_authors_count: + one: и още %{count} + other: и още %{count} души + info-message: Това е съвместна чернова за предложение. Това означава, че можете да помогнете на авторите да оформят предложението си, като използвате раздела за коментари по-долу, или да го подобрите директно, като поискате редакторски достъп. След като авторите Ви предоставят достъп, ще можете да извършвате промени в черновата. + publish: Публикувай + publish_info: Публикуване на тази версия на черновата или + published_proposal: публикувано предложение + request_access: Заявка за достъп + requested_access: Изпратена е заявка за достъп + version_history: вижте хронологията на версиите за това предложение + withdraw: оттеглете черновата + states: + open: Отвори + published: Публикувано + withdrawn: Оттеглено + update: + error: Възникна проблем при запазването на съвместната чернова. + success: Съвместната чернова беше актуализирана успешно. + wizard_aside: + back_from_collaborative_draft: Назад към съвместните чернови + info: Създавате съвместна чернова. + wizard_header: + title: Създайте своята съвместна чернова content_blocks: highlighted_proposals: proposals: Предложения + create: + error: Възникна проблем при запазването на предложението. + success: Предложението беше създадено успешно. Запазено като чернова. + last_activity: + new_proposal_at_html: "Ново предложение на адрес: %{link}" + proposal_updated_at_html: "Предложение беше актуализирано на: %{link}" + models: + collaborative_draft: + fields: + authors: Автори + contributions: Добавки + new: + limit_reached: Не можете да създавате нови предложения, докато сте надхвърлили ограничението. + proposals: + compare: + continue: Продължи + complete: + send: Изпрати + count: + proposals_count: + one: "%{count} предложение" + other: "%{count} предложения" + edit: + add_image: Добавяне на изображение + edit_image: Редактиране на изображение + gallery_legend: "(Незадължително) Добавете изображение към картата с предложението" + filters_small_view: + close_modal: Затвори прозореца + filter: Филтър + filter_by: Филтрирай по + unfold: Разгъване + index: + click_here: Виж всички предложения + collaborative_drafts_list: Достъп до съвместни чернови + new_proposal: Ново предложение + see_all: Виж всички предложения + see_all_withdrawn: Вижте всички оттеглени предложения + text_banner: Разглеждате списъка с предложения, оттеглени от своите автори. %{go_back_link}. + view_proposal: Преглед на предложението + linked_proposals: + proposal_votes: + one: поддръжка + other: поддръжки + new: + send: Продължи + title: Създайте Ваше предложение + orders: + label: 'Подреждане на предложенията по:' + most_commented: Най-коментирани + most_endorsed: Най-препоръчвани + most_followed: Най-следвани + most_voted: Най-подкрепяни + random: Произволно + recent: Скорошни + with_more_authors: С повече автори + participatory_texts: + index: + document_index: Индекс на документ + view_index: + see_index: Вижте индекса + placeholder: + address: 37 Homewood Drive Brownsburg, IN 46112 + preview: + announcement_body: Вашето предложение е запазено като чернова. Трябва да се публикува, за да се появи на сайта. + announcement_title: Вашето предложение все още не е публикувано + proposal: + creation_date: 'Създадено на:' + view_proposal: Преглед на предложението + proposals: + empty: Все още няма предложение + empty_filters: Няма предложение, което да отговаря на тези критерии + show: + back_to: Назад към + back_to_list: Назад към списъка + endorsements_list: Списък с одобрения + read_less: Виж по-малко + read_more: Прочетете повече + report: Отчет + tags: + changed_from: "(променено от предишното %{previous_name} от администратор)" + votes_count: + most_popular_proposal: Най-популярно предложение + need_more_votes: Има нужда от повече подкрепяния + voting_rules: + minimum_votes_per_user: + given_enough_votes: Предоставили сте достатъчно подкрепяния. + threshold_per_proposal: + description: За да бъдат валидирани, предложенията трябва да съберат %{limit} подкрепяния + vote_limit: + left: Оставащи + votes: Подкрепа + wizard_aside: + info: Вие създавате предложение. + wizard_steps: + see_steps: вижте стъпките + step_of: Стъпка %{current_step_num} от общо %{total_steps} + proposals_picker: + close: Затвори + more_proposals: Има още %{number} предложения. Прецизирайте търсенето си, за да ги намерите. + no_proposals: Няма предложения, които да съответстват на критериите Ви за търсене, или няма никакви предложения. versions: collaborative_drafts: back_to_resource: Обратно към съвместната чернова diff --git a/decidim-proposals/config/locales/ca.yml b/decidim-proposals/config/locales/ca.yml index eb4a670733b30..64da725ca1c87 100644 --- a/decidim-proposals/config/locales/ca.yml +++ b/decidim-proposals/config/locales/ca.yml @@ -111,7 +111,7 @@ ca: state_eq: label: Estat values: - accepted: Acceptada + accepted: Acceptades evaluating: En avaluació published: Publicades rejected: Rebutjada @@ -231,48 +231,48 @@ ca: notification_title: Algú ha deixat una nota a la proposta %{resource_title}. Revisa-la ara a través del taulell d'admistració collaborative_draft_access_accepted: email_intro: 'S''ha acceptat %{requester_name} per accedir com a contribuidora de l''esborrany col·laboratiu %{resource_title}.' - email_outro: Has rebut aquesta notificació perquè ets una contribuïdora de %{resource_title}. + email_outro: Has rebut aquesta notificació perquè vas contribuir a la proposta "%{resource_title}". email_subject: "S'ha acceptat %{requester_name} per accedir com a contribuidora del %{resource_title}." notification_title: %{requester_name} %{requester_nickname} ha estat acceptat per accedir com a contribuidora de l'esborrany col·laboratiu %{resource_title}. collaborative_draft_access_rejected: email_intro: 'S''ha rebutjat que %{requester_name} accedeixi com a contribuidora de l''esborrany col·laboratiu %{resource_title}.' - email_outro: Has rebut aquesta notificació perquè ets una contribuïdora de %{resource_title}. + email_outro: Has rebut aquesta notificació perquè vas contribuir a la proposta "%{resource_title}". email_subject: "S'ha rebutjat %{requester_name} per accedir com a contribuïdora de l'esborrany col·laboratiu %{resource_title}." notification_title: %{requester_name} %{requester_nickname} ha estat rebutjat per accedir com a contribuïdora de l'esborrany col·laboratiu %{resource_title}. collaborative_draft_access_requested: email_intro: '%{requester_name} ha sol·licitat accés com a contribuïdora. Pots acceptar o rebutjar la sol·licitud de l''esborrany col·laboratiu %{resource_title}.' - email_outro: Has rebut aquesta notificació perquè ets contribuïdora de %{resource_title}. + email_outro: Has rebut aquesta notificació perquè vas contribuir a la proposta "%{resource_title}". email_subject: "%{requester_name} ha demanat accés per contribuir a %{resource_title}." notification_title: %{requester_name} %{requester_nickname} ha sol·licitat accés per contribuir a l'esborrany col·laboratiu de %{resource_title}. Si us plau, accepta o rebutja la sol·licitud. collaborative_draft_access_requester_accepted: email_intro: Has estat acceptada com a contribuïdora de l'esborrany col·laboratiu %{resource_title}. - email_outro: Has rebut aquesta notificació perquè has sol·licitat ser contribuïdora de %{resource_title}. + email_outro: Has rebut aquesta notificació perquè has sol·licitat poder contribuïr a la proposta "%{resource_title}". email_subject: Has estat acceptada com a contribuïdora de %{resource_title}. notification_title: Has estat acceptada com a contribuïdora de l'esborrany col·laboratiu %{resource_title}. collaborative_draft_access_requester_rejected: email_intro: Has estat rebutjada per accedir com a contribuïdora de l'esborrany col·laboratiu %{resource_title}. - email_outro: Has rebut aquesta notificació perquè has sol·licitat ser contribuïdora de %{resource_title}. + email_outro: Has rebut aquesta notificació perquè has sol·licitat poder contribuïr a la proposta "%{resource_title}". email_subject: Has estat rebutjada com a contribuïdora de %{resource_title}. notification_title: Has estat rebutjada per accedir com a contribuïdora de l'esborrany col·laboratiu %{resource_title}. collaborative_draft_withdrawn: email_intro: %{author_name} %{author_nickname} ha retirat l'esborrany col·laboratiu %{resource_title}. - email_outro: Has rebut aquesta notificació perquè ets contribuïdora de %{resource_title}. + email_outro: Has rebut aquesta notificació perquè vas contribuir a la proposta "%{resource_title}". email_subject: "%{author_name} %{author_nickname} ha retirat l'esborrany col·laboratiu %{resource_title}." notification_title: %{author_name} %{author_nickname} ha retirat l'esborrany col·laboratiu %{resource_title}. creation_enabled: email_intro: 'Ara pots crear noves propostes a %{participatory_space_title}! Comença a participar a aquesta pàgina:' - email_outro: Has rebut aquesta notificació perquè estàs seguint %{participatory_space_title}. Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint l'espai "%{participatory_space_title}". Pots deixar de rebre notificacions seguint l'enllaç anterior. email_subject: Les propostes ja estan disponibles a %{participatory_space_title} notification_title: Ara pots presentar noves propostes a %{participatory_space_title} endorsing_enabled: email_intro: 'Pots adherir-te a les propostes a %{participatory_space_title}. Comença a participar en aquesta pàgina:' - email_outro: Has rebut aquesta notificació perquè estàs seguint %{participatory_space_title}. Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint l'espai "%{participatory_space_title}". Pots deixar de rebre notificacions seguint l'enllaç anterior. email_subject: L'adhesió a les propostes de %{participatory_space_title} ha començat notification_title: Ara ja pots començar a adherir-te a propostes a %{participatory_space_title} proposal_accepted: affected_user: email_intro: 'S''ha acceptat la teva proposta "%{resource_title}". Pots llegir la resposta en aquesta pàgina:' - email_outro: Has rebut aquesta notificació perquè ets autora de "%{resource_title}". + email_outro: Has rebut aquesta notificació perquè vas presentar aquesta proposta "%{resource_title}". email_subject: S'ha acceptat la teva proposta notification_title: S'ha acceptat la teva proposta %{resource_title}. follower: @@ -283,7 +283,7 @@ ca: proposal_evaluating: affected_user: email_intro: 'La teva proposta "%{resource_title}" s''està avaluant. Pots consultar la resposta en aquesta pàgina:' - email_outro: Has rebut aquesta notificació perquè ets autora de "%{resource_title}". + email_outro: Has rebut aquesta notificació perquè vas presentar aquesta proposta "%{resource_title}". email_subject: S'està avaluant la teva proposta notification_title: S'està avaluant la teva proposta %{resource_title}. follower: @@ -293,24 +293,24 @@ ca: notification_title: S'ha avaluat la proposta %{resource_title}. proposal_mentioned: email_intro: La teva proposta "%{mentioned_proposal_title}" ha estat esmentada als comentaris en aquest espai. - email_outro: Has rebut aquesta notificació perquè ets autora de "%{resource_title}". + email_outro: Has rebut aquesta notificació perquè vas presentar aquesta proposta "%{resource_title}". email_subject: S'ha mencionat la teva proposta "%{mentioned_proposal_title}" notification_title: La teva proposta "%{mentioned_proposal_title}" ha estat esmentada en aquest espai als comentaris. proposal_published: email_intro: '%{author_name} %{author_nickname}, a qui segueixes, ha publicat una nova proposta anomenada "%{resource_title}". Consulta i contribueix:' - email_outro: Has rebut aquesta notificació perquè estàs seguint %{author_nickname}. Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint a "%{author_nickname}". Pots deixar de rebre notificacions seguint l'enllaç anterior. email_subject: Nova proposta "%{resource_title}" de %{author_nickname} notification_title: La proposta %{resource_title} ha estat publicada per %{author_name} %{author_nickname}. proposal_published_for_space: - email_intro: La proposta "%{resource_title}" s'ha afegit a "%{participatory_space_title}", que segueixes. - email_outro: Has rebut aquesta notificació perquè estàs seguint "%{participatory_space_title}". Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_intro: La proposta "%{resource_title}" s'ha afegit a l'espai "%{participatory_space_title}", que segueixes. + email_outro: Has rebut aquesta notificació perquè estàs seguint l'espai "%{participatory_space_title}". Pots deixar de rebre notificacions seguint l'enllaç anterior. email_subject: Nova proposta "%{resource_title}" afegida a %{participatory_space_title} notification_title: '%{author} ha afegit la proposta %{resource_title} a %{participatory_space_title}' notification_title_official: S'ha afegit la proposta oficial %{resource_title} a %{participatory_space_title} proposal_rejected: affected_user: email_intro: 'La teva proposta "%{resource_title}" ha estat rebutjada. Pots llegir la resposta en aquesta pàgina:' - email_outro: Has rebut aquesta notificació perquè ets autora de "%{resource_title}". + email_outro: Has rebut aquesta notificació perquè vas presentar aquesta proposta "%{resource_title}". email_subject: La teva proposta ha estat rebutjada notification_title: La teva proposta %{resource_title} ha estat rebutjada. follower: @@ -320,18 +320,18 @@ ca: notification_title: S'ha rebutjat la proposta %{resource_title}. proposal_update_category: email_intro: 'Una administradora ha actualitzat la categoria de la teva proposta "%{resource_title}", fes-hi una ullada:' - email_outro: Has rebut aquesta notificació perquè ets autora de la proposta. + email_outro: Has rebut aquesta notificació perquè vas presentar aquesta proposta. email_subject: S'ha actualitzat la categoria de la proposta %{resource_title} notification_title: La categoria de la proposta %{resource_title} ha estat actualitzada per una administradora. proposal_update_scope: email_intro: 'Una administradora ha actualitzat l''àmbit de la teva proposta "%{resource_title}", fes-hi una ullada:' - email_outro: Has rebut aquesta notificació perquè ets autora de la proposta. + email_outro: Has rebut aquesta notificació perquè vas presentar aquesta proposta. email_subject: S'ha actualitzat l'àmbit de la proposta %{resource_title} notification_title: L'àmbit de la proposta %{resource_title} ha estat actualitzat per una administradora. voting_enabled: email_intro: 'Pots començar a donar suports a les propostes de %{participatory_space_title}! Comença a participar en aquesta pàgina:' - email_outro: Has rebut aquesta notificació perquè estàs seguint %{participatory_space_title}. Pots deixar de rebre notificacions seguint l'enllaç anterior. - email_subject: El recolzament a propostes ha començat per a %{participatory_space_title} + email_outro: Has rebut aquesta notificació perquè estàs seguint l'espai "%{participatory_space_title}". Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_subject: El recolzament a propostes ha començat per a l'espai "%{participatory_space_title}" notification_title: Ja pots començar a donar suports a propostes a %{participatory_space_title} gamification: badges: @@ -387,7 +387,7 @@ ca: title: Suports participatory_spaces: highlighted_proposals: - see_all: Veure tots (%{count}) + see_all: Veure totes (%{count}) proposals: actions: answer_proposal: Respondre a la proposta @@ -471,7 +471,7 @@ ca: success: El text participatiu s'ha actualitzat correctament. proposal_answers: form: - accepted: Acceptades + accepted: Acceptada answer_proposal: Resposta evaluating: En avaluació not_answered: No resposta @@ -602,7 +602,7 @@ ca: create: "%{user_name} ha assignat la proposta %{resource_name} a una avaluadora" delete: "%{user_name} ha desfet l'assignació a una avaluadora de la proposta %{proposal_title}" answers: - accepted: Acceptades + accepted: Acceptada evaluating: En avaluació not_answered: No resposta rejected: Rebutjada @@ -619,7 +619,7 @@ ca: filter_scope_values: all: Totes filter_state_values: - accepted: Acceptades + accepted: Acceptada all: Totes evaluating: En avaluació not_answered: No resposta @@ -779,7 +779,7 @@ ca: no_similars_found: Ben fet! No s'han trobat propostes semblants title: Propostes similars complete: - send: Enviar + send: Envia title: Completa la teva proposta count: proposals_count: diff --git a/decidim-proposals/config/locales/cs.yml b/decidim-proposals/config/locales/cs.yml index acbcf3e4dca65..256cf5a960a24 100644 --- a/decidim-proposals/config/locales/cs.yml +++ b/decidim-proposals/config/locales/cs.yml @@ -12,6 +12,8 @@ cs: state: Stav title: Titul user_group_id: Vytvořit návrh spolupráce jako + import_participatory_text: + document: Textový dokument k participaci proposal: address: Adresa answer: Odpovědět @@ -183,7 +185,6 @@ cs: proposal_wizard_step_1_help_text: Text průvodce kroku nápovědy "Vytvořit" Návrh proposal_wizard_step_2_help_text: Text průvodce kroku nápovědy "Porovnat" návrhy proposal_wizard_step_3_help_text: Text průvodce kroku nápovědy „Dokončit“ Návrh - proposal_wizard_step_4_help_text: Text průvodce kroku nápovědy "Publikovat" Návrh resources_permissions_enabled: Pro každý návrh lze nastavit oprávnění akce scope_id: Oblast působnosti scopes_enabled: Oblasti působnosti povoleny @@ -283,6 +284,7 @@ cs: notification_title: Váš návrh %{resource_title} byl přijat. follower: email_intro: 'Návrh "%{resource_title}" byl přijat. Odpověď můžete číst na této stránce:' + email_outro: Toto oznámení jste obdrželi, protože sledujete "%{resource_title}". Můžete sledování odhlásit na předchozím odkazu. email_subject: Návrh, který sledujete, byl přijat notification_title: Návrh %{resource_title} byl přijat. proposal_evaluating: @@ -293,6 +295,7 @@ cs: notification_title: Váš návrh %{resource_title} je hodnocen. follower: email_intro: 'V současné době se hodnotí návrh "%{resource_title}". V této stránce můžete zkontrolovat odpověď:' + email_outro: Toto oznámení jste obdrželi, protože sledujete "%{resource_title}". Můžete sledování odhlásit na předchozím odkazu. email_subject: Návrh, který sledujete, se hodnotí notification_title: Návrh %{resource_title} se hodnotí. proposal_mentioned: @@ -319,6 +322,7 @@ cs: notification_title: Váš návrh %{resource_title} byl zamítnut. follower: email_intro: 'Návrh "%{resource_title}" byl zamítnut. Odpověď můžete číst na této stránce:' + email_outro: Toto oznámení jste obdrželi, protože sledujete "%{resource_title}". Můžete sledování odhlásit na předchozím odkazu. email_subject: Návrh, který sledujete, byl zamítnut notification_title: Návrh %{resource_title} byl zamítnut. proposal_update_category: diff --git a/decidim-proposals/config/locales/de.yml b/decidim-proposals/config/locales/de.yml index b44d81a0f5c25..718f201f04a47 100644 --- a/decidim-proposals/config/locales/de.yml +++ b/decidim-proposals/config/locales/de.yml @@ -779,7 +779,7 @@ de: no_similars_found: Gut gemacht! Keine ähnlichen Vorschläge gefunden title: Ähnliche Vorschläge complete: - send: Senden + send: Abschicken title: Vorschlag vervollständigen count: proposals_count: diff --git a/decidim-proposals/config/locales/el.yml b/decidim-proposals/config/locales/el.yml index 30951ef5d6559..501a174b9d5f7 100644 --- a/decidim-proposals/config/locales/el.yml +++ b/decidim-proposals/config/locales/el.yml @@ -175,7 +175,6 @@ el: proposal_wizard_step_1_help_text: Κείμενο βοήθειας βήματος «Δημιουργίας» του οδηγού πρότασης proposal_wizard_step_2_help_text: Κείμενο βοήθειας βήματος «Σύγκρισης» του οδηγού πρότασης proposal_wizard_step_3_help_text: Κείμενο βοήθειας βήματος «Ολοκλήρωσης» του οδηγού πρότασης - proposal_wizard_step_4_help_text: Κείμενο βοήθειας βήματος «Δημοσίευσης» του οδηγού πρότασης resources_permissions_enabled: Μπορούν να οριστούν δικαιώματα ενεργειών για κάθε πρόταση scope_id: Πεδίο εφαρμογής scopes_enabled: Τα πεδία εφαρμογής ενεργοποιήθηκαν diff --git a/decidim-proposals/config/locales/es-MX.yml b/decidim-proposals/config/locales/es-MX.yml index 11e7650d9cbce..8f36d7b6cea3f 100644 --- a/decidim-proposals/config/locales/es-MX.yml +++ b/decidim-proposals/config/locales/es-MX.yml @@ -177,7 +177,7 @@ es-MX: proposal_wizard_step_1_help_text: Texto de ayuda para el paso "Crear" del asistente de propuesta proposal_wizard_step_2_help_text: Texto de ayuda para el paso "Comparar" del asistente de propuesta proposal_wizard_step_3_help_text: Texto de ayuda para el paso "Comparar" del asistente de propuesta - proposal_wizard_step_4_help_text: 'Asistente de propuesta: texto de ayuda paso "Publicar"' + proposal_wizard_step_4_help_text: Texto de ayuda para el paso "Publicar" del asistente de propuestas resources_permissions_enabled: Se pueden establecer permisos de acciones para cada propuesta scope_id: Ámbito scopes_enabled: Ámbitos habilitados @@ -277,7 +277,7 @@ es-MX: notification_title: Su propuesta %{resource_title} ha sido aceptada. follower: email_intro: 'La propuesta "%{resource_title}" ha sido aceptada. Puedes leer la respuesta en esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo el espacio "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. email_subject: Una propuesta que estás siguiendo ha sido aceptada notification_title: La propuesta %{resource_title} ha sido aceptada. proposal_evaluating: @@ -288,7 +288,7 @@ es-MX: notification_title: Su propuesta %{resource_title} está siendo evaluada. follower: email_intro: 'La propuesta "%{resource_title}" se está evaluando actualmente. Puedes encontrar la respuesta en esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo el espacio "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. email_subject: Una propuesta que estás siguiendo está siendo evaluada notification_title: La propuesta %{resource_title} está siendo evaluada. proposal_mentioned: @@ -315,7 +315,7 @@ es-MX: notification_title: Su propuesta %{resource_title} ha sido rechazada. follower: email_intro: 'La propuesta "%{resource_title}" ha sido rechazada. Puedes leer la respuesta en esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo el espacio "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. email_subject: Una propuesta que estás siguiendo ha sido rechazada notification_title: La propuesta %{resource_title} ha sido rechazada. proposal_update_category: @@ -941,7 +941,7 @@ es-MX: step_1: Crear tu propuesta step_2: Comparar step_3: Completar - step_4: Publicar tu propuesta + step_4: Publica tu propuesta step_of: Paso %{current_step_num} de %{total_steps} title: Pasos de creación de una propuesta proposals_picker: diff --git a/decidim-proposals/config/locales/es-PY.yml b/decidim-proposals/config/locales/es-PY.yml index 24ef8b8ca9705..bb8c8cb2d4f97 100644 --- a/decidim-proposals/config/locales/es-PY.yml +++ b/decidim-proposals/config/locales/es-PY.yml @@ -177,7 +177,7 @@ es-PY: proposal_wizard_step_1_help_text: Asistente de propuesta "Crear" paso texto de ayuda proposal_wizard_step_2_help_text: Asistente de propuesta "Comparar" texto de ayuda paso proposal_wizard_step_3_help_text: Texto de ayuda al paso "Completar" de propuestas - proposal_wizard_step_4_help_text: Asistente de propuesta Texto de ayuda paso "Publicar" + proposal_wizard_step_4_help_text: Texto de ayuda para el paso "Publicar" del asistente de propuestas resources_permissions_enabled: Los permisos sobre acciones pueden establecerse para cada propuesta scope_id: Ámbito scopes_enabled: Ámbitos habilitados @@ -277,7 +277,7 @@ es-PY: notification_title: Su propuesta %{resource_title} ha sido aceptada. follower: email_intro: 'La propuesta "%{resource_title}" ha sido aceptada. Puedes leer la respuesta en esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo el espacio "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. email_subject: Una propuesta que estás siguiendo ha sido aceptada notification_title: La propuesta %{resource_title} ha sido aceptada. proposal_evaluating: @@ -288,7 +288,7 @@ es-PY: notification_title: Su propuesta %{resource_title} está siendo evaluada. follower: email_intro: 'La propuesta "%{resource_title}" se está evaluando actualmente. Puedes encontrar la respuesta en esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo el espacio "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. email_subject: Una propuesta que estás siguiendo está siendo evaluada notification_title: La propuesta %{resource_title} está siendo evaluada. proposal_mentioned: @@ -315,7 +315,7 @@ es-PY: notification_title: Su propuesta %{resource_title} ha sido rechazada. follower: email_intro: 'La propuesta "%{resource_title}" ha sido rechazada. Puedes leer la respuesta en esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo el espacio "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. email_subject: Una propuesta que estás siguiendo ha sido rechazada notification_title: La propuesta %{resource_title} ha sido rechazada. proposal_update_category: diff --git a/decidim-proposals/config/locales/es.yml b/decidim-proposals/config/locales/es.yml index 09720c0917e76..f341ce476681e 100644 --- a/decidim-proposals/config/locales/es.yml +++ b/decidim-proposals/config/locales/es.yml @@ -111,7 +111,7 @@ es: state_eq: label: Estado values: - accepted: Aceptada + accepted: Aceptadas evaluating: En evaluación published: Publicada rejected: Rechazada @@ -236,22 +236,22 @@ es: notification_title: %{requester_name} %{requester_nickname} ha sido aceptada para acceder como contribuidora del borrador colaborativo %{resource_title}. collaborative_draft_access_rejected: email_intro: 'Se ha denegado que %{requester_name} acceda como contribuidora del borrador colaborativo %{resource_title}.' - email_outro: Has recibido esta notificación porque eres una contribuidora de %{resource_title}. + email_outro: Has recibido esta notificación porque has contribuido en la propuesta "%{resource_title}". email_subject: "%{requester_name} ha sido rechazado para acceder como contribuidora del borrador colaborativo %{resource_title}." notification_title: %{requester_name} %{requester_nickname} ha sido rechazado para acceder como contribuidora del borrador colaborativo %{resource_title}. collaborative_draft_access_requested: email_intro: '%{requester_name} ha solicitado acceso como contribuidora. Puede aceptar o rechazar la solicitud de la página de borrador colaborativo de %{resource_title}.' - email_outro: Has recibido esta notificación porque eres contribuidora de %{resource_title}. + email_outro: Has recibido esta notificación porque has contribuido en la propuesta "%{resource_title}". email_subject: "%{requester_name} ha solicitado acceso para contribuir a %{resource_title}." notification_title: %{requester_name} %{requester_nickname} solicitó acceso para contribuir al borrador colaborativo %{resource_title}. Por favor, acepta o rechaza la solicitud. collaborative_draft_access_requester_accepted: email_intro: Has sido aceptada para acceder como contribuidora del borrador colaborativo %{resource_title}. - email_outro: Has recibido esta notificación porque has solicitado ser contribuidora de %{resource_title}. + email_outro: Has recibido esta notificación porque has solicitado contribuir en la propuesta "%{resource_title}". email_subject: Has sido aceptada como contribuidora de %{resource_title}. notification_title: Has sido aceptada acceder como contribuidora del borrador colaborativo %{resource_title}. collaborative_draft_access_requester_rejected: email_intro: Ha sido rechazada para acceder como contribuidora del borrador colaborativo %{resource_title}. - email_outro: Has recibido esta notificación porque has solicitado ser contribuidora de %{resource_title}. + email_outro: Has recibido esta notificación porque has solicitado contribuir en la propuesta "%{resource_title}". email_subject: Has sido rechazada como contribuidora de %{resource_title}. notification_title: Has sido rechazada como contribuidora del borrador colaborativo %{resource_title}. collaborative_draft_withdrawn: @@ -272,28 +272,28 @@ es: proposal_accepted: affected_user: email_intro: 'Tu propuesta "%{resource_title}" ha sido aceptada. Puedes leer la respuesta en esta página:' - email_outro: Has recibido esta notificación porque eres autora de "%{resource_title}". + email_outro: Has recibido esta notificación porque presentaste la propuesta "%{resource_title}". email_subject: Tu propuesta ha sido aceptada notification_title: Tu propuesta %{resource_title} ha sido aceptada. follower: email_intro: 'La propuesta "%{resource_title}" ha sido aceptada. Puedes leer la respuesta en esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo el espacio "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. email_subject: Una propuesta que estás siguiendo ha sido aceptada notification_title: La propuesta %{resource_title} ha sido aceptada. proposal_evaluating: affected_user: email_intro: 'Tu propuesta "%{resource_title}" está siendo evaluada. Puedes consultar la respuesta en esta página:' - email_outro: Has recibido esta notificación porque eres autora de "%{resource_title}". + email_outro: Has recibido esta notificación porque presentaste la propuesta "%{resource_title}". email_subject: Tu propuesta está siendo evaluada notification_title: Tu propuesta %{resource_title} está siendo evaluada. follower: email_intro: 'La propuesta "%{resource_title}" se está evaluando actualmente. Puedes encontrar la respuesta en esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo el espacio "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. email_subject: Una propuesta que estás siguiendo está siendo evaluada notification_title: La propuesta %{resource_title} está siendo evaluada. proposal_mentioned: email_intro: Tu propuesta "%{mentioned_proposal_title}" se ha mencionado en este espacio en los comentarios. - email_outro: Has recibido esta notificación porque eres autora de "%{resource_title}". + email_outro: Has recibido esta notificación porque presentaste la propuesta "%{resource_title}". email_subject: Tu propuesta "%{mentioned_proposal_title}" ha sido mencionada notification_title: Tu propuesta "%{mentioned_proposal_title}" se ha mencionado en este espacio en los comentarios. proposal_published: @@ -302,20 +302,20 @@ es: email_subject: Nueva propuesta "%{resource_title}" de %{author_nickname} notification_title: La propuesta %{resource_title} ha sido publicada por %{author_name} %{author_nickname}. proposal_published_for_space: - email_intro: La propuesta "%{resource_title}" se ha añadido en "%{participatory_space_title}", que estás siguiendo. - email_outro: Recibiste esta notificación porque estás siguiendo "%{participatory_space_title}". Puedes dejar de recibir notificaciones siguiendo el enlace anterior. + email_intro: La propuesta "%{resource_title}" se ha añadido en el espacio "%{participatory_space_title}", que estás siguiendo. + email_outro: Recibiste esta notificación porque estás siguiendo el espacio "%{participatory_space_title}". Puedes dejar de recibir notificaciones siguiendo el enlace anterior. email_subject: Nueva propuesta "%{resource_title}" añadida a %{participatory_space_title} notification_title: La propuesta %{resource_title} ha sido añadida a %{participatory_space_title} por %{author} notification_title_official: Se ha añadido la propuesta oficial %{resource_title} en %{participatory_space_title} proposal_rejected: affected_user: email_intro: 'Tu propuesta "%{resource_title}" ha sido rechazada. Puedes leer la respuesta en esta página:' - email_outro: Has recibido esta notificación porque eres autora de "%{resource_title}". + email_outro: Has recibido esta notificación porque presentaste la propuesta "%{resource_title}". email_subject: Tu propuesta ha sido rechazada notification_title: Tu propuesta %{resource_title} ha sido rechazada. follower: email_intro: 'La propuesta "%{resource_title}" ha sido rechazada. Puedes leer la respuesta en esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo el espacio "%{resource_title}". Puedes dejar de seguirlo desde el enlace anterior. email_subject: Una propuesta que estás siguiendo ha sido rechazada notification_title: La propuesta %{resource_title} ha sido rechazada. proposal_update_category: @@ -471,7 +471,7 @@ es: success: Texto participativo actualizado correctamente. proposal_answers: form: - accepted: Aceptadas + accepted: Aceptada answer_proposal: Respuesta evaluating: En evaluación not_answered: No contestada @@ -602,7 +602,7 @@ es: create: "%{user_name} asignó la propuesta %{resource_name} a una evaluadora" delete: "%{user_name} desasignó una evaluadora de la propuesta %{proposal_title}" answers: - accepted: Aceptadas + accepted: Aceptada evaluating: En evaluación not_answered: No contestada rejected: Rechazada @@ -619,7 +619,7 @@ es: filter_scope_values: all: Todas filter_state_values: - accepted: Aceptadas + accepted: Aceptada all: Todas evaluating: En evaluación not_answered: No contestada diff --git a/decidim-proposals/config/locales/eu.yml b/decidim-proposals/config/locales/eu.yml index ca62d0ebce38a..ddb32d7cc29ff 100644 --- a/decidim-proposals/config/locales/eu.yml +++ b/decidim-proposals/config/locales/eu.yml @@ -177,7 +177,7 @@ eu: proposal_wizard_step_1_help_text: Proposamen laguntzailea "Sortu" urrats laguntza testua proposal_wizard_step_2_help_text: Proposamen laguntzailea "Konparatu" urrats laguntza testua proposal_wizard_step_3_help_text: Proposamen laguntzailea "Bete" urrats laguntza testua - proposal_wizard_step_4_help_text: Proposamen laguntzailea "Argitaratu" urrats laguntza testua + proposal_wizard_step_4_help_text: Proposamen laguntzailea "Argitaratu" urrats-laguntza testua resources_permissions_enabled: Ekintza-baimenak proposamen bakoitzerako ezarri daitezke scope_id: Esparrua scopes_enabled: Esparruak gaituta diff --git a/decidim-proposals/config/locales/fr-CA.yml b/decidim-proposals/config/locales/fr-CA.yml index 6e435fcb89cee..f482dde12ccbb 100644 --- a/decidim-proposals/config/locales/fr-CA.yml +++ b/decidim-proposals/config/locales/fr-CA.yml @@ -177,7 +177,7 @@ fr-CA: proposal_wizard_step_1_help_text: Texte d'aide à l'étape "Créer" de la création de proposition proposal_wizard_step_2_help_text: Texte d'aide à l'étape "Comparer" de la création de proposition proposal_wizard_step_3_help_text: Texte d'aide à l'étape "Compléter" de la création de proposition - proposal_wizard_step_4_help_text: Texte d'aide à l'étape "Publier" de la création de proposition + proposal_wizard_step_4_help_text: Texte d'aide à l'étape "Publier" de l'assistant de proposition resources_permissions_enabled: Les autorisations d'actions peuvent être définies pour chaque proposition scope_id: Secteur scopes_enabled: Secteurs activés @@ -941,7 +941,7 @@ fr-CA: step_1: Créer une proposition step_2: Comparer aux autres propositions step_3: Compléter votre proposition - step_4: Publier votre proposition + step_4: Publier la proposition step_of: Étape %{current_step_num} sur %{total_steps} title: Étapes de création de proposition proposals_picker: diff --git a/decidim-proposals/config/locales/fr.yml b/decidim-proposals/config/locales/fr.yml index ebe8c7f83413d..304494022decd 100644 --- a/decidim-proposals/config/locales/fr.yml +++ b/decidim-proposals/config/locales/fr.yml @@ -177,7 +177,7 @@ fr: proposal_wizard_step_1_help_text: Texte d'aide à l'étape "Créer" de la création de proposition proposal_wizard_step_2_help_text: Texte d'aide à l'étape "Comparer" de la création de proposition proposal_wizard_step_3_help_text: Texte d'aide à l'étape "Compléter" de la création de proposition - proposal_wizard_step_4_help_text: Texte d'aide à l'étape "Publier" de la création de proposition + proposal_wizard_step_4_help_text: Texte d'aide à l'étape "Publier" de l'assistant de proposition resources_permissions_enabled: Les autorisations d'actions peuvent être définies pour chaque proposition scope_id: Secteur scopes_enabled: Secteurs activés @@ -941,7 +941,7 @@ fr: step_1: Créer une proposition step_2: Comparer aux autres propositions step_3: Compléter votre proposition - step_4: Publier votre proposition + step_4: Publier la proposition step_of: Étape %{current_step_num} sur %{total_steps} title: Étapes de création de proposition proposals_picker: diff --git a/decidim-proposals/config/locales/gl.yml b/decidim-proposals/config/locales/gl.yml index 35bc4e48c0ba7..56bcaf6de216a 100644 --- a/decidim-proposals/config/locales/gl.yml +++ b/decidim-proposals/config/locales/gl.yml @@ -157,7 +157,6 @@ gl: proposal_wizard_step_1_help_text: Asistente de propostas "Crear" texto de axuda paso a paso proposal_wizard_step_2_help_text: Asistente de propostas "Comparar" texto de axuda paso a paso proposal_wizard_step_3_help_text: Asistente de propostas Texto de axuda de paso "Completo" - proposal_wizard_step_4_help_text: Asistente de propostas "Publica" o texto de axuda paso a paso resources_permissions_enabled: Os permisos de acción pódense establecer para cada proposta scope_id: Ámbito scopes_enabled: Ámbitos habilitados @@ -663,7 +662,7 @@ gl: error: Houbo erros ao votar a proposta. proposals: compare: - continue: Continúe + continue: Continuar no_similars_found: Ben feito! Non se atoparon propostas similares title: Propostas similares complete: diff --git a/decidim-proposals/config/locales/he-IL.yml b/decidim-proposals/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-proposals/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-proposals/config/locales/hu.yml b/decidim-proposals/config/locales/hu.yml index 8a7892918868e..e2df13699af96 100644 --- a/decidim-proposals/config/locales/hu.yml +++ b/decidim-proposals/config/locales/hu.yml @@ -22,6 +22,7 @@ hu: category_id: Kategória decidim_scope_id: Hatáskör has_address: Van lakcíme + scope_id: Hatáskör state: Állapot suggested_hashtags: Javasolt hashtagek title: Cím @@ -147,7 +148,6 @@ hu: proposal_wizard_step_1_help_text: Javaslat varázsló "Létrehozás" gomb súgójának szövege proposal_wizard_step_2_help_text: Javaslat varázsló "Összehasonlítás" gomb súgójának szövege proposal_wizard_step_3_help_text: Javaslat varázsló "Teljesítés" gomb súgójának szövege - proposal_wizard_step_4_help_text: Javaslat varázsló "Közzététel" gomb súgójának szövege resources_permissions_enabled: Egyes javaslatokhoz műveleti engedélyeket állíthatsz be threshold_per_proposal: Küszöbérték javaslatonként vote_limit: Támogatási limit felhasználónként @@ -704,7 +704,7 @@ hu: error: Hiba történt a javaslatra való szavazás során. proposals: compare: - continue: Folytatás + continue: Tovább no_similars_found: Szép munka! Nincsen hasonló javaslat title: Hasonló javaslatok complete: diff --git a/decidim-proposals/config/locales/id-ID.yml b/decidim-proposals/config/locales/id-ID.yml index 4a8ff4422a5d0..9a9004eadfd9c 100644 --- a/decidim-proposals/config/locales/id-ID.yml +++ b/decidim-proposals/config/locales/id-ID.yml @@ -99,7 +99,6 @@ id: proposal_wizard_step_1_help_text: Panduan proposal "Buat" teks bantuan langkah proposal_wizard_step_2_help_text: Proposal wizard "Bandingkan" langkah bantuan teks proposal_wizard_step_3_help_text: Panduan proposal, selesaikan langkah bantuan teks - proposal_wizard_step_4_help_text: Panduan proposal "Publikasikan" langkah bantuan teks resources_permissions_enabled: Izin tindakan dapat diatur untuk setiap proposal threshold_per_proposal: Ambang batas per proposal vote_limit: Batas suara per pengguna diff --git a/decidim-proposals/config/locales/is-IS.yml b/decidim-proposals/config/locales/is-IS.yml index 251e4a8ea2c5f..bd211ccd5b69f 100644 --- a/decidim-proposals/config/locales/is-IS.yml +++ b/decidim-proposals/config/locales/is-IS.yml @@ -45,7 +45,6 @@ is: proposal_wizard_step_1_help_text: Tillaga töframaður "Búa til" skref hjálpartexta proposal_wizard_step_2_help_text: Tillaga töframaður "Bera saman" skref hjálpartexta proposal_wizard_step_3_help_text: Tillaga töframaður "Complete" skref hjálpartexta - proposal_wizard_step_4_help_text: Tillaga "Birta" skref hjálpartexti threshold_per_proposal: Gildi fyrir hverja tillögu step: announcement: Tilkynning @@ -206,7 +205,6 @@ is: no_similars_found: Vel gert! Engar svipaðar tillögur fundust title: Svipaðar tillögur complete: - send: Senda title: Ljúka tillögu þinni edit: back: Til baka diff --git a/decidim-proposals/config/locales/it.yml b/decidim-proposals/config/locales/it.yml index 3d3aa745bc15a..093518ab2e9c0 100644 --- a/decidim-proposals/config/locales/it.yml +++ b/decidim-proposals/config/locales/it.yml @@ -161,7 +161,6 @@ it: proposal_wizard_step_1_help_text: Procedura guidata proposta "Crea" testo guida passo proposal_wizard_step_2_help_text: Procedura guidata di proposta "Confronta" il testo della guida del passo proposal_wizard_step_3_help_text: Procedura guidata "Completa" del testo della guida guidata della proposta - proposal_wizard_step_4_help_text: Procedura guidata "Pubblica" del testo della guida per la procedura guidata resources_permissions_enabled: Le autorizzazioni delle azioni possono essere impostate per ogni proposta scope_id: Ambito scopes_enabled: Ambiti abilitati @@ -697,7 +696,7 @@ it: error: Ci sono stati errori durante la votazione della proposta. proposals: compare: - continue: Prosegui + continue: Continua no_similars_found: Molto bene! Non sono state trovate proposte simili title: Proposte simili complete: diff --git a/decidim-proposals/config/locales/lt.yml b/decidim-proposals/config/locales/lt.yml index 58f993d50a86e..683c206ef815f 100644 --- a/decidim-proposals/config/locales/lt.yml +++ b/decidim-proposals/config/locales/lt.yml @@ -183,7 +183,6 @@ lt: proposal_wizard_step_1_help_text: Pasiūlymo vedlio etapo „Sukurti“ pagalbos tekstas proposal_wizard_step_2_help_text: Pasiūlymo vedlio etapo „Palyginti“ pagalbos tekstas proposal_wizard_step_3_help_text: Pasiūlymo vedlio etapo „Užbaigti“ pagalbos tekstas - proposal_wizard_step_4_help_text: Pasiūlymo vedlio etapo „Paskelbti“ pagalbos tekstas resources_permissions_enabled: Kiekvienam pasiūlymui galima nustatyti leistinus veiksmus scope_id: Apimtis scopes_enabled: Sritys įjungtos diff --git a/decidim-proposals/config/locales/lv.yml b/decidim-proposals/config/locales/lv.yml index ec78715de33f8..a26d19e3b72c4 100644 --- a/decidim-proposals/config/locales/lv.yml +++ b/decidim-proposals/config/locales/lv.yml @@ -123,7 +123,6 @@ lv: proposal_wizard_step_1_help_text: Priekšlikumu vedņa „Izveidot” soļa palīdzības teksts proposal_wizard_step_2_help_text: Priekšlikumu vedņa "Salīdzināt" soļa palīdzības teksts proposal_wizard_step_3_help_text: Priekšlikuma vedņa „Pabeigt” soļa palīdzības teksts - proposal_wizard_step_4_help_text: Priekšlikumu vedņa „Publicēt” soļa palīdzības teksts resources_permissions_enabled: Katram priekšlikumam var iestatīt darbības atļaujas threshold_per_proposal: Slieksnis vienam priekšlikumam vote_limit: Atbalsta limits vienam dalībniekam diff --git a/decidim-proposals/config/locales/nl.yml b/decidim-proposals/config/locales/nl.yml index 2fcfcb3450e3a..a7f0681b9d3d9 100644 --- a/decidim-proposals/config/locales/nl.yml +++ b/decidim-proposals/config/locales/nl.yml @@ -153,7 +153,6 @@ nl: proposal_wizard_step_1_help_text: Helptekst "Maak" bij het maken van een nieuw voorstel proposal_wizard_step_2_help_text: Helptekst "Vergelijk" bij het maken van een nieuw voorstel proposal_wizard_step_3_help_text: Voorstel wizard "Complete" stap helptekst - proposal_wizard_step_4_help_text: Helptekst "Publiceren" bij het maken van een nieuw voorstel resources_permissions_enabled: Actiemachtigingen kunnen voor elk voorstel worden ingesteld scope_id: Scope scopes_enabled: Scopes ingeschakeld @@ -870,7 +869,7 @@ nl: step_1: Maak je voorstel step_2: Vergelijk step_3: Compleet - step_4: Publiceer uw voorstel + step_4: Publiceer je voorstel step_of: Stap %{current_step_num} van %{total_steps} title: Voorstel creatie stappen proposals_picker: diff --git a/decidim-proposals/config/locales/no.yml b/decidim-proposals/config/locales/no.yml index 9a5d907abc0b3..091c4cca225a5 100644 --- a/decidim-proposals/config/locales/no.yml +++ b/decidim-proposals/config/locales/no.yml @@ -166,7 +166,6 @@ proposal_wizard_step_1_help_text: Forslags veiviseren "Opprett" trinn-hjelpeteksten proposal_wizard_step_2_help_text: Forslags veiviseren "Sammenlign" trinn-hjelpeteksten proposal_wizard_step_3_help_text: Forslags veiviseren "Fullfør " trinn-hjelpeteksten - proposal_wizard_step_4_help_text: Forslags veiviseren "Publiser" trinn-hjelpeteksten resources_permissions_enabled: Handlings tillatelser kan settes for hvert forslag scope_id: Tema scopes_enabled: Aktiverte temaer diff --git a/decidim-proposals/config/locales/pl.yml b/decidim-proposals/config/locales/pl.yml index 8e10889d7add3..6c07b601825cd 100644 --- a/decidim-proposals/config/locales/pl.yml +++ b/decidim-proposals/config/locales/pl.yml @@ -38,12 +38,17 @@ pl: origin_component_id: Komponent z którego kopiuję propozycję proposals_import: import_proposals: Importuj propozycje + keep_answers: Zachowaj stan i odpowiedzi keep_authors: Zachowaj oryginalnych autorów valuation_assignment: admin_log: valuator_role_id: Imię weryfikatora errors: models: + participatory_text: + attributes: + document: + allowed_file_content_types: 'Nieprawidłowy typ dokumentu. Dozwolone są tylko pliki z następującymi rozszerzeniami: %{types}' proposal: attributes: add_documents: @@ -59,9 +64,11 @@ pl: attributes: base: not_official: Nieoficjalne + supported: Otrzymano wsparcie lub poparcie proposals_split: attributes: base: + not_official: Nie są oficjalne supported: Otrzymano wsparcie lub potwierdzenia models: decidim/proposals/accepted_proposal_event: Wniosek został przyjęty @@ -148,6 +155,17 @@ pl: collaborative_drafts_enabled: Zezwalaj na wspólne szkice comments_enabled: Komentarze włączone comments_max_length: Maksymalna długość komentarzy (Pozostaw 0 dla wartości domyślnej) + default_sort_order: Domyślne sortowanie propozycji + default_sort_order_help: Domyślnie oznacza, że jeśli wsparcie jest włączone, propozycje będą wyświetlane w kolejności losowej, a jeśli wsparcie jest zablokowane, zostaną posortowane według najbardziej popieranych. + default_sort_order_options: + default: Domyślne + most_commented: Najczęściej komentowane + most_endorsed: Najbardziej popierane + most_followed: Najczęściej obserwowane + most_voted: Najbardziej wspierane + random: Losowo + recent: Ostatnie + with_more_authors: Z większą liczbą autorów geocoding_enabled: Włączono geokodowanie minimum_votes_per_user: Minimalna liczba wsparć na użytkownika new_proposal_body_template: Szablon treści nowej propozycji @@ -167,7 +185,7 @@ pl: proposal_wizard_step_1_help_text: 'Tekst pomocy Kreatora - krok: "Utwórz"' proposal_wizard_step_2_help_text: 'Tekst pomocy Kreatora - krok: "Porównaj"' proposal_wizard_step_3_help_text: 'Tekst pomocy Kreatora - krok: "Dokończ"' - proposal_wizard_step_4_help_text: 'Tekst pomocy Kreatora - krok: "Publikuj"' + proposal_wizard_step_4_help_text: Tekst pomocy kroku „Opublikuj” kreatora propozycji resources_permissions_enabled: Uprawnienia działań można ustawić dla każdej propozycji scope_id: Zakres scopes_enabled: Zakresy włączone @@ -189,12 +207,16 @@ pl: answers_with_costs: Zezwalaj na koszty w odpowiedziach na propozycje automatic_hashtags: Hashtagi dodane do wszystkich propozycji comments_blocked: Komentarze zablokowane + creation_enabled: Uczestnicy mogą tworzyć propozycje + creation_enabled_readonly: To ustawienie jest wyłączone, gdy aktywujesz funkcjonalność tekstów partycypacyjnych. Aby przesłać propozycje jako tekst partycypacyjny, kliknij przycisk "Tekst partycypacyjny" i postępuj zgodnie z instrukcjami. + default_sort_order: Domyślne sortowanie propozycji default_sort_order_options: most_voted: Najwiecej wsparć endorsements_blocked: Rekomendacje zostały zablokowane endorsements_enabled: Rekomendacje włączone proposal_answering_enabled: Włączono odpowiadanie na propozycję publish_answers_immediately: Natychmiast publikuj odpowiedzi na propozycje + publish_answers_immediately_help_html: 'Pamiętaj, że jeśli odpowiesz na dowolną propozycję bez włączonej tej opcji, musisz ją opublikować ręcznie, wybierając ją i korzystając z akcji do publikacji. Aby uzyskać więcej informacji na temat tego, jak to działa, zobacz stronę z dokumentacją odpowiedzi na propozycje.' suggested_hashtags: Hashtagi sugerowane użytkownikom dodającym nowe propozycje votes_blocked: Wspieranie zablokowane votes_enabled: Wspieranie włączone @@ -271,6 +293,8 @@ pl: email_intro: Propozycja "%{resource_title}" została dodana do przestrzeni "%{participatory_space_title}", którą obserwujesz. email_outro: Otrzymałeś to powiadomienie, ponieważ obserwujesz "%{participatory_space_title}". Aby przestać otrzymywać powiadomienia kliknij w powyższy link, a następnie na stronie kliknij w przycisk obserwowania. email_subject: Nowa propozycja "%{resource_title}" została dodana do %{participatory_space_title} + notification_title: Propozycja %{resource_title} została dodana do %{participatory_space_title} przez %{author} + notification_title_official: Oficjalna propozycja %{resource_title} została dodana do %{participatory_space_title} proposal_rejected: affected_user: email_intro: 'Twoja propozycja "%{resource_title}" została odrzucona. Możesz przeczytać odpowiedź na tej stronie:' @@ -394,6 +418,7 @@ pl: many: odpowiedzi na propozycję other: odpowiedzi na propozycję title: + answers: Importuj odpowiedzi do propozycji proposals: Importuj propozycje models: proposal: @@ -751,10 +776,15 @@ pl: few: "%{count} propozycji" many: "%{count} propozycji" other: "%{count} propozycji" + dynamic_map_instructions: + description: Współrzędne zostaną zaktualizowane po kliknięciu przycisku 'podgląd'. Jednakże adres nie ulegnie zmianie. + instructions: Możesz przenieść punkt na mapie. edit: + add_documents: Dodaj dokumenty add_image: Dodaj obraz attachment_legend: "(Opcjonalnie) Dodaj załącznik" back: Wróć + edit_documents: Edytuj dokumenty edit_image: Edytuj obraz gallery_legend: "(Opcjonalnie) Dodaj obraz do karty propozycji" select_a_category: Wybierz kategorię @@ -784,9 +814,12 @@ pl: filter_by: Filtruj według unfold: Rozwiń index: + click_here: Zobacz wszystkie propozycje collaborative_drafts_list: Wspólne szkice new_proposal: Nowa propozycja + see_all: Zobacz wszystkie propozycje see_all_withdrawn: Zobacz wszystkie wycofane propozycje + text_banner: Oglądasz listę propozycji wycofanych przez ich autorów. %{go_back_link}. view_proposal: Zobacz propozycję linked_proposals: proposal_votes: @@ -796,6 +829,7 @@ pl: other: wsparcia new: send: Dalej + title: Utwórz swoją propozycję orders: label: 'Sortuj propozycje według:' most_commented: Najczęściej komentowane @@ -806,6 +840,8 @@ pl: recent: Najnowsze with_more_authors: Z większą liczbą autorów participatory_texts: + index: + document_index: Indeks dokumentu view_index: see_index: Zobacz indeks placeholder: @@ -944,3 +980,4 @@ pl: statistics: proposals_accepted: Przyjęte propozycje proposals_count: Propozycje + supports_count: Głosy poparcia diff --git a/decidim-proposals/config/locales/pt-BR.yml b/decidim-proposals/config/locales/pt-BR.yml index d5fed22024ab3..8379f2d808e07 100644 --- a/decidim-proposals/config/locales/pt-BR.yml +++ b/decidim-proposals/config/locales/pt-BR.yml @@ -156,7 +156,6 @@ pt-BR: proposal_wizard_step_1_help_text: Assistente de propostas "Criar" passo ajuda texto proposal_wizard_step_2_help_text: Assistente de proposta "Comparar" passo ajuda texto proposal_wizard_step_3_help_text: Texto de ajuda da etapa "Completa" do assistente de proposta - proposal_wizard_step_4_help_text: Assistente de propostas "Publicar" passo ajuda texto resources_permissions_enabled: Permissões de ações podem ser definidas para cada proposta scope_id: Escopo scopes_enabled: Escopos habilitados diff --git a/decidim-proposals/config/locales/pt.yml b/decidim-proposals/config/locales/pt.yml index 57c86f7c206ee..ab4cf2b770fd3 100644 --- a/decidim-proposals/config/locales/pt.yml +++ b/decidim-proposals/config/locales/pt.yml @@ -171,7 +171,6 @@ pt: proposal_wizard_step_1_help_text: Texto de ajuda do passo "Criar" do Assistente de Propostas proposal_wizard_step_2_help_text: Texto de ajuda do passo "Comparar" do Assistente de Propostas proposal_wizard_step_3_help_text: Texto de ajuda do passo "Concluir" do Assistente de Propostas - proposal_wizard_step_4_help_text: Texto de ajuda do passo "Publicar" do Assistente de Propostas resources_permissions_enabled: As permissões de ações podem ser definidas para cada proposta scope_id: Âmbito scopes_enabled: Âmbitos activados diff --git a/decidim-proposals/config/locales/ru.yml b/decidim-proposals/config/locales/ru.yml index 8e000504b41db..d1b6e981b6f30 100644 --- a/decidim-proposals/config/locales/ru.yml +++ b/decidim-proposals/config/locales/ru.yml @@ -8,6 +8,7 @@ ru: body: Основной текст category_id: Категория has_address: Имеет адрес + scope_id: Охват state: Cостояние title: Заголовок user_group_id: Создать предложение в качестве @@ -82,7 +83,6 @@ ru: proposal_wizard_step_1_help_text: Справка мастера предложений о шаге "Создать" proposal_wizard_step_2_help_text: Справка мастера предложений о шаге "Сравнить" proposal_wizard_step_3_help_text: Справка мастера предложений о шаге "Завершить" - proposal_wizard_step_4_help_text: Справка мастера предложений о шаге "Обнародовать" resources_permissions_enabled: Для каждого предложения можно задать те или иные разрешения на действия threshold_per_proposal: Порог для каждого предложения vote_limit: Предельное количество голосов для одного участника @@ -270,7 +270,6 @@ ru: no_similars_found: Хорошая работа! Подобных предложений не найдено title: Похожие предложения complete: - send: Отправить title: Завершите свое предложение edit: attachment_legend: "(Необязательно) Добавить вложение" @@ -284,6 +283,7 @@ ru: send: Предпросмотр title: Редактировать черновик предложения filters: + all: Все category: Категория origin: Источник related_to: Связано с diff --git a/decidim-proposals/config/locales/sk.yml b/decidim-proposals/config/locales/sk.yml index e024423eddc52..865f47da337b9 100644 --- a/decidim-proposals/config/locales/sk.yml +++ b/decidim-proposals/config/locales/sk.yml @@ -130,7 +130,6 @@ sk: proposal_wizard_step_1_help_text: Pomocný text Sprievodcu "Vytvoriť" návrh proposal_wizard_step_2_help_text: Pomocný text Sprievodcu "Porovnať" návrhu proposal_wizard_step_3_help_text: Pomocný text Sprievodcu "Dokončiť" návrh - proposal_wizard_step_4_help_text: Pomocný text Sprievodcu "Publikovať" návrh resources_permissions_enabled: Pre každý návrh možno nastaviť povolenia akcie threshold_per_proposal: Maximálny limit na návrh vote_limit: Počet hlasov na užívateľa diff --git a/decidim-proposals/config/locales/sv.yml b/decidim-proposals/config/locales/sv.yml index 30a8e75da7a4b..448ebdc5438da 100644 --- a/decidim-proposals/config/locales/sv.yml +++ b/decidim-proposals/config/locales/sv.yml @@ -171,7 +171,6 @@ sv: proposal_wizard_step_1_help_text: Hjälptext till steget "Skapa" i förslagsguiden proposal_wizard_step_2_help_text: Hjälptext till steget "Jämför" i förslagsguiden proposal_wizard_step_3_help_text: Hjälptext till steget "Komplettera" i förslagsguiden - proposal_wizard_step_4_help_text: Förslagsguidens hjälptext för steg "Publicera" resources_permissions_enabled: Åtgärdsbehörigheter kan ställas in för varje förslag scope_id: Omfång scopes_enabled: Omfång aktiverade diff --git a/decidim-proposals/config/locales/tr-TR.yml b/decidim-proposals/config/locales/tr-TR.yml index d7df8b6d4eeaa..fac609ae32a2c 100644 --- a/decidim-proposals/config/locales/tr-TR.yml +++ b/decidim-proposals/config/locales/tr-TR.yml @@ -143,7 +143,6 @@ tr: proposal_wizard_step_1_help_text: Teklif sihirbazı "Oluştur" adımı yardım metni proposal_wizard_step_2_help_text: Teklif sihirbazı "Karşılaştır" adımı yardım metni proposal_wizard_step_3_help_text: Teklif sihirbazı "Tamamlandı" adımı yardım metni - proposal_wizard_step_4_help_text: Teklif sihirbazı "Yayınla" adımı yardım metni resources_permissions_enabled: Her teklif için işlem izinleri ayarlanabilir scope_id: Kapsam scopes_enabled: Kapsamlar etkinleştirildi @@ -818,7 +817,7 @@ tr: wizard_aside: back: Geri back_from_step_1: Teklifte geri dön - back_from_step_2: Tekliflere geri dön + back_from_step_2: Teklifte geri dön back_from_step_3: Teklifleri karşılaştırmaya geri dön back_from_step_4: Taslağı düzenlemeye dön info: teklif. diff --git a/decidim-proposals/config/locales/uk.yml b/decidim-proposals/config/locales/uk.yml index 7dec909722c6f..5c902a31d0367 100644 --- a/decidim-proposals/config/locales/uk.yml +++ b/decidim-proposals/config/locales/uk.yml @@ -8,6 +8,7 @@ uk: body: Основний текст category_id: Категорія has_address: Має адресу + scope_id: Обсяг state: Стан title: Назва user_group_id: Створити пропозицію як @@ -82,7 +83,6 @@ uk: proposal_wizard_step_1_help_text: Довідка майстра пропозицій щодо кроку "Створити" proposal_wizard_step_2_help_text: Довідка майстра пропозицій щодо кроку "Порівняти" proposal_wizard_step_3_help_text: Довідка майстра пропозицій щодо кроку "Завершити" - proposal_wizard_step_4_help_text: Довідка майстра пропозицій щодо кроку "Оприлюднити" resources_permissions_enabled: Для кожної пропозиції можна встановити ті чи інші дозволи на дії threshold_per_proposal: Поріг на кожну пропозицію vote_limit: Гранична кількість голосів від одного учасника @@ -270,7 +270,6 @@ uk: no_similars_found: Гарна робота! Не знайдено схожий пропозицій title: Подібні пропозиції complete: - send: Надіслати title: Завершіть свою пропозицію edit: attachment_legend: "(Необов'язково) Додати вкладений файл" @@ -284,6 +283,7 @@ uk: send: Попередній перегляд title: Редагувати чернетку пропозиції filters: + all: Усі category: Категорія origin: Джерело related_to: Пов'язане з diff --git a/decidim-proposals/config/locales/zh-CN.yml b/decidim-proposals/config/locales/zh-CN.yml index 39c125b08106b..1105e7d9e4c2c 100644 --- a/decidim-proposals/config/locales/zh-CN.yml +++ b/decidim-proposals/config/locales/zh-CN.yml @@ -136,7 +136,6 @@ zh-CN: proposal_wizard_step_1_help_text: 建议向导“创建”步骤帮助文本 proposal_wizard_step_2_help_text: 建议向导“Compare”步骤帮助文本 proposal_wizard_step_3_help_text: 建议向导“完成”步骤帮助文本 - proposal_wizard_step_4_help_text: 建议向导"发布"步骤帮助文本 resources_permissions_enabled: 每个提案都可以设置动作权限 scope_id: 范围 scopes_enabled: 范围已启用 diff --git a/decidim-proposals/config/locales/zh-TW.yml b/decidim-proposals/config/locales/zh-TW.yml index 7ea2b862ef8b5..e96d58b33dec8 100644 --- a/decidim-proposals/config/locales/zh-TW.yml +++ b/decidim-proposals/config/locales/zh-TW.yml @@ -171,7 +171,6 @@ zh-TW: proposal_wizard_step_1_help_text: 提案向導「創建」步驟說明文字 proposal_wizard_step_2_help_text: 提案向導「比較」步驟說明文字 proposal_wizard_step_3_help_text: 提案向導「完成」步驟說明文字 - proposal_wizard_step_4_help_text: 提案向導「發佈」步驟說明文字 resources_permissions_enabled: 每個提案都可以設定行動權限 scope_id: 範圍 scopes_enabled: 啟用範圍 diff --git a/decidim-proposals/db/migrate/20240404202756_add_valuation_assignments_count_to_decidim_proposals_proposals.rb b/decidim-proposals/db/migrate/20240404202756_add_valuation_assignments_count_to_decidim_proposals_proposals.rb new file mode 100644 index 0000000000000..89c51425156da --- /dev/null +++ b/decidim-proposals/db/migrate/20240404202756_add_valuation_assignments_count_to_decidim_proposals_proposals.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class AddValuationAssignmentsCountToDecidimProposalsProposals < ActiveRecord::Migration[6.1] + def change + add_column :decidim_proposals_proposals, :valuation_assignments_count, :integer, default: 0 + + reversible do |dir| + dir.up do + Decidim::Proposals::Proposal.reset_column_information + Decidim::Proposals::Proposal.find_each do |record| + Decidim::Proposals::Proposal.reset_counters(record.id, :valuation_assignments) + end + end + end + end +end diff --git a/decidim-proposals/lib/decidim/proposals/test/factories.rb b/decidim-proposals/lib/decidim/proposals/test/factories.rb index 50d9f6b07de1b..22d157105777f 100644 --- a/decidim-proposals/lib/decidim/proposals/test/factories.rb +++ b/decidim-proposals/lib/decidim/proposals/test/factories.rb @@ -6,10 +6,12 @@ FactoryBot.define do factory :proposal_component, parent: :component do - name { Decidim::Components::Namer.new(participatory_space.organization.available_locales, :proposals).i18n_name } + transient do + skip_injection { false } + end + name { generate_component_name(participatory_space.organization.available_locales, :proposals) } manifest_name { :proposals } - participatory_space { create(:participatory_process, :with_steps, organization: organization) } - + participatory_space { create(:participatory_process, :with_steps, organization: organization, skip_injection: skip_injection) } trait :with_endorsements_enabled do step_settings do { @@ -250,28 +252,16 @@ skip_injection { false } end - title do - if skip_injection - Decidim::Faker::Localized.localized { generate(:title) } - else - Decidim::Faker::Localized.localized { " #{generate(:title)}" } - end - end - body do - if skip_injection - Decidim::Faker::Localized.localized { Faker::Lorem.sentences(number: 3).join("\n") } - else - Decidim::Faker::Localized.localized { " #{Faker::Lorem.sentences(number: 3).join("\n")}" } - end - end - component { create(:proposal_component) } + title { generate_localized_title(:proposal_title, skip_injection: skip_injection) } + body { generate_localized_description(:proposal_body, skip_injection: skip_injection) } + component { create(:proposal_component, skip_injection: skip_injection) } published_at { Time.current } address { "#{Faker::Address.street_name}, #{Faker::Address.city}" } latitude { Faker::Address.latitude } longitude { Faker::Address.longitude } cost { 20_000 } - cost_report { { en: "My cost report" } } - execution_period { { en: "My execution period" } } + cost_report { generate_localized_title(:proposal_cost_report, skip_injection: skip_injection) } + execution_period { generate_localized_title(:proposal_execution_period, skip_injection: skip_injection) } after(:build) do |proposal, evaluator| proposal.title = if evaluator.title.is_a?(String) @@ -289,7 +279,7 @@ proposal.body = Decidim::ContentProcessor.parse_with_processor(:hashtag, proposal.body, current_organization: proposal.organization).rewrite if proposal.component - users = evaluator.users || [create(:user, :confirmed, organization: proposal.component.participatory_space.organization)] + users = evaluator.users || [create(:user, :confirmed, organization: proposal.component.participatory_space.organization, skip_injection: evaluator.skip_injection)] users.each_with_index do |user, idx| user_group = evaluator.user_groups[idx] proposal.coauthorships.build(author: user, user_group: user_group) @@ -306,18 +296,18 @@ end trait :participant_author do - after :build do |proposal| + after :build do |proposal, evaluator| proposal.coauthorships.clear - user = build(:user, organization: proposal.component.participatory_space.organization) + user = build(:user, organization: proposal.component.participatory_space.organization, skip_injection: evaluator.skip_injection) proposal.coauthorships.build(author: user) end end trait :user_group_author do - after :build do |proposal| + after :build do |proposal, evaluator| proposal.coauthorships.clear - user = create(:user, organization: proposal.component.participatory_space.organization) - user_group = create(:user_group, :verified, organization: user.organization, users: [user]) + user = create(:user, organization: proposal.component.participatory_space.organization, skip_injection: evaluator.skip_injection) + user_group = create(:user_group, :verified, organization: user.organization, users: [user], skip_injection: evaluator.skip_injection) proposal.coauthorships.build(author: user, user_group: user_group) end end @@ -330,10 +320,10 @@ end trait :official_meeting do - after :build do |proposal| + after :build do |proposal, evaluator| proposal.coauthorships.clear - component = build(:meeting_component, participatory_space: proposal.component.participatory_space) - proposal.coauthorships.build(author: build(:meeting, component: component)) + component = build(:meeting_component, participatory_space: proposal.component.participatory_space, skip_injection: evaluator.skip_injection) + proposal.coauthorships.build(author: build(:meeting, component: component, skip_injection: evaluator.skip_injection)) end end @@ -382,78 +372,89 @@ end trait :hidden do - after :create do |proposal| - create(:moderation, hidden_at: Time.current, reportable: proposal) + after :create do |proposal, evaluator| + create(:moderation, hidden_at: Time.current, reportable: proposal, skip_injection: evaluator.skip_injection) end end trait :with_votes do - after :create do |proposal| - create_list(:proposal_vote, 5, proposal: proposal) + after :create do |proposal, evaluator| + create_list(:proposal_vote, 5, proposal: proposal, skip_injection: evaluator.skip_injection) end end trait :with_endorsements do - after :create do |proposal| + after :create do |proposal, evaluator| 5.times.collect do - create(:endorsement, resource: proposal, author: build(:user, organization: proposal.participatory_space.organization)) + create(:endorsement, resource: proposal, skip_injection: evaluator.skip_injection, + author: build(:user, organization: proposal.participatory_space.organization, skip_injection: evaluator.skip_injection)) end end end trait :with_amendments do - after :create do |proposal| - create_list(:proposal_amendment, 5, amendable: proposal) + after :create do |proposal, evaluator| + create_list(:proposal_amendment, 5, amendable: proposal, skip_injection: evaluator.skip_injection) end end trait :with_photo do - after :create do |proposal| - proposal.attachments << create(:attachment, :with_image, attached_to: proposal) + after :create do |proposal, evaluator| + proposal.attachments << create(:attachment, :with_image, attached_to: proposal, skip_injection: evaluator.skip_injection) end end trait :with_document do - after :create do |proposal| - proposal.attachments << create(:attachment, :with_pdf, attached_to: proposal) + after :create do |proposal, evaluator| + proposal.attachments << create(:attachment, :with_pdf, attached_to: proposal, skip_injection: evaluator.skip_injection) end end end factory :proposal_vote, class: "Decidim::Proposals::ProposalVote" do - proposal { build(:proposal) } - author { build(:user, organization: proposal.organization) } + transient do + skip_injection { false } + end + proposal { build(:proposal, skip_injection: skip_injection) } + author { build(:user, organization: proposal.organization, skip_injection: skip_injection) } end factory :proposal_amendment, class: "Decidim::Amendment" do - amendable { build(:proposal) } - emendation { build(:proposal, component: amendable.component) } - amender { build(:user, organization: amendable.component.participatory_space.organization) } + transient do + skip_injection { false } + end + amendable { build(:proposal, skip_injection: skip_injection) } + emendation { build(:proposal, component: amendable.component, skip_injection: skip_injection) } + amender { build(:user, organization: amendable.component.participatory_space.organization, skip_injection: skip_injection) } state { Decidim::Amendment::STATES.sample } end factory :proposal_note, class: "Decidim::Proposals::ProposalNote" do + transient do + skip_injection { false } + end body { Faker::Lorem.sentences(number: 3).join("\n") } - proposal { build(:proposal) } - author { build(:user, organization: proposal.organization) } + proposal { build(:proposal, skip_injection: skip_injection) } + author { build(:user, organization: proposal.organization, skip_injection: skip_injection) } end factory :collaborative_draft, class: "Decidim::Proposals::CollaborativeDraft" do transient do users { nil } + skip_injection { false } # user_groups correspondence to users is by sorting order user_groups { [] } end - title { " #{generate(:title)}" } - body { "\n#{Faker::Lorem.sentences(number: 3).join("\n")}" } - component { create(:proposal_component) } + title { generate_localized_title(:collaborative_draft_title, skip_injection: skip_injection)["en"] } + body { generate_localized_description(:collaborative_draft_body, skip_injection: skip_injection)["en"] } + component { create(:proposal_component, skip_injection: skip_injection) } address { "#{Faker::Address.street_name}, #{Faker::Address.city}" } state { "open" } after(:build) do |collaborative_draft, evaluator| if collaborative_draft.component - users = evaluator.users || [create(:user, organization: collaborative_draft.component.participatory_space.organization)] + users = evaluator.users || [create(:user, organization: collaborative_draft.component.participatory_space.organization, skip_injection: evaluator.skip_injection)] users.each_with_index do |user, idx| user_group = evaluator.user_groups[idx] collaborative_draft.coauthorships.build(author: user, user_group: user_group) @@ -476,17 +477,23 @@ end factory :participatory_text, class: "Decidim::Proposals::ParticipatoryText" do - title { { en: " #{generate(:title)}" } } - description { { en: "\n#{Faker::Lorem.sentences(number: 3).join("\n")}" } } - component { create(:proposal_component) } + transient do + skip_injection { false } + end + title { generate_localized_title(:participatory_text_title, skip_injection: skip_injection) } + description { generate_localized_description(:participatory_text_description, skip_injection: skip_injection) } + component { create(:proposal_component, skip_injection: skip_injection) } end factory :valuation_assignment, class: "Decidim::Proposals::ValuationAssignment" do + transient do + skip_injection { false } + end proposal valuator_role do space = proposal.component.participatory_space organization = space.organization - build :participatory_process_user_role, role: :valuator, user: build(:user, organization: organization) + build :participatory_process_user_role, role: :valuator, skip_injection: skip_injection, user: build(:user, organization: organization, skip_injection: skip_injection) end end end diff --git a/decidim-proposals/lib/decidim/proposals/valuatable.rb b/decidim-proposals/lib/decidim/proposals/valuatable.rb index 7471e3af2bf64..d1143621e4de4 100644 --- a/decidim-proposals/lib/decidim/proposals/valuatable.rb +++ b/decidim-proposals/lib/decidim/proposals/valuatable.rb @@ -8,7 +8,8 @@ module Valuatable include Decidim::Comments::Commentable included do - has_many :valuation_assignments, foreign_key: "decidim_proposal_id", dependent: :destroy + has_many :valuation_assignments, foreign_key: "decidim_proposal_id", dependent: :destroy, + counter_cache: :valuation_assignments_count, class_name: "Decidim::Proposals::ValuationAssignment" def valuators valuator_role_ids = valuation_assignments.where(proposal: self).pluck(:valuator_role_id) diff --git a/decidim-proposals/lib/decidim/proposals/version.rb b/decidim-proposals/lib/decidim/proposals/version.rb index 44009dfd7a2f8..6ea553fee5dcd 100644 --- a/decidim-proposals/lib/decidim/proposals/version.rb +++ b/decidim-proposals/lib/decidim/proposals/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds decidim-proposals version. module Proposals def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-proposals/spec/events/decidim/proposals/admin/update_proposal_category_event_spec.rb b/decidim-proposals/spec/events/decidim/proposals/admin/update_proposal_category_event_spec.rb index 9a6d73ea84226..6c6e8215100e1 100644 --- a/decidim-proposals/spec/events/decidim/proposals/admin/update_proposal_category_event_spec.rb +++ b/decidim-proposals/spec/events/decidim/proposals/admin/update_proposal_category_event_spec.rb @@ -3,12 +3,12 @@ require "spec_helper" describe Decidim::Proposals::Admin::UpdateProposalCategoryEvent do - let(:resource) { create :proposal, title: "It's my super proposal" } + let(:resource) { create :proposal, title: "It is my super proposal" } let(:event_name) { "decidim.events.proposals.proposal_update_category" } let(:email_subject) { "The #{translated(resource.title)} proposal category has been updated" } - let(:email_intro) { "An admin has updated the category of your proposal \"#{decidim_html_escape(translated(resource.title))}\", check it out in this page:" } + let(:email_intro) { "An admin has updated the category of your proposal \"#{resource_title}\", check it out in this page:" } let(:email_outro) { "You have received this notification because you are the author of the proposal." } - let(:notification_title) { "The #{decidim_html_escape(translated(resource.title))} proposal category has been updated by an admin." } + let(:notification_title) { "The #{resource_title} proposal category has been updated by an admin." } include_context "when a simple event" it_behaves_like "a simple event" diff --git a/decidim-proposals/spec/events/decidim/proposals/admin/update_proposal_scope_event_spec.rb b/decidim-proposals/spec/events/decidim/proposals/admin/update_proposal_scope_event_spec.rb index 82b6750c7a793..1249dfa9ec658 100644 --- a/decidim-proposals/spec/events/decidim/proposals/admin/update_proposal_scope_event_spec.rb +++ b/decidim-proposals/spec/events/decidim/proposals/admin/update_proposal_scope_event_spec.rb @@ -3,13 +3,12 @@ require "spec_helper" describe Decidim::Proposals::Admin::UpdateProposalScopeEvent do - let(:resource) { create :proposal, title: "It's my super proposal" } - let(:resource_title) { translated(resource.title) } + let(:resource) { create :proposal, title: "It is my super proposal" } let(:event_name) { "decidim.events.proposals.proposal_update_scope" } - let(:email_subject) { "The #{decidim_sanitize(resource_title)} proposal scope has been updated" } - let(:email_intro) { "An admin has updated the scope of your proposal \"#{decidim_html_escape(resource_title)}\", check it out in this page:" } + let(:email_subject) { "The #{resource_title} proposal scope has been updated" } + let(:email_intro) { "An admin has updated the scope of your proposal \"#{resource_title}\", check it out in this page:" } let(:email_outro) { "You have received this notification because you are the author of the proposal." } - let(:notification_title) { "The #{decidim_html_escape(resource_title)} proposal scope has been updated by an admin." } + let(:notification_title) { "The #{resource_title} proposal scope has been updated by an admin." } include_context "when a simple event" it_behaves_like "a simple event" diff --git a/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_access_accepted_event_spec.rb b/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_access_accepted_event_spec.rb index 1cc2e492aa27a..ec4692765ea34 100644 --- a/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_access_accepted_event_spec.rb +++ b/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_access_accepted_event_spec.rb @@ -6,7 +6,7 @@ include_context "when a simple event" let(:event_name) { "decidim.events.proposals.collaborative_draft_access_accepted" } - let(:resource) { create :collaborative_draft, title: "It's my collaborative draft" } + let(:resource) { create :collaborative_draft, title: "It is my collaborative draft" } let(:resource_path) { Decidim::ResourceLocatorPresenter.new(resource).path } let(:resource_title) { resource.title } let(:author) { resource.authors.first } @@ -25,9 +25,9 @@ context "when the notification is for coauthor users" do let(:email_subject) { "#{requester_name} has been accepted to access as a contributor of the #{resource_title}." } - let(:email_intro) { %(#{requester_name} has been accepted to access as a contributor of the #{decidim_html_escape(resource_title)} collaborative draft.) } - let(:email_outro) { %(You have received this notification because you are a collaborator of #{decidim_html_escape(resource_title)}.) } - let(:notification_title) { %(#{requester_name} #{requester_nickname} has been accepted to access as a contributor of the #{decidim_html_escape(resource_title)} collaborative draft.) } + let(:email_intro) { %(#{requester_name} has been accepted to access as a contributor of the #{resource_title} collaborative draft.) } + let(:email_outro) { %(You have received this notification because you are a collaborator of #{resource_title}.) } + let(:notification_title) { %(#{requester_name} #{requester_nickname} has been accepted to access as a contributor of the #{resource_title} collaborative draft.) } it_behaves_like "a simple event" it_behaves_like "a simple event email" @@ -37,9 +37,9 @@ context "when the notification is for the requester" do let(:event_name) { "decidim.events.proposals.collaborative_draft_access_requester_accepted" } let(:email_subject) { "You have been accepted as a contributor of #{resource_title}." } - let(:email_intro) { %(You have been accepted to access as a contributor of the #{decidim_html_escape(resource_title)} collaborative draft.) } - let(:email_outro) { %(You have received this notification because you requested to become a collaborator of #{decidim_html_escape(resource_title)}.) } - let(:notification_title) { %(You have been accepted to access as a contributor of the #{decidim_html_escape(resource_title)} collaborative draft.) } + let(:email_intro) { %(You have been accepted to access as a contributor of the #{resource_title} collaborative draft.) } + let(:email_outro) { %(You have received this notification because you requested to become a collaborator of #{resource_title}.) } + let(:notification_title) { %(You have been accepted to access as a contributor of the #{resource_title} collaborative draft.) } it_behaves_like "a simple event" it_behaves_like "a simple event email" diff --git a/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_access_rejected_event_spec.rb b/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_access_rejected_event_spec.rb index 3eaed1d779adb..ded9da11f5795 100644 --- a/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_access_rejected_event_spec.rb +++ b/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_access_rejected_event_spec.rb @@ -6,9 +6,8 @@ include_context "when a simple event" let(:event_name) { "decidim.events.proposals.collaborative_draft_access_rejected" } - let(:resource) { create :collaborative_draft, title: "It's my collaborative draft" } + let(:resource) { create :collaborative_draft, title: "It is my collaborative draft" } let(:resource_path) { Decidim::ResourceLocatorPresenter.new(resource).path } - let(:resource_title) { decidim_html_escape(resource.title) } let(:author) { resource.authors.first } let(:author_id) { author.id } let(:author_presenter) { Decidim::UserPresenter.new(author) } @@ -24,7 +23,7 @@ let(:extra) { { requester_id: requester_id } } context "when the notification is for coauthor users" do - let(:email_subject) { "#{requester_name} has been rejected to access as a contributor of the #{translated(resource.title)} collaborative draft." } + let(:email_subject) { "#{requester_name} has been rejected to access as a contributor of the #{resource_title} collaborative draft." } let(:email_intro) { %(#{requester_name} has been rejected to access as a contributor of the #{resource_title} collaborative draft.) } let(:email_outro) { %(You have received this notification because you are a collaborator of #{resource_title}.) } let(:notification_title) { %(#{requester_name} #{requester_nickname} has been rejected to access as a contributor of the #{resource_title} collaborative draft.) } @@ -36,7 +35,7 @@ context "when the notification is for the requester" do let(:event_name) { "decidim.events.proposals.collaborative_draft_access_requester_rejected" } - let(:email_subject) { "You have been rejected as a contributor of #{translated(resource.title)}." } + let(:email_subject) { "You have been rejected as a contributor of #{resource_title}." } let(:email_intro) { %(You have been rejected to access as a contributor of the #{resource_title} collaborative draft.) } let(:email_outro) { %(You have received this notification because you requested to become a collaborator of #{resource_title}.) } let(:notification_title) { %(You have been rejected to access as a contributor of the #{resource_title} collaborative draft.) } diff --git a/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_access_requested_event_spec.rb b/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_access_requested_event_spec.rb index 2227a8c374733..9c4cf31899f19 100644 --- a/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_access_requested_event_spec.rb +++ b/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_access_requested_event_spec.rb @@ -6,7 +6,7 @@ include_context "when a simple event" let(:event_name) { "decidim.events.proposals.collaborative_draft_access_requested" } - let(:resource) { create :collaborative_draft, title: "It's my collaborative draft" } + let(:resource) { create :collaborative_draft, title: "It is my collaborative draft" } let(:resource_path) { Decidim::ResourceLocatorPresenter.new(resource).path } let(:resource_title) { resource.title } let(:author) { resource.authors.first } @@ -24,9 +24,9 @@ let(:extra) { { requester_id: requester_id } } context "when the notification is for coauthor users" do - let(:notification_title) { %(#{requester_name} #{requester_nickname} requested access to contribute to the #{decidim_html_escape(resource_title)} collaborative draft. Please accept or reject the request.) } - let(:email_outro) { %(You have received this notification because you are a collaborator of #{decidim_html_escape(resource_title)}.) } - let(:email_intro) { %(#{requester_name} requested access as a contributor. You can accept or reject the request from the #{decidim_html_escape(resource_title)} collaborative draft page.) } + let(:notification_title) { %(#{requester_name} #{requester_nickname} requested access to contribute to the #{resource_title} collaborative draft. Please accept or reject the request.) } + let(:email_outro) { %(You have received this notification because you are a collaborator of #{resource_title}.) } + let(:email_intro) { %(#{requester_name} requested access as a contributor. You can accept or reject the request from the #{resource_title} collaborative draft page.) } let(:email_subject) { "#{requester_name} requested access to contribute to #{resource_title}." } it_behaves_like "a simple event" diff --git a/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_withdrawn_event_spec.rb b/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_withdrawn_event_spec.rb index 5cf781a1442df..f20d879392abe 100644 --- a/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_withdrawn_event_spec.rb +++ b/decidim-proposals/spec/events/decidim/proposals/collaborative_draft_withdrawn_event_spec.rb @@ -6,9 +6,8 @@ include_context "when a simple event" let(:event_name) { "decidim.events.proposals.collaborative_draft_withdrawn" } - let(:resource) { create :collaborative_draft, title: "It's my collaborative draft" } + let(:resource) { create :collaborative_draft, title: "It is my collaborative draft" } let(:resource_path) { Decidim::ResourceLocatorPresenter.new(resource).path } - let(:resource_title) { decidim_html_escape(resource.title) } let(:author) { resource.authors.first } let(:author_id) { author.id } let(:author_presenter) { Decidim::UserPresenter.new(author) } @@ -22,7 +21,7 @@ let(:notification_title) { %(#{author_name} #{author_nickname} withdrawn the #{resource_title} collaborative draft.) } let(:email_outro) { %(You have received this notification because you are a collaborator of #{resource_title}.) } let(:email_intro) { %(#{author_name} #{author_nickname} withdrawn the #{resource_title} collaborative draft.) } - let(:email_subject) { "#{author_name} #{author_nickname} withdrawn the #{decidim_sanitize(resource_title)} collaborative draft." } + let(:email_subject) { "#{author_name} #{author_nickname} withdrawn the #{resource_title} collaborative draft." } it_behaves_like "a simple event" it_behaves_like "a simple event email" diff --git a/decidim-proposals/spec/events/decidim/proposals/creation_enabled_event_spec.rb b/decidim-proposals/spec/events/decidim/proposals/creation_enabled_event_spec.rb index 3218dbaca7157..e6b2f98ae9b51 100644 --- a/decidim-proposals/spec/events/decidim/proposals/creation_enabled_event_spec.rb +++ b/decidim-proposals/spec/events/decidim/proposals/creation_enabled_event_spec.rb @@ -11,12 +11,11 @@ module Proposals let(:event_name) { "decidim.events.proposals.creation_enabled" } let(:resource) { create(:proposal_component) } - let(:participatory_space) { resource.participatory_space } let(:resource_path) { main_component_path(resource) } - let(:email_subject) { "Proposals now available in #{participatory_space.title["en"]}" } + let(:email_subject) { "Proposals now available in #{participatory_space_title}" } let(:email_intro) { "You can now create new proposals in #{participatory_space_title}! Start participating in this page:" } - let(:email_outro) { "You have received this notification because you are following #{participatory_space.title["en"]}. You can stop receiving notifications following the previous link." } - let(:notification_title) { "You can now put forward new proposals in #{participatory_space.title["en"]}" } + let(:email_outro) { "You have received this notification because you are following #{participatory_space_title}. You can stop receiving notifications following the previous link." } + let(:notification_title) { "You can now put forward new proposals in #{participatory_space_title}" } it_behaves_like "a simple event" it_behaves_like "a simple event email" diff --git a/decidim-proposals/spec/events/decidim/proposals/endorsing_enabled_event_spec.rb b/decidim-proposals/spec/events/decidim/proposals/endorsing_enabled_event_spec.rb index eef00726375bf..9465e4fb279e6 100644 --- a/decidim-proposals/spec/events/decidim/proposals/endorsing_enabled_event_spec.rb +++ b/decidim-proposals/spec/events/decidim/proposals/endorsing_enabled_event_spec.rb @@ -13,10 +13,10 @@ module Proposals let(:resource) { create(:proposal_component) } let(:participatory_space) { resource.participatory_space } let(:resource_path) { main_component_path(resource) } - let(:email_subject) { "Proposals endorsing has started for #{participatory_space.title["en"]}" } + let(:email_subject) { "Proposals endorsing has started for #{participatory_space_title}" } let(:email_intro) { "You can endorse proposals in #{participatory_space_title}! Start participating in this page:" } - let(:email_outro) { "You have received this notification because you are following #{participatory_space.title["en"]}. You can stop receiving notifications following the previous link." } - let(:notification_title) { "You can now start endorsing proposals in #{participatory_space.title["en"]}" } + let(:email_outro) { "You have received this notification because you are following #{participatory_space_title}. You can stop receiving notifications following the previous link." } + let(:notification_title) { "You can now start endorsing proposals in #{participatory_space_title}" } it_behaves_like "a simple event" it_behaves_like "a simple event email" diff --git a/decidim-proposals/spec/events/decidim/proposals/proposal_mentioned_event_spec.rb b/decidim-proposals/spec/events/decidim/proposals/proposal_mentioned_event_spec.rb index 956b682ea2f40..21742a006be1e 100644 --- a/decidim-proposals/spec/events/decidim/proposals/proposal_mentioned_event_spec.rb +++ b/decidim-proposals/spec/events/decidim/proposals/proposal_mentioned_event_spec.rb @@ -34,13 +34,13 @@ describe "email_subject" do it "is generated correctly" do - expect(subject.email_subject).to eq("Your proposal \"#{decidim_sanitize(translated(mentioned_proposal.title))}\" has been mentioned") + expect(subject.email_subject).to eq("Your proposal \"#{decidim_sanitize_translated(mentioned_proposal.title)}\" has been mentioned") end end context "with content" do let(:content) do - "Your proposal \"#{decidim_html_escape(translated(mentioned_proposal.title))}\" has been mentioned " \ + "Your proposal \"#{decidim_sanitize_translated(mentioned_proposal.title)}\" has been mentioned " \ "in this space in the comments." end diff --git a/decidim-proposals/spec/events/decidim/proposals/publish_proposal_event_spec.rb b/decidim-proposals/spec/events/decidim/proposals/publish_proposal_event_spec.rb index cd49a7fe6d62f..de56606b01273 100644 --- a/decidim-proposals/spec/events/decidim/proposals/publish_proposal_event_spec.rb +++ b/decidim-proposals/spec/events/decidim/proposals/publish_proposal_event_spec.rb @@ -5,10 +5,10 @@ module Decidim module Proposals describe PublishProposalEvent do - let(:resource) { create :proposal, title: "A nice proposal" } + let(:resource) { create :proposal } let(:participatory_process) { create :participatory_process, organization: organization } let(:proposal_component) { create(:proposal_component, participatory_space: participatory_process) } - let(:resource_title) { translated(resource.title) } + let(:resource_title) { decidim_sanitize_translated(resource.title) } let(:event_name) { "decidim.events.proposals.proposal_published" } include_context "when a simple event" @@ -23,7 +23,7 @@ module Proposals describe "email_subject" do context "when resource title contains apostrophes" do - let(:resource) { create :proposal, title: "It's a nice proposal" } + let(:resource) { create :proposal } it "is generated correctly" do expect(subject.email_subject).to eq("New proposal \"#{resource_title}\" by @#{author.nickname}") @@ -60,7 +60,7 @@ module Proposals end context "when the proposal is official" do - let(:resource) { create :proposal, :official, title: "A nice proposal" } + let(:resource) { create :proposal, :official } let(:extra) { { participatory_space: resource.participatory_space } } describe "notification_title" do @@ -72,14 +72,15 @@ module Proposals end context "when the target are the participatory space followers" do + include_context "when a simple event" + let(:event_name) { "decidim.events.proposals.proposal_published_for_space" } - let(:notification_title) { "The proposal A nice proposal has been added to #{participatory_space_title} by #{author.name} @#{author.nickname}" } + let(:notification_title) { "The proposal #{resource_title} has been added to #{participatory_space_title} by #{author.name} @#{author.nickname}" } let(:email_outro) { "You have received this notification because you are following \"#{participatory_space_title}\". You can stop receiving notifications following the previous link." } - let(:email_intro) { "The proposal \"A nice proposal\" has been added to \"#{participatory_space_title}\" that you are following." } + let(:email_intro) { "The proposal \"#{resource_title}\" has been added to \"#{participatory_space_title}\" that you are following." } let(:email_subject) { "New proposal \"#{resource_title}\" added to #{participatory_space_title}" } let(:extra) { { participatory_space: true } } - include_context "when a simple event" it_behaves_like "a simple event" it_behaves_like "a simple event email" it_behaves_like "a simple event notification" diff --git a/decidim-proposals/spec/events/decidim/proposals/rejected_proposal_event_spec.rb b/decidim-proposals/spec/events/decidim/proposals/rejected_proposal_event_spec.rb index 38628bdb0e41b..32f9c2280e5eb 100644 --- a/decidim-proposals/spec/events/decidim/proposals/rejected_proposal_event_spec.rb +++ b/decidim-proposals/spec/events/decidim/proposals/rejected_proposal_event_spec.rb @@ -4,12 +4,11 @@ describe Decidim::Proposals::RejectedProposalEvent do let(:resource) { create :proposal, :with_answer, title: "It's my super proposal" } - let(:resource_title) { translated(resource.title) } let(:event_name) { "decidim.events.proposals.proposal_rejected" } let(:email_subject) { "A proposal you're following has been rejected" } - let(:email_intro) { "The proposal \"#{decidim_html_escape(resource_title)}\" has been rejected. You can read the answer in this page:" } - let(:email_outro) { "You have received this notification because you are following \"#{decidim_html_escape(resource_title)}\". You can unfollow it from the previous link." } - let(:notification_title) { "The #{decidim_html_escape(resource_title)} proposal has been rejected." } + let(:email_intro) { "The proposal \"#{resource_title}\" has been rejected. You can read the answer in this page:" } + let(:email_outro) { "You have received this notification because you are following \"#{resource_title}\". You can unfollow it from the previous link." } + let(:notification_title) { "The #{resource_title} proposal has been rejected." } let(:resource_text) { translated(resource.answer) } include_context "when a simple event" diff --git a/decidim-proposals/spec/events/decidim/proposals/voting_enabled_event_spec.rb b/decidim-proposals/spec/events/decidim/proposals/voting_enabled_event_spec.rb index 528191a1e40ee..8684308b6ee80 100644 --- a/decidim-proposals/spec/events/decidim/proposals/voting_enabled_event_spec.rb +++ b/decidim-proposals/spec/events/decidim/proposals/voting_enabled_event_spec.rb @@ -10,10 +10,10 @@ module Proposals include_context "when a simple event" let(:event_name) { "decidim.events.proposals.voting_enabled" } - let(:email_subject) { "Proposal support has started for #{participatory_space.title["en"]}" } + let(:email_subject) { "Proposal support has started for #{participatory_space_title}" } let(:email_intro) { "You can support proposals in #{participatory_space_title}! Start participating in this page:" } - let(:email_outro) { "You have received this notification because you are following #{participatory_space.title["en"]}. You can stop receiving notifications following the previous link." } - let(:notification_title) { "You can now start supporting proposals in #{participatory_space.title["en"]}" } + let(:email_outro) { "You have received this notification because you are following #{participatory_space_title}. You can stop receiving notifications following the previous link." } + let(:notification_title) { "You can now start supporting proposals in #{participatory_space_title}" } let(:resource) { create(:proposal_component) } let(:participatory_space) { resource.participatory_space } let(:resource_path) { main_component_path(resource) } diff --git a/decidim-proposals/spec/shared/manage_proposals_examples.rb b/decidim-proposals/spec/shared/manage_proposals_examples.rb index f480563d31858..c8933e190f65a 100644 --- a/decidim-proposals/spec/shared/manage_proposals_examples.rb +++ b/decidim-proposals/spec/shared/manage_proposals_examples.rb @@ -354,8 +354,8 @@ end proposal.reload - expect(proposal.answered_at).to be_within(2.seconds).of Time.zone.now - expect(proposal.state_published_at).to be_within(2.seconds).of Time.zone.now + expect(proposal.answered_at).to be_within(5.seconds).of Time.zone.now + expect(proposal.state_published_at).to be_within(5.seconds).of Time.zone.now end it "can accept a proposal" do @@ -373,8 +373,8 @@ end proposal.reload - expect(proposal.answered_at).to be_within(2.seconds).of Time.zone.now - expect(proposal.state_published_at).to be_within(2.seconds).of Time.zone.now + expect(proposal.answered_at).to be_within(5.seconds).of Time.zone.now + expect(proposal.state_published_at).to be_within(5.seconds).of Time.zone.now end it "can mark a proposal as evaluating" do @@ -392,8 +392,8 @@ end proposal.reload - expect(proposal.answered_at).to be_within(2.seconds).of Time.zone.now - expect(proposal.state_published_at).to be_within(2.seconds).of Time.zone.now + expect(proposal.answered_at).to be_within(5.seconds).of Time.zone.now + expect(proposal.state_published_at).to be_within(5.seconds).of Time.zone.now end it "can mark a proposal as 'not answered'" do @@ -452,7 +452,7 @@ end proposal.reload - expect(proposal.answered_at).to be_within(2.seconds).of Time.zone.now + expect(proposal.answered_at).to be_within(5.seconds).of Time.zone.now end end diff --git a/decidim-proposals/spec/system/amendable/amend_proposal_spec.rb b/decidim-proposals/spec/system/amendable/amend_proposal_spec.rb index 7d46d2ac3f48f..9fe0637c5cf4f 100644 --- a/decidim-proposals/spec/system/amendable/amend_proposal_spec.rb +++ b/decidim-proposals/spec/system/amendable/amend_proposal_spec.rb @@ -245,6 +245,10 @@ context "when the form is filled correctly" do before do + login_as user, scope: :user + visit proposal_path + expect(page).to have_content(proposal_title) + click_link "Amend Proposal" within ".new_amendment" do fill_in "amendment[emendation_params][title]", with: "More sidewalks and less roads" fill_in "amendment[emendation_params][body]", with: "Cities need more people, not more cars" @@ -260,6 +264,10 @@ context "when the form is filled incorrectly" do before do + login_as user, scope: :user + visit proposal_path + expect(page).to have_content(proposal_title) + click_link "Amend Proposal" within ".new_amendment" do fill_in "amendment[emendation_params][title]", with: "INVALID TITLE" end diff --git a/decidim-proposals/spec/system/collaborative_drafts_spec.rb b/decidim-proposals/spec/system/collaborative_drafts_spec.rb index 325f7094a0542..f46fbbe7c9d45 100644 --- a/decidim-proposals/spec/system/collaborative_drafts_spec.rb +++ b/decidim-proposals/spec/system/collaborative_drafts_spec.rb @@ -91,7 +91,7 @@ end let(:html_body) { strip_tags(collaborative_draft.body).gsub(/\n/, " ").strip } - let(:stripped_body) { %(alert("BODY"); #{html_body}) } + let(:stripped_body) { %(alert("collaborative_draft_body"); #{html_body}) } it "shows the title" do expect(page).to have_content(collaborative_draft.title) diff --git a/decidim-proposals/spec/system/proposals_spec.rb b/decidim-proposals/spec/system/proposals_spec.rb index be910b1e9adde..fa43fd163a701 100644 --- a/decidim-proposals/spec/system/proposals_spec.rb +++ b/decidim-proposals/spec/system/proposals_spec.rb @@ -154,7 +154,7 @@ end it "shows the author as meeting" do - expect(page).to have_content(translated(proposal.authors.first.title)) + expect(page).to have_content(decidim_sanitize_translated(proposal.authors.first.title)) end it_behaves_like "rendering safe content", ".columns.mediumlarge-8.large-9" @@ -494,6 +494,7 @@ let!(:component) do create(:proposal_component, :with_votes_disabled, + :with_proposal_limit, manifest: manifest, participatory_space: participatory_process) end diff --git a/decidim-proposals/spec/system/vote_proposal_spec.rb b/decidim-proposals/spec/system/vote_proposal_spec.rb index 706eb61487a77..59b3b30a29f72 100644 --- a/decidim-proposals/spec/system/vote_proposal_spec.rb +++ b/decidim-proposals/spec/system/vote_proposal_spec.rb @@ -140,6 +140,9 @@ def expect_page_not_to_include_votes end describe "vote counter" do + let(:proposals) { create_list(:proposal, 2, component: component) } + let(:proposal_title) { translated(proposals.first.title) } + context "when votes are blocked" do let!(:component) do create(:proposal_component, @@ -153,7 +156,12 @@ def expect_page_not_to_include_votes it "doesn't show the remaining votes counter" do visit_component - expect(page).to have_css(".voting-rules") + expect(page).to have_no_css(".voting-rules") + expect(page).to have_no_css(".remaining-votes-counter") + + click_on proposal_title + + expect(page).to have_no_css(".voting-rules") expect(page).to have_no_css(".remaining-votes-counter") end end @@ -173,6 +181,34 @@ def expect_page_not_to_include_votes expect(page).to have_css(".voting-rules") expect(page).to have_css(".remaining-votes-counter") + + click_on proposal_title + + expect(page).to have_css(".voting-rules") + expect(page).to have_css(".remaining-votes-counter") + end + end + + context "when votes are disabled" do + let!(:component) do + create(:proposal_component, + :with_votes_disabled, + :with_vote_limit, + vote_limit: vote_limit, + manifest: manifest, + participatory_space: participatory_process) + end + + it "does not show the remaining votes counter" do + visit_component + + expect(page).to have_no_css(".voting-rules") + expect(page).to have_no_css(".remaining-votes-counter") + + click_on proposal_title + + expect(page).to have_no_css(".voting-rules") + expect(page).to have_no_css(".remaining-votes-counter") end end end diff --git a/decidim-sortitions/config/locales/bg.yml b/decidim-sortitions/config/locales/bg.yml index 0185d5de17008..ef7ef0a7a7edd 100644 --- a/decidim-sortitions/config/locales/bg.yml +++ b/decidim-sortitions/config/locales/bg.yml @@ -3,6 +3,149 @@ bg: activemodel: attributes: sortition: - additional_info: Сортиране на информация + additional_info: Информация за сортировката decidim_category_id: Категории от набора от предложения, в които искате да приложите жребий decidim_proposals_component_id: Предложенията са зададени + dice: Резултат от хвърлянето на зара. Хвърлете 6-странен зар или потърсете друг произволен начин за генериране на число от 1 до 6 и въведете тук полученото число пред няколко свидетели. Това допринася за качеството и гаранции за случайността на резултата + target_items: Брой на предложенията, които да бъдат избрани (указва броя на предложенията, които искате да бъдат избрани чрез хвърляне на жребий от групата предложения, които сте избрали по-рано) + title: Заглавие + witnesses: Свидетели + models: + decidim/sortitions/create_sortition_event: Сортиране + activerecord: + models: + decidim/sortitions/sortition: + one: Сортиране + other: Сортирания + decidim: + components: + sortitions: + actions: + comment: Коментар + name: Сортирания + settings: + global: + comments_enabled: Коментарите са разрешени + comments_max_length: Максимална дължина на коментарите (Оставете 0 за стойност по подразбиране) + events: + sortitions: + sortition_created: + email_intro: Сортировката „%{resource_title}“ беше добавена към пространството за участие „%{participatory_space_title}“, което следвате. + email_outro: Получавате това известие, защото следвате "%{participatory_space_title}". Може да премахнете следването чрез предходния линк. + email_subject: Беше добавена нова сортировка в(ъв) %{participatory_space_title} + notification_title: Сортировката %{resource_title} беше добавена в(ъв) %{participatory_space_title} + sortitions: + admin: + actions: + destroy: Отмяна на сортировката + edit: Редактирай + new: Нова сортировка + show: Детайли за сортировката + models: + sortition: + fields: + category: Категория + created_at: Дата на създаване + decidim_proposals_component: Компонент Предложения + dice: Зар + reference: Препоръка + request_timestamp: Време за теглене на жребий + seed: Seed + target_items: Елементи за селектиране + title: Заглавие + name: + one: Сортиране + other: Сортирания + sortitions: + confirm_destroy: + confirm_destroy: Наистина ли искате да отмените тази сортировка? + destroy: Отмяна на сортировка + title: Отменяне на сортировката + create: + error: Възникна проблем при създаването на нова сортировка. + success: Жребият беше създаден успешно + destroy: + error: Жребият не може да се отмени. + success: Жребият беше отменен успешно + edit: + title: Актуализирайте информацията за сортировката + update: Актуализация + form: + all_categories: Всички категории + select_proposal_component: Изберете набора от предложения + title: Нов жребий за предложения + index: + title: Сортировки + new: + confirm: Когато натиснете бутона „Напред“, системата ще запише датата и часа (с точност до секунди) и заедно с хвърлянето на зара тази информация ще се използва за генериране на избор на случаен принцип. Действието няма да може да бъде отменено — когато щракнете върху бутона, резултатът от жребия ще бъде публикуван заедно с въведените в този формуляр данни и няма да подлежи на промяна. Моля, прегледайте съдържанието внимателно + create: Създаване + title: Нова сортировка + show: + selected_proposals: Избрани предложения за жребия + update: + error: Възникна проблем при актуализирането на сортировката. + success: Жребият беше актуализиран успешно + admin_log: + sortition: + create: "%{user_name} създаде сортировка %{resource_name} в пространството %{space_name}" + delete: "%{user_name} отмени сортировката %{resource_name} в пространството %{space_name}" + update: "%{user_name} актуализира сортировката %{resource_name} в пространството %{space_name}" + sortitions: + count: + proposals_count: + one: 1 предложение + other: "%{count} предложения" + filters: + active: Активно + all: Всички + cancelled: Отменено + category: Категория + category_prompt: Изберете категория + search: Търсене + state: Статус + filters_small_view: + close_modal: Затвори прозореца + filter: Филтър + filter_by: Филтрирай по + unfold: Разгъване + linked_sortitions: + selected_proposals: Избрани предложения + orders: + label: 'Подреждане на сортировките по:' + random: Случаен + recent: Скорошни + results_count: + count: + one: избрано предложение + other: избрани предложения + show: + algorithm: Код на алгоритъма за жребия в сортировката + any_category: от всички категории + back: Назад към списъка + cancelled: Отменена сортировка + candidate_proposal_ids: Ред и ID номерата на предложенията в сортировката + candidate_proposals_info: 'Сортирането беше извършено сред следните предложения (%{category_label}), със следните идентификатори (с удебелен шрифт избраните предложения) ' + category: от категорията %{category} + dice_result: "(1) Резултат от жребия" + introduction: 'Тази страница съдържа резултатите от сортирането %{reference}. Чрез това сортиране, %{target_items} брой резултати са избрани на случаен принцип и с равно вероятностно разпределение от набора от предложения, показани по-долу. Заедно с резултатите, информацията, показана на тази страница, предоставя цялата информация, необходима за максимизиране на гаранциите и за възпроизвеждане на резултатите. Ключът към качеството на това сортиране е двойната случайност, осигурена от хвърлянето на зарове (потвърдено от свидетели) и точното време на сортирането, което осигурява вход за алгоритъм, който генерира случаен избор. Времето за начало за сортирането е толкова точно (секунди), че е невъзможно да се контролира от хора, като по този начин се осигурява двоен „неконтролируем“ вход, за да се гарантира справедлив резултат. ' + mathematical_result: Резултат (1) x (2) + proposals_selected_by_sortition: Избрани чрез (жребий) сортировка предложения + sortition_reproducibility_details: Подробности за възпроизвеждане на жребия + time_seed: "(2) Време за зареждане" + witnesses: Свидетели + sortition: + random_seed: Случаен подбор + selected_proposals: + one: избрано предложение + other: избрани предложения + view: Изглед + sortition_author: + deleted: Изтрит участник + sortition_cancel_author: + deleted: Изтрит участник + sortitions_count: + count: + one: 1 сортировка + other: "%{count} сортировки" + statistics: + sortitions_count: Сортировки diff --git a/decidim-sortitions/config/locales/ca.yml b/decidim-sortitions/config/locales/ca.yml index 8053bc32561f0..172c9384e9540 100644 --- a/decidim-sortitions/config/locales/ca.yml +++ b/decidim-sortitions/config/locales/ca.yml @@ -31,7 +31,7 @@ ca: sortitions: sortition_created: email_intro: El sorteig "%{resource_title}" s'ha afegit a "%{participatory_space_title}" que segueixes. - email_outro: Has rebut aquesta notificació perquè estàs seguint "%{participatory_space_title}". Pots deixar de seguir-lo des de l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint l'espai "%{participatory_space_title}". Pots deixar de seguir-lo des de l'enllaç anterior. email_subject: Nou sorteig afegit a %{participatory_space_title} notification_title: El sorteig %{resource_title} s'ha afegit a %{participatory_space_title} sortitions: diff --git a/decidim-sortitions/config/locales/he-IL.yml b/decidim-sortitions/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-sortitions/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-sortitions/config/locales/pl.yml b/decidim-sortitions/config/locales/pl.yml index 463636ccafbd5..fad5b0f93dd29 100644 --- a/decidim-sortitions/config/locales/pl.yml +++ b/decidim-sortitions/config/locales/pl.yml @@ -22,6 +22,8 @@ pl: decidim: components: sortitions: + actions: + comment: Skomentuj name: Wybory losowe settings: global: @@ -157,3 +159,5 @@ pl: few: "%{count} wyborów losowych" many: "%{count} wybory losowe" other: "%{count} wybory losowe" + statistics: + sortitions_count: Wybory przez losowanie diff --git a/decidim-sortitions/lib/decidim/sortitions/test/factories.rb b/decidim-sortitions/lib/decidim/sortitions/test/factories.rb index 49ec02cc43dd0..0e7a3b3fad88b 100644 --- a/decidim-sortitions/lib/decidim/sortitions/test/factories.rb +++ b/decidim-sortitions/lib/decidim/sortitions/test/factories.rb @@ -6,16 +6,22 @@ FactoryBot.define do factory :sortition_component, parent: :component do - name { Decidim::Components::Namer.new(participatory_space.organization.available_locales, :sortitions).i18n_name } + transient do + skip_injection { false } + end + name { generate_component_name(participatory_space.organization.available_locales, :sortitions, skip_injection: skip_injection) } manifest_name { :sortitions } - participatory_space { create(:participatory_process, :with_steps, organization: organization) } + participatory_space { create(:participatory_process, :with_steps, organization: organization, skip_injection: skip_injection) } end factory :sortition, class: "Decidim::Sortitions::Sortition" do - component { create(:sortition_component) } - decidim_proposals_component { create(:proposal_component, organization: component.organization) } + transient do + skip_injection { false } + end + component { create(:sortition_component, skip_injection: skip_injection) } + decidim_proposals_component { create(:proposal_component, organization: component.organization, skip_injection: skip_injection) } - title { generate_localized_title } + title { generate_localized_title(:sortition_title, skip_injection: skip_injection) } author do create(:user, :admin, organization: component.organization) if component end @@ -23,15 +29,15 @@ dice { Faker::Number.between(from: 1, to: 6).to_i } target_items { Faker::Number.between(from: 1, to: 5).to_i } request_timestamp { Time.now.utc } - witnesses { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } - additional_info { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } - selected_proposals { create_list(:proposal, target_items, component: decidim_proposals_component).pluck(:id) } + witnesses { generate_localized_description(:sortition_witnesses, skip_injection: skip_injection) } + additional_info { generate_localized_description(:sortition_additional_info, skip_injection: skip_injection) } + selected_proposals { create_list(:proposal, target_items, component: decidim_proposals_component, skip_injection: skip_injection).pluck(:id) } candidate_proposals { selected_proposals } trait :cancelled do cancelled_on { Time.now.utc } - cancel_reason { Decidim::Faker::Localized.wrapped("

    ", "

    ") { generate_localized_title } } - cancelled_by_user { create(:user, :admin, organization: component.organization) if component } + cancel_reason { generate_localized_description(:sortition_cancel_reason, skip_injection: skip_injection) } + cancelled_by_user { create(:user, :admin, organization: component.organization, skip_injection: skip_injection) if component } end end end diff --git a/decidim-sortitions/lib/decidim/sortitions/version.rb b/decidim-sortitions/lib/decidim/sortitions/version.rb index 597a9adbc24e9..fc103a5353c33 100644 --- a/decidim-sortitions/lib/decidim/sortitions/version.rb +++ b/decidim-sortitions/lib/decidim/sortitions/version.rb @@ -3,7 +3,7 @@ module Decidim module Sortitions def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-sortitions/spec/events/decidim/sortitions/create_sortition_event_spec.rb b/decidim-sortitions/spec/events/decidim/sortitions/create_sortition_event_spec.rb index d1c12b68d9ab8..baaf06426e70b 100644 --- a/decidim-sortitions/spec/events/decidim/sortitions/create_sortition_event_spec.rb +++ b/decidim-sortitions/spec/events/decidim/sortitions/create_sortition_event_spec.rb @@ -7,7 +7,7 @@ let(:notification_title) { "The sortition #{resource_title} has been added to #{participatory_space_title}" } let(:email_outro) { "You have received this notification because you are following \"#{participatory_space_title}\". You can unfollow it from the previous link." } let(:email_intro) { "The sortition \"#{resource_title}\" has been added to \"#{participatory_space_title}\" that you are following." } - let(:email_subject) { "New sortition added to #{participatory_space_title}" } + let(:email_subject) { "New sortition added to #{decidim_sanitize_translated(participatory_space.title)}" } let(:event_name) { "decidim.events.sortitions.sortition_created" } include_context "when a simple event" diff --git a/decidim-sortitions/spec/requests/sortition_search_spec.rb b/decidim-sortitions/spec/requests/sortition_search_spec.rb index 8aa31295205a8..891422caed2eb 100644 --- a/decidim-sortitions/spec/requests/sortition_search_spec.rb +++ b/decidim-sortitions/spec/requests/sortition_search_spec.rb @@ -32,22 +32,22 @@ it_behaves_like "a resource search with categories", :sortition, :single it "displays all non-cancelled sortitions without any filters" do - expect(subject).to include(translated(sortition1.title)) - expect(subject).to include(translated(sortition2.title)) - expect(subject).to include(translated(sortition3.title)) - expect(subject).to include(translated(sortition4.title)) - expect(subject).not_to include(translated(sortition5.title)) + expect(subject).to include(decidim_escape_translated(sortition1.title)) + expect(subject).to include(decidim_escape_translated(sortition2.title)) + expect(subject).to include(decidim_escape_translated(sortition3.title)) + expect(subject).to include(decidim_escape_translated(sortition4.title)) + expect(subject).not_to include(decidim_escape_translated(sortition5.title)) end context "when searching by text" do let(:filter_params) { { search_text_cont: "doggo" } } it "displays only the sortitions containing the search_text" do - expect(subject).to include(translated(sortition1.title)) - expect(subject).to include(translated(sortition2.title)) - expect(subject).to include(translated(sortition3.title)) - expect(subject).not_to include(translated(sortition4.title)) - expect(subject).not_to include(translated(sortition5.title)) + expect(subject).to include(decidim_escape_translated(sortition1.title)) + expect(subject).to include(decidim_escape_translated(sortition2.title)) + expect(subject).to include(decidim_escape_translated(sortition3.title)) + expect(subject).not_to include(decidim_escape_translated(sortition4.title)) + expect(subject).not_to include(decidim_escape_translated(sortition5.title)) end end @@ -58,11 +58,11 @@ let(:state) { "active" } it "displays the active sortitions" do - expect(subject).to include(translated(sortition1.title)) - expect(subject).to include(translated(sortition2.title)) - expect(subject).to include(translated(sortition3.title)) - expect(subject).to include(translated(sortition4.title)) - expect(subject).not_to include(translated(sortition5.title)) + expect(subject).to include(decidim_escape_translated(sortition1.title)) + expect(subject).to include(decidim_escape_translated(sortition2.title)) + expect(subject).to include(decidim_escape_translated(sortition3.title)) + expect(subject).to include(decidim_escape_translated(sortition4.title)) + expect(subject).not_to include(decidim_escape_translated(sortition5.title)) end end @@ -70,11 +70,11 @@ let(:state) { "cancelled" } it "displays only the cancelled sortition" do - expect(subject).not_to include(translated(sortition1.title)) - expect(subject).not_to include(translated(sortition2.title)) - expect(subject).not_to include(translated(sortition3.title)) - expect(subject).not_to include(translated(sortition4.title)) - expect(subject).to include(translated(sortition5.title)) + expect(subject).not_to include(decidim_escape_translated(sortition1.title)) + expect(subject).not_to include(decidim_escape_translated(sortition2.title)) + expect(subject).not_to include(decidim_escape_translated(sortition3.title)) + expect(subject).not_to include(decidim_escape_translated(sortition4.title)) + expect(subject).to include(decidim_escape_translated(sortition5.title)) end end @@ -82,11 +82,11 @@ let(:state) { "all" } it "displays all the sortitions" do - expect(subject).to include(translated(sortition1.title)) - expect(subject).to include(translated(sortition2.title)) - expect(subject).to include(translated(sortition3.title)) - expect(subject).to include(translated(sortition4.title)) - expect(subject).to include(translated(sortition5.title)) + expect(subject).to include(decidim_escape_translated(sortition1.title)) + expect(subject).to include(decidim_escape_translated(sortition2.title)) + expect(subject).to include(decidim_escape_translated(sortition3.title)) + expect(subject).to include(decidim_escape_translated(sortition4.title)) + expect(subject).to include(decidim_escape_translated(sortition5.title)) end end end diff --git a/decidim-sortitions/spec/types/integration_schema_spec.rb b/decidim-sortitions/spec/types/integration_schema_spec.rb index dce02375b9db6..ab815c433046b 100644 --- a/decidim-sortitions/spec/types/integration_schema_spec.rb +++ b/decidim-sortitions/spec/types/integration_schema_spec.rb @@ -45,7 +45,7 @@ { "__typename" => "Sortitions", "id" => current_component.id.to_s, - "name" => { "translation" => "Sortitions" }, + "name" => { "translation" => translated(current_component.name) }, "sortitions" => { "edges" => [ { diff --git a/decidim-surveys/config/locales/bg.yml b/decidim-surveys/config/locales/bg.yml index bb348535b1445..8d786cc66cc8f 100644 --- a/decidim-surveys/config/locales/bg.yml +++ b/decidim-surveys/config/locales/bg.yml @@ -2,10 +2,71 @@ bg: activemodel: models: - decidim/surveys/closed_survey_event: Анкетата завърши + decidim/surveys/closed_survey_event: Анкетата приключи decidim/surveys/opened_survey_event: Анкетата започна activerecord: models: decidim/surveys/survey: one: Анкета other: Анкети + decidim/surveys/survey_answer: + one: Отговор + other: Отговори + decidim: + components: + surveys: + actions: + answer: Отговор + name: Анкета + settings: + global: + announcement: Съобщение + clean_after_publish: Изтриване на отговорите при публикуване на проучването + ends_at: Отговорите се приемат до + ends_at_help: Оставете празно при липса на конкретна дата + scope_id: Обхват + scopes_enabled: Обхватите са активирани + starts_at: Отговорите се приемат от + starts_at_help: Оставете празно при липса на конкретна дата + step: + allow_answers: Разрешаване на отговори + allow_unregistered: Разрешаване на нерегистрирани потребители да отговарят на въпросите в проучването + allow_unregistered_help: Ако е активно, няма да се изисква влизане, за да се отговори на анкетата. Това може да доведе до лоши или ненадеждни данни и ще e по-уязвимo на автоматизирани атаки. Използвайте с повишено внимание! Имайте предвид, че участник може да отговори на едно и също проучване няколко пъти, като използва различни браузъри или функцията за „частно сърфиране“ на своя уеб браузър. + announcement: Съобщение + events: + surveys: + survey_closed: + email_intro: Анкетата %{resource_title} в(ъв) %{participatory_space_title} беше затворена. + email_outro: Получавате това известие, защото следвате %{participatory_space_title}. Може да прекратите известията чрез предходния линк. + email_subject: Приключи анкетата в(ъв) %{participatory_space_title} + notification_title: Анкетата %{resource_title} в(ъв) %{participatory_space_title} приключи. + survey_opened: + email_intro: 'Анкетата %{resource_title} в(ъв) %{participatory_space_title} вече е отворена. Можете да участвате в нея от тази страница:' + email_outro: Получавате това известие, защото следвате %{participatory_space_title}. Може да прекратите известията чрез предходния линк. + email_subject: Нова анкета в(ъв) %{participatory_space_title} + notification_title: Анкетата %{resource_title} в(ъв) %{participatory_space_title} вече е отворена. + metrics: + survey_answers: + description: Брой на анкетите с отговори от участници + object: отговори на анкети + title: Отговори на анкети + statistics: + answers_count: Отговори + surveys: + admin: + component: + actions: + answers_alert: Ако публикувате компонента, всички резултати ще бъдат премахнати. + exports: + survey_user_answers: Отговори на участник в анкети + surveys: + update: + invalid: Възникна проблем при запазването на анкетата. + success: Анкетата беше запазена успешно. + last_activity: + new_survey_at_html: "Ново допитване на %{link}" + surveys: + answer: + invalid: Възникна проблем при попълването на отговорите на анкетата. + spam_detected: Възникна проблем при попълването на отговорите във формуляра. Навярно сте били твърде бързи, бихте ли опитали отново? + success: Отговорите на анкетата са попълнени успешно. diff --git a/decidim-surveys/config/locales/ca.yml b/decidim-surveys/config/locales/ca.yml index 3ed8c3c68fb7e..eeea31c7441c1 100644 --- a/decidim-surveys/config/locales/ca.yml +++ b/decidim-surveys/config/locales/ca.yml @@ -37,12 +37,12 @@ ca: surveys: survey_closed: email_intro: L'enquesta %{resource_title} a %{participatory_space_title} ha estat tancada. - email_outro: Has rebut aquesta notificació perquè estàs seguint %{participatory_space_title}. Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint l'espai "%{participatory_space_title}". Pots deixar de rebre notificacions seguint l'enllaç anterior. email_subject: S'ha acabat una enquesta a %{participatory_space_title} notification_title: L'enquesta %{resource_title} a %{participatory_space_title} ha acabat. survey_opened: email_intro: 'L''enquesta %{resource_title} a %{participatory_space_title} ja està oberta. Pots participar-hi des d''aquesta pàgina:' - email_outro: Has rebut aquesta notificació perquè estàs seguint %{participatory_space_title}. Pots deixar de rebre notificacions seguint l'enllaç anterior. + email_outro: Has rebut aquesta notificació perquè estàs seguint l'espai "%{participatory_space_title}". Pots deixar de rebre notificacions seguint l'enllaç anterior. email_subject: Una nova enquesta a %{participatory_space_title} notification_title: L'enquesta %{resource_title} en %{participatory_space_title} ja està oberta. metrics: diff --git a/decidim-surveys/config/locales/es.yml b/decidim-surveys/config/locales/es.yml index 13626362ac785..d67dc9be02b4b 100644 --- a/decidim-surveys/config/locales/es.yml +++ b/decidim-surveys/config/locales/es.yml @@ -37,12 +37,12 @@ es: surveys: survey_closed: email_intro: La encuesta %{resource_title} en %{participatory_space_title} se ha cerrado. - email_outro: Has recibido esta notificación porqué estás siguiendo %{participatory_space_title}. Puedes dejar de recibir notificaciones siguiendo el enlace anterior. + email_outro: Has recibido esta notificación porqué estás siguiendo el espacio "%{participatory_space_title}". Puedes dejar de recibir notificaciones siguiendo el enlace anterior. email_subject: Ha terminado una encuesta en %{participatory_space_title} notification_title: La encuesta %{resource_title} en %{participatory_space_title} ha terminado. survey_opened: email_intro: 'Ya está abierta la encuesta %{resource_title} en %{participatory_space_title}. Puedes participar desde esta página:' - email_outro: Has recibido esta notificación porque estás siguiendo %{participatory_space_title}. Puedes dejar de recibir notificaciones siguiendo el enlace anterior. + email_outro: Has recibido esta notificación porque estás siguiendo el espacio "%{participatory_space_title}". Puedes dejar de recibir notificaciones siguiendo el enlace anterior. email_subject: Nueva encuesta en %{participatory_space_title} notification_title: Ya está abierta la encuesta %{resource_title} en %{participatory_space_title}. metrics: diff --git a/decidim-surveys/config/locales/he-IL.yml b/decidim-surveys/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-surveys/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-surveys/lib/decidim/surveys/test/factories.rb b/decidim-surveys/lib/decidim/surveys/test/factories.rb index d8dc88f5be56c..4103062040599 100644 --- a/decidim-surveys/lib/decidim/surveys/test/factories.rb +++ b/decidim-surveys/lib/decidim/surveys/test/factories.rb @@ -6,13 +6,19 @@ FactoryBot.define do factory :surveys_component, parent: :component do - name { Decidim::Components::Namer.new(participatory_space.organization.available_locales, :surveys).i18n_name } + transient do + skip_injection { false } + end + name { generate_component_name(participatory_space.organization.available_locales, :surveys, skip_injection: skip_injection) } manifest_name { :surveys } - participatory_space { create(:participatory_process, :with_steps) } + participatory_space { create(:participatory_process, :with_steps, skip_injection: skip_injection) } end factory :survey, class: "Decidim::Surveys::Survey" do - questionnaire { build(:questionnaire, :with_questions) } - component { build(:surveys_component) } + transient do + skip_injection { false } + end + questionnaire { build(:questionnaire, :with_questions, skip_injection: skip_injection) } + component { build(:surveys_component, skip_injection: skip_injection) } end end diff --git a/decidim-surveys/lib/decidim/surveys/version.rb b/decidim-surveys/lib/decidim/surveys/version.rb index faed65770bfdf..b876805034d29 100644 --- a/decidim-surveys/lib/decidim/surveys/version.rb +++ b/decidim-surveys/lib/decidim/surveys/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-surveys version. module Surveys def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-surveys/spec/events/decidim/surveys/closed_survey_event_spec.rb b/decidim-surveys/spec/events/decidim/surveys/closed_survey_event_spec.rb index 7b35352c6b732..52f73e1bd5202 100644 --- a/decidim-surveys/spec/events/decidim/surveys/closed_survey_event_spec.rb +++ b/decidim-surveys/spec/events/decidim/surveys/closed_survey_event_spec.rb @@ -13,10 +13,11 @@ module Surveys let(:resource) { create(:surveys_component) } let(:participatory_space) { resource.participatory_space } let(:resource_path) { main_component_path(resource) } + let(:resource_title) { decidim_sanitize_translated(resource.name) } let(:email_subject) { "A survey has finished in #{participatory_space_title}" } - let(:email_intro) { "The survey #{resource.name["en"]} in #{participatory_space_title} has been closed." } + let(:email_intro) { "The survey #{resource_title} in #{participatory_space_title} has been closed." } let(:email_outro) { "You have received this notification because you are following #{participatory_space_title}. You can stop receiving notifications following the previous link." } - let(:notification_title) { "The survey #{resource.name["en"]} in #{participatory_space_title} has finished." } + let(:notification_title) { "The survey #{resource_title} in #{participatory_space_title} has finished." } it_behaves_like "a simple event" it_behaves_like "a simple event email" diff --git a/decidim-surveys/spec/events/decidim/surveys/opened_survey_event_spec.rb b/decidim-surveys/spec/events/decidim/surveys/opened_survey_event_spec.rb index 9d2a3e5ecde84..bfcc44a60bf68 100644 --- a/decidim-surveys/spec/events/decidim/surveys/opened_survey_event_spec.rb +++ b/decidim-surveys/spec/events/decidim/surveys/opened_survey_event_spec.rb @@ -13,10 +13,11 @@ module Surveys let(:resource) { create(:surveys_component) } let(:participatory_space) { resource.participatory_space } let(:resource_path) { main_component_path(resource) } + let(:resource_title) { decidim_sanitize_translated(resource.name) } let(:email_subject) { "A new survey in #{participatory_space_title}" } - let(:email_intro) { "The survey #{resource.name["en"]} in #{participatory_space_title} is now open. You can participate in it from this page:" } + let(:email_intro) { "The survey #{resource_title} in #{participatory_space_title} is now open. You can participate in it from this page:" } let(:email_outro) { "You have received this notification because you are following #{participatory_space_title}. You can stop receiving notifications following the previous link." } - let(:notification_title) { "The survey #{resource.name["en"]} in #{participatory_space_title} is now open." } + let(:notification_title) { "The survey #{resource_title} in #{participatory_space_title} is now open." } it_behaves_like "a simple event" it_behaves_like "a simple event email" diff --git a/decidim-surveys/spec/types/integration_schema_spec.rb b/decidim-surveys/spec/types/integration_schema_spec.rb index 799e0fd2caeb3..3c9732517dc80 100644 --- a/decidim-surveys/spec/types/integration_schema_spec.rb +++ b/decidim-surveys/spec/types/integration_schema_spec.rb @@ -54,7 +54,7 @@ { "__typename" => "Surveys", "id" => current_component.id.to_s, - "name" => { "translation" => "Survey" }, + "name" => { "translation" => translated(current_component.name) }, "surveys" => { "edges" => [ { diff --git a/decidim-system/app/commands/decidim/system/register_organization.rb b/decidim-system/app/commands/decidim/system/register_organization.rb index 0654453770c68..e1dd8b4fd14c1 100644 --- a/decidim-system/app/commands/decidim/system/register_organization.rb +++ b/decidim-system/app/commands/decidim/system/register_organization.rb @@ -2,6 +2,9 @@ module Decidim module System + class InvitationFailedError < ActiveRecord::RecordInvalid + end + # A command with all the business logic when creating a new organization in # the system. It creates the organization and invites the admin to the # system. @@ -24,7 +27,6 @@ def call @organization = nil invite_form = nil - invitation_failed = false transaction do @organization = create_organization @@ -32,13 +34,14 @@ def call PopulateHelp.call(@organization) CreateDefaultContentBlocks.call(@organization) invite_form = invite_user_form(@organization) - invitation_failed = invite_form.invalid? + raise InvitationFailedError if invite_form.invalid? end - return broadcast(:invalid) if invitation_failed Decidim::InviteUser.call(invite_form) if @organization && invite_form broadcast(:ok) + rescue InvitationFailedError + broadcast(:invalid_invitation) rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique broadcast(:invalid) end diff --git a/decidim-system/app/controllers/decidim/system/organizations_controller.rb b/decidim-system/app/controllers/decidim/system/organizations_controller.rb index 088e8c53a5f6e..f9661d459d6e5 100644 --- a/decidim-system/app/controllers/decidim/system/organizations_controller.rb +++ b/decidim-system/app/controllers/decidim/system/organizations_controller.rb @@ -22,6 +22,11 @@ def create redirect_to organizations_path end + on(:invalid_invitation) do + flash.now[:alert] = t("organizations.create.error_invitation", scope: "decidim.system") + render :new + end + on(:invalid) do flash.now[:alert] = t("organizations.create.error", scope: "decidim.system") render :new diff --git a/decidim-system/app/forms/decidim/system/update_organization_form.rb b/decidim-system/app/forms/decidim/system/update_organization_form.rb index eb6e18645ecaa..d433296700282 100644 --- a/decidim-system/app/forms/decidim/system/update_organization_form.rb +++ b/decidim-system/app/forms/decidim/system/update_organization_form.rb @@ -46,6 +46,7 @@ class UpdateOrganizationForm < Form validates :name, :host, :users_registration_mode, presence: true validate :validate_organization_uniqueness + validate :validate_secret_key_base_for_encryption validates :users_registration_mode, inclusion: { in: Decidim::Organization.users_registration_modes } def map_model(model) @@ -96,6 +97,14 @@ def validate_organization_uniqueness errors.add(:name, :taken) if Decidim::Organization.where(name: name).where.not(id: id).exists? errors.add(:host, :taken) if Decidim::Organization.where(host: host).where.not(id: id).exists? end + + # We need a valid secret key base for encrypting the SMTP password with it + # It is also necessary for other things in Rails (like Cookies encryption) + def validate_secret_key_base_for_encryption + return if Rails.application.secrets.secret_key_base&.length == 128 + + errors.add(:password, I18n.t("activemodel.errors.models.organization.attributes.password.secret_key")) + end end end end diff --git a/decidim-system/app/mailers/decidim/system/application_mailer.rb b/decidim-system/app/mailers/decidim/system/application_mailer.rb deleted file mode 100644 index 5f92460e49102..0000000000000 --- a/decidim-system/app/mailers/decidim/system/application_mailer.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -module Decidim - module System - # Custom application mailer, scoped to the system mailer. - # - class ApplicationMailer < ActionMailer::Base - default from: Decidim.config.mailer_sender - layout "mailer" - end - end -end diff --git a/decidim-system/config/locales/bg.yml b/decidim-system/config/locales/bg.yml index 70c161a2c3b67..38d510adeebcc 100644 --- a/decidim-system/config/locales/bg.yml +++ b/decidim-system/config/locales/bg.yml @@ -1,5 +1,37 @@ --- bg: + activemodel: + attributes: + oauth_application: + name: Име на приложението за OAuth + organization_logo: Лого на организацията (квадратно) + organization_name: Организация + organization_url: URL адрес на организацията + redirect_uri: URI за пренасочване + organization: + address: Име на SMTP хост + from_email: Имейл адрес + from_label: Етикет + password: Парола + port: Порт + user_name: Потребителско име + organization_file_uploads: + allowed_content_types: + admin: Администраторски MIME типове + default: MIME типове по подразбиране + allowed_file_extensions: + admin: Административни файлови разширения + default: Файлови разширения по подразбиране + image: Разширения на файлове с изображения + maximum_file_size: + avatar: Размер на файла на аватара + default: Размер на файла по подразбиране + errors: + models: + oauth_application: + attributes: + redirect_uri: + must_be_ssl: URI адресът за пренасочване трябва да бъде SSL URI decidim: system: actions: @@ -7,6 +39,179 @@ bg: destroy: Изтрий edit: Редактирай new: Нов + save: Запази + title: Действия admins: + create: + error: Възникна проблем при създаването на нов администратор. + success: Администраторът беше създаден успешно + destroy: + success: Администраторът беше изтрит успешно + edit: + title: Редактиране на администратора + update: Обновяване + index: + title: Администратори + new: + create: Създаване + title: Нов администратор show: + destroy: Унищожи edit: Редактирай + update: + error: Възникна проблем при актуализирането на този администратор. + success: Администраторът беше актуализиран успешно + dashboard: + show: + current_organizations: Текущи организации + default_pages: + placeholders: + content: Моля, добавете важно съдържание на статичната страница %{page} в администраторското табло. + title: Заглавие по подразбиране за %{page} + devise: + passwords: + edit: + change_your_password: Промени паролата си + minimum_characters: "(%{minimum} символа минимум)" + new: + forgot_your_password: Забравили сте паролата си + send_me_reset_password_instructions: Изпратете ми инструкции за възстановяване на паролата + shared: + links: + did_not_receive_confirmation_instructions?: Не сте ли получили указания за потвърждение? + did_not_receive_unlock_instructions?: Не сте получили инструкции за отключване? + forgot_your_password?: Забравили сте паролата си? + log_in: Вход + sign_up: Регистрация + menu: + admins: Администратори + dashboard: Табло за управление + oauth_applications: Приложения за OAuth + organizations: Организации + models: + admin: + fields: + created_at: Създаден на + email: Имейл + name: Администратор + validations: + email_uniqueness: вече съществува друг администратор със същия имейл + oauth_application: + fields: + created_at: Създаден на + name: Име на приложението за OAuth + organization_name: Организация + name: Приложение за OAuth + organization: + actions: + save_and_invite: Създаване на организация и покана на администратор + fields: + created_at: Създадено на + file_upload_settings: Настройки за качване на файл + name: Име + omniauth_settings: Настройки за Omniauth + smtp_settings: SMTP Настройки + name: Организация + oauth_applications: + create: + error: Възникна проблем при създаването на това приложение. + success: Приложението беше създадено успешно. + destroy: + error: Възникна проблем при премахването на това приложение. + success: Приложението беше премахнато успешно. + edit: + save: Запази + title: Редактиране на приложението + form: + select_organization: Избор на организация + index: + confirm_delete: Сигурни ли сте, че искате да изтриете това приложение? + title: Приложения за OAuth + new: + save: Запази + title: Ново приложение + update: + error: Възникна проблем при актуализирането на това приложение. + success: Приложението беше актуализирано успешно. + organizations: + advanced_settings: + hide: Скрий разширените настройки + show: Показване на разширените настройки + create: + error: Възникна проблем при създаването на нова организация. + success: Организацията беше създадена успешно. + edit: + secondary_hosts_hint: Въведете всяка от тях на нов ред + title: Редактиране на организацията + file_upload_settings: + content_types: + admin_hint: Тези типове MIME са разрешени за качвания в администраторския раздел. Потребителите с администратори трябва да са наясно с рисковете при качването на някои формати на документи, така че можете да очаквате да бъдат по-предпазливи при качването на файлове. + default_hint: Тези типове MIME са разрешени за всички потребители по подразбиране. + intro_html: Добавяте заместващи символи със знака звездичка за MIME типовете, напр. изображение/*. + title: Разрешени MIME типове + file_extensions: + admin_hint: Тези файлови разширения са разрешени за качване в раздела за администриране. Администраторите трябва да са наясно с рисковете при качването на някои формати документи, така че можете да очаквате да бъдат по-предпазливи при качването на файлове. + default_hint: Тези файлови разширения са разрешени за всички потребители по подразбиране. + image_hint: Тези файлови разширения са разрешени за всякакъв вид качване на изображения. + title: Разрешени файлови разширения + file_sizes: + avatar_hint: Мегабайти (MB). Това ограничение за размера на файла се използва за качване на изображения на аватар. + default_hint: Мегабайти (MB). Това ограничение за размера на файла е по подразбиране, което се използва за всички качвания на файлове, освен ако не е посочено друго. + title: Максимална големина на файловете + intro: | + Моля, бъдете изключително внимателни, когато обмисляте да промените тези настройки. Колкото по-малко позволявате, толкова по-добре. + Разрешаването на конкретни файлови разширения или типове MIME може да изложи потребителите на системата на рискове за сигурността и може също да повлияе на достъпността на уебсайта. + index: + title: Организации + new: + default: По подразбиране? + enabled: Активно + locale: Локално + reference_prefix_hint: Референтният префикс се използва за уникално идентифициране на ресурсите в цялата организация. + secondary_hosts_hint: Въведете всеки един от тях на нов ред. + title: Нова организация + omniauth_settings: + decidim: + client_id: ID на клиента + client_secret: Тайна на клиента + site_url: Уебсайт URL + enabled: Активно + enabled_by_default: Този доставчик е активиран по подразбиране. Може да бъде редактиран, но не и деактивиран. + facebook: + app_id: Идентификатор (ID) на приложението + app_secret: Тайна на приложението + google_oauth2: + client_id: ID на клиента + client_secret: Тайна на клиента + icon: Икона + icon_path: Път до иконата + twitter: + api_key: API ключ + api_secret: Тайна на API + smtp_settings: + fieldsets: + sender: Подател + instructions: + from_label: 'Подателят на имейла ще бъде: „името-на-организацията-ви “. Оставете празно, за да използвате „имейл адресът“ като етикет' + placeholder: + from_email: your-organization@example.org + from_label: your-organization-name + update: + error: Възникна проблем при актуализирането на тази организация. + success: Организацията беше актуализирана успешно. + users_registration_mode: + disabled: Достъпът е възможен само с външни профили + enabled: Разрешете на участниците да се регистрират и да влизат в профилите си + existing: Не разрешавайте на участниците да се регистрират, но разрешете на съществуващите участници да влизат в профила си + shared: + notices: + no_organization_warning_html: Трябва да създадете организация, за да започнете. Уверете се, че сте прочели %{guide}, преди да продължите. + our_getting_started_guide: нашето стартово ръководство + titles: + dashboard: Табло за управление + decidim: Civil Power + layouts: + decidim: + system: + login_items: + logout: Изход diff --git a/decidim-system/config/locales/en.yml b/decidim-system/config/locales/en.yml index cd6fb45dc18a5..46395d2f98758 100644 --- a/decidim-system/config/locales/en.yml +++ b/decidim-system/config/locales/en.yml @@ -32,6 +32,10 @@ en: attributes: redirect_uri: must_be_ssl: The redirect URI must be a SSL URI + organization: + attributes: + password: + secret_key: You need to define the SECRET_KEY_BASE environment variable to be able to save this field decidim: system: actions: @@ -139,6 +143,7 @@ en: show: Show advanced settings create: error: There was a problem creating a new organization. + error_invitation: There was a problem creating a new organization. Review your organization admin name. success: Organization successfully created. edit: secondary_hosts_hint: Enter each one of them in a new line @@ -192,7 +197,7 @@ en: fieldsets: sender: Sender instructions: - from_label: 'Email sender will be: "your-organization-name ". Leave blank to use the ''Email address'' as label' + from_label: 'Email sender will be: "your-organization-name ". Leave blank to use the same name as the defined for the organization.' placeholder: from_email: your-organization@example.org from_label: your-organization-name diff --git a/decidim-system/config/locales/eo.yml b/decidim-system/config/locales/eo.yml index 7599814048735..4323652d927d1 100644 --- a/decidim-system/config/locales/eo.yml +++ b/decidim-system/config/locales/eo.yml @@ -1 +1,8 @@ +--- eo: + activemodel: + attributes: + oauth_application: + organization_logo: Organizaĵa emblemo (kvadrata) + organization_url: Organizo URL + redirect_uri: Adresado URL diff --git a/decidim-system/config/locales/he-IL.yml b/decidim-system/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-system/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-system/config/locales/hu.yml b/decidim-system/config/locales/hu.yml index fe8b3ea94ce09..daf9861b0a18d 100644 --- a/decidim-system/config/locales/hu.yml +++ b/decidim-system/config/locales/hu.yml @@ -1,5 +1,22 @@ --- hu: + activemodel: + attributes: + oauth_application: + organization_logo: Szervezet logója (négyzet) + organization_url: Szervezet URL + redirect_uri: Redirect URI + organization: + address: SMTP host név + password: Jelszó + port: Port + user_name: Felhasználónév + errors: + models: + oauth_application: + attributes: + redirect_uri: + must_be_ssl: Az átirányítási URI-nak SSL URI-nak kell lennie decidim: system: actions: diff --git a/decidim-system/config/locales/is-IS.yml b/decidim-system/config/locales/is-IS.yml index 8b3dcaaf008b7..f3863e10007f8 100644 --- a/decidim-system/config/locales/is-IS.yml +++ b/decidim-system/config/locales/is-IS.yml @@ -1,5 +1,11 @@ --- is: + activemodel: + attributes: + organization: + password: Lykilorð + port: Gátt + user_name: Notendanafn decidim: system: actions: diff --git a/decidim-system/config/locales/lv.yml b/decidim-system/config/locales/lv.yml index fe66db21befd0..05fa13912074e 100644 --- a/decidim-system/config/locales/lv.yml +++ b/decidim-system/config/locales/lv.yml @@ -1,5 +1,22 @@ --- lv: + activemodel: + attributes: + oauth_application: + organization_logo: Organizācijas logotips (kvadrāts) + organization_url: Organizācijas URL + redirect_uri: Novirzīšanas URI + organization: + address: SMTP saimniekdatora nosaukums + password: Parole + port: Ports + user_name: Lietotājvārds + errors: + models: + oauth_application: + attributes: + redirect_uri: + must_be_ssl: Novirzīšanas URI jābūt SSL URI decidim: system: actions: diff --git a/decidim-system/config/locales/nl.yml b/decidim-system/config/locales/nl.yml index 4408f41f0f8c3..15a83b6adb3fe 100644 --- a/decidim-system/config/locales/nl.yml +++ b/decidim-system/config/locales/nl.yml @@ -2,6 +2,10 @@ nl: activemodel: attributes: + oauth_application: + organization_logo: Logo organisatie (vierkant) + organization_url: URL van de organisatie + redirect_uri: URI doorsturen organization: address: SMTP hostname from_email: E-mailadres @@ -9,6 +13,12 @@ nl: password: Wachtwoord port: Poort user_name: Gebruikersnaam + errors: + models: + oauth_application: + attributes: + redirect_uri: + must_be_ssl: De omleidings-URI moet een SSL-URI zijn decidim: system: actions: diff --git a/decidim-system/config/locales/pl.yml b/decidim-system/config/locales/pl.yml index e08ab9714db87..643089da18840 100644 --- a/decidim-system/config/locales/pl.yml +++ b/decidim-system/config/locales/pl.yml @@ -56,14 +56,31 @@ pl: create: Utwórz title: Nowy administrator show: + destroy: Zniszcz edit: Edytuj update: error: Podczas aktualizowania tego administratora wystąpił błąd. success: Administrator został zaktualizowany + dashboard: + show: + current_organizations: Bieżące organizacje default_pages: placeholders: content: Proszę dodać istotne treści do strony statycznej %{page} w panelu administratora. title: Domyślny tytuł dla %{page} + devise: + passwords: + edit: + change_your_password: Zmień swoje hasło + minimum_characters: "(Minimum %{minimum} znaków)" + new: + forgot_your_password: Zapomniałeś hasła + send_me_reset_password_instructions: Wyślij mi instrukcje resetowania hasła + shared: + links: + did_not_receive_confirmation_instructions?: Nie otrzymałeś(aś) instrukcji potwierdzenia? + did_not_receive_unlock_instructions?: Nie dotarła instrukcja odblokowania? + forgot_your_password?: Nie pamiętasz hasła? menu: admins: Administratorzy dashboard: Panel diff --git a/decidim-system/config/locales/ru.yml b/decidim-system/config/locales/ru.yml index 1a615c296a5f9..df0e5d9959e17 100644 --- a/decidim-system/config/locales/ru.yml +++ b/decidim-system/config/locales/ru.yml @@ -1,5 +1,22 @@ --- ru: + activemodel: + attributes: + oauth_application: + organization_logo: Логотип организации (квадрат) + organization_url: Веб-адрес организации + redirect_uri: URI перенаправления + organization: + address: Имя хоста SMTP + password: Пароль + port: Порт + user_name: Имя пользователя + errors: + models: + oauth_application: + attributes: + redirect_uri: + must_be_ssl: URI перенаправления должен быть SSL URI decidim: system: actions: diff --git a/decidim-system/config/locales/sk.yml b/decidim-system/config/locales/sk.yml index 05b81528007e7..29e4456a746f3 100644 --- a/decidim-system/config/locales/sk.yml +++ b/decidim-system/config/locales/sk.yml @@ -1,5 +1,22 @@ --- sk: + activemodel: + attributes: + oauth_application: + organization_logo: Logo organizácie (štvorec) + organization_url: Odkaz na stránku organizácie + redirect_uri: Presmerovať URI + organization: + address: SMTP hostname + password: Heslo + port: Port + user_name: Používateľské meno + errors: + models: + oauth_application: + attributes: + redirect_uri: + must_be_ssl: Presmerovacie URI musí byť SSL URI decidim: system: actions: diff --git a/decidim-system/config/locales/sl.yml b/decidim-system/config/locales/sl.yml index 1bbecbe8ec4d2..9c5955bb61522 100644 --- a/decidim-system/config/locales/sl.yml +++ b/decidim-system/config/locales/sl.yml @@ -1,5 +1,22 @@ --- sl: + activemodel: + attributes: + oauth_application: + organization_logo: Logo organizacije (kvadratni) + organization_url: Domača stran organizacije + redirect_uri: Preusmeritev URI + organization: + address: SMTP Gostitelj + password: Geslo + port: Vrata + user_name: Uporabniško ime + errors: + models: + oauth_application: + attributes: + redirect_uri: + must_be_ssl: URL preusmeritev mora bit SSL decidim: system: actions: diff --git a/decidim-system/config/locales/sr-CS.yml b/decidim-system/config/locales/sr-CS.yml index 25e8912f51d63..fa1b678387f1a 100644 --- a/decidim-system/config/locales/sr-CS.yml +++ b/decidim-system/config/locales/sr-CS.yml @@ -1,5 +1,22 @@ --- sr: + activemodel: + attributes: + oauth_application: + organization_logo: Logo organizacije (kvadrat) + organization_url: Link organizacije + redirect_uri: Preusmeren URL + organization: + address: SMTP domaćin + password: Šifra + port: Port + user_name: Korisničko ime + errors: + models: + oauth_application: + attributes: + redirect_uri: + must_be_ssl: URI za preusmeravanje mora biti SSL URI decidim: system: models: diff --git a/decidim-system/config/locales/uk.yml b/decidim-system/config/locales/uk.yml index 80b988990ad1a..69a5e0df8eaf5 100644 --- a/decidim-system/config/locales/uk.yml +++ b/decidim-system/config/locales/uk.yml @@ -1,5 +1,17 @@ --- uk: + activemodel: + attributes: + oauth_application: + organization_logo: Логотип організації (квадрат) + organization_url: Адреса сайту організації + redirect_uri: URI перенаправлення + errors: + models: + oauth_application: + attributes: + redirect_uri: + must_be_ssl: URI перенаправлення має бути SSL URI decidim: system: actions: diff --git a/decidim-system/lib/decidim/system/version.rb b/decidim-system/lib/decidim/system/version.rb index 83820294c3b0e..579f1863d3933 100644 --- a/decidim-system/lib/decidim/system/version.rb +++ b/decidim-system/lib/decidim/system/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-system version. module System def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-system/spec/commands/decidim/system/register_organization_spec.rb b/decidim-system/spec/commands/decidim/system/register_organization_spec.rb index 7dc169d410058..b828449bc9f6a 100644 --- a/decidim-system/spec/commands/decidim/system/register_organization_spec.rb +++ b/decidim-system/spec/commands/decidim/system/register_organization_spec.rb @@ -17,21 +17,21 @@ module System let(:params) do { name: "Gotham City", - host: "decide.gotham.gov", - secondary_hosts: "foo.gotham.gov\r\n\r\nbar.gotham.gov", + host: "decide.example.org", + secondary_hosts: "foo.example.org\r\n\r\nbar.example.org", reference_prefix: "JKR", organization_admin_name: "Fiorello Henry La Guardia", - organization_admin_email: "f.laguardia@gotham.gov", + organization_admin_email: "f.laguardia@example.org", available_locales: ["en"], default_locale: "en", users_registration_mode: "enabled", force_users_to_authenticate_before_access_organization: "false", smtp_settings: { - "address" => "mail.gotham.gov", + "address" => "mail.example.org", "port" => "25", "user_name" => "f.laguardia", "password" => Decidim::AttributeEncryptor.encrypt("password"), - "from_email" => "decide@gotham.gov", + "from_email" => "decide@example.org", "from_label" => from_label }, omniauth_settings_facebook_enabled: true, @@ -53,11 +53,11 @@ module System organization = Organization.last expect(organization.name).to eq("Gotham City") - expect(organization.host).to eq("decide.gotham.gov") - expect(organization.secondary_hosts).to match_array(["foo.gotham.gov", "bar.gotham.gov"]) - expect(organization.external_domain_whitelist).to match_array(["decidim.org", "github.com"]) - expect(organization.smtp_settings["from"]).to eq("Decide Gotham ") - expect(organization.smtp_settings["from_email"]).to eq("decide@gotham.gov") + expect(organization.host).to eq("decide.example.org") + expect(organization.secondary_hosts).to contain_exactly("foo.example.org", "bar.example.org") + expect(organization.external_domain_whitelist).to contain_exactly("decidim.org", "github.com") + expect(organization.smtp_settings["from"]).to eq("Decide Gotham ") + expect(organization.smtp_settings["from_email"]).to eq("decide@example.org") expect(organization.omniauth_settings["omniauth_settings_facebook_enabled"]).to be(true) expect(organization.file_upload_settings).to eq(upload_settings) expect( @@ -72,7 +72,7 @@ module System expect { command.call }.to change(User, :count).by(1) admin = User.last - expect(admin.email).to eq("f.laguardia@gotham.gov") + expect(admin.email).to eq("f.laguardia@example.org") expect(admin.organization.name).to eq("Gotham City") expect(admin).to be_admin expect(admin).to be_created_by_invite @@ -115,10 +115,10 @@ module System organization = Organization.last - expect(organization.smtp_settings["from"]).to eq("Decide Gotham ") + expect(organization.smtp_settings["from"]).to eq("Decide Gotham ") expect(organization.smtp_settings["from_label"]).to eq("Decide Gotham") - expect(organization.smtp_settings["from_email"]).to eq("decide@gotham.gov") - expect(last_email.From.value).to eq("Decide Gotham ") + expect(organization.smtp_settings["from_email"]).to eq("decide@example.org") + expect(last_email.From.value).to eq("Decide Gotham ") end context "when from_label is empty" do @@ -131,9 +131,9 @@ module System organization = Organization.last - expect(organization.smtp_settings["from"]).to eq("decide@gotham.gov") - expect(organization.smtp_settings["from_email"]).to eq("decide@gotham.gov") - expect(last_email.From.value).to eq("decide@gotham.gov") + expect(organization.smtp_settings["from"]).to eq("decide@example.org") + expect(organization.smtp_settings["from_email"]).to eq("decide@example.org") + expect(last_email.From.value).to eq("Gotham City ") end end end diff --git a/decidim-system/spec/commands/decidim/system/update_organization_spec.rb b/decidim-system/spec/commands/decidim/system/update_organization_spec.rb index ed8b694acca0a..16ec181b82f55 100644 --- a/decidim-system/spec/commands/decidim/system/update_organization_spec.rb +++ b/decidim-system/spec/commands/decidim/system/update_organization_spec.rb @@ -18,16 +18,16 @@ module System let(:params) do { name: "Gotham City", - host: "decide.gotham.gov", - secondary_hosts: "foo.gotham.gov\r\n\r\nbar.gotham.gov", + host: "decide.example.org", + secondary_hosts: "foo.example.org\r\n\r\nbar.example.org", force_users_to_authenticate_before_access_organization: false, users_registration_mode: "existing", smtp_settings: { - "address" => "mail.gotham.gov", + "address" => "mail.example.org", "port" => "25", "user_name" => "f.laguardia", "password" => Decidim::AttributeEncryptor.encrypt("password"), - "from_email" => "decide@gotham.gov", + "from_email" => "decide@example.org", "from_label" => from_label }, omniauth_settings_facebook_enabled: true, @@ -49,11 +49,11 @@ module System organization = Organization.last expect(organization.name).to eq("Gotham City") - expect(organization.host).to eq("decide.gotham.gov") - expect(organization.secondary_hosts).to match_array(["foo.gotham.gov", "bar.gotham.gov"]) + expect(organization.host).to eq("decide.example.org") + expect(organization.secondary_hosts).to contain_exactly("foo.example.org", "bar.example.org") expect(organization.users_registration_mode).to eq("existing") - expect(organization.smtp_settings["from"]).to eq("Decide Gotham ") - expect(organization.smtp_settings["from_email"]).to eq("decide@gotham.gov") + expect(organization.smtp_settings["from"]).to eq("Decide Gotham ") + expect(organization.smtp_settings["from_email"]).to eq("decide@example.org") expect(organization.omniauth_settings["omniauth_settings_facebook_enabled"]).to be(true) expect(organization.file_upload_settings).to eq(upload_settings) expect( @@ -72,8 +72,8 @@ module System command.call organization = Organization.last - expect(organization.smtp_settings["from"]).to eq("decide@gotham.gov") - expect(organization.smtp_settings["from_email"]).to eq("decide@gotham.gov") + expect(organization.smtp_settings["from"]).to eq("decide@example.org") + expect(organization.smtp_settings["from_email"]).to eq("decide@example.org") end end end diff --git a/decidim-system/spec/forms/decidim/system/update_organization_form_spec.rb b/decidim-system/spec/forms/decidim/system/update_organization_form_spec.rb index e2f7331207f72..76e731f2f24ef 100644 --- a/decidim-system/spec/forms/decidim/system/update_organization_form_spec.rb +++ b/decidim-system/spec/forms/decidim/system/update_organization_form_spec.rb @@ -7,11 +7,11 @@ module Decidim::System subject do described_class.new( name: "Gotham City", - host: "decide.gotham.gov", - secondary_hosts: "foo.gotham.gov\r\n\r\nbar.gotham.gov", + host: "decide.example.org", + secondary_hosts: "foo.example.org\r\n\r\nbar.example.org", reference_prefix: "JKR", organization_admin_name: "Fiorello Henry La Guardia", - organization_admin_email: "f.laguardia@gotham.gov", + organization_admin_email: "f.laguardia@example.org", available_locales: ["en"], default_locale: "en", users_registration_mode: "enabled", @@ -27,11 +27,11 @@ module Decidim::System let(:smtp_settings) do { - "address" => "mail.gotham.gov", + "address" => "mail.example.org", "port" => 25, "user_name" => "f.laguardia", "password" => password, - "from_email" => "decide@gotham.gov", + "from_email" => "decide@example.org", "from_label" => from_label } end @@ -69,7 +69,7 @@ module Decidim::System it "concatenates from_label and from_email" do from = subject.set_from - expect(from).to eq("Decide Gotham ") + expect(from).to eq("Decide Gotham ") end context "when from_label is empty" do @@ -78,7 +78,7 @@ module Decidim::System it "returns the email" do from = subject.set_from - expect(from).to eq("decide@gotham.gov") + expect(from).to eq("decide@example.org") end end end diff --git a/decidim-system/spec/system/organizations_spec.rb b/decidim-system/spec/system/organizations_spec.rb index 5ce62a6f3c505..a1b1c674bcc23 100644 --- a/decidim-system/spec/system/organizations_spec.rb +++ b/decidim-system/spec/system/organizations_spec.rb @@ -53,6 +53,48 @@ expect(page).to have_content("There's an error in this field") end end + + context "with an invalid organization admin name" do + before do + click_on "Organizations" + click_on "New" + end + + it "does not create an organization" do + fill_in "Name", with: "Citizen Corp 2" + fill_in "Reference prefix", with: "CCORP" + fill_in "Host", with: "www.example.org" + fill_in "Organization admin name", with: "system@example.org" + fill_in "Organization admin email", with: "system@example.org" + check "organization_available_locales_en" + choose "organization_default_locale_en" + choose "Allow participants to register and login" + + click_on "Create organization & invite admin" + + within ".flash", match: :first do + expect(page).to have_content("There was a problem creating a new organization. Review your organization admin name.") + end + end + end + + context "without the secret key defined" do + before do + allow(Rails.application.secrets).to receive(:secret_key_base).and_return(nil) + end + + it "does not create an organization" do + fill_in "Name", with: "Citizen Corp" + fill_in "Host", with: "www.example.org" + fill_in "Reference prefix", with: "CCORP" + fill_in "Organization admin name", with: "City Mayor" + fill_in "Organization admin email", with: "mayor@example.org" + click_on "Create organization & invite admin" + + click_on "Show advanced settings" + expect(page).to have_content("You need to define the SECRET_KEY_BASE environment variable to be able to save this field") + end + end end describe "showing an organization with different locale than user" do @@ -102,6 +144,21 @@ expect(page).to have_css("div.flash.success") expect(page).to have_content("Citizens Rule!") end + + context "without the secret key defined" do + before do + allow(Rails.application.secrets).to receive(:secret_key_base).and_return(nil) + end + + it "shows the error message" do + fill_in "Name", with: "Citizens Rule!" + fill_in "Host", with: "www.example.org" + click_on "Save" + + click_on "Show advanced settings" + expect(page).to have_content("You need to define the SECRET_KEY_BASE environment variable to be able to save this field") + end + end end describe "editing an organization with disabled OmniAuth provider" do diff --git a/decidim-templates/app/views/decidim/templates/admin/questionnaire_templates/_preview.html.erb b/decidim-templates/app/views/decidim/templates/admin/questionnaire_templates/_preview.html.erb index 0050cdb90bb79..c2cbe2b588b57 100644 --- a/decidim-templates/app/views/decidim/templates/admin/questionnaire_templates/_preview.html.erb +++ b/decidim-templates/app/views/decidim/templates/admin/questionnaire_templates/_preview.html.erb @@ -14,7 +14,7 @@
    - <%= decidim_form_for(@preview_form, url: "", method: :post, html: { class: "form answer-questionnaire" }, data: { "safe-path" => "" }) do |form| %> + <%= decidim_form_for(@preview_form, url: "", method: :post, authenticity_token: !defined?(skip_authenticity_token), html: { class: "form answer-questionnaire" }, data: { "safe-path" => "" }) do |form| %> <%= invisible_captcha %> <% answer_idx = 0 %> <% cleaned_answer_idx = 0 %> diff --git a/decidim-templates/app/views/decidim/templates/admin/questionnaire_templates/preview.js.erb b/decidim-templates/app/views/decidim/templates/admin/questionnaire_templates/preview.js.erb index da247b34be757..3b43cbb5e9d12 100644 --- a/decidim-templates/app/views/decidim/templates/admin/questionnaire_templates/preview.js.erb +++ b/decidim-templates/app/views/decidim/templates/admin/questionnaire_templates/preview.js.erb @@ -7,5 +7,5 @@ $templateName.html("<%= translated_attribute @template.name %>"); $templateDescription.html("<%= translated_attribute @template.description %>"); - $preview.html("<%= j(render partial: "preview", locals: { questionnaire: @questionnaire }) %>"); + $preview.html("<%= j(render partial: "preview", locals: { skip_authenticity_token: true, questionnaire: @questionnaire }) %>"); }()); diff --git a/decidim-templates/config/locales/bg.yml b/decidim-templates/config/locales/bg.yml index d0e375da96f10..86d148de4a43c 100644 --- a/decidim-templates/config/locales/bg.yml +++ b/decidim-templates/config/locales/bg.yml @@ -1 +1,74 @@ +--- bg: + activemodel: + attributes: + questionnaire: + title: Заглавие + template: + description: Описание + name: Име + decidim: + admin: + menu: + templates: Шаблони + templates: + apply: + error: Възникна проблем при прилагането на този шаблон. + success: Шаблонът е приложен успешно + copy: + error: Възникна проблем при копирането на този шаблон. + success: Шаблонът е копиран успешно + create: + error: Възникна проблем при създаването на този шаблон. + success: Шаблонът е създаден успешно + destroy: + success: Шаблонът е изтрит успешно + empty: Все още няма шаблони. + update: + error: Възникна проблем при обновяването на този шаблон. + success: Шаблонът е обновен успешно + titles: + template_types: + questionnaires: Шаблони за въпросници + templates: Шаблони + models: + questionnaire_template: + fields: + questions: Брой въпроси + title: Заглавие на въпросник + template: + fields: + created_at: Създаден на + name: Шаблон + templates: + admin: + questionnaire_templates: + choose: + create_from_template: Създайте от шаблон + description: На път сте да създадете нов въпросник. Можете да изберете предварително дефиниран шаблон и да го промените след това. + label: Избор на шаблон + placeholder: Избор на шаблон + skip_template: Пропусни + edit: + edit: Редактирай + empty: Все още няма въпроси + questionnaire: Въпросник + form: + save: Запази + template_title: Информация за шаблона + title: Шаблон за въпросник %{questionnaire_for} + index: + confirm_delete: Сигурни ли сте, че желаете да изтриете този шаблон? + title: Шаблони за въпросници + preview: + current_step: Стъпка %{step} + of_total_steps: от %{total_steps} + tos_agreement: С участието си приемате Условията на услугата + admin_log: + template: + create: "%{user_name} създаде шаблона на въпросника %{resource_name}" + delete: "%{user_name} изтри шаблона на въпросника %{resource_name}" + duplicate: "%{user_name} дублира шаблона на въпросника %{resource_name}" + update: "%{user_name} актуализира шаблона на въпросника %{resource_name}" + template_types: + questionnaires: Въпросници diff --git a/decidim-templates/config/locales/he-IL.yml b/decidim-templates/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-templates/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-templates/config/locales/pl.yml b/decidim-templates/config/locales/pl.yml index f154b3042b1ab..1e81d8e6ea1a1 100644 --- a/decidim-templates/config/locales/pl.yml +++ b/decidim-templates/config/locales/pl.yml @@ -1,5 +1,12 @@ --- pl: + activemodel: + attributes: + questionnaire: + title: Tytuł + template: + description: Opis + name: Nazwa decidim: admin: menu: diff --git a/decidim-templates/decidim-templates.gemspec b/decidim-templates/decidim-templates.gemspec index 787b80097903a..ccd970ce2c093 100644 --- a/decidim-templates/decidim-templates.gemspec +++ b/decidim-templates/decidim-templates.gemspec @@ -28,4 +28,6 @@ Gem::Specification.new do |s| s.add_development_dependency "decidim-admin", Decidim::Templates.version s.add_development_dependency "decidim-dev", Decidim::Templates.version + s.add_development_dependency "decidim-participatory_processes", Decidim::Templates.version + s.add_development_dependency "decidim-surveys", Decidim::Templates.version end diff --git a/decidim-templates/lib/decidim/templates/test/factories.rb b/decidim-templates/lib/decidim/templates/test/factories.rb index ed94c23d09fe2..acb384f268bd2 100644 --- a/decidim-templates/lib/decidim/templates/test/factories.rb +++ b/decidim-templates/lib/decidim/templates/test/factories.rb @@ -5,28 +5,35 @@ FactoryBot.define do factory :template, class: "Decidim::Templates::Template" do + transient do + skip_injection { false } + end organization - templatable { build(:dummy_resource) } - name { Decidim::Faker::Localized.sentence } + name { generate_localized_title(:template_name, skip_injection: skip_injection) } + description { generate_localized_title(:template_description, skip_injection: skip_injection) } + templatable { build(:dummy_resource, skip_injection: skip_injection) } ## Questionnaire templates factory :questionnaire_template do + transient do + skip_injection { false } + end trait :with_questions do - after(:create) do |template| - template.templatable = create(:questionnaire, :with_questions, questionnaire_for: template) + after(:create) do |template, evaluator| + template.templatable = create(:questionnaire, :with_questions, questionnaire_for: template, skip_injection: evaluator.skip_injection) template.save! end end trait :with_all_questions do - after(:create) do |template| - template.templatable = create(:questionnaire, :with_all_questions, questionnaire_for: template) + after(:create) do |template, evaluator| + template.templatable = create(:questionnaire, :with_all_questions, questionnaire_for: template, skip_injection: evaluator.skip_injection) template.save! end end - after(:create) do |template| - template.templatable = create(:questionnaire, questionnaire_for: template) + after(:create) do |template, evaluator| + template.templatable = create(:questionnaire, questionnaire_for: template, skip_injection: evaluator.skip_injection) template.save! end end diff --git a/decidim-templates/lib/decidim/templates/test/shared_examples/uses_questionnaire_templates.rb b/decidim-templates/lib/decidim/templates/test/shared_examples/uses_questionnaire_templates.rb index fa180e608c57b..979af6e3f75cf 100644 --- a/decidim-templates/lib/decidim/templates/test/shared_examples/uses_questionnaire_templates.rb +++ b/decidim-templates/lib/decidim/templates/test/shared_examples/uses_questionnaire_templates.rb @@ -20,7 +20,7 @@ end context "when there are templates" do - let!(:templates) { create_list(:questionnaire_template, 6, :with_questions, organization: questionnaire.questionnaire_for.organization) } + let!(:templates) { create_list(:questionnaire_template, 6, :with_questions, skip_injection: true, organization: questionnaire.questionnaire_for.organization) } let(:template) { templates.first } let(:question) { template.templatable.questions.first } @@ -74,7 +74,7 @@ end describe "apply a template" do - let!(:templates) { create_list(:questionnaire_template, 6, :with_questions, organization: questionnaire.questionnaire_for.organization) } + let!(:templates) { create_list(:questionnaire_template, 6, :with_questions, skip_injection: true, organization: questionnaire.questionnaire_for.organization) } let(:template) { templates.first } let(:question) { template.templatable.questions.first } let(:questionnaire_question) { questionnaire.questions.first } diff --git a/decidim-templates/lib/decidim/templates/version.rb b/decidim-templates/lib/decidim/templates/version.rb index 966f103ae7a30..8fb03be24eeb5 100644 --- a/decidim-templates/lib/decidim/templates/version.rb +++ b/decidim-templates/lib/decidim/templates/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-templates version. module Templates def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim-templates/spec/factories.rb b/decidim-templates/spec/factories.rb index 02f6849bb118b..e755d0639ccae 100644 --- a/decidim-templates/spec/factories.rb +++ b/decidim-templates/spec/factories.rb @@ -3,3 +3,4 @@ require "decidim/core/test/factories" require "decidim/forms/test/factories" require "decidim/templates/test/factories" +require "decidim/participatory_processes/test/factories" diff --git a/decidim-templates/spec/system/admin/admin_applies_questionnaire_template_to_component_spec.rb b/decidim-templates/spec/system/admin/admin_applies_questionnaire_template_to_component_spec.rb new file mode 100644 index 0000000000000..17d215c798b16 --- /dev/null +++ b/decidim-templates/spec/system/admin/admin_applies_questionnaire_template_to_component_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe "Admin applies questionnaire templates", type: :system do + let!(:organization) { create(:organization) } + let!(:user) { create(:user, :admin, :confirmed, organization: organization) } + let!(:participatory_space) { create(:participatory_process, organization: organization) } + let!(:component) { create(:component, participatory_space: participatory_space) } + let!(:questionnaire_template) { create(:questionnaire_template, :with_all_questions, organization: organization, skip_injection: true) } + + around do |example| + ActionController::Base.allow_forgery_protection = true + example.run + ActionController::Base.allow_forgery_protection = false + end + + before do + switch_to_host(organization.host) + login_as user, scope: :user + visit decidim_admin_participatory_processes.components_path(participatory_space) + end + + it "installs a survey component" do + find("button[data-toggle=add-component-dropdown]").click + + within "#add-component-dropdown" do + find(".surveys").click + end + + click_on "Add component" + click_on "Survey" + + page.all("svg.icon--pencil")[1].click + + select(translated_attribute(questionnaire_template.name), from: "select-template") + expect(page).to have_content("If you are human, ignore this field") + click_on "Create from template" + + expect(page).to have_content("Template applied successfully") + end +end diff --git a/decidim-verifications/config/locales/bg.yml b/decidim-verifications/config/locales/bg.yml index 88bcfe13feb4f..30c928daa02cb 100644 --- a/decidim-verifications/config/locales/bg.yml +++ b/decidim-verifications/config/locales/bg.yml @@ -3,17 +3,279 @@ bg: activemodel: attributes: config: - available_methods: Достъпни методи - offline: Извън линия - offline_explanation: Инструкции за проверка извън линия - online: На линия + available_methods: Възможни методи + offline: Офлайн + offline_explanation: Инструкции за офлайн верификация + online: Онлайн + confirmation: + verification_code: Код за потвърждение id_document_information: document_number: Номер на документ (с буквите) document_type: Тип на документа + id_document_upload: + document_number: Номер на документа (с буква) + document_type: Тип на Вашия документ + user: Участник + verification_attachment: Сканирано копие на Вашия документ + mobile_phone: + mobile_phone_number: Номер на мобилен телефон + offline_confirmation: + email: Имейл на участника + postal_letter_address: + full_address: Пълен адрес + postal_letter_confirmation: + verification_code: Код за потвърждение + postal_letter_postage: + full_address: Пълен адрес + verification_code: Код за потвърждение + errors: + models: + census_data: + attributes: + file: + malformed: Неправилен файл за импортиране, моля, прочетете внимателно инструкциите и се уверете, че файлът е UTF-8 кодиран. decidim: + admin: + menu: + authorization_revocation: + before_date_info: Полезна функция, ако процесът вече е започнал и искате да анулирате разрешенията на предходния процес. + button: Отмени всичко + button_before: Отмени преди дата + destroy: + confirm: Отмяната на оторизациите преди определена дата е действие, което не може да бъде отменено. Сигурни ли сте, че искате да продължите? + confirm_all: Отмяната на всички оторизации е действие, което не може да бъде отменено. Сигурни ли сте, че искате да продължите? + destroy_nok: Възникна проблем при отмяната на оторизации. + destroy_ok: Всички съвпадащи оторизации бяха отменени успешно. + info: Има общо %{count} потвърдени участници. + no_data: Няма потвърдени участници + title: Оторизации за отмяна + authorization_workflows: Оторизации + admin_log: + organization: + update_id_documents_config: "%{user_name} актуализира конфигурацията за оторизация на документи за самоличност" + user: + grant_id_documents_offline_verification: "%{user_name} потвърди %{resource_name}, като използва офлайн проверка на документите за самоличност" + authorization_handlers: + admin: + csv_census: + help: + - Администраторите качват CSV с имейлите на приетите участници + - Само участници с имейл в този CSV файл могат да бъдат потвърдени + id_documents: + help: + - Потребителите попълват своята информация за самоличност и качват копие на своя документ. + - Попълнете информацията, присъстваща в каченото изображение. + - Информацията трябва да съответства на това, което е попълнил потребителят. + - Ако не можете да видите ясно информацията или не можете да я проверите, можете да отхвърлите заявката и потребителят ще има възможността да я коригира. + postal_letter: + help: + - Участниците искат да им бъде изпратен код за потвърждение на техния адрес. + - Изпращате писмото до техния адрес с кода за потвърждение. + - Маркирате писмото като "изпратено". + - След като маркирате писмото като изпратено, участникът ще може да въведе кода и да бъде потвърден. + csv_census: + explanation: Потвърждение чрез преброяването на участниците в организацията + name: Преброяване на участниците в организацията + direct: Директен + help: Помощ + id_documents: + explanation: Качете документите си за самоличност, за да можем да проверим самоличността Ви + name: Документи за самоличност + multistep: Много-стъпков + name: Име + postal_letter: + explanation: Ще Ви изпратим писмо по пощата с код, който ще трябва да въведете, за да потвърдим адреса Ви + name: Код с писмо по пощата + events: + verifications: + verify_with_managed_user: + email_intro: Участникът %{resource_title} се е опитал да се удостовери с данните на друг участник (%{managed_user_name}). + email_outro: Проверете Списък с конфликти при верификация и се свържете с участника, за да потвърдите данните му и да разрешите проблема. + email_subject: Неуспешен опит за проверка към друг участник + notification_title: Участникът %{resource_title} се е опитал да се удостовери с данните на друг участник (%{managed_user_name}). verifications: + authorizations: + authorization_metadata: + info: 'Това са данните от текущото потвърждение:' + no_data_stored: Няма съхранени данни. + create: + error: Възникна проблем при създаването на оторизацията. + success: Успешно се удостоверихте. + unconfirmed: Трябва да потвърдите имейла си, с оглед на Вашата оторизация. + destroy: + error: Възникна проблем при изтриването на оторизацията. + success: Успешно изтрихте удостоверяването. + first_login: + actions: + another_dummy_authorization_handler: Проверка спрямо друг манипулатор на оторизации + csv_census: Проверка спрямо преброяването на участниците в организацията + dummy_authorization_handler: Проверка спрямо примерния инструмент за оторизация + dummy_authorization_workflow: Проверка спрямо примерния работен процес за оторизиране + id_documents: Потвърдете самоличността си, като качите документ за самоличност + postal_letter: Верифицирайте се, чрез получаване на оторизационен код по пощата + sms: Верифицирайте се, чрез получаване на оторизационен код с SMS + title: Потвърждение на Вашата самоличност + verify_with_these_options: 'Това са възможните опции, с които да потвърдите самоличността си:' + index: + expired_verification: Изтекло потвърждение + pending_verification: Очаква проверка + show_renew_info: Щракнете, за да подновите верификацията + unauthorized_verification: Ново потвърждение + new: + authorize: Изпрати + authorize_with: Потвърждение чрез %{authorizer} + renew_modal: + cancel: Отмяна + close: затваряне + continue: Продължи + info_renew: Ако искате да актуализирате данните, продължете с подновяването + title: Подновяване на верификацията + skip_verification: Можете да пропуснете това засега и %{link} + start_exploring: започнете да разглеждате + csv_census: + admin: + census: + create: + error: Възникна грешка при импортирането на преброяването. + success: Успешно бяха импортирани %{count} елемента (%{errors} грешки) + destroy_all: + success: Всички данни от преброяването бяха изтрити + destroy: + confirm: Изтриването на преброяването е действие, което не може да бъде отменено. Сигурни ли сте, че искате да продължите? + title: Изтриване на всички данни от преброяването + index: + data: Заредени са общо %{count} записа. Датата на последното качване е на %{due_date} + empty: Няма данни от преброяването. Използвайте формуляра по-долу, за да ги импортирате чрез файл във формат CSV. + title: Текущи данни от преброяването + instructions: + body: За тази цел трябва да влезете в администрацията на системата и да добавите оторизация за csv_census в организацията + title: Трябва да активирате преброяването чрез файл във формат CSV за тази организация + new: + file: "файл във формат .csv с данни за електронните пощи" + info: 'Трябва да бъде файл във формат CSV, съдържащ само една колона с електронната поща:' + submit: Качване на файл + title: Качване на ново преброяване + authorizations: + new: + error: Не можахме да потвърдим вашия акаунт или не сте в преброяването на организацията. + success: Профилът Ви беше потвърден успешно. dummy_authorization: extra_explanation: postal_codes: one: Участието е ограничено до участници с пощенски код %{postal_codes}. other: 'Участието е ограничено до участници с пощенски кодове %{postal_codes}.' + scope: Участието е ограничено до участници в обхвата %{scope_name}. + user_postal_codes: + one: Участието е ограничено до участници с пощенски код %{postal_codes}, а вашият пощенски код е %{user_postal_code}. + other: 'Участието е ограничено до участници с някой от следните пощенски кодове: %{postal_codes}. Вашият пощенски код е %{user_postal_code}.' + user_scope: Участието е ограничено до участници с обхват %{scope_name}, а вашият обхват е %{user_scope_name}. + id_documents: + admin: + config: + edit: + title: Конфигурация на документите за самоличност + update: Обновяване + update: + error: Възникна проблем при актуализирането на конфигурацията. + success: Конфигурирането е успешно обновено + confirmations: + create: + error: Потвърждението не съвпада. Моля, опитайте отново или отхвърлете потвърждението, за да може участникът да го коригира. + success: Участникът беше потвърден успешно + new: + introduce_user_data: Въведете данните от изображението + reject: Откажи + verify: Провери + offline_confirmations: + create: + error: Потвърждението не съвпада. Моля, опитайте отново или кажете на участника да го коригира + success: Участникът беше потвърден успешно + new: + cancel: Отказ + introduce_user_data: Въведете електронната поща на участника и данните от документа + verify: Провери + pending_authorizations: + index: + config: Конфигуриране + offline_verification: Офлайн проверка + title: Изчакващи онлайн проверки + verification_number: 'Верификация #%{n}' + rejections: + create: + success: Потвърждението беше отхвърлено. Участниците ще получат напомняне да коригират документите си + authorizations: + choose: + choose_a_type: 'Моля, изберете как искате да бъдете проверен:' + offline: Офлайн + online: Онлайн + title: Потвърдете личноста си, чрез документ за самоличност + create: + error: Възникна грешка при качването на документа Ви + success: Документът беше качен успешно + edit: + being_reviewed: Преглеждаме документите Ви. Скоро ще потвърдим самоличността Ви. + offline: Използване на офлайн верификация + online: Използване на онлайн верификация + rejection_clarity: Уверете се, че информацията се вижда ясно в каченото изображение + rejection_correctness: Уверете се, че въведената информация е правилна + rejection_notice: Възникна проблем с потвърждението на самоличността Ви. Моля, опитайте отново + send: Заявете верификация отново + new: + send: Заявете верификация + title: Качете Вашия документ за самоличност + update: + error: Възникна грешка при повторното качване на документа Ви. + success: Документът беше успешно качен повторно. + identification_number: ЕГН + passport: Паспорт/лична карта + postal_letter: + admin: + pending_authorizations: + index: + address: Адрес + letter_sent_at: Писмо изпратено на + mark_as_sent: Маркирй като "изпратено" + not_yet_sent: Все още не е изпратено + title: Изходящи верификации + username: Псевдоним + verification_code: Код за потвърждение + postages: + create: + error: Грешка при обозначаването на писмото като "изпратено". + success: Писмото беше обозначено успешно като "изпратено". + authorizations: + create: + error: Възникна проблем със заявката Ви + success: Благодарим Ви! Ще изпратим код за потвърждение на Вашия адрес + edit: + send: Потвърди + title: Въведете кода за потвърждение, който получихте + waiting_for_letter: Скоро ще изпратим писмо с код за потвърждение на Вашия адрес + new: + send: Изпратете ми писмо + title: Заявете кода си за потвърждение + update: + error: Кодът Ви за потвърждение не съвпада с нашия. Моля, проверете отново писмото, което Ви изпратихме + success: Поздравления! Успешно потвърдихте самоличността си. + sms: + authorizations: + create: + error: Възникна проблем със заявката Ви + success: Благодарим Ви! Изпратихме SMS на Вашия телефон.. + destroy: + success: Кодът за потвърждение беше успешно презареден. Моля, въведете повторно телефонния си номер. + edit: + confirm_destroy: Сигурни ли сте, че желаете да преиздадете кода за потвърждение? + destroy: Преиздаване на код за потвърждение + resend: Не получихте ли кода за потвърждение? + send: Потвърди + title: Въведете кода за потвърждение, който получихте + new: + send: Изпратете ми SMS + title: Заявете кода си за потвърждение + update: + error: Кодът Ви за потвърждение не съвпада с нашия. Моля, проверете отново съобщението, което Ви изпратихме със SMS. + success: Поздравления. Успешно потвърдихте самоличността си. + errors: + messages: + uppercase_only_letters_numbers: трябва да бъде само с главни букви и да съдържа само букви и/или цифри diff --git a/decidim-verifications/config/locales/he-IL.yml b/decidim-verifications/config/locales/he-IL.yml new file mode 100644 index 0000000000000..af6fa60a73f2c --- /dev/null +++ b/decidim-verifications/config/locales/he-IL.yml @@ -0,0 +1 @@ +he: diff --git a/decidim-verifications/config/locales/pl.yml b/decidim-verifications/config/locales/pl.yml index 311549bcdbb12..18e4275bda73a 100644 --- a/decidim-verifications/config/locales/pl.yml +++ b/decidim-verifications/config/locales/pl.yml @@ -76,6 +76,13 @@ pl: postal_letter: explanation: Wyślemy Ci list pocztowy z kodem, który musisz wprowadzić, abyśmy mogli zweryfikować twój adres name: Kod listem pocztowym + events: + verifications: + verify_with_managed_user: + email_intro: Uczestnik %{resource_title} próbował zweryfikować siebie z danymi innego uczestnika (%{managed_user_name}). + email_outro: Sprawdź listę konfliktów weryfikacji i skontaktuj się z uczestnikiem, aby zweryfikować jego dane i rozwiązać problem. + email_subject: Nieudana próba weryfikacji względem innego uczestnika + notification_title: Uczestnik %{resource_title} próbował zweryfikować siebie z danymi innego uczestnika (%{managed_user_name}). verifications: authorizations: authorization_metadata: @@ -210,6 +217,9 @@ pl: new: send: Poproś o weryfikację title: Prześlij swój dokument tożsamości + update: + error: Podczas ponownego ładowania dokumentu wystąpił błąd. + success: Ponowne przesyłanie dokumentu się powiodło. identification_number: Numer identyfikacyjny passport: Paszport postal_letter: diff --git a/decidim-verifications/lib/decidim/verifications/test/factories.rb b/decidim-verifications/lib/decidim/verifications/test/factories.rb index e0c2128f50ed3..b2d251fd348b9 100644 --- a/decidim-verifications/lib/decidim/verifications/test/factories.rb +++ b/decidim-verifications/lib/decidim/verifications/test/factories.rb @@ -5,13 +5,19 @@ FactoryBot.define do factory :csv_datum, class: "Decidim::Verifications::CsvDatum" do + transient do + skip_injection { false } + end email { generate(:email) } organization end factory :conflict, class: "Decidim::Verifications::Conflict" do - current_user { create(:user) } - managed_user { create(:user, managed: true, organization: current_user.organization) } + transient do + skip_injection { false } + end + current_user { create(:user, skip_injection: skip_injection) } + managed_user { create(:user, managed: true, organization: current_user.organization, skip_injection: skip_injection) } unique_id { "12345678X" } times { 1 } end diff --git a/decidim-verifications/lib/decidim/verifications/version.rb b/decidim-verifications/lib/decidim/verifications/version.rb index 687770f719ba7..4b06e62e62f42 100644 --- a/decidim-verifications/lib/decidim/verifications/version.rb +++ b/decidim-verifications/lib/decidim/verifications/version.rb @@ -4,7 +4,7 @@ module Decidim # This holds the decidim-verifications version. module Verifications def self.version - "0.27.5" + "0.27.6" end end end diff --git a/decidim_app-design/Gemfile.lock b/decidim_app-design/Gemfile.lock index aea3d209b8151..1529531b5f5bf 100644 --- a/decidim_app-design/Gemfile.lock +++ b/decidim_app-design/Gemfile.lock @@ -1,63 +1,63 @@ PATH remote: .. specs: - decidim (0.27.5) - decidim-accountability (= 0.27.5) - decidim-admin (= 0.27.5) - decidim-api (= 0.27.5) - decidim-assemblies (= 0.27.5) - decidim-blogs (= 0.27.5) - decidim-budgets (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-debates (= 0.27.5) - decidim-forms (= 0.27.5) - decidim-generators (= 0.27.5) - decidim-meetings (= 0.27.5) - decidim-pages (= 0.27.5) - decidim-participatory_processes (= 0.27.5) - decidim-proposals (= 0.27.5) - decidim-sortitions (= 0.27.5) - decidim-surveys (= 0.27.5) - decidim-system (= 0.27.5) - decidim-templates (= 0.27.5) - decidim-verifications (= 0.27.5) - decidim-accountability (0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-admin (0.27.5) + decidim (0.27.6) + decidim-accountability (= 0.27.6) + decidim-admin (= 0.27.6) + decidim-api (= 0.27.6) + decidim-assemblies (= 0.27.6) + decidim-blogs (= 0.27.6) + decidim-budgets (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-debates (= 0.27.6) + decidim-forms (= 0.27.6) + decidim-generators (= 0.27.6) + decidim-meetings (= 0.27.6) + decidim-pages (= 0.27.6) + decidim-participatory_processes (= 0.27.6) + decidim-proposals (= 0.27.6) + decidim-sortitions (= 0.27.6) + decidim-surveys (= 0.27.6) + decidim-system (= 0.27.6) + decidim-templates (= 0.27.6) + decidim-verifications (= 0.27.6) + decidim-accountability (0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-admin (0.27.6) active_link_to (~> 1.0) - decidim-core (= 0.27.5) + decidim-core (= 0.27.6) devise (~> 4.7) devise-i18n (~> 1.2) devise_invitable (~> 2.0, >= 2.0.9) - decidim-api (0.27.5) - decidim-core (= 0.27.5) + decidim-api (0.27.6) + decidim-core (= 0.27.6) graphql (~> 1.12, < 1.13) graphql-docs (~> 2.1.0) rack-cors (~> 1.0) - decidim-assemblies (0.27.5) - decidim-core (= 0.27.5) - decidim-blogs (0.27.5) - decidim-admin (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-budgets (0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-comments (0.27.5) - decidim-core (= 0.27.5) + decidim-assemblies (0.27.6) + decidim-core (= 0.27.6) + decidim-blogs (0.27.6) + decidim-admin (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-budgets (0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-comments (0.27.6) + decidim-core (= 0.27.6) redcarpet (~> 3.5, >= 3.5.1) - decidim-conferences (0.27.5) - decidim-core (= 0.27.5) - decidim-meetings (= 0.27.5) + decidim-conferences (0.27.6) + decidim-core (= 0.27.6) + decidim-meetings (= 0.27.6) wicked_pdf (~> 2.1) wkhtmltopdf-binary (~> 0.12) - decidim-consultations (0.27.5) - decidim-admin (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-core (0.27.5) + decidim-consultations (0.27.6) + decidim-admin (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-core (0.27.6) active_link_to (~> 1.0) acts_as_list (~> 0.9) batch-loader (~> 1.2) @@ -82,7 +82,6 @@ PATH loofah (~> 2.19.0) mime-types (>= 1.16, < 4.0) mini_magick (~> 4.9) - mustache (~> 1.1.0) omniauth (~> 2.0) omniauth-facebook (~> 5.0) omniauth-google-oauth2 (~> 1.0) @@ -107,15 +106,15 @@ PATH webpacker (= 6.0.0.rc.5) webpush (~> 1.1) wisper (~> 2.0) - decidim-debates (0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-dev (0.27.5) + decidim-debates (0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-dev (0.27.6) axe-core-rspec (~> 4.1.0) byebug (~> 11.0) capybara (~> 3.24) db-query-matchers (~> 0.10.0) - decidim (= 0.27.5) + decidim (= 0.27.6) erb_lint (~> 0.0.35) factory_bot_rails (~> 4.8) i18n-tasks (~> 0.9.18) @@ -138,62 +137,62 @@ PATH w3c_rspec_validators (~> 0.3.0) webmock (~> 3.6) wisper-rspec (~> 1.0) - decidim-elections (0.27.5) + decidim-elections (0.27.6) decidim-bulletin_board (= 0.23) - decidim-core (= 0.27.5) - decidim-forms (= 0.27.5) - decidim-proposals (= 0.27.5) + decidim-core (= 0.27.6) + decidim-forms (= 0.27.6) + decidim-proposals (= 0.27.6) rack-attack (~> 6.0) voting_schemes-dummy (= 0.23) voting_schemes-electionguard (= 0.23) - decidim-forms (0.27.5) - decidim-core (= 0.27.5) + decidim-forms (0.27.6) + decidim-core (= 0.27.6) wicked_pdf (~> 2.1) wkhtmltopdf-binary (~> 0.12) - decidim-generators (0.27.5) - decidim-core (= 0.27.5) - decidim-initiatives (0.27.5) - decidim-admin (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-verifications (= 0.27.5) + decidim-generators (0.27.6) + decidim-core (= 0.27.6) + decidim-initiatives (0.27.6) + decidim-admin (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-verifications (= 0.27.6) origami (~> 2.1) rexml (~> 3.2.5) wicked (~> 1.3) wicked_pdf (~> 2.1) wkhtmltopdf-binary (~> 0.12) - decidim-meetings (0.27.5) - decidim-core (= 0.27.5) - decidim-forms (= 0.27.5) + decidim-meetings (0.27.6) + decidim-core (= 0.27.6) + decidim-forms (= 0.27.6) icalendar (~> 2.5) - decidim-pages (0.27.5) - decidim-core (= 0.27.5) - decidim-participatory_processes (0.27.5) - decidim-core (= 0.27.5) - decidim-proposals (0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) + decidim-pages (0.27.6) + decidim-core (= 0.27.6) + decidim-participatory_processes (0.27.6) + decidim-core (= 0.27.6) + decidim-proposals (0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) doc2text (~> 0.4.5) redcarpet (~> 3.5, >= 3.5.1) - decidim-sortitions (0.27.5) - decidim-admin (= 0.27.5) - decidim-comments (= 0.27.5) - decidim-core (= 0.27.5) - decidim-proposals (= 0.27.5) - decidim-surveys (0.27.5) - decidim-core (= 0.27.5) - decidim-forms (= 0.27.5) - decidim-system (0.27.5) + decidim-sortitions (0.27.6) + decidim-admin (= 0.27.6) + decidim-comments (= 0.27.6) + decidim-core (= 0.27.6) + decidim-proposals (= 0.27.6) + decidim-surveys (0.27.6) + decidim-core (= 0.27.6) + decidim-forms (= 0.27.6) + decidim-system (0.27.6) active_link_to (~> 1.0) - decidim-core (= 0.27.5) + decidim-core (= 0.27.6) devise (~> 4.7) devise-i18n (~> 1.2) devise_invitable (~> 2.0, >= 2.0.9) - decidim-templates (0.27.5) - decidim-core (= 0.27.5) - decidim-forms (= 0.27.5) - decidim-verifications (0.27.5) - decidim-core (= 0.27.5) + decidim-templates (0.27.6) + decidim-core (= 0.27.6) + decidim-forms (= 0.27.6) + decidim-verifications (0.27.6) + decidim-core (= 0.27.6) GEM remote: https://rubygems.org/ @@ -265,7 +264,7 @@ GEM addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) ast (2.4.2) - axe-core-api (4.8.0) + axe-core-api (4.9.0) dumb_delegator virtus axe-core-rspec (4.1.0) @@ -287,6 +286,7 @@ GEM html_tokenizer (~> 0.0.6) parser (>= 2.4) smart_properties + bigdecimal (3.1.7) bindex (0.8.1) bootsnap (1.10.3) msgpack (~> 1.2) @@ -294,16 +294,16 @@ GEM browser (2.7.1) builder (3.2.4) byebug (11.1.3) - capybara (3.39.2) + capybara (3.40.0) addressable matrix mini_mime (>= 0.1.3) - nokogiri (~> 1.8) + nokogiri (~> 1.11) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - carrierwave (2.2.5) + carrierwave (2.2.6) activemodel (>= 5.0.0) activesupport (>= 5.0.0) addressable (~> 2.6) @@ -323,7 +323,7 @@ GEM actionpack (>= 5.0) cells (>= 4.1.6, < 5.0.0) charlock_holmes (0.7.7) - chef-utils (18.3.0) + chef-utils (18.4.12) concurrent-ruby childprocess (4.1.0) coercible (1.0.0) @@ -338,10 +338,11 @@ GEM colorize (0.8.1) commonmarker (0.23.10) concurrent-ruby (1.2.3) - crack (0.4.5) + crack (1.0.0) + bigdecimal rexml crass (1.0.6) - css_parser (1.16.0) + css_parser (1.17.1) addressable date (3.3.4) date_validator (0.12.0) @@ -361,7 +362,7 @@ GEM declarative-option (0.1.0) descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) - devise (4.9.3) + devise (4.9.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) @@ -372,13 +373,13 @@ GEM devise_invitable (2.0.9) actionmailer (>= 5.0) devise (>= 4.6) - diff-lcs (1.5.0) + diff-lcs (1.5.1) diffy (3.4.2) doc2text (0.4.7) nokogiri (>= 1.13.2, < 1.17.0) rubyzip (~> 2.3.0) docile (1.4.0) - doorkeeper (5.6.9) + doorkeeper (5.7.0) railties (>= 5) doorkeeper-i18n (4.0.1) dumb_delegator (1.0.0) @@ -394,7 +395,7 @@ GEM temple erubi (1.12.0) escape_utils (1.3.0) - excon (0.109.0) + excon (0.110.0) execjs (2.9.1) extended-markdown-filter (0.7.0) html-pipeline (~> 2.9) @@ -456,7 +457,7 @@ GEM faraday_middleware graphql-client graphql (1.12.24) - graphql-client (0.18.0) + graphql-client (0.19.0) activesupport (>= 3.0) graphql graphql-docs (2.1.0) @@ -469,12 +470,12 @@ GEM sass (~> 3.4) hashdiff (1.1.0) hashie (5.0.0) - highline (2.1.0) + highline (3.0.1) hkdf (0.3.0) html-pipeline (2.14.3) activesupport (>= 2) nokogiri (>= 1.4) - html_tokenizer (0.0.7) + html_tokenizer (0.0.8) htmlentities (4.3.4) i18n (1.14.1) concurrent-ruby (~> 1.0) @@ -497,7 +498,7 @@ GEM ruby-vips (>= 2.0.17, < 3) invisible_captcha (0.13.0) rails (>= 3.2.0) - json (2.7.1) + json (2.7.2) jwt (2.2.3) kaminari (1.2.2) activesupport (>= 4.1.0) @@ -535,7 +536,7 @@ GEM net-imap net-pop net-smtp - marcel (1.0.2) + marcel (1.0.4) matrix (0.4.2) mdl (0.13.0) kramdown (~> 2.3) @@ -546,7 +547,7 @@ GEM method_source (1.0.0) mime-types (3.5.2) mime-types-data (~> 3.2015) - mime-types-data (3.2024.0206) + mime-types-data (3.2024.0305) mini_magick (4.12.0) mini_mime (1.1.5) mini_portile2 (2.8.5) @@ -559,7 +560,6 @@ GEM msgpack (1.4.5) multi_xml (0.6.0) multipart-post (2.4.0) - mustache (1.1.1) net-imap (0.4.10) date net-protocol @@ -592,11 +592,11 @@ GEM rack-protection omniauth-facebook (5.0.0) omniauth-oauth2 (~> 1.2) - omniauth-google-oauth2 (1.1.1) + omniauth-google-oauth2 (1.1.2) jwt (>= 2.0) - oauth2 (~> 2.0.6) + oauth2 (~> 2.0) omniauth (~> 2.0) - omniauth-oauth2 (~> 1.8.0) + omniauth-oauth2 (~> 1.8) omniauth-oauth (1.2.0) oauth omniauth (>= 1.0, < 3) @@ -624,7 +624,7 @@ GEM pg_search (2.3.6) activerecord (>= 5.2) activesupport (>= 5.2) - premailer (1.22.0) + premailer (1.23.0) addressable css_parser (>= 1.12.0) htmlentities (>= 4.0.0) @@ -700,24 +700,24 @@ GEM actionpack (>= 5.2) railties (>= 5.2) rexml (3.2.5) - rspec (3.12.0) - rspec-core (~> 3.12.0) - rspec-expectations (~> 3.12.0) - rspec-mocks (~> 3.12.0) + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) rspec-cells (0.3.9) cells (>= 4.0.0, < 6.0.0) rspec-rails (>= 3.0.0, < 6.2.0) - rspec-core (3.12.2) - rspec-support (~> 3.12.0) - rspec-expectations (3.12.3) + rspec-core (3.13.0) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) + rspec-support (~> 3.13.0) rspec-html-matchers (0.9.4) nokogiri (~> 1) rspec (>= 3.0.0.a, < 4) - rspec-mocks (3.12.6) + rspec-mocks (3.13.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) + rspec-support (~> 3.13.0) rspec-rails (4.1.2) actionpack (>= 4.2) activesupport (>= 4.2) @@ -728,7 +728,7 @@ GEM rspec-support (~> 3.10) rspec-retry (0.6.2) rspec-core (> 3.3) - rspec-support (3.12.1) + rspec-support (3.13.1) rspec_junit_formatter (0.3.0) rspec-core (>= 2, < 4, != 2.12.0) rubocop (1.28.2) @@ -752,10 +752,10 @@ GEM rubocop-rspec (2.11.1) rubocop (~> 1.19) ruby-progressbar (1.11.0) - ruby-vips (2.2.0) + ruby-vips (2.2.1) ffi (~> 1.12) ruby2_keywords (0.0.5) - rubyXL (3.4.25) + rubyXL (3.4.27) nokogiri (>= 1.10.8) rubyzip (>= 1.3.0) rubyzip (2.3.2) @@ -812,7 +812,7 @@ GEM valid_email2 (2.3.1) activemodel (>= 3.2) mail (~> 2.5) - version_gem (1.1.3) + version_gem (1.1.4) virtus (2.0.0) axiom-types (~> 0.1) coercible (~> 1.0) @@ -836,7 +836,7 @@ GEM activemodel (>= 6.0.0) bindex (>= 0.4.0) railties (>= 6.0.0) - webmock (3.19.1) + webmock (3.23.0) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -853,7 +853,7 @@ GEM websocket-extensions (0.1.5) wicked (1.4.0) railties (>= 3.0.7) - wicked_pdf (2.7.0) + wicked_pdf (2.8.0) activesupport wisper (2.0.1) wisper-rspec (1.1.0) diff --git a/decidim_app-design/package-lock.json b/decidim_app-design/package-lock.json index 258ffc6db0061..b69344dfbe5e2 100644 --- a/decidim_app-design/package-lock.json +++ b/decidim_app-design/package-lock.json @@ -11073,18 +11073,21 @@ } }, "node_modules/leaflet": { - "version": "1.3.1", - "integrity": "sha512-adQOIzh+bfdridLM1xIgJ9VnJbAUY3wqs/ueF+ITla+PLQ1z47USdBKUf+iD9FuUA8RtlT6j6hZBfZoA6mW+XQ==" + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" }, "node_modules/leaflet-tilelayer-here": { - "version": "1.0.2", - "integrity": "sha512-PQytY0goCZLANGabPCPQJDhCrXrwdVP6F5NEgw/zjunrfFhQ1XwnBUNCWi0irUWQsETNntcwfkomikhlQ7uCRQ==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/leaflet-tilelayer-here/-/leaflet-tilelayer-here-2.0.1.tgz", + "integrity": "sha512-lujfnFt7TuEk3bHGsWt/w01XBfrU9zy7B6C8fzJDr8txhNmVNA00kRRrEJPaLaFyVeSwwA5vWS6zDg2W13DCIA==" }, "node_modules/leaflet.markercluster": { - "version": "1.4.1", - "integrity": "sha512-ZSEpE/EFApR0bJ1w/dUGwTSUvWlpalKqIzkaYdYB7jaftQA/Y2Jav+eT4CMtEYFj+ZK4mswP13Q2acnPBnhGOw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz", + "integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==", "peerDependencies": { - "leaflet": "~1.3.1" + "leaflet": "^1.3.1" } }, "node_modules/leven": { @@ -17407,12 +17410,12 @@ }, "packages/browserslist-config": { "name": "@decidim/browserslist-config", - "version": "0.27.5", + "version": "0.27.6", "license": "AGPL-3.0" }, "packages/core": { "name": "@decidim/core", - "version": "0.27.5", + "version": "0.27.6", "license": "AGPL-3.0", "dependencies": { "@joeattardi/emoji-button": "^4.6.2", @@ -17433,9 +17436,9 @@ "jquery": "^3.2.1", "jquery-serializejson": "2.9.0", "js-cookie": "^3.0.1", - "leaflet": "1.3.1", - "leaflet-tilelayer-here": "1.0.2", - "leaflet.markercluster": "1.4.1", + "leaflet": "^1.9.4", + "leaflet-tilelayer-here": "^2.0.1", + "leaflet.markercluster": "^1.5.3", "morphdom": "2.6.1", "prop-types": "^15.7.2", "quill": "1.3.7", @@ -17467,7 +17470,7 @@ }, "packages/dev": { "name": "@decidim/dev", - "version": "0.27.5", + "version": "0.27.6", "dev": true, "license": "AGPL-3.0", "dependencies": { @@ -17476,7 +17479,7 @@ }, "packages/elections": { "name": "@decidim/elections", - "version": "0.27.5", + "version": "0.27.6", "license": "AGPL-3.0", "dependencies": { "@decidim/decidim-bulletin_board": "0.23.0", @@ -17486,7 +17489,7 @@ }, "packages/eslint-config": { "name": "@decidim/eslint-config", - "version": "0.27.5", + "version": "0.27.6", "dev": true, "license": "AGPL-3.0", "peerDependencies": { @@ -17503,7 +17506,7 @@ }, "packages/stylelint-config": { "name": "@decidim/stylelint-config", - "version": "0.27.5", + "version": "0.27.6", "dev": true, "license": "AGPL-3.0", "peerDependencies": { @@ -17512,7 +17515,7 @@ }, "packages/webpacker": { "name": "@decidim/webpacker", - "version": "0.27.5", + "version": "0.27.6", "license": "AGPL-3.0", "dependencies": { "@babel/core": "^7.15.5", @@ -20067,9 +20070,9 @@ "jquery": "^3.2.1", "jquery-serializejson": "2.9.0", "js-cookie": "^3.0.1", - "leaflet": "1.3.1", - "leaflet-tilelayer-here": "1.0.2", - "leaflet.markercluster": "1.4.1", + "leaflet": "^1.9.4", + "leaflet-tilelayer-here": "^2.0.1", + "leaflet.markercluster": "^1.5.3", "morphdom": "2.6.1", "prop-types": "^15.7.2", "quill": "1.3.7", @@ -28016,16 +28019,19 @@ } }, "leaflet": { - "version": "1.3.1", - "integrity": "sha512-adQOIzh+bfdridLM1xIgJ9VnJbAUY3wqs/ueF+ITla+PLQ1z47USdBKUf+iD9FuUA8RtlT6j6hZBfZoA6mW+XQ==" + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" }, "leaflet-tilelayer-here": { - "version": "1.0.2", - "integrity": "sha512-PQytY0goCZLANGabPCPQJDhCrXrwdVP6F5NEgw/zjunrfFhQ1XwnBUNCWi0irUWQsETNntcwfkomikhlQ7uCRQ==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/leaflet-tilelayer-here/-/leaflet-tilelayer-here-2.0.1.tgz", + "integrity": "sha512-lujfnFt7TuEk3bHGsWt/w01XBfrU9zy7B6C8fzJDr8txhNmVNA00kRRrEJPaLaFyVeSwwA5vWS6zDg2W13DCIA==" }, "leaflet.markercluster": { - "version": "1.4.1", - "integrity": "sha512-ZSEpE/EFApR0bJ1w/dUGwTSUvWlpalKqIzkaYdYB7jaftQA/Y2Jav+eT4CMtEYFj+ZK4mswP13Q2acnPBnhGOw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz", + "integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==", "requires": {} }, "leven": { diff --git a/decidim_app-design/packages/browserslist-config/package.json b/decidim_app-design/packages/browserslist-config/package.json index 277db1c27cd3e..0b5480a8c2c30 100644 --- a/decidim_app-design/packages/browserslist-config/package.json +++ b/decidim_app-design/packages/browserslist-config/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/browserslist-config", "description": "The Browserslist configuration for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git", diff --git a/decidim_app-design/packages/core/package.json b/decidim_app-design/packages/core/package.json index 424c520705cc4..4f90f50dd4238 100644 --- a/decidim_app-design/packages/core/package.json +++ b/decidim_app-design/packages/core/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/core", "description": "The core dependencies for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git", @@ -28,9 +28,9 @@ "jquery": "^3.2.1", "jquery-serializejson": "2.9.0", "js-cookie": "^3.0.1", - "leaflet": "1.3.1", - "leaflet-tilelayer-here": "1.0.2", - "leaflet.markercluster": "1.4.1", + "leaflet": "^1.9.4", + "leaflet-tilelayer-here": "^2.0.1", + "leaflet.markercluster": "^1.5.3", "morphdom": "2.6.1", "prop-types": "^15.7.2", "quill": "1.3.7", diff --git a/decidim_app-design/packages/dev/package.json b/decidim_app-design/packages/dev/package.json index 5091e66b32c4c..1d31808bf7191 100644 --- a/decidim_app-design/packages/dev/package.json +++ b/decidim_app-design/packages/dev/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/dev", "description": "The dev dependencies for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git", diff --git a/decidim_app-design/packages/elections/package.json b/decidim_app-design/packages/elections/package.json index 2c16f548377e0..c2d8e2f070ebc 100644 --- a/decidim_app-design/packages/elections/package.json +++ b/decidim_app-design/packages/elections/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/elections", "description": "The elections and votings dependencies for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git", diff --git a/decidim_app-design/packages/eslint-config/package.json b/decidim_app-design/packages/eslint-config/package.json index 470f44cfb5989..ad1e3ff5e6f2e 100644 --- a/decidim_app-design/packages/eslint-config/package.json +++ b/decidim_app-design/packages/eslint-config/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/eslint-config", "description": "The eslint configuration for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git", diff --git a/decidim_app-design/packages/stylelint-config/package.json b/decidim_app-design/packages/stylelint-config/package.json index 98d2b578553d2..2588384b6a274 100644 --- a/decidim_app-design/packages/stylelint-config/package.json +++ b/decidim_app-design/packages/stylelint-config/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/stylelint-config", "description": "The stylelint configuration for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git", diff --git a/decidim_app-design/packages/webpacker/package.json b/decidim_app-design/packages/webpacker/package.json index 093f691ff94d8..5da61013352b3 100644 --- a/decidim_app-design/packages/webpacker/package.json +++ b/decidim_app-design/packages/webpacker/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/webpacker", "description": "The webpacker dependencies for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git", diff --git a/docs/modules/develop/pages/releases.adoc b/docs/modules/develop/pages/releases.adoc index 820ea6a709f40..7fd5f525574ec 100644 --- a/docs/modules/develop/pages/releases.adoc +++ b/docs/modules/develop/pages/releases.adoc @@ -16,6 +16,7 @@ Mark `develop` as the reference to the next release: . Turn develop into the `dev` branch for the next release: .. Update `.decidim-version` to the new `dev` development version: `x.y.z.dev`, where `x.y.z` is the new semver number for the next version .. Run `bin/rake update_versions`, this will update all references to the new version. + .. Run `bin/rake patch_generators`, this will update the Gemfile for the generators to the new version. .. Run `bin/rake bundle`, this will update all the `Gemfile.lock` files .. Run `bin/rake webpack`, this will update the JavaScript bundle. . Update `SECURITY.md` and change the supported version to the new version. @@ -90,6 +91,7 @@ If this is a *Release Candidate version* release, the steps to follow are: . Checkout the release stable branch `git checkout release/x.y-stable`. . Update `.decidim-version` to the new version `x.y.z.rc1` . Run `bin/rake update_versions`, this will update all references to the new version. +. Run `bin/rake patch_generators`, this will update the Gemfile for the generators to the new version. . Run `bin/rake bundle`, this will update all the `Gemfile.lock` files . Run `bin/rake webpack`, this will update the JavaScript bundle. . Run `bin/rspec`, this will check things like if all the officially supported languages translations are OK. @@ -110,6 +112,7 @@ Release Candidates will be tested in a production server (usually Metadecidim) d . Checkout the release stable branch `git checkout release/x.y-stable`. . Update `.decidim-version` by removing the `.rcN` suffix, leaving a clean version number like `x.y.z` . Run `bin/rake update_versions`, this will update all references to the new version. +. Run `bin/rake patch_generators`, this will update the Gemfile for the generators to the new version. . Run `bin/rake bundle`, this will update all the `Gemfile.lock` files . Run `bin/rake webpack`, this will update the JavaScript bundle. . Update `CHANGELOG.MD`. @@ -136,6 +139,7 @@ The process is very similar from releasing a new Decidim version: . Checkout the branch you want to release: `git checkout -b release/x.y-stable` . Update `.decidim-version` to the new version number. . Run `bin/rake update_versions`, this will update all references to the new version. +. Run `bin/rake patch_generators`, this will update the Gemfile for the generators to the new version. . Run `bin/rake bundle`, this will update all the `Gemfile.lock` files . Run `bin/rake webpack`, this will update the JavaScript bundle. . Update `CHANGELOG.MD`. diff --git a/docs/modules/install/pages/manual.adoc b/docs/modules/install/pages/manual.adoc index c18c8c230d17d..d93b753d4e099 100644 --- a/docs/modules/install/pages/manual.adoc +++ b/docs/modules/install/pages/manual.adoc @@ -12,6 +12,10 @@ In order to develop on decidim, you'll need: We're starting with an Ubuntu 22.04.1 LTS. This is an opinionated guide, so you're free to use the technology that you are most comfortable. If you have any doubts and you're blocked you can go and ask on https://matrix.to/#/#decidimdevs:matrix.org[our Matrix.org chat room for developers]. +The compatibility between the different versions of the components is the following: + +include::install:partial$version_matrix.adoc[] + We recommend to have at least some basic proficiency in GNU/Linux (i.e. how to use the command-line, packages, etc), networking knowledge, server administration, development in general, and some basic knowledge about software package managers. It would be great to have Ruby on Rails development basics (a good starting point is http://guides.rubyonrails.org/getting_started.html[Getting Started with Ruby on Rails]) and have some knowledge on how package libraries are working (we use `bundler` for handling ruby packages, and `npm`/`yarn` for handling javascript). In this guide, we'll see how to install rbenv, PostgreSQL, Node.js and, Decidim, and how to configure everything together for a development environment. Mind that if you want to make a production deployment with real users this guide isn't enough, you should configure a web server (like nginx), backups, monitoring, etc. This is out of the scope of this guide, but you can follow the https://platoniq.github.io/decidim-install/[Platoniq guide]. diff --git a/docs/modules/install/pages/update.adoc b/docs/modules/install/pages/update.adoc index d344dc9400a61..746e1c3362768 100644 --- a/docs/modules/install/pages/update.adoc +++ b/docs/modules/install/pages/update.adoc @@ -85,6 +85,11 @@ gem "decidim-initiatives", DECIDIM_VERSION gem "decidim-dev", DECIDIM_VERSION ---- +== Compatiblity versions matrix + +There are different versions of Decidim that are compatible with different versions of Ruby and Node. You can check the following table to see which versions are compatible with each other: + +include::install:partial$version_matrix.adoc[] [discrete] == Recommendations diff --git a/docs/modules/install/partials/version_matrix.adoc b/docs/modules/install/partials/version_matrix.adoc new file mode 100644 index 0000000000000..0e478d7e8353e --- /dev/null +++ b/docs/modules/install/partials/version_matrix.adoc @@ -0,0 +1,13 @@ + +|=== +|Decidim version |Ruby version |Node version | Status + +|develop | 3.2.2 | 18.17.x | Unreleased + +|v0.28 | 3.1.1 | 18.17.x | Bug fixes and security updates + +|v0.27 | 3.0.2 | 16.18.x | Bug fixes and security updates + +|v0.26 | 2.7.5+ | 16.9.x | Not maintained + +|=== diff --git a/lib/decidim/version.rb b/lib/decidim/version.rb index 411688aa6cd2f..33312e17e28b8 100644 --- a/lib/decidim/version.rb +++ b/lib/decidim/version.rb @@ -3,6 +3,6 @@ # This holds the decidim version and the faker version it uses. module Decidim def self.version - "0.27.5" + "0.27.6" end end diff --git a/package-lock.json b/package-lock.json index 258ffc6db0061..b69344dfbe5e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11073,18 +11073,21 @@ } }, "node_modules/leaflet": { - "version": "1.3.1", - "integrity": "sha512-adQOIzh+bfdridLM1xIgJ9VnJbAUY3wqs/ueF+ITla+PLQ1z47USdBKUf+iD9FuUA8RtlT6j6hZBfZoA6mW+XQ==" + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" }, "node_modules/leaflet-tilelayer-here": { - "version": "1.0.2", - "integrity": "sha512-PQytY0goCZLANGabPCPQJDhCrXrwdVP6F5NEgw/zjunrfFhQ1XwnBUNCWi0irUWQsETNntcwfkomikhlQ7uCRQ==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/leaflet-tilelayer-here/-/leaflet-tilelayer-here-2.0.1.tgz", + "integrity": "sha512-lujfnFt7TuEk3bHGsWt/w01XBfrU9zy7B6C8fzJDr8txhNmVNA00kRRrEJPaLaFyVeSwwA5vWS6zDg2W13DCIA==" }, "node_modules/leaflet.markercluster": { - "version": "1.4.1", - "integrity": "sha512-ZSEpE/EFApR0bJ1w/dUGwTSUvWlpalKqIzkaYdYB7jaftQA/Y2Jav+eT4CMtEYFj+ZK4mswP13Q2acnPBnhGOw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz", + "integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==", "peerDependencies": { - "leaflet": "~1.3.1" + "leaflet": "^1.3.1" } }, "node_modules/leven": { @@ -17407,12 +17410,12 @@ }, "packages/browserslist-config": { "name": "@decidim/browserslist-config", - "version": "0.27.5", + "version": "0.27.6", "license": "AGPL-3.0" }, "packages/core": { "name": "@decidim/core", - "version": "0.27.5", + "version": "0.27.6", "license": "AGPL-3.0", "dependencies": { "@joeattardi/emoji-button": "^4.6.2", @@ -17433,9 +17436,9 @@ "jquery": "^3.2.1", "jquery-serializejson": "2.9.0", "js-cookie": "^3.0.1", - "leaflet": "1.3.1", - "leaflet-tilelayer-here": "1.0.2", - "leaflet.markercluster": "1.4.1", + "leaflet": "^1.9.4", + "leaflet-tilelayer-here": "^2.0.1", + "leaflet.markercluster": "^1.5.3", "morphdom": "2.6.1", "prop-types": "^15.7.2", "quill": "1.3.7", @@ -17467,7 +17470,7 @@ }, "packages/dev": { "name": "@decidim/dev", - "version": "0.27.5", + "version": "0.27.6", "dev": true, "license": "AGPL-3.0", "dependencies": { @@ -17476,7 +17479,7 @@ }, "packages/elections": { "name": "@decidim/elections", - "version": "0.27.5", + "version": "0.27.6", "license": "AGPL-3.0", "dependencies": { "@decidim/decidim-bulletin_board": "0.23.0", @@ -17486,7 +17489,7 @@ }, "packages/eslint-config": { "name": "@decidim/eslint-config", - "version": "0.27.5", + "version": "0.27.6", "dev": true, "license": "AGPL-3.0", "peerDependencies": { @@ -17503,7 +17506,7 @@ }, "packages/stylelint-config": { "name": "@decidim/stylelint-config", - "version": "0.27.5", + "version": "0.27.6", "dev": true, "license": "AGPL-3.0", "peerDependencies": { @@ -17512,7 +17515,7 @@ }, "packages/webpacker": { "name": "@decidim/webpacker", - "version": "0.27.5", + "version": "0.27.6", "license": "AGPL-3.0", "dependencies": { "@babel/core": "^7.15.5", @@ -20067,9 +20070,9 @@ "jquery": "^3.2.1", "jquery-serializejson": "2.9.0", "js-cookie": "^3.0.1", - "leaflet": "1.3.1", - "leaflet-tilelayer-here": "1.0.2", - "leaflet.markercluster": "1.4.1", + "leaflet": "^1.9.4", + "leaflet-tilelayer-here": "^2.0.1", + "leaflet.markercluster": "^1.5.3", "morphdom": "2.6.1", "prop-types": "^15.7.2", "quill": "1.3.7", @@ -28016,16 +28019,19 @@ } }, "leaflet": { - "version": "1.3.1", - "integrity": "sha512-adQOIzh+bfdridLM1xIgJ9VnJbAUY3wqs/ueF+ITla+PLQ1z47USdBKUf+iD9FuUA8RtlT6j6hZBfZoA6mW+XQ==" + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" }, "leaflet-tilelayer-here": { - "version": "1.0.2", - "integrity": "sha512-PQytY0goCZLANGabPCPQJDhCrXrwdVP6F5NEgw/zjunrfFhQ1XwnBUNCWi0irUWQsETNntcwfkomikhlQ7uCRQ==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/leaflet-tilelayer-here/-/leaflet-tilelayer-here-2.0.1.tgz", + "integrity": "sha512-lujfnFt7TuEk3bHGsWt/w01XBfrU9zy7B6C8fzJDr8txhNmVNA00kRRrEJPaLaFyVeSwwA5vWS6zDg2W13DCIA==" }, "leaflet.markercluster": { - "version": "1.4.1", - "integrity": "sha512-ZSEpE/EFApR0bJ1w/dUGwTSUvWlpalKqIzkaYdYB7jaftQA/Y2Jav+eT4CMtEYFj+ZK4mswP13Q2acnPBnhGOw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz", + "integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==", "requires": {} }, "leven": { diff --git a/packages/browserslist-config/package.json b/packages/browserslist-config/package.json index 277db1c27cd3e..0b5480a8c2c30 100644 --- a/packages/browserslist-config/package.json +++ b/packages/browserslist-config/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/browserslist-config", "description": "The Browserslist configuration for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git", diff --git a/packages/core/package.json b/packages/core/package.json index 424c520705cc4..4f90f50dd4238 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/core", "description": "The core dependencies for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git", @@ -28,9 +28,9 @@ "jquery": "^3.2.1", "jquery-serializejson": "2.9.0", "js-cookie": "^3.0.1", - "leaflet": "1.3.1", - "leaflet-tilelayer-here": "1.0.2", - "leaflet.markercluster": "1.4.1", + "leaflet": "^1.9.4", + "leaflet-tilelayer-here": "^2.0.1", + "leaflet.markercluster": "^1.5.3", "morphdom": "2.6.1", "prop-types": "^15.7.2", "quill": "1.3.7", diff --git a/packages/dev/package.json b/packages/dev/package.json index 5091e66b32c4c..1d31808bf7191 100644 --- a/packages/dev/package.json +++ b/packages/dev/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/dev", "description": "The dev dependencies for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git", diff --git a/packages/elections/package.json b/packages/elections/package.json index 2c16f548377e0..c2d8e2f070ebc 100644 --- a/packages/elections/package.json +++ b/packages/elections/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/elections", "description": "The elections and votings dependencies for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git", diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 470f44cfb5989..ad1e3ff5e6f2e 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/eslint-config", "description": "The eslint configuration for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git", diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index 98d2b578553d2..2588384b6a274 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/stylelint-config", "description": "The stylelint configuration for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git", diff --git a/packages/webpacker/package.json b/packages/webpacker/package.json index 093f691ff94d8..5da61013352b3 100644 --- a/packages/webpacker/package.json +++ b/packages/webpacker/package.json @@ -1,7 +1,7 @@ { "name": "@decidim/webpacker", "description": "The webpacker dependencies for Decidim", - "version": "0.27.5", + "version": "0.27.6", "repository": { "url": "git@github.com:decidim/decidim.git", "type": "git",