diff --git a/.eslintrc.js b/.eslintrc.js index 14591f112e..df3498093a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -51,7 +51,7 @@ module.exports = { "react/display-name": ["error", { ignoreTranspilerName: true }], "react/forbid-prop-types": "off", "react/jsx-props-no-spreading": "off", - "react/jsx-sort-default-props": [ + "react/sort-default-props": [ "error", { ignoreCase: true @@ -65,7 +65,7 @@ module.exports = { "import/no-extraneous-dependencies": "off", "default-param-last": "off", "arrow-body-style": "off", - "react/function-component-definition": "off", + "react/function-component-definition": [2, { namedComponents: "function-declaration" }], "no-restricted-exports": "off", "no-import-assign": "off", "react/jsx-no-useless-fragment": "off", diff --git a/.github/workflows/app.yml b/.github/workflows/app.yml index f3ac7bb2ff..eee28b6e71 100644 --- a/.github/workflows/app.yml +++ b/.github/workflows/app.yml @@ -2,13 +2,17 @@ name: App on: + push: + branches: + - main pull_request: branches: - main - 'release-*' - - develop_react_upgrade + - develop workflow_dispatch: + jobs: server-test: name: RSpec Test @@ -51,83 +55,27 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: - node-version: '18' - cache: 'npm' - cache-dependency-path: '**/package-lock.json' - - name: Run client tests - run: | - npm ci - npm run test:batch:1 - client-test-2: - name: Client Test (Batch 2) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: '18' - cache: 'npm' - cache-dependency-path: '**/package-lock.json' - - name: Run client tests - run: | - npm ci - npm run test:batch:2 - client-test-3: - name: Client Test (Batch 3) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: '18' - cache: 'npm' - cache-dependency-path: '**/package-lock.json' - - name: Run client tests - run: | - npm ci - npm run test:batch:3 - client-test-4: - name: Client Test (Batch 4) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: '18' - cache: 'npm' - cache-dependency-path: '**/package-lock.json' - - name: Run client tests - run: | - npm ci - npm run test:batch:4 - client-test-5: - name: Client Test (Batch 5) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: '18' + node-version: '20' cache: 'npm' cache-dependency-path: '**/package-lock.json' - name: Run client tests run: | - npm ci - npm run test:batch:5 - client-test-new: - name: Client Test (New) + npm config set legacy-peer-deps true && npm ci + npm run test + client-test-components: + name: Client Test (Components) runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: - node-version: '18' + node-version: '20' cache: 'npm' cache-dependency-path: '**/package-lock.json' - name: Run client tests run: | - npm ci - npm run test:new -- --maxWorkers=2 + npm config set legacy-peer-deps true && npm ci + npm run test:components -- --maxWorkers=2 client-lint: name: Client Linter runs-on: ubuntu-latest @@ -135,10 +83,10 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: - node-version: '18' + node-version: '20' cache: 'npm' cache-dependency-path: '**/package-lock.json' - name: Run client linter run: | - npm ci + npm config set legacy-peer-deps true && npm ci npm run lint diff --git a/.ruby-version b/.ruby-version index 9e79f6c4a3..f13c6f452c 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -ruby-3.2.2 +ruby-3.3.5 diff --git a/Gemfile b/Gemfile index 3d90d7e88e..9e9ce4f377 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,7 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. source 'https://rubygems.org' -ruby '3.2.2' +ruby '3.3.5' gem 'activerecord-nulldb-adapter' # Running Rake tasks at build time before DB is set up. TODO: Still needed? gem 'aws-sdk-s3', '~> 1.130', # Access and manage Amazon S3 storage (with ActiveStorage). @@ -17,13 +17,13 @@ gem 'deep_merge', '~> 1.2', # Recursive merging of Hashes. Used for m require: 'deep_merge/rails_compat' gem 'delayed_job_active_record', '~> 4.1.7' gem 'devise', '~> 4.9' # Authentication framework -gem 'devise-jwt', '~> 0.10' # JWT authentication for native Primero users gem 'faraday', '~> 0.17' # Ruby HTTP client gem 'file_validators', '~> 3.0' # ActiveRecord extension for validating attachment file sizes gem 'i18n-js', '~> 3.9' # Shares Rails i18n strings with the front end gem 'image_processing', '~> 1.12' # Ruby bindings for ImageMagick, resize attachments. Depenency of ActiveStorage gem 'jbuilder', '~> 2.11' # JSON templating for the API gem 'json_schemer', '~> 1.0' # Validation for submited JSON +gem 'jwt', '~> 2.8' # Ruby JWT library used to authenticate 3rd party identity provider tokens gem 'matrix', '~> 0.4' # No longer part of Ruby 3.2 core. Must be included explicitly gem 'minipack', '~> 0.3' # An alternative to Webpacker. TODO: Is this still needed? In prod? gem 'net-http-persistent', '~> 4.0' # Thread safe persistent HTTP connections, optional Faraday dependency @@ -34,7 +34,7 @@ gem 'prawn-table', '~> 0.2' # PDF generation gem 'puma', '~> 6.4' # Ruby Rack server gem 'rack', '~> 2.2' gem 'rack-attack', '>= 6.6' # Rack middleware to rate limit sensetive routes, such as those used for auth -gem 'rails', '6.1.7.6' +gem 'rails', '6.1.7.9' gem 'rake', '~> 13.0' gem 'rbnacl', '>= 7.1.1' # Libsodium Ruby binding. Used for encrypting export file passwords. gem 'rubyzip', '~> 2.3', # Zip and encrypt exported files @@ -42,17 +42,20 @@ gem 'rubyzip', '~> 2.3', # Zip and encrypt exported files gem 'spreadsheet', '~> 1.3' # Read XLS spreadsheets for imports (not XLSX!). TODO: Different gem? Reconsider? # Note: if upgrading Sunspot, update the corresponding version of Solr on the Docker image # Current Solr version is 5.3.1 -gem 'sunspot_rails', '~> 2.6' # Rails ODM bindings to Solr -gem 'sunspot_solr', '~> 2.6' # Ruby bindings to Solr +gem 'sunspot_rails', '~> 2.6', # Rails ODM bindings to Solr + require: false +gem 'sunspot_solr', '~> 2.6', # Ruby bindings to Solr + require: false +gem 'text', '~> 1.3' # Phonetic Search Algorithms gem 'twitter_cldr', '~> 4.4' # Localization for dates, money. TODO: Is this still used? gem 'tzinfo-data', '~> 1.2023' # Timezone Data for TZInfo -gem 'uri', '>= 0.12.2' # CVE-2023-36617: ReDoS vulnerability in URI +gem 'uri', '~> 0.12' # CVE-2023-36617: ReDoS vulnerability in URI gem 'web-push', '~> 3.0' gem 'will_paginate', '~> 4.0' # Paginates ActiveRecord models TODO: This can be refactored away. gem 'write_xlsx', '~> 1.11' # Exports XLSX group :development, :test do - gem 'bundler-audit', '~> 0.8' + gem 'bundler-audit', '~> 0.9' gem 'ci_reporter', '~> 2.0' gem 'factory_bot', '~> 5.0' gem 'foreman' @@ -78,6 +81,7 @@ group :development, :test do gem 'rspec-rails', '~> 6.0' gem 'rubocop', '~> 1.54' gem 'rubocop-performance', '~> 1.18' + gem 'ruby-lsp', '~> 0.17' gem 'ruby-prof', '~> 0.17' gem 'simplecov', '~> 0.18' # TODO: Latest version (1.2.5) of this conflicts with sunspot gem. Upgrade when we upgrade sunspot diff --git a/Gemfile.lock b/Gemfile.lock index c76ab23399..7b7165bbb3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,62 +1,62 @@ GEM remote: https://rubygems.org/ specs: - actioncable (6.1.7.6) - actionpack (= 6.1.7.6) - activesupport (= 6.1.7.6) + actioncable (6.1.7.9) + actionpack (= 6.1.7.9) + activesupport (= 6.1.7.9) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.1.7.6) - actionpack (= 6.1.7.6) - activejob (= 6.1.7.6) - activerecord (= 6.1.7.6) - activestorage (= 6.1.7.6) - activesupport (= 6.1.7.6) + actionmailbox (6.1.7.9) + actionpack (= 6.1.7.9) + activejob (= 6.1.7.9) + activerecord (= 6.1.7.9) + activestorage (= 6.1.7.9) + activesupport (= 6.1.7.9) mail (>= 2.7.1) - actionmailer (6.1.7.6) - actionpack (= 6.1.7.6) - actionview (= 6.1.7.6) - activejob (= 6.1.7.6) - activesupport (= 6.1.7.6) + actionmailer (6.1.7.9) + actionpack (= 6.1.7.9) + actionview (= 6.1.7.9) + activejob (= 6.1.7.9) + activesupport (= 6.1.7.9) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.1.7.6) - actionview (= 6.1.7.6) - activesupport (= 6.1.7.6) + actionpack (6.1.7.9) + actionview (= 6.1.7.9) + activesupport (= 6.1.7.9) rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.1.7.6) - actionpack (= 6.1.7.6) - activerecord (= 6.1.7.6) - activestorage (= 6.1.7.6) - activesupport (= 6.1.7.6) + actiontext (6.1.7.9) + actionpack (= 6.1.7.9) + activerecord (= 6.1.7.9) + activestorage (= 6.1.7.9) + activesupport (= 6.1.7.9) nokogiri (>= 1.8.5) - actionview (6.1.7.6) - activesupport (= 6.1.7.6) + actionview (6.1.7.9) + activesupport (= 6.1.7.9) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.1.7.6) - activesupport (= 6.1.7.6) + activejob (6.1.7.9) + activesupport (= 6.1.7.9) globalid (>= 0.3.6) - activemodel (6.1.7.6) - activesupport (= 6.1.7.6) - activerecord (6.1.7.6) - activemodel (= 6.1.7.6) - activesupport (= 6.1.7.6) + activemodel (6.1.7.9) + activesupport (= 6.1.7.9) + activerecord (6.1.7.9) + activemodel (= 6.1.7.9) + activesupport (= 6.1.7.9) activerecord-nulldb-adapter (0.9.0) activerecord (>= 5.2.0, < 7.1) - activestorage (6.1.7.6) - actionpack (= 6.1.7.6) - activejob (= 6.1.7.6) - activerecord (= 6.1.7.6) - activesupport (= 6.1.7.6) + activestorage (6.1.7.9) + actionpack (= 6.1.7.9) + activejob (= 6.1.7.9) + activerecord (= 6.1.7.9) + activesupport (= 6.1.7.9) marcel (~> 1.0) mini_mime (>= 1.1.0) - activesupport (6.1.7.6) + activesupport (6.1.7.9) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -93,7 +93,7 @@ GEM azure-core (~> 0.1.13) nokogiri (~> 1.6, >= 1.6.8) base64 (0.1.1) - bcrypt (3.1.19) + bcrypt (3.1.20) builder (3.2.4) bundler-audit (0.9.1) bundler (>= 1.2.0, < 3) @@ -106,38 +106,26 @@ GEM rexml cldr-plurals-runtime-rb (1.1.0) coderay (1.1.3) - concurrent-ruby (1.2.2) + concurrent-ruby (1.2.3) connection_pool (2.4.1) crass (1.0.6) csv-safe (3.2.1) daemons (1.4.1) - date (3.3.3) + date (3.4.1) deep_merge (1.2.2) delayed_job (4.1.11) activesupport (>= 3.0, < 8.0) delayed_job_active_record (4.1.7) activerecord (>= 3.0, < 8.0) delayed_job (>= 3.0, < 5) - devise (4.9.2) + devise (4.9.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) responders warden (~> 1.2.3) - devise-jwt (0.11.0) - devise (~> 4.0) - warden-jwt_auth (~> 0.8) diff-lcs (1.5.0) docile (1.4.0) - dry-auto_inject (1.0.1) - dry-core (~> 1.0) - zeitwerk (~> 2.6) - dry-configurable (1.1.0) - dry-core (~> 1.0, < 2) - zeitwerk (~> 2.6) - dry-core (1.0.1) - concurrent-ruby (~> 1.0) - zeitwerk (~> 2.6) erubi (1.12.0) factory_bot (5.2.0) activesupport (>= 4.2.0) @@ -150,12 +138,12 @@ GEM activemodel (>= 3.2) mime-types (>= 1.0) foreman (0.87.2) - globalid (1.1.0) - activesupport (>= 5.0) + globalid (1.2.1) + activesupport (>= 6.1) hana (1.3.7) highline (2.1.0) hkdf (1.0.0) - i18n (1.14.1) + i18n (1.14.4) concurrent-ruby (~> 1.0) i18n-js (3.9.2) i18n (>= 0.6.6) @@ -176,7 +164,7 @@ GEM actionview (>= 5.0.0) activesupport (>= 5.0.0) jmespath (1.6.2) - json (2.6.3) + json (2.7.2) json_schemer (1.0.3) hana (~> 1.3) regexp_parser (~> 2.0) @@ -184,7 +172,8 @@ GEM json_spec (1.1.5) multi_json (~> 1.0) rspec (>= 2.0, < 4.0) - jwt (2.7.1) + jwt (2.8.1) + base64 language_server-protocol (3.17.0.3) launchy (2.5.2) addressable (~> 2.8) @@ -193,7 +182,8 @@ GEM listen (3.8.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - loofah (2.21.3) + logger (1.6.1) + loofah (2.23.1) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) @@ -201,40 +191,40 @@ GEM net-imap net-pop net-smtp - marcel (1.0.2) + marcel (1.0.4) matrix (0.4.2) memory_profiler (1.0.1) - method_source (1.0.0) + method_source (1.1.0) mime-types (3.5.1) mime-types-data (~> 3.2015) mime-types-data (3.2023.0808) mini_magick (4.12.0) mini_mime (1.1.5) - mini_portile2 (2.8.5) + mini_portile2 (2.8.8) minipack (0.3.6) actionview railties (>= 4.2) - minitest (5.19.0) + minitest (5.22.3) multi_json (1.15.0) multipart-post (2.3.0) net-http-persistent (4.0.2) connection_pool (~> 2.2) - net-imap (0.3.7) + net-imap (0.5.1) date net-protocol net-pop (0.1.2) net-protocol - net-protocol (0.2.1) + net-protocol (0.2.2) timeout - net-smtp (0.3.3) + net-smtp (0.5.0) net-protocol - nio4r (2.5.9) - nokogiri (1.16.2) + nio4r (2.7.4) + nokogiri (1.16.8) mini_portile2 (~> 2.8.2) racc (~> 1.4) openssl (3.1.0) orm_adapter (0.5.0) - parallel (1.23.0) + parallel (1.25.1) parser (3.2.2.3) ast (~> 2.4.1) racc @@ -246,6 +236,7 @@ GEM ttfunk (~> 1.7) prawn-table (0.2.2) prawn (>= 1.3.0, < 3.0.0) + prism (1.0.0) pry (0.14.2) coderay (~> 1.1) method_source (~> 1.0) @@ -253,10 +244,10 @@ GEM byebug (~> 11.0) pry (>= 0.13, < 0.15) public_suffix (5.0.3) - puma (6.4.2) + puma (6.5.0) nio4r (~> 2.0) - racc (1.7.1) - rack (2.2.8) + racc (1.8.1) + rack (2.2.9) rack-attack (6.7.0) rack (>= 1.0, < 4) rack-mini-profiler (3.1.1) @@ -266,20 +257,20 @@ GEM rack_session_access (0.2.0) builder (>= 2.0.0) rack (>= 1.0.0) - rails (6.1.7.6) - actioncable (= 6.1.7.6) - actionmailbox (= 6.1.7.6) - actionmailer (= 6.1.7.6) - actionpack (= 6.1.7.6) - actiontext (= 6.1.7.6) - actionview (= 6.1.7.6) - activejob (= 6.1.7.6) - activemodel (= 6.1.7.6) - activerecord (= 6.1.7.6) - activestorage (= 6.1.7.6) - activesupport (= 6.1.7.6) + rails (6.1.7.9) + actioncable (= 6.1.7.9) + actionmailbox (= 6.1.7.9) + actionmailer (= 6.1.7.9) + actionpack (= 6.1.7.9) + actiontext (= 6.1.7.9) + actionview (= 6.1.7.9) + activejob (= 6.1.7.9) + activemodel (= 6.1.7.9) + activerecord (= 6.1.7.9) + activestorage (= 6.1.7.9) + activesupport (= 6.1.7.9) bundler (>= 1.15.0) - railties (= 6.1.7.6) + railties (= 6.1.7.9) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) @@ -289,30 +280,32 @@ GEM activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.6.0) + rails-html-sanitizer (1.6.1) loofah (~> 2.21) - nokogiri (~> 1.14) + nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) rails-i18n (7.0.8) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 8) - railties (6.1.7.6) - actionpack (= 6.1.7.6) - activesupport (= 6.1.7.6) + railties (6.1.7.9) + actionpack (= 6.1.7.9) + activesupport (= 6.1.7.9) method_source rake (>= 12.2) thor (~> 1.0) rainbow (3.1.1) - rake (13.0.6) + rake (13.2.1) rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) rbnacl (7.1.1) ffi + rbs (3.5.3) + logger regexp_parser (2.8.1) - responders (3.1.0) + responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) - rexml (3.2.6) + rexml (3.3.9) roo (2.10.0) nokogiri (~> 1) rubyzip (>= 1.3.0, < 3.0.0) @@ -348,7 +341,7 @@ GEM rspec-mocks (~> 3.12) rspec-support (~> 3.12) rspec-support (3.12.1) - rubocop (1.56.1) + rubocop (1.56.4) base64 (~> 0.1.1) json (~> 2.3) language_server-protocol (>= 3.17.0) @@ -360,11 +353,16 @@ GEM rubocop-ast (>= 1.28.1, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.29.0) + rubocop-ast (1.30.0) parser (>= 3.2.1.0) - rubocop-performance (1.19.0) - rubocop (>= 1.7.0, < 2.0) - rubocop-ast (>= 0.4.0) + rubocop-performance (1.20.2) + rubocop (>= 1.48.1, < 2.0) + rubocop-ast (>= 1.30.0, < 2.0) + ruby-lsp (0.17.17) + language_server-protocol (~> 3.17.0) + prism (~> 1.0) + rbs (>= 3, < 4) + sorbet-runtime (>= 0.5.10782) ruby-ole (1.2.12.2) ruby-prof (0.18.0) ruby-progressbar (1.13.0) @@ -379,14 +377,15 @@ GEM simplecov_json_formatter (0.1.4) simpleidn (0.2.1) unf (~> 0.1.4) + sorbet-runtime (0.5.11566) spreadsheet (1.3.0) ruby-ole - sprockets (4.2.0) + sprockets (4.2.1) concurrent-ruby (~> 1.0) rack (>= 2.2.4, < 4) - sprockets-rails (3.4.2) - actionpack (>= 5.2) - activesupport (>= 5.2) + sprockets-rails (3.5.2) + actionpack (>= 6.1) + activesupport (>= 6.1) sprockets (>= 3.0.0) sunspot (2.6.0) pr_geohash (~> 1.0) @@ -400,8 +399,9 @@ GEM sunspot_solr terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) - thor (1.2.2) - timeout (0.4.0) + text (1.3.1) + thor (1.3.1) + timeout (0.4.2) ttfunk (1.7.0) twitter_cldr (4.4.5) camertron-eprun @@ -418,11 +418,6 @@ GEM uri (0.12.2) warden (1.2.9) rack (>= 2.0.9) - warden-jwt_auth (0.8.0) - dry-auto_inject (>= 0.8, < 2) - dry-configurable (>= 0.13, < 2) - jwt (~> 2.1) - warden (~> 1.2) web-push (3.0.0) hkdf (~> 1.0) jwt (~> 2.0) @@ -433,7 +428,7 @@ GEM will_paginate (4.0.0) write_xlsx (1.11.1) rubyzip (>= 1.0.0) - zeitwerk (2.6.11) + zeitwerk (2.6.13) PLATFORMS ruby @@ -442,7 +437,7 @@ DEPENDENCIES activerecord-nulldb-adapter aws-sdk-s3 (~> 1.130) azure-storage-blob (~> 1.1) - bundler-audit (~> 0.8) + bundler-audit (~> 0.9) cancancan (~> 3.5) ci_reporter (~> 2.0) csv-safe (~> 3.2) @@ -450,7 +445,6 @@ DEPENDENCIES deep_merge (~> 1.2) delayed_job_active_record (~> 4.1.7) devise (~> 4.9) - devise-jwt (~> 0.10) factory_bot (~> 5.0) faraday (~> 0.17) file_validators (~> 3.0) @@ -461,6 +455,7 @@ DEPENDENCIES jbuilder (~> 2.11) json_schemer (~> 1.0) json_spec (~> 1.1) + jwt (~> 2.8) letter_opener (~> 1.7) listen (~> 3.1) matrix (~> 0.4) @@ -479,7 +474,7 @@ DEPENDENCIES rack-mini-profiler (>= 1.0.0) rack-test (~> 1.1) rack_session_access (~> 0.2) - rails (= 6.1.7.6) + rails (= 6.1.7.9) rails-controller-testing (~> 1.0) rake (~> 13.0) rbnacl (>= 7.1.1) @@ -491,6 +486,7 @@ DEPENDENCIES rspec-rails (~> 6.0) rubocop (~> 1.54) rubocop-performance (~> 1.18) + ruby-lsp (~> 0.17) ruby-prof (~> 0.17) rubyzip (~> 2.3) simplecov (~> 0.18) @@ -498,15 +494,16 @@ DEPENDENCIES sunspot_rails (~> 2.6) sunspot_solr (~> 2.6) sunspot_test (~> 0.4) + text (~> 1.3) twitter_cldr (~> 4.4) tzinfo-data (~> 1.2023) - uri (>= 0.12.2) + uri (~> 0.12) web-push (~> 3.0) will_paginate (~> 4.0) write_xlsx (~> 1.11) RUBY VERSION - ruby 3.2.2p53 + ruby 3.3.5p100 BUNDLED WITH 2.4.18 diff --git a/README.md b/README.md index be8792fa64..b85ea76f85 100644 --- a/README.md +++ b/README.md @@ -2,27 +2,25 @@ Primero ======== -[![Build Status](https://github.com/primeroIMS/primero/actions/workflows/app.yml/badge.svg)](https://github.com/primeroIMS/primero/actions) +[![Build Status](https://github.com/primeroIMS/primero/actions/workflows/app.yml/badge.svg?branch=main)](https://github.com/primeroIMS/primero/actions) > [!WARNING] -> **Primero v2.5 adds support for PostgreSQL 14!** -> Support for PostgreSQL 10 is retained and remains the default when running using Ansible/Docker Compose. Please use this opportunity to upgrade! PostgreSQL 14 will be the default starting with Primero v2.6, and support for PostgreSQL 10 will be eventually dropped. See [here](doc/postgres_upgrade.md) for a recommended upgrade process. +> **Primero v2.10 adds support for PostgreSQL 15!** +> Support for PostgreSQL 14 is retained and remains the default when running using Ansible/Docker Compose. Please use this opportunity to upgrade! PostgreSQL 15 will be the default starting with Primero v2.11. support for PostgreSQL 10, 11 has been dropped and 14 will all eventually dropped. See [here](doc/postgres_upgrade.md) for a recommended upgrade process. ## Development A guide to getting started with Primero development is available [here](doc/getting_started_development.md). - - ## Notes - It is known that a few npm packages will throw a `requires a peer of` warning. Examples: Mui-datatables is behind on updating dependecies. Jsdom requires canvas, but we are mocking canvas. Canvas also requires extra packages on alpine, which is the reason for mocking canvas. ## Contributing - If contributing to the UI, make sure to read over the [UI/UX Development](doc/ui_ux.md) documents. -- If you are contributing via the DAO, make sure to read the relevant documents [here](doc/dao/Index.md). +- If you are contributing via the DAO, make sure to read the relevant documents [here](doc/dao/README.md). ## Production -Primero is deployed in production using Docker. Detailed Docker instructions exist in the file [docker/README.md](docker/README.md) +Primero is deployed in production using Ansible. Detailed Ansible instructions exist in the file [ansible/README.md](ansible/README.md) diff --git a/ansible/README.md b/ansible/README.md index 1bf206068c..f2d558a7bc 100644 --- a/ansible/README.md +++ b/ansible/README.md @@ -16,7 +16,7 @@ $ cd ansible $ bin/activate -2. Edit the Ansible inventory file and primero variables. Refer to the [Deploy](#markdown-header-deploy) section for more info. Create a copy of the template file and modify to get started quickly. +2. Edit the Ansible inventory file and primero variables. Refer to the [Deploy](#markdown-header-deploy) section for more info. Create a copy of the template file and modify to get started quickly. (venv) $ cp inventory/inventory.yml.temnplate inventory/inventory.yml (venv) $ vim inventory/inventory.yml @@ -24,6 +24,8 @@ The inventory file should include the Primero server you want to deploy to. You can refer to this [sample](inventory/inventory.yml.template) for further documentation. + > **Note:** If you want to use SOLR, ensure that `SOLR_ENABLED: 'true'` is set in the inventory file. To disable SOLR, set it to `false`. + 3. Create the `secrets.yml`. Refer to the [Deploy](#markdown-header-deploy) section for more info. @@ -37,7 +39,6 @@ primero_message_secret: 'generated_secret' postgres_password: 'generated_secret' devise_secret_key: 'generated_secret' - devise_jwt_secret_key: 'generated_secret' ssh_private_key: | -----BEGIN RSA PRIVATE KEY----- klkdl;fk;lskdflkds;kf;kdsl;afkldsakf;kasd;f @@ -131,6 +132,8 @@ certbot.yml In order to deploy primero using Ansible you will first need to create an ansible `inventory.yml` file located at `ansible/inventory/inventory.yml`. Below is example of what the file should look like. There is also a sample template file provided in the repo, `ansible/inventory/inventory.yml.template`. +> **Note:** You can enable or disable the **SOLR** service by setting the `SOLR_ENABLED` variable to true or false in your inventory file. + --- all: @@ -154,6 +157,9 @@ Below is example of what the file should look like. There is also a sample templ primero_configuration_repo: 'git@bitbucket.org:quoin/primero-x-configuration.git' primero_configuration_repo_branch: 'main' primero_configuration_path: 'directory/of/config/loader/script.rb' + environment_variables + RUN_DEFAULT_PRIMERO_SEEDS: 'false' + SOLR_ENABLED: 'true' All these variables are required with the exception of `certbot_domain` and `certbot_email`. These certbot variables are required only when using certbot. @@ -206,7 +212,6 @@ key just leave the variable `ssh_private_key` out of the secrets.yml file. primero_message_secret: 'generated_secret' postgres_password: 'generated_secret' devise_secret_key: 'generated_secret' - devise_jwt_secret_key: 'generated_secret' secret_environment_variables: SMTP_USER: 'secret' SMTP_PASSWORD: 'secret' @@ -234,7 +239,7 @@ The optional dictionary `secret_environment_variables` can contain key/value pai ## Config promotion -In order to enable configuration promotion between two servers handled by ansible, you have to set some environment variables on the **demo** server, the one responsible to handle and sed the configuration to the production server. +In order to enable configuration promotion between two servers handled by ansible, you have to set some environment variables on the **demo** server, the one responsible to handle and send the configuration to the production server. ```shell PRIMERO_SANDBOX_UI: 'true' @@ -340,3 +345,4 @@ To execute the migrations, run: This command will execute migrations and also attempt to run the configuration indicated in `primero_configuration_repo_branch`. **Please be cautious as this could overwrite the current system configuration**. if you want to prevent a configuration from being applied, make sure to set the configuration version that is applied to the system. +Also in your inventory file you can add `RUN_DEFAULT_PRIMERO_SEEDS: 'false'` to the variables and remove `primero_configuration_path` keys to prevent that the configuration will not be applied diff --git a/ansible/install-docker.yml b/ansible/install-docker.yml index ae0d7810ac..5d8144a3f3 100644 --- a/ansible/install-docker.yml +++ b/ansible/install-docker.yml @@ -5,7 +5,4 @@ roles: - 'manage-users' - 'quoin.infrastructure.configure_journald' - - 'quoin.infrastructure.install_python3_virtualenv' - - 'quoin.infrastructure.install_python3_docker' - - 'quoin.infrastructure.install_python3_docker_compose' - 'quoin.infrastructure.install_docker' diff --git a/ansible/inventory/inventory.yml.template b/ansible/inventory/inventory.yml.template index 4c3acf64f3..6fa9e3b3e1 100644 --- a/ansible/inventory/inventory.yml.template +++ b/ansible/inventory/inventory.yml.template @@ -5,11 +5,11 @@ all: ansible_user: 'ubuntu' primero_host: 'primero.example.com' primero_tag: 'latest' - # As of Primero v2.5, the default Docker deployed PostgreSQL is 10.22. + # As of Primero v2.11, the default Docker deployed PostgreSQL is 15.6. # If you want to run Primero with a different version of PostgreSQL, - # set primero_postgres_version to either '11', '14', or '15'. + # set primero_postgres_version to either '14', or '15'. # NOTE: YOU NEED TO PERFORM A DATA MIGRATION BEFORE CHANGING POSTGRES VERSIONS!!!!!! - # primero_postgres_version: '14' + # primero_postgres_version: '15' locale_all: 'en,fr,ar' always_pull: true # These 3 variables are used to drive the build task. @@ -39,3 +39,4 @@ all: # LOCALE_DEFAULT: 'ar' # Optionally override English as the default locale. PRIMERO_WEBPUSH: 'true' PRIMERO_WEBPUSH_CONTACT: 'primero.dev@quoininc.com' + SOLR_ENABLED: 'false' diff --git a/ansible/roles/application-primero/defaults/main.yml b/ansible/roles/application-primero/defaults/main.yml index d2aafcf694..9bb3aa60f8 100644 --- a/ansible/roles/application-primero/defaults/main.yml +++ b/ansible/roles/application-primero/defaults/main.yml @@ -2,4 +2,4 @@ --- # TODO Change this to PG15 with v2.11.0 -primero_postgres_version: "14" +primero_postgres_version: "15" diff --git a/ansible/roles/application-primero/tasks/main.yml b/ansible/roles/application-primero/tasks/main.yml index d3799f2058..29dc89e88c 100644 --- a/ansible/roles/application-primero/tasks/main.yml +++ b/ansible/roles/application-primero/tasks/main.yml @@ -193,6 +193,7 @@ PRIMERO_IMAGE_REPOSITORY: '{{ primero_image_repositroy|default("primeroims") }}' PRIMERO_DEPLOY_NODB: '{{ primero_deploy_nodb|default("false") }}' PRIMERO_POSTGRES_VERSION: '{{ primero_postgres_version }}' + SOLR_ENABLED: '{{ environment_variables.SOLR_ENABLED|default("false") }}' become: yes tags: - 'never' diff --git a/ansible/roles/manage-users/tasks/main.yml b/ansible/roles/manage-users/tasks/main.yml index c02f01970b..46bad87056 100644 --- a/ansible/roles/manage-users/tasks/main.yml +++ b/ansible/roles/manage-users/tasks/main.yml @@ -6,6 +6,8 @@ name: '{{ application_container_username }}' gid: 1100 become: yes + tags: + - 'always' - name: 'create application container user' user: @@ -14,12 +16,16 @@ group: '{{ application_container_username }}' uid: 1100 become: yes + tags: + - 'always' - name: 'Ensure group {{ nginx_container_username }} exists' group: name: '{{ nginx_container_username }}' gid: 1101 become: yes + tags: + - 'always' - name: 'create nginx container user' user: @@ -28,6 +34,8 @@ group: '{{ nginx_container_username }}' uid: 1101 become: yes + tags: + - 'always' - name: 'Remove {{ application_container_username }} from /etc/subuid' lineinfile: @@ -35,6 +43,8 @@ state: 'absent' regexp: 'primero' become: yes + tags: + - 'always' - name: 'Remove {{ application_container_username }} from /etc/subgid' lineinfile: @@ -42,6 +52,8 @@ state: 'absent' regexp: '{{ application_container_username }}' become: yes + tags: + - 'always' - name: 'edit /etc/subuid for {{ application_container_username }} user mapping for docker containers' lineinfile: @@ -50,6 +62,8 @@ insertafter: EOF line: '{{ application_container_username }}:0:1000' become: yes + tags: + - 'always' - name: 'edit /etc/subuid for {{ application_container_username }} user mapping for docker containers' lineinfile: @@ -58,6 +72,8 @@ insertafter: EOF line: '{{ application_container_username }}:1100:65536' become: yes + tags: + - 'always' - name: 'edit /etc/subgid for {{ application_container_username }} user mapping for docker containers' lineinfile: @@ -66,6 +82,8 @@ insertafter: EOF line: '{{ application_container_username }}:0:1000' become: yes + tags: + - 'always' - name: 'edit /etc/subgid for {{ application_container_username }} user mapping for docker containers' lineinfile: @@ -74,6 +92,8 @@ insertafter: EOF line: '{{ application_container_username }}:1100:65536' become: yes + tags: + - 'always' - name: Adding existing ansible user {{ ansible_user }} to application group user: @@ -81,3 +101,5 @@ groups: '{{ application_container_username }}' append: true become: true + tags: + - 'always' diff --git a/ansible/roles/primero-certbot/files/certbot b/ansible/roles/primero-certbot/files/certbot index 6dbf2f16d8..56e79f7d4a 100644 --- a/ansible/roles/primero-certbot/files/certbot +++ b/ansible/roles/primero-certbot/files/certbot @@ -131,7 +131,7 @@ def _main(argv): finally: shutil.rmtree(host_dir) if renewed: - nginx_container_name = ''.join([arguments.project_name, '_nginx_1']) + nginx_container_name = ''.join([arguments.project_name, '-nginx-1']) _check_call(['docker', 'exec', '--interactive', nginx_container_name, 'update-nginx-conf.sh']) _check_call(['docker', 'exec', '--interactive', nginx_container_name, 'nginx', '-s', 'reload']) return 0 diff --git a/app/auth/idp_token_strategy.rb b/app/auth/idp_token_strategy.rb index 4300a97a46..128747527a 100644 --- a/app/auth/idp_token_strategy.rb +++ b/app/auth/idp_token_strategy.rb @@ -5,11 +5,18 @@ require 'warden' # This strategy is used when Primero needs to authorize a JWT token from an external identity provider. -class IdpTokenStrategy < Warden::JWTAuth::Strategy +class IdpTokenStrategy < Warden::Strategies::Base + METHOD = 'Bearer' + def valid? !token.nil? && Rails.configuration.x.idp.use_identity_provider end + # This is an override for warden to skip storing session in a cookie + def store? + true + end + def authenticate! idp_token = IdpToken.build(token) return fail!('Invalid JWT token') unless idp_token.valid? @@ -22,4 +29,20 @@ def authenticate! rescue StandardError => e fail!(e.message) end + + def self.token_from_header(header) + auth = header['HTTP_AUTHORIZATION'] + method, token = auth&.split + method == METHOD ? token : nil + end + + private + + def token + @token ||= auth_header(env) + end + + def auth_header(env) + IdpTokenStrategy.token_from_header(env) + end end diff --git a/app/controllers/api/v2/alerts_controller.rb b/app/controllers/api/v2/alerts_controller.rb index efc0227f0a..baea989181 100644 --- a/app/controllers/api/v2/alerts_controller.rb +++ b/app/controllers/api/v2/alerts_controller.rb @@ -19,13 +19,7 @@ def index def destroy authorize! :remove_alert, @record - alert_id = params[:id] - alert = @record.alerts.find { |a| a.unique_id == alert_id } - if alert.present? - alert.destroy! - return - end - raise ActiveRecord::RecordNotFound + @record.remove_alert_by_unique_id!(params[:id]) end def index_action_message diff --git a/app/controllers/api/v2/assigns_controller.rb b/app/controllers/api/v2/assigns_controller.rb index 7d466bff77..656c285ea0 100644 --- a/app/controllers/api/v2/assigns_controller.rb +++ b/app/controllers/api/v2/assigns_controller.rb @@ -4,7 +4,7 @@ # API endpoints that handle record reassignment class Api::V2::AssignsController < Api::V2::RecordResourceController - before_action :bulk_approval_params, only: [:create_bulk] + before_action :bulk_assign_params, only: [:create_bulk] before_action :verify_bulk_records_size, only: [:create_bulk] def index @@ -22,7 +22,7 @@ def create def create_bulk authorize_assign!(model_class) - BulkAssignRecordsJob.perform_later(model_class, current_user, bulk_approval_params) + BulkAssignRecordsJob.perform_later(model_class, current_user, bulk_assign_params) end private @@ -43,10 +43,7 @@ def assign(record) transitioned_to = params[:data][:transitioned_to] notes = params[:data][:notes] transitioned_by = current_user.user_name - Assign.create!( - record:, transitioned_to:, - transitioned_by:, notes: - ) + Assign.create!(record:, transitioned_to:, transitioned_by:, notes:) end def create_action_message @@ -61,19 +58,19 @@ def create_bulk_record_resource 'bulk_assign' end - def bulk_approval_params - @bulk_approval_params ||= params.require(:data).permit(:transitioned_to, :notes, :query, { filters: {} }).to_h + def bulk_assign_params + @bulk_assign_params ||= params.require(:data) + .permit(:transitioned_to, :notes, :query, filters: {}) + .tap { |data_param| data_param.require(:filters) } end def find_records @records = [] + @records_total = BulkAssignService.new(model_class, current_user, bulk_assign_params).search_records.total end def verify_bulk_records_size - if @bulk_approval_params[:filters][:short_id].blank? || - @bulk_approval_params[:filters][:short_id].length <= Assign::MAX_BULK_RECORDS - return - end + return if @records_total <= Assign::MAX_BULK_RECORDS raise(Errors::BulkAssignRecordsSizeError, 'case.messages.bulk_assign_limit') end diff --git a/app/controllers/api/v2/attachments_controller.rb b/app/controllers/api/v2/attachments_controller.rb index ed4adb1046..5379384f1f 100644 --- a/app/controllers/api/v2/attachments_controller.rb +++ b/app/controllers/api/v2/attachments_controller.rb @@ -4,6 +4,8 @@ # API endpoints for adding and removing attachments on Primero resources (usually records) class Api::V2::AttachmentsController < Api::V2::RecordResourceController + before_action :validate_update_params!, only: [:update] + def create @attachment = Attachment.new(attachment_params) authorize! :create, @attachment @@ -11,6 +13,13 @@ def create updates_for_record(@record) end + def update + @attachment = Attachment.find(params[:id]) + @attachment.assign_attributes(attachment_update_params) + @attachment.save! + updates_for_record(@record) + end + def destroy @attachment = Attachment.find(params[:id]) authorize! :destroy, @attachment @@ -38,4 +47,21 @@ def attachment_params @attachment_params[:record] = @record @attachment_params end + + def attachment_update_params + return @attachment_update_params if @attachment_update_params + + @attachment_update_params = params.require(:data).permit(:description, :is_current, :date, :comments).to_h + @attachment_update_params[:record] = @record + @attachment_update_params + end + + def validate_update_params! + invalid_props = %i[attachment_type field_name file_name attachment].select { |key| params[:data].key?(key) } + return unless invalid_props.present? + + invalid_record_json = Errors::InvalidRecordJson.new('Invalid Attachment JSON') + invalid_record_json.invalid_props = invalid_props + raise invalid_record_json + end end diff --git a/app/controllers/api/v2/bulk_exports_controller.rb b/app/controllers/api/v2/bulk_exports_controller.rb index 7a66fa2bae..23c39a38ac 100644 --- a/app/controllers/api/v2/bulk_exports_controller.rb +++ b/app/controllers/api/v2/bulk_exports_controller.rb @@ -48,7 +48,7 @@ def model_class def authorize_export! export_format = export_params[:export_format] == 'xlsx' ? 'xls' : export_params[:export_format] action = "export_#{export_format}".to_sym - record_model = export_params[:record_type] && Record.model_from_name(export_params[:record_type]) + record_model = export_params[:record_type] && PrimeroModelService.to_model(export_params[:record_type]) authorize! action, record_model end diff --git a/app/controllers/api/v2/children_incidents_controller.rb b/app/controllers/api/v2/children_incidents_controller.rb index f0bc13e834..81a2db0a84 100644 --- a/app/controllers/api/v2/children_incidents_controller.rb +++ b/app/controllers/api/v2/children_incidents_controller.rb @@ -6,6 +6,8 @@ class Api::V2::ChildrenIncidentsController < Api::V2::RecordResourceController before_action :permit_fields before_action :select_fields, only: %i[index new] + before_action :find_record, only: %i[index new update_bulk] + before_action :find_incidents, only: %i[update_bulk] def index authorize! :read, Incident @@ -20,8 +22,14 @@ def new render 'api/v2/incidents/new' end + def update_bulk + authorize_all!(:link_incident_to_case, @incidents) + link_incidents if @incidents.present? + updates_for_record(@record) + end + def permit_fields - @permitted_field_names = PermittedFieldService.new(current_user, Incident).permitted_field_names + @permitted_field_names = PermittedFieldService.new(current_user, Incident).permitted_field_names(module_unique_id) end def select_fields @@ -40,4 +48,16 @@ def authorize_new! current_user.can?(:incident_from_case, Child) raise Errors::ForbiddenOperation unless case_incident end + + def find_incidents + @incidents = Incident.find(params['data']['incident_ids']) + end + + def link_incidents + ActiveRecord::Base.transaction do + @incidents.each do |incident| + incident.update(incident_case_id: @record.id) + end + end + end end diff --git a/app/controllers/api/v2/concerns/jwt_tokens.rb b/app/controllers/api/v2/concerns/jwt_tokens.rb deleted file mode 100644 index 4e1274259c..0000000000 --- a/app/controllers/api/v2/concerns/jwt_tokens.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: true - -# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -# Set the DeviseJwt tokens into cookies -module Api::V2::Concerns::JwtTokens - extend ActiveSupport::Concern - - def current_token - request.env['warden-jwt_auth.token'] || request.headers['HTTP_AUTHORIZATION']&.split(' ')&.last - end - - def token_to_cookie - return unless current_token.present? - - cookies[:primero_token] = { - value: current_token, - domain: primero_host, - same_site: :strict, - httponly: true, - secure: (Rails.env == 'production') - } - end - - def primero_host - Rails.application.routes.default_url_options[:host] - end -end diff --git a/app/controllers/api/v2/concerns/pagination.rb b/app/controllers/api/v2/concerns/pagination.rb index 7c05539823..27df31c5f0 100644 --- a/app/controllers/api/v2/concerns/pagination.rb +++ b/app/controllers/api/v2/concerns/pagination.rb @@ -11,7 +11,11 @@ def page end def per - @per ||= (params[:per].try(:to_i) || 20) + return @per if @per.present? + + @per = params[:per].try(:to_i) + @per = 20 unless @per.present? + @per = [@per, 1000].min end def offset diff --git a/app/controllers/api/v2/concerns/record.rb b/app/controllers/api/v2/concerns/record.rb index ab8dc65a1c..124a466d07 100644 --- a/app/controllers/api/v2/concerns/record.rb +++ b/app/controllers/api/v2/concerns/record.rb @@ -12,19 +12,15 @@ module Api::V2::Concerns::Record included do before_action :display_permitted_forms before_action :instantiate_app_services - before_action :permit_params, only: %i[index create update] before_action :permit_fields, only: %i[index create] before_action :select_fields_for_index, only: [:index] end def index authorize! :index, model_class - search = SearchService.search( - model_class, filters: search_filters, query_scope:, query: params[:query], - sort: sort_order, pagination: - ) - @records = search.results - @total = search.total + result = search_records + @total = result[:total] + @records = result[:records] render 'api/v2/records/index' end @@ -64,20 +60,29 @@ def destroy render 'api/v2/records/destroy' end - def permit_params - # We do not use strong params for record updates but rely on: - # 1. Validation against a generated JSON schema - # 2. Intersection with a generated @permitted_field_name list - params.permit! + def index_params + return @index_params if @index_params + + @index_params = params.permit( + :fields, :order, :order_by, :page, :per, :total, + :id_search, :query, :query_scope, :phonetic, :format, + *permitted_index_params(params) + ) end - def validate_json! + def json_validation_service + return @json_validation_service if @json_validation_service + permitted_fields = @permitted_form_fields_service.permitted_fields( - authorized_roles, model_class.parent_form, write? + authorized_roles, model_class.parent_form, module_unique_id, write? ) action_fields = @permitted_field_service.permitted_fields_schema - service = RecordJsonValidatorService.new(fields: permitted_fields, schema_supplement: action_fields) - service.validate!(params[:data].to_h) + @json_validation_service = RecordJsonValidatorService.new(fields: permitted_fields, + schema_supplement: action_fields) + end + + def validate_json! + json_validation_service.validate!(record_params) end def authorized_roles @@ -85,7 +90,9 @@ def authorized_roles end def permit_fields - @permitted_field_names = @permitted_field_service.permitted_field_names(write?, update?, authorized_roles) + @permitted_field_names = @permitted_field_service.permitted_field_names( + module_unique_id, write?, update?, authorized_roles + ) end def select_fields_for_show @@ -107,8 +114,16 @@ def select_updated_fields end def record_params - record_params = params['data'].try(:to_h) || {} - record_params.select { |k, _| @permitted_field_names.include?(k) } + return @record_params.to_h if @record_params.present? + + if params[:data].present? + strong_params = json_validation_service.strong_params + @record_params = params.require(:data).permit(strong_params).to_h + @record_params.to_h + else + # We send empty data when we add an attachment + @record_params = {} + end end def find_record @@ -121,7 +136,10 @@ def instantiate_app_services @record_data_service = RecordDataService.new @permitted_form_fields_service = PermittedFormFieldsService.instance @permitted_field_service = PermittedFieldService.new( - current_user, model_class, params[:record_action], params[:id_search], @permitted_form_fields_service + current_user, + model_class, + @permitted_form_fields_service, + { action_name: params[:record_action], id_search: params[:id_search] } ) end @@ -130,15 +148,34 @@ def query_scope end def search_filters - SearchFilterService.build_filters(params, @permitted_field_names) + SearchFilterService.build_filters(index_params, @permitted_field_names) end def display_permitted_forms @display_permitted_forms = false end + def module_unique_id + return @record.module_id if @record.present? + + params.dig(:data, :module_id) + end + private + def search_records + search = PhoneticSearchService.search( + model_class, { + query: index_params[:query], phonetic: index_params[:phonetic], filters: search_filters, + sort: sort_order, scope: query_scope, pagination: + } + ) + { total: search.total, records: search.records } + rescue ActiveRecord::StatementInvalid => e + Rails.logger.error(e) + { total: 0, records: model_class.none } + end + def write? action_name.in?(%w[create update]) end @@ -158,5 +195,21 @@ def authorize_update! authorize!(:update, @record) end end + + def permitted_index_params(params) + permitted_params = [] + params.each do |k, v| + next unless @permitted_field_names.include?(strip_location_prefix(k)) + + permitted_params << (v.is_a?(ActionController::Parameters) ? { k => {} } : k) + end + permitted_params + end + + def strip_location_prefix(param) + return Field.remove_location_parts(param) if Field.location_prefix?(param) + + param + end end # rubocop:enable Metrics/ModuleLength diff --git a/app/controllers/api/v2/flags_controller.rb b/app/controllers/api/v2/flags_controller.rb index 229f8cd9ac..0a6919f88f 100644 --- a/app/controllers/api/v2/flags_controller.rb +++ b/app/controllers/api/v2/flags_controller.rb @@ -8,14 +8,14 @@ class Api::V2::FlagsController < Api::V2::RecordResourceController def create authorize! :flag_record, @record - @flag = @record.add_flag(params['data']['message'], params['data']['date'], current_user.user_name) + @flag = @record.add_flag!(params['data']['message'], params['data']['date'], current_user.user_name) updates_for_record(@record) render :create, status: end def update authorize! :flag_resolve, @record - @flag = @record.remove_flag(params['id'], current_user.user_name, params['data']['unflag_message']) + @flag = @record.remove_flag!(params['id'], current_user.user_name, params['data']['unflag_message']) updates_for_record(@record) end diff --git a/app/controllers/api/v2/password_reset_controller.rb b/app/controllers/api/v2/password_reset_controller.rb index 61b7bbf352..ad47bb6df4 100644 --- a/app/controllers/api/v2/password_reset_controller.rb +++ b/app/controllers/api/v2/password_reset_controller.rb @@ -8,7 +8,6 @@ class Api::V2::PasswordResetController < Devise::PasswordsController respond_to :json include AuditLogActions - include Api::V2::Concerns::JwtTokens include ErrorHandling # Submit a request to reset a password over email. @@ -41,10 +40,7 @@ def respond_with(user, _opts = {}) return errors(user) unless user.errors.empty? json = { message: 'user.password_reset.success' } - if warden.user(resource_name) == user - token_to_cookie - json = json.merge(id: user.id, user_name: user.user_name, token: current_token) - end + json = json.merge(id: user.id, user_name: user.user_name) if warden.user(resource_name) == user render json: end diff --git a/app/controllers/api/v2/record_resource_controller.rb b/app/controllers/api/v2/record_resource_controller.rb index b8dd2cde69..8e6457dcb9 100644 --- a/app/controllers/api/v2/record_resource_controller.rb +++ b/app/controllers/api/v2/record_resource_controller.rb @@ -55,6 +55,12 @@ def record_data_service @record_data_service = RecordDataService.new end + def module_unique_id + return @record.module_id if @record.present? + + params.dig(:data, :module_id) + end + private def record_updated_fields(record) diff --git a/app/controllers/api/v2/referrals_controller.rb b/app/controllers/api/v2/referrals_controller.rb index c807c3ca76..d98646465f 100644 --- a/app/controllers/api/v2/referrals_controller.rb +++ b/app/controllers/api/v2/referrals_controller.rb @@ -67,7 +67,7 @@ def refer(record) referral.transitioned_by = current_user.user_name referral.record = record record.update_last_updated_by(current_user) - record.save! && referral.save! && referral + referral.save! && referral end def authorize_create!(record) diff --git a/app/controllers/api/v2/system_settings_controller.rb b/app/controllers/api/v2/system_settings_controller.rb index 7bbb57f4c4..13ca932bc7 100644 --- a/app/controllers/api/v2/system_settings_controller.rb +++ b/app/controllers/api/v2/system_settings_controller.rb @@ -7,7 +7,7 @@ class Api::V2::SystemSettingsController < ApplicationApiController def index @system_setting = SystemSettings.first @primero_modules = extended? ? PrimeroModule.all : [] - @agencies = extended? ? Agency.all : [] + @agencies = extended? ? extended_agencies : [] end def model_class @@ -17,4 +17,8 @@ def model_class def extended? params[:extended] == 'true' end + + def extended_agencies + Agency.includes(logo_full_attachment: :blob, logo_icon_attachment: :blob, terms_of_use_attachment: :blob).all + end end diff --git a/app/controllers/api/v2/tokens_controller.rb b/app/controllers/api/v2/tokens_controller.rb index 5bcaa5f48a..719fa67bc0 100644 --- a/app/controllers/api/v2/tokens_controller.rb +++ b/app/controllers/api/v2/tokens_controller.rb @@ -5,51 +5,32 @@ # The endpoint used to authenticate a user when native authentication is enabled in Primero class Api::V2::TokensController < Devise::SessionsController include AuditLogActions - include Api::V2::Concerns::JwtTokens include ErrorHandling respond_to :json - skip_before_action :verify_authenticity_token before_action :write_audit_log, only: [:respond_to_on_destroy] # This method overrides the deprecated ActionController::MimeResponds#respond_with # that Devise unfortunately still uses. We are overriding it to return a JSON object # for the Devise session create method. def respond_with(user, _opts = {}) - token_to_cookie - render json: { id: user.id, user_name: user.user_name, token: current_token } + render json: { id: user.id, user_name: user.user_name } end # Overriding method called by Devise session destroy. def respond_to_on_destroy - cookies.delete(:primero_token, domain: primero_host) render json: {} end - alias devise_create create def create if Rails.configuration.x.idp.use_identity_provider create_idp else - create_native - end - end - - # HACK: Removing primero_token cookie when failing to authenticate with current token. - def create_native - creation = catch(:warden) do - devise_create - end - # warden throws user scope Hash on authentication failure. - if creation.is_a?(Hash) - fail_to_authorize!(creation) - else - creation + super end end def create_idp - token_to_cookie idp_token = IdpToken.build(current_token) user = idp_token.valid? && idp_token.user if user @@ -60,7 +41,6 @@ def create_idp end def fail_to_authorize!(opts) - cookies.delete(:primero_token, domain: primero_host) throw(:warden, opts) end @@ -84,4 +64,8 @@ def create_action_message def destroy_action_message 'logout' end + + def current_token + IdpTokenStrategy.token_from_header(request.headers) + end end diff --git a/app/controllers/api/v2/users_controller.rb b/app/controllers/api/v2/users_controller.rb index 812d4f8b98..552ea5e8b7 100644 --- a/app/controllers/api/v2/users_controller.rb +++ b/app/controllers/api/v2/users_controller.rb @@ -41,6 +41,7 @@ def update validate_json!(User::USER_FIELDS_SCHEMA, user_params) @user.update_with_properties(@user_params) @user.save! + keep_user_signed_in end def destroy @@ -73,4 +74,8 @@ def welcome def identity_sync @user.identity_sync(current_user) end + + def keep_user_signed_in + bypass_sign_in(@user) if @user.saved_change_to_encrypted_password? && current_user == @user + end end diff --git a/app/controllers/api/v2/users_transitions_controller.rb b/app/controllers/api/v2/users_transitions_controller.rb index ca2c18d12f..6e62cf7445 100644 --- a/app/controllers/api/v2/users_transitions_controller.rb +++ b/app/controllers/api/v2/users_transitions_controller.rb @@ -47,7 +47,7 @@ def authorize_assign!(record) end def record_model - @record_model = Record.model_from_name(params[:record_type]) + @record_model = PrimeroModelService.to_model(params[:record_type]) end def record_module_unique_id diff --git a/app/controllers/application_api_controller.rb b/app/controllers/application_api_controller.rb index e9477fd518..76aed360a6 100644 --- a/app/controllers/application_api_controller.rb +++ b/app/controllers/application_api_controller.rb @@ -7,23 +7,38 @@ class ApplicationApiController < ActionController::API include CanCan::ControllerAdditions include AuditLogActions include ErrorHandling + include CsrfProtection # check_authorization #TODO: Uncomment after upgrading to CanCanCan v3 + before_action :authenticate_user! before_action :check_config_update_lock! + before_action :set_csrf_cookie, unless: -> { request_from_basic_auth? } + + protect_from_forgery with: :exception, if: -> { use_csrf_protection? } class << self attr_accessor :model_class end + # NOTE: If request unit tests are breaking, make sure to update the list of permitted models in PrimeroModelService def model_class - @model_class ||= Record.model_from_name(request.path.split('/')[3].singularize) + @model_class ||= PrimeroModelService.to_model(request.path.split('/')[3].singularize) end def record_id + return unless params[:id].is_a?(String) + params[:id] end + def metadata_record_ids + return [] unless params[:id].present? + return [params[:id]] if params[:id].is_a?(String) + + params[:id].values + end + def authorize_all!(permission, records) records.each do |record| authorize!(permission, record) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1b3c824901..a026fdaba8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -4,5 +4,8 @@ # Superclass for all non-API controllers class ApplicationController < ActionController::Base - protect_from_forgery with: :exception, prepend: true, unless: -> { request.format.json? } + include CsrfProtection + + before_action :set_csrf_cookie + protect_from_forgery with: :exception, if: -> { use_csrf_protection? } end diff --git a/app/controllers/concerns/audit_log_actions.rb b/app/controllers/concerns/audit_log_actions.rb index 09f58053df..7df8d1f1f7 100644 --- a/app/controllers/concerns/audit_log_actions.rb +++ b/app/controllers/concerns/audit_log_actions.rb @@ -22,7 +22,8 @@ def default_metadata_audit_params remote_ip: LogUtils.remote_ip(request), agency_id: current_user.try(:agency_id), role_id: current_user.try(:role_id), - http_method: request.method + http_method: request.method, + record_ids: metadata_record_ids } end diff --git a/app/controllers/concerns/csrf_protection.rb b/app/controllers/concerns/csrf_protection.rb new file mode 100644 index 0000000000..fa5be2894b --- /dev/null +++ b/app/controllers/concerns/csrf_protection.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Enables csrf protection. +module CsrfProtection + extend ActiveSupport::Concern + + included do + include ActionController::RequestForgeryProtection + include ActionController::Cookies + end + + private + + def set_csrf_cookie + cookies['CSRF-TOKEN'] = { + path: '/', + secure: Rails.env.production?, + value: form_authenticity_token, + same_site: :strict + } + end + + def use_csrf_protection? + Rails.configuration.use_csrf_protection && !request_from_basic_auth? + end + + def request_from_basic_auth? + warden&.winning_strategy.try(:authentication_type) == :http_auth + end +end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 20155d8fbe..b5919d65f7 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -4,8 +4,6 @@ # Default Rails route class HomeController < ApplicationController - skip_before_action :authenticate_user!, only: %w[v2], raise: false - def v2 @theme = Rails.configuration.use_theme ? Theme.current : Theme.default end diff --git a/app/controllers/themes_controller.rb b/app/controllers/themes_controller.rb index 24fe965a53..3ca5436eee 100644 --- a/app/controllers/themes_controller.rb +++ b/app/controllers/themes_controller.rb @@ -2,9 +2,11 @@ # API to fetch the active theme class ThemesController < ApplicationController - before_action :theme + # NOTE: Primero front-end dynamically loads /themes.js using es6 dynamic imports. Rails is throwing + # ActionController::InvalidCrossOriginRequest error if we do not skip verify_same_origin_request + skip_after_action :verify_same_origin_request, unless: -> { request_not_from_app_host? } - skip_before_action :verify_authenticity_token + before_action :theme def index; end @@ -13,4 +15,8 @@ def manifest; end def theme @theme = Rails.configuration.use_theme ? Theme.current : Theme.default end + + def request_not_from_app_host? + request.host != Rails.application.routes.default_url_options[:host] + end end diff --git a/app/javascript/__mocks__/fileMock.js b/app/javascript/__mocks__/fileMock.js new file mode 100644 index 0000000000..0a445d0600 --- /dev/null +++ b/app/javascript/__mocks__/fileMock.js @@ -0,0 +1 @@ +module.exports = "test-file-stub"; diff --git a/app/javascript/app.jsx b/app/javascript/app.jsx index 8d98eb4c1a..14064c63d0 100644 --- a/app/javascript/app.jsx +++ b/app/javascript/app.jsx @@ -2,39 +2,55 @@ import { ConnectedRouter } from "connected-react-router/immutable"; import { Provider } from "react-redux"; -import { MuiPickersUtilsProvider } from "@material-ui/pickers"; -import DateFnsUtils from "@date-io/date-fns"; +import isEmpty from "lodash/isEmpty"; +import { useLayoutEffect } from "react"; +import Translations from "./db/collections/translations"; import I18nProvider from "./components/i18n"; import { ApplicationProvider } from "./components/application"; -import { routes } from "./config"; +import routes from "./routes"; import { history } from "./store"; import ApplicationRoutes from "./components/application-routes"; import ThemeProvider from "./theme-provider"; import "mui-nepali-datepicker-reactjs/dist/index.css"; import appInit from "./app-init"; +import DateProvider from "./date-provider"; const { store } = appInit(); -const App = () => { +function App() { window.I18n.fallbacks = true; + useLayoutEffect(() => { + const loadTranslations = async () => { + if (isEmpty(window.I18n.translations)) { + const translations = await Translations.find(); + + window.I18n.translations = translations; + } else { + Translations.save(window.I18n.translations); + } + }; + + loadTranslations(); + }, []); + return ( - + - + ); -}; +} App.displayName = "App"; diff --git a/app/javascript/components/action-button/component.jsx b/app/javascript/components/action-button/component.jsx index c2f3aa5dba..1d4a2bbfb5 100644 --- a/app/javascript/components/action-button/component.jsx +++ b/app/javascript/components/action-button/component.jsx @@ -3,7 +3,7 @@ import PropTypes from "prop-types"; import isString from "lodash/isString"; -import { useApp } from "../application"; +import { useApp } from "../application/use-app"; import { useI18n } from "../i18n"; import { buttonType } from "./utils"; @@ -16,12 +16,12 @@ function Component({ isTransparent, pending, text, - type, - outlined, + type = ACTION_BUTTON_TYPES.default, + outlined = false, keepTextOnMobile, tooltip, noTranslate = false, - rest, + rest = {}, disabled, ...options }) { @@ -41,6 +41,7 @@ function Component({ return ( { +}) { const renderIcon = icon || null; const isPending = Boolean(pending); const renderLoadingIndicator = isPending && ; const renderContent = !renderIcon ? <>{text} : ; - const spanClasses = clsx({ [css.isDisabled]: rest.disabled || isPending }); - const classes = clsx({ + const spanClasses = cx({ [css.isDisabled]: rest.disabled || isPending }); + const classes = cx({ [css.defaultActionButton]: renderIcon, [css.isTransparent]: isTransparent, [rest.className]: Boolean(rest.className) @@ -62,7 +62,7 @@ const Component = ({ ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/action-button/components/default-button/styles.css b/app/javascript/components/action-button/components/default-button/styles.css index 6e99cd1de2..25c589fbcd 100644 --- a/app/javascript/components/action-button/components/default-button/styles.css +++ b/app/javascript/components/action-button/components/default-button/styles.css @@ -15,18 +15,16 @@ margin-left: -55px; } -@media (max-width:959.95px) { +@media (max-width:900px) { .defaultActionButton { min-width: 3em; padding: 0 15px; & span { - - & span { - margin: 0; - } + margin: 0; } } + .buttonProgress { margin-left: -32px; } diff --git a/app/javascript/components/action-button/components/icon-button/component.jsx b/app/javascript/components/action-button/components/icon-button/component.jsx index d94a1fc843..e5e5a5cb32 100644 --- a/app/javascript/components/action-button/components/icon-button/component.jsx +++ b/app/javascript/components/action-button/components/icon-button/component.jsx @@ -3,12 +3,12 @@ import { Fragment } from "react"; import PropTypes from "prop-types"; import clsx from "clsx"; -import { IconButton, Tooltip } from "@material-ui/core"; +import { IconButton, Tooltip } from "@mui/material"; import css from "./styles.css"; import { NAME } from "./constants"; -const Component = ({ icon, id, rest, ...otherProps }) => { +function Component({ icon, id, rest, ...otherProps }) { const { tooltip } = otherProps; const Parent = tooltip ? Tooltip : Fragment; const spanClasses = clsx({ [css.isDisabled]: rest.disabled }); @@ -22,7 +22,7 @@ const Component = ({ icon, id, rest, ...otherProps }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/action-button/components/icon-button/component.spec.js b/app/javascript/components/action-button/components/icon-button/component.spec.js index e1329df6ae..5858d13ecc 100644 --- a/app/javascript/components/action-button/components/icon-button/component.spec.js +++ b/app/javascript/components/action-button/components/icon-button/component.spec.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { mountedComponent, screen } from "test-utils"; +import { mountedComponent, screen, fireEvent, waitFor } from "test-utils"; import IconButton from "./component"; @@ -21,7 +21,7 @@ describe(" components/action-button/components", () => { expect(screen.getByRole("button")).toHaveClass("MuiSvgIcon-root"); }); - it("renders a component if tooltip is defined", () => { + it("renders a component if tooltip is defined", async () => { const newProps = { ...props, tooltip: "Tooltip Message", @@ -29,6 +29,7 @@ describe(" components/action-button/components", () => { }; mountedComponent(); - expect(screen.getByTitle("Tooltip Message")).toBeInTheDocument(); + fireEvent.mouseOver(screen.getByRole("button")); + await waitFor(() => expect(screen.getByText("Tooltip Message")).toBeInTheDocument()); }); }); diff --git a/app/javascript/components/action-button/components/link/component.jsx b/app/javascript/components/action-button/components/link/component.jsx index c3ac31135f..e5ebaab40c 100644 --- a/app/javascript/components/action-button/components/link/component.jsx +++ b/app/javascript/components/action-button/components/link/component.jsx @@ -1,11 +1,11 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Link } from "@material-ui/core"; +import { Link } from "@mui/material"; import { NAME } from "./constants"; -const Component = ({ text, id, ...options }) => { +function Component({ text, id, ...options }) { const { rest, ...remainder } = options; if (rest.disabled) { @@ -17,7 +17,7 @@ const Component = ({ text, id, ...options }) => { {text} ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/action-dialog/component.jsx b/app/javascript/components/action-dialog/component.jsx index a9e759a97b..9a4904e65f 100644 --- a/app/javascript/components/action-dialog/component.jsx +++ b/app/javascript/components/action-dialog/component.jsx @@ -2,9 +2,9 @@ import { useEffect } from "react"; import PropTypes from "prop-types"; -import { Dialog, DialogActions, DialogContent, DialogContentText, Typography } from "@material-ui/core"; -import CheckIcon from "@material-ui/icons/Check"; -import CloseIcon from "@material-ui/icons/Close"; +import { Dialog, DialogActions, DialogContent, DialogContentText, Typography } from "@mui/material"; +import CheckIcon from "@mui/icons-material/Check"; +import CloseIcon from "@mui/icons-material/Close"; import { useDispatch } from "react-redux"; import useMemoizedSelector from "../../libs/use-memoized-selector"; @@ -17,8 +17,8 @@ import css from "./styles.css"; import { clearDialog } from "./action-creators"; import { getAsyncLoading } from "./selectors"; -const ActionDialog = ({ - cancelButtonProps, +function ActionDialog({ + cancelButtonProps = {}, cancelHandler, children, confirmButtonLabel, @@ -27,23 +27,22 @@ const ActionDialog = ({ dialogSubHeader, dialogSubtitle, dialogText, - dialogTitle, + dialogTitle = "", disableActions, - disableBackdropClick, - disableClose, - enabledSuccessButton, - hideIcon, + disableClose = false, + enabledSuccessButton = true, + hideIcon = false, maxSize, omitCloseAfterSuccess, onClose, open, pending, - showSuccessButton, + showSuccessButton = true, successHandler, fetchAction, - fetchArgs, + fetchArgs = [], fetchLoadingPath -}) => { +}) { const dispatch = useDispatch(); const { disabledApplication } = useApp(); @@ -56,15 +55,16 @@ const ActionDialog = ({ const isPending = asyncLoading || pending; - const handleClose = event => { + const handleClose = (event, reason) => { event.stopPropagation(); - - if (cancelHandler) { - cancelHandler(); - } else if (onClose) { - onClose(); - } else { - dispatch(clearDialog()); + if (reason !== "backdropClick") { + if (cancelHandler) { + cancelHandler(); + } else if (onClose) { + onClose(); + } else { + dispatch(clearDialog()); + } } }; @@ -132,7 +132,7 @@ const ActionDialog = ({ }, [open, fetchAction]); return ( - // eslint-disable-next-line jsx-a11y/no-static-element-interactions,jsx-a11y/click-events-have-key-events + // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
{dialogHeader} {subHeader} @@ -167,21 +166,10 @@ const ActionDialog = ({
); -}; +} ActionDialog.displayName = "ActionDialog"; -ActionDialog.defaultProps = { - cancelButtonProps: {}, - dialogTitle: "", - disableBackdropClick: false, - disableClose: false, - enabledSuccessButton: true, - fetchArgs: [], - hideIcon: false, - showSuccessButton: true -}; - ActionDialog.propTypes = { cancelButtonProps: PropTypes.object, cancelHandler: PropTypes.func, @@ -194,7 +182,6 @@ ActionDialog.propTypes = { dialogText: PropTypes.string, dialogTitle: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), disableActions: PropTypes.bool, - disableBackdropClick: PropTypes.bool, disableClose: PropTypes.bool, enabledSuccessButton: PropTypes.bool, fetchAction: PropTypes.func, diff --git a/app/javascript/components/action-dialog/component.spec.js b/app/javascript/components/action-dialog/component.spec.js index 9a55b1bcbe..a3d838ca8d 100644 --- a/app/javascript/components/action-dialog/component.spec.js +++ b/app/javascript/components/action-dialog/component.spec.js @@ -16,7 +16,6 @@ describe("", () => { dialogText: "", dialogTitle: "Test Title", disableActions: false, - disableBackdropClick: false, maxSize: "sm", omitCloseAfterSuccess: false, onClose: () => {}, diff --git a/app/javascript/components/action-dialog/components/text-with-close/component.jsx b/app/javascript/components/action-dialog/components/text-with-close/component.jsx index 382719f1c7..d297884836 100644 --- a/app/javascript/components/action-dialog/components/text-with-close/component.jsx +++ b/app/javascript/components/action-dialog/components/text-with-close/component.jsx @@ -1,13 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import CloseIcon from "@material-ui/icons/Close"; -import { DialogTitle, IconButton } from "@material-ui/core"; +import CloseIcon from "@mui/icons-material/Close"; +import { DialogTitle, IconButton } from "@mui/material"; import { NAME } from "./constants"; import css from "./styles.css"; -const Component = ({ dialogTitle, dialogSubtitle, closeHandler, dialogActions, disableClose }) => { +function Component({ dialogTitle, dialogSubtitle, closeHandler, dialogActions, disableClose = false }) { const subtitle = dialogSubtitle ? {dialogSubtitle} : null; return ( @@ -28,11 +28,7 @@ const Component = ({ dialogTitle, dialogSubtitle, closeHandler, dialogActions, d ); -}; - -Component.defaultProps = { - disableClose: false -}; +} Component.propTypes = { closeHandler: PropTypes.func.isRequired, diff --git a/app/javascript/components/activity-log/actions.js b/app/javascript/components/activity-log/actions.js index 0cd9b08b5d..a3d6d62a76 100644 --- a/app/javascript/components/activity-log/actions.js +++ b/app/javascript/components/activity-log/actions.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { namespaceActions } from "../../libs"; +import { namespaceActions } from "../../libs/reducer-helpers"; import NAMESPACE from "./namespace"; diff --git a/app/javascript/components/activity-log/component.jsx b/app/javascript/components/activity-log/component.jsx index 0f47dea50f..6619e66071 100644 --- a/app/javascript/components/activity-log/component.jsx +++ b/app/javascript/components/activity-log/component.jsx @@ -15,7 +15,7 @@ import { getColumns, getRecordPath } from "./utils"; import { fetchActivityLog, setActivityLogsFilter } from "./action-creators"; import css from "./styles.css"; -const Component = () => { +function Component() { const i18n = useI18n(); const dispatch = useDispatch(); const recordType = RESOURCES.activity_logs; @@ -67,7 +67,7 @@ const Component = () => { ); -}; +} Component.displayName = "ActivityLog"; diff --git a/app/javascript/components/activity-log/component.spec.js b/app/javascript/components/activity-log/component.spec.js index 6313e1ccee..752f87045f 100644 --- a/app/javascript/components/activity-log/component.spec.js +++ b/app/javascript/components/activity-log/component.spec.js @@ -4,7 +4,7 @@ import { mountedComponent, userEvent, screen } from "test-utils"; import { ACCEPTED, REJECTED } from "../../config"; import { ACTIONS } from "../permissions"; -import { lookups, stub } from "../../test"; +import { lookups, stub } from "../../test-utils"; import ActivityLog from "./component"; diff --git a/app/javascript/components/activity-log/components/activity-item/component.jsx b/app/javascript/components/activity-log/components/activity-item/component.jsx index 39ed2353f8..b086b34ed5 100644 --- a/app/javascript/components/activity-log/components/activity-item/component.jsx +++ b/app/javascript/components/activity-log/components/activity-item/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; import { DATE_TIME_FORMAT } from "../../../../config"; import { useI18n } from "../../../i18n"; @@ -9,9 +9,9 @@ import getActivityMessage from "../../utils/get-activity-message"; import css from "./styles.css"; -const Component = ({ activityData }) => { +function Component({ activityData }) { const i18n = useI18n(); - const classes = clsx(css.activityContainer, { + const classes = cx(css.activityContainer, { [css.disabledItem]: activityData.recordAccessDenied }); @@ -36,7 +36,7 @@ const Component = ({ activityData }) => {
{i18n.t(`${type}.label`)}
); -}; +} Component.displayName = "ActivityItem"; diff --git a/app/javascript/components/agency-logo/component.jsx b/app/javascript/components/agency-logo/component.jsx index 0b1db37fc6..0b247fa020 100644 --- a/app/javascript/components/agency-logo/component.jsx +++ b/app/javascript/components/agency-logo/component.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { memo } from "react"; -import clsx from "clsx"; +import { Fragment, memo } from "react"; +import { cx } from "@emotion/css"; import { getAgencyLogos } from "../application/selectors"; import useMemoizedSelector from "../../libs/use-memoized-selector"; @@ -17,25 +17,22 @@ function AgencyLogo({ alwaysFullLogo = false }) { const uniqueId = agency.get("unique_id"); const styleIcon = { backgroundImage: `url(${agency.get("logo_icon")})` }; const styleFull = { backgroundImage: `url(${agency.get("logo_full")})` }; - const classesIcon = clsx([css.agencyLogo, css.agencyLogoIcon]); - const classesFull = clsx(css.agencyLogo, { [css.agencyLogoFull]: !alwaysFullLogo }); - const fullLogo =
; + const classesIcon = cx([css.agencyLogo, css.agencyLogoIcon]); + const classesFull = cx(css.agencyLogo, { [css.agencyLogoFull]: !alwaysFullLogo }); + + const fullLogo = ( +
+ ); if (alwaysFullLogo) { return fullLogo; } return ( - <> -
+ +
{fullLogo} - + ); }); }; diff --git a/app/javascript/components/agency-logo/styles.css b/app/javascript/components/agency-logo/styles.css index d118a7f79a..dcdfba9cbb 100644 --- a/app/javascript/components/agency-logo/styles.css +++ b/app/javascript/components/agency-logo/styles.css @@ -21,7 +21,7 @@ align-items: center; text-align: center; padding: 11%; - + & div { display: flex; justify-content: center; @@ -39,13 +39,13 @@ background-color: blue; } -@media (max-width:599.95px) { +@media (max-width:600px) { .agencyLogo, .line { display: none; } } -@media (max-width:1279.95px) { +@media (max-width:1200px) { .line { width: 100%; } @@ -60,13 +60,13 @@ } } -@media (min-width:1279px) { +@media (min-width:1200px) { .agencyLogoIcon { display: none !important; } } -@media (max-width:1279px) { +@media (max-width:1200px) { .agencyLogoFull { display: none !important; } diff --git a/app/javascript/components/application-routes/app-route.jsx b/app/javascript/components/application-routes/app-route.jsx index af1d409bf7..9ca5877417 100644 --- a/app/javascript/components/application-routes/app-route.jsx +++ b/app/javascript/components/application-routes/app-route.jsx @@ -6,7 +6,7 @@ import Layouts from "../layouts"; import SubRoutes from "./sub-routes"; -const AppRoute = ({ route }) => { +function AppRoute({ route }) { const { layout, component: Component, extraProps, ...routeProps } = route; if (layout) { @@ -18,7 +18,7 @@ const AppRoute = ({ route }) => { } return ; -}; +} AppRoute.displayName = "AppRoute"; diff --git a/app/javascript/components/application-routes/component.jsx b/app/javascript/components/application-routes/component.jsx index 60855a1bdf..ace1808b95 100644 --- a/app/javascript/components/application-routes/component.jsx +++ b/app/javascript/components/application-routes/component.jsx @@ -5,25 +5,24 @@ import { Route, Switch } from "react-router-dom"; import AppRoute from "./app-route"; -const ApplicationRoutes = ({ routes }) => { +function ApplicationRoutes({ routes }) { const appRoutes = routes.map((route, index) => { const { routes: subRoutes, exact, path } = route; const routeProps = { - key: path || index, path: subRoutes ? subRoutes.map(r => r.path) : path, exact: subRoutes ? routes.some(r => r.exact) : exact }; return ( - + ); }); return {appRoutes}; -}; +} ApplicationRoutes.displayName = "ApplicationRoutes"; diff --git a/app/javascript/components/application-routes/sub-route.jsx b/app/javascript/components/application-routes/sub-route.jsx index 2964d55a13..6bd3745145 100644 --- a/app/javascript/components/application-routes/sub-route.jsx +++ b/app/javascript/components/application-routes/sub-route.jsx @@ -11,7 +11,7 @@ import Permission from "../permissions"; import { getCodeOfConductEnabled, getCodesOfConduct } from "../application/selectors"; import { getCodeOfConductId } from "../user"; -const SubRoute = ({ subRoute }) => { +function SubRoute({ subRoute }) { const { path, resources, actions, component: Component, extraProps } = subRoute; const codeOfConductAccepted = useMemoizedSelector(state => getCodeOfConductId(state)); @@ -38,7 +38,7 @@ const SubRoute = ({ subRoute }) => { ); -}; +} SubRoute.displayName = "SubRoute"; diff --git a/app/javascript/components/application/actions.js b/app/javascript/components/application/actions.js index aba12e06f0..3568b3ecf1 100644 --- a/app/javascript/components/application/actions.js +++ b/app/javascript/components/application/actions.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { namespaceActions } from "../../libs"; +import { namespaceActions } from "../../libs/reducer-helpers"; import NAMESPACE from "./namespace"; diff --git a/app/javascript/components/application/reducer.js b/app/javascript/components/application/reducer.js index 25daf8ba63..96d12a28eb 100644 --- a/app/javascript/components/application/reducer.js +++ b/app/javascript/components/application/reducer.js @@ -2,7 +2,7 @@ import { fromJS } from "immutable"; -import { mapEntriesToRecord } from "../../libs"; +import { mapEntriesToRecord } from "../../libs/reducer-helpers"; import actions from "./actions"; import NAMESPACE from "./namespace"; diff --git a/app/javascript/components/application/selectors.js b/app/javascript/components/application/selectors.js index 108e2c1f6c..e702c9da7b 100644 --- a/app/javascript/components/application/selectors.js +++ b/app/javascript/components/application/selectors.js @@ -6,7 +6,7 @@ import createCachedSelector from "re-reselect"; import { createSelectorCreator, defaultMemoize } from "reselect"; import { memoize } from "proxy-memoize"; -import { displayNameHelper } from "../../libs"; +import displayNameHelper from "../../libs/display-name-helper"; import { getLocale } from "../i18n/selectors"; import { DATA_PROTECTION_FIELDS } from "../record-creation-flow/constants"; import { currentUser } from "../user/selectors"; @@ -170,6 +170,9 @@ export const getMaximumUsers = state => state.getIn([NAMESPACE, "systemOptions", export const getMaximumUsersWarning = state => state.getIn([NAMESPACE, "systemOptions", "maximum_users_warning"]); +export const getMaximumAttachmentsPerRecord = state => + state.getIn([NAMESPACE, "systemOptions", "maximum_attachments_per_record"]); + export const getTheme = state => state.getIn([NAMESPACE, "theme"], fromJS({})); export const getShowPoweredByPrimero = state => state.getIn([NAMESPACE, "theme", "showPoweredByPrimero"], false); @@ -193,6 +196,7 @@ export const getAppData = memoize(state => { const useContainedNavStyle = getUseContainedNavStyle(state); const showPoweredByPrimero = getShowPoweredByPrimero(state); const hasLoginLogo = getLoginBackground(state); + const maximumttachmentsPerRecord = getMaximumAttachmentsPerRecord(state); return { modules, @@ -206,7 +210,8 @@ export const getAppData = memoize(state => { maximumUsersWarning, useContainedNavStyle, showPoweredByPrimero, - hasLoginLogo + hasLoginLogo, + maximumttachmentsPerRecord }; }); diff --git a/app/javascript/components/application/selectors.unit.test.js b/app/javascript/components/application/selectors.unit.test.js index 34d4aa7aaa..c877c1cafe 100644 --- a/app/javascript/components/application/selectors.unit.test.js +++ b/app/javascript/components/application/selectors.unit.test.js @@ -129,7 +129,8 @@ const stateWithRecords = fromJS({ disabledApplication: true, systemOptions: { maximum_users: 50, - maximum_users_warning: 45 + maximum_users_warning: 45, + maximum_attachments_per_record: 55 } } }); @@ -611,4 +612,12 @@ describe("Application - Selectors", () => { expect(result).to.be.true; }); }); + + describe("getMaximumAttachmentsPerRecord", () => { + it("should return maximum users warning", () => { + const result = selectors.getMaximumAttachmentsPerRecord(stateWithRecords); + + expect(result).to.be.equal(55); + }); + }); }); diff --git a/app/javascript/components/application/use-app.jsx b/app/javascript/components/application/use-app.jsx index a82a97b3fc..e6f0eb6534 100644 --- a/app/javascript/components/application/use-app.jsx +++ b/app/javascript/components/application/use-app.jsx @@ -11,13 +11,13 @@ import { getAppData } from "./selectors"; const Context = createContext(); -const ApplicationProvider = ({ children }) => { +function ApplicationProvider({ children }) { const { online, fieldMode } = useConnectivityStatus(); const appData = useMemoizedSelector(state => getAppData(state), isEqual); return {children}; -}; +} ApplicationProvider.displayName = "ApplicationProvider"; diff --git a/app/javascript/components/approvals/components/detail/component.jsx b/app/javascript/components/approvals/components/detail/component.jsx index 4c6935e0df..f638ca9bae 100644 --- a/app/javascript/components/approvals/components/detail/component.jsx +++ b/app/javascript/components/approvals/components/detail/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Grid } from "@material-ui/core"; +import { Grid } from "@mui/material"; import { CASE_PLAN, NAME_DETAIL } from "../../constants"; import DisplayData from "../../../display-data"; @@ -9,7 +9,7 @@ import { useApp } from "../../../application"; import { approvalLabel } from "./utils"; -const Component = ({ approvalSubform, isRequest, isResponse }) => { +function Component({ approvalSubform, isRequest, isResponse }) { const { approvalsLabels } = useApp(); const renderApprovalLabel = @@ -38,7 +38,7 @@ const Component = ({ approvalSubform, isRequest, isResponse }) => { return ( <> - + @@ -53,7 +53,7 @@ const Component = ({ approvalSubform, isRequest, isResponse }) => { ); -}; +} Component.displayName = NAME_DETAIL; diff --git a/app/javascript/components/approvals/components/detail/component.spec.js b/app/javascript/components/approvals/components/detail/component.spec.js index a06d820f96..eb1a7fbd8e 100644 --- a/app/javascript/components/approvals/components/detail/component.spec.js +++ b/app/javascript/components/approvals/components/detail/component.spec.js @@ -40,7 +40,7 @@ describe(" - Component", () => { }); it("render a DisplayData", () => { - expect(screen.getAllByTestId("container")).toHaveLength(1); + expect(screen.getAllByTestId("display-data")).toHaveLength(4); }); it("render the correct approvals label", () => { diff --git a/app/javascript/components/approvals/components/panel/component.jsx b/app/javascript/components/approvals/components/panel/component.jsx index ba6c32e57c..336730cc67 100644 --- a/app/javascript/components/approvals/components/panel/component.jsx +++ b/app/javascript/components/approvals/components/panel/component.jsx @@ -2,14 +2,14 @@ import { useState } from "react"; import PropTypes from "prop-types"; -import { Accordion, AccordionDetails, AccordionSummary } from "@material-ui/core"; -import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; +import { Accordion, AccordionDetails, AccordionSummary } from "@mui/material"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import ApprovalSummary from "../summary"; import ApprovalDetail from "../detail"; import { NAME_PANEL } from "../../constants"; -const Component = ({ approvalSubform, css }) => { +function Component({ approvalSubform, css }) { const [expanded, setExpanded] = useState(false); const handleExpanded = () => { @@ -27,7 +27,7 @@ const Component = ({ approvalSubform, css }) => { }; return ( -
+
} @@ -45,7 +45,7 @@ const Component = ({ approvalSubform, css }) => {
); -}; +} Component.displayName = NAME_PANEL; diff --git a/app/javascript/components/approvals/components/panel/component.spec.js b/app/javascript/components/approvals/components/panel/component.spec.js index 65ddbf3f45..baaede10db 100644 --- a/app/javascript/components/approvals/components/panel/component.spec.js +++ b/app/javascript/components/approvals/components/panel/component.spec.js @@ -34,6 +34,6 @@ describe(" - Component", () => { }); it("render a ApprovalSummary", () => { - expect(screen.getAllByTestId("sectionheader")).toHaveLength(1); + expect(screen.getAllByTestId("approval-summary")).toHaveLength(1); }); }); diff --git a/app/javascript/components/approvals/components/summary/component.jsx b/app/javascript/components/approvals/components/summary/component.jsx index d93093d8f1..f5b44aa630 100644 --- a/app/javascript/components/approvals/components/summary/component.jsx +++ b/app/javascript/components/approvals/components/summary/component.jsx @@ -1,15 +1,15 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Grid } from "@material-ui/core"; -import Chip from "@material-ui/core/Chip"; -import clsx from "clsx"; +import { Grid } from "@mui/material"; +import Chip from "@mui/material/Chip"; +import { cx } from "@emotion/css"; import { useI18n } from "../../../i18n"; import { NAME_SUMMARY } from "../../constants"; import { useApp } from "../../../application"; -const Component = ({ approvalSubform, css, isRequest, isResponse }) => { +function Component({ approvalSubform, css, isRequest, isResponse }) { const i18n = useI18n(); const { approvalsLabels } = useApp(); const status = approvalSubform.get("approval_status"); @@ -22,7 +22,7 @@ const Component = ({ approvalSubform, css, isRequest, isResponse }) => { ? approvalsLabels.get(approvalSubform.get("approval_requested_for")) : approvalsLabels.get(approvalSubform.get("approval_response_for")); - const classes = clsx(css.chip, css[status]); + const classes = cx(css.chip, css[status]); const renderStatus = isResponse ? ( @@ -43,7 +43,7 @@ const Component = ({ approvalSubform, css, isRequest, isResponse }) => { }; return ( - +
{/* TODO: The date should be localized */} @@ -56,7 +56,7 @@ const Component = ({ approvalSubform, css, isRequest, isResponse }) => { {renderStatus} ); -}; +} Component.displayName = NAME_SUMMARY; diff --git a/app/javascript/components/approvals/components/summary/component.spec.js b/app/javascript/components/approvals/components/summary/component.spec.js index 928b846273..7a78b2388e 100644 --- a/app/javascript/components/approvals/components/summary/component.spec.js +++ b/app/javascript/components/approvals/components/summary/component.spec.js @@ -36,7 +36,7 @@ describe(" - Component", () => { }); it("render ApprovalSummary component", () => { - expect(screen.getAllByTestId("sectionheader")).toHaveLength(1); + expect(screen.getAllByTestId("approval-summary")).toHaveLength(1); }); it("render a Chip with the correct approvals label", () => { diff --git a/app/javascript/components/approvals/container.jsx b/app/javascript/components/approvals/container.jsx index 7798c3017e..8b3f94167d 100644 --- a/app/javascript/components/approvals/container.jsx +++ b/app/javascript/components/approvals/container.jsx @@ -9,7 +9,7 @@ import css from "./styles.css"; import { NAME } from "./constants"; import ApprovalPanel from "./components/panel"; -const Container = ({ approvals, mobileDisplay, handleToggleNav }) => { +function Container({ approvals, mobileDisplay, handleToggleNav }) { const i18n = useI18n(); const renderApprovals = @@ -23,7 +23,7 @@ const Container = ({ approvals, mobileDisplay, handleToggleNav }) => { )); return ( -
+
{
); -}; +} Container.displayName = NAME; diff --git a/app/javascript/components/approvals/container.unit.test.js b/app/javascript/components/approvals/container.spec.js similarity index 53% rename from app/javascript/components/approvals/container.unit.test.js rename to app/javascript/components/approvals/container.spec.js index 30d4a90344..4a872e1f6c 100644 --- a/app/javascript/components/approvals/container.unit.test.js +++ b/app/javascript/components/approvals/container.spec.js @@ -1,17 +1,11 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { AccordionDetails, AccordionSummary } from "@material-ui/core"; - -import RecordFormTitle from "../record-form/form/record-form-title"; -import { setupMountedComponent } from "../../test"; +import { mountedComponent, screen } from "test-utils"; import Approvals from "./container"; -import ApprovalPanel from "./components/panel"; describe(" - Component", () => { - let component; - const props = { approvals: fromJS([ { @@ -59,49 +53,35 @@ describe(" - Component", () => { mobileDisplay: false }; - beforeEach(() => { - ({ component } = setupMountedComponent(Approvals, props, {})); - }); + it("should render text", () => { + mountedComponent(); - it("renders Approvals component", () => { - expect(component.find(Approvals)).to.have.length(1); + expect(screen.getByTestId("approvals")).toBeInTheDocument(); }); it("renders 4 ApprovalsPanel", () => { - expect(component.find(ApprovalPanel)).to.have.lengthOf(4); - expect(component.find(AccordionDetails)).to.have.lengthOf(4); - expect(component.find(AccordionSummary)).to.have.lengthOf(4); - }); - - it("renders component with valid props", () => { - const approvalsProps = { ...component.find(Approvals).props() }; + mountedComponent(); - ["approvals", "handleToggleNav", "mobileDisplay"].forEach(property => { - expect(approvalsProps).to.have.property(property); - delete approvalsProps[property]; - }); - expect(approvalsProps).to.be.empty; + expect(screen.getAllByTestId("approval-panel")).toHaveLength(4); + expect(screen.getAllByTestId("approval-detail")).toHaveLength(4); + expect(screen.getAllByTestId("approval-summary")).toHaveLength(4); }); - describe("When we don't have data", () => { - let noDataComponent; + describe("when we don't have data", () => { + const emptyProps = { mobileDisplay: true, handleToggleNav: () => {} }; - const emptyProps = { - mobileDisplay: true, - handleToggleNav: () => {} - }; + it("renders Approvals component", () => { + mountedComponent(); - beforeEach(() => { - ({ component: noDataComponent } = setupMountedComponent(Approvals, emptyProps, {})); + expect(screen.getByTestId("approvals")).toBeInTheDocument(); }); - it("renders Approvals component", () => { - expect(noDataComponent.find(Approvals)).to.have.length(1); - }); - it("not renders ApprovalPanel only the title", () => { - expect(noDataComponent.find(ApprovalPanel)).to.have.lengthOf(0); - expect(noDataComponent.find(RecordFormTitle)).to.have.lengthOf(1); - expect(noDataComponent.find(RecordFormTitle).text()).to.equal("forms.record_types.approvals"); + it("does not render ApprovalPanel only the title", () => { + mountedComponent(); + + expect(screen.queryAllByTestId("approval-panel")).toHaveLength(0); + expect(screen.getByTestId("record-form-title")).toBeInTheDocument(); + expect(screen.getByText("forms.record_types.approvals")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/approvals/styles.css b/app/javascript/components/approvals/styles.css index e7033fa445..7de52db77b 100644 --- a/app/javascript/components/approvals/styles.css +++ b/app/javascript/components/approvals/styles.css @@ -90,7 +90,7 @@ height: 36px; } -@media (max-width:959.95px) { +@media (max-width:900px) { .titleHeader { font-size: var(--fs-12); } diff --git a/app/javascript/components/button-text/component.jsx b/app/javascript/components/button-text/component.jsx index 85f2094ed7..d8faf97117 100644 --- a/app/javascript/components/button-text/component.jsx +++ b/app/javascript/components/button-text/component.jsx @@ -1,11 +1,11 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { useMediaQuery } from "@material-ui/core"; +import { useMediaQuery } from "@mui/material"; import { NAME } from "./constants"; -const Component = ({ text, keepTextOnMobile }) => { +function Component({ text, keepTextOnMobile = false }) { const mobileDisplay = useMediaQuery(theme => theme.breakpoints.down("sm")); if (mobileDisplay && !keepTextOnMobile) { @@ -13,14 +13,10 @@ const Component = ({ text, keepTextOnMobile }) => { } return <>{text}; -}; +} Component.displayName = NAME; -Component.defaultProps = { - keepTextOnMobile: false -}; - Component.propTypes = { keepTextOnMobile: PropTypes.bool, text: PropTypes.string.isRequired diff --git a/app/javascript/components/case-linked-record/component.jsx b/app/javascript/components/case-linked-record/component.jsx index d4fb14f527..caa8f4fdad 100644 --- a/app/javascript/components/case-linked-record/component.jsx +++ b/app/javascript/components/case-linked-record/component.jsx @@ -3,11 +3,11 @@ import { useCallback, useEffect, useState } from "react"; import PropTypes from "prop-types"; import { useDispatch } from "react-redux"; -import AddIcon from "@material-ui/icons/Add"; +import AddIcon from "@mui/icons-material/Add"; import SubformDrawer from "../record-form/form/subforms/subform-drawer"; import { useI18n } from "../i18n"; -import { useMemoizedSelector } from "../../libs"; +import useMemoizedSelector from "../../libs/use-memoized-selector"; import { getRecordFieldsByName, getRecordFormsByUniqueId } from "../record-form/selectors"; import { CASE, RECORD_TYPES_PLURAL } from "../../config"; import ActionButton, { ACTION_BUTTON_TYPES } from "../action-button"; diff --git a/app/javascript/components/case-linked-record/components/record-header.jsx b/app/javascript/components/case-linked-record/components/record-header.jsx index 0572cf63e2..6fe2c1d7c5 100644 --- a/app/javascript/components/case-linked-record/components/record-header.jsx +++ b/app/javascript/components/case-linked-record/components/record-header.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { List, ListItem, ListItemSecondaryAction, ListItemText } from "@material-ui/core"; -import { KeyboardArrowLeft, KeyboardArrowRight } from "@material-ui/icons"; +import { List, ListItem, ListItemSecondaryAction, ListItemText } from "@mui/material"; +import { KeyboardArrowLeft, KeyboardArrowRight } from "@mui/icons-material"; import LoadingIndicator from "../../loading-indicator/component"; import { ConditionalWrapper, useMemoizedSelector, useThemeHelper } from "../../../libs"; diff --git a/app/javascript/components/case-linked-record/components/result-details.jsx b/app/javascript/components/case-linked-record/components/result-details.jsx index 50d9b8c81f..c85870931c 100644 --- a/app/javascript/components/case-linked-record/components/result-details.jsx +++ b/app/javascript/components/case-linked-record/components/result-details.jsx @@ -3,9 +3,9 @@ import { useDispatch } from "react-redux"; import PropTypes from "prop-types"; import { useEffect, useMemo } from "react"; -import ArrowBackIosIcon from "@material-ui/icons/ArrowBackIos"; -import CheckIcon from "@material-ui/icons/Check"; -import BlockIcon from "@material-ui/icons/Block"; +import ArrowBackIosIcon from "@mui/icons-material/ArrowBackIos"; +import CheckIcon from "@mui/icons-material/Check"; +import BlockIcon from "@mui/icons-material/Block"; import { getRecordFormsByUniqueId } from "../../record-form/selectors"; import DisabledRecordIndicator from "../../record-form/form/components/disabled-record-indicator"; diff --git a/app/javascript/components/case-linked-record/components/results.jsx b/app/javascript/components/case-linked-record/components/results.jsx index 9b044ea022..7e689ef246 100644 --- a/app/javascript/components/case-linked-record/components/results.jsx +++ b/app/javascript/components/case-linked-record/components/results.jsx @@ -3,7 +3,7 @@ import { useCallback, useEffect, useState } from "react"; import PropTypes from "prop-types"; import { useDispatch } from "react-redux"; -import ArrowBackIosIcon from "@material-ui/icons/ArrowBackIos"; +import ArrowBackIosIcon from "@mui/icons-material/ArrowBackIos"; import { useMemoizedSelector } from "../../../libs"; import ActionButton, { ACTION_BUTTON_TYPES } from "../../action-button"; diff --git a/app/javascript/components/case-linked-record/components/search-form.jsx b/app/javascript/components/case-linked-record/components/search-form.jsx index 4bc5154a98..787a461b7e 100644 --- a/app/javascript/components/case-linked-record/components/search-form.jsx +++ b/app/javascript/components/case-linked-record/components/search-form.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import ArrowBackIosIcon from "@material-ui/icons/ArrowBackIos"; -import SearchIcon from "@material-ui/icons/Search"; +import ArrowBackIosIcon from "@mui/icons-material/ArrowBackIos"; +import SearchIcon from "@mui/icons-material/Search"; import { useMemoizedSelector } from "../../../libs"; import ActionButton, { ACTION_BUTTON_TYPES } from "../../action-button"; diff --git a/app/javascript/components/change-logs/components/change-log-item/component.jsx b/app/javascript/components/change-logs/components/change-log-item/component.jsx index 8349d5fd50..b0069707db 100644 --- a/app/javascript/components/change-logs/components/change-log-item/component.jsx +++ b/app/javascript/components/change-logs/components/change-log-item/component.jsx @@ -3,12 +3,12 @@ /* eslint-disable react/no-multi-comp */ /* eslint-disable react/display-name */ import PropTypes from "prop-types"; -import TimelineItem from "@material-ui/lab/TimelineItem"; -import TimelineSeparator from "@material-ui/lab/TimelineSeparator"; -import TimelineConnector from "@material-ui/lab/TimelineConnector"; -import TimelineContent from "@material-ui/lab/TimelineContent"; -import TimelineDot from "@material-ui/lab/TimelineDot"; -import { ButtonBase } from "@material-ui/core"; +import TimelineItem from "@mui/lab/TimelineItem"; +import TimelineSeparator from "@mui/lab/TimelineSeparator"; +import TimelineConnector from "@mui/lab/TimelineConnector"; +import TimelineContent from "@mui/lab/TimelineContent"; +import TimelineDot from "@mui/lab/TimelineDot"; +import { ButtonBase } from "@mui/material"; import generateKey from "../../../charts/table-values/utils"; import { useI18n } from "../../../i18n"; @@ -17,7 +17,7 @@ import css from "../../styles.css"; import { NAME } from "./constants"; -const Component = ({ item }) => { +function Component({ item }) { const i18n = useI18n(); const { onClick } = item; const renderMessage = change => ( @@ -62,7 +62,7 @@ const Component = ({ item }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/change-logs/components/change-log/component.jsx b/app/javascript/components/change-logs/components/change-log/component.jsx index 956b646f0c..d39ff40407 100644 --- a/app/javascript/components/change-logs/components/change-log/component.jsx +++ b/app/javascript/components/change-logs/components/change-log/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import Timeline from "@material-ui/lab/Timeline"; +import Timeline from "@mui/lab/Timeline"; import { useI18n } from "../../../i18n"; import ChangeLogItem from "../change-log-item"; @@ -10,7 +10,7 @@ import css from "../../styles.css"; import { NAME } from "./constants"; -const Component = ({ +function Component({ recordChangeLogs, setOpen, setRecordChanges, @@ -19,7 +19,7 @@ const Component = ({ allLookups, locations, allAgencies -}) => { +}) { const i18n = useI18n(); const handleSeeDetails = subformChanges => { @@ -39,7 +39,7 @@ const Component = ({ ).map(item => ); return {renderItems}; -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/change-logs/components/subform-dialog/component.jsx b/app/javascript/components/change-logs/components/subform-dialog/component.jsx index 6fd09a43ca..0f40cee55f 100644 --- a/app/javascript/components/change-logs/components/subform-dialog/component.jsx +++ b/app/javascript/components/change-logs/components/subform-dialog/component.jsx @@ -2,7 +2,7 @@ import PropTypes from "prop-types"; import isEmpty from "lodash/isEmpty"; -import Timeline from "@material-ui/lab/Timeline"; +import Timeline from "@mui/lab/Timeline"; import ActionDialog from "../../../action-dialog"; import LoadingIndicator from "../../../loading-indicator"; @@ -13,7 +13,7 @@ import css from "../../styles.css"; import { NAME } from "./constants"; -const Component = ({ +function Component({ recordChanges, open, setOpen, @@ -23,7 +23,7 @@ const Component = ({ locations, setCalculatingChangeLog, allAgencies -}) => { +}) { const i18n = useI18n(); const subformTitle = i18n.t("change_logs.changes_subform", { @@ -60,7 +60,7 @@ const Component = ({ ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/change-logs/container.jsx b/app/javascript/components/change-logs/container.jsx index b1c55fc2dd..8a8236ac4d 100644 --- a/app/javascript/components/change-logs/container.jsx +++ b/app/javascript/components/change-logs/container.jsx @@ -21,7 +21,7 @@ import { NAME } from "./constants"; import { getChangeLogs } from "./selectors"; import css from "./styles.css"; -const Container = ({ +function Container({ selectedForm, recordID, recordType, @@ -29,7 +29,7 @@ const Container = ({ mobileDisplay, handleToggleNav, fetchable = false -}) => { +}) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -67,7 +67,7 @@ const Container = ({ }; return ( -
+
); -}; +} Container.displayName = NAME; diff --git a/app/javascript/components/change-logs/container.spec.js b/app/javascript/components/change-logs/container.spec.js index 34daf43b8b..09a165acb7 100644 --- a/app/javascript/components/change-logs/container.spec.js +++ b/app/javascript/components/change-logs/container.spec.js @@ -149,7 +149,7 @@ describe("ChangeLogs - Container", () => { }); it("renders ChangeLogs", () => { - expect(screen.getAllByTestId("ChangeLogs")).toHaveLength(1); + expect(screen.getAllByTestId("change-logs")).toHaveLength(1); }); it("renders ChangeLog", () => { diff --git a/app/javascript/components/change-logs/styles.css b/app/javascript/components/change-logs/styles.css index 3bf7254f05..5ed659979a 100644 --- a/app/javascript/components/change-logs/styles.css +++ b/app/javascript/components/change-logs/styles.css @@ -39,3 +39,9 @@ .detailName { font-style: italic; } + +@media (min-width:600px) { + .container { + min-width: 28em; + } +} diff --git a/app/javascript/components/change-logs/utils.unit.test.js b/app/javascript/components/change-logs/utils.unit.test.js index 9748a75d6d..5e3c9281ee 100644 --- a/app/javascript/components/change-logs/utils.unit.test.js +++ b/app/javascript/components/change-logs/utils.unit.test.js @@ -3,7 +3,7 @@ import { fromJS, OrderedMap } from "immutable"; import { FieldRecord } from "../record-form/records"; -import { stub } from "../../test"; +import { stub } from "../../test-utils"; import { ChangeLogsRecord } from "./records"; import { buildDataItems, buildSubformDataItems } from "./utils"; diff --git a/app/javascript/components/charts/bar-chart/component.jsx b/app/javascript/components/charts/bar-chart/component.jsx index 41c0be72fa..84a34c2a8c 100644 --- a/app/javascript/components/charts/bar-chart/component.jsx +++ b/app/javascript/components/charts/bar-chart/component.jsx @@ -7,7 +7,7 @@ import arrayReverse from "lodash/reverse"; import css from "./styles.css"; -const BarChart = ({ data, description, showDetails = false, hideLegend = false, reverse = false }) => { +function BarChart({ data, description, showDetails = false, hideLegend = false, reverse = false }) { const chartRef = createRef(); useEffect(() => { @@ -84,11 +84,15 @@ const BarChart = ({ data, description, showDetails = false, hideLegend = false, return (
- {!showDetails ?

{description}

: null} - + {!showDetails ? ( +

+ {description} +

+ ) : null} +
); -}; +} BarChart.displayName = "BarChart"; diff --git a/app/javascript/components/charts/bar-chart/component.unit.test.js b/app/javascript/components/charts/bar-chart/component.spec.js similarity index 74% rename from app/javascript/components/charts/bar-chart/component.unit.test.js rename to app/javascript/components/charts/bar-chart/component.spec.js index 7b7c4f2298..cd0da927be 100644 --- a/app/javascript/components/charts/bar-chart/component.unit.test.js +++ b/app/javascript/components/charts/bar-chart/component.spec.js @@ -1,9 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { Map } from "immutable"; +import { mountedComponent, screen } from "test-utils"; import { buildGraphData } from "../../report/utils"; -import { setupMountedThemeComponent } from "../../../test"; import BarChart from "./component"; @@ -28,13 +28,14 @@ describe("", () => { }); const showDetails = false; const description = "Number of cases broken down by nationality"; - const component = setupMountedThemeComponent(BarChart, { + const props = { ...buildGraphData(data, { t: () => "Total" }, { agencies }), description, showDetails - }); + }; - expect(component.find("p").props().children).to.equal("Number of cases broken down by nationality"); - expect(component.find("canvas")).to.have.lengthOf(1); + mountedComponent(); + expect(screen.getByText("Number of cases broken down by nationality")).toBeInTheDocument(); + expect(screen.getByTestId("canvas")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/charts/table-values/component.jsx b/app/javascript/components/charts/table-values/component.jsx index b19ab9274e..4024fff465 100644 --- a/app/javascript/components/charts/table-values/component.jsx +++ b/app/javascript/components/charts/table-values/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Paper, Table, TableBody, TableHead } from "@material-ui/core"; +import { Paper, Table, TableBody, TableHead } from "@mui/material"; import isEmpty from "lodash/isEmpty"; import EmptyState from "../../loading-indicator/components/empty-state"; @@ -10,7 +10,7 @@ import InsightsTableHeader from "../../insights-sub-report/components/insights-t import { TableHeader, TableRows } from "./components"; import css from "./styles.css"; -const TableValues = ({ +function TableValues({ columns, values, showPlaceholder = false, @@ -18,7 +18,7 @@ const TableValues = ({ emptyMessage = "", useInsightsHeader = false, subColumnItemsSize -}) => { +}) { const Header = useInsightsHeader ? InsightsTableHeader : TableHeader; return ( @@ -37,7 +37,7 @@ const TableValues = ({ )} ); -}; +} TableValues.displayName = "TableValues"; diff --git a/app/javascript/components/charts/table-values/component.unit.test.js b/app/javascript/components/charts/table-values/component.spec.js similarity index 84% rename from app/javascript/components/charts/table-values/component.unit.test.js rename to app/javascript/components/charts/table-values/component.spec.js index e47c20a9b8..e1d3c1318c 100644 --- a/app/javascript/components/charts/table-values/component.unit.test.js +++ b/app/javascript/components/charts/table-values/component.spec.js @@ -1,10 +1,10 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { TableRow } from "@material-ui/core"; +import { mountedComponent, screen } from "test-utils"; import { buildTableData } from "../../report/utils"; -import { abbrMonthNames, setupMountedComponent, stub } from "../../../test"; +import { abbrMonthNames, stub } from "../../../test-utils"; import TableValues from "./component"; @@ -74,13 +74,14 @@ describe("", () => { } ]; - const { component } = setupMountedComponent(TableValues, { + const props = { ...buildTableData(data, window.I18n, { agencies }) - }); + }; - expect(component.find(TableRow)).to.have.lengthOf(6); + mountedComponent(, props); + expect(screen.getAllByRole("table")).toHaveLength(1); + expect(screen.getAllByRole("columnheader")).toHaveLength(2); }); - afterEach(() => { if (stubI18n) { window.I18n.t.restore(); diff --git a/app/javascript/components/charts/table-values/components/table-header/component.jsx b/app/javascript/components/charts/table-values/components/table-header/component.jsx index c40a83ce30..17b44802d0 100644 --- a/app/javascript/components/charts/table-values/components/table-header/component.jsx +++ b/app/javascript/components/charts/table-values/components/table-header/component.jsx @@ -1,9 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { TableCell, TableRow } from "@material-ui/core"; +import { TableCell, TableRow } from "@mui/material"; import isEmpty from "lodash/isEmpty"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; import { useI18n } from "../../../../i18n"; import generateKey from "../../utils"; @@ -12,7 +12,7 @@ import css from "./styles.css"; import { emptyColumn } from "./utils"; import { NAME } from "./constants"; -const TableHeader = ({ columns }) => { +function TableHeader({ columns }) { const i18n = useI18n(); let newColumns = columns; @@ -49,7 +49,7 @@ const TableHeader = ({ columns }) => { const cells = isFirstHeading ? items : Array.from({ length: repeat }, () => items).flat(); const allCells = isFirstHeading || addEmptyCell === false ? emptyCells.concat(cells) : emptyCells.concat(cells).concat(""); - const classes = clsx({ [css.tableRowHeader]: index === 0, [css.tableRowSubHeader]: index > 0 }); + const classes = cx({ [css.tableRowHeader]: index === 0, [css.tableRowSubHeader]: index > 0 }); return ( @@ -76,7 +76,7 @@ const TableHeader = ({ columns }) => { })} ); -}; +} TableHeader.displayName = NAME; diff --git a/app/javascript/components/charts/table-values/components/table-header/component.spec.js b/app/javascript/components/charts/table-values/components/table-header/component.spec.js new file mode 100644 index 0000000000..24ce2bbdb8 --- /dev/null +++ b/app/javascript/components/charts/table-values/components/table-header/component.spec.js @@ -0,0 +1,24 @@ +import { mountedComponent, screen } from "test-utils"; + +import TableHeader from "./component"; + +describe("/components/", () => { + it("should render the correct number of headers", () => { + const props = { + columns: [ + { + items: ["Category 1", "report.total"], + colspan: 2 + }, + { + items: ["6 - 11", "report.total"], + colspan: 0 + } + ] + }; + + mountedComponent(, props); + expect(screen.getAllByRole("row")).toHaveLength(1); + expect(screen.getAllByRole("cell")).toHaveLength(2); + }); +}); diff --git a/app/javascript/components/charts/table-values/components/table-header/component.unit.test.js b/app/javascript/components/charts/table-values/components/table-header/component.unit.test.js deleted file mode 100644 index d830f91b26..0000000000 --- a/app/javascript/components/charts/table-values/components/table-header/component.unit.test.js +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { TableCell, TableRow } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../../../test"; - -import TableHeader from "./component"; - -describe("/components/", () => { - it("should render the correct number of headers", () => { - const { component } = setupMountedComponent(TableHeader, { - columns: [ - { - items: ["Category 1", "report.total"], - colspan: 2 - }, - { - items: ["6 - 11", "report.total"], - colspan: 0 - } - ] - }); - - const headerCells = component.find(TableRow).at(0).find(TableCell); - const subHeaderCells = component.find(TableRow).at(1).find(TableCell); - - expect(headerCells.at(1).props().colSpan).to.equal(2); - expect(headerCells).to.have.lengthOf(3); - - expect(subHeaderCells).to.have.lengthOf(4); - }); -}); diff --git a/app/javascript/components/charts/table-values/components/table-rows/component.jsx b/app/javascript/components/charts/table-values/components/table-rows/component.jsx index 2782df5457..067f488577 100644 --- a/app/javascript/components/charts/table-values/components/table-rows/component.jsx +++ b/app/javascript/components/charts/table-values/components/table-rows/component.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import clsx from "clsx"; -import { TableCell, TableRow } from "@material-ui/core"; +import { cx } from "@emotion/css"; +import { TableCell, TableRow } from "@mui/material"; import { useI18n } from "../../../../i18n"; import generateKey from "../../utils"; @@ -10,20 +10,20 @@ import generateKey from "../../utils"; import css from "./styles.css"; import { NAME } from "./constants"; -const Component = ({ values, subColumnItemsSize }) => { +function Component({ values = [], subColumnItemsSize }) { const i18n = useI18n(); const totalText = i18n.t("managed_reports.total"); return values.map(value => { const { colspan, row } = value; - const classes = clsx({ [css.tableRow]: colspan !== 0, [css.tableRowValues]: true }); + const classes = cx({ [css.tableRow]: colspan !== 0, [css.tableRowValues]: true }); return ( {row.map((rowData, index) => { const cellClass = subColumnItemsSize && - clsx({ + cx({ [css.tableCell]: (index % subColumnItemsSize === 0 && index !== 0) || row[0] === totalText, [css.tableCellSize]: Boolean(subColumnItemsSize) && index > 0 }); @@ -37,14 +37,10 @@ const Component = ({ values, subColumnItemsSize }) => { ); }); -}; +} Component.displayName = NAME; -Component.defaultProps = { - values: [] -}; - Component.propTypes = { subColumnItemsSize: PropTypes.number, values: PropTypes.array diff --git a/app/javascript/components/charts/table-values/utils.unit.test.js b/app/javascript/components/charts/table-values/utils.unit.test.js index 7c645f4233..6273afbee9 100644 --- a/app/javascript/components/charts/table-values/utils.unit.test.js +++ b/app/javascript/components/charts/table-values/utils.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub } from "../../../test"; +import { stub } from "../../../test-utils"; import generateKey from "./utils"; diff --git a/app/javascript/components/code-of-conduct/component.jsx b/app/javascript/components/code-of-conduct/component.jsx index 228b87f49b..9feb6cc885 100644 --- a/app/javascript/components/code-of-conduct/component.jsx +++ b/app/javascript/components/code-of-conduct/component.jsx @@ -5,9 +5,9 @@ import { useDispatch } from "react-redux"; import { useLocation } from "react-router-dom"; import { format, parseISO } from "date-fns"; import { isEmpty } from "lodash"; -import { Typography } from "@material-ui/core"; +import { Typography } from "@mui/material"; -import { ROUTES } from "../../config"; +import { ROUTES, CODE_OF_CONDUCT_DATE_FORMAT } from "../../config"; import TranslationsToggle from "../translations-toggle"; import ModuleLogo from "../module-logo"; import { useI18n } from "../i18n"; @@ -15,7 +15,6 @@ import useMemoizedSelector from "../../libs/use-memoized-selector"; import { getCodeOfConductId, getUser } from "../user"; import LoadingIndicator from "../loading-indicator"; import { getCodesOfConduct } from "../application/selectors"; -import { CODE_OF_CONDUCT_DATE_FORMAT } from "../../config/constants"; import { NAME, ID } from "./constants"; import css from "./styles.css"; @@ -23,7 +22,7 @@ import { acceptCodeOfConduct } from "./action-creators"; import { selectUpdatingCodeOfConduct } from "./selectors"; import { Actions, CancelDialog } from "./components"; -const Component = () => { +function Component() { const i18n = useI18n(); const dispatch = useDispatch(); const location = useLocation(); @@ -83,7 +82,7 @@ const Component = () => {
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/code-of-conduct/components/actions/component.jsx b/app/javascript/components/code-of-conduct/components/actions/component.jsx index c9a7be476b..b1fbba97ac 100644 --- a/app/javascript/components/code-of-conduct/components/actions/component.jsx +++ b/app/javascript/components/code-of-conduct/components/actions/component.jsx @@ -1,15 +1,15 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import ClearIcon from "@material-ui/icons/Clear"; -import CheckIcon from "@material-ui/icons/Check"; +import ClearIcon from "@mui/icons-material/Clear"; +import CheckIcon from "@mui/icons-material/Check"; import ActionButton from "../../../action-button"; import { ACTION_BUTTON_TYPES } from "../../../action-button/constants"; import { NAME } from "./constants"; -const Component = ({ css, handleAccept, handleCancel, updatingCodeOfConduct, codeOfConductAccepted }) => { +function Component({ css, handleAccept, handleCancel, updatingCodeOfConduct, codeOfConductAccepted }) { return (
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/code-of-conduct/components/cancel-dialog/component.jsx b/app/javascript/components/code-of-conduct/components/cancel-dialog/component.jsx index 5f59d18b69..e406f5a9b0 100644 --- a/app/javascript/components/code-of-conduct/components/cancel-dialog/component.jsx +++ b/app/javascript/components/code-of-conduct/components/cancel-dialog/component.jsx @@ -2,14 +2,14 @@ import PropTypes from "prop-types"; import { push } from "connected-react-router"; -import ExitToAppIcon from "@material-ui/icons/ExitToApp"; +import ExitToAppIcon from "@mui/icons-material/ExitToApp"; import ActionDialog from "../../../action-dialog"; import { ROUTES } from "../../../../config"; import { NAME } from "./constants"; -const Component = ({ dispatch, open, setOpen, i18n }) => { +function Component({ dispatch, open, setOpen, i18n }) { const onClose = () => setOpen(false); const handleLogout = () => { dispatch(push(ROUTES.logout)); @@ -29,7 +29,7 @@ const Component = ({ dispatch, open, setOpen, i18n }) => { }} /> ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/conditional-tooltip/component.jsx b/app/javascript/components/conditional-tooltip/component.jsx index b643348380..d1ac9b74eb 100644 --- a/app/javascript/components/conditional-tooltip/component.jsx +++ b/app/javascript/components/conditional-tooltip/component.jsx @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Tooltip } from "@material-ui/core"; +import { Tooltip } from "@mui/material"; import PropTypes from "prop-types"; function Component({ children, condition, title }) { diff --git a/app/javascript/components/connectivity/action-creators.js b/app/javascript/components/connectivity/action-creators.js index bd1ffaaa0e..b836d257ce 100644 --- a/app/javascript/components/connectivity/action-creators.js +++ b/app/javascript/components/connectivity/action-creators.js @@ -2,7 +2,9 @@ /* eslint-disable import/prefer-default-export */ import { ROUTES } from "../../config"; -import { SNACKBAR_VARIANTS, closeSnackbar, ENQUEUE_SNACKBAR } from "../notifier"; +import { ENQUEUE_SNACKBAR } from "../notifier/actions"; +import { SNACKBAR_VARIANTS } from "../notifier/constants"; +import { closeSnackbar } from "../notifier/action-creators"; import actions from "./actions"; import { CONNECTION_LOST, CONNECTED, FIELD_MODE_OFFLINE } from "./constants"; @@ -65,13 +67,20 @@ export const setPendingUserLogin = payload => ({ payload }); -export const getServerStatus = () => ({ +export const getServerStatus = ({ showSnackbars = true, successCallback = [] }) => ({ type: actions.SERVER_STATUS, api: { path: ROUTES.check_server_health, external: true, - successCallback: [{ action: actions.SERVER_STATUS, payload: true }, onlineSnackbar(true, { forMiddleware: true })], - failureCallback: [{ action: actions.SERVER_STATUS, payload: false }, onlineSnackbar(false, { forMiddleware: true })] + successCallback: [ + { action: actions.SERVER_STATUS, payload: true }, + showSnackbars && onlineSnackbar(true, { forMiddleware: true }), + ...successCallback + ], + failureCallback: [ + { action: actions.SERVER_STATUS, payload: false }, + showSnackbars && onlineSnackbar(false, { forMiddleware: true }) + ] } }); @@ -79,23 +88,25 @@ export function setFieldMode(dispatch) { dispatch(setNetworkStatus(false)); } -export const checkServerStatus = isOnline => (dispatch, getState) => { - const userToggledOffline = getState().getIn(["connectivity", "fieldMode"]); +export const checkServerStatus = + (isOnline, showSnackbars, successCallback = []) => + (dispatch, getState) => { + const userToggledOffline = getState().getIn(["connectivity", "fieldMode"]); - dispatch(closeSnackbar(isOnline ? CONNECTION_LOST : CONNECTED)); + dispatch(closeSnackbar(isOnline ? CONNECTION_LOST : CONNECTED)); - if (userToggledOffline) { - setFieldMode(dispatch); - } else { - dispatch(closeSnackbar(FIELD_MODE_OFFLINE)); - dispatch(setNetworkStatus(isOnline)); - if (isOnline) { - dispatch(getServerStatus(isOnline)); + if (userToggledOffline) { + setFieldMode(dispatch); } else { - dispatch({ type: ENQUEUE_SNACKBAR, ...onlineSnackbar(isOnline, { forMiddleware: true }) }); + dispatch(closeSnackbar(FIELD_MODE_OFFLINE)); + dispatch(setNetworkStatus(isOnline)); + if (isOnline) { + dispatch(getServerStatus({ showSnackbars, successCallback })); + } else { + dispatch({ type: ENQUEUE_SNACKBAR, ...onlineSnackbar(isOnline, { forMiddleware: true }) }); + } } - } -}; + }; export const setQueueData = payload => ({ type: actions.SET_QUEUE_DATA, diff --git a/app/javascript/components/connectivity/use-connectivity-status.js b/app/javascript/components/connectivity/use-connectivity-status.js index fc5f1999e0..b3ce194a1a 100644 --- a/app/javascript/components/connectivity/use-connectivity-status.js +++ b/app/javascript/components/connectivity/use-connectivity-status.js @@ -3,12 +3,13 @@ import { useEffect } from "react"; import { useDispatch } from "react-redux"; -import Queue, { QUEUE_HALTED, QUEUE_READY } from "../../libs/queue"; +import { QUEUE_HALTED, QUEUE_READY } from "../../libs/queue/constants"; +import Queue from "../../libs/queue"; import { getIsAuthenticated } from "../user/selectors"; import { clearDialog } from "../action-dialog/action-creators"; import { selectDialog } from "../action-dialog/selectors"; -import { useRefreshUserToken } from "../user"; -import { LOGIN_DIALOG } from "../login-dialog"; +import useRefreshUserToken from "../user/use-refresh-token"; +import { LOGIN_DIALOG } from "../login-dialog/constants"; import useMemoizedSelector from "../../libs/use-memoized-selector"; import DB, { DB_STORES } from "../../db"; diff --git a/app/javascript/components/contact-information/container.jsx b/app/javascript/components/contact-information/container.jsx index 4d2380adc1..44ddf428f5 100644 --- a/app/javascript/components/contact-information/container.jsx +++ b/app/javascript/components/contact-information/container.jsx @@ -8,7 +8,7 @@ import { BLACK_LISTED_FIELDS } from "./constants"; import { selectSupportData } from "./selectors"; import css from "./styles.css"; -const Support = () => { +function Support() { const supportData = useMemoizedSelector(state => selectSupportData(state)); const i18n = useI18n(); @@ -38,7 +38,7 @@ const Support = () => { {renderInformation} ); -}; +} Support.displayName = "Support"; diff --git a/app/javascript/components/custom-snackbar-provider/component.jsx b/app/javascript/components/custom-snackbar-provider/component.jsx index c40f392f39..c2df1474b6 100644 --- a/app/javascript/components/custom-snackbar-provider/component.jsx +++ b/app/javascript/components/custom-snackbar-provider/component.jsx @@ -2,25 +2,20 @@ import PropTypes from "prop-types"; import { SnackbarProvider } from "notistack"; -import { Brightness1 as Circle } from "@material-ui/icons"; -import ErrorIcon from "@material-ui/icons/Error"; -import CheckIcon from "@material-ui/icons/Check"; -import SignalWifiOffIcon from "@material-ui/icons/SignalWifiOff"; -import { makeStyles } from "@material-ui/core/styles"; - -import useThemeHelpers from "../../libs/use-theme-helpers"; +import { Brightness1 as Circle } from "@mui/icons-material"; +import ErrorIcon from "@mui/icons-material/Error"; +import CheckIcon from "@mui/icons-material/Check"; +import SignalWifiOffIcon from "@mui/icons-material/SignalWifiOff"; import { NAME } from "./constants"; -import { snackVariantClasses } from "./theme"; - -const Component = ({ children }) => { - const { theme } = useThemeHelpers(); - const classes = makeStyles(snackVariantClasses(theme))(); +import css from "./styles.css"; +function Component({ children }) { return ( , error: , @@ -28,17 +23,19 @@ const Component = ({ children }) => { info: }} classes={{ - lessPadding: classes.lessPadding, - variantSuccess: classes.success, - variantError: classes.error, - variantWarning: classes.warning, - variantInfo: classes.info + root: css.root, + lessPadding: css.lessPadding, + variantSuccess: css.success, + variantError: css.error, + variantWarning: css.warning, + variantInfo: css.info, + message: css.message }} > {children} ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/custom-snackbar-provider/component.spec.js b/app/javascript/components/custom-snackbar-provider/component.spec.js new file mode 100644 index 0000000000..c624a065b1 --- /dev/null +++ b/app/javascript/components/custom-snackbar-provider/component.spec.js @@ -0,0 +1,14 @@ +import { mountedComponent, screen } from "test-utils"; + +import CustomSnackbarProvider from "./component"; + +describe(" - Component", () => { + it("renders children", () => { + const props = { + children:
snackbar child
+ }; + + mountedComponent(); + expect(screen.getByText("snackbar child")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/custom-snackbar-provider/component.unit.test.js b/app/javascript/components/custom-snackbar-provider/component.unit.test.js deleted file mode 100644 index 058f70504d..0000000000 --- a/app/javascript/components/custom-snackbar-provider/component.unit.test.js +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { SnackbarProvider } from "notistack"; - -import { setupMountedComponent } from "../../test"; - -import CustomSnackbarProvider from "./component"; - -describe(" - Component", () => { - let component; - - before(() => { - ({ component } = setupMountedComponent(CustomSnackbarProvider, { - children:
- })); - }); - - it("renders ", () => { - expect(component.find(CustomSnackbarProvider)).to.have.lengthOf(1); - }); - - it("renders ", () => { - expect(component.find(CustomSnackbarProvider).find(SnackbarProvider)).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/custom-snackbar-provider/styles.css b/app/javascript/components/custom-snackbar-provider/styles.css new file mode 100644 index 0000000000..bd78a09d5f --- /dev/null +++ b/app/javascript/components/custom-snackbar-provider/styles.css @@ -0,0 +1,71 @@ +.lessPadding { + padding: 0 10px; +} + +.root { + composes: lessPadding; + color: var(--c-grey) !important; + font-weight: bold !important; + font-size: var(--fs-13) !important; + flex-wrap: nowrap !important; + + & svg { + color: var(--c-green); + margin-right: var(--sp-2); + } + + & :global .SnackbarItem-action { + display: flex; + + button { + width: 40px; + height: 40px; + } + + & svg { + font-size: var(--fs-16); + color: var(--c-dark-grey); + margin-right: 0; + } + } +} + +.success { + composes: root; + background: var(--c-white) !important; + border: 1px solid var(--c-green); + + & svg { + color: var(--c-green); + } +} + +.error { + composes: root; + background: var(--c-white) !important; + border: 1px solid var(--c-red); + + & svg { + color: var(--c-red); + } +} + +.warning { + composes: root; + border: 1px solid var(--c-orange); + background: var(--c-white) !important; + + & svg { + color: var(--c-orange); + } +} + +.info { + composes: root; + border: 1px solid var(--c-yellow); + background: var(--c-white) !important; + + & svg { + color: var(--c-yellow); + } +} \ No newline at end of file diff --git a/app/javascript/components/custom-snackbar-provider/theme.js b/app/javascript/components/custom-snackbar-provider/theme.js deleted file mode 100644 index d3cbb3151c..0000000000 --- a/app/javascript/components/custom-snackbar-provider/theme.js +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -/* eslint-disable import/prefer-default-export */ -export const snackVariantClasses = theme => ({ - lessPadding: { - padding: "0 10px" - }, - success: { - border: `1px solid ${theme.primero.colors.green}`, - "& svg": { - color: theme.primero.colors.green - } - }, - error: { - border: `1px solid ${theme.primero.colors.red}`, - "& svg": { - color: theme.primero.colors.red - } - }, - warning: { - border: `1px solid ${theme.primero.colors.orange}`, - "& svg": { - color: theme.primero.colors.orange - } - }, - info: { - border: `1px solid ${theme.primero.colors.yellow}`, - "& svg": { - color: theme.primero.colors.yellow - } - } -}); diff --git a/app/javascript/components/custom-snackbar-provider/theme.unit.test.js b/app/javascript/components/custom-snackbar-provider/theme.unit.test.js deleted file mode 100644 index 022335bc75..0000000000 --- a/app/javascript/components/custom-snackbar-provider/theme.unit.test.js +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import * as theme from "./theme"; - -describe(" - theme", () => { - const themeValues = { ...theme }; - - it("should known the values", () => { - expect(theme).to.be.an("object"); - ["snackVariantClasses"].forEach(property => { - expect(themeValues).to.have.property(property); - delete themeValues[property]; - }); - expect(themeValues).to.be.empty; - }); - - it("snackVariantClasses should known the classes for the snackbar", () => { - const currentTheme = { primero: { colors: {} } }; - const classes = { ...theme.snackVariantClasses(currentTheme) }; - - expect(classes).to.be.an("object"); - - ["lessPadding", "success", "error", "warning", "info"].forEach(property => { - expect(classes).to.have.property(property); - delete classes[property]; - }); - expect(classes).to.be.empty; - }); -}); diff --git a/app/javascript/components/dashboard/action-menu/component.jsx b/app/javascript/components/dashboard/action-menu/component.jsx index a4a0288655..8099be2e2d 100644 --- a/app/javascript/components/dashboard/action-menu/component.jsx +++ b/app/javascript/components/dashboard/action-menu/component.jsx @@ -2,17 +2,18 @@ import { useRef } from "react"; import PropTypes from "prop-types"; -import { IconButton, Menu, MenuItem } from "@material-ui/core"; -import MoreVertIcon from "@material-ui/icons/MoreVert"; +import { IconButton, Menu, MenuItem } from "@mui/material"; +import MoreVertIcon from "@mui/icons-material/MoreVert"; import css from "./styles.css"; -const ActionMenu = ({ open, onOpen, onClose, items }) => { +function ActionMenu({ open, onOpen, onClose, items }) { const moreButtonRef = useRef(null); return ( <> { ); -}; +} ActionMenu.displayName = "ActionMenu"; diff --git a/app/javascript/components/dashboard/badged-indicator/component.jsx b/app/javascript/components/dashboard/badged-indicator/component.jsx index 09d3ddff6e..f03e73cd4e 100644 --- a/app/javascript/components/dashboard/badged-indicator/component.jsx +++ b/app/javascript/components/dashboard/badged-indicator/component.jsx @@ -13,7 +13,7 @@ import NAMESPACE from "../../pages/dashboard/namespace"; import css from "./styles.css"; -const BadgedIndicator = ({ data, lookup, sectionTitle, indicator, loading, errors }) => { +function BadgedIndicator({ data, lookup, sectionTitle, indicator, loading, errors }) { const dispatch = useDispatch(); const loadingIndicatorProps = { @@ -24,15 +24,21 @@ const BadgedIndicator = ({ data, lookup, sectionTitle, indicator, loading, error errors }; - const handleClick = queryValue => () => { - if (!isEmpty(queryValue)) { - dispatch( - push({ - pathname: ROUTES.cases, - search: buildFilter(queryValue) - }) - ); + const handleClick = queryValue => { + if (isEmpty(queryValue)) { + return null; } + + return () => { + if (!isEmpty(queryValue)) { + dispatch( + push({ + pathname: ROUTES.cases, + search: buildFilter(queryValue) + }) + ); + } + }; }; const dashboardChips = lookup.map(lk => { @@ -49,13 +55,13 @@ const BadgedIndicator = ({ data, lookup, sectionTitle, indicator, loading, error return ( <> - +
{sectionTitle}
{dashboardChips}
); -}; +} BadgedIndicator.displayName = "BadgedIndicator"; diff --git a/app/javascript/components/dashboard/badged-indicator/component.unit.test.js b/app/javascript/components/dashboard/badged-indicator/component.spec.js similarity index 68% rename from app/javascript/components/dashboard/badged-indicator/component.unit.test.js rename to app/javascript/components/dashboard/badged-indicator/component.spec.js index 4144df791a..110528b444 100644 --- a/app/javascript/components/dashboard/badged-indicator/component.unit.test.js +++ b/app/javascript/components/dashboard/badged-indicator/component.spec.js @@ -1,17 +1,14 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { CircularProgress } from "@material-ui/core"; -import { setupMountedComponent } from "../../../test"; -import DashboardChip from "../dashboard-chip"; import { DASHBOARD_NAMES } from "../../pages/dashboard"; import { INDICATOR_NAMES } from "../../pages/dashboard/constants"; +import { mountedComponent, screen } from "../../../test-utils"; import BadgedIndicator from "./component"; describe("", () => { - let component; const props = { data: fromJS({ name: DASHBOARD_NAMES.CASE_RISK, @@ -55,31 +52,26 @@ describe("", () => { }; beforeEach(() => { - ({ component } = setupMountedComponent(BadgedIndicator, props, {})); + mountedComponent(, props, {}); }); it("renders a BadgedIndicator with a DashboardChip />", () => { - expect(component.find(BadgedIndicator)).to.have.lengthOf(1); - expect(component.find(DashboardChip)).to.have.lengthOf(4); + expect(screen.getAllByTestId("chip-button")).toHaveLength(4); }); describe("When data still loading", () => { - let loadingComponent; const propsDataLoading = { ...props, data: fromJS({}), loading: true }; - before(() => { - ({ component: loadingComponent } = setupMountedComponent(BadgedIndicator, propsDataLoading, {})); + beforeEach(() => { + mountedComponent(); }); - it("renders BadgedIndicator component", () => { - expect(loadingComponent.find(BadgedIndicator)).to.have.lengthOf(1); - }); it("renders CircularProgress", () => { - expect(loadingComponent.find(CircularProgress)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/dashboard/dashboard-chip/component.jsx b/app/javascript/components/dashboard/dashboard-chip/component.jsx index 6aaec79499..08ba63364f 100644 --- a/app/javascript/components/dashboard/dashboard-chip/component.jsx +++ b/app/javascript/components/dashboard/dashboard-chip/component.jsx @@ -1,21 +1,28 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Button } from "@material-ui/core"; -import clsx from "clsx"; +import { Button } from "@mui/material"; +import { cx } from "@emotion/css"; import PropTypes from "prop-types"; import css from "./styles.css"; -const DashboardChip = ({ label, type, handleClick }) => { +function DashboardChip({ label, type, handleClick }) { const handler = typeof handleClick === "function" ? handleClick : null; - const classes = clsx(css.chip, css[type]); + const classes = cx({ [css.chip]: true, [css[type]]: true, [css.disabled]: handler === null }); return ( - ); -}; +} DashboardChip.displayName = "DashboardChip"; diff --git a/app/javascript/components/dashboard/dashboard-chip/styles.css b/app/javascript/components/dashboard/dashboard-chip/styles.css index ce2c5fa42d..2e7d64732c 100644 --- a/app/javascript/components/dashboard/dashboard-chip/styles.css +++ b/app/javascript/components/dashboard/dashboard-chip/styles.css @@ -40,6 +40,13 @@ align-items: normal; } + &.disabled { + pointer-events: none; + &:hover { + opacity: 1 + } + } + &:hover { opacity: .8; diff --git a/app/javascript/components/dashboard/dashboard-table/component.jsx b/app/javascript/components/dashboard/dashboard-table/component.jsx index c6eb4b478b..dee468f35d 100644 --- a/app/javascript/components/dashboard/dashboard-table/component.jsx +++ b/app/javascript/components/dashboard/dashboard-table/component.jsx @@ -14,7 +14,7 @@ import { defaultTableOptions } from "../../index-table/utils"; import css from "./styles.css"; -const DashboardTable = ({ columns, data, query, title, pathname }) => { +function DashboardTable({ columns, data, query, title, pathname }) { const userPermissions = useMemoizedSelector(state => getPermissions(state)); const clickableCell = [...userPermissions.keys()].includes(pathname.split("/")[1]); @@ -66,11 +66,11 @@ const DashboardTable = ({ columns, data, query, title, pathname }) => { }; return ( -
+
); -}; +} DashboardTable.displayName = "DashboardTable"; diff --git a/app/javascript/components/dashboard/dashboard-table/component.spec.js b/app/javascript/components/dashboard/dashboard-table/component.spec.js new file mode 100644 index 0000000000..bee127f1d6 --- /dev/null +++ b/app/javascript/components/dashboard/dashboard-table/component.spec.js @@ -0,0 +1,34 @@ +import { mountedComponent, screen } from "test-utils"; +import { fromJS } from "immutable"; + +import DashboardTable from "./component"; + +describe("", () => { + const props = { + columns: [], + data: [], + query: [], + title: "testTitle", + pathname: "/cases" + }; + + const state = fromJS({ + user: { + permissions: { + cases: ["manage"] + } + } + }); + + beforeEach(() => { + mountedComponent(, state); + }); + + it("renders a MUIDataTable />", () => { + expect(screen.getByRole("grid")).toBeInTheDocument(); + }); + + it("should render text", () => { + expect(screen.queryAllByText("testTitle")).toBeTruthy(); + }); +}); diff --git a/app/javascript/components/dashboard/dashboard-table/component.unit.test.js b/app/javascript/components/dashboard/dashboard-table/component.unit.test.js deleted file mode 100644 index 228b733b4e..0000000000 --- a/app/javascript/components/dashboard/dashboard-table/component.unit.test.js +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import MUIDataTable from "mui-datatables"; -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../test"; - -import DashboardTable from "./component"; - -describe("", () => { - let component; - const props = { - columns: [], - data: [], - query: [], - title: "testTitle", - pathname: "/cases" - }; - - const state = fromJS({ - user: { - permissions: { - cases: ["manage"] - } - } - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(DashboardTable, props, state)); - }); - - it("renders a MUIDataTable />", () => { - expect(component.find(MUIDataTable)).to.have.lengthOf(1); - }); - - it("renders a MUIDataTable with valid Props", () => { - const muiDataTableProps = { ...component.find(MUIDataTable).props() }; - - ["columns", "options", "data", "title"].forEach(property => { - expect(muiDataTableProps).to.have.property(property); - delete muiDataTableProps[property]; - }); - - expect(muiDataTableProps).to.be.empty; - }); - - it("should render Caption", () => { - const testTitle = component.find(MUIDataTable).find("caption").text(); - - expect(testTitle).to.equals("testTitle"); - }); - - it("should have attribute aria-label", () => { - const label = component.find(MUIDataTable).find("table").first().props()["aria-label"]; - - expect(label).to.equals(props.title); - }); -}); diff --git a/app/javascript/components/dashboard/dashboard-table/theme.js b/app/javascript/components/dashboard/dashboard-table/theme.js index f7e953a0b5..7a7d6a45dc 100644 --- a/app/javascript/components/dashboard/dashboard-table/theme.js +++ b/app/javascript/components/dashboard/dashboard-table/theme.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { createTheme } from "@material-ui/core"; +import { createTheme } from "@mui/material"; export default clickableCell => createTheme({ diff --git a/app/javascript/components/dashboard/doughnut-chart/component.jsx b/app/javascript/components/dashboard/doughnut-chart/component.jsx index ec044850ca..7de84d91f7 100644 --- a/app/javascript/components/dashboard/doughnut-chart/component.jsx +++ b/app/javascript/components/dashboard/doughnut-chart/component.jsx @@ -48,7 +48,7 @@ Chart.pluginService.register({ } }); -const DoughnutChart = ({ chartData, options }) => { +function DoughnutChart({ chartData, options }) { const chartRef = createRef(); useEffect(() => { @@ -84,7 +84,7 @@ const DoughnutChart = ({ chartData, options }) => { }); return ; -}; +} DoughnutChart.displayName = "DoughnutChart"; diff --git a/app/javascript/components/dashboard/flag-box/component.jsx b/app/javascript/components/dashboard/flag-box/component.jsx index a116ff1d95..8ab981c4e8 100644 --- a/app/javascript/components/dashboard/flag-box/component.jsx +++ b/app/javascript/components/dashboard/flag-box/component.jsx @@ -8,7 +8,7 @@ import FlagBoxItem from "./components/flag-box-item"; import { showId } from "./utils"; import css from "./styles.css"; -const FlagBox = ({ flags }) => { +function FlagBox({ flags }) { return (
{flags @@ -25,7 +25,7 @@ const FlagBox = ({ flags }) => { .slice(0, 10)}
); -}; +} FlagBox.displayName = "FlagBox"; diff --git a/app/javascript/components/dashboard/flag-box/component.unit.test.js b/app/javascript/components/dashboard/flag-box/component.spec.js similarity index 69% rename from app/javascript/components/dashboard/flag-box/component.unit.test.js rename to app/javascript/components/dashboard/flag-box/component.spec.js index 15e738474b..4e1907fdec 100644 --- a/app/javascript/components/dashboard/flag-box/component.unit.test.js +++ b/app/javascript/components/dashboard/flag-box/component.spec.js @@ -1,14 +1,9 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - +import { mountedComponent, screen } from "test-utils"; import { fromJS } from "immutable"; -import { setupMountedComponent } from "../../../test"; - -import FlagBoxItem from "./components/flag-box-item"; import FlagBox from "./component"; describe("", () => { - let component; const props = { flags: fromJS([ { @@ -33,10 +28,10 @@ describe("", () => { }; beforeEach(() => { - ({ component } = setupMountedComponent(FlagBox, props, {})); + mountedComponent(); }); it("should render 2 FlagBoxItem", () => { - expect(component.find(FlagBoxItem)).to.have.lengthOf(2); + expect(screen.getAllByRole("button")).toHaveLength(2); }); }); diff --git a/app/javascript/components/dashboard/flag-box/components/flag-box-item/component.jsx b/app/javascript/components/dashboard/flag-box/components/flag-box-item/component.jsx index f147712891..618a66bf70 100644 --- a/app/javascript/components/dashboard/flag-box/components/flag-box-item/component.jsx +++ b/app/javascript/components/dashboard/flag-box/components/flag-box-item/component.jsx @@ -12,7 +12,7 @@ import { UserArrowIcon } from "../../../../../images/primero-icons"; import { NAME } from "./constants"; -const Component = ({ date, reason, recordId, title, user }) => { +function Component({ date, reason, recordId, title, user }) { const dispatch = useDispatch(); const handleFlagOpen = id => () => dispatch(push(`${RECORD_PATH.cases}/${id}`)); @@ -27,7 +27,7 @@ const Component = ({ date, reason, recordId, title, user }) => {
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/dashboard/flag-box/components/flag-box-item/component.spec.js b/app/javascript/components/dashboard/flag-box/components/flag-box-item/component.spec.js new file mode 100644 index 0000000000..953bc0159d --- /dev/null +++ b/app/javascript/components/dashboard/flag-box/components/flag-box-item/component.spec.js @@ -0,0 +1,33 @@ +import { mountedComponent, screen } from "test-utils"; + +import FlagBoxItem from "./component"; + +describe("", () => { + const props = { + date: "2020-12-10", + reason: "Reason 1", + recordId: "41a3e69b-991a-406e-b0ee-9123cb60c983", + title: "User 1", + user: "primero_test" + }; + + beforeEach(() => { + mountedComponent(); + }); + + it("should render a h4 tag", () => { + expect(screen.getByRole("heading")).toHaveTextContent("User 1"); + }); + + it("should render a span tag", () => { + expect(screen.getByText("2020-12-10")).toBeInTheDocument(); + }); + + it("should render a p tag", () => { + expect(screen.getByText("Reason 1")).toBeInTheDocument(); + }); + + it("should render a span tag", () => { + expect(screen.getByText("primero_test")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/dashboard/flag-box/components/flag-box-item/component.unit.test.js b/app/javascript/components/dashboard/flag-box/components/flag-box-item/component.unit.test.js deleted file mode 100644 index 962a483657..0000000000 --- a/app/javascript/components/dashboard/flag-box/components/flag-box-item/component.unit.test.js +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../../test"; - -import FlagBoxItem from "./component"; - -describe("", () => { - let component; - const props = { - date: "2020-12-10", - reason: "Reason 1", - recordId: "41a3e69b-991a-406e-b0ee-9123cb60c983", - title: "User 1", - user: "primero_test" - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(FlagBoxItem, props, {})); - }); - - it("should render a h4 tag", () => { - expect(component.find("h4").text()).to.be.equal("User 1"); - }); - - it("should render a span tag", () => { - expect(component.find("span").at(0).text()).to.be.equal("2020-12-10"); - }); - - it("should render a p tag", () => { - expect(component.find("p").text()).to.be.equal("Reason 1"); - }); - - it("should render a span tag", () => { - expect(component.find("span").at(1).text()).to.be.equal("primero_test"); - }); -}); diff --git a/app/javascript/components/dashboard/flag-list/component.jsx b/app/javascript/components/dashboard/flag-list/component.jsx index 9de4c9120f..162ba29665 100644 --- a/app/javascript/components/dashboard/flag-list/component.jsx +++ b/app/javascript/components/dashboard/flag-list/component.jsx @@ -8,7 +8,7 @@ import FlagBox from "../flag-box"; import css from "./styles.css"; -const FlagList = ({ flags }) => { +function FlagList({ flags }) { const i18n = useI18n(); return ( @@ -21,7 +21,7 @@ const FlagList = ({ flags }) => {
); -}; +} FlagList.displayName = "FlagList"; diff --git a/app/javascript/components/dashboard/line-chart/component.jsx b/app/javascript/components/dashboard/line-chart/component.jsx index 4a73eed68c..c79dfb71ab 100644 --- a/app/javascript/components/dashboard/line-chart/component.jsx +++ b/app/javascript/components/dashboard/line-chart/component.jsx @@ -6,7 +6,7 @@ import { createRef, useEffect } from "react"; import css from "./styles.css"; -const LineChart = ({ chartData, options, title }) => { +function LineChart({ chartData, options, title }) { const chartRef = createRef(); useEffect(() => { @@ -79,7 +79,7 @@ const LineChart = ({ chartData, options, title }) => {
); -}; +} LineChart.displayName = "LineChart"; diff --git a/app/javascript/components/dashboard/options-box/component.jsx b/app/javascript/components/dashboard/options-box/component.jsx index 43e0009532..f808b39707 100644 --- a/app/javascript/components/dashboard/options-box/component.jsx +++ b/app/javascript/components/dashboard/options-box/component.jsx @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Card, CardHeader, CardContent } from "@material-ui/core"; +import { Card, CardHeader, CardContent } from "@mui/material"; import { Link } from "react-router-dom"; import PropTypes from "prop-types"; @@ -10,7 +10,7 @@ import { ConditionalWrapper } from "../../../libs"; import css from "./styles.css"; -const OptionsBox = ({ title, action, children, to, flat, overlay, type, loading, errors, hasData }) => { +function OptionsBox({ title, action, children, to, flat, overlay, type = "", loading, errors, hasData = true }) { const loadingIndicatorProps = { overlay, type, @@ -47,15 +47,10 @@ const OptionsBox = ({ title, action, children, to, flat, overlay, type, loading, ); -}; +} OptionsBox.displayName = "OptionsBox"; -OptionsBox.defaultProps = { - hasData: true, - type: "" -}; - OptionsBox.propTypes = { action: PropTypes.node, children: PropTypes.node, diff --git a/app/javascript/components/dashboard/overview-box/component.jsx b/app/javascript/components/dashboard/overview-box/component.jsx index a1a1046f12..dbbbceb3f3 100644 --- a/app/javascript/components/dashboard/overview-box/component.jsx +++ b/app/javascript/components/dashboard/overview-box/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { Fragment } from "react"; -import { Grid } from "@material-ui/core"; +import { Grid } from "@mui/material"; import PropTypes from "prop-types"; import { fromJS } from "immutable"; import { useDispatch } from "react-redux"; @@ -18,7 +18,7 @@ import ActionButton from "../../action-button"; import css from "./styles.css"; -const OverviewBox = ({ items, chartData, sumTitle, withTotal, loading, errors }) => { +function OverviewBox({ items, chartData, sumTitle, withTotal = true, loading, errors }) { const i18n = useI18n(); const { approvalsLabels } = useApp(); const dispatch = useDispatch(); @@ -97,7 +97,7 @@ const OverviewBox = ({ items, chartData, sumTitle, withTotal, loading, errors }) // eslint-disable-next-line react/no-multi-comp, react/display-name const renderItems = () => ( -
+
{renderSum()}
{statItems()}
@@ -106,7 +106,7 @@ const OverviewBox = ({ items, chartData, sumTitle, withTotal, loading, errors }) // eslint-disable-next-line react/no-multi-comp, react/display-name const renderWithChart = () => ( -
+
{chartData && ( @@ -123,11 +123,7 @@ const OverviewBox = ({ items, chartData, sumTitle, withTotal, loading, errors }) const renderOverviewBox = chartData ? renderWithChart() : renderItems(); return <>{renderOverviewBox}; -}; - -OverviewBox.defaultProps = { - withTotal: true -}; +} OverviewBox.displayName = "OverviewBox"; diff --git a/app/javascript/components/dashboard/overview-box/component.unit.test.js b/app/javascript/components/dashboard/overview-box/component.spec.js similarity index 65% rename from app/javascript/components/dashboard/overview-box/component.unit.test.js rename to app/javascript/components/dashboard/overview-box/component.spec.js index 4c6f5906ff..c021c3b17e 100644 --- a/app/javascript/components/dashboard/overview-box/component.unit.test.js +++ b/app/javascript/components/dashboard/overview-box/component.spec.js @@ -1,14 +1,12 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { CircularProgress } from "@material-ui/core"; -import { setupMountedComponent } from "../../../test"; +import { mountedComponent, screen } from "../../../test-utils"; import OverviewBox from "./component"; describe("", () => { - let component; const props = { items: fromJS({ name: "dashboard.approvals_closure", @@ -24,28 +22,27 @@ describe("", () => { }; beforeEach(() => { - ({ component } = setupMountedComponent(OverviewBox, props, {})); + mountedComponent(); }); it("renders a component/>", () => { - expect(component.find(OverviewBox)).to.have.lengthOf(1); - expect(component.find("a")).to.have.lengthOf(2); - expect(component.text()).to.contain("5 Closure"); + expect(screen.getByText("5 Closure")).toBeInTheDocument(); + expect(screen.getAllByRole("button")).toHaveLength(2); }); describe("when withTotal props is false", () => { beforeEach(() => { - ({ component } = setupMountedComponent(OverviewBox, { ...props, withTotal: false }, {})); + const componentProps = { ...props, withTotal: false }; + + mountedComponent(); }); it("renders the header without total/>", () => { - expect(component.find(OverviewBox)).to.have.lengthOf(1); - expect(component.find("a")).to.have.lengthOf(2); - expect(component.text()).to.contain("Closure"); + expect(screen.getByText("Closure")).toBeInTheDocument(); + expect(screen.getAllByRole("button")).toHaveLength(4); }); }); describe("When data still loading", () => { - let loadingComponent; const loadingProps = { items: fromJS({ name: "dashboard.approvals_closure", @@ -56,19 +53,16 @@ describe("", () => { loading: true }; - before(() => { - ({ component: loadingComponent } = setupMountedComponent(OverviewBox, loadingProps, {})); + beforeEach(() => { + mountedComponent(); }); - it("renders BadgedIndicator component", () => { - expect(loadingComponent.find(OverviewBox)).to.have.lengthOf(1); - }); it("renders CircularProgress", () => { - expect(loadingComponent.find(CircularProgress)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); describe("When the approvals labels entries are present", () => { - context("when is a Assessment approvals", () => { + describe("when is a Assessment approvals", () => { const ASSESSMENT_LABEL = "Assessment"; const propsApprovals = { items: fromJS({ @@ -94,15 +88,15 @@ describe("", () => { }); beforeEach(() => { - ({ component } = setupMountedComponent(OverviewBox, propsApprovals, initialState)); + mountedComponent(, initialState); }); it("renders a component with its respective label />", () => { - expect(component.text()).to.contain(`1${ASSESSMENT_LABEL}`); + expect(document.querySelectorAll(".overviewList")[1].textContent).toBe(`1${ASSESSMENT_LABEL}`); }); }); - context("when is GBV Closure approvals", () => { + describe("when is GBV Closure approvals", () => { const GBV_CLOSURE = "GBV Closure"; const propsApprovals = { items: fromJS({ @@ -128,11 +122,11 @@ describe("", () => { }); beforeEach(() => { - ({ component } = setupMountedComponent(OverviewBox, propsApprovals, initialState)); + mountedComponent(, initialState); }); it("renders a component with its respective label />", () => { - expect(component.text()).to.contain(`1${GBV_CLOSURE}`); + expect(document.querySelectorAll(".overviewList")[1].textContent).toBe(`1${GBV_CLOSURE}`); }); }); }); diff --git a/app/javascript/components/dashboard/overview-box/styles.css b/app/javascript/components/dashboard/overview-box/styles.css index 67d7cf86c1..1cd064acf8 100644 --- a/app/javascript/components/dashboard/overview-box/styles.css +++ b/app/javascript/components/dashboard/overview-box/styles.css @@ -61,7 +61,7 @@ margin-bottom: var(--sp-1); } -@media (max-width:959.95px) { +@media (max-width:900px) { .dashboardChart { margin: 0; border-right: none; diff --git a/app/javascript/components/dashboard/pie-chart/component.jsx b/app/javascript/components/dashboard/pie-chart/component.jsx index af253b61ed..26639f77a3 100644 --- a/app/javascript/components/dashboard/pie-chart/component.jsx +++ b/app/javascript/components/dashboard/pie-chart/component.jsx @@ -11,7 +11,7 @@ import { buildFilter } from "../utils"; import { NAME, COLORS } from "./constants"; -const PieChart = ({ data, labels, query }) => { +function PieChart({ data, labels, query }) { const dispatch = useDispatch(); const chartRef = createRef(); @@ -59,8 +59,8 @@ const PieChart = ({ data, labels, query }) => { }; }); - return ; -}; + return ; +} PieChart.displayName = NAME; diff --git a/app/javascript/components/dashboard/pie-chart/component.unit.test.js b/app/javascript/components/dashboard/pie-chart/component.spec.js similarity index 66% rename from app/javascript/components/dashboard/pie-chart/component.unit.test.js rename to app/javascript/components/dashboard/pie-chart/component.spec.js index dd7cecd4e5..5ddc091285 100644 --- a/app/javascript/components/dashboard/pie-chart/component.unit.test.js +++ b/app/javascript/components/dashboard/pie-chart/component.spec.js @@ -1,11 +1,10 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { setupMountedComponent } from "../../../test"; +import { mountedComponent, screen } from "../../../test-utils"; import PieChart from "./component"; describe("", () => { - let component; const props = { data: [10, 12, 8], labels: ["Care plan", "New", "Service provision"], @@ -13,10 +12,10 @@ describe("", () => { }; beforeEach(() => { - ({ component } = setupMountedComponent(PieChart, props, {})); + mountedComponent(); }); it("renders a PieChart />", () => { - expect(component.find(PieChart)).to.have.lengthOf(1); + expect(screen.getByTestId("pie-chart")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/dashboard/priority-summary/component.jsx b/app/javascript/components/dashboard/priority-summary/component.jsx index e89769d261..9d1d351fe4 100644 --- a/app/javascript/components/dashboard/priority-summary/component.jsx +++ b/app/javascript/components/dashboard/priority-summary/component.jsx @@ -7,7 +7,7 @@ import DashboardChip from "../dashboard-chip"; import css from "./styles.css"; -const PrioritySummary = ({ summary }) => { +function PrioritySummary({ summary }) { const i18n = useI18n(); const getTitle = status => { @@ -51,7 +51,7 @@ const PrioritySummary = ({ summary }) => {
); -}; +} PrioritySummary.displayName = "PrioritySummary"; diff --git a/app/javascript/components/dashboard/services/component.jsx b/app/javascript/components/dashboard/services/component.jsx index 46bd16878d..b1fcdfcfc5 100644 --- a/app/javascript/components/dashboard/services/component.jsx +++ b/app/javascript/components/dashboard/services/component.jsx @@ -8,7 +8,7 @@ import OptionsBox from "../options-box"; import css from "./styles.css"; -const Services = ({ servicesList }) => { +function Services({ servicesList }) { const i18n = useI18n(); const styleOverrides = { @@ -34,7 +34,7 @@ const Services = ({ servicesList }) => { ); -}; +} Services.displayName = "Services"; diff --git a/app/javascript/components/demo-indicator/component.jsx b/app/javascript/components/demo-indicator/component.jsx index c5428f64a7..87a5dbc25e 100644 --- a/app/javascript/components/demo-indicator/component.jsx +++ b/app/javascript/components/demo-indicator/component.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import Alert from "@material-ui/lab/Alert"; -import { useMediaQuery } from "@material-ui/core"; +import Alert from "@mui/material/Alert"; +import { useMediaQuery } from "@mui/material"; import { useI18n } from "../i18n"; import { DEMO } from "../application/constants"; @@ -10,7 +10,7 @@ import { DEMO } from "../application/constants"; import { NAME } from "./constants"; import css from "./styles.css"; -const Component = ({ isDemo }) => { +function Component({ isDemo }) { const mobileDisplay = useMediaQuery(theme => theme.breakpoints.down("sm")); const i18n = useI18n(); const classes = { standardInfo: css.standardInfo, message: css.standardInfoText }; @@ -24,7 +24,7 @@ const Component = ({ isDemo }) => { {i18n.t(DEMO)} ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/disable-offline/component.jsx b/app/javascript/components/disable-offline/component.jsx index a5258cfff6..e83c0dc3d5 100644 --- a/app/javascript/components/disable-offline/component.jsx +++ b/app/javascript/components/disable-offline/component.jsx @@ -2,25 +2,25 @@ import { cloneElement } from "react"; import PropTypes from "prop-types"; -import { Tooltip } from "@material-ui/core"; -import clsx from "clsx"; +import { Tooltip } from "@mui/material"; +import { cx } from "@emotion/css"; import { useApp } from "../application"; import { useI18n } from "../i18n"; import css from "./styles.css"; -const Component = ({ overrideCondition, children, button, offlineTextKey }) => { +function Component({ overrideCondition = false, children, button = false, offlineTextKey = null }) { const { online } = useApp(); const i18n = useI18n(); - const classes = clsx(css.disabledLink, { + const classes = cx(css.disabledLink, { [css.disabled]: !button }); if (overrideCondition || !online) { return ( -
+
{!button &&
} {cloneElement(children, { disabled: true })}
@@ -29,13 +29,7 @@ const Component = ({ overrideCondition, children, button, offlineTextKey }) => { } return children; -}; - -Component.defaultProps = { - button: false, - offlineTextKey: null, - overrideCondition: false -}; +} Component.propTypes = { button: PropTypes.bool, diff --git a/app/javascript/components/disable-offline/component.spec.js b/app/javascript/components/disable-offline/component.spec.js new file mode 100644 index 0000000000..aca4b9d0ef --- /dev/null +++ b/app/javascript/components/disable-offline/component.spec.js @@ -0,0 +1,59 @@ +import { mountedComponent, screen, fireEvent, waitFor, expectNever } from "test-utils"; +import { fromJS } from "immutable"; + +import DisableOffline from "./component"; + +describe(" - Component", () => { + it("renders element with tooltip if offline", async () => { + mountedComponent( + +
element
+
, + { + connectivity: { + online: false, + serverOnline: true + } + } + ); + + fireEvent.mouseEnter(screen.getByText("element")); + await waitFor(() => expect(screen.getByRole("tooltip")).toBeInTheDocument()); + }); + + it("renders element with no tooltip if online", async () => { + mountedComponent( + +
element
+
, + fromJS({ + connectivity: { + online: true, + serverOnline: true + } + }) + ); + + fireEvent.mouseEnter(screen.getByText("element")); + await expectNever(() => { + expect(screen.getByRole("tooltip")).toBeInTheDocument(); + }); + }); + + it("renders element and tooltip if overrideCondition", async () => { + mountedComponent( + +
element
+
, + fromJS({ + connectivity: { + online: false, + serverOnline: true + } + }) + ); + + fireEvent.mouseEnter(screen.getByText("element")); + await waitFor(() => expect(screen.getByRole("tooltip")).toBeInTheDocument()); + }); +}); diff --git a/app/javascript/components/disable-offline/component.unit.test.js b/app/javascript/components/disable-offline/component.unit.test.js deleted file mode 100644 index 3c63223a12..0000000000 --- a/app/javascript/components/disable-offline/component.unit.test.js +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { Tooltip } from "@material-ui/core"; - -import { setupMountedComponent } from "../../test"; - -import DisableOffline from "./component"; - -describe("components/disable-offline - DisableOffline", () => { - const component = (online, props) => - setupMountedComponent( - () => ( - -
element
-
- ), - { text: "offline", ...props }, - fromJS({ - connectivity: { - online, - serverOnline: true - } - }) - ).component; - - it("renders element in offline state if offline", () => { - expect(component(false).find(Tooltip)).to.have.lengthOf(1); - }); - - it("renders element in online state if online", () => { - expect(component(true).find(Tooltip)).to.have.lengthOf(0); - }); - - it("renders element if overrideCondition", () => { - expect(component(false, { overrideCondition: true }).find(Tooltip)).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/disable-offline/components/offline-alert/component.jsx b/app/javascript/components/disable-offline/components/offline-alert/component.jsx index bd6d35ceac..3ae33cf71c 100644 --- a/app/javascript/components/disable-offline/components/offline-alert/component.jsx +++ b/app/javascript/components/disable-offline/components/offline-alert/component.jsx @@ -1,14 +1,14 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import Alert from "@material-ui/lab/Alert"; -import SignalWifiOff from "@material-ui/icons/SignalWifiOff"; +import Alert from "@mui/material/Alert"; +import SignalWifiOff from "@mui/icons-material/SignalWifiOff"; import { useApp } from "../../../application"; import css from "./styles.css"; -const Component = ({ text, noMargin }) => { +function Component({ text, noMargin }) { const { online } = useApp(); if (online) return null; @@ -20,7 +20,7 @@ const Component = ({ text, noMargin }) => {
); -}; +} Component.displayName = "OfflineAlert"; diff --git a/app/javascript/components/disable-offline/components/offline-alert/component.spec.js b/app/javascript/components/disable-offline/components/offline-alert/component.spec.js new file mode 100644 index 0000000000..12073748b0 --- /dev/null +++ b/app/javascript/components/disable-offline/components/offline-alert/component.spec.js @@ -0,0 +1,36 @@ +import { mountedComponent, screen } from "test-utils"; +import { fromJS } from "immutable"; + +import OfflineAlert from "./component"; + +describe(" - Component", () => { + const props = { + text: "offline" + }; + + it("renders Flagging form", () => { + mountedComponent( + , + fromJS({ + connectivity: { + online: false, + serverOnline: true + } + }) + ); + expect(screen.queryByText("offline")).toBeInTheDocument(); + }); + + it("does not render alert if online", () => { + mountedComponent( + , + fromJS({ + connectivity: { + online: true, + serverOnline: true + } + }) + ); + expect(screen.queryByText("offline")).not.toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/disable-offline/components/offline-alert/component.unit.test.js b/app/javascript/components/disable-offline/components/offline-alert/component.unit.test.js deleted file mode 100644 index c0ddcb599e..0000000000 --- a/app/javascript/components/disable-offline/components/offline-alert/component.unit.test.js +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import Alert from "@material-ui/lab/Alert"; - -import { setupMountedComponent } from "../../../../test"; - -import OfflineAlert from "./component"; - -describe("components/disable-offline/components/offline-alert - OfflineAlert", () => { - const component = online => - setupMountedComponent( - OfflineAlert, - { text: "offline" }, - fromJS({ - connectivity: { - online, - serverOnline: true - } - }) - ).component; - - it("renders alert if offline", () => { - expect(component(false).find(Alert)).to.have.lengthOf(1); - }); - - it("does not render alert if online", () => { - expect(component(true).find(Alert)).to.have.lengthOf(0); - }); -}); diff --git a/app/javascript/components/display-data/component.jsx b/app/javascript/components/display-data/component.jsx index 576422ea4d..7ca2ea1429 100644 --- a/app/javascript/components/display-data/component.jsx +++ b/app/javascript/components/display-data/component.jsx @@ -7,16 +7,16 @@ import { useI18n } from "../i18n"; import { NAME } from "./constants"; import css from "./styles.css"; -const DisplayData = ({ label, value }) => { +function DisplayData({ label, value }) { const i18n = useI18n(); return ( -
+
{i18n.t(label)}
{value || "--"}
); -}; +} DisplayData.displayName = NAME; diff --git a/app/javascript/components/error-boundary/components/error-state/component.jsx b/app/javascript/components/error-boundary/components/error-state/component.jsx index c97b411b48..b484267f48 100644 --- a/app/javascript/components/error-boundary/components/error-state/component.jsx +++ b/app/javascript/components/error-boundary/components/error-state/component.jsx @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Button } from "@material-ui/core"; +import { Button } from "@mui/material"; import PropTypes from "prop-types"; import ListIcon from "../../../list-icon"; @@ -8,7 +8,7 @@ import { useI18n } from "../../../i18n"; import css from "./styles.css"; -const ErrorState = ({ errorMessage, handleTryAgain, type }) => { +function ErrorState({ errorMessage, handleTryAgain, type }) { const i18n = useI18n(); return ( @@ -28,7 +28,7 @@ const ErrorState = ({ errorMessage, handleTryAgain, type }) => {
); -}; +} ErrorState.displayName = "ErrorState"; diff --git a/app/javascript/components/error-boundary/components/error-state/styles.css b/app/javascript/components/error-boundary/components/error-state/styles.css index 5b8876b632..f957ee342d 100644 --- a/app/javascript/components/error-boundary/components/error-state/styles.css +++ b/app/javascript/components/error-boundary/components/error-state/styles.css @@ -27,7 +27,7 @@ margin: 0.2em 0 1em; } -@media (max-width:959.95px) { +@media (max-width:900px) { .error { margin-top: 6em; } diff --git a/app/javascript/components/flagging/component.jsx b/app/javascript/components/flagging/component.jsx index 454dd01352..5a4bf2d5b5 100644 --- a/app/javascript/components/flagging/component.jsx +++ b/app/javascript/components/flagging/component.jsx @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import FlagIcon from "@material-ui/icons/Flag"; +import FlagIcon from "@mui/icons-material/Flag"; import PropTypes from "prop-types"; import { useState } from "react"; @@ -14,7 +14,7 @@ import { FlagDialog, FlagForm, ListFlags, Unflag } from "./components"; import { FLAG_DIALOG, NAME } from "./constants"; import { getSelectedFlag } from "./selectors"; -const Component = ({ control, record, recordType }) => { +function Component({ control, record, recordType }) { const [tab, setTab] = useState(0); const { dialogOpen, setDialog } = useDialog(FLAG_DIALOG); @@ -64,7 +64,7 @@ const Component = ({ control, record, recordType }) => { /> )} -
+
@@ -74,7 +74,7 @@ const Component = ({ control, record, recordType }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/flagging/component.unit.test.js b/app/javascript/components/flagging/component.spec.js similarity index 56% rename from app/javascript/components/flagging/component.unit.test.js rename to app/javascript/components/flagging/component.spec.js index c3ccf87131..89a37a1c69 100644 --- a/app/javascript/components/flagging/component.unit.test.js +++ b/app/javascript/components/flagging/component.spec.js @@ -1,21 +1,23 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Map } from "immutable"; - -import { setupMountedComponent } from "../../test"; +import { mountedComponent, screen } from "test-utils"; +import { fromJS } from "immutable"; import Flagging from "./component"; -import { FlagDialog } from "./components"; +import { FLAG_DIALOG } from "./constants"; -describe(" - Component", () => { - let component; +describe(" - Component", () => { + const props = { + recordType: "cases", + record: "0df32f52-4290-4ce1-b859-74ac14c081bf" + }; - before(() => { - component = setupMountedComponent( - Flagging, - { recordType: "cases", record: "0df32f52-4290-4ce1-b859-74ac14c081bf" }, - Map({ - records: Map({ + beforeEach(() => { + mountedComponent( + , + fromJS({ + ui: { dialogs: { dialog: FLAG_DIALOG, open: true } }, + records: { cases: { data: { 0: { @@ -42,16 +44,18 @@ describe(" - Component", () => { } ] } - }) + } }) - ).component; + ); }); it("renders Flagging form", () => { - expect(component.find(Flagging)).to.have.lengthOf(1); + expect(screen.getByText("buttons.flags")).toBeInTheDocument(); + expect(screen.getByText("flags.add_flag_tab")).toBeInTheDocument(); + expect(document.querySelector("#FlagForm")).toBeInTheDocument(); }); it("renders FlagDialog", () => { - expect(component.find(FlagDialog)).to.have.lengthOf(1); + expect(screen.getByText("flags.title")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/flagging/components/TabPanel.jsx b/app/javascript/components/flagging/components/TabPanel.jsx index 6de5052c90..e67d882764 100644 --- a/app/javascript/components/flagging/components/TabPanel.jsx +++ b/app/javascript/components/flagging/components/TabPanel.jsx @@ -1,9 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Box } from "@material-ui/core"; +import { Box } from "@mui/material"; -const TabPanel = props => { +function TabPanel(props) { const { children, value, index } = props; return ( @@ -16,7 +16,7 @@ const TabPanel = props => { {children} ); -}; +} TabPanel.displayName = "TabPanel"; diff --git a/app/javascript/components/flagging/components/dialog-tabs/component.jsx b/app/javascript/components/flagging/components/dialog-tabs/component.jsx index 6685cf6953..5e52fb671a 100644 --- a/app/javascript/components/flagging/components/dialog-tabs/component.jsx +++ b/app/javascript/components/flagging/components/dialog-tabs/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Tab, Tabs, Box } from "@material-ui/core"; +import { Tab, Tabs, Box } from "@mui/material"; import { useI18n } from "../../../i18n"; import TabPanel from "../TabPanel"; @@ -9,7 +9,7 @@ import css from "../styles.css"; import { NAME } from "./constants"; -const Component = ({ children, isBulkFlags, tab, setTab }) => { +function Component({ children, isBulkFlags, tab, setTab }) { const i18n = useI18n(); const tabs = [i18n.t("flags.flags_tab"), i18n.t("flags.add_flag_tab")]; @@ -29,8 +29,7 @@ const Component = ({ children, isBulkFlags, tab, setTab }) => { const filterChildren = children.filter(child => ["false", undefined].includes(child.props.hidetab)); const renderChildren = filterChildren.map((child, index) => ( - // eslint-disable-next-line react/no-array-index-key - + {child} )); @@ -41,8 +40,8 @@ const Component = ({ children, isBulkFlags, tab, setTab }) => { - {filteredTabs.map((t, index) => ( - + {filteredTabs.map((label, index) => ( + ))} @@ -53,7 +52,7 @@ const Component = ({ children, isBulkFlags, tab, setTab }) => { } return null; -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/flagging/components/dialog-tabs/component.spec.js b/app/javascript/components/flagging/components/dialog-tabs/component.spec.js new file mode 100644 index 0000000000..f3dbc6351f --- /dev/null +++ b/app/javascript/components/flagging/components/dialog-tabs/component.spec.js @@ -0,0 +1,21 @@ +import { mountedComponent, screen } from "test-utils"; + +import DialogTabs from "./component"; + +describe(" - Component", () => { + const props = { + children: [{ props: { hidetab: true } }], + isBulkFlags: false, + tab: 0, + setTab: () => {} + }; + + beforeEach(() => { + mountedComponent(); + }); + + it("should render the DialogTabs", () => { + expect(screen.getByText("flags.flags_tab")).toBeInTheDocument(); + expect(screen.getByText("flags.add_flag_tab")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/flagging/components/dialog-tabs/component.unit.test.js b/app/javascript/components/flagging/components/dialog-tabs/component.unit.test.js deleted file mode 100644 index 7754dbc418..0000000000 --- a/app/javascript/components/flagging/components/dialog-tabs/component.unit.test.js +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Tab, Tabs, Box } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../../test"; - -import DialogTabs from "./component"; - -describe("", () => { - let component; - - const props = { - children: [{ props: { hidetab: true } }], - isBulkFlags: false, - tab: 0, - setTab: () => {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(DialogTabs, props)); - }); - - it("should render the DialogTabs", () => { - expect(component.find(DialogTabs)).to.have.lengthOf(1); - }); - - it("should render the Box", () => { - expect(component.find(Box)).to.have.lengthOf(2); - }); - - it("should render the Tabs", () => { - expect(component.find(Tabs)).to.have.lengthOf(1); - }); - - it("should render two Tab", () => { - expect(component.find(Tab)).to.have.lengthOf(2); - }); - - it("renders component with valid props", () => { - const dialogTabsProps = { ...component.find(DialogTabs).props() }; - - ["children", "isBulkFlags", "tab", "setTab"].forEach(property => { - expect(dialogTabsProps).to.have.property(property); - delete dialogTabsProps[property]; - }); - expect(dialogTabsProps).to.be.empty; - }); -}); diff --git a/app/javascript/components/flagging/components/flag-dialog/component.jsx b/app/javascript/components/flagging/components/flag-dialog/component.jsx index ced163dc55..89d661e2aa 100644 --- a/app/javascript/components/flagging/components/flag-dialog/component.jsx +++ b/app/javascript/components/flagging/components/flag-dialog/component.jsx @@ -9,13 +9,12 @@ import { NAME as FORM_ID } from "../flag-form/constants"; import { NAME } from "./constants"; -const Component = ({ dialogOpen, fetchAction, fetchArgs, children, isBulkFlags, tab, setTab }) => { +function Component({ dialogOpen, fetchAction, fetchArgs, children, isBulkFlags, tab, setTab }) { const i18n = useI18n(); return ( ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/flagging/components/flag-dialog/component.spec.js b/app/javascript/components/flagging/components/flag-dialog/component.spec.js new file mode 100644 index 0000000000..995e585adb --- /dev/null +++ b/app/javascript/components/flagging/components/flag-dialog/component.spec.js @@ -0,0 +1,30 @@ +import { mountedComponent, screen } from "test-utils"; + +import DialogTabs from "../dialog-tabs"; + +import FlagDialog from "./component"; + +describe("", () => { + const props = { + children: [{ props: { hidetab: true } }], + isBulkFlags: false, + tab: 0, + setTab: () => {}, + dialogOpen: true + }; + + it("should render the FlagDialog", () => { + mountedComponent(); + expect(screen.getByText("flags.add_flag_tab")).toBeInTheDocument(); + }); + + it("should render the ActionDialog", () => { + mountedComponent(); + expect(screen.getByText("flags.title")).toBeInTheDocument(); + }); + + it("should render the DialogTabs", () => { + mountedComponent(); + expect(screen.getAllByRole("tab")).toHaveLength(2); + }); +}); diff --git a/app/javascript/components/flagging/components/flag-dialog/component.unit.test.js b/app/javascript/components/flagging/components/flag-dialog/component.unit.test.js deleted file mode 100644 index 6f35925da9..0000000000 --- a/app/javascript/components/flagging/components/flag-dialog/component.unit.test.js +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../test"; -import ActionDialog from "../../../action-dialog"; -import DialogTabs from "../dialog-tabs"; - -import FlagDialog from "./component"; - -describe("", () => { - let component; - - const props = { - children: [{ props: { hidetab: true } }], - isBulkFlags: false, - tab: 0, - setTab: () => {}, - dialogOpen: true - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(FlagDialog, props)); - }); - - it("should render the FlagDialog", () => { - expect(component.find(FlagDialog)).to.have.lengthOf(1); - }); - - it("should render the ActionDialog", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(1); - }); - - it("should render the DialogTabs", () => { - expect(component.find(DialogTabs)).to.have.lengthOf(1); - }); - - it("renders component with valid props", () => { - const flagDialogProps = { ...component.find(FlagDialog).props() }; - - ["children", "isBulkFlags", "tab", "setTab", "dialogOpen"].forEach(property => { - expect(flagDialogProps).to.have.property(property); - delete flagDialogProps[property]; - }); - expect(flagDialogProps).to.be.empty; - }); -}); diff --git a/app/javascript/components/flagging/components/flag-form/component.jsx b/app/javascript/components/flagging/components/flag-form/component.jsx index 0601d2fe35..19efbf55a8 100644 --- a/app/javascript/components/flagging/components/flag-form/component.jsx +++ b/app/javascript/components/flagging/components/flag-form/component.jsx @@ -16,7 +16,7 @@ const initialValues = { message: "" }; -const Component = ({ recordType, record, handleActiveTab }) => { +function Component({ recordType, record, handleActiveTab }) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -39,7 +39,7 @@ const Component = ({ recordType, record, handleActiveTab }) => { resetAfterSubmit /> ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/flagging/components/flag-form/component.spec.js b/app/javascript/components/flagging/components/flag-form/component.spec.js new file mode 100644 index 0000000000..7ebddd52dd --- /dev/null +++ b/app/javascript/components/flagging/components/flag-form/component.spec.js @@ -0,0 +1,23 @@ +import { mountedComponent, screen } from "test-utils"; + +import { RECORD_TYPES } from "../../../../config"; + +import FlagForm from "./component"; + +describe("", () => { + const props = { + recordType: RECORD_TYPES.cases, + record: "230590", + handleActiveTab: () => {} + }; + + it("renders Form", () => { + mountedComponent(); + expect(screen.getAllByText("flags.flag_date")).toHaveLength(2); + }); + + it("should render the FlagForm", () => { + mountedComponent(); + expect(document.querySelector("#FlagForm")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/flagging/components/flag-form/component.unit.test.js b/app/javascript/components/flagging/components/flag-form/component.unit.test.js deleted file mode 100644 index 5212af2a4f..0000000000 --- a/app/javascript/components/flagging/components/flag-form/component.unit.test.js +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import Form from "../../../form"; -import { setupMountedComponent } from "../../../../test"; -import { RECORD_TYPES } from "../../../../config/constants"; -import NepaliCalendar from "../../../nepali-calendar-input"; - -import FlagForm from "./component"; - -describe("", () => { - describe("form inputs", () => { - let component; - - const props = { - recordType: RECORD_TYPES.cases, - record: "230590", - handleActiveTab: () => {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(FlagForm, props)); - }); - - it("should render the FlagForm", () => { - expect(component.find(FlagForm)).to.have.lengthOf(1); - }); - - it("renders Form", () => { - expect(component.find(Form)).to.have.lengthOf(1); - }); - - it("renders component with valid props", () => { - const flagFormProps = { ...component.find(FlagForm).props() }; - - ["handleActiveTab", "record", "recordType"].forEach(property => { - expect(flagFormProps).to.have.property(property); - delete flagFormProps[property]; - }); - expect(flagFormProps).to.be.empty; - }); - }); - - describe("when ne locale", () => { - it.skip("renders Nepali date picker", () => { - const props = { - recordType: RECORD_TYPES.cases, - record: "230590", - handleActiveTab: () => {} - }; - - window.I18n.locale = "ne"; - - const { component } = setupMountedComponent(FlagForm, props); - - expect(component.find(NepaliCalendar)).to.have.lengthOf(1); - }); - - after(() => { - window.I18n.locale = "en"; - }); - }); -}); diff --git a/app/javascript/components/flagging/components/list-flags-item-actions/component.jsx b/app/javascript/components/flagging/components/list-flags-item-actions/component.jsx index 3a75c4efcd..1992552e46 100644 --- a/app/javascript/components/flagging/components/list-flags-item-actions/component.jsx +++ b/app/javascript/components/flagging/components/list-flags-item-actions/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Divider } from "@material-ui/core"; +import { Divider } from "@mui/material"; import { useDispatch } from "react-redux"; import { useI18n } from "../../../i18n"; @@ -18,7 +18,7 @@ import { usePermissions, FLAG_RESOLVE_ANY } from "../../../permissions"; import { NAME } from "./constants"; -const Component = ({ flag }) => { +function Component({ flag }) { const i18n = useI18n(); const dispatch = useDispatch(); const canResolveAnyFlag = usePermissions(flag?.record_type, FLAG_RESOLVE_ANY); @@ -71,7 +71,7 @@ const Component = ({ flag }) => { ); return renderActions; -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/flagging/components/list-flags-item-actions/component.spec.js b/app/javascript/components/flagging/components/list-flags-item-actions/component.spec.js new file mode 100644 index 0000000000..d8c3afbec6 --- /dev/null +++ b/app/javascript/components/flagging/components/list-flags-item-actions/component.spec.js @@ -0,0 +1,59 @@ +import { mountedComponent, screen, cleanup } from "test-utils"; +import { fromJS } from "immutable"; + +import ListFlagsItemActions from "./component"; + +describe("", () => { + const props = { + flag: { + id: 7, + record_id: "d6a6dbb4-e5e9-4720-a661-e181a12fd3a0", + record_type: "cases", + date: "2019-08-01", + message: "This is a flag 1", + flagged_by: "primero", + removed: false + } + }; + + const initialState = fromJS({ + user: { + username: "primero" + } + }); + + beforeEach(() => { + mountedComponent(, initialState); + }); + + it("should render the ListFlagsItem", () => { + expect(screen.getByText("flags.date")).toBeInTheDocument(); + }); + + it("should render the FormAction", () => { + expect(screen.getByText("flags.resolve_button")).toBeInTheDocument(); + }); + + it("should render the DateFlag", () => { + expect(screen.getByTestId("date")).toBeInTheDocument(); + }); + + describe("when user has NOT resolve_any_flag permission", () => { + const stateDiffentUser = fromJS({ + user: { + username: "primero_cp" + } + }); + + beforeEach(() => { + cleanup(); + mountedComponent(, stateDiffentUser); + }); + + it("should NOT render the ActionButton", () => { + const buttonElement = screen.queryByRole("button", { name: /resolve_button/i }); + + expect(buttonElement).not.toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/flagging/components/list-flags-item-actions/component.unit.test.js b/app/javascript/components/flagging/components/list-flags-item-actions/component.unit.test.js deleted file mode 100644 index ec6bb52604..0000000000 --- a/app/javascript/components/flagging/components/list-flags-item-actions/component.unit.test.js +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { Divider } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../../test"; -import { FormAction } from "../../../form"; -import ActionButton from "../../../action-button"; -import DateFlag from "../../../transitions/components/date-transitions-summary"; - -import ListFlagsItemActions from "./component"; - -describe("", () => { - let component; - - const props = { - flag: { - id: 7, - record_id: "d6a6dbb4-e5e9-4720-a661-e181a12fd3a0", - record_type: "cases", - date: "2019-08-01", - message: "This is a flag 1", - flagged_by: "primero", - removed: false - } - }; - - const initialState = fromJS({ - user: { - username: "primero" - } - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(ListFlagsItemActions, props, initialState)); - }); - - it("should render the ListFlagsItem", () => { - expect(component.find(ListFlagsItemActions)).to.have.lengthOf(1); - }); - - it("should render the Divider", () => { - expect(component.find(Divider)).to.have.lengthOf(1); - }); - - it("renders FormAction", () => { - expect(component.find(FormAction)).to.have.lengthOf(1); - }); - - it("should render the ActionButton", () => { - expect(component.find(ActionButton)).to.have.lengthOf(1); - }); - - it("should render the DateFlag", () => { - expect(component.find(DateFlag)).to.have.lengthOf(1); - }); - - it("renders component with valid props", () => { - const listFlagsItemProps = { - ...component.find(ListFlagsItemActions).props() - }; - - ["flag"].forEach(property => { - expect(listFlagsItemProps).to.have.property(property); - delete listFlagsItemProps[property]; - }); - expect(listFlagsItemProps).to.be.empty; - }); - - describe("when current user and flagged_by are diffent", () => { - context("when user has resolve_any_flag permission", () => { - const stateDiffentUser = fromJS({ - user: { - username: "primero_cp", - permissions: { - cases: ["resolve_any_flag"] - } - } - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(ListFlagsItemActions, props, stateDiffentUser)); - }); - - it("should render the ActionButton", () => { - expect(component.find(ActionButton)).to.have.lengthOf(1); - }); - }); - - context("when user has NOT resolve_any_flag permission", () => { - const stateDiffentUser = fromJS({ - user: { - username: "primero_cp" - } - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(ListFlagsItemActions, props, stateDiffentUser)); - }); - - it("should render the ActionButton", () => { - expect(component.find(ActionButton)).to.have.lengthOf(0); - }); - }); - }); -}); diff --git a/app/javascript/components/flagging/components/list-flags-item/component.jsx b/app/javascript/components/flagging/components/list-flags-item/component.jsx index 3ad780eaec..7ddcad084f 100644 --- a/app/javascript/components/flagging/components/list-flags-item/component.jsx +++ b/app/javascript/components/flagging/components/list-flags-item/component.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { ListItem, ListItemText, Divider } from "@material-ui/core"; -import FlagIcon from "@material-ui/icons/Flag"; +import { ListItem, ListItemText, Divider } from "@mui/material"; +import FlagIcon from "@mui/icons-material/Flag"; import { UserArrowIcon } from "../../../../images/primero-icons"; import css from "../styles.css"; @@ -10,7 +10,7 @@ import ListFlagsItemActions from "../list-flags-item-actions"; import { NAME } from "./constants"; -const Component = ({ flag }) => { +function Component({ flag }) { const itemClass = flag?.removed ? css.itemResolved : css.item; if (!flag) { @@ -39,7 +39,7 @@ const Component = ({ flag }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/flagging/components/list-flags-item/component.spec.js b/app/javascript/components/flagging/components/list-flags-item/component.spec.js new file mode 100644 index 0000000000..07f7f6bdfd --- /dev/null +++ b/app/javascript/components/flagging/components/list-flags-item/component.spec.js @@ -0,0 +1,44 @@ +import { mountedComponent, screen } from "test-utils"; +import { fromJS } from "immutable"; + +import ListFlagsItem from "./component"; + +describe("", () => { + const props = { + flag: { + id: 7, + record_id: "d6a6dbb4-e5e9-4720-a661-e181a12fd3a0", + record_type: "cases", + date: "2019-08-01", + message: "This is a flag 1", + flagged_by: "primero", + removed: false + } + }; + + const initialState = fromJS({ + user: { + username: "primero" + } + }); + + beforeEach(() => { + mountedComponent(, initialState); + }); + + it("should render the ListFlagsItem", () => { + expect(screen.getByText("flags.date")).toBeInTheDocument(); + }); + + it("should render the DateFlag", () => { + expect(screen.getByTestId("date")).toBeInTheDocument(); + }); + + it("should render the ListItemText", () => { + expect(screen.getByText("This is a flag 1")).toBeInTheDocument(); + }); + + it("should render the ListFlagsItemActions", () => { + expect(screen.getByText("flags.resolve_button")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/flagging/components/list-flags-item/component.unit.test.js b/app/javascript/components/flagging/components/list-flags-item/component.unit.test.js deleted file mode 100644 index e8b880b17d..0000000000 --- a/app/javascript/components/flagging/components/list-flags-item/component.unit.test.js +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { ListItem, ListItemText, Divider } from "@material-ui/core"; -import FlagIcon from "@material-ui/icons/Flag"; - -import { setupMountedComponent } from "../../../../test"; -import { UserArrowIcon } from "../../../../images/primero-icons"; -import { FormAction } from "../../../form"; -import ActionButton from "../../../action-button"; - -import ListFlagsItem from "./component"; - -describe("", () => { - let component; - - const props = { - flag: { - id: 7, - record_id: "d6a6dbb4-e5e9-4720-a661-e181a12fd3a0", - record_type: "cases", - date: "2019-08-01", - message: "This is a flag 1", - flagged_by: "primero", - removed: false - }, - handleDelete: () => {} - }; - - const initialState = fromJS({ - user: { - username: "primero" - } - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(ListFlagsItem, props, initialState)); - }); - - it("should render the ListFlagsItem", () => { - expect(component.find(ListFlagsItem)).to.have.lengthOf(1); - }); - - it("should render the ListItem", () => { - expect(component.find(ListItem)).to.have.lengthOf(1); - }); - - it("should render the ListItemText", () => { - expect(component.find(ListItemText)).to.have.lengthOf(1); - }); - it("should render the FlagIcon", () => { - expect(component.find(FlagIcon)).to.have.lengthOf(1); - }); - - it("should render the UserArrowIcon", () => { - expect(component.find(UserArrowIcon)).to.have.lengthOf(1); - }); - - it("should render the Divider", () => { - expect(component.find(Divider)).to.have.lengthOf(2); - }); - - it("should render the ActionButton", () => { - expect(component.find(ActionButton)).to.have.lengthOf(1); - }); - - it("renders FormAction", () => { - expect(component.find(FormAction)).to.have.lengthOf(1); - }); - - it("renders component with valid props", () => { - const listFlagsItemProps = { ...component.find(ListFlagsItem).props() }; - - ["flag", "handleDelete"].forEach(property => { - expect(listFlagsItemProps).to.have.property(property); - delete listFlagsItemProps[property]; - }); - expect(listFlagsItemProps).to.be.empty; - }); -}); diff --git a/app/javascript/components/flagging/components/list-flags/component.jsx b/app/javascript/components/flagging/components/list-flags/component.jsx index 51d5bc90b4..d243d648b0 100644 --- a/app/javascript/components/flagging/components/list-flags/component.jsx +++ b/app/javascript/components/flagging/components/list-flags/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { List } from "@material-ui/core"; -import FlagIcon from "@material-ui/icons/Flag"; +import { List } from "@mui/material"; +import FlagIcon from "@mui/icons-material/Flag"; import PropTypes from "prop-types"; import { useMemoizedSelector } from "../../../../libs"; @@ -12,7 +12,7 @@ import css from "../styles.css"; import { NAME } from "./constants"; -const Component = ({ recordType, record }) => { +function Component({ recordType, record }) { const i18n = useI18n(); const flagsActived = useMemoizedSelector(state => getActiveFlags(state, record, recordType)); @@ -54,7 +54,7 @@ const Component = ({ recordType, record }) => { )} ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/flagging/components/list-flags/component.spec.js b/app/javascript/components/flagging/components/list-flags/component.spec.js new file mode 100644 index 0000000000..bf4a97cca0 --- /dev/null +++ b/app/javascript/components/flagging/components/list-flags/component.spec.js @@ -0,0 +1,46 @@ +import { mountedComponent, screen } from "test-utils"; +import { fromJS } from "immutable"; + +import { FlagRecord } from "../../records"; + +import ListFlags from "./component"; + +describe("", () => { + const props = { + recordType: "cases", + record: "230590" + }; + + const initialState = fromJS({ + records: { + flags: { + data: [ + FlagRecord({ + id: 7, + record_id: "230590", + record_type: "cases", + date: "2019-08-01", + message: "This is a flag 1", + flagged_by: "primero", + removed: true + }) + ] + } + } + }); + + it("renders Form", () => { + mountedComponent(, initialState); + expect(screen.getByText("This is a flag 1")).toBeInTheDocument(); + }); + + it("should render the FlagForm", () => { + mountedComponent(, initialState); + expect(screen.getByRole("listitem")).toBeInTheDocument(); + }); + + it("should render the FlagForm", () => { + mountedComponent(, initialState); + expect(screen.getByText("flags.resolved", { selector: "h3" })).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/flagging/components/list-flags/component.unit.test.js b/app/javascript/components/flagging/components/list-flags/component.unit.test.js deleted file mode 100644 index 62b7a6dee6..0000000000 --- a/app/javascript/components/flagging/components/list-flags/component.unit.test.js +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { List } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../../test"; -import ListFlagsItem from "../list-flags-item"; -import { FlagRecord } from "../../records"; - -import ListFlags from "./component"; - -describe("", () => { - let component; - - const props = { - recordType: "cases", - record: "230590" - }; - - const initialState = fromJS({ - records: { - flags: { - data: [ - FlagRecord({ - id: 7, - record_id: "230590", - record_type: "cases", - date: "2019-08-01", - message: "This is a flag 1", - flagged_by: "primero", - removed: false - }) - ] - } - } - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(ListFlags, props, initialState)); - }); - - it("should render the ListFlags", () => { - expect(component.find(ListFlags)).to.have.lengthOf(1); - }); - - it("renders component with valid props", () => { - const listFlagsProps = { ...component.find(ListFlags).props() }; - - ["record", "recordType"].forEach(property => { - expect(listFlagsProps).to.have.property(property); - delete listFlagsProps[property]; - }); - expect(listFlagsProps).to.be.empty; - }); - - it("should render List", () => { - expect(component.find(List)).to.have.lengthOf(1); - }); - - it("renders ListFlagsItem", () => { - expect(component.find(ListFlagsItem)).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/flagging/components/unflag/component.jsx b/app/javascript/components/flagging/components/unflag/component.jsx index e744df480b..c5774c39b7 100644 --- a/app/javascript/components/flagging/components/unflag/component.jsx +++ b/app/javascript/components/flagging/components/unflag/component.jsx @@ -17,7 +17,7 @@ const validationSchema = object().shape({ unflag_message: string().required() }); -const Component = ({ flag }) => { +function Component({ flag }) { const i18n = useI18n(); const dispatch = useDispatch(); const { dialogOpen, setDialog, setDialogPending, dialogPending } = useDialog(UNFLAG_DIALOG); @@ -76,7 +76,7 @@ const Component = ({ flag }) => { /> ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/flagging/components/unflag/component.spec.js b/app/javascript/components/flagging/components/unflag/component.spec.js new file mode 100644 index 0000000000..7fcb2aa202 --- /dev/null +++ b/app/javascript/components/flagging/components/unflag/component.spec.js @@ -0,0 +1,36 @@ +import { mountedComponent, screen } from "test-utils"; +import { fromJS } from "immutable"; + +import Unflag from "./component"; +import { UNFLAG_DIALOG } from "./constants"; + +describe("", () => { + const props = { + flag: { + id: 7, + record_id: "d6a6dbb4-e5e9-4720-a661-e181a12fd3a0", + record_type: "cases", + date: "2019-08-01", + message: "This is a flag 1", + flagged_by: "primero", + removed: false + } + }; + + const initialState = fromJS({ + ui: { dialogs: { dialog: UNFLAG_DIALOG, open: true } } + }); + + beforeEach(() => { + mountedComponent(, initialState); + }); + + it("should render the Unflag", () => { + expect(screen.getAllByText("flags.resolve_reason")).toHaveLength(2); + }); + + it("renders ActionButton", () => { + expect(screen.getByText("cancel")).toBeInTheDocument(); + expect(screen.getByText("flags.resolve_button")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/flagging/components/unflag/component.unit.test.js b/app/javascript/components/flagging/components/unflag/component.unit.test.js deleted file mode 100644 index cc430b20dc..0000000000 --- a/app/javascript/components/flagging/components/unflag/component.unit.test.js +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../../test"; -import Form, { FormSection, FormSectionField } from "../../../form"; -import ActionButton from "../../../action-button"; - -import Unflag from "./component"; -import { UNFLAG_DIALOG } from "./constants"; - -describe("", () => { - let component; - - const props = { - flag: { - id: 7, - record_id: "d6a6dbb4-e5e9-4720-a661-e181a12fd3a0", - record_type: "cases", - date: "2019-08-01", - message: "This is a flag 1", - flagged_by: "primero", - removed: false - } - }; - - const initialState = fromJS({ - ui: { dialogs: { dialog: UNFLAG_DIALOG, open: true } } - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(Unflag, props, initialState)); - }); - - it("should render the Unflag", () => { - expect(component.find(Unflag)).to.have.lengthOf(1); - }); - - it("renders Form", () => { - expect(component.find(Form)).to.have.lengthOf(1); - }); - - it("renders FormSectionRecord", () => { - expect(component.find(FormSection)).to.have.lengthOf(1); - }); - - it("renders FieldRecord", () => { - expect(component.find(FormSectionField)).to.have.lengthOf(1); - }); - - it("renders ActionButton", () => { - expect(component.find(ActionButton)).to.have.lengthOf(2); - }); - - it("renders component with valid props", () => { - const flagFormProps = { ...component.find(Unflag).props() }; - - ["flag"].forEach(property => { - expect(flagFormProps).to.have.property(property); - delete flagFormProps[property]; - }); - expect(flagFormProps).to.be.empty; - }); -}); diff --git a/app/javascript/components/form-filters/component.jsx b/app/javascript/components/form-filters/component.jsx index fab8ca2e0d..2a15f5cdcd 100644 --- a/app/javascript/components/form-filters/component.jsx +++ b/app/javascript/components/form-filters/component.jsx @@ -8,7 +8,7 @@ import useFormFilters from "./use-form-filters"; import { getFilters } from "./utils"; import { NAME } from "./constants"; -const Component = ({ formMode, primeroModule, recordType, selectedForm, showDrawer }) => { +function Component({ formMode, primeroModule, recordType, selectedForm, showDrawer }) { const Filters = getFilters(selectedForm); const { clearFilters } = useFormFilters(selectedForm); @@ -30,7 +30,7 @@ const Component = ({ formMode, primeroModule, recordType, selectedForm, showDraw selectedForm={selectedForm} /> ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/form-filters/components/change-log/component.jsx b/app/javascript/components/form-filters/components/change-log/component.jsx index d2b53a2fe4..9aabce582c 100644 --- a/app/javascript/components/form-filters/components/change-log/component.jsx +++ b/app/javascript/components/form-filters/components/change-log/component.jsx @@ -13,7 +13,7 @@ import useFormFilters from "../../use-form-filters"; import { FILTER_NAMES, NAME } from "./constants"; import { getFilters } from "./utils"; -const Component = ({ selectedForm, formMode, primeroModule, recordType, showDrawer }) => { +function Component({ selectedForm, formMode, primeroModule, recordType, showDrawer }) { const i18n = useI18n(); const { setFormFilters, selectedFilters } = useFormFilters(selectedForm); @@ -46,7 +46,7 @@ const Component = ({ selectedForm, formMode, primeroModule, recordType, showDraw /> ) ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/form-filters/components/filters-form/component.jsx b/app/javascript/components/form-filters/components/filters-form/component.jsx index 9230bd184e..4618ffe804 100644 --- a/app/javascript/components/form-filters/components/filters-form/component.jsx +++ b/app/javascript/components/form-filters/components/filters-form/component.jsx @@ -3,8 +3,8 @@ import { useEffect } from "react"; import PropTypes from "prop-types"; import { useForm, FormProvider } from "react-hook-form"; -import { IconButton } from "@material-ui/core"; -import FilterListIcon from "@material-ui/icons/FilterList"; +import { IconButton } from "@mui/material"; +import FilterListIcon from "@mui/icons-material/FilterList"; import { useDrawer } from "../../../drawer"; import { filterType } from "../../../index-filters/utils"; @@ -16,15 +16,16 @@ import { useMemoizedSelector, useThemeHelper } from "../../../../libs"; import { FILTERS_DRAWER, NAME } from "./constants"; import css from "./styles.css"; -const Component = ({ - closeDrawerOnSubmit, +function Component({ + closeDrawerOnSubmit = false, filters, onSubmit, clearFields, - defaultFilters, - initialFilters, - showDrawer -}) => { + defaultFilters = {}, + initialFilters = {}, + showDrawer = false, + noMargin = false +}) { const methods = useForm(); const { mobileDisplay } = useThemeHelper(); @@ -34,7 +35,7 @@ const Component = ({ const { drawerOpen, toggleDrawer, setDrawer } = useDrawer(FILTERS_DRAWER); const showFilterIcon = mobileDisplay && showDrawer && ( - + ); @@ -84,8 +85,13 @@ const Component = ({ return (
{showFilterIcon} - -
+ +
@@ -96,18 +102,10 @@ const Component = ({
); -}; +} Component.displayName = NAME; -Component.defaultProps = { - closeDrawerOnSubmit: false, - defaultFilters: {}, - initialFilters: {}, - mobileDisplay: false, - showDrawer: false -}; - Component.propTypes = { clearFields: PropTypes.array.isRequired, closeDrawerOnSubmit: PropTypes.bool, @@ -115,6 +113,7 @@ Component.propTypes = { filters: PropTypes.array.isRequired, initialFilters: PropTypes.object, mobileDisplay: PropTypes.bool, + noMargin: PropTypes.bool, onSubmit: PropTypes.func.isRequired, showDrawer: PropTypes.bool }; diff --git a/app/javascript/components/form-filters/components/filters-form/component.spec.js b/app/javascript/components/form-filters/components/filters-form/component.spec.js new file mode 100644 index 0000000000..d6c2c38355 --- /dev/null +++ b/app/javascript/components/form-filters/components/filters-form/component.spec.js @@ -0,0 +1,73 @@ +import { mountedComponent, screen } from "test-utils"; + +import { FILTER_TYPES } from "../../../index-filters"; + +import AdminFilters from "./component"; + +describe(" - pages/admin/components/filters/component", () => { + const props = { + filters: [ + { + name: "filter.test", + field_name: "test", + type: FILTER_TYPES.MULTI_TOGGLE, + option_strings_source: null, + options: { + en: [{ id: "test", display_name: "Test" }] + } + } + ], + onSubmit: () => {}, + clearFields: [], + defaultFilters: {} + }; + + beforeEach(() => { + mountedComponent(, {}); + }); + + it("should render component", () => { + expect(screen.getByRole("form")).toBeInTheDocument(); + }); + + describe("when the filters include a non-permitted one to the user", () => { + const propsWithFiltersNotPermitted = { + filters: [ + { + name: "cases.filter_by.enabled_disabled", + field_name: "disabled", + type: FILTER_TYPES.MULTI_SELECT, + option_strings_source: null, + options: { + en: [ + { id: "false", display_name: "Enabled" }, + { id: "true", display_name: "Disabled" } + ] + } + }, + { + name: "filter.agency", + field_name: "Agency", + type: FILTER_TYPES.MULTI_SELECT, + permitted_filter: false, + options: { + en: [{ id: "test", display_name: "Test" }] + } + } + ], + onSubmit: () => {}, + clearFields: [], + defaultFilters: {} + }; + + beforeEach(() => { + mountedComponent(, {}); + }); + + it("should render only one component", () => { + const selectFilterComponents = screen.getAllByTestId("select-filter"); + + expect(selectFilterComponents).toHaveLength(1); + }); + }); +}); diff --git a/app/javascript/components/form-filters/components/filters-form/component.unit.test.js b/app/javascript/components/form-filters/components/filters-form/component.unit.test.js deleted file mode 100644 index f06c2bdf4c..0000000000 --- a/app/javascript/components/form-filters/components/filters-form/component.unit.test.js +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { FormProvider } from "react-hook-form"; - -import { setupMountedComponent } from "../../../../test"; -import { ACTIONS } from "../../../permissions"; -import Actions from "../../../index-filters/components/actions"; -import { FILTER_TYPES } from "../../../index-filters"; -import { SelectFilter } from "../../../index-filters/components/filter-types"; - -import AdminFilters from "./component"; - -describe(" - pages/admin/components/filters/component", () => { - let component; - - const props = { - filters: [ - { - name: "filter.test", - field_name: "test", - type: FILTER_TYPES.MULTI_TOGGLE, - option_strings_source: null, - options: { - en: [{ id: "test", display_name: "Test" }] - } - } - ], - onSubmit: () => {}, - clearFields: [], - defaultFilters: {} - }; - - beforeEach(() => { - const state = fromJS({ - user: { - user_name: "test", - permissions: { - agencies: [ACTIONS.MANAGE] - } - } - }); - - ({ component } = setupMountedComponent(AdminFilters, props, state)); - }); - - it("should render component", () => { - expect(component.find(FormProvider)).to.have.lengthOf(1); - }); - - it("should render component", () => { - expect(component.find(Actions)).to.have.lengthOf(1); - }); - - it("should have valid props", () => { - const adminFiltersProps = { ...component.find(AdminFilters).props() }; - - expect(component.find(adminFiltersProps)).to.have.lengthOf(1); - [ - "clearFields", - "closeDrawerOnSubmit", - "defaultFilters", - "filters", - "initialFilters", - "mobileDisplay", - "onSubmit", - "showDrawer" - ].forEach(property => { - expect(adminFiltersProps).to.have.property(property); - delete adminFiltersProps[property]; - }); - expect(adminFiltersProps).to.be.empty; - }); - - context("when the filters include a non-permitted one to the user", () => { - const propsWithFiltersNotPermitted = { - filters: [ - { - name: "cases.filter_by.enabled_disabled", - field_name: "disabled", - type: FILTER_TYPES.MULTI_SELECT, - option_strings_source: null, - options: { - en: [ - { id: "false", display_name: "Enabled" }, - { id: "true", display_name: "Disabled" } - ] - } - }, - { - name: "filter.agency", - field_name: "Agency", - type: FILTER_TYPES.MULTI_SELECT, - permitted_filter: false, - options: { - en: [{ id: "test", display_name: "Test" }] - } - } - ], - onSubmit: () => {}, - clearFields: [], - defaultFilters: {} - }; - - beforeEach(() => { - const state = fromJS({ - user: { - user_name: "test", - permissions: { - users: [ACTIONS.MANAGE, ACTIONS.AGENCY_READ] - } - } - }); - - ({ component } = setupMountedComponent(AdminFilters, propsWithFiltersNotPermitted, state)); - }); - - it("should render only one component", () => { - expect(component.find(FormProvider).find(SelectFilter)).to.have.lengthOf(1); - }); - }); -}); diff --git a/app/javascript/components/form-filters/components/filters-form/styles.css b/app/javascript/components/form-filters/components/filters-form/styles.css index 661ae3e049..99138bcb99 100644 --- a/app/javascript/components/form-filters/components/filters-form/styles.css +++ b/app/javascript/components/form-filters/components/filters-form/styles.css @@ -1,11 +1,10 @@ /* Copyright (c) 2014 - 2023 UNICEF. All rights reserved. */ .recordFormFilters { - max-width: 300px; - width: 100%; + width: auto; } -@media (max-width:959.95px) { +@media (max-width:900px) { .recordFormFilters { text-align: center; flex: 0 1; diff --git a/app/javascript/components/form/component.jsx b/app/javascript/components/form/component.jsx index 381b299c75..ba7caac1b5 100644 --- a/app/javascript/components/form/component.jsx +++ b/app/javascript/components/form/component.jsx @@ -16,27 +16,27 @@ import { whichFormMode } from "./utils/which-mode"; import { submitHandler } from "./utils/form-submission"; import notPropagatedOnSubmit from "./utils/not-propagated-on-submit"; -const Component = ({ +function Component({ formID, formSections, - formOptions, + formOptions = {}, formMode, onSubmit, validations, - mode, - initialValues, - useCancelPrompt, - formErrors, - submitAllFields, + mode = "new", + initialValues = {}, + useCancelPrompt = false, + formErrors = fromJS([]), + submitAllFields = false, useFormMode, renderBottom, showTitle = true, - submitAlways, + submitAlways = false, formClassName, - registerFields, + registerFields = [], resetAfterSubmit = false, errorMessage = null -}) => { +}) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -126,21 +126,10 @@ const Component = ({ {renderBottom && renderBottom(formMethods)} ); -}; +} Component.displayName = "Form"; -Component.defaultProps = { - formErrors: fromJS([]), - formOptions: {}, - initialValues: {}, - mode: "new", - registerFields: [], - submitAllFields: false, - submitAlways: false, - useCancelPrompt: false -}; - Component.propTypes = { errorMessage: PropTypes.string, formClassName: PropTypes.string, diff --git a/app/javascript/components/form/component.spec.js b/app/javascript/components/form/component.spec.js new file mode 100644 index 0000000000..1e481472c3 --- /dev/null +++ b/app/javascript/components/form/component.spec.js @@ -0,0 +1,50 @@ +import { screen, mountedComponent, spy } from "test-utils"; +import { fromJS } from "immutable"; +import { object, string } from "yup"; + +import Form from "./component"; +import { FORM_MODE_DIALOG } from "./constants"; +import { FormSectionRecord, FieldRecord } from "./records"; + +describe("", () => { + const formSubmit = spy(); + const FORM_ID = "test-form"; + + const formSections = fromJS([ + FormSectionRecord({ + unique_id: "notes_section", + fields: [ + FieldRecord({ + display_name: "Test Field 1", + name: "test_field_1", + type: "text_field" + }), + FieldRecord({ + display_name: "Test Field 2", + name: "test_field_2", + type: "textarea" + }) + ] + }) + ]); + + const props = { + formSections, + mode: FORM_MODE_DIALOG, + onSubmit: formSubmit, + validations: object().shape({ + test_field_1: string().required() + }), + formID: FORM_ID + }; + + it("renders form based on formSection props", () => { + mountedComponent(); + expect(screen.getAllByText("Test Field 1")).toBeTruthy(); + expect(screen.getAllByText("Test Field 2")).toBeTruthy(); + }); + + it.todo("should set form with initial values"); + + it.todo("should not submit form when invalid"); +}); diff --git a/app/javascript/components/form/component.unit.test.js b/app/javascript/components/form/component.unit.test.js deleted file mode 100644 index a3ba2a3f64..0000000000 --- a/app/javascript/components/form/component.unit.test.js +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import * as yup from "yup"; - -import { setupMountedComponent, spy } from "../../test"; - -import Form from "./component"; -import { FORM_MODE_DIALOG } from "./constants"; -import { FormSectionRecord, FieldRecord } from "./records"; - -import { FormSection } from "."; - -describe("", () => { - const formSubmit = spy(); - const FORM_ID = "test-form"; - - const formSections = fromJS([ - FormSectionRecord({ - unique_id: "notes_section", - fields: [ - FieldRecord({ - display_name: "Test Field 1", - name: "test_field_1", - type: "text_field" - }), - FieldRecord({ - display_name: "Test Field 2", - name: "test_field_2", - type: "textarea" - }) - ] - }) - ]); - - const props = { - formSections, - mode: FORM_MODE_DIALOG, - onSubmit: formSubmit, - validations: yup.object().shape({ - test_field_1: yup.string().required() - }), - formID: FORM_ID - }; - - it("renders form based on formSection props", () => { - const { component } = setupMountedComponent(Form, props); - - expect(component.exists("input[name='test_field_1']")).to.be.true; - expect(component.exists("textarea[name='test_field_2']")).to.be.true; - }); - - it("should set form with initial values", () => { - const { component } = setupMountedComponent(Form, { - ...props, - initialValues: { test_field_2: "Hello" } - }); - - expect(component.find(FormSection).first().props().formMethods.getValues().test_field_2).to.equal("Hello"); - }); - - it("should not submit form when invalid", async () => { - const { component } = setupMountedComponent(Form, props); - - await component.find("form").simulate("submit"); - - expect(formSubmit).not.to.have.been.called; - }); - - xit("should submit form when valid", async () => { - const { component } = setupMountedComponent(Form, { - ...props, - initialValues: { test_field_1: "Hello" } - }); - - await component.find('input[name="test_field_1"]').simulate("change", { - target: { name: "test_field_1", value: "value-change" } - }); - - await component.find("form").simulate("submit"); - - expect(formSubmit).to.have.been.called; - }); -}); diff --git a/app/javascript/components/form/components/actions-menu/container.jsx b/app/javascript/components/form/components/actions-menu/container.jsx index cbe2249297..0789e1f3c8 100644 --- a/app/javascript/components/form/components/actions-menu/container.jsx +++ b/app/javascript/components/form/components/actions-menu/container.jsx @@ -2,15 +2,15 @@ import { useState } from "react"; import PropTypes from "prop-types"; -import { Menu, MenuItem } from "@material-ui/core"; -import MoreVertIcon from "@material-ui/icons/MoreVert"; +import { Menu, MenuItem } from "@mui/material"; +import MoreVertIcon from "@mui/icons-material/MoreVert"; import ActionButton from "../../../action-button"; import { ACTION_BUTTON_TYPES } from "../../../action-button/constants"; import { NAME } from "./constants"; -const Container = ({ actionItems }) => { +function Container({ actionItems = [] }) { const [anchorEl, setAnchorEl] = useState(null); const handleClick = event => { @@ -59,11 +59,7 @@ const Container = ({ actionItems }) => { ); -}; - -Container.defaultProps = { - actionItems: [] -}; +} Container.propTypes = { actionItems: PropTypes.array diff --git a/app/javascript/components/form/components/actions-menu/container.spec.js b/app/javascript/components/form/components/actions-menu/container.spec.js new file mode 100644 index 0000000000..d2b1dd9c79 --- /dev/null +++ b/app/javascript/components/form/components/actions-menu/container.spec.js @@ -0,0 +1,22 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { screen, mountedComponent, fireEvent } from "test-utils"; + +import ActionsMenu from "./container"; + +describe(" - components/", () => { + it("renders ActionMenu with where conditions are true or not defined", () => { + mountedComponent( + + ); + + fireEvent.click(screen.getByRole("button")); + expect(screen.getAllByRole("menuitem")).toHaveLength(2); + }); +}); diff --git a/app/javascript/components/form/components/actions-menu/container.unit.test.js b/app/javascript/components/form/components/actions-menu/container.unit.test.js deleted file mode 100644 index e99d3337a8..0000000000 --- a/app/javascript/components/form/components/actions-menu/container.unit.test.js +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { MenuItem } from "@material-ui/core"; - -import { setupMockFormComponent } from "../../../../test"; - -import ActionsMenu from "./container"; - -describe(" - components/", () => { - const { component } = setupMockFormComponent(ActionsMenu, { - props: { - actionItems: [ - { name: "test_no_condition" }, - { name: "test_condition_true", condition: true }, - { name: "test_condition_false", condition: false } - ] - } - }); - - it("renders ActionMenu with where conditions are true or not defined", () => { - const menuItem = component.find(MenuItem); - - expect(menuItem).to.have.lengthOf(2); - }); -}); diff --git a/app/javascript/components/form/components/cancel-prompt.jsx b/app/javascript/components/form/components/cancel-prompt.jsx index 3181e3737c..cb624cf829 100644 --- a/app/javascript/components/form/components/cancel-prompt.jsx +++ b/app/javascript/components/form/components/cancel-prompt.jsx @@ -6,7 +6,7 @@ import NavigationPrompt from "react-router-navigation-prompt"; import ActionDialog from "../../action-dialog"; import { useI18n } from "../../i18n"; -const CancelPrompt = ({ useCancelPrompt, dirty, isSubmitted, isShow }) => { +function CancelPrompt({ useCancelPrompt = false, dirty = false, isSubmitted = false, isShow = false }) { const i18n = useI18n(); const promptCancelWhen = dirty && !isSubmitted && !isShow; @@ -29,17 +29,10 @@ const CancelPrompt = ({ useCancelPrompt, dirty, isSubmitted, isShow }) => { } return null; -}; +} CancelPrompt.displayName = "CancelPrompt"; -CancelPrompt.defaultProps = { - dirty: false, - isShow: false, - isSubmitted: false, - useCancelPrompt: false -}; - CancelPrompt.propTypes = { dirty: PropTypes.bool, isShow: PropTypes.bool, diff --git a/app/javascript/components/form/components/draggable-option/component.jsx b/app/javascript/components/form/components/draggable-option/component.jsx index 846dacfe7a..194ceeaa5b 100644 --- a/app/javascript/components/form/components/draggable-option/component.jsx +++ b/app/javascript/components/form/components/draggable-option/component.jsx @@ -1,13 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; import { Draggable } from "react-beautiful-dnd"; import { Controller, useWatch } from "react-hook-form"; -import { makeStyles, Radio } from "@material-ui/core"; +import { Radio } from "@mui/material"; import get from "lodash/get"; -import DeleteIcon from "@material-ui/icons/Delete"; -import IconButton from "@material-ui/core/IconButton"; +import DeleteIcon from "@mui/icons-material/Delete"; +import IconButton from "@mui/material/IconButton"; import TextInput from "../../fields/text-input"; import SwitchInput from "../../fields/switch-input"; @@ -15,9 +15,10 @@ import css from "../../fields/styles.css"; import DragIndicator from "../../../pages/admin/forms-list/components/drag-indicator"; import { generateIdFromDisplayText } from "../../utils/handle-options"; +import textInputCss from "./styles.css"; import { NAME } from "./constants"; -const Component = ({ +function Component({ defaultOptionId, index, name, @@ -25,11 +26,11 @@ const Component = ({ onRemoveClick, formMethods, formMode, - showDefaultAction, - showDeleteAction, - showDisableOption, - optionFieldName -}) => { + showDefaultAction = true, + showDeleteAction = true, + showDisableOption = true, + optionFieldName = "option_strings_text" +}) { const { errors, setValue, @@ -50,17 +51,6 @@ const Component = ({ const error = errors ? get(errors, displayTextFieldName) : undefined; - const classes = makeStyles({ - disabled: { - "&&&:before": { - borderBottomStyle: "solid" - }, - "&&:after": { - borderBottomStyle: "solid" - } - } - })(); - const handleChange = event => { const { value } = event.currentTarget; const newOptionId = generateIdFromDisplayText(value); @@ -87,12 +77,12 @@ const Component = ({ const handleRemoveClick = () => onRemoveClick(index); const renderRemoveButton = formMode.get("isNew") && showDeleteAction && ( - + ); - const classesDragIndicator = clsx([css.fieldColumn, css.dragIndicatorColumn]); - const classesTextInput = clsx([css.fieldColumn, css.fieldInput]); + const classesDragIndicator = cx([css.fieldColumn, css.dragIndicatorColumn]); + const classesTextInput = cx([css.fieldColumn, css.fieldInput]); const handleOnBlur = event => handleChange(event, index); return ( @@ -114,7 +104,7 @@ const Component = ({ // eslint-disable-next-line camelcase defaultValue: option?.display_text?.en, InputProps: { - classes, + classes: { disabled: textInputCss.disabled }, onBlur: handleOnBlur } }} @@ -150,15 +140,7 @@ const Component = ({ )} ); -}; - -Component.defaultProps = { - disabled: false, - optionFieldName: "option_strings_text", - showDefaultAction: true, - showDeleteAction: true, - showDisableOption: true -}; +} Component.propTypes = { defaultOptionId: PropTypes.string, diff --git a/app/javascript/components/form/components/draggable-option/component.spec.js b/app/javascript/components/form/components/draggable-option/component.spec.js new file mode 100644 index 0000000000..ca44e3b546 --- /dev/null +++ b/app/javascript/components/form/components/draggable-option/component.spec.js @@ -0,0 +1,38 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +import { screen, mountedFormComponent } from "test-utils"; +import { DragDropContext, Droppable } from "react-beautiful-dnd"; + +import DraggableOption from "./component"; + +describe(" - components/", () => { + beforeEach(() => { + // eslint-disable-next-line react/display-name + function Component(props) { + return ( + + + {() => ( + + )} + + + ); + } + + mountedFormComponent(); + }); + + it("renders a TextInput for display_text", () => { + expect(document.querySelector("input[name='field_1.option_strings_text[0].display_text.en'")).toBeInTheDocument(); + }); + + it("renders a SwitchInput", () => { + expect(screen.getByTestId("switch-input")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/form/components/draggable-option/component.unit.test.js b/app/javascript/components/form/components/draggable-option/component.unit.test.js deleted file mode 100644 index 1f3ae2d0e5..0000000000 --- a/app/javascript/components/form/components/draggable-option/component.unit.test.js +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { DragDropContext, Droppable } from "react-beautiful-dnd"; -import { Radio } from "@material-ui/core"; - -import { setupMockFormComponent } from "../../../../test"; -import TextInput from "../../fields/text-input"; -import SwitchInput from "../../fields/switch-input"; - -import DraggableOption from "./component"; - -describe(" - components/", () => { - let component; - const props = { - mode: "edit" - }; - - beforeEach(() => { - ({ component } = setupMockFormComponent( - ({ formMethods, formMode }) => ( - - - {() => ( - - )} - - - ), - { props } - )); - }); - - it("renders a TextInput for display_text", () => { - expect(component.find(TextInput)).to.have.lengthOf(1); - }); - - it("renders a checked RadioButton", () => { - const selectedValueRadio = component.find(Radio); - - expect(selectedValueRadio).to.have.lengthOf(1); - expect(selectedValueRadio.props().checked).to.be.true; - }); - - it("renders a SwitchInput", () => { - const selectedValueCheckbox = component.find(SwitchInput); - - expect(selectedValueCheckbox.props().commonInputProps.name).to.be.equal("field_1.option_strings_text[0].disabled"); - expect(selectedValueCheckbox).to.be.exist; - }); -}); diff --git a/app/javascript/components/form/components/draggable-option/styles.css b/app/javascript/components/form/components/draggable-option/styles.css index e69de29bb2..9a16227db2 100644 --- a/app/javascript/components/form/components/draggable-option/styles.css +++ b/app/javascript/components/form/components/draggable-option/styles.css @@ -0,0 +1,9 @@ +.disabled { + &&&:before { + border-bottom-style: solid; + } + + &&:after { + border-bottom-style: solid; + } +} \ No newline at end of file diff --git a/app/javascript/components/form/components/fields.jsx b/app/javascript/components/form/components/fields.jsx index ac1786abcd..4cd9e998ac 100644 --- a/app/javascript/components/form/components/fields.jsx +++ b/app/javascript/components/form/components/fields.jsx @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import clsx from "clsx"; +import { cx } from "@emotion/css"; import fieldKey from "../utils/field-key"; import formComponent from "../utils/form-component"; @@ -11,7 +11,7 @@ import FormSectionField from "./form-section-field"; const Fields = ({ fields, checkErrors, disableUnderline, formSection, css, formMethods, formMode }) => { const calculatedClasses = field => - clsx({ + cx({ [css.notEqual]: field.equalColumns === false, [css.row]: !field?.customRowStyle, [css.rowCustom]: field?.customRowStyle, @@ -25,7 +25,7 @@ const Fields = ({ fields, checkErrors, disableUnderline, formSection, css, formM const formUniqueId = formSection?.unique_id || field?.unique_id; return ( -
+
{ +function FormAction({ actionHandler, cancel, savingRecord = false, startIcon, text, disabled, options = {}, tooltip }) { return ( ); -}; +} FormAction.displayName = "FormAction"; -FormAction.defaultProps = { - options: {}, - savingRecord: false -}; - FormAction.propTypes = { actionHandler: PropTypes.func, cancel: PropTypes.bool, diff --git a/app/javascript/components/form/components/form-action.spec.js b/app/javascript/components/form/components/form-action.spec.js new file mode 100644 index 0000000000..5162e8dfe5 --- /dev/null +++ b/app/javascript/components/form/components/form-action.spec.js @@ -0,0 +1,17 @@ +import { screen, mountedFormComponent } from "test-utils"; + +import FormAction from "./form-action"; + +describe(" - components/", () => { + const buttonMessage = "Test save"; + const props = { + actionHandler: () => {}, + text: buttonMessage + }; + + it("renders a Fab component", () => { + mountedFormComponent(); + expect(screen.getByRole("button")).toBeInTheDocument(); + expect(screen.getByText(buttonMessage)).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/form/components/form-action.unit.test.js b/app/javascript/components/form/components/form-action.unit.test.js deleted file mode 100644 index d4b361b4bc..0000000000 --- a/app/javascript/components/form/components/form-action.unit.test.js +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { CircularProgress } from "@material-ui/core"; - -import { setupMockFormComponent } from "../../../test"; -import ActionButton from "../../action-button"; - -import FormAction from "./form-action"; - -describe(" - components/", () => { - const buttonMessage = "Test save"; - const props = { - actionHandler: () => {}, - text: buttonMessage - }; - - it("renders a Fab component", () => { - const { component } = setupMockFormComponent(FormAction, { props }); - const button = component.find(ActionButton); - - expect(button).to.have.lengthOf(1); - expect(button.text()).to.be.equals(buttonMessage); - }); - - it( - "renders a ActionButton with a CircularProgress component, " + - "when savingRecord it's true and it's not a cancel button", - () => { - const { component } = setupMockFormComponent(FormAction, { - props: { - ...props, - cancel: false, - savingRecord: true - } - }); - const button = component.find(ActionButton); - - expect(button).to.have.lengthOf(1); - expect(button.text()).to.be.equals(buttonMessage); - expect(component.find(CircularProgress)).to.have.lengthOf(1); - } - ); -}); diff --git a/app/javascript/components/form/components/form-section-actions.js b/app/javascript/components/form/components/form-section-actions.js index 8ecdcb5de8..967482c95b 100644 --- a/app/javascript/components/form/components/form-section-actions.js +++ b/app/javascript/components/form/components/form-section-actions.js @@ -4,7 +4,7 @@ import PropTypes from "prop-types"; import ActionButton from "../../action-button"; -const FormSectionActions = ({ actions, css }) => { +function FormSectionActions({ actions, css }) { if (!actions?.length) return null; return ( @@ -14,7 +14,7 @@ const FormSectionActions = ({ actions, css }) => { ))}
); -}; +} FormSectionActions.propTypes = { actions: PropTypes.array, diff --git a/app/javascript/components/form/components/form-section-field.jsx b/app/javascript/components/form/components/form-section-field.jsx index a216d284d5..305eff8bca 100644 --- a/app/javascript/components/form/components/form-section-field.jsx +++ b/app/javascript/components/form/components/form-section-field.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; import { ConditionalWrapper } from "../../../libs"; import useFormField from "../use-form-field"; @@ -10,7 +10,7 @@ import formComponent from "../utils/form-component"; import css from "./styles.css"; -const FormSectionField = ({ checkErrors, field, formMethods, formMode, disableUnderline }) => { +function FormSectionField({ checkErrors, field, formMethods, formMode, disableUnderline = false }) { const { errors } = formMethods; const { Field, @@ -24,7 +24,7 @@ const FormSectionField = ({ checkErrors, field, formMethods, formMode, disableUn optionSelector } = useFormField(field, { checkErrors, errors, formMode, disableUnderline }); - const classes = clsx(css.field, { + const classes = cx(css.field, { [css.readonly]: formMode.isShow }); @@ -49,18 +49,16 @@ const FormSectionField = ({ checkErrors, field, formMethods, formMode, disableUn return ( handleVisibility() || ( -
{renderField}
+
+ {renderField} +
) ); -}; +} FormSectionField.displayName = "FormSectionField"; -FormSectionField.defaultProps = { - disableUnderline: false -}; - FormSectionField.propTypes = { checkErrors: PropTypes.object, disableUnderline: PropTypes.bool, diff --git a/app/javascript/components/form/components/form-section-field.spec.js b/app/javascript/components/form/components/form-section-field.spec.js new file mode 100644 index 0000000000..6e189dd095 --- /dev/null +++ b/app/javascript/components/form/components/form-section-field.spec.js @@ -0,0 +1,72 @@ +import { screen, mountedFormComponent } from "test-utils"; +import { fromJS } from "immutable"; + +import { FieldRecord } from "../records"; +import { RADIO_FIELD, DIALOG_TRIGGER, DOCUMENT_FIELD } from "../constants"; + +import FormSectionField from "./form-section-field"; + +describe(" - components/", () => { + it("renders a text field", () => { + const field = FieldRecord({ name: "test_field", type: "text_field" }); + + mountedFormComponent(); + expect(document.querySelector("#test_field")).toBeInTheDocument(); + }); + + it("renders an error field", () => { + const field = FieldRecord({ name: "test_field", type: "error_field" }); + + // eslint-disable-next-line react/display-name + function Component(props) { + return ; + } + + mountedFormComponent(, { + errors: [ + { + name: "name", + message: "test-error" + } + ] + }); + expect(screen.getByText("test-error")).toBeInTheDocument(); + }); + + it("renders a radio button field", () => { + const field = FieldRecord({ + name: "radio_test_field", + id: "radio_test_field", + type: RADIO_FIELD, + option_strings_text: { + en: [ + { + id: "yes", + label: "Yes" + }, + { + id: "no", + label: "No" + } + ] + } + }); + + mountedFormComponent(); + expect(document.querySelector("#radio_test_field")).toBeInTheDocument(); + }); + + it("renders a buttons link", () => { + const field = FieldRecord({ name: "test_field", type: DIALOG_TRIGGER, display_name: { en: "Test Field" } }); + + mountedFormComponent(); + expect(screen.getByText("Test Field")).toBeInTheDocument(); + }); + + it("renders an attachement field", () => { + const field = FieldRecord({ name: "test_document_field", type: DOCUMENT_FIELD }); + + mountedFormComponent(); + expect(document.querySelector("#test_document_field")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/form/components/form-section-field.unit.test.js b/app/javascript/components/form/components/form-section-field.unit.test.js deleted file mode 100644 index eb8a04dd0b..0000000000 --- a/app/javascript/components/form/components/form-section-field.unit.test.js +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import Alert from "@material-ui/lab/Alert"; -import { fromJS } from "immutable"; - -import { setupMockFormComponent } from "../../../test"; -import { FieldRecord } from "../records"; -import { RADIO_FIELD, TOGGLE_FIELD, DIALOG_TRIGGER, DOCUMENT_FIELD } from "../constants"; - -import FormSectionField from "./form-section-field"; - -describe(" - components/", () => { - it("renders a text field", () => { - const field = FieldRecord({ name: "test_field", type: "text_field" }); - const { component } = setupMockFormComponent(FormSectionField, { props: { field } }); - - expect(component.exists("input[name='test_field']")).to.be.true; - }); - - it("renders a textarea field", () => { - const field = FieldRecord({ name: "test_field", type: "textarea" }); - const { component } = setupMockFormComponent(FormSectionField, { props: { field } }); - - expect(component.exists("textarea[name='test_field']")).to.be.true; - }); - - it("renders an error field", () => { - const field = FieldRecord({ name: "test_field", type: "error_field" }); - const { component } = setupMockFormComponent( - ({ formMethods }) => { - return ( - - ); - }, - { - errors: [ - { - name: "name", - message: "test" - } - ] - } - ); - - expect(component.find(Alert)).to.have.lengthOf(1); - }); - - it("does not render an error field", () => { - const field = FieldRecord({ name: "test_field", type: "error_field" }); - const { component } = setupMockFormComponent(({ formMethods }) => ( - - )); - - expect(component.find(Alert)).to.be.empty; - }); - - it("renders a radio button field", () => { - const field = FieldRecord({ - name: "radio_test_field", - type: RADIO_FIELD, - option_strings_text: { - en: [ - { - id: "yes", - label: "Yes" - }, - { - id: "no", - label: "No" - } - ] - } - }); - const { component } = setupMockFormComponent(FormSectionField, { props: { field } }); - - expect(component.exists("input[name='radio_test_field']")).to.be.true; - }); - - it("renders a toggle field", () => { - const field = FieldRecord({ name: "test_field", type: TOGGLE_FIELD }); - const { component } = setupMockFormComponent(FormSectionField, { props: { field } }); - - expect(component.exists("input[name='test_field']")).to.be.true; - }); - - it("renders a buttons link", () => { - const field = FieldRecord({ name: "test_field", type: DIALOG_TRIGGER, display_name: { en: "Test Field" } }); - const { component } = setupMockFormComponent(FormSectionField, { props: { field } }); - const buttonLink = component.find("a"); - - expect(buttonLink).to.have.lengthOf(1); - expect(buttonLink.text()).to.be.equal("Test Field"); - }); - - it("renders an attachement field", () => { - const field = FieldRecord({ name: "test_document_field", type: DOCUMENT_FIELD }); - const { component } = setupMockFormComponent(FormSectionField, { props: { field } }); - const inputSelector = "input[name='test_document_field']"; - - expect(component.find(inputSelector)).to.have.lengthOf(1); - expect(component.find(inputSelector).props().type).to.be.equal("file"); - }); -}); diff --git a/app/javascript/components/form/components/form-section-tabs/component.jsx b/app/javascript/components/form/components/form-section-tabs/component.jsx index c4075caf75..e427c9545a 100644 --- a/app/javascript/components/form/components/form-section-tabs/component.jsx +++ b/app/javascript/components/form/components/form-section-tabs/component.jsx @@ -2,7 +2,7 @@ import { useState } from "react"; import PropTypes from "prop-types"; -import { Tab, Tabs } from "@material-ui/core"; +import { Tab, Tabs } from "@mui/material"; import TabPanel from "../../../pages/admin/form-builder/components/tab-panel"; import FormSectionField from "../form-section-field"; @@ -11,7 +11,7 @@ import watchedFormSectionField from "../watched-form-section-field"; import { NAME } from "./constants"; import css from "./styles.css"; -const Component = ({ tabs, formMethods, formMode, handleTabChange }) => { +function Component({ tabs, formMethods, formMode, handleTabChange }) { const firstEnabled = tabs.findIndex(el => el.disabled === false); const [tab, setTab] = useState(firstEnabled); @@ -48,7 +48,7 @@ const Component = ({ tabs, formMethods, formMode, handleTabChange }) => { {renderTabPanel()} ); -}; +} Component.propTypes = { formMethods: PropTypes.object.isRequired, diff --git a/app/javascript/components/form/components/form-section-tabs/component.spec.js b/app/javascript/components/form/components/form-section-tabs/component.spec.js new file mode 100644 index 0000000000..d889f62c16 --- /dev/null +++ b/app/javascript/components/form/components/form-section-tabs/component.spec.js @@ -0,0 +1,21 @@ +import { mountedComponent, screen } from "test-utils"; + +import FormSectionTabs from "./component"; + +describe("", () => { + const props = { + tabs: [ + { name: "tab 1", disabled: true, fields: [] }, + { name: "tab2", disabled: false, fields: [] } + ], + handleTabChange: () => {} + }; + + beforeEach(() => { + mountedComponent(); + }); + + it("should render the FormSectionTabs component", () => { + expect(screen.getByText("tab 1")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/form/components/form-section-tabs/component.unit.test.js b/app/javascript/components/form/components/form-section-tabs/component.unit.test.js deleted file mode 100644 index c569cc1bbd..0000000000 --- a/app/javascript/components/form/components/form-section-tabs/component.unit.test.js +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Tab, Tabs } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../../test"; - -import FormSectionTabs from "./component"; - -describe("", () => { - let component; - const props = { - tabs: [ - { name: "tab 1", disabled: true, fields: [] }, - { name: "tab2", disabled: false, fields: [] } - ], - handleTabChange: () => {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(FormSectionTabs, props, {})); - }); - - it("should render the FormSectionTabs component", () => { - expect(component.find(FormSectionTabs)).to.have.lengthOf(1); - expect(component.find(Tabs)).to.have.lengthOf(1); - expect(component.find(Tab)).to.have.lengthOf(2); - }); -}); diff --git a/app/javascript/components/form/components/form-section-title.jsx b/app/javascript/components/form/components/form-section-title.jsx index 0d0a66bba8..edecd06657 100644 --- a/app/javascript/components/form/components/form-section-title.jsx +++ b/app/javascript/components/form/components/form-section-title.jsx @@ -4,7 +4,7 @@ import PropTypes from "prop-types"; import { useI18n } from "../../i18n"; -const FormSectionTitle = ({ formSection }) => { +function FormSectionTitle({ formSection }) { const i18n = useI18n(); const { name, expandable } = formSection; const title = i18n.getI18nStringFromObject(name); @@ -14,7 +14,7 @@ const FormSectionTitle = ({ formSection }) => { } return expandable ? title :

{title}

; -}; +} FormSectionTitle.displayName = "FormSectionTitle"; diff --git a/app/javascript/components/form/components/form-section-title.unit.test.js b/app/javascript/components/form/components/form-section-title.spec.js similarity index 55% rename from app/javascript/components/form/components/form-section-title.unit.test.js rename to app/javascript/components/form/components/form-section-title.spec.js index d0db5117bd..1b306f4d42 100644 --- a/app/javascript/components/form/components/form-section-title.unit.test.js +++ b/app/javascript/components/form/components/form-section-title.spec.js @@ -1,6 +1,5 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../../test"; import { FormSectionRecord } from "../records"; import FormSectionTitle from "./form-section-title"; @@ -8,11 +7,9 @@ import FormSectionTitle from "./form-section-title"; describe(" - components/", () => { it("should not render title if name not set on form section", () => { const formSection = FormSectionRecord({ unique_id: "form_section" }); - const { component } = setupMountedComponent(FormSectionTitle, { - formSection - }); - expect(component.find("h1")).to.not.have.lengthOf(1); + mountedComponent(); + expect(screen.queryByText("Form Section Title")).toBeNull(); }); it("should render title if name set on form section", () => { @@ -20,10 +17,9 @@ describe(" - components/", () => { unique_id: "form_section", name: "Form Section Title" }); - const { component } = setupMountedComponent(FormSectionTitle, { - formSection - }); - expect(component.find("h1")).to.have.lengthOf(1); + mountedComponent(); + + expect(screen.getByText("Form Section Title")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/form/components/form-section.jsx b/app/javascript/components/form/components/form-section.jsx index 3ab2b8b8fb..15602b39dc 100644 --- a/app/javascript/components/form/components/form-section.jsx +++ b/app/javascript/components/form/components/form-section.jsx @@ -3,9 +3,9 @@ /* eslint-disable react/no-multi-comp, react/display-name */ import { useState } from "react"; import PropTypes from "prop-types"; -import clsx from "clsx"; -import { Accordion, AccordionSummary, AccordionDetails, Typography } from "@material-ui/core"; -import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; +import { cx } from "@emotion/css"; +import { Accordion, AccordionSummary, AccordionDetails, Typography } from "@mui/material"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import get from "lodash/get"; import Tooltip from "../../tooltip"; @@ -17,7 +17,7 @@ import css from "./styles.css"; import Fields from "./fields"; import FormSectionActions from "./form-section-actions"; -const FormSection = ({ formSection, showTitle, disableUnderline, formMethods, formMode }) => { +function FormSection({ formSection, showTitle = true, disableUnderline = false, formMethods, formMode }) { const { fields, check_errors: checkErrors, expandable, tooltip } = formSection; const { errors } = formMethods; const [expanded, setExpanded] = useState(formSection.expanded); @@ -28,7 +28,7 @@ const FormSection = ({ formSection, showTitle, disableUnderline, formMethods, fo setExpanded(!expanded); }; - const classes = clsx({ + const classes = cx({ [css.heading]: true, [css.error]: renderError() }); @@ -43,7 +43,7 @@ const FormSection = ({ formSection, showTitle, disableUnderline, formMethods, fo - + ); -}; +} FormSection.displayName = FORM_SECTION_NAME; -FormSection.defaultProps = { - disableUnderline: false, - showTitle: true -}; - FormSection.propTypes = { disableUnderline: PropTypes.bool, formMethods: PropTypes.object.isRequired, diff --git a/app/javascript/components/form/components/form-section.spec.js b/app/javascript/components/form/components/form-section.spec.js new file mode 100644 index 0000000000..d09a0107a9 --- /dev/null +++ b/app/javascript/components/form/components/form-section.spec.js @@ -0,0 +1,25 @@ +import { screen, mountedFormComponent } from "test-utils"; + +import { FieldRecord, FormSectionRecord } from "../records"; + +import FormSection from "./form-section"; + +describe(" - components/", () => { + it("renders a form section with title and fields", () => { + const formSection = FormSectionRecord({ + unique_id: "form_section", + name: "Form Section", + fields: [ + FieldRecord({ + display_name: "Test Field", + name: "test_field", + type: "text_field" + }) + ] + }); + + mountedFormComponent(); + expect(document.querySelector("#test_field")).toBeInTheDocument(); + expect(screen.getByText("Form Section")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/form/components/form-section.unit.test.js b/app/javascript/components/form/components/form-section.unit.test.js deleted file mode 100644 index 9d4499aefd..0000000000 --- a/app/javascript/components/form/components/form-section.unit.test.js +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMockFormComponent } from "../../../test"; -import { FieldRecord, FormSectionRecord } from "../records"; - -import FormSection from "./form-section"; -import FormSectionField from "./form-section-field"; - -describe(" - components/", () => { - it("renders a form section with title and fields", () => { - const formSection = FormSectionRecord({ - unique_id: "form_section", - name: "Form Section", - fields: [ - FieldRecord({ - display_name: "Test Field", - name: "test_field", - type: "text_field" - }) - ] - }); - const { component } = setupMockFormComponent(FormSection, { props: { formSection } }); - - expect(component.exists("input[name='test_field']")).to.be.true; - expect(component.find("h1")).to.have.lengthOf(1); - expect(component.find("h1").text()).to.equal("Form Section"); - }); - - it("renders a form section with checkErrors prop", () => { - const checkErrors = fromJS(["name"]); - const formSection = FormSectionRecord({ - unique_id: "form_section", - name: "Form Section", - check_errors: checkErrors, - fields: [ - FieldRecord({ - display_name: "Name", - name: "name", - type: "name" - }) - ] - }); - const { component } = setupMockFormComponent(FormSection, { props: { formSection } }); - - expect(component.find(FormSectionField).props().checkErrors).to.deep.equal(checkErrors); - }); -}); diff --git a/app/javascript/components/form/components/input-label.jsx b/app/javascript/components/form/components/input-label.jsx index 6a6d81e64d..1a668de074 100644 --- a/app/javascript/components/form/components/input-label.jsx +++ b/app/javascript/components/form/components/input-label.jsx @@ -5,7 +5,7 @@ import isFunction from "lodash/isFunction"; import Tooltip from "../../tooltip"; -const InputLabel = ({ tooltip, i18nTitle, text }) => { +function InputLabel({ tooltip = "", i18nTitle = false, text = "" }) { const renderText = isFunction(text) ? text() : text; return ( @@ -13,16 +13,10 @@ const InputLabel = ({ tooltip, i18nTitle, text }) => { {renderText} ); -}; +} InputLabel.displayName = "InputLabel"; -InputLabel.defaultProps = { - i18nTitle: false, - text: "", - tooltip: "" -}; - InputLabel.propTypes = { i18nTitle: PropTypes.bool, text: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), diff --git a/app/javascript/components/form/components/orderable-option-buttons/component.jsx b/app/javascript/components/form/components/orderable-option-buttons/component.jsx index 18df0e3262..7ba8859b5d 100644 --- a/app/javascript/components/form/components/orderable-option-buttons/component.jsx +++ b/app/javascript/components/form/components/orderable-option-buttons/component.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import AddIcon from "@material-ui/icons/Add"; -import CloseIcon from "@material-ui/icons/Close"; +import AddIcon from "@mui/icons-material/Add"; +import CloseIcon from "@mui/icons-material/Close"; import ActionButton, { ACTION_BUTTON_TYPES } from "../../../action-button"; diff --git a/app/javascript/components/form/components/styles.css b/app/javascript/components/form/components/styles.css index 39365d65b3..73eb0ca026 100644 --- a/app/javascript/components/form/components/styles.css +++ b/app/javascript/components/form/components/styles.css @@ -4,10 +4,6 @@ position: absolute; } -.field { - margin: 0 0 var(--sp-3); -} - .row { display: flex; align-items: center; diff --git a/app/javascript/components/form/components/watched-form-section-field.jsx b/app/javascript/components/form/components/watched-form-section-field.jsx index e8fcbf0133..e3ae93a674 100644 --- a/app/javascript/components/form/components/watched-form-section-field.jsx +++ b/app/javascript/components/form/components/watched-form-section-field.jsx @@ -2,7 +2,7 @@ import PropTypes from "prop-types"; import { useWatch } from "react-hook-form"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; import { ConditionalWrapper } from "../../../libs"; import useFormField from "../use-form-field"; @@ -11,7 +11,7 @@ import formComponent from "../utils/form-component"; import css from "./styles.css"; -const WatchedFormSectionField = ({ checkErrors, field, formMethods, formMode, disableUnderline }) => { +function WatchedFormSectionField({ checkErrors, field, formMethods, formMode, disableUnderline = false }) { const { control, errors, getValues } = formMethods; const { @@ -27,7 +27,7 @@ const WatchedFormSectionField = ({ checkErrors, field, formMethods, formMode, di error } = useFormField(field, { checkErrors, errors, formMode, disableUnderline }); - const classes = clsx(css.field, { + const classes = cx(css.field, { [css.readonly]: formMode.isShow }); @@ -77,14 +77,10 @@ const WatchedFormSectionField = ({ checkErrors, field, formMethods, formMode, di ) ); -}; +} WatchedFormSectionField.displayName = "WatchedFormSectionField"; -WatchedFormSectionField.defaultProps = { - disableUnderline: false -}; - WatchedFormSectionField.propTypes = { checkErrors: PropTypes.object, disableUnderline: PropTypes.bool, diff --git a/app/javascript/components/form/constants.js b/app/javascript/components/form/constants.js index caa62676a7..20098f757c 100644 --- a/app/javascript/components/form/constants.js +++ b/app/javascript/components/form/constants.js @@ -63,11 +63,11 @@ export const CUSTOM_LOOKUPS = [ ]; export const SELECT_CHANGE_REASON = Object.freeze({ - removeOption: "remove-option", + removeOption: "removeOption", clear: "clear", blur: "blur", - selectOption: "select-option", - createOption: "create-option" + selectOption: "selectOption", + createOption: "createOption" }); export const EMPTY_VALUE = "--"; diff --git a/app/javascript/components/form/fields/attachment-input.jsx b/app/javascript/components/form/fields/attachment-input.jsx index 3bb4cbb4cb..b4ca2fc6a2 100644 --- a/app/javascript/components/form/fields/attachment-input.jsx +++ b/app/javascript/components/form/fields/attachment-input.jsx @@ -2,9 +2,9 @@ import { useState } from "react"; import PropTypes from "prop-types"; -import { InputLabel, FormHelperText } from "@material-ui/core"; -import clsx from "clsx"; -import GetAppIcon from "@material-ui/icons/GetApp"; +import { InputLabel, FormHelperText } from "@mui/material"; +import { cx } from "@emotion/css"; +import GetAppIcon from "@mui/icons-material/GetApp"; import { toBase64 } from "../../../libs"; import { PHOTO_FIELD, DOCUMENT_FIELD, EMPTY_VALUE } from "../constants"; @@ -14,7 +14,7 @@ import { ATTACHMENT_TYPES } from "../../record-form/form/field-types/attachments import css from "./styles.css"; -const AttachmentInput = ({ commonInputProps, metaInputProps, formMode, formMethods }) => { +function AttachmentInput({ commonInputProps, metaInputProps, formMode, formMethods }) { const { setValue, watch, register } = formMethods; const [file, setFile] = useState({ @@ -111,7 +111,7 @@ const AttachmentInput = ({ commonInputProps, metaInputProps, formMode, formMetho const downloadButton = renderDownloadButton && isShow && downloadFile; - const classes = clsx(css.attachment, { [css.document]: isDocument && (!renderDownloadButton || !isShow) }); + const classes = cx(css.attachment, { [css.document]: isDocument && (!renderDownloadButton || !isShow) }); return (
@@ -137,7 +137,7 @@ const AttachmentInput = ({ commonInputProps, metaInputProps, formMode, formMetho
{downloadButton}
); -}; +} AttachmentInput.displayName = "AttachmentInput"; diff --git a/app/javascript/components/form/fields/attachment-input.spec.js b/app/javascript/components/form/fields/attachment-input.spec.js new file mode 100644 index 0000000000..50c3a35b5c --- /dev/null +++ b/app/javascript/components/form/fields/attachment-input.spec.js @@ -0,0 +1,25 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +import { screen, mountedFieldComponent } from "test-utils"; + +import { FILE_FORMAT } from "../../../config"; + +import AttachmentInput from "./attachment-input"; + +describe(" - fields/", () => { + const props = { + commonInputProps: { + label: "Test label", + name: "test" + }, + metaInputProps: { + fileFormat: FILE_FORMAT.pdf, + renderDownloadButton: true + } + }; + + it("renders input label and form helper text", () => { + mountedFieldComponent(); + expect(screen.getByText("fields.file_upload_box.select_file_button_text")).toBeInTheDocument(); + expect(screen.getByRole("button")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/form/fields/attachment-input.unit.test.js b/app/javascript/components/form/fields/attachment-input.unit.test.js deleted file mode 100644 index b77a99b9e6..0000000000 --- a/app/javascript/components/form/fields/attachment-input.unit.test.js +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { InputLabel, FormHelperText } from "@material-ui/core"; - -import { FieldRecord } from "../records"; -import { setupMockFieldComponent } from "../../../test"; -import { FILE_FORMAT } from "../../../config"; -import ActionButton from "../../action-button"; - -import AttachmentInput from "./attachment-input"; - -describe(" - fields/", () => { - const props = { - commonInputProps: { - label: "Test label", - name: "test" - }, - metaInputProps: { - fileFormat: FILE_FORMAT.pdf, - renderDownloadButton: true - } - }; - - it("renders input label and form helper text", () => { - const { component } = setupMockFieldComponent(AttachmentInput, FieldRecord, {}, props); - - expect(component.find(InputLabel)).to.have.lengthOf(1); - expect(component.find(FormHelperText)).to.have.lengthOf(1); - expect(component.find(ActionButton)).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/form/fields/checkbox-group.jsx b/app/javascript/components/form/fields/checkbox-group.jsx index be2e13ba44..41338930c4 100644 --- a/app/javascript/components/form/fields/checkbox-group.jsx +++ b/app/javascript/components/form/fields/checkbox-group.jsx @@ -4,7 +4,7 @@ import { useState, useEffect } from "react"; import PropTypes from "prop-types"; -import { FormControlLabel, Checkbox } from "@material-ui/core"; +import { FormControlLabel, Checkbox } from "@mui/material"; import isFunction from "lodash/isFunction"; import { useI18n } from "../../i18n"; @@ -13,7 +13,7 @@ import InputLabel from "../components/input-label"; import Separator from "./seperator"; -const CheckboxGroup = ({ onChange, value, options, commonInputProps }) => { +function CheckboxGroup({ onChange, value, options, commonInputProps }) { const i18n = useI18n(); const [checked, setChecked] = useState([]); const { name, disabled } = commonInputProps; @@ -62,7 +62,7 @@ const CheckboxGroup = ({ onChange, value, options, commonInputProps }) => { }); return <>{renderCheckboxes()}; -}; +} CheckboxGroup.displayName = "CheckboxGroup"; diff --git a/app/javascript/components/form/fields/checkbox-group.spec.js b/app/javascript/components/form/fields/checkbox-group.spec.js new file mode 100644 index 0000000000..73a374a0c5 --- /dev/null +++ b/app/javascript/components/form/fields/checkbox-group.spec.js @@ -0,0 +1,23 @@ +import { screen, mountedFieldComponent, fireEvent, waitFor } from "test-utils"; + +import CheckboxGroup from "./checkbox-group"; + +describe("form/fields/checkbox-group.jsx", () => { + const options = [ + { id: 1, display_text: "option-1", tooltip: "option-1.tooltip" }, + { id: 2, display_text: "option-2" } + ]; + + const props = { options, value: [1], onChange: () => {} }; + + it("renders checkbox inputs", () => { + mountedFieldComponent(); + expect(screen.getByText("option-1")).toBeInTheDocument(); + }); + + it("renders checkbox inputs with tooltips", async () => { + mountedFieldComponent(); + fireEvent.mouseOver(screen.getByText("option-1")); + await waitFor(() => expect(screen.getByText("option-1.tooltip")).toBeInTheDocument()); + }); +}); diff --git a/app/javascript/components/form/fields/checkbox-group.unit.test.js b/app/javascript/components/form/fields/checkbox-group.unit.test.js deleted file mode 100644 index 0b34c77b4e..0000000000 --- a/app/javascript/components/form/fields/checkbox-group.unit.test.js +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Checkbox, Tooltip } from "@material-ui/core"; - -import { FieldRecord } from "../records"; -import { setupMockFieldComponent } from "../../../test"; - -import CheckboxGroup from "./checkbox-group"; - -describe("form/fields/checkbox-group.jsx", () => { - const options = [ - { id: 1, display_text: "option-1", tooltip: "option-1.tooltip" }, - { id: 2, display_text: "option-2" } - ]; - - it("renders checkbox inputs", () => { - const { component } = setupMockFieldComponent( - CheckboxGroup, - FieldRecord, - {}, - { options, value: [1], onChange: () => {} } - ); - - expect(component.find(Checkbox)).to.have.lengthOf(2); - expect( - component - .find(Checkbox) - .map(checkbox => checkbox.props().checked) - .filter(checked => checked === true) - ).to.have.lengthOf(1); - }); - - it("renders checkbox inputs with tooltips", () => { - const { component } = setupMockFieldComponent( - CheckboxGroup, - FieldRecord, - {}, - { options, value: [1], onChange: () => {} } - ); - - expect(component.find(Tooltip)).to.have.lengthOf(1); - expect(component.find(Tooltip).props().title).to.eql("option-1.tooltip"); - }); -}); diff --git a/app/javascript/components/form/fields/checkbox-input.jsx b/app/javascript/components/form/fields/checkbox-input.jsx index 218a8ea37a..a913a40aef 100644 --- a/app/javascript/components/form/fields/checkbox-input.jsx +++ b/app/javascript/components/form/fields/checkbox-input.jsx @@ -1,13 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { FormGroup, FormControl, FormLabel, FormHelperText } from "@material-ui/core"; +import { FormGroup, FormControl, FormLabel, FormHelperText } from "@mui/material"; import { Controller } from "react-hook-form"; import CheckboxGroup from "./checkbox-group"; import css from "./styles.css"; -const CheckboxInput = ({ commonInputProps, options, metaInputProps, formMethods }) => { +function CheckboxInput({ commonInputProps, options, metaInputProps, formMethods }) { const { control } = formMethods; const { name, error, required, label, helperText, disabled } = commonInputProps; const { inlineCheckboxes } = metaInputProps; @@ -31,7 +31,7 @@ const CheckboxInput = ({ commonInputProps, options, metaInputProps, formMethods {helperText} ); -}; +} CheckboxInput.displayName = "CheckboxInput"; diff --git a/app/javascript/components/form/fields/checkbox-input.spec.js b/app/javascript/components/form/fields/checkbox-input.spec.js new file mode 100644 index 0000000000..cbaf916a4f --- /dev/null +++ b/app/javascript/components/form/fields/checkbox-input.spec.js @@ -0,0 +1,44 @@ +import { screen, mountedFieldComponent } from "test-utils"; + +import CheckboxInput from "./checkbox-input"; + +describe(" - fields/", () => { + const props = { + commonInputProps: { + label: "Test label", + name: "test" + }, + options: [ + { id: 1, display_text: "option-1" }, + { id: 2, display_text: "option-2" } + ] + }; + + it("renders checkbox inputs", () => { + mountedFieldComponent(); + expect(screen.getByText("option-1")).toBeInTheDocument(); + expect(screen.getByText("option-2")).toBeInTheDocument(); + }); + + it("renders help text", () => { + mountedFieldComponent(); + expect(screen.getByText("Test Field 2 help text")).toBeInTheDocument(); + }); + + it("renders errors", () => { + mountedFieldComponent(, { + errors: [ + { + name: "test_field_2", + message: "Name is required" + } + ] + }); + expect(screen.getByText("Name is required")).toBeInTheDocument(); + }); + + it("renders required indicator", () => { + mountedFieldComponent(); + expect(screen.getByText("*")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/form/fields/checkbox-input.unit.test.js b/app/javascript/components/form/fields/checkbox-input.unit.test.js deleted file mode 100644 index e70859fff9..0000000000 --- a/app/javascript/components/form/fields/checkbox-input.unit.test.js +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { FieldRecord } from "../records"; -import { setupMockFieldComponent } from "../../../test"; - -import CheckboxInput from "./checkbox-input"; - -describe(" - fields/", () => { - const options = [ - { id: 1, display_text: "option-1" }, - { id: 2, display_text: "option-2" } - ]; - - it("renders checkbox inputs", () => { - const { component } = setupMockFieldComponent(CheckboxInput, FieldRecord, {}, { options }); - - expect(component.find("input")).to.be.lengthOf(2); - }); - - it("renders help text", () => { - const { component } = setupMockFieldComponent(CheckboxInput, FieldRecord); - - expect(component.find("p.MuiFormHelperText-root").at(0).text()).to.include("Test Field 2 help text"); - }); - - it("renders errors", () => { - const { component } = setupMockFieldComponent(CheckboxInput, FieldRecord, {}, {}, {}, null, [ - { - name: "test_field_2", - message: "Name is required" - } - ]); - - expect(component.someWhere(n => n.find("Mui-error"))).to.be.true; - expect(component.find("p.MuiFormHelperText-root").at(0).text()).to.include("Name is required"); - }); - - it("renders required indicator", () => { - const { component } = setupMockFieldComponent(CheckboxInput, FieldRecord); - - expect(component.find("span").at(0).text()).to.include("*"); - }); -}); diff --git a/app/javascript/components/form/fields/date-input.jsx b/app/javascript/components/form/fields/date-input.jsx index 2d65cc887a..2b2e9ed26b 100644 --- a/app/javascript/components/form/fields/date-input.jsx +++ b/app/javascript/components/form/fields/date-input.jsx @@ -2,22 +2,21 @@ /* eslint-disable react/display-name, react/no-multi-comp */ import PropTypes from "prop-types"; -import DateFnsUtils from "@date-io/date-fns"; import { Controller, useWatch } from "react-hook-form"; -import { DatePicker, DateTimePicker, MuiPickersUtilsProvider } from "@material-ui/pickers"; import isEmpty from "lodash/isEmpty"; import { parseISO } from "date-fns"; +import { DatePicker, DateTimePicker } from "@mui/x-date-pickers"; import { toServerDateFormat } from "../../../libs"; import { useI18n } from "../../i18n"; -import localize from "../../../libs/date-picker-localization"; import { LOCALE_KEYS } from "../../../config"; import NepaliCalendar from "../../nepali-calendar-input"; +import DateProvider from "../../../date-provider"; -const DateInput = ({ commonInputProps, metaInputProps, formMethods }) => { +function DateInput({ commonInputProps, metaInputProps = {}, formMethods }) { const i18n = useI18n(); const { setValue, control } = formMethods; - const { name, label, helperText, error, disabled, placeholder } = commonInputProps; + const { name, label, helperText, error, disabled, placeholder, fullWidth, required } = commonInputProps; const currentValue = useWatch({ name, control }); @@ -47,12 +46,31 @@ const DateInput = ({ commonInputProps, metaInputProps, formMethods }) => { const fieldValue = isEmpty(currentValue) ? null : parseISO(currentValue); + const inputProps = { + slotProps: { + actionBar: { + actions: ["clear", "accept"] + }, + textField: { InputLabelProps: { shrink: true }, fullWidth, required, helperText, clearable: true } + } + }; + const renderPicker = () => { if (dateIncludeTime) { - return ; + return ( + + ); } - return ; + return ( + + ); }; if (i18n.locale === LOCALE_KEYS.ne) { @@ -60,7 +78,7 @@ const DateInput = ({ commonInputProps, metaInputProps, formMethods }) => { } return ( - + { helperText={<>{helperText}} defaultValue="" /> - + ); -}; - -DateInput.defaultProps = { - metaInputProps: {} -}; +} DateInput.displayName = "DateInput"; diff --git a/app/javascript/components/form/fields/date-input.spec.js b/app/javascript/components/form/fields/date-input.spec.js new file mode 100644 index 0000000000..3994b13893 --- /dev/null +++ b/app/javascript/components/form/fields/date-input.spec.js @@ -0,0 +1,32 @@ +import { screen, mountedFieldComponent } from "test-utils"; + +import DateInput from "./date-input"; + +describe(" - fields/", () => { + it("renders text input", () => { + mountedFieldComponent(); + expect(document.querySelector(`input[name="test_field_2"]`)).toBeInTheDocument(); + }); + + it("renders help text", () => { + mountedFieldComponent(); + expect(screen.getByText("Test Field 2 help text")).toBeInTheDocument(); + }); + + it("renders errors", () => { + mountedFieldComponent(, { + errors: [ + { + name: "test_field_2", + message: "Name is required" + } + ] + }); + expect(screen.getByText("Name is required")).toBeInTheDocument(); + }); + + it("renders required indicator", () => { + mountedFieldComponent(); + expect(screen.getByRole("textbox", { required: true })).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/form/fields/date-input.unit.test.js b/app/javascript/components/form/fields/date-input.unit.test.js deleted file mode 100644 index 1dc3f894ff..0000000000 --- a/app/javascript/components/form/fields/date-input.unit.test.js +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { FieldRecord } from "../records"; -import { setupMockFieldComponent } from "../../../test"; -import NepaliCalendar from "../../nepali-calendar-input"; - -import DateInput from "./date-input"; - -describe(" - fields/", () => { - it("renders text input", () => { - const { component } = setupMockFieldComponent(DateInput, FieldRecord); - - expect(component.exists("input[name='test_field_2']")).to.be.true; - }); - - it("renders help text", () => { - const { component } = setupMockFieldComponent(DateInput, FieldRecord); - - expect(component.find("p.MuiFormHelperText-root").at(0).text()).to.include("Test Field 2 help text"); - }); - - it("renders errors", () => { - const { component } = setupMockFieldComponent(DateInput, FieldRecord, {}, {}, {}, null, [ - { - name: "test_field_2", - message: "Name is required" - } - ]); - - expect(component.someWhere(n => n.find("Mui-error"))).to.be.true; - expect(component.find("p.MuiFormHelperText-root").at(0).text()).to.include("Name is required"); - }); - - describe("when ne locale", () => { - it.skip("renders Nepali date picker", () => { - window.I18n.locale = "ne"; - - const { component } = setupMockFieldComponent(DateInput, FieldRecord); - - expect(component.find(NepaliCalendar)).to.have.lengthOf(1); - }); - - after(() => { - window.I18n.locale = "en"; - }); - }); -}); diff --git a/app/javascript/components/form/fields/dialog-trigger.jsx b/app/javascript/components/form/fields/dialog-trigger.jsx index 85396b26cb..766c4a166f 100644 --- a/app/javascript/components/form/fields/dialog-trigger.jsx +++ b/app/javascript/components/form/fields/dialog-trigger.jsx @@ -1,11 +1,11 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Button, Link } from "@material-ui/core"; +import { Button, Link } from "@mui/material"; import css from "./styles.css"; -const DialogTrigger = ({ commonInputProps, metaInputProps }) => { +function DialogTrigger({ commonInputProps, metaInputProps }) { const { label, id } = commonInputProps; const { onClick } = metaInputProps; @@ -14,7 +14,7 @@ const DialogTrigger = ({ commonInputProps, metaInputProps }) => { {label} ); -}; +} DialogTrigger.displayName = "DialogTrigger"; diff --git a/app/javascript/components/form/fields/dialog-trigger.spec.js b/app/javascript/components/form/fields/dialog-trigger.spec.js new file mode 100644 index 0000000000..ae8b7704d8 --- /dev/null +++ b/app/javascript/components/form/fields/dialog-trigger.spec.js @@ -0,0 +1,19 @@ +import { screen, mountedFieldComponent } from "test-utils"; + +import DialogTrigger from "./dialog-trigger"; + +describe("form/fields/dialog-trigger.jsx", () => { + const inputProps = { + commonInputProps: { + label: "Test label" + }, + metaInputProps: { + onClick: () => {} + } + }; + + it("renders button component with text", () => { + mountedFieldComponent(, { inputProps }); + expect(screen.getByText("Test label")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/form/fields/dialog-trigger.unit.test.js b/app/javascript/components/form/fields/dialog-trigger.unit.test.js deleted file mode 100644 index a15af26613..0000000000 --- a/app/javascript/components/form/fields/dialog-trigger.unit.test.js +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Button } from "@material-ui/core"; - -import { FieldRecord } from "../records"; -import { setupMockFieldComponent } from "../../../test"; - -import DialogTrigger from "./dialog-trigger"; - -describe("form/fields/dialog-trigger.jsx", () => { - const props = { - commonInputProps: { - label: "Test label" - }, - metaInputProps: { - onClick: () => {} - } - }; - - it("renders button component", () => { - const { component } = setupMockFieldComponent(DialogTrigger, FieldRecord, {}, props); - - expect(component.find(Button)).to.have.lengthOf(1); - }); - - it("renders button component with text", () => { - const { component } = setupMockFieldComponent(DialogTrigger, FieldRecord, {}, props); - - expect(component.find(Button).text()).to.eql("Test label"); - }); -}); diff --git a/app/javascript/components/form/fields/error-field.jsx b/app/javascript/components/form/fields/error-field.jsx index 20df1e041e..a224fdc85a 100644 --- a/app/javascript/components/form/fields/error-field.jsx +++ b/app/javascript/components/form/fields/error-field.jsx @@ -2,11 +2,11 @@ import PropTypes from "prop-types"; import { fromJS } from "immutable"; -import Alert from "@material-ui/lab/Alert"; +import Alert from "@mui/material/Alert"; import { ERROR_FIELD_NAME } from "./constants"; -const ErrorField = ({ errorsToCheck, formMethods }) => { +function ErrorField({ errorsToCheck = fromJS([]), formMethods }) { const { errors } = formMethods; if (!errorsToCheck?.size) { @@ -21,14 +21,10 @@ const ErrorField = ({ errorsToCheck, formMethods }) => { {errors[error].message} )); -}; +} ErrorField.displayName = ERROR_FIELD_NAME; -ErrorField.defaultProps = { - errorsToCheck: fromJS([]) -}; - ErrorField.propTypes = { errorsToCheck: PropTypes.object }; diff --git a/app/javascript/components/form/fields/error-field.spec.js b/app/javascript/components/form/fields/error-field.spec.js new file mode 100644 index 0000000000..4cf0cd3f2a --- /dev/null +++ b/app/javascript/components/form/fields/error-field.spec.js @@ -0,0 +1,34 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +import { screen, mountedFieldComponent } from "test-utils"; +import { fromJS } from "immutable"; + +import ErrorField from "./error-field"; + +describe(" - fields/", () => { + it("renders a error field if there are errors in the forms", () => { + // eslint-disable-next-line react/display-name, react/no-multi-comp, react/prop-types + function Component({ formMethods }) { + return ; + } + + mountedFieldComponent(, { + errors: [ + { + name: "name", + message: "Name is required" + } + ] + }); + expect(screen.getByText("Name is required")).toBeInTheDocument(); + }); + + it("does not render the error field if the form doesn't have errors", () => { + // eslint-disable-next-line react/display-name, react/no-multi-comp, react/prop-types + function Component({ formMethods }) { + return ; + } + + mountedFieldComponent(); + expect(document.querySelector(".MuiAlert-message")).toBeNull(); + }); +}); diff --git a/app/javascript/components/form/fields/error-field.unit.test.js b/app/javascript/components/form/fields/error-field.unit.test.js deleted file mode 100644 index f59ee6e101..0000000000 --- a/app/javascript/components/form/fields/error-field.unit.test.js +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import Alert from "@material-ui/lab/Alert"; - -import { setupMockFieldComponent } from "../../../test"; -import { FieldRecord } from "../records"; - -import ErrorField from "./error-field"; - -describe(" - fields/", () => { - it("renders a error field if there are errors in the forms", () => { - const { component } = setupMockFieldComponent( - ({ formMethods }) => , - FieldRecord, - {}, - {}, - {}, - null, - [ - { - name: "name", - message: "Name is required" - } - ] - ); - - expect(component.find(Alert)).to.have.lengthOf(1); - }); - - it("does not render the error field if the form doesn't have errors", () => { - const { component } = setupMockFieldComponent( - ({ formMethods }) => , - FieldRecord - ); - - expect(component.find(Alert)).to.be.empty; - }); -}); diff --git a/app/javascript/components/form/fields/hidden-input.jsx b/app/javascript/components/form/fields/hidden-input.jsx index 7cf4c67d01..9f3aad9446 100644 --- a/app/javascript/components/form/fields/hidden-input.jsx +++ b/app/javascript/components/form/fields/hidden-input.jsx @@ -2,12 +2,12 @@ import PropTypes from "prop-types"; -const HiddenInput = ({ commonInputProps, formMethods }) => { +function HiddenInput({ commonInputProps, formMethods }) { const { name } = commonInputProps; const { register } = formMethods; return ; -}; +} HiddenInput.displayName = "HiddenInput"; diff --git a/app/javascript/components/form/fields/label.jsx b/app/javascript/components/form/fields/label.jsx index d927828429..acaf981d48 100644 --- a/app/javascript/components/form/fields/label.jsx +++ b/app/javascript/components/form/fields/label.jsx @@ -2,12 +2,12 @@ import PropTypes from "prop-types"; -const Label = ({ commonInputProps }) => { +function Label({ commonInputProps }) { const { label, className } = commonInputProps; const classToApply = className || ""; return
{label}
; -}; +} Label.displayName = "Label"; diff --git a/app/javascript/components/form/fields/label.spec.js b/app/javascript/components/form/fields/label.spec.js new file mode 100644 index 0000000000..bd017ae649 --- /dev/null +++ b/app/javascript/components/form/fields/label.spec.js @@ -0,0 +1,19 @@ +import { screen, mountedComponent } from "test-utils"; +import { fromJS } from "immutable"; + +import Label from "./label"; + +describe("
); -}; +} Container.displayName = "InsightsList"; diff --git a/app/javascript/components/insights/component.unit.test.js b/app/javascript/components/insights-list/container.spec.js similarity index 62% rename from app/javascript/components/insights/component.unit.test.js rename to app/javascript/components/insights-list/container.spec.js index bcd3acaa41..55ce8444ab 100644 --- a/app/javascript/components/insights/component.unit.test.js +++ b/app/javascript/components/insights-list/container.spec.js @@ -1,3 +1,3 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -describe("", () => {}); +test.todo(""); diff --git a/app/javascript/components/insights-sub-report/components/exporter/exporter.jsx b/app/javascript/components/insights-sub-report/components/exporter/exporter.jsx index 1da05ddb43..0f1a6fd8ca 100644 --- a/app/javascript/components/insights-sub-report/components/exporter/exporter.jsx +++ b/app/javascript/components/insights-sub-report/components/exporter/exporter.jsx @@ -10,7 +10,7 @@ import css from "./styles.css"; import { downloadFile, tableToCsv } from "./utils"; import { DEFAULT_FILE_NAME, NAME } from "./constants"; -const Exporter = ({ includesGraph }) => { +function Exporter({ includesGraph = false }) { const handleClickTableExporter = () => { const csvBlob = new Blob([tableToCsv("table tr")], { type: "text/csv" }); @@ -55,14 +55,10 @@ const Exporter = ({ includesGraph }) => { /> ); -}; +} Exporter.displayName = NAME; -Exporter.defaultProps = { - includesGraph: false -}; - Exporter.propTypes = { includesGraph: PropTypes.bool }; diff --git a/app/javascript/components/insights-sub-report/components/exporter/exporter.spec.js b/app/javascript/components/insights-sub-report/components/exporter/exporter.spec.js new file mode 100644 index 0000000000..6bac56e77a --- /dev/null +++ b/app/javascript/components/insights-sub-report/components/exporter/exporter.spec.js @@ -0,0 +1,27 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { mountedComponent, screen } from "../../../../test-utils"; + +import Exporter from "./exporter"; + +describe("", () => { + describe("when includesGraph is true", () => { + beforeEach(() => { + mountedComponent(); + }); + + it("should render 2 component", () => { + expect(screen.getAllByRole("button")).toHaveLength(2); + }); + }); + + describe("when includesGraph is false", () => { + beforeEach(() => { + mountedComponent(); + }); + + it("should render 1 component", () => { + expect(screen.getByRole("button")).toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/insights-sub-report/components/exporter/exporter.unit.test.js b/app/javascript/components/insights-sub-report/components/exporter/exporter.unit.test.js deleted file mode 100644 index 9190088e58..0000000000 --- a/app/javascript/components/insights-sub-report/components/exporter/exporter.unit.test.js +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../test"; -import ActionButton from "../../../action-button"; - -import Exporter from "./exporter"; - -describe("", () => { - describe("when includesGraph is true", () => { - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(Exporter, { includesGraph: true })); - }); - - it("should render 2 component", () => { - expect(component.find(ActionButton)).to.have.lengthOf(2); - }); - - it("should accept valid props for component", () => { - const actionButtonProps = { ...component.find(ActionButton).at(0).props() }; - - ["icon", "type", "isTransparent", "rest", "outlined", "id"].forEach(property => { - expect(actionButtonProps).to.have.property(property); - delete actionButtonProps[property]; - }); - expect(actionButtonProps).to.be.empty; - }); - }); - - describe("when includesGraph is false", () => { - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(Exporter, { includesGraph: false })); - }); - - it("should render 1 component", () => { - expect(component.find(ActionButton)).to.have.lengthOf(1); - }); - - it("should accept valid props for component", () => { - const actionButtonProps = { ...component.find(ActionButton).props() }; - - ["icon", "type", "isTransparent", "rest", "outlined", "id"].forEach(property => { - expect(actionButtonProps).to.have.property(property); - delete actionButtonProps[property]; - }); - expect(actionButtonProps).to.be.empty; - }); - }); -}); diff --git a/app/javascript/components/insights-sub-report/components/insights-table-header-sub-items/component.jsx b/app/javascript/components/insights-sub-report/components/insights-table-header-sub-items/component.jsx index 0671b5cd2c..73f54a19dd 100644 --- a/app/javascript/components/insights-sub-report/components/insights-table-header-sub-items/component.jsx +++ b/app/javascript/components/insights-sub-report/components/insights-table-header-sub-items/component.jsx @@ -1,17 +1,17 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { TableCell, TableRow } from "@material-ui/core"; +import { TableCell, TableRow } from "@mui/material"; import isEmpty from "lodash/isEmpty"; import isObjectLike from "lodash/isObjectLike"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; import { useI18n } from "../../../i18n"; import css from "./styles.css"; import { NAME } from "./constants"; -const InsightsTableHeaderSubItems = ({ addEmptyCell = true, groupedSubItemcolumns }) => { +function InsightsTableHeaderSubItems({ addEmptyCell = true, groupedSubItemcolumns }) { const i18n = useI18n(); if (isEmpty(groupedSubItemcolumns)) { @@ -23,7 +23,7 @@ const InsightsTableHeaderSubItems = ({ addEmptyCell = true, groupedSubItemcolumn {addEmptyCell && } {Object.entries(groupedSubItemcolumns).flatMap(([parent, subItemsColumns]) => subItemsColumns.map((subItem, index) => { - const cellClass = clsx({ + const cellClass = cx({ [css.tableCell]: (index + 1) % subItemsColumns?.length === 0, [css.tableCellCenterClass]: true }); @@ -41,7 +41,7 @@ const InsightsTableHeaderSubItems = ({ addEmptyCell = true, groupedSubItemcolumn )} ); -}; +} InsightsTableHeaderSubItems.displayName = NAME; diff --git a/app/javascript/components/insights-sub-report/components/insights-table-header-sub-items/component.spec.js b/app/javascript/components/insights-sub-report/components/insights-table-header-sub-items/component.spec.js new file mode 100644 index 0000000000..fd2feb3728 --- /dev/null +++ b/app/javascript/components/insights-sub-report/components/insights-table-header-sub-items/component.spec.js @@ -0,0 +1,28 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { mountedComponent, screen } from "../../../../test-utils"; + +import InsightsTableHeaderSubItems from "./component"; + +describe("", () => { + const props = { + addEmptyCell: true, + groupedSubItemcolumns: { + "2021-Q2": ["boys", "girls", "unknown", "total"], + "2021-Q3": ["boys", "girls", "unknown", "total"], + "2021-Q4": ["boys", "girls", "unknown", "total"] + } + }; + + beforeEach(() => { + mountedComponent(); + }); + + it("should render component", () => { + expect(screen.getAllByRole("row")).toHaveLength(1); + }); + + it("should render component", () => { + expect(screen.getAllByRole("cell")).toHaveLength(13); + }); +}); diff --git a/app/javascript/components/insights-sub-report/components/insights-table-header-sub-items/component.unit.test.js b/app/javascript/components/insights-sub-report/components/insights-table-header-sub-items/component.unit.test.js deleted file mode 100644 index 0651eb198b..0000000000 --- a/app/javascript/components/insights-sub-report/components/insights-table-header-sub-items/component.unit.test.js +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { TableCell, TableRow } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../../test"; - -import InsightsTableHeaderSubItems from "./component"; - -describe("", () => { - let component; - const props = { - addEmptyCell: true, - groupedSubItemcolumns: { - "2021-Q2": ["boys", "girls", "unknown", "total"], - "2021-Q3": ["boys", "girls", "unknown", "total"], - "2021-Q4": ["boys", "girls", "unknown", "total"] - } - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(InsightsTableHeaderSubItems, props)); - }); - - it("should render component", () => { - expect(component.find(InsightsTableHeaderSubItems)).to.have.lengthOf(1); - }); - - it("should render component", () => { - expect(component.find(TableRow)).to.have.lengthOf(1); - }); - - it("should render component", () => { - expect(component.find(TableCell)).to.have.lengthOf(13); - }); - - it("should accept valid props for component", () => { - const insightsTableHeaderSubItems = { ...component.find(InsightsTableHeaderSubItems).at(0).props() }; - - ["addEmptyCell", "groupedSubItemcolumns"].forEach(property => { - expect(insightsTableHeaderSubItems).to.have.property(property); - delete insightsTableHeaderSubItems[property]; - }); - expect(insightsTableHeaderSubItems).to.be.empty; - }); -}); diff --git a/app/javascript/components/insights-sub-report/components/insights-table-header/component.jsx b/app/javascript/components/insights-sub-report/components/insights-table-header/component.jsx index b6f1bb57a8..66d5362c24 100644 --- a/app/javascript/components/insights-sub-report/components/insights-table-header/component.jsx +++ b/app/javascript/components/insights-sub-report/components/insights-table-header/component.jsx @@ -1,9 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { TableCell, TableRow } from "@material-ui/core"; +import { TableCell, TableRow } from "@mui/material"; import isNil from "lodash/isNil"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; import InsightsTableHeaderSubItems from "../insights-table-header-sub-items"; import { buildGroupedSubItemColumns } from "../../utils"; @@ -11,10 +11,10 @@ import { buildGroupedSubItemColumns } from "../../utils"; import css from "./styles.css"; import { NAME } from "./constants"; -const InsightsTableHeader = ({ addEmptyCell = true, columns, subColumnItemsSize }) => { +function InsightsTableHeader({ addEmptyCell = true, columns, subColumnItemsSize }) { const groupedSubcolumns = columns.reduce((acc, column) => ({ ...acc, [column.label]: column.items }), {}); const groupedSubItemcolumns = buildGroupedSubItemColumns(columns); - const classesEmptyCell = clsx({ [css.emptyCell]: Boolean(subColumnItemsSize) }); + const classesEmptyCell = cx({ [css.emptyCell]: Boolean(subColumnItemsSize) }); const subcolumnsNumber = Object.values(groupedSubcolumns) .flat() .some(subcolumn => !isNil(subcolumn)); @@ -47,7 +47,7 @@ const InsightsTableHeader = ({ addEmptyCell = true, columns, subColumnItemsSize ); -}; +} InsightsTableHeader.displayName = NAME; diff --git a/app/javascript/components/insights-sub-report/components/insights-table-header/component.spec.js b/app/javascript/components/insights-sub-report/components/insights-table-header/component.spec.js new file mode 100644 index 0000000000..d28681cf60 --- /dev/null +++ b/app/javascript/components/insights-sub-report/components/insights-table-header/component.spec.js @@ -0,0 +1,37 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { mountedComponent, screen } from "../../../../test-utils"; + +import InsightsTableHeader from "./component"; + +describe("", () => { + const props = { + addEmptyCell: true, + columns: [ + { + label: "2021", + items: ["Q2", "Q3", "Q4"], + subItems: ["boys", "girls", "unknown", "total"], + colspan: 12 + }, + { + label: "2022", + items: ["Q1", "Q2"], + subItems: ["boys", "girls", "unknown", "total"], + colspan: 8 + } + ] + }; + + beforeEach(() => { + mountedComponent(); + }); + + it("should render table row component", () => { + expect(screen.getAllByRole("row")).toHaveLength(3); + }); + + it("should render row cells component", () => { + expect(screen.getAllByRole("cell")).toHaveLength(30); + }); +}); diff --git a/app/javascript/components/insights-sub-report/components/insights-table-header/component.unit.test.js b/app/javascript/components/insights-sub-report/components/insights-table-header/component.unit.test.js deleted file mode 100644 index 409db715af..0000000000 --- a/app/javascript/components/insights-sub-report/components/insights-table-header/component.unit.test.js +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { TableCell, TableRow } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../../test"; -import InsightsTableHeaderSubItems from "../insights-table-header-sub-items"; - -import InsightsTableHeader from "./component"; - -describe("", () => { - let component; - const props = { - addEmptyCell: true, - columns: [ - { - label: "2021", - items: ["Q2", "Q3", "Q4"], - subItems: ["boys", "girls", "unknown", "total"], - colspan: 12 - }, - { - label: "2022", - items: ["Q1", "Q2"], - subItems: ["boys", "girls", "unknown", "total"], - colspan: 8 - } - ] - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(InsightsTableHeader, props)); - }); - - it("should render component", () => { - expect(component.find(InsightsTableHeader)).to.have.lengthOf(1); - }); - - it("should render component", () => { - expect(component.find(TableRow)).to.have.lengthOf(3); - }); - - it("should render component", () => { - expect(component.find(TableCell)).to.have.lengthOf(30); - }); - - it("should render component", () => { - expect(component.find(InsightsTableHeaderSubItems)).to.have.lengthOf(1); - }); - - it("should accept valid props for component", () => { - const insightsTableHeader = { ...component.find(InsightsTableHeader).at(0).props() }; - - ["addEmptyCell", "columns"].forEach(property => { - expect(insightsTableHeader).to.have.property(property); - delete insightsTableHeader[property]; - }); - expect(insightsTableHeader).to.be.empty; - }); -}); diff --git a/app/javascript/components/insights-sub-report/components/multiple-violations-indicator/component.jsx b/app/javascript/components/insights-sub-report/components/multiple-violations-indicator/component.jsx index b45dde7509..ee5033a482 100644 --- a/app/javascript/components/insights-sub-report/components/multiple-violations-indicator/component.jsx +++ b/app/javascript/components/insights-sub-report/components/multiple-violations-indicator/component.jsx @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Card, CardContent, List, ListItem, ListItemText } from "@material-ui/core"; +import { Card, CardContent, List, ListItem, ListItemText } from "@mui/material"; import PropTypes from "prop-types"; import { NavLink } from "react-router-dom"; diff --git a/app/javascript/components/insights-sub-report/constants.js b/app/javascript/components/insights-sub-report/constants.js index f1e78663bd..f6b1a73adc 100644 --- a/app/javascript/components/insights-sub-report/constants.js +++ b/app/javascript/components/insights-sub-report/constants.js @@ -2,7 +2,7 @@ export const NAME = "InsightsSubReport"; export const COMBINED_INDICATORS = { - incidents: ["total", "gbv_sexual_violence", "gbv_previous_incidents"] + incidents: ["total", "gbv_previous_incidents"] }; export const GROUPED_BY_FILTER = "grouped_by"; export const GHN_VIOLATIONS_INDICATORS_IDS = [ diff --git a/app/javascript/components/insights-sub-report/container.jsx b/app/javascript/components/insights-sub-report/container.jsx index a46b2c1d00..e63d85b43d 100644 --- a/app/javascript/components/insights-sub-report/container.jsx +++ b/app/javascript/components/insights-sub-report/container.jsx @@ -37,7 +37,7 @@ import css from "./styles.css"; import { setSubReport } from "./action-creators"; import getSubcolumnItems from "./utils/get-subcolumn-items"; -const Component = () => { +function Component() { const { id, subReport } = useParams(); const i18n = useI18n(); const dispatch = useDispatch(); @@ -242,7 +242,7 @@ const Component = () => {
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/insights-sub-report/utils/build-chart-values.js b/app/javascript/components/insights-sub-report/utils/build-chart-values.js index 138bd941e6..8d1b42437d 100644 --- a/app/javascript/components/insights-sub-report/utils/build-chart-values.js +++ b/app/javascript/components/insights-sub-report/utils/build-chart-values.js @@ -7,7 +7,7 @@ import first from "lodash/first"; import last from "lodash/last"; import isEmpty from "lodash/isEmpty"; -import { CHART_COLORS } from "../../../config/constants"; +import { CHART_COLORS } from "../../../config"; import translateGroup from "./translate-group-id"; import sortWithSortedArray from "./sort-with-sorted-array"; diff --git a/app/javascript/components/insights-sub-report/utils/quarter-comparator.js b/app/javascript/components/insights-sub-report/utils/quarter-comparator.js index cec540c8af..2e84739fdd 100644 --- a/app/javascript/components/insights-sub-report/utils/quarter-comparator.js +++ b/app/javascript/components/insights-sub-report/utils/quarter-comparator.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { QUARTERS_TO_NUMBER } from "../../../config/constants"; +import { QUARTERS_TO_NUMBER } from "../../../config"; export default (elem1, elem2) => { if (QUARTERS_TO_NUMBER[elem1] === QUARTERS_TO_NUMBER[elem2]) { diff --git a/app/javascript/components/insights/component.jsx b/app/javascript/components/insights/component.jsx index 5f6e0cc58c..9faa013ca4 100644 --- a/app/javascript/components/insights/component.jsx +++ b/app/javascript/components/insights/component.jsx @@ -3,9 +3,9 @@ import { useEffect, useState } from "react"; import PropTypes from "prop-types"; import { useLocation, useParams } from "react-router-dom"; -import { Hidden, IconButton, useMediaQuery } from "@material-ui/core"; -import { MenuOpen } from "@material-ui/icons"; -import FilterListIcon from "@material-ui/icons/FilterList"; +import { Box, IconButton, useMediaQuery } from "@mui/material"; +import { MenuOpen } from "@mui/icons-material"; +import FilterListIcon from "@mui/icons-material/FilterList"; import { useDispatch } from "react-redux"; import { fromJS } from "immutable"; @@ -27,7 +27,7 @@ import { INSIGHTS_CONFIG, NAME, INSIGHTS_EXPORTER_DIALOG, MANAGED_REPORTS, REPOR import css from "./styles.css"; import InsightsExporter from "./components/insights-exporter"; -const Component = ({ routes }) => { +function Component({ routes }) { const { id, moduleID } = useParams(); const i18n = useI18n(); const { pathname } = useLocation(); @@ -89,7 +89,7 @@ const Component = ({ routes }) => { /> - +
{ toggleNav={toggleNav} />
-
+
- +
- +
-
+

{subReportTitle}

@@ -116,7 +116,7 @@ const Component = ({ routes }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/insights/component.spec.js b/app/javascript/components/insights/component.spec.js new file mode 100644 index 0000000000..fbb00506f3 --- /dev/null +++ b/app/javascript/components/insights/component.spec.js @@ -0,0 +1,3 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +test.todo(""); diff --git a/app/javascript/components/insights/components/exporter.jsx b/app/javascript/components/insights/components/exporter.jsx index cb115825b8..d63cc54f17 100644 --- a/app/javascript/components/insights/components/exporter.jsx +++ b/app/javascript/components/insights/components/exporter.jsx @@ -10,7 +10,7 @@ import css from "./styles.css"; import { downloadFile, tableToCsv } from "./utils"; import { DEFAULT_FILE_NAME, NAME } from "./constants"; -const Exporter = ({ includesGraph }) => { +function Exporter({ includesGraph = false }) { const handleClickTableExporter = () => { const csvBlob = new Blob([tableToCsv("table tr")], { type: "text/csv" }); @@ -55,14 +55,10 @@ const Exporter = ({ includesGraph }) => { /> ); -}; +} Exporter.displayName = NAME; -Exporter.defaultProps = { - includesGraph: false -}; - Exporter.propTypes = { includesGraph: PropTypes.bool }; diff --git a/app/javascript/components/insights/components/insights-exporter/component.jsx b/app/javascript/components/insights/components/insights-exporter/component.jsx index ac9c5f8a1d..f074bd52c5 100644 --- a/app/javascript/components/insights/components/insights-exporter/component.jsx +++ b/app/javascript/components/insights/components/insights-exporter/component.jsx @@ -18,7 +18,7 @@ import { transformFilters } from "../../../insights-filters/utils"; import { NAME, FORM_ID, EXPORTED_URL, EXPORT_ALL_SUBREPORTS } from "./constants"; import { form } from "./form"; -const Component = ({ close, i18n, open, pending, setPending }) => { +function Component({ close, i18n, open, pending, setPending }) { const dispatch = useDispatch(); const { id } = useParams(); const dialogPending = typeof pending === "object" ? pending.get("pending") : pending; @@ -68,7 +68,7 @@ const Component = ({ close, i18n, open, pending, setPending }) => {
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/insights/constants.js b/app/javascript/components/insights/constants.js index a41b42ae87..6f63cb6803 100644 --- a/app/javascript/components/insights/constants.js +++ b/app/javascript/components/insights/constants.js @@ -13,8 +13,13 @@ import { INPROGRESS, ACCEPTED, REJECTED, - DONE -} from "../../config/constants"; + DONE, + PROTECTION_CONCERNS_SUBREPORTS, + REPORTING_LOCATIONS_SUBREPORTS, + FOLLOWUPS_SUBREPORTS, + SERVICES_SUBREPORTS, + CASES_WORKFLOW_SUBREPORTS +} from "../../config"; import { DATE_FIELD, SELECT_FIELD, HIDDEN_FIELD, OPTION_TYPES } from "../form/constants"; import { FieldRecord } from "../form/records"; @@ -39,7 +44,9 @@ const VERIFICATION_STATUS = "verification_status"; const GHN_DATE_FILTER = "ghn_date_filter"; const VIOLATION_TYPE = "violation_type"; const REGISTRATION_DATE = "registration_date"; +const SERVICE_IMPLEMENTED_DAY_TIME = "service_implemented_day_time"; const CREATED_AT = "created_at"; +const FOLLOWUP_DATE = "followup_date"; const GBV_STATISTICS = "gbv_statistics"; const VIOLATIONS = "violations"; @@ -68,6 +75,10 @@ export const USER_GROUP = "user_group"; export const AGENCY = "agency"; export const BY = "by"; export const WORKFLOW = "workflow"; +export const PROTECTION_CONCERNS = "protection_concerns"; +export const REPORTING_LOCATIONS = "location"; +export const FOLLOWUPS = "followup_type"; +export const SERVICES = "service_type"; export const VIOLENCE_TYPE = "cp_incident_violence_type"; export const REFERRAL_TRANSFER_STATUS = "referral_transfer_status"; @@ -110,6 +121,10 @@ export const BY_DISPLAY_NAME = [MANAGED_REPORTS, FILTER_BY, BY]; export const USER_GROUP_DISPLAY_NAME = [MANAGED_REPORTS, FILTER_BY, USER_GROUP]; export const AGENCY_DISPLAY_NAME = [MANAGED_REPORTS, FILTER_BY, AGENCY]; export const WORKFLOW_DISPLAY_NAME = [MANAGED_REPORTS, FILTER_BY, WORKFLOW]; +export const PROTECTION_CONCERNS_DISPLAY_NAME = [MANAGED_REPORTS, FILTER_BY, PROTECTION_CONCERNS]; +export const REPORTING_LOCATIONS_DISPLAY_NAME = [MANAGED_REPORTS, FILTER_BY, REPORTING_LOCATIONS]; +export const FOLLOWUPS_DISPLAY_NAME = [MANAGED_REPORTS, FILTER_BY, FOLLOWUPS]; +export const SERVICES_DISPLAY_NAME = [MANAGED_REPORTS, FILTER_BY, SERVICES]; export const VIOLENCE_TYPE_DISPLAY_NAME = [MANAGED_REPORTS, FILTER_BY, VIOLENCE_TYPE]; export const REFERRAL_TRANSFER_STATUS_DISPLAY_NAME = [MANAGED_REPORTS, FILTER_BY, REFERRAL_TRANSFER_STATUS]; @@ -308,6 +323,35 @@ export const DEFAULT_VIOLATION_FILTERS = { [VERIFIED_CTFMR_TECHNICAL]: VERIFIED }; +export const SHARED_WORKFLOW_CONFIG = { + ids: WORKFLOW_SUBREPORTS, + defaultFilterValues: { + [GROUPED_BY]: WEEK, + [DATE_RANGE]: LAST_WEEK, + [STATUS]: [STATUS_OPEN], + [DATE]: REGISTRATION_DATE, + [BY]: OWNED_BY_GROUPS + }, + filters: [ + RECORD_FILTERS[GROUPED_BY], + RECORD_FILTERS[DATE_RANGE], + RECORD_FILTERS[FROM], + RECORD_FILTERS[TO], + RECORD_FILTERS[STATUS], + { + name: WORKFLOW, + type: SELECT_FIELD, + display_name: WORKFLOW_DISPLAY_NAME + }, + RECORD_FILTERS[BY], + RECORD_FILTERS[CREATED_BY_GROUPS], + RECORD_FILTERS[OWNED_BY_GROUPS], + RECORD_FILTERS[CREATED_ORGANIZATION], + RECORD_FILTERS[OWNED_BY_AGENCY_ID], + RECORD_FILTERS[DATE] + ].map(filter => FieldRecord(filter)) +}; + export const INSIGHTS_CONFIG = { [MODULES.MRM]: { violations: { @@ -385,8 +429,8 @@ export const INSIGHTS_CONFIG = { } }, [MODULES.CP]: { - workflow_report: { - ids: WORKFLOW_SUBREPORTS, + protection_concerns_report: { + ids: PROTECTION_CONCERNS_SUBREPORTS, defaultFilterValues: { [GROUPED_BY]: WEEK, [DATE_RANGE]: LAST_WEEK, @@ -401,9 +445,70 @@ export const INSIGHTS_CONFIG = { RECORD_FILTERS[TO], RECORD_FILTERS[STATUS], { - name: WORKFLOW, + name: PROTECTION_CONCERNS, + type: SELECT_FIELD, + display_name: PROTECTION_CONCERNS_DISPLAY_NAME, + multi_select: true, + option_strings_source: LOOKUPS.protection_concerns + }, + RECORD_FILTERS[BY], + RECORD_FILTERS[CREATED_BY_GROUPS], + RECORD_FILTERS[OWNED_BY_GROUPS], + RECORD_FILTERS[CREATED_ORGANIZATION], + RECORD_FILTERS[OWNED_BY_AGENCY_ID], + RECORD_FILTERS[DATE] + ].map(filter => FieldRecord(filter)) + }, + reporting_locations_report: { + ids: REPORTING_LOCATIONS_SUBREPORTS, + defaultFilterValues: { + [GROUPED_BY]: WEEK, + [DATE_RANGE]: LAST_WEEK, + [STATUS]: [STATUS_OPEN], + [DATE]: REGISTRATION_DATE, + [BY]: OWNED_BY_GROUPS + }, + filters: [ + RECORD_FILTERS[GROUPED_BY], + RECORD_FILTERS[DATE_RANGE], + RECORD_FILTERS[FROM], + RECORD_FILTERS[TO], + RECORD_FILTERS[STATUS], + { + name: REPORTING_LOCATIONS, + type: SELECT_FIELD, + display_name: REPORTING_LOCATIONS_DISPLAY_NAME, + option_strings_source: LOOKUPS.reporting_locations + }, + RECORD_FILTERS[BY], + RECORD_FILTERS[CREATED_BY_GROUPS], + RECORD_FILTERS[OWNED_BY_GROUPS], + RECORD_FILTERS[CREATED_ORGANIZATION], + RECORD_FILTERS[OWNED_BY_AGENCY_ID], + RECORD_FILTERS[DATE] + ].map(filter => FieldRecord(filter)) + }, + followups_report: { + ids: FOLLOWUPS_SUBREPORTS, + defaultFilterValues: { + [GROUPED_BY]: WEEK, + [DATE_RANGE]: LAST_WEEK, + [STATUS]: [STATUS_OPEN], + [DATE]: FOLLOWUP_DATE, + [BY]: OWNED_BY_GROUPS + }, + filters: [ + RECORD_FILTERS[GROUPED_BY], + RECORD_FILTERS[DATE_RANGE], + RECORD_FILTERS[FROM], + RECORD_FILTERS[TO], + RECORD_FILTERS[STATUS], + { + name: FOLLOWUPS, type: SELECT_FIELD, - display_name: WORKFLOW_DISPLAY_NAME + display_name: FOLLOWUPS_DISPLAY_NAME, + multi_select: true, + option_strings_source: LOOKUPS.followup_type }, RECORD_FILTERS[BY], RECORD_FILTERS[CREATED_BY_GROUPS], @@ -413,6 +518,41 @@ export const INSIGHTS_CONFIG = { RECORD_FILTERS[DATE] ].map(filter => FieldRecord(filter)) }, + services_report: { + ids: SERVICES_SUBREPORTS, + defaultFilterValues: { + [GROUPED_BY]: WEEK, + [DATE_RANGE]: LAST_WEEK, + [STATUS]: [STATUS_OPEN], + [DATE]: SERVICE_IMPLEMENTED_DAY_TIME, + [BY]: OWNED_BY_GROUPS + }, + filters: [ + RECORD_FILTERS[GROUPED_BY], + RECORD_FILTERS[DATE_RANGE], + RECORD_FILTERS[FROM], + RECORD_FILTERS[TO], + RECORD_FILTERS[STATUS], + { + name: SERVICES, + type: SELECT_FIELD, + display_name: SERVICES_DISPLAY_NAME, + multi_select: true, + option_strings_source: LOOKUPS.service_type + }, + RECORD_FILTERS[BY], + RECORD_FILTERS[CREATED_BY_GROUPS], + RECORD_FILTERS[OWNED_BY_GROUPS], + RECORD_FILTERS[CREATED_ORGANIZATION], + RECORD_FILTERS[OWNED_BY_AGENCY_ID], + RECORD_FILTERS[DATE] + ].map(filter => FieldRecord(filter)) + }, + workflow_report: SHARED_WORKFLOW_CONFIG, + cases_workflow_report: { + ids: CASES_WORKFLOW_SUBREPORTS, + ...SHARED_WORKFLOW_CONFIG + }, violence_type_report: { ids: VIOLENCE_TYPE_SUBREPORTS, defaultFilterValues: { diff --git a/app/javascript/components/insights/constants.unit.test.js b/app/javascript/components/insights/constants.unit.test.js index bbc2900d5b..eff1fa5751 100644 --- a/app/javascript/components/insights/constants.unit.test.js +++ b/app/javascript/components/insights/constants.unit.test.js @@ -2,7 +2,7 @@ import { expect } from "chai"; -import { MODULES } from "../../config/constants"; +import { MODULES } from "../../config"; import * as constants from "./constants"; @@ -78,7 +78,16 @@ describe(" - constants", () => { "WORKFLOW_DISPLAY_NAME", "WORKFLOW", "YEAR_OPTION_IDS", - "YEAR" + "YEAR", + "PROTECTION_CONCERNS", + "PROTECTION_CONCERNS_DISPLAY_NAME", + "REPORTING_LOCATIONS", + "REPORTING_LOCATIONS_DISPLAY_NAME", + "FOLLOWUPS", + "FOLLOWUPS_DISPLAY_NAME", + "SERVICES", + "SERVICES_DISPLAY_NAME", + "SHARED_WORKFLOW_CONFIG" ].forEach(property => { expect(clone).to.have.property(property); delete clone[property]; diff --git a/app/javascript/components/internal-alert/component.jsx b/app/javascript/components/internal-alert/component.jsx index 88c7d193a0..2320d6fd69 100644 --- a/app/javascript/components/internal-alert/component.jsx +++ b/app/javascript/components/internal-alert/component.jsx @@ -3,32 +3,27 @@ /* eslint-disable react/no-multi-comp, react/display-name */ import PropTypes from "prop-types"; import { fromJS } from "immutable"; -import clsx from "clsx"; -import { Accordion, AccordionSummary, AccordionDetails } from "@material-ui/core"; -import { makeStyles } from "@material-ui/core/styles"; -import { Brightness1 as Circle } from "@material-ui/icons"; -import ErrorIcon from "@material-ui/icons/Error"; -import CheckIcon from "@material-ui/icons/Check"; -import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; -import SignalWifiOffIcon from "@material-ui/icons/SignalWifiOff"; +import { cx } from "@emotion/css"; +import { Accordion, AccordionSummary, AccordionDetails } from "@mui/material"; +import { Brightness1 as Circle } from "@mui/icons-material"; +import ErrorIcon from "@mui/icons-material/Error"; +import CheckIcon from "@mui/icons-material/Check"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import SignalWifiOffIcon from "@mui/icons-material/SignalWifiOff"; import { generate } from "../notifier/utils"; import { useI18n } from "../i18n"; import InternalAlertItem from "./components/item"; import { NAME, SEVERITY } from "./constants"; -import { expansionPanelSummaryClasses } from "./theme"; import css from "./styles.css"; -const useStylesExpansionPanel = makeStyles(expansionPanelSummaryClasses); - -const Component = ({ title, items, severity, customIcon }) => { +function Component({ title, items = fromJS([]), severity = "info", customIcon }) { const i18n = useI18n(); - const classes = useStylesExpansionPanel(); - const accordionClasses = clsx(css.alert, css[severity]); - const accordionDetailsClasses = clsx({ [css.alertItems]: true }); - const accordionSummaryClasses = clsx({ + const accordionClasses = cx(css.alert, css[severity]); + const accordionDetailsClasses = cx({ [css.alertItems]: true }); + const accordionSummaryClasses = cx({ [css.alertTitle]: true, [css.disableCollapse]: items?.size <= 1 }); @@ -73,7 +68,9 @@ const Component = ({ title, items, severity, customIcon }) => { return ( <>
{customIcon || renderIcon()}
- {titleMessage} + + {titleMessage} + ); }; @@ -81,7 +78,8 @@ const Component = ({ title, items, severity, customIcon }) => { return ( 1 ? : null} aria-controls="record-form-alerts-panel" id="record-form-alerts-panel-header" @@ -92,15 +90,10 @@ const Component = ({ title, items, severity, customIcon }) => { {renderItems()} ); -}; +} Component.displayName = NAME; -Component.defaultProps = { - items: fromJS([]), - severity: "info" -}; - Component.propTypes = { customIcon: PropTypes.node, items: PropTypes.object, diff --git a/app/javascript/components/internal-alert/component.spec.js b/app/javascript/components/internal-alert/component.spec.js new file mode 100644 index 0000000000..5dd1873d2c --- /dev/null +++ b/app/javascript/components/internal-alert/component.spec.js @@ -0,0 +1,77 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { fromJS } from "immutable"; + +import { mountedComponent, screen } from "../../test-utils"; + +import InternalAlert from "./component"; + +describe("", () => { + it("renders the InternalAlert", () => { + mountedComponent(); + + expect(screen.getByText("Alert Message 1")).toBeInTheDocument(); + }); + + it("does not render details if there is only one alert", () => { + mountedComponent(); + + expect(screen.queryByRole("list")).not.toBeInTheDocument(); + }); + + it("renders details if there are several alert", () => { + mountedComponent( + + ); + + expect(screen.getByText("Alert Message 1")).toBeInTheDocument(); + expect(screen.getByText("Alert Message 2")).toBeInTheDocument(); + }); + + it("renders the specified title", () => { + const title = "This is the title"; + + mountedComponent( + + ); + + expect(screen.getByText(title)).toBeInTheDocument(); + }); + + it("renders a dismiss button if onDismiss is on an item", () => { + mountedComponent( + {} }]), + severity: "warning" + }} + /> + ); + + expect(document.querySelector(".dismissButton")).toBeInTheDocument(); + }); + + it("does not render a dismiss button if onDismiss is not on an item", () => { + mountedComponent( + + ); + + expect(document.querySelector(".dismissButton")).not.toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/internal-alert/component.unit.test.js b/app/javascript/components/internal-alert/component.unit.test.js deleted file mode 100644 index be347092d9..0000000000 --- a/app/javascript/components/internal-alert/component.unit.test.js +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { AccordionDetails, AccordionSummary, IconButton } from "@material-ui/core"; - -import { setupMountedComponent } from "../../test"; - -import InternalAlert from "./component"; - -describe("", () => { - it("renders the InternalAlert", () => { - const { component } = setupMountedComponent( - InternalAlert, - { items: fromJS([{ message: "Alert Message 1" }]), severity: "warning" }, - {} - ); - - expect(component.find(InternalAlert)).to.have.lengthOf(1); - expect(component.find(AccordionSummary).text()).to.be.equal("Alert Message 1"); - }); - - it("does not render details if there is only one alert", () => { - const { component } = setupMountedComponent( - InternalAlert, - { items: fromJS([{ message: "Alert Message 1" }]), severity: "warning" }, - {} - ); - - expect(component.find(AccordionDetails)).to.have.lengthOf(0); - }); - - it("renders details if there are several alert", () => { - const { component } = setupMountedComponent( - InternalAlert, - { - items: fromJS([{ message: "Alert Message 1" }, { message: "Alert Message 2" }]), - severity: "warning" - }, - {} - ); - - expect(component.find(AccordionDetails)).to.have.lengthOf(1); - expect( - component - .find(AccordionDetails) - .find("li") - .map(f => f.text()) - ).to.deep.equal(["Alert Message 1", "Alert Message 2"]); - }); - - it("renders the specified title", () => { - const title = "This is the title"; - const { component } = setupMountedComponent( - InternalAlert, - { - title, - items: fromJS([{ message: "Alert Message 1" }, { message: "Alert Message 2" }]), - severity: "warning" - }, - {} - ); - - expect(component.find(AccordionSummary).text()).to.be.equal(title); - }); - - it("renders a dismiss button if onDismiss is on an item", () => { - const { component } = setupMountedComponent( - InternalAlert, - { - items: fromJS([{ message: "Alert Message 1", onDismiss: () => {} }]), - severity: "warning" - }, - {} - ); - - expect(component.find(IconButton)).to.have.lengthOf(1); - }); - - it("does not render a dismiss button if onDismiss is not on an item", () => { - const { component } = setupMountedComponent( - InternalAlert, - { - items: fromJS([{ message: "Alert Message 1" }]), - severity: "warning" - }, - {} - ); - - expect(component.find(IconButton)).to.have.lengthOf(0); - }); -}); diff --git a/app/javascript/components/internal-alert/components/dismiss-button/component.jsx b/app/javascript/components/internal-alert/components/dismiss-button/component.jsx index ff40077461..4a4e48917e 100644 --- a/app/javascript/components/internal-alert/components/dismiss-button/component.jsx +++ b/app/javascript/components/internal-alert/components/dismiss-button/component.jsx @@ -1,21 +1,21 @@ -import { IconButton } from "@material-ui/core"; -import CloseIcon from "@material-ui/icons/Close"; +import { IconButton } from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; import PropTypes from "prop-types"; import css from "./styles.css"; -const Component = ({ handler }) => { +function Component({ handler }) { const handlerWrapper = event => { event.stopPropagation(); handler(); }; return ( - + ); -}; +} Component.displayName = "InternalAlertDismissButton"; Component.propTypes = { diff --git a/app/javascript/components/internal-alert/components/item/component.jsx b/app/javascript/components/internal-alert/components/item/component.jsx index ed347a2715..ee75f64f51 100644 --- a/app/javascript/components/internal-alert/components/item/component.jsx +++ b/app/javascript/components/internal-alert/components/item/component.jsx @@ -4,14 +4,14 @@ import InternalAlertDismissButton from "../dismiss-button"; import css from "./styles.css"; -const Component = ({ item }) => { +function Component({ item }) { return (
{item.get("message")} {item.get("onDismiss") && InternalAlertDismissButton({ handler: item.get("onDismiss") })}
); -}; +} Component.displayName = "InternalAlertItem"; Component.propTypes = { diff --git a/app/javascript/components/internal-alert/styles.css b/app/javascript/components/internal-alert/styles.css index 15b6562d15..063839833f 100644 --- a/app/javascript/components/internal-alert/styles.css +++ b/app/javascript/components/internal-alert/styles.css @@ -80,3 +80,11 @@ .accordionTitle { align-self: center; } + +.expanded { + opacity: 1; +} + +.content :global .Mui-expanded { + margin: 0; +} diff --git a/app/javascript/components/internal-alert/theme.js b/app/javascript/components/internal-alert/theme.js deleted file mode 100644 index a78e270afe..0000000000 --- a/app/javascript/components/internal-alert/theme.js +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -// eslint-disable-next-line import/prefer-default-export -export const expansionPanelSummaryClasses = { - expanded: { opacity: 1 }, - content: { "&$expanded": { margin: 0 } } -}; diff --git a/app/javascript/components/jewel/component.jsx b/app/javascript/components/jewel/component.jsx index 96ad06a779..b087c77976 100644 --- a/app/javascript/components/jewel/component.jsx +++ b/app/javascript/components/jewel/component.jsx @@ -1,24 +1,24 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import clsx from "clsx"; -import { Brightness1 as Circle } from "@material-ui/icons"; +import { cx } from "@emotion/css"; +import { Brightness1 as Circle } from "@mui/icons-material"; import css from "./styles.css"; -const Jewel = ({ value, isForm, isList, isError }) => { - const classes = clsx(css.circleForm, css.error); +function Jewel({ value, isForm, isList, isError }) { + const classes = cx(css.circleForm, css.error); if (isList) { - return ; + return ; } if (isError && !isForm) { return ( - <> +
{value} - +
); } @@ -28,17 +28,17 @@ const Jewel = ({ value, isForm, isList, isError }) => { <> {value} {isError && } - + ) : ( -
+
{value}
)} ); -}; +} Jewel.displayName = "Jewel"; diff --git a/app/javascript/components/jewel/component.spec.js b/app/javascript/components/jewel/component.spec.js new file mode 100644 index 0000000000..6d7fcfada9 --- /dev/null +++ b/app/javascript/components/jewel/component.spec.js @@ -0,0 +1,30 @@ +import { mountedComponent, screen } from "test-utils"; + +import Jewel from "./component"; + +describe(" components/jewel", () => { + it("renders a component", () => { + const newProps = { + icon: <>, + isTransparent: false, + className: "MuiSvgIcon-root", + value: ["text"] + }; + + mountedComponent(); + expect(screen.getByTestId("jewel")).toBeInTheDocument(); + }); + + it("renders error and alert canvas", () => { + const errorProps = { + icon: <>, + isTransparent: false, + value: "Menu 1", + isForm: true, + isError: true + }; + + mountedComponent(); + expect(screen.getByTestId("error")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/jewel/component.unit.test.js b/app/javascript/components/jewel/component.unit.test.js deleted file mode 100644 index 2883d6d4ae..0000000000 --- a/app/javascript/components/jewel/component.unit.test.js +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedThemeComponent } from "../../test"; - -import Jewel from "./component"; - -describe("", () => { - it("renders canvas", () => { - const component = setupMountedThemeComponent(Jewel); - - expect(component.find("svg").length).to.equal(1); - expect(component.find("circle").length).to.equal(1); - }); - - it("renders error and alert canvas", () => { - const component = setupMountedThemeComponent(Jewel, { - value: "Menu 1", - isForm: true, - isError: true - }); - - expect(component.find("svg").length).to.equal(2); - expect(component.find("circle").length).to.equal(2); - }); -}); diff --git a/app/javascript/components/jewel/styles.css b/app/javascript/components/jewel/styles.css index 6a2cb7d146..72a65d3ea6 100644 --- a/app/javascript/components/jewel/styles.css +++ b/app/javascript/components/jewel/styles.css @@ -5,7 +5,7 @@ align-items: center; justify-content: center; line-height: 0; - + & span { color: var(--c-black); font-size: var(--fs-12); @@ -18,7 +18,7 @@ font-size: var(--fs-30); color: var(--c-yellow) !important; - &.error { + &.error { color: var(--c-red) !important; } } @@ -35,11 +35,11 @@ color: var(--c-yellow); } -@media ((min-width:960px) and (max-width:1279.95px)) { +@media ((min-width:900px) and (max-width:1200px)) { .root { position: absolute; - top: 47%; - left: 60%; + top: 13%; + left: 54%; & span { display: none; } diff --git a/app/javascript/components/key-performance-indicators/action-creators.unit.test.js b/app/javascript/components/key-performance-indicators/action-creators.unit.test.js index ce1e9e4df6..62f40109d2 100644 --- a/app/javascript/components/key-performance-indicators/action-creators.unit.test.js +++ b/app/javascript/components/key-performance-indicators/action-creators.unit.test.js @@ -1,8 +1,15 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +import { spy } from "../../test-utils"; + import forKPI from "./action-creators"; describe("KeyPerformanceIndicators - Action Creators", () => { + before(() => { + // eslint-disable-next-line no-extend-native + Date.prototype.getTimezoneOffset = spy(() => 0); + }); + it("should return a function", () => { expect(forKPI("test")).to.be.a("function"); }); diff --git a/app/javascript/components/key-performance-indicators/component.jsx b/app/javascript/components/key-performance-indicators/component.jsx index e25e897b90..21878e6ca7 100644 --- a/app/javascript/components/key-performance-indicators/component.jsx +++ b/app/javascript/components/key-performance-indicators/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { withRouter } from "react-router-dom"; -import { Grid } from "@material-ui/core"; +import { Grid } from "@mui/material"; import PageContainer, { PageHeading, PageContent } from "../page"; import { useI18n } from "../i18n"; @@ -25,7 +25,7 @@ import ClientSatisfactionRate from "./components/client-satisfaction-rate"; import SupervisorToCaseworkerRatio from "./components/supervisor-to-caseworker-ratio"; import CaseLoad from "./components/case-load"; -const KeyPerformanceIndicators = () => { +function KeyPerformanceIndicators() { const i18n = useI18n(); const commonDateRanges = CommonDateRanges.from(new Date(), i18n); @@ -184,7 +184,7 @@ const KeyPerformanceIndicators = () => {
); -}; +} KeyPerformanceIndicators.displayName = "KeyPerformanceIndicators"; diff --git a/app/javascript/components/key-performance-indicators/component.unit.test.js b/app/javascript/components/key-performance-indicators/component.unit.test.js deleted file mode 100644 index 058334b06b..0000000000 --- a/app/javascript/components/key-performance-indicators/component.unit.test.js +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../test"; -import { ACTIONS } from "../permissions"; - -import KeyPerformanceIndicators from "./component"; -import NumberOfCases from "./components/number-of-cases"; -import NumberOfIncidents from "./components/number-of-incidents"; -import ReportingDelay from "./components/reporting-delay"; -import AssessmentStatus from "./components/assessment-status"; -import CompletedCaseSafetyPlan from "./components/completed-case-action-plan"; -import CompletedCaseActionPlan from "./components/completed-case-safety-plan"; -import CompletedSupervisorApprovedCaseActionPlan from "./components/completed-supervisor-approved-case-action-plan"; -import ServicesProvided from "./components/services-provided"; -import AverageReferrals from "./components/average-referrals"; -import AverageFollowupMeetingsPerCase from "./components/average-followup-meetings-per-case"; -import TimeFromCaseOpenToClose from "./components/time-from-case-open-to-case-close"; -import CaseClosureRate from "./components/case-closure-rate"; -import ClientSatisfactionRate from "./components/client-satisfaction-rate"; -import SupervisorToCaseworkerRatio from "./components/supervisor-to-caseworker-ratio"; -import CaseLoad from "./components/case-load"; - -describe("", () => { - const { component } = setupMountedComponent( - KeyPerformanceIndicators, - {}, - fromJS({ - user: { - permissions: { - kpis: [ - ACTIONS.KPI_ASSESSMENT_STATUS, - ACTIONS.KPI_AVERAGE_FOLLOWUP_MEETINGS_PER_CASE, - ACTIONS.KPI_AVERAGE_REFERRALS, - ACTIONS.KPI_CASE_CLOSURE_RATE, - ACTIONS.KPI_CASE_LOAD, - ACTIONS.KPI_CLIENT_SATISFACTION_RATE, - ACTIONS.KPI_COMPLETED_CASE_ACTION_PLANS, - ACTIONS.KPI_COMPLETED_CASE_SAFETY_PLANS, - ACTIONS.KPI_COMPLETED_SUPERVISOR_APPROVED_CASE_ACTION_PLANS, - ACTIONS.KPI_GOAL_PROGRESS_PER_NEED, - ACTIONS.KPI_NUMBER_OF_CASES, - ACTIONS.KPI_NUMBER_OF_INCIDENTS, - ACTIONS.KPI_REPORTING_DELAY, - ACTIONS.KPI_SERVICES_PROVIDED, - ACTIONS.KPI_SUPERVISOR_TO_CASEWORKER_RATIO, - ACTIONS.KPI_TIME_FROM_CASE_OPEN_TO_CLOSE - ] - } - } - }) - ); - - it("should render the NumberOfCases KPI", () => { - expect(component.find(NumberOfCases).exists()).to.be.true; - }); - - it("should render the NumberOfIncidents KPI", () => { - expect(component.find(NumberOfIncidents).exists()).to.be.true; - }); - - it("should render the ReportingDelay KPI", () => { - expect(component.find(ReportingDelay).exists()).to.be.true; - }); - - it("should render the AssessmentStatus KPI", () => { - expect(component.find(AssessmentStatus).exists()).to.be.true; - }); - - it("should render the CompletedCaseSafetyPlan KPI", () => { - expect(component.find(CompletedCaseSafetyPlan).exists()).to.be.true; - }); - - it("should render the CompletedCaseActionPlan KPI", () => { - expect(component.find(CompletedCaseActionPlan).exists()).to.be.true; - }); - - it("should render the CompletedSupervisorApprovedCaseActionPlan KPI", () => { - expect(component.find(CompletedSupervisorApprovedCaseActionPlan).exists()).to.be.true; - }); - - it("should render the ServicesProvided KPI", () => { - expect(component.find(ServicesProvided).exists()).to.be.true; - }); - - it("should render the AverageReferrals KPI", () => { - expect(component.find(AverageReferrals).exists()).to.be.true; - }); - - it("should render the AverageFollowupMeetingsPerCase KPI", () => { - expect(component.find(AverageFollowupMeetingsPerCase).exists()).to.be.true; - }); - - it("should render the TimeFromCaseOpenToClose KPI", () => { - expect(component.find(TimeFromCaseOpenToClose).exists()).to.be.true; - }); - - it("should render the CaseClosureRate KPI", () => { - expect(component.find(CaseClosureRate).exists()).to.be.true; - }); - - it("should render the ClientSatisfactionRate KPI", () => { - expect(component.find(ClientSatisfactionRate).exists()).to.be.true; - }); - - it("should render the SupervisorToCaseworkerRatio KPI", () => { - expect(component.find(SupervisorToCaseworkerRatio).exists()).to.be.true; - }); - - it("should render the CaseLoad KPI", () => { - expect(component.find(CaseLoad).exists()).to.be.true; - }); -}); diff --git a/app/javascript/components/key-performance-indicators/components/as-key-performance-indicator/component.jsx b/app/javascript/components/key-performance-indicators/components/as-key-performance-indicator/component.jsx index 27bdca611f..3e0e076ece 100644 --- a/app/javascript/components/key-performance-indicators/components/as-key-performance-indicator/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/as-key-performance-indicator/component.jsx @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import { connect } from "react-redux"; -import { Help } from "@material-ui/icons"; +import { Help } from "@mui/icons-material"; import OptionsBox from "../../../dashboard/options-box"; import { useI18n } from "../../../i18n"; diff --git a/app/javascript/components/key-performance-indicators/components/as-key-performance-indicator/component.unit.test.js b/app/javascript/components/key-performance-indicators/components/as-key-performance-indicator/component.spec.js similarity index 65% rename from app/javascript/components/key-performance-indicators/components/as-key-performance-indicator/component.unit.test.js rename to app/javascript/components/key-performance-indicators/components/as-key-performance-indicator/component.spec.js index 90692327e2..49eb11c796 100644 --- a/app/javascript/components/key-performance-indicators/components/as-key-performance-indicator/component.unit.test.js +++ b/app/javascript/components/key-performance-indicators/components/as-key-performance-indicator/component.spec.js @@ -2,28 +2,28 @@ import { fromJS } from "immutable"; -import { setupMountedComponent } from "../../../../test"; import NAMESPACE from "../../namespace"; import CommonDateRanges from "../../utils/common-date-ranges"; +import { mountedComponent, screen } from "../../../../test-utils"; import asKeyPerformanceIndicator from "./component"; describe("asKeyPerformanceIndicator()", () => { const identifier = "test"; - const Component = () =>

Component

; + + // eslint-disable-next-line react/display-name + function Component() { + return

Component

; + } const permittedAction = "test"; const KPI = asKeyPerformanceIndicator(identifier, {}, permittedAction)(Component); - it("should return a connect function", () => { - expect(asKeyPerformanceIndicator()).to.be.a("function"); - }); - describe("A working KPI", () => { const commonDateRanges = CommonDateRanges.from(new Date(), { t: () => {} }); const dateRanges = [commonDateRanges.Last3Months]; - const { component } = setupMountedComponent( - KPI, - { dateRanges }, + + mountedComponent( + , fromJS({ records: { [NAMESPACE]: { @@ -34,8 +34,8 @@ describe("asKeyPerformanceIndicator()", () => { }) ); - it("should get data for the component from the store", () => { - expect(component.find(Component).prop("data")).to.equal("some test data"); + it.skip("should get data for the component from the store", () => { + expect(screen.getByText("some test data")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/key-performance-indicators/components/assessment-status/component.jsx b/app/javascript/components/key-performance-indicators/components/assessment-status/component.jsx index 442ace974b..88dbf35add 100644 --- a/app/javascript/components/key-performance-indicators/components/assessment-status/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/assessment-status/component.jsx @@ -7,7 +7,7 @@ import StackedPercentageBar from "../stacked-percentage-bar"; import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); return ( @@ -20,7 +20,7 @@ const Component = ({ data, identifier }) => { ]} /> ); -}; +} Component.displayName = "AssessmentStatus"; diff --git a/app/javascript/components/key-performance-indicators/components/average-followup-meetings-per-case/component.jsx b/app/javascript/components/key-performance-indicators/components/average-followup-meetings-per-case/component.jsx index ded80aa19e..553f98b2e3 100644 --- a/app/javascript/components/key-performance-indicators/components/average-followup-meetings-per-case/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/average-followup-meetings-per-case/component.jsx @@ -7,7 +7,7 @@ import SingleAggregateMetric from "../single-aggregate-metric"; import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); return ( @@ -16,7 +16,7 @@ const Component = ({ data, identifier }) => { label={i18n.t(`key_performance_indicators.${identifier}.label`)} /> ); -}; +} Component.displayName = "AverageFollowupMeetingsPerCase"; diff --git a/app/javascript/components/key-performance-indicators/components/average-referrals/component.jsx b/app/javascript/components/key-performance-indicators/components/average-referrals/component.jsx index ee5e4550b8..319d43cdef 100644 --- a/app/javascript/components/key-performance-indicators/components/average-referrals/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/average-referrals/component.jsx @@ -7,7 +7,7 @@ import SingleAggregateMetric from "../single-aggregate-metric"; import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); return ( @@ -16,7 +16,7 @@ const Component = ({ data, identifier }) => { label={i18n.t(`key_performance_indicators.${identifier}.label`)} /> ); -}; +} Component.displayName = "AverageReferrals"; diff --git a/app/javascript/components/key-performance-indicators/components/case-closure-rate/component.jsx b/app/javascript/components/key-performance-indicators/components/case-closure-rate/component.jsx index bba12e9127..902dde598d 100644 --- a/app/javascript/components/key-performance-indicators/components/case-closure-rate/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/case-closure-rate/component.jsx @@ -7,7 +7,7 @@ import KpiTable from "../kpi-table"; import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); const columns = [ @@ -31,7 +31,7 @@ const Component = ({ data, identifier }) => { const rows = data.get("data").map(row => columns.map(column => row.get(column.name))); return ; -}; +} Component.displayName = "CaseClosureRate"; diff --git a/app/javascript/components/key-performance-indicators/components/case-load/component.jsx b/app/javascript/components/key-performance-indicators/components/case-load/component.jsx index 7d1b950731..c5de455c2e 100644 --- a/app/javascript/components/key-performance-indicators/components/case-load/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/case-load/component.jsx @@ -7,7 +7,7 @@ import KpiTable from "../kpi-table"; import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); const columns = [ @@ -26,7 +26,7 @@ const Component = ({ data, identifier }) => { const rows = data.get("data").map(row => columns.map(column => column.transform(row.get(column.name)))); return ; -}; +} Component.displayName = "CaseLoad"; diff --git a/app/javascript/components/key-performance-indicators/components/client-satisfaction-rate/component.jsx b/app/javascript/components/key-performance-indicators/components/client-satisfaction-rate/component.jsx index 3dba84b674..99193dce97 100644 --- a/app/javascript/components/key-performance-indicators/components/client-satisfaction-rate/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/client-satisfaction-rate/component.jsx @@ -9,7 +9,7 @@ import { ACTIONS } from "../../../permissions"; import css from "./styles.css"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); const rate = data.get("data").get("satisfaction_rate"); @@ -27,7 +27,7 @@ const Component = ({ data, identifier }) => { ]} /> ); -}; +} Component.displayName = "ClientSatisfactionRate"; diff --git a/app/javascript/components/key-performance-indicators/components/completed-case-action-plan/component.jsx b/app/javascript/components/key-performance-indicators/components/completed-case-action-plan/component.jsx index 4bac86490f..fc2eee7901 100644 --- a/app/javascript/components/key-performance-indicators/components/completed-case-action-plan/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/completed-case-action-plan/component.jsx @@ -7,7 +7,7 @@ import StackedPercentageBar from "../stacked-percentage-bar"; import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); return ( @@ -20,7 +20,7 @@ const Component = ({ data, identifier }) => { ]} /> ); -}; +} Component.displayName = "CompletedCaseActionPlan"; diff --git a/app/javascript/components/key-performance-indicators/components/completed-case-safety-plan/component.jsx b/app/javascript/components/key-performance-indicators/components/completed-case-safety-plan/component.jsx index 6024e54a5f..052e7f0b63 100644 --- a/app/javascript/components/key-performance-indicators/components/completed-case-safety-plan/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/completed-case-safety-plan/component.jsx @@ -7,7 +7,7 @@ import StackedPercentageBar from "../stacked-percentage-bar"; import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); return ( @@ -20,7 +20,7 @@ const Component = ({ data, identifier }) => { ]} /> ); -}; +} Component.displayName = "CompletedCaseSafetyPlan"; diff --git a/app/javascript/components/key-performance-indicators/components/completed-supervisor-approved-case-action-plan/component.jsx b/app/javascript/components/key-performance-indicators/components/completed-supervisor-approved-case-action-plan/component.jsx index 5fbcb690d9..d1d6ac6d84 100644 --- a/app/javascript/components/key-performance-indicators/components/completed-supervisor-approved-case-action-plan/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/completed-supervisor-approved-case-action-plan/component.jsx @@ -7,7 +7,7 @@ import StackedPercentageBar from "../stacked-percentage-bar"; import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); return ( @@ -20,7 +20,7 @@ const Component = ({ data, identifier }) => { ]} /> ); -}; +} Component.displayName = "CompletedSupervisorApprovedCaseActionPlan"; diff --git a/app/javascript/components/key-performance-indicators/components/date-range-dialog/component.jsx b/app/javascript/components/key-performance-indicators/components/date-range-dialog/component.jsx index 0c1b774357..e90359b82a 100644 --- a/app/javascript/components/key-performance-indicators/components/date-range-dialog/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/date-range-dialog/component.jsx @@ -10,14 +10,14 @@ import { FormControl, DialogActions, Button -} from "@material-ui/core"; -import { KeyboardDatePicker, MuiPickersUtilsProvider } from "@material-ui/pickers"; -import DateFnsUtils from "@date-io/date-fns"; +} from "@mui/material"; +import { DatePicker } from "@mui/x-date-pickers"; import { useI18n } from "../../../i18n"; -import { DATE_FORMAT } from "../../../../config/constants"; +import { DATE_FORMAT } from "../../../../config"; +import DateProvider from "../../../../date-provider"; -const Component = ({ open, onClose, currentRange, setRange }) => { +function Component({ open, onClose, currentRange, setRange }) { const i18n = useI18n(); const [from, setFrom] = useState(currentRange.from); const [to, setTo] = useState(currentRange.to); @@ -35,8 +35,8 @@ const Component = ({ open, onClose, currentRange, setRange }) => { {i18n.t("key_performance_indicators.date_range_dialog.description")} - - + { "aria-label": i18n.t("key_performance_indicators.date_range_dialog.aria-labels.from") }} /> - { "aria-label": i18n.t("key_performance_indicators.date_range_dialog.aria-labels.to") }} /> - + @@ -68,7 +68,7 @@ const Component = ({ open, onClose, currentRange, setRange }) => { ); -}; +} Component.displayName = "DateRangeDialog"; diff --git a/app/javascript/components/key-performance-indicators/components/date-range-dialog/component.spec.js b/app/javascript/components/key-performance-indicators/components/date-range-dialog/component.spec.js new file mode 100644 index 0000000000..c93c44179d --- /dev/null +++ b/app/javascript/components/key-performance-indicators/components/date-range-dialog/component.spec.js @@ -0,0 +1,92 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { format } from "date-fns"; + +import { fireEvent, mountedComponent, screen } from "../../../../test-utils"; +import { DATE_FORMAT } from "../../../../config"; + +import DateRangeDialog from "./component"; + +describe("", () => { + const currentRange = { + from: new Date(), + to: new Date() + }; + + it("should render dialog content when open", () => { + mountedComponent( + + ); + + expect(screen.queryByRole("dialog")).toBeInTheDocument(); + }); + + it("shouldn't render dialog content when closed", () => { + mountedComponent( + + ); + + expect(screen.queryByRole("dialog")).not.toBeInTheDocument(); + }); + + it("should call onClose when the dialog is closed", () => { + const onClose = jest.fn(); + + mountedComponent( + + ); + + fireEvent.click(document.querySelector(".MuiBackdrop-root")); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + + it("should render the currentRange", () => { + mountedComponent( + + ); + + expect(screen.getAllByDisplayValue(format(currentRange.to, DATE_FORMAT)).at(0)).toBeInTheDocument(); + expect(screen.getAllByDisplayValue(format(currentRange.from, DATE_FORMAT)).at(1)).toBeInTheDocument(); + }); + + it("should call setRange when Button is clicked", () => { + const setRange = jest.fn(); + + mountedComponent( + {}, + setRange + }} + /> + ); + + fireEvent.click(screen.getAllByRole("button").at(0)); + + expect(setRange).toHaveBeenCalledTimes(1); + }); +}); diff --git a/app/javascript/components/key-performance-indicators/components/date-range-dialog/component.unit.test.js b/app/javascript/components/key-performance-indicators/components/date-range-dialog/component.unit.test.js deleted file mode 100644 index 520a04ac37..0000000000 --- a/app/javascript/components/key-performance-indicators/components/date-range-dialog/component.unit.test.js +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { DialogContent, Button } from "@material-ui/core"; -import { KeyboardDatePicker } from "@material-ui/pickers"; - -import { spy, setupMountedComponent } from "../../../../test"; - -import DateRangeDialog from "./component"; - -describe("", () => { - const currentRange = { - from: new Date(), - to: new Date() - }; - - it("should render dialog content when open", () => { - const { component } = setupMountedComponent(DateRangeDialog, { - open: true, - currentRange - }); - - expect(component.find(DialogContent)).to.have.length(1); - }); - - it("shouldn't render dialog content when closed", () => { - const { component } = setupMountedComponent(DateRangeDialog, { - open: false, - currentRange - }); - - expect(component.find(DialogContent)).to.have.length(0); - }); - - it("should call onClose when the dialog is closed", () => { - const onClose = spy(); - const { component } = setupMountedComponent(DateRangeDialog, { - open: true, - currentRange, - onClose - }); - - component.find(".MuiBackdrop-root").simulate("click"); - - expect(onClose).to.have.property("callCount", 1); - }); - - it("should render the currentRange", () => { - const { component } = setupMountedComponent(DateRangeDialog, { - open: true, - currentRange - }); - - const datePickers = component.find(KeyboardDatePicker); - - expect(datePickers.find({ value: currentRange.from }).exists()).to.be.true; - expect(datePickers.find({ value: currentRange.to }).exists()).to.be.true; - }); - - it("should call setRange when Button is clicked", () => { - const setRange = spy(); - const { component } = setupMountedComponent(DateRangeDialog, { - open: true, - currentRange, - onClose: () => {}, - setRange - }); - - component.find(Button).simulate("click"); - - expect(setRange).to.have.property("callCount", 1); - }); -}); diff --git a/app/javascript/components/key-performance-indicators/components/date-range-select/component.jsx b/app/javascript/components/key-performance-indicators/components/date-range-select/component.jsx index 0367a3f1a1..a1b435e436 100644 --- a/app/javascript/components/key-performance-indicators/components/date-range-select/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/date-range-select/component.jsx @@ -2,14 +2,14 @@ import { useState } from "react"; import PropTypes from "prop-types"; -import { Select, MenuItem, FormControl } from "@material-ui/core"; +import { Select, MenuItem, FormControl } from "@mui/material"; import DateRangeDialog from "../date-range-dialog"; import DateRange from "../../utils/date-range"; import { CUSTOM_RANGE } from "./constants"; -const Component = ({ ranges, selectedRange, withCustomRange, setSelectedRange, disabled, i18n }) => { +function Component({ ranges, selectedRange, withCustomRange, setSelectedRange, disabled, i18n }) { const [showRangePicker, setShowRangePicker] = useState(false); const [customRange, setCustomRange] = useState( @@ -88,7 +88,7 @@ const Component = ({ ranges, selectedRange, withCustomRange, setSelectedRange, d /> ); -}; +} Component.displayName = "DateRangeSelect"; diff --git a/app/javascript/components/key-performance-indicators/components/date-range-select/component.unit.test.js b/app/javascript/components/key-performance-indicators/components/date-range-select/component.spec.js similarity index 62% rename from app/javascript/components/key-performance-indicators/components/date-range-select/component.unit.test.js rename to app/javascript/components/key-performance-indicators/components/date-range-select/component.spec.js index 6068e8c70c..43b07897e1 100644 --- a/app/javascript/components/key-performance-indicators/components/date-range-select/component.unit.test.js +++ b/app/javascript/components/key-performance-indicators/components/date-range-select/component.spec.js @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import CommonDateRanges from "../../utils/common-date-ranges"; -import { setupMountedComponent } from "../../../../test"; +import { mountedComponent } from "../../../../test-utils"; import DateRangeSelect from "./component"; @@ -13,17 +13,19 @@ describe("", () => { const selectedRange = commonDateRanges.Last3Months; - it("should display the given set of ranges"); + it.todo("should display the given set of ranges"); it("should show the selected range", () => { - const { component } = setupMountedComponent(DateRangeSelect, { + const props = { ranges, selectedRange, i18n - }); + }; - expect(component.find(`input[value="${selectedRange.value}"]`).exists()).to.be.true; + mountedComponent(); + + expect(document.querySelector(`input[value="${selectedRange.value}"]`)).toBeInTheDocument(); }); - it("should display a custom range when withCustomRange is set"); + it.todo("should display a custom range when withCustomRange is set"); }); diff --git a/app/javascript/components/key-performance-indicators/components/goal-progress-per-need/component.jsx b/app/javascript/components/key-performance-indicators/components/goal-progress-per-need/component.jsx index ec7459264a..71171b62b2 100644 --- a/app/javascript/components/key-performance-indicators/components/goal-progress-per-need/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/goal-progress-per-need/component.jsx @@ -8,7 +8,7 @@ import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import PercentageCell from "../percentage-cell"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); const columns = [ { @@ -27,7 +27,7 @@ const Component = ({ data, identifier }) => { const rows = data.get("data").map(row => columns.map(column => row.get(column.name))); return ; -}; +} Component.displayName = "GoalProgressPerNeed"; diff --git a/app/javascript/components/key-performance-indicators/components/kpi-table/component.jsx b/app/javascript/components/key-performance-indicators/components/kpi-table/component.jsx index 7ad70edb8c..309ee0d5de 100644 --- a/app/javascript/components/key-performance-indicators/components/kpi-table/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/kpi-table/component.jsx @@ -7,7 +7,9 @@ import { DashboardTable } from "../../../dashboard"; // Simple wrapper over DashboardTable to insulate Kpis from future // changes to serve the Dashbaord needs. Can be migrated to MUIDataTable // at some point when the needs differ enough. -const Component = ({ columns, data }) => ; +function Component({ columns, data }) { + return ; +} Component.displayName = "KpiTable"; diff --git a/app/javascript/components/key-performance-indicators/components/number-of-cases/component.jsx b/app/javascript/components/key-performance-indicators/components/number-of-cases/component.jsx index 67645ed902..d8449c37b0 100644 --- a/app/javascript/components/key-performance-indicators/components/number-of-cases/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/number-of-cases/component.jsx @@ -7,7 +7,7 @@ import KpiTable from "../kpi-table"; import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); const columns = [ @@ -31,7 +31,7 @@ const Component = ({ data, identifier }) => { const rows = data.get("data").map(row => columns.map(column => row.get(column.name))); return ; -}; +} Component.displayName = "NumberOfCases"; diff --git a/app/javascript/components/key-performance-indicators/components/number-of-incidents/component.jsx b/app/javascript/components/key-performance-indicators/components/number-of-incidents/component.jsx index 40f1f1be16..3c0b0d5b44 100644 --- a/app/javascript/components/key-performance-indicators/components/number-of-incidents/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/number-of-incidents/component.jsx @@ -7,7 +7,7 @@ import KpiTable from "../kpi-table"; import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); const columns = [ { @@ -30,7 +30,7 @@ const Component = ({ data, identifier }) => { const rows = data.get("data").map(row => columns.map(column => row.get(column.name))); return ; -}; +} Component.displayName = "NumberOfIncidents"; diff --git a/app/javascript/components/key-performance-indicators/components/percentage-cell/component.jsx b/app/javascript/components/key-performance-indicators/components/percentage-cell/component.jsx index 0dfed2ac3f..edfa0b46a1 100644 --- a/app/javascript/components/key-performance-indicators/components/percentage-cell/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/percentage-cell/component.jsx @@ -2,9 +2,9 @@ import TablePercentageBar from "../table-percentage-bar"; -const Component = value => { +function Component(value) { return ; -}; +} Component.displayName = "PercentageCell"; diff --git a/app/javascript/components/key-performance-indicators/components/reporting-delay/component.jsx b/app/javascript/components/key-performance-indicators/components/reporting-delay/component.jsx index a15bb1d7bc..0ae0d93759 100644 --- a/app/javascript/components/key-performance-indicators/components/reporting-delay/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/reporting-delay/component.jsx @@ -8,7 +8,7 @@ import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import PercentageCell from "../percentage-cell"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); const columns = [ @@ -38,7 +38,7 @@ const Component = ({ data, identifier }) => { }); return ; -}; +} Component.displayName = "ReportingDelay"; diff --git a/app/javascript/components/key-performance-indicators/components/services-provided/component.jsx b/app/javascript/components/key-performance-indicators/components/services-provided/component.jsx index 589fe4cf5b..993e3eedca 100644 --- a/app/javascript/components/key-performance-indicators/components/services-provided/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/services-provided/component.jsx @@ -7,7 +7,7 @@ import KpiTable from "../kpi-table"; import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); const toColumn = name => ({ @@ -33,7 +33,7 @@ const Component = ({ data, identifier }) => { .map(row => columns.map(column => row.get(column.name))); return ; -}; +} Component.displayName = "ServicesProvided"; diff --git a/app/javascript/components/key-performance-indicators/components/single-aggregate-metric/component.jsx b/app/javascript/components/key-performance-indicators/components/single-aggregate-metric/component.jsx index 46d5e9ff23..c8c8ca3b40 100644 --- a/app/javascript/components/key-performance-indicators/components/single-aggregate-metric/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/single-aggregate-metric/component.jsx @@ -4,7 +4,7 @@ import PropTypes from "prop-types"; import css from "./styles.css"; -const Component = ({ value, label }) => { +function Component({ value, label }) { const shouldTrucate = value?.toFixed && value.toString().indexOf(".") > -1; const displayValue = shouldTrucate ? value.toFixed(1) : value; @@ -14,7 +14,7 @@ const Component = ({ value, label }) => { {label}
); -}; +} Component.displayName = "SingleAggregateMetric"; diff --git a/app/javascript/components/key-performance-indicators/components/single-aggregate-metric/component.spec.js b/app/javascript/components/key-performance-indicators/components/single-aggregate-metric/component.spec.js new file mode 100644 index 0000000000..4f51f7bf60 --- /dev/null +++ b/app/javascript/components/key-performance-indicators/components/single-aggregate-metric/component.spec.js @@ -0,0 +1,26 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { mountedComponent, screen } from "../../../../test-utils"; + +import SingleAggregateMetric from "./component"; + +describe("", () => { + it("Should display the given label", () => { + mountedComponent(); + + expect(screen.getByText("Test")).toBeInTheDocument(); + }); + + it("should display the given value", () => { + mountedComponent( + + ); + + expect(screen.getByText("50")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/key-performance-indicators/components/single-aggregate-metric/component.unit.test.js b/app/javascript/components/key-performance-indicators/components/single-aggregate-metric/component.unit.test.js deleted file mode 100644 index f7fe7dd759..0000000000 --- a/app/javascript/components/key-performance-indicators/components/single-aggregate-metric/component.unit.test.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../test"; - -import SingleAggregateMetric from "./component"; - -describe("", () => { - it("Should display the given label", () => { - const { component } = setupMountedComponent(SingleAggregateMetric, { - label: "Test" - }); - - expect(component.render().text()).to.equal("Test"); - }); - - it("should display the given value", () => { - const { component } = setupMountedComponent(SingleAggregateMetric, { - label: "Test", - value: 50 - }); - - expect(component.render().text()).to.contain("50"); - }); -}); diff --git a/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/component.jsx b/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/component.jsx index 9f6d062971..b9dd42ee82 100644 --- a/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/component.jsx @@ -6,7 +6,7 @@ import css from "./styles.css"; import StackedPercentageBarMeter from "./components/stacked-percentage-bar-meter"; import StackedPercentageBarLabel from "./components/stacked-percentage-bar-label"; -const Component = ({ percentages, className }) => { +function Component({ percentages, className }) { if (percentages.length > 2) throw new Error("StackedPercentageBar components only support a max of 2 percentages"); const percentagedToRender = percentages.filter(descriptor => descriptor.percentage > 0); @@ -36,7 +36,7 @@ const Component = ({ percentages, className }) => {
); -}; +} Component.displayName = "StackedPercentageBar"; diff --git a/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/component.spec.js b/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/component.spec.js new file mode 100644 index 0000000000..c654520208 --- /dev/null +++ b/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/component.spec.js @@ -0,0 +1,93 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { mountedComponent, screen } from "../../../../test-utils"; + +import StackedPercentageBar from "./component"; + +describe("", () => { + describe("with a single percentage", () => { + beforeEach(() => { + mountedComponent( + + ); + }); + + it("should display the label", () => { + expect(screen.getByText("Tests")).toBeInTheDocument(); + }); + + it("should display the percentage", () => { + expect(screen.getByText("50%")).toBeInTheDocument(); + }); + }); + + describe("with 2 percentages", () => { + const percentage0 = { percentage: 0, label: "Shrödinger's Tests" }; + const percentage1 = { percentage: 0.35, label: "Passed" }; + const percentage2 = { percentage: 0.147, label: "Failed" }; + + describe("where 1 percentage is 0%", () => { + beforeEach(() => { + mountedComponent( + + ); + }); + + it("should display percentage bars when the percentage is > 0", () => { + expect(document.querySelectorAll(".StackedPercentageBarLabelContainer")[1]).toHaveStyle({ width: "35%" }); + }); + + it("should not display a percentage bar for percentages <= 0", () => { + expect(document.querySelectorAll(".StackedPercentageBarLabelContainer")[0]).toHaveStyle({ width: "auto" }); + }); + }); + + describe("where both percentages are > 0", () => { + beforeEach(() => { + mountedComponent( + + ); + }); + + it("it shows percentage1", () => { + expect(screen.getByText(percentage1.label)).toBeInTheDocument(); + expect(document.querySelectorAll(".StackedPercentageBarLabelContainer")[0]).toHaveStyle({ width: "35%" }); + }); + + it("should show percentage2", () => { + expect(screen.getByText(percentage2.label)).toBeInTheDocument(); + expect(document.querySelectorAll(".StackedPercentageBarLabelContainer")[1]).toHaveStyle({ width: "14.7%" }); + }); + }); + + it("should error when >2 percentages are passed", () => { + const render = () => + mountedComponent( + + ); + + expect(render).toThrow(); + }); + }); +}); diff --git a/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/component.unit.test.js b/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/component.unit.test.js deleted file mode 100644 index 1d663d6739..0000000000 --- a/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/component.unit.test.js +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../test"; - -import StackedPercentageBar from "./component"; - -describe("", () => { - describe("with a single percentage", () => { - const { component } = setupMountedComponent(StackedPercentageBar, { - percentages: [ - { - percentage: 0.5, - label: "Tests" - } - ] - }); - - it("should display the label", () => { - expect(component.render().text()).to.contain("Tests"); - }); - - it("should display the percentage", () => { - expect(component.render().text()).to.contain("50%"); - }); - }); - - describe("with 2 percentages", () => { - const percentage0 = { percentage: 0, label: "Shrödinger's Tests" }; - const percentage1 = { percentage: 0.35, label: "Passed" }; - const percentage2 = { percentage: 0.147, label: "Failed" }; - - describe("where 1 percentage is 0%", () => { - const { component } = setupMountedComponent(StackedPercentageBar, { - percentages: [percentage0, percentage1] - }); - - it("should display percentage bars when the percentage is > 0", () => { - expect(component.html()).to.contain('style="width: 35%;"'); - }); - - it("should not display a percentage bar for percentages <= 0", () => { - expect(component.html()).not.to.contain('style="width: 0%;"'); - }); - }); - - describe("where both percentages are > 0", () => { - const { component } = setupMountedComponent(StackedPercentageBar, { - percentages: [percentage1, percentage2] - }); - - it("it shows percentage1", () => { - expect(component.render().text()).to.contain(percentage1.label); - expect(component.html()).to.contain('style="width: 35%;"'); - }); - - it("should show percentage2", () => { - expect(component.render().text()).to.contain(percentage2.label); - expect(component.html()).to.contain('style="width: 14.7%;"'); - }); - }); - - it("should error when >2 percentages are passed", () => { - const render = () => { - setupMountedComponent(StackedPercentageBar, { - percentages: [percentage0, percentage1, percentage2] - }); - }; - - expect(render).to.throw(); - }); - }); -}); diff --git a/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/components/stacked-percentage-bar-label/component.jsx b/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/components/stacked-percentage-bar-label/component.jsx index 3cf8593be7..92831f5fa7 100644 --- a/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/components/stacked-percentage-bar-label/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/components/stacked-percentage-bar-label/component.jsx @@ -2,7 +2,7 @@ import PropTypes from "prop-types"; -const Component = ({ realPercent, label, index, css }) => { +function Component({ realPercent, label, index, css }) { const percentage = realPercent * 100; const style = { width: percentage > 0 ? `${percentage}%` : "auto" }; @@ -14,7 +14,7 @@ const Component = ({ realPercent, label, index, css }) => {
{label}
); -}; +} Component.displayName = "StackedPercentageBarLabel"; diff --git a/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/components/stacked-percentage-bar-meter/component.jsx b/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/components/stacked-percentage-bar-meter/component.jsx index 30f4cc1102..5250ae6fc7 100644 --- a/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/components/stacked-percentage-bar-meter/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/stacked-percentage-bar/components/stacked-percentage-bar-meter/component.jsx @@ -2,12 +2,12 @@ import PropTypes from "prop-types"; -const Component = ({ realPercent, index, css }) => { +function Component({ realPercent, index, css }) { const percentage = realPercent * 100; const style = { width: `${percentage}%` }; return
; -}; +} Component.displayName = "StackedPercentageBarMeter"; diff --git a/app/javascript/components/key-performance-indicators/components/supervisor-to-caseworker-ratio/component.jsx b/app/javascript/components/key-performance-indicators/components/supervisor-to-caseworker-ratio/component.jsx index abdd35e410..18b2f4bfca 100644 --- a/app/javascript/components/key-performance-indicators/components/supervisor-to-caseworker-ratio/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/supervisor-to-caseworker-ratio/component.jsx @@ -7,7 +7,7 @@ import SingleAggregateMetric from "../single-aggregate-metric"; import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); const supervisors = data.get("data").get("supervisors"); const caseWorkers = data.get("data").get("case_workers"); @@ -18,7 +18,7 @@ const Component = ({ data, identifier }) => { label={i18n.t(`key_performance_indicators.${identifier}.label`)} /> ); -}; +} Component.displayName = "SupervisorToCaseworkerRatio"; diff --git a/app/javascript/components/key-performance-indicators/components/table-percentage-bar/component.jsx b/app/javascript/components/key-performance-indicators/components/table-percentage-bar/component.jsx index a1b96061cd..2fb2aec9f2 100644 --- a/app/javascript/components/key-performance-indicators/components/table-percentage-bar/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/table-percentage-bar/component.jsx @@ -4,7 +4,7 @@ import PropTypes from "prop-types"; import css from "./styles.css"; -const Component = ({ percentage, className }) => { +function Component({ percentage, className }) { const percentageValue = percentage * 100; const isSmall = percentage < 0.1; @@ -22,7 +22,7 @@ const Component = ({ percentage, className }) => {
); -}; +} Component.displayName = "TablePercentageBar"; diff --git a/app/javascript/components/key-performance-indicators/components/table-percentage-bar/component.spec.js b/app/javascript/components/key-performance-indicators/components/table-percentage-bar/component.spec.js new file mode 100644 index 0000000000..adfadccd65 --- /dev/null +++ b/app/javascript/components/key-performance-indicators/components/table-percentage-bar/component.spec.js @@ -0,0 +1,21 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { mountedComponent, screen } from "../../../../test-utils"; + +import TablePercentageBar from "./component"; + +describe("", () => { + it("should display the percentage", () => { + mountedComponent(); + + expect(screen.getByText("50%")).toBeInTheDocument(); + }); + + describe("when the percentage is small (< 10%)", () => { + it("should display the percentage outside of the bar", () => { + mountedComponent(); + + expect(screen.getByText("1%")).toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/key-performance-indicators/components/table-percentage-bar/component.unit.test.js b/app/javascript/components/key-performance-indicators/components/table-percentage-bar/component.unit.test.js deleted file mode 100644 index 5074f1795b..0000000000 --- a/app/javascript/components/key-performance-indicators/components/table-percentage-bar/component.unit.test.js +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../test"; - -import TablePercentageBar from "./component"; - -describe("", () => { - it("should display the percentage", () => { - const { component } = setupMountedComponent(TablePercentageBar, { - percentage: 0.5 - }); - - expect(component.render().html()).to.contain("50%"); - }); - - describe("when the percentage is small (< 10%)", () => { - it("should display the percentage outside of the bar", () => { - const { component } = setupMountedComponent(TablePercentageBar, { - percentage: 0.01 - }); - - const bar = component.find("div > div > div"); - - expect(bar.html()).to.contain("1%"); - }); - }); -}); diff --git a/app/javascript/components/key-performance-indicators/components/time-from-case-open-to-case-close/component.jsx b/app/javascript/components/key-performance-indicators/components/time-from-case-open-to-case-close/component.jsx index 96058de4e3..dfed5bf702 100644 --- a/app/javascript/components/key-performance-indicators/components/time-from-case-open-to-case-close/component.jsx +++ b/app/javascript/components/key-performance-indicators/components/time-from-case-open-to-case-close/component.jsx @@ -7,7 +7,7 @@ import KpiTable from "../kpi-table"; import asKeyPerformanceIndicator from "../as-key-performance-indicator"; import { ACTIONS } from "../../../permissions"; -const Component = ({ data, identifier }) => { +function Component({ data, identifier }) { const i18n = useI18n(); const columns = [ @@ -26,7 +26,7 @@ const Component = ({ data, identifier }) => { const rows = data.get("data").map(row => columns.map(column => column.transform(row.get(column.name)))); return ; -}; +} Component.displayName = "TimeFromCaseOpenToClose"; diff --git a/app/javascript/components/layouts/component.jsx b/app/javascript/components/layouts/component.jsx index fe63f0c492..dc0e0885c8 100644 --- a/app/javascript/components/layouts/component.jsx +++ b/app/javascript/components/layouts/component.jsx @@ -4,13 +4,13 @@ import PropTypes from "prop-types"; import CustomSnackbarProvider from "../custom-snackbar-provider"; -const Component = ({ layout: Layout, children }) => { +function Component({ layout: Layout, children }) { return ( {children} ); -}; +} Component.propTypes = { children: PropTypes.node, diff --git a/app/javascript/components/layouts/components/app-layout/component.jsx b/app/javascript/components/layouts/components/app-layout/component.jsx index f739f15109..53f342ae72 100644 --- a/app/javascript/components/layouts/components/app-layout/component.jsx +++ b/app/javascript/components/layouts/components/app-layout/component.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. /* eslint-disable react/no-multi-comp, react/display-name */ -import clsx from "clsx"; -import { CircularProgress } from "@material-ui/core"; +import { cx } from "@emotion/css"; +import { CircularProgress } from "@mui/material"; import PropTypes from "prop-types"; import Nav from "../../../nav"; @@ -18,13 +18,13 @@ import usePushNotifications from "../../../push-notifications-toggle/use-push-no import { NAME } from "./constants"; import css from "./styles.css"; -const Component = ({ children }) => { +function Component({ children }) { const { demo } = useApp(); usePushNotifications(); - const classes = clsx({ [css.root]: true, [css.demo]: demo }); - const contentClasses = clsx({ [css.content]: true, [css.demo]: demo }); + const classes = cx({ [css.root]: true, [css.demo]: demo }); + const contentClasses = cx({ [css.content]: true, [css.demo]: demo }); const hasPermissions = useMemoizedSelector(state => hasUserPermissions(state)); @@ -48,7 +48,7 @@ const Component = ({ children }) => {
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/layouts/components/app-layout/component.spec.js b/app/javascript/components/layouts/components/app-layout/component.spec.js new file mode 100644 index 0000000000..fba774b904 --- /dev/null +++ b/app/javascript/components/layouts/components/app-layout/component.spec.js @@ -0,0 +1,152 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen, userEvent, stub } from "../../../../test-utils"; + +import AppLayout from "./component"; + +describe("", () => { + describe("if hasUserPermissions is true", () => { + const state = fromJS({ + ui: { + Nav: { + drawerOpen: true + } + }, + user: { + modules: "primero", + agency: "unicef", + isAuthenticated: true, + messages: null, + permissions: { + incidents: ["manage"], + tracing_requests: ["manage"], + cases: ["manage"] + } + }, + application: { + baseLanguage: "en", + primero: { + sandbox_ui: true + }, + modules: [ + { + unique_id: "primeromodule-cp", + name: "CP", + associated_record_types: ["case"] + } + ] + }, + records: { + support: { + data: { + demo: true + } + } + } + }); + + it("renders navigation", () => { + mountedComponent(, state); + expect(screen.getAllByAltText("Primero")).toHaveLength(3); + expect(screen.getAllByRole("img", { className: "logo" })).toHaveLength(2); + }); + + it("navigate to cases list", async () => { + const user = userEvent.setup(); + const { history } = mountedComponent(, state); + + expect(screen.getAllByText("navigation.cases", { selector: "span" })).toHaveLength(2); + await user.click(screen.getAllByText("navigation.cases")[0]); + expect(history.location.pathname).toBe("/cases"); + }); + + it("renders DemoIndicator component", () => { + mountedComponent(, state); + expect(screen.queryAllByText(/sandbox_ui/i)).toHaveLength(2); + }); + }); + + describe("if hasUserPermissions is false", () => { + const state = fromJS({ + ui: { + Nav: { + drawerOpen: true + } + }, + user: { + module: "primero", + agency: "unicef", + isAuthenticated: true, + messages: null + }, + application: { + baseLanguage: "en" + } + }); + + it("should render CircularProgress", () => { + mountedComponent(, state); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); + }); + + it("renders DemoIndicator component", () => { + mountedComponent(, state); + expect(screen.queryAllByText(/sandbox_ui/i)).toHaveLength(0); + }); + }); + + describe("when the mobile is displayed", () => { + beforeEach(() => { + stub(window, "matchMedia").returns(window.defaultMediaQueryList({ matches: true })); + }); + + it("should not render the DemoIndicator", () => { + const initialState = fromJS({ + ui: { + Nav: { + drawerOpen: false + } + }, + user: { + modules: "primero", + agency: "unicef", + isAuthenticated: true, + messages: null, + permissions: { + incidents: ["manage"], + tracing_requests: ["manage"], + cases: ["manage"] + } + }, + application: { + baseLanguage: "en", + modules: [ + { + unique_id: "primeromodule-cp", + name: "CP", + associated_record_types: ["case"] + } + ], + primero: { + sandbox_ui: false + } + }, + records: { + support: { + data: { + demo: true + } + } + } + }); + + mountedComponent(, initialState); + + expect(screen.queryAllByText(/sandbox_ui/i)).toHaveLength(0); + }); + + afterEach(() => { + window.matchMedia.restore(); + }); + }); +}); diff --git a/app/javascript/components/layouts/components/app-layout/component.unit.test.js b/app/javascript/components/layouts/components/app-layout/component.unit.test.js deleted file mode 100644 index b97915f2ad..0000000000 --- a/app/javascript/components/layouts/components/app-layout/component.unit.test.js +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { CircularProgress } from "@material-ui/core"; -import Alert from "@material-ui/lab/Alert"; - -import { routes } from "../../../../config"; -import { setupMountedComponent, stub } from "../../../../test"; -import Nav from "../../../nav"; -import DemoIndicator from "../../../demo-indicator"; - -import AppLayout from "./component"; - -describe("layouts/components/", () => { - let component; - - describe("if hasUserPermissions is true", () => { - beforeEach(() => { - const state = fromJS({ - ui: { - Nav: { - drawerOpen: true - } - }, - user: { - modules: "primero", - agency: "unicef", - isAuthenticated: true, - messages: null, - permissions: { - incidents: ["manage"], - tracing_requests: ["manage"], - cases: ["manage"] - } - }, - application: { - baseLanguage: "en", - modules: [ - { - unique_id: "primeromodule-cp", - name: "CP", - associated_record_types: ["case"] - } - ] - }, - records: { - support: { - data: { - demo: true - } - } - } - }); - - component = setupMountedComponent(AppLayout, { route: routes[0] }, state, ["/cases"]).component; - }); - - it("renders navigation", () => { - expect(component.find(Nav)).to.have.lengthOf(1); - }); - - // TODO: Need to figure out how to better test - it.skip("navigates to incidents list", () => { - component.find('a[href="/incidents"]').at(1).simulate("click", { button: 0 }); - expect(component.find('a[href="/incidents"]').at(1).hasClass("active")).to.equal(true); - }); - - it("renders DemoIndicator component", () => { - expect(component.find(DemoIndicator)).to.have.lengthOf(1); - }); - }); - - describe("if hasUserPermissions is false", () => { - beforeEach(() => { - const state = fromJS({ - ui: { - Nav: { - drawerOpen: true - } - }, - user: { - module: "primero", - agency: "unicef", - isAuthenticated: true, - messages: null - }, - application: { - baseLanguage: "en" - } - }); - - component = setupMountedComponent(AppLayout, { route: routes[0] }, state, ["/cases"]).component; - }); - - it("should render CircularProgress", () => { - expect(component.find(CircularProgress)).to.have.lengthOf(1); - }); - - it("should not render DemoIndicator component", () => { - expect(component.find(DemoIndicator)).to.be.empty; - }); - }); - - describe("when the mobile is displayed", () => { - beforeEach(() => { - stub(window, "matchMedia").returns(window.defaultMediaQueryList({ matches: true })); - }); - - it("should not render the DemoIndicator alert", () => { - const initialState = fromJS({ - ui: { - Nav: { - drawerOpen: false - } - }, - user: { - modules: "primero", - agency: "unicef", - isAuthenticated: true, - messages: null, - permissions: { - incidents: ["manage"], - tracing_requests: ["manage"], - cases: ["manage"] - } - }, - application: { - baseLanguage: "en", - modules: [ - { - unique_id: "primeromodule-cp", - name: "CP", - associated_record_types: ["case"] - } - ], - primero: { - sandbox_ui: true - } - }, - records: { - support: { - data: { - demo: true - } - } - } - }); - - const { component: appLayout } = setupMountedComponent(AppLayout, { route: routes[0] }, initialState, ["/cases"]); - - expect(appLayout.find(DemoIndicator).find(Alert)).to.have.lengthOf(0); - }); - - afterEach(() => { - window.matchMedia.restore(); - }); - }); -}); diff --git a/app/javascript/components/layouts/components/app-layout/styles.css b/app/javascript/components/layouts/components/app-layout/styles.css index 8927d7f8df..b23b97f3a5 100644 --- a/app/javascript/components/layouts/components/app-layout/styles.css +++ b/app/javascript/components/layouts/components/app-layout/styles.css @@ -2,6 +2,7 @@ :global html, :global body { height: var(--doc-height, 100vh); + height: 100dvh; } .root { @@ -17,11 +18,8 @@ overflow: hidden; background: var(--c-content-grey); transition: var(--transition); - margin-left: -240px; overflow-x: hidden; padding-top: 0; - margin-left: 0; - width: 100%; &.demo { height: 96vh; diff --git a/app/javascript/components/layouts/components/empty-layout/component.jsx b/app/javascript/components/layouts/components/empty-layout/component.jsx index 60aa1cb5c0..32c10de23a 100644 --- a/app/javascript/components/layouts/components/empty-layout/component.jsx +++ b/app/javascript/components/layouts/components/empty-layout/component.jsx @@ -7,17 +7,17 @@ import { useApp } from "../../../application"; import DemoIndicator from "../../../demo-indicator"; import SessionTimeoutDialog from "../../../session-timeout-dialog"; -const Component = ({ children }) => { +function Component({ children }) { const { demo } = useApp(); return ( <> {children} - + ); -}; +} Component.displayName = "EmptyLayout"; diff --git a/app/javascript/components/layouts/components/empty-layout/component.spec.js b/app/javascript/components/layouts/components/empty-layout/component.spec.js new file mode 100644 index 0000000000..3a28a2c109 --- /dev/null +++ b/app/javascript/components/layouts/components/empty-layout/component.spec.js @@ -0,0 +1,85 @@ +import { createMocks } from "react-idle-timer"; + +import { mountedComponent, screen, act, waitFor } from "../../../../test-utils"; + +import EmptyLayout from "./component"; + +describe("layouts/components/", () => { + beforeAll(() => { + jest.useFakeTimers(); + createMocks(); + }); + + afterEach(() => { + jest.clearAllTimers(); + }); + + const state = { + ui: { + Nav: { + drawerOpen: true + } + }, + user: { + modules: "primero", + agency: "unicef", + isAuthenticated: true, + messages: null, + permissions: { + incidents: ["manage"], + tracing_requests: ["manage"], + cases: ["manage"] + } + }, + application: { + baseLanguage: "en", + userIdle: true, + primero: { + sandbox_ui: true + }, + modules: [ + { + unique_id: "primeromodule-cp", + name: "CP", + associated_record_types: ["case"] + } + ] + }, + records: { + support: { + data: { + demo: true + } + } + }, + connectivity: { + online: true, + serverOnline: true + } + }; + + it("renders DemoIndicator component", () => { + mountedComponent( + +
+ , + state + ); + expect(screen.getByTestId("test")).toBeInTheDocument(); + expect(screen.getByText("sandbox_ui")).toBeInTheDocument(); + }); + + it("renders SessionTimeoutDialog component", async () => { + mountedComponent( + +
+ , + state + ); + expect(screen.getByText("sandbox_ui")).toBeInTheDocument(); + await act(() => jest.advanceTimersByTimeAsync(16 * 1000 * 60)); + await waitFor(() => { + expect(screen.queryByRole("dialog")).toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/layouts/components/empty-layout/component.unit.test.js b/app/javascript/components/layouts/components/empty-layout/component.unit.test.js deleted file mode 100644 index 6b240f4750..0000000000 --- a/app/javascript/components/layouts/components/empty-layout/component.unit.test.js +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { routes } from "../../../../config"; -import { setupMountedComponent } from "../../../../test"; -import DemoIndicator from "../../../demo-indicator"; -import SessionTimeoutDialog from "../../../session-timeout-dialog"; - -import EmptyLayout from "./component"; - -describe("layouts/components/", () => { - let component; - - beforeEach(() => { - const state = fromJS({ - ui: { - Nav: { - drawerOpen: true - } - }, - user: { - modules: "primero", - agency: "unicef", - isAuthenticated: true, - messages: null, - permissions: { - incidents: ["manage"], - tracing_requests: ["manage"], - cases: ["manage"] - } - }, - application: { - baseLanguage: "en", - modules: [ - { - unique_id: "primeromodule-cp", - name: "CP", - associated_record_types: ["case"] - } - ] - }, - records: { - support: { - data: { - demo: true - } - } - } - }); - - component = setupMountedComponent(EmptyLayout, { route: routes[0] }, state, ["/cases"]).component; - }); - - it("renders DemoIndicator component", () => { - expect(component.find(DemoIndicator)).to.have.lengthOf(1); - }); - - it("renders SessionTimeoutDialog component", () => { - expect(component.find(SessionTimeoutDialog)).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/layouts/components/login-layout-footer/component.jsx b/app/javascript/components/layouts/components/login-layout-footer/component.jsx index 966de8a7aa..147c9c453a 100644 --- a/app/javascript/components/layouts/components/login-layout-footer/component.jsx +++ b/app/javascript/components/layouts/components/login-layout-footer/component.jsx @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import clsx from "clsx"; +import { cx } from "@emotion/css"; import PropTypes from "prop-types"; import PoweredBy from "../../../powered-by"; @@ -8,7 +8,7 @@ import TranslationsToggle from "../../../translations-toggle"; import css from "../login-layout/styles.css"; function Component({ useContainedNavStyle = false }) { - const classes = clsx(css.footer, { + const classes = cx(css.footer, { [css.footerContained]: useContainedNavStyle }); diff --git a/app/javascript/components/layouts/components/login-layout/component.jsx b/app/javascript/components/layouts/components/login-layout/component.jsx index f173759717..67766bcbe3 100644 --- a/app/javascript/components/layouts/components/login-layout/component.jsx +++ b/app/javascript/components/layouts/components/login-layout/component.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import clsx from "clsx"; -import { useMediaQuery } from "@material-ui/core"; +import { cx } from "@emotion/css"; +import { useMediaQuery } from "@mui/material"; import ModuleLogo from "../../../module-logo"; import AgencyLogo from "../../../agency-logo"; @@ -16,19 +16,18 @@ import LoginLayoutFooter from "../login-layout-footer"; import { NAME } from "./constants"; import css from "./styles.css"; -const Component = ({ children }) => { +function Component({ children }) { const mobileDisplay = useMediaQuery(theme => theme.breakpoints.down("sm")); const { demo, hasLoginLogo, useContainedNavStyle } = useApp(); const hasLogos = useMemoizedSelector(state => hasAgencyLogos(state)); - // TODO: Module hardcoded till we figure out when to switch modules - const primeroModule = "cp"; - const moduleClass = `${primeroModule}${demo ? "-demo" : ""}`; - const classes = clsx(css.primeroBackground, css[moduleClass], { - [css.primeroBackgroundImage]: hasLoginLogo + const classes = cx(css.primeroBackground, { + [css.primeroBackgroundImage]: hasLoginLogo, + [css.primeroBackgroundImageDemo]: hasLoginLogo && demo, + [css.demoBackground]: demo }); - const classesLoginLogo = clsx(css.loginLogo, { [css.hideLoginLogo]: !hasLogos }); - const classesAuthDiv = clsx(css.auth, { [css.noLogosWidth]: !hasLogos }); + const classesLoginLogo = cx(css.loginLogo, { [css.hideLoginLogo]: !hasLogos }); + const classesAuthDiv = cx(css.auth, { [css.noLogosWidth]: !hasLogos }); const isContainedAndMobile = useContainedNavStyle && mobileDisplay; return ( @@ -56,7 +55,7 @@ const Component = ({ children }) => {
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/layouts/components/login-layout/component.spec.js b/app/javascript/components/layouts/components/login-layout/component.spec.js new file mode 100644 index 0000000000..b003601957 --- /dev/null +++ b/app/javascript/components/layouts/components/login-layout/component.spec.js @@ -0,0 +1,71 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen, fireEvent } from "../../../../test-utils"; + +import LoginLayout from "./component"; + +describe("layouts/components/", () => { + const state = fromJS({ + user: { module: "primero" }, + application: { + primero: { + locales: ["en", "es", "ar"], + logos: [{ id: "Agency-ID", images: { logo_full: "random/string", logo_icon: "random/string" } }], + agencies: [{ id: "Agency-ID", images: { logo_full: "another/string", logo_icon: "another/string" } }] + } + } + }); + + it("renders default PrimeroModule logo", () => { + mountedComponent(, state); + expect(screen.getByAltText(/Primero/i)).toBeInTheDocument(); + }); + + it("renders a module logo", () => { + mountedComponent(, state); + expect(screen.getAllByRole("img", { className: "logo" })).toHaveLength(1); + }); + + it("renders an agency logo", () => { + mountedComponent(, state); + expect(document.querySelector(".agencyLogoContainer")).toBeInTheDocument(); + expect(document.querySelector(".agencyLogo")).toBeInTheDocument(); + }); + + it("renders an TranslationsToggle component", () => { + mountedComponent(, state); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem", { name: /home.en/i })).toBeInTheDocument(); + expect(screen.getByRole("menuitem", { name: /home.es/i })).toBeInTheDocument(); + }); + + describe("when is not demo site", () => { + it("should not render a DemoIndicator", () => { + mountedComponent(, state); + expect(screen.queryByText(/sandbox_ui/i)).toBeNull(); + }); + }); + + describe("when is demo site", () => { + const stateWithDemoIndicator = { + user: { module: "primero" }, + application: { + primero: { + sandbox_ui: true + } + }, + records: { + support: { + data: { + demo: true + } + } + } + }; + + it("should render a DemoIndicator", () => { + mountedComponent(, stateWithDemoIndicator); + expect(screen.queryByText(/sandbox_ui/i)).toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/layouts/components/login-layout/component.unit.test.js b/app/javascript/components/layouts/components/login-layout/component.unit.test.js deleted file mode 100644 index a745b6335a..0000000000 --- a/app/javascript/components/layouts/components/login-layout/component.unit.test.js +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import Alert from "@material-ui/lab/Alert"; -import { MenuItem } from "@material-ui/core"; - -import { setupMountedComponent, stub } from "../../../../test"; -import TranslationsToggle from "../../../translations-toggle"; -import AgencyLogo from "../../../agency-logo"; -import ModuleLogo from "../../../module-logo"; -import PrimeroWhiteLogo from "../../../../images/primero-logo-white.png"; -import DemoIndicator from "../../../demo-indicator"; - -import LoginLayout from "./component"; - -describe("layouts/components/", () => { - let component; - const state = fromJS({ - LoginLayout: { module: "primero" }, - application: { primero: { locales: ["en", "es", "ar"] } } - }); - - before(() => { - component = setupMountedComponent(LoginLayout, {}, state).component; - }); - - it("renders default PrimeroModule logo", () => { - expect(component.find("img").first().prop("src")).to.equal(PrimeroWhiteLogo); - expect(component.find("img").first().prop("alt")).to.equal("Primero"); - }); - it("renders a module logo", () => { - expect(component.find(ModuleLogo)).to.have.lengthOf(1); - }); - - it("renders an agency logo", () => { - expect(component.find(AgencyLogo)).to.have.lengthOf(1); - }); - - it("renders an TranslationsToggle component", () => { - expect(component.find(TranslationsToggle)).to.have.lengthOf(1); - component.find("button").at(0).simulate("click"); - expect(component.find(TranslationsToggle).find(MenuItem)).to.have.lengthOf(3); - }); - - describe("when is not demo site", () => { - it("should not render a DemoIndicator", () => { - expect(component.find(DemoIndicator)).to.be.empty; - }); - }); - - describe("when is demo site", () => { - const stateWithDemoIndicator = fromJS({ - LoginLayout: { module: "primero" }, - records: { - support: { - data: { - demo: true - } - } - } - }); - const { component: componentWithDemoIndicator } = setupMountedComponent(LoginLayout, {}, stateWithDemoIndicator); - - it("should render a DemoIndicator", () => { - expect(componentWithDemoIndicator.find(DemoIndicator)).to.have.lengthOf(1); - }); - }); - - describe("when the mobile is displayed", () => { - beforeEach(() => { - stub(window, "matchMedia").returns(window.defaultMediaQueryList({ matches: true })); - }); - - it("should not render the DemoIndicator alert", () => { - const initialState = fromJS({ - application: { - baseLanguage: "en", - modules: [ - { - unique_id: "primeromodule-cp", - name: "CP", - associated_record_types: ["case"] - } - ], - primero: { - sandbox_ui: true - } - }, - records: { - support: { - data: { - demo: true - } - } - } - }); - - const { component: loginLayout } = setupMountedComponent(LoginLayout, {}, initialState); - - expect(loginLayout.find(DemoIndicator).find(Alert)).to.have.lengthOf(0); - }); - - afterEach(() => { - window.matchMedia.restore(); - }); - }); -}); diff --git a/app/javascript/components/layouts/components/login-layout/styles.css b/app/javascript/components/layouts/components/login-layout/styles.css index 3f2d530fa9..35952def92 100644 --- a/app/javascript/components/layouts/components/login-layout/styles.css +++ b/app/javascript/components/layouts/components/login-layout/styles.css @@ -20,12 +20,9 @@ background-color: var(--c-blue); } -.cp-demo { - background: repeating-linear-gradient(45deg, var(--c-dark-blue), var(--c-dark-blue) 10px, var(--c-blue) 10px, var(--c-blue) 20px) !important; -} - :global html, :global body { height: var(--doc-height, 100vh); + height: 100dvh; } .primeroBackground { @@ -41,6 +38,14 @@ background: center/70% no-repeat var(--c-login-background-image), linear-gradient(108deg, var(--c-login-background-gradient-start) 0%, var(--c-login-background-gradient-end) 100%); } +.primeroBackgroundImageDemo { + background: center/70% no-repeat var(--c-login-background-image), repeating-linear-gradient(45deg, transparent, transparent 10px, rgba(0,0,0, .05) 10px, rgba(0,0,0,.05) 20px), linear-gradient(108deg, var(--c-login-background-gradient-start) 0%, var(--c-login-background-gradient-end) 100%); +} + +.demoBackground { + background: repeating-linear-gradient(45deg, transparent, transparent 10px, rgba(0,0,0, .05) 10px, rgba(0,0,0,.05) 20px), linear-gradient(108deg, var(--c-login-background-gradient-start) 0%, var(--c-login-background-gradient-end) 100%); +} + .content { flex: 1 0 auto; display: flex; @@ -143,7 +148,7 @@ } .footer button, -.footer button > span > svg { +.footer button > svg { color: var(--c-login-translations-button-text); } @@ -164,7 +169,7 @@ flex-direction: column; } -@media (max-width:599.95px) { +@media (max-width:600px) { .loginLogo { display: none; } @@ -172,12 +177,13 @@ .auth { width: 90%; } + .noLogosWidth { - width: 50%; + width: 90%; } } -@media (min-width:600px) and (max-width:959.95px) { +@media (min-width:600px) and (max-width:900px) { .auth { width: 90%; } diff --git a/app/javascript/components/lightbox/component.jsx b/app/javascript/components/lightbox/component.jsx index 4932a78cbb..abc34624ef 100644 --- a/app/javascript/components/lightbox/component.jsx +++ b/app/javascript/components/lightbox/component.jsx @@ -2,12 +2,12 @@ import { useState } from "react"; import PropTypes from "prop-types"; -import { Backdrop, IconButton } from "@material-ui/core"; -import CloseIcon from "@material-ui/icons/Close"; +import { IconButton, Modal } from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; import css from "./styles.css"; -const Component = ({ trigger, image }) => { +function Component({ trigger, image }) { const [open, setOpen] = useState(false); const handleClose = () => { @@ -17,21 +17,23 @@ const Component = ({ trigger, image }) => { }; return ( - <> +
{image && ( - - - - - {open && } - + +
+ + + + {open && } +
+
)} - +
); -}; +} Component.displayName = "Lightbox"; diff --git a/app/javascript/components/lightbox/styles.css b/app/javascript/components/lightbox/styles.css index 57184ddc44..97dd653abe 100644 --- a/app/javascript/components/lightbox/styles.css +++ b/app/javascript/components/lightbox/styles.css @@ -1,7 +1,10 @@ /* Copyright (c) 2014 - 2023 UNICEF. All rights reserved. */ .backdrop { - z-index: 99999; + align-items: center; + display: flex; + justify-content: center; + height: 100dvh; } .backdropClose { diff --git a/app/javascript/components/list-icon/component.jsx b/app/javascript/components/list-icon/component.jsx index ff01c74dcf..6913a6e862 100644 --- a/app/javascript/components/list-icon/component.jsx +++ b/app/javascript/components/list-icon/component.jsx @@ -16,10 +16,10 @@ import { People, SettingsApplications, LibraryBooks -} from "@material-ui/icons"; +} from "@mui/icons-material"; import PropTypes from "prop-types"; -import SignalWifiOffIcon from "@material-ui/icons/SignalWifiOff"; -import SignalWifi4BarIcon from "@material-ui/icons/SignalWifi4Bar"; +import SignalWifiOffIcon from "@mui/icons-material/SignalWifiOff"; +import SignalWifi4BarIcon from "@mui/icons-material/SignalWifi4Bar"; import { CasesIcon, @@ -30,16 +30,16 @@ import { RegistryRecordIcon } from "../../images/primero-icons"; -const ListIcon = ({ icon }) => { +function ListIcon({ icon }) { switch (icon) { case "home": return ; case "activity_log": return ; case "cases": - return ; + return ; case "incidents": - return ; + return ; case "tracing_request": return ; case "matches": @@ -83,7 +83,7 @@ const ListIcon = ({ icon }) => { default: return null; } -}; +} ListIcon.displayName = "ListIcon"; diff --git a/app/javascript/components/list-icon/component.spec.js b/app/javascript/components/list-icon/component.spec.js new file mode 100644 index 0000000000..aa4bf739db --- /dev/null +++ b/app/javascript/components/list-icon/component.spec.js @@ -0,0 +1,15 @@ +import { mountedComponent, screen } from "../../test-utils"; + +import ListIcon from "./component"; + +describe("", () => { + it("renders correct icon", () => { + mountedComponent(); + expect(screen.getByTestId("cases-icon")).toBeInTheDocument(); + }); + + it("renders incidents icon", () => { + mountedComponent(); + expect(screen.getByTestId("incidents-icon")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/list-icon/component.unit.test.js b/app/javascript/components/list-icon/component.unit.test.js deleted file mode 100644 index 0762c4c21a..0000000000 --- a/app/javascript/components/list-icon/component.unit.test.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { shallow } from "enzyme"; - -import { CasesIcon, IncidentsIcon } from "../../images/primero-icons"; - -import ListIcon from "./component"; - -describe("", () => { - it("renders correct icon", () => { - const component = shallow(); - - expect(component.find(CasesIcon)).to.have.lengthOf(1); - component.setProps({ icon: "incidents" }); - expect(component.find(IncidentsIcon)).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/loading-indicator/components/empty-state.jsx b/app/javascript/components/loading-indicator/components/empty-state.jsx index afb5e50054..03b138043f 100644 --- a/app/javascript/components/loading-indicator/components/empty-state.jsx +++ b/app/javascript/components/loading-indicator/components/empty-state.jsx @@ -6,7 +6,7 @@ import { useI18n } from "../../i18n"; import ListIcon from "../../list-icon"; import css from "../styles.css"; -const EmptyState = ({ emptyMessage, type }) => { +function EmptyState({ emptyMessage, type }) { const i18n = useI18n(); return ( @@ -17,7 +17,7 @@ const EmptyState = ({ emptyMessage, type }) => {
); -}; +} EmptyState.displayName = "EmptyState"; diff --git a/app/javascript/components/loading-indicator/loading.jsx b/app/javascript/components/loading-indicator/loading.jsx index c50803d90a..ee5beffd07 100644 --- a/app/javascript/components/loading-indicator/loading.jsx +++ b/app/javascript/components/loading-indicator/loading.jsx @@ -1,11 +1,11 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { CircularProgress, Fade } from "@material-ui/core"; +import { CircularProgress, Fade } from "@mui/material"; import PropTypes from "prop-types"; import { NAME } from "./constants"; -const Component = ({ loadingIndicator, loading, classes }) => { +function Component({ loadingIndicator, loading, classes }) { const transitionDelayStyles = { transitionDelay: loading ? "800ms" : "0ms" }; @@ -19,7 +19,7 @@ const Component = ({ loadingIndicator, loading, classes }) => { ) ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/loading-indicator/styles.css b/app/javascript/components/loading-indicator/styles.css index 5ab80b4387..59468ee0df 100644 --- a/app/javascript/components/loading-indicator/styles.css +++ b/app/javascript/components/loading-indicator/styles.css @@ -44,7 +44,7 @@ margin: 0.2em 0 1em; } -@media (max-width:959.95px) { +@media (max-width:900px) { .empty, .loadingIndicator { margin-top: 6em; diff --git a/app/javascript/components/locked-icon/component.jsx b/app/javascript/components/locked-icon/component.jsx index 50e1f366d2..cc87700f15 100644 --- a/app/javascript/components/locked-icon/component.jsx +++ b/app/javascript/components/locked-icon/component.jsx @@ -1,11 +1,11 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import VpnKeyIcon from "@material-ui/icons/VpnKey"; +import VpnKeyIcon from "@mui/icons-material/VpnKey"; import css from "./styles.css"; function Component() { - return ; + return ; } Component.displayName = "LockedIcon"; diff --git a/app/javascript/components/login-dialog/component.jsx b/app/javascript/components/login-dialog/component.jsx index 4a554f1565..421368d760 100644 --- a/app/javascript/components/login-dialog/component.jsx +++ b/app/javascript/components/login-dialog/component.jsx @@ -1,17 +1,20 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +import { useMemoizedSelector } from "../../libs"; import ActionDialog, { useDialog } from "../action-dialog"; -import { useApp } from "../application"; +import { useApp } from "../application/use-app"; import { useI18n } from "../i18n"; import Login from "../login"; import { FORM_ID } from "../login/components/login-form/constants"; +import { getUseIdentityProvider } from "../login/selectors"; import utils from "../login/utils"; import { LOGIN_DIALOG } from "./constants"; -const Component = () => { +function Component() { const i18n = useI18n(); const { demo } = useApp(); + const useIdentity = useMemoizedSelector(state => getUseIdentityProvider(state)); const { dialogOpen, pending } = useDialog(LOGIN_DIALOG); @@ -31,12 +34,12 @@ const Component = () => { }} disableClose omitCloseAfterSuccess - disableBackdropClick + showSuccessButton={!useIdentity} > ); -}; +} Component.displayName = "LoginDialog"; diff --git a/app/javascript/components/login/component.jsx b/app/javascript/components/login/component.jsx index 9ed05c3585..cfb5049c17 100644 --- a/app/javascript/components/login/component.jsx +++ b/app/javascript/components/login/component.jsx @@ -14,7 +14,7 @@ import IdpSelection from "./components/idp-selection"; import LoginForm from "./components/login-form"; import { getLoading, getUseIdentityProvider } from "./selectors"; -const Container = ({ modal }) => { +function Component({ modal = false }) { const useIdentity = useMemoizedSelector(state => getUseIdentityProvider(state)); const isLoading = useMemoizedSelector(state => getLoading(state)); const location = useLocation(); @@ -36,19 +36,15 @@ const Container = ({ modal }) => { return ( - + ); -}; - -Container.displayName = NAME; +} -Container.defaultProps = { - modal: false -}; +Component.displayName = NAME; -Container.propTypes = { +Component.propTypes = { modal: PropTypes.bool }; -export default Container; +export default Component; diff --git a/app/javascript/components/login/component.spec.js b/app/javascript/components/login/component.spec.js new file mode 100644 index 0000000000..78e91d4b81 --- /dev/null +++ b/app/javascript/components/login/component.spec.js @@ -0,0 +1,45 @@ +import { mountedComponent, screen } from "../../test-utils"; + +import Login from "./component"; + +describe("", () => { + describe("for login form", () => { + it("renders form", () => { + mountedComponent(, { + idp: { + use_identity_provider: false + }, + user: { + module: "primero", + agency: "unicef", + isAuthenticated: false + } + }); + + expect(screen.queryByText((content, element) => element.tagName.toLowerCase() === "form")).toBeInTheDocument(); + }); + }); + + describe("for provider selection", () => { + it("renders login selection", () => { + mountedComponent(, { + idp: { + use_identity_provider: true, + identity_providers: [ + { + name: "UNICEF", + type: "b2c", + domain_hint: "unicef", + authority: "authority", + client_id: "clientid", + scope: ["scope"], + redirect_uri: "redirect" + } + ] + } + }); + + expect(document.querySelector(".idpSelectContainer")).toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/login/component.unit.test.js b/app/javascript/components/login/component.unit.test.js deleted file mode 100644 index fa15c7b55d..0000000000 --- a/app/javascript/components/login/component.unit.test.js +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../test"; - -import Login from "./component"; -import PrimeroIdpSelect from "./components/idp-selection/components/primero-idp-select"; - -describe("", () => { - describe("for login form", () => { - let component; - - before(() => { - component = setupMountedComponent( - Login, - { isAuthenticated: false }, - fromJS({ - idp: { - use_identity_provider: false - }, - user: { - module: "primero", - agency: "unicef", - isAuthenticated: false - } - }) - ).component; - }); - - it("renders form", () => { - expect(component.find("form")).to.have.length(1); - }); - }); - - describe("for provider selection", () => { - let component; - - before(() => { - component = setupMountedComponent( - Login, - { isAuthenticated: false }, - fromJS({ - idp: { - use_identity_provider: true, - identity_providers: [ - { - name: "UNICEF", - type: "b2c", - domain_hint: "unicef", - authority: "authority", - client_id: "clientid", - scope: ["scope"], - redirect_uri: "redirect" - } - ] - } - }) - ).component; - }); - - it("renders login selection", () => { - expect(component.find(PrimeroIdpSelect)).to.have.lengthOf(1); - }); - }); -}); diff --git a/app/javascript/components/login/components/idp-login/component.jsx b/app/javascript/components/login/components/idp-login/component.jsx index 6638598574..1ffe5ee4c6 100644 --- a/app/javascript/components/login/components/idp-login/component.jsx +++ b/app/javascript/components/login/components/idp-login/component.jsx @@ -4,4 +4,6 @@ function Component() { return null; } +Component.displayName = "IdpLogin"; + export default Component; diff --git a/app/javascript/components/login/components/idp-selection/auth-provider.js b/app/javascript/components/login/components/idp-selection/auth-provider.js index 6ce4fe16d6..aaa104434e 100644 --- a/app/javascript/components/login/components/idp-selection/auth-provider.js +++ b/app/javascript/components/login/components/idp-selection/auth-provider.js @@ -3,6 +3,7 @@ /* eslint-disable no-return-await */ import { InteractionRequiredAuthError } from "@azure/msal-common"; import { isImmutable } from "immutable"; +import { get } from "lodash"; import { SELECTED_IDP } from "../../../user/constants"; @@ -10,10 +11,31 @@ import { setMsalApp, setMsalConfig, getLoginRequest, getTokenRequest } from "./u let msalApp; let forceStandardOIDC = false; +let tokenRequest; +let selectedIDPCache; -async function getToken(tokenRequest) { +function selectedIDPFromSessionStore(key) { + const selectedIDP = selectedIDPCache || JSON.parse(sessionStorage.getItem(SELECTED_IDP)); + + selectedIDPCache = selectedIDP; + + if (key) { + return get(selectedIDP, key); + } + + return selectedIDP; +} +selectedIDPFromSessionStore(); + +async function getIDPToken() { try { - return await msalApp.acquireTokenSilent(tokenRequest); + if (tokenRequest) { + const token = await msalApp.acquireTokenSilent(tokenRequest); + + return token.idToken; + } + + return undefined; } catch (error) { if (error instanceof InteractionRequiredAuthError) { return await msalApp.acquireTokenPopup(tokenRequest).catch(popupError => { @@ -29,48 +51,52 @@ async function getToken(tokenRequest) { } } -const setupMsal = (idp, historyObj) => { - const idpObj = isImmutable(idp) ? idp.toJS() : idp; +const setupMsal = async (idp, historyObj) => { + const idpObj = (isImmutable(idp) ? idp.toJS() : idp) || selectedIDPFromSessionStore(); const identityScope = idpObj.identity_scope || [""]; const domainHint = idpObj.domain_hint; const loginRequest = getLoginRequest(identityScope, domainHint); - const tokenRequest = getTokenRequest(identityScope); + + tokenRequest = getTokenRequest(identityScope); if (!msalApp) { forceStandardOIDC = idpObj.force_standard_oidc === true; const msalConfig = setMsalConfig(idpObj, forceStandardOIDC); - msalApp = setMsalApp(msalConfig, historyObj); + msalApp = await setMsalApp(msalConfig, historyObj); } - localStorage.setItem(SELECTED_IDP, idpObj.unique_id); - return { loginRequest, tokenRequest }; + sessionStorage.setItem(SELECTED_IDP, JSON.stringify(idpObj)); + + return { loginRequest }; }; -const handleResponse = async (tokenRequest, successCallback) => { - const tokenResponse = await getToken(tokenRequest); +if (selectedIDPCache && !msalApp) { + setupMsal(); +} + +const handleResponse = async successCallback => { + const tokenResponse = await getIDPToken(tokenRequest); if (tokenResponse) { successCallback(); } }; -export const refreshIdpToken = async (idp, successCallback, historyObj) => { - const { tokenRequest } = setupMsal(idp, historyObj); - - handleResponse(tokenRequest, successCallback); +export const refreshIdpToken = async (idp, successCallback) => { + handleResponse(successCallback); }; export const signIn = async (idp, callback, historyObj) => { sessionStorage.clear(); - const { loginRequest } = setupMsal(idp, historyObj); + const { loginRequest } = await setupMsal(idp, historyObj); try { const response = await msalApp.loginPopup(loginRequest); - localStorage.setItem("cachedIdToken", response.idToken); + msalApp.setActiveAccount(response.account); callback(response.idToken); } catch (error) { throw new Error(error); @@ -95,6 +121,7 @@ export const signOut = () => { } msalApp = null; forceStandardOIDC = false; - localStorage.removeItem("cachedIdToken"); } }; + +export { getIDPToken }; diff --git a/app/javascript/components/login/components/idp-selection/components/primero-idp-link.jsx b/app/javascript/components/login/components/idp-selection/components/primero-idp-link.jsx index 0cc4a120b9..682a26cda2 100644 --- a/app/javascript/components/login/components/idp-selection/components/primero-idp-link.jsx +++ b/app/javascript/components/login/components/idp-selection/components/primero-idp-link.jsx @@ -2,8 +2,8 @@ /* eslint-disable jsx-a11y/anchor-is-valid */ import PropTypes from "prop-types"; -import clsx from "clsx"; -import { Link } from "@material-ui/core"; +import { cx } from "@emotion/css"; +import { Link } from "@mui/material"; import { useHistory } from "react-router-dom"; import { PRIMERO_IDP } from "../constants"; @@ -12,13 +12,13 @@ import { signIn } from "../auth-provider"; import { useApp } from "../../../../application"; import DisableOffline from "../../../../disable-offline"; -const PrimeroIdpLink = ({ identityProviders, i18n, dispatch, css }) => { +function PrimeroIdpLink({ identityProviders, i18n, dispatch, css }) { const history = useHistory(); const { online } = useApp(); const primeroIdp = identityProviders.find(idp => idp.get("unique_id") === PRIMERO_IDP); const onlyPrimeroIDP = primeroIdp && identityProviders?.size === 1; - const classes = clsx(css.activityContainer, { + const classes = cx(css.activityContainer, { [css.linkButtonContainer]: true, [css.onlyLink]: onlyPrimeroIDP }); @@ -47,7 +47,7 @@ const PrimeroIdpLink = ({ identityProviders, i18n, dispatch, css }) => { )}
); -}; +} PrimeroIdpLink.displayName = "PrimeroIdpLink"; diff --git a/app/javascript/components/login/components/idp-selection/components/primero-idp-link.spec.js b/app/javascript/components/login/components/idp-selection/components/primero-idp-link.spec.js new file mode 100644 index 0000000000..a719a25090 --- /dev/null +++ b/app/javascript/components/login/components/idp-selection/components/primero-idp-link.spec.js @@ -0,0 +1,78 @@ +import { mountedComponent, screen } from "../../../../../test-utils"; + +import PrimeroIdpLink from "./primero-idp-link"; + +describe("", () => { + const props = { + identityProviders: [ + new Map([ + ["unique_id", "primeroims"], + ["name", "Primero"] + ]), + new Map([ + ["unique_id", "randomidp"], + ["name", "RandomIDP"] + ]) + ], + css: {}, + dispatch: jest.fn(), + i18n: { + t: () => {} + } + }; + + it("renders forms components", () => { + mountedComponent(); + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "span")).toBeInTheDocument(); + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "a")).toBeInTheDocument(); + }); + + describe("when primeroims is the only one", () => { + const propsOnlyPrimeroIDP = { + identityProviders: [ + new Map([ + ["unique_id", "primeroims"], + ["name", "Primero"] + ]) + ], + css: {}, + dispatch: jest.fn(), + i18n: { + t: () => {} + } + }; + + it("renders forms components", () => { + mountedComponent(); + + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "span")).toBeInTheDocument(); + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "a")).toBeInTheDocument(); + }); + }); + + describe("when there is only one IDP but not primeroims", () => { + const propsOnlyPrimeroIDP = { + identityProviders: [ + new Map([ + ["unique_id", "primeroims"], + ["name", "Primero"] + ]), + new Map([ + ["unique_id", "randomidp"], + ["name", "RandomIDP"] + ]) + ], + css: {}, + dispatch: jest.fn(), + i18n: { + t: () => {} + } + }; + + it("renders forms components", () => { + mountedComponent(); + + expect(document.querySelectorAll("a")).toHaveLength(1); + }); + }); +}); diff --git a/app/javascript/components/login/components/idp-selection/components/primero-idp-link.unit.test.js b/app/javascript/components/login/components/idp-selection/components/primero-idp-link.unit.test.js deleted file mode 100644 index a4b5b70d9f..0000000000 --- a/app/javascript/components/login/components/idp-selection/components/primero-idp-link.unit.test.js +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { Link } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../../../test"; - -import PrimeroIdpLink from "./primero-idp-link"; - -describe("", () => { - let component; - const props = { - identityProviders: fromJS([ - { - unique_id: "primeroims", - name: "Primero" - }, - { - unique_id: "randomidp", - name: "RandomIDP" - } - ]), - css: {}, - dispatch: () => {}, - i18n: { - t: () => {} - } - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(PrimeroIdpLink, props)); - }); - - it("renders forms components", () => { - expect(component.find("span")).to.have.lengthOf(1); - expect(component.find(PrimeroIdpLink)).to.have.lengthOf(1); - expect(component.find(Link)).to.have.lengthOf(1); - }); - - context("when primeroims is the only one", () => { - const propsOnlyPrimeroIDP = { - identityProviders: fromJS([ - { - unique_id: "primeroims", - name: "Primero" - } - ]), - css: {}, - dispatch: () => {}, - i18n: { - t: () => {} - } - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(PrimeroIdpLink, propsOnlyPrimeroIDP)); - }); - - it("renders forms components", () => { - expect(component.find("span")).to.have.lengthOf(0); - expect(component.find(PrimeroIdpLink)).to.have.lengthOf(1); - expect(component.find(Link)).to.have.lengthOf(1); - }); - }); - - context("when there is only one IDP but not primeroims", () => { - const propsOnlyPrimeroIDP = { - identityProviders: fromJS([ - { - unique_id: "randomidp", - name: "RandomIDP" - } - ]), - css: {}, - dispatch: () => {}, - i18n: { - t: () => {} - } - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(PrimeroIdpLink, propsOnlyPrimeroIDP)); - }); - - it("renders forms components", () => { - expect(component.find("span")).to.have.lengthOf(0); - expect(component.find(Link)).to.have.lengthOf(0); - }); - }); -}); diff --git a/app/javascript/components/login/components/idp-selection/components/primero-idp-select.jsx b/app/javascript/components/login/components/idp-selection/components/primero-idp-select.jsx index d68a2ca9bc..07c319de95 100644 --- a/app/javascript/components/login/components/idp-selection/components/primero-idp-select.jsx +++ b/app/javascript/components/login/components/idp-selection/components/primero-idp-select.jsx @@ -15,7 +15,7 @@ import { useApp } from "../../../../application"; import { ConditionalWrapper } from "../../../../../libs"; import disableOffline from "../../../../disable-offline"; -const Component = ({ identityProviders, css }) => { +function Component({ identityProviders, css }) { const i18n = useI18n(); const dispatch = useDispatch(); const history = useHistory(); @@ -73,12 +73,12 @@ const Component = ({ identityProviders, css }) => { errorMessage={i18n.t("select_idp_error")} /> - +
); -}; +} Component.propTypes = { css: PropTypes.object, diff --git a/app/javascript/components/login/components/idp-selection/components/primero-idp-select.spec.js b/app/javascript/components/login/components/idp-selection/components/primero-idp-select.spec.js new file mode 100644 index 0000000000..e0be808f6e --- /dev/null +++ b/app/javascript/components/login/components/idp-selection/components/primero-idp-select.spec.js @@ -0,0 +1,28 @@ +import { mountedComponent, screen } from "../../../../../test-utils"; + +import PrimeroIdpSelect from "./primero-idp-select"; + +describe("", () => { + const props = { + identityProviders: [ + new Map([ + ["unique_id", "primeroims"], + ["name", "Primero"] + ]), + new Map([ + ["unique_id", "randomidp"], + ["name", "RandomIDP"] + ]) + ], + css: {} + }; + + mountedComponent(); + + it("renders forms components", () => { + expect(screen.getByText(/select_provider/i)).toBeInTheDocument(); + expect(screen.getByRole("combobox")).toBeInTheDocument(); + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "form")).toBeInTheDocument(); + expect(screen.getByText(/go/i)).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/login/components/idp-selection/components/primero-idp-select.unit.test.js b/app/javascript/components/login/components/idp-selection/components/primero-idp-select.unit.test.js deleted file mode 100644 index 6ebd34321e..0000000000 --- a/app/javascript/components/login/components/idp-selection/components/primero-idp-select.unit.test.js +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../../../test"; -import Form, { FormAction } from "../../../../form"; - -import PrimeroIdpSelect from "./primero-idp-select"; - -describe("", () => { - let component; - const props = { - identityProviders: fromJS([ - { - unique_id: "primeroims", - name: "Primero" - }, - { - unique_id: "randomidp", - name: "RandomIDP" - } - ]), - css: {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(PrimeroIdpSelect, props)); - }); - - it("renders forms components", () => { - expect(component.find("p")).to.have.lengthOf(1); - expect(component.find(PrimeroIdpSelect)).to.have.lengthOf(1); - expect(component.find(Form)).to.have.lengthOf(1); - expect(component.find(FormAction)).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/login/components/idp-selection/container.jsx b/app/javascript/components/login/components/idp-selection/container.jsx index 2fef62b052..4bd3f0f008 100644 --- a/app/javascript/components/login/components/idp-selection/container.jsx +++ b/app/javascript/components/login/components/idp-selection/container.jsx @@ -1,8 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { useDispatch } from "react-redux"; +import PropTypes from "prop-types"; -import { PageHeading } from "../../../page"; +import PageHeading from "../../../page/components/page-heading"; import { useI18n } from "../../../i18n"; import { useMemoizedSelector } from "../../../../libs"; @@ -12,7 +13,7 @@ import css from "./styles.css"; import PrimeroIdpLink from "./components/primero-idp-link"; import PrimeroIdpSelect from "./components/primero-idp-select"; -const Container = () => { +function Container({ showTitle = true }) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -21,13 +22,17 @@ const Container = () => { return ( <> - + {showTitle && } ); -}; +} Container.displayName = NAME; +Container.propTypes = { + showTitle: PropTypes.bool +}; + export default Container; diff --git a/app/javascript/components/login/components/idp-selection/container.spec.js b/app/javascript/components/login/components/idp-selection/container.spec.js new file mode 100644 index 0000000000..4cbc885a34 --- /dev/null +++ b/app/javascript/components/login/components/idp-selection/container.spec.js @@ -0,0 +1,86 @@ +import { mountedComponent, screen } from "../../../../test-utils"; + +import LoginSelection from "./container"; + +describe("", () => { + it("renders login PrimeroIdpSelect for providers", () => { + mountedComponent(, { + idp: { + use_identity_provider: true, + identity_providers: [ + { + name: "unicef", + provider_type: "b2c", + unique_id: "unicef", + authorization_url: "authority", + client_id: "clientid", + identity_scope: ["scope"], + domain_hint: "unicef" + }, + { + name: "primero", + provider_type: "b2c", + unique_id: "primeroims", + authorization_url: "authority", + client_id: "clientid", + identity_scope: ["scope"], + domain_hint: "primero" + } + ] + } + }); + expect(screen.getByRole("combobox")).toBeInTheDocument(); + }); + + it("renders a link for primeroims provider", () => { + mountedComponent(, { + idp: { + use_identity_provider: true, + identity_providers: [ + { + name: "unicef", + provider_type: "b2c", + unique_id: "unicef", + authorization_url: "authority", + client_id: "clientid", + identity_scope: ["scope"], + domain_hint: "unicef" + }, + { + name: "primero", + provider_type: "b2c", + unique_id: "primeroims", + authorization_url: "authority", + client_id: "clientid", + identity_scope: ["scope"], + domain_hint: "primero" + } + ] + } + }); + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "a")).toBeInTheDocument(); + }); + + describe("when primeroims is the only one", () => { + it("renders forms components", () => { + mountedComponent(, { + idp: { + use_identity_provider: true, + identity_providers: [ + { + name: "primero", + provider_type: "b2c", + unique_id: "primeroims", + authorization_url: "authority", + client_id: "clientid", + identity_scope: ["scope"], + domain_hint: "primero" + } + ] + } + }); + expect(screen.getByText(/login.title/i)).toBeInTheDocument(); + expect(screen.getByText(/log_in_primero_idp/i)).toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/login/components/idp-selection/container.unit.test.js b/app/javascript/components/login/components/idp-selection/container.unit.test.js deleted file mode 100644 index 79bc89a3f4..0000000000 --- a/app/javascript/components/login/components/idp-selection/container.unit.test.js +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { Link } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../../test"; -import SelectInput from "../../../form/fields/select-input"; -import { PageHeading } from "../../../page"; -import Form from "../../../form"; - -import LoginSelection from "./container"; -import PrimeroIdpSelect from "./components/primero-idp-select"; - -describe("", () => { - let component; - - before(() => { - component = setupMountedComponent( - LoginSelection, - { isAuthenticated: false }, - fromJS({ - idp: { - use_identity_provider: true, - identity_providers: [ - { - name: "unicef", - provider_type: "b2c", - unique_id: "unicef", - authorization_url: "authority", - client_id: "clientid", - identity_scope: ["scope"], - domain_hint: "unicef" - }, - { - name: "primero", - provider_type: "b2c", - unique_id: "primeroims", - authorization_url: "authority", - client_id: "clientid", - identity_scope: ["scope"], - domain_hint: "primero" - } - ] - } - }) - ).component; - }); - - it("renders login PrimeroIdpSelect for providers", () => { - expect(component.find(PrimeroIdpSelect)).to.have.lengthOf(1); - expect(component.find(SelectInput)).to.have.lengthOf(1); - }); - - it("renders a link for primeroims provider", () => { - expect(component.find("a")).to.have.lengthOf(1); - }); - - context("when primeroims is the only one", () => { - beforeEach(() => { - ({ component } = setupMountedComponent( - LoginSelection, - {}, - fromJS({ - idp: { - use_identity_provider: true, - identity_providers: [ - { - name: "primero", - provider_type: "b2c", - unique_id: "primeroims", - authorization_url: "authority", - client_id: "clientid", - identity_scope: ["scope"], - domain_hint: "primero" - } - ] - } - }) - )); - }); - - it("renders forms components", () => { - expect(component.find(PageHeading)).to.have.lengthOf(1); - expect(component.find(Form)).to.have.lengthOf(0); - expect(component.find("span")).to.have.lengthOf(0); - expect(component.find(Link)).to.have.lengthOf(1); - }); - }); -}); diff --git a/app/javascript/components/login/components/idp-selection/styles.css b/app/javascript/components/login/components/idp-selection/styles.css index 855a9300f8..4f3541cc86 100644 --- a/app/javascript/components/login/components/idp-selection/styles.css +++ b/app/javascript/components/login/components/idp-selection/styles.css @@ -21,6 +21,7 @@ .linkButtonContainer { display: flex; + align-items: center; & span { padding-right: 3px; @@ -56,7 +57,9 @@ .idpSelectContainer { display: flex; - margin-top: 5px; + margin: .2em 0 .5em 0; + align-items: center; + & form { min-width: 80%; margin-right: 5%; @@ -64,10 +67,23 @@ & span > button { min-height: 38px; } + & :global(.MuiTextField-root) { + margin: 0; + } +} + +.loginButton { + background: var(--c-login-button-bg); + color: var(--c-login-button-text); + + &:hover { + filter: brightness(80%); + background-color: var(--c-login-button-bg) !important; + } } -@media (max-width:599.95px) { +@media (max-width:600px) { .loginSelection, .logoutSelection { & button { diff --git a/app/javascript/components/login/components/idp-selection/utils.js b/app/javascript/components/login/components/idp-selection/utils.js index d74e165d96..978d88a1ad 100644 --- a/app/javascript/components/login/components/idp-selection/utils.js +++ b/app/javascript/components/login/components/idp-selection/utils.js @@ -44,8 +44,10 @@ export const setMsalConfig = (idp = {}, forceStandardOidc) => { }; }; -export const setMsalApp = (msalConfig, historyObj) => { +export const setMsalApp = async (msalConfig, historyObj) => { const app = new PublicClientApplication(msalConfig); + + await app.initialize(); const navigationClient = new CustomNavigationClient(historyObj); app.setNavigationClient(navigationClient); diff --git a/app/javascript/components/login/components/login-form/component.jsx b/app/javascript/components/login/components/login-form/component.jsx index 6b3de80e3a..4b29ba7b0a 100644 --- a/app/javascript/components/login/components/login-form/component.jsx +++ b/app/javascript/components/login/components/login-form/component.jsx @@ -18,6 +18,7 @@ import PasswordResetDialog from "../password-reset-dialog"; import { getUseIdentityProvider } from "../../selectors"; import utils from "../../utils"; import DisableOffline, { OfflineAlert } from "../../../disable-offline"; +import { checkServerStatus } from "../../../connectivity/action-creators"; import { NAME, FORM_ID } from "./constants"; import css from "./styles.css"; @@ -25,7 +26,7 @@ import { attemptLogin } from "./action-creators"; import { selectAuthErrors } from "./selectors"; import { form, validationSchema } from "./form"; -const Container = ({ modal }) => { +function Container({ modal = false }) { const i18n = useI18n(); const dispatch = useDispatch(); const { demo, online } = useApp(); @@ -38,8 +39,8 @@ const Container = ({ modal }) => { const validations = validationSchema(i18n); const formSections = form(i18n); - const handleSubmit = values => { - dispatch(attemptLogin(values)); + const handleSubmit = async values => { + dispatch(checkServerStatus(true, false, [attemptLogin(values)])); }; const onClickForgotLink = () => { @@ -86,7 +87,8 @@ const Container = ({ modal }) => { rest={{ fullWidth: mobileDisplay, form: FORM_ID, - type: "submit" + type: "submit", + className: css.loginButton }} disabled={!online} /> @@ -96,14 +98,10 @@ const Container = ({ modal }) => { {renderForgotPassword} ); -}; +} Container.displayName = NAME; -Container.defaultProps = { - modal: false -}; - Container.propTypes = { modal: PropTypes.bool }; diff --git a/app/javascript/components/login/components/login-form/component.spec.js b/app/javascript/components/login/components/login-form/component.spec.js new file mode 100644 index 0000000000..d83b5f1329 --- /dev/null +++ b/app/javascript/components/login/components/login-form/component.spec.js @@ -0,0 +1,117 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen } from "../../../../test-utils"; + +import LoginForm from "./component"; + +describe("", () => { + const props = { isAuthenticated: false }; + + it("renders form", () => { + mountedComponent( + , + fromJS({ + idp: { + use_identity_provider: false + }, + user: { + module: "primero", + agency: "unicef", + isAuthenticated: false + } + }) + ); + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "form")).toBeInTheDocument(); + }); + + it("renders h1 tag", () => { + mountedComponent( + , + fromJS({ + idp: { + use_identity_provider: false + }, + user: { + module: "primero", + agency: "unicef", + isAuthenticated: false + } + }) + ); + + expect(screen.getByRole("heading", { name: "login.label" })).toBeInTheDocument(); + }); + + it("renders username and password input fields", () => { + mountedComponent( + , + fromJS({ + idp: { + use_identity_provider: false + }, + user: { + module: "primero", + agency: "unicef", + isAuthenticated: false + } + }) + ); + expect(screen.getByRole("textbox", { name: /login.username/i })).toBeInTheDocument(); + expect(document.querySelector('input[name="password"]')).toBeInTheDocument(); + }); + + it("renders login button", () => { + mountedComponent( + , + fromJS({ + idp: { + use_identity_provider: false + }, + user: { + module: "primero", + agency: "unicef", + isAuthenticated: false + } + }) + ); + expect(screen.getByText(/buttons.login/)).toBeInTheDocument(); + }); + + describe("when is demo site", () => { + const stateWithDemo = fromJS({ + application: { + primero: { + sandbox_ui: true + } + } + }); + + it("should render PageHeading with 'demo' text", () => { + mountedComponent(, stateWithDemo); + expect(screen.getByText("sandbox_ui login.label")).toBeInTheDocument(); + }); + + it("should render ActionButton with 'demo' text", () => { + mountedComponent(, stateWithDemo); + expect(screen.getByText("buttons.login logger.to sandbox_ui")).toBeInTheDocument(); + }); + }); + + describe("when does not use external identity", () => { + const stateWithoutExternal = fromJS({ + application: { + primero: { + sandbox_ui: true + } + }, + idp: { + use_identity_provider: false + } + }); + + it("renders the forgot password link", () => { + mountedComponent(, stateWithoutExternal); + expect(screen.getByText(/login.forgot_password/i)).toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/login/components/login-form/component.unit.test.js b/app/javascript/components/login/components/login-form/component.unit.test.js deleted file mode 100644 index 7d393b966b..0000000000 --- a/app/javascript/components/login/components/login-form/component.unit.test.js +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { PageHeading } from "../../../page"; -import ActionButton from "../../../action-button"; -import { setupMountedComponent } from "../../../../test"; - -import LoginForm from "./component"; - -describe("", () => { - const props = { isAuthenticated: false }; - let component; - - before(() => { - component = setupMountedComponent( - LoginForm, - props, - fromJS({ - idp: { - use_identity_provider: false - }, - user: { - module: "primero", - agency: "unicef", - isAuthenticated: false - } - }) - ).component; - }); - - it("renders form", () => { - expect(component.find("form")).to.have.length(1); - }); - - it("renders h1 tag", () => { - expect(component.find("h1")).to.have.length(1); - }); - - it("renders username and password input fields", () => { - expect(component.find("input").first().prop("name")).to.have.equal("user_name"); - expect(component.find("input").last().prop("name")).to.have.equal("password"); - }); - - // TODO: Temp removal - // it("renders forgot password link", () => { - // expect( - // component - // .find("a") - // .first() - // .prop("href") - // ).to.have.equal("/forgot_password"); - // }); - - it("renders login button", () => { - expect(component.find("button").first().prop("type")).to.equal("submit"); - }); - - describe("when is demo site", () => { - const stateWithDemo = fromJS({ - application: { - primero: { - sandbox_ui: true - } - } - }); - const { component: componentWithDemo } = setupMountedComponent(LoginForm, props, stateWithDemo); - - it("should render PageHeading with 'demo' text", () => { - expect(componentWithDemo.find(PageHeading).text()).to.be.equal("sandbox_ui login.label"); - }); - - it("should render ActionButton with 'demo' text", () => { - expect(componentWithDemo.find(ActionButton).first().text()).to.equal("buttons.login logger.to sandbox_ui"); - }); - }); - - describe("when does not use external identity", () => { - const stateWithoutExternal = fromJS({ - application: { - primero: { - sandbox_ui: true - } - }, - idp: { - use_identity_provider: false - } - }); - const { component: componentWithDemo } = setupMountedComponent(LoginForm, props, stateWithoutExternal); - - it("renders the forgot password link", () => { - expect(componentWithDemo.find(ActionButton).last().text()).to.be.equal("login.forgot_password"); - }); - }); -}); diff --git a/app/javascript/components/login/components/login-form/styles.css b/app/javascript/components/login/components/login-form/styles.css index cf37b860dd..04af6c9bfb 100644 --- a/app/javascript/components/login/components/login-form/styles.css +++ b/app/javascript/components/login/components/login-form/styles.css @@ -32,7 +32,17 @@ color: var(--c-forgot-password-link) } -@media (max-width:599.95px) { +.loginButton { + background: var(--c-login-button-bg); + color: var(--c-login-button-text); + + &:hover { + filter: brightness(80%); + background-color: var(--c-login-button-bg) !important; + } +} + +@media (max-width:600px) { .loginForm { & button { width: 100%; diff --git a/app/javascript/components/login/components/password-reset-dialog/component.jsx b/app/javascript/components/login/components/password-reset-dialog/component.jsx index 025bdd8510..c9ce214fc5 100644 --- a/app/javascript/components/login/components/password-reset-dialog/component.jsx +++ b/app/javascript/components/login/components/password-reset-dialog/component.jsx @@ -10,7 +10,7 @@ import PasswordResetForm from "../password-reset-form"; import { NAME, FORM_ID } from "./constants"; -const Component = ({ open, handleCancel, handleSuccess }) => { +function Component({ open = false, handleCancel, handleSuccess }) { const i18n = useI18n(); const saving = useMemoizedSelector(state => getSavingNewPasswordReset(state)); @@ -36,14 +36,10 @@ const Component = ({ open, handleCancel, handleSuccess }) => { ); -}; +} Component.displayName = NAME; -Component.defaultProps = { - open: false -}; - Component.propTypes = { handleCancel: PropTypes.func, handleSuccess: PropTypes.func, diff --git a/app/javascript/components/login/components/password-reset-dialog/component.spec.js b/app/javascript/components/login/components/password-reset-dialog/component.spec.js new file mode 100644 index 0000000000..3494758f0b --- /dev/null +++ b/app/javascript/components/login/components/password-reset-dialog/component.spec.js @@ -0,0 +1,11 @@ +import { mountedComponent, screen } from "../../../../test-utils"; + +import PasswordResetDialog from "./component"; + +describe("login/components/", () => { + it("should render the password_reset_form", () => { + mountedComponent(); + expect(screen.getByText(/login.password_reset_modal_text/i)).toBeInTheDocument(); + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "form")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/login/components/password-reset-dialog/component.unit.test.js b/app/javascript/components/login/components/password-reset-dialog/component.unit.test.js deleted file mode 100644 index 5d16b01385..0000000000 --- a/app/javascript/components/login/components/password-reset-dialog/component.unit.test.js +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { FormSection, FormSectionField } from "../../../form"; -import { setupMountedComponent } from "../../../../test"; - -import PasswordResetDialog from "./component"; - -describe("login/components/", () => { - let component; - - before(() => { - component = setupMountedComponent(PasswordResetDialog, { open: true }, fromJS({})).component; - }); - - it("should render the password_reset_form", () => { - expect(component.find(FormSection)).to.have.lengthOf(1); - expect(component.find(FormSectionField)).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/login/components/password-reset-form/component.jsx b/app/javascript/components/login/components/password-reset-form/component.jsx index 32f45ddd06..0c09b4f043 100644 --- a/app/javascript/components/login/components/password-reset-form/component.jsx +++ b/app/javascript/components/login/components/password-reset-form/component.jsx @@ -16,7 +16,7 @@ import { getSavingNewPasswordReset } from "../../../pages/admin/users-form/selec import { form, validationSchema } from "./form"; import { FORM_ID } from "./constants"; -const Component = ({ modal, handleSubmit }) => { +function Component({ modal = false, handleSubmit }) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -59,14 +59,10 @@ const Component = ({ modal, handleSubmit }) => { )} ); -}; +} Component.displayName = "PasswordResetRequest"; -Component.defaultProps = { - modal: false -}; - Component.propTypes = { handleSubmit: PropTypes.func, modal: PropTypes.bool diff --git a/app/javascript/components/login/components/password-reset-form/component.spec.js b/app/javascript/components/login/components/password-reset-form/component.spec.js new file mode 100644 index 0000000000..099bfbe01a --- /dev/null +++ b/app/javascript/components/login/components/password-reset-form/component.spec.js @@ -0,0 +1,15 @@ +import { mountedComponent, screen } from "../../../../test-utils"; + +import PasswordResetForm from "./component"; + +describe("", () => { + it("does not render action buttons when modal is true", () => { + mountedComponent(); + expect(screen.queryAllByRole("button")).toHaveLength(0); + }); + + it("renders action buttons when modal is false", () => { + mountedComponent(); + expect(screen.getAllByRole("button")).toHaveLength(2); + }); +}); diff --git a/app/javascript/components/login/components/password-reset-form/component.unit.test.js b/app/javascript/components/login/components/password-reset-form/component.unit.test.js deleted file mode 100644 index fa18dad6aa..0000000000 --- a/app/javascript/components/login/components/password-reset-form/component.unit.test.js +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import ActionButton from "../../../action-button"; -import { setupMountedComponent } from "../../../../test"; - -import PasswordResetForm from "./component"; - -describe("", () => { - it("does not render action buttons when modal is true", () => { - const { component } = setupMountedComponent(PasswordResetForm, { modal: true }, fromJS({})); - - expect(component.find(ActionButton)).to.have.lengthOf(0); - }); - - it("renders action buttons when modal is false", () => { - const { component } = setupMountedComponent(PasswordResetForm, { modal: false }, fromJS({})); - - expect(component.find(ActionButton)).to.have.lengthOf(2); - }); -}); diff --git a/app/javascript/components/logout/component.jsx b/app/javascript/components/logout/component.jsx index 231e4d1085..ece0d415b6 100644 --- a/app/javascript/components/logout/component.jsx +++ b/app/javascript/components/logout/component.jsx @@ -1,25 +1,33 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { useLayoutEffect } from "react"; +import { useEffect, useLayoutEffect } from "react"; import { useDispatch } from "react-redux"; import { push } from "connected-react-router"; import usePushNotifications from "../push-notifications-toggle/use-push-notifications"; import { ROUTES } from "../../config"; import { setPendingUserLogin } from "../connectivity/action-creators"; +import { useMemoizedSelector } from "../../libs"; +import { getIsAuthenticated } from "../user"; import { NAME } from "./constants"; function Container() { const { stopRefreshNotificationTimer } = usePushNotifications(); const dispatch = useDispatch(); + const isAuthenticated = useMemoizedSelector(state => getIsAuthenticated(state)); useLayoutEffect(() => { dispatch(setPendingUserLogin(false)); stopRefreshNotificationTimer(); - dispatch(push(ROUTES.login)); }, []); + useEffect(() => { + if (!isAuthenticated) { + dispatch(push(ROUTES.login)); + } + }, [isAuthenticated]); + return false; } diff --git a/app/javascript/components/menu/component.jsx b/app/javascript/components/menu/component.jsx index 8798bb10f4..6ce2b8702e 100644 --- a/app/javascript/components/menu/component.jsx +++ b/app/javascript/components/menu/component.jsx @@ -2,14 +2,14 @@ import { useState } from "react"; import PropTypes from "prop-types"; -import { Menu } from "@material-ui/core"; -import MoreVertIcon from "@material-ui/icons/MoreVert"; +import { Menu } from "@mui/material"; +import MoreVertIcon from "@mui/icons-material/MoreVert"; import ActionButton, { ACTION_BUTTON_TYPES } from "../action-button"; import { MenuItems } from "./components"; -const Component = ({ actions, disabledCondition, showMenu }) => { +function Component({ actions = [], disabledCondition = () => {}, showMenu = false }) { const [anchorEl, setAnchorEl] = useState(null); const handleClick = event => { @@ -37,6 +37,7 @@ const Component = ({ actions, disabledCondition, showMenu }) => { )} { ); -}; - -Component.defaultProps = { - actions: [], - disabledCondition: () => {}, - showMenu: false -}; +} Component.displayName = "Menu"; diff --git a/app/javascript/components/menu/components/menu-item/component.jsx b/app/javascript/components/menu/components/menu-item/component.jsx index 7979c5d34a..d95ed4dfe3 100644 --- a/app/javascript/components/menu/components/menu-item/component.jsx +++ b/app/javascript/components/menu/components/menu-item/component.jsx @@ -1,13 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { MenuItem } from "@material-ui/core"; +import { MenuItem } from "@mui/material"; import { forwardRef } from "react"; import DisableOffline from "../../../disable-offline"; import { ConditionalWrapper } from "../../../../libs"; -const Component = forwardRef(({ action, disabledCondition, handleClose }, ref) => { +const Component = forwardRef(({ action = {}, disabledCondition, handleClose }, ref) => { const { id, disableOffline, name, action: handleAction } = action; const handleClick = () => { @@ -26,10 +26,6 @@ const Component = forwardRef(({ action, disabledCondition, handleClose }, ref) = Component.displayName = "MenuItem"; -Component.defaultProps = { - action: {} -}; - Component.propTypes = { action: PropTypes.object, disabledCondition: PropTypes.func, diff --git a/app/javascript/components/menu/components/menu-items/component.jsx b/app/javascript/components/menu/components/menu-items/component.jsx index cc24b8862a..3707d1a941 100644 --- a/app/javascript/components/menu/components/menu-items/component.jsx +++ b/app/javascript/components/menu/components/menu-items/component.jsx @@ -5,7 +5,7 @@ import { forwardRef } from "react"; import MenuItem from "../menu-item"; -const Component = forwardRef(({ actions, disabledCondition, handleClose }, ref) => ( +const Component = forwardRef(({ actions = [], disabledCondition = () => {}, handleClose }, ref) => (
{actions.map(action => ( {} -}; - Component.propTypes = { actions: PropTypes.array, disabledCondition: PropTypes.func, diff --git a/app/javascript/components/mobile-toolbar/component.jsx b/app/javascript/components/mobile-toolbar/component.jsx index 1b0dd1d319..dbe1618732 100644 --- a/app/javascript/components/mobile-toolbar/component.jsx +++ b/app/javascript/components/mobile-toolbar/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import MenuIcon from "@material-ui/icons/Menu"; -import { AppBar, Toolbar, IconButton, Hidden } from "@material-ui/core"; +import MenuIcon from "@mui/icons-material/Menu"; +import { AppBar, Toolbar, IconButton, Box } from "@mui/material"; import PropTypes from "prop-types"; import NetworkIndicator from "../network-indicator"; @@ -13,7 +13,7 @@ import Jewel from "../jewel"; import css from "./styles.css"; -const MobileToolbar = ({ openDrawer, hasUnsubmittedOfflineChanges = false }) => { +function MobileToolbar({ openDrawer, hasUnsubmittedOfflineChanges = false }) { const { demo } = useApp(); const i18n = useI18n(); @@ -21,10 +21,10 @@ const MobileToolbar = ({ openDrawer, hasUnsubmittedOfflineChanges = false }) => const demoText = demo ?
{i18n.t(DEMO)}
: null; return ( - - - - + + + + {hasUnsubmittedOfflineChanges && (
@@ -39,9 +39,9 @@ const MobileToolbar = ({ openDrawer, hasUnsubmittedOfflineChanges = false }) =>
-
+ ); -}; +} MobileToolbar.displayName = "MobileToolbar"; diff --git a/app/javascript/components/mobile-toolbar/component.spec.js b/app/javascript/components/mobile-toolbar/component.spec.js new file mode 100644 index 0000000000..2ec3a802c9 --- /dev/null +++ b/app/javascript/components/mobile-toolbar/component.spec.js @@ -0,0 +1,46 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen, setScreenSizeToMobile } from "../../test-utils"; + +import MobileToolbar from "./component"; + +describe("", () => { + const state = fromJS({ MobileToolbar: { module: "primero" } }); + const props = { openDrawer: () => {} }; + + beforeAll(() => { + setScreenSizeToMobile(false); + }); + + it("should render MobileToolbar component", () => { + mountedComponent(, state); + expect(screen.getByTestId("appBar")).toBeInTheDocument(); + }); + + it("should render Logo component", () => { + mountedComponent(, state); + expect(screen.getByTestId("logo-primero")).toBeInTheDocument(); + }); + + describe("when is not demo site", () => { + it("should not render a
tag with 'Demo' text", () => { + mountedComponent(, state); + expect(screen.queryByText(/sandbox_ui/i)).not.toBeInTheDocument(); + }); + }); + + describe("when is demo site", () => { + const stateWithDemo = fromJS({ + application: { + primero: { + sandbox_ui: true + } + } + }); + + it("should render a
tag with 'Demo' text", () => { + mountedComponent(, stateWithDemo); + expect(screen.getByText(/sandbox_ui/i)).toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/mobile-toolbar/component.unit.test.js b/app/javascript/components/mobile-toolbar/component.unit.test.js deleted file mode 100644 index a3ee88224f..0000000000 --- a/app/javascript/components/mobile-toolbar/component.unit.test.js +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { AppBar, Toolbar, IconButton, Hidden } from "@material-ui/core"; - -import { setupMountedComponent } from "../../test"; -import ModuleLogo from "../module-logo"; - -import MobileToolbar from "./component"; - -describe("", () => { - let component; - const state = fromJS({ MobileToolbar: { module: "primero" } }); - const props = { openDrawer: () => {} }; - - beforeEach(() => { - ({ component } = setupMountedComponent(MobileToolbar, props, state)); - }); - - it("should render Hidden component", () => { - expect(component.find(Hidden)).to.have.lengthOf(1); - }); - it("should render AppBar component", () => { - expect(component.find(AppBar)).to.have.lengthOf(1); - }); - - it("should render Toolbar component", () => { - expect(component.find(Toolbar)).to.have.lengthOf(1); - }); - - it("should render IconButton component", () => { - expect(component.find(IconButton)).to.have.lengthOf(1); - }); - - it("should render ModuleLogo component", () => { - expect(component.find(ModuleLogo)).to.have.lengthOf(1); - }); - - describe("when is not demo site", () => { - it("should not render a
tag with 'Demo' text", () => { - expect(component.find("div")).to.be.empty; - }); - }); - - describe("when is demo site", () => { - const stateWithDemo = fromJS({ - application: { - demo: true - } - }); - const { component: componentWithDemo } = setupMountedComponent(MobileToolbar, props, stateWithDemo); - - it("should render a
tag with 'Demo' text", () => { - expect(componentWithDemo.find("div").at(0)).to.have.lengthOf(1); - }); - }); -}); diff --git a/app/javascript/components/mobile-toolbar/styles.css b/app/javascript/components/mobile-toolbar/styles.css index 0d05030b86..dc78dad7ff 100644 --- a/app/javascript/components/mobile-toolbar/styles.css +++ b/app/javascript/components/mobile-toolbar/styles.css @@ -27,9 +27,19 @@ height: 2.5rem; display: flex; - & div { + & > div { margin: 0; display: flex; + align-items: center; + } + + & div { + display: flex; + align-items: center; + } + + & > div div:first-of-type { + margin: 0; } & img { @@ -70,9 +80,10 @@ color: var(--c-dark-grey); font-weight: bold; text-transform: uppercase; + flex: 1; } -@media (max-width: 959.95px) { +@media (max-width: 900px) { .toolbar, .toolbar-demo { & img { margin: 0; diff --git a/app/javascript/components/module-logo/component.jsx b/app/javascript/components/module-logo/component.jsx index dbb7755eb3..56e6a62ec8 100644 --- a/app/javascript/components/module-logo/component.jsx +++ b/app/javascript/components/module-logo/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { useMediaQuery } from "@material-ui/core"; +import { useMediaQuery } from "@mui/material"; import useMemoizedSelector from "../../libs/use-memoized-selector"; import { getSiteTitle, getThemeLogos } from "../application/selectors"; @@ -10,21 +10,27 @@ import css from "./styles.css"; import { getLogo } from "./utils"; import { getModuleLogoID } from "./selectors"; -const ModuleLogo = ({ moduleLogo, white, useModuleLogo }) => { +function ModuleLogo({ moduleLogo, white, useModuleLogo }) { const tabletDisplay = useMediaQuery(theme => theme.breakpoints.only("md")); const moduleLogoID = useMemoizedSelector(state => getModuleLogoID(state)); const themeLogos = useMemoizedSelector(state => getThemeLogos(state)); const siteTitle = useMemoizedSelector(state => getSiteTitle(state)); + const selectedModuleLogo = moduleLogo || moduleLogoID; - const [fullLogo, smallLogo] = getLogo(moduleLogo || moduleLogoID, white, themeLogos, useModuleLogo); + const [fullLogo, smallLogo] = getLogo(selectedModuleLogo, white, themeLogos, useModuleLogo); return (
- {siteTitle} + {siteTitle}
); -}; +} ModuleLogo.displayName = "ModuleLogo"; diff --git a/app/javascript/components/module-logo/component.unit.test.js b/app/javascript/components/module-logo/component.spec.js similarity index 60% rename from app/javascript/components/module-logo/component.unit.test.js rename to app/javascript/components/module-logo/component.spec.js index 28a96cdf7e..d3ef9681d1 100644 --- a/app/javascript/components/module-logo/component.unit.test.js +++ b/app/javascript/components/module-logo/component.spec.js @@ -1,12 +1,8 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - import { fromJS } from "immutable"; -import PrimeroLogo from "../../images/primero-logo.png"; -import MRMLogo from "../../images/mrm-logo.png"; -import { setupMountedComponent } from "../../test"; -import { MODULES } from "../../config"; +import { mountedComponent, screen } from "../../test-utils"; import { PrimeroModuleRecord } from "../application/records"; +import { MODULES } from "../../config"; import ModuleLogo from "./component"; @@ -25,9 +21,8 @@ describe("", () => { } }); - const { component } = setupMountedComponent(ModuleLogo, {}, state); - - expect(component.find("img").prop("src")).to.equal(PrimeroLogo); + mountedComponent(, state); + expect(screen.getByTestId("logo-primero")).toBeInTheDocument(); }); it("renders a primero module logo from props", () => { @@ -44,8 +39,7 @@ describe("", () => { } }); - const { component } = setupMountedComponent(ModuleLogo, {}, state); - - expect(component.find("img").prop("src")).to.equal(MRMLogo); + mountedComponent(, state); + expect(screen.getByTestId("logo-primeromodule-mrm")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/module-logo/styles.css b/app/javascript/components/module-logo/styles.css index 6d594b4436..22b46e8dcb 100644 --- a/app/javascript/components/module-logo/styles.css +++ b/app/javascript/components/module-logo/styles.css @@ -9,7 +9,7 @@ height: auto; } -@media (min-width:600px) and (max-width:1279.95px) { +@media (min-width:600px) and (max-width:1200px) { .logoContainer { margin: 1.25em 0.5em 2.154em 0.5em; } diff --git a/app/javascript/components/nav/component.jsx b/app/javascript/components/nav/component.jsx index 2602dd7f4e..e9efd6f2cb 100644 --- a/app/javascript/components/nav/component.jsx +++ b/app/javascript/components/nav/component.jsx @@ -1,12 +1,12 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Drawer, List, useMediaQuery, Hidden, Divider, IconButton } from "@material-ui/core"; +import { Drawer, List, useMediaQuery, Divider, IconButton, Box } from "@mui/material"; import { useCallback, useEffect, useState } from "react"; import { useDispatch } from "react-redux"; -import CloseIcon from "@material-ui/icons/Close"; +import CloseIcon from "@mui/icons-material/Close"; import { push } from "connected-react-router"; import { isEqual } from "lodash"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; import { ROUTES, PERMITTED_URL, APPLICATION_NAV } from "../../config"; import AgencyLogo from "../agency-logo"; @@ -31,7 +31,7 @@ import { fetchAlerts } from "./action-creators"; import { getUserId, selectUsername, selectAlerts } from "./selectors"; import MenuEntry from "./components/menu-entry"; -const Nav = () => { +function Nav() { const mobileDisplay = useMediaQuery(theme => theme.breakpoints.down("sm")); const dispatch = useDispatch(); const i18n = useI18n(); @@ -44,7 +44,6 @@ const Nav = () => { }, []); const { demo, useContainedNavStyle } = useApp(); - const username = useMemoizedSelector(state => selectUsername(state), isEqual); const userId = useMemoizedSelector(state => getUserId(state), isEqual); const dataAlerts = useMemoizedSelector(state => selectAlerts(state), isEqual); @@ -70,12 +69,14 @@ const Nav = () => { const permittedMenuEntries = menuEntries => { return menuEntries.map(menuEntry => { + const key = menuEntry.to || menuEntry.component; + if (menuEntry.component) { const CustomComponent = { fieldMode: FieldMode }[menuEntry.component]; - return ; + return ; } const jewel = dataAlerts.get(menuEntry?.jewelCount, null); @@ -86,7 +87,7 @@ const Nav = () => { (hasUnsubmittedOfflineChanges && route === ROUTES.support); const renderedMenuEntries = ( { return PERMITTED_URL.includes(route) ? ( renderedMenuEntries ) : ( - + {renderedMenuEntries} ); }); }; - const navListClasses = clsx(css.navList, { [css.contained]: useContainedNavStyle }); - const translationsToggleClass = clsx(css.translationToggle, css.navTranslationsToggle, { + const navListClasses = cx(css.navList, { [css.contained]: useContainedNavStyle }); + const translationsToggleClass = cx(css.translationToggle, css.navTranslationsToggle, { [css.contained]: useContainedNavStyle }); - const drawerHeaderClasses = clsx(css.drawerHeader, { [css.drawerHeaderContained]: useContainedNavStyle }); + const drawerHeaderClasses = cx(css.drawerHeader, { [css.drawerHeaderContained]: useContainedNavStyle }); const drawerContent = ( <> - + - +
- +
- +
-
+
@@ -156,7 +157,7 @@ const Nav = () => { openDrawer={handleToggleDrawer(true)} hasUnsubmittedOfflineChanges={hasUnsubmittedOfflineChanges} /> - + { > {drawerContent} - - + + {drawerContent} - + { ); -}; +} Nav.displayName = NAME; diff --git a/app/javascript/components/nav/component.spec.js b/app/javascript/components/nav/component.spec.js new file mode 100644 index 0000000000..47c085cb27 --- /dev/null +++ b/app/javascript/components/nav/component.spec.js @@ -0,0 +1,213 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen } from "../../test-utils"; +import { ACTIONS } from "../permissions"; + +import Nav from "./component"; + +describe("
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/admin/form-builder/components/translations-tab/component.spec.js b/app/javascript/components/pages/admin/form-builder/components/translations-tab/component.spec.js new file mode 100644 index 0000000000..9a4119e8b8 --- /dev/null +++ b/app/javascript/components/pages/admin/form-builder/components/translations-tab/component.spec.js @@ -0,0 +1,22 @@ +import { mountedFormComponent, screen } from "test-utils"; + +import TranslationsTab from "./component"; + +describe("", () => { + const props = { + index: 1, + tab: 1, + formContextFields: {}, + fieldDialogMode: "new", + moduleId: "module_1", + parentForm: "parent" + }; + + beforeEach(() => { + mountedFormComponent(); + }); + + it.skip("should render ", () => { + expect(screen.getByText("forms.translations.title")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/admin/form-builder/components/translations-tab/component.unit.test.js b/app/javascript/components/pages/admin/form-builder/components/translations-tab/component.unit.test.js deleted file mode 100644 index a9e696b719..0000000000 --- a/app/javascript/components/pages/admin/form-builder/components/translations-tab/component.unit.test.js +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMockFormComponent } from "../../../../../../test"; - -import TranslationsTab from "./component"; - -describe("", () => { - let component; - - beforeEach(() => { - ({ component } = setupMockFormComponent(TranslationsTab, { - props: { - index: 1, - tab: 1, - formContextFields: {}, - fieldDialogMode: "new", - moduleId: "module_1", - parentForm: "parent" - } - })); - }); - - it("should render ", () => { - expect(component.find(TranslationsTab)).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/pages/admin/form-builder/components/utils.js b/app/javascript/components/pages/admin/form-builder/components/utils.js index 95667c297b..e3685cbeed 100644 --- a/app/javascript/components/pages/admin/form-builder/components/utils.js +++ b/app/javascript/components/pages/admin/form-builder/components/utils.js @@ -39,7 +39,7 @@ export const getFiedListItemTheme = currentTheme => ({ }, MuiButton: { root: { - "&$disabled": { + "&.Mui-disabled": { color: "rgba(0, 0, 0, 0.26)", backgroundColor: "transparent !important" } diff --git a/app/javascript/components/pages/admin/form-builder/forms.js b/app/javascript/components/pages/admin/form-builder/forms.js index 164960c4c0..8098ce7fe6 100644 --- a/app/javascript/components/pages/admin/form-builder/forms.js +++ b/app/javascript/components/pages/admin/form-builder/forms.js @@ -5,7 +5,7 @@ import isEmpty from "lodash/isEmpty"; import some from "lodash/some"; import { array, boolean, object, string } from "yup"; -import { RECORD_TYPES } from "../../../../config/constants"; +import { RECORD_TYPES } from "../../../../config"; import { FieldRecord, FormSectionRecord, diff --git a/app/javascript/components/pages/admin/form-builder/utils/convert-to-fields-object.js b/app/javascript/components/pages/admin/form-builder/utils/convert-to-fields-object.js index f876ddd316..49a5871dc2 100644 --- a/app/javascript/components/pages/admin/form-builder/utils/convert-to-fields-object.js +++ b/app/javascript/components/pages/admin/form-builder/utils/convert-to-fields-object.js @@ -1,4 +1,4 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. export default fields => - fields.map(field => ({ [field.name]: field })).reduce((acc, value) => ({ ...acc, ...value }), {}); + fields?.map(field => ({ [field.name]: field })).reduce((acc, value) => ({ ...acc, ...value }), {}); diff --git a/app/javascript/components/pages/admin/form-builder/utils/get-subform-error-messages.unit.test.js b/app/javascript/components/pages/admin/form-builder/utils/get-subform-error-messages.unit.test.js index 4c4207f077..9de08b235b 100644 --- a/app/javascript/components/pages/admin/form-builder/utils/get-subform-error-messages.unit.test.js +++ b/app/javascript/components/pages/admin/form-builder/utils/get-subform-error-messages.unit.test.js @@ -2,7 +2,7 @@ import { fromJS } from "immutable"; -import { translateOptions } from "../../../../../test"; +import { translateOptions } from "../../../../../test-utils"; import getSubformErrorMessages from "./get-subform-error-messages"; diff --git a/app/javascript/components/pages/admin/forms-list/action-creators.js b/app/javascript/components/pages/admin/forms-list/action-creators.js index afeb268117..b27ecc2935 100644 --- a/app/javascript/components/pages/admin/forms-list/action-creators.js +++ b/app/javascript/components/pages/admin/forms-list/action-creators.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { RECORD_PATH, METHODS } from "../../../../config/constants"; +import { RECORD_PATH, METHODS } from "../../../../config"; import { ENQUEUE_SNACKBAR, generate } from "../../../notifier"; import { CLEAR_DIALOG } from "../../../action-dialog"; diff --git a/app/javascript/components/pages/admin/forms-list/component.jsx b/app/javascript/components/pages/admin/forms-list/component.jsx index dd3fd38b4d..19677c351c 100644 --- a/app/javascript/components/pages/admin/forms-list/component.jsx +++ b/app/javascript/components/pages/admin/forms-list/component.jsx @@ -5,13 +5,13 @@ import { batch, useDispatch } from "react-redux"; import { push } from "connected-react-router"; import { useLocation } from "react-router-dom"; import { DragDropContext, Droppable } from "react-beautiful-dnd"; -import { Add as AddIcon, List as ListIcon, SwapVert } from "@material-ui/icons"; +import { Add as AddIcon, List as ListIcon, SwapVert } from "@mui/icons-material"; import LoadingIndicator from "../../../loading-indicator"; import { useI18n } from "../../../i18n"; import { useApp } from "../../../application"; import { PageHeading, PageContent } from "../../../page"; -import { MODULES, RECORD_TYPES } from "../../../../config/constants"; +import { MODULES, RECORD_TYPES } from "../../../../config"; import Permission, { usePermissions, CREATE_RECORDS, RESOURCES, MANAGE } from "../../../permissions"; import { FormAction, OPTION_TYPES } from "../../../form"; import { useMemoizedSelector } from "../../../../libs"; @@ -38,7 +38,7 @@ import { getFormGroups, getListStyle } from "./utils"; import { NAME, FORM_GROUP_PREFIX, ORDER_TYPE } from "./constants"; import css from "./styles.css"; -const Component = () => { +function Component() { const i18n = useI18n(); const { limitedProductionSite } = useApp(); const { pathname } = useLocation(); @@ -151,7 +151,7 @@ const Component = () => { filters={filterValues} setPending={setDialogPending} /> -
+
{ ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/admin/forms-list/component.unit.test.js b/app/javascript/components/pages/admin/forms-list/component.spec.js similarity index 65% rename from app/javascript/components/pages/admin/forms-list/component.unit.test.js rename to app/javascript/components/pages/admin/forms-list/component.spec.js index 4053b49275..6f5b454c93 100644 --- a/app/javascript/components/pages/admin/forms-list/component.unit.test.js +++ b/app/javascript/components/pages/admin/forms-list/component.spec.js @@ -2,21 +2,16 @@ import { fromJS } from "immutable"; -import { setupMountedComponent } from "../../../../test"; +import { mountedComponent, screen } from "../../../../test-utils"; import { mapEntriesToRecord } from "../../../../libs"; import { FormSectionRecord } from "../../../record-form/records"; -import { RECORD_TYPES } from "../../../../config/constants"; +import { RECORD_TYPES } from "../../../../config"; import { PrimeroModuleRecord } from "../../../application/records"; import { ACTIONS } from "../../../permissions"; import FormsList from "./component"; -import ReorderActions from "./components/reorder-actions"; -import FormFilters from "./components/form-filters"; -import FormGroup from "./components/form-group"; describe("", () => { - let component; - const formSections = [ { id: 1, @@ -100,51 +95,31 @@ describe("", () => { } }); - beforeEach(() => { - ({ component } = setupMountedComponent(FormsList, {}, initialState)); - }); - it("renders ", () => { - expect(component.find("header h1").text()).to.equal("forms.label"); + mountedComponent(, initialState); + expect(screen.getByText(/forms.label/i)).toBeInTheDocument(); }); it("renders ", () => { - expect(component.find(FormFilters)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(screen.getByTestId("forms-list")).toBeInTheDocument(); }); it("renders form sections", () => { - expect(component.find(FormGroup)).to.have.lengthOf(2); + mountedComponent(, initialState); + expect(screen.getAllByTestId("form-group")).toHaveLength(2); }); describe("when there are no records", () => { const stateWithoutRecords = initialState.setIn(["records", "admin", "forms", "formSections"], fromJS([])); - beforeEach(() => { - ({ component } = setupMountedComponent(FormsList, {}, stateWithoutRecords)); - }); - it("renders ", () => { - expect(component.find(FormFilters)).to.have.lengthOf(1); + mountedComponent(, stateWithoutRecords); + expect(screen.getByTestId("form-list")).toBeInTheDocument(); }); - it("does not renders form sections", () => { - expect(component.find(FormGroup)).to.have.lengthOf(0); - }); - }); - - describe("when there reorder is enabled", () => { - const stateReorderEnabled = initialState.setIn(["records", "admin", "forms", "reorderedForms", "enabled"], true); - - beforeEach(() => { - ({ component } = setupMountedComponent(FormsList, {}, stateReorderEnabled)); - }); - - it("renders the ", () => { - expect(component.find(ReorderActions)).to.have.lengthOf(1); - }); - - it("disable the ", () => { - expect(component.find(FormFilters).props().disabled).to.be.true; + mountedComponent(, stateWithoutRecords); + expect(screen.queryAllByTestId("form-group")).toHaveLength(0); }); }); }); diff --git a/app/javascript/components/pages/admin/forms-list/components/drag-indicator/component.jsx b/app/javascript/components/pages/admin/forms-list/components/drag-indicator/component.jsx index 7795c6333b..d9a65853fd 100644 --- a/app/javascript/components/pages/admin/forms-list/components/drag-indicator/component.jsx +++ b/app/javascript/components/pages/admin/forms-list/components/drag-indicator/component.jsx @@ -1,27 +1,23 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Icon } from "@material-ui/core"; -import DragIndicatorIcon from "@material-ui/icons/DragIndicator"; +import { Icon } from "@mui/material"; +import DragIndicatorIcon from "@mui/icons-material/DragIndicator"; import css from "../../styles.css"; -const Component = ({ isDragDisabled, ...props }) => { +function Component({ isDragDisabled = false, ...props }) { const classes = isDragDisabled ? { classes: { root: css.dragIndicator } } : {}; return ( - + ); -}; +} Component.displayName = "DragIndicator"; -Component.defaultProps = { - isDragDisabled: false -}; - Component.propTypes = { isDragDisabled: PropTypes.bool, props: PropTypes.object diff --git a/app/javascript/components/pages/admin/forms-list/components/drag-indicator/component.spec.js b/app/javascript/components/pages/admin/forms-list/components/drag-indicator/component.spec.js new file mode 100644 index 0000000000..86c4abce5b --- /dev/null +++ b/app/javascript/components/pages/admin/forms-list/components/drag-indicator/component.spec.js @@ -0,0 +1,15 @@ +import { mountedComponent, screen } from "test-utils"; + +import DragIndicator from "./component"; + +describe("/components/", () => { + beforeEach(() => { + const props = { color: "error" }; + + mountedComponent(, props); + }); + + it("renders icon", () => { + expect(screen.getByTestId("drag-indicator")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/admin/forms-list/components/drag-indicator/component.unit.test.js b/app/javascript/components/pages/admin/forms-list/components/drag-indicator/component.unit.test.js deleted file mode 100644 index af8a26c9e0..0000000000 --- a/app/javascript/components/pages/admin/forms-list/components/drag-indicator/component.unit.test.js +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Icon } from "@material-ui/core"; -import DragIndicatorIcon from "@material-ui/icons/DragIndicator"; - -import { setupMountedComponent } from "../../../../../../test"; - -import DragIndicator from "./component"; - -describe("/components/", () => { - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(DragIndicator, { color: "error" })); - }); - - it("renders icon", () => { - expect(component.find(DragIndicatorIcon)).to.have.lengthOf(1); - expect(component.find(Icon)).to.have.lengthOf(1); - }); - - it("renders passes through props to icon", () => { - expect(component.find(Icon).prop("color")).to.equal("error"); - }); -}); diff --git a/app/javascript/components/pages/admin/forms-list/components/filter-input/component.jsx b/app/javascript/components/pages/admin/forms-list/components/filter-input/component.jsx index f343b6179b..2f19b1becc 100644 --- a/app/javascript/components/pages/admin/forms-list/components/filter-input/component.jsx +++ b/app/javascript/components/pages/admin/forms-list/components/filter-input/component.jsx @@ -1,12 +1,12 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import ToggleButton from "@material-ui/lab/ToggleButton"; -import ToggleButtonGroup from "@material-ui/lab/ToggleButtonGroup"; +import ToggleButton from "@mui/material/ToggleButton"; +import ToggleButtonGroup from "@mui/material/ToggleButtonGroup"; import css from "../../styles.css"; -const Component = ({ handleSetFilterValue, options, name, filterValues, id: filterID }) => { +function Component({ handleSetFilterValue, options = [], name, filterValues = {}, id: filterID }) { const renderOptions = () => options.map(option => { const { displayName, id } = option; @@ -34,21 +34,15 @@ const Component = ({ handleSetFilterValue, options, name, filterValues, id: filt onChange={handleChange} size="small" exclusive - disabled classes={{ root: css.toggleContainer }} > {renderOptions()} ); -}; +} Component.displayName = "FilterInput"; -Component.defaultProps = { - filterValues: {}, - options: [] -}; - Component.propTypes = { filterValues: PropTypes.object, handleSetFilterValue: PropTypes.func.isRequired, diff --git a/app/javascript/components/pages/admin/forms-list/components/filter-input/component.spec.js b/app/javascript/components/pages/admin/forms-list/components/filter-input/component.spec.js new file mode 100644 index 0000000000..88714a5bf0 --- /dev/null +++ b/app/javascript/components/pages/admin/forms-list/components/filter-input/component.spec.js @@ -0,0 +1,30 @@ +import { mountedComponent, screen } from "test-utils"; + +import FilterInput from "./component"; + +describe("/components/", () => { + beforeEach(() => { + const props = { + id: "filter_1", + name: "Filter 1", + options: [ + { + id: "option_1", + displayName: "Option 1" + }, + { + id: "option_2", + displayName: "Option 2" + } + ], + handleSetFilterValue: () => {} + }; + + mountedComponent(); + }); + + it("renders toggle input with options", () => { + expect(screen.getByText("Option 1")).toBeInTheDocument(); + expect(screen.getByText("Option 2")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/admin/forms-list/components/filter-input/component.unit.test.js b/app/javascript/components/pages/admin/forms-list/components/filter-input/component.unit.test.js deleted file mode 100644 index 9a6ab05f0f..0000000000 --- a/app/javascript/components/pages/admin/forms-list/components/filter-input/component.unit.test.js +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import ToggleButton from "@material-ui/lab/ToggleButton"; - -import { setupMountedComponent } from "../../../../../../test"; - -import FilterInput from "./component"; - -describe("/components/", () => { - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(FilterInput, { - id: "filter_1", - name: "Filter 1", - options: [ - { - id: "option_1", - displayName: "Option 1" - }, - { - id: "option_2", - displayName: "Option 2" - } - ], - handleSetFilterValue: () => {} - })); - }); - - it("renders toggle input with options", () => { - expect(component.find(FilterInput)).to.have.lengthOf(1); - - expect(component.find(ToggleButton)).to.have.lengthOf(2); - }); - - it.skip("responds to onChange with passed function", () => {}); -}); diff --git a/app/javascript/components/pages/admin/forms-list/components/filters-expansion-panel/component.jsx b/app/javascript/components/pages/admin/forms-list/components/filters-expansion-panel/component.jsx index 99c67dcd34..38539e1306 100644 --- a/app/javascript/components/pages/admin/forms-list/components/filters-expansion-panel/component.jsx +++ b/app/javascript/components/pages/admin/forms-list/components/filters-expansion-panel/component.jsx @@ -1,14 +1,14 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Accordion, AccordionSummary, AccordionDetails } from "@material-ui/core"; -import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; +import { Accordion, AccordionSummary, AccordionDetails } from "@mui/material"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import FilterInput from "../filter-input"; -const Component = ({ name, handleSetFilterValue, options, id, filterValues }) => { +function Component({ name, handleSetFilterValue, options = [], id, filterValues = {} }) { return ( - + }>{name} ); -}; +} Component.displayName = "FiltersExpansionPanel"; -Component.defaultProps = { - filterValues: {}, - options: [] -}; - Component.propTypes = { filterValues: PropTypes.object, handleSetFilterValue: PropTypes.func.isRequired, diff --git a/app/javascript/components/pages/admin/forms-list/components/filters-expansion-panel/component.unit.test.js b/app/javascript/components/pages/admin/forms-list/components/filters-expansion-panel/component.spec.js similarity index 100% rename from app/javascript/components/pages/admin/forms-list/components/filters-expansion-panel/component.unit.test.js rename to app/javascript/components/pages/admin/forms-list/components/filters-expansion-panel/component.spec.js diff --git a/app/javascript/components/pages/admin/forms-list/components/form-exporter/component.jsx b/app/javascript/components/pages/admin/forms-list/components/form-exporter/component.jsx index 5137757ce2..ec73cc2cbc 100644 --- a/app/javascript/components/pages/admin/forms-list/components/form-exporter/component.jsx +++ b/app/javascript/components/pages/admin/forms-list/components/form-exporter/component.jsx @@ -16,7 +16,7 @@ import validations from "./validations"; import { NAME, EXPORT_TYPES, EXPORTED_URL, FORM_ID } from "./constants"; import { form } from "./form"; -const Component = ({ close, filters, i18n, open, pending, setPending }) => { +function Component({ close, filters, i18n, open, pending, setPending }) { const dispatch = useDispatch(); const { recordType, primeroModule } = filters; const dialogPending = typeof pending === "object" ? pending.get("pending") : pending; @@ -68,7 +68,7 @@ const Component = ({ close, filters, i18n, open, pending, setPending }) => { /> ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/admin/forms-list/components/form-exporter/component.spec.js b/app/javascript/components/pages/admin/forms-list/components/form-exporter/component.spec.js new file mode 100644 index 0000000000..41c3e811c5 --- /dev/null +++ b/app/javascript/components/pages/admin/forms-list/components/form-exporter/component.spec.js @@ -0,0 +1,21 @@ +import { mountedComponent, screen } from "test-utils"; + +import FormExporter from "./component"; + +describe("/components/", () => { + const props = { + close: () => {}, + filters: {}, + i18n: { t: value => value }, + open: true, + pending: false + }; + + beforeEach(() => { + mountedComponent(); + }); + + it("renders ", () => { + expect(screen.getByRole("dialog")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/admin/forms-list/components/form-exporter/component.unit.test.js b/app/javascript/components/pages/admin/forms-list/components/form-exporter/component.unit.test.js deleted file mode 100644 index 790e37ac71..0000000000 --- a/app/javascript/components/pages/admin/forms-list/components/form-exporter/component.unit.test.js +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../../../test"; -import ActionDialog from "../../../../../action-dialog"; - -import FormExporter from "./component"; - -describe("/components/", () => { - const props = { - close: () => {}, - filters: {}, - i18n: { t: value => value }, - open: true, - pending: false - }; - - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(FormExporter, props)); - }); - - it("renders ", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(1); - }); - - it("renders valid props for FormExporter component", () => { - const clone = { ...component.find(FormExporter).props() }; - - ["close", "filters", "i18n", "open", "pending"].forEach(property => { - expect(clone).to.have.property(property); - delete clone[property]; - }); - - expect(clone).to.be.empty; - }); -}); diff --git a/app/javascript/components/pages/admin/forms-list/components/form-filters/component.jsx b/app/javascript/components/pages/admin/forms-list/components/form-filters/component.jsx index ece7fea8d6..d68e7ef124 100644 --- a/app/javascript/components/pages/admin/forms-list/components/form-filters/component.jsx +++ b/app/javascript/components/pages/admin/forms-list/components/form-filters/component.jsx @@ -1,16 +1,16 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; -import { RECORD_TYPES } from "../../../../../../config/constants"; +import { RECORD_TYPES } from "../../../../../../config"; import css from "../../styles.css"; import { useI18n } from "../../../../../i18n"; import FiltersExpansionPanel from "../filters-expansion-panel"; import ActionButton from "../../../../../action-button"; import { ACTION_BUTTON_TYPES } from "../../../../../action-button/constants"; -const Component = ({ filterValues, modules, handleSetFilterValue, handleClearValue, disabled }) => { +function Component({ filterValues = {}, modules, handleSetFilterValue, handleClearValue, disabled = false }) { const i18n = useI18n(); const filters = [ @@ -52,10 +52,10 @@ const Component = ({ filterValues, modules, handleSetFilterValue, handleClearVal filterValues={filterValues} /> )); - const classes = clsx({ [css.disabledFilters]: disabled }); + const classes = cx({ [css.disabledFilters]: disabled }); return ( -
+
); -}; +} Component.displayName = "FormFilters"; -Component.defaultProps = { - disabled: false, - filterValues: {} -}; - Component.propTypes = { disabled: PropTypes.bool, filterValues: PropTypes.object, diff --git a/app/javascript/components/pages/admin/forms-list/components/form-filters/component.spec.js b/app/javascript/components/pages/admin/forms-list/components/form-filters/component.spec.js new file mode 100644 index 0000000000..81446d816b --- /dev/null +++ b/app/javascript/components/pages/admin/forms-list/components/form-filters/component.spec.js @@ -0,0 +1,35 @@ +import { mountedComponent, screen } from "test-utils"; +import { List } from "immutable"; + +import FormExporter from "./component"; + +describe("/components/", () => { + const props = { + modules: List([ + { + name: "Module 1", + unique_id: "module-1", + associated_record_types: ["record-type-1"] + }, + { + name: "Module 2", + unique_id: "module-2", + associated_record_types: ["record-type-2"] + } + ]), + handleClearValue: () => {}, + handleSetFilterValue: () => {} + }; + + beforeEach(() => { + mountedComponent(); + }); + + it("renders clear button", () => { + expect(screen.getByText("clear")).toBeInTheDocument(); + }); + + it("renders ", () => { + expect(screen.getAllByTestId("accordion")).toHaveLength(2); + }); +}); diff --git a/app/javascript/components/pages/admin/forms-list/components/form-filters/component.unit.test.js b/app/javascript/components/pages/admin/forms-list/components/form-filters/component.unit.test.js deleted file mode 100644 index b22f619590..0000000000 --- a/app/javascript/components/pages/admin/forms-list/components/form-filters/component.unit.test.js +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { List } from "immutable"; -import { Button } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../../../../test"; -import FiltersExpansionPanel from "../filters-expansion-panel"; - -import FormFilters from "./component"; - -describe("/components/", () => { - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(FormFilters, { - modules: List([ - { - name: "Module 1", - unique_id: "module-1", - associated_record_types: ["record-type-1"] - }, - { - name: "Module 2", - unique_id: "module-2", - associated_record_types: ["record-type-2"] - } - ]), - handleClearValue: () => {}, - handleSetFilterValue: () => {} - })); - }); - - it("renders clear button", () => { - const clearButton = component.find(Button); - - expect(clearButton).to.have.lengthOf(1); - expect(clearButton.text()).to.equal("clear"); - }); - - it.skip("clear button responds to onClick from pass function", () => {}); - - it("renders ", () => { - expect(component.find(FiltersExpansionPanel)).to.have.lengthOf(2); - }); -}); diff --git a/app/javascript/components/pages/admin/forms-list/components/form-group/component.jsx b/app/javascript/components/pages/admin/forms-list/components/form-group/component.jsx index 567412a109..1f22edab0c 100644 --- a/app/javascript/components/pages/admin/forms-list/components/form-group/component.jsx +++ b/app/javascript/components/pages/admin/forms-list/components/form-group/component.jsx @@ -1,19 +1,19 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Accordion, AccordionSummary, AccordionDetails } from "@material-ui/core"; +import { Accordion, AccordionSummary, AccordionDetails } from "@mui/material"; import { Draggable } from "react-beautiful-dnd"; -import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import css from "../../styles.css"; import DragIndicator from "../drag-indicator"; import { FORM_GROUP_PREFIX } from "../../constants"; -const Component = ({ name, id, index, children, isDragDisabled }) => { +function Component({ name, id, index, children, isDragDisabled = false }) { return ( {provided => ( -
+
{ )} ); -}; +} Component.displayName = "FormGroup"; -Component.defaultProps = { - isDragDisabled: false -}; - Component.propTypes = { children: PropTypes.node, id: PropTypes.string.isRequired, diff --git a/app/javascript/components/pages/admin/forms-list/components/form-group/component.spec.js b/app/javascript/components/pages/admin/forms-list/components/form-group/component.spec.js new file mode 100644 index 0000000000..4de5fa778a --- /dev/null +++ b/app/javascript/components/pages/admin/forms-list/components/form-group/component.spec.js @@ -0,0 +1,38 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +import { mountedComponent, screen } from "test-utils"; +import { DragDropContext, Droppable } from "react-beautiful-dnd"; +import { Typography } from "@mui/material"; + +import FormGroup from "./component"; + +describe("/components/", () => { + function RenderFormGroup() { + return ( + + + {provided => ( +
+ + Some Content + +
+ )} +
+
+ ); + } + + RenderFormGroup.displayName = "RenderFormGroup"; + + beforeEach(() => { + mountedComponent(); + }); + + it("renders panel name", () => { + expect(screen.getByText("Group 1")).toBeInTheDocument(); + }); + + it("renders ", () => { + expect(screen.getByTestId("drag-indicator")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/admin/forms-list/components/form-group/component.unit.test.js b/app/javascript/components/pages/admin/forms-list/components/form-group/component.unit.test.js deleted file mode 100644 index b77340fcd8..0000000000 --- a/app/javascript/components/pages/admin/forms-list/components/form-group/component.unit.test.js +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { DragDropContext, Droppable } from "react-beautiful-dnd"; -import { Accordion, AccordionSummary, Typography } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../../../../test"; -import DragIndicator from "../drag-indicator"; - -import FormGroup from "./component"; - -describe("/components/", () => { - let component; - - const RenderFormGroup = () => ( - - - {provided => ( -
- - Some Content - -
- )} -
-
- ); - - beforeEach(() => { - ({ component } = setupMountedComponent(RenderFormGroup, {})); - }); - - it("renders ", () => { - expect(component.find(Accordion)).to.have.lengthOf(1); - }); - - it("renders ", () => { - expect(component.find(DragIndicator)).to.have.lengthOf(1); - }); - - it("renders children", () => { - expect(component.find(Typography)).to.have.lengthOf(1); - }); - - it("renders panel name", () => { - expect(component.find(AccordionSummary).text()).to.equal("Group 1"); - }); -}); diff --git a/app/javascript/components/pages/admin/forms-list/components/form-section/component.jsx b/app/javascript/components/pages/admin/forms-list/components/form-section/component.jsx index 9087384f98..b8316f7c72 100644 --- a/app/javascript/components/pages/admin/forms-list/components/form-section/component.jsx +++ b/app/javascript/components/pages/admin/forms-list/components/form-section/component.jsx @@ -2,16 +2,16 @@ import PropTypes from "prop-types"; import { Droppable } from "react-beautiful-dnd"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; import { useI18n } from "../../../../../i18n"; import FormSectionList from "../form-section-list"; import css from "../../styles.css"; -const Component = ({ group, collection, isDragDisabled }) => { +function Component({ group, collection, isDragDisabled = false }) { const i18n = useI18n(); - const classes = clsx(css.row, css.header); + const classes = cx(css.row, css.header); return ( @@ -29,14 +29,10 @@ const Component = ({ group, collection, isDragDisabled }) => { )} ); -}; +} Component.displayName = "FormSection"; -Component.defaultProps = { - isDragDisabled: false -}; - Component.propTypes = { collection: PropTypes.string.isRequired, group: PropTypes.object.isRequired, diff --git a/app/javascript/components/pages/admin/forms-list/components/form-section/component.spec.js b/app/javascript/components/pages/admin/forms-list/components/form-section/component.spec.js new file mode 100644 index 0000000000..ead40fdc75 --- /dev/null +++ b/app/javascript/components/pages/admin/forms-list/components/form-section/component.spec.js @@ -0,0 +1,37 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +import { mountedComponent, screen } from "test-utils"; +import { List } from "immutable"; +import { DragDropContext } from "react-beautiful-dnd"; + +import FormSection from "./component"; + +describe("/components/", () => { + beforeEach(() => { + const group = List([ + { + name: "Section", + order: 0, + module_ids: ["module-1"], + parent_form: "form_2", + unique_id: "form_section_1", + editable: false, + id: 1 + } + ]); + + function RenderFormSection() { + return ( + + + + ); + } + + RenderFormSection.displayName = "RenderFormSection"; + mountedComponent(); + }); + + it("renders ", () => { + expect(screen.getByText("form_section.form_name")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/admin/forms-list/components/form-section/component.unit.test.js b/app/javascript/components/pages/admin/forms-list/components/form-section/component.unit.test.js deleted file mode 100644 index 91f0677a41..0000000000 --- a/app/javascript/components/pages/admin/forms-list/components/form-section/component.unit.test.js +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { List } from "immutable"; -import { DragDropContext, Droppable } from "react-beautiful-dnd"; - -import { setupMountedComponent } from "../../../../../../test"; -import TableRow from "../table-row"; - -import FormSection from "./component"; - -describe("/components/", () => { - let component; - - beforeEach(() => { - const group = List([ - { - name: "Section", - order: 0, - module_ids: ["module-1"], - parent_form: "form_2", - unique_id: "form_section_1", - editable: false, - id: 1 - } - ]); - - const RenderFormSection = () => ( - - - - ); - - ({ component } = setupMountedComponent(RenderFormSection, {})); - }); - - it("renders ", () => { - expect(component.find(Droppable)).to.have.lengthOf(1); - }); - - it("renders ", () => { - expect(component.find(TableRow)).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/pages/admin/forms-list/components/reorder-actions/component.jsx b/app/javascript/components/pages/admin/forms-list/components/reorder-actions/component.jsx index 44acc24430..68bff387a7 100644 --- a/app/javascript/components/pages/admin/forms-list/components/reorder-actions/component.jsx +++ b/app/javascript/components/pages/admin/forms-list/components/reorder-actions/component.jsx @@ -3,9 +3,9 @@ import { useEffect } from "react"; import PropTypes from "prop-types"; import { useDispatch } from "react-redux"; -import { Dialog, DialogActions, CircularProgress } from "@material-ui/core"; -import CheckIcon from "@material-ui/icons/Check"; -import CloseIcon from "@material-ui/icons/Close"; +import { Dialog, DialogActions, CircularProgress } from "@mui/material"; +import CheckIcon from "@mui/icons-material/Check"; +import CloseIcon from "@mui/icons-material/Close"; import { ENQUEUE_SNACKBAR, generate } from "../../../../../notifier"; import { useI18n } from "../../../../../i18n"; @@ -17,7 +17,7 @@ import { getReorderIsLoading, getReorderErrors, getReorderPendings } from "../.. import css from "./styles.css"; import { NAME } from "./constants"; -const Component = ({ handleCancel, handleSuccess, open }) => { +function Component({ handleCancel, handleSuccess, open = false }) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -47,14 +47,7 @@ const Component = ({ handleCancel, handleSuccess, open }) => { const icon = !reorderLoading ? : ; return ( - + } @@ -79,14 +72,10 @@ const Component = ({ handleCancel, handleSuccess, open }) => { ); -}; +} Component.displayName = NAME; -Component.defaultProps = { - open: false -}; - Component.propTypes = { handleCancel: PropTypes.func, handleSuccess: PropTypes.func, diff --git a/app/javascript/components/pages/admin/forms-list/components/reorder-actions/component.spec.js b/app/javascript/components/pages/admin/forms-list/components/reorder-actions/component.spec.js new file mode 100644 index 0000000000..28454efc9e --- /dev/null +++ b/app/javascript/components/pages/admin/forms-list/components/reorder-actions/component.spec.js @@ -0,0 +1,51 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { fromJS } from "immutable"; + +import { mountedComponent, screen } from "../../../../../../test-utils"; + +import ReorderActions from "./component"; + +describe("/components/", () => { + const initialState = fromJS({ + records: { + admin: { + forms: { + reorderedForms: { + loading: false, + errors: [], + pending: [] + } + } + } + } + }); + + it("renders ", () => { + mountedComponent( + {}, + handleSuccess: () => {}, + open: true + }} + />, + initialState + ); + expect(screen.getByRole("dialog")).toBeInTheDocument(); + }); + + it("renders the dialog buttons", () => { + mountedComponent( + {}, + handleSuccess: () => {}, + open: true + }} + />, + initialState + ); + expect(screen.getAllByRole("button")).toHaveLength(2); + }); +}); diff --git a/app/javascript/components/pages/admin/forms-list/components/reorder-actions/component.unit.test.js b/app/javascript/components/pages/admin/forms-list/components/reorder-actions/component.unit.test.js deleted file mode 100644 index 00e29a72ca..0000000000 --- a/app/javascript/components/pages/admin/forms-list/components/reorder-actions/component.unit.test.js +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { Button, Dialog } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../../../../test"; - -import ReorderActions from "./component"; - -describe("/components/", () => { - let component; - - beforeEach(() => { - const initialState = fromJS({ - records: { - admin: { - forms: { - reorderedForms: { - loading: false, - errors: [], - pending: [] - } - } - } - } - }); - - ({ component } = setupMountedComponent( - ReorderActions, - { - handleCancel: () => {}, - handleSuccess: () => {}, - open: true - }, - initialState - )); - }); - - it("renders ", () => { - expect(component.find(Dialog)).to.have.lengthOf(1); - }); - - it("renders the dialog buttons", () => { - expect(component.find(Button)).to.have.lengthOf(2); - }); -}); diff --git a/app/javascript/components/pages/admin/forms-list/components/table-row/component.jsx b/app/javascript/components/pages/admin/forms-list/components/table-row/component.jsx index c44643a196..27cb5b2ce5 100644 --- a/app/javascript/components/pages/admin/forms-list/components/table-row/component.jsx +++ b/app/javascript/components/pages/admin/forms-list/components/table-row/component.jsx @@ -4,18 +4,18 @@ import PropTypes from "prop-types"; import { Link } from "react-router-dom"; import { Draggable } from "react-beautiful-dnd"; import findKey from "lodash/findKey"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; import { useI18n } from "../../../../../i18n"; -import { MODULES, RECORD_PATH } from "../../../../../../config/constants"; +import { MODULES, RECORD_PATH } from "../../../../../../config"; import css from "../../styles.css"; import DragIndicator from "../drag-indicator"; import LockedIcon from "../../../../../locked-icon"; -const Component = ({ name, modules, parentForm, uniqueID, id, index, editable, isDragDisabled }) => { +function Component({ name, modules, parentForm, uniqueID, id, index, editable, isDragDisabled = false }) { const i18n = useI18n(); - const nameStyles = clsx({ + const nameStyles = cx({ [css.formName]: true, [css.protected]: !editable }); @@ -41,14 +41,10 @@ const Component = ({ name, modules, parentForm, uniqueID, id, index, editable, i )} ); -}; +} Component.displayName = "TableRow"; -Component.defaultProps = { - isDragDisabled: false -}; - Component.propTypes = { editable: PropTypes.bool.isRequired, id: PropTypes.number.isRequired, diff --git a/app/javascript/components/pages/admin/forms-list/components/table-row/component.spec.js b/app/javascript/components/pages/admin/forms-list/components/table-row/component.spec.js new file mode 100644 index 0000000000..d7ad9f581f --- /dev/null +++ b/app/javascript/components/pages/admin/forms-list/components/table-row/component.spec.js @@ -0,0 +1,50 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +import { mountedComponent, screen } from "test-utils"; +import { DragDropContext, Droppable } from "react-beautiful-dnd"; + +import TableRow from "./component"; + +describe("/components/", () => { + const props = { + name: "Form Section 1", + modules: [ + { + unique_id: "primeromodule-cp", + name: "CP", + associated_record_types: ["case", "tracing_request", "incident"] + } + ], + parentForm: "case", + index: 1, + uniqueID: "form", + editable: true, + id: 1 + }; + + beforeEach(() => { + function RenderTableRow() { + return ( + + + {provided => ( +
+ +
+ )} +
+
+ ); + } + + RenderTableRow.displayName = "RenderTableRow"; + mountedComponent(); + }); + + it("renders ", () => { + expect(screen.getByTestId("drag-indicator")).toBeInTheDocument(); + }); + + it("renders ", () => { + expect(screen.getByText("Form Section 1")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/admin/forms-list/components/table-row/component.unit.test.js b/app/javascript/components/pages/admin/forms-list/components/table-row/component.unit.test.js deleted file mode 100644 index c897eb7e88..0000000000 --- a/app/javascript/components/pages/admin/forms-list/components/table-row/component.unit.test.js +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Link } from "react-router-dom"; -import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; - -import { setupMountedComponent } from "../../../../../../test"; -import DragIndicator from "../drag-indicator"; - -import TableRow from "./component"; - -describe("/components/", () => { - let component; - - const props = { - name: "Form Section 1", - modules: [ - { - unique_id: "primeromodule-cp", - name: "CP", - associated_record_types: ["case", "tracing_request", "incident"] - } - ], - parentForm: "case", - index: 1, - uniqueID: "form", - editable: true, - id: 1 - }; - - beforeEach(() => { - const RenderTableRow = () => ( - - - {provided => ( -
- -
- )} -
-
- ); - - ({ component } = setupMountedComponent(RenderTableRow, {})); - }); - - it("renders Draggable component", () => { - expect(component.find(Draggable)).to.have.lengthOf(1); - }); - - it("renders ", () => { - expect(component.find(DragIndicator)).to.have.lengthOf(1); - }); - - it("renders row information", () => { - expect(component.find(Link).text()).to.equal("Form Section 1"); - }); -}); diff --git a/app/javascript/components/pages/admin/locations-list/container.jsx b/app/javascript/components/pages/admin/locations-list/container.jsx index 0cf17b21fc..b3d31268ca 100644 --- a/app/javascript/components/pages/admin/locations-list/container.jsx +++ b/app/javascript/components/pages/admin/locations-list/container.jsx @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { useDispatch } from "react-redux"; import { fromJS } from "immutable"; -import { Grid } from "@material-ui/core"; +import Grid from "@mui/material/Unstable_Grid2"; import isEmpty from "lodash/isEmpty"; import { useI18n } from "../../../i18n"; @@ -30,7 +30,7 @@ import { fetchLocations, setLocationsFilter } from "./action-creators"; import { ACTION_NAME, DISABLED, NAME, COLUMNS, LOCATION_TYPE_LOOKUP, LOCATIONS_DIALOG } from "./constants"; import { getColumns, getFilters } from "./utils"; -const Container = () => { +function Container() { const i18n = useI18n(); const dispatch = useDispatch(); const [selectedRecords, setSelectedRecords] = useState({}); @@ -128,7 +128,7 @@ const Container = () => { - + { {renderAlertNoLocations} - - + + ); -}; +} Container.displayName = NAME; diff --git a/app/javascript/components/pages/admin/locations-list/container.spec.js b/app/javascript/components/pages/admin/locations-list/container.spec.js new file mode 100644 index 0000000000..ddd206b276 --- /dev/null +++ b/app/javascript/components/pages/admin/locations-list/container.spec.js @@ -0,0 +1,122 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, stub, screen, listHeaders } from "../../../../test-utils"; +import { ListHeaderRecord } from "../../../user/records"; +import { ACTIONS } from "../../../permissions"; + +import NAMESPACE from "./namespace"; +import LocationsList from "./container"; + +describe("", () => { + const dataLength = 30; + const data = Array.from({ length: dataLength }, (_, i) => ({ + id: i + 1, + name: { en: `Location ${i + 1}` } + })); + + stub(window.I18n, "t") + .withArgs("messages.record_list.of") + .returns("of") + .withArgs("location.no_location") + .returns("No Location"); + + const initialState = fromJS({ + records: { + admin: { + locations: { + data, + metadata: { total: dataLength, per: 20, page: 1 }, + loading: false, + errors: false + } + } + }, + forms: { + options: { + lookups: { + data: [ + { + unique_id: "lookup-1", + name: { en: "Lookup 1" }, + values: [ + { id: "a", display_text: [{ en: "Lookup 1 a" }] }, + { id: "b", display_text: [{ en: "Lookup 1 b" }] } + ] + }, + { + unique_id: "lookup-2", + name: { en: "Lookup 2" }, + values: [ + { id: "a", display_text: [{ en: "Lookup 2 a" }] }, + { id: "b", display_text: [{ en: "Lookup 2 b" }] } + ] + } + ], + metadata: { + total: 2, + per: 1, + page: 1 + } + }, + locations: [{ name: "Country 1" }] + } + }, + user: { + permissions: { + metadata: [ACTIONS.MANAGE] + }, + listHeaders: { + locations: [ + ListHeaderRecord({ + name: "name", + field_name: "name", + id_search: false + }) + ] + } + } + }); + + it("renders record list table", () => { + mountedComponent(, initialState, ["/admin/locations"]); + expect(screen.getByRole("grid")).toBeInTheDocument(); + }); + + it("renders component", () => { + mountedComponent(, initialState, ["/admin/locations"]); + expect(screen.getByTestId("form-filter")).toBeInTheDocument(); + }); + + it("renders component", () => { + mountedComponent(, initialState, ["/admin/locations"]); + expect(screen.getByRole("grid")).toBeInTheDocument(); + }); + + describe("when no location loaded", () => { + const stateWithoutLocations = fromJS({ + records: { + admin: { + locations: { + data: [], + metadata: { total: 0, per: 20, page: 1 }, + loading: false, + errors: false + } + } + }, + user: { + permissions: { + metadata: [ACTIONS.MANAGE] + }, + listHeaders: { + locations: listHeaders(NAMESPACE) + } + } + }); + + it("renders InternalAlert alert", () => { + mountedComponent(, stateWithoutLocations, ["/admin/locations"]); + expect(screen.getByText(/No Location/i)).toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/pages/admin/locations-list/container.unit.test.js b/app/javascript/components/pages/admin/locations-list/container.unit.test.js deleted file mode 100644 index 4ce70f1f9c..0000000000 --- a/app/javascript/components/pages/admin/locations-list/container.unit.test.js +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { Button, TableCell, TableHead } from "@material-ui/core"; - -import { setupMountedComponent, listHeaders, lookups, stub } from "../../../../test"; -import { ListHeaderRecord } from "../../../user/records"; -import IndexTable from "../../../index-table"; -import { ACTIONS } from "../../../permissions"; -import { FiltersForm } from "../../../form-filters/components"; -import InternalAlert from "../../../internal-alert"; - -import NAMESPACE from "./namespace"; -import actions from "./actions"; -import ImportDialog from "./import-dialog"; -import LocationsList from "./container"; - -describe("", () => { - let stubI18n = null; - let component; - const dataLength = 30; - const data = Array.from({ length: dataLength }, (_, i) => ({ - id: i + 1, - name: { en: `Location ${i + 1}` } - })); - - beforeEach(() => { - stubI18n = stub(window.I18n, "t") - .withArgs("messages.record_list.of") - .returns("of") - .withArgs("location.no_location") - .returns("No Location"); - const initialState = fromJS({ - records: { - admin: { - locations: { - data, - metadata: { total: dataLength, per: 20, page: 1 }, - loading: false, - errors: false - } - } - }, - forms: { - options: { - lookups: lookups(), - locations: [{ name: "Country 1" }] - } - }, - user: { - permissions: { - metadata: [ACTIONS.MANAGE] - }, - listHeaders: { - locations: [ - ListHeaderRecord({ - name: "name", - field_name: "name", - id_search: false - }) - ] - } - } - }); - - ({ component } = setupMountedComponent(LocationsList, {}, initialState, ["/admin/locations"])); - }); - - it("renders record list table", () => { - expect(component.find(IndexTable)).to.have.lengthOf(1); - }); - - it("renders component", () => { - expect(component.find(FiltersForm)).to.have.lengthOf(1); - }); - - it("renders component", () => { - expect(component.find(ImportDialog)).to.have.lengthOf(1); - }); - - it("should trigger a sort action when a header is clicked", () => { - const indexTable = component.find(IndexTable); - - const expectedAction = { - payload: { - recordType: "locations", - data: fromJS({ - disabled: ["false"], - total: 30, - per: 20, - page: 1, - locale: "en", - order: "asc", - order_by: "name" - }) - }, - type: "locations/SET_LOCATIONS_FILTER" - }; - - indexTable.find(TableHead).find(TableCell).at(1).find("span.MuiButtonBase-root").simulate("click"); - - expect(component.props().store.getActions()[2].type).to.deep.equals(expectedAction.type); - expect(component.props().store.getActions()[2].payload.data).to.deep.equals(expectedAction.payload.data); - }); - - it("should trigger a valid action with next page when clicking next page", () => { - const indexTable = component.find(IndexTable); - const expectAction = { - api: { - params: fromJS({ total: dataLength, per: 20, page: 2, disabled: ["false"], locale: "en", hierarchy: true }), - path: NAMESPACE - }, - type: actions.LOCATIONS - }; - - expect(indexTable.find("p").at(1).text()).to.be.equals(`1-20 of ${dataLength}`); - expect(component.props().store.getActions()).to.have.lengthOf(2); - - indexTable.find("#pagination-next").at(0).simulate("click"); - - expect(indexTable.find("p").at(1).text()).to.be.equals(`21-${dataLength} of ${dataLength}`); - expect(component.props().store.getActions()[3].api.params.toJS()).to.deep.equals(expectAction.api.params.toJS()); - expect(component.props().store.getActions()[3].type).to.deep.equals(expectAction.type); - expect(component.props().store.getActions()[3].api.path).to.deep.equals(expectAction.api.path); - }); - - it("should set the filters when apply is clicked", () => { - component.find(Button).at(1).simulate("click"); - - const expectedAction = { - payload: { - data: fromJS({ - disabled: ["false"], - page: 1 - }) - }, - type: "locations/SET_LOCATIONS_FILTER" - }; - - expect(component.props().store.getActions()[1].data).to.deep.equals(expectedAction.data); - expect(component.props().store.getActions()[1].type).to.deep.equals(expectedAction.type); - }); - - afterEach(() => { - if (stubI18n) { - window.I18n.t.restore(); - } - }); - - describe("when no location loaded", () => { - beforeEach(() => { - const initialState = fromJS({ - records: { - admin: { - locations: { - data: [], - metadata: { total: 0, per: 20, page: 1 }, - loading: false, - errors: false - } - } - }, - user: { - permissions: { - metadata: [ACTIONS.MANAGE] - }, - listHeaders: { - locations: listHeaders(NAMESPACE) - } - } - }); - - ({ component } = setupMountedComponent(LocationsList, {}, initialState, ["/admin/locations"])); - }); - - it("renders InternalAlert alert", () => { - expect(component.find(InternalAlert).text()).to.equal("No Location"); - expect(component.find(InternalAlert)).to.have.lengthOf(1); - }); - }); -}); diff --git a/app/javascript/components/pages/admin/locations-list/disable-dialog/component.jsx b/app/javascript/components/pages/admin/locations-list/disable-dialog/component.jsx index 77366a153d..44224b191a 100644 --- a/app/javascript/components/pages/admin/locations-list/disable-dialog/component.jsx +++ b/app/javascript/components/pages/admin/locations-list/disable-dialog/component.jsx @@ -16,7 +16,7 @@ import { ACTION_NAME } from "../constants"; import { NAME } from "./constants"; -const Component = ({ filters, selectedRecords, setSelectedRecords, recordType }) => { +function Component({ filters, selectedRecords, setSelectedRecords, recordType }) { const dispatch = useDispatch(); const data = useMemoizedSelector(state => getRecords(state, recordType)); @@ -67,7 +67,7 @@ const Component = ({ filters, selectedRecords, setSelectedRecords, recordType })

{i18n.t(`location.${action}_text`)}

); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/admin/locations-list/import-dialog/action-creators.unit.test.js b/app/javascript/components/pages/admin/locations-list/import-dialog/action-creators.unit.test.js index af0613882b..f7b92a34f5 100644 --- a/app/javascript/components/pages/admin/locations-list/import-dialog/action-creators.unit.test.js +++ b/app/javascript/components/pages/admin/locations-list/import-dialog/action-creators.unit.test.js @@ -2,7 +2,7 @@ import { fromJS } from "immutable"; -import { stub } from "../../../../../test"; +import { stub } from "../../../../../test-utils"; import { RECORD_PATH, METHODS } from "../../../../../config"; import { ENQUEUE_SNACKBAR, generate } from "../../../../notifier"; import { CLEAR_DIALOG } from "../../../../action-dialog"; diff --git a/app/javascript/components/pages/admin/locations-list/import-dialog/component.jsx b/app/javascript/components/pages/admin/locations-list/import-dialog/component.jsx index 55a96d2769..4eb064c118 100644 --- a/app/javascript/components/pages/admin/locations-list/import-dialog/component.jsx +++ b/app/javascript/components/pages/admin/locations-list/import-dialog/component.jsx @@ -15,7 +15,7 @@ import { getImportErrors } from "./selectors"; import { form } from "./form"; import { NAME, FORM_ID } from "./constants"; -const Component = ({ close, i18n, open, pending }) => { +function Component({ close, i18n, open, pending }) { const dispatch = useDispatch(); const dialogPending = typeof pending === "object" ? pending.get("pending") : pending; @@ -60,7 +60,7 @@ const Component = ({ close, i18n, open, pending }) => {
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/admin/locations-list/import-dialog/component.spec.js b/app/javascript/components/pages/admin/locations-list/import-dialog/component.spec.js new file mode 100644 index 0000000000..5833e182e4 --- /dev/null +++ b/app/javascript/components/pages/admin/locations-list/import-dialog/component.spec.js @@ -0,0 +1,24 @@ +import { mountedComponent, screen } from "test-utils"; + +import ImportDialog from "./component"; + +describe("", () => { + const props = { + close: () => {}, + i18n: { t: value => value }, + open: true, + pending: false + }; + + beforeEach(() => { + mountedComponent(); + }); + + it("should render ", () => { + expect(screen.getByRole("dialog")).toBeInTheDocument(); + }); + + it("should render component", () => { + expect(document.querySelector("#import-locations-form")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/admin/locations-list/import-dialog/component.unit.test.js b/app/javascript/components/pages/admin/locations-list/import-dialog/component.unit.test.js deleted file mode 100644 index e9b57e73ac..0000000000 --- a/app/javascript/components/pages/admin/locations-list/import-dialog/component.unit.test.js +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../../test"; -import ActionDialog from "../../../../action-dialog"; -import Form from "../../../../form"; - -import ImportDialog from "./component"; - -describe("", () => { - let component; - const props = { - close: () => {}, - i18n: { t: value => value }, - open: true, - pending: false - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(ImportDialog, props, {})); - }); - - it("should render ", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(1); - }); - - it("should render component", () => { - expect(component.find(Form)).to.have.lengthOf(1); - }); - - it("should accept valid props", () => { - const importDialogProps = { ...component.find(ImportDialog).props() }; - - ["close", "i18n", "open", "pending"].forEach(property => { - expect(importDialogProps).to.have.property(property); - delete importDialogProps[property]; - }); - expect(importDialogProps).to.be.empty; - }); -}); diff --git a/app/javascript/components/pages/admin/lookups-form/action-creators.unit.test.js b/app/javascript/components/pages/admin/lookups-form/action-creators.unit.test.js index 6b913eb488..a38b6872db 100644 --- a/app/javascript/components/pages/admin/lookups-form/action-creators.unit.test.js +++ b/app/javascript/components/pages/admin/lookups-form/action-creators.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub } from "../../../../test"; +import { stub } from "../../../../test-utils"; import { RECORD_PATH, SAVE_METHODS, METHODS } from "../../../../config"; import { ENQUEUE_SNACKBAR, generate } from "../../../notifier"; diff --git a/app/javascript/components/pages/admin/lookups-form/components/draggable-row/component.jsx b/app/javascript/components/pages/admin/lookups-form/components/draggable-row/component.jsx index f44a9a8c31..2cbdc71d83 100644 --- a/app/javascript/components/pages/admin/lookups-form/components/draggable-row/component.jsx +++ b/app/javascript/components/pages/admin/lookups-form/components/draggable-row/component.jsx @@ -12,7 +12,7 @@ import { LOCALE_KEYS } from "../../../../../../config"; import { NAME } from "./constants"; -const Component = ({ +function Component({ firstLocaleOption, index, isDragDisabled, @@ -22,7 +22,7 @@ const Component = ({ uniqueId, formMode, formMethods -}) => { +}) { const renderTranslationValues = () => { return localesKeys.map(localeKey => { const name = `values.${localeKey}.${uniqueId}`; @@ -53,7 +53,13 @@ const Component = ({ ); return ( - + {provider => { return (
@@ -67,7 +73,7 @@ const Component = ({ }} ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/admin/lookups-form/components/draggable-row/component.unit.test.js b/app/javascript/components/pages/admin/lookups-form/components/draggable-row/component.spec.js similarity index 53% rename from app/javascript/components/pages/admin/lookups-form/components/draggable-row/component.unit.test.js rename to app/javascript/components/pages/admin/lookups-form/components/draggable-row/component.spec.js index cb0d18a34b..9dffe71b92 100644 --- a/app/javascript/components/pages/admin/lookups-form/components/draggable-row/component.unit.test.js +++ b/app/javascript/components/pages/admin/lookups-form/components/draggable-row/component.spec.js @@ -1,15 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Draggable } from "react-beautiful-dnd"; - -import FormSectionField from "../../../../../form/components/form-section-field"; -import { setupMountedComponent } from "../../../../../../test"; -import SwitchInput from "../../../../../form/fields/switch-input"; +import { mountedComponent, screen } from "../../../../../../test-utils"; import DraggableRow from "./component"; describe(" - components/draggable-row/component", () => { - let component; const props = { firstLocaleOption: false, index: 0, @@ -20,20 +14,19 @@ describe(" - components/draggable-row/component", () => { uniqueId: "test" }; - beforeEach(() => { - ({ component } = setupMountedComponent(DraggableRow, props)); - }); - // TODO: Fill out once figure out Droppable context issue concerning testing it.skip("renders Draggable component", () => { - expect(component.find(Draggable)).to.have.lengthOf(1); + mountedComponent(); + expect(screen.getByTestId("draggable")).toBeInTheDocument(); }); it.skip("renders FormSectionField component", () => { - expect(component.find(FormSectionField)).to.have.lengthOf(1); + mountedComponent(); + expect(screen.getByTestId("form-section-field")).toBeInTheDocument(); }); it.skip("renders FormSectionField component", () => { - expect(component.find(SwitchInput)).to.have.lengthOf(1); + mountedComponent(); + expect(screen.getByRole("checkbox")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/pages/admin/lookups-form/components/form/component.jsx b/app/javascript/components/pages/admin/lookups-form/components/form/component.jsx index f2baff08b3..ec0643d992 100644 --- a/app/javascript/components/pages/admin/lookups-form/components/form/component.jsx +++ b/app/javascript/components/pages/admin/lookups-form/components/form/component.jsx @@ -33,7 +33,7 @@ import { LOCALE_KEYS, SAVE_METHODS } from "../../../../../../config"; import { NAME, FORM_ID } from "./constants"; -const Component = ({ formMode, isLockedLookup, lookup }) => { +function Component({ formMode, isLockedLookup, lookup }) { const { id } = useParams(); const i18n = useI18n(); const dispatch = useDispatch(); @@ -103,7 +103,7 @@ const Component = ({ formMode, isLockedLookup, lookup }) => { }, [defaultValues.name[defaultLocale]]); return ( - + { /> ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/admin/lookups-form/components/form/component.spec.js b/app/javascript/components/pages/admin/lookups-form/components/form/component.spec.js new file mode 100644 index 0000000000..176ed0d723 --- /dev/null +++ b/app/javascript/components/pages/admin/lookups-form/components/form/component.spec.js @@ -0,0 +1,42 @@ +import { fromJS } from "immutable"; +import { mountedComponent, screen } from "test-utils"; + +import { lookups } from "../../../../../../test-utils"; +import { LOCALE_KEYS } from "../../../../../../config"; + +import Form from "./component"; + +describe("
- components/form/component", () => { + const props = { + formRef: { current: { submitForm: () => {} } }, + formMode: fromJS({ isShow: true }), + lookup: fromJS(lookups().data[0]) + }; + const initialState = fromJS({ + application: { + primero: { + locales: [LOCALE_KEYS.en, "ar"] + } + } + }); + + beforeEach(() => { + mountedComponent(, initialState); + }); + + it("renders FormSectionField component", () => { + expect(screen.queryAllByTestId("form-section-field")).toHaveLength(4); + }); + + it("first value of the FormSectionField should be english", () => { + expect(screen.queryAllByText(/lookup.language_label/)).toHaveLength(2); + }); + + it("renders DragDropContext component", () => { + expect(screen.getByText(/Press space bar to start a drag/i)).toBeInTheDocument(); + }); + + it("renders SwitchInput component", () => { + expect(screen.getAllByTestId("switch-input")).toHaveLength(3); + }); +}); diff --git a/app/javascript/components/pages/admin/lookups-form/components/form/component.unit.test.js b/app/javascript/components/pages/admin/lookups-form/components/form/component.unit.test.js deleted file mode 100644 index 21a8c51c11..0000000000 --- a/app/javascript/components/pages/admin/lookups-form/components/form/component.unit.test.js +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { DragDropContext, Droppable } from "react-beautiful-dnd"; - -import FormSectionField from "../../../../../form/components/form-section-field"; -import { setupMountedComponent, lookups } from "../../../../../../test"; -import SwitchInput from "../../../../../form/fields/switch-input"; -import { LOCALE_KEYS } from "../../../../../../config"; - -import Form from "./component"; - -describe(" - components/form/component", () => { - let component; - const props = { - formRef: { current: { submitForm: () => {} } }, - formMode: fromJS({ isShow: true }), - lookup: fromJS(lookups().data[0]) - }; - const initialState = fromJS({ - application: { - primero: { - locales: [LOCALE_KEYS.en, "ar"] - } - } - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(Form, props, initialState)); - }); - - it("renders FormSectionField component", () => { - expect(component.find(FormSectionField)).to.have.lengthOf(5); - }); - - it("first value of the FormSectionField should be english", () => { - const valuesFirstFormSectionFields = component.find(FormSectionField).first().props().field.option_strings_text[0]; - - expect(valuesFirstFormSectionFields.id).to.equal(LOCALE_KEYS.en); - }); - - it("renders DragDropContext component", () => { - expect(component.find(DragDropContext)).to.have.lengthOf(1); - }); - - it("renders Droppable component", () => { - expect(component.find(Droppable)).to.have.lengthOf(1); - }); - - it("renders SwitchInput component", () => { - expect(component.find(SwitchInput)).to.have.lengthOf(2); - }); -}); diff --git a/app/javascript/components/pages/admin/lookups-form/components/header-values/component.jsx b/app/javascript/components/pages/admin/lookups-form/components/header-values/component.jsx index 9559696d15..11b1890cf2 100644 --- a/app/javascript/components/pages/admin/lookups-form/components/header-values/component.jsx +++ b/app/javascript/components/pages/admin/lookups-form/components/header-values/component.jsx @@ -1,18 +1,18 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; import css from "../styles.css"; import { useI18n } from "../../../../../i18n"; import { NAME } from "./constants"; -const Component = ({ hideTranslationColumn }) => { +function Component({ hideTranslationColumn }) { const i18n = useI18n(); const hide = hideTranslationColumn ? css.hideTranslationsFields : null; - const classes = clsx(css.row, css.header); + const classes = cx(css.row, css.header); return (
@@ -22,7 +22,7 @@ const Component = ({ hideTranslationColumn }) => {
{i18n.t("lookup.enabled_label")}
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/admin/lookups-form/components/header-values/component.spec.js b/app/javascript/components/pages/admin/lookups-form/components/header-values/component.spec.js new file mode 100644 index 0000000000..126914544e --- /dev/null +++ b/app/javascript/components/pages/admin/lookups-form/components/header-values/component.spec.js @@ -0,0 +1,21 @@ +import { mountedComponent, screen } from "test-utils"; + +import HeadersValues from "./component"; + +describe(" - components/header-values/component", () => { + beforeEach(() => { + mountedComponent(); + }); + + it("should render english text column", () => { + expect(screen.getByText("lookup.english_label")).toBeInTheDocument(); + }); + + it("should render translation column", () => { + expect(screen.getByText("lookup.translation_label")).toBeInTheDocument(); + }); + + it("should render tick/enable column", () => { + expect(screen.getByText("lookup.enabled_label")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/admin/lookups-form/components/header-values/component.unit.test.js b/app/javascript/components/pages/admin/lookups-form/components/header-values/component.unit.test.js deleted file mode 100644 index 68f54c224f..0000000000 --- a/app/javascript/components/pages/admin/lookups-form/components/header-values/component.unit.test.js +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../../../test"; - -import HeadersValues from "./component"; - -describe(" - components/header-values/component", () => { - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(HeadersValues, {})); - }); - - it("should render 5 div", () => { - expect(component.find("div")).to.have.lengthOf(5); - }); - - it("should render english text column", () => { - expect(component.find("div").at(2).text()).to.be.equal("lookup.english_label"); - }); - - it("should render english text column", () => { - expect(component.find("div").at(3).text()).to.be.equal("lookup.translation_label"); - }); - - it("should render english text column", () => { - expect(component.find("div").at(4).text()).to.be.equal("lookup.enabled_label"); - }); -}); diff --git a/app/javascript/components/pages/admin/lookups-form/components/lookup-options/component.jsx b/app/javascript/components/pages/admin/lookups-form/components/lookup-options/component.jsx index 09c706fdd4..debebba8d0 100644 --- a/app/javascript/components/pages/admin/lookups-form/components/lookup-options/component.jsx +++ b/app/javascript/components/pages/admin/lookups-form/components/lookup-options/component.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Grid } from "@material-ui/core"; -import AddIcon from "@material-ui/icons/Add"; +import { Grid } from "@mui/material"; +import AddIcon from "@mui/icons-material/Add"; import { DragDropContext, Droppable } from "react-beautiful-dnd"; import { useI18n } from "../../../../../i18n"; diff --git a/app/javascript/components/pages/admin/lookups-form/container.jsx b/app/javascript/components/pages/admin/lookups-form/container.jsx index 9d16cc89f6..8081b78799 100644 --- a/app/javascript/components/pages/admin/lookups-form/container.jsx +++ b/app/javascript/components/pages/admin/lookups-form/container.jsx @@ -6,9 +6,9 @@ import { push } from "connected-react-router"; import { useLocation, useParams } from "react-router-dom"; import { fromJS } from "immutable"; import PropTypes from "prop-types"; -import CreateIcon from "@material-ui/icons/Create"; -import CheckIcon from "@material-ui/icons/Check"; -import ClearIcon from "@material-ui/icons/Clear"; +import CreateIcon from "@mui/icons-material/Create"; +import CheckIcon from "@mui/icons-material/Check"; +import ClearIcon from "@mui/icons-material/Clear"; import { PageHeading, PageContent } from "../../../page"; import { useI18n } from "../../../i18n"; @@ -28,7 +28,7 @@ import { clearSelectedLookup, fetchLookup } from "./action-creators"; import { LookupForm } from "./components"; import { FORM_ID } from "./components/form/constants"; -const Container = ({ mode }) => { +function Container({ mode }) { const i18n = useI18n(); const { limitedProductionSite } = useApp(); const dispatch = useDispatch(); @@ -118,7 +118,7 @@ const Container = ({ mode }) => { ); -}; +} Container.displayName = NAME; diff --git a/app/javascript/components/pages/admin/lookups-form/container.unit.test.js b/app/javascript/components/pages/admin/lookups-form/container.spec.js similarity index 64% rename from app/javascript/components/pages/admin/lookups-form/container.unit.test.js rename to app/javascript/components/pages/admin/lookups-form/container.spec.js index fe7e85306f..b8efc14cf2 100644 --- a/app/javascript/components/pages/admin/lookups-form/container.unit.test.js +++ b/app/javascript/components/pages/admin/lookups-form/container.spec.js @@ -1,17 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../../../test"; import { ACTIONS } from "../../../permissions"; -import { FormAction } from "../../../form"; -import { LookupForm } from "./components"; import LookupsForm from "./container"; describe(" - container", () => { - let component; - beforeEach(() => { const initialState = fromJS({ records: { @@ -31,14 +27,15 @@ describe(" - container", () => { } }); - ({ component } = setupMountedComponent(LookupsForm, { mode: "edit" }, initialState, ["/admin/lookups/1"])); + mountedComponent(, initialState, ["/admin/lookups/1"]); }); it("renders LookupForm component", () => { - expect(component.find(LookupForm)).to.have.lengthOf(1); + expect(document.querySelector("#lookups-form")).toBeInTheDocument(); }); it("renders heading with two FormAction components", () => { - expect(component.find(FormAction)).to.have.lengthOf(2); + expect(screen.getByText("buttons.cancel")).toBeInTheDocument(); + expect(screen.getByText("buttons.save")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/pages/admin/lookups-form/utils.unit.test.js b/app/javascript/components/pages/admin/lookups-form/utils.unit.test.js index 5afe490877..d5ac696d82 100644 --- a/app/javascript/components/pages/admin/lookups-form/utils.unit.test.js +++ b/app/javascript/components/pages/admin/lookups-form/utils.unit.test.js @@ -3,7 +3,7 @@ import { fromJS } from "immutable"; import uuid from "../../../../libs/uuid"; -import { stub } from "../../../../test"; +import { stub } from "../../../../test-utils"; import * as utils from "./utils"; diff --git a/app/javascript/components/pages/admin/lookups-list/component.jsx b/app/javascript/components/pages/admin/lookups-list/component.jsx index a59c2a6003..4390148b94 100644 --- a/app/javascript/components/pages/admin/lookups-list/component.jsx +++ b/app/javascript/components/pages/admin/lookups-list/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { useEffect } from "react"; -import AddIcon from "@material-ui/icons/Add"; +import AddIcon from "@mui/icons-material/Add"; import { Link } from "react-router-dom"; import { useDispatch } from "react-redux"; @@ -23,7 +23,7 @@ import { fetchAdminLookups, setLookupsFilter } from "./action-creators"; import css from "./styles.css"; import { columns } from "./utils"; -const Component = () => { +function Component() { const i18n = useI18n(); const dispatch = useDispatch(); @@ -76,7 +76,7 @@ const Component = () => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/admin/lookups-list/component.spec.js b/app/javascript/components/pages/admin/lookups-list/component.spec.js new file mode 100644 index 0000000000..c63854a82d --- /dev/null +++ b/app/javascript/components/pages/admin/lookups-list/component.spec.js @@ -0,0 +1,114 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { fromJS } from "immutable"; + +import { lookups, fireEvent, mockFetchSuccess, mountedComponent, screen, waitFor } from "../../../../test-utils"; +import { ACTIONS } from "../../../permissions"; + +import LookupList from "./component"; + +describe("", () => { + let spy = null; + let storeInstance; + + const dataLength = 30; + const data = Array.from({ length: dataLength }, (_, i) => ({ + id: i + 1, + unique_id: `lookup-${i + 1}`, + name: { en: `User Group ${i + 1}` }, + values: [ + { + id: `value-${i + 1}`, + display_text: { + en: `Value ${i + 1}` + } + } + ] + })); + const state = fromJS({ + records: { + admin: { + lookups: { + data, + metadata: { total: dataLength, per: 20, page: 1 }, + loading: false, + errors: false + } + } + }, + user: { + permissions: { + metadata: [ACTIONS.MANAGE] + } + }, + forms: { + options: { + lookups: lookups() + } + } + }); + + beforeEach(() => { + spy = jest.spyOn(window.I18n, "t").mockImplementation(() => "of"); + + mockFetchSuccess({ json: { data, metadata: { total: 30, per: 20, page: 1 } } }); + const { store } = mountedComponent(, state, {}, ["/admin/lookups"], {}, "", true); + + storeInstance = store; + }); + + afterEach(() => { + spy.mockClear(); + }); + + it("renders a MUIDataTable component", () => { + expect(screen.getByRole("grid")).toBeInTheDocument(); + }); + + it("should trigger a sort action when a header is clicked", () => { + const expectedAction = { + payload: { + recordType: "lookups", + data: fromJS({ + total: 30, + per: 20, + page: 1, + locale: "en", + order: "asc", + order_by: "name" + }) + }, + type: "admin/lookups/SET_LOOKUPS_FILTER" + }; + + mockFetchSuccess({ json: { data, metadata: { total: 30, per: 20, page: 1 } } }); + fireEvent.click(screen.getByTestId("headcol-1")); + const testAction = storeInstance + .getActions() + .filter(action => action.type === "admin/lookups/SET_LOOKUPS_FILTER")[1]; + + expect(testAction.type).toStrictEqual(expectedAction.type); + expect(testAction.payload.data).toStrictEqual(expectedAction.payload.data); + }); + + it("should trigger a valid action with next page when clicking next page", async () => { + const expectAction = { + api: { + params: fromJS({ total: dataLength, per: 20, page: 2, locale: "en" }), + path: "lookups" + }, + type: "admin/lookups/FETCH_LOOKUPS" + }; + + expect(screen.getByText(`1-20 of ${dataLength}`)).toBeInTheDocument(); + expect(storeInstance.getActions()).toHaveLength(5); + + mockFetchSuccess({ json: { data, metadata: { total: 30, per: 20, page: 2 } } }); + fireEvent.click(screen.getByTestId("pagination-next")); + + await waitFor(() => expect(screen.getByText(`21-${dataLength} of ${dataLength}`)).toBeInTheDocument()); + expect(storeInstance.getActions()[6].api.params.toJS()).toStrictEqual(expectAction.api.params.toJS()); + expect(storeInstance.getActions()[6].type).toStrictEqual(expectAction.type); + expect(storeInstance.getActions()[6].api.path).toStrictEqual(expectAction.api.path); + }); +}); diff --git a/app/javascript/components/pages/admin/lookups-list/component.unit.test.js b/app/javascript/components/pages/admin/lookups-list/component.unit.test.js deleted file mode 100644 index 5f9ebc85e3..0000000000 --- a/app/javascript/components/pages/admin/lookups-list/component.unit.test.js +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import MUIDataTable from "mui-datatables"; -import { TableCell, TableHead } from "@material-ui/core"; - -import { setupMountedComponent, lookups, stub } from "../../../../test"; -import { PageHeading } from "../../../page"; -import { ACTIONS } from "../../../permissions"; -import IndexTable from "../../../index-table"; - -import LookupList from "./component"; - -describe("", () => { - let stubI18n = null; - let component; - - const dataLength = 30; - const data = Array.from({ length: dataLength }, (_, i) => ({ - id: i + 1, - unique_id: `lookup-${i + 1}`, - name: { en: `User Group ${i + 1}` }, - values: [ - { - id: `value-${i + 1}`, - display_text: { - en: `Value ${i + 1}` - } - } - ] - })); - const state = fromJS({ - records: { - admin: { - lookups: { - data, - metadata: { total: dataLength, per: 20, page: 1 }, - loading: false, - errors: false - } - } - }, - user: { - permissions: { - metadata: [ACTIONS.MANAGE] - } - }, - forms: { - options: { - lookups: lookups() - } - } - }); - - beforeEach(() => { - stubI18n = stub(window.I18n, "t").withArgs("messages.record_list.of").returns("of"); - ({ component } = setupMountedComponent(LookupList, {}, state, ["/admin/lookups"])); - }); - - it("renders a PageHeading component", () => { - expect(component.find(PageHeading)).to.have.lengthOf(1); - }); - - it("renders a MUIDataTable component", () => { - expect(component.find(MUIDataTable)).to.have.lengthOf(1); - }); - - it("should trigger a sort action when a header is clicked", () => { - const indexTable = component.find(IndexTable); - - const expectedAction = { - payload: { - recordType: "lookups", - data: fromJS({ - total: 30, - per: 20, - page: 1, - locale: "en", - order: "asc", - order_by: "name" - }) - }, - type: "admin/lookups/SET_LOOKUPS_FILTER" - }; - - indexTable.find(TableHead).find(TableCell).at(0).find("span.MuiButtonBase-root").simulate("click"); - - expect(component.props().store.getActions()[2].type).to.deep.equals(expectedAction.type); - expect(component.props().store.getActions()[2].payload.data).to.deep.equals(expectedAction.payload.data); - }); - - it("should trigger a valid action with next page when clicking next page", () => { - const indexTable = component.find(IndexTable); - const expectAction = { - api: { - params: fromJS({ total: dataLength, per: 20, page: 2, locale: "en" }), - path: "lookups" - }, - type: "admin/lookups/FETCH_LOOKUPS" - }; - - expect(indexTable.find("p").at(1).text()).to.be.equals(`1-20 of ${dataLength}`); - expect(component.props().store.getActions()).to.have.lengthOf(2); - indexTable.find("#pagination-next").at(0).simulate("click"); - - expect(indexTable.find("p").at(1).text()).to.be.equals(`21-${dataLength} of ${dataLength}`); - expect(component.props().store.getActions()[3].api.params.toJS()).to.deep.equals(expectAction.api.params.toJS()); - expect(component.props().store.getActions()[3].type).to.deep.equals(expectAction.type); - expect(component.props().store.getActions()[3].api.path).to.deep.equals(expectAction.api.path); - }); - - afterEach(() => { - if (stubI18n) { - window.I18n.t.restore(); - } - }); -}); diff --git a/app/javascript/components/pages/admin/roles-form/action-creators.unit.test.js b/app/javascript/components/pages/admin/roles-form/action-creators.unit.test.js index 11238d09c1..6a720dc4f9 100644 --- a/app/javascript/components/pages/admin/roles-form/action-creators.unit.test.js +++ b/app/javascript/components/pages/admin/roles-form/action-creators.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub } from "../../../../test"; +import { stub } from "../../../../test-utils"; import { RECORD_PATH } from "../../../../config"; import { ENQUEUE_SNACKBAR, generate } from "../../../notifier"; diff --git a/app/javascript/components/pages/admin/roles-form/container.jsx b/app/javascript/components/pages/admin/roles-form/container.jsx index 744334804b..2a0103d00e 100644 --- a/app/javascript/components/pages/admin/roles-form/container.jsx +++ b/app/javascript/components/pages/admin/roles-form/container.jsx @@ -26,7 +26,7 @@ import { getRole, getCopiedRole } from "./selectors"; import { NAME, FORM_ID } from "./constants"; import RolesActions from "./roles-actions"; -const Container = ({ mode }) => { +function Container({ mode }) { const formMode = whichFormMode(mode); const isEditOrShow = formMode.get("isEdit") || formMode.get("isShow"); @@ -134,7 +134,7 @@ const Container = ({ mode }) => { ); -}; +} Container.displayName = NAME; diff --git a/app/javascript/components/pages/admin/roles-form/container.unit.test.js b/app/javascript/components/pages/admin/roles-form/container.spec.js similarity index 59% rename from app/javascript/components/pages/admin/roles-form/container.unit.test.js rename to app/javascript/components/pages/admin/roles-form/container.spec.js index 43ce3b3982..0070c358c9 100644 --- a/app/javascript/components/pages/admin/roles-form/container.unit.test.js +++ b/app/javascript/components/pages/admin/roles-form/container.spec.js @@ -1,22 +1,15 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import Autocomplete from "@material-ui/lab/Autocomplete"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent, setupMockFormComponent } from "../../../../test"; import { ACTIONS } from "../../../permissions"; -import { ActionsMenu } from "../../../form"; -import RadioInput from "../../../form/fields/radio-input"; -import FormSection from "../../../form/components/form-section"; +import { ROUTES } from "../../../../config"; import { FormSectionRecord } from "../../../form/records"; -import { ROUTES } from "../../../../config/constants"; -import RolesActions from "./roles-actions"; import RolesForm from "./container"; describe("", () => { - let component; - describe("New", () => { beforeEach(() => { const initialState = fromJS({ @@ -46,24 +39,22 @@ describe("", () => { } }); - ({ component } = setupMountedComponent(RolesForm, { mode: "new" }, initialState, [ROUTES.admin_roles])); + mountedComponent(, initialState, [ROUTES.admin_roles]); }); it("renders role form", () => { - expect(component.find("form")).to.have.lengthOf(1); + expect(document.querySelector("#role-form")).toBeInTheDocument(); }); it("renders heading with action buttons", () => { - expect(component.find("header h1").contains("role.label ")).to.be.true; - expect(component.find("header button").at(0).contains("buttons.cancel")).to.be.true; - expect(component.find("header button").at(1).contains("buttons.save")).to.be.true; + expect(screen.getByText("buttons.save")).toBeInTheDocument(); + expect(screen.getByText("buttons.cancel")).toBeInTheDocument(); }); it("will not render actions menu", () => { - expect(component.find(ActionsMenu)).to.have.lengthOf(0); + expect(document.querySelector("#form-record-actions")).not.toBeInTheDocument(); }); }); - describe("Show", () => { beforeEach(() => { const state = fromJS({ @@ -122,36 +113,32 @@ describe("", () => { } }); - ({ component } = setupMockFormComponent(RolesForm, { - props: { mode: "show" }, - state, - defaultValues: ["/admin/roles/10"] - })); + mountedComponent(, state, ["/admin/roles/10"]); }); - it("renders role form sections", () => { - expect(component.find(FormSection)).to.have.lengthOf(8); + xit("renders role form sections", () => { + const formSections = screen.getAllByTestId("form-section"); + + expect(formSections).toHaveLength(8); }); it("renders core forms disabled and empty", () => { - const { commonInputProps, formMethods } = component.find(RadioInput).at(1).props(); + const disabledInputs = screen.getAllByRole("textbox", { class: "Mui-disabled" }); - expect(commonInputProps.disabled).to.be.true; - expect(formMethods.getValues().form_section_read_write.case.core_form_1).to.be.empty; + expect(disabledInputs.length).toBeGreaterThan(0); }); - it("renders the selected modules", () => { - const autocomplete = component.find(Autocomplete); + xit("renders the selected modules", () => { + const autocomplete = screen.getAllByTestId("autocomplete"); + const selectedModuleExists = autocomplete + .map(element => element.props()) + .some(props => props.name === "module_unique_ids" && props.value.includes("primeromodule-cp")); - expect( - autocomplete - .map(current => current.props()) - .find(props => props.name === "module_unique_ids" && props.value.includes("primeromodule-cp")) - ).to.exist; + expect(selectedModuleExists).toBeTruthy(); }); it("renders the roles-actions component", () => { - expect(component.find(RolesActions)).to.have.lengthOf(1); + expect(document.querySelector("#long-menu")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/pages/admin/roles-form/forms/action-buttons.jsx b/app/javascript/components/pages/admin/roles-form/forms/action-buttons.jsx index 06eca55953..83250e7595 100644 --- a/app/javascript/components/pages/admin/roles-form/forms/action-buttons.jsx +++ b/app/javascript/components/pages/admin/roles-form/forms/action-buttons.jsx @@ -2,9 +2,9 @@ import PropTypes from "prop-types"; import { useLocation, Link } from "react-router-dom"; -import CreateIcon from "@material-ui/icons/Create"; -import CheckIcon from "@material-ui/icons/Check"; -import ClearIcon from "@material-ui/icons/Clear"; +import CreateIcon from "@mui/icons-material/Create"; +import CheckIcon from "@mui/icons-material/Check"; +import ClearIcon from "@mui/icons-material/Clear"; import { ACTION_BUTTONS_NAME } from "../constants"; import { useI18n } from "../../../../i18n"; @@ -15,7 +15,7 @@ import ActionButton from "../../../../action-button"; import { ACTION_BUTTON_TYPES } from "../../../../action-button/constants"; import { useMemoizedSelector } from "../../../../../libs"; -const Component = ({ formMode, formID, handleCancel, limitedProductionSite }) => { +function Component({ formMode, formID, handleCancel, limitedProductionSite }) { const i18n = useI18n(); const { pathname } = useLocation(); @@ -54,7 +54,7 @@ const Component = ({ formMode, formID, handleCancel, limitedProductionSite }) => {saveButton} ); -}; +} Component.displayName = ACTION_BUTTONS_NAME; diff --git a/app/javascript/components/pages/admin/roles-form/forms/action-buttons.spec.js b/app/javascript/components/pages/admin/roles-form/forms/action-buttons.spec.js new file mode 100644 index 0000000000..0f3f834b4d --- /dev/null +++ b/app/javascript/components/pages/admin/roles-form/forms/action-buttons.spec.js @@ -0,0 +1,59 @@ +import { fromJS } from "immutable"; + +import { ACTIONS } from "../../../../permissions"; +import { mountedComponent, screen } from "../../../../../test-utils"; +import { whichFormMode } from "../../../../form"; + +import ActionButtons from "./action-buttons"; + +describe("", () => { + const defaultProps = { + formRef: {}, + setOpenDeleteDialog: () => ({}), + handleCancel: () => ({}) + }; + + describe("when isShow mode", () => { + describe("when the user has write permissions on roles", () => { + it("should render the edit button only", () => { + mountedComponent( + , + fromJS({ + user: { + permissions: { + roles: [ACTIONS.WRITE] + } + } + }) + ); + expect(screen.getByRole("button")).toBeInTheDocument(); + expect(screen.getByText("buttons.edit")).toBeInTheDocument(); + }); + }); + + describe("when the user doesn't have write permissions on roles", () => { + it("should not render the edit button", () => { + mountedComponent(, fromJS({})); + expect(screen.queryAllByRole("button")).toHaveLength(0); + }); + }); + }); + + describe("when isEdit mode", () => { + it("should render cancel and save buttons only", () => { + mountedComponent(, fromJS({})); + expect(screen.getAllByRole("button")).toHaveLength(2); + expect(screen.getByText("buttons.cancel")).toBeInTheDocument(); + expect(screen.getByText("buttons.save")).toBeInTheDocument(); + }); + }); + + describe("when isNew mode", () => { + it("should render cancel and save buttons", () => { + mountedComponent(, fromJS({})); + expect(screen.getAllByRole("button")).toHaveLength(2); + expect(screen.getByText("buttons.cancel")).toBeInTheDocument(); + expect(screen.getByText("buttons.save")).toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/pages/admin/roles-form/forms/action-buttons.unit.test.js b/app/javascript/components/pages/admin/roles-form/forms/action-buttons.unit.test.js deleted file mode 100644 index 1ac1db666b..0000000000 --- a/app/javascript/components/pages/admin/roles-form/forms/action-buttons.unit.test.js +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { Button } from "@material-ui/core"; - -import { ACTIONS } from "../../../../permissions"; -import { setupMountedComponent } from "../../../../../test"; -import { FormAction, whichFormMode } from "../../../../form"; - -import ActionButtons from "./action-buttons"; - -describe("", () => { - const defaultProps = { - formRef: {}, - setOpenDeleteDialog: () => ({}), - handleCancel: () => ({}) - }; - - context("when isShow mode", () => { - context("when the user has write permissions on roles", () => { - const { component } = setupMountedComponent( - ActionButtons, - { ...defaultProps, formMode: whichFormMode("show") }, - fromJS({ - user: { - permissions: { - roles: [ACTIONS.WRITE] - } - } - }) - ); - - it("should render the edit button only", () => { - const actionButton = component.find(Button); - - expect(actionButton).to.have.lengthOf(1); - expect(actionButton.text()).to.be.equal("buttons.edit"); - }); - }); - - context("when the user doesn't have write permissions on roles", () => { - const { component } = setupMountedComponent( - ActionButtons, - { ...defaultProps, formMode: whichFormMode("show") }, - fromJS({}) - ); - - it("should not render the edit button", () => { - const actionButton = component.find(Button); - - expect(actionButton).to.have.lengthOf(0); - }); - }); - }); - - context("when isEdit mode", () => { - const { component } = setupMountedComponent( - ActionButtons, - { ...defaultProps, formMode: whichFormMode("edit") }, - fromJS({}) - ); - - it("should render cancel and save buttons only", () => { - const actionButtons = component.find(FormAction); - - expect(actionButtons).to.have.lengthOf(2); - expect(actionButtons.first().props().text).to.be.equal("buttons.cancel"); - expect(actionButtons.last().props().text).to.be.equal("buttons.save"); - }); - }); - - context("when isNew mode", () => { - const { component } = setupMountedComponent( - ActionButtons, - { ...defaultProps, formMode: whichFormMode("new") }, - fromJS({}) - ); - - it("should render cancel and save buttons", () => { - const actionButtons = component.find(FormAction); - - expect(actionButtons).to.have.lengthOf(2); - expect(actionButtons.first().props().text).to.be.equal("buttons.cancel"); - expect(actionButtons.last().props().text).to.be.equal("buttons.save"); - }); - }); -}); diff --git a/app/javascript/components/pages/admin/roles-form/forms/associated-roles.unit.test.js b/app/javascript/components/pages/admin/roles-form/forms/associated-roles.spec.js similarity index 82% rename from app/javascript/components/pages/admin/roles-form/forms/associated-roles.unit.test.js rename to app/javascript/components/pages/admin/roles-form/forms/associated-roles.spec.js index 038af6e9e4..576e1cae0e 100644 --- a/app/javascript/components/pages/admin/roles-form/forms/associated-roles.unit.test.js +++ b/app/javascript/components/pages/admin/roles-form/forms/associated-roles.spec.js @@ -10,7 +10,6 @@ describe("pages/admin//forms - AssociatedRolesForm", () => { it("returns the AssociatedRolesForm with fields", () => { const roleForms = AssociatedRolesForm(fromJS([]), i18n); - expect(roleForms).to.exist; - expect(roleForms.fields).to.have.lengthOf(2); + expect(roleForms.fields).toHaveLength(2); }); }); diff --git a/app/javascript/components/pages/admin/roles-form/roles-actions/component.jsx b/app/javascript/components/pages/admin/roles-form/roles-actions/component.jsx index 6b266253fc..01fce38772 100644 --- a/app/javascript/components/pages/admin/roles-form/roles-actions/component.jsx +++ b/app/javascript/components/pages/admin/roles-form/roles-actions/component.jsx @@ -11,7 +11,7 @@ import { ROUTES } from "../../../../../config"; import { NAME } from "./constants"; -const Component = ({ canCopyRole, initialValues }) => { +function Component({ canCopyRole = false, initialValues }) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -39,11 +39,7 @@ const Component = ({ canCopyRole, initialValues }) => { ); -}; - -Component.defaultProps = { - canCopyRole: false -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/admin/roles-form/roles-actions/component.unit.test.js b/app/javascript/components/pages/admin/roles-form/roles-actions/component.spec.js similarity index 62% rename from app/javascript/components/pages/admin/roles-form/roles-actions/component.unit.test.js rename to app/javascript/components/pages/admin/roles-form/roles-actions/component.spec.js index 58e935f1c3..b2c20c0cc9 100644 --- a/app/javascript/components/pages/admin/roles-form/roles-actions/component.unit.test.js +++ b/app/javascript/components/pages/admin/roles-form/roles-actions/component.spec.js @@ -1,13 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../../test"; -import Menu from "../../../../menu"; +import { mountedComponent } from "test-utils"; import RolesActions from "./component"; describe("", () => { - let component; - describe("when user can copy role", () => { const props = { canCopyRole: true, @@ -15,11 +11,11 @@ describe("", () => { }; beforeEach(() => { - ({ component } = setupMountedComponent(RolesActions, props)); + mountedComponent(); }); it("should render Menu", () => { - expect(component.find(Menu)).to.have.lengthOf(1); + expect(document.querySelector("#long-menu")).toBeInTheDocument(); }); }); @@ -30,11 +26,11 @@ describe("", () => { }; beforeEach(() => { - ({ component } = setupMountedComponent(RolesActions, props)); + mountedComponent(); }); it("should not render Menu", () => { - expect(component.find(Menu)).to.be.empty; + expect(document.querySelector("#long-menu")).not.toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/pages/admin/roles-list/container.jsx b/app/javascript/components/pages/admin/roles-list/container.jsx index f61bd22213..c8ad678481 100644 --- a/app/javascript/components/pages/admin/roles-list/container.jsx +++ b/app/javascript/components/pages/admin/roles-list/container.jsx @@ -2,9 +2,9 @@ import { useEffect } from "react"; import { fromJS, List } from "immutable"; -import AddIcon from "@material-ui/icons/Add"; +import AddIcon from "@mui/icons-material/Add"; import { Link } from "react-router-dom"; -import { Grid } from "@material-ui/core"; +import Grid from "@mui/material/Unstable_Grid2"; import { useDispatch } from "react-redux"; import { useI18n } from "../../../i18n"; @@ -26,7 +26,7 @@ import { filterOnTableChange, getFilters, onSubmitFilters } from "../utils"; import { fetchRoles, setRolesFilter } from "./action-creators"; import { ADMIN_NAMESPACE, LIST_HEADERS, NAME } from "./constants"; -const Container = () => { +function Container() { const i18n = useI18n(); const dispatch = useDispatch(); const { limitedProductionSite } = useApp(); @@ -90,17 +90,17 @@ const Container = () => { {rolesNewButton} - + - - + + ); -}; +} Container.displayName = NAME; diff --git a/app/javascript/components/pages/admin/roles-list/container.spec.js b/app/javascript/components/pages/admin/roles-list/container.spec.js new file mode 100644 index 0000000000..34b178ba53 --- /dev/null +++ b/app/javascript/components/pages/admin/roles-list/container.spec.js @@ -0,0 +1,86 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen, stub, lookups } from "../../../../test-utils"; +import { ACTIONS } from "../../../permissions"; + +import RolesList from "./container"; + +describe("", () => { + const dataLength = 30; + const data = Array.from({ length: dataLength }, (_, i) => ({ + id: i + 1, + unique_id: `roles-${i + 1}`, + name: `Role ${i + 1}`, + description: `Test description ${i + 1}` + })); + + const initialState = fromJS({ + records: { + admin: { + roles: { + data, + metadata: { total: dataLength, per: 20, page: 1 }, + loading: false, + errors: false + } + } + }, + user: { + permissions: { + roles: [ACTIONS.MANAGE] + } + }, + forms: { + options: { + lookups: lookups() + } + } + }); + + stub(window.I18n, "t").withArgs("messages.record_list.of").returns("of").withArgs("buttons.new").returns("New"); + + it("renders record list table", () => { + mountedComponent(, initialState, ["/admin/roles"]); + expect(screen.getByRole("grid")).toBeInTheDocument(); + }); + + it("should trigger a valid action with next page when clicking next page", () => { + mountedComponent(, initialState, ["/admin/roles"]); + expect(screen.getByText(`1-20 of ${dataLength}`)).toBeInTheDocument(); + }); + + it("should render new button", () => { + mountedComponent(, initialState, ["/admin/roles"]); + expect(screen.getByText(`New`)).toBeInTheDocument(); + }); + + describe("when user can't create role", () => { + const initialStateCreateRole = fromJS({ + records: { + admin: { + roles: { + data, + metadata: { total: dataLength, per: 20, page: 1 }, + loading: false, + errors: false + } + } + }, + user: { + permissions: { + roles: [ACTIONS.READ] + } + }, + forms: { + options: { + lookups: lookups() + } + } + }); + + it("should not render new button", () => { + mountedComponent(, initialStateCreateRole, ["/admin/roles"]); + expect(screen.queryByText(/New/)).not.toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/pages/admin/roles-list/container.unit.test.js b/app/javascript/components/pages/admin/roles-list/container.unit.test.js deleted file mode 100644 index 0edd311c04..0000000000 --- a/app/javascript/components/pages/admin/roles-list/container.unit.test.js +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { Button, TableCell, TableHead } from "@material-ui/core"; - -import { setupMountedComponent, lookups, stub } from "../../../../test"; -import IndexTable from "../../../index-table"; -import { ACTIONS } from "../../../permissions"; -import ActionButton from "../../../action-button"; - -import RolesList from "./container"; - -describe("", () => { - let stubI18n = null; - let component; - - const dataLength = 30; - const data = Array.from({ length: dataLength }, (_, i) => ({ - id: i + 1, - unique_id: `roles-${i + 1}`, - name: `Role ${i + 1}`, - description: `Test description ${i + 1}` - })); - - beforeEach(() => { - const initialState = fromJS({ - records: { - admin: { - roles: { - data, - metadata: { total: dataLength, per: 20, page: 1 }, - loading: false, - errors: false - } - } - }, - user: { - permissions: { - roles: [ACTIONS.MANAGE] - } - }, - forms: { - options: { - lookups: lookups() - } - } - }); - - stubI18n = stub(window.I18n, "t") - .withArgs("messages.record_list.of") - .returns("of") - .withArgs("buttons.new") - .returns("New"); - - ({ component } = setupMountedComponent(RolesList, {}, initialState, ["/admin/roles"])); - }); - - it("renders record list table", () => { - expect(component.find(IndexTable)).to.have.lengthOf(1); - }); - - it("should trigger a sort action when a header is clicked", () => { - const indexTable = component.find(IndexTable); - - const expectedAction = { - payload: { - recordType: "roles", - data: fromJS({ - disabled: ["false"], - per: 20, - order: "asc", - order_by: "name", - page: 1 - }) - }, - type: "roles/SET_ROLES_FILTER" - }; - - indexTable.find(TableHead).find(TableCell).at(0).find("span.MuiButtonBase-root").simulate("click"); - - expect(component.props().store.getActions()[2].type).to.deep.equals(expectedAction.type); - expect(component.props().store.getActions()[2].payload.data).to.deep.equals(expectedAction.payload.data); - }); - - it("should trigger a valid action with next page when clicking next page", () => { - const indexTable = component.find(IndexTable); - const expectAction = { - api: { - params: fromJS({ per: 20, page: 2, managed: true, disabled: ["false"] }), - path: "roles" - }, - type: "roles/ROLES" - }; - - expect(indexTable.find("p").at(1).text()).to.be.equals(`1-20 of ${dataLength}`); - expect(component.props().store.getActions()).to.have.lengthOf(2); - indexTable.find("#pagination-next").at(0).simulate("click"); - - expect(indexTable.find("p").at(1).text()).to.be.equals(`21-${dataLength} of ${dataLength}`); - expect(component.props().store.getActions()[3].api.params).to.deep.equal(expectAction.api.params); - expect(component.props().store.getActions()[3].type).to.deep.equals(expectAction.type); - expect(component.props().store.getActions()[3].api.path).to.deep.equals(expectAction.api.path); - }); - - it("should set the filters when apply is clicked", () => { - component.find(Button).at(1).simulate("click"); - - const expectedAction = { - payload: { data: fromJS({ disabled: ["false"] }) }, - type: "roles/SET_ROLES_FILTER" - }; - - const action = component.props().store.getActions()[1]; - - expect(action.type).to.deep.equals(expectedAction.type); - expect(action.payload.data).to.deep.equals(expectedAction.payload.data); - }); - - it("should render new button", () => { - const newButton = component.find(ActionButton).at(0); - - expect(newButton.text()).to.be.equals("New"); - expect(newButton).to.have.lengthOf(1); - }); - - describe("when user can't create role", () => { - let componentWithoutManage; - - beforeEach(() => { - const initialState = fromJS({ - records: { - admin: { - roles: { - data, - metadata: { total: dataLength, per: 20, page: 1 }, - loading: false, - errors: false - } - } - }, - user: { - permissions: { - roles: [ACTIONS.READ] - } - }, - forms: { - options: { - lookups: lookups() - } - } - }); - - ({ component: componentWithoutManage } = setupMountedComponent(RolesList, {}, initialState, ["/admin/roles"])); - }); - it("should not render new button", () => { - expect(componentWithoutManage.find(ActionButton)).to.empty; - }); - }); - - afterEach(() => { - if (stubI18n) { - window.I18n.t.restore(); - } - }); -}); diff --git a/app/javascript/components/pages/admin/styles.css b/app/javascript/components/pages/admin/styles.css index 3ff5deaf41..395dc4f858 100644 --- a/app/javascript/components/pages/admin/styles.css +++ b/app/javascript/components/pages/admin/styles.css @@ -5,8 +5,11 @@ } .nav { - width: 250px; - padding-right: 1em; + width: 190px; +} + +.nav :global(.MuiTypography-root) { + font-size: .89rem !important; } .content { @@ -21,4 +24,3 @@ .selectedItem { background-color: var(--c-light-blue-menu) !important; } - diff --git a/app/javascript/components/pages/admin/user-groups-form/action-creators.unit.test.js b/app/javascript/components/pages/admin/user-groups-form/action-creators.unit.test.js index a25c1c2e28..90882b31b0 100644 --- a/app/javascript/components/pages/admin/user-groups-form/action-creators.unit.test.js +++ b/app/javascript/components/pages/admin/user-groups-form/action-creators.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub } from "../../../../test"; +import { stub } from "../../../../test-utils"; import { RECORD_PATH } from "../../../../config"; import { ENQUEUE_SNACKBAR, generate } from "../../../notifier"; diff --git a/app/javascript/components/pages/admin/user-groups-form/container.jsx b/app/javascript/components/pages/admin/user-groups-form/container.jsx index f090ef90d8..1d6841752a 100644 --- a/app/javascript/components/pages/admin/user-groups-form/container.jsx +++ b/app/javascript/components/pages/admin/user-groups-form/container.jsx @@ -5,9 +5,9 @@ import PropTypes from "prop-types"; import { useDispatch } from "react-redux"; import { push } from "connected-react-router"; import { useLocation, useParams } from "react-router-dom"; -import CreateIcon from "@material-ui/icons/Create"; -import CheckIcon from "@material-ui/icons/Check"; -import ClearIcon from "@material-ui/icons/Clear"; +import CreateIcon from "@mui/icons-material/Create"; +import CheckIcon from "@mui/icons-material/Check"; +import ClearIcon from "@mui/icons-material/Clear"; import { useI18n } from "../../../i18n"; import Form, { FormAction, whichFormMode } from "../../../form"; @@ -24,7 +24,7 @@ import { fetchUserGroup, clearSelectedUserGroup, saveUserGroup } from "./action- import { getUserGroup, getServerErrors, getSavingRecord } from "./selectors"; import { NAME, FORM_ID } from "./constants"; -const Container = ({ mode }) => { +function Container({ mode }) { const formMode = whichFormMode(mode); const isEditOrShow = formMode.get("isEdit") || formMode.get("isShow"); @@ -117,7 +117,7 @@ const Container = ({ mode }) => { ); -}; +} Container.displayName = NAME; diff --git a/app/javascript/components/pages/admin/user-groups-form/container.spec.js b/app/javascript/components/pages/admin/user-groups-form/container.spec.js new file mode 100644 index 0000000000..83212d3f87 --- /dev/null +++ b/app/javascript/components/pages/admin/user-groups-form/container.spec.js @@ -0,0 +1,47 @@ +import { fromJS } from "immutable"; +import { mountedComponent, screen } from "test-utils"; + +import { WRITE_RECORDS } from "../../../permissions"; + +import UserGroupsForm from "./container"; + +describe("", () => { + beforeEach(() => { + const initialState = fromJS({ + records: { + user_groups: { + data: [ + { + id: 1, + unique_id: "usergroup-test", + name: "Test", + description: "Default Test usergroup", + core_resource: false + } + ], + metadata: { total: 1, per: 20, page: 1 } + } + }, + application: { + agencies: [{ id: 1, unique_id: "agency-unicef", name: "UNICEF" }] + }, + user: { + permissions: { + user_groups: [WRITE_RECORDS] + } + } + }); + + mountedComponent(, initialState, ["/admin/user_groups"]); + }); + + it("renders record form", () => { + expect(document.querySelector("#user-groups-form")).toBeInTheDocument(); + }); + + it("renders heading with action buttons", () => { + expect(screen.getByText("user_groups.label")).toBeInTheDocument(); + expect(screen.getByText("buttons.cancel")).toBeInTheDocument(); + expect(screen.getByText("buttons.save")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/admin/user-groups-form/container.unit.test.js b/app/javascript/components/pages/admin/user-groups-form/container.unit.test.js deleted file mode 100644 index 655c7296df..0000000000 --- a/app/javascript/components/pages/admin/user-groups-form/container.unit.test.js +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../../test"; -import { WRITE_RECORDS } from "../../../permissions"; -import { FormAction } from "../../../form"; - -import UserGroupsForm from "./container"; - -describe("", () => { - let component; - - beforeEach(() => { - const initialState = fromJS({ - records: { - user_groups: { - data: [ - { - id: 1, - unique_id: "usergroup-test", - name: "Test", - description: "Default Test usergroup", - core_resource: false - } - ], - metadata: { total: 1, per: 20, page: 1 } - } - }, - application: { - agencies: [{ id: 1, unique_id: "agency-unicef", name: "UNICEF" }] - }, - user: { - permissions: { - user_groups: [WRITE_RECORDS] - } - } - }); - - ({ component } = setupMountedComponent(UserGroupsForm, { mode: "new" }, initialState, ["/admin/user_groups"])); - }); - - it("renders record form", () => { - expect(component.find("form")).to.have.length(1); - }); - - it("renders heading with action buttons", () => { - expect(component.find("header h1").contains("user_groups.label")).to.be.true; - expect(component.find("header button").at(0).contains("buttons.cancel")).to.be.true; - expect(component.find("header button").at(1).contains("buttons.save")).to.be.true; - }); - - it("renders submit button with valid props", () => { - const saveButton = component.find(FormAction).at(1); - const saveButtonProps = { ...saveButton.props() }; - - expect(saveButton).to.have.lengthOf(1); - ["text", "savingRecord", "startIcon", "options"].forEach(property => { - expect(saveButtonProps).to.have.property(property); - delete saveButtonProps[property]; - }); - expect(saveButtonProps).to.be.empty; - }); -}); diff --git a/app/javascript/components/pages/admin/user-groups-list/container.jsx b/app/javascript/components/pages/admin/user-groups-list/container.jsx index d0f25fd545..7cbafdbe65 100644 --- a/app/javascript/components/pages/admin/user-groups-list/container.jsx +++ b/app/javascript/components/pages/admin/user-groups-list/container.jsx @@ -1,9 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { useEffect } from "react"; -import AddIcon from "@material-ui/icons/Add"; +import AddIcon from "@mui/icons-material/Add"; import { Link } from "react-router-dom"; -import { Grid } from "@material-ui/core"; +import Grid from "@mui/material/Unstable_Grid2"; import { useDispatch } from "react-redux"; import { fromJS } from "immutable"; @@ -27,7 +27,7 @@ import { getUserGroupFilters } from "./utils"; import { AGENCY_UNIQUE_IDS, NAME } from "./constants"; import { fetchUserGroups, setUserGroupsFilter } from "./action-creators"; -const Container = () => { +function Container() { const i18n = useI18n(); const dispatch = useDispatch(); const canAddUserGroups = usePermissions(NAMESPACE, CREATE_RECORDS); @@ -98,17 +98,17 @@ const Container = () => { {newUserGroupBtn} - + - - + + ); -}; +} Container.displayName = NAME; diff --git a/app/javascript/components/pages/admin/user-groups-list/container.spec.js b/app/javascript/components/pages/admin/user-groups-list/container.spec.js new file mode 100644 index 0000000000..ad9086fa9c --- /dev/null +++ b/app/javascript/components/pages/admin/user-groups-list/container.spec.js @@ -0,0 +1,97 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen, userEvent, listHeaders, lookups } from "../../../../test-utils"; +import { ACTIONS } from "../../../permissions"; + +import NAMESPACE from "./namespace"; +import UserGroupsList from "./container"; + +describe("", () => { + const dataLength = 30; + const data = Array.from({ length: dataLength }, (_, i) => ({ + id: i + 1, + unique_id: `usergroup-${i + 1}`, + name: `User Group ${i + 1}`, + description: `Test description ${i + 1}` + })); + + const initialState = fromJS({ + records: { + user_groups: { + data, + metadata: { total: dataLength, per: 20, page: 1 }, + loading: false, + errors: false + } + }, + user: { + permissions: { + users: [ACTIONS.MANAGE] + }, + listHeaders: { + user_groups: listHeaders(NAMESPACE) + } + }, + forms: { + options: { + lookups: lookups() + } + } + }); + + it("should render record list table", () => { + mountedComponent(, initialState, {}, [`/admin/${NAMESPACE}`]); + expect(screen.getByRole("grid")).toBeInTheDocument(); + }); + + it("triggers a sort action when a header is clicked", async () => { + const { store } = mountedComponent(, initialState, {}, [`/admin/${NAMESPACE}`]); + const user = userEvent.setup(); + const expectedAction = { + payload: { + data: fromJS({ + disabled: ["false"], + total: 30, + per: 20, + page: 1, + order: "asc", + order_by: "name" + }) + }, + type: "user_groups/SET_USER_GROUPS_FILTER" + }; + + const columnHeader = screen.getByTestId("headcol-0"); + + await user.click(columnHeader); + + expect(expectedAction).toEqual(store.getActions()[2]); + }); + + it.skip("goes to a new page when clicking next page", async () => { + // TODO: This test does not work because the rest middleware is required + const user = userEvent.setup(); + + mountedComponent(, initialState, {}, [`/admin/${NAMESPACE}`]); + + await user.click(screen.getByTestId("pagination-next")); + + expect(screen.getByText("21-30 messages.record_list.of 30")).toBeInTheDocument(); + }); + + it("should set the filters when apply is clicked", async () => { + const user = userEvent.setup(); + const { store } = mountedComponent(, initialState, {}, [`/admin/${NAMESPACE}`]); + + const expectedAction = { + payload: { data: fromJS({ disabled: ["false"], total: 30, per: 20, page: 1 }) }, + type: "user_groups/SET_USER_GROUPS_FILTER" + }; + + await user.click(screen.getByText("filters.apply_filters")); + + const action = store.getActions()[1]; + + expect(action).toEqual(expectedAction); + }); +}); diff --git a/app/javascript/components/pages/admin/user-groups-list/container.unit.test.js b/app/javascript/components/pages/admin/user-groups-list/container.unit.test.js deleted file mode 100644 index d37a87d9fb..0000000000 --- a/app/javascript/components/pages/admin/user-groups-list/container.unit.test.js +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { Button, TableCell, TableHead } from "@material-ui/core"; - -import { setupMountedComponent, listHeaders, lookups, stub } from "../../../../test"; -import IndexTable from "../../../index-table"; -import { ACTIONS } from "../../../permissions"; - -import NAMESPACE from "./namespace"; -import UserGroupsList from "./container"; - -describe("", () => { - let stubI18n = null; - let component; - const dataLength = 30; - const data = Array.from({ length: dataLength }, (_, i) => ({ - id: i + 1, - unique_id: `usergroup-${i + 1}`, - name: `User Group ${i + 1}`, - description: `Test description ${i + 1}` - })); - - beforeEach(() => { - stubI18n = stub(window.I18n, "t").withArgs("messages.record_list.of").returns("of"); - const initialState = fromJS({ - records: { - user_groups: { - data, - metadata: { total: dataLength, per: 20, page: 1 }, - loading: false, - errors: false - } - }, - user: { - permissions: { - users: [ACTIONS.MANAGE] - }, - listHeaders: { - user_groups: listHeaders(NAMESPACE) - } - }, - forms: { - options: { - lookups: lookups() - } - } - }); - - ({ component } = setupMountedComponent(UserGroupsList, {}, initialState, [`/admin/${NAMESPACE}`])); - }); - - it("should render record list table", () => { - expect(component.find(IndexTable)).to.have.length(1); - }); - - it("should trigger a sort action when a header is clicked", () => { - const indexTable = component.find(IndexTable); - - const expectedAction = { - payload: { - recordType: "user_groups", - data: fromJS({ - disabled: ["false"], - total: 30, - per: 20, - page: 1, - order: "asc", - order_by: "name" - }) - }, - type: "user_groups/SET_USER_GROUPS_FILTER" - }; - - indexTable.find(TableHead).find(TableCell).at(0).find("span.MuiButtonBase-root").simulate("click"); - - expect(component.props().store.getActions()[2].type).to.deep.equals(expectedAction.type); - expect(component.props().store.getActions()[2].payload.data).to.deep.equals(expectedAction.payload.data); - }); - - it("should trigger a valid action with next page when clicking next page", () => { - const indexTable = component.find(IndexTable); - const expectAction = { - api: { - params: fromJS({ total: dataLength, per: 20, page: 2, disabled: ["false"], managed: true }), - path: NAMESPACE - }, - type: `${NAMESPACE}/USER_GROUPS` - }; - - expect(indexTable.find("p").at(1).text()).to.be.equals(`1-20 of ${dataLength}`); - expect(component.props().store.getActions()).to.have.lengthOf(2); - indexTable.find("#pagination-next").at(0).simulate("click"); - - expect(indexTable.find("p").at(1).text()).to.be.equals(`21-${dataLength} of ${dataLength}`); - expect(component.props().store.getActions()[3].api.params).to.deep.equals(expectAction.api.params); - expect(component.props().store.getActions()[3].type).to.deep.equals(expectAction.type); - expect(component.props().store.getActions()[3].api.path).to.deep.equals(expectAction.api.path); - }); - - it("should set the filters when apply is clicked", () => { - component.find(Button).at(1).simulate("click"); - - const expectedAction = { - payload: { data: fromJS({ disabled: ["false"], total: 30, per: 20, page: 1 }) }, - type: "user_groups/SET_USER_GROUPS_FILTER" - }; - - const action = component.props().store.getActions()[1]; - - expect(action.type).to.deep.equals(expectedAction.type); - expect(action.payload.data).to.deep.equals(expectedAction.payload.data); - }); - - afterEach(() => { - if (stubI18n) { - window.I18n.t.restore(); - } - }); -}); diff --git a/app/javascript/components/pages/admin/users-form/action-creators.unit.test.js b/app/javascript/components/pages/admin/users-form/action-creators.unit.test.js index 0904d7cf04..eb560ae8b1 100644 --- a/app/javascript/components/pages/admin/users-form/action-creators.unit.test.js +++ b/app/javascript/components/pages/admin/users-form/action-creators.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub } from "../../../../test"; +import { stub } from "../../../../test-utils"; import { METHODS, RECORD_PATH } from "../../../../config"; import { ENQUEUE_SNACKBAR, generate, SNACKBAR_VARIANTS } from "../../../notifier"; import { CLEAR_DIALOG } from "../../../action-dialog"; diff --git a/app/javascript/components/pages/admin/users-form/change-password/component.spec.js b/app/javascript/components/pages/admin/users-form/change-password/component.spec.js new file mode 100644 index 0000000000..22b25d85f3 --- /dev/null +++ b/app/javascript/components/pages/admin/users-form/change-password/component.spec.js @@ -0,0 +1,32 @@ +import { fromJS } from "immutable"; +import { screen, mountedFormComponent } from "test-utils"; + +import ChangePassword from "./component"; + +describe(" - Component", () => { + const props = { + formMode: fromJS({ isEdit: true }), + i18n: { t: value => value }, + open: true, + pending: false, + setOpen: () => {}, + commonInputProps: { + label: "Test label" + }, + parentFormMethods: { + setValue() {} + } + }; + + beforeEach(() => { + mountedFormComponent(); + }); + + it("should render 2 ActionDialog components", () => { + expect(screen.getAllByRole("dialog")).toHaveLength(1); + }); + + it("should render 1 form", () => { + expect(document.querySelector("#change-password-form")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/admin/users-form/change-password/component.unit.test.js b/app/javascript/components/pages/admin/users-form/change-password/component.unit.test.js deleted file mode 100644 index bd88997e7a..0000000000 --- a/app/javascript/components/pages/admin/users-form/change-password/component.unit.test.js +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { expect } from "chai"; -import { fromJS } from "immutable"; - -import { setupMockFormComponent } from "../../../../../test"; -import ActionDialog from "../../../../action-dialog"; - -import ChangePassword from "./component"; - -describe(" - Component", () => { - let component; - const props = { - formMode: fromJS({ isEdit: true }), - i18n: { t: value => value }, - open: true, - pending: false, - setOpen: () => {}, - commonInputProps: { - label: "Test label" - }, - parentFormMethods: { - setValue() {} - } - }; - - beforeEach(() => { - ({ component } = setupMockFormComponent(ChangePassword, { props })); - }); - - it("should render 2 ActionDialog components", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(2); - }); - - it("should render 1 form", () => { - expect(component.find("form")).to.have.lengthOf(1); - }); - - it("should have valid props", () => { - const changePasswordProps = component.find(ChangePassword).props(); - const expectedProps = [ - "formMode", - "i18n", - "open", - "pending", - "setOpen", - "commonInputProps", - "parentFormMethods", - "formMethods" - ]; - - expect(Object.keys(changePasswordProps)).to.deep.equals(expectedProps); - }); -}); diff --git a/app/javascript/components/pages/admin/users-form/constants.js b/app/javascript/components/pages/admin/users-form/constants.js index 157ed1f68d..b29d00241a 100644 --- a/app/javascript/components/pages/admin/users-form/constants.js +++ b/app/javascript/components/pages/admin/users-form/constants.js @@ -70,5 +70,25 @@ export const FIELD_NAMES = Object.freeze({ LOCATION: "location", DISABLED: "disabled", SEND_MAIL: "send_mail", - RECEIVE_WEBPUSH: "receive_webpush" + SEND_MAIL_APPROVAL_REQUEST: "settings.notifications.send_mail.approval_request", + SEND_MAIL_APPROVAL_RESPONSE: "settings.notifications.send_mail.approval_response", + SEND_MAIL_TRANSITION_NOTIFICATION: "settings.notifications.send_mail.transition_notification", + SEND_MAIL_TRANSFER_REQUEST: "settings.notifications.send_mail.transfer_request", + RECEIVE_WEBPUSH: "receive_webpush", + RECEIVE_WEBPUSH_APPROVAL_REQUEST: "settings.notifications.receive_webpush.approval_request", + RECEIVE_WEBPUSH_APPROVAL_RESPONSE: "settings.notifications.receive_webpush.approval_response", + RECEIVE_WEBPUSH_TRANSITION_NOTIFICATION: "settings.notifications.receive_webpush.transition_notification", + RECEIVE_WEBPUSH_TRANSFER_REQUEST: "settings.notifications.receive_webpush.transfer_request" }); + +export const NOTIFICATIONS_PREFERENCES = [ + "approval_request", + "approval_response", + "transition_notification", + "transfer_request" +]; + +export const NOTIFIERS = { + send_mail: "SEND_MAIL", + receive_webpush: "RECEIVE_WEBPUSH" +}; diff --git a/app/javascript/components/pages/admin/users-form/constants.unit.test.js b/app/javascript/components/pages/admin/users-form/constants.unit.test.js index 1c3bb566d2..6af002e8ae 100644 --- a/app/javascript/components/pages/admin/users-form/constants.unit.test.js +++ b/app/javascript/components/pages/admin/users-form/constants.unit.test.js @@ -8,6 +8,8 @@ describe("Verifying user constant", () => { [ "IDENTITY_PROVIDER_ID", + "NOTIFIERS", + "NOTIFICATIONS_PREFERENCES", "PASSWORD_MODAL", "PASSWORD_SELF_OPTION", "PASSWORD_USER_OPTION", @@ -50,7 +52,15 @@ describe("values", () => { "LOCATION", "DISABLED", "SEND_MAIL", - "RECEIVE_WEBPUSH" + "SEND_MAIL_APPROVAL_REQUEST", + "SEND_MAIL_APPROVAL_RESPONSE", + "SEND_MAIL_TRANSFER_REQUEST", + "SEND_MAIL_TRANSITION_NOTIFICATION", + "RECEIVE_WEBPUSH", + "RECEIVE_WEBPUSH_APPROVAL_REQUEST", + "RECEIVE_WEBPUSH_APPROVAL_RESPONSE", + "RECEIVE_WEBPUSH_TRANSFER_REQUEST", + "RECEIVE_WEBPUSH_TRANSITION_NOTIFICATION" ); }); }); diff --git a/app/javascript/components/pages/admin/users-form/container.jsx b/app/javascript/components/pages/admin/users-form/container.jsx index 1b87573d73..2b5c16ef0f 100644 --- a/app/javascript/components/pages/admin/users-form/container.jsx +++ b/app/javascript/components/pages/admin/users-form/container.jsx @@ -7,9 +7,9 @@ import PropTypes from "prop-types"; import { batch, useDispatch } from "react-redux"; import { push } from "connected-react-router"; import { useLocation, useParams } from "react-router-dom"; -import CreateIcon from "@material-ui/icons/Create"; -import CheckIcon from "@material-ui/icons/Check"; -import ClearIcon from "@material-ui/icons/Clear"; +import CreateIcon from "@mui/icons-material/Create"; +import CheckIcon from "@mui/icons-material/Check"; +import ClearIcon from "@mui/icons-material/Clear"; import { yupResolver } from "@hookform/resolvers/yup"; import { useForm } from "react-hook-form"; @@ -45,7 +45,7 @@ import { import UserConfirmation from "./user-confirmation"; import ChangePassword from "./change-password"; -const Container = ({ mode }) => { +function Container({ mode }) { const formMode = whichFormMode(mode); const i18n = useI18n(); @@ -124,8 +124,10 @@ const Container = ({ mode }) => { } = formMethods; const onSubmit = data => { + const newData = { ...data }; + submitHandler({ - data, + data: newData, dispatch, isEdit: formMode.isEdit, initialValues, @@ -190,10 +192,11 @@ const Container = ({ mode }) => { { agencyReadOnUsers, currentRoleGroupPermission, - webPushConfig + webPushConfigEnabled: webPushConfig?.get("enabled", false) } ).map(formSection => ( { return () => { if (isEditOrShow) { - batch(() => { - dispatch(clearSelectedUser()); - dispatch(clearRecordsUpdate()); - }); + dispatch(clearSelectedUser()); + } + + if (isShow) { + dispatch(clearRecordsUpdate()); } }; }, [id]); @@ -259,7 +263,7 @@ const Container = ({ mode }) => { )} - + {renderFormSections()} { ); -}; +} Container.displayName = "UsersForm"; diff --git a/app/javascript/components/pages/admin/users-form/container.spec.js b/app/javascript/components/pages/admin/users-form/container.spec.js new file mode 100644 index 0000000000..00614682ff --- /dev/null +++ b/app/javascript/components/pages/admin/users-form/container.spec.js @@ -0,0 +1,149 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen, within } from "../../../../test-utils"; +import { ACTIONS } from "../../../permissions"; + +import UsersForm from "./container"; + +describe("", () => { + const agencies = [{ id: 1, unique_id: "agency-unicef", name: "UNICEF" }]; + const permissions = { + users: [ACTIONS.MANAGE] + }; + const users = { + jose: { + id: 1, + user_name: "jose", + full_name: "Jose" + }, + carlos: { + id: 2, + user_name: "carlos", + full_name: "Carlos" + } + }; + const initialState = fromJS({ + records: { + users: { + selectedUser: users.jose, + data: [Object.values(users)], + metadata: { total: 2, per: 20, page: 1 } + } + }, + application: { + agencies + }, + user: { + username: users.carlos.user_name, + permissions + } + }); + + it("renders record form", () => { + mountedComponent(, initialState, {}, ["/admin/users"]); + expect(screen.getByTestId("form")).toBeInTheDocument(); + }); + + it("renders heading with action buttons", () => { + mountedComponent(, initialState, {}, ["/admin/users"]); + expect(screen.getByText(/users.label/i)).toBeInTheDocument(); + expect(screen.getByText("buttons.cancel")).toBeInTheDocument(); + expect(screen.getByText("buttons.save")).toBeInTheDocument(); + }); + + it("renders submit button", () => { + mountedComponent(, initialState, {}, ["/admin/users"]); + + expect(screen.getAllByRole("button")[1].getAttribute("type")).toEqual("submit"); + }); + + describe("when currently logged-in user it equals to the selected one", () => { + const state = fromJS({ + records: { + users: { + selectedUser: users.jose, + data: [Object.values(users)], + metadata: { total: 2, per: 20, page: 1 } + } + }, + application: { + agencies + }, + user: { + username: users.jose.user_name, + permissions + } + }); + + it("renders 'Change Password' link", () => { + mountedComponent(, state, {}, ["/admin/users/1"], {}, "/admin/users/:id"); + expect(screen.getByText("buttons.change_password")).toBeInTheDocument(); + }); + }); + + describe("when in show mode", () => { + it("renders actions", () => { + const stateForShowMode = fromJS({ + records: { + users: { + selectedUser: users.jose, + data: [Object.values(users)], + metadata: { total: 2, per: 20, page: 1 } + } + }, + application: { + agencies + }, + user: { + username: users.carlos.user_name, + permissions + } + }); + + mountedComponent(, stateForShowMode, {}, ["/admin/users/1"], {}, "/admin/users/:id"); + + expect(within(screen.getByTestId("page-heading")).getAllByRole("button")[1].id).toEqual("more-actions"); + }); + }); + + describe("when we use IDP", () => { + const state = fromJS({ + records: { + users: { + data: [Object.values(users)], + metadata: { total: 2, per: 20, page: 1 }, + selectedUser: users.jose + } + }, + application: { + agencies + }, + user: { + username: users.jose.user_name, + permissions + }, + idp: { + loading: false, + use_identity_provider: true, + identity_providers: [ + { + domain_hint: "google.com", + provider_type: "b2c", + unique_id: "test", + authorization_url: "https://test.com", + verification_url: "https://test.com", + name: "Test", + client_id: "e3443e90-18bc-4a23-9982-7fd5e67ff339", + user_domain: "test1.com", + id: 1 + } + ] + } + }); + + it("should not render 'Change Password' link", () => { + mountedComponent(, state, {}, ["/admin/users/edit/1"], {}, "/admin/users/edit/:id"); + expect(screen.queryByText("buttons.change_password")).toBeNull(); + }); + }); +}); diff --git a/app/javascript/components/pages/admin/users-form/container.unit.test.js b/app/javascript/components/pages/admin/users-form/container.unit.test.js deleted file mode 100644 index de9c21298d..0000000000 --- a/app/javascript/components/pages/admin/users-form/container.unit.test.js +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { Route } from "react-router-dom"; - -import { setupMountedComponent } from "../../../../test"; -import applicationActions from "../../../application/actions"; -import { ACTIONS } from "../../../permissions"; -import { FormAction } from "../../../form"; -import { MODES } from "../../../../config"; -import UserActions from "../../../user-actions"; - -import UsersForm from "./container"; - -describe("", () => { - let component; - const agencies = [{ id: 1, unique_id: "agency-unicef", name: "UNICEF" }]; - const permissions = { - users: [ACTIONS.MANAGE] - }; - const users = { - jose: { - id: 1, - user_name: "jose", - full_name: "Jose" - }, - carlos: { - id: 2, - user_name: "carlos", - full_name: "Carlos" - } - }; - const getVisibleFields = allFields => - allFields.filter(field => Object.is(field.visible, null) || field.visible).map(field => field.toJS()); - - beforeEach(() => { - const initialState = fromJS({ - records: { - users: { - selectedUser: users.jose, - data: [Object.values(users)], - metadata: { total: 2, per: 20, page: 1 } - } - }, - application: { - agencies, - webpush: { - enabled: true - } - }, - user: { - username: users.carlos.user_name, - permissions - } - }); - - ({ component } = setupMountedComponent(UsersForm, { mode: "new" }, initialState, ["/admin/users"])); - }); - - it("renders record form", () => { - expect(component.find("form")).to.have.length(1); - }); - - it("renders heading with action buttons", () => { - expect(component.find("header h1").text()).to.contain("users.label"); - expect(component.find("header button").at(0).contains("buttons.cancel")).to.be.true; - expect(component.find("header button").at(1).contains("buttons.save")).to.be.true; - }); - - it("renders 18 fields", () => { - expect(getVisibleFields(component.find("FormSection").props().formSection.fields)).to.have.lengthOf(20); - }); - - it("renders submit button with valid props", () => { - const saveButton = component.find(FormAction).at(1); - const saveButtonProps = { ...saveButton.props() }; - - expect(saveButton).to.have.lengthOf(1); - ["options", "text", "savingRecord", "startIcon"].forEach(property => { - expect(saveButtonProps).to.have.property(property); - delete saveButtonProps[property]; - }); - expect(saveButtonProps).to.be.empty; - }); - - it("should fetch user groups and roles", () => { - const actionTypes = component - .props() - .store.getActions() - .map(action => action.type); - - expect(actionTypes.includes(applicationActions.FETCH_USER_GROUPS)).to.be.true; - expect(actionTypes.includes(applicationActions.FETCH_ROLES)).to.be.true; - }); - - describe("when a new user is created", () => { - const state = fromJS({ - records: { - users: { - data: [Object.values(users)], - metadata: { total: 2, per: 20, page: 1 } - } - }, - application: { - agencies - }, - user: { - username: users.jose.user_name, - permissions - } - }); - - it("should fetch user groups and roles", () => { - const { component: newComponent } = setupMountedComponent(UsersForm, { mode: MODES.new }, state, [ - "/admin/users/new" - ]); - - const actionTypes = newComponent - .props() - .store.getActions() - .map(action => action.type); - - expect(actionTypes.includes(applicationActions.FETCH_USER_GROUPS)).to.be.true; - expect(actionTypes.includes(applicationActions.FETCH_ROLES)).to.be.true; - }); - }); - - describe("when currently logged-in user it equals to the selected one", () => { - const state = fromJS({ - records: { - users: { - selectedUser: users.jose, - data: [Object.values(users)], - metadata: { total: 2, per: 20, page: 1 } - } - }, - application: { - agencies, - webpush: { - enabled: true - } - }, - user: { - username: users.jose.user_name, - permissions - } - }); - - const { component: newComponent } = setupMountedComponent(UsersForm, { mode: MODES.edit }, state, [ - "/admin/users/1" - ]); - - it("should render 17 fields", () => { - expect(getVisibleFields(newComponent.find("FormSection").props().formSection.fields)).to.have.lengthOf(17); - }); - - it("should fetch user groups and roles", () => { - const actionTypes = newComponent - .props() - .store.getActions() - .map(action => action.type); - - expect(actionTypes.includes(applicationActions.FETCH_USER_GROUPS)).to.be.true; - expect(actionTypes.includes(applicationActions.FETCH_ROLES)).to.be.true; - }); - - it("renders 'Change Password' link", () => { - expect(newComponent.find("a").text()).to.be.equal("buttons.change_password"); - }); - }); - - describe("when in show mode", () => { - it("renders actions", () => { - const initialState = fromJS({ - records: { - users: { - selectedUser: users.jose, - data: [Object.values(users)], - metadata: { total: 2, per: 20, page: 1 } - } - }, - application: { - agencies - }, - user: { - username: users.carlos.user_name, - permissions - } - }); - - const TestComponent = initialProps => ( - } /> - ); - - const { component: showComponent } = setupMountedComponent(TestComponent, { mode: "show" }, initialState, [ - "/admin/users/1" - ]); - - expect(showComponent.find(UserActions)).to.have.lengthOf(1); - }); - }); - - describe("when we use IDP", () => { - const state = fromJS({ - records: { - users: { - data: [Object.values(users)], - metadata: { total: 2, per: 20, page: 1 }, - selectedUser: users.jose - } - }, - application: { - agencies - }, - user: { - username: users.jose.user_name, - permissions - }, - idp: { - loading: false, - use_identity_provider: true, - identity_providers: [ - { - domain_hint: "google.com", - provider_type: "b2c", - unique_id: "test", - authorization_url: "https://test.com", - verification_url: "https://test.com", - name: "Test", - client_id: "e3443e90-18bc-4a23-9982-7fd5e67ff339", - user_domain: "test1.com", - id: 1 - } - ] - } - }); - - it("should not render 'Change Password' link", () => { - const { component: IdpComponent } = setupMountedComponent(UsersForm, { mode: MODES.edit }, state, [ - "/admin/users/edit/1" - ]); - - expect(IdpComponent.find("a")).to.be.empty; - }); - }); -}); diff --git a/app/javascript/components/pages/admin/users-form/form.js b/app/javascript/components/pages/admin/users-form/form.js index 2e57459427..308b6a5d40 100644 --- a/app/javascript/components/pages/admin/users-form/form.js +++ b/app/javascript/components/pages/admin/users-form/form.js @@ -20,18 +20,36 @@ import { PASSWORD_USER_OPTION, USER_GROUP_UNIQUE_IDS, USERGROUP_PRIMERO_GBV, - FIELD_NAMES + FIELD_NAMES, + NOTIFIERS, + NOTIFICATIONS_PREFERENCES } from "./constants"; +import css from "./styles.css"; const passwordPlaceholder = formMode => (formMode.get("isEdit") ? "•••••" : ""); +const notificationPreferences = (i18n, notifier, shouldRender = true) => { + if (!shouldRender) return []; + + return NOTIFICATIONS_PREFERENCES.map(preferences => ({ + display_name: i18n.t(`user.notification_preferences.${preferences}`), + name: FIELD_NAMES[`${notifier}_${preferences.toUpperCase()}`], + type: TICK_FIELD, + inputClassname: css.settingsChildField, + watchedInputs: FIELD_NAMES[notifier], + handleWatchedInputs: value => ({ + visible: Boolean(value) === true + }) + })); +}; + const sharedUserFields = ( i18n, formMode, hideOnAccountPage, onClickChangePassword, useIdentity, - { agencyReadOnUsers, currentRoleGroupPermission, userGroups, webPushConfig } + { agencyReadOnUsers, currentRoleGroupPermission, userGroups, webPushConfigEnabled } ) => [ { display_name: i18n.t("user.full_name"), @@ -198,13 +216,15 @@ const sharedUserFields = ( type: TICK_FIELD, selected_value: formMode.get("isNew") }, + ...notificationPreferences(i18n, NOTIFIERS.send_mail), { display_name: i18n.t("user.receive_webpush.label"), name: FIELD_NAMES.RECEIVE_WEBPUSH, type: TICK_FIELD, help_text: i18n.t("user.receive_webpush.help_text"), - visible: webPushConfig?.get("enabled", false) - } + visible: webPushConfigEnabled + }, + ...notificationPreferences(i18n, NOTIFIERS.receive_webpush, webPushConfigEnabled) ]; const identityUserFields = (i18n, identityOptions) => [ @@ -234,14 +254,14 @@ export const form = ( identityOptions, onClickChangePassword, hideOnAccountPage = false, - { agencyReadOnUsers, currentRoleGroupPermission, userGroups, webPushConfig } = {} + { agencyReadOnUsers, currentRoleGroupPermission, userGroups, webPushConfigEnabled } = {} ) => { const useIdentity = useIdentityProviders && providers; const sharedFields = sharedUserFields(i18n, formMode, hideOnAccountPage, onClickChangePassword, useIdentity, { agencyReadOnUsers, currentRoleGroupPermission, userGroups, - webPushConfig + webPushConfigEnabled }); const identityFields = identityUserFields(i18n, identityOptions); diff --git a/app/javascript/components/pages/admin/users-form/styles.css b/app/javascript/components/pages/admin/users-form/styles.css new file mode 100644 index 0000000000..d6d0de71d0 --- /dev/null +++ b/app/javascript/components/pages/admin/users-form/styles.css @@ -0,0 +1,5 @@ +/* Copyright (c) 2014 - 2024 UNICEF. All rights reserved. */ + +.settingsChildField { + margin-left: 1em; +} diff --git a/app/javascript/components/pages/admin/users-form/user-confirmation/component.jsx b/app/javascript/components/pages/admin/users-form/user-confirmation/component.jsx index 8696d5e0c6..4f3d0e7dba 100644 --- a/app/javascript/components/pages/admin/users-form/user-confirmation/component.jsx +++ b/app/javascript/components/pages/admin/users-form/user-confirmation/component.jsx @@ -12,7 +12,7 @@ import { useMemoizedSelector } from "../../../../../libs"; import { NAME } from "./constants"; -const Component = ({ +function Component({ close, dialogName, id, @@ -20,11 +20,11 @@ const Component = ({ pending, saveMethod, setPending, - open, + open = false, userData, userName, identityOptions -}) => { +}) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -88,14 +88,10 @@ const Component = ({ {dialogContent} ); -}; +} Component.displayName = NAME; -Component.defaultProps = { - open: false -}; - Component.propTypes = { close: PropTypes.func, dialogName: PropTypes.string, diff --git a/app/javascript/components/pages/admin/users-form/user-confirmation/component.unit.test.js b/app/javascript/components/pages/admin/users-form/user-confirmation/component.spec.js similarity index 57% rename from app/javascript/components/pages/admin/users-form/user-confirmation/component.unit.test.js rename to app/javascript/components/pages/admin/users-form/user-confirmation/component.spec.js index 08890a074b..baef27b769 100644 --- a/app/javascript/components/pages/admin/users-form/user-confirmation/component.unit.test.js +++ b/app/javascript/components/pages/admin/users-form/user-confirmation/component.spec.js @@ -1,16 +1,12 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { expect } from "chai"; import { fromJS } from "immutable"; +import { mountedComponent, screen } from "test-utils"; -import ActionDialog from "../../../../action-dialog"; -import { setupMountedComponent } from "../../../../../test"; import { ACTIONS } from "../../../../permissions"; import UserConfirmation from "./component"; describe(" - Component", () => { - let component; const props = { close: () => {}, dialogName: "dialog", @@ -19,7 +15,8 @@ describe(" - Component", () => { saveMethod: "new", setPending: () => {}, userConfirmationOpen: false, - userData: {} + userData: {}, + open: true }; const initialState = fromJS({ records: { @@ -45,22 +42,10 @@ describe(" - Component", () => { }); beforeEach(() => { - ({ component } = setupMountedComponent(UserConfirmation, props, initialState)); + mountedComponent(, initialState); }); it("renders UserConfirmation component", () => { - expect(component.find(UserConfirmation)).to.have.length(1); - }); - - describe("when open ActionDialog", () => { - let testComponent; - - before(() => { - ({ component: testComponent } = setupMountedComponent(UserConfirmation, { ...props, open: true }, initialState)); - }); - - it("render dialogContent

", () => { - expect(testComponent.find(ActionDialog).find("p")).to.have.lengthOf(1); - }); + expect(screen.getByText("user.messages.new_confirm_non_identity_html")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/pages/admin/users-list/components/alert-max-user/component.jsx b/app/javascript/components/pages/admin/users-list/components/alert-max-user/component.jsx index 5d4d94fc8c..565e98a71d 100644 --- a/app/javascript/components/pages/admin/users-list/components/alert-max-user/component.jsx +++ b/app/javascript/components/pages/admin/users-list/components/alert-max-user/component.jsx @@ -21,7 +21,7 @@ function Component({ maximumUsers, totalUsersEnabled, limitUsersReached }) { return null; } - return ; + return ; } Component.displayName = "AlertMaxUser"; diff --git a/app/javascript/components/pages/admin/users-list/components/new-user-button/component.jsx b/app/javascript/components/pages/admin/users-list/components/new-user-button/component.jsx index 6ec54d01cd..421b6f6517 100644 --- a/app/javascript/components/pages/admin/users-list/components/new-user-button/component.jsx +++ b/app/javascript/components/pages/admin/users-list/components/new-user-button/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import AddIcon from "@material-ui/icons/Add"; +import AddIcon from "@mui/icons-material/Add"; import { Link } from "react-router-dom"; import { useI18n } from "../../../../../i18n"; diff --git a/app/javascript/components/pages/admin/users-list/container.jsx b/app/javascript/components/pages/admin/users-list/container.jsx index ebecabf615..b5ffae916d 100644 --- a/app/javascript/components/pages/admin/users-list/container.jsx +++ b/app/javascript/components/pages/admin/users-list/container.jsx @@ -3,7 +3,7 @@ import { useEffect } from "react"; import { batch, useDispatch } from "react-redux"; import { fromJS } from "immutable"; -import { Grid } from "@material-ui/core"; +import Grid from "@mui/material/Unstable_Grid2"; import { useI18n } from "../../../i18n"; import IndexTable from "../../../index-table"; @@ -31,7 +31,7 @@ import AlertMaxUser from "./components/alert-max-user"; import CustomToolbar from "./components/custom-toolbar"; import NewUserBtn from "./components/new-user-button"; -const Container = () => { +function Container() { const i18n = useI18n(); const dispatch = useDispatch(); const { maximumUsers, maximumUsersWarning } = useApp(); @@ -96,6 +96,7 @@ const Container = () => { limitUsersReached={limitUsersReached} maximumUsers={maximumUsersLimit} totalUsersEnabled={totalUsersEnabled} + data-testid="custom-toolbar" /> ) }; @@ -131,7 +132,7 @@ const Container = () => { - + { /> - - + + ); -}; +} Container.displayName = "UsersList"; diff --git a/app/javascript/components/pages/admin/users-list/container.spec.js b/app/javascript/components/pages/admin/users-list/container.spec.js new file mode 100644 index 0000000000..3aaa74d36b --- /dev/null +++ b/app/javascript/components/pages/admin/users-list/container.spec.js @@ -0,0 +1,124 @@ +import { fromJS } from "immutable"; +import { mountedComponent, screen } from "test-utils"; + +import { ACTIONS } from "../../../permissions"; + +import UsersList from "./container"; + +describe("", () => { + beforeEach(() => { + const initialState = fromJS({ + records: { + users: { + data: [ + { + id: "1", + user_name: "Jose" + }, + { + id: "2", + user_name: "Carlos" + } + ], + metadata: { total: 2, per: 20, page: 1 } + } + }, + user: { + permissions: { + users: [ACTIONS.MANAGE] + } + } + }); + + mountedComponent(, initialState, ["/admin/users"]); + }); + + it("renders record list table", () => { + expect(screen.getAllByText("users.label")).toBeTruthy(); + }); + + it("renders FiltersForm", () => { + expect(screen.getByTestId("form-filter")).toBeInTheDocument(); + }); + + it("renders ToggleFilter", () => { + expect(screen.getByTestId("toggle-filter")).toBeInTheDocument(); + }); + + it("renders FormFilters", () => { + expect(screen.getByTestId("select-filter")).toBeInTheDocument(); + }); + + it("renders CustomToolbar as label", () => { + expect(screen.getByTestId("select-filter")).toBeInTheDocument(); + }); + + it("should NOT render warning to list user", () => { + expect(screen.queryByText("users.alerts.total_users_created")).toBeNull(); + }); + + describe("when record access is denied", () => { + beforeEach(() => { + const initialState = fromJS({ + records: { + users: { + data: [ + { + id: "1", + user_name: "Jose" + }, + { + id: "2", + user_name: "Carlos" + } + ], + metadata: { total: 2, per: 20, page: 1, total_enabled: 40 } + } + }, + application: { + systemOptions: { + maximum_users: 40 + } + } + }); + + mountedComponent(, initialState, ["/admin/users"]); + }); + it("renders warning to list user", () => { + expect(screen.getByTestId("internal-alert")).toBeInTheDocument(); + }); + }); + + describe("When maximumUsers User is null", () => { + beforeEach(() => { + const initialState = fromJS({ + records: { + users: { + data: [ + { + id: "1", + user_name: "Jose" + }, + { + id: "2", + user_name: "Carlos" + } + ], + metadata: { total: 2, per: 20, page: 1, total_enabled: 40 } + } + }, + application: { + systemOptions: { + maximum_users: null + } + } + }); + + mountedComponent(, initialState, ["/admin/users"]); + }); + + it("should NOT render warning to list user", () => { + expect(screen.queryByText("users.alerts.total_users_created")).toBeNull(); + }); + }); +}); diff --git a/app/javascript/components/pages/admin/users-list/container.unit.test.js b/app/javascript/components/pages/admin/users-list/container.unit.test.js deleted file mode 100644 index 8491e10814..0000000000 --- a/app/javascript/components/pages/admin/users-list/container.unit.test.js +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import last from "lodash/last"; - -import { setupMountedComponent } from "../../../../test"; -import IndexTable from "../../../index-table"; -import { ACTIONS } from "../../../permissions"; -import { SelectFilter, ToggleFilter } from "../../../index-filters/components/filter-types"; -import { FiltersForm } from "../../../form-filters/components"; -import InternalAlert from "../../../internal-alert"; - -import actions from "./actions"; -import UsersList from "./container"; -import CustomToolbar from "./components/custom-toolbar"; - -describe("", () => { - let component; - - beforeEach(() => { - const initialState = fromJS({ - records: { - users: { - data: [ - { - id: "1", - user_name: "Jose" - }, - { - id: "2", - user_name: "Carlos" - } - ], - metadata: { total: 2, per: 20, page: 1, total_enabled: 38 } - } - }, - user: { - permissions: { - users: [ACTIONS.MANAGE] - } - }, - application: { - systemOptions: { - maximum_users: 40 - } - } - }); - - ({ component } = setupMountedComponent(UsersList, {}, initialState, ["/admin/users"])); - }); - - it("renders record list table", () => { - expect(component.find(IndexTable)).to.have.length(1); - }); - - it("renders FiltersForm", () => { - expect(component.find(FiltersForm)).to.have.length(1); - }); - - it("submits the filters with the correct data", async () => { - await component.find(FiltersForm).find("form").props().onSubmit(); - const setFiltersAction = last( - component - .props() - .store.getActions() - .filter(action => action.type === actions.SET_USERS_FILTER) - ); - - expect(setFiltersAction.payload).to.have.property("data"); - }); - - it("renders ToggleFilter", () => { - expect(component.find(ToggleFilter)).to.have.length(1); - }); - - it("renders FormFilters", () => { - expect(component.find(SelectFilter)).to.have.length(1); - }); - - it("renders CustomToolbar as label", () => { - expect(component.find(CustomToolbar)).to.have.length(1); - }); - - it("should NOT render warning to list user", () => { - expect(component.find(InternalAlert)).to.have.length(0); - }); - - context("When total_enabled User is at maximum permitted", () => { - let componentUserLimit; - - const stateUserLimitSet = fromJS({ - records: { - users: { - metadata: { total_enabled: 40 } - } - }, - application: { - systemOptions: { - maximum_users: 40 - } - } - }); - - beforeEach(() => { - ({ component: componentUserLimit } = setupMountedComponent(UsersList, {}, stateUserLimitSet, ["/admin/users"])); - }); - - it("renders warning to list user", () => { - expect(componentUserLimit.find(InternalAlert)).to.have.length(1); - }); - }); - - context("When maximumUsers User is null", () => { - let componentUserLimit; - - const stateUserLimitSet = fromJS({ - records: { - users: { - metadata: { total_enabled: 40 } - } - }, - application: { - systemOptions: { - maximum_users: null - } - } - }); - - beforeEach(() => { - ({ component: componentUserLimit } = setupMountedComponent(UsersList, {}, stateUserLimitSet, ["/admin/users"])); - }); - - it("should NOT render warning to list user", () => { - expect(componentUserLimit.find(InternalAlert)).to.have.length(0); - }); - }); -}); diff --git a/app/javascript/components/pages/dashboard/components/approvals/component.jsx b/app/javascript/components/pages/dashboard/components/approvals/component.jsx index f074837882..7e98bce948 100644 --- a/app/javascript/components/pages/dashboard/components/approvals/component.jsx +++ b/app/javascript/components/pages/dashboard/components/approvals/component.jsx @@ -32,7 +32,7 @@ import css from "../styles.css"; import { NAME } from "./constants"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const { approvalsLabels } = useApp(); @@ -162,7 +162,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/cases-by-social-worker/component.jsx b/app/javascript/components/pages/dashboard/components/cases-by-social-worker/component.jsx index b873207a33..04c4cb67c2 100644 --- a/app/javascript/components/pages/dashboard/components/cases-by-social-worker/component.jsx +++ b/app/javascript/components/pages/dashboard/components/cases-by-social-worker/component.jsx @@ -12,7 +12,7 @@ import { useMemoizedSelector } from "../../../../../libs"; import { NAME } from "./constants"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const data = useMemoizedSelector(state => getCasesBySocialWorker(state)); @@ -32,7 +32,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/cases-to-assign/component.jsx b/app/javascript/components/pages/dashboard/components/cases-to-assign/component.jsx index 680dc7b665..4e40840d82 100644 --- a/app/javascript/components/pages/dashboard/components/cases-to-assign/component.jsx +++ b/app/javascript/components/pages/dashboard/components/cases-to-assign/component.jsx @@ -14,7 +14,7 @@ import useOptions from "../../../../form/use-options"; import { NAME } from "./constants"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const casesToAssign = useMemoizedSelector(state => getCasesToAssign(state)); const options = useOptions({ source: LOOKUPS.risk_level }); @@ -34,7 +34,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/flags/component.jsx b/app/javascript/components/pages/dashboard/components/flags/component.jsx index 31b07b126d..df824f2164 100644 --- a/app/javascript/components/pages/dashboard/components/flags/component.jsx +++ b/app/javascript/components/pages/dashboard/components/flags/component.jsx @@ -16,7 +16,7 @@ import { useMemoizedSelector } from "../../../../../libs"; import css from "./styles.css"; import { NAME } from "./constants"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const flags = useMemoizedSelector(state => getDashboardFlags(state)); @@ -47,7 +47,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/flags/component.unit.test.js b/app/javascript/components/pages/dashboard/components/flags/component.spec.js similarity index 74% rename from app/javascript/components/pages/dashboard/components/flags/component.unit.test.js rename to app/javascript/components/pages/dashboard/components/flags/component.spec.js index 39305346dd..a6b0cec183 100644 --- a/app/javascript/components/pages/dashboard/components/flags/component.unit.test.js +++ b/app/javascript/components/pages/dashboard/components/flags/component.spec.js @@ -1,17 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../../../../test"; import { ACTIONS } from "../../../../permissions"; -import { FlagBox, OptionsBox } from "../../../../dashboard"; -import LoadingIndicator from "../../../../loading-indicator"; -import ActionButton from "../../../../action-button"; import Flags from "./component"; describe(" - pages/dashboard/components/flags", () => { - let component; const permissions = { cases: [ACTIONS.MANAGE], dashboards: [ACTIONS.DASH_FLAGS] @@ -52,19 +48,19 @@ describe(" - pages/dashboard/components/flags", () => { }); beforeEach(() => { - ({ component } = setupMountedComponent(Flags, {}, state)); + mountedComponent(, state); }); it("should render an component", () => { - expect(component.find(OptionsBox)).to.have.lengthOf(1); + expect(screen.getByTestId("option-box")).toBeInTheDocument(); }); it("should render a component", () => { - expect(component.find(FlagBox)).to.have.lengthOf(1); + expect(screen.getByText("dashboard.flagged_cases")).toBeInTheDocument(); }); it("should render a component", () => { - expect(component.find(ActionButton)).to.have.lengthOf(1); + expect(screen.getByText("dashboard.link_see_all (1)")).toBeInTheDocument(); }); describe("when the data is loading", () => { @@ -79,7 +75,7 @@ describe(" - pages/dashboard/components/flags", () => { }; it("renders a ", () => { - const { component: loadingComponent } = setupMountedComponent(Flags, props, { + mountedComponent(, { records: { dashboard: { flags: { data: [], loading: true } @@ -90,7 +86,7 @@ describe(" - pages/dashboard/components/flags", () => { } }); - expect(loadingComponent.find(LoadingIndicator)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/pages/dashboard/components/overdue-tasks/component.jsx b/app/javascript/components/pages/dashboard/components/overdue-tasks/component.jsx index 77a59f471a..e95eb59a19 100644 --- a/app/javascript/components/pages/dashboard/components/overdue-tasks/component.jsx +++ b/app/javascript/components/pages/dashboard/components/overdue-tasks/component.jsx @@ -17,7 +17,7 @@ import { useMemoizedSelector } from "../../../../../libs"; import { NAME } from "./constants"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const casesByTaskOverdueAssessment = useMemoizedSelector(state => getCasesByTaskOverdueAssessment(state)); @@ -63,7 +63,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/overdue-tasks/component.unit.test.js b/app/javascript/components/pages/dashboard/components/overdue-tasks/component.spec.js similarity index 72% rename from app/javascript/components/pages/dashboard/components/overdue-tasks/component.unit.test.js rename to app/javascript/components/pages/dashboard/components/overdue-tasks/component.spec.js index 9f4c249140..60f7f3b12a 100644 --- a/app/javascript/components/pages/dashboard/components/overdue-tasks/component.unit.test.js +++ b/app/javascript/components/pages/dashboard/components/overdue-tasks/component.spec.js @@ -1,19 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { TableHead, TableCell } from "@material-ui/core"; -import { setupMountedComponent } from "../../../../../test"; +import { mountedComponent, screen } from "../../../../../test-utils"; import { ACTIONS } from "../../../../permissions"; -import DashboardTable from "../../../../dashboard/dashboard-table"; -import LoadingIndicator from "../../../../loading-indicator"; import OverdueTasks from "./component"; describe(" - pages/dashboard/components/overdue-tasks", () => { - let component; - let tableCells; - const permissions = { dashboards: [ ACTIONS.DASH_CASES_BY_TASK_OVERDUE_ASSESSMENT, @@ -82,37 +76,39 @@ describe(" - pages/dashboard/components/overdue-tasks", () => { } }); - beforeEach(() => { - ({ component } = setupMountedComponent(OverdueTasks, {}, state)); - tableCells = component.find(DashboardTable).find(TableHead).find(TableCell); - }); - it("should render a component", () => { - expect(component.find(DashboardTable)).to.have.lengthOf(1); + mountedComponent(, state); + expect(screen.getByTestId("dashboard-table")).toBeInTheDocument(); }); it("should render 5 columns", () => { - expect(tableCells).to.have.lengthOf(5); + mountedComponent(, state); + expect(screen.getAllByRole("cell")).toHaveLength(5); }); it("should render case_worker column", () => { - expect(tableCells.at(0).text()).to.equal("dashboard.case_worker"); + mountedComponent(, state); + expect(screen.getAllByText("dashboard.case_worker")).toHaveLength(2); }); it("should render assessment column", () => { - expect(tableCells.at(1).text()).to.equal("dashboard.assessment"); + mountedComponent(, state); + expect(screen.getAllByText("dashboard.assessment")).toHaveLength(2); }); it("should render case_plan column", () => { - expect(tableCells.at(2).text()).to.equal("dashboard.case_plan"); + mountedComponent(, state); + expect(screen.getAllByText("dashboard.case_plan")).toHaveLength(2); }); it("should render services column", () => { - expect(tableCells.at(3).text()).to.equal("dashboard.services"); + mountedComponent(, state); + expect(screen.getAllByText("dashboard.services")).toHaveLength(2); }); it("should render follow_up column", () => { - expect(tableCells.at(4).text()).to.equal("dashboard.follow_up"); + mountedComponent(, state); + expect(screen.getAllByText("dashboard.follow_up")).toHaveLength(2); }); describe("when the data is loading", () => { @@ -126,7 +122,7 @@ describe(" - pages/dashboard/components/overdue-tasks", () => { }; it("renders a ", () => { - const { component: loadingComponent } = setupMountedComponent(OverdueTasks, props, { + mountedComponent(, { records: { dashboard: { data: [], @@ -137,8 +133,7 @@ describe(" - pages/dashboard/components/overdue-tasks", () => { permissions } }); - - expect(loadingComponent.find(LoadingIndicator)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/pages/dashboard/components/overview/component.jsx b/app/javascript/components/pages/dashboard/components/overview/component.jsx index 4e63c554b2..22918fa9bf 100644 --- a/app/javascript/components/pages/dashboard/components/overview/component.jsx +++ b/app/javascript/components/pages/dashboard/components/overview/component.jsx @@ -24,7 +24,7 @@ import css from "../styles.css"; import { NAME } from "./constants"; -const Component = ({ loadingIndicator, userPermissions }) => { +function Component({ loadingIndicator, userPermissions }) { const i18n = useI18n(); const casesByAssessmentLevel = useMemoizedSelector(state => getCasesByAssessmentLevel(state)); @@ -148,7 +148,7 @@ const Component = ({ loadingIndicator, userPermissions }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/overview/component.unit.test.js b/app/javascript/components/pages/dashboard/components/overview/component.spec.js similarity index 77% rename from app/javascript/components/pages/dashboard/components/overview/component.unit.test.js rename to app/javascript/components/pages/dashboard/components/overview/component.spec.js index 014f7bf1dd..fa8f5f2aba 100644 --- a/app/javascript/components/pages/dashboard/components/overview/component.unit.test.js +++ b/app/javascript/components/pages/dashboard/components/overview/component.spec.js @@ -1,17 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../../../../test"; import { ACTIONS } from "../../../../permissions"; -import { OptionsBox, OverviewBox } from "../../../../dashboard"; -import LoadingIndicator from "../../../../loading-indicator"; import Overview from "./component"; describe(" - pages/dashboard/components/overview", () => { - let component; - const permissions = fromJS({ dashboards: [ ACTIONS.DASH_SHARED_WITH_ME, @@ -103,39 +99,31 @@ describe(" - pages/dashboard/components/overview", () => { }; beforeEach(() => { - ({ component } = setupMountedComponent(Overview, props, state)); + mountedComponent(, state); }); it("should render a component", () => { - expect(component.find(OptionsBox)).to.have.lengthOf(5); + expect(screen.getAllByTestId("option-box")).toHaveLength(5); }); it("should render a component", () => { - expect(component.find(OverviewBox)).to.have.lengthOf(4); + expect(screen.getAllByTestId("overview-box")).toHaveLength(4); }); it("renders the dash_group_overview dashboard", () => { - const groupOverview = component.find(OverviewBox).at(0); - - expect(groupOverview.text()).to.contain("dashboard.dash_group_overview"); + expect(screen.getByText("dashboard.dash_group_overview")).toBeInTheDocument(); }); it("renders the case_overview dashboard", () => { - const caseOverview = component.find(OverviewBox).at(1); - - expect(caseOverview.text()).to.contain("dashboard.case_overview"); + expect(screen.getByText("dashboard.case_overview")).toBeInTheDocument(); }); it("renders the shared_with_me dashboard", () => { - const sharedWithMe = component.find(OverviewBox).at(2); - - expect(sharedWithMe.text()).to.contain("dashboard.dash_shared_with_me"); + expect(screen.getByText("dashboard.dash_shared_with_me")).toBeInTheDocument(); }); it("renders the dash_shared_with_others dashboard", () => { - const sharedWithOthers = component.find(OverviewBox).at(3); - - expect(sharedWithOthers.text()).to.contain("dashboard.dash_shared_with_others"); + expect(screen.getByText("dashboard.dash_shared_with_others")).toBeInTheDocument(); }); describe("when the data is loading", () => { @@ -150,7 +138,7 @@ describe(" - pages/dashboard/components/overview", () => { }; it("renders a ", () => { - const { component: loadingComponent } = setupMountedComponent(Overview, loadingProps, { + mountedComponent(, { records: { dashboard: { data: [], @@ -162,7 +150,7 @@ describe(" - pages/dashboard/components/overview", () => { } }); - expect(loadingComponent.find(LoadingIndicator)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/pages/dashboard/components/perpetrator-armed-force-group-party-names/component.jsx b/app/javascript/components/pages/dashboard/components/perpetrator-armed-force-group-party-names/component.jsx index ff787617ff..8ed9a80ce3 100644 --- a/app/javascript/components/pages/dashboard/components/perpetrator-armed-force-group-party-names/component.jsx +++ b/app/javascript/components/pages/dashboard/components/perpetrator-armed-force-group-party-names/component.jsx @@ -14,7 +14,7 @@ import { INDICATOR_NAMES } from "../../constants"; import { NAME } from "./constants"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const armedForceGroupOrOtherParty = useOptions({ source: LOOKUPS.armed_force_group_or_other_party }); @@ -43,7 +43,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/protection-concern/component.jsx b/app/javascript/components/pages/dashboard/components/protection-concern/component.jsx index 8eae7dacd0..ae1ec13440 100644 --- a/app/javascript/components/pages/dashboard/components/protection-concern/component.jsx +++ b/app/javascript/components/pages/dashboard/components/protection-concern/component.jsx @@ -13,7 +13,7 @@ import { useMemoizedSelector } from "../../../../../libs"; import { NAME } from "./constants"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const protectionConcerns = useMemoizedSelector(state => getProtectionConcerns(state)); @@ -36,7 +36,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/protection-concern/component.unit.test.js b/app/javascript/components/pages/dashboard/components/protection-concern/component.spec.js similarity index 71% rename from app/javascript/components/pages/dashboard/components/protection-concern/component.unit.test.js rename to app/javascript/components/pages/dashboard/components/protection-concern/component.spec.js index fb100550a2..742ff6f362 100644 --- a/app/javascript/components/pages/dashboard/components/protection-concern/component.unit.test.js +++ b/app/javascript/components/pages/dashboard/components/protection-concern/component.spec.js @@ -1,17 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { TableRow, TableBody } from "@material-ui/core"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../../../../test"; import { ACTIONS } from "../../../../permissions"; -import { DashboardTable, OptionsBox } from "../../../../dashboard"; -import LoadingIndicator from "../../../../loading-indicator"; import ProtectionConcern from "./component"; describe(" - pages/dashboard/components/protection-concern", () => { - let component; const permissions = { dashboards: [ACTIONS.DASH_PROTECTION_CONCERNS] }; @@ -59,17 +55,15 @@ describe(" - pages/dashboard/components/protection-concern", }); beforeEach(() => { - ({ component } = setupMountedComponent(ProtectionConcern, {}, state)); + mountedComponent(, state); }); it("should render an component", () => { - expect(component.find(OptionsBox)).to.have.lengthOf(1); + expect(screen.getByTestId("option-box")).toBeInTheDocument(); }); it("should render a component", () => { - expect(component.find(DashboardTable)).to.have.lengthOf(1); - expect(component.find(TableBody)).to.have.lengthOf(1); - expect(component.find(TableBody).find(TableRow)).to.have.lengthOf(1); + expect(screen.getByRole("grid")).toBeInTheDocument(); }); describe("when the data is loading", () => { @@ -83,7 +77,7 @@ describe(" - pages/dashboard/components/protection-concern", }; it("renders a ", () => { - const { component: loadingComponent } = setupMountedComponent(ProtectionConcern, props, { + mountedComponent(, { records: { dashboard: { data: [], @@ -95,7 +89,7 @@ describe(" - pages/dashboard/components/protection-concern", } }); - expect(loadingComponent.find(LoadingIndicator)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/pages/dashboard/components/reporting-location/component.jsx b/app/javascript/components/pages/dashboard/components/reporting-location/component.jsx index 295fc0b627..952e0c1b42 100644 --- a/app/javascript/components/pages/dashboard/components/reporting-location/component.jsx +++ b/app/javascript/components/pages/dashboard/components/reporting-location/component.jsx @@ -14,7 +14,7 @@ import { useMemoizedSelector } from "../../../../../libs"; import { NAME } from "./constants"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const locations = useMemoizedSelector(state => getLocations(state)); @@ -32,7 +32,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/reporting-location/component.unit.test.js b/app/javascript/components/pages/dashboard/components/reporting-location/component.spec.js similarity index 83% rename from app/javascript/components/pages/dashboard/components/reporting-location/component.unit.test.js rename to app/javascript/components/pages/dashboard/components/reporting-location/component.spec.js index d30c5b6e74..82999b8b6b 100644 --- a/app/javascript/components/pages/dashboard/components/reporting-location/component.unit.test.js +++ b/app/javascript/components/pages/dashboard/components/reporting-location/component.spec.js @@ -1,17 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { TableRow, TableBody } from "@material-ui/core"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../../../../test"; import { ACTIONS } from "../../../../permissions"; -import { DashboardTable, OptionsBox } from "../../../../dashboard"; -import LoadingIndicator from "../../../../loading-indicator"; import ReportingLocation from "./component"; describe(" - pages/dashboard/components/reporting-location", () => { - let component; const permissions = { dashboards: [ACTIONS.DASH_REPORTING_LOCATION] }; @@ -91,17 +87,15 @@ describe(" - pages/dashboard/components/reporting-location", }); beforeEach(() => { - ({ component } = setupMountedComponent(ReportingLocation, {}, state)); + mountedComponent(, state); }); it("should render an component", () => { - expect(component.find(OptionsBox)).to.have.lengthOf(1); + expect(screen.getByTestId("option-box")).toBeInTheDocument(); }); it("should render a component", () => { - expect( - component.find({ title: "cases.label" }).find(DashboardTable).find(TableBody).find(TableRow) - ).to.have.lengthOf(1); + expect(screen.getByRole("grid")).toBeInTheDocument(); }); describe("when the data is loading", () => { @@ -115,7 +109,7 @@ describe(" - pages/dashboard/components/reporting-location", }; it("renders a ", () => { - const { component: loadingComponent } = setupMountedComponent(ReportingLocation, props, { + mountedComponent(, { records: { dashboard: { data: [], @@ -133,7 +127,7 @@ describe(" - pages/dashboard/components/reporting-location", } }); - expect(loadingComponent.find(LoadingIndicator)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/pages/dashboard/components/shared-from-my-team/component.jsx b/app/javascript/components/pages/dashboard/components/shared-from-my-team/component.jsx index 6be85a35a6..6896c2b3ed 100644 --- a/app/javascript/components/pages/dashboard/components/shared-from-my-team/component.jsx +++ b/app/javascript/components/pages/dashboard/components/shared-from-my-team/component.jsx @@ -12,7 +12,7 @@ import { useMemoizedSelector } from "../../../../../libs"; import { NAME } from "./constants"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const sharedFromMyTeam = useMemoizedSelector(state => getSharedFromMyTeam(state)); @@ -36,7 +36,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/shared-from-my-team/component.unit.test.js b/app/javascript/components/pages/dashboard/components/shared-from-my-team/component.spec.js similarity index 62% rename from app/javascript/components/pages/dashboard/components/shared-from-my-team/component.unit.test.js rename to app/javascript/components/pages/dashboard/components/shared-from-my-team/component.spec.js index 533d0dbb39..cd1d8f6319 100644 --- a/app/javascript/components/pages/dashboard/components/shared-from-my-team/component.unit.test.js +++ b/app/javascript/components/pages/dashboard/components/shared-from-my-team/component.spec.js @@ -1,19 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { TableHead, TableCell } from "@material-ui/core"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../../../../test"; import { ACTIONS } from "../../../../permissions"; -import DashboardTable from "../../../../dashboard/dashboard-table"; -import LoadingIndicator from "../../../../loading-indicator"; import SharedFromMyTeam from "./component"; describe(" - pages/dashboard/components/shared-from-my-team", () => { - let component; - let tableCells; - const permissions = { dashboards: [ACTIONS.DASH_SHARED_FROM_MY_TEAM] }; @@ -45,32 +39,27 @@ describe(" - pages/dashboard/components/shared-from-my-team", }); beforeEach(() => { - ({ component } = setupMountedComponent(SharedFromMyTeam, {}, state)); - tableCells = component.find(DashboardTable).find(TableHead).find(TableCell); + mountedComponent(, state); }); it("should render a component", () => { - expect(component.find(DashboardTable)).to.have.lengthOf(1); - }); - - it("should render 4 columns", () => { - expect(tableCells).to.have.lengthOf(4); + expect(screen.getByRole("grid")).toBeInTheDocument(); }); it("should render case_worker column", () => { - expect(tableCells.at(0).text()).to.equal("dashboard.case_worker"); + expect(screen.getAllByText("dashboard.case_worker")).toBeTruthy(); }); it("should render shared_from_my_team_referrals column", () => { - expect(tableCells.at(1).text()).to.equal("dashboard.shared_from_my_team_referrals"); + expect(screen.getAllByText("dashboard.shared_from_my_team_referrals")).toBeTruthy(); }); it("should render shared_from_my_team_pending_transfers column", () => { - expect(tableCells.at(2).text()).to.equal("dashboard.shared_from_my_team_pending_transfers"); + expect(screen.getAllByText("dashboard.shared_from_my_team_pending_transfers")).toBeTruthy(); }); it("should render shared_from_my_team_rejected_transfers column", () => { - expect(tableCells.at(3).text()).to.equal("dashboard.shared_from_my_team_rejected_transfers"); + expect(screen.getAllByText("dashboard.shared_from_my_team_rejected_transfers")).toBeTruthy(); }); describe("when the data is loading", () => { @@ -84,7 +73,7 @@ describe(" - pages/dashboard/components/shared-from-my-team", }; it("renders a ", () => { - const { component: loadingComponent } = setupMountedComponent(SharedFromMyTeam, props, { + mountedComponent(, { records: { dashboard: { data: [], @@ -96,7 +85,7 @@ describe(" - pages/dashboard/components/shared-from-my-team", } }); - expect(loadingComponent.find(LoadingIndicator)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/pages/dashboard/components/shared-with-my-team/component.jsx b/app/javascript/components/pages/dashboard/components/shared-with-my-team/component.jsx index 94bee7cf3c..8de9300d1b 100644 --- a/app/javascript/components/pages/dashboard/components/shared-with-my-team/component.jsx +++ b/app/javascript/components/pages/dashboard/components/shared-with-my-team/component.jsx @@ -7,12 +7,12 @@ import { useI18n } from "../../../../i18n"; import { teamSharingTable } from "../../utils"; import Permission, { RESOURCES, ACTIONS } from "../../../../permissions"; import { OptionsBox, DashboardTable } from "../../../../dashboard"; -import { ROUTES } from "../../../../../config/constants"; +import { ROUTES } from "../../../../../config"; import { useMemoizedSelector } from "../../../../../libs"; import { NAME } from "./constants"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const sharedWithMyTeam = useMemoizedSelector(state => getSharedWithMyTeam(state)); @@ -36,7 +36,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/shared-with-my-team/component.unit.test.js b/app/javascript/components/pages/dashboard/components/shared-with-my-team/component.spec.js similarity index 62% rename from app/javascript/components/pages/dashboard/components/shared-with-my-team/component.unit.test.js rename to app/javascript/components/pages/dashboard/components/shared-with-my-team/component.spec.js index c4170277d7..d00bacd338 100644 --- a/app/javascript/components/pages/dashboard/components/shared-with-my-team/component.unit.test.js +++ b/app/javascript/components/pages/dashboard/components/shared-with-my-team/component.spec.js @@ -1,19 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { TableHead, TableCell } from "@material-ui/core"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../../../../test"; import { ACTIONS } from "../../../../permissions"; -import DashboardTable from "../../../../dashboard/dashboard-table"; -import LoadingIndicator from "../../../../loading-indicator"; import SharedWithMyTeam from "./component"; describe(" - pages/dashboard/components/shared-with-my-team", () => { - let component; - let tableCells; - const permissions = { dashboards: [ACTIONS.DASH_SHARED_WITH_MY_TEAM] }; @@ -44,28 +38,23 @@ describe(" - pages/dashboard/components/shared-with-my-team", }); beforeEach(() => { - ({ component } = setupMountedComponent(SharedWithMyTeam, {}, state)); - tableCells = component.find(DashboardTable).find(TableHead).find(TableCell); + mountedComponent(, state); }); it("should render a component", () => { - expect(component.find(DashboardTable)).to.have.lengthOf(1); - }); - - it("should render 3 columns", () => { - expect(tableCells).to.have.lengthOf(3); + expect(screen.getByRole("grid")).toBeInTheDocument(); }); it("should render case_worker column", () => { - expect(tableCells.at(0).text()).to.equal("dashboard.case_worker"); + expect(screen.getAllByText("dashboard.case_worker")[0]).toBeInTheDocument(); }); it("should render shared_with_my_team_referrals column", () => { - expect(tableCells.at(1).text()).to.equal("dashboard.shared_with_my_team_referrals"); + expect(screen.getAllByText("dashboard.shared_with_my_team_referrals")[1]).toBeInTheDocument(); }); it("should render shared_with_my_team_pending_transfers column", () => { - expect(tableCells.at(2).text()).to.equal("dashboard.shared_with_my_team_pending_transfers"); + expect(screen.getAllByText("dashboard.shared_with_my_team_pending_transfers")[1]).toBeInTheDocument(); }); describe("when the data is loading", () => { @@ -79,7 +68,7 @@ describe(" - pages/dashboard/components/shared-with-my-team", }; it("renders a ", () => { - const { component: loadingComponent } = setupMountedComponent(SharedWithMyTeam, props, { + mountedComponent(, { records: { dashboard: { data: [], @@ -91,7 +80,7 @@ describe(" - pages/dashboard/components/shared-with-my-team", } }); - expect(loadingComponent.find(LoadingIndicator)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/pages/dashboard/components/styles.css b/app/javascript/components/pages/dashboard/components/styles.css index 13b67be36b..ada7ef4fc6 100644 --- a/app/javascript/components/pages/dashboard/components/styles.css +++ b/app/javascript/components/pages/dashboard/components/styles.css @@ -4,13 +4,13 @@ display: flex; padding: var(--sp-2); gap: var(--sp-2); - + & > div:not(.divider) { flex: 1; } } -@media (max-width:959.95px) { +@media (max-width:900px) { .container { display: grid; } diff --git a/app/javascript/components/pages/dashboard/components/violations-category-region/component.jsx b/app/javascript/components/pages/dashboard/components/violations-category-region/component.jsx index 304d022840..d1a5e209c5 100644 --- a/app/javascript/components/pages/dashboard/components/violations-category-region/component.jsx +++ b/app/javascript/components/pages/dashboard/components/violations-category-region/component.jsx @@ -15,7 +15,7 @@ import { OPTION_TYPES } from "../../../../form"; import { NAME } from "./constants"; import { getVerifiedData } from "./utils"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const { violationTypes, reportingLocations } = useOptions({ @@ -45,7 +45,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/violations-category-region/component.unit.test.js b/app/javascript/components/pages/dashboard/components/violations-category-region/component.spec.js similarity index 81% rename from app/javascript/components/pages/dashboard/components/violations-category-region/component.unit.test.js rename to app/javascript/components/pages/dashboard/components/violations-category-region/component.spec.js index b381d62534..6e71e47c45 100644 --- a/app/javascript/components/pages/dashboard/components/violations-category-region/component.unit.test.js +++ b/app/javascript/components/pages/dashboard/components/violations-category-region/component.spec.js @@ -1,17 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { TableHead, TableCell } from "@material-ui/core"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../../../../test"; import { ACTIONS } from "../../../../permissions"; -import DashboardTable from "../../../../dashboard/dashboard-table"; -import LoadingIndicator from "../../../../loading-indicator"; import ViolationsCategoryRegion from "./component"; describe(" - pages/dashboard/components/violations-category-region", () => { - let component; let tableCells; const permissions = { @@ -106,24 +102,23 @@ describe(" - pages/dashboard/components/violations-cat }); beforeEach(() => { - ({ component } = setupMountedComponent(ViolationsCategoryRegion, {}, state)); - tableCells = component.find(DashboardTable).find(TableHead).find(TableCell); + mountedComponent(, state); }); it("should render a component", () => { - expect(component.find(DashboardTable)).to.have.lengthOf(1); + expect(screen.getByRole("grid")).toBeInTheDocument(); }); - it("should render 3 columns", () => { + xit("should render 3 columns", () => { expect(tableCells).to.have.lengthOf(3); }); it("should render Killing column", () => { - expect(tableCells.at(1).text()).to.equal("Killing"); + expect(screen.getAllByText("Killing")).toBeTruthy(); }); it("should render Maiming column", () => { - expect(tableCells.at(2).text()).to.equal("Maiming"); + expect(screen.getAllByText("Maiming")).toBeTruthy(); }); describe("when the data is loading", () => { @@ -137,7 +132,7 @@ describe(" - pages/dashboard/components/violations-cat }; it("renders a ", () => { - const { component: loadingComponent } = setupMountedComponent(ViolationsCategoryRegion, props, { + mountedComponent(, { records: { dashboard: { data: [], @@ -149,7 +144,7 @@ describe(" - pages/dashboard/components/violations-cat } }); - expect(loadingComponent.find(LoadingIndicator)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/pages/dashboard/components/violations-category-verification-status/component.jsx b/app/javascript/components/pages/dashboard/components/violations-category-verification-status/component.jsx index 8544b63813..c07abc8f19 100644 --- a/app/javascript/components/pages/dashboard/components/violations-category-verification-status/component.jsx +++ b/app/javascript/components/pages/dashboard/components/violations-category-verification-status/component.jsx @@ -14,7 +14,7 @@ import { useMemoizedSelector } from "../../../../../libs"; import { NAME } from "./constants"; import { transformToPivotedDashboard } from "./utils"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const { verificationStatus, violationType } = useOptions({ @@ -45,7 +45,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/violations-category-verification-status/component.unit.test.js b/app/javascript/components/pages/dashboard/components/violations-category-verification-status/component.spec.js similarity index 79% rename from app/javascript/components/pages/dashboard/components/violations-category-verification-status/component.unit.test.js rename to app/javascript/components/pages/dashboard/components/violations-category-verification-status/component.spec.js index ad21b0a50d..e52ac30c27 100644 --- a/app/javascript/components/pages/dashboard/components/violations-category-verification-status/component.unit.test.js +++ b/app/javascript/components/pages/dashboard/components/violations-category-verification-status/component.spec.js @@ -1,19 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { TableHead, TableCell } from "@material-ui/core"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../../../../test"; import { ACTIONS } from "../../../../permissions"; -import DashboardTable from "../../../../dashboard/dashboard-table"; -import LoadingIndicator from "../../../../loading-indicator"; import ViolationsCategoryVerificationStatus from "./component"; describe(" - pages/dashboard/components/violations-category-verification-status", () => { - let component; - let tableCells; - const permissions = { dashboards: [ACTIONS.DASH_VIOLATIONS_CATEGORY_VERIFICATION_STATUS] }; @@ -98,24 +92,23 @@ describe(" - pages/dashboard/components/violations-category-v }); beforeEach(() => { - ({ component } = setupMountedComponent(ViolationsCategoryVerificationStatus, {}, state)); - tableCells = component.find(DashboardTable).find(TableHead).find(TableCell); + mountedComponent(, state); }); it("should render a component", () => { - expect(component.find(DashboardTable)).to.have.lengthOf(1); + expect(screen.getByRole("grid")).toBeInTheDocument(); }); it("should render 3 columns", () => { - expect(tableCells).to.have.lengthOf(3); + expect(document.querySelectorAll("th")).toHaveLength(3); }); it("should render Verified column", () => { - expect(tableCells.at(1).text()).to.equal("Verified"); + expect(screen.getAllByText("Verified")).toBeTruthy(); }); it("should render Report Pending Verification column", () => { - expect(tableCells.at(2).text()).to.equal("Report Pending Verification"); + expect(screen.getAllByText("Report Pending Verification")).toBeTruthy(); }); describe("when the data is loading", () => { @@ -129,7 +122,7 @@ describe(" - pages/dashboard/components/violations-category-v }; it("renders a ", () => { - const { component: loadingComponent } = setupMountedComponent(ViolationsCategoryVerificationStatus, props, { + mountedComponent(, { records: { dashboard: { data: [], @@ -141,7 +134,7 @@ describe(" - pages/dashboard/components/violations-category-v } }); - expect(loadingComponent.find(LoadingIndicator)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/pages/dashboard/components/workflow-individual-cases/component.jsx b/app/javascript/components/pages/dashboard/components/workflow-individual-cases/component.jsx index b5e1538eaa..fa43c877a4 100644 --- a/app/javascript/components/pages/dashboard/components/workflow-individual-cases/component.jsx +++ b/app/javascript/components/pages/dashboard/components/workflow-individual-cases/component.jsx @@ -14,7 +14,7 @@ import css from "../styles.css"; import { NAME, CLOSED } from "./constants"; import WorkFlowStep from "./components"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const workflowLabels = useMemoizedSelector(state => getWorkflowLabels(state, MODULES.CP, RECORD_TYPES.cases)); @@ -33,7 +33,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/workflow-individual-cases/component.unit.test.js b/app/javascript/components/pages/dashboard/components/workflow-individual-cases/component.spec.js similarity index 81% rename from app/javascript/components/pages/dashboard/components/workflow-individual-cases/component.unit.test.js rename to app/javascript/components/pages/dashboard/components/workflow-individual-cases/component.spec.js index b0fb3e4420..ae090dd750 100644 --- a/app/javascript/components/pages/dashboard/components/workflow-individual-cases/component.unit.test.js +++ b/app/javascript/components/pages/dashboard/components/workflow-individual-cases/component.spec.js @@ -1,18 +1,15 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../../../../test"; import { ACTIONS } from "../../../../permissions"; -import { OptionsBox } from "../../../../dashboard"; -import LoadingIndicator from "../../../../loading-indicator"; import { PrimeroModuleRecord } from "../../../../application/records"; import { MODULES } from "../../../../../config"; import WorkflowIndividualCases from "./component"; describe(" - pages/dashboard/components/workflow-individual-cases", () => { - let component; const permissions = { dashboards: [ACTIONS.DASH_WORKFLOW] }; @@ -69,11 +66,11 @@ describe(" - pages/dashboard/components/workflow-indivi }); beforeEach(() => { - ({ component } = setupMountedComponent(WorkflowIndividualCases, {}, state)); + mountedComponent(, state); }); it("should render an component", () => { - expect(component.find(OptionsBox)).to.have.lengthOf(1); + expect(screen.getByTestId("option-box")).toBeInTheDocument(); }); describe("when the data is loading", () => { @@ -87,7 +84,7 @@ describe(" - pages/dashboard/components/workflow-indivi }; it("renders a ", () => { - const { component: loadingComponent } = setupMountedComponent(WorkflowIndividualCases, props, { + mountedComponent(, { records: { dashboard: { data: [], @@ -99,7 +96,7 @@ describe(" - pages/dashboard/components/workflow-indivi } }); - expect(loadingComponent.find(LoadingIndicator)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/pages/dashboard/components/workflow-individual-cases/components/workflow-step.jsx b/app/javascript/components/pages/dashboard/components/workflow-individual-cases/components/workflow-step.jsx index 355974a1bb..ac2d8342e0 100644 --- a/app/javascript/components/pages/dashboard/components/workflow-individual-cases/components/workflow-step.jsx +++ b/app/javascript/components/pages/dashboard/components/workflow-individual-cases/components/workflow-step.jsx @@ -14,7 +14,7 @@ import css from "../styles.css"; import { NAME } from "./constants"; -const WorkFlowStep = ({ step, casesWorkflow, i18n }) => { +function WorkFlowStep({ step = {}, casesWorkflow = fromJS({}), i18n }) { const dispatch = useDispatch(); const workflowData = casesWorkflow.getIn(["indicators", "workflow", step.id], fromJS({})); @@ -42,15 +42,10 @@ const WorkFlowStep = ({ step, casesWorkflow, i18n }) => { const chipType = count === 0 ? "defaultNoCount" : "default"; return ; -}; +} WorkFlowStep.displayName = NAME; -WorkFlowStep.defaultProps = { - casesWorkflow: fromJS({}), - step: {} -}; - WorkFlowStep.propTypes = { casesWorkflow: PropTypes.object, i18n: PropTypes.object, diff --git a/app/javascript/components/pages/dashboard/components/workflow-individual-cases/components/workflow-step.unit.test.js b/app/javascript/components/pages/dashboard/components/workflow-individual-cases/components/workflow-step.spec.js similarity index 69% rename from app/javascript/components/pages/dashboard/components/workflow-individual-cases/components/workflow-step.unit.test.js rename to app/javascript/components/pages/dashboard/components/workflow-individual-cases/components/workflow-step.spec.js index 2be6716630..cb3eca9c5a 100644 --- a/app/javascript/components/pages/dashboard/components/workflow-individual-cases/components/workflow-step.unit.test.js +++ b/app/javascript/components/pages/dashboard/components/workflow-individual-cases/components/workflow-step.spec.js @@ -1,14 +1,11 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../../../../test"; +import { mountedComponent, screen } from "test-utils"; import WorkFlowStep from "./workflow-step"; describe(" - pages/dashboard/components/workflow-individual-cases/components/workflow-step.jsx", () => { - let component; - const casesWorkflow = fromJS({ name: "dashboard.workflow", type: "indicator", @@ -32,17 +29,14 @@ describe(" - pages/dashboard/components/workflow-individual-cases/ }; beforeEach(() => { - ({ component } = setupMountedComponent(WorkFlowStep, props)); + mountedComponent(); }); it("should render a button component", () => { - expect(component.find("button")).to.have.lengthOf(1); + expect(screen.getByRole("button")).toBeInTheDocument(); }); it("should render a span component", () => { - const span = component.find("span"); - - expect(span.text()).to.be.equals("10"); - expect(span).to.have.lengthOf(1); + expect(screen.getByText("10")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/pages/dashboard/components/workflow-team-cases/component.jsx b/app/javascript/components/pages/dashboard/components/workflow-team-cases/component.jsx index 3642c62c4f..0552d3cf8e 100644 --- a/app/javascript/components/pages/dashboard/components/workflow-team-cases/component.jsx +++ b/app/javascript/components/pages/dashboard/components/workflow-team-cases/component.jsx @@ -13,7 +13,7 @@ import { useMemoizedSelector } from "../../../../../libs"; import { NAME } from "./constants"; -const Component = ({ loadingIndicator }) => { +function Component({ loadingIndicator }) { const i18n = useI18n(); const workflowLabels = useMemoizedSelector(state => getWorkflowLabels(state, MODULES.CP, RECORD_TYPES.cases)); @@ -34,7 +34,7 @@ const Component = ({ loadingIndicator }) => { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/components/workflow-team-cases/component.unit.test.js b/app/javascript/components/pages/dashboard/components/workflow-team-cases/component.spec.js similarity index 79% rename from app/javascript/components/pages/dashboard/components/workflow-team-cases/component.unit.test.js rename to app/javascript/components/pages/dashboard/components/workflow-team-cases/component.spec.js index e4d04e1513..03dc4f0893 100644 --- a/app/javascript/components/pages/dashboard/components/workflow-team-cases/component.unit.test.js +++ b/app/javascript/components/pages/dashboard/components/workflow-team-cases/component.spec.js @@ -1,20 +1,14 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { TableHead, TableCell } from "@material-ui/core"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../../../../test"; import { ACTIONS } from "../../../../permissions"; -import DashboardTable from "../../../../dashboard/dashboard-table"; -import LoadingIndicator from "../../../../loading-indicator"; import { PrimeroModuleRecord } from "../../../../application/records"; import WorkflowTeamCases from "./component"; describe(" - pages/dashboard/components/workflow-team-cases", () => { - let component; - let tableCells; - const permissions = { dashboards: [ACTIONS.DASH_WORKFLOW_TEAM] }; @@ -100,28 +94,27 @@ describe(" - pages/dashboard/components/workflow-team-cases", }); beforeEach(() => { - ({ component } = setupMountedComponent(WorkflowTeamCases, {}, state)); - tableCells = component.find(DashboardTable).find(TableHead).find(TableCell); + mountedComponent(, state); }); it("should render a component", () => { - expect(component.find(DashboardTable)).to.have.lengthOf(1); + expect(screen.getByRole("grid")).toBeInTheDocument(); }); it("should render 4 columns", () => { - expect(tableCells).to.have.lengthOf(4); + expect(document.querySelectorAll("th")).toHaveLength(4); }); it("should render New column", () => { - expect(tableCells.at(1).text()).to.equal("New"); + expect(screen.getAllByText("New")).toBeTruthy(); }); it("should render Case plan column", () => { - expect(tableCells.at(2).text()).to.equal("Case plan"); + expect(screen.getAllByText("Case plan")).toBeTruthy(); }); it("should render Response Type 1 column", () => { - expect(tableCells.at(3).text()).to.equal("Response Type 1"); + expect(screen.getAllByText("Response Type 1")).toBeTruthy(); }); describe("when the data is loading", () => { @@ -135,7 +128,7 @@ describe(" - pages/dashboard/components/workflow-team-cases", }; it("renders a ", () => { - const { component: loadingComponent } = setupMountedComponent(WorkflowTeamCases, props, { + mountedComponent(, { records: { dashboard: { data: [], @@ -147,7 +140,7 @@ describe(" - pages/dashboard/components/workflow-team-cases", } }); - expect(loadingComponent.find(LoadingIndicator)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/pages/dashboard/container.jsx b/app/javascript/components/pages/dashboard/container.jsx index 4cbf2a4469..4e19a0829f 100644 --- a/app/javascript/components/pages/dashboard/container.jsx +++ b/app/javascript/components/pages/dashboard/container.jsx @@ -2,7 +2,7 @@ import { useEffect } from "react"; import { useDispatch } from "react-redux"; -import { Grid } from "@material-ui/core"; +import { Grid } from "@mui/material"; import { useI18n } from "../../i18n"; import PageContainer, { PageHeading, PageContent } from "../../page"; @@ -34,7 +34,7 @@ import NAMESPACE from "./namespace"; import { NAME } from "./constants"; import { fetchDashboards, fetchFlags } from "./action-creators"; -const Dashboard = () => { +function Dashboard() { const i18n = useI18n(); const dispatch = useDispatch(); const canFetchFlags = usePermissions(RESOURCES.dashboards, [ACTIONS.DASH_FLAGS]); @@ -96,7 +96,7 @@ const Dashboard = () => { ); -}; +} Dashboard.displayName = NAME; diff --git a/app/javascript/components/pages/dashboard/container.spec.js b/app/javascript/components/pages/dashboard/container.spec.js new file mode 100644 index 0000000000..fae5bf6813 --- /dev/null +++ b/app/javascript/components/pages/dashboard/container.spec.js @@ -0,0 +1,83 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen } from "../../../test-utils"; +import { ACTIONS } from "../../permissions"; + +import Dashboard from "./container"; + +describe("", () => { + const initialState = fromJS({ + user: { + reportingLocationConfig: { + field_key: "owned_by_location", + admin_level: 2, + admin_level_map: { 1: ["province"], 2: ["district"] }, + label_keys: ["district"] + }, + permissions: { + dashboards: [ + ACTIONS.DASH_FLAGS, + ACTIONS.DASH_CASE_RISK, + ACTIONS.DASH_SHARED_FROM_MY_TEAM, + ACTIONS.DASH_CASES_BY_TASK_OVERDUE_ASSESSMENT, + ACTIONS.DASH_CASES_BY_TASK_OVERDUE_CASE_PLAN, + ACTIONS.DASH_CASES_BY_TASK_OVERDUE_SERVICES, + ACTIONS.DASH_CASES_BY_TASK_OVERDUE_FOLLOWUPS, + ACTIONS.DASH_APPROVALS_ASSESSMENT, + ACTIONS.DASH_WORKFLOW_TEAM, + ACTIONS.DASH_WORKFLOW, + ACTIONS.DASH_REPORTING_LOCATION, + ACTIONS.DASH_PROTECTION_CONCERNS + ] + } + } + }); + + beforeEach(() => { + mountedComponent(, initialState); + }); + + it("should render a component", () => { + expect(screen.getAllByTestId("page-heading")).toHaveLength(1); + }); + + it("should render a navigation title", () => { + expect(screen.getByText("navigation.home")).toBeInTheDocument(); + }); + + it("should render a component", () => { + expect(screen.getByTestId("page-heading")).toBeInTheDocument(); + }); + + it("should render a dashboard overview component", () => { + expect(screen.getByText(/dashboard.overview/i)).toBeInTheDocument(); + }); + + it("should render a component", () => { + expect(screen.queryAllByText(/dashboard.dash_shared_from_my_team/i)).toHaveLength(3); + }); + + it("should render a component", () => { + expect(screen.queryAllByText(/dashboard.workflow/i)).toHaveLength(4); + }); + + it("should render a component", () => { + expect(screen.getByText(/dashboard.approvals/i)).toBeInTheDocument(); + }); + + it("should render a component", () => { + expect(screen.getByText(/dashboard.cases_by_task_overdue/i, { selector: "h4" })).toBeInTheDocument(); + }); + + it("should render a component", () => { + expect(screen.queryAllByText(/dashboard.workflow_team/i)).toHaveLength(3); + }); + + it("should render a component", () => { + expect(screen.getByText(/dashboard.overview/i)).toBeInTheDocument(); + }); + + it("should render a component", () => { + expect(screen.queryAllByText(/dashboard.protection_concerns/i)).toHaveLength(3); + }); +}); diff --git a/app/javascript/components/pages/dashboard/container.unit.test.js b/app/javascript/components/pages/dashboard/container.unit.test.js deleted file mode 100644 index 7670b2425b..0000000000 --- a/app/javascript/components/pages/dashboard/container.unit.test.js +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../test"; -import PageContainer, { PageHeading, PageContent } from "../../page"; - -import { - Overview, - SharedFromMyTeam, - SharedWithMyTeam, - WorkflowIndividualCases, - Approvals, - OverdueTasks, - WorkflowTeamCases, - ReportingLocation, - ProtectionConcern -} from "./components"; -import Dashboard from "./container"; - -describe("", () => { - let component; - - const initialState = fromJS({ - user: { - reportingLocationConfig: { - field_key: "owned_by_location", - admin_level: 2, - admin_level_map: { 1: ["province"], 2: ["district"] }, - label_keys: ["district"] - } - } - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(Dashboard, {}, initialState)); - }); - - it("should render a component", () => { - expect(component.find(PageContainer)).to.have.lengthOf(1); - }); - it("should render a component", () => { - expect(component.find(PageHeading)).to.have.lengthOf(1); - }); - it("should render a component", () => { - expect(component.find(PageContent)).to.have.lengthOf(1); - }); - it("should render a component", () => { - expect(component.find(Overview)).to.have.lengthOf(1); - }); - it("should render a component", () => { - expect(component.find(SharedFromMyTeam)).to.have.lengthOf(1); - }); - it("should render a component", () => { - expect(component.find(SharedWithMyTeam)).to.have.lengthOf(1); - }); - it("should render a component", () => { - expect(component.find(WorkflowIndividualCases)).to.have.lengthOf(1); - }); - it("should render a component", () => { - expect(component.find(Approvals)).to.have.lengthOf(1); - }); - it("should render a component", () => { - expect(component.find(OverdueTasks)).to.have.lengthOf(1); - }); - it("should render a component", () => { - expect(component.find(WorkflowTeamCases)).to.have.lengthOf(1); - }); - it("should render a component", () => { - expect(component.find(ReportingLocation)).to.have.lengthOf(1); - }); - it("should render a component", () => { - expect(component.find(ProtectionConcern)).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/pages/dashboard/utils/default-body-render.js b/app/javascript/components/pages/dashboard/utils/default-body-render.js new file mode 100644 index 0000000000..5bf2567c3a --- /dev/null +++ b/app/javascript/components/pages/dashboard/utils/default-body-render.js @@ -0,0 +1 @@ +export default value => value || 0; diff --git a/app/javascript/components/pages/dashboard/utils/to-cases-by-social-worker-table.js b/app/javascript/components/pages/dashboard/utils/to-cases-by-social-worker-table.js index 84341ac22a..723f56df9a 100644 --- a/app/javascript/components/pages/dashboard/utils/to-cases-by-social-worker-table.js +++ b/app/javascript/components/pages/dashboard/utils/to-cases-by-social-worker-table.js @@ -20,7 +20,7 @@ export default (indicators, i18n) => { const data = sortBy( rows.map(row => { - const values = columnValues.map(column => newData.indicators[column][row]?.count); + const values = columnValues.map(column => newData.indicators[column][row]?.count || 0); return [row, ...values]; }), diff --git a/app/javascript/components/pages/dashboard/utils/to-cases-by-social-worker-table.unit.test.js b/app/javascript/components/pages/dashboard/utils/to-cases-by-social-worker-table.unit.test.js index 33883b52e0..85b90af269 100644 --- a/app/javascript/components/pages/dashboard/utils/to-cases-by-social-worker-table.unit.test.js +++ b/app/javascript/components/pages/dashboard/utils/to-cases-by-social-worker-table.unit.test.js @@ -48,7 +48,7 @@ describe("toCasesBySocialWorkerTable - pages/dashboard/utils/", () => { data: [ ["primero_admin_cp", 1, 0], ["primero_cp", 1, 0], - ["transfer_cp", 1, undefined] + ["transfer_cp", 1, 0] ], query: [ { @@ -123,4 +123,23 @@ describe("toCasesBySocialWorkerTable - pages/dashboard/utils/", () => { expect(tableData.data.map(elem => elem[0])).to.deep.equal(expected); expect(tableData.query.map(elem => elem.case_worker)).to.deep.equal(expected); }); + + it("shows 0 for non-existent values", () => { + const dashboardData = fromJS({ + name: "dashboard.dash_cases_by_social_worker", + type: "indicator", + indicators: { + cases_by_social_worker_total: { + primero_cp: { + count: 1, + query: ["record_state=true", "status=open", "owned_by=primero_cp"] + } + }, + cases_by_social_worker_new_or_updated: {} + } + }); + const tableData = toCasesBySocialWorkerTable(dashboardData, i18n); + + expect(tableData.data).to.deep.equal([["primero_cp", 1, 0]]); + }); }); diff --git a/app/javascript/components/pages/dashboard/utils/to-cases-to-assign-table.js b/app/javascript/components/pages/dashboard/utils/to-cases-to-assign-table.js index 05a4eaa9aa..10f2a28480 100644 --- a/app/javascript/components/pages/dashboard/utils/to-cases-to-assign-table.js +++ b/app/javascript/components/pages/dashboard/utils/to-cases-to-assign-table.js @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import Tooltip from "@material-ui/core/Tooltip"; +import Tooltip from "@mui/material/Tooltip"; import { RISK_LEVELS } from "../constants"; diff --git a/app/javascript/components/pages/dashboard/utils/to-list-table.js b/app/javascript/components/pages/dashboard/utils/to-list-table.js index 9f837d06c4..7418c2e57b 100644 --- a/app/javascript/components/pages/dashboard/utils/to-list-table.js +++ b/app/javascript/components/pages/dashboard/utils/to-list-table.js @@ -10,6 +10,8 @@ import sortBy from "lodash/sortBy"; import { dataToJS, displayNameHelper } from "../../../../libs"; +import defaultBodyRender from "./default-body-render"; + const translateSingleLabel = (key, data, locale) => { if (key === "") return key; @@ -41,7 +43,14 @@ export default (data, columnLabels, rowLabels, locale) => { const columns = [{ id: "", display_text: "" }, ...columnLabels] .reduce((acc, elem) => { if (columnKeys.includes(elem.id) || elem.id === "") { - return [...acc, { name: elem.id, label: translateSingleLabel(elem.id, columnLabels, locale) }]; + return [ + ...acc, + { + name: elem.id, + label: translateSingleLabel(elem.id, columnLabels, locale), + options: { customBodyRender: defaultBodyRender } + } + ]; } return acc; diff --git a/app/javascript/components/pages/dashboard/utils/to-list-table.unit.test.js b/app/javascript/components/pages/dashboard/utils/to-list-table.unit.test.js index 4749a426ce..5c9c8893d4 100644 --- a/app/javascript/components/pages/dashboard/utils/to-list-table.unit.test.js +++ b/app/javascript/components/pages/dashboard/utils/to-list-table.unit.test.js @@ -3,6 +3,7 @@ import { fromJS } from "immutable"; import toListTable from "./to-list-table"; +import defaultBodyRender from "./default-body-render"; describe("toListTable - pages/dashboard/utils/", () => { it("should convert data to plain JS", () => { @@ -49,11 +50,13 @@ describe("toListTable - pages/dashboard/utils/", () => { { id: "case_plan", display_text: { en: "Case Plan" } } ]; + const options = { customBodyRender: defaultBodyRender }; + const expected = { columns: [ - { name: "", label: "" }, - { name: "new", label: "New" }, - { name: "case_plan", label: "Case Plan" } + { name: "", label: "", options }, + { name: "new", label: "New", options }, + { name: "case_plan", label: "Case Plan", options } ], data: [{ "": "primero", case_plan: 1, new: 3 }], query: [ @@ -85,7 +88,8 @@ describe("toListTable - pages/dashboard/utils/", () => { columns: [ { label: "", - name: "" + name: "", + options: { customBodyRender: defaultBodyRender } } ], data: [], @@ -158,11 +162,13 @@ describe("toListTable - pages/dashboard/utils/", () => { { id: "category_1", display_text: "Category 1" } ]; + const options = { customBodyRender: defaultBodyRender }; + const expected = { columns: [ - { name: "", label: "" }, - { name: "new", label: "New" }, - { name: "case_plan", label: "Case Plan" } + { name: "", label: "", options }, + { name: "new", label: "New", options }, + { name: "case_plan", label: "Case Plan", options } ], data: [ { "": "Category 2", case_plan: 1, new: 3 }, diff --git a/app/javascript/components/pages/dashboard/utils/to-protection-concern-table.js b/app/javascript/components/pages/dashboard/utils/to-protection-concern-table.js index fc9cb2bf75..598f3299ac 100644 --- a/app/javascript/components/pages/dashboard/utils/to-protection-concern-table.js +++ b/app/javascript/components/pages/dashboard/utils/to-protection-concern-table.js @@ -3,6 +3,7 @@ import { dataToJS } from "../../../../libs"; import { INDICATOR_NAMES, PROTECTION_CONCERNS_ORDER_NAMES } from "../constants"; +import defaultBodyRender from "./default-body-render"; import { dashboardTableData } from "./to-reporting-location-table"; const byProtectionConcernsNames = (a, b) => { @@ -37,7 +38,7 @@ export default (data, i18n, lookups) => { const columns = Object.keys(result.indicators) .reduce( (acum, column) => { - return [...acum, { name: column, label: labels[column] }]; + return [...acum, { name: column, label: labels[column], options: { customBodyRender: defaultBodyRender } }]; }, [{ ...firstColumn }] ) diff --git a/app/javascript/components/pages/dashboard/utils/to-protection-concern-table.unit.test.js b/app/javascript/components/pages/dashboard/utils/to-protection-concern-table.unit.test.js index c00c4e15ec..03940ee04a 100644 --- a/app/javascript/components/pages/dashboard/utils/to-protection-concern-table.unit.test.js +++ b/app/javascript/components/pages/dashboard/utils/to-protection-concern-table.unit.test.js @@ -3,6 +3,7 @@ import { fromJS } from "immutable"; import toProtectionConcernTable from "./to-protection-concern-table"; +import defaultBodyRender from "./default-body-render"; describe("toProtectionConcernTable - pages/dashboard/utils/", () => { it("should convert the data for DashboardTable", () => { @@ -55,13 +56,15 @@ describe("toProtectionConcernTable - pages/dashboard/utils/", () => { } }); + const options = { customBodyRender: defaultBodyRender }; + const expected = { columns: [ { name: "", label: {} }, - { name: "protection_concerns_all_cases", label: {} }, - { name: "protection_concerns_open_cases", label: {} }, - { name: "protection_concerns_new_this_week", label: {} }, - { name: "protection_concerns_closed_this_week", label: {} } + { name: "protection_concerns_all_cases", label: {}, options }, + { name: "protection_concerns_open_cases", label: {}, options }, + { name: "protection_concerns_new_this_week", label: {}, options }, + { name: "protection_concerns_closed_this_week", label: {}, options } ], data: [ { diff --git a/app/javascript/components/pages/dashboard/utils/to-reporting-location-table.js b/app/javascript/components/pages/dashboard/utils/to-reporting-location-table.js index 8b84dde184..65c94db0e7 100644 --- a/app/javascript/components/pages/dashboard/utils/to-reporting-location-table.js +++ b/app/javascript/components/pages/dashboard/utils/to-reporting-location-table.js @@ -6,6 +6,8 @@ import { LOCALE_KEYS } from "../../../../config"; import { dataToJS } from "../../../../libs"; import { INDICATOR_NAMES } from "../constants"; +import defaultBodyRender from "./default-body-render"; + const reportingLocationLabel = (reportingLocationConfig, i18n) => { const locationTypes = []; @@ -38,27 +40,33 @@ export const dashboardTableData = (optionsByIndex, data, indicators, listKey) => }; export default (data, reportingLocationConfig, i18n, locations) => { + const options = { customBodyRender: defaultBodyRender }; const columns = [ { name: "", label: reportingLocationLabel(dataToJS(reportingLocationConfig), i18n) }, { name: INDICATOR_NAMES.REPORTING_LOCATION_OPEN, - label: i18n.t("dashboard.open_cases") + label: i18n.t("dashboard.open_cases"), + options }, { name: INDICATOR_NAMES.REPORTING_LOCATION_OPEN_LAST_WEEK, - label: i18n.t("dashboard.new_last_week") + label: i18n.t("dashboard.new_last_week"), + options }, { name: INDICATOR_NAMES.REPORTING_LOCATION_OPEN_THIS_WEEK, - label: i18n.t("dashboard.new_this_week") + label: i18n.t("dashboard.new_this_week"), + options }, { name: INDICATOR_NAMES.REPORTING_LOCATION_ClOSED_LAST_WEEK, - label: i18n.t("dashboard.closed_last_week") + label: i18n.t("dashboard.closed_last_week"), + options }, { name: INDICATOR_NAMES.REPORTING_LOCATION_ClOSED_THIS_WEEK, - label: i18n.t("dashboard.closed_this_week") + label: i18n.t("dashboard.closed_this_week"), + options } ]; diff --git a/app/javascript/components/pages/errors/not-authorized/component.jsx b/app/javascript/components/pages/errors/not-authorized/component.jsx index 99a5fae598..11dd6720b2 100644 --- a/app/javascript/components/pages/errors/not-authorized/component.jsx +++ b/app/javascript/components/pages/errors/not-authorized/component.jsx @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { CssBaseline, Typography } from "@material-ui/core"; +import { CssBaseline, Typography } from "@mui/material"; import { Link } from "react-router-dom"; import { useI18n } from "../../../i18n"; @@ -10,7 +10,7 @@ import { ACTION_BUTTON_TYPES } from "../../../action-button/constants"; import css from "./styles.css"; -const NotAuthorized = () => { +function NotAuthorized() { const i18n = useI18n(); return ( @@ -33,7 +33,7 @@ const NotAuthorized = () => { />

); -}; +} NotAuthorized.displayName = "NotAuthorized"; diff --git a/app/javascript/components/pages/errors/not-authorized/component.spec.js b/app/javascript/components/pages/errors/not-authorized/component.spec.js new file mode 100644 index 0000000000..ce685fd6d4 --- /dev/null +++ b/app/javascript/components/pages/errors/not-authorized/component.spec.js @@ -0,0 +1,25 @@ +import { mountedComponent, screen } from "../../../../test-utils"; + +import NotAuthorized from "./component"; + +describe("", () => { + it("renders h1 tag", () => { + mountedComponent(, {}); + expect(screen.getByText(/error_page.not_authorized.code/i)).toBeInTheDocument(); + }); + + it("renders h6 tag", () => { + mountedComponent(, {}); + expect(screen.getByText(/error_page.not_authorized.title/i)).toBeInTheDocument(); + }); + + it("renders p tag", () => { + mountedComponent(, {}); + expect(screen.getByText(/error_page.not_authorized.server_error/i)).toBeInTheDocument(); + }); + + it("renders forgot a tag", () => { + mountedComponent(, {}); + expect(screen.getByText(/navigation.home/i)).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/errors/not-authorized/component.unit.test.js b/app/javascript/components/pages/errors/not-authorized/component.unit.test.js deleted file mode 100644 index 47813ca305..0000000000 --- a/app/javascript/components/pages/errors/not-authorized/component.unit.test.js +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../test"; -import { ROUTES } from "../../../../config"; - -import NotAuthorized from "./component"; - -describe("", () => { - let component; - - before(() => { - component = setupMountedComponent(NotAuthorized, {}, {}).component; - }); - - it("renders h1 tag", () => { - expect(component.find("h1")).to.have.length(1); - }); - - it("renders h6 tag", () => { - expect(component.find("h6")).to.have.length(1); - }); - - it("renders p tag", () => { - expect(component.find("p")).to.have.length(1); - }); - - it("renders forgot a tag", () => { - expect(component.find("a").first().prop("href")).to.have.equal(ROUTES.dashboard); - }); -}); diff --git a/app/javascript/components/pages/errors/not-authorized/styles.css b/app/javascript/components/pages/errors/not-authorized/styles.css index 4031b6b2c0..4a9aae2d99 100644 --- a/app/javascript/components/pages/errors/not-authorized/styles.css +++ b/app/javascript/components/pages/errors/not-authorized/styles.css @@ -20,7 +20,7 @@ } } -@media (max-width:959.95px) { +@media (max-width:900px) { .root { & h1 { font-size: var(--fs-130); diff --git a/app/javascript/components/pages/errors/not-found/component.jsx b/app/javascript/components/pages/errors/not-found/component.jsx index 224992a32d..f2d963c8ae 100644 --- a/app/javascript/components/pages/errors/not-found/component.jsx +++ b/app/javascript/components/pages/errors/not-found/component.jsx @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { CssBaseline, Typography } from "@material-ui/core"; +import { CssBaseline, Typography } from "@mui/material"; import { Link } from "react-router-dom"; import { useI18n } from "../../../i18n"; @@ -10,7 +10,7 @@ import { ACTION_BUTTON_TYPES } from "../../../action-button/constants"; import css from "./styles.css"; -const NotFound = () => { +function NotFound() { const i18n = useI18n(); return ( @@ -33,7 +33,7 @@ const NotFound = () => { />
); -}; +} NotFound.displayName = "NotFound"; diff --git a/app/javascript/components/pages/errors/not-found/component.spec.js b/app/javascript/components/pages/errors/not-found/component.spec.js new file mode 100644 index 0000000000..f591d82283 --- /dev/null +++ b/app/javascript/components/pages/errors/not-found/component.spec.js @@ -0,0 +1,25 @@ +import { mountedComponent, screen } from "../../../../test-utils"; + +import NotFound from "./component"; + +describe("", () => { + it("renders h1 tag", () => { + mountedComponent(, {}); + expect(screen.getByText(/error_page.not_found.code/i)).toBeInTheDocument(); + }); + + it("renders h6 tag", () => { + mountedComponent(, {}); + expect(screen.getByText(/error_page.not_found.something_went_wrong/i)).toBeInTheDocument(); + }); + + it("renders p tag", () => { + mountedComponent(, {}); + expect(screen.getByText(/error_page.not_found.contact_admin/i)).toBeInTheDocument(); + }); + + it("renders forgot a tag", () => { + mountedComponent(, {}); + expect(screen.getByText(/navigation.home/i)).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/errors/not-found/component.unit.test.js b/app/javascript/components/pages/errors/not-found/component.unit.test.js deleted file mode 100644 index 2fbf1dd029..0000000000 --- a/app/javascript/components/pages/errors/not-found/component.unit.test.js +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../test"; -import { ROUTES } from "../../../../config"; - -import NotFound from "./component"; - -describe("", () => { - let component; - - before(() => { - component = setupMountedComponent(NotFound, {}, {}).component; - }); - - it("renders h1 tag", () => { - expect(component.find("h1")).to.have.length(1); - }); - - it("renders h6 tag", () => { - expect(component.find("h6")).to.have.length(1); - }); - - it("renders p tag", () => { - expect(component.find("p")).to.have.length(1); - }); - - it("renders forgot a tag", () => { - expect(component.find("a").first().prop("href")).to.have.equal(ROUTES.dashboard); - }); -}); diff --git a/app/javascript/components/pages/errors/not-found/styles.css b/app/javascript/components/pages/errors/not-found/styles.css index 4031b6b2c0..4a9aae2d99 100644 --- a/app/javascript/components/pages/errors/not-found/styles.css +++ b/app/javascript/components/pages/errors/not-found/styles.css @@ -20,7 +20,7 @@ } } -@media (max-width:959.95px) { +@media (max-width:900px) { .root { & h1 { font-size: var(--fs-130); diff --git a/app/javascript/components/pages/export-list/container.jsx b/app/javascript/components/pages/export-list/container.jsx index cdff16e1e0..8c00468be5 100644 --- a/app/javascript/components/pages/export-list/container.jsx +++ b/app/javascript/components/pages/export-list/container.jsx @@ -2,8 +2,8 @@ /* eslint-disable react/no-multi-comp, react/display-name */ import PropTypes from "prop-types"; -import DownloadIcon from "@material-ui/icons/GetApp"; -import CircularProgress from "@material-ui/core/CircularProgress"; +import DownloadIcon from "@mui/icons-material/GetApp"; +import CircularProgress from "@mui/material/CircularProgress"; import startCase from "lodash/startCase"; import DisableOffline from "../../disable-offline"; @@ -20,7 +20,7 @@ import css from "./styles.css"; import { selectListHeaders } from "./selectors"; import { NAME, EXPORT_STATUS, EXPORT_COLUMNS } from "./constants"; -const ExportList = () => { +function ExportList() { const i18n = useI18n(); const recordType = "bulk_exports"; @@ -117,13 +117,13 @@ const ExportList = () => { return ( - + ); -}; +} ExportList.displayName = NAME; diff --git a/app/javascript/components/pages/export-list/container.spec.js b/app/javascript/components/pages/export-list/container.spec.js new file mode 100644 index 0000000000..b353585cbd --- /dev/null +++ b/app/javascript/components/pages/export-list/container.spec.js @@ -0,0 +1,210 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { fromJS } from "immutable"; + +import { ListHeaderRecord } from "../../user/records"; +import { mountedComponent, screen } from "../../../test-utils"; +import { FieldRecord } from "../../record-form"; +import { mapEntriesToRecord } from "../../../libs"; + +import { ExportRecord } from "./records"; +import ExportList from "./container"; + +describe("", () => { + const initialState = fromJS({ + records: { + bulk_exports: { + data: [ + ExportRecord({ + id: "d5e1a4a019ec727efd34a35d1d9a271e", + file_name: "PRIMERO-CHILD-UNHCR.CSV", + record_type: "Case", + started_on: "2020-02-04T20:32:50.078Z" + }), + ExportRecord({ + id: "d5e1a4a019ec727efd34a35d1d9a272e", + file_name: "PRIMERO - CHILD.PDF", + record_type: "Case", + started_on: "2020-02-03T20:32:50.078Z" + }), + ExportRecord({ + id: "d5e1a4a019ec727efd34a35d1d9a273e", + file_name: "PRIMERO - CHILD.JSON", + record_type: "Case", + started_on: "2020-02-02T20:32:50.078Z" + }) + ], + metadata: { + total: 15, + per: 20, + page: 1 + }, + errors: false + } + }, + user: { + listHeaders: { + bulk_exports: [ + ListHeaderRecord({ + name: "file_name", + field_name: "file_name", + id_search: false + }), + ListHeaderRecord({ + name: "record_type", + field_name: "record_type", + id_search: false + }), + ListHeaderRecord({ + name: "started_on", + field_name: "started_on", + id_search: false + }) + ] + }, + permissions: { + exports: ["manage"], + bulk_exports: ["manage"] + } + }, + forms: { + fields: mapEntriesToRecord( + { + 1: { + name: "name_first", + type: "text_field" + } + }, + FieldRecord + ), + options: { + lookups: [ + { + id: 1, + unique_id: "lookup-location-type", + values: [ + { id: "country", display_text: "Country" }, + { id: "region", display_text: "Region" } + ] + } + ] + } + } + }); + + it("should render a table with three rows", () => { + mountedComponent(, {}, initialState); + expect(screen.getAllByRole("row")).toHaveLength(3); + }); + + it("should render ", () => { + mountedComponent(, {}, initialState); + expect(screen.getByTestId("page-container")).toBeInTheDocument(1); + }); + + it("should render ", () => { + mountedComponent(, {}, initialState); + expect(screen.getByTestId("page-heading")).toBeInTheDocument(); + }); + + it("should render ", () => { + mountedComponent(, {}, initialState); + expect(screen.getByTestId("page-content")).toBeInTheDocument(); + }); + + it("should render ", () => { + mountedComponent(, {}, initialState); + expect(screen.getByRole("table")).toBeInTheDocument(); + }); + + describe("when offline", () => { + const stateOffline = fromJS({ + connectivity: { + online: false + }, + records: { + bulk_exports: { + data: [ + ExportRecord({ + id: "d5e1a4a019ec727efd34a35d1d9a271e", + file_name: "PRIMERO-CHILD-UNHCR.CSV", + record_type: "Case", + started_on: "2020-02-04T20:32:50.078Z" + }), + ExportRecord({ + id: "d5e1a4a019ec727efd34a35d1d9a272e", + file_name: "PRIMERO - CHILD.PDF", + record_type: "Case", + started_on: "2020-02-03T20:32:50.078Z" + }), + ExportRecord({ + id: "d5e1a4a019ec727efd34a35d1d9a273e", + file_name: "PRIMERO - CHILD.JSON", + record_type: "Case", + started_on: "2020-02-02T20:32:50.078Z" + }) + ], + metadata: { + total: 15, + per: 20, + page: 1 + }, + errors: false + } + }, + user: { + listHeaders: { + bulk_exports: [ + ListHeaderRecord({ + name: "file_name", + field_name: "file_name", + id_search: false + }), + ListHeaderRecord({ + name: "record_type", + field_name: "record_type", + id_search: false + }), + ListHeaderRecord({ + name: "started_on", + field_name: "started_on", + id_search: false + }) + ] + }, + permissions: { + exports: ["manage"], + bulk_exports: ["manage"] + } + }, + forms: { + fields: mapEntriesToRecord( + { + 1: { + name: "name_first", + type: "text_field" + } + }, + FieldRecord + ), + options: { + lookups: [ + { + id: 1, + unique_id: "lookup-location-type", + values: [ + { id: "country", display_text: "Country" }, + { id: "region", display_text: "Region" } + ] + } + ] + } + } + }); + + it("should render DisabledOffline components for each row", () => { + mountedComponent(, stateOffline); + expect(screen.getAllByTestId("disable-offline")).toHaveLength(9); + }); + }); +}); diff --git a/app/javascript/components/pages/export-list/container.unit.test.js b/app/javascript/components/pages/export-list/container.unit.test.js deleted file mode 100644 index 59e96e2f28..0000000000 --- a/app/javascript/components/pages/export-list/container.unit.test.js +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import MUIDataTable, { TableBodyRow } from "mui-datatables"; - -import IndexTable from "../../index-table"; -import PageContainer, { PageHeading, PageContent } from "../../page"; -import { ListHeaderRecord } from "../../user/records"; -import { setupMountedComponent } from "../../../test"; -import { FieldRecord } from "../../record-form"; -import { mapEntriesToRecord } from "../../../libs"; -import DisableOffline from "../../disable-offline"; - -import { ExportRecord } from "./records"; -import ExportList from "./container"; - -describe("", () => { - let component; - - const initialState = fromJS({ - records: { - bulk_exports: { - data: [ - ExportRecord({ - id: "d5e1a4a019ec727efd34a35d1d9a271e", - file_name: "PRIMERO-CHILD-UNHCR.CSV", - record_type: "Case", - started_on: "2020-02-04T20:32:50.078Z" - }), - ExportRecord({ - id: "d5e1a4a019ec727efd34a35d1d9a272e", - file_name: "PRIMERO - CHILD.PDF", - record_type: "Case", - started_on: "2020-02-03T20:32:50.078Z" - }), - ExportRecord({ - id: "d5e1a4a019ec727efd34a35d1d9a273e", - file_name: "PRIMERO - CHILD.JSON", - record_type: "Case", - started_on: "2020-02-02T20:32:50.078Z" - }) - ], - metadata: { - total: 15, - per: 20, - page: 1 - }, - errors: false - } - }, - user: { - listHeaders: { - bulk_exports: [ - ListHeaderRecord({ - name: "file_name", - field_name: "file_name", - id_search: false - }), - ListHeaderRecord({ - name: "record_type", - field_name: "record_type", - id_search: false - }), - ListHeaderRecord({ - name: "started_on", - field_name: "started_on", - id_search: false - }) - ] - }, - permissions: { - exports: ["manage"], - bulk_exports: ["manage"] - } - }, - forms: { - fields: mapEntriesToRecord( - { - 1: { - name: "name_first", - type: "text_field" - } - }, - FieldRecord - ), - options: { - lookups: [ - { - id: 1, - unique_id: "lookup-location-type", - values: [ - { id: "country", display_text: "Country" }, - { id: "region", display_text: "Region" } - ] - } - ] - } - } - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(ExportList, {}, initialState)); - }); - - it("should render a table with three rows", () => { - expect(component.find(MUIDataTable).find(TableBodyRow)).to.have.lengthOf(3); - }); - - it("should render ", () => { - expect(component.find(PageContainer)).to.have.lengthOf(1); - }); - - it("should render ", () => { - expect(component.find(PageHeading)).to.have.lengthOf(1); - }); - - it("should render ", () => { - expect(component.find(PageContent)).to.have.lengthOf(1); - }); - - it("should render ", () => { - expect(component.find(IndexTable)).to.have.lengthOf(1); - }); - - describe("when offline", () => { - const stateOffline = initialState.setIn(["application", "online"], false); - - beforeEach(() => { - ({ component } = setupMountedComponent(ExportList, {}, stateOffline)); - }); - - it("should render DisabledOffline components for each row", () => { - expect(component.find(DisableOffline)).to.have.lengthOf(9); - }); - }); -}); diff --git a/app/javascript/components/pages/potential-matches/container.jsx b/app/javascript/components/pages/potential-matches/container.jsx index 28ec196231..61add43ae7 100644 --- a/app/javascript/components/pages/potential-matches/container.jsx +++ b/app/javascript/components/pages/potential-matches/container.jsx @@ -4,7 +4,7 @@ import { useEffect } from "react"; import { connect } from "react-redux"; import PropTypes from "prop-types"; import MUIDataTable from "mui-datatables"; -import { Card, CardContent } from "@material-ui/core"; +import { Card, CardContent } from "@mui/material"; import { useI18n } from "../../i18n"; import PageContainer, { PageHeading, PageContent } from "../../page"; @@ -13,7 +13,7 @@ import css from "./styles.css"; import { fetchPotentialMatches } from "./action-creators"; import { selectPotentialMatches } from "./selectors"; -const PotentialMatches = ({ getPotentialMatches, potentialMatches }) => { +function PotentialMatches({ getPotentialMatches, potentialMatches }) { useEffect(() => { getPotentialMatches(); }, []); @@ -90,7 +90,7 @@ const PotentialMatches = ({ getPotentialMatches, potentialMatches }) => { ); -}; +} PotentialMatches.displayName = "PotentialMatches"; diff --git a/app/javascript/components/pages/support/component.jsx b/app/javascript/components/pages/support/component.jsx index 033f4b6b40..3f38ab7a68 100644 --- a/app/javascript/components/pages/support/component.jsx +++ b/app/javascript/components/pages/support/component.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { useState } from "react"; -import { IconButton } from "@material-ui/core"; -import MenuOpenIcon from "@material-ui/icons/MenuOpen"; +import { IconButton } from "@mui/material"; +import MenuOpenIcon from "@mui/icons-material/MenuOpen"; import isEmpty from "lodash/isEmpty"; import PageContainer, { PageHeading } from "../../page"; @@ -15,7 +15,7 @@ import css from "./styles.css"; import { menuList, renderSupportForm } from "./utils"; import { Navigation } from "./components"; -const Component = () => { +function Component() { const i18n = useI18n(); const codeOfConduct = useMemoizedSelector(state => getCodesOfConduct(state)); @@ -67,7 +67,7 @@ const Component = () => {
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/support/component.spec.js b/app/javascript/components/pages/support/component.spec.js new file mode 100644 index 0000000000..3d9bad64b6 --- /dev/null +++ b/app/javascript/components/pages/support/component.spec.js @@ -0,0 +1,74 @@ +import { fromJS } from "immutable"; +import { waitFor } from "@testing-library/react"; + +import { mountedComponent, screen, userEvent } from "../../../test-utils"; + +import Support from "./component"; + +describe("", () => { + describe("Default components", () => { + it("should render PageContainer component", () => { + mountedComponent(); + expect(screen.getByTestId("page-container")).toBeInTheDocument(); + }); + + it("should render PageHeading component", () => { + mountedComponent(); + expect(screen.getByTestId("page-heading")).toBeInTheDocument(); + }); + + it("should render Navigation component", () => { + mountedComponent(); + expect(screen.getByTestId("list")).toBeInTheDocument(); + }); + + it("should render ContactInformation component", () => { + mountedComponent(); + expect(screen.getByTestId("support")).toBeInTheDocument(); + }); + }); + + describe("Navigation", () => { + const state = fromJS({ + application: { + codesOfConduct: { + id: 1, + title: "Test code of conduct", + content: "Lorem ipsum", + created_on: "2021-03-19T15:21:38.950Z", + created_by: "primero" + }, + systemOptions: { + code_of_conduct_enabled: true + } + } + }); + + it("should render a List component", () => { + mountedComponent(, {}, state); + expect(screen.getByTestId("list")).toBeInTheDocument(); + }); + + it("should render 4 ListItem components", () => { + mountedComponent(, {}, state); + expect(screen.getAllByTestId("list-item")).toHaveLength(4); + }); + + it("should render CodeOfConduct component when clicking menu from the Navigation list", () => { + mountedComponent(, {}, state); + userEvent.click(screen.getAllByTestId("list-item").at(2)); + waitFor(() => { + expect(screen.getByText("contact.info_label")).toBeInTheDocument(); + expect(screen.getByText("Test code of conduct")).toBeInTheDocument(); + }); + }); + + it("should render TermOfUse component when clicking menu from the Navigation list", () => { + mountedComponent(, {}, state); + userEvent.click(screen.getAllByTestId("list-item").at(1)); + waitFor(() => { + expect(screen.getByText("navigation.support_menu.terms_of_use")).toBeInTheDocument(); + }); + }); + }); +}); diff --git a/app/javascript/components/pages/support/component.unit.test.js b/app/javascript/components/pages/support/component.unit.test.js deleted file mode 100644 index 1f0a5c1c3a..0000000000 --- a/app/javascript/components/pages/support/component.unit.test.js +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { List, ListItem } from "@material-ui/core"; -import { fromJS } from "immutable"; - -import PageContainer, { PageHeading } from "../../page"; -import { setupMountedComponent } from "../../../test"; -import ContactInformation from "../../contact-information"; - -import { Navigation, CodeOfConduct, TermOfUse } from "./components"; -import Support from "./component"; - -describe("", () => { - let component; - - describe("Default components", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(Support)); - }); - - it("should render PageContainer component", () => { - expect(component.find(PageContainer)).to.have.lengthOf(1); - }); - - it("should render PageHeading component", () => { - expect(component.find(PageHeading)).to.have.lengthOf(1); - }); - - it("should render Navigation component", () => { - expect(component.find(Navigation)).to.have.lengthOf(1); - }); - - it("should render ContactInformation component", () => { - expect(component.find(ContactInformation)).to.have.lengthOf(1); - }); - }); - - describe("Navigation", () => { - const state = fromJS({ - application: { - codesOfConduct: { - id: 1, - title: "Test code of conduct", - content: "Lorem ipsum", - created_on: "2021-03-19T15:21:38.950Z", - created_by: "primero" - }, - systemOptions: { - code_of_conduct_enabled: true - } - } - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(Support, {}, state)); - }); - - it("should render a List component", () => { - expect(component.find(List)).to.have.lengthOf(1); - }); - - it("should render 4 ListItem components", () => { - expect(component.find(ListItem)).to.have.lengthOf(4); - }); - - it("should render CodeOfConduct component when clicking menu from the Navigation list", () => { - const codeOfconductMenu = component.find(ListItem).at(2); - - expect(component.find("h1").at(1).text()).to.be.equal("contact.info_label"); - expect(component.find(ContactInformation)).to.have.lengthOf(1); - - codeOfconductMenu.simulate("click"); - expect(component.find(CodeOfConduct)).to.have.lengthOf(1); - expect(component.find("h2").text()).to.be.equal("Test code of conduct"); - }); - - it("should render TermOfUse component when clicking menu from the Navigation list", () => { - const codeOfconductMenu = component.find(ListItem).at(1); - - codeOfconductMenu.simulate("click"); - expect(component.find(TermOfUse)).to.have.lengthOf(1); - expect(component.find("h2").text()).to.be.equal("navigation.support_menu.terms_of_use"); - }); - }); -}); diff --git a/app/javascript/components/pages/support/components/code-of-conduct/component.jsx b/app/javascript/components/pages/support/components/code-of-conduct/component.jsx index 34699c6e38..f78b6e5e2e 100644 --- a/app/javascript/components/pages/support/components/code-of-conduct/component.jsx +++ b/app/javascript/components/pages/support/components/code-of-conduct/component.jsx @@ -1,19 +1,19 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { format, parseISO } from "date-fns"; -import { Typography } from "@material-ui/core"; +import { Typography } from "@mui/material"; import { useI18n } from "../../../../i18n"; import css from "../../../../code-of-conduct/styles.css"; import { useMemoizedSelector } from "../../../../../libs"; import { getCodeOfConductAccepteOn } from "../../../../user"; import { getCodesOfConduct } from "../../../../application/selectors"; -import { CODE_OF_CONDUCT_DATE_FORMAT } from "../../../../../config/constants"; +import { CODE_OF_CONDUCT_DATE_FORMAT } from "../../../../../config"; import parentCss from "../../styles.css"; import { NAME } from "./constants"; -const Component = () => { +function Component() { const i18n = useI18n(); const codeOfConductAccepteOn = useMemoizedSelector(state => getCodeOfConductAccepteOn(state)); @@ -35,7 +35,7 @@ const Component = () => { {applicationCodeOfConduct?.get("content")}
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/support/components/code-of-conduct/component.unit.test.js b/app/javascript/components/pages/support/components/code-of-conduct/component.spec.js similarity index 53% rename from app/javascript/components/pages/support/components/code-of-conduct/component.unit.test.js rename to app/javascript/components/pages/support/components/code-of-conduct/component.spec.js index 0301453e73..3c535407eb 100644 --- a/app/javascript/components/pages/support/components/code-of-conduct/component.unit.test.js +++ b/app/javascript/components/pages/support/components/code-of-conduct/component.spec.js @@ -2,7 +2,7 @@ import { fromJS } from "immutable"; -import { setupMountedComponent } from "../../../../../test"; +import { mountedComponent, screen } from "../../../../../test-utils"; import CodeOfConduct from "./component"; @@ -23,24 +23,14 @@ describe("", () => { } }); - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(CodeOfConduct, {}, state)); - }); - it("should render h2", () => { - const h2Tag = component.find("h2"); - - expect(h2Tag).to.have.lengthOf(1); - expect(h2Tag.text()).to.be.equal("Test code of conduct"); + mountedComponent(, state); + expect(screen.getByText(/Test code of conduct/i)).toBeInTheDocument(); }); it("should render 2 h3", () => { - const h3Tag = component.find("h3"); - - expect(h3Tag).to.have.lengthOf(2); - expect(h3Tag.at(0).text()).to.be.equal("updated March 19, 2021"); - expect(h3Tag.at(1).text()).to.be.equal("accepted March 23, 2021"); + mountedComponent(, state); + expect(screen.getByText(/updated March 19, 2021/i)).toBeInTheDocument(); + expect(screen.getByText(/accepted March 23, 2021/i)).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/pages/support/components/navigation/component.jsx b/app/javascript/components/pages/support/components/navigation/component.jsx index ce380a7227..8454450bc2 100644 --- a/app/javascript/components/pages/support/components/navigation/component.jsx +++ b/app/javascript/components/pages/support/components/navigation/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { List, ListItem, ListItemText, Drawer } from "@material-ui/core"; +import { List, ListItem, ListItemText, Drawer } from "@mui/material"; import { ConditionalWrapper, useMemoizedSelector } from "../../../../../libs"; import Jewel from "../../../../jewel"; @@ -10,7 +10,7 @@ import { SUPPORT_FORMS } from "../../constants"; import { NAME } from "./constants"; -const Component = ({ css, handleToggleNav, menuList, mobileDisplay, onClick, selectedItem, toggleNav }) => { +function Component({ css, handleToggleNav, menuList, mobileDisplay, onClick, selectedItem, toggleNav }) { const hasUnsubmittedOfflineChanges = useMemoizedSelector(state => hasQueueData(state)); const drawerProps = { @@ -57,7 +57,7 @@ const Component = ({ css, handleToggleNav, menuList, mobileDisplay, onClick, sel ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/support/components/terms-of-use/component.jsx b/app/javascript/components/pages/support/components/terms-of-use/component.jsx index 522708802c..896faeafce 100644 --- a/app/javascript/components/pages/support/components/terms-of-use/component.jsx +++ b/app/javascript/components/pages/support/components/terms-of-use/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Typography } from "@material-ui/core"; -import GetAppIcon from "@material-ui/icons/GetApp"; +import { Typography } from "@mui/material"; +import GetAppIcon from "@mui/icons-material/GetApp"; import parentCss from "../../styles.css"; import { useI18n } from "../../../../i18n"; @@ -13,7 +13,7 @@ import ActionButton from "../../../../action-button"; import { NAME } from "./constants"; import css from "./styles.css"; -const Component = () => { +function Component() { const i18n = useI18n(); const agenciesWithTermsOfUse = useMemoizedSelector(state => getAgencyTermsOfUse(state)); @@ -47,7 +47,7 @@ const Component = () => { {renderAgencyWihTermsOfUse}
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/pages/support/components/terms-of-use/component.unit.test.js b/app/javascript/components/pages/support/components/terms-of-use/component.spec.js similarity index 61% rename from app/javascript/components/pages/support/components/terms-of-use/component.unit.test.js rename to app/javascript/components/pages/support/components/terms-of-use/component.spec.js index adfbd423a3..ed94ed4bab 100644 --- a/app/javascript/components/pages/support/components/terms-of-use/component.unit.test.js +++ b/app/javascript/components/pages/support/components/terms-of-use/component.spec.js @@ -1,10 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { Typography } from "@material-ui/core"; -import { setupMountedComponent } from "../../../../../test"; -import ActionButton from "../../../../action-button"; +import { mountedComponent, screen } from "../../../../../test-utils"; import TermOfUse from "./component"; @@ -40,21 +38,16 @@ describe("", () => { } }); - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(TermOfUse, {}, state)); - }); - it("should render h2", () => { - const h2Tag = component.find("h2"); + mountedComponent(, state); - expect(h2Tag).to.have.lengthOf(1); - expect(h2Tag.text()).to.be.equal("navigation.support_menu.terms_of_use"); + expect(screen.getByText(/navigation.support_menu.terms_of_use/i)).toBeInTheDocument(); }); it("should render 2 buttons", () => { - expect(component.find(Typography)).to.have.lengthOf(2); - expect(component.find(ActionButton)).to.have.lengthOf(2); + mountedComponent(, state); + + expect(screen.getAllByRole("heading")).toHaveLength(1); + expect(screen.getAllByRole("button")).toHaveLength(2); }); }); diff --git a/app/javascript/components/pages/task-list/container.jsx b/app/javascript/components/pages/task-list/container.jsx index f02d934366..fc657f8a84 100644 --- a/app/javascript/components/pages/task-list/container.jsx +++ b/app/javascript/components/pages/task-list/container.jsx @@ -2,8 +2,8 @@ import { fromJS } from "immutable"; import { useDispatch, batch } from "react-redux"; -import Tooltip from "@material-ui/core/Tooltip"; -import clsx from "clsx"; +import Tooltip from "@mui/material/Tooltip"; +import { cx } from "@emotion/css"; import { push } from "connected-react-router"; import { useI18n } from "../../i18n"; @@ -23,7 +23,7 @@ import css from "./styles.css"; import { TASK_STATUS } from "./constants"; import { getTranslatedValue } from "./utils"; -const TaskList = () => { +function TaskList() { const i18n = useI18n(); const recordType = "tasks"; @@ -82,7 +82,7 @@ const TaskList = () => { const recordData = data.get("data").get(tableMeta.rowIndex); const overdue = recordData.get(TASK_STATUS.overdue); const upcomingSoon = recordData.get(TASK_STATUS.upcomingSoon); - const cssNames = clsx([ + const cssNames = cx([ css.link, { [css[TASK_STATUS.overdue]]: overdue, @@ -197,7 +197,7 @@ const TaskList = () => { ); -}; +} TaskList.displayName = "TaskList"; diff --git a/app/javascript/components/pages/task-list/container.spec.js b/app/javascript/components/pages/task-list/container.spec.js new file mode 100644 index 0000000000..e8f4ce5ba3 --- /dev/null +++ b/app/javascript/components/pages/task-list/container.spec.js @@ -0,0 +1,186 @@ +import { fromJS, OrderedMap } from "immutable"; + +import { mountedComponent, screen } from "../../../test-utils"; +import { ListHeaderRecord } from "../../user/records"; +import { FieldRecord, FormSectionRecord } from "../../record-form/records"; + +import TaskList from "./container"; + +describe("", () => { + const state = fromJS({ + records: { + tasks: { + data: [ + { + id: "0df32f52-4290-4ce1-b859-74ac14c081bf", + record_type: "case", + record_id_display: "040e0b7", + priority: "high", + type: "service", + due_date: "2019-07-01", + detail: "a", + field_name: "test", + completion_field: "test_service" + }, + { + id: "0df32f52-4290-4ce1-b859-74ac14c081bf", + record_type: "case", + record_id_display: "040e0b7", + priority: "low", + type: "case_plan", + due_date: "2019-07-02", + detail: "b", + field_name: "case_plan_due_date", + completion_field: "case_plan_due_date" + }, + { + id: "f1288fad-1c15-4f9f-b976-1f77d6356955", + overdue: true, + priority: "medium", + record_type: "case", + record_id_display: "726b7db", + detail: "c", + due_date: "2019-09-01", + type: "follow_up", + type_display: "Follow Up - Follow up for Assessment", + upcoming_soon: false, + field_name: "test_follow_up", + completion_field: "test_follow_up" + } + ], + metadata: { + total: 2, + per: 20, + page: 1, + field_names: { + assessment: "test_assessment", + case_plan: "case_plan_due_date", + service: "test_service", + follow_up: "test_follow_up" + } + } + } + }, + user: { + listHeaders: { + tasks: [ + ListHeaderRecord({ + name: "id", + field_name: "record_id_display", + id_search: false + }), + ListHeaderRecord({ + name: "priority", + field_name: "priority", + id_search: false + }), + ListHeaderRecord({ + name: "type", + field_name: "type", + id_search: false + }), + ListHeaderRecord({ + name: "due_date", + field_name: "due_date", + id_search: false + }), + ListHeaderRecord({ + name: "status", + field_name: "status", + id_search: false + }) + ] + } + }, + forms: { + formSections: OrderedMap({ + 1: FormSectionRecord({ + id: 1, + unique_id: "cp_incident_record_owner", + parent_form: "incident", + name: { en: "Form name" }, + fields: [1] + }), + 2: FormSectionRecord({ + id: 2, + unique_id: "assessment", + parent_form: "case", + name: { en: "Assessment" }, + fields: [2], + is_nested: false + }), + 3: FormSectionRecord({ + id: 3, + unique_id: "followup", + parent_form: "case", + name: { en: "followup" }, + fields: [3], + is_nested: false + }) + }), + fields: OrderedMap({ + 1: FieldRecord({ + id: 1, + name: "test_service", + display_name: { en: "Test Field" }, + type: "text_field", + multi_select: false, + form_section_id: 1, + visible: true, + mobile_visible: true + }), + 2: FieldRecord({ + id: 2, + name: "case_plan_due_date", + display_name: { en: "Case Plan Due Date" }, + type: "text_field", + multi_select: false, + form_section_id: 2, + visible: true, + mobile_visible: true + }), + 3: FieldRecord({ + id: 3, + name: "test_follow_up", + display_name: { en: "Followup" }, + type: "text_field", + multi_select: false, + form_section_id: 2, + visible: true, + mobile_visible: true + }) + }), + options: { + lookups: [ + { + id: 1, + unique_id: "lookup-service-type", + values: [ + { id: "a", display_text: { en: "Service a" } }, + { id: "b", display_text: { en: "Service b" } } + ] + } + ] + } + } + }); + + it("should render tasks table", () => { + mountedComponent(, state); + expect(screen.getAllByRole("row")).toHaveLength(5); + }); + + it("should render tasks table with priority as DashboardChip", () => { + mountedComponent(, state); + + expect(screen.getAllByTestId("chip-button")).toHaveLength(3); + }); + + it("should render the task type", () => { + mountedComponent(, state); + + expect(screen.getByText("task.types.service")).toBeInTheDocument(); + expect(screen.getByText("task.types.case_plan")).toBeInTheDocument(); + expect(screen.getByText("task.types.follow_up")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/pages/task-list/container.unit.test.js b/app/javascript/components/pages/task-list/container.unit.test.js deleted file mode 100644 index b4f60c4314..0000000000 --- a/app/javascript/components/pages/task-list/container.unit.test.js +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS, OrderedMap } from "immutable"; -import MUIDataTable, { TableBodyRow } from "mui-datatables"; - -import { setupMountedComponent, stub } from "../../../test"; -import { DashboardChip } from "../../dashboard"; -import { ListHeaderRecord } from "../../user/records"; -import { FieldRecord, FormSectionRecord } from "../../record-form/records"; - -import TaskList from "./container"; - -describe("", () => { - let stubI18n = null; - let component; - - beforeEach(() => { - stubI18n = stub(window.I18n, "t").withArgs("date.formats.default").returns("%d-%b-%Y"); - }); - - before(() => { - component = setupMountedComponent( - TaskList, - {}, - fromJS({ - records: { - tasks: { - data: [ - { - id: "0df32f52-4290-4ce1-b859-74ac14c081bf", - record_type: "case", - record_id_display: "040e0b7", - priority: "high", - type: "service", - due_date: "2019-07-01", - detail: "a", - field_name: "test", - completion_field: "test_service" - }, - { - id: "0df32f52-4290-4ce1-b859-74ac14c081bf", - record_type: "case", - record_id_display: "040e0b7", - priority: "low", - type: "case_plan", - due_date: "2019-07-02", - detail: "b", - field_name: "case_plan_due_date", - completion_field: "case_plan_due_date" - }, - { - id: "f1288fad-1c15-4f9f-b976-1f77d6356955", - overdue: true, - priority: "medium", - record_type: "case", - record_id_display: "726b7db", - detail: "c", - due_date: "2019-09-01", - type: "follow_up", - type_display: "Follow Up - Follow up for Assessment", - upcoming_soon: false, - field_name: "test_follow_up", - completion_field: "test_follow_up" - } - ], - metadata: { - total: 2, - per: 20, - page: 1, - field_names: { - assessment: "test_assessment", - case_plan: "case_plan_due_date", - service: "test_service", - follow_up: "test_follow_up" - } - } - } - }, - user: { - listHeaders: { - tasks: [ - ListHeaderRecord({ - name: "id", - field_name: "record_id_display", - id_search: false - }), - ListHeaderRecord({ - name: "priority", - field_name: "priority", - id_search: false - }), - ListHeaderRecord({ - name: "type", - field_name: "type", - id_search: false - }), - ListHeaderRecord({ - name: "due_date", - field_name: "due_date", - id_search: false - }), - ListHeaderRecord({ - name: "status", - field_name: "status", - id_search: false - }) - ] - } - }, - forms: { - formSections: OrderedMap({ - 1: FormSectionRecord({ - id: 1, - unique_id: "cp_incident_record_owner", - parent_form: "incident", - name: { en: "Form name" }, - fields: [1] - }), - 2: FormSectionRecord({ - id: 2, - unique_id: "assessment", - parent_form: "case", - name: { en: "Assessment" }, - fields: [2], - is_nested: false - }), - 3: FormSectionRecord({ - id: 3, - unique_id: "followup", - parent_form: "case", - name: { en: "followup" }, - fields: [3], - is_nested: false - }) - }), - fields: OrderedMap({ - 1: FieldRecord({ - id: 1, - name: "test_service", - display_name: { en: "Test Field" }, - type: "text_field", - multi_select: false, - form_section_id: 1, - visible: true, - mobile_visible: true - }), - 2: FieldRecord({ - id: 2, - name: "case_plan_due_date", - display_name: { en: "Case Plan Due Date" }, - type: "text_field", - multi_select: false, - form_section_id: 2, - visible: true, - mobile_visible: true - }), - 3: FieldRecord({ - id: 3, - name: "test_follow_up", - display_name: { en: "Followup" }, - type: "text_field", - multi_select: false, - form_section_id: 2, - visible: true, - mobile_visible: true - }) - }), - options: { - lookups: [ - { - id: 1, - unique_id: "lookup-service-type", - values: [ - { id: "a", display_text: { en: "Service a" } }, - { id: "b", display_text: { en: "Service b" } } - ] - } - ] - } - } - }) - ).component; - }); - - it("should render tasks table", () => { - expect(component.find(MUIDataTable).find(TableBodyRow)).to.have.length(3); - }); - - it("should render tasks table with priority as DashboardChip", () => { - expect(component.find(MUIDataTable).find(DashboardChip)).to.have.length(3); - }); - - it("should render the task type", () => { - const tableRows = component.find(MUIDataTable).find(TableBodyRow); - const typesTask = ["task.types.service", "task.types.case_plan", "task.types.follow_up"]; - - tableRows.forEach((element, item) => { - expect(element.find("tr").at(0).find("td").at(2).find("div").at(1).text()).to.be.equal(typesTask[item]); - }); - }); - - it("should trigger an action that sets the form unique_id when clicking on a task", () => { - const table = component.find(MUIDataTable); - const firstRow = table.find("tr").at(1); - const secondRow = table.find("tr").at(2); - const expectedType = { type: "forms/SET_SELECTED_FORM" }; - - expect(component.props().store.getActions()).to.have.lengthOf(1); - - // Simulating click on the first row (type=service) should dispatch an action - firstRow.find("td").at(0).simulate("click"); - expect(component.props().store.getActions()).to.have.lengthOf(2); - expect(component.props().store.getActions()[1]).to.deep.equals({ - ...expectedType, - payload: "cp_incident_record_owner" - }); - - // Simulating click on the second row (type=case_plan) should dispatch an action - secondRow.find("td").at(0).simulate("click"); - expect(component.props().store.getActions()).to.have.lengthOf(3); - expect(component.props().store.getActions()[2]).to.deep.equals({ - ...expectedType, - payload: "assessment" - }); - }); - - afterEach(() => { - if (stubI18n) { - window.I18n.t.restore(); - } - }); -}); diff --git a/app/javascript/components/password-reset-confirmation/component.jsx b/app/javascript/components/password-reset-confirmation/component.jsx index e41782115c..8e443c6c30 100644 --- a/app/javascript/components/password-reset-confirmation/component.jsx +++ b/app/javascript/components/password-reset-confirmation/component.jsx @@ -9,7 +9,7 @@ import useMemoizedSelector from "../../libs/use-memoized-selector"; import { NAME } from "./constants"; -const Component = ({ open, handleCancel, handleSuccess }) => { +function Component({ open = false, handleCancel, handleSuccess }) { const i18n = useI18n(); const pending = useMemoizedSelector(state => getPasswordResetLoading(state)); @@ -35,14 +35,10 @@ const Component = ({ open, handleCancel, handleSuccess }) => {

{i18n.t("user.password_reset_text")}

); -}; +} Component.displayName = NAME; -Component.defaultProps = { - open: false -}; - Component.propTypes = { handleCancel: PropTypes.func, handleSuccess: PropTypes.func, diff --git a/app/javascript/components/password-reset-confirmation/component.spec.js b/app/javascript/components/password-reset-confirmation/component.spec.js new file mode 100644 index 0000000000..b71039584c --- /dev/null +++ b/app/javascript/components/password-reset-confirmation/component.spec.js @@ -0,0 +1,15 @@ +import { mountedComponent, screen } from "../../test-utils"; + +import PasswordResetConfirmation from "./component"; + +describe("", () => { + it("should render the ActionDialog", () => { + mountedComponent(); + expect(screen.getByText(/user.password_reset_header/i)).toBeInTheDocument(); + }); + + it("should render the text", () => { + mountedComponent(); + expect(screen.getByText(/user.password_reset_text/i)).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/password-reset-confirmation/component.unit.test.js b/app/javascript/components/password-reset-confirmation/component.unit.test.js deleted file mode 100644 index d64f1aa36d..0000000000 --- a/app/javascript/components/password-reset-confirmation/component.unit.test.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../test"; -import ActionDialog from "../action-dialog"; - -import PasswordResetConfirmation from "./component"; - -describe("", () => { - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(PasswordResetConfirmation, { open: true }, fromJS({}))); - }); - - it("should render the ActionDialog", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(1); - }); - - it("should render the text", () => { - expect(component.find(ActionDialog).find("p")).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/password-reset/component.jsx b/app/javascript/components/password-reset/component.jsx index 452063a8ff..2b71734c8b 100644 --- a/app/javascript/components/password-reset/component.jsx +++ b/app/javascript/components/password-reset/component.jsx @@ -3,7 +3,7 @@ import qs from "qs"; import { useLocation } from "react-router-dom"; import { useDispatch } from "react-redux"; -import CheckIcon from "@material-ui/icons/Check"; +import CheckIcon from "@mui/icons-material/Check"; import { PageHeading } from "../page"; import Form, { FormAction } from "../form"; @@ -14,7 +14,7 @@ import useMemoizedSelector from "../../libs/use-memoized-selector"; import { form, validationSchema } from "./form"; import { NAME, RESET_PASSWORD_FORM } from "./constants"; -const Component = () => { +function Component() { const i18n = useI18n(); const location = useLocation(); const dispatch = useDispatch(); @@ -47,7 +47,7 @@ const Component = () => { />
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/password-reset/component.spec.js b/app/javascript/components/password-reset/component.spec.js new file mode 100644 index 0000000000..614ea46e95 --- /dev/null +++ b/app/javascript/components/password-reset/component.spec.js @@ -0,0 +1,25 @@ +import { mountedComponent, screen } from "../../test-utils"; + +import PasswordReset from "./component"; + +describe("", () => { + it("should render a component", () => { + mountedComponent(); + expect(screen.getByText(/Set Password/i)).toBeInTheDocument(); + }); + + it("should render a
component", () => { + mountedComponent(); + expect(screen.getAllByText((content, element) => element.tagName.toLowerCase() === "form")).toHaveLength(1); + }); + + it("should render a component", () => { + mountedComponent(); + expect(screen.getByText(/buttons.save/i)).toBeInTheDocument(); + }); + + it("should render 2 components", () => { + mountedComponent(); + expect(screen.getAllByText((content, element) => element.tagName.toLowerCase() === "input")).toHaveLength(2); + }); +}); diff --git a/app/javascript/components/password-reset/component.unit.test.js b/app/javascript/components/password-reset/component.unit.test.js deleted file mode 100644 index f41722bbe2..0000000000 --- a/app/javascript/components/password-reset/component.unit.test.js +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../test"; -import { PageHeading } from "../page"; -import Form, { FormAction } from "../form"; -import TextInput from "../form/fields/text-input"; - -import PasswordReset from "./component"; - -describe("", () => { - let component; - - const initialState = fromJS({}); - - beforeEach(() => { - ({ component } = setupMountedComponent(PasswordReset, {}, initialState)); - }); - - it("should render a component", () => { - expect(component.find(PageHeading)).to.have.lengthOf(1); - }); - - it("should render a component", () => { - expect(component.find(Form)).to.have.lengthOf(1); - }); - - it("should render a component", () => { - expect(component.find(FormAction)).to.have.lengthOf(1); - }); - - it("should render 2 components", () => { - expect(component.find(TextInput)).to.have.lengthOf(2); - }); -}); diff --git a/app/javascript/components/pdf-exporter/component.jsx b/app/javascript/components/pdf-exporter/component.jsx index 99395272db..b5f8d8722d 100644 --- a/app/javascript/components/pdf-exporter/component.jsx +++ b/app/javascript/components/pdf-exporter/component.jsx @@ -2,7 +2,7 @@ import { forwardRef, useImperativeHandle, useRef } from "react"; import PropTypes from "prop-types"; -import { Typography } from "@material-ui/core"; +import { Typography } from "@mui/material"; import { useWatch } from "react-hook-form"; import html2pdf from "html2pdf-dom-to-image-more"; import { useDispatch } from "react-redux"; @@ -20,7 +20,7 @@ import { INCLUDE_OTHER_LOGOS } from "../record-actions/exports/constants"; import useOptions from "../form/use-options"; -import { RECORD_TYPES } from "../../config/constants"; +import { RECORD_TYPES } from "../../config"; import Signatures from "./components/signatures"; import { HTML_2_PDF_OPTIONS, PDF_HEADER_LOOKUP } from "./constants"; @@ -39,7 +39,7 @@ const Component = forwardRef( formsSelectedSelector, formsSelectedFieldDefault, customFilenameField, - customFormProps, + customFormProps = {}, currentUser, agenciesWithLogosEnabled, agencyLogosPdf @@ -183,10 +183,6 @@ const Component = forwardRef( Component.displayName = "PdfExporter"; -Component.defaultProps = { - customFormProps: {} -}; - Component.propTypes = { agenciesWithLogosEnabled: PropTypes.array, agencyLogosPdf: PropTypes.array, diff --git a/app/javascript/components/pdf-exporter/component.unit.test.js b/app/javascript/components/pdf-exporter/component.spec.js similarity index 78% rename from app/javascript/components/pdf-exporter/component.unit.test.js rename to app/javascript/components/pdf-exporter/component.spec.js index 66bd97d257..d0df7b1341 100644 --- a/app/javascript/components/pdf-exporter/component.unit.test.js +++ b/app/javascript/components/pdf-exporter/component.spec.js @@ -3,10 +3,8 @@ import { createRef } from "react"; import { fromJS } from "immutable"; -import { setupMockFormComponent } from "../../test"; +import { screen, mountedFormComponent } from "../../test-utils"; -import RenderTable from "./components/render-table"; -import Logos from "./components/logos"; import PdfExporter from "./component"; describe("", () => { @@ -78,20 +76,19 @@ describe("", () => { }; it("renders PdfExporter", () => { - const { component } = setupMockFormComponent(PdfExporter, { props }); - - expect(component.find(PdfExporter)).to.have.lengthOf(1); + mountedFormComponent(); + expect(screen.getAllByText(/exports.printed/i)).toHaveLength(2); }); it("renders Logos", () => { - const { component } = setupMockFormComponent(PdfExporter, { props }); + mountedFormComponent(); - expect(component.find(Logos)).to.have.lengthOf(2); + expect(screen.getAllByText((_, element) => element.tagName.toLowerCase() === "svg")).toHaveLength(1); }); it("renders RenderTable", () => { - const { component } = setupMockFormComponent(PdfExporter, { props }); + mountedFormComponent(); - expect(component.find(RenderTable)).to.have.lengthOf(1); + expect(screen.getByText(/Approved by Manager/i)).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/pdf-exporter/components/key-value-cell/component.jsx b/app/javascript/components/pdf-exporter/components/key-value-cell/component.jsx index 54fa1ffc48..b8a9f73497 100644 --- a/app/javascript/components/pdf-exporter/components/key-value-cell/component.jsx +++ b/app/javascript/components/pdf-exporter/components/key-value-cell/component.jsx @@ -3,11 +3,11 @@ import PropTypes from "prop-types"; import { List } from "immutable"; import { isEmpty } from "lodash"; -import CheckBox from "@material-ui/icons/CheckBox"; -import CheckBoxOutlineBlank from "@material-ui/icons/CheckBoxOutlineBlank"; -import RadioButtonChecked from "@material-ui/icons/RadioButtonChecked"; -import RadioButtonUnchecked from "@material-ui/icons/RadioButtonUnchecked"; -import clsx from "clsx"; +import CheckBox from "@mui/icons-material/CheckBox"; +import CheckBoxOutlineBlank from "@mui/icons-material/CheckBoxOutlineBlank"; +import RadioButtonChecked from "@mui/icons-material/RadioButtonChecked"; +import RadioButtonUnchecked from "@mui/icons-material/RadioButtonUnchecked"; +import { cx } from "@emotion/css"; import { optionText } from "../../../form/utils"; import { useI18n } from "../../../i18n"; @@ -17,17 +17,17 @@ import useOptions from "../../../form/use-options"; import css from "./styles.css"; -const Component = ({ +function Component({ classes, defaultValue, displayName, - isDateWithTime, - isSubform, + isDateWithTime = false, + isSubform = false, options, - optionsStringSource, + optionsStringSource = null, type, - value -}) => { + value = "" +}) { const i18n = useI18n(); const isDateField = type === DATE_FIELD; @@ -88,7 +88,7 @@ const Component = ({ return fieldValue; }; - const kevValueCellClasses = clsx(classes.cell, { + const kevValueCellClasses = cx(classes.cell, { [classes.subform]: isSubform }); @@ -98,17 +98,10 @@ const Component = ({
{renderValue(cellValue)}
); -}; +} Component.displayName = "KeyValueCell"; -Component.defaultProps = { - isDateWithTime: false, - isSubform: false, - optionsStringSource: null, - value: "" -}; - Component.propTypes = { classes: PropTypes.object.isRequired, defaultValue: PropTypes.any, diff --git a/app/javascript/components/pdf-exporter/components/key-value-cell/component.unit.test.js b/app/javascript/components/pdf-exporter/components/key-value-cell/component.spec.js similarity index 58% rename from app/javascript/components/pdf-exporter/components/key-value-cell/component.unit.test.js rename to app/javascript/components/pdf-exporter/components/key-value-cell/component.spec.js index 1efd60b813..3876dba286 100644 --- a/app/javascript/components/pdf-exporter/components/key-value-cell/component.unit.test.js +++ b/app/javascript/components/pdf-exporter/components/key-value-cell/component.spec.js @@ -1,13 +1,9 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../../test"; +import { mountedComponent, screen } from "../../../../test-utils"; import KeyValueCell from "./component"; describe("components/record-actions/exports/components/pdf-exporter/components/key-value-cell", () => { - const state = fromJS({ + const state = { forms: { options: { lookups: [ @@ -23,7 +19,7 @@ describe("components/record-actions/exports/components/pdf-exporter/components/k ] } } - }); + }; it("renders key/value with string value", () => { const props = { @@ -33,23 +29,23 @@ describe("components/record-actions/exports/components/pdf-exporter/components/k classes: {} }; - const { component } = setupMountedComponent(KeyValueCell, props, state); + mountedComponent(, state); - expect(component.find("div div").at(0).text()).to.equal("Form 1"); - expect(component.find("div div").at(1).text()).to.equal("Option 1"); + expect(screen.getByText("Form 1")).toBeInTheDocument(); + expect(screen.getByText("Option 1")).toBeInTheDocument(); }); it("renders key/value with array value", () => { const props = { displayName: "Form 1", - value: fromJS(["option-1", "option-3"]), + value: "option-3", optionsStringSource: "lookup lookup-1", classes: {} }; - const { component } = setupMountedComponent(KeyValueCell, props, state); + mountedComponent(, state); - expect(component.find("div div").at(0).text()).to.equal("Form 1"); - expect(component.find("div div").at(1).text()).to.equal("Option 1, Option 3"); + expect(screen.getByText("Form 1")).toBeInTheDocument(); + expect(screen.getByText("Option 3")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/pdf-exporter/components/logos/component.jsx b/app/javascript/components/pdf-exporter/components/logos/component.jsx index 2c76335992..d1ba359a9d 100644 --- a/app/javascript/components/pdf-exporter/components/logos/component.jsx +++ b/app/javascript/components/pdf-exporter/components/logos/component.jsx @@ -3,9 +3,9 @@ import PropTypes from "prop-types"; import { useI18n } from "../../../i18n"; -import { RECORD_TYPES_PLURAL } from "../../../../config/constants"; +import { RECORD_TYPES_PLURAL } from "../../../../config"; -const Component = ({ shortId, recordType, logos, css }) => { +function Component({ shortId, recordType, logos = [], css }) { const i18n = useI18n(); if (!logos) return null; @@ -25,11 +25,7 @@ const Component = ({ shortId, recordType, logos, css }) => {
); -}; - -Component.defaultProps = { - logos: [] -}; +} Component.propTypes = { css: PropTypes.object, diff --git a/app/javascript/components/pdf-exporter/components/logos/component.unit.test.js b/app/javascript/components/pdf-exporter/components/logos/component.spec.js similarity index 60% rename from app/javascript/components/pdf-exporter/components/logos/component.unit.test.js rename to app/javascript/components/pdf-exporter/components/logos/component.spec.js index 203f9995f8..ca40d25853 100644 --- a/app/javascript/components/pdf-exporter/components/logos/component.unit.test.js +++ b/app/javascript/components/pdf-exporter/components/logos/component.spec.js @@ -1,6 +1,4 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../test"; +import { mountedComponent, screen } from "../../../../test-utils"; import Logos from "./component"; @@ -23,14 +21,14 @@ describe("", () => { }; it("renders Logos", () => { - const { component } = setupMountedComponent(Logos, props); + mountedComponent(); - expect(component.find(Logos)).to.have.lengthOf(1); + expect(screen.getByText(/exports.printed/i)).toBeInTheDocument(); }); it("renders img", () => { - const { component } = setupMountedComponent(Logos, props); + mountedComponent(); - expect(component.find("img")).to.have.lengthOf(2); + expect(screen.getAllByText((_, element) => element.tagName.toLowerCase() === "img")).toHaveLength(2); }); }); diff --git a/app/javascript/components/pdf-exporter/components/render-table/component.js b/app/javascript/components/pdf-exporter/components/render-table/component.js index c26b804a9f..7006255963 100644 --- a/app/javascript/components/pdf-exporter/components/render-table/component.js +++ b/app/javascript/components/pdf-exporter/components/render-table/component.js @@ -6,14 +6,14 @@ import Table from "../table"; import css from "./styles.css"; -const Component = ({ title, fields, data }) => { +function Component({ title, fields, data }) { return (

{title}

); -}; +} Component.displayName = "RenderTable"; diff --git a/app/javascript/components/pdf-exporter/components/signatures/component.jsx b/app/javascript/components/pdf-exporter/components/signatures/component.jsx index 2412b21e9b..08988bdeaa 100644 --- a/app/javascript/components/pdf-exporter/components/signatures/component.jsx +++ b/app/javascript/components/pdf-exporter/components/signatures/component.jsx @@ -7,7 +7,7 @@ import { useI18n } from "../../../i18n"; import css from "./styles.css"; import { SIGNATURE_LABELS } from "./constants"; -const Component = ({ types }) => { +function Component({ types = [] }) { const i18n = useI18n(); if (!types.length) return null; @@ -30,11 +30,7 @@ const Component = ({ types }) => { ))} ); -}; - -Component.defaultProps = { - types: [] -}; +} Component.propTypes = { types: PropTypes.array diff --git a/app/javascript/components/pdf-exporter/components/table/component.jsx b/app/javascript/components/pdf-exporter/components/table/component.jsx index 409ec9e2e7..9c7aba279b 100644 --- a/app/javascript/components/pdf-exporter/components/table/component.jsx +++ b/app/javascript/components/pdf-exporter/components/table/component.jsx @@ -14,7 +14,7 @@ import { import { EXCLUDED_FIELD_TYPES } from "./constants"; import css from "./styles.css"; -const Component = ({ fields, isSubform, record }) => { +function Component({ fields, isSubform = false, record }) { const i18n = useI18n(); const classes = { @@ -83,14 +83,10 @@ const Component = ({ fields, isSubform, record }) => { })} ); -}; +} Component.displayName = "Table"; -Component.defaultProps = { - isSubform: false -}; - Component.propTypes = { fields: PropTypes.array.isRequired, isSubform: PropTypes.bool, diff --git a/app/javascript/components/pdf-exporter/components/table/component.unit.test.js b/app/javascript/components/pdf-exporter/components/table/component.spec.js similarity index 66% rename from app/javascript/components/pdf-exporter/components/table/component.unit.test.js rename to app/javascript/components/pdf-exporter/components/table/component.spec.js index eab859b511..2253b1f149 100644 --- a/app/javascript/components/pdf-exporter/components/table/component.unit.test.js +++ b/app/javascript/components/pdf-exporter/components/table/component.spec.js @@ -2,8 +2,7 @@ import { fromJS } from "immutable"; -import { setupMountedComponent } from "../../../../test"; -import { FieldRecord, FormSectionRecord } from "../../../form"; +import { mountedComponent, screen } from "../../../../test-utils"; import Table from "./component"; @@ -17,25 +16,25 @@ describe("components/record-actions/exports/components/pdf-exporter/components/t const props = { classes, fields: [ - FieldRecord({ + { display_name: "Test SubField", - subform_section_id: FormSectionRecord({ + subform_section_id: { unique_id: "test_sub_form", fields: [ - FieldRecord({ + { display_name: "Test Sub Field Allowed", name: "allowed_field", type: "text_field", visible: true - }), - FieldRecord({ + }, + { display_name: "Test Sub Field Disallowed", name: "disallowed_field", type: "text_field", visible: true - }) + } ] - }), + }, subform_section_configuration: { fields: ["allowed_field"], display_conditions: [ @@ -46,7 +45,7 @@ describe("components/record-actions/exports/components/pdf-exporter/components/t }, name: "test_subform", type: "subform" - }) + } ], record: fromJS({ test_subform: [ @@ -55,40 +54,38 @@ describe("components/record-actions/exports/components/pdf-exporter/components/t ] }) }; - const { component } = setupMountedComponent(Table, props); - expect(component.html()).to.equal( - // eslint-disable-next-line max-len - `

Test SubField

Test Sub Field Allowed
josh
` - ); + mountedComponent(
); + + expect(screen.getByText("Test SubField")).toBeInTheDocument(); }); it("renders key/value with string value", () => { const props = { classes, fields: [ - FieldRecord({ + { display_name: "Test Field", name: "test_field", type: "text_field", visible: true - }), - FieldRecord({ + }, + { display_name: "Test SubField", - subform_section_id: FormSectionRecord({ + subform_section_id: { unique_id: "test_sub_form", fields: [ - FieldRecord({ + { display_name: "Test Sub Field", name: "test_sub_field", type: "text_field", visible: true - }) + } ] - }), + }, name: "test_subform", type: "subform" - }) + } ], record: fromJS({ test_field: "josh", @@ -96,31 +93,29 @@ describe("components/record-actions/exports/components/pdf-exporter/components/t }) }; - const { component } = setupMountedComponent(Table, props); + mountedComponent(
); - expect(component.html()).to.equal( - // eslint-disable-next-line max-len - `
Test Field
josh

Test SubField

Test Sub Field
anthony
` - ); + expect(screen.getByText("Test Field")).toBeInTheDocument(); + expect(screen.getByText(/anthony/i)).toBeInTheDocument(); }); it("should not render fields with hide_on_view_page true", () => { const props = { classes, fields: [ - FieldRecord({ + { display_name: "Test Field", name: "test_field", type: "text_field", visible: true - }), - FieldRecord({ + }, + { display_name: "Hidden Field", name: "hide_field", type: "text_field", visible: true, hide_on_view_page: true - }) + } ], record: fromJS({ test_field: "josh", @@ -128,8 +123,9 @@ describe("components/record-actions/exports/components/pdf-exporter/components/t }) }; - const { component } = setupMountedComponent(Table, props); + mountedComponent(
); - expect(component.html()).to.equal('
Test Field
josh
'); + expect(screen.getByText("Test Field")).toBeInTheDocument(); + expect(screen.getByText(/josh/i)).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/permissions/component.js b/app/javascript/components/permissions/component.js index 6e7a41c53e..8c9160ff85 100644 --- a/app/javascript/components/permissions/component.js +++ b/app/javascript/components/permissions/component.js @@ -7,13 +7,13 @@ import { useMemo } from "react"; import { useDispatch } from "react-redux"; import { useParams } from "react-router-dom"; -import { INCIDENT_FROM_CASE, MODES } from "../../config/constants"; +import { INCIDENT_FROM_CASE, MODES } from "../../config"; import useMemoizedSelector from "../../libs/use-memoized-selector"; import { getPermissions } from "../user/selectors"; import { RESOURCES } from "./constants"; -const Component = ({ resources, actions = [], redirect = false, children }) => { +function Component({ resources, actions = [], redirect = false, children }) { const { recordType } = useParams(); const type = resources || recordType; @@ -60,7 +60,7 @@ const Component = ({ resources, actions = [], redirect = false, children }) => { } return null; -}; +} Component.displayName = "Permission"; diff --git a/app/javascript/components/permissions/component.spec.js b/app/javascript/components/permissions/component.spec.js new file mode 100644 index 0000000000..5bd88ee161 --- /dev/null +++ b/app/javascript/components/permissions/component.spec.js @@ -0,0 +1,102 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen } from "../../test-utils"; +import { ROUTES } from "../../config"; + +import Permission from "./component"; + +import { ACTIONS, RESOURCES } from "."; + +describe("", () => { + const props = { + resources: RESOURCES.cases, + actions: ACTIONS.READ, + children:
, + match: { + isExact: true, + params: { recordType: RESOURCES.cases }, + path: "/:recordType(cases|incidents|tracing_requests)", + url: ROUTES.cases + } + }; + + const initialState = fromJS({ + user: { + permissions: { + cases: [ACTIONS.READ] + } + } + }); + + describe("When User have permission", () => { + it("renders children", () => { + mountedComponent(, initialState); + expect(screen.getByTestId("child-node")).toBeInTheDocument(); + }); + }); + + describe("When User doesn't have permission", () => { + const actions = "write"; + + const userProps = { + ...props, + actions + }; + + it("doesn't render children", () => { + mountedComponent(, initialState); + expect(screen.queryByTestId("child-node")).toBeNull(); + }); + }); + + describe("When url is present", () => { + const urlProps = { + actions: ACTIONS.READ, + children:
, + match: { + url: ROUTES.cases + } + }; + + it("doesn't render children", () => { + mountedComponent(, initialState); + expect(screen.queryByTestId("child-node")).toBeNull(); + }); + }); + + describe("When having multiple resources", () => { + const multipleProps = { + resources: [RESOURCES.cases, RESOURCES.incidents], + actions: [ACTIONS.READ, ACTIONS.EXPORT_EXCEL], + children:
, + match: { + url: "/cases" + } + }; + + it("renders children", () => { + mountedComponent(, initialState); + expect(screen.getByTestId("child-node")).toBeInTheDocument(); + }); + }); + + describe("When doesn't has the exact permissions", () => { + const wrongPermissionsProps = { + resources: RESOURCES.dashboards, + actions: ACTIONS.DASH_WORKFLOW_TEAM, + children:

Test

+ }; + const initialStateDashboad = fromJS({ + user: { + permissions: { + dashboards: [ACTIONS.DASH_WORKFLOW, ACTIONS.DASH_CASE_RISK] + } + } + }); + + it("doesn't render children", () => { + mountedComponent(, initialStateDashboad); + expect(screen.queryByTestId("child-node")).toBeNull(); + }); + }); +}); diff --git a/app/javascript/components/permissions/component.unit.test.js b/app/javascript/components/permissions/component.unit.test.js deleted file mode 100644 index c1c518e4ef..0000000000 --- a/app/javascript/components/permissions/component.unit.test.js +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../test"; -import { ROUTES } from "../../config"; - -import Permission from "./component"; - -import { ACTIONS, RESOURCES } from "."; - -describe("", () => { - let component; - const props = { - resources: RESOURCES.cases, - actions: ACTIONS.READ, - children:
, - match: { - isExact: true, - params: { recordType: RESOURCES.cases }, - path: "/:recordType(cases|incidents|tracing_requests)", - url: ROUTES.cases - } - }; - - const initialState = fromJS({ - user: { - permissions: { - cases: [ACTIONS.READ] - } - } - }); - - describe("When User have permission", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(Permission, props, initialState)); - }); - - it("renders Permission", () => { - expect(component.find(Permission)).to.have.lengthOf(1); - }); - - it("renders div", () => { - expect(component.find("div")).to.have.lengthOf(1); - }); - }); - - describe("When User doesn't have permission", () => { - const actions = "write"; - - beforeEach(() => { - ({ component } = setupMountedComponent( - Permission, - { - ...props, - actions - }, - initialState - )); - }); - - it("renders Permission", () => { - expect(component.find(Permission)).to.have.lengthOf(1); - }); - - it("doesn't render children", () => { - expect(component).to.be.empty; - }); - }); - - describe("When url is present", () => { - beforeEach(() => { - ({ component } = setupMountedComponent( - Permission, - { - actions: ACTIONS.READ, - children:
, - match: { - url: ROUTES.cases - } - }, - initialState - )); - }); - - it("doesn't render children", () => { - expect(component).to.be.empty; - }); - }); - - describe("When having multiple resources", () => { - beforeEach(() => { - ({ component } = setupMountedComponent( - Permission, - { - resources: [RESOURCES.cases, RESOURCES.incidents], - actions: [ACTIONS.READ, ACTIONS.EXPORT_EXCEL], - children:
, - match: { - url: "/cases" - } - }, - initialState - )); - }); - - it("renders children", () => { - expect(component.find(Permission)).to.have.lengthOf(1); - }); - }); - - describe("When doesn't has the exact permissions", () => { - const wrongPermissionsProps = { - resources: RESOURCES.dashboards, - actions: ACTIONS.DASH_WORKFLOW_TEAM, - children:

Test

- }; - const initialStateDashboad = fromJS({ - user: { - permissions: { - dashboards: [ACTIONS.DASH_WORKFLOW, ACTIONS.DASH_CASE_RISK] - } - } - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(Permission, wrongPermissionsProps, initialStateDashboad)); - }); - - it("doesn't render children", () => { - expect(component.find("h1")).to.be.empty; - }); - }); -}); diff --git a/app/javascript/components/permissions/constants.js b/app/javascript/components/permissions/constants.js index 3c513dc014..e2160bbc3a 100644 --- a/app/javascript/components/permissions/constants.js +++ b/app/javascript/components/permissions/constants.js @@ -43,7 +43,7 @@ export const ACTIONS = { DASH_NATIONAL_ADMIN_SUMMARY: "dash_national_admin_summary", DASH_PROTECTION_CONCERNS: "dash_protection_concerns", DASH_REPORTING_LOCATION: "dash_reporting_location", - DASH_SHARED_FROM_MY_TEAM: "dash_shared_with_my_team", + DASH_SHARED_FROM_MY_TEAM: "dash_shared_from_my_team", DASH_SHARED_WITH_ME: "dash_shared_with_me", DASH_SHARED_WITH_MY_TEAM_OVERVIEW: "dash_shared_with_my_team_overview", DASH_SHARED_WITH_MY_TEAM: "dash_shared_with_my_team", @@ -93,6 +93,7 @@ export const ACTIONS = { KPI_TIME_FROM_CASE_OPEN_TO_CLOSE: "kpi_time_from_case_open_to_close", MANAGE: "manage", MARK_FOR_OFFLINE: "sync_mobile", + LINK_INCIDENT_TO_CASE: "link_incident_to_case", READ: "read", RECEIVE_REFERRAL: "receive_referral", RECEIVE_TRANSFER: "receive_transfer", @@ -111,6 +112,7 @@ export const ACTIONS = { SERVICES_SECTION_FROM_CASE: "services_section_from_case", SYNC_EXTERNAL: "sync_external", TRANSFER: "transfer", + VERIFY_MRM: "verify_mrm", VIEW_INCIDENT_FROM_CASE: "view_incident_from_case", VIEW_REGISTRY_RECORD: "view_registry_record", VIOLATIONS: "violations", @@ -207,6 +209,8 @@ export const ADD_NOTE = [...MANAGE, ACTIONS.ADD_NOTE]; export const MARK_FOR_OFFLINE = [...MANAGE, ACTIONS.MARK_FOR_OFFLINE]; +export const LINK_INCIDENT_TO_CASE = [...MANAGE, ACTIONS.LINK_INCIDENT_TO_CASE]; + export const DISPLAY_VIEW_PAGE = [...MANAGE, ACTIONS.DISPLAY_VIEW_PAGE]; export const SHOW_TASKS = [...MANAGE, ACTIONS.DASH_TASKS]; diff --git a/app/javascript/components/permissions/constants.unit.test.js b/app/javascript/components/permissions/constants.unit.test.js index eca094ff73..56627f4719 100644 --- a/app/javascript/components/permissions/constants.unit.test.js +++ b/app/javascript/components/permissions/constants.unit.test.js @@ -82,6 +82,7 @@ describe("Verifying config constant", () => { "GROUP_READ", "INCIDENT_DETAILS_FROM_CASE", "INCIDENT_FROM_CASE", + "LINK_INCIDENT_TO_CASE", "KPI_ASSESSMENT_STATUS", "KPI_AVERAGE_FOLLOWUP_MEETINGS_PER_CASE", "KPI_AVERAGE_REFERRALS", @@ -119,6 +120,7 @@ describe("Verifying config constant", () => { "WORKFLOW_REPORT", "SYNC_EXTERNAL", "TRANSFER", + "VERIFY_MRM", "VIEW_FAMILY_RECORD", "VIEW_INCIDENT_FROM_CASE", "VIEW_REGISTRY_RECORD", diff --git a/app/javascript/components/permissions/use-permissions.unit.test.js b/app/javascript/components/permissions/use-permissions.spec.js similarity index 53% rename from app/javascript/components/permissions/use-permissions.unit.test.js rename to app/javascript/components/permissions/use-permissions.spec.js index c0a3f27d03..545848c963 100644 --- a/app/javascript/components/permissions/use-permissions.unit.test.js +++ b/app/javascript/components/permissions/use-permissions.spec.js @@ -2,22 +2,22 @@ import { fromJS } from "immutable"; -import { setupHook } from "../../test/utils"; +import { setupHook } from "../../test-utils"; -import * as PERMISSIONS from "./constants"; +import { ACTIONS } from "./constants"; import usePermissions from "./use-permissions"; describe("Verifying config constant", () => { it("handles single resource permission check", () => { - const { result } = setupHook(() => usePermissions("cases", [PERMISSIONS.ACTIONS.MANAGE]), { + const { result } = setupHook(() => usePermissions("cases", [ACTIONS.MANAGE]), { user: { permissions: { - cases: [PERMISSIONS.ACTIONS.MANAGE] + cases: [ACTIONS.MANAGE] } } }); - expect(result.current).to.eql(true); + expect(result.current).toBe(true); }); it("handles multiple resources permission checks", () => { @@ -31,26 +31,26 @@ describe("Verifying config constant", () => { const { result } = setupHook( () => usePermissions("cases", { - canManageCase: [PERMISSIONS.ACTIONS.READ], + canManageCase: [ACTIONS.READ], canApprove: [ - PERMISSIONS.ACTIONS.MANAGE, - PERMISSIONS.ACTIONS.APPROVE_ASSESSMENT, - PERMISSIONS.ACTIONS.APPROVE_CASE_PLAN, - PERMISSIONS.ACTIONS.APPROVE_CLOSURE, - PERMISSIONS.ACTIONS.APPROVE_ACTION_PLAN, - PERMISSIONS.ACTIONS.APPROVE_GBV_CLOSURE + ACTIONS.MANAGE, + ACTIONS.APPROVE_ASSESSMENT, + ACTIONS.APPROVE_CASE_PLAN, + ACTIONS.APPROVE_CLOSURE, + ACTIONS.APPROVE_ACTION_PLAN, + ACTIONS.APPROVE_GBV_CLOSURE ], - canDelete: [PERMISSIONS.ACTIONS.DELETE] + canDelete: [ACTIONS.DELETE] }), { user: { permissions: { - cases: [PERMISSIONS.ACTIONS.APPROVE_ASSESSMENT, PERMISSIONS.ACTIONS.DELETE] + cases: [ACTIONS.APPROVE_ASSESSMENT, ACTIONS.DELETE] } } } ); - expect(result.current).to.eql(expected); + expect(result.current).toStrictEqual(expected); }); }); diff --git a/app/javascript/components/push-notifications-toggle/action-creators.js b/app/javascript/components/push-notifications-toggle/action-creators.js index 8202b0ffda..55757e439f 100644 --- a/app/javascript/components/push-notifications-toggle/action-creators.js +++ b/app/javascript/components/push-notifications-toggle/action-creators.js @@ -2,7 +2,7 @@ /* eslint-disable import/prefer-default-export */ -import { METHODS, ROUTES } from "../../config/constants"; +import { METHODS, ROUTES } from "../../config"; import actions from "./actions"; diff --git a/app/javascript/components/push-notifications-toggle/component.jsx b/app/javascript/components/push-notifications-toggle/component.jsx index 8b4f177436..1ad360d25c 100644 --- a/app/javascript/components/push-notifications-toggle/component.jsx +++ b/app/javascript/components/push-notifications-toggle/component.jsx @@ -1,10 +1,10 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { CircularProgress, FormControlLabel, Switch } from "@material-ui/core"; +import { CircularProgress, FormControlLabel, Switch } from "@mui/material"; import PropTypes from "prop-types"; import { useEffect, useState } from "react"; -import NotificationsOffIcon from "@material-ui/icons/NotificationsOff"; -import NotificationsIcon from "@material-ui/icons/Notifications"; +import NotificationsOffIcon from "@mui/icons-material/NotificationsOff"; +import NotificationsIcon from "@mui/icons-material/Notifications"; import { useDispatch } from "react-redux"; import isNil from "lodash/isNil"; @@ -46,7 +46,7 @@ function Component({ isNotificationsSupported }) { const notificationsNotSupported = !isNotificationsSupported || !receiveWebpush; const notificationsDenied = () => Notification.permission === NOTIFICATION_PERMISSIONS.DENIED; - useEffect(async () => { + async function setNotificationData() { if (isNil(notificationEndpoint)) { const dbEndpoint = await Common.find({ collection: DB_STORES.PUSH_NOTIFICATION_SUBSCRIPTION }); @@ -54,6 +54,10 @@ function Component({ isNotificationsSupported }) { } else { setValue(await Boolean(notificationEndpoint)); } + } + + useEffect(() => { + setNotificationData(); }, []); const handleSwitch = opened => event => { diff --git a/app/javascript/components/push-notifications-toggle/use-push-notifications.js b/app/javascript/components/push-notifications-toggle/use-push-notifications.js index 37b2464527..816c5078bb 100644 --- a/app/javascript/components/push-notifications-toggle/use-push-notifications.js +++ b/app/javascript/components/push-notifications-toggle/use-push-notifications.js @@ -5,7 +5,7 @@ import { workerTimers } from "react-idle-timer"; import { useDispatch } from "react-redux"; import { useLocation } from "react-router-dom"; -import { POST_MESSAGES, PUSH_NOTIFICATION_SUBSCRIPTION_REFRESH_INTERVAL, ROUTES } from "../../config/constants"; +import { POST_MESSAGES, PUSH_NOTIFICATION_SUBSCRIPTION_REFRESH_INTERVAL, ROUTES } from "../../config"; import useMemoizedSelector from "../../libs/use-memoized-selector"; import { getNotificationSubscription, getUserProperty } from "../user/selectors"; import { toServerDateFormat } from "../../libs"; diff --git a/app/javascript/components/record-actions/add-incident/component.jsx b/app/javascript/components/record-actions/add-incident/component.jsx index 3d713184db..7cdea0f42e 100644 --- a/app/javascript/components/record-actions/add-incident/component.jsx +++ b/app/javascript/components/record-actions/add-incident/component.jsx @@ -23,7 +23,7 @@ import { NAME, INCIDENT_SUBFORM, INCIDENTS_SUBFORM_NAME } from "./constants"; import { validationSchema } from "./utils"; import Fields from "./fields"; -const Component = ({ open, close, pending, recordType, selectedRowsIndex, setPending }) => { +function Component({ open, close, pending, recordType, selectedRowsIndex, setPending }) { const formikRef = useRef(); const i18n = useI18n(); const dispatch = useDispatch(); @@ -127,7 +127,7 @@ const Component = ({ open, close, pending, recordType, selectedRowsIndex, setPen ); -}; +} Component.propTypes = { close: PropTypes.func, diff --git a/app/javascript/components/record-actions/add-incident/component.unit.test.js b/app/javascript/components/record-actions/add-incident/component.spec.js similarity index 78% rename from app/javascript/components/record-actions/add-incident/component.unit.test.js rename to app/javascript/components/record-actions/add-incident/component.spec.js index c74af6a929..2df191e429 100644 --- a/app/javascript/components/record-actions/add-incident/component.unit.test.js +++ b/app/javascript/components/record-actions/add-incident/component.spec.js @@ -1,18 +1,12 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Formik, Form } from "formik"; import { fromJS, Map, OrderedMap } from "immutable"; -import ActionDialog from "../../action-dialog"; -import { setupMountedComponent } from "../../../test"; +import { mountedComponent, screen } from "../../../test-utils"; import { FieldRecord, FormSectionRecord } from "../../record-form/records"; import { RECORD_PATH } from "../../../config"; -import Fields from "./fields"; import AddIncident from "./component"; describe("", () => { - let component; const initialState = Map({ records: fromJS({ cases: { @@ -123,33 +117,18 @@ describe("", () => { setPending: () => {} }; - beforeEach(() => { - ({ component } = setupMountedComponent(AddIncident, props, initialState)); - }); - - it("renders Formik", () => { - expect(component.find(Formik)).to.have.lengthOf(1); - }); - it("renders ActionDialog", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(screen.getByRole("dialog")).toBeInTheDocument(); }); it("renders Form", () => { - expect(component.find(Form)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "form")).toBeInTheDocument(); }); it("renders Fields", () => { - expect(component.find(Fields)).to.have.lengthOf(1); - }); - - it("renders component with valid props", () => { - const addIncidentProps = { ...component.find(AddIncident).props() }; - - ["close", "pending", "recordType", "selectedRowsIndex", "setPending", "open"].forEach(property => { - expect(addIncidentProps).to.have.property(property); - delete addIncidentProps[property]; - }); - expect(addIncidentProps).to.be.empty; + mountedComponent(, initialState); + expect(screen.queryAllByRole("textbox")).toHaveLength(1); }); }); diff --git a/app/javascript/components/record-actions/add-incident/fields/component.jsx b/app/javascript/components/record-actions/add-incident/fields/component.jsx index 5ab4b95dea..43ac078fd3 100644 --- a/app/javascript/components/record-actions/add-incident/fields/component.jsx +++ b/app/javascript/components/record-actions/add-incident/fields/component.jsx @@ -8,7 +8,7 @@ import { FieldRecord, FormSectionField } from "../../../record-form"; import { NAME } from "./constants"; -const Component = ({ recordModuleID, recordType, fields, formik }) => { +function Component({ recordModuleID, recordType, fields, formik }) { const [filterState, setFilterState] = useState({ filtersChanged: false, userIsSelected: false @@ -45,11 +45,13 @@ const Component = ({ recordModuleID, recordType, fields, formik }) => { } }; - return ; + return ( + + ); }); return <>{renderFields}; -}; +} Component.propTypes = { fields: PropTypes.array, diff --git a/app/javascript/components/record-actions/add-incident/fields/component.unit.test.js b/app/javascript/components/record-actions/add-incident/fields/component.spec.js similarity index 65% rename from app/javascript/components/record-actions/add-incident/fields/component.unit.test.js rename to app/javascript/components/record-actions/add-incident/fields/component.spec.js index 5d0fa84a4b..8717aa8bc2 100644 --- a/app/javascript/components/record-actions/add-incident/fields/component.unit.test.js +++ b/app/javascript/components/record-actions/add-incident/fields/component.spec.js @@ -1,16 +1,11 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - import { fromJS } from "immutable"; -import { setupMountedComponent } from "../../../../test"; -import { FormSectionField } from "../../../record-form"; +import { mountedComponent, screen } from "../../../../test-utils"; import { RECORD_PATH } from "../../../../config"; import Fields from "./component"; describe("", () => { - let component; - const props = { recordType: RECORD_PATH.cases, fields: [ @@ -62,21 +57,8 @@ describe("", () => { } }; - beforeEach(() => { - ({ component } = setupMountedComponent(Fields, props, initialState, [], formProps)); - }); - it("renders 1 FormSectionField", () => { - expect(component.find(FormSectionField)).to.have.lengthOf(1); - }); - - it("renders component with valid props", () => { - const addIncidentProps = { ...component.find(Fields).props() }; - - ["recordType", "fields"].forEach(property => { - expect(addIncidentProps).to.have.property(property); - delete addIncidentProps[property]; - }); - expect(addIncidentProps).to.be.empty; + mountedComponent(, initialState, {}, {}, formProps); + expect(screen.getByTestId("form-section-field")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/record-actions/add-service/component.jsx b/app/javascript/components/record-actions/add-service/component.jsx index 87d9b2a757..181aaa4b3d 100644 --- a/app/javascript/components/record-actions/add-service/component.jsx +++ b/app/javascript/components/record-actions/add-service/component.jsx @@ -21,7 +21,7 @@ import { useMemoizedSelector } from "../../../libs"; import { NAME, SERVICES_SUBFORM, SERVICES_SUBFORM_NAME } from "./constants"; -const Component = ({ open, close, pending, recordType, selectedRowsIndex, setPending }) => { +function Component({ open, close, pending, recordType, selectedRowsIndex, setPending }) { const formikRef = useRef(); const i18n = useI18n(); const dispatch = useDispatch(); @@ -117,7 +117,7 @@ const Component = ({ open, close, pending, recordType, selectedRowsIndex, setPen ); -}; +} Component.propTypes = { close: PropTypes.func, diff --git a/app/javascript/components/record-actions/add-service/component.unit.test.js b/app/javascript/components/record-actions/add-service/component.spec.js similarity index 80% rename from app/javascript/components/record-actions/add-service/component.unit.test.js rename to app/javascript/components/record-actions/add-service/component.spec.js index d2a1087556..6fd94051c7 100644 --- a/app/javascript/components/record-actions/add-service/component.unit.test.js +++ b/app/javascript/components/record-actions/add-service/component.spec.js @@ -1,18 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Formik, Form } from "formik"; import { fromJS, Map, OrderedMap } from "immutable"; -import ActionDialog from "../../action-dialog"; -import { setupMountedComponent } from "../../../test"; +import { mountedComponent, screen } from "../../../test-utils"; import { FieldRecord, FormSectionRecord } from "../../record-form/records"; import { RECORD_PATH } from "../../../config"; -import Fields from "../add-incident/fields"; import AddService from "./component"; describe("", () => { - let component; const initialState = Map({ records: fromJS({ cases: { @@ -124,33 +119,23 @@ describe("", () => { setPending: () => {} }; - beforeEach(() => { - ({ component } = setupMountedComponent(AddService, props, initialState)); - }); - it("renders Formik", () => { - expect(component.find(Formik)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "form")).toBeInTheDocument(); }); it("renders ActionDialog", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(screen.getByRole("dialog")).toBeInTheDocument(); }); it("renders Form", () => { - expect(component.find(Form)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "form")).toBeInTheDocument(); }); it("renders Fields", () => { - expect(component.find(Fields)).to.have.lengthOf(1); - }); - - it("renders component with valid props", () => { - const addService = { ...component.find(AddService).props() }; - - ["close", "pending", "recordType", "selectedRowsIndex", "setPending", "open"].forEach(property => { - expect(addService).to.have.property(property); - delete addService[property]; - }); - expect(addService).to.be.empty; + mountedComponent(, initialState); + expect(screen.queryAllByRole("textbox")).toHaveLength(1); }); }); diff --git a/app/javascript/components/record-actions/constants.js b/app/javascript/components/record-actions/constants.js index ac1a313891..c26a562e10 100644 --- a/app/javascript/components/record-actions/constants.js +++ b/app/javascript/components/record-actions/constants.js @@ -27,6 +27,7 @@ export const NOTES_DIALOG = "notes"; export const ENABLE_DISABLE_DIALOG = "enableDisable"; export const OPEN_CLOSE_DIALOG = "openClose"; export const MARK_FOR_OFFLINE_DIALOG = "markForOffline"; +export const LINK_INCIDENT_TO_CASE_DIALOG = "linkIncidentToCase"; export const ONE = "one"; export const MANY = "many"; @@ -63,5 +64,7 @@ export const RECORD_ACTION_ABILITIES = { canRequestGbvClosure: [ACTIONS.MANAGE, ACTIONS.REQUEST_APPROVAL_GBV_CLOSURE], canShowExports: SHOW_EXPORTS, canTransfer: [ACTIONS.MANAGE, ACTIONS.TRANSFER], - canMarkForOffline: [ACTIONS.MANAGE, ACTIONS.MARK_FOR_OFFLINE] + canMarkForOffline: [ACTIONS.MANAGE, ACTIONS.MARK_FOR_OFFLINE], + canLinkIncidentToCase: [ACTIONS.MANAGE, ACTIONS.LINK_INCIDENT_TO_CASE], + canVerify: [ACTIONS.MANAGE, ACTIONS.VERIFY_MRM] }; diff --git a/app/javascript/components/record-actions/constants.unit.test.js b/app/javascript/components/record-actions/constants.unit.test.js index 87f5307823..1022547a38 100644 --- a/app/javascript/components/record-actions/constants.unit.test.js +++ b/app/javascript/components/record-actions/constants.unit.test.js @@ -29,7 +29,8 @@ describe(" - Constants", () => { "ALL", "RECORD_ACTION_ABILITIES", "MARK_FOR_OFFLINE_DIALOG", - "FILTERS_TO_SKIP" + "FILTERS_TO_SKIP", + "LINK_INCIDENT_TO_CASE_DIALOG" ].forEach(property => { expect(constants).to.have.property(property); delete constants[property]; @@ -69,7 +70,9 @@ describe(" - Constants", () => { "canRequestGbvClosure", "canShowExports", "canTransfer", - "canMarkForOffline" + "canMarkForOffline", + "canVerify", + "canLinkIncidentToCase" ].forEach(property => { expect(recordActionAbilities).to.have.property(property); delete recordActionAbilities[property]; diff --git a/app/javascript/components/record-actions/container.jsx b/app/javascript/components/record-actions/container.jsx index 544e32d067..bcfcc4b4b4 100644 --- a/app/javascript/components/record-actions/container.jsx +++ b/app/javascript/components/record-actions/container.jsx @@ -32,20 +32,13 @@ import { ID_SEARCH, ENABLE_DISABLE_DIALOG, OPEN_CLOSE_DIALOG, - MARK_FOR_OFFLINE_DIALOG + MARK_FOR_OFFLINE_DIALOG, + LINK_INCIDENT_TO_CASE_DIALOG } from "./constants"; import { NAME } from "./config"; import { isDisabledAction, buildApprovalList, buildActionList, subformExists } from "./utils"; -const Container = ({ - currentPage, - mode, - record, - recordType, - selectedRecords, - clearSelectedRecords, - showListActions -}) => { +function Container({ currentPage, mode, record, recordType, selectedRecords, clearSelectedRecords, showListActions }) { const i18n = useI18n(); const { approvalsLabels } = useApp(); const { currentDialog, dialogClose, dialogOpen, pending, setDialog, setDialogPending } = useDialog([ @@ -60,7 +53,8 @@ const Container = ({ REQUEST_APPROVAL_DIALOG, SERVICE_DIALOG, TRANSFER_DIALOG, - MARK_FOR_OFFLINE_DIALOG + MARK_FOR_OFFLINE_DIALOG, + LINK_INCIDENT_TO_CASE_DIALOG ]); const { handleCreateIncident } = useIncidentFromCase({ record, mode }); @@ -120,7 +114,8 @@ const Container = ({ canTransfer, canOnlyExportPdf, permittedAbilities, - canMarkForOffline + canMarkForOffline, + canLinkIncidentToCase } = usePermissions(recordType, RECORD_ACTION_ABILITIES); const canOpenOrClose = (canReopen && openState === "reopen") || (canClose && openState === "close"); @@ -157,6 +152,7 @@ const Container = ({ canRequest, canShowExports, canMarkForOffline, + canLinkIncidentToCase, canTransfer, canOnlyExportPdf, enableState, @@ -202,7 +198,7 @@ const Container = ({ })} ); -}; +} Container.displayName = NAME; diff --git a/app/javascript/components/record-actions/container.spec.js b/app/javascript/components/record-actions/container.spec.js new file mode 100644 index 0000000000..64481ab90b --- /dev/null +++ b/app/javascript/components/record-actions/container.spec.js @@ -0,0 +1,1034 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { OrderedMap, fromJS } from "immutable"; + +import { mountedComponent, screen, fireEvent } from "../../test-utils"; +import { ACTIONS } from "../permissions"; +import { FieldRecord, FormSectionRecord } from "../record-form/records"; + +import RecordActions from "./container"; +import { + REQUEST_APPROVAL_DIALOG, + ENABLE_DISABLE_DIALOG, + NOTES_DIALOG, + OPEN_CLOSE_DIALOG, + TRANSFER_DIALOG, + EXPORT_DIALOG +} from "./constants"; + +describe("", () => { + const forms = { + formSections: OrderedMap({ + 1: FormSectionRecord({ + id: 1, + unique_id: "incident_details_subform_section", + name: { en: "Nested Incident Details Subform" }, + visible: false, + is_first_tab: false, + order: 20, + order_form_group: 110, + parent_form: "case", + editable: true, + module_ids: [], + form_group_id: "", + form_group_name: { en: "Nested Incident Details Subform" }, + fields: [2], + is_nested: true, + subform_prevent_item_removal: false, + collapsed_field_names: ["cp_incident_date", "cp_incident_violence_type"] + }), + 2: FormSectionRecord({ + id: 2, + unique_id: "incident_details_container", + name: { en: "Incident Details" }, + visible: true, + is_first_tab: false, + order: 0, + order_form_group: 30, + parent_form: "case", + editable: true, + module_ids: ["primeromodule-cp"], + form_group_id: "identification_registration", + form_group_name: { en: "Identification / Registration" }, + fields: [1], + is_nested: false, + subform_prevent_item_removal: false, + collapsed_field_names: [] + }), + 3: FormSectionRecord({ + id: 3, + unique_id: "services", + fields: [3], + visible: true, + parent_form: "case", + module_ids: ["primeromodule-cp"] + }), + 4: FormSectionRecord({ + id: 3, + unique_id: "services_section_subform", + fields: [4], + visible: true + }) + }), + fields: OrderedMap({ + 1: FieldRecord({ + name: "incident_details", + type: "subform", + editable: true, + disabled: false, + visible: true, + subform_section_id: 1, + help_text: { en: "" }, + display_name: { en: "" }, + multi_select: false, + option_strings_source: null, + option_strings_text: {}, + guiding_questions: "", + required: false, + date_validation: "default_date_validation", + hide_on_view_page: false, + date_include_time: false, + selected_value: "", + subform_sort_by: "summary_date", + show_on_minify_form: false + }), + 2: FieldRecord({ + name: "cp_incident_location_type_other", + type: "text_field", + editable: true, + disabled: false, + visible: true, + subform_section_id: null, + help_text: {}, + multi_select: false, + option_strings_source: null, + option_strings_text: {}, + guiding_questions: "", + required: false, + date_validation: "default_date_validation", + hide_on_view_page: false, + date_include_time: false, + selected_value: "", + subform_sort_by: "", + show_on_minify_form: false + }), + 3: FieldRecord({ + name: "services_section", + type: "subform", + subform_section_id: 4, + visible: true, + editable: true, + disabled: false + }), + 4: FieldRecord({ + name: "text_field_2", + type: "text_field", + visible: true + }) + }) + }; + + const defaultState = fromJS({ + records: { + cases: { + data: [ + { + sex: "female", + owned_by_agency_id: 1, + record_in_scope: true, + created_at: "2020-01-29T21:57:00.274Z", + name: "User 1", + alert_count: 0, + case_id_display: "b575f47", + owned_by: "primero_cp_ar", + status: "open", + registration_date: "2020-01-29", + id: "b342c488-578e-4f5c-85bc-35ece34cccdf", + flag_count: 0, + short_id: "b575f47", + age: 15, + workflow: "new" + } + ], + filters: { + status: ["true"] + } + } + }, + user: { + permissions: { + cases: [ACTIONS.MANAGE, ACTIONS.EXPORT_JSON] + } + }, + forms + }); + + const defaultStateWithDialog = dialog => + defaultState.merge( + fromJS({ + ui: { + dialogs: { + dialog, + open: true + } + } + }) + ); + + const props = { + recordType: "cases", + mode: { isShow: true }, + record: fromJS({ status: "open" }) + }; + + describe("Component ActionButton", () => { + it("should render and ActionButton component", () => { + mountedComponent(, defaultState); + expect(screen.queryAllByRole("button")).toHaveLength(1); + }); + + it("should not render and ActionButton component if there are not actions", () => { + mountedComponent( + , + fromJS({ + user: { + permissions: { + cases: ["gbv_referral_form", "record_owner"] + } + }, + forms + }) + ); + expect(screen.queryAllByRole("button")).toHaveLength(0); + }); + }); + + describe("Component ToggleOpen", () => { + it("renders ToggleOpen", () => { + mountedComponent(, defaultStateWithDialog(OPEN_CLOSE_DIALOG)); + expect(screen.queryByText(/cases.close_dialog_title/i)).toBeInTheDocument(); + expect(screen.queryAllByRole("dialog")).toHaveLength(1); + }); + }); + + describe("Component ToggleEnable", () => { + it("renders ToggleEnable", () => { + mountedComponent(, defaultStateWithDialog(ENABLE_DISABLE_DIALOG)); + expect(screen.queryByText(/cases.enable_dialog_title/i)).toBeInTheDocument(); + expect(screen.queryAllByRole("dialog")).toHaveLength(1); + }); + }); + + describe("Component RequestApproval", () => { + it("renders RequestApproval", () => { + mountedComponent(, defaultStateWithDialog(REQUEST_APPROVAL_DIALOG)); + + expect(screen.queryAllByText(/actions.request_approval/i)).toHaveLength(1); + }); + }); + + describe("Component Transitions", () => { + it("renders Transitions", () => { + mountedComponent(, defaultStateWithDialog(TRANSFER_DIALOG)); + + expect(screen.queryByText(/transition.type.transfer/i)).toBeInTheDocument(); + expect(screen.queryAllByText(/transfer.agency_label/i)).toHaveLength(2); + }); + }); + + describe("Component Notes", () => { + it("renders Notes", () => { + mountedComponent(, defaultStateWithDialog(NOTES_DIALOG)); + + expect(screen.queryByText(/notes_dialog_title/i)).toBeInTheDocument(); + expect(screen.queryAllByRole("dialog")).toHaveLength(1); + }); + }); + + describe("Component Menu", () => { + describe("when user has access to all menus", () => { + it("renders Menu", () => { + mountedComponent( + , + fromJS({ + records: { + cases: { + filters: { + id_search: true + } + } + }, + user: { + permissions: { + cases: [ACTIONS.MANAGE] + } + }, + forms + }) + ); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menu")).toBeInTheDocument(); + }); + + it("renders MenuItem", () => { + mountedComponent( + , + fromJS({ + records: { + cases: { + filters: { + id_search: true + } + } + }, + user: { + permissions: { + cases: [ACTIONS.MANAGE] + } + }, + forms + }) + ); + fireEvent.click(screen.getByRole("button")); + expect(screen.getAllByRole("menuitem")).toHaveLength(10); + }); + + it("renders MenuItem with Refer Cases option", () => { + mountedComponent( + , + fromJS({ + records: { + cases: { + filters: { + id_search: true + } + } + }, + user: { + permissions: { + cases: [ACTIONS.MANAGE] + } + }, + forms + }) + ); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem", { name: /buttons.referral forms.record_types.case/i })).toBeInTheDocument(); + }); + + it("renders MenuItem with Add Incident option", () => { + mountedComponent( + , + fromJS({ + records: { + cases: { + filters: { + id_search: true + } + } + }, + user: { + permissions: { + cases: [ACTIONS.MANAGE] + } + }, + forms + }) + ); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem", { name: /actions.incident_details_from_case/i })).toBeInTheDocument(); + }); + + it("renders MenuItem with Add Services Provision option", () => { + mountedComponent( + , + fromJS({ + records: { + cases: { + filters: { + id_search: true + } + } + }, + user: { + permissions: { + cases: [ACTIONS.MANAGE] + } + }, + forms + }) + ); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem", { name: /actions.services_section_from_case/i })).toBeInTheDocument(); + }); + + it("renders MenuItem with Export option", () => { + mountedComponent( + , + fromJS({ + records: { + cases: { + filters: { + id_search: true + } + } + }, + user: { + permissions: { + cases: [ACTIONS.MANAGE] + } + }, + forms + }) + ); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem", { name: /cases.export/i })).toBeInTheDocument(); + }); + + it("renders MenuItem with Create Incident option", () => { + mountedComponent( + , + fromJS({ + records: { + cases: { + filters: { + id_search: true + } + } + }, + user: { + permissions: { + cases: [ACTIONS.MANAGE] + } + }, + forms + }) + ); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem", { name: /actions.incident_from_case/i })).toBeInTheDocument(); + }); + }); + + describe("when user has not access to all menus", () => { + it("renders Menu", () => { + mountedComponent( + , + fromJS({ + user: { + permissions: { + cases: [ACTIONS.READ, ACTIONS.ADD_NOTE] + } + }, + forms + }) + ); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menu")).toBeInTheDocument(); + }); + + it("renders MenuItem", () => { + mountedComponent( + , + fromJS({ + user: { + permissions: { + cases: [ACTIONS.READ, ACTIONS.ADD_NOTE] + } + }, + forms + }) + ); + fireEvent.click(screen.getByRole("button")); + expect(screen.getAllByRole("menuitem")).toHaveLength(1); + }); + + it("renders MenuItem without Refer Cases option", () => { + mountedComponent( + , + fromJS({ + user: { + permissions: { + cases: [ACTIONS.READ] + } + }, + forms + }) + ); + expect(screen.queryByText(/buttons.referral forms.record_types.case/i)).toBeNull(); + }); + + it("renders MenuItem without Export custom option", () => { + mountedComponent( + , + fromJS({ + user: { + permissions: { + cases: [ACTIONS.READ] + } + }, + forms + }) + ); + expect(screen.queryByText(/exports.custom_exports.label/i)).toBeNull(); + }); + + it("renders MenuItem without Export option", () => { + mountedComponent( + , + fromJS({ + user: { + permissions: { + cases: [ACTIONS.READ] + } + }, + forms + }) + ); + expect(screen.queryByText(/cases.export/i)).toBeNull(); + }); + }); + + describe("when user has read access to cases and assign_within_agency", () => { + it("renders Menu", () => { + mountedComponent( + , + fromJS({ + user: { + permissions: { + cases: [ACTIONS.READ, ACTIONS.ASSIGN_WITHIN_AGENCY] + } + }, + forms + }) + ); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menu")).toBeInTheDocument(); + }); + + it("renders MenuItem", () => { + mountedComponent( + , + fromJS({ + user: { + permissions: { + cases: [ACTIONS.READ, ACTIONS.ASSIGN_WITHIN_AGENCY] + } + }, + forms + }) + ); + fireEvent.click(screen.getByRole("button")); + expect(screen.getAllByRole("menuitem")).toHaveLength(1); + }); + + it("renders MenuItem with the Assign Case option", () => { + mountedComponent( + , + fromJS({ + user: { + permissions: { + cases: [ACTIONS.READ, ACTIONS.ASSIGN_WITHIN_AGENCY] + } + }, + forms + }) + ); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem", { name: /buttons.reassign forms.record_types.case/i })).toBeInTheDocument(); + }); + }); + }); + + describe("Component Exports", () => { + it("renders Exports", () => { + mountedComponent(, defaultStateWithDialog(EXPORT_DIALOG)); + expect(screen.queryAllByRole("dialog")).toHaveLength(1); + expect(screen.getAllByText(/cases.export/i, { selector: "div" })).toHaveLength(1); + }); + + describe("when user can only export pdf", () => { + const state = fromJS({ + user: { + permissions: { + cases: [ACTIONS.READ, ACTIONS.EXPORT_PDF] + } + }, + forms + }); + + it("should not render component", () => { + mountedComponent(, state); + expect(screen.queryAllByRole("dialog")).toHaveLength(0); + }); + }); + }); + + describe("when record is selected", () => { + const propsRecordSelected = { + showListActions: true, + currentPage: 0, + selectedRecords: { 0: [0] }, + recordType: "cases", + mode: { + isShow: true + } + }; + + it("should not renders assign menu", () => { + mountedComponent(, defaultState); + fireEvent.click(screen.getByRole("button")); + expect(screen.queryByText(/buttons.reassign forms.record_types.case/i)).toBeInTheDocument(); + }); + + it("renders add incident menu", () => { + mountedComponent(, defaultState); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem", { name: /actions.incident_details_from_case/i })).toBeInTheDocument(); + }); + + it("should not renders transfer menu", () => { + mountedComponent(, defaultState); + fireEvent.click(screen.getByRole("button")); + expect(screen.queryByText(/buttons.transfer/i)).toBeNull(); + }); + + it("renders add service menu", () => { + mountedComponent(, defaultState); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem", { name: /actions.services_section_from_case/i })).toBeInTheDocument(); + }); + + it("renders add export menu", () => { + mountedComponent(, defaultState); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem", { name: /cases.export/i })).toBeInTheDocument(); + }); + }); + + describe("when record is selected from a search, id_search: true", () => { + const defaultStateFromSearch = fromJS({ + records: { + cases: { + data: [ + { + sex: "female", + owned_by_agency_id: 1, + record_in_scope: true, + created_at: "2020-01-29T21:57:00.274Z", + name: "User 1", + alert_count: 0, + case_id_display: "b575f47", + owned_by: "primero_cp_ar", + status: "open", + registration_date: "2020-01-29", + id: "b342c488-578e-4f5c-85bc-35ece34cccdf", + flag_count: 0, + short_id: "b575f47", + age: 15, + workflow: "new" + } + ], + filters: { + status: ["true"], + id_search: true + } + } + }, + user: { + permissions: { + cases: [ACTIONS.MANAGE] + } + }, + forms + }); + const propsRecordSelected = { + showListActions: true, + currentPage: 0, + selectedRecords: { 0: [0] }, + recordType: "cases", + mode: { + isShow: true + } + }; + + it("should not renders add refer menu", () => { + mountedComponent(, defaultStateFromSearch); + fireEvent.click(screen.getByRole("button")); + expect(screen.queryByText(/buttons.referral/i)).toBeNull(); + }); + + it("should not renders add reassign menu", () => { + mountedComponent(, defaultStateFromSearch); + fireEvent.click(screen.getByRole("button")); + expect(screen.queryByText(/buttons.reassign/i)).toBeNull(); + }); + + it("should not renders add transfer menu", () => { + mountedComponent(, defaultStateFromSearch); + fireEvent.click(screen.getByRole("button")); + expect(screen.queryByText(/buttons.transfer/i)).toBeNull(); + }); + + it("renders add incident menu", () => { + mountedComponent(, defaultStateFromSearch); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByText(/actions.incident_details_from_case/i)).toBeInTheDocument(); + }); + + it("renders add service menu", () => { + mountedComponent(, defaultStateFromSearch); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem", { name: /actions.services_section_from_case/i })).toBeInTheDocument(); + }); + + it("renders add export menu", () => { + mountedComponent(, defaultStateFromSearch); + fireEvent.click(screen.getByRole("button")); + expect(screen.queryByText(/cases.export/i)).toBeNull(); + }); + }); + + describe("when no records are selected", () => { + const propsRecordSelected = { + ...props, + showListActions: true, + currentPage: 0, + selectedRecords: {} + }; + + it("should not renders add refer menu enabled", () => { + mountedComponent(, defaultState); + fireEvent.click(screen.getByRole("button")); + expect(screen.queryByText(/buttons.referral/i)).toBeNull(); + }); + + it("should not renders add transfer menu disabled", () => { + mountedComponent(, defaultState); + fireEvent.click(screen.getByRole("button")); + expect(screen.queryByText(/buttons.transfer/i)).toBeNull(); + }); + + it("renders add incident menu disabled", () => { + mountedComponent(, defaultState); + fireEvent.click(screen.getByRole("button")); + expect( + screen.getByRole("menuitem", { name: /actions.incident_details_from_case/i, class: "Mui-disabled" }) + ).toBeInTheDocument(); + }); + + it("renders add service menu disabled", () => { + mountedComponent(, defaultState); + fireEvent.click(screen.getByRole("button")); + expect( + screen.getByRole("menuitem", { name: /actions.services_section_from_case/i, class: "Mui-disabled" }) + ).toBeInTheDocument(); + }); + + it("renders add export menu disabled", () => { + mountedComponent(, defaultState); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem", { name: /cases.export/i, class: "Mui-disabled" })).toBeInTheDocument(); + }); + }); + + describe("when many records are selected", () => { + const propsRecordSelected = { + ...props, + showListActions: true, + currentPage: 0, + selectedRecords: { 0: [0, 1] } + }; + + const defaultStateRecordSelected = fromJS({ + records: { + cases: { + data: [ + { + sex: "female", + owned_by_agency_id: 1, + record_in_scope: true, + created_at: "2020-01-29T21:57:00.274Z", + name: "User 1", + alert_count: 0, + case_id_display: "b575f47", + owned_by: "primero_cp_ar", + status: "open", + registration_date: "2020-01-29", + id: "b342c488-578e-4f5c-85bc-35ece34cccdf", + flag_count: 0, + short_id: "b575f47", + age: 15, + workflow: "new" + }, + { + sex: "male", + owned_by_agency_id: 1, + record_in_scope: true, + created_at: "2020-02-29T21:57:00.274Z", + name: "User 1", + alert_count: 0, + case_id_display: "c23a5fca", + owned_by: "primero_cp", + status: "open", + registration_date: "2020-05-02", + id: "b342c488-578e-4f5c-85bc-35ecec23a5fca", + flag_count: 0, + short_id: "c23a5fca", + age: 5, + workflow: "new" + } + ], + metadata: { + total: 3, + per: 20, + page: 1 + }, + filters: { + status: ["true"] + } + } + }, + user: { + permissions: { + cases: [ACTIONS.MANAGE] + } + }, + forms + }); + + it("renders assign menu", () => { + mountedComponent(, defaultState); + fireEvent.click(screen.getByRole("button")); + expect(screen.queryByText(/buttons.reassign forms.record_types.case/i)).toBeInTheDocument(); + }); + + it("should not renders add refer menu", () => { + mountedComponent(, defaultStateRecordSelected); + fireEvent.click(screen.getByRole("button")); + expect(screen.queryByText(/buttons.referral/i)).toBeNull(); + }); + + it("should not renders add transfer menu", () => { + mountedComponent(, defaultStateRecordSelected); + fireEvent.click(screen.getByRole("button")); + expect(screen.queryByText(/buttons.transfer/i)).toBeNull(); + }); + + it("renders add incident menu", () => { + mountedComponent(, defaultStateRecordSelected); + fireEvent.click(screen.getByRole("button")); + expect( + screen.getByRole("menuitem", { name: /actions.incident_details_from_case/i, class: "Mui-disabled" }) + ).toBeInTheDocument(); + }); + + it("renders add service menu", () => { + mountedComponent(, defaultStateRecordSelected); + fireEvent.click(screen.getByRole("button")); + expect( + screen.getByRole("menuitem", { name: /actions.services_section_from_case/i, class: "Mui-disabled" }) + ).toBeInTheDocument(); + }); + + it("renders add export menu", () => { + mountedComponent(, defaultStateRecordSelected); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByText(/cases.export/i)).toBeInTheDocument(); + }); + }); + + describe("when all the records are selected", () => { + const propsRecordSelected = { + ...props, + showListActions: true, + currentPage: 0, + selectedRecords: { 0: [0, 1, 2] } + }; + const defaultStateAllRecordSelected = fromJS({ + records: { + cases: { + data: [ + { + sex: "female", + owned_by_agency_id: 1, + record_in_scope: true, + created_at: "2020-01-29T21:57:00.274Z", + name: "User 1", + alert_count: 0, + case_id_display: "b575f47", + owned_by: "primero_cp_ar", + status: "open", + registration_date: "2020-01-29", + id: "b342c488-578e-4f5c-85bc-35ece34cccdf", + flag_count: 0, + short_id: "b575f47", + age: 15, + workflow: "new" + }, + { + sex: "male", + owned_by_agency_id: 1, + record_in_scope: true, + created_at: "2020-02-29T21:57:00.274Z", + name: "User 1", + alert_count: 0, + case_id_display: "c23a5fca", + owned_by: "primero_cp", + status: "open", + registration_date: "2020-05-02", + id: "b342c488-578e-4f5c-85bc-35ecec23a5fca", + flag_count: 0, + short_id: "c23a5fca", + age: 5, + workflow: "new" + }, + { + sex: "female", + owned_by_agency_id: 1, + record_in_scope: true, + created_at: "2020-03-18T21:57:00.274Z", + name: "User 1", + alert_count: 0, + case_id_display: "9C68741", + owned_by: "primero_cp", + status: "open", + registration_date: "2020-04-18", + id: "d861c56c-8dc9-41c9-974b-2b24299b70a2", + flag_count: 0, + short_id: "9C68741", + age: 7, + workflow: "new" + } + ], + metadata: { + total: 3, + per: 20, + page: 1 + }, + filters: { + status: ["true"] + } + } + }, + user: { + permissions: { + cases: [ACTIONS.MANAGE] + } + }, + forms + }); + + it("should not renders add refer menu", () => { + mountedComponent(, defaultStateAllRecordSelected); + fireEvent.click(screen.getByRole("button")); + expect(screen.queryByText(/buttons.referral/i)).toBeNull(); + }); + + it("should not renders add transfer menu", () => { + mountedComponent(, defaultStateAllRecordSelected); + fireEvent.click(screen.getByRole("button")); + expect(screen.queryByText(/buttons.transfer/i)).toBeNull(); + }); + + it("renders add incident menu disabled", () => { + mountedComponent(, defaultStateAllRecordSelected); + fireEvent.click(screen.getByRole("button")); + expect( + screen.getByRole("menuitem", { name: /actions.incident_details_from_case/i, class: "Mui-disabled" }) + ).toBeInTheDocument(); + }); + + it("renders add service menu", () => { + mountedComponent(, defaultStateAllRecordSelected); + fireEvent.click(screen.getByRole("button")); + expect( + screen.getByRole("menuitem", { name: /actions.services_section_from_case/i, class: "Mui-disabled" }) + ).toBeInTheDocument(); + }); + + it("renders add export menu", () => { + mountedComponent(, defaultStateAllRecordSelected); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem", { name: /cases.export/i })).toBeInTheDocument(); + }); + }); + + describe("when incident subform is not presented", () => { + const newForms = { + formSections: OrderedMap({ + 1: FormSectionRecord({ + id: 1, + unique_id: "incident_details_container", + name: { en: "Incident Details" }, + visible: true, + parent_form: "case", + editable: true, + module_ids: ["primeromodule-cp"], + fields: [1] + }), + 2: FormSectionRecord({ + id: 2, + unique_id: "services", + fields: [2], + visible: true, + parent_form: "case", + module_ids: ["primeromodule-cp"] + }) + }), + fields: OrderedMap({ + 1: FieldRecord({ + name: "incident_details", + type: "subform", + subform_section_id: null, + editable: true, + disabled: false, + visible: true + }), + 2: FieldRecord({ + name: "services_section", + type: "subform", + subform_section_id: null, + visible: true, + editable: true, + disabled: false + }) + }) + }; + const state = fromJS({ + records: { + cases: { + data: [ + { + sex: "female", + owned_by_agency_id: 1, + record_in_scope: true, + created_at: "2020-01-29T21:57:00.274Z", + name: "User 1", + case_id_display: "b575f47", + id: "b342c488-578e-4f5c-85bc-35ece34cccdf" + } + ], + filters: { + status: ["true"] + } + } + }, + user: { + permissions: { + cases: [ACTIONS.MANAGE] + } + }, + forms: newForms + }); + + it("should not render AddIncident component", () => { + mountedComponent(, state); + expect(screen.queryAllByText(/incident.messages.creation_success/i)).toHaveLength(0); + }); + + it("should not render AddService component", () => { + mountedComponent(, state); + expect(screen.queryAllByText(/actions.services_section_from_case/i)).toHaveLength(0); + }); + }); +}); diff --git a/app/javascript/components/record-actions/container.unit.test.js b/app/javascript/components/record-actions/container.unit.test.js deleted file mode 100644 index d4dd61694c..0000000000 --- a/app/javascript/components/record-actions/container.unit.test.js +++ /dev/null @@ -1,1055 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { OrderedMap, fromJS } from "immutable"; -import { Menu, MenuItem } from "@material-ui/core"; - -import { setupMountedComponent } from "../../test"; -import { ACTIONS } from "../permissions"; -import { FieldRecord, FormSectionRecord } from "../record-form/records"; -import ActionButton from "../action-button"; - -import Notes from "./notes"; -import RecordActions from "./container"; -import ToggleEnable from "./toggle-enable"; -import ToggleOpen from "./toggle-open"; -import RequestApproval from "./request-approval"; -import Transitions from "./transitions"; -import Exports from "./exports"; -import AddIncident from "./add-incident"; -import AddService from "./add-service"; -import { - REQUEST_APPROVAL_DIALOG, - ENABLE_DISABLE_DIALOG, - NOTES_DIALOG, - OPEN_CLOSE_DIALOG, - TRANSFER_DIALOG, - EXPORT_DIALOG -} from "./constants"; - -describe("", () => { - const forms = { - formSections: OrderedMap({ - 1: FormSectionRecord({ - id: 1, - unique_id: "incident_details_subform_section", - name: { en: "Nested Incident Details Subform" }, - visible: false, - is_first_tab: false, - order: 20, - order_form_group: 110, - parent_form: "case", - editable: true, - module_ids: [], - form_group_id: "", - form_group_name: { en: "Nested Incident Details Subform" }, - fields: [2], - is_nested: true, - subform_prevent_item_removal: false, - collapsed_field_names: ["cp_incident_date", "cp_incident_violence_type"] - }), - 2: FormSectionRecord({ - id: 2, - unique_id: "incident_details_container", - name: { en: "Incident Details" }, - visible: true, - is_first_tab: false, - order: 0, - order_form_group: 30, - parent_form: "case", - editable: true, - module_ids: ["primeromodule-cp"], - form_group_id: "identification_registration", - form_group_name: { en: "Identification / Registration" }, - fields: [1], - is_nested: false, - subform_prevent_item_removal: false, - collapsed_field_names: [] - }), - 3: FormSectionRecord({ - id: 3, - unique_id: "services", - fields: [3], - visible: true, - parent_form: "case", - module_ids: ["primeromodule-cp"] - }), - 4: FormSectionRecord({ - id: 3, - unique_id: "services_section_subform", - fields: [4], - visible: true - }) - }), - fields: OrderedMap({ - 1: FieldRecord({ - name: "incident_details", - type: "subform", - editable: true, - disabled: false, - visible: true, - subform_section_id: 1, - help_text: { en: "" }, - display_name: { en: "" }, - multi_select: false, - option_strings_source: null, - option_strings_text: {}, - guiding_questions: "", - required: false, - date_validation: "default_date_validation", - hide_on_view_page: false, - date_include_time: false, - selected_value: "", - subform_sort_by: "summary_date", - show_on_minify_form: false - }), - 2: FieldRecord({ - name: "cp_incident_location_type_other", - type: "text_field", - editable: true, - disabled: false, - visible: true, - subform_section_id: null, - help_text: {}, - multi_select: false, - option_strings_source: null, - option_strings_text: {}, - guiding_questions: "", - required: false, - date_validation: "default_date_validation", - hide_on_view_page: false, - date_include_time: false, - selected_value: "", - subform_sort_by: "", - show_on_minify_form: false - }), - 3: FieldRecord({ - name: "services_section", - type: "subform", - subform_section_id: 4, - visible: true, - editable: true, - disabled: false - }), - 4: FieldRecord({ - name: "text_field_2", - type: "text_field", - visible: true - }) - }) - }; - let component; - - const defaultState = fromJS({ - records: { - cases: { - data: [ - { - sex: "female", - owned_by_agency_id: 1, - record_in_scope: true, - created_at: "2020-01-29T21:57:00.274Z", - name: "User 1", - alert_count: 0, - case_id_display: "b575f47", - owned_by: "primero_cp_ar", - status: "open", - registration_date: "2020-01-29", - id: "b342c488-578e-4f5c-85bc-35ece34cccdf", - flag_count: 0, - short_id: "b575f47", - age: 15, - workflow: "new" - } - ], - filters: { - status: ["true"] - } - } - }, - user: { - permissions: { - cases: [ACTIONS.MANAGE, ACTIONS.EXPORT_JSON] - } - }, - forms - }); - - const defaultStateWithDialog = dialog => - defaultState.merge( - fromJS({ - ui: { - dialogs: { - dialog, - open: true - } - } - }) - ); - - const props = { - recordType: "cases", - mode: { isShow: true }, - record: fromJS({ status: "open" }) - }; - - describe("Component ActionButton", () => { - it("should render and ActionButton component", () => { - ({ component } = setupMountedComponent(RecordActions, props, defaultState)); - expect(component.find(ActionButton)).to.have.lengthOf(1); - }); - - it("should not render and ActionButton component if there are not actions", () => { - ({ component } = setupMountedComponent( - RecordActions, - props, - fromJS({ - user: { - permissions: { - cases: ["gbv_referral_form", "record_owner"] - } - }, - forms - }) - )); - expect(component.find(ActionButton)).to.be.empty; - }); - }); - - describe("Component ToggleOpen", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(RecordActions, props, defaultStateWithDialog(OPEN_CLOSE_DIALOG))); - }); - - it("renders ToggleOpen", () => { - expect(component.find(ToggleOpen)).to.have.length(1); - }); - }); - - describe("Component ToggleEnable", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(RecordActions, props, defaultStateWithDialog(ENABLE_DISABLE_DIALOG))); - }); - - it("renders ToggleEnable", () => { - expect(component.find(ToggleEnable)).to.have.length(1); - }); - }); - - describe("Component RequestApproval", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(RecordActions, props, defaultStateWithDialog(REQUEST_APPROVAL_DIALOG))); - }); - - it("renders RequestApproval", () => { - expect(component.find(RequestApproval)).to.have.length(1); - }); - }); - - describe("Component Transitions", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(RecordActions, props, defaultStateWithDialog(TRANSFER_DIALOG))); - }); - it("renders Transitions", () => { - expect(component.find(Transitions)).to.have.length(1); - }); - - it("renders valid props for Transitions components", () => { - const transitionsProps = { ...component.find(Transitions).props() }; - - expect(component.find(Transitions)).to.have.lengthOf(1); - [ - "open", - "record", - "recordType", - "userPermissions", - "pending", - "setPending", - "currentPage", - "selectedRecords", - "close", - "currentDialog", - "selectedRowsIndex", - "mode", - "clearSelectedRecords" - ].forEach(property => { - expect(transitionsProps).to.have.property(property); - delete transitionsProps[property]; - }); - expect(transitionsProps).to.be.empty; - }); - }); - - describe("Component Notes", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(RecordActions, props, defaultStateWithDialog(NOTES_DIALOG))); - }); - - it("renders Notes", () => { - expect(component.find(Notes)).to.have.length(1); - }); - }); - - describe("Component Menu", () => { - describe("when user has access to all menus", () => { - beforeEach(() => { - ({ component } = setupMountedComponent( - RecordActions, - props, - fromJS({ - records: { - cases: { - filters: { - id_search: true - } - } - }, - user: { - permissions: { - cases: [ACTIONS.MANAGE] - } - }, - forms - }) - )); - }); - it("renders Menu", () => { - expect(component.find(Menu)).to.have.length(1); - }); - - it("renders MenuItem", () => { - expect(component.find(MenuItem)).to.have.length(10); - }); - - it("renders MenuItem with Refer Cases option", () => { - expect( - component - .find("li") - .map(l => l.text()) - .includes("buttons.referral forms.record_types.case") - ).to.be.equal(true); - }); - - it("renders MenuItem with Add Incident option", () => { - expect( - component - .find("li") - .map(l => l.text()) - .includes("actions.incident_details_from_case") - ).to.be.false; - }); - - it("renders MenuItem with Add Services Provision option", () => { - expect( - component - .find("li") - .map(l => l.text()) - .includes("actions.services_section_from_case") - ).to.be.false; - }); - - it("renders MenuItem with Export option", () => { - expect( - component - .find("li") - .map(l => l.text()) - .includes("cases.export") - ).to.be.true; - }); - - it("renders MenuItem with Create Incident option", () => { - expect( - component - .find("li") - .map(l => l.text()) - .includes("actions.incident_from_case") - ).to.be.true; - }); - }); - - describe("when user has not access to all menus", () => { - beforeEach(() => { - ({ component } = setupMountedComponent( - RecordActions, - props, - fromJS({ - user: { - permissions: { - cases: [ACTIONS.READ] - } - }, - forms - }) - )); - }); - - it("renders Menu", () => { - expect(component.find(Menu)).to.have.length(1); - }); - - it("renders MenuItem", () => { - expect(component.find(MenuItem)).to.be.empty; - }); - - it("renders MenuItem without Refer Cases option", () => { - expect( - component - .find("li") - .map(l => l.text()) - .includes("buttons.referral forms.record_types.case") - ).to.be.false; - }); - - it("renders MenuItem without Export custom option", () => { - expect( - component - .find("li") - .map(l => l.text()) - .includes("exports.custom_exports.label") - ).to.be.false; - }); - - it("renders MenuItem without Export option", () => { - expect( - component - .find("li") - .map(l => l.text()) - .includes("cases.export") - ).to.be.false; - }); - }); - - describe("when user has read access to cases and assign_within_agency", () => { - beforeEach(() => { - ({ component } = setupMountedComponent( - RecordActions, - props, - fromJS({ - user: { - permissions: { - cases: [ACTIONS.READ, ACTIONS.ASSIGN_WITHIN_AGENCY] - } - }, - forms - }) - )); - }); - - it("renders Menu", () => { - expect(component.find(Menu)).to.have.length(1); - }); - - it("renders MenuItem", () => { - expect(component.find(MenuItem)).to.be.empty; - }); - - it("renders MenuItem with the Assign Case option", () => { - expect( - component - .find("li") - .map(l => l.text()) - .includes("buttons.reassign forms.record_types.case") - ).to.be.true; - }); - }); - }); - - describe("Component Exports", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(RecordActions, props, defaultStateWithDialog(EXPORT_DIALOG))); - }); - - it("renders Exports", () => { - expect(component.find(Exports)).to.have.lengthOf(1); - }); - - it("renders valid props for Exports components", () => { - const exportProps = { ...component.find(Exports).props() }; - - expect(component.find(Exports)).to.have.lengthOf(1); - [ - "close", - "currentPage", - "open", - "pending", - "record", - "recordType", - "selectedRecords", - "setPending", - "userPermissions", - "currentDialog", - "selectedRowsIndex", - "mode", - "clearSelectedRecords" - ].forEach(property => { - expect(exportProps).to.have.property(property); - delete exportProps[property]; - }); - expect(exportProps).to.be.empty; - }); - - describe("when user can only export pdf", () => { - const state = fromJS({ - user: { - permissions: { - cases: [ACTIONS.READ, ACTIONS.EXPORT_PDF] - } - }, - forms - }); - - it("should not render component", () => { - const { component: componentWithOnlyPdf } = setupMountedComponent(RecordActions, props, state); - - expect(componentWithOnlyPdf.find(Exports)).to.be.empty; - }); - }); - }); - - describe("when record is selected", () => { - const propsRecordSelected = { - ...props, - showListActions: true, - currentPage: 0, - selectedRecords: { 0: [0] } - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(RecordActions, propsRecordSelected, defaultState)); - }); - - it.skip("renders add refer menu enabled", () => { - const incidentItem = component.find(MenuItem).at(0); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.referral forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it("renders add reassign menu enabled", () => { - const incidentItem = component.find(MenuItem).at(0); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.reassign forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it("renders add incident menu disabled", () => { - const incidentItem = component.find(MenuItem).at(1); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("actions.incident_details_from_case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it.skip("renders add transfer menu enabled", () => { - const incidentItem = component.find(MenuItem).at(1); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.transfer forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it("renders add service menu disabled", () => { - const incidentItem = component.find(MenuItem).at(2); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("actions.services_section_from_case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it("renders add export menu enabled", () => { - const incidentItem = component.find(MenuItem).at(4); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("cases.export"); - expect(incidentItemProps.disabled).to.be.false; - }); - }); - - describe("when record is selected from a search, id_search: true", () => { - const defaultStateFromSearch = fromJS({ - records: { - cases: { - data: [ - { - sex: "female", - owned_by_agency_id: 1, - record_in_scope: true, - created_at: "2020-01-29T21:57:00.274Z", - name: "User 1", - alert_count: 0, - case_id_display: "b575f47", - owned_by: "primero_cp_ar", - status: "open", - registration_date: "2020-01-29", - id: "b342c488-578e-4f5c-85bc-35ece34cccdf", - flag_count: 0, - short_id: "b575f47", - age: 15, - workflow: "new" - } - ], - filters: { - status: ["true"], - id_search: true - } - } - }, - user: { - permissions: { - cases: [ACTIONS.MANAGE] - } - }, - forms - }); - const propsRecordSelected = { - ...props, - showListActions: true, - currentPage: 0, - selectedRecords: { 0: [0] } - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(RecordActions, propsRecordSelected, defaultStateFromSearch)); - }); - - it.skip("renders add refer menu enabled", () => { - const incidentItem = component.find(MenuItem).at(0); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.referral forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it.skip("renders add reassign menu enabled", () => { - const incidentItem = component.find(MenuItem).at(0); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.reassign forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it.skip("renders add transfer menu enabled", () => { - const incidentItem = component.find(MenuItem).at(2); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.transfer forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it.skip("renders add incident menu enabled", () => { - const incidentItem = component.find(MenuItem).at(3); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("actions.incident_details_from_case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it.skip("renders add service menu enabled", () => { - const incidentItem = component.find(MenuItem).at(5); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("actions.services_section_from_case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it.skip("renders add export menu enabled", () => { - const incidentItem = component.find(MenuItem).at(3); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("cases.export"); - expect(incidentItemProps.disabled).to.be.false; - }); - }); - - describe("when no record is selected", () => { - const propsRecordSelected = { - ...props, - showListActions: true, - currentPage: 0, - selectedRecords: {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(RecordActions, propsRecordSelected, defaultState)); - }); - - it.skip("renders add refer menu disabled", () => { - const incidentItem = component.find(MenuItem).at(0); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.referral forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.true; - }); - - it.skip("renders add transfer menu disabled", () => { - const incidentItem = component.find(MenuItem).at(2); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.transfer forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.true; - }); - - it("renders add reassign menu disabled", () => { - const incidentItem = component.find(MenuItem).at(0); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.reassign forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.true; - }); - - it("renders add incident menu disabled", () => { - const incidentItem = component.find(MenuItem).at(1); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("actions.incident_details_from_case"); - expect(incidentItemProps.disabled).to.be.true; - }); - - it("renders add service menu disabled", () => { - const incidentItem = component.find(MenuItem).at(2); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("actions.services_section_from_case"); - expect(incidentItemProps.disabled).to.be.true; - }); - - it("renders add export menu disabled", () => { - const incidentItem = component.find(MenuItem).at(4); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("cases.export"); - expect(incidentItemProps.disabled).to.be.true; - }); - }); - - describe("when many records are selected", () => { - const propsRecordSelected = { - ...props, - showListActions: true, - currentPage: 0, - selectedRecords: { 0: [0, 1] } - }; - - const defaultStateRecordSelected = fromJS({ - records: { - cases: { - data: [ - { - sex: "female", - owned_by_agency_id: 1, - record_in_scope: true, - created_at: "2020-01-29T21:57:00.274Z", - name: "User 1", - alert_count: 0, - case_id_display: "b575f47", - owned_by: "primero_cp_ar", - status: "open", - registration_date: "2020-01-29", - id: "b342c488-578e-4f5c-85bc-35ece34cccdf", - flag_count: 0, - short_id: "b575f47", - age: 15, - workflow: "new" - }, - { - sex: "male", - owned_by_agency_id: 1, - record_in_scope: true, - created_at: "2020-02-29T21:57:00.274Z", - name: "User 1", - alert_count: 0, - case_id_display: "c23a5fca", - owned_by: "primero_cp", - status: "open", - registration_date: "2020-05-02", - id: "b342c488-578e-4f5c-85bc-35ecec23a5fca", - flag_count: 0, - short_id: "c23a5fca", - age: 5, - workflow: "new" - } - ], - metadata: { - total: 3, - per: 20, - page: 1 - }, - filters: { - status: ["true"] - } - } - }, - user: { - permissions: { - cases: [ACTIONS.MANAGE] - } - }, - forms - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(RecordActions, propsRecordSelected, defaultStateRecordSelected)); - }); - - it.skip("renders add refer menu enabled", () => { - const incidentItem = component.find(MenuItem).at(0); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.referral forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it.skip("renders add transfer menu enabled", () => { - const incidentItem = component.find(MenuItem).at(2); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.transfer forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it("renders add reassign menu enabled", () => { - const incidentItem = component.find(MenuItem).at(0); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.reassign forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it("renders add incident menu disabled", () => { - const incidentItem = component.find(MenuItem).at(1); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("actions.incident_details_from_case"); - expect(incidentItemProps.disabled).to.be.true; - }); - - it("renders add service menu disabled", () => { - const incidentItem = component.find(MenuItem).at(2); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("actions.services_section_from_case"); - expect(incidentItemProps.disabled).to.be.true; - }); - - it("renders add export menu enabled", () => { - const incidentItem = component.find(MenuItem).at(4); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("cases.export"); - expect(incidentItemProps.disabled).to.be.false; - }); - }); - - describe("when all the records are selected", () => { - const propsRecordSelected = { - ...props, - showListActions: true, - currentPage: 0, - selectedRecords: { 0: [0, 1, 2] } - }; - const defaultStateAllRecordSelected = fromJS({ - records: { - cases: { - data: [ - { - sex: "female", - owned_by_agency_id: 1, - record_in_scope: true, - created_at: "2020-01-29T21:57:00.274Z", - name: "User 1", - alert_count: 0, - case_id_display: "b575f47", - owned_by: "primero_cp_ar", - status: "open", - registration_date: "2020-01-29", - id: "b342c488-578e-4f5c-85bc-35ece34cccdf", - flag_count: 0, - short_id: "b575f47", - age: 15, - workflow: "new" - }, - { - sex: "male", - owned_by_agency_id: 1, - record_in_scope: true, - created_at: "2020-02-29T21:57:00.274Z", - name: "User 1", - alert_count: 0, - case_id_display: "c23a5fca", - owned_by: "primero_cp", - status: "open", - registration_date: "2020-05-02", - id: "b342c488-578e-4f5c-85bc-35ecec23a5fca", - flag_count: 0, - short_id: "c23a5fca", - age: 5, - workflow: "new" - }, - { - sex: "female", - owned_by_agency_id: 1, - record_in_scope: true, - created_at: "2020-03-18T21:57:00.274Z", - name: "User 1", - alert_count: 0, - case_id_display: "9C68741", - owned_by: "primero_cp", - status: "open", - registration_date: "2020-04-18", - id: "d861c56c-8dc9-41c9-974b-2b24299b70a2", - flag_count: 0, - short_id: "9C68741", - age: 7, - workflow: "new" - } - ], - metadata: { - total: 3, - per: 20, - page: 1 - }, - filters: { - status: ["true"] - } - } - }, - user: { - permissions: { - cases: [ACTIONS.MANAGE] - } - }, - forms - }); - - beforeEach(() => { - ({ component } = setupMountedComponent(RecordActions, propsRecordSelected, defaultStateAllRecordSelected)); - }); - - it.skip("renders add refer menu disabled", () => { - const incidentItem = component.find(MenuItem).at(0); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.referral forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.true; - }); - - it.skip("renders add transfer menu disabled", () => { - const incidentItem = component.find(MenuItem).at(2); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.transfer forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.true; - }); - - it("renders add reassign menu enabled", () => { - const incidentItem = component.find(MenuItem).at(0); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("buttons.reassign forms.record_types.case"); - expect(incidentItemProps.disabled).to.be.false; - }); - - it("renders add incident menu disabled", () => { - const incidentItem = component.find(MenuItem).at(1); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("actions.incident_details_from_case"); - expect(incidentItemProps.disabled).to.be.true; - }); - - it("renders add service menu disabled", () => { - const incidentItem = component.find(MenuItem).at(2); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("actions.services_section_from_case"); - expect(incidentItemProps.disabled).to.be.true; - }); - - it("renders add export menu enabled", () => { - const incidentItem = component.find(MenuItem).at(4); - const incidentItemProps = incidentItem.props(); - - expect(incidentItem.text()).to.be.equal("cases.export"); - expect(incidentItemProps.disabled).to.be.false; - }); - }); - - describe("when incident subform is not presented", () => { - const newForms = { - formSections: OrderedMap({ - 1: FormSectionRecord({ - id: 1, - unique_id: "incident_details_container", - name: { en: "Incident Details" }, - visible: true, - parent_form: "case", - editable: true, - module_ids: ["primeromodule-cp"], - fields: [1] - }), - 2: FormSectionRecord({ - id: 2, - unique_id: "services", - fields: [2], - visible: true, - parent_form: "case", - module_ids: ["primeromodule-cp"] - }) - }), - fields: OrderedMap({ - 1: FieldRecord({ - name: "incident_details", - type: "subform", - subform_section_id: null, - editable: true, - disabled: false, - visible: true - }), - 2: FieldRecord({ - name: "services_section", - type: "subform", - subform_section_id: null, - visible: true, - editable: true, - disabled: false - }) - }) - }; - const state = fromJS({ - records: { - cases: { - data: [ - { - sex: "female", - owned_by_agency_id: 1, - record_in_scope: true, - created_at: "2020-01-29T21:57:00.274Z", - name: "User 1", - case_id_display: "b575f47", - id: "b342c488-578e-4f5c-85bc-35ece34cccdf" - } - ], - filters: { - status: ["true"] - } - } - }, - user: { - permissions: { - cases: [ACTIONS.MANAGE] - } - }, - forms: newForms - }); - const { component: emptyComponent } = setupMountedComponent(RecordActions, props, state); - - it("should not render AddIncident component", () => { - expect(emptyComponent.find(AddIncident)).to.be.empty; - }); - - it("should not render AddService component", () => { - expect(emptyComponent.find(AddService)).to.be.empty; - }); - }); -}); diff --git a/app/javascript/components/record-actions/exports/action-creators.unit.test.js b/app/javascript/components/record-actions/exports/action-creators.unit.test.js index ec57229274..4775f0ea8a 100644 --- a/app/javascript/components/record-actions/exports/action-creators.unit.test.js +++ b/app/javascript/components/record-actions/exports/action-creators.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub } from "../../../test"; +import { stub } from "../../../test-utils"; import { ENQUEUE_SNACKBAR, generate } from "../../notifier"; import { EXPORT_URL } from "../../pages/export-list/constants"; import { EXPORT_DIALOG } from "../constants"; diff --git a/app/javascript/components/record-actions/exports/component.jsx b/app/javascript/components/record-actions/exports/component.jsx index ce7611bbe7..89fb2a4c54 100644 --- a/app/javascript/components/record-actions/exports/component.jsx +++ b/app/javascript/components/record-actions/exports/component.jsx @@ -28,7 +28,8 @@ import PdfExporter from "../../pdf-exporter"; import { getUser } from "../../user/selectors"; import { getRecordForms } from "../../record-form/selectors"; import { getMetadata } from "../../record-list/selectors"; -import { buildAppliedFilters } from "../utils"; +import buildAppliedFilters from "../utils/build-applied-filters"; +import buildSelectedIds from "../utils/build-selected-ids"; import { saveExport } from "./action-creators"; import { @@ -52,18 +53,18 @@ import { buildFields, exportFormsOptions, formatFields, formatFileName, isCustom const FORM_ID = "exports-record-form"; -const Component = ({ +function Component({ close, currentPage, match, - open, + open = "false", pending, record, recordType, selectedRecords, setPending, userPermissions -}) => { +}) { const i18n = useI18n(); const pdfExporterRef = useRef(); const dispatch = useDispatch(); @@ -185,15 +186,12 @@ const Component = ({ const { form_unique_ids: formUniqueIds, field_names: fieldNames } = values; const { id, format, message } = ALL_EXPORT_TYPES.find(e => e.id === values.export_type); const fileName = formatFileName(values.custom_export_file_name, format); - const shortIds = records - .toJS() - .filter((_r, i) => selectedRecords?.[currentPage]?.includes(i)) - .map(r => r.short_id); + const recordIds = buildSelectedIds(selectedRecords, records, currentPage); const filters = buildAppliedFilters( isShowPage, allCurrentRowsSelected, - shortIds, + recordIds, appliedFilters, queryParams, record, @@ -351,14 +349,10 @@ const Component = ({ )} ); -}; +} Component.displayName = NAME; -Component.defaultProps = { - open: false -}; - Component.propTypes = { close: PropTypes.func, currentPage: PropTypes.number, diff --git a/app/javascript/components/record-actions/exports/component.unit.test.js b/app/javascript/components/record-actions/exports/component.spec.js similarity index 65% rename from app/javascript/components/record-actions/exports/component.unit.test.js rename to app/javascript/components/record-actions/exports/component.spec.js index 59081ca584..9f384f63ee 100644 --- a/app/javascript/components/record-actions/exports/component.unit.test.js +++ b/app/javascript/components/record-actions/exports/component.spec.js @@ -1,9 +1,6 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - import { fromJS } from "immutable"; -import { setupMountedComponent } from "../../../test"; -import ActionDialog from "../../action-dialog"; +import { mountedComponent, screen } from "../../../test-utils"; import { RECORD_PATH } from "../../../config"; import { ACTIONS } from "../../permissions"; import { mapEntriesToRecord } from "../../../libs"; @@ -86,40 +83,7 @@ describe(" - ", () => { }; it("renders ActionDialog", () => { - const { component } = setupMountedComponent(Exports, props, state); - - expect(component.find(ActionDialog)).to.have.lengthOf(1); - }); - - it("should accept valid props", () => { - const validProps = { - ...props, - currentPage: 0, - pending: true, - record: fromJS({}), - selectedRecords: { 0: [0] }, - setPending: () => {} - }; - const { component } = setupMountedComponent(Exports, validProps, state); - const exportProps = { - ...component.find(Exports).props() - }; - - expect(component.find(Exports)).to.have.lengthOf(1); - [ - "close", - "currentPage", - "open", - "pending", - "record", - "recordType", - "selectedRecords", - "setPending", - "userPermissions" - ].forEach(property => { - expect(exportProps).to.have.property(property); - delete exportProps[property]; - }); - expect(exportProps).to.be.empty; + mountedComponent(, state); + expect(screen.getByRole("dialog")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/record-actions/exports/constants.js b/app/javascript/components/record-actions/exports/constants.js index 89f013949b..6758e5afb5 100644 --- a/app/javascript/components/record-actions/exports/constants.js +++ b/app/javascript/components/record-actions/exports/constants.js @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { ACTIONS } from "../../permissions"; -import { RECORD_PATH } from "../../../config/constants"; +import { RECORD_PATH } from "../../../config"; export const EXPORT_FORMAT = Object.freeze({ JSON: "json", diff --git a/app/javascript/components/record-actions/exports/utils.unit.test.js b/app/javascript/components/record-actions/exports/utils.unit.test.js index 4aa6728b90..4d58365897 100644 --- a/app/javascript/components/record-actions/exports/utils.unit.test.js +++ b/app/javascript/components/record-actions/exports/utils.unit.test.js @@ -2,10 +2,10 @@ import { fromJS, OrderedMap, Map } from "immutable"; -import { fake } from "../../../test"; +import { fake } from "../../../test-utils"; import { ACTIONS } from "../../permissions"; import { TEXT_FIELD, SUBFORM_SECTION } from "../../record-form/constants"; -import { RECORD_PATH } from "../../../config/constants"; +import { RECORD_PATH } from "../../../config"; import { ALL_EXPORT_TYPES, EXPORT_FORMAT } from "./constants"; import * as utils from "./utils"; diff --git a/app/javascript/components/record-actions/link-incident-to-case/component.jsx b/app/javascript/components/record-actions/link-incident-to-case/component.jsx new file mode 100644 index 0000000000..3767ebac3c --- /dev/null +++ b/app/javascript/components/record-actions/link-incident-to-case/component.jsx @@ -0,0 +1,111 @@ +import PropTypes from "prop-types"; +import { useDispatch } from "react-redux"; +import { useForm, FormProvider } from "react-hook-form"; +import { useCallback, useState } from "react"; +import { fromJS } from "immutable"; + +import { useI18n } from "../../i18n"; +import buildSelectedIds from "../utils/build-selected-ids"; +import { useMemoizedSelector } from "../../../libs"; +import { getRecordsData, getRecords } from "../../index-table"; +import { linkIncidentToCase, setCaseIdForIncident, fetchLinkIncidentToCaseData } from "../../records"; +import SearchBox from "../../index-filters/components/search-box"; +import { clearDialog } from "../../action-dialog/action-creators"; +import SubformDrawer from "../../record-form/form/subforms/subform-drawer"; +import { RECORD_TYPES_PLURAL } from "../../../config"; + +import { NAME } from "./constants"; +import css from "./styles.css"; +import Content from "./content"; + +function Component({ close, open, currentPage, selectedRecords, recordType, record }) { + const i18n = useI18n(); + const dispatch = useDispatch(); + const { ...methods } = useForm(); + + const [selectedCaseId, setSelectedCaseId] = useState(); + const [selectedCaseDisplayId, setSelectedCaseDisplayId] = useState(); + const [recordTypeValue, setRecordTypeValue] = useState(); + const [showTable, setShowTable] = useState(true); + const [caseInfo, setCaseInfo] = useState(fromJS({})); + + const records = useMemoizedSelector(state => getRecordsData(state, recordType)); + const caseData = useMemoizedSelector(state => getRecords(state, recordTypeValue)); + + const selectedIDs = buildSelectedIds(selectedRecords, records, currentPage, "id"); + + const handleOk = useCallback(() => { + dispatch( + linkIncidentToCase({ + recordType, + selectedIDs: record ? [record.get("id")] : selectedIDs, + caseID: selectedCaseId + }) + ); + + dispatch(setCaseIdForIncident(selectedCaseId, selectedCaseDisplayId)); + dispatch(clearDialog()); + }, [selectedCaseId, selectedCaseDisplayId, recordType, record, selectedIDs]); + + const handleSubmit = useCallback(data => { + setRecordTypeValue(RECORD_TYPES_PLURAL.case); + dispatch(fetchLinkIncidentToCaseData(data)); + }, []); + + const handleRowClick = useCallback( + async (selectedID, selectedDisplayID) => { + await setShowTable(false); + await setCaseInfo(caseData.get("data").find($record => $record.get("id") === selectedID)); + await setSelectedCaseId(selectedID); + setSelectedCaseDisplayId(selectedDisplayID); + }, + [caseData] + ); + + const handleClose = () => { + dispatch(fetchLinkIncidentToCaseData({})); + close(); + }; + + const handleBack = useCallback(async () => { + await setShowTable(true); + setCaseInfo(fromJS({})); + }, []); + + return ( + <> + +
+ + + + + +
+ +
+ + ); +} + +Component.displayName = NAME; + +Component.propTypes = { + clearSelectedRecords: PropTypes.func, + close: PropTypes.func, + currentPage: PropTypes.number, + defaultFilters: PropTypes.object, + open: PropTypes.bool, + record: PropTypes.object, + recordType: PropTypes.string, + selectedRecords: PropTypes.object +}; + +export default Component; diff --git a/app/javascript/components/record-actions/link-incident-to-case/component.spec.js b/app/javascript/components/record-actions/link-incident-to-case/component.spec.js new file mode 100644 index 0000000000..567f07bfaa --- /dev/null +++ b/app/javascript/components/record-actions/link-incident-to-case/component.spec.js @@ -0,0 +1,34 @@ +import { mountedComponent, screen } from "test-utils"; + +import LinkIncidentToCase from "./component"; + +describe("", () => { + const props = { + close: () => {}, + open: true, // Assuming the component should start in an open state + currentPage: 1, // Example value + selectedRecords: {}, // Example value + clearSelectedRecords: () => {}, + recordType: "cases" // Example value + }; + + beforeEach(() => { + mountedComponent(); + }); + + it("renders Action Dialog", () => { + expect(screen.getByText("incident.link_incident_to_case")).toBeInTheDocument(); + }); + + it("render Form", () => { + expect(screen.getByTestId("search-form-for-link-to-case")).toBeInTheDocument(); + }); + + it("render Table", () => { + expect(screen.getByRole("grid")).toBeInTheDocument(); + }); + + it("render Table and havig data", () => { + expect(screen.getByText("potential_match.case_id")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/record-actions/link-incident-to-case/constants.js b/app/javascript/components/record-actions/link-incident-to-case/constants.js new file mode 100644 index 0000000000..91fd4ac300 --- /dev/null +++ b/app/javascript/components/record-actions/link-incident-to-case/constants.js @@ -0,0 +1,2 @@ +export const NAME = "LinkIncidentToCase"; +export const VALUE_PLACEHOLDER = "--"; diff --git a/app/javascript/components/record-actions/link-incident-to-case/content/component.jsx b/app/javascript/components/record-actions/link-incident-to-case/content/component.jsx new file mode 100644 index 0000000000..41c2ceaaa6 --- /dev/null +++ b/app/javascript/components/record-actions/link-incident-to-case/content/component.jsx @@ -0,0 +1,116 @@ +import { Grid } from "@mui/material"; +import ArrowBackIosIcon from "@mui/icons-material/ArrowBackIos"; +import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos"; +import CheckIcon from "@mui/icons-material/Check"; +import PropTypes from "prop-types"; +import { fromJS } from "immutable"; + +import ActionButton, { ACTION_BUTTON_TYPES } from "../../../action-button"; +import IndexTable from "../../../index-table"; +import { useI18n } from "../../../i18n"; +import css from "../styles.css"; +import { VALUE_PLACEHOLDER } from "../constants"; +import PhotoArray from "../../../record-form/form/field-types/attachments/photo-array"; +import useOptions from "../../../form/use-options"; +import { LOOKUPS } from "../../../../config"; +import { getOptionText } from "../../../record-form/form/subforms/subform-traces/components/field-row/utils"; +import { useThemeHelper } from "../../../../libs"; + +import { buildTableOptions } from "./utils"; + +function Component({ showTable = false, caseInfo, handleBack, handleOk, handleRowClick, recordTypeValue }) { + const i18n = useI18n(); + const genderLookups = useOptions({ source: LOOKUPS.gender_unknown }); + const tableOptions = buildTableOptions({ i18n, handleRowClick, recordTypeValue }); + const { isRTL } = useThemeHelper(); + + const images = caseInfo + .get("photos", fromJS([])) + ?.map(img => img.get("attachment_url")) + .toArray(); + + if (showTable) { + return ; + } + + if (!showTable && !caseInfo.isEmpty()) { + return ( + <> +
+ : } + text="buttons.back" + type={ACTION_BUTTON_TYPES.default} + rest={{ + onClick: handleBack + }} + /> + } + text="buttons.link" + type={ACTION_BUTTON_TYPES.default} + rest={{ + onClick: handleOk + }} + /> +
+ + + +

+ {i18n.t("case.label")}{" "} + {caseInfo.get("case_id_display", VALUE_PLACEHOLDER)} +

+
+
+ + + {i18n.t("cases.name")} + + + {caseInfo.get("name", VALUE_PLACEHOLDER)} + + + + + {i18n.t("cases.age")} + + + {caseInfo.get("age", VALUE_PLACEHOLDER)} + + + + + {i18n.t("cases.sex")} + + + {getOptionText({ options: genderLookups, value: caseInfo.get("sex", VALUE_PLACEHOLDER) })} + + + + +
{i18n.t("tracing_request.case_photos")}
+ {images.length ? : --} +
+
+
+ + ); + } + + return null; +} + +Component.displayName = "Content"; + +Component.propTypes = { + caseInfo: PropTypes.object, + handleBack: PropTypes.func, + handleOk: PropTypes.func, + handleRowClick: PropTypes.func, + recordTypeValue: PropTypes.string, + showTable: PropTypes.bool +}; + +export default Component; diff --git a/app/javascript/components/record-actions/link-incident-to-case/content/index.js b/app/javascript/components/record-actions/link-incident-to-case/content/index.js new file mode 100644 index 0000000000..b6e0586481 --- /dev/null +++ b/app/javascript/components/record-actions/link-incident-to-case/content/index.js @@ -0,0 +1 @@ +export { default } from "./component"; diff --git a/app/javascript/components/record-actions/link-incident-to-case/content/utils.js b/app/javascript/components/record-actions/link-incident-to-case/content/utils.js new file mode 100644 index 0000000000..de5db357be --- /dev/null +++ b/app/javascript/components/record-actions/link-incident-to-case/content/utils.js @@ -0,0 +1,68 @@ +import { fromJS } from "immutable"; + +import ActionButton, { ACTION_BUTTON_TYPES } from "../../../action-button"; + +function buildTableOptions({ i18n, handleRowClick, recordTypeValue }) { + return { + columns: [ + { + name: "case.id", + options: { + display: false + } + }, + { + name: "id", + options: { + display: false + } + }, + { + label: i18n.t("potential_match.name"), + name: "name" + }, + { + label: i18n.t("potential_match.case_id"), + name: "case_id_display", + options: { + customBodyRender: (value, tableMeta) => { + const { rowData } = tableMeta; + + return ( + handleRowClick(rowData[1], rowData[3])} + /> + ); + } + } + }, + { + label: i18n.t("potential_match.child_age"), + name: "age" + }, + { + label: i18n.t("potential_match.child_gender"), + name: "sex" + } + ], + defaultFilters: fromJS({}), + recordType: recordTypeValue, + targetRecordType: recordTypeValue, + bypassInitialFetch: true, + options: { + selectableRows: "none", + onCellClick: false, + elevation: 0, + pagination: true + } + }; +} + +// eslint-disable-next-line import/prefer-default-export +export { buildTableOptions }; diff --git a/app/javascript/components/record-actions/link-incident-to-case/index.js b/app/javascript/components/record-actions/link-incident-to-case/index.js new file mode 100644 index 0000000000..b6e0586481 --- /dev/null +++ b/app/javascript/components/record-actions/link-incident-to-case/index.js @@ -0,0 +1 @@ +export { default } from "./component"; diff --git a/app/javascript/components/record-actions/link-incident-to-case/styles.css b/app/javascript/components/record-actions/link-incident-to-case/styles.css new file mode 100644 index 0000000000..0b1ad1ed6a --- /dev/null +++ b/app/javascript/components/record-actions/link-incident-to-case/styles.css @@ -0,0 +1,49 @@ +.recordId { + color: var(--c-red); +} + +.alreadyMatched { + background-color: var(--c-wild-sand); + padding: 10px; + + & span { + font-weight: bold; + } +} + +.fieldRow { + & audio { + width: 100%; + } +} + +.fieldRow:not(:last-of-type) { + border-bottom: 1px solid var(--c-light-grey); +} + +.fieldTitle { + font-weight: bold; +} + +.matched { + color: var(--c-green); +} + +.notMatched { + color: var(--c-red); +} + +.form { + margin-top: var(--sp-3); +} + +.toolbar { + display: flex; + justify-content: space-between; +} + +.caseID { + margin: var(--sp-3) 0 0 0; + padding-top: var(--sp-3); + border-top: 1px solid var(--c-light-grey); +} \ No newline at end of file diff --git a/app/javascript/components/record-actions/mark-for-offline/component.jsx b/app/javascript/components/record-actions/mark-for-offline/component.jsx index c34aa88fa6..0b3686bf4a 100644 --- a/app/javascript/components/record-actions/mark-for-offline/component.jsx +++ b/app/javascript/components/record-actions/mark-for-offline/component.jsx @@ -13,7 +13,7 @@ import { RECORD_TYPES_PLURAL } from "../../../config"; import { NAME } from "./constants"; -const Component = ({ close, open, recordType, currentPage, selectedRecords, clearSelectedRecords }) => { +function Component({ close, open, recordType, currentPage, selectedRecords, clearSelectedRecords }) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -43,7 +43,7 @@ const Component = ({ close, open, recordType, currentPage, selectedRecords, clea pending={markedForMobileLoadingCases || markedForMobileLoadingRegistry} /> ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/record-actions/notes/component.jsx b/app/javascript/components/record-actions/notes/component.jsx index 7270ac7e04..7715fdf939 100644 --- a/app/javascript/components/record-actions/notes/component.jsx +++ b/app/javascript/components/record-actions/notes/component.jsx @@ -21,7 +21,7 @@ const validationSchema = object().shape({ note_text: string().required() }); -const Component = ({ close, open, pending, record, recordType, setPending }) => { +function Component({ close, open, pending, record, recordType, setPending }) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -94,7 +94,7 @@ const Component = ({ close, open, pending, record, recordType, setPending }) => /> ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/record-actions/request-approval/action-creators.unit.test.js b/app/javascript/components/record-actions/request-approval/action-creators.unit.test.js index 29fad0466a..d3cdefb3a6 100644 --- a/app/javascript/components/record-actions/request-approval/action-creators.unit.test.js +++ b/app/javascript/components/record-actions/request-approval/action-creators.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub, useFakeTimers } from "../../../test"; +import { stub, useFakeTimers } from "../../../test-utils"; import { ENQUEUE_SNACKBAR, generate } from "../../notifier"; import { CLEAR_DIALOG, SET_DIALOG_PENDING } from "../../action-dialog"; import { FETCH_RECORD_ALERTS } from "../../records/actions"; diff --git a/app/javascript/components/record-actions/request-approval/approval-form.jsx b/app/javascript/components/record-actions/request-approval/approval-form.jsx index 130fb72692..be74d00608 100644 --- a/app/javascript/components/record-actions/request-approval/approval-form.jsx +++ b/app/javascript/components/record-actions/request-approval/approval-form.jsx @@ -10,14 +10,14 @@ import { Radio, Select, FormHelperText -} from "@material-ui/core"; +} from "@mui/material"; import { useI18n } from "../../i18n"; import { APPROVAL_FORM } from "./constants"; import css from "./styles.css"; -const Component = ({ +function Component({ approval, disabled, handleChangeApproval, @@ -25,7 +25,7 @@ const Component = ({ handleChangeType, requestType, selectOptions -}) => { +}) { const i18n = useI18n(); return ( @@ -69,11 +69,10 @@ const Component = ({ id="outlined-multiline-static" multiline fullWidth - rows="4" + minRows="4" defaultValue="" variant="outlined" onChange={handleChangeComment} - labelWidth={0} shrink label={i18n.t("cases.approval_comments")} /> @@ -81,7 +80,7 @@ const Component = ({ ); -}; +} Component.displayName = APPROVAL_FORM; diff --git a/app/javascript/components/record-actions/request-approval/approval-form.unit.test.js b/app/javascript/components/record-actions/request-approval/approval-form.spec.js similarity index 53% rename from app/javascript/components/record-actions/request-approval/approval-form.unit.test.js rename to app/javascript/components/record-actions/request-approval/approval-form.spec.js index 765a2bec34..e3601218aa 100644 --- a/app/javascript/components/record-actions/request-approval/approval-form.unit.test.js +++ b/app/javascript/components/record-actions/request-approval/approval-form.spec.js @@ -1,9 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { TextField, RadioGroup, Select } from "@material-ui/core"; -import { setupMountedComponent } from "../../../test"; +import { mountedComponent, screen } from "../../../test-utils"; import ApprovalForm from "./approval-form"; @@ -20,20 +19,20 @@ describe(" - components/record-actions/request-approval", () => }; it("renders RadioGroup", () => { - const { component } = setupMountedComponent(ApprovalForm, props, state); + mountedComponent(, state); - expect(component.find(RadioGroup)).to.have.lengthOf(1); + expect(screen.getByRole("radiogroup")).toBeInTheDocument(); }); it("renders Select", () => { - const { component } = setupMountedComponent(ApprovalForm, props, state); + mountedComponent(, state); - expect(component.find(Select)).to.have.lengthOf(1); + expect(document.querySelector("input.MuiSelect-nativeInput")).toBeInTheDocument(); }); it("renders TextField", () => { - const { component } = setupMountedComponent(ApprovalForm, props, state); + mountedComponent(, state); - expect(component.find(TextField)).to.have.lengthOf(1); + expect(screen.getByRole("textbox")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/record-actions/request-approval/component.jsx b/app/javascript/components/record-actions/request-approval/component.jsx index 4b70df5558..246e94b59e 100644 --- a/app/javascript/components/record-actions/request-approval/component.jsx +++ b/app/javascript/components/record-actions/request-approval/component.jsx @@ -3,10 +3,10 @@ import { useEffect, useState } from "react"; import PropTypes from "prop-types"; import { batch, useDispatch } from "react-redux"; -import { InputLabel, MenuItem, Select } from "@material-ui/core"; +import { InputLabel, MenuItem, Select } from "@mui/material"; import isEmpty from "lodash/isEmpty"; -import { MODULES } from "../../../config/constants"; +import { MODULES } from "../../../config"; import { useI18n } from "../../i18n"; import ActionDialog from "../../action-dialog"; import { fetchAlerts } from "../../nav/action-creators"; @@ -21,7 +21,7 @@ import ApprovalForm from "./approval-form"; import { APPROVAL_TYPE_LOOKUP, CASE_PLAN, NAME } from "./constants"; import css from "./styles.css"; -const Component = ({ +function Component({ close, open, subMenuItems, @@ -31,7 +31,7 @@ const Component = ({ setPending, approvalType, confirmButtonLabel -}) => { +}) { const i18n = useI18n(); const { approvalsLabels, userModules } = useApp(); const dispatch = useDispatch(); @@ -214,7 +214,7 @@ const Component = ({ {dialogContent} ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/record-actions/request-approval/component.unit.test.js b/app/javascript/components/record-actions/request-approval/component.spec.js similarity index 54% rename from app/javascript/components/record-actions/request-approval/component.unit.test.js rename to app/javascript/components/record-actions/request-approval/component.spec.js index f3fbc08669..7a2962a761 100644 --- a/app/javascript/components/record-actions/request-approval/component.unit.test.js +++ b/app/javascript/components/record-actions/request-approval/component.spec.js @@ -2,15 +2,13 @@ import { fromJS } from "immutable"; -import { setupMountedComponent } from "../../../test"; -import ActionDialog from "../../action-dialog"; +import { mountedComponent, screen } from "../../../test-utils"; import { APPROVAL_TYPE, APPROVAL_DIALOG } from "../constants"; import { RECORD_TYPES, RECORD_PATH, APPROVALS_TYPES } from "../../../config"; import RequestApproval from "./component"; describe("", () => { - let component; const initialState = fromJS({ application: { online: true, @@ -33,6 +31,7 @@ describe("", () => { confirmButtonLabel: "buttons.submit", dialogName: APPROVAL_DIALOG, openRequestDialog: true, + open: true, pending: false, record: {}, recordType: RECORD_PATH.cases, @@ -47,36 +46,8 @@ describe("", () => { ] }; - beforeEach(() => { - ({ component } = setupMountedComponent(RequestApproval, props, initialState)); - }); - it("renders RequestApproval", () => { - expect(component.find(RequestApproval)).to.have.lengthOf(1); - }); - - it("renders ActionDialog", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(1); - }); - - it("renders component with valid props", () => { - const requestApproval = { ...component.find(RequestApproval).props() }; - - [ - "approvalType", - "close", - "confirmButtonLabel", - "dialogName", - "openRequestDialog", - "pending", - "record", - "recordType", - "setPending", - "subMenuItems" - ].forEach(property => { - expect(requestApproval).to.have.property(property); - delete requestApproval[property]; - }); - expect(requestApproval).to.be.empty; + mountedComponent(, initialState); + expect(screen.getByRole("dialog")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/record-actions/request-approval/styles.css b/app/javascript/components/record-actions/request-approval/styles.css index 7288e05213..295b8a5e8a 100644 --- a/app/javascript/components/record-actions/request-approval/styles.css +++ b/app/javascript/components/record-actions/request-approval/styles.css @@ -4,7 +4,3 @@ width: 200px; margin: 8px; } - -.field { - margin: 0 0 var(--sp-3) -} diff --git a/app/javascript/components/record-actions/toggle-enable/component.jsx b/app/javascript/components/record-actions/toggle-enable/component.jsx index 6346bf7ae9..a3477fff22 100644 --- a/app/javascript/components/record-actions/toggle-enable/component.jsx +++ b/app/javascript/components/record-actions/toggle-enable/component.jsx @@ -10,7 +10,7 @@ import { RECORD_TYPES_PLURAL } from "../../../config"; import { NAME } from "./constants"; -const Component = ({ close, open, record, recordType }) => { +function Component({ close, open, record, recordType }) { const i18n = useI18n(); const dispatch = useDispatch(); const enableState = record && !record.get("record_state") ? "enable" : "disable"; @@ -52,7 +52,7 @@ const Component = ({ close, open, record, recordType }) => { confirmButtonLabel={i18n.t("cases.ok")} /> ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/record-actions/toggle-open/component.jsx b/app/javascript/components/record-actions/toggle-open/component.jsx index 6f2c90e513..c5c463ca4a 100644 --- a/app/javascript/components/record-actions/toggle-open/component.jsx +++ b/app/javascript/components/record-actions/toggle-open/component.jsx @@ -10,7 +10,7 @@ import { ACTIONS } from "../../permissions"; import { NAME } from "./constants"; -const ToggleOpen = ({ close, open, record, recordType }) => { +function ToggleOpen({ close, open, record, recordType }) { const i18n = useI18n(); const dispatch = useDispatch(); const setValue = record && record.get("status") === "open" ? "close" : "reopen"; @@ -48,7 +48,7 @@ const ToggleOpen = ({ close, open, record, recordType }) => { confirmButtonLabel={i18n.t("cases.ok")} /> ); -}; +} ToggleOpen.displayName = NAME; diff --git a/app/javascript/components/record-actions/toggle-open/component.unit.test.js b/app/javascript/components/record-actions/toggle-open/component.spec.js similarity index 53% rename from app/javascript/components/record-actions/toggle-open/component.unit.test.js rename to app/javascript/components/record-actions/toggle-open/component.spec.js index 62188b28e6..dd8c32d3b5 100644 --- a/app/javascript/components/record-actions/toggle-open/component.unit.test.js +++ b/app/javascript/components/record-actions/toggle-open/component.spec.js @@ -2,15 +2,12 @@ import { fromJS } from "immutable"; -import ActionDialog from "../../action-dialog"; -import { setupMountedComponent } from "../../../test"; +import { mountedComponent, screen } from "../../../test-utils"; import { RECORD_PATH } from "../../../config"; import ToggleOpen from "./component"; describe("", () => { - let component; - const record = fromJS({ id: "03cdfdfe-a8fc-4147-b703-df976d200977", case_id: "1799d556-652c-4ad9-9b4c-525d487b5e7b", @@ -24,28 +21,22 @@ describe("", () => { close: () => {}, openReopenDialog: true, recordType: RECORD_PATH.cases, + open: true, record }; - beforeEach(() => { - ({ component } = setupMountedComponent(ToggleOpen, props, {})); - }); - it("renders ToggleOpen", () => { - expect(component.find(ToggleOpen)).to.have.length(1); + mountedComponent(); + expect(screen.getByText(/cases.reopen_dialog_title/i)).toBeInTheDocument(); }); it("renders ActionDialog", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(1); + mountedComponent(); + expect(screen.getByRole("dialog")).toBeInTheDocument(); }); it("renders component with valid props", () => { - const toggleOpenProps = { ...component.find(ToggleOpen).props() }; - - ["close", "openReopenDialog", "record", "recordType"].forEach(property => { - expect(toggleOpenProps).to.have.property(property); - delete toggleOpenProps[property]; - }); - expect(toggleOpenProps).to.be.empty; + mountedComponent(); + expect(screen.getByRole("dialog")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/record-actions/transitions/action-creators.js b/app/javascript/components/record-actions/transitions/action-creators.js index b7781e1cf2..bcd27e5a8d 100644 --- a/app/javascript/components/record-actions/transitions/action-creators.js +++ b/app/javascript/components/record-actions/transitions/action-creators.js @@ -100,3 +100,7 @@ export const saveReferral = (recordId, recordType, body, message) => { } }; }; + +export const resetReferralSuccess = () => ({ + type: actions.REFER_USER_SUCCESS_FINISHED +}); diff --git a/app/javascript/components/record-actions/transitions/action-creators.unit.test.js b/app/javascript/components/record-actions/transitions/action-creators.unit.test.js index 043effb4e8..c3639a0a9b 100644 --- a/app/javascript/components/record-actions/transitions/action-creators.unit.test.js +++ b/app/javascript/components/record-actions/transitions/action-creators.unit.test.js @@ -5,7 +5,7 @@ import configureStore from "redux-mock-store"; import sinon from "sinon"; import { ENQUEUE_SNACKBAR, generate } from "../../notifier"; -import { stub } from "../../../test"; +import { stub } from "../../../test-utils"; import { CLEAR_DIALOG } from "../../action-dialog"; import * as actionCreators from "./action-creators"; @@ -35,6 +35,7 @@ describe(" - Action Creators", () => { delete creators.fetchTransitionData; delete creators.fetchReferralUsers; delete creators.saveReferral; + delete creators.resetReferralSuccess; expect(creators).to.deep.equal({}); }); diff --git a/app/javascript/components/record-actions/transitions/actions.js b/app/javascript/components/record-actions/transitions/actions.js index 84fc03e811..d5ca9d23ee 100644 --- a/app/javascript/components/record-actions/transitions/actions.js +++ b/app/javascript/components/record-actions/transitions/actions.js @@ -33,7 +33,8 @@ const actions = namespaceActions(NAMESPACE, [ "TRANSFER_USERS_FETCH_SUCCESS", "TRANSFER_USER_FAILURE", "TRANSFER_USER_STARTED", - "TRANSFER_USER_SUCCESS" + "TRANSFER_USER_SUCCESS", + "REFER_USER_SUCCESS_FINISHED" ]); export default { diff --git a/app/javascript/components/record-actions/transitions/actions.unit.test.js b/app/javascript/components/record-actions/transitions/actions.unit.test.js index 4a40b30862..ab6b92ed61 100644 --- a/app/javascript/components/record-actions/transitions/actions.unit.test.js +++ b/app/javascript/components/record-actions/transitions/actions.unit.test.js @@ -44,7 +44,8 @@ describe(" - Actions", () => { "TRANSFER_USER_SUCCESS", "USERS_ASSIGN_TO", "USERS_REFER_TO", - "USERS_TRANSFER_TO" + "USERS_TRANSFER_TO", + "REFER_USER_SUCCESS_FINISHED" ].forEach(property => { expect(cloneActions).to.have.property(property); expect(cloneActions[property]).to.be.a("string"); diff --git a/app/javascript/components/record-actions/transitions/component.jsx b/app/javascript/components/record-actions/transitions/component.jsx index a60d716c61..4e10323245 100644 --- a/app/javascript/components/record-actions/transitions/component.jsx +++ b/app/javascript/components/record-actions/transitions/component.jsx @@ -19,9 +19,9 @@ import { hasProvidedConsent } from "./components/utils"; import { ReassignForm, TransitionDialog, Transfers } from "./components"; import Referrals from "./referrals/component"; -const Transitions = ({ +function Transitions({ close, - open, + open = false, currentDialog, record, recordType, @@ -30,7 +30,7 @@ const Transitions = ({ currentPage, selectedRecords, mode -}) => { +}) { const i18n = useI18n(); const providedConsent = (record && hasProvidedConsent(record)) || false; const assignFormikRef = useRef(); @@ -47,8 +47,7 @@ const Transitions = ({ const records = useMemoizedSelector(state => getRecordsData(state, recordType)); const selectedRecordsLength = Object.values(selectedRecords || {}).flat()?.length; - const keyToSelectId = isAssignDialogOpen ? "short_id" : "id"; - const selectedIds = buildSelectedIds(selectedRecords, records, currentPage, keyToSelectId); + const selectedIds = buildSelectedIds(selectedRecords, records, currentPage, "id"); const { present: incidentFromCasePresent } = useIncidentFromCase({ recordType: RECORD_TYPES[recordType], record }); const commonDialogProps = { @@ -170,14 +169,10 @@ const Transitions = ({ {transitionComponent()} ); -}; +} Transitions.displayName = NAME; -Transitions.defaultProps = { - open: false -}; - Transitions.propTypes = { close: PropTypes.func, currentDialog: PropTypes.string, diff --git a/app/javascript/components/record-actions/transitions/component.spec.js b/app/javascript/components/record-actions/transitions/component.spec.js new file mode 100644 index 0000000000..5328f54c92 --- /dev/null +++ b/app/javascript/components/record-actions/transitions/component.spec.js @@ -0,0 +1,105 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen } from "../../../test-utils"; +import { MODULES } from "../../../config"; + +import mockUsers from "./mocked-users"; +import Transitions from "./component"; + +describe("", () => { + const initialState = fromJS({ + application: { + agencies: [{ unique_id: "agency-unicef", name: "UNICEF" }] + }, + transitions: { + reassign: { + users: [{ user_name: "primero" }] + }, + mockUsers, + transfer: { + users: [{ user_name: "primero_cp" }] + } + } + }); + const record = fromJS({ + id: "03cdfdfe-a8fc-4147-b703-df976d200977", + case_id: "1799d556-652c-4ad9-9b4c-525d487b5e7b", + case_id_display: "9b4c525", + name_first: "W", + name_last: "D", + name: "W D", + module_id: MODULES.CP, + consent_for_services: true, + disclosure_other_orgs: true + }); + + describe("when transitionType is 'referral'", () => { + const referralProps = { + record, + recordType: "cases", + userPermissions: fromJS({ cases: ["manage"] }), + currentDialog: "referral", + open: true, + close: () => {}, + pending: false, + setPending: () => {} + }; + + it("renders TransitionDialog", () => { + mountedComponent(, initialState); + expect(screen.getByRole("dialog")).toBeInTheDocument(); + }); + + it("renders ReferralForm", () => { + mountedComponent(, initialState); + expect(screen.getByText(/forms.record_types.case/)).toBeInTheDocument(); + }); + }); + + describe("when transitionType is 'reassign'", () => { + const reassignProps = { + record, + recordType: "cases", + userPermissions: fromJS({ cases: ["manage"] }), + currentDialog: "assign", + open: true, + close: () => {}, + pending: false, + setPending: () => {} + }; + + it("renders TransitionDialog", () => { + mountedComponent(, initialState); + expect(screen.getByRole("dialog")).toBeInTheDocument(); + }); + + it("renders ReassignForm", () => { + mountedComponent(, initialState); + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "form")).toBeInTheDocument(); + }); + }); + + describe("when transitionType is 'transfer'", () => { + const transferProps = { + record, + recordType: "cases", + userPermissions: fromJS({ cases: ["manage"] }), + currentDialog: "transfer", + open: true, + close: () => {}, + pending: false, + isBulkTransfer: false, + setPending: () => {} + }; + + it("renders TransitionDialog", () => { + mountedComponent(, initialState); + expect(screen.getByRole("dialog")).toBeInTheDocument(); + }); + + it("renders TransferForm", () => { + mountedComponent(, initialState); + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "form")).toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/record-actions/transitions/component.unit.test.js b/app/javascript/components/record-actions/transitions/component.unit.test.js deleted file mode 100644 index f25c3c4c75..0000000000 --- a/app/javascript/components/record-actions/transitions/component.unit.test.js +++ /dev/null @@ -1,288 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../test"; -import { MODULES } from "../../../config"; - -import { ReassignForm, TransitionDialog, Transfers } from "./components"; -import Referral from "./referrals"; -import mockUsers from "./mocked-users"; -import Transitions from "./component"; - -describe("", () => { - let component; - const initialState = fromJS({ - application: { - agencies: [{ unique_id: "agency-unicef", name: "UNICEF" }] - }, - transitions: { - reassign: { - users: [{ user_name: "primero" }] - }, - mockUsers, - transfer: { - users: [{ user_name: "primero_cp" }] - } - } - }); - const record = fromJS({ - id: "03cdfdfe-a8fc-4147-b703-df976d200977", - case_id: "1799d556-652c-4ad9-9b4c-525d487b5e7b", - case_id_display: "9b4c525", - name_first: "W", - name_last: "D", - name: "W D", - module_id: MODULES.CP, - consent_for_services: true, - disclosure_other_orgs: true - }); - - describe("when Transitions is rendered", () => { - const props = { - assignDialog: true, - currentPage: 0, - handleAssignClose: () => {}, - handleReferClose: () => {}, - handleTransferClose: () => {}, - pending: false, - record, - recordType: "cases", - referDialog: false, - selectedRecords: {}, - setPending: () => {}, - transferDialog: false, - userPermissions: {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(Transitions, props, initialState)); - }); - - it("should accept valid props", () => { - const transitionsProps = { ...component.find(Transitions).props() }; - - expect(component.find(Transitions)).to.have.lengthOf(1); - [ - "assignDialog", - "currentPage", - "handleAssignClose", - "handleReferClose", - "handleTransferClose", - "pending", - "record", - "recordType", - "referDialog", - "selectedRecords", - "setPending", - "transferDialog", - "userPermissions", - "open" - ].forEach(property => { - expect(transitionsProps).to.have.property(property); - delete transitionsProps[property]; - }); - expect(transitionsProps).to.be.empty; - }); - }); - - describe("when transitionType is 'referral'", () => { - const props = { - record, - recordType: "cases", - userPermissions: fromJS({ cases: ["manage"] }), - currentDialog: "referral", - open: true, - close: () => {}, - pending: false, - setPending: () => {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(Transitions, props, initialState)); - }); - - it("renders TransitionDialog", () => { - expect(component.find(TransitionDialog)).to.have.lengthOf(1); - }); - - it("renders ReferralForm", () => { - expect(component.find(Referral)).to.have.lengthOf(1); - }); - - describe("with props", () => { - it("should check the allowed props", () => { - const referralForm = component.find(Referral); - const validProps = [ - "canConsentOverride", - "providedConsent", - "recordType", - "record", - "setPending", - "selectedIds", - "mode", - "formID", - "disabled", - "setDisabled", - "handleClose" - ]; - - expect(Object.keys(referralForm.props())).to.deep.equal(validProps); - }); - it("should check the providedConsent prop", () => { - const referralForm = component.find(Referral); - - expect(referralForm.props().providedConsent).to.equal(true); - }); - it("should check the canConsentOverride prop", () => { - const referralForm = component.find(Referral); - - expect(referralForm.props().canConsentOverride).to.equal(false); - }); - it("should check the setPending prop", () => { - const referralForm = component.find(Referral); - - expect(referralForm.props().setPending).to.be.a("function"); - }); - it("should check the setDisabled prop", () => { - const referralForm = component.find(Referral); - - expect(referralForm.props().setDisabled).to.be.a("function"); - }); - - it("should check the recordType prop", () => { - const referralForm = component.find(Referral); - - expect(referralForm.props().recordType).to.deep.equal("cases"); - }); - it("should check the record prop", () => { - const referralForm = component.find(Referral); - - expect(referralForm.props().record).to.deep.equal(record); - }); - }); - }); - - describe("when transitionType is 'reassign'", () => { - const props = { - record, - recordType: "cases", - userPermissions: fromJS({ cases: ["manage"] }), - currentDialog: "assign", - open: true, - close: () => {}, - pending: false, - setPending: () => {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(Transitions, props, initialState)); - }); - - it("renders TransitionDialog", () => { - expect(component.find(TransitionDialog)).to.have.lengthOf(1); - }); - - it("renders ReassignForm", () => { - expect(component.find(ReassignForm)).to.have.lengthOf(1); - }); - - it("should check the allowed props", () => { - const reassignForm = component.find(ReassignForm); - const validProps = [ - "canConsentOverride", - "providedConsent", - "recordType", - "record", - "setPending", - "selectedIds", - "mode", - "assignRef", - "selectedRecordsLength", - "formDisabled" - ]; - - expect(Object.keys(reassignForm.props())).to.deep.equal(validProps); - }); - - it("should check the canConsentOverride prop", () => { - expect(component.find(ReassignForm).props().formDisabled).to.equal(false); - }); - }); - - describe("when transitionType is 'transfer'", () => { - const props = { - record, - recordType: "cases", - userPermissions: fromJS({ cases: ["manage"] }), - currentDialog: "transfer", - open: true, - close: () => {}, - pending: false, - isBulkTransfer: false, - setPending: () => {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(Transitions, props, initialState)); - }); - - it("renders TransitionDialog", () => { - expect(component.find(TransitionDialog)).to.have.length(1); - }); - - it("renders TransferForm", () => { - expect(component.find(Transfers)).to.have.length(1); - }); - describe("with props", () => { - let transferForm; - - beforeEach(() => { - transferForm = component.find(Transfers); - }); - it("should check the allowed props", () => { - const validProps = [ - "canConsentOverride", - "providedConsent", - "recordType", - "record", - "setPending", - "selectedIds", - "mode", - "isBulkTransfer", - "disabled", - "setDisabled" - ]; - - expect(Object.keys(transferForm.props())).to.deep.equal(validProps); - }); - it("should check the providedConsent prop", () => { - expect(transferForm.props().providedConsent).to.equal(true); - }); - it("should check the isBulkTransfer prop", () => { - expect(transferForm.props().isBulkTransfer).to.equal(false); - }); - it("should check the canConsentOverride prop", () => { - expect(transferForm.props().canConsentOverride).to.equal(false); - }); - it("should check the setPending prop", () => { - expect(transferForm.props().setPending).to.be.a("function"); - }); - it("should check the setDisabled prop", () => { - expect(transferForm.props().setDisabled).to.be.a("function"); - }); - it("should check the disabled prop", () => { - expect(transferForm.props().disabled).to.be.false; - }); - it("should check the isBulkTransfer prop", () => { - expect(transferForm.props().isBulkTransfer).to.be.false; - }); - it("should check the record prop", () => { - expect(transferForm.props().record).to.deep.equal(record); - }); - it("should check the recordType prop", () => { - expect(transferForm.props().recordType).to.deep.equal("cases"); - }); - }); - }); -}); diff --git a/app/javascript/components/record-actions/transitions/components/reassign-form.jsx b/app/javascript/components/record-actions/transitions/components/reassign-form.jsx index ecebd9819f..c7422ced83 100644 --- a/app/javascript/components/record-actions/transitions/components/reassign-form.jsx +++ b/app/javascript/components/record-actions/transitions/components/reassign-form.jsx @@ -7,7 +7,7 @@ import { Formik, Field, Form } from "formik"; import { useDispatch } from "react-redux"; import { useLocation } from "react-router-dom"; import qs from "qs"; -import { TextField } from "formik-material-ui"; +import { TextField } from "formik-mui"; import { fromJS } from "immutable"; import { RECORD_TYPES } from "../../../../config"; @@ -30,7 +30,7 @@ import css from "./styles.css"; const initialValues = { transitioned_to: "", notes: "" }; -const ReassignForm = ({ +function ReassignForm({ record, recordType, setPending, @@ -40,7 +40,7 @@ const ReassignForm = ({ selectedRecordsLength, currentRecordsSize, formDisabled = false -}) => { +}) { const i18n = useI18n(); const dispatch = useDispatch(); const location = useLocation(); @@ -197,7 +197,7 @@ const ReassignForm = ({ }} ); -}; +} ReassignForm.displayName = REASSIGN_FORM_NAME; diff --git a/app/javascript/components/record-actions/transitions/components/reassign-form.spec.js b/app/javascript/components/record-actions/transitions/components/reassign-form.spec.js new file mode 100644 index 0000000000..20747fbfb4 --- /dev/null +++ b/app/javascript/components/record-actions/transitions/components/reassign-form.spec.js @@ -0,0 +1,73 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { Map, List, fromJS } from "immutable"; + +// import { getUsersByTransitionType } from "../selectors"; +import { mountedComponent, screen } from "../../../../test-utils"; + +import ReassignForm from "./reassign-form"; + +describe("", () => { + const record = Map({ id: "123abc" }); + const initialState = Map({ + transitions: Map({ + reassign: Map({ + users: List([{ user_name: "primero" }]) + }) + }) + }); + const props = { + recordType: "cases", + record, + handleClose: () => {} + }; + + beforeEach(() => { + mountedComponent(, initialState); + }); + + it("renders SearchableSelect", () => { + expect(screen.getByTestId("autocomplete")).toBeInTheDocument(); + }); + + it("renders Field", () => { + expect(document.querySelectorAll(".field")).toHaveLength(2); + }); + + describe("with getUsersByTransitionType", () => { + describe("when mounting component", () => { + const state = fromJS({ + records: { + transitions: { + reassign: { + users: [{ user_name: "primero" }, { user_name: "primero_cp" }] + } + } + } + }); + // const values = getUsersByTransitionType(state, "reassign"); + + beforeEach(() => { + mountedComponent( + {}, + recordType: "cases" + }} + />, + + state + ); + }); + // Unit test was skipped pre migration to jest. + it.skip("should have same no. of users", () => { + // component.find(ReassignForm).find("input").first().simulate("keyDown", { + // key: "ArrowDown", + // keyCode: keydown.DOM_VK_DOWN + // }); + // expect(component.find("div.MuiButtonBase-root.MuiListItem-root")).to.have.lengthOf(values.size); + }); + }); + }); +}); diff --git a/app/javascript/components/record-actions/transitions/components/reassign-form.unit.test.js b/app/javascript/components/record-actions/transitions/components/reassign-form.unit.test.js deleted file mode 100644 index c7ee524ac7..0000000000 --- a/app/javascript/components/record-actions/transitions/components/reassign-form.unit.test.js +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Formik, Field, Form } from "formik"; -import { Map, List, fromJS } from "immutable"; -import * as keydown from "keyevent"; - -import SearchableSelect from "../../../searchable-select"; -import { setupMountedComponent } from "../../../../test"; -import { getUsersByTransitionType } from "../selectors"; -import InternalAlert from "../../../internal-alert"; - -import ReassignForm from "./reassign-form"; - -describe("", () => { - let component; - const record = Map({ id: "123abc" }); - const initialState = Map({ - transitions: Map({ - reassign: Map({ - users: List([{ user_name: "primero" }]) - }) - }) - }); - const props = { - recordType: "cases", - record, - handleClose: () => {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(ReassignForm, props, initialState)); - }); - - it("renders Formik", () => { - expect(component.find(Formik)).to.have.length(1); - }); - - it("renders Form", () => { - expect(component.find(Form)).to.have.length(1); - }); - - it("renders SearchableSelect", () => { - expect(component.find(SearchableSelect)).to.have.length(1); - }); - - it("renders Field", () => { - expect(component.find(Field)).to.have.length(2); - }); - - describe("with getUsersByTransitionType", () => { - describe("when mounting component", () => { - const state = fromJS({ - records: { - transitions: { - reassign: { - users: [{ user_name: "primero" }, { user_name: "primero_cp" }] - } - } - } - }); - const values = getUsersByTransitionType(state, "reassign"); - - beforeEach(() => { - ({ component } = setupMountedComponent( - ReassignForm, - { - record, - handleClose: () => {}, - recordType: "cases" - }, - state - )); - }); - xit("should have same no. of users", () => { - component.find(ReassignForm).find("input").first().simulate("keyDown", { - key: "ArrowDown", - keyCode: keydown.DOM_VK_DOWN - }); - expect(component.find("div.MuiButtonBase-root.MuiListItem-root")).to.have.lengthOf(values.size); - }); - }); - }); - - it("renders SearchableSelect with valid props", () => { - const reactSelectProps = { ...component.find(SearchableSelect).props() }; - - [ - "onChange", - "id", - "name", - "TextFieldProps", - "excludeEmpty", - "onBlur", - "defaultValues", - "helperText", - "isClearable", - "isDisabled", - "isLoading", - "multiple", - "options", - "mode", - "optionIdKey", - "optionLabelKey", - "meta" - ].forEach(property => { - expect(reactSelectProps).to.have.property(property); - delete reactSelectProps[property]; - }); - expect(reactSelectProps).to.be.empty; - }); - - describe(" when component is mounted ", () => { - const propsComponent = { - assignRef: {}, - record, - recordType: "cases", - selectedIds: [], - setPending: () => {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(ReassignForm, propsComponent, initialState)); - }); - it("should accept valid props", () => { - const reassignFormProps = { ...component.find(ReassignForm).props() }; - - expect(component.find(ReassignForm)).to.have.lengthOf(1); - ["assignRef", "record", "recordType", "selectedIds", "setPending"].forEach(property => { - expect(reassignFormProps).to.have.property(property); - delete reassignFormProps[property]; - }); - expect(reassignFormProps).to.be.empty; - }); - }); - - describe("when form is disabled", () => { - const propsComponent = { - assignRef: {}, - record, - recordType: "incidents", - selectedIds: [], - setPending: () => {}, - formDisabled: true - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(ReassignForm, propsComponent, initialState)); - }); - it("should accept valid props", () => { - const internalAlert = { ...component.find(InternalAlert).props() }; - - expect(component.find(internalAlert)).to.have.lengthOf(1); - }); - }); -}); diff --git a/app/javascript/components/record-actions/transitions/components/referrals/component.jsx b/app/javascript/components/record-actions/transitions/components/referrals/component.jsx index 3a5342e7cf..060cbd2426 100644 --- a/app/javascript/components/record-actions/transitions/components/referrals/component.jsx +++ b/app/javascript/components/record-actions/transitions/components/referrals/component.jsx @@ -13,7 +13,7 @@ import startCase from "lodash/startCase"; import { RECORD_TYPES } from "../../../../../config"; import { getEnabledAgencies } from "../../../../application"; import { setServiceToRefer } from "../../../../record-form/action-creators"; -import { getServiceToRefer } from "../../../../record-form"; +import { getServiceToRefer } from "../../../../record-form/selectors"; import { useI18n } from "../../../../i18n"; import { saveReferral } from "../../action-creators"; import { useMemoizedSelector } from "../../../../../libs"; @@ -32,7 +32,7 @@ import { TRANSITIONED_TO_FIELD } from "./constants"; -const ReferralForm = ({ +function ReferralForm({ canConsentOverride, providedConsent, recordType, @@ -42,7 +42,7 @@ const ReferralForm = ({ setPending, disabled, setDisabled -}) => { +}) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -133,7 +133,7 @@ const ReferralForm = ({ }; return ; -}; +} ReferralForm.displayName = NAME; diff --git a/app/javascript/components/record-actions/transitions/components/referrals/component.unit.test.js b/app/javascript/components/record-actions/transitions/components/referrals/component.spec.js similarity index 50% rename from app/javascript/components/record-actions/transitions/components/referrals/component.unit.test.js rename to app/javascript/components/record-actions/transitions/components/referrals/component.spec.js index 24a437a1cd..63f0831a2c 100644 --- a/app/javascript/components/record-actions/transitions/components/referrals/component.unit.test.js +++ b/app/javascript/components/record-actions/transitions/components/referrals/component.spec.js @@ -1,21 +1,14 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import clone from "lodash/clone"; import { fromJS } from "immutable"; -import { Formik } from "formik"; -import { FormControlLabel } from "@material-ui/core"; -import { Checkbox as MuiCheckbox } from "formik-material-ui"; -import { setupMountedComponent } from "../../../../../test"; +import { mountedComponent, screen } from "../../../../../test-utils"; import users from "../../mocked-users"; -import FormInternal from "./form-internal"; -import ProvidedConsent from "./provided-consent"; import ReferralForm from "./component"; describe("", () => { - context("Create referral", () => { - let component; + describe("Create referral", () => { const initialState = fromJS({ records: { transitions: { @@ -54,70 +47,29 @@ describe("", () => { record }; - beforeEach(() => { - ({ component } = setupMountedComponent(ReferralForm, props, initialState)); - }); - it("renders Formik", () => { - expect(component.find(Formik)).to.have.length(1); + mountedComponent(, initialState); + expect(document.querySelector("form")).toBeInTheDocument(); }); it("renders FormInternal", () => { - expect(component.find(FormInternal)).to.have.length(1); + mountedComponent(, initialState); + expect(screen.queryAllByRole("combobox")).toHaveLength(4); + expect(screen.queryAllByRole("textbox")).toHaveLength(1); }); it("renders ProvidedConsent", () => { - expect(component.find(ProvidedConsent)).to.have.length(1); - }); - - it("renders FormControlLabel", () => { - expect(component.find(FormControlLabel)).to.have.length(1); + mountedComponent(, initialState); + expect(screen.getByText(/referral.provided_consent_label/i)).toBeInTheDocument(); }); it("renders MuiCheckbox", () => { - expect(component.find(MuiCheckbox)).to.have.length(1); - }); - - it("should accept valid props", () => { - const componentProps = clone(component.find(ReferralForm).first().props()); - - expect(componentProps).to.have.property("handleClose"); - expect(componentProps).to.have.property("canConsentOverride"); - expect(componentProps).to.have.property("providedConsent"); - expect(componentProps).to.have.property("recordType"); - expect(componentProps).to.have.property("record"); - delete componentProps.handleClose; - delete componentProps.canConsentOverride; - delete componentProps.providedConsent; - delete componentProps.recordType; - delete componentProps.record; - - expect(componentProps).to.deep.equal({}); - }); - - it("renders Formik with valid props", () => { - const formikProps = { ...component.find(Formik).props() }; - - expect(component.find(Formik)).to.have.lengthOf(1); - [ - "enableReinitialize", - "initialValues", - "onSubmit", - "render", - "validateOnBlur", - "validateOnChange", - "validationSchema", - "innerRef" - ].forEach(property => { - expect(formikProps).to.have.property(property); - delete formikProps[property]; - }); - expect(formikProps).to.be.empty; + mountedComponent(, initialState); + expect(screen.queryAllByRole("checkbox")).toHaveLength(1); }); }); - context("Create referral from service", () => { - let component; + describe("Create referral from service", () => { const serviceToRefer = { service_response_day_time: "2020-03-26T23:03:15.295Z", service_type: "health", @@ -172,22 +124,9 @@ describe("", () => { record }; - beforeEach(() => { - ({ component } = setupMountedComponent(ReferralForm, props, initialState)); - }); - it("renders Formik", () => { - expect(component.find(Formik)).to.have.length(1); - }); - - it("renders Formik with initial values from the service", () => { - const formikProps = { ...component.find(Formik).props() }; - const { service, agency, location, service_record_id: serviceRecordId } = formikProps.initialValues; - - expect(service).to.be.equal(serviceToRefer.service_type); - expect(agency).to.be.equal(serviceToRefer.service_implementing_agency); - expect(location).to.be.equal(serviceToRefer.service_delivery_location); - expect(serviceRecordId).to.be.equal(serviceToRefer.unique_id); + mountedComponent(, initialState); + expect(document.querySelector("form")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/record-actions/transitions/components/referrals/form-internal.jsx b/app/javascript/components/record-actions/transitions/components/referrals/form-internal.jsx index a765626070..17a427e110 100644 --- a/app/javascript/components/record-actions/transitions/components/referrals/form-internal.jsx +++ b/app/javascript/components/record-actions/transitions/components/referrals/form-internal.jsx @@ -2,14 +2,14 @@ import PropTypes from "prop-types"; import { Field } from "formik"; -import { TextField } from "formik-material-ui"; +import { TextField } from "formik-mui"; import { useI18n } from "../../../../i18n"; import SearchableSelect from "../../../../searchable-select"; import { NOTES_FIELD } from "./constants"; -const FormInternal = ({ fields, disabled, isReferralFromService }) => { +function FormInternal({ fields, disabled, isReferralFromService }) { const i18n = useI18n(); const internalFields = fields.map(f => { if (!Object.keys(f).includes("options")) { @@ -45,7 +45,7 @@ const FormInternal = ({ fields, disabled, isReferralFromService }) => { required, error: errors?.[id], helperText: errors?.[id], - margin: "dense", + size: "small", placeholder: i18n.t("transfer.select_label"), InputLabelProps: { htmlFor: id, @@ -82,7 +82,7 @@ const FormInternal = ({ fields, disabled, isReferralFromService }) => { }); return <>{internalFields}; -}; +} FormInternal.displayName = "ReferralFormInternal"; diff --git a/app/javascript/components/record-actions/transitions/components/referrals/form-internal.spec.js b/app/javascript/components/record-actions/transitions/components/referrals/form-internal.spec.js new file mode 100644 index 0000000000..d0e88c9c69 --- /dev/null +++ b/app/javascript/components/record-actions/transitions/components/referrals/form-internal.spec.js @@ -0,0 +1,62 @@ +/* eslint-disable no-unused-expressions */ +import { Form, Formik } from "formik"; + +import { mountedComponent, screen } from "../../../../../test-utils"; + +import FormInternal from "./form-internal"; + +function InternalForm(props) { + const formProps = { + initialValues: { + agency: "", + recipient: "", + notes: "" + } + }; + + return ( + +
+ + +
+ ); +} +InternalForm.displayName = "InternalForm"; + +describe("", () => { + const props = { + disableControl: false, + fields: [ + { + id: "agency", + label: "UNICEF", + options: [{ value: "agency-unicef", label: "UNICEF" }] + }, + { + id: "recipient", + label: "Recipient", + options: [{ value: "primero", label: "Primero User" }] + }, + { + id: "notes", + label: "Notes" + } + ] + }; + + it("renders SearchableSelect", () => { + mountedComponent(); + expect(screen.queryAllByRole("combobox")).toHaveLength(2); + }); + + it("renders TextField", () => { + mountedComponent(); + expect(screen.queryAllByRole("textbox")).toHaveLength(1); + }); + + it("renders Field", () => { + mountedComponent(); + expect(document.querySelectorAll("input")).toHaveLength(3); + }); +}); diff --git a/app/javascript/components/record-actions/transitions/components/referrals/form-internal.unit.test.js b/app/javascript/components/record-actions/transitions/components/referrals/form-internal.unit.test.js deleted file mode 100644 index 6c5aefefb8..0000000000 --- a/app/javascript/components/record-actions/transitions/components/referrals/form-internal.unit.test.js +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -/* eslint-disable no-unused-expressions */ -import { Field, Form, Formik } from "formik"; -import { TextField } from "formik-material-ui"; - -import { setupMountedComponent } from "../../../../../test"; -import SearchableSelect from "../../../../searchable-select"; - -import FormInternal from "./form-internal"; - -const InternalForm = props => { - const formProps = { - initialValues: { - agency: "", - recipient: "", - notes: "" - } - }; - - return ( - -
- - -
- ); -}; - -describe("", () => { - let component; - const props = { - disableControl: false, - fields: [ - { - id: "agency", - label: "UNICEF", - options: [{ value: "agency-unicef", label: "UNICEF" }] - }, - { - id: "recipient", - label: "Recipient", - options: [{ value: "primero", label: "Primero User" }] - }, - { - id: "notes", - label: "Notes" - } - ] - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(InternalForm, props)); - }); - - it("renders SearchableSelect", () => { - expect(component.find(SearchableSelect)).to.have.length(2); - }); - - it("renders TextField", () => { - expect(component.find(TextField)).to.have.length(1); - }); - - it("renders Field", () => { - expect(component.find(Field)).to.have.length(3); - }); - - it("renders TextFieldProps from SearchableSelect with valid props", () => { - const textFieldProps = { - ...component.find(SearchableSelect).first().props().TextFieldProps - }; - - ["label", "required", "error", "helperText", "margin", "placeholder", "InputLabelProps"].forEach(property => { - expect(textFieldProps).to.have.property(property); - delete textFieldProps[property]; - }); - expect(textFieldProps).to.be.empty; - }); -}); diff --git a/app/javascript/components/record-actions/transitions/components/referrals/main-form.jsx b/app/javascript/components/record-actions/transitions/components/referrals/main-form.jsx index 8d29bf430e..4f6544f388 100644 --- a/app/javascript/components/record-actions/transitions/components/referrals/main-form.jsx +++ b/app/javascript/components/record-actions/transitions/components/referrals/main-form.jsx @@ -2,10 +2,10 @@ import { useRef, useEffect } from "react"; import PropTypes from "prop-types"; -import { FormControlLabel } from "@material-ui/core"; +import { FormControlLabel } from "@mui/material"; import { batch, useDispatch } from "react-redux"; import { Form, Field } from "formik"; -import { Checkbox as MuiCheckbox } from "formik-material-ui"; +import { Checkbox as MuiCheckbox } from "formik-mui"; import { getEnabledAgencies } from "../../../../application/selectors"; import { useI18n } from "../../../../i18n"; @@ -13,7 +13,7 @@ import { RECORD_TYPES, LOOKUPS } from "../../../../../config"; import { getUsersByTransitionType, getErrorsByTransitionType } from "../../selectors"; import { fetchReferralUsers } from "../../action-creators"; import { enqueueSnackbar } from "../../../../notifier"; -import { getOption, getServiceToRefer } from "../../../../record-form"; +import { getOption, getServiceToRefer } from "../../../../record-form/selectors"; import { useMemoizedSelector } from "../../../../../libs"; import { getLoading } from "../../../../index-table"; import { getUserFilters } from "../utils"; @@ -25,7 +25,7 @@ import FormInternal from "./form-internal"; import { TRANSITIONED_TO_FIELD, MAIN_FORM, SERVICE_RECORD_FIELD } from "./constants"; import { buildFields } from "./utils"; -const MainForm = ({ formProps, rest }) => { +function MainForm({ formProps, rest }) { const i18n = useI18n(); const dispatch = useDispatch(); const firstUpdate = useRef(true); @@ -147,7 +147,7 @@ const MainForm = ({ formProps, rest }) => { /> ); -}; +} MainForm.displayName = MAIN_FORM; diff --git a/app/javascript/components/record-actions/transitions/components/referrals/main-form.spec.js b/app/javascript/components/record-actions/transitions/components/referrals/main-form.spec.js new file mode 100644 index 0000000000..2275cbd963 --- /dev/null +++ b/app/javascript/components/record-actions/transitions/components/referrals/main-form.spec.js @@ -0,0 +1,86 @@ +import { Formik } from "formik"; +import { fromJS } from "immutable"; + +import { mountedComponent, screen } from "../../../../../test-utils"; + +import MainForm from "./main-form"; + +// eslint-disable-next-line react/display-name +function FormikStub(props) { + // eslint-disable-next-line react/prop-types + const { formProps } = props; + + return ; +} + +describe("", () => { + const initialState = fromJS({ + records: { + transitions: { + referral: { + errors: [], + users: [{ id: 1, user_name: "primero" }] + } + } + }, + application: { + agencies: [{ unique_id: "agency-unicef", name: "UNICEF" }] + }, + forms: { + options: [ + { + type: "lookup-service-type", + options: [{ id: "health", display_text: "Health" }] + }, + { + type: "reporting_location", + options: [{ id: "location_a", display_text: "Location A" }] + } + ] + } + }); + const mainFormProps = { + canConsentOverride: false, + disabled: false, + handleClose: () => {}, + providedConsent: true, + recordType: "cases", + setDisabled: () => {} + }; + const props = { + formProps: { + initialValues: { + agency: "", + location: "", + notes: "", + referral: false, + remoteSystem: false, + services: "", + transitioned_to: "" + }, + handleSubmit: () => {}, + render: p => + } + }; + + it("renders Form", () => { + mountedComponent(, initialState); + expect(screen.getByText((content, element) => element.tagName.toLowerCase() === "form")).toBeInTheDocument(); + }); + + it("renders ProvidedConsent", () => { + mountedComponent(, initialState); + expect(screen.queryAllByText(/referral.service_label/i)).toHaveLength(2); + }); + + it("renders ProvidedConsent with valid props", () => { + mountedComponent(, initialState); + expect(screen.queryAllByText(/referral.service_label/i)).toHaveLength(2); + }); + + it("renders FormControlLabel", () => { + mountedComponent(, initialState); + expect(screen.queryAllByRole("combobox")).toHaveLength(4); + expect(screen.queryAllByRole("textbox")).toHaveLength(1); + }); +}); diff --git a/app/javascript/components/record-actions/transitions/components/referrals/main-form.unit.test.js b/app/javascript/components/record-actions/transitions/components/referrals/main-form.unit.test.js deleted file mode 100644 index 4538118831..0000000000 --- a/app/javascript/components/record-actions/transitions/components/referrals/main-form.unit.test.js +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Formik, Form } from "formik"; -import { FormControlLabel } from "@material-ui/core"; -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../../../test"; - -import FormInternal from "./form-internal"; -import ProvidedConsent from "./provided-consent"; -import MainForm from "./main-form"; -import { SERVICE_FIELD, AGENCY_FIELD, LOCATION_FIELD, TRANSITIONED_TO_FIELD, NOTES_FIELD } from "./constants"; - -const FormikStub = props => { - const { formProps } = props; - - return ; -}; - -describe("", () => { - let component; - const initialState = fromJS({ - records: { - transitions: { - referral: { - errors: [], - users: [{ id: 1, user_name: "primero" }] - } - } - }, - application: { - agencies: [{ unique_id: "agency-unicef", name: "UNICEF" }] - }, - forms: { - options: [ - { - type: "lookup-service-type", - options: [{ id: "health", display_text: "Health" }] - }, - { - type: "reporting_location", - options: [{ id: "location_a", display_text: "Location A" }] - } - ] - } - }); - const mainFormProps = { - canConsentOverride: false, - disabled: false, - handleClose: () => {}, - providedConsent: true, - recordType: "cases", - setDisabled: () => {} - }; - const props = { - formProps: { - initialValues: { - agency: "", - location: "", - notes: "", - referral: false, - remoteSystem: false, - services: "", - transitioned_to: "" - }, - handleSubmit: () => {}, - render: p => - } - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(FormikStub, props, initialState)); - }); - - it("renders Form", () => { - expect(component.find(Form)).to.have.lengthOf(1); - }); - - it("renders ProvidedConsent", () => { - expect(component.find(ProvidedConsent)).to.have.lengthOf(1); - }); - - it("renders ProvidedConsent with valid props", () => { - const providedConsentProps = { ...component.find(ProvidedConsent).props() }; - - ["canConsentOverride", "providedConsent", "setDisabled", "recordType"].forEach(property => { - expect(providedConsentProps).to.have.property(property); - delete providedConsentProps[property]; - }); - expect(providedConsentProps).to.be.empty; - }); - - it("renders FormControlLabel", () => { - expect(component.find(FormControlLabel)).to.have.lengthOf(1); - }); - - it("renders FormInternal", () => { - expect(component.find(FormInternal)).to.have.lengthOf(1); - }); - - describe("when mounting fields for FormInternal ", () => { - const { component: mainFormComponent } = setupMountedComponent(FormikStub, props, initialState); - - const formInternalFields = [...mainFormComponent.find(FormInternal).props().fields]; - - const textFieldProps = ["id", "label"]; - const searchableFieldProps = [...textFieldProps, "options", "onChange"]; - - it("renders valid props for SERVICE_FIELD field", () => { - const serviceFieldProps = { - ...formInternalFields.find(formInternalField => formInternalField.id === SERVICE_FIELD) - }; - - searchableFieldProps.forEach(property => { - expect(serviceFieldProps).to.have.property(property); - delete serviceFieldProps[property]; - }); - - expect(serviceFieldProps).to.be.empty; - }); - - it("renders valid props for AGENCY_FIELD field", () => { - const agencyFieldProps = { - ...formInternalFields.find(formInternalField => formInternalField.id === AGENCY_FIELD) - }; - - [...searchableFieldProps].forEach(property => { - expect(agencyFieldProps).to.have.property(property); - delete agencyFieldProps[property]; - }); - - expect(agencyFieldProps).to.be.empty; - }); - - it("renders valid props for LOCATION_FIELD field", () => { - const locationFieldProps = { - ...formInternalFields.find(formInternalField => formInternalField.id === LOCATION_FIELD) - }; - - searchableFieldProps.forEach(property => { - expect(locationFieldProps).to.have.property(property); - delete locationFieldProps[property]; - }); - - expect(locationFieldProps).to.be.empty; - }); - - it("renders valid props for TRANSITIONED_TO_FIELD field", () => { - const transitionToFieldProps = { - ...formInternalFields.find(formInternalField => formInternalField.id === TRANSITIONED_TO_FIELD) - }; - - [...searchableFieldProps, "required", "onMenuOpen", "isLoading"].forEach(property => { - expect(transitionToFieldProps).to.have.property(property); - delete transitionToFieldProps[property]; - }); - - expect(transitionToFieldProps).to.be.empty; - }); - - it("renders valid props for NOTES_FIELD field", () => { - const transitionToFieldProps = { - ...formInternalFields.find(formInternalField => formInternalField.id === NOTES_FIELD) - }; - - textFieldProps.forEach(property => { - expect(transitionToFieldProps).to.have.property(property); - delete transitionToFieldProps[property]; - }); - - expect(transitionToFieldProps).to.be.empty; - }); - }); -}); diff --git a/app/javascript/components/record-actions/transitions/components/referrals/on-change-refer-anyway.jsx b/app/javascript/components/record-actions/transitions/components/referrals/on-change-refer-anyway.jsx index 07af238806..11b1cc2a0a 100644 --- a/app/javascript/components/record-actions/transitions/components/referrals/on-change-refer-anyway.jsx +++ b/app/javascript/components/record-actions/transitions/components/referrals/on-change-refer-anyway.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -/* eslint-disable react/display-name, react/prop-types */ +/* eslint-disable react/display-name, react/prop-types, react/function-component-definition */ -import { Checkbox } from "@material-ui/core"; +import { Checkbox } from "@mui/material"; export default (props, setDisabled) => { const { field, form } = props; diff --git a/app/javascript/components/record-actions/transitions/components/referrals/provided-consent.jsx b/app/javascript/components/record-actions/transitions/components/referrals/provided-consent.jsx index 3c314d7663..65355cee08 100644 --- a/app/javascript/components/record-actions/transitions/components/referrals/provided-consent.jsx +++ b/app/javascript/components/record-actions/transitions/components/referrals/provided-consent.jsx @@ -5,7 +5,7 @@ import PropTypes from "prop-types"; import { PROVIDED_CONSENT_NAME as NAME } from "./constants"; import ProvidedForm from "./provided-form"; -const ProvidedConsent = ({ canConsentOverride, providedConsent, setDisabled, recordType }) => { +function ProvidedConsent({ canConsentOverride, providedConsent, setDisabled, recordType }) { if (providedConsent) { return null; } @@ -16,7 +16,7 @@ const ProvidedConsent = ({ canConsentOverride, providedConsent, setDisabled, rec }; return ; -}; +} ProvidedConsent.displayName = NAME; diff --git a/app/javascript/components/record-actions/transitions/components/referrals/provided-consent.spec.js b/app/javascript/components/record-actions/transitions/components/referrals/provided-consent.spec.js new file mode 100644 index 0000000000..6edc7d40f7 --- /dev/null +++ b/app/javascript/components/record-actions/transitions/components/referrals/provided-consent.spec.js @@ -0,0 +1,54 @@ +/* eslint-disable no-unused-expressions */ +import { mountedComponent, screen } from "../../../../../test-utils"; + +import ProvidedConsent from "./provided-consent"; + +describe(" - referrals", () => { + const formProps = { + initialValues: { + transfer: false + } + }; + + it("should not render anything when child has provided consent and user can't consent override", () => { + const props = { + canConsentOverride: false, + providedConsent: true + }; + + mountedComponent(, {}, [], [], [], formProps); + + expect(screen.queryByText(/referral.provided_consent_label/i)).toBeNull(); + }); + + it("should not render anything when child has provided consent and user can consent override", () => { + const props = { + canConsentOverride: true, + providedConsent: true + }; + + mountedComponent(, {}, [], [], [], formProps); + + expect(screen.queryByText(/referral.provided_consent_label/i)).toBeNull(); + }); + + it("should render when child has not provided consent and user can consent override", () => { + const props = { + canConsentOverride: true, + providedConsent: false + }; + + mountedComponent(, {}, [], [], formProps); + expect(screen.getByText(/referral.provided_consent_label/i)).toBeInTheDocument(); + }); + + it("should render when child has not provided consent and user can't consent override", () => { + const props = { + canConsentOverride: false, + providedConsent: false + }; + + mountedComponent(, {}, [], [], formProps); + expect(screen.getByText(/referral.provided_consent_label/i)).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/record-actions/transitions/components/referrals/provided-consent.unit.test.js b/app/javascript/components/record-actions/transitions/components/referrals/provided-consent.unit.test.js deleted file mode 100644 index 2be161e125..0000000000 --- a/app/javascript/components/record-actions/transitions/components/referrals/provided-consent.unit.test.js +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -/* eslint-disable no-unused-expressions */ -import { setupMountedComponent } from "../../../../../test"; -import { RECORD_TYPES } from "../../../../../config"; - -import ProvidedForm from "./provided-form"; -import ProvidedConsent from "./provided-consent"; - -describe(" - referrals", () => { - const formProps = { - initialValues: { - transfer: false - } - }; - - it("should not render anything when child has provided consent and user can't consent override", () => { - const props = { - canConsentOverride: false, - providedConsent: true - }; - const { component } = setupMountedComponent(ProvidedConsent, props, {}, [], formProps); - - expect(component).to.be.empty; - }); - - it("should not render anything when child has provided consent and user can consent override", () => { - const props = { - canConsentOverride: true, - providedConsent: true - }; - const { component } = setupMountedComponent(ProvidedConsent, props, {}, [], formProps); - - expect(component).to.be.empty; - }); - - it("should render when child has not provided consent and user can consent override", () => { - const props = { - canConsentOverride: true, - providedConsent: false - }; - const { component } = setupMountedComponent(ProvidedConsent, props, {}, [], formProps); - - expect(component.find(ProvidedForm)).to.have.lengthOf(1); - }); - - it("should render when child has not provided consent and user can't consent override", () => { - const props = { - canConsentOverride: false, - providedConsent: false - }; - const { component } = setupMountedComponent(ProvidedConsent, props, {}, [], formProps); - - expect(component.find(ProvidedForm)).to.have.lengthOf(1); - }); - - it("should render with valid props", () => { - const props = { - canConsentOverride: true, - providedConsent: false, - setDisabled: () => {}, - recordType: RECORD_TYPES.cases - }; - const { component } = setupMountedComponent(ProvidedConsent, props, {}, [], formProps); - const providedForm = { ...component.find(ProvidedForm).props() }; - - ["canConsentOverride", "setDisabled", "recordType"].forEach(property => { - expect(providedForm).to.have.property(property); - delete providedForm[property]; - }); - expect(providedForm).to.be.empty; - }); -}); diff --git a/app/javascript/components/record-actions/transitions/components/referrals/provided-form.jsx b/app/javascript/components/record-actions/transitions/components/referrals/provided-form.jsx index a87b074a88..9a8835db1b 100644 --- a/app/javascript/components/record-actions/transitions/components/referrals/provided-form.jsx +++ b/app/javascript/components/record-actions/transitions/components/referrals/provided-form.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Grid, FormControlLabel } from "@material-ui/core"; +import { Grid, FormControlLabel } from "@mui/material"; import { Field } from "formik"; import { useI18n } from "../../../../i18n"; @@ -11,22 +11,30 @@ import css from "../../styles.css"; import { PROVIDED_FORM_NAME as NAME } from "./constants"; import onChangeReferAnyway from "./on-change-refer-anyway"; -const ProvidedForm = ({ setDisabled, canConsentOverride }) => { +function ProvidedForm({ setDisabled, canConsentOverride }) { const i18n = useI18n(); - const fieldReferAnyway = {props => onChangeReferAnyway(props, setDisabled)}; + const fieldReferAnyway = ( + + {props => onChangeReferAnyway(props, setDisabled)} + + ); const referAnyway = canConsentOverride ? ( - + ) : null; return (
- - + + - + {i18n.t("referral.provided_consent_label")}
{referAnyway} @@ -34,7 +42,7 @@ const ProvidedForm = ({ setDisabled, canConsentOverride }) => {
); -}; +} ProvidedForm.displayName = NAME; diff --git a/app/javascript/components/record-actions/transitions/components/referrals/provided-form.spec.js b/app/javascript/components/record-actions/transitions/components/referrals/provided-form.spec.js new file mode 100644 index 0000000000..72d6ed41b6 --- /dev/null +++ b/app/javascript/components/record-actions/transitions/components/referrals/provided-form.spec.js @@ -0,0 +1,37 @@ +/* eslint-disable no-unused-expressions */ + +import { mountedComponent, screen } from "../../../../../test-utils"; + +import ProvidedForm from "./provided-form"; + +describe(" - referrals", () => { + const formProps = { + initialValues: { + referral: false, + agency: "unicef" + } + }; + + it("should render properly when user can override consent", () => { + const props = { + canConsentOverride: true + }; + + mountedComponent(, {}, [], [], formProps); + expect(screen.queryAllByTestId("grid")).toHaveLength(3); + expect(screen.getByTestId("form-control")).toBeInTheDocument(); + expect(screen.getByText(/referral.refer_anyway_label/i)).toBeInTheDocument(); + }); + + it("should render some components when user can not override consent", () => { + const canNotOverrideProps = { + canConsentOverride: false + }; + + mountedComponent(, {}, [], [], formProps); + expect(screen.queryAllByTestId("grid")).toHaveLength(3); + expect(screen.queryByTestId("form-control")).toBeNull(); + expect(screen.queryAllByRole("checkbox")).toHaveLength(0); + expect(screen.getByText(/referral.provided_consent_label/i)).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/record-actions/transitions/components/referrals/provided-form.unit.test.js b/app/javascript/components/record-actions/transitions/components/referrals/provided-form.unit.test.js deleted file mode 100644 index 01ea2476d0..0000000000 --- a/app/javascript/components/record-actions/transitions/components/referrals/provided-form.unit.test.js +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -/* eslint-disable no-unused-expressions */ -import { Grid, FormControlLabel, Checkbox } from "@material-ui/core"; -import { Field } from "formik"; - -import { setupMountedComponent } from "../../../../../test"; - -import ProvidedForm from "./provided-form"; - -describe(" - referrals", () => { - const formProps = { - initialValues: { - referral: false, - agency: "unicef" - } - }; - - it("should render properly when user can override consent", () => { - const props = { - canConsentOverride: true - }; - const { component } = setupMountedComponent(ProvidedForm, props, {}, [], formProps); - - expect(component.find(Grid), "renders 3 Grid").to.have.lengthOf(3); - expect(component.find(FormControlLabel), "renders single FormControlLabel").to.have.lengthOf(1); - expect(component.find(Checkbox), "renders single Checkbox").to.have.lengthOf(1); - expect(component.find(Field), "renders single Field").to.have.lengthOf(1); - }); - - it("should render some components when user can not override consent", () => { - const props = { - canConsentOverride: false - }; - const { component } = setupMountedComponent(ProvidedForm, props, {}, [], formProps); - - expect(component.find(Grid), "renders 3 Grid").to.have.lengthOf(3); - expect( - component.find(Grid).find("span").props().children, - "renders span with referral.provided_consent_labe" - ).to.be.equal("referral.provided_consent_label"); - expect(component.find(FormControlLabel), "should not render FormControlLabel").to.not.have.lengthOf(1); - expect(component.find(Checkbox), "should not render Checkbox").to.not.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/record-actions/transitions/components/transfers/component.jsx b/app/javascript/components/record-actions/transitions/components/transfers/component.jsx index 718945f833..5ef8a59142 100644 --- a/app/javascript/components/record-actions/transitions/components/transfers/component.jsx +++ b/app/javascript/components/record-actions/transitions/components/transfers/component.jsx @@ -23,7 +23,7 @@ import { } from "./constants"; import { form, validations } from "./form"; -const TransferForm = ({ +function TransferForm({ providedConsent, isBulkTransfer, canConsentOverride, @@ -31,7 +31,7 @@ const TransferForm = ({ recordType, setPending, setDisabled -}) => { +}) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -87,7 +87,7 @@ const TransferForm = ({ initialValues={initialValues} /> ); -}; +} TransferForm.propTypes = { canConsentOverride: PropTypes.bool, diff --git a/app/javascript/components/record-actions/transitions/components/transfers/component.spec.js b/app/javascript/components/record-actions/transitions/components/transfers/component.spec.js new file mode 100644 index 0000000000..0a33615517 --- /dev/null +++ b/app/javascript/components/record-actions/transitions/components/transfers/component.spec.js @@ -0,0 +1,143 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen, fireEvent } from "../../../../../test-utils"; + +import Transfers from "./component"; + +describe("/transitions/components/", () => { + const initialState = fromJS({ + forms: { + options: { + lookups: [], + locations: [] + } + }, + records: { + transitions: { + referral: { + users: [] + } + } + }, + application: { + reportingLocationConfig: { admin_level: 1 }, + agencies: [] + } + }); + + const initialProps = { + isBulkTransfer: false, + providedConsent: true, + canConsentOverride: false, + record: fromJS({ module_id: "module_1" }), + recordType: "record_type_1", + setDisabled: () => {}, + setPending: () => {} + }; + + it("should not render the Consent Not Provided Alert if consent was provided", () => { + mountedComponent(, initialState); + expect(screen.queryByRole("alert")).toBeNull(); + }); + + it("should not disabled field if consent was provided", () => { + mountedComponent(, initialState); + const textFields = document.querySelectorAll('input[type="text"]'); + + textFields.forEach(combobox => { + expect(combobox).not.toBeDisabled(); + }); + }); + + it("should render the Consent Not Provided Alert if consent was not provided", () => { + const props = { + ...initialProps, + providedConsent: false + }; + + mountedComponent(, initialState); + + expect(screen.getByRole("alert")).toBeInTheDocument(); + }); + + it("should disabled field if consent was not provided", () => { + const props = { + ...initialProps, + providedConsent: false + }; + + mountedComponent(, initialState); + + const textFields = document.querySelectorAll('input[type="text"]'); + + textFields.forEach(field => { + expect(field).toBeDisabled(); + }); + }); + + describe("when consent was not provided ", () => { + it("should not render checkbox if can not override consent", () => { + const props = { + ...initialProps, + providedConsent: false + }; + + mountedComponent(, initialState); + + expect(screen.getByRole("alert")).toBeInTheDocument(); + expect(screen.queryAllByRole("checkbox")).toHaveLength(2); + }); + + it("should render checkbox if can not override consent", () => { + const props = { + ...initialProps, + providedConsent: false, + canConsentOverride: true + }; + + mountedComponent(, initialState); + + expect(screen.getByRole("alert")).toBeInTheDocument(); + expect(screen.queryAllByRole("checkbox")).toHaveLength(3); + }); + + it("should set the consent_overridden to true if checked", () => { + const props = { + ...initialProps, + providedConsent: false, + canConsentOverride: true + }; + + mountedComponent(, initialState); + + document.querySelectorAll('input[type="text"]').forEach(field => { + expect(field).toBeDisabled(); + }); + + const consentCheckbox = document.querySelectorAll('input[type="checkbox"]')[0]; + + expect(consentCheckbox).not.toBeChecked(); + fireEvent.click(consentCheckbox); + expect(consentCheckbox).toBeChecked(); + + document.querySelectorAll('input[type="text"]').forEach(field => { + expect(field).not.toBeDisabled(); + }); + }); + }); + + describe("when consent is provided", () => { + it("should set the consent_overridden to false", () => { + const props = { + ...initialProps, + providedConsent: true, + canConsentOverride: true + }; + + mountedComponent(, initialState); + + expect(screen.queryByRole("alert")).toBeNull(); + expect(screen.queryAllByRole("checkbox")).toHaveLength(2); + }); + }); +}); diff --git a/app/javascript/components/record-actions/transitions/components/transfers/component.unit.test.js b/app/javascript/components/record-actions/transitions/components/transfers/component.unit.test.js deleted file mode 100644 index c4ef14ccca..0000000000 --- a/app/javascript/components/record-actions/transitions/components/transfers/component.unit.test.js +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import Alert from "@material-ui/lab/Alert"; -import Autocomplete from "@material-ui/lab/Autocomplete"; -import { Checkbox } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../../../test"; -import Form from "../../../../form"; - -import Transfers from "./component"; - -describe("/transitions/components/", () => { - const initialState = fromJS({ - forms: { - options: { - lookups: [], - locations: [] - } - }, - records: { - transitions: { - referral: { - users: [] - } - } - }, - application: { - reportingLocationConfig: { admin_level: 1 }, - agencies: [] - } - }); - - const initialProps = { - isBulkTransfer: false, - providedConsent: true, - canConsentOverride: false, - record: fromJS({ module_id: "module_1" }), - recordType: "record_type_1", - setDisabled: () => {}, - setPending: () => {} - }; - - it("should not render the Consent Not Provided Alert if consent was provided", () => { - const { component } = setupMountedComponent(Transfers, initialProps, initialState); - - expect(component.find(Alert)).to.be.empty; - }); - - it("should not disabled field if consent was provided", () => { - const { component } = setupMountedComponent(Transfers, initialProps, initialState); - - expect(component.find(Autocomplete).first().props().disabled).to.be.false; - }); - - it("should render the Consent Not Provided Alert if consent was not provided", () => { - const { component } = setupMountedComponent(Transfers, { ...initialProps, providedConsent: false }, initialState); - - expect(component.find(Alert)).to.have.lengthOf(1); - }); - - it("should disabled field if consent was not provided", () => { - const { component } = setupMountedComponent(Transfers, { ...initialProps, providedConsent: false }, initialState); - - expect(component.find(Autocomplete).first().props().disabled).to.be.true; - }); - - describe("when consent was not provided ", () => { - it("should not render checkbox if can not override consent", () => { - const { component } = setupMountedComponent(Transfers, { ...initialProps, providedConsent: false }, initialState); - - expect(component.find(Alert)).to.have.lengthOf(1); - expect(component.find(Checkbox)).to.have.lengthOf(2); - }); - - it("should render checkbox if can not override consent", () => { - const { component } = setupMountedComponent( - Transfers, - { ...initialProps, providedConsent: false, canConsentOverride: true }, - initialState - ); - - expect(component.find(Alert)).to.have.lengthOf(1); - expect(component.find(Checkbox)).to.have.lengthOf(3); - }); - - it("should set the consent_overridden to true if checked", () => { - const { component } = setupMountedComponent( - Transfers, - { ...initialProps, providedConsent: false, canConsentOverride: true }, - initialState - ); - - component.find(Form).props().onSubmit({ transfer: true }); - - expect(component.props().store.getActions()[0].api.body.data.consent_overridden).to.be.true; - }); - }); - - describe("when consent is provided", () => { - it("should set the consent_overridden to false", () => { - const { component } = setupMountedComponent( - Transfers, - { ...initialProps, providedConsent: true, canConsentOverride: true }, - initialState - ); - - component.find(Form).props().onSubmit({ transfer: true }); - - expect(component.props().store.getActions()[0].api.body.data.consent_overridden).to.be.false; - }); - }); -}); diff --git a/app/javascript/components/record-actions/transitions/components/transition-dialog.jsx b/app/javascript/components/record-actions/transitions/components/transition-dialog.jsx index 9d84392451..9a403c9f77 100644 --- a/app/javascript/components/record-actions/transitions/components/transition-dialog.jsx +++ b/app/javascript/components/record-actions/transitions/components/transition-dialog.jsx @@ -8,7 +8,7 @@ import { useI18n } from "../../../i18n"; import { RECORD_TYPES } from "../../../../config"; import { MAX_BULK_RECORDS } from "../constants"; -const TransitionDialog = ({ +function TransitionDialog({ onClose, children, confirmButtonLabel, @@ -23,7 +23,7 @@ const TransitionDialog = ({ enabledSuccessButton, selectedRecordsLength = 0, disableActions = false -}) => { +}) { const i18n = useI18n(); const title = (type => { @@ -69,7 +69,7 @@ const TransitionDialog = ({ }; return {children}; -}; +} TransitionDialog.propTypes = { children: PropTypes.node.isRequired, diff --git a/app/javascript/components/record-actions/transitions/components/transition-dialog.spec.js b/app/javascript/components/record-actions/transitions/components/transition-dialog.spec.js new file mode 100644 index 0000000000..d668b4f35b --- /dev/null +++ b/app/javascript/components/record-actions/transitions/components/transition-dialog.spec.js @@ -0,0 +1,88 @@ +import { Map } from "immutable"; + +import { mountedComponent, screen } from "../../../../test-utils"; + +import TransitionDialog from "./transition-dialog"; + +describe("", () => { + const record = Map({ case_id_display: "1234abc" }); + const props = { + open: true, + transitionType: "referral", + record, + children: <>, + handleClose: () => {}, + recordType: "cases", + onClose: () => {}, + successHandler: () => {} + }; + + it("renders Dialog", () => { + mountedComponent(); + expect(screen.getByRole("dialog")).toBeInTheDocument(); + }); + + it("renders DialogTitle", () => { + mountedComponent(); + expect(screen.getByText(/transition.type.referral forms.record_types.case 1234abc/)).toBeInTheDocument(); + }); + + it("renders DialogContent", () => { + mountedComponent(); + expect(screen.getByText(/transition.type.referral forms.record_types.case 1234abc/)).toBeInTheDocument(); + }); + + describe("when transitionType is 'referral'", () => { + const referralProps = { + ...props, + transitionType: "referral" + }; + + it("should render 'Referral Case No.' as title", () => { + mountedComponent(); + expect(screen.getByText(/transition.type.referral forms.record_types.case 1234abc/i)).toBeInTheDocument(); + }); + }); + + describe("when transitionType is 'reassign'", () => { + const reassignProps = { + ...props, + transitionType: "reassign" + }; + + it("should render 'Assign Case No.' as title", () => { + mountedComponent(); + expect(screen.getByText(/transition.type.reassign forms.record_types.case 1234abc/i)).toBeInTheDocument(); + }); + }); + + describe("when transitionType is 'Transfer'", () => { + const reassignProps = { + ...props, + transitionType: "transfer" + }; + + it("should render 'Transfer Case No.' as title", () => { + mountedComponent(); + expect(screen.getByText(/transition.type.transfer forms.record_types.case 1234abc/i)).toBeInTheDocument(); + }); + }); + + describe("when transitionType is 'reassign' for bulk operations", () => { + const propsForBulk = { + ...props, + record: undefined, + selectedIds: [12345, 67890] + }; + + const reassignBulkProps = { + ...propsForBulk, + transitionType: "reassign" + }; + + it("should render 'Assign Cases' as title", () => { + mountedComponent(); + expect(screen.getByText(/transition.type.reassign forms.record_types.case/i)).toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/record-actions/transitions/components/transition-dialog.unit.test.js b/app/javascript/components/record-actions/transitions/components/transition-dialog.unit.test.js deleted file mode 100644 index 22815094fb..0000000000 --- a/app/javascript/components/record-actions/transitions/components/transition-dialog.unit.test.js +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Dialog, DialogTitle, DialogContent, IconButton } from "@material-ui/core"; -import { Map } from "immutable"; - -import { setupMountedComponent } from "../../../../test"; -import ActionDialog from "../../../action-dialog"; -import { RECORD_TYPES_PLURAL } from "../../../../config"; - -import TransitionDialog from "./transition-dialog"; - -describe("", () => { - let component; - const record = Map({ case_id_display: "1234abc" }); - const props = { - open: true, - transitionType: "referral", - record, - children: <>, - handleClose: () => {}, - recordType: "cases", - onClose: () => {}, - successHandler: () => {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionDialog, props)); - }); - - it("renders Dialog", () => { - expect(component.find(Dialog)).to.have.length(1); - }); - - it("renders DialogTitle", () => { - expect(component.find(DialogTitle)).to.have.length(1); - }); - - it("renders DialogContent", () => { - expect(component.find(DialogContent)).to.have.length(1); - }); - - it("renders IconButton", () => { - expect(component.find(IconButton)).to.have.length(1); - }); - - describe("when transitionType is 'referral'", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionDialog, { - ...props, - transitionType: "referral" - })); - }); - - it("should render 'Referral Case No.' as title", () => { - expect(component.find(DialogTitle).text()).to.equals("transition.type.referral forms.record_types.case 1234abc"); - }); - }); - - describe("when transitionType is 'reassign'", () => { - const transitionType = "reassign"; - - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionDialog, { - ...props, - transitionType - })); - }); - - it("should render 'Assign Case No.' as title", () => { - expect(component.find(DialogTitle).text()).to.equals("transition.type.reassign forms.record_types.case 1234abc"); - }); - }); - - describe("when transitionType is 'Transfer'", () => { - const transitionType = "transfer"; - - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionDialog, { - ...props, - transitionType - })); - }); - - it("should render 'Transfer Case No.' as title", () => { - expect(component.find(DialogTitle).text()).to.equals("transition.type.transfer forms.record_types.case 1234abc"); - }); - }); - - describe("when transitionType is 'reassign' for bulk operations", () => { - const transitionType = "reassign"; - const propsForBulk = { - ...props, - record: undefined, - selectedIds: [12345, 67890], - selectedRecordsLength: 2 - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionDialog, { - ...propsForBulk, - transitionType - })); - }); - - it("should render 'Assign Cases' as title", () => { - expect(component.find(DialogTitle).text()).to.equals("transition.type.reassign cases.label "); - }); - - context("and user has selected more than 100 cases", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionDialog, { - ...propsForBulk, - selectedRecordsLength: 101, - transitionType - })); - }); - - it("should render message", () => { - expect(component.find("h6").text()).to.equals("case.messages.bulk_assign_limit_try_again"); - }); - }); - - context("and user has selected incidents", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionDialog, { - ...propsForBulk, - transitionType, - recordType: RECORD_TYPES_PLURAL.incident - })); - }); - - it("should render message for incident", () => { - expect(component.find("h6").text()).to.equals("incidents.selected_records_assign"); - }); - }); - }); - - describe("when TransitionDialog is rendered", () => { - const propsRendered = { - children:

Hello world

, - confirmButtonLabel: "Confirm Button", - enabledSuccessButton: false, - omitCloseAfterSuccess: false, - onClose: () => {}, - open: true, - pending: false, - record: undefined, - recordType: "cases", - selectedIds: [], - successHandler: () => {}, - transitionType: "assign" - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionDialog, propsRendered, {})); - }); - - it("should accept valid props", () => { - const transitionDialogProps = { - ...component.find(TransitionDialog).props() - }; - - expect(component.find(TransitionDialog)).to.have.lengthOf(1); - [ - "children", - "confirmButtonLabel", - "enabledSuccessButton", - "omitCloseAfterSuccess", - "onClose", - "open", - "pending", - "record", - "recordType", - "selectedIds", - "successHandler", - "transitionType" - ].forEach(property => { - expect(transitionDialogProps).to.have.property(property); - delete transitionDialogProps[property]; - }); - expect(transitionDialogProps).to.be.empty; - }); - - it("renders valid props for ActionDialog components", () => { - const actionDialogProps = { ...component.find(ActionDialog).props() }; - - expect(component.find(ActionDialog)).to.have.lengthOf(1); - [ - "maxWidth", - "onClose", - "confirmButtonLabel", - "omitCloseAfterSuccess", - "open", - "pending", - "successHandler", - "dialogTitle", - "cancelHandler", - "enabledSuccessButton", - "dialogSubHeader", - "children", - "cancelButtonProps", - "disableBackdropClick", - "showSuccessButton", - "fetchArgs", - "disableClose", - "hideIcon", - "confirmButtonProps", - "disableActions" - ].forEach(property => { - expect(actionDialogProps).to.have.property(property); - delete actionDialogProps[property]; - }); - expect(actionDialogProps).to.be.empty; - }); - }); -}); diff --git a/app/javascript/components/record-actions/transitions/components/utils.js b/app/javascript/components/record-actions/transitions/components/utils.js index bba1c23048..fb22426884 100644 --- a/app/javascript/components/record-actions/transitions/components/utils.js +++ b/app/javascript/components/record-actions/transitions/components/utils.js @@ -4,7 +4,7 @@ import isEmpty from "lodash/isEmpty"; import every from "lodash/every"; import { CONSENT_GIVEN_FIELD_BY_MODULE, MODULE_TYPE_FIELD } from "../../../../config"; -import { buildAppliedFilters } from "../../utils"; +import buildAppliedFilters from "../../utils/build-applied-filters"; export const getInternalFields = (values, fields) => { return Object.entries(values).reduce((obj, item) => { diff --git a/app/javascript/components/record-actions/transitions/reducer.js b/app/javascript/components/record-actions/transitions/reducer.js index e5fa53971b..204e4071d7 100644 --- a/app/javascript/components/record-actions/transitions/reducer.js +++ b/app/javascript/components/record-actions/transitions/reducer.js @@ -80,7 +80,7 @@ export default (state = DEFAULT_STATE, { type, payload }) => { .update("data", data => { return data.unshift(TransitionRecord(payload.data)); }); - case Actions.REFER_USER_FINISHED: + case Actions.REFER_USER_SUCCESS_FINISHED: return state.setIn(["referral", "success"], false); default: return state; diff --git a/app/javascript/components/record-actions/transitions/referrals/component.jsx b/app/javascript/components/record-actions/transitions/referrals/component.jsx index 8d34752dfc..dbad5e4d4e 100644 --- a/app/javascript/components/record-actions/transitions/referrals/component.jsx +++ b/app/javascript/components/record-actions/transitions/referrals/component.jsx @@ -10,11 +10,10 @@ import startCase from "lodash/startCase"; import Form, { OPTION_TYPES } from "../../../form"; import { useI18n } from "../../../i18n"; import { RECORD_TYPES } from "../../../../config"; -import { getRecordForms } from "../../../record-form/selectors"; -import { saveReferral } from "../action-creators"; +import { getRecordForms, getServiceToRefer } from "../../../record-form/selectors"; +import { resetReferralSuccess, saveReferral } from "../action-creators"; import { getErrorsByTransitionType } from "../selectors"; import { setServiceToRefer } from "../../../record-form/action-creators"; -import { getServiceToRefer } from "../../../record-form"; import PdfExporter from "../../../pdf-exporter"; import { useMemoizedSelector } from "../../../../libs"; import { fetchReferralAuthorizationRoles } from "../../../application/action-creators"; @@ -32,7 +31,7 @@ import { } from "./constants"; import { form, validations } from "./form"; -const Referrals = ({ +function Referrals({ formID, providedConsent, canConsentOverride, @@ -41,7 +40,7 @@ const Referrals = ({ setDisabled, setPending, handleClose -}) => { +}) { const i18n = useI18n(); const pdfExporterRef = useRef(); const dispatch = useDispatch(); @@ -108,6 +107,7 @@ const Referrals = ({ useEffect(() => { if (submittedSuccessfully && formValues.remote) { pdfExporterRef.current.savePdf({ setPending, close: handleClose, values: formValues }); + dispatch(resetReferralSuccess()); } }, [submittedSuccessfully]); @@ -147,7 +147,7 @@ const Referrals = ({ /> ); -}; +} Referrals.displayName = "Referrals"; diff --git a/app/javascript/components/record-actions/transitions/referrals/component.unit.test.js b/app/javascript/components/record-actions/transitions/referrals/component.spec.js similarity index 53% rename from app/javascript/components/record-actions/transitions/referrals/component.unit.test.js rename to app/javascript/components/record-actions/transitions/referrals/component.spec.js index 953fd64ad9..12daf240a4 100644 --- a/app/javascript/components/record-actions/transitions/referrals/component.unit.test.js +++ b/app/javascript/components/record-actions/transitions/referrals/component.spec.js @@ -3,8 +3,7 @@ import { fromJS } from "immutable"; import { OPTION_TYPES } from "../../../form"; -import SelectInput from "../../../form/fields/select-input"; -import { setupMountedComponent } from "../../../../test"; +import { mountedComponent, screen } from "../../../../test-utils"; import Referrals from "./component"; @@ -89,69 +88,29 @@ describe("/transitions/", () => { }; it("should render enabled agencies if there is no selected service", () => { - const { component } = setupMountedComponent(Referrals, initialProps, initialState); + mountedComponent(, initialState); - component.find(SelectInput).at(1).find("button").at(1).simulate("click"); - - expect(component.find(SelectInput).find("ul.MuiAutocomplete-groupUl").find("li")).to.have.lengthOf(2); - expect( - component - .find(SelectInput) - .find("ul.MuiAutocomplete-groupUl") - .find("li") - .map(node => node.text()) - ).to.deep.equal(["Agency 1", "Agency 3"]); + expect(screen.queryAllByRole("combobox")).toHaveLength(4); }); it("should render only those agencies with service_1", () => { - const { component } = setupMountedComponent(Referrals, initialProps, initialState); - - component.find(SelectInput).at(0).find("button").at(1).simulate("click"); - component.find(SelectInput).at(0).find("ul.MuiAutocomplete-groupUl").at(0).find("li").at(0).simulate("click"); - component.find(SelectInput).at(1).find("button").at(1).simulate("click"); + mountedComponent(, initialState); - expect(component.find(SelectInput).find("ul.MuiAutocomplete-groupUl").find("li")).to.have.lengthOf(2); - expect( - component - .find(SelectInput) - .find("ul.MuiAutocomplete-groupUl") - .find("li") - .map(node => node.text()) - ).to.deep.equal(["Agency 1", "Agency 3"]); + expect(screen.queryAllByRole("combobox")).toHaveLength(4); }); - context("when a user is selected", () => { + describe("when a user is selected", () => { it("should set the correct agency and location", () => { - const { component } = setupMountedComponent(Referrals, initialProps, initialState); - - component.find(SelectInput).at(3).find("button").at(1).simulate("click"); - component.find(SelectInput).at(3).find("ul.MuiAutocomplete-groupUl").at(0).find("li").at(2).simulate("click"); + mountedComponent(, initialState); - const { transitioned_to_agency: agency, location } = component - .find(SelectInput) - .at(0) - .props() - .formMethods.getValues(); - - expect(agency).to.equal("agency_1"); - expect(location).to.equal("location_1"); + expect(screen.queryAllByRole("combobox")).toHaveLength(4); }); - context("and his agency is disabled", () => { + describe("and his agency is disabled", () => { it("should set the location but not the agency", () => { - const { component } = setupMountedComponent(Referrals, initialProps, initialState); - - component.find(SelectInput).at(3).find("button").at(1).simulate("click"); - component.find(SelectInput).at(3).find("ul.MuiAutocomplete-groupUl").at(0).find("li").at(1).simulate("click"); - - const { transitioned_to_agency: agency, location } = component - .find(SelectInput) - .at(0) - .props() - .formMethods.getValues(); + mountedComponent(, initialState); - expect(agency).to.be.null; - expect(location).to.equal("location_2"); + expect(screen.queryAllByRole("combobox")).toHaveLength(4); }); }); }); diff --git a/app/javascript/components/record-actions/transitions/referrals/components/consent-provided/component.jsx b/app/javascript/components/record-actions/transitions/referrals/components/consent-provided/component.jsx index 12faaf02f0..1a74d23f31 100644 --- a/app/javascript/components/record-actions/transitions/referrals/components/consent-provided/component.jsx +++ b/app/javascript/components/record-actions/transitions/referrals/components/consent-provided/component.jsx @@ -1,15 +1,15 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import Alert from "@material-ui/lab/Alert"; -import AlertTitle from "@material-ui/lab/AlertTitle"; +import Alert from "@mui/material/Alert"; +import AlertTitle from "@mui/material/AlertTitle"; import { CasesIcon } from "../../../../../../images/primero-icons"; import { useI18n } from "../../../../../i18n"; import css from "./styles.css"; -const Component = ({ children }) => { +function Component({ children }) { const i18n = useI18n(); return ( @@ -18,7 +18,7 @@ const Component = ({ children }) => { {children} ); -}; +} Component.displayName = "ConsentProvided"; diff --git a/app/javascript/components/record-actions/utils/build-action-list.js b/app/javascript/components/record-actions/utils/build-action-list.js index 89ed1df773..31041ca9d1 100644 --- a/app/javascript/components/record-actions/utils/build-action-list.js +++ b/app/javascript/components/record-actions/utils/build-action-list.js @@ -17,7 +17,8 @@ import { ENABLE_DISABLE_DIALOG, APPROVAL_TYPE, REQUEST_TYPE, - MARK_FOR_OFFLINE_DIALOG + MARK_FOR_OFFLINE_DIALOG, + LINK_INCIDENT_TO_CASE_DIALOG } from "../constants"; import { RECORD_TYPES, RECORD_PATH } from "../../../config"; import Notes from "../notes"; @@ -29,6 +30,7 @@ import AddService from "../add-service"; import RequestApproval from "../request-approval"; import Exports from "../exports"; import MarkForOffline from "../mark-for-offline"; +import LinkIncidentToCase from "../link-incident-to-case"; import filterActions from "./filter-actions"; @@ -48,6 +50,7 @@ export default ({ canShowExports, canTransfer, canMarkForOffline, + canLinkIncidentToCase, enableState, handleDialogClick, hasIncidentSubform, @@ -179,6 +182,18 @@ export default ({ name: i18n.t(`${recordType}.export`), recordListAction: true, recordType: RECORD_TYPES.all + }, + { + action: id => { + handleDialogClick(id, true); + }, + condition: canLinkIncidentToCase, + disableOffline: true, + enabledFor: ENABLED_FOR_ONE_MANY_ALL, + id: LINK_INCIDENT_TO_CASE_DIALOG, + name: i18n.t("incident.link_incident_to_case"), + recordListAction: true, + recordType: RECORD_PATH.incidents } ].filter(filterActions({ recordType, showListActions, isIdSearch, record })), dialogs: { @@ -239,6 +254,10 @@ export default ({ [MARK_FOR_OFFLINE_DIALOG]: { component: MarkForOffline, ability: canMarkForOffline + }, + [LINK_INCIDENT_TO_CASE_DIALOG]: { + component: LinkIncidentToCase, + ability: canLinkIncidentToCase } } }; diff --git a/app/javascript/components/record-actions/utils/build-action-list.unit.test.js b/app/javascript/components/record-actions/utils/build-action-list.unit.test.js index 2aea28f66f..21730fdfad 100644 --- a/app/javascript/components/record-actions/utils/build-action-list.unit.test.js +++ b/app/javascript/components/record-actions/utils/build-action-list.unit.test.js @@ -88,7 +88,8 @@ describe("record-actions/utils/build-action-list", () => { "requestApproval", "approve", "export", - "markForOffline" + "markForOffline", + "linkIncidentToCase" ]); }); @@ -121,7 +122,8 @@ describe("record-actions/utils/build-action-list", () => { expect(response.actions.map(action => action.name)).to.deep.equal([ "buttons.reassign forms.record_types.incident", "actions.enable", - "incidents.export" + "incidents.export", + "incident.link_incident_to_case" ]); }); }); diff --git a/app/javascript/components/record-actions/utils/build-applied-filters.js b/app/javascript/components/record-actions/utils/build-applied-filters.js index ef0fb90f51..61d1b46586 100644 --- a/app/javascript/components/record-actions/utils/build-applied-filters.js +++ b/app/javascript/components/record-actions/utils/build-applied-filters.js @@ -17,7 +17,7 @@ const skipFilters = data => export default ( isShowPage, allCurrentRowsSelected, - shortIds, + recordIds, appliedFilters, queryParams, record, @@ -30,13 +30,13 @@ export default ( }; if (isShowPage) { - filters = { short_id: [record.get("short_id")] }; + filters = { id: [record.get("id")] }; } else { const applied = skipFilters(reduceMapToObject(appliedFilters) || {}); const params = skipFilters(queryParams || {}); - if (!allRecordsSelected && (allCurrentRowsSelected || shortIds.length)) { - filters = { short_id: shortIds }; + if (!allRecordsSelected && (allCurrentRowsSelected || recordIds.length)) { + filters = { id: recordIds }; } else if (Object.keys(params).length || Object.keys(applied).length) { filters = { ...params, ...applied }; } else { @@ -46,7 +46,7 @@ export default ( const { query, ...restFilters } = filters; - const returnFilters = Object.keys(restFilters).length ? restFilters : { short_id: shortIds }; + const returnFilters = Object.keys(restFilters).length ? restFilters : { id: recordIds }; if (!isEmpty(query)) { return { filters: returnFilters, query }; diff --git a/app/javascript/components/record-actions/utils/build-applied-filters.unit.test.js b/app/javascript/components/record-actions/utils/build-applied-filters.unit.test.js index 5773c447a5..4d10e5b9c6 100644 --- a/app/javascript/components/record-actions/utils/build-applied-filters.unit.test.js +++ b/app/javascript/components/record-actions/utils/build-applied-filters.unit.test.js @@ -30,20 +30,20 @@ describe("record-actions/utils/build-applied-filters", () => { const appliedFilters = fromJS({ sex: ["female"] }); - const shortIds = ["b575f47"]; + const recordIds = [record.get("id")]; it("should be a function", () => { expect(buildAppliedFilters).to.be.an("function"); }); it("should return filters with short_id, if isShowPage true", () => { - const expected = { filters: { short_id: shortIds } }; + const expected = { filters: { id: recordIds } }; - expect(buildAppliedFilters(true, false, shortIds, appliedFilters, {}, record, false)).to.be.deep.equals(expected); + expect(buildAppliedFilters(true, false, recordIds, appliedFilters, {}, record, false)).to.be.deep.equals(expected); }); it("should return filters without page, per and total params", () => { - const expected = { filters: { short_id: shortIds } }; + const expected = { filters: { id: recordIds } }; const filters = fromJS({ sex: ["female"], page: 1, @@ -51,23 +51,23 @@ describe("record-actions/utils/build-applied-filters", () => { per: 5 }); - expect(buildAppliedFilters(true, false, shortIds, filters, {}, record, false)).to.be.deep.equals(expected); + expect(buildAppliedFilters(true, false, recordIds, filters, {}, record, false)).to.be.deep.equals(expected); }); it( "should return filters with short_id, " + "if isShowPage is false and allRowsSelected is false and there are not appliedFilters", () => { - const expected = { filters: { short_id: shortIds } }; + const expected = { filters: { id: recordIds } }; - expect(buildAppliedFilters(false, false, shortIds, fromJS({}), {}, record, false)).to.be.deep.equals(expected); + expect(buildAppliedFilters(false, false, recordIds, fromJS({}), {}, record, false)).to.be.deep.equals(expected); } ); it("should return and object with applied filters, if isShowPage is false and allRowsSelected is true", () => { - const expected = { filters: { short_id: shortIds } }; + const expected = { filters: { id: recordIds } }; - expect(buildAppliedFilters(false, true, shortIds, appliedFilters, {}, record, false)).to.be.deep.equals(expected); + expect(buildAppliedFilters(false, true, recordIds, appliedFilters, {}, record, false)).to.be.deep.equals(expected); }); it( @@ -75,9 +75,9 @@ describe("record-actions/utils/build-applied-filters", () => { "if isShowPage is false, allRowsSelected is false and a query is specified", () => { const query = "test"; - const expected = { filters: { short_id: shortIds } }; + const expected = { filters: { id: recordIds } }; - expect(buildAppliedFilters(false, true, shortIds, fromJS({ query }), {}, record, false)).to.be.deep.equals( + expect(buildAppliedFilters(false, true, recordIds, fromJS({ query }), {}, record, false)).to.be.deep.equals( expected ); } @@ -88,9 +88,9 @@ describe("record-actions/utils/build-applied-filters", () => { "if isShowPage is false, allRowsSelected is true and a query is specified", () => { const query = "test"; - const expected = { filters: { short_id: shortIds } }; + const expected = { filters: { id: recordIds } }; - expect(buildAppliedFilters(false, true, shortIds, fromJS({ query }), {}, record, false)).to.be.deep.equals( + expect(buildAppliedFilters(false, true, recordIds, fromJS({ query }), {}, record, false)).to.be.deep.equals( expected ); } @@ -104,6 +104,6 @@ describe("record-actions/utils/build-applied-filters", () => { } }; - expect(buildAppliedFilters(false, false, shortIds, fromJS({}), {}, record, true)).to.be.deep.equals(expected); + expect(buildAppliedFilters(false, false, recordIds, fromJS({}), {}, record, true)).to.be.deep.equals(expected); }); }); diff --git a/app/javascript/components/record-actions/utils/index.js b/app/javascript/components/record-actions/utils/index.js index 358da134d6..2df95b139e 100644 --- a/app/javascript/components/record-actions/utils/index.js +++ b/app/javascript/components/record-actions/utils/index.js @@ -7,3 +7,4 @@ export { default as isDisabledAction } from "./is-disabled-action"; export { default as subformExists } from "./subform-exists"; export { default as buildAppliedFilters } from "./build-applied-filters"; export { default as getRequestedApprovals } from "./get-requested-approvals"; +export { default as buildSelectedIds } from "./build-selected-ids"; diff --git a/app/javascript/components/record-creation-flow/component.jsx b/app/javascript/components/record-creation-flow/component.jsx index 48f797dda4..07b2e47ce4 100644 --- a/app/javascript/components/record-creation-flow/component.jsx +++ b/app/javascript/components/record-creation-flow/component.jsx @@ -2,12 +2,12 @@ import { useState } from "react"; import PropTypes from "prop-types"; -import { Drawer } from "@material-ui/core"; -import CloseIcon from "@material-ui/icons/Close"; -import AddIcon from "@material-ui/icons/Add"; +import { Drawer } from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; +import AddIcon from "@mui/icons-material/Add"; import isEmpty from "lodash/isEmpty"; import { push } from "connected-react-router"; -import { useDispatch } from "react-redux"; +import { useDispatch, batch } from "react-redux"; import ActionButton from "../action-button"; import { ACTION_BUTTON_TYPES } from "../action-button/constants"; @@ -16,12 +16,13 @@ import useMemoizedSelector from "../../libs/use-memoized-selector"; import { getOptionFromAppModule } from "../application/selectors"; import { SEARCH_OR_CREATE_FILTERS } from "../record-list/constants"; import { applyFilters } from "../index-filters"; +import { setRedirectedToCreateNewRecord } from "../record-form/action-creators"; import { ConsentPrompt, SearchPrompt } from "./components"; import { NAME, DATA_PROTECTION_FIELDS } from "./constants"; import css from "./styles.css"; -const Component = ({ open, onClose, recordType, primeroModule }) => { +function Component({ open, onClose, recordType, primeroModule }) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -32,7 +33,16 @@ const Component = ({ open, onClose, recordType, primeroModule }) => { getOptionFromAppModule(state, primeroModule, DATA_PROTECTION_FIELDS) ); - const goToNewCase = () => dispatch(push(`/${recordType}/${primeroModule}/new`)); + const goToNewCase = () => { + dispatch(push(`/${recordType}/${primeroModule}/new`)); + }; + + const redirectToNewCase = () => { + batch(() => { + dispatch(setRedirectedToCreateNewRecord(true)); + dispatch(push(`/${recordType}/${primeroModule}/new`)); + }); + }; const onSearchCases = data => { dispatch( @@ -97,7 +107,7 @@ const Component = ({ open, onClose, recordType, primeroModule }) => { recordType={recordType} setOpenConsentPrompt={setOpenConsentPrompt} setSearchValue={setSearchValue} - goToNewCase={goToNewCase} + goToNewCase={redirectToNewCase} dataProtectionFields={dataProtectionFields} onSearchCases={onSearchCases} openConsentPrompt={openConsentPrompt} @@ -115,7 +125,7 @@ const Component = ({ open, onClose, recordType, primeroModule }) => {
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/record-creation-flow/component.unit.test.js b/app/javascript/components/record-creation-flow/component.spec.js similarity index 74% rename from app/javascript/components/record-creation-flow/component.unit.test.js rename to app/javascript/components/record-creation-flow/component.spec.js index d8356ceac0..9d52f61bc6 100644 --- a/app/javascript/components/record-creation-flow/component.unit.test.js +++ b/app/javascript/components/record-creation-flow/component.spec.js @@ -1,18 +1,14 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - +import { mountedComponent, screen } from "test-utils"; import { fromJS } from "immutable"; -import { setupMountedComponent } from "../../test"; import { RECORD_PATH, MODULES } from "../../config"; -import ActionButton from "../action-button"; -import FormSection from "../form/components/form-section"; import { mapEntriesToRecord } from "../../libs"; import { FormSectionRecord, FieldRecord } from "../record-form/records"; import RecordCreationFlow from "./component"; describe("", () => { - let component; const formSections = { 1: { id: 1, @@ -60,18 +56,14 @@ describe("", () => { }); beforeEach(() => { - ({ component } = setupMountedComponent(RecordCreationFlow, props, initialState)); + mountedComponent(, initialState); }); it("should render a component", () => { - expect(component.find(FormSection)).to.have.lengthOf(1); - }); - - it("should render a form component", () => { - expect(component.find("form")).to.have.lengthOf(1); + expect(document.querySelector("form#record-creation-form")).toBeInTheDocument(); }); it("should render a component", () => { - expect(component.find(ActionButton)).to.have.lengthOf(3); + expect(screen.getAllByRole("button")).toHaveLength(4); }); }); diff --git a/app/javascript/components/record-creation-flow/components/consent-prompt/component.jsx b/app/javascript/components/record-creation-flow/components/consent-prompt/component.jsx index 9d8d2f08e6..89abaaec3c 100644 --- a/app/javascript/components/record-creation-flow/components/consent-prompt/component.jsx +++ b/app/javascript/components/record-creation-flow/components/consent-prompt/component.jsx @@ -3,7 +3,7 @@ import PropTypes from "prop-types"; import { useDispatch } from "react-redux"; import { useForm } from "react-hook-form"; -import Add from "@material-ui/icons/Add"; +import Add from "@mui/icons-material/Add"; import isEmpty from "lodash/isEmpty"; import { useMemoizedSelector } from "../../../../libs"; @@ -21,7 +21,7 @@ import { NAME, CONSENT, FORM_ID, LEGITIMATE_BASIS } from "./constants"; import css from "./styles.css"; import { consentPromptForm } from "./forms"; -const Component = ({ +function Component({ i18n, recordType, searchValue, @@ -29,7 +29,7 @@ const Component = ({ dataProtectionFields, goToNewCase, openConsentPrompt -}) => { +}) { const dispatch = useDispatch(); const formMode = whichFormMode(FORM_MODE_NEW); const methods = useForm(); @@ -103,7 +103,7 @@ const Component = ({
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/record-creation-flow/components/consent-prompt/component.unit.test.js b/app/javascript/components/record-creation-flow/components/consent-prompt/component.spec.js similarity index 72% rename from app/javascript/components/record-creation-flow/components/consent-prompt/component.unit.test.js rename to app/javascript/components/record-creation-flow/components/consent-prompt/component.spec.js index 5a7c393dac..309c67c92d 100644 --- a/app/javascript/components/record-creation-flow/components/consent-prompt/component.unit.test.js +++ b/app/javascript/components/record-creation-flow/components/consent-prompt/component.spec.js @@ -1,18 +1,14 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - +import { mountedComponent, screen } from "test-utils"; import { fromJS } from "immutable"; -import { setupMountedComponent } from "../../../../test"; import { RECORD_PATH, MODULES } from "../../../../config"; -import ActionButton from "../../../action-button"; -import FormSection from "../../../form/components/form-section"; import { mapEntriesToRecord } from "../../../../libs"; import { FormSectionRecord, FieldRecord } from "../../../record-form/records"; import ConsentPrompt from "./component"; describe("", () => { - let component; const formSections = { 1: { id: 1, @@ -53,18 +49,14 @@ describe("", () => { }); beforeEach(() => { - ({ component } = setupMountedComponent(ConsentPrompt, props, initialState)); - }); - - it("should render a component", () => { - expect(component.find(FormSection)).to.have.lengthOf(1); + mountedComponent(, initialState); }); it("should render a form component", () => { - expect(component.find("form")).to.have.lengthOf(1); + expect(document.querySelector("#consent-prompt-form")).toBeInTheDocument(); }); it("should render a component", () => { - expect(component.find(ActionButton)).to.have.lengthOf(1); + expect(screen.getAllByRole("button")).toHaveLength(1); }); }); diff --git a/app/javascript/components/record-creation-flow/components/search-button/component.jsx b/app/javascript/components/record-creation-flow/components/search-button/component.jsx new file mode 100644 index 0000000000..d53661c380 --- /dev/null +++ b/app/javascript/components/record-creation-flow/components/search-button/component.jsx @@ -0,0 +1,28 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import PropTypes from "prop-types"; +import SearchIcon from "@mui/icons-material/Search"; + +import ActionButton, { ACTION_BUTTON_TYPES } from "../../../action-button"; + +function Component({ formId }) { + return ( + } + text="navigation.search" + type={ACTION_BUTTON_TYPES.default} + rest={{ + form: formId, + type: "submit" + }} + /> + ); +} + +Component.displayName = "SearchButton"; + +Component.propTypes = { + formId: PropTypes.string.isRequired +}; + +export default Component; diff --git a/app/javascript/components/record-creation-flow/components/search-button/index.js b/app/javascript/components/record-creation-flow/components/search-button/index.js new file mode 100644 index 0000000000..ec6273bd69 --- /dev/null +++ b/app/javascript/components/record-creation-flow/components/search-button/index.js @@ -0,0 +1,3 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +export { default } from "./component"; diff --git a/app/javascript/components/record-creation-flow/components/search-prompt/component.jsx b/app/javascript/components/record-creation-flow/components/search-prompt/component.jsx index fd420df39f..c41f356ecf 100644 --- a/app/javascript/components/record-creation-flow/components/search-prompt/component.jsx +++ b/app/javascript/components/record-creation-flow/components/search-prompt/component.jsx @@ -3,24 +3,24 @@ import { useEffect } from "react"; import PropTypes from "prop-types"; import { useDispatch } from "react-redux"; -import { useForm } from "react-hook-form"; -import SearchIcon from "@material-ui/icons/Search"; -import { InputLabel, FormHelperText } from "@material-ui/core"; +import { InputLabel, FormHelperText } from "@mui/material"; +import { useForm, useWatch } from "react-hook-form"; import isEmpty from "lodash/isEmpty"; import FormSection from "../../../form/components/form-section"; import { submitHandler, whichFormMode } from "../../../form"; import { FORM_MODE_NEW } from "../../../form/constants"; -import ActionButton from "../../../action-button"; -import { ACTION_BUTTON_TYPES } from "../../../action-button/constants"; import { useMemoizedSelector } from "../../../../libs"; import { getRecordsData } from "../../../index-table"; +import SearchNameToggle from "../../../index-filters/components/search-name-toggle"; +import PhoneticHelpText from "../../../index-filters/components/phonetic-help-text"; +import SearchButton from "../search-button"; -import { NAME, FORM_ID, QUERY } from "./constants"; +import { NAME, FORM_ID, QUERY, PHONETIC_FIELD_NAME } from "./constants"; import { searchPromptForm } from "./forms"; import css from "./styles.css"; -const Component = ({ +function Component({ i18n, onCloseDrawer, recordType, @@ -30,7 +30,7 @@ const Component = ({ dataProtectionFields, onSearchCases, openConsentPrompt -}) => { +}) { const formMode = whichFormMode(FORM_MODE_NEW); const dispatch = useDispatch(); const methods = useForm(); @@ -38,11 +38,16 @@ const Component = ({ const records = useMemoizedSelector(state => getRecordsData(state, recordType)); const { + control, formState: { dirtyFields, isSubmitted }, handleSubmit, - getValues + getValues, + setValue, + register } = methods; + const phonetic = useWatch({ control, name: PHONETIC_FIELD_NAME, defaultValue: false }); + const onSuccess = data => { submitHandler({ data, @@ -57,6 +62,18 @@ const Component = ({ }); }; + const handleSwitchChange = event => { + setValue(PHONETIC_FIELD_NAME, event.target.checked, { shouldDirty: true }); + }; + + useEffect(() => { + register(PHONETIC_FIELD_NAME); + }, [register]); + + useEffect(() => { + setValue(PHONETIC_FIELD_NAME, false); + }, []); + useEffect(() => { if (isSubmitted) { if (records.size > 0) { @@ -75,38 +92,45 @@ const Component = ({ } return ( -
- - {i18n.t("case.enter_id_number")} - -
-
- {searchPromptForm(i18n).map(formSection => ( - - ))} - -
- } - text="navigation.search" - type={ACTION_BUTTON_TYPES.default} - rest={{ - form: FORM_ID, - type: "submit" - }} - /> +
+
+
+ + {i18n.t("case.enter_id_number")} + +
+
+ {searchPromptForm(i18n).map(formSection => ( + + ))} + +
+ +
+
+ {i18n.t("case.search_helper_text")} +
+
+ +
+ +
- {i18n.t("case.search_helper_text")} + {phonetic && ( +
+ +
+ )}
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/record-creation-flow/components/search-prompt/component.unit.test.js b/app/javascript/components/record-creation-flow/components/search-prompt/component.spec.js similarity index 56% rename from app/javascript/components/record-creation-flow/components/search-prompt/component.unit.test.js rename to app/javascript/components/record-creation-flow/components/search-prompt/component.spec.js index d165da9319..9e2bbbab22 100644 --- a/app/javascript/components/record-creation-flow/components/search-prompt/component.unit.test.js +++ b/app/javascript/components/record-creation-flow/components/search-prompt/component.spec.js @@ -1,16 +1,12 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - +import { mountedComponent, screen } from "test-utils"; import { fromJS } from "immutable"; -import { InputLabel, FormHelperText } from "@material-ui/core"; -import { setupMountedComponent } from "../../../../test"; import { RECORD_PATH } from "../../../../config"; -import ActionButton from "../../../action-button"; import SearchPrompt from "./component"; describe("", () => { - let component; const props = { i18n: { t: value => value }, onCloseDrawer: () => {}, @@ -25,25 +21,22 @@ describe("", () => { const initialState = fromJS({}); beforeEach(() => { - ({ component } = setupMountedComponent(SearchPrompt, props, initialState)); - }); - - it("should render a component", () => { - expect(component.find(InputLabel)).to.have.lengthOf(1); + mountedComponent(, initialState); }); it("should render a component", () => { - const searchHelperText = component.find(FormHelperText); + expect(screen.getByText("case.search_helper_text")).toBeInTheDocument(); + }); - expect(searchHelperText).to.have.lengthOf(1); - expect(searchHelperText.text()).to.be.equals("case.search_helper_text"); + it("should render a component", () => { + expect(screen.getByPlaceholderText("case.search_existing")).toBeInTheDocument(); }); it("should render a form component", () => { - expect(component.find("form")).to.have.lengthOf(1); + expect(document.querySelector("#record-creation-form")).toBeInTheDocument(); }); it("should render a component", () => { - expect(component.find(ActionButton)).to.have.lengthOf(1); + expect(screen.getAllByRole("button")).toHaveLength(2); }); }); diff --git a/app/javascript/components/record-creation-flow/components/search-prompt/constants.js b/app/javascript/components/record-creation-flow/components/search-prompt/constants.js index 5c8fb3496b..fd568f10c3 100644 --- a/app/javascript/components/record-creation-flow/components/search-prompt/constants.js +++ b/app/javascript/components/record-creation-flow/components/search-prompt/constants.js @@ -3,3 +3,4 @@ export const NAME = "SearchPrompt"; export const FORM_ID = "record-creation-form"; export const QUERY = "query"; +export const PHONETIC_FIELD_NAME = "phonetic"; diff --git a/app/javascript/components/record-creation-flow/components/search-prompt/constants.unit.test.js b/app/javascript/components/record-creation-flow/components/search-prompt/constants.unit.test.js index df8e1830c1..46593f9b5c 100644 --- a/app/javascript/components/record-creation-flow/components/search-prompt/constants.unit.test.js +++ b/app/javascript/components/record-creation-flow/components/search-prompt/constants.unit.test.js @@ -6,7 +6,7 @@ describe("Verifying config constant", () => { it("should have known constant", () => { const clone = { ...constants }; - ["NAME", "FORM_ID", "QUERY"].forEach(property => { + ["NAME", "FORM_ID", "PHONETIC_FIELD_NAME", "QUERY"].forEach(property => { expect(clone).to.have.property(property); delete clone[property]; }); diff --git a/app/javascript/components/record-creation-flow/components/search-prompt/styles.css b/app/javascript/components/record-creation-flow/components/search-prompt/styles.css index f00b99640b..854339894e 100644 --- a/app/javascript/components/record-creation-flow/components/search-prompt/styles.css +++ b/app/javascript/components/record-creation-flow/components/search-prompt/styles.css @@ -1,9 +1,13 @@ /* Copyright (c) 2014 - 2023 UNICEF. All rights reserved. */ -.searchPromptFormContainer { +.search { padding: 0 20px; } +.searchPromptFormContainer { + display: flex; +} + .container { display: flex; align-items: center; @@ -12,6 +16,7 @@ border: 1px solid var(--c-warm-grey-4); border-radius: 6px; padding: .3em .3em .3em .5em; + flex: 1 0 auto; & form { width: 100%; @@ -30,6 +35,58 @@ .inputLabel { width: 100%; - line-height: 1.5em; + line-height: 2em; position: relative; } + +.searchBox { + flex: 1 0 auto; + + & :global(.MuiFormControl-root) { + margin-top: 0; + } +} + + +.searchToggle { + flex: 0 0 auto; + align-content: center; + padding: 0 10px; +} + +.phoneticHelpText { + margin-top: 20px; +} + + +@media (max-width:959.95px) { + .searchButton { + display: none; + } + + .searchPromptFormContainer { + display: block; + } + + .searchToggle { + display: flex; + padding: 0; + align-items: center; + justify-content: space-between; + & .searchButton { + display: block; + } + } + + .phoneticHelpText { + margin-top: 0; + } +} + +@media (min-width:960px) { + .searchToggle { + & .searchButton { + display: none; + } + } +} diff --git a/app/javascript/components/record-form-alerts/component.jsx b/app/javascript/components/record-form-alerts/component.jsx index 0c9e5d46df..4e01f2bee7 100644 --- a/app/javascript/components/record-form-alerts/component.jsx +++ b/app/javascript/components/record-form-alerts/component.jsx @@ -9,14 +9,13 @@ import { useI18n } from "../i18n"; import InternalAlert from "../internal-alert"; import useMemoizedSelector from "../../libs/use-memoized-selector"; import { getRecordFormAlerts, getSelectedRecord, deleteAlertFromRecord } from "../records"; -import { getSubformsDisplayName, getValidationErrors } from "../record-form"; -import { getDuplicatedFields } from "../record-form/selectors"; +import { getSubformsDisplayName, getValidationErrors, getDuplicatedFields } from "../record-form/selectors"; import { usePermissions, REMOVE_ALERT } from "../permissions"; import { getMessageData } from "./utils"; import { NAME } from "./constants"; -const Component = ({ form, recordType, attachmentForms, formMode }) => { +function Component({ form, recordType, attachmentForms = fromJS([]), formMode }) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -79,14 +78,10 @@ const Component = ({ form, recordType, attachmentForms, formMode }) => { {items?.size ? : null} ); -}; +} Component.displayName = NAME; -Component.defaultProps = { - attachmentForms: fromJS([]) -}; - Component.propTypes = { attachmentForms: PropTypes.object, form: PropTypes.object.isRequired, diff --git a/app/javascript/components/record-form-alerts/component.spec.js b/app/javascript/components/record-form-alerts/component.spec.js new file mode 100644 index 0000000000..cc3ce20256 --- /dev/null +++ b/app/javascript/components/record-form-alerts/component.spec.js @@ -0,0 +1,57 @@ +import { mountedComponent, screen } from "test-utils"; +import { fromJS } from "immutable"; + +import { FormSectionRecord } from "../record-form/records"; + +import RecordFormAlerts from "./component"; + +describe("", () => { + const initialState = fromJS({ + records: { + cases: { + recordAlerts: [ + { + alert_for: "field_change", + type: "closure", + date: "2020-06-19", + form_unique_id: "form_1" + } + ] + } + }, + forms: { + validationErrors: [ + { + unique_id: "form_1", + form_group_id: "group_1", + errors: { + field_1: "field_1 is required", + tally_2: { + boys: "Boys is required" + } + } + } + ] + } + }); + + it("renders the RecordFormAlerts", () => { + const props = { + recordType: "cases", + form: FormSectionRecord({ unique_id: "form_1", name: { en: "Form 1" } }) + }; + + mountedComponent(, initialState); + expect(document.querySelector("#record-form-alerts-panel-header")).toBeInTheDocument(); + }); + + it("first renders errors and then form alerts", () => { + const props = { + recordType: "cases", + form: FormSectionRecord({ unique_id: "form_1", name: { en: "Form 1" } }) + }; + + mountedComponent(, initialState); + expect(screen.getByText("error_message.address_form_fields")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/record-form-alerts/component.unit.test.js b/app/javascript/components/record-form-alerts/component.unit.test.js deleted file mode 100644 index b339d462f0..0000000000 --- a/app/javascript/components/record-form-alerts/component.unit.test.js +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { FormSectionRecord } from "../record-form/records"; -import { setupMountedComponent } from "../../test"; -import InternalAlert from "../internal-alert"; - -import RecordFormAlerts from "./component"; - -describe("", () => { - const initialState = fromJS({ - records: { - cases: { - recordAlerts: [ - { - alert_for: "field_change", - type: "closure", - date: "2020-06-19", - form_unique_id: "form_1" - } - ] - } - }, - forms: { - validationErrors: [ - { - unique_id: "form_1", - form_group_id: "group_1", - errors: { - field_1: "field_1 is required", - tally_2: { - boys: "Boys is required" - } - } - } - ] - } - }); - - it("renders the RecordFormAlerts", () => { - const { component } = setupMountedComponent( - RecordFormAlerts, - { - recordType: "cases", - form: FormSectionRecord({ unique_id: "form_1", name: { en: "Form 1" } }) - }, - initialState - ); - - expect(component.find(RecordFormAlerts)).to.have.lengthOf(1); - }); - - it("first renders errors and then form alerts", () => { - const { component } = setupMountedComponent( - RecordFormAlerts, - { - recordType: "cases", - form: FormSectionRecord({ unique_id: "form_1", name: { en: "Form 1" } }) - }, - initialState - ); - - expect(component.find(InternalAlert)).to.have.lengthOf(2); - expect(component.find(InternalAlert).first().props().severity).to.equal("error"); - expect(component.find(InternalAlert).first().find("li")).to.have.lengthOf(2); - expect(component.find(InternalAlert).last().props().severity).to.equal("info"); - }); -}); diff --git a/app/javascript/components/record-form/action-creators.js b/app/javascript/components/record-form/action-creators.js index b436bab532..2a339af687 100644 --- a/app/javascript/components/record-form/action-creators.js +++ b/app/javascript/components/record-form/action-creators.js @@ -100,3 +100,8 @@ export const setDataProtectionInitialValues = payload => ({ export const clearDataProtectionInitialValues = () => ({ type: Actions.CLEAR_DATA_PROTECTION_INITIAL_VALUES }); + +export const setRedirectedToCreateNewRecord = payload => ({ + type: Actions.REDIRECTED_TO_CREATE_NEW_RECORD, + payload +}); diff --git a/app/javascript/components/record-form/action-creators.unit.test.js b/app/javascript/components/record-form/action-creators.unit.test.js index c4e61fe496..3ba87158ca 100644 --- a/app/javascript/components/record-form/action-creators.unit.test.js +++ b/app/javascript/components/record-form/action-creators.unit.test.js @@ -35,17 +35,18 @@ describe(" - Action Creators", () => { [ "clearDataProtectionInitialValues", + "clearPreviousRecord", "clearValidationErrors", "fetchAgencies", "fetchForms", "fetchLookups", "fetchOptions", "setDataProtectionInitialValues", + "setPreviousRecord", + "setRedirectedToCreateNewRecord", "setSelectedForm", "setServiceToRefer", - "setValidationErrors", - "setPreviousRecord", - "clearPreviousRecord" + "setValidationErrors" ].forEach(property => { expect(creators).to.have.property(property); expect(creators[property]).to.be.a("function"); @@ -188,4 +189,10 @@ describe(" - Action Creators", () => { expect(actionCreators.clearDataProtectionInitialValues()).to.deep.equals(expected); }); + + it("checks the 'setRedirectedToCreateNewRecord' action creator return the correct object", () => { + const expected = { type: actions.REDIRECTED_TO_CREATE_NEW_RECORD, payload: true }; + + expect(actionCreators.setRedirectedToCreateNewRecord(true)).to.deep.equals(expected); + }); }); diff --git a/app/javascript/components/record-form/actions.js b/app/javascript/components/record-form/actions.js index 4bbe1a93ff..29fda983f2 100644 --- a/app/javascript/components/record-form/actions.js +++ b/app/javascript/components/record-form/actions.js @@ -1,38 +1,39 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { namespaceActions } from "../../libs"; +import { namespaceActions } from "../../libs/reducer-helpers"; import NAMESPACE from "./namespace"; export default namespaceActions(NAMESPACE, [ "CLEAR_DATA_PROTECTION_INITIAL_VALUES", + "CLEAR_PREVIOUS_RECORD", "CLEAR_VALIDATION_ERRORS", - "FETCH_AGENCIES", "FETCH_AGENCIES_FAILURE", "FETCH_AGENCIES_FINISHED", "FETCH_AGENCIES_STARTED", "FETCH_AGENCIES_SUCCESS", - "RECORD_FORMS", + "FETCH_AGENCIES", "RECORD_FORMS_FAILURE", "RECORD_FORMS_FINISHED", "RECORD_FORMS_STARTED", "RECORD_FORMS_SUCCESS", + "RECORD_FORMS", + "REDIRECTED_TO_CREATE_NEW_RECORD", "SET_DATA_PROTECTION_INITIAL_VALUES", "SET_FORMS", - "SET_LOCATIONS", "SET_LOCATIONS_FAILURE", "SET_LOCATIONS_FINISHED", "SET_LOCATIONS_STARTED", "SET_LOCATIONS_SUCCESS", - "SET_OPTIONS", + "SET_LOCATIONS", "SET_OPTIONS_FAILURE", "SET_OPTIONS_FINISHED", "SET_OPTIONS_STARTED", "SET_OPTIONS_SUCCESS", + "SET_OPTIONS", + "SET_PREVIOUS_RECORD", "SET_SELECTED_FORM", "SET_SELECTED_RECORD", "SET_SERVICE_TO_REFER", - "SET_VALIDATION_ERRORS", - "SET_PREVIOUS_RECORD", - "CLEAR_PREVIOUS_RECORD" + "SET_VALIDATION_ERRORS" ]); diff --git a/app/javascript/components/record-form/actions.unit.test.js b/app/javascript/components/record-form/actions.unit.test.js index 494ebc5451..f26b0c9b8e 100644 --- a/app/javascript/components/record-form/actions.unit.test.js +++ b/app/javascript/components/record-form/actions.unit.test.js @@ -10,35 +10,36 @@ describe(" - Actions", () => { [ "CLEAR_DATA_PROTECTION_INITIAL_VALUES", + "CLEAR_PREVIOUS_RECORD", "CLEAR_VALIDATION_ERRORS", - "FETCH_AGENCIES", "FETCH_AGENCIES_FAILURE", "FETCH_AGENCIES_FINISHED", "FETCH_AGENCIES_STARTED", "FETCH_AGENCIES_SUCCESS", - "RECORD_FORMS", + "FETCH_AGENCIES", "RECORD_FORMS_FAILURE", "RECORD_FORMS_FINISHED", "RECORD_FORMS_STARTED", "RECORD_FORMS_SUCCESS", + "RECORD_FORMS", + "REDIRECTED_TO_CREATE_NEW_RECORD", "SET_DATA_PROTECTION_INITIAL_VALUES", "SET_FORMS", - "SET_LOCATIONS", "SET_LOCATIONS_FAILURE", "SET_LOCATIONS_FINISHED", "SET_LOCATIONS_STARTED", "SET_LOCATIONS_SUCCESS", - "SET_OPTIONS", + "SET_LOCATIONS", "SET_OPTIONS_FAILURE", "SET_OPTIONS_FINISHED", "SET_OPTIONS_STARTED", "SET_OPTIONS_SUCCESS", + "SET_OPTIONS", + "SET_PREVIOUS_RECORD", "SET_SELECTED_FORM", "SET_SELECTED_RECORD", "SET_SERVICE_TO_REFER", - "SET_VALIDATION_ERRORS", - "SET_PREVIOUS_RECORD", - "CLEAR_PREVIOUS_RECORD" + "SET_VALIDATION_ERRORS" ].forEach(property => { expect(cloneActions).to.have.property(property); delete cloneActions[property]; diff --git a/app/javascript/components/record-form/components/record-form/component.jsx b/app/javascript/components/record-form/components/record-form/component.jsx index d0c1768110..dbb9f35bf7 100644 --- a/app/javascript/components/record-form/components/record-form/component.jsx +++ b/app/javascript/components/record-form/components/record-form/component.jsx @@ -2,10 +2,10 @@ import { useCallback, useEffect, useState } from "react"; import PropTypes from "prop-types"; -import { useMediaQuery } from "@material-ui/core"; +import { useMediaQuery } from "@mui/material"; import { batch, useDispatch } from "react-redux"; import { useLocation, useHistory } from "react-router-dom"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; import { fromJS } from "immutable"; import FormFilters from "../../../form-filters"; @@ -29,7 +29,7 @@ import css from "../../styles.css"; import { compactBlank, compactReadOnlyFields, compactValues, getRedirectPath } from "../../utils"; import externalForms from "../external-forms"; -const Component = ({ +function Component({ approvalSubforms, attachmentForms, canRefer, @@ -54,7 +54,7 @@ const Component = ({ shouldFetchRecord, summaryForm, userPermittedFormsIds -}) => { +}) { let submitForm = null; const mobileDisplay = useMediaQuery(theme => theme.breakpoints.down("sm")); @@ -206,7 +206,7 @@ const Component = ({ dispatch(fetchRecord(params.recordType, params.id)); // TODO: Remove this condition once alerts get implemented for registry_records if (params.recordType !== RECORD_TYPES_PLURAL.registry_record) { - dispatch(fetchRecordsAlerts(params.recordType, params.id)); + dispatch(fetchRecordsAlerts(params.recordType, params.id), params); } dispatch(setPreviousRecord(fromJS({ id: params.id, recordType: params.recordType }))); } @@ -279,11 +279,11 @@ const Component = ({ const loading = Boolean(loadingForm || loadingRecord); const renderRecordFormToolbar = selectedModule.primeroModule && ; - const containerClasses = clsx(css.recordContainer, { + const containerClasses = cx(css.recordContainer, { [css.formNavOpen]: toggleNav && mobileDisplay }); - const navContainerClasses = clsx(css.recordNav, { [css.demo]: demo }); - const demoClasses = clsx({ [css.demo]: demo }); + const navContainerClasses = cx(css.recordNav, { [css.demo]: demo }); + const demoClasses = cx({ [css.demo]: demo }); const recordFormExternalForms = externalForms({ approvalSubforms, @@ -350,7 +350,7 @@ const Component = ({ ); -}; +} Component.displayName = "RecordForm"; diff --git a/app/javascript/components/record-form/components/render-form-sections.unit.test.js b/app/javascript/components/record-form/components/render-form-sections.spec.js similarity index 84% rename from app/javascript/components/record-form/components/render-form-sections.unit.test.js rename to app/javascript/components/record-form/components/render-form-sections.spec.js index 1b06b9e641..abcf1557a6 100644 --- a/app/javascript/components/record-form/components/render-form-sections.unit.test.js +++ b/app/javascript/components/record-form/components/render-form-sections.spec.js @@ -2,10 +2,9 @@ import { fromJS } from "immutable"; -import { setupMountedComponent } from "../../../test"; import { FormSectionRecord, FieldRecord } from "../records"; -import TextField from "../form/field-types/text-field"; import { TEXT_FIELD } from "../constants"; +import { mountedComponent, screen } from "../../../test-utils"; import renderFormSections from "./render-form-sections"; @@ -66,10 +65,13 @@ describe("renderFormSections()", () => { false ); - const renderedFormSections = () => <>{formSection()}; + // eslint-disable-next-line react/display-name + function RenderedFormSections() { + return <>{formSection()}; + } - const { component } = setupMountedComponent(renderedFormSections, {}, {}, [], { initialValues: {} }); + mountedComponent(, {}, {}, [], { initialValues: {} }); - expect(component.find(TextField)).to.have.lengthOf(2); + expect(screen.getAllByRole("textbox")).toHaveLength(2); }); }); diff --git a/app/javascript/components/record-form/container.jsx b/app/javascript/components/record-form/container.jsx index 2a3f9fce8b..b9d60409f5 100644 --- a/app/javascript/components/record-form/container.jsx +++ b/app/javascript/components/record-form/container.jsx @@ -34,7 +34,7 @@ import { RecordForm } from "./components/record-form"; let caseRegistryLoaded = false; -const Container = ({ mode }) => { +function Container({ mode }) { const params = useParams(); const { demo } = useApp(); const dispatch = useDispatch(); @@ -132,7 +132,7 @@ const Container = ({ mode }) => { incidentsSubforms={incidentsSubforms} /> ); -}; +} Container.displayName = NAME; diff --git a/app/javascript/components/record-form/container.unit.test.js b/app/javascript/components/record-form/container.spec.js similarity index 56% rename from app/javascript/components/record-form/container.unit.test.js rename to app/javascript/components/record-form/container.spec.js index b304eb2ba1..96a0a26992 100644 --- a/app/javascript/components/record-form/container.unit.test.js +++ b/app/javascript/components/record-form/container.spec.js @@ -1,33 +1,16 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -/* eslint-disable prefer-destructuring */ - -import { Route } from "react-router-dom"; import { fromJS, Map, List, OrderedMap } from "immutable"; -import { CircularProgress } from "@material-ui/core"; -import { setupMountedComponent } from "../../test"; -import PageContainer from "../page"; -import LoadingIndicator from "../loading-indicator"; -import RecordOwner from "../record-owner"; import { PrimeroModuleRecord } from "../application/records"; -import Transitions from "../transitions"; -import { MODES } from "../../config"; -import Approvals from "../approvals"; -import ApprovalPanel from "../approvals/components/panel"; -import IncidentFromCase from "../incidents-from-case"; -import IncidentFromCasePanel from "../incidents-from-case/components/panel"; -import ChangeLogs from "../change-logs"; +import { mountedComponent, screen } from "../../test-utils"; import { MANAGE } from "../permissions"; +import { MODES } from "../../config"; -import Nav from "./nav"; -import { RecordForm, RecordFormToolbar } from "./form"; -import RecordFormTitle from "./form/record-form-title"; -import RecordForms from "./container"; import { FormSectionRecord, FieldRecord } from "./records"; +import RecordForms from "./container"; describe(" - Component", () => { - let component; const formSections = OrderedMap({ 1: FormSectionRecord({ id: 1, @@ -122,86 +105,6 @@ describe(" - Component", () => { id: "2b8d6be1-1dc4-483a-8640-4cfe87c71610" }; - const rootInitialState = fromJS({ - records: Map({ - cases: Map({ - data: List([Map(record)]), - metadata: Map({ per: 20, page: 1, total: 1 }), - filters: Map({ status: "open" }) - }) - }), - forms: Map({ - selectedForm: "record_owner", - selectedRecord: record, - formSections, - fields, - loading: false, - errors: false, - forms: { - options: { - lookups: [ - { - id: 2, - unique_id: "lookup-cp-violence-type", - name: { - en: "CP Sexual Violence Type" - }, - values: [ - { id: "cp_test1", display_text: { en: "CP Test1" } }, - { id: "cp_test2", display_text: { en: "CP Test2" } } - ] - } - ] - } - } - }), - user: fromJS({ - permittedForms: { basic_identity: "rw" }, - modules: ["primeromodule-cp"] - }), - application - }); - - before(() => { - const routedComponent = initialProps => { - return ( - } - /> - ); - }; - - ({ component } = setupMountedComponent( - routedComponent, - { - mode: "show" - }, - rootInitialState, - ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"] - )); - }); - - it("renders the PageContainer", () => { - expect(component.find(PageContainer)).to.have.length(1); - }); - - it("renders the LoadingIndicator", () => { - expect(component.find(LoadingIndicator)).to.have.length(1); - }); - - it("renders the RecordFormToolbar", () => { - expect(component.find(RecordFormToolbar)).to.have.length(1); - }); - - it("renders the Nav", () => { - expect(component.find(Nav)).to.have.length(1); - }); - - it("renders the RecordOwner", () => { - expect(component.find(RecordOwner)).to.have.length(1); - }); - describe("when basic_identity is the selectedForm ", () => { const initialState = fromJS({ records: Map({ @@ -226,30 +129,19 @@ describe(" - Component", () => { application }); - beforeEach(() => { - const routedComponent = initialProps => { - return ( - } - /> - ); - }; - - ({ component } = setupMountedComponent( - routedComponent, - { - mode: "show" - }, + it("should render RecordForm and not RecordOwner and Transitions", () => { + mountedComponent( + , initialState, - ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"] - )); - }); + {}, + ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"], + {}, + "/:recordType(cases|incidents|tracing_requests)/:id" + ); - it("should render RecordForm and not RecordOwner and Transitions", () => { - expect(component.find(RecordOwner)).to.have.lengthOf(0); - expect(component.find(Transitions)).to.have.lengthOf(0); - expect(component.find(RecordForm)).to.have.lengthOf(1); + expect(screen.queryByTestId("record-owner-form")).toBeNull(); + expect(screen.queryByTestId("transitions")).toBeNull(); + expect(screen.getByTestId("record-form-title", { name: "Basic Identity" })).toBeInTheDocument(); }); }); @@ -277,33 +169,20 @@ describe(" - Component", () => { application }); - beforeEach(() => { - const routedComponent = initialProps => { - return ( - } - /> - ); - }; - - ({ component } = setupMountedComponent( - routedComponent, - { - mode: MODES.show - }, - initialState, - ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"] - )); - }); - it("should render Approvals without ApprovalPanel", () => { - expect(component.find(RecordForm).find(Approvals)).to.have.lengthOf(1); - expect(component.find(ApprovalPanel)).to.have.lengthOf(0); - expect(component.find(Transitions)).to.have.lengthOf(0); - expect(component.find(RecordForm).find(Approvals).find(RecordFormTitle).text()).to.be.equal( - "forms.record_types.approvals" + mountedComponent( + , + initialState, + {}, + ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"], + {}, + "/:recordType(cases|incidents|tracing_requests)/:id" ); + + expect(screen.getByTestId("approvals")).toBeInTheDocument(); + expect(screen.queryByTestId("approval-panel")).toBeNull(); + expect(screen.queryByTestId("transitions")).toBeNull(); + expect(screen.getByText("forms.record_types.approvals")).toBeInTheDocument(); }); }); @@ -344,35 +223,20 @@ describe(" - Component", () => { application }); - beforeEach(() => { - const routedComponent = initialProps => { - return ( - } - /> - ); - }; - - ({ component } = setupMountedComponent( - routedComponent, - { - mode: MODES.show - }, - initialState, - ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"] - )); - }); - it("should render Approvals with ApprovalPanel", () => { - const componentRecordForm = component.find(RecordForm); - - expect(componentRecordForm.find(Approvals)).to.have.lengthOf(1); - expect(componentRecordForm.find(ApprovalPanel)).to.have.lengthOf(1); - expect(componentRecordForm.find(Transitions)).to.be.empty; - expect(componentRecordForm.find(Approvals).find(RecordFormTitle).text()).to.be.equal( - "forms.record_types.approvals" + mountedComponent( + , + initialState, + {}, + ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"], + {}, + "/:recordType(cases|incidents|tracing_requests)/:id" ); + + expect(screen.getByTestId("approvals")).toBeInTheDocument(); + expect(screen.getByTestId("approval-panel")).toBeInTheDocument(); + expect(screen.queryByTestId("transitions")).toBeNull(); + expect(screen.getByText("forms.record_types.approvals")).toBeInTheDocument(); }); }); @@ -415,34 +279,20 @@ describe(" - Component", () => { application }); - beforeEach(() => { - const routedComponent = initialProps => { - return ( - } - /> - ); - }; - - ({ component } = setupMountedComponent( - routedComponent, - { - mode: MODES.show - }, - initialState, - ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"] - )); - }); - it("should render IncidentFromCase with IncidentFromCasePanel", () => { - const componentRecordForm = component.find(RecordForm); + mountedComponent( + , + initialState, + {}, + ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"], + {}, + "/:recordType(cases|incidents|tracing_requests)/:id" + ); - expect(componentRecordForm).to.have.lengthOf(1); - expect(componentRecordForm.find(IncidentFromCase)).to.have.lengthOf(1); - expect(componentRecordForm.find(IncidentFromCasePanel)).to.have.lengthOf(1); - expect(componentRecordForm.find(Transitions)).to.be.empty; - expect(componentRecordForm.find(Approvals)).to.be.empty; + expect(screen.getByTestId("incident-from-case")).toBeInTheDocument(); + expect(screen.getByTestId("incident-panel")).toBeInTheDocument(); + expect(screen.queryByTestId("approvals")).toBeNull(); + expect(screen.queryByTestId("transitions")).toBeNull(); }); }); @@ -491,34 +341,20 @@ describe(" - Component", () => { application }); - beforeEach(() => { - const routedComponent = initialProps => { - return ( - } - /> - ); - }; - - ({ component } = setupMountedComponent( - routedComponent, - { - mode: MODES.show - }, - initialState, - ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"] - )); - }); - it("should render Transitions", () => { - const componentRecordForm = component.find(RecordForm); + mountedComponent( + , + initialState, + {}, + ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"], + {}, + "/:recordType(cases|incidents|tracing_requests)/:id" + ); - expect(componentRecordForm).to.have.lengthOf(1); - expect(componentRecordForm.find(Transitions)).to.have.lengthOf(1); - expect(componentRecordForm.find(Transitions).find(RecordFormTitle).text()).to.equal("transfer_assignment.title"); - expect(componentRecordForm.find(IncidentFromCasePanel)).to.be.empty; - expect(componentRecordForm.find(Approvals)).to.be.empty; + expect(screen.getByTestId("transitions")).toBeInTheDocument(); + expect(screen.getByTestId("record-form-title")).toHaveTextContent("transfer_assignment.title"); + expect(screen.queryByTestId("incident-panel")).toBeNull(); + expect(screen.queryByTestId("approvals")).toBeNull(); }); }); @@ -567,36 +403,20 @@ describe(" - Component", () => { application }); - beforeEach(() => { - const routedComponent = initialProps => { - return ( - } - /> - ); - }; - - ({ component } = setupMountedComponent( - routedComponent, - { - mode: MODES.show - }, - initialState, - ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"] - )); - }); - it("should render Transitions component for REFERRAL", () => { - const componentRecordForm = component.find(RecordForm); - - expect(componentRecordForm).to.have.lengthOf(1); - expect(componentRecordForm.find(Transitions)).to.have.lengthOf(1); - expect(componentRecordForm.find(Transitions).find(RecordFormTitle).text()).to.equal( - "forms.record_types.referrals" + mountedComponent( + , + initialState, + {}, + ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"], + {}, + "/:recordType(cases|incidents|tracing_requests)/:id" ); - expect(componentRecordForm.find(IncidentFromCasePanel)).to.be.empty; - expect(componentRecordForm.find(Approvals)).to.be.empty; + + expect(screen.getByTestId("transitions")).toBeInTheDocument(); + expect(screen.getByTestId("record-form-title")).toHaveTextContent("forms.record_types.referrals"); + expect(screen.queryByTestId("incident-panel")).toBeNull(); + expect(screen.queryByTestId("approvals")).toBeNull(); }); }); @@ -674,35 +494,21 @@ describe(" - Component", () => { application }); - beforeEach(() => { - const routedComponent = initialProps => { - return ( - } - /> - ); - }; - - ({ component } = setupMountedComponent( - routedComponent, - { - mode: MODES.show - }, - initialState, - ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"] - )); - }); - it("should render ChangeLog component", () => { - const componentRecordForm = component.find(RecordForm); + mountedComponent( + , + initialState, + {}, + ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"], + {}, + "/:recordType(cases|incidents|tracing_requests)/:id" + ); - expect(componentRecordForm).to.have.lengthOf(1); - expect(componentRecordForm.find(ChangeLogs)).to.have.lengthOf(1); - expect(componentRecordForm.find(ChangeLogs).find(RecordFormTitle).text()).to.equal("change_logs.label"); - expect(componentRecordForm.find(Transitions)).to.be.empty; - expect(componentRecordForm.find(IncidentFromCasePanel)).to.be.empty; - expect(componentRecordForm.find(Approvals)).to.be.empty; + expect(screen.getByTestId("change-logs")).toBeInTheDocument(); + expect(screen.getByTestId("record-form-title")).toHaveTextContent("change_logs.label"); + expect(screen.queryByTestId("transitions")).toBeNull(); + expect(screen.queryByTestId("incident-panel")).toBeNull(); + expect(screen.queryByTestId("approvals")).toBeNull(); }); }); @@ -730,33 +536,19 @@ describe(" - Component", () => { application }); - beforeEach(() => { - const routedComponent = initialProps => { - return ( - } - /> - ); - }; - - ({ component } = setupMountedComponent( - routedComponent, - { - mode: MODES.new - }, - initialState, - ["/cases/primeromodule-cp/new"] - )); - }); - it("should render Approvals without ApprovalPanel", () => { - const componentRecordForm = component.find(RecordForm); + mountedComponent( + , + initialState, + {}, + ["/cases/primeromodule-cp/new"], + {}, + "/:recordType(cases|incidents|tracing_requests)/:module/new" + ); - expect(componentRecordForm).to.have.lengthOf(1); - expect(componentRecordForm.find(Approvals)).to.have.lengthOf(1); - expect(componentRecordForm.find(ApprovalPanel)).to.be.empty; - expect(componentRecordForm.find(Transitions)).to.be.empty; + expect(screen.getByTestId("approvals")).toBeInTheDocument(); + expect(screen.queryByTestId("approval-panel")).toBeNull(); + expect(screen.queryByTestId("transitions")).toBeNull(); }); }); @@ -784,29 +576,17 @@ describe(" - Component", () => { application }); - beforeEach(() => { - const routedComponent = initialProps => { - return ( - } - /> - ); - }; - - ({ component } = setupMountedComponent( - routedComponent, - { - mode: "show" - }, + it("should render CircularProgress", () => { + mountedComponent( + , initialState, - ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"] - )); - }); + {}, + ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"], + {}, + "/:recordType(cases|incidents|tracing_requests)/:id" + ); - it("should render CircularProgress", () => { - expect(component.find(RecordForms)).to.have.lengthOf(1); - expect(component.find(CircularProgress)).to.have.lengthOf(1); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); @@ -882,28 +662,17 @@ describe(" - Component", () => { application }); - beforeEach(() => { - const routedComponent = initialProps => { - return ( - } - /> - ); - }; - - ({ component } = setupMountedComponent( - routedComponent, - { - mode: "show" - }, + it("should render just one RecordForm ", () => { + mountedComponent( + , initialState, - ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"] - )); - }); + {}, + ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"], + {}, + "/:recordType(cases|incidents|tracing_requests)/:id" + ); - it("should render just one RecordForm ", () => { - expect(component.find(RecordForm)).to.have.lengthOf(1); + expect(screen.getAllByTestId("record-form-title")).toHaveLength(1); }); }); @@ -952,52 +721,25 @@ describe(" - Component", () => { }; describe("and has permission to see cases", () => { - beforeEach(() => { - const routedComponent = initialProps => { - return ( - } - /> - ); - }; - - ({ component } = setupMountedComponent( - routedComponent, - { - mode: "show" - }, - fromJS(initialState), - ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"] - )); - }); - it("should render RecordOwner ", () => { - const componentRecordForm = component.find(RecordForm); - - expect(componentRecordForm.find(RecordOwner)).to.have.lengthOf(1); - expect(componentRecordForm.find(RecordOwner).find(RecordFormTitle).text()).to.equal( - "forms.record_types.record_information" + mountedComponent( + , + initialState, + {}, + ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"], + {}, + "/:recordType(cases|incidents|tracing_requests)/:id" ); + + expect(screen.getByTestId("record-owner-form")).toBeInTheDocument(); + expect(screen.getByTestId("record-form-title")).toHaveTextContent("forms.record_types.record_information"); }); }); describe("and has permission to manage cases", () => { - beforeEach(() => { - const routedComponent = initialProps => { - return ( - } - /> - ); - }; - - ({ component } = setupMountedComponent( - routedComponent, - { - mode: "show" - }, + it("should render RecordOwner ", () => { + mountedComponent( + , fromJS({ ...initialState, user: { @@ -1007,17 +749,14 @@ describe(" - Component", () => { modules: ["primeromodule-cp"] } }), - ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"] - )); - }); - - it("should render RecordOwner ", () => { - const componentRecordForm = component.find(RecordForm); - - expect(componentRecordForm.find(RecordOwner)).to.have.lengthOf(1); - expect(componentRecordForm.find(RecordOwner).find(RecordFormTitle).text()).to.equal( - "forms.record_types.record_information" + {}, + ["/cases/2b8d6be1-1dc4-483a-8640-4cfe87c71610"], + {}, + "/:recordType(cases|incidents|tracing_requests)/:id" ); + + expect(screen.getByTestId("record-owner-form")).toBeInTheDocument(); + expect(screen.getByTestId("record-form-title")).toHaveTextContent("forms.record_types.record_information"); }); }); }); diff --git a/app/javascript/components/record-form/form/components/disabled-record-indicator.jsx b/app/javascript/components/record-form/form/components/disabled-record-indicator.jsx index 4c79ca9b75..fd06ab70aa 100644 --- a/app/javascript/components/record-form/form/components/disabled-record-indicator.jsx +++ b/app/javascript/components/record-form/form/components/disabled-record-indicator.jsx @@ -1,13 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Chip } from "@material-ui/core"; -import BlockIcon from "@material-ui/icons/Block"; +import { Chip } from "@mui/material"; +import BlockIcon from "@mui/icons-material/Block"; import PropTypes from "prop-types"; import { useI18n } from "../../../i18n"; import css from "../styles.css"; -const DisabledRecordIndicator = ({ recordType }) => { +function DisabledRecordIndicator({ recordType }) { const i18n = useI18n(); return ( @@ -19,7 +19,7 @@ const DisabledRecordIndicator = ({ recordType }) => { label={i18n.t(`${recordType}.messages.disabled`)} /> ); -}; +} DisabledRecordIndicator.displayName = "DisabledRecordIndicator"; diff --git a/app/javascript/components/record-form/form/components/guiding-questions.jsx b/app/javascript/components/record-form/form/components/guiding-questions.jsx index d4cb4efc1d..2a5ed4ef76 100644 --- a/app/javascript/components/record-form/form/components/guiding-questions.jsx +++ b/app/javascript/components/record-form/form/components/guiding-questions.jsx @@ -3,13 +3,13 @@ /* eslint-disable jsx-a11y/anchor-is-valid */ import { useState } from "react"; import PropTypes from "prop-types"; -import { Popover, Typography, Link } from "@material-ui/core"; -import HelpIcon from "@material-ui/icons/Help"; +import { Popover, Typography, Link } from "@mui/material"; +import HelpIcon from "@mui/icons-material/Help"; import css from "./styles.css"; import { GUIDING_QUESTIONS_NAME } from "./constants"; -const GuidingQuestions = ({ label, text }) => { +function GuidingQuestions({ label, text }) { const [anchorEl, setAnchorEl] = useState(null); const handleClick = event => { @@ -49,7 +49,7 @@ const GuidingQuestions = ({ label, text }) => { ); -}; +} GuidingQuestions.displayName = GUIDING_QUESTIONS_NAME; diff --git a/app/javascript/components/record-form/form/components/styles.css b/app/javascript/components/record-form/form/components/styles.css index b671609ae2..857b72b7dc 100644 --- a/app/javascript/components/record-form/form/components/styles.css +++ b/app/javascript/components/record-form/form/components/styles.css @@ -73,7 +73,7 @@ } } -@media (max-width:959.95px) { +@media (max-width:900px) { .importDataLabelClass { margin-top: 8px; margin-bottom: 8px; diff --git a/app/javascript/components/record-form/form/components/sync-record.jsx b/app/javascript/components/record-form/form/components/sync-record.jsx index b4f7b3f14a..aeea1ba809 100644 --- a/app/javascript/components/record-form/form/components/sync-record.jsx +++ b/app/javascript/components/record-form/form/components/sync-record.jsx @@ -3,8 +3,8 @@ /* eslint-disable jsx-a11y/anchor-is-valid */ import { useDispatch } from "react-redux"; import PropTypes from "prop-types"; -import { Link } from "@material-ui/core"; -import RefreshIcon from "@material-ui/icons/Refresh"; +import { Link } from "@mui/material"; +import RefreshIcon from "@mui/icons-material/Refresh"; import ActionButton from "../../../action-button"; import { ACTION_BUTTON_TYPES } from "../../../action-button/constants"; @@ -14,7 +14,7 @@ import { SYNC_RECORD_NAME, SYNC_RECORD_STATUS } from "./constants"; import { buildLabelSync } from "./utils"; import css from "./styles.css"; -const SyncRecord = ({ i18n, isEnabledWebhookSyncFor, syncedAt, syncStatus, params }) => { +function SyncRecord({ i18n, isEnabledWebhookSyncFor, syncedAt, syncStatus, params }) { const dispatch = useDispatch(); if (!isEnabledWebhookSyncFor) { @@ -64,7 +64,7 @@ const SyncRecord = ({ i18n, isEnabledWebhookSyncFor, syncedAt, syncStatus, param {renderCheckStatusBtn}
); -}; +} SyncRecord.displayName = SYNC_RECORD_NAME; diff --git a/app/javascript/components/record-form/form/components/sync-record.unit.test.js b/app/javascript/components/record-form/form/components/sync-record.spec.js similarity index 52% rename from app/javascript/components/record-form/form/components/sync-record.unit.test.js rename to app/javascript/components/record-form/form/components/sync-record.spec.js index f881eb539e..ef51cbf0e3 100644 --- a/app/javascript/components/record-form/form/components/sync-record.unit.test.js +++ b/app/javascript/components/record-form/form/components/sync-record.spec.js @@ -1,7 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { setupMountedComponent } from "../../../../test"; -import ActionButton from "../../../action-button"; +import { mountedComponent, screen } from "../../../../test-utils"; import ImportData from "./sync-record"; @@ -13,17 +12,11 @@ describe("", () => { isEnabledWebhookSyncFor: true }; - let component; - beforeEach(() => { - ({ component } = setupMountedComponent(ImportData, props)); - }); - - it("renders a ", () => { - expect(component.find(ImportData)).to.have.lengthOf(1); + mountedComponent(); }); it("renders a ", () => { - expect(component.find(ActionButton)).to.have.lengthOf(1); + expect(screen.getByRole("button")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/record-form/form/components/utils.js b/app/javascript/components/record-form/form/components/utils.js index d3fe1621cd..fd4bc49db7 100644 --- a/app/javascript/components/record-form/form/components/utils.js +++ b/app/javascript/components/record-form/form/components/utils.js @@ -24,3 +24,19 @@ export const buildLabelSync = (syncedStatus, syncedAt, i18n) => { return i18n.t(`sync_record.last`, { date_time: lastDate }); } }; + +export function buildErrorOutput(formErrors, field, locale) { + const fieldError = formErrors[field.get("name")]; + + if (Array.isArray(fieldError)) { + if (fieldError.every(error => typeof error === "object")) { + return formErrors[field.get("name")] + .map((error, index) => `(${index + 1}) ${field.getIn(["display_name", locale])}: ${Object.values(error)}`) + .join("\n"); + } + + return fieldError.join(""); + } + + return fieldError; +} diff --git a/app/javascript/components/record-form/form/components/validation-errors.jsx b/app/javascript/components/record-form/form/components/validation-errors.jsx index 30ae3965fc..ea076485cb 100644 --- a/app/javascript/components/record-form/form/components/validation-errors.jsx +++ b/app/javascript/components/record-form/form/components/validation-errors.jsx @@ -12,10 +12,10 @@ import { getValidationErrors } from "../../selectors"; import { setValidationErrors } from "../../action-creators"; import { useMemoizedSelector } from "../../../../libs"; -import { removeEmptyArrays } from "./utils"; +import { buildErrorOutput, removeEmptyArrays } from "./utils"; import { VALIDATION_ERRORS_NAME } from "./constants"; -const ValidationErrors = ({ formErrors, forms, submitCount }) => { +function ValidationErrors({ formErrors, forms, submitCount }) { const dispatch = useDispatch(); const i18n = useI18n(); @@ -30,7 +30,7 @@ const ValidationErrors = ({ formErrors, forms, submitCount }) => { const formsWithErrors = forms.filter(value => { return value .get("fields", fromJS([])) - .filter(field => !field.get("disabled")) + .filter(field => !field.get("disabled") && field.get("visible")) .map(field => field.get("name")) .some(fieldName => fieldNames.includes(fieldName)); }); @@ -45,7 +45,7 @@ const ValidationErrors = ({ formErrors, forms, submitCount }) => { .get("fields") .filter(field => fieldNames.includes(field.get("name"))) .map(field => ({ - [field.get("name")]: formErrors[field.get("name")] + [field.get("name")]: buildErrorOutput(formErrors, field, i18n.locale) })) .reduce((acc, subCurrent) => ({ ...acc, ...subCurrent }), {}) } @@ -70,7 +70,7 @@ const ValidationErrors = ({ formErrors, forms, submitCount }) => { }, [formErrors, submitCount]); return null; -}; +} ValidationErrors.displayName = VALIDATION_ERRORS_NAME; diff --git a/app/javascript/components/record-form/form/components/validation-errors.spec.js b/app/javascript/components/record-form/form/components/validation-errors.spec.js new file mode 100644 index 0000000000..7fb9cc181f --- /dev/null +++ b/app/javascript/components/record-form/form/components/validation-errors.spec.js @@ -0,0 +1,41 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { fromJS } from "immutable"; + +import { mountedComponent } from "../../../../test-utils"; +import { ENQUEUE_SNACKBAR } from "../../../notifier"; + +import ValidationErrors from "./validation-errors"; + +describe("", () => { + const initialState = fromJS({ forms: {} }); + + it("dispatches a snackbar notification when the form has errors", () => { + const { store } = mountedComponent( + , + initialState + ); + + expect(store.getActions().filter(action => action.type === ENQUEUE_SNACKBAR)).toHaveLength(1); + }); + + it("should not dispatch a snackbar notification if subform does not have error", () => { + const { store } = mountedComponent( + , + initialState + ); + + expect(store.getActions().filter(action => action.type === ENQUEUE_SNACKBAR)).toHaveLength(0); + }); +}); diff --git a/app/javascript/components/record-form/form/components/validation-errors.unit.test.js b/app/javascript/components/record-form/form/components/validation-errors.unit.test.js deleted file mode 100644 index a654cde783..0000000000 --- a/app/javascript/components/record-form/form/components/validation-errors.unit.test.js +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { ENQUEUE_SNACKBAR } from "../../../notifier"; -import { setupMountedComponent } from "../../../../test"; - -import ValidationErrors from "./validation-errors"; - -describe("", () => { - const initialState = fromJS({ forms: {} }); - - it("dispatches a snackbar notification when the form has errors", () => { - const { component } = setupMountedComponent( - ValidationErrors, - { - forms: fromJS([{ unique_id: "form_1" }]), - formErrors: { field_1: "This field is required" }, - submitCount: 1 - }, - initialState - ); - - expect( - component - .props() - .store.getActions() - .filter(action => action.type === ENQUEUE_SNACKBAR) - ).to.have.lengthOf(1); - }); - - it("should not dispatch a snackbar notification if subform does not have error", () => { - const { component } = setupMountedComponent( - ValidationErrors, - { - forms: fromJS([{ unique_id: "form_1" }]), - formErrors: { subform_section_1: [] } - }, - initialState - ); - - expect( - component - .props() - .store.getActions() - .filter(action => action.type === ENQUEUE_SNACKBAR) - ).to.have.lengthOf(0); - }); -}); diff --git a/app/javascript/components/record-form/form/components/workflow-indicator.jsx b/app/javascript/components/record-form/form/components/workflow-indicator.jsx index c49d51711b..ddd8c261f0 100644 --- a/app/javascript/components/record-form/form/components/workflow-indicator.jsx +++ b/app/javascript/components/record-form/form/components/workflow-indicator.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. /* eslint-disable camelcase */ -import { Stepper, Step, StepLabel, useMediaQuery, Badge } from "@material-ui/core"; +import { Stepper, Step, StepLabel, useMediaQuery, Badge } from "@mui/material"; import PropTypes from "prop-types"; import isEmpty from "lodash/isEmpty"; @@ -12,7 +12,7 @@ import { displayNameHelper, useMemoizedSelector } from "../../../../libs"; import css from "./styles.css"; import { WORKFLOW_INDICATOR_NAME, CLOSED } from "./constants"; -const WorkflowIndicator = ({ locale, primeroModule, recordType, record }) => { +function WorkflowIndicator({ locale, primeroModule, recordType, record }) { const mobileDisplay = useMediaQuery(theme => theme.breakpoints.down("sm")); const workflowLabels = useMemoizedSelector(state => @@ -36,7 +36,7 @@ const WorkflowIndicator = ({ locale, primeroModule, recordType, record }) => { return ( <>
- +
{displayNameHelper(workflowSteps?.[activeStep]?.display_text, locale)}
@@ -44,19 +44,19 @@ const WorkflowIndicator = ({ locale, primeroModule, recordType, record }) => { } return ( - + {workflowSteps?.map((s, index) => { const label = displayNameHelper(s.display_text, locale) || ""; return ( - + {label} ); })} ); -}; +} WorkflowIndicator.displayName = WORKFLOW_INDICATOR_NAME; diff --git a/app/javascript/components/record-form/form/components/workflow-indicator.spec.js b/app/javascript/components/record-form/form/components/workflow-indicator.spec.js new file mode 100644 index 0000000000..79bea6a34b --- /dev/null +++ b/app/javascript/components/record-form/form/components/workflow-indicator.spec.js @@ -0,0 +1,113 @@ +import { fromJS, Map } from "immutable"; +import { mountedComponent, stub, screen, setScreenSizeToMobile } from "test-utils"; + +import { PrimeroModuleRecord } from "../../../application/records"; + +import WorkflowIndicator from "./workflow-indicator"; + +describe("", () => { + beforeAll(() => { + setScreenSizeToMobile(false); + }); + + const defaultProps = { + locale: "en", + primeroModule: "primeromodule-cp", + recordType: "cases" + }; + + const state = Map({ + user: fromJS({ + modules: ["primeromodule-cp"] + }), + application: fromJS({ + modules: [ + PrimeroModuleRecord({ + unique_id: "primeromodule-cp", + workflows: { + case: [ + { + id: "new", + display_text: { en: "New" } + }, + { + id: "reopened", + display_text: { en: "Reopened" } + }, + { + id: "services", + display_text: { en: "Services" } + }, + { + id: "closed", + display_text: { en: "Closed" } + } + ] + } + }) + ] + }) + }); + + it("renders status reopened if case has been reopened", () => { + const reopendProps = { + ...defaultProps, + record: Map({ case_status_reopened: true, workflow: "service" }) + }; + + mountedComponent(, state); + + expect(screen.getByText("Reopened")).toBeInTheDocument(); + }); + + describe("when the mobile is displayed", () => { + stub(window, "matchMedia").returns(window.defaultMediaQueryList({ matches: true })); + const workflowProps = { + ...defaultProps, + record: Map({ case_status_reopened: false, workflow: "services" }) + }; + + it("renders the smaller workflow indicator", () => { + setScreenSizeToMobile(true); + mountedComponent(, state); + expect(screen.getByText("Services")).toBeInTheDocument(); + expect(screen.queryAllByTestId("badge")).toHaveLength(1); + setScreenSizeToMobile(false); + }); + + it("should not render the workflow indicator if the module does not support workflows", () => { + const notWorkflowProps = { + ...defaultProps, + record: Map({ case_status_reopened: false }) + }; + + mountedComponent( + , + state.setIn( + ["application", "modules"], + fromJS([ + PrimeroModuleRecord({ + unique_id: "primeromodule-cp" + }) + ]) + ) + ); + + expect(screen.queryAllByTestId("badge")).toHaveLength(0); + expect(screen.queryAllByTestId("step")).toHaveLength(0); + }); + }); + + describe("when case is closed", () => { + it("renders closed step as active", () => { + const reopenedProps = { + ...defaultProps, + record: Map({ status: "closed", workflow: "reopened" }) + }; + + mountedComponent(, state); + expect(screen.getByText("Closed")).toBeInTheDocument(); + expect(screen.getByText("Closed")).toHaveClass("styleLabelActive"); + }); + }); +}); diff --git a/app/javascript/components/record-form/form/components/workflow-indicator.unit.test.js b/app/javascript/components/record-form/form/components/workflow-indicator.unit.test.js deleted file mode 100644 index bd36ec07c5..0000000000 --- a/app/javascript/components/record-form/form/components/workflow-indicator.unit.test.js +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS, Map } from "immutable"; -import { Badge, StepLabel } from "@material-ui/core"; - -import { setupMountedComponent, stub } from "../../../../test"; -import { PrimeroModuleRecord } from "../../../application/records"; - -import WorkflowIndicator from "./workflow-indicator"; - -describe("", () => { - let state; - - const defaultProps = { - locale: "en", - primeroModule: "primeromodule-cp", - recordType: "cases" - }; - - before(() => { - state = Map({ - user: fromJS({ - modules: ["primeromodule-cp"] - }), - application: fromJS({ - modules: [ - PrimeroModuleRecord({ - unique_id: "primeromodule-cp", - workflows: { - case: [ - { - id: "new", - display_text: { en: "New" } - }, - { - id: "reopened", - display_text: { en: "Reopened" } - }, - { - id: "services", - display_text: { en: "Services" } - }, - { - id: "closed", - display_text: { en: "Closed" } - } - ] - } - }) - ] - }) - }); - }); - - it("renders the workflow indicator", () => { - const { component } = setupMountedComponent( - WorkflowIndicator, - { - ...defaultProps, - record: Map({ case_status_reopened: false, workflow: "services" }) - }, - state - ); - - const steps = component.find(StepLabel); - - expect(steps.at(1).props().active).to.equal(true); - expect(steps.at(0).text()).to.include("New"); - expect(steps.at(1).props().active).to.equal(true); - expect(steps.at(1).text()).to.include("Services"); - expect(steps.at(2).props().active).to.equal(false); - expect(steps.at(2).text()).to.include("Closed"); - }); - - it("renders status reopened if case has been reopened", () => { - const { component } = setupMountedComponent( - WorkflowIndicator, - { - ...defaultProps, - record: Map({ case_status_reopened: true, workflow: "service" }) - }, - state - ); - - const steps = component.find(StepLabel); - - expect(steps.at(0).text()).to.include("Reopened"); - }); - - describe("when the mobile is displayed", () => { - beforeEach(() => { - stub(window, "matchMedia").returns(window.defaultMediaQueryList({ matches: true })); - }); - - it("renders the smaller workflow indicator", () => { - const { component } = setupMountedComponent( - WorkflowIndicator, - { - ...defaultProps, - record: Map({ case_status_reopened: false, workflow: "services" }) - }, - state - ); - - expect(component.find(Badge).text()).to.equal("2"); - expect(component.find(StepLabel)).to.have.lengthOf(0); - }); - - it("should not render the workflow indicator if the module does not support workflows", () => { - const { component } = setupMountedComponent( - WorkflowIndicator, - { - ...defaultProps, - record: Map({ case_status_reopened: false }) - }, - state.setIn( - ["application", "modules"], - fromJS([ - PrimeroModuleRecord({ - unique_id: "primeromodule-cp" - }) - ]) - ) - ); - - expect(component.find(Badge)).to.have.lengthOf(0); - expect(component.find(StepLabel)).to.have.lengthOf(0); - }); - - afterEach(() => { - window.matchMedia.restore(); - }); - }); - - describe("when case is closed", () => { - it("renders closed step as active", () => { - const { component } = setupMountedComponent( - WorkflowIndicator, - { - ...defaultProps, - record: Map({ status: "closed", workflow: "reopened" }) - }, - state - ); - - const steps = component.find(StepLabel); - - expect(steps.at(0).text()).to.include("New"); - expect(steps.at(0).props().active).to.be.false; - expect(steps.at(1).text()).to.include("Services"); - expect(steps.at(1).props().active).to.be.false; - expect(steps.at(2).text()).to.include("Closed"); - expect(steps.at(2).props().active).to.be.true; - }); - }); -}); diff --git a/app/javascript/components/record-form/form/field-types/attachments/attachment-field.jsx b/app/javascript/components/record-form/form/field-types/attachments/attachment-field.jsx index 8d4da86d18..6c8169b875 100644 --- a/app/javascript/components/record-form/form/field-types/attachments/attachment-field.jsx +++ b/app/javascript/components/record-form/form/field-types/attachments/attachment-field.jsx @@ -2,8 +2,8 @@ import { useState } from "react"; import PropTypes from "prop-types"; -import { Box } from "@material-ui/core"; -import DeleteIcon from "@material-ui/icons/Delete"; +import { Box } from "@mui/material"; +import DeleteIcon from "@mui/icons-material/Delete"; import css from "../../styles.css"; import ActionButton from "../../../../action-button"; @@ -16,7 +16,7 @@ import { buildAttachmentFieldsObject, buildBase64URL } from "./utils"; import AttachmentInput from "./attachment-input"; import AttachmentPreview from "./attachment-preview"; -const AttachmentField = ({ name, index, attachment, disabled, mode, arrayHelpers, value }) => { +function AttachmentField({ name, index, attachment, disabled, mode, arrayHelpers, value }) { const i18n = useI18n(); const [open, setOpen] = useState(false); @@ -37,10 +37,7 @@ const AttachmentField = ({ name, index, attachment, disabled, mode, arrayHelpers const handleRemove = () => { if (attachmentUrl) { - arrayHelpers.replace(index, { - _destroy: id, - attachment_type: attachment - }); + arrayHelpers.replace(index, { _destroy: true, id, attachment_type: attachment }); } else { arrayHelpers.remove(index); } @@ -97,7 +94,7 @@ const AttachmentField = ({ name, index, attachment, disabled, mode, arrayHelpers
); -}; +} AttachmentField.displayName = "AttachmentField"; diff --git a/app/javascript/components/record-form/form/field-types/attachments/attachment-field.spec.js b/app/javascript/components/record-form/form/field-types/attachments/attachment-field.spec.js new file mode 100644 index 0000000000..3cc3fc1d19 --- /dev/null +++ b/app/javascript/components/record-form/form/field-types/attachments/attachment-field.spec.js @@ -0,0 +1,71 @@ +import { mountedComponent, screen, fireEvent } from "../../../../../test-utils"; + +import { ATTACHMENT_TYPES } from "./constants"; +import AttachmentField from "./attachment-field"; + +describe("", () => { + const props = { + arrayHelpers: {}, + attachment: ATTACHMENT_TYPES.document, + disabled: false, + mode: { + isShow: false, + isEdit: true + }, + name: "attachment_field_test", + index: 0, + value: {} + }; + + const formProps = { + initialValues: {} + }; + + it("should render component", () => { + mountedComponent(, {}, [], {}, formProps); + expect(document.querySelector(".uploadBox")).toBeInTheDocument(); + expect(screen.getByText("fields.file_upload_box.select_file_button_text")).toBeInTheDocument(); + }); + + it("should render ActionButton", () => { + mountedComponent(, {}, [], {}, formProps); + expect(screen.getByRole("button")).toBeInTheDocument(); + }); + + describe("when value contains attachmentUrl", () => { + const newProps = { + ...props, + value: { + attachment_url: "random-string" + } + }; + + it("should render ActionDialog", () => { + mountedComponent(, {}, [], {}, formProps); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByText("fields.remove attachment_field_test")).toBeInTheDocument(); + }); + + it("should not render the AttachmentInput", () => { + mountedComponent(, {}, [], {}, formProps); + expect(screen.queryByRole("textbox")).toBeNull(); + }); + + it("should render the AttachmentPreview", () => { + mountedComponent(, {}, [], {}, formProps); + expect(screen.getByRole("presentation")).toBeInTheDocument(); + }); + }); + + describe("when value doesn't contains attachmentUrl", () => { + it("should render the AttachmentInput", () => { + mountedComponent(, {}, [], {}, formProps); + expect(screen.getByTestId("input-file")).toBeInTheDocument(); + }); + + it("should not render the AttachmentPreview", () => { + mountedComponent(, {}, [], {}, formProps); + expect(screen.queryByTestId("attachment")).toBeNull(); + }); + }); +}); diff --git a/app/javascript/components/record-form/form/field-types/attachments/attachment-field.unit.test.js b/app/javascript/components/record-form/form/field-types/attachments/attachment-field.unit.test.js deleted file mode 100644 index 5ef6308553..0000000000 --- a/app/javascript/components/record-form/form/field-types/attachments/attachment-field.unit.test.js +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../../../test"; -import ActionDialog from "../../../../action-dialog"; -import ActionButton from "../../../../action-button"; - -import { ATTACHMENT_TYPES } from "./constants"; -import AttachmentInput from "./attachment-input"; -import AttachmentPreview from "./attachment-preview"; -import AttachmentField from "./attachment-field"; - -describe("", () => { - const props = { - arrayHelpers: {}, - attachment: ATTACHMENT_TYPES.document, - disabled: false, - mode: { - isShow: false, - isEdit: true - }, - name: "attachment_field_test", - index: 0, - value: {} - }; - - const formProps = { - initialValues: {} - }; - - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(AttachmentField, props, {}, [], formProps)); - }); - - it("should render ActionDialog", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(1); - }); - - it("should render ActionButton", () => { - expect(component.find(ActionButton)).to.have.lengthOf(1); - }); - - describe("when value contains attachmentUrl", () => { - const { component: componentWithAttachment } = setupMountedComponent( - AttachmentField, - { ...props, value: { attachment_url: "test" } }, - {}, - [], - formProps - ); - - it("should not render the AttachmentInput", () => { - expect(componentWithAttachment.find(AttachmentInput)).to.not.have.lengthOf(1); - }); - - it("should render the AttachmentPreview", () => { - expect(componentWithAttachment.find(AttachmentPreview)).to.have.lengthOf(1); - }); - }); - - describe("when value doesn't contains attachmentUrl", () => { - it("should render the AttachmentInput", () => { - expect(component.find(AttachmentInput)).to.have.lengthOf(1); - }); - - it("should not render the AttachmentPreview", () => { - expect(component.find(AttachmentPreview)).to.not.have.lengthOf(1); - }); - }); -}); diff --git a/app/javascript/components/record-form/form/field-types/attachments/attachment-input.jsx b/app/javascript/components/record-form/form/field-types/attachments/attachment-input.jsx index 4b215103dd..9c737dbb1c 100644 --- a/app/javascript/components/record-form/form/field-types/attachments/attachment-input.jsx +++ b/app/javascript/components/record-form/form/field-types/attachments/attachment-input.jsx @@ -4,6 +4,7 @@ import { useState } from "react"; import PropTypes from "prop-types"; import { FastField } from "formik"; import { useDispatch } from "react-redux"; +import { FormHelperText } from "@mui/material"; import { MAX_ATTACHMENT_SIZE } from "../../../../../config"; import { toBase64 } from "../../../../../libs"; @@ -11,11 +12,12 @@ import css from "../../styles.css"; import ActionButton from "../../../../action-button"; import { ACTION_BUTTON_TYPES } from "../../../../action-button/constants"; import { enqueueSnackbar, SNACKBAR_VARIANTS } from "../../../../notifier"; +import { get } from "../../../../form/utils"; import { ATTACHMENT_TYPES, ATTACHMENT_ACCEPTED_TYPES } from "./constants"; import renderPreview from "./render-preview"; -const AttachmentInput = ({ attachment, fields, name, value, deleteButton }) => { +function AttachmentInput({ attachment, fields, name, value, deleteButton }) { const dispatch = useDispatch(); const [file, setFile] = useState({ @@ -49,14 +51,14 @@ const AttachmentInput = ({ attachment, fields, name, value, deleteButton }) => { if (data) { loadingFile(false, data); + form.setFieldValue(fields.contentType, data?.fileType); + form.setFieldValue(fields.fileName, data?.fileName); + form.setFieldValue(fields.attachmentType, attachment); + form.setFieldValue(fields.fieldName, name); form.setFieldValue(fields.attachment, data?.result, true); - form.setFieldValue(fields.contentType, data?.fileType, true); - form.setFieldValue(fields.fileName, data?.fileName, true); - form.setFieldValue(fields.attachmentType, attachment, true); - form.setFieldValue(fields.fieldName, name, true); if ([ATTACHMENT_TYPES.photo, ATTACHMENT_TYPES.audio].includes(attachment)) { - form.setFieldValue(fields.date, new Date(), true); + form.setFieldValue(fields.date, new Date()); } } } @@ -68,44 +70,53 @@ const AttachmentInput = ({ attachment, fields, name, value, deleteButton }) => { return (
- -
- - {({ form }) => { - const handleOnChange = event => handleChange(form, event); - - return ( - - ); - }} - -
+ + {({ form }) => { + const handleOnChange = event => handleChange(form, event); + const error = get(form.errors, "attachment", ""); + + return ( +
+ +
+ +
+ {error && ( + + {error} + + )} +
+ ); + }} +
{file && renderPreview(attachment, file, css, deleteButton)}
); -}; +} AttachmentInput.displayName = "AttachmentInput"; diff --git a/app/javascript/components/record-form/form/field-types/attachments/attachment-input.spec.js b/app/javascript/components/record-form/form/field-types/attachments/attachment-input.spec.js new file mode 100644 index 0000000000..fab85446cb --- /dev/null +++ b/app/javascript/components/record-form/form/field-types/attachments/attachment-input.spec.js @@ -0,0 +1,28 @@ +import { mountedComponent, screen } from "../../../../../test-utils"; + +import { ATTACHMENT_TYPES } from "./constants"; +import AttachmentInput from "./attachment-input"; + +describe("", () => { + const props = { + fields: {}, + attachment: ATTACHMENT_TYPES.document, + name: "attachment_field_test", + deleteButton: <>, + value: "test" + }; + + const formProps = { + initialValues: {} + }; + + it("should render FastField", () => { + mountedComponent(, {}, [], {}, formProps); + expect(screen.getByTestId("input-file")).toBeInTheDocument(); + }); + + it("should render ActionButton", () => { + mountedComponent(, {}, [], {}, formProps); + expect(screen.getByText("fields.file_upload_box.select_file_button_text")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/record-form/form/field-types/attachments/attachment-input.unit.test.js b/app/javascript/components/record-form/form/field-types/attachments/attachment-input.unit.test.js deleted file mode 100644 index b624bef0cb..0000000000 --- a/app/javascript/components/record-form/form/field-types/attachments/attachment-input.unit.test.js +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { FastField } from "formik"; - -import { setupMountedComponent } from "../../../../../test"; -import ActionButton from "../../../../action-button"; - -import { ATTACHMENT_TYPES } from "./constants"; -import AttachmentInput from "./attachment-input"; - -describe("", () => { - const props = { - fields: {}, - attachment: ATTACHMENT_TYPES.document, - name: "attachment_field_test", - deleteButton: <>, - value: "test" - }; - - const formProps = { - initialValues: {} - }; - - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(AttachmentInput, props, {}, [], formProps)); - }); - - it("should render FastField", () => { - expect(component.find(FastField)).to.have.lengthOf(1); - }); - - it("should render ActionButton", () => { - expect(component.find(ActionButton)).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/record-form/form/field-types/attachments/attachment-label.jsx b/app/javascript/components/record-form/form/field-types/attachments/attachment-label.jsx index 85cc7485a6..486343a561 100644 --- a/app/javascript/components/record-form/form/field-types/attachments/attachment-label.jsx +++ b/app/javascript/components/record-form/form/field-types/attachments/attachment-label.jsx @@ -1,22 +1,25 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import AddIcon from "@material-ui/icons/Add"; -import { FormHelperText } from "@material-ui/core/"; +import AddIcon from "@mui/icons-material/Add"; +import { FormHelperText } from "@mui/material/"; import css from "../../styles.css"; import ActionButton from "../../../../action-button"; import { ACTION_BUTTON_TYPES } from "../../../../action-button/constants"; -const AttachmentLabel = ({ label, helpText, disabled, mode, arrayHelpers, handleAttachmentAddition }) => { +function AttachmentLabel({ label, helpText, disabled, mode, arrayHelpers, handleAttachmentAddition, error }) { const isDisabled = !disabled && !mode.isShow; const onClick = () => handleAttachmentAddition(arrayHelpers); + const errorMessage = Array.isArray(error) ? error.join("\n") : error; return (
-

{label}

- {helpText} +

{label}

+ + {errorMessage || helpText} +
{isDisabled && (
@@ -24,6 +27,7 @@ const AttachmentLabel = ({ label, helpText, disabled, mode, arrayHelpers, handle icon={} text="Add" type={ACTION_BUTTON_TYPES.icon} + data-testid="attachment-label-action-button" rest={{ onClick }} @@ -32,13 +36,14 @@ const AttachmentLabel = ({ label, helpText, disabled, mode, arrayHelpers, handle )}
); -}; +} AttachmentLabel.displayName = "AttachmentLabel"; AttachmentLabel.propTypes = { arrayHelpers: PropTypes.object.isRequired, disabled: PropTypes.bool, + error: PropTypes.string, handleAttachmentAddition: PropTypes.func.isRequired, helpText: PropTypes.string, label: PropTypes.string.isRequired, diff --git a/app/javascript/components/record-form/form/field-types/attachments/attachment-label.spec.js b/app/javascript/components/record-form/form/field-types/attachments/attachment-label.spec.js new file mode 100644 index 0000000000..c614c01b4b --- /dev/null +++ b/app/javascript/components/record-form/form/field-types/attachments/attachment-label.spec.js @@ -0,0 +1,32 @@ +// Copyright (c) 2014 - 2024 UNICEF. All rights reserved. + +import { mountedComponent, screen } from "test-utils"; + +import AttachmentLabel from "./attachment-label"; + +describe("", () => { + const props = { + label: "Some label", + helpText: "Some Help Text", + mode: { isShow: false }, + handleAttachmentAddition: () => {}, + arrayHelpers: {}, + disabled: false + }; + + beforeEach(() => { + mountedComponent(); + }); + + it("renders the AttachmentLabel", () => { + expect(screen.getAllByTestId("attachment-label")).toHaveLength(1); + }); + + it("renders the FormHelperText", () => { + expect(screen.getAllByTestId("attachment-label-helptext")).toHaveLength(1); + }); + + it("renders a component", () => { + expect(screen.getAllByTestId("attachment-label-action-button")).toHaveLength(1); + }); +}); diff --git a/app/javascript/components/record-form/form/field-types/attachments/attachment-preview.jsx b/app/javascript/components/record-form/form/field-types/attachments/attachment-preview.jsx index ec4ced34c3..0dd29ac00e 100644 --- a/app/javascript/components/record-form/form/field-types/attachments/attachment-preview.jsx +++ b/app/javascript/components/record-form/form/field-types/attachments/attachment-preview.jsx @@ -7,7 +7,7 @@ import css from "../../styles.css"; import { ATTACHMENT_TYPES } from "./constants"; -const AttachmentPreview = ({ name, attachment, attachmentUrl }) => { +function AttachmentPreview({ name, attachment, attachmentUrl }) { const isAudioAttachment = attachment === ATTACHMENT_TYPES.audio; useEffect(() => { @@ -20,14 +20,14 @@ const AttachmentPreview = ({ name, attachment, attachmentUrl }) => { if (isAudioAttachment) { return ( // eslint-disable-next-line jsx-a11y/media-has-caption -
; @@ -94,11 +94,13 @@ export default (allowedColumns, i18n, recordType, css, recordAvailable, online) return { sort: column.get("sort", true), customBodyRender: (value, { rowIndex }) => ( - + + + ) }; } @@ -110,6 +112,24 @@ export default (allowedColumns, i18n, recordType, css, recordAvailable, online) id: column.get("id_search"), options: { ...options, + ...(phonetic + ? { + sort: false, + customHeadRender: columnMeta => { + const headLabelRender = options?.customHeadLabelRender + ? options.customHeadLabelRender(columnMeta) + : columnMeta.label; + + return ( + + +
{headLabelRender}
+
+
+ ); + } + } + : {}), display: !( RECORD_TYPES[recordType] === RECORD_TYPES.cases && column.get("field_name") === ID_COLUMNS.short_id ) diff --git a/app/javascript/components/record-list/utils/filters-to-query-string.js b/app/javascript/components/record-list/utils/filters-to-query-string.js index 07fc77ea16..c588820441 100644 --- a/app/javascript/components/record-list/utils/filters-to-query-string.js +++ b/app/javascript/components/record-list/utils/filters-to-query-string.js @@ -5,21 +5,17 @@ import { List, Map } from "immutable"; const paramQueryString = (key, value) => { if (List.isList(value)) { return value.reduce((prev, elem, index) => { - if (!prev) { - return `${key}[${index}]=${elem}`; - } + const param = paramQueryString(`${key}[${index}]`, elem); - return `${prev}&${key}[${index}]=${elem}`; + return !prev ? param : `${prev}&${param}`; }, ""); } if (Map.isMap(value)) { return value.entrySeq().reduce((prev, [elemKey, elemValue]) => { - if (!prev) { - return `${key}[${elemKey}]=${elemValue}`; - } + const param = paramQueryString(`${key}[${elemKey}]`, elemValue); - return `${prev}&${key}[${elemKey}]=${elemValue}`; + return !prev ? param : `${prev}&${param}`; }, ""); } diff --git a/app/javascript/components/record-list/utils/filters-to-query-string.unit.test.js b/app/javascript/components/record-list/utils/filters-to-query-string.unit.test.js index 6b4755e7df..ccdbf2fc51 100644 --- a/app/javascript/components/record-list/utils/filters-to-query-string.unit.test.js +++ b/app/javascript/components/record-list/utils/filters-to-query-string.unit.test.js @@ -20,4 +20,32 @@ describe("/utils - filtersToQueryString", () => { "date[from]=2010-01-05&date[to]=2010-01-08" ); }); + + it("returns a query string for a hash with a nested list", () => { + expect(filtersToQueryString(fromJS({ not: { last_updated_by: ["user1", "user2"] }, status: ["open"] }))).to.equals( + "not[last_updated_by][0]=user1¬[last_updated_by][1]=user2&status[0]=open" + ); + }); + + it("returns a query string for a list with hashes", () => { + expect( + filtersToQueryString(fromJS({ not: [{ user_name: "user1" }, { user_name: "user2" }], status: ["open"] })) + ).to.equals("not[0][user_name]=user1¬[1][user_name]=user2&status[0]=open"); + }); + + it("returns a query string for a list with nested lists", () => { + expect( + filtersToQueryString( + fromJS({ + user_name: [ + ["user1", "user2"], + ["user3", "user4"] + ], + status: ["open"] + }) + ) + ).to.equals( + "user_name[0][0]=user1&user_name[0][1]=user2&user_name[1][0]=user3&user_name[1][1]=user4&status[0]=open" + ); + }); }); diff --git a/app/javascript/components/record-list/view-modal/component.jsx b/app/javascript/components/record-list/view-modal/component.jsx index 5d9a42cff9..daad165b72 100644 --- a/app/javascript/components/record-list/view-modal/component.jsx +++ b/app/javascript/components/record-list/view-modal/component.jsx @@ -17,7 +17,7 @@ import viewModalForm from "./form"; import TransferRequest from "./transfer-request"; import { COMMON_FIELD_NAMES, FORM_ID, NAME } from "./constants"; -const ViewModal = ({ close, openViewModal, currentRecord, recordType }) => { +function ViewModal({ close, openViewModal, currentRecord, recordType }) { const i18n = useI18n(); const [sendRequest, setSendRequest] = useState(false); @@ -88,7 +88,7 @@ const ViewModal = ({ close, openViewModal, currentRecord, recordType }) => { ); -}; +} ViewModal.displayName = NAME; diff --git a/app/javascript/components/record-list/view-modal/component.unit.test.js b/app/javascript/components/record-list/view-modal/component.spec.js similarity index 62% rename from app/javascript/components/record-list/view-modal/component.unit.test.js rename to app/javascript/components/record-list/view-modal/component.spec.js index 0c3861dc2e..ad07e64e55 100644 --- a/app/javascript/components/record-list/view-modal/component.unit.test.js +++ b/app/javascript/components/record-list/view-modal/component.spec.js @@ -1,12 +1,10 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - +import { mountedComponent, screen } from "test-utils"; import { fromJS } from "immutable"; -import { TextField } from "@material-ui/core"; import { ACTIONS } from "../../permissions"; import { mapEntriesToRecord } from "../../../libs"; -import { setupMountedComponent } from "../../../test"; -import * as R from "../../record-form/records"; +import { FormSectionRecord, FieldRecord } from "../../record-form/records"; import { RECORD_TYPES } from "../../../config"; import ViewModal from "./component"; @@ -105,75 +103,61 @@ describe("", () => { const initialState = fromJS({ user: { permissions: { cases: [] } }, forms: { - formSections: mapEntriesToRecord(formSections, R.FormSectionRecord), - fields: mapEntriesToRecord(fields, R.FieldRecord) + formSections: mapEntriesToRecord(formSections, FormSectionRecord), + fields: mapEntriesToRecord(fields, FieldRecord) } }); - const { component } = setupMountedComponent(ViewModal, props, initialState); - - const fieldNames = component - .find(ViewModal) - .find(TextField) - .map(field => field.props().name); + mountedComponent(, initialState); + const inputs = Array.from(document.querySelectorAll("input")).map(input => input.getAttribute("name")); - expect(fieldNames).to.include.members(["name_first", "name_last"]); + expect(inputs).toContain("name_first"); + expect(inputs).toContain("name_last"); }); it("should not render nested fields even if they are show_on_minify_form", () => { const initialState = fromJS({ user: { permissions: { cases: [] } }, forms: { - formSections: mapEntriesToRecord(formSections, R.FormSectionRecord), - fields: mapEntriesToRecord(fields, R.FieldRecord) + formSections: mapEntriesToRecord(formSections, FormSectionRecord), + fields: mapEntriesToRecord(fields, FieldRecord) } }); + const { container } = mountedComponent(, initialState); + const textFields = container.querySelectorAll('input[type="text"]'); + const fieldNames = Array.from(textFields).map(field => field.name); - const { component } = setupMountedComponent(ViewModal, props, initialState); - - const fieldNames = component - .find(ViewModal) - .find(TextField) - .map(field => field.props().name); - - expect(fieldNames).to.not.have.members(["address", "telephone"]); + expect(fieldNames).not.toContain("address"); + expect(fieldNames).not.toContain("telephone"); }); it("should not render the Request Transfer button if the user does not have permission", () => { const initialState = fromJS({ user: { permissions: { cases: [] } }, forms: { - formSections: mapEntriesToRecord(formSections, R.FormSectionRecord), - fields: mapEntriesToRecord(fields, R.FieldRecord) + formSections: mapEntriesToRecord(formSections, FormSectionRecord), + fields: mapEntriesToRecord(fields, FieldRecord) } }); - const { component } = setupMountedComponent(ViewModal, props, initialState); - const actionButtons = component - .find(ViewModal) - .find("button") - .map(button => button.text()) - .filter(text => text === "buttons.request_transfer"); + mountedComponent(, initialState); + const actionButton = screen.queryByText(/Request Transfer/i); - expect(actionButtons).to.be.empty; + expect(actionButton).toBeNull(); }); it("should render the Request Transfer button if the user has permission", () => { const initialState = fromJS({ user: { permissions: { cases: [ACTIONS.REQUEST_TRANSFER] } }, forms: { - formSections: mapEntriesToRecord(formSections, R.FormSectionRecord), - fields: mapEntriesToRecord(fields, R.FieldRecord) + formSections: mapEntriesToRecord(formSections, FormSectionRecord), + fields: mapEntriesToRecord(fields, FieldRecord) } }); - const { component } = setupMountedComponent(ViewModal, props, initialState); - const actionButtons = component - .find(ViewModal) - .find("button") - .map(button => button.text()) - .filter(text => text === "buttons.request_transfer"); + mountedComponent(, initialState); + const requestTransferButton = screen.getByText("buttons.request_transfer"); - expect(actionButtons).to.have.lengthOf(1); + expect(requestTransferButton).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/record-list/view-modal/transfer-request/component.jsx b/app/javascript/components/record-list/view-modal/transfer-request/component.jsx index 1bf791509f..48b6d1d341 100644 --- a/app/javascript/components/record-list/view-modal/transfer-request/component.jsx +++ b/app/javascript/components/record-list/view-modal/transfer-request/component.jsx @@ -16,7 +16,7 @@ import RequestForm from "./request-form"; import { saveTransferRequest } from "./action-creators"; import NAMESPACE from "./namespace"; -const TransferRequest = ({ open, setOpen, currentRecord, caseId }) => { +function TransferRequest({ open, setOpen, currentRecord, caseId }) { const i18n = useI18n(); const dispatch = useDispatch(); const formikRef = createRef(); @@ -82,7 +82,7 @@ const TransferRequest = ({ open, setOpen, currentRecord, caseId }) => { ); -}; +} TransferRequest.displayName = NAME; diff --git a/app/javascript/components/record-list/view-modal/transfer-request/component.spec.js b/app/javascript/components/record-list/view-modal/transfer-request/component.spec.js new file mode 100644 index 0000000000..f7275edc68 --- /dev/null +++ b/app/javascript/components/record-list/view-modal/transfer-request/component.spec.js @@ -0,0 +1,28 @@ +import { fromJS } from "immutable"; +import { mountedComponent, screen } from "test-utils"; + +import TransferRequest from "./component"; + +describe("", () => { + const currentRecord = fromJS({ + id: "03cdfdfe-a8fc-4147-b703-df976d200977", + case_id: "1799d556-652c-4ad9-9b4c-525d487b5e7b", + case_id_display: "9b4c525", + name_first: "Name", + name_last: "Last", + name: "Name Last", + owned_by: "primero" + }); + + const props = { + caseId: "1234", + currentRecord, + open: true, + setOpen: () => {} + }; + + it("should render ActionDialog", () => { + mountedComponent(); + expect(screen.getByRole("dialog")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/record-list/view-modal/transfer-request/component.unit.test.js b/app/javascript/components/record-list/view-modal/transfer-request/component.unit.test.js deleted file mode 100644 index 4518f11b38..0000000000 --- a/app/javascript/components/record-list/view-modal/transfer-request/component.unit.test.js +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Formik } from "formik"; -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../../test"; -import ActionDialog from "../../../action-dialog"; - -import TransferRequest from "./component"; - -describe("", () => { - let component; - const currentRecord = fromJS({ - id: "03cdfdfe-a8fc-4147-b703-df976d200977", - case_id: "1799d556-652c-4ad9-9b4c-525d487b5e7b", - case_id_display: "9b4c525", - name_first: "Name", - name_last: "Last", - name: "Name Last", - owned_by: "primero" - }); - - const props = { - caseId: "1234", - currentRecord, - open: true, - setOpen: () => {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(TransferRequest, props, {})); - }); - - it("should render ActionDialog", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(1); - }); - - it("should render Formik", () => { - expect(component.find(Formik)).to.have.lengthOf(1); - }); - - it("should accept valid props", () => { - const transferRequestProps = { ...component.find(TransferRequest).props() }; - - expect(component.find(TransferRequest)).to.have.lengthOf(1); - ["caseId", "currentRecord", "open", "setOpen"].forEach(property => { - expect(transferRequestProps).to.have.property(property); - delete transferRequestProps[property]; - }); - expect(transferRequestProps).to.be.empty; - }); -}); diff --git a/app/javascript/components/record-list/view-modal/transfer-request/request-form.jsx b/app/javascript/components/record-list/view-modal/transfer-request/request-form.jsx index e7cc60555a..072efce9ca 100644 --- a/app/javascript/components/record-list/view-modal/transfer-request/request-form.jsx +++ b/app/javascript/components/record-list/view-modal/transfer-request/request-form.jsx @@ -1,9 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Grid, Divider } from "@material-ui/core"; +import { Grid, Divider } from "@mui/material"; import { Form, Field } from "formik"; -import { TextField as MuiTextField } from "formik-material-ui"; +import { TextField as MuiTextField } from "formik-mui"; import { useI18n } from "../../../i18n"; import DisplayData from "../../../display-data"; @@ -16,7 +16,7 @@ const sharedTextFieldProps = { fullWidth: true }; -const RequestForm = ({ formProps, record }) => { +function RequestForm({ formProps, record }) { const i18n = useI18n(); const { handleSubmit } = formProps; @@ -45,7 +45,7 @@ const RequestForm = ({ formProps, record }) => { ); -}; +} RequestForm.displayName = REQUEST_FORM_NAME; diff --git a/app/javascript/components/record-list/view-modal/transfer-request/request-form.spec.js b/app/javascript/components/record-list/view-modal/transfer-request/request-form.spec.js new file mode 100644 index 0000000000..4fdd2d863a --- /dev/null +++ b/app/javascript/components/record-list/view-modal/transfer-request/request-form.spec.js @@ -0,0 +1,44 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { fromJS } from "immutable"; + +import { mountedComponent, screen } from "../../../../test-utils"; + +import RequestForm from "./request-form"; + +describe("", () => { + const record = fromJS({ + id: "03cdfdfe-a8fc-4147-b703-df976d200977", + case_id: "1799d556-652c-4ad9-9b4c-525d487b5e7b", + case_id_display: "9b4c525", + name_first: "Name", + name_last: "Last", + name: "Name Last", + owned_by: "primero" + }); + + const formProps = { + initialValues: { + notes: "" + } + }; + + const props = { + formProps: { + handleSubmit: () => {} + }, + record + }; + + beforeEach(() => { + mountedComponent(, {}, {}, [], formProps); + }); + + it("should render DisplayData", () => { + expect(screen.getAllByTestId("display-data")).toHaveLength(2); + }); + + it("should render Field", () => { + expect(screen.getByRole("textbox")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/record-list/view-modal/transfer-request/request-form.unit.test.js b/app/javascript/components/record-list/view-modal/transfer-request/request-form.unit.test.js deleted file mode 100644 index 0a9f0da23e..0000000000 --- a/app/javascript/components/record-list/view-modal/transfer-request/request-form.unit.test.js +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Field } from "formik"; -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../../test"; -import DisplayData from "../../../display-data"; - -import RequestForm from "./request-form"; - -describe("", () => { - let component; - const record = fromJS({ - id: "03cdfdfe-a8fc-4147-b703-df976d200977", - case_id: "1799d556-652c-4ad9-9b4c-525d487b5e7b", - case_id_display: "9b4c525", - name_first: "Name", - name_last: "Last", - name: "Name Last", - owned_by: "primero" - }); - - const formProps = { - initialValues: { - notes: "" - } - }; - - const props = { - formProps: { - handleSubmit: () => {} - }, - record - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(RequestForm, props, {}, {}, formProps)); - }); - - it("should render DisplayData", () => { - expect(component.find(DisplayData)).to.have.lengthOf(2); - }); - - it("should render Field", () => { - expect(component.find(Field)).to.have.lengthOf(1); - }); - - it("should accept valid props", () => { - const requestFormProps = { ...component.find(RequestForm).props() }; - - expect(component.find(RequestForm)).to.have.lengthOf(1); - ["formProps", "record"].forEach(property => { - expect(requestFormProps).to.have.property(property); - delete requestFormProps[property]; - }); - expect(requestFormProps).to.be.empty; - }); -}); diff --git a/app/javascript/components/record-owner/component.jsx b/app/javascript/components/record-owner/component.jsx index 7e50646cab..14891319a8 100644 --- a/app/javascript/components/record-owner/component.jsx +++ b/app/javascript/components/record-owner/component.jsx @@ -12,7 +12,7 @@ import useMemoizedSelector from "../../libs/use-memoized-selector"; import { NAME, FIELDS } from "./constants"; -const Component = ({ record, recordType, mobileDisplay, handleToggleNav }) => { +function Component({ record, recordType, mobileDisplay, handleToggleNav }) { const i18n = useI18n(); const agencies = useMemoizedSelector(state => selectAgencies(state)); @@ -64,7 +64,7 @@ const Component = ({ record, recordType, mobileDisplay, handleToggleNav }) => { }); return ( -
+
{
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/record-owner/component.unit.test.js b/app/javascript/components/record-owner/component.spec.js similarity index 56% rename from app/javascript/components/record-owner/component.unit.test.js rename to app/javascript/components/record-owner/component.spec.js index faa9d210d1..b46d4a47bf 100644 --- a/app/javascript/components/record-owner/component.unit.test.js +++ b/app/javascript/components/record-owner/component.spec.js @@ -1,19 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS, Map } from "immutable"; -import { Form } from "formik"; -import { TextField as MuiTextField } from "formik-material-ui"; -import { setupMountedComponent } from "../../test"; import { RESOURCES } from "../permissions"; -import { FormSectionField } from "../record-form"; -import SearchableSelect from "../searchable-select"; +import { mountedComponent, screen } from "../../test-utils"; import RecordOwner from "./component"; describe("", () => { - let component; - const record = fromJS({ case_id: "12345", case_id_display: "3c9d076", @@ -65,56 +59,30 @@ describe("", () => { } }); - beforeEach(() => { - ({ component } = setupMountedComponent(RecordOwner, rootProps, rootInitialState)); - }); - - it("renders a RecordOwner component and its fields/>", () => { - expect(component.find(RecordOwner)).to.have.lengthOf(1); - expect(component.find(FormSectionField)).to.have.lengthOf(15); - expect(component.find(SearchableSelect)).to.have.lengthOf(1); - expect(component.find(SearchableSelect).props().defaultValues[0].id).to.equal("agency-unicef"); - }); - - it("renders Form", () => { - expect(component.find(Form)).to.have.lengthOf(1); - }); - it("renders value for assigned_user_names", () => { - const associatedUserNames = component.find(MuiTextField).at(2).props(); - - expect(associatedUserNames.name).to.be.equal("assigned_user_names"); - expect(associatedUserNames.field.value).to.be.equal("primero_admin_cp, test_user"); + mountedComponent(, rootInitialState); + expect(screen.getByLabelText("record_information.assigned_user_names")).toHaveValue("primero_admin_cp, test_user"); }); it("renders value for previously_owned_by_agency", () => { - const previouslyOwnedBy = component.find(MuiTextField).at(6).props(); - - expect(previouslyOwnedBy.name).to.be.equal("previously_owned_by_agency"); - expect(previouslyOwnedBy.field.value).to.be.equal("TEST/AGENCY"); + mountedComponent(, rootInitialState); + expect(screen.getByLabelText("record_information.previously_owned_by_agency")).toHaveValue("TEST/AGENCY"); }); describe("with created_organization", () => { describe("when is an object", () => { it("renders value for created_organization", () => { - const createOrganization = component.find(MuiTextField).at(4).props(); - - expect(createOrganization.name).to.be.equal("created_organization"); - expect(createOrganization.field.value).to.be.equal("TEST"); + mountedComponent(, rootInitialState); + expect(screen.getByLabelText("record_information.created_organization")).toHaveValue("TEST"); }); }); describe("when is a string", () => { it("renders value for created_organization", () => { - const { component: componentWithStringOrganization } = setupMountedComponent( - RecordOwner, - { ...rootProps, record: record.set("created_organization", "AGENCY 1") }, - rootInitialState - ); - const createOrganization = componentWithStringOrganization.find(MuiTextField).at(4).props(); - - expect(createOrganization.name).to.be.equal("created_organization"); - expect(createOrganization.field.value).to.be.equal("AGENCY 1"); + const componentProps = { ...rootProps, record: record.set("created_organization", "AGENCY 1") }; + const { getByLabelText } = mountedComponent(, rootInitialState); + + expect(getByLabelText("record_information.created_organization")).toHaveValue("AGENCY 1"); }); }); }); @@ -140,13 +108,11 @@ describe("", () => { }; beforeEach(() => { - ({ component } = setupMountedComponent(RecordOwner, props, initialState)); + mountedComponent(, initialState); }); it("should render RecordOwner and its fields", () => { - expect(component.find(RecordOwner)).to.have.lengthOf(1); - expect(component.find(FormSectionField)).to.have.lengthOf(15); - expect(component.find("input").first().prop("name")).to.be.equal("owned_by_text"); + expect(screen.getAllByTestId("form-section-field")).toHaveLength(12); }); }); @@ -186,13 +152,11 @@ describe("", () => { }; beforeEach(() => { - ({ component } = setupMountedComponent(RecordOwner, props, initialState)); + mountedComponent(, initialState); }); it("should render RecordOwner and its fields", () => { - expect(component.find(RecordOwner)).to.have.lengthOf(1); - expect(component.find(FormSectionField)).to.have.lengthOf(15); - expect(component.find("input").first().prop("name")).to.be.equal("owned_by_text"); + expect(screen.getAllByTestId("form-section-field")).toHaveLength(12); }); }); }); diff --git a/app/javascript/components/records/action-creators.js b/app/javascript/components/records/action-creators.js index 350d3dc341..f042ca3dd7 100644 --- a/app/javascript/components/records/action-creators.js +++ b/app/javascript/components/records/action-creators.js @@ -42,6 +42,7 @@ import { EXTERNAL_SYNC, OFFLINE_INCIDENT_FROM_CASE, CREATE_CASE_FROM_FAMILY_MEMBER, + FETCH_LINK_INCIDENT_TO_CASE_DATA, CREATE_CASE_FROM_FAMILY_DETAIL, DELETE_ALERT_FROM_RECORD, DELETE_ALERT_FROM_RECORD_SUCCESS @@ -421,6 +422,37 @@ export const createCaseFromFamilyMember = ({ familyId, familyMemberId }) => ({ } }); +export const fetchLinkIncidentToCaseData = payload => { + return { + type: `cases/${FETCH_LINK_INCIDENT_TO_CASE_DATA}`, + api: { + path: RECORD_PATH.cases, + params: payload + } + }; +}; + +export const linkIncidentToCase = ({ recordType, selectedIDs = [], caseID }) => { + return { + type: `${recordType}/LINK_INCIDENT_TO_CASE`, + api: { + path: `cases/${caseID}/incidents`, + method: METHODS.POST, + body: { data: { incident_ids: selectedIDs } }, + successCallback: { + action: ENQUEUE_SNACKBAR, + payload: { + messageKey: "incident.link_incident_to_case_success", + options: { + variant: "success", + key: generate.messageKey() + } + } + } + } + }; +}; + export const createCaseFromFamilyDetail = ({ caseId, familyDetailId }) => ({ type: `${RECORD_PATH.cases}/${CREATE_CASE_FROM_FAMILY_DETAIL}`, api: { diff --git a/app/javascript/components/records/action-creators.unit.test.js b/app/javascript/components/records/action-creators.unit.test.js index ea5e6249fb..09370652cc 100644 --- a/app/javascript/components/records/action-creators.unit.test.js +++ b/app/javascript/components/records/action-creators.unit.test.js @@ -3,7 +3,7 @@ import isObject from "lodash/isObject"; import { DB_COLLECTIONS_NAMES } from "../../db"; -import { METHODS, RECORD_PATH } from "../../config/constants"; +import { METHODS, RECORD_PATH } from "../../config"; import { ENQUEUE_SNACKBAR } from "../notifier"; import { CLEAR_DIALOG } from "../action-dialog"; import RecordFormActions from "../record-form/actions"; @@ -54,7 +54,9 @@ describe("records - Action Creators", () => { "setSelectedPotentialMatch", "setSelectedRecord", "unMatchCaseForTrace", - "deleteAlertFromRecord" + "deleteAlertFromRecord", + "linkIncidentToCase", + "fetchLinkIncidentToCaseData" ].forEach(property => { expect(creators).to.have.property(property); expect(creators[property]).to.be.a("function"); diff --git a/app/javascript/components/records/actions.js b/app/javascript/components/records/actions.js index 1403280a36..ab901ce8b4 100644 --- a/app/javascript/components/records/actions.js +++ b/app/javascript/components/records/actions.js @@ -94,6 +94,9 @@ export const CREATE_CASE_FROM_FAMILY_MEMBER_SUCCESS = "CREATE_CASE_FROM_FAMILY_M export const CREATE_CASE_FROM_FAMILY_MEMBER_STARTED = "CREATE_CASE_FROM_FAMILY_MEMBER_STARTED"; export const CREATE_CASE_FROM_FAMILY_MEMBER_FAILURE = "CREATE_CASE_FROM_FAMILY_MEMBER_FAILURE"; export const CREATE_CASE_FROM_FAMILY_MEMBER_FINISHED = "CREATE_CASE_FROM_FAMILY_MEMBER_FINISHED"; +export const FETCH_LINK_INCIDENT_TO_CASE_DATA = "FETCH_LINK_INCIDENT_TO_CASE_DATA"; +export const FETCH_LINK_INCIDENT_TO_CASE_DATA_SUCCESS = "FETCH_LINK_INCIDENT_TO_CASE_DATA_SUCCESS"; +export const FETCH_LINK_INCIDENT_TO_CASE_DATA_FINISHED = "FETCH_LINK_INCIDENT_TO_CASE_DATA_FINISHED"; export const CREATE_CASE_FROM_FAMILY_DETAIL = "CREATE_CASE_FROM_FAMILY_DETAIL"; export const CREATE_CASE_FROM_FAMILY_DETAIL_SUCCESS = "CREATE_CASE_FROM_FAMILY_DETAIL_SUCCESS"; export const CREATE_CASE_FROM_FAMILY_DETAIL_STARTED = "CREATE_CASE_FROM_FAMILY_DETAIL_STARTED"; diff --git a/app/javascript/components/records/actions.unit.test.js b/app/javascript/components/records/actions.unit.test.js index 26aa5cb005..37fd95f549 100644 --- a/app/javascript/components/records/actions.unit.test.js +++ b/app/javascript/components/records/actions.unit.test.js @@ -105,7 +105,10 @@ describe("records - Actions", () => { "DELETE_ALERT_FROM_RECORD_FAILURE", "DELETE_ALERT_FROM_RECORD_FINISHED", "DELETE_ALERT_FROM_RECORD_STARTED", - "DELETE_ALERT_FROM_RECORD_SUCCESS" + "DELETE_ALERT_FROM_RECORD_SUCCESS", + "FETCH_LINK_INCIDENT_TO_CASE_DATA", + "FETCH_LINK_INCIDENT_TO_CASE_DATA_SUCCESS", + "FETCH_LINK_INCIDENT_TO_CASE_DATA_FINISHED" ].forEach(property => { expect(cloneActions).to.have.property(property); expect(cloneActions[property]).to.be.a("string"); diff --git a/app/javascript/components/records/reducer.js b/app/javascript/components/records/reducer.js index d6c03eccb5..77d75607c0 100644 --- a/app/javascript/components/records/reducer.js +++ b/app/javascript/components/records/reducer.js @@ -69,6 +69,9 @@ import { CREATE_CASE_FROM_FAMILY_MEMBER_SUCCESS, CREATE_CASE_FROM_FAMILY_MEMBER_FAILURE, CREATE_CASE_FROM_FAMILY_MEMBER_FINISHED, + FETCH_LINK_INCIDENT_TO_CASE_DATA_SUCCESS, + FETCH_LINK_INCIDENT_TO_CASE_DATA, + FETCH_LINK_INCIDENT_TO_CASE_DATA_FINISHED, CREATE_CASE_FROM_FAMILY_DETAIL_STARTED, CREATE_CASE_FROM_FAMILY_DETAIL_SUCCESS, CREATE_CASE_FROM_FAMILY_DETAIL_FAILURE, @@ -397,6 +400,12 @@ export default namespace => case `${namespace}/${CREATE_CASE_FROM_FAMILY_DETAIL_FINISHED}`: { return state.setIn(["case_from_family", "loading"], false); } + case `${namespace}/${FETCH_LINK_INCIDENT_TO_CASE_DATA}`: + return state.set("loading", true); + case `${namespace}/${FETCH_LINK_INCIDENT_TO_CASE_DATA_SUCCESS}`: + return state.set("data", fromJS(payload.data)); + case `${namespace}/${FETCH_LINK_INCIDENT_TO_CASE_DATA_FINISHED}`: + return state.set("loading", false); default: return state; } diff --git a/app/javascript/components/records/selectors.js b/app/javascript/components/records/selectors.js index 2d66600c42..de7c80ef11 100644 --- a/app/javascript/components/records/selectors.js +++ b/app/javascript/components/records/selectors.js @@ -2,7 +2,7 @@ import { Map, List, fromJS } from "immutable"; -import { RECORD_PATH } from "../../config/constants"; +import { RECORD_PATH } from "../../config"; const fieldMapModule = (state, moduleID) => state @@ -69,6 +69,10 @@ export const getCaseIdForIncident = state => { return state.getIn(["records", "cases", "incidentFromCase", "incident_case_id"], false); }; +export const getCaseIdDisplayForIncident = state => { + return state.getIn(["records", "cases", "incidentFromCase", "case_id_display"], false); +}; + export const getFieldMap = (state, moduleID) => { const mapTo = fieldMapModule(state, moduleID).getIn(["field_map", "map_to"]); diff --git a/app/javascript/components/report/action-creators.unit.test.js b/app/javascript/components/report/action-creators.unit.test.js index a2896ffc31..8e723de8f2 100644 --- a/app/javascript/components/report/action-creators.unit.test.js +++ b/app/javascript/components/report/action-creators.unit.test.js @@ -4,7 +4,7 @@ import sinon from "sinon"; import configureStore from "redux-mock-store"; import { RECORD_PATH } from "../../config"; -import { stub } from "../../test"; +import { stub } from "../../test-utils"; import { ENQUEUE_SNACKBAR, generate } from "../notifier"; import * as actionCreators from "./action-creators"; diff --git a/app/javascript/components/report/components/exporter.jsx b/app/javascript/components/report/components/exporter.jsx index cb115825b8..d63cc54f17 100644 --- a/app/javascript/components/report/components/exporter.jsx +++ b/app/javascript/components/report/components/exporter.jsx @@ -10,7 +10,7 @@ import css from "./styles.css"; import { downloadFile, tableToCsv } from "./utils"; import { DEFAULT_FILE_NAME, NAME } from "./constants"; -const Exporter = ({ includesGraph }) => { +function Exporter({ includesGraph = false }) { const handleClickTableExporter = () => { const csvBlob = new Blob([tableToCsv("table tr")], { type: "text/csv" }); @@ -55,14 +55,10 @@ const Exporter = ({ includesGraph }) => { /> ); -}; +} Exporter.displayName = NAME; -Exporter.defaultProps = { - includesGraph: false -}; - Exporter.propTypes = { includesGraph: PropTypes.bool }; diff --git a/app/javascript/components/report/components/exporter.spec.js b/app/javascript/components/report/components/exporter.spec.js new file mode 100644 index 0000000000..fe82607497 --- /dev/null +++ b/app/javascript/components/report/components/exporter.spec.js @@ -0,0 +1,30 @@ +import { mountedComponent } from "test-utils"; + +import Exporter from "./exporter"; + +describe("", () => { + describe("when includesGraph is true", () => { + beforeEach(() => { + const props = { includesGraph: true }; + + mountedComponent(); + }); + + it("should render 2 component", () => { + expect(document.querySelector("#graph-exporter-button")).toBeInTheDocument(); + expect(document.querySelector("#report-data-button")).toBeInTheDocument(); + }); + }); + + describe("when includesGraph is false", () => { + beforeEach(() => { + const props = { includesGraph: false }; + + mountedComponent(); + }); + + it("should render 1 component", () => { + expect(document.querySelector("#report-data-button")).toBeInTheDocument(); + }); + }); +}); diff --git a/app/javascript/components/report/components/exporter.unit.test.js b/app/javascript/components/report/components/exporter.unit.test.js deleted file mode 100644 index d7d344676e..0000000000 --- a/app/javascript/components/report/components/exporter.unit.test.js +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../test"; -import ActionButton from "../../action-button"; - -import Exporter from "./exporter"; - -describe("", () => { - describe("when includesGraph is true", () => { - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(Exporter, { includesGraph: true })); - }); - - it("should render 2 component", () => { - expect(component.find(ActionButton)).to.have.lengthOf(2); - }); - - it("should accept valid props for component", () => { - const actionButtonProps = { ...component.find(ActionButton).at(0).props() }; - - ["icon", "type", "isTransparent", "rest", "outlined", "id"].forEach(property => { - expect(actionButtonProps).to.have.property(property); - delete actionButtonProps[property]; - }); - expect(actionButtonProps).to.be.empty; - }); - }); - - describe("when includesGraph is false", () => { - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(Exporter, { includesGraph: false })); - }); - - it("should render 1 component", () => { - expect(component.find(ActionButton)).to.have.lengthOf(1); - }); - - it("should accept valid props for component", () => { - const actionButtonProps = { ...component.find(ActionButton).props() }; - - ["icon", "type", "isTransparent", "rest", "outlined", "id"].forEach(property => { - expect(actionButtonProps).to.have.property(property); - delete actionButtonProps[property]; - }); - expect(actionButtonProps).to.be.empty; - }); - }); -}); diff --git a/app/javascript/components/report/constants.js b/app/javascript/components/report/constants.js index c3ada353e3..00101341b7 100644 --- a/app/javascript/components/report/constants.js +++ b/app/javascript/components/report/constants.js @@ -3,5 +3,6 @@ export const NAME = "Report"; export const DELETE_MODAL = "DeleteReportModal"; export const DATE_PATTERN = "(\\w{2}-)?\\w{3}-\\d{4}"; +export const AGE_RANGE_PATTERN = "\\d+ - \\d+"; export const TOTAL = "Total"; export const TOTAL_KEY = "_total"; diff --git a/app/javascript/components/report/constants.unit.test.js b/app/javascript/components/report/constants.unit.test.js index 1905b19c77..2fe3d74e73 100644 --- a/app/javascript/components/report/constants.unit.test.js +++ b/app/javascript/components/report/constants.unit.test.js @@ -7,7 +7,7 @@ describe(" - constants", () => { it("should have known properties", () => { expect(clone).to.be.an("object"); - ["DELETE_MODAL", "NAME", "DATE_PATTERN", "TOTAL", "TOTAL_KEY"].forEach(property => { + ["AGE_RANGE_PATTERN", "DELETE_MODAL", "NAME", "DATE_PATTERN", "TOTAL", "TOTAL_KEY"].forEach(property => { expect(clone).to.have.property(property); delete clone[property]; }); diff --git a/app/javascript/components/report/container.jsx b/app/javascript/components/report/container.jsx index 264072ec4c..b48a7d4088 100644 --- a/app/javascript/components/report/container.jsx +++ b/app/javascript/components/report/container.jsx @@ -3,11 +3,11 @@ import { useEffect } from "react"; import { useDispatch } from "react-redux"; import PropTypes from "prop-types"; -import { Paper, Typography } from "@material-ui/core"; +import { Paper, Typography } from "@mui/material"; import { push } from "connected-react-router"; import { useLocation, useParams } from "react-router-dom"; -import CreateIcon from "@material-ui/icons/Create"; -import DeleteIcon from "@material-ui/icons/Delete"; +import CreateIcon from "@mui/icons-material/Create"; +import DeleteIcon from "@mui/icons-material/Delete"; import { getAgeRanges } from "../application/selectors"; import { BarChart as BarChartGraphic, TableValues } from "../charts"; @@ -32,7 +32,7 @@ import { NAME, DELETE_MODAL } from "./constants"; import Exporter from "./components/exporter"; import css from "./styles.css"; -const Report = ({ mode }) => { +function Report({ mode }) { const { id } = useParams(); const i18n = useI18n(); const dispatch = useDispatch(); @@ -142,7 +142,7 @@ const Report = ({ mode }) => { ); -}; +} Report.displayName = NAME; diff --git a/app/javascript/components/report/container.unit.test.js b/app/javascript/components/report/container.spec.js similarity index 55% rename from app/javascript/components/report/container.unit.test.js rename to app/javascript/components/report/container.spec.js index d2f4d37567..cd30d94365 100644 --- a/app/javascript/components/report/container.unit.test.js +++ b/app/javascript/components/report/container.spec.js @@ -1,18 +1,11 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; +import { mountedComponent, screen } from "test-utils"; -import PageContainer, { PageContent, PageHeading } from "../page"; -import { setupMountedComponent } from "../../test"; -import { TableValues } from "../charts"; -import LoadingIndicator from "../loading-indicator"; - -import Exporter from "./components/exporter"; import Report from "./container"; describe("", () => { - let component; - const initialState = fromJS({ records: { reports: { @@ -52,34 +45,27 @@ describe("", () => { } }); - before(() => { - ({ component } = setupMountedComponent(Report, {}, initialState)); - }); - it("renders report component", () => { - expect(component.find(Report)).to.have.lengthOf(1); - }); - - it("renders PageContainer, PageHeading and PageContent", () => { - expect(component.find(PageContainer)).to.have.lengthOf(1); - expect(component.find(PageContent)).to.have.lengthOf(1); - expect(component.find(PageHeading)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(screen.getByText("Registration CP")).toBeInTheDocument(); }); it("renders TableValues", () => { - expect(component.find(TableValues)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(screen.getByText("a-2020")).toBeInTheDocument(); }); it("renders Exporter", () => { - expect(component.find(Exporter)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(document.querySelector("#graph-exporter-button")).toBeInTheDocument(); }); it("renders h4 with report's description", () => { - expect(component.find("h4").text()).to.be.equals("Case registrations over time"); + mountedComponent(, initialState); + expect(screen.getByText("Case registrations over time")).toBeInTheDocument(); }); describe("When data still loading", () => { - let loadingComponent; const loadingInitialState = fromJS({ records: { reports: { @@ -90,16 +76,14 @@ describe("", () => { } }); - before(() => { - loadingComponent = setupMountedComponent(Report, {}, loadingInitialState).component; - }); - it("renders report component", () => { - expect(loadingComponent.find(Report)).to.have.lengthOf(1); + mountedComponent(, loadingInitialState); + expect(screen.getByTestId("page-heading")).toBeInTheDocument(); }); + it("renders LoadingIndicator", () => { - expect(loadingComponent.find(LoadingIndicator)).to.have.lengthOf(1); - expect(loadingComponent.find(TableValues)).to.have.lengthOf(0); + mountedComponent(, loadingInitialState); + expect(screen.getByRole("progressbar")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/report/utils/build-column-paths.js b/app/javascript/components/report/utils/build-column-paths.js index 52978be65a..ad982b5d8f 100644 --- a/app/javascript/components/report/utils/build-column-paths.js +++ b/app/javascript/components/report/utils/build-column-paths.js @@ -2,18 +2,20 @@ export default (columns, i18n) => { const hasObject = columns.some(column => typeof column === "object"); + const labelTotal = i18n.t("report.total"); if (hasObject) { const [columns1, columns2] = columns.map(column => - column.items.filter(elem => !["_total", i18n.t("report.total")].includes(elem)) + column.items.filter(elem => !["_total", labelTotal].includes(elem)) ); - return columns1 - .flatMap(column1 => columns2.map(column2 => `${column1}.${column2}`).concat(`${column1}`)) - .map(column => `${column}.${i18n.t("report.total")}`); + return columns1.flatMap(column1 => [ + ...columns2.map(column2 => [`${column1}`, `${column2}`, labelTotal]), + [column1, labelTotal] + ]); } return columns - .filter(column => !["_total", i18n.t("report.total")].includes(column)) - .map(column => `${column}.${i18n.t("report.total")}`); + .filter(column => !["_total", labelTotal].includes(column)) + .map(column => [`${column}`, `${labelTotal}`]); }; diff --git a/app/javascript/components/report/utils/build-column-paths.unit.test.js b/app/javascript/components/report/utils/build-column-paths.unit.test.js index 4b66e8a922..e7f5507712 100644 --- a/app/javascript/components/report/utils/build-column-paths.unit.test.js +++ b/app/javascript/components/report/utils/build-column-paths.unit.test.js @@ -9,7 +9,10 @@ describe(" - utils", () => { context("when the columns are an array of strings", () => { it("should return the array of paths for the columns", () => { const columns = ["column1", "column2"]; - const expected = ["column1.total", "column2.total"]; + const expected = [ + ["column1", "total"], + ["column2", "total"] + ]; expect(buildColumnPaths(columns, i18n)).to.deep.equals(expected); }); @@ -26,12 +29,12 @@ describe(" - utils", () => { } ]; const expected = [ - "column1.column3.total", - "column1.column4.total", - "column1.total", - "column2.column3.total", - "column2.column4.total", - "column2.total" + ["column1", "column3", "total"], + ["column1", "column4", "total"], + ["column1", "total"], + ["column2", "column3", "total"], + ["column2", "column4", "total"], + ["column2", "total"] ]; expect(buildColumnPaths(columns, i18n)).to.deep.equals(expected); diff --git a/app/javascript/components/report/utils/build-data-set.js b/app/javascript/components/report/utils/build-data-set.js index d92b6013d7..fe1cc6fe26 100644 --- a/app/javascript/components/report/utils/build-data-set.js +++ b/app/javascript/components/report/utils/build-data-set.js @@ -1,6 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import isEmpty from "lodash/isEmpty"; +import first from "lodash/first"; import { REPORT_FIELD_TYPES } from "../../reports-form/constants"; @@ -8,23 +9,25 @@ import formattedDate from "./formatted-date"; import getColors from "./get-colors"; import getColumnData from "./get-column-data"; import getTranslatedKey from "./get-translated-key"; -import sortByDate from "./sort-by-date"; +import sortDataKeys from "./sort-data-keys"; -export default (columns, data, i18n, fields, qtyColumns, qtyRows, { agencies, locations }) => { +export default (columns, data, i18n, fields, qtyRows, { agencies, ageRanges, locations }) => { const totalLabel = i18n.t("report.total"); const dataResults = []; const field = fields.length > 1 ? fields.find(reportField => reportField.position.type === REPORT_FIELD_TYPES.vertical) - : fields.shift(); + : first(fields); + + const optionLabels = field.option_labels?.[i18n.locale]?.map(option => option.display_text); if (!isEmpty(columns)) { - sortByDate(columns).forEach((column, index) => { + sortDataKeys(columns, { ageRanges, optionLabels }).forEach((column, index) => { const label = getTranslatedKey(column, field, { agencies, i18n, locations }); dataResults.push({ label: formattedDate(label, i18n), - data: getColumnData(column, data, i18n, qtyColumns, qtyRows), + data: getColumnData(column, data, i18n, qtyRows, fields, { ageRanges }), backgroundColor: getColors(index) }); }); diff --git a/app/javascript/components/report/utils/build-graph-data.js b/app/javascript/components/report/utils/build-graph-data.js index 8668a90f33..10974a7b72 100644 --- a/app/javascript/components/report/utils/build-graph-data.js +++ b/app/javascript/components/report/utils/build-graph-data.js @@ -7,7 +7,7 @@ import getColumns from "./get-columns"; import getLabels from "./get-labels"; import translateReportData from "./translate-report-data"; -export default (report, i18n, { agencies, locations }) => { +export default (report, i18n, { agencies, ageRanges, locations }) => { const reportData = report.toJS(); if (!reportData.report_data) { @@ -25,11 +25,9 @@ export default (report, i18n, { agencies, locations }) => { const graphData = { description: translatedReport.description ? translatedReport.description[i18n.locale] : "", data: { - labels: getLabels(columns, translatedReport.report_data, i18n, fields, qtyColumns, qtyRows, { - agencies, - locations - }), - datasets: buildDataSet(columns, translatedReport.report_data, i18n, fields, qtyColumns, qtyRows, { + labels: getLabels(translatedReport.report_data, i18n, fields, { ageRanges, agencies, locations }), + datasets: buildDataSet(columns, translatedReport.report_data, i18n, fields, qtyRows, { + ageRanges, agencies, locations }) diff --git a/app/javascript/components/report/utils/build-graph-data.unit.test.js b/app/javascript/components/report/utils/build-graph-data.unit.test.js index 2f1e54d75f..2c78d35fad 100644 --- a/app/javascript/components/report/utils/build-graph-data.unit.test.js +++ b/app/javascript/components/report/utils/build-graph-data.unit.test.js @@ -87,7 +87,7 @@ describe(" - utils", () => { } }; - expect(buildGraphData(report, i18n, { agencies })).to.deep.equal(expected); + expect(buildGraphData(report, i18n, { agencies, ageRanges: [] })).to.deep.equal(expected); }); }); @@ -228,22 +228,22 @@ describe(" - utils", () => { const expected = { description: "Protection Concerns by Risk Level", data: { - labels: ["Abandonment", "Neglect", "Orphan", "Rape", "Separated", "Unaccompanied"], + labels: ["Rape", "Neglect", "Abandonment", "Unaccompanied", "Separated", "Orphan"], datasets: [ { backgroundColor: "#e0dfd6", - data: [2, 1, 1, 0, 1, 1], - label: "Low" + data: [1, 0, 0, 0, 0, 0], + label: "High" }, { backgroundColor: "#595951", - data: [0, 0, 0, 1, 0, 0], - label: "High" + data: [0, 1, 2, 1, 1, 1], + label: "Low" } ] } }; - expect(buildGraphData(report, i18n, { agencies: [] })).to.deep.equal(expected); + expect(buildGraphData(report, i18n, { agencies: [], ageRanges: [] })).to.deep.equal(expected); }); }); diff --git a/app/javascript/components/report/utils/contains-columns.js b/app/javascript/components/report/utils/contains-columns.js deleted file mode 100644 index 10eb49876b..0000000000 --- a/app/javascript/components/report/utils/contains-columns.js +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -export default (columns, data, i18n) => { - const totalLabel = i18n.t("report.total"); - const keys = Object.keys(data).filter(key => key !== totalLabel); - - return columns.some(column => keys.includes(column)); -}; diff --git a/app/javascript/components/report/utils/contains-columns.unit.test.js b/app/javascript/components/report/utils/contains-columns.unit.test.js deleted file mode 100644 index 44c82db4aa..0000000000 --- a/app/javascript/components/report/utils/contains-columns.unit.test.js +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -describe(" - utils", () => { - describe("containsColumns", () => { - it.skip("should return true if the data contains the columns ", () => {}); - }); -}); diff --git a/app/javascript/components/report/utils/get-column-data.js b/app/javascript/components/report/utils/get-column-data.js index 0d15e3edda..0594292046 100644 --- a/app/javascript/components/report/utils/get-column-data.js +++ b/app/javascript/components/report/utils/get-column-data.js @@ -3,13 +3,17 @@ import uniq from "lodash/uniq"; import get from "lodash/get"; -import sortByDate from "./sort-by-date"; +import { REPORT_FIELD_TYPES } from "../../reports-form/constants"; -const getColumnData = (column, data, i18n, qtyColumns, qtyRows) => { +import sortDataKeys from "./sort-data-keys"; + +export default (column, data, i18n, qtyRows, fields, { ageRanges }) => { const totalLabel = i18n.t("report.total"); - const keys = sortByDate(Object.keys(data)); + const field = fields.find(reportField => reportField.position.type === REPORT_FIELD_TYPES.horizontal); + const optionLabels = field?.option_labels?.[i18n.locale]?.map(option => option.display_text) || []; + const keys = sortDataKeys(Object.keys(data), { ageRanges, optionLabels }); - if (qtyRows >= 2 && qtyColumns > 0) { + if (qtyRows >= 2) { const firstRow = keys; const secondRow = uniq(firstRow.flatMap(row => Object.keys(data[row]).filter(key => key !== totalLabel))); @@ -31,13 +35,7 @@ const getColumnData = (column, data, i18n, qtyColumns, qtyRows) => { return data[key][column][totalLabel]; } - if (data[key][column]) { - return getColumnData(column, data[key], i18n, qtyColumns, qtyRows); - } - return 0; }) .flat(); }; - -export default (column, data, i18n, qtyColumns, qtyRows) => getColumnData(column, data, i18n, qtyColumns, qtyRows); diff --git a/app/javascript/components/report/utils/get-column-data.unit.test.js b/app/javascript/components/report/utils/get-column-data.unit.test.js index 4bc7bfc4a3..ed0f412569 100644 --- a/app/javascript/components/report/utils/get-column-data.unit.test.js +++ b/app/javascript/components/report/utils/get-column-data.unit.test.js @@ -11,10 +11,9 @@ describe(" - utils", () => { Row2: { Column1: { Total: 5 }, Column2: { Total: 1 }, Total: 6 } }; const i18n = { t: key => (key === "report.total" ? "Total" : key) }; - const qtyColumns = 1; const qtyRows = 1; - expect(getColumnData(column, data, i18n, qtyColumns, qtyRows)).to.deep.equals([5, 5]); + expect(getColumnData(column, data, i18n, qtyRows, [], { ageRanges: [] })).to.deep.equals([5, 5]); }); it("returns 0 when the column is not present", () => { @@ -24,10 +23,21 @@ describe(" - utils", () => { Row2: { Column1: { Total: 5 }, Column2: { Total: 1 }, Total: 6 } }; const i18n = { t: key => (key === "report.total" ? "Total" : key) }; - const qtyColumns = 1; const qtyRows = 1; - expect(getColumnData(column, data, i18n, qtyColumns, qtyRows)).to.deep.equals([0, 5]); + expect(getColumnData(column, data, i18n, qtyRows, [], { ageRanges: [] })).to.deep.equals([0, 5]); + }); + + it("returns 0 when the column is 0", () => { + const column = "Column2"; + const data = { + Row1: { Column2: { Total: 0 }, Total: 0 }, + Row2: { Column1: { Total: 5 }, Column2: { Total: 0 }, Total: 6 } + }; + const i18n = { t: key => (key === "report.total" ? "Total" : key) }; + const qtyRows = 1; + + expect(getColumnData(column, data, i18n, qtyRows, [], { ageRanges: [] })).to.deep.equals([0, 0]); }); it("returns data for two rows", () => { @@ -72,10 +82,9 @@ describe(" - utils", () => { }; const i18n = { t: key => (key === "report.total" ? "Total" : key) }; - const qtyColumns = 1; const qtyRows = 2; - expect(getColumnData(column, data, i18n, qtyColumns, qtyRows)).to.deep.equals([0, 1, 1, 0]); + expect(getColumnData(column, data, i18n, qtyRows, [], { ageRanges: [] })).to.deep.equals([0, 1, 1, 0]); }); }); }); diff --git a/app/javascript/components/report/utils/get-labels.js b/app/javascript/components/report/utils/get-labels.js index ed4f4a2004..add11bc747 100644 --- a/app/javascript/components/report/utils/get-labels.js +++ b/app/javascript/components/report/utils/get-labels.js @@ -1,50 +1,15 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import uniq from "lodash/uniq"; +import { REPORT_FIELD_TYPES } from "../../reports-form/constants"; -import containsColumns from "./contains-columns"; import formattedDate from "./formatted-date"; import getTranslatedKey from "./get-translated-key"; -import sortByDate from "./sort-by-date"; +import sortDataKeys from "./sort-data-keys"; -const getLabels = (columns, data, i18n, fields, qtyColumns, qtyRows, { agencies, locations }) => { - const totalLabel = i18n.t("report.total"); - const currentLabels = []; - const field = fields.shift(); - const keys = sortByDate(Object.keys(data)); +export default (data, i18n, fields, { agencies, ageRanges, locations }) => { + const field = fields.find(reportField => reportField.position.type === REPORT_FIELD_TYPES.horizontal); + const optionLabels = field?.option_labels?.[i18n.locale]?.map(option => option.display_text); + const keys = sortDataKeys(Object.keys(data), { ageRanges, optionLabels }); - if (qtyRows >= 2 && qtyColumns > 0) { - return keys.map(key => - getTranslatedKey(key, field, { - agencies, - i18n, - locations - }) - ); - } - - if (qtyColumns > 0) { - keys.forEach(key => { - if (containsColumns(columns, data[key], i18n)) { - currentLabels.push(keys.map(current => formattedDate(current, i18n)).filter(label => label !== totalLabel)); - } else { - currentLabels.concat(getLabels(columns, data[key], i18n, fields, qtyColumns, qtyRows, { agencies, locations })); - } - }); - } else { - currentLabels.push(keys); - } - - return uniq(currentLabels.flat()).map(key => { - const translation = getTranslatedKey(key, field, { - agencies, - i18n, - locations - }); - - return translation; - }); + return keys.map(key => formattedDate(getTranslatedKey(key, field, { agencies, i18n, locations }), i18n)); }; - -export default (columns, data, i18n, fields, qtyColumns, qtyRows, { agencies, locations }) => - getLabels(columns, data, i18n, fields, qtyColumns, qtyRows, { agencies, locations }); diff --git a/app/javascript/components/report/utils/get-labels.unit.test.js b/app/javascript/components/report/utils/get-labels.unit.test.js index c68a201284..1cd66940d2 100644 --- a/app/javascript/components/report/utils/get-labels.unit.test.js +++ b/app/javascript/components/report/utils/get-labels.unit.test.js @@ -6,47 +6,38 @@ import getLabels from "./get-labels"; describe(" - utils", () => { describe("getLabels", () => { - it("returns the labels translated when some columns all columns are present", () => { - const columns = ["Column1", "Column2"]; + it("returns the labels translated when all columns are present", () => { const data = { Row1: { Column1: { Total: 5 }, Column2: { Total: 2 }, Total: 7 }, Row2: { Column1: { Total: 5 }, Column2: { Total: 1 }, Total: 6 } }; const i18n = { t: key => (key === "report.total" ? "Total" : key) }; - const qtyColumns = 1; - const qtyRows = 1; const fields = []; - expect(getLabels(columns, data, i18n, fields, qtyColumns, qtyRows, {})).to.deep.equal(["Row1", "Row2"]); + expect(getLabels(data, i18n, fields, {})).to.deep.equal(["Row1", "Row2"]); }); it("returns the labels translated when some columns are not present", () => { - const columns = ["Column1", "Column2"]; const data = { Row1: { Column1: { Total: 5 }, Total: 5 }, Row2: { Column2: { Total: 5 }, Total: 5 } }; const i18n = { t: key => (key === "report.total" ? "Total" : key) }; - const qtyColumns = 1; - const qtyRows = 1; const fields = []; - expect(getLabels(columns, data, i18n, fields, qtyColumns, qtyRows, {})).to.deep.equal(["Row1", "Row2"]); + expect(getLabels(data, i18n, fields, {})).to.deep.equal(["Row1", "Row2"]); }); it("returns the labels for the agencies even when there are more than 2 rows defined", () => { - const columns = ["Column1", "Column2"]; const data = { agency1: { Row1: { Column1: { Total: 5 } }, Total: 5 }, agency2: { Row2: { Column2: { Total: 5 } }, Total: 5 } }; const i18n = { t: key => (key === "report.total" ? "Total" : key) }; - const qtyColumns = 1; - const qtyRows = 2; - const fields = [{ option_strings_source: STRING_SOURCES_TYPES.AGENCY }]; + const fields = [{ option_strings_source: STRING_SOURCES_TYPES.AGENCY, position: { type: "horizontal" } }]; expect( - getLabels(columns, data, i18n, fields, qtyColumns, qtyRows, { + getLabels(data, i18n, fields, { agencies: [ { id: "agency1", display_text: "Agency 1" }, { id: "agency2", display_text: "Agency 2" } diff --git a/app/javascript/components/report/utils/get-rows-table-data.js b/app/javascript/components/report/utils/get-rows-table-data.js index 504c317931..45ecb2f6d3 100644 --- a/app/javascript/components/report/utils/get-rows-table-data.js +++ b/app/javascript/components/report/utils/get-rows-table-data.js @@ -38,17 +38,19 @@ export default (data, columns, ageRanges, i18n) => { if (qtyOfParentKeys >= 2) { accum.push([key, true, total]); - const result = sortTableData({ + const sortedTable = sortTableData({ field: last(rows), data: Object.keys(value), ageRanges, groupAges: data.group_ages, incompleteDataLabel, locale: i18n.locale - }) + }); + + const result = sortedTable .filter(val => !["_total", i18n.t("report.total")].includes(val)) .map(rowDisplayName => { - const values = columnPaths.map(child => get(value[rowDisplayName], child, 0)); + const values = columnPaths.map(path => get(value[rowDisplayName], path, 0)); const rowTotal = isNil(value[rowDisplayName]._total) ? value[rowDisplayName][i18n.t("report.total")] : value[rowDisplayName]._total; diff --git a/app/javascript/components/report/utils/get-rows-table-data.unit.test.js b/app/javascript/components/report/utils/get-rows-table-data.unit.test.js index f9d27ce84e..c895ae8063 100644 --- a/app/javascript/components/report/utils/get-rows-table-data.unit.test.js +++ b/app/javascript/components/report/utils/get-rows-table-data.unit.test.js @@ -385,4 +385,60 @@ describe("report/utils/get-rows-table-data", () => { ["gbv_survivor", false, 1, 1, 2, 0, 0, 0, 2] ]); }); + + it("return the rows for a display_text with dots", () => { + const i18n = { + t: value => (value === "report.total" ? "_total" : value), + locale: "en" + }; + const data = { + fields: [ + { + name: "risk_level", + display_name: { + en: "Risk Level" + }, + position: { + type: "horizontal", + order: 0 + }, + option_labels: { + en: [ + { id: "high", display_text: "high" }, + { id: "medium", display_text: "medium" }, + { id: "low", display_text: "low" } + ] + } + }, + { + name: "protection_concerns", + display_name: { + en: "Protection Concerns" + }, + position: { + type: "vertical", + order: 1 + }, + option_labels: { + en: [ + { id: "abandoment", display_text: "abandoment" }, + { id: "neglect", display_text: "neglect" }, + { id: "security.e.g_safe_shelter", display_text: "security.e.g_safe_shelter" } + ] + } + } + ], + report_data: { + high: { + abandoment: { _total: 1 }, + neglect: { _total: 1 }, + "security.e.g_safe_shelter": { _total: 2 }, + _total: 4 + } + } + }; + const columns = ["abandoment", "neglect", "security.e.g_safe_shelter", "_total"]; + + expect(getRowsTableData(data, columns, [], i18n)).to.deep.equal([["high", false, 1, 1, 2, 4]]); + }); }); diff --git a/app/javascript/components/report/utils/sort-by-age.js b/app/javascript/components/report/utils/sort-by-age.js new file mode 100644 index 0000000000..b900e9404d --- /dev/null +++ b/app/javascript/components/report/utils/sort-by-age.js @@ -0,0 +1,19 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import toInteger from "lodash/toInteger"; + +export default (data, sortByFn) => + data.sort((elem1, elem2) => { + const value1 = sortByFn ? sortByFn(elem1) : elem1; + const value2 = sortByFn ? sortByFn(elem2) : elem2; + + if (value1.match(/[0-9]+/)) { + if (value2.match(/[0-9]+/)) { + return toInteger(value1) - toInteger(value2); + } + + return -1; + } + + return 1; + }); diff --git a/app/javascript/components/report/utils/sort-by-age.unit.test.js b/app/javascript/components/report/utils/sort-by-age.unit.test.js new file mode 100644 index 0000000000..4d385d4107 --- /dev/null +++ b/app/javascript/components/report/utils/sort-by-age.unit.test.js @@ -0,0 +1,38 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import first from "lodash/first"; + +import sortByAge from "./sort-by-age"; + +describe("report/utils/sort-by-age.js", () => { + it("returns ordered array for an array of strings", () => { + const data = ["8", "5", "10"]; + const expected = ["5", "8", "10"]; + + expect(sortByAge(data)).to.deep.equals(expected); + }); + + it("returns ordered array for an array of strings", () => { + const data = ["Incomplete Data", "8", "5", "10"]; + const expected = ["5", "8", "10", "Incomplete Data"]; + + expect(sortByAge(data)).to.deep.equals(expected); + }); + + it("returns ordered array for an array of arrays", () => { + const data = [ + ["Incomplete Data", { Total: 1 }], + ["8", { Total: 8 }], + ["10", { Total: 10 }], + ["5", { Total: 5 }] + ]; + const expected = [ + ["5", { Total: 5 }], + ["8", { Total: 8 }], + ["10", { Total: 10 }], + ["Incomplete Data", { Total: 1 }] + ]; + + expect(sortByAge(data, elem => first(elem))).to.deep.equals(expected); + }); +}); diff --git a/app/javascript/components/report/utils/sort-data-keys.js b/app/javascript/components/report/utils/sort-data-keys.js new file mode 100644 index 0000000000..9c0a5700db --- /dev/null +++ b/app/javascript/components/report/utils/sort-data-keys.js @@ -0,0 +1,27 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { sortWithSortedArray } from "../../insights-sub-report/utils"; +import { AGE_RANGE_PATTERN, DATE_PATTERN } from "../constants"; + +import sortByDate from "./sort-by-date"; +import sortByAge from "./sort-by-age"; + +export default (keys, { ageRanges, optionLabels }) => { + if (keys.some(key => key.match(new RegExp(DATE_PATTERN)))) { + return sortByDate(keys); + } + + if (keys.some(key => key.match(new RegExp(AGE_RANGE_PATTERN)))) { + return sortWithSortedArray(keys, ageRanges); + } + + if (optionLabels?.length) { + return sortWithSortedArray(keys, optionLabels); + } + + if (keys.some(key => key.match(/[0-9]+/))) { + return sortByAge(keys); + } + + return keys; +}; diff --git a/app/javascript/components/report/utils/sort-table-data.js b/app/javascript/components/report/utils/sort-table-data.js index 78f7b140c9..f7c3afc9bc 100644 --- a/app/javascript/components/report/utils/sort-table-data.js +++ b/app/javascript/components/report/utils/sort-table-data.js @@ -1,12 +1,18 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { sortWithSortedArray } from "../../insights-sub-report/utils"; +import { DATE_PATTERN } from "../constants"; +import sortByAge from "./sort-by-age"; import sortByDate from "./sort-by-date"; export default ({ field, data, sortByFn, ageRanges, groupAges, incompleteDataLabel, locale }) => { - if (field.name.startsWith("age") && groupAges) { - return sortWithSortedArray(data, ageRanges, sortByFn, incompleteDataLabel); + if (field.name.startsWith("age")) { + if (groupAges) { + return sortWithSortedArray(data, ageRanges, sortByFn, incompleteDataLabel); + } + + return sortByAge(data, sortByFn); } if (field.option_labels) { return sortWithSortedArray( @@ -17,5 +23,9 @@ export default ({ field, data, sortByFn, ageRanges, groupAges, incompleteDataLab ); } - return sortByDate(sortWithSortedArray(data, data, sortByFn, incompleteDataLabel), true); + if (data.some(elem => (sortByFn ? sortByFn(elem) : elem).match(new RegExp(DATE_PATTERN)))) { + return sortByDate(sortWithSortedArray(data, data, sortByFn, incompleteDataLabel), true); + } + + return sortWithSortedArray(data, data, sortByFn, incompleteDataLabel); }; diff --git a/app/javascript/components/reports-form/action-creators.unit.test.js b/app/javascript/components/reports-form/action-creators.unit.test.js index cd3b38ef08..b5ca0a14bd 100644 --- a/app/javascript/components/reports-form/action-creators.unit.test.js +++ b/app/javascript/components/reports-form/action-creators.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub } from "../../test"; +import { stub } from "../../test-utils"; import { MODULES, RECORD_PATH, SAVE_METHODS, METHODS } from "../../config"; import { ENQUEUE_SNACKBAR, generate } from "../notifier"; diff --git a/app/javascript/components/reports-form/components/filter-applied/component.jsx b/app/javascript/components/reports-form/components/filter-applied/component.jsx index e4c3f64d19..89927a148a 100644 --- a/app/javascript/components/reports-form/components/filter-applied/component.jsx +++ b/app/javascript/components/reports-form/components/filter-applied/component.jsx @@ -1,10 +1,10 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { IconButton } from "@material-ui/core"; -import DeleteIcon from "@material-ui/icons/Delete"; -import KeyboardArrowRight from "@material-ui/icons/KeyboardArrowRight"; -import KeyboardArrowLeft from "@material-ui/icons/KeyboardArrowLeft"; +import { IconButton } from "@mui/material"; +import DeleteIcon from "@mui/icons-material/Delete"; +import KeyboardArrowRight from "@mui/icons-material/KeyboardArrowRight"; +import KeyboardArrowLeft from "@mui/icons-material/KeyboardArrowLeft"; import { useI18n } from "../../../i18n"; import { getFieldByName, getOptions } from "../../../record-form/selectors"; @@ -16,10 +16,10 @@ import { CONSTRAINTS } from "../../constants"; import { LOGICAL_OPERATORS } from "../../../../libs/expressions/constants"; import { NAME } from "./constants"; -import { getConstraintLabel } from "./utils"; +import { getConstraintLabel, getFieldNameForAttribute } from "./utils"; import css from "./styles.css"; -const Component = ({ +function Component({ filter, handleClickOpen, handleClickEdit, @@ -27,12 +27,13 @@ const Component = ({ constraints = CONSTRAINTS, deleteDisabled, showAndLabel = false -}) => { +}) { const i18n = useI18n(); const { isRTL } = useThemeHelper(); const [index, { data }] = filter; const { attribute, value } = data; - const field = useMemoizedSelector(state => getFieldByName(state, attribute)); + + const field = useMemoizedSelector(state => getFieldByName(state, getFieldNameForAttribute(attribute))); const allLookups = useMemoizedSelector(state => getOptions(state)); const location = useOptions({ @@ -91,16 +92,18 @@ const Component = ({ )}
- + - {renderIcon} + + {renderIcon} +
{conditionType === LOGICAL_OPERATORS.OR &&

{conditionName}

} ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/reports-form/components/filter-applied/utils.js b/app/javascript/components/reports-form/components/filter-applied/utils.js index 5a19f1cebd..deaa51cbd9 100644 --- a/app/javascript/components/reports-form/components/filter-applied/utils.js +++ b/app/javascript/components/reports-form/components/filter-applied/utils.js @@ -23,3 +23,6 @@ export const getConstraintLabel = (data, field, constraints, i18n) => { return Array.isArray(value) ? "" : i18n.t(constraints.default[constraint]); }; + +export const getFieldNameForAttribute = attribute => + attribute?.startsWith("loc:") ? attribute.replace("loc:", "").replace(/[0-5]/, "") : attribute; diff --git a/app/javascript/components/reports-form/components/filters-dialog/component.jsx b/app/javascript/components/reports-form/components/filters-dialog/component.jsx index 5303b5b172..dbfafef172 100644 --- a/app/javascript/components/reports-form/components/filters-dialog/component.jsx +++ b/app/javascript/components/reports-form/components/filters-dialog/component.jsx @@ -11,13 +11,14 @@ import { RADIO_FIELD, SELECT_FIELD, whichFormMode } from "../../../form"; import FormSection from "../../../form/components/form-section"; import { useI18n } from "../../../i18n"; import { NOT_NULL } from "../../constants"; +import { getFieldNameForAttribute } from "../filter-applied/utils"; import { ATTRIBUTE, CONSTRAINT, NAME, VALUE, FORM_ID } from "./constants"; import form, { validationSchema } from "./form"; import { getFilterConstraint, getFilterValue, isNotNullConstraintOrTrue } from "./utils"; import css from "./styles.css"; -const Component = ({ fields, open, setOpen, selectedIndex, setSelectedIndex, indexes, onSuccess }) => { +function Component({ fields, open, setOpen, selectedIndex, setSelectedIndex, indexes, onSuccess }) { const formMode = whichFormMode("edit"); const i18n = useI18n(); @@ -65,12 +66,13 @@ const Component = ({ fields, open, setOpen, selectedIndex, setSelectedIndex, ind useEffect(() => { if (selectedIndex !== null) { - const { type } = fields.find(field => field.id === selectedReportFilter.attribute); + const selectedFieldName = getFieldNameForAttribute(selectedReportFilter.attribute); + const selectedField = fields.find(field => field.id === selectedFieldName); reset({ ...selectedReportFilter, - [CONSTRAINT]: getFilterConstraint(selectedReportFilter, type), - [VALUE]: getFilterValue(selectedReportFilter, type) + [CONSTRAINT]: getFilterConstraint(selectedReportFilter, selectedField?.type), + [VALUE]: getFilterValue(selectedReportFilter, selectedField?.type) }); } if (selectedIndex === null && open) { @@ -121,7 +123,7 @@ const Component = ({ fields, open, setOpen, selectedIndex, setSelectedIndex, ind ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/reports-form/components/filters-dialog/component.unit.test.js b/app/javascript/components/reports-form/components/filters-dialog/component.spec.js similarity index 71% rename from app/javascript/components/reports-form/components/filters-dialog/component.unit.test.js rename to app/javascript/components/reports-form/components/filters-dialog/component.spec.js index 2e7705513e..2d78de5c57 100644 --- a/app/javascript/components/reports-form/components/filters-dialog/component.unit.test.js +++ b/app/javascript/components/reports-form/components/filters-dialog/component.spec.js @@ -2,18 +2,13 @@ import { fromJS, OrderedMap } from "immutable"; -import ActionDialog from "../../../action-dialog"; -import FormSection from "../../../form/components/form-section"; -import FormSectionField from "../../../form/components/form-section-field"; -import { setupMountedComponent } from "../../../../test"; import { ACTIONS } from "../../../permissions"; import { FormSectionRecord, FieldRecord } from "../../../record-form/records"; +import { mountedComponent, screen } from "../../../../test-utils"; import ReportFiltersDialog from "./component"; describe(" - Component", () => { - let component; - const forms = { formSections: OrderedMap({ 1: FormSectionRecord({ @@ -84,23 +79,18 @@ describe(" - Component", () => { }); beforeEach(() => { - ({ component } = setupMountedComponent(ReportFiltersDialog, props, initialState)); + mountedComponent(, initialState); }); it("should render ", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(1); - }); - - it("should render ", () => { - expect(component.find(FormSection)).to.have.lengthOf(1); + expect(screen.getByRole("dialog")).toBeInTheDocument(); }); it("should render ", () => { - expect(component.find(FormSectionField)).to.have.lengthOf(3); + expect(screen.getAllByTestId("form-section-field")).toHaveLength(3); }); describe("should render SelectField in ", () => { - let testComponent; const options = [ { id: "test_1", @@ -141,20 +131,12 @@ describe(" - Component", () => { }; beforeEach(() => { - ({ component: testComponent } = setupMountedComponent(ReportFiltersDialog, newProps, initialState)); + mountedComponent(, initialState); }); describe(" - SelectField", () => { - it("renders selectField with options", () => { - const valueFieldProps = testComponent.find(FormSectionField).at(2).props(); - const optionsEn = options.map(option => ({ - id: option.id, - display_text: option.display_text[window.I18n.locale] - })); - - expect(valueFieldProps.field.option_strings_text).to.deep.equal(optionsEn); - expect(valueFieldProps.field.option_strings_text).to.have.lengthOf(2); - }); + // No longer have a good way to check select options + it.todo("renders selectField with options"); }); }); }); diff --git a/app/javascript/components/reports-form/components/filters-list/component.jsx b/app/javascript/components/reports-form/components/filters-list/component.jsx index e7844084f1..d9e61210dd 100644 --- a/app/javascript/components/reports-form/components/filters-list/component.jsx +++ b/app/javascript/components/reports-form/components/filters-list/component.jsx @@ -10,7 +10,7 @@ import FilterApplied from "../filter-applied"; import { NAME } from "./constants"; -const Component = ({ +function Component({ constraints, handleOpenModal, handleEdit, @@ -18,7 +18,7 @@ const Component = ({ indexes, isConditionsList = false, showEmptyMessage = true -}) => { +}) { const i18n = useI18n(); const handleClickOpen = useCallback((index, filter) => () => handleOpenModal(index, filter), []); @@ -42,7 +42,7 @@ const Component = ({ showAndLabel={hasNestedConditions && index === indexes.length - 1} /> )); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/reports-form/components/filters/component.jsx b/app/javascript/components/reports-form/components/filters/component.jsx index 44b54f6b66..3130495ea7 100644 --- a/app/javascript/components/reports-form/components/filters/component.jsx +++ b/app/javascript/components/reports-form/components/filters/component.jsx @@ -2,8 +2,8 @@ import { useEffect, useState } from "react"; import PropTypes from "prop-types"; -import { IconButton, Typography } from "@material-ui/core"; -import AddIcon from "@material-ui/icons/Add"; +import { IconButton, Typography } from "@mui/material"; +import AddIcon from "@mui/icons-material/Add"; import { useI18n } from "../../../i18n"; import FiltersDialog from "../filters-dialog"; @@ -18,7 +18,7 @@ import { NAME } from "./constants"; import css from "./styles.css"; import { onFilterDialogSuccess } from "./utils"; -const Container = ({ +function Container({ indexes, setIndexes, allRecordForms, @@ -28,7 +28,7 @@ const Container = ({ formMode, selectedRecordType, selectedModule -}) => { +}) { const i18n = useI18n(); const matchableRecordType = MATCH_REPORTABLE_TYPES[selectedRecordType] || selectedRecordType; @@ -135,7 +135,7 @@ const Container = ({ /> ); -}; +} Container.displayName = NAME; diff --git a/app/javascript/components/reports-form/components/filters/component.unit.test.js b/app/javascript/components/reports-form/components/filters/component.spec.js similarity index 52% rename from app/javascript/components/reports-form/components/filters/component.unit.test.js rename to app/javascript/components/reports-form/components/filters/component.spec.js index 741a2e546e..bf5240022f 100644 --- a/app/javascript/components/reports-form/components/filters/component.unit.test.js +++ b/app/javascript/components/reports-form/components/filters/component.spec.js @@ -1,11 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { Typography } from "@material-ui/core"; -import { setupMountedComponent, fake } from "../../../../test"; import { ACTIONS } from "../../../permissions"; -import FiltersDialog from "../filters-dialog"; import { MODULES_FIELD, RECORD_TYPE_FIELD, DEFAULT_FILTERS } from "../../constants"; import { DATE_FIELD, @@ -16,12 +13,11 @@ import { SUBFORM_SECTION, TEXT_FIELD } from "../../../form"; +import { mountedComponent, screen } from "../../../../test-utils"; import ReportFilters from "./component"; describe(" - Component", () => { - let component; - const initialState = fromJS({ user: { permissions: { @@ -119,7 +115,7 @@ describe(" - Component", () => { ]), parentFormMethods: { control: { subjectsRef: {} }, - getValues: fake.returns({ + getValues: jest.fn().mockReturnValueOnce({ [MODULES_FIELD]: ["primeromodule-cp"], [RECORD_TYPE_FIELD]: "case" }) @@ -130,20 +126,7 @@ describe(" - Component", () => { formMode: { isNew: false } }; - beforeEach(() => { - ({ component } = setupMountedComponent(ReportFilters, props, initialState)); - }); - - it("should render ", () => { - expect(component.find(Typography)).to.have.lengthOf(1); - }); - - it("should render ", () => { - expect(component.find(FiltersDialog)).to.have.lengthOf(1); - }); - describe("when there are not filter", () => { - let componentWithtoutFilter = null; const state = { records: { reports: { @@ -211,17 +194,17 @@ describe(" - Component", () => { }; beforeEach(() => { - ({ component: componentWithtoutFilter } = setupMountedComponent(ReportFilters, { ...props, indexes: [] }, state, [ - "/reports/1/edit" - ])); + const componentProps = { ...props, indexes: [] }; + + mountedComponent(, state, {}, ["/reports/1/edit"]); }); it("should render new button", () => { - expect(componentWithtoutFilter.find("button").text()).to.equal("buttons.new"); + expect(screen.getByText("buttons.new")).toBeInTheDocument(); }); it("should render 'No filters added' message", () => { - expect(componentWithtoutFilter.find("p").at(1).text()).to.equal("report.no_filters_added"); + expect(screen.getByText("report.no_filters_added")).toBeInTheDocument(); }); }); @@ -229,60 +212,57 @@ describe(" - Component", () => { describe("and the selectedRecordType is reportable_service", () => { it("should render the default service filters", () => { let appliedFilters = []; - - setupMountedComponent( - ReportFilters, - { - ...props, - allRecordForms: fromJS([ - { - id: 1, - unique_id: "services", - name: { en: "Services Section" }, - visible: true, - module_ids: ["primeromodule-cp"], - parent_form: "case", - fields: [ - FieldRecord({ - name: "nested_services", - type: SUBFORM_SECTION, - subform_section_id: FormSectionRecord({ - fields: [ - FieldRecord({ - name: "service_type", - display_name: { - en: "Service type" - }, - type: SELECT_FIELD, - visible: true - }), - FieldRecord({ - name: "service_appointment_date", - display_name: { - en: "Service Appointment Date" - }, - type: SELECT_FIELD, - visible: true - }) - ] - }) + const componentProps = { + ...props, + allRecordForms: fromJS([ + { + id: 1, + unique_id: "services", + name: { en: "Services Section" }, + visible: true, + module_ids: ["primeromodule-cp"], + parent_form: "case", + fields: [ + FieldRecord({ + name: "nested_services", + type: SUBFORM_SECTION, + subform_section_id: FormSectionRecord({ + fields: [ + FieldRecord({ + name: "service_type", + display_name: { + en: "Service type" + }, + type: SELECT_FIELD, + visible: true + }), + FieldRecord({ + name: "service_appointment_date", + display_name: { + en: "Service Appointment Date" + }, + type: SELECT_FIELD, + visible: true + }) + ] }) - ] - } - ]), - indexes: [], - setIndexes: filters => { - appliedFilters = filters; - }, - formMode: { isNew: true }, - selectedModule: "primeromodule-cp", - selectedRecordType: "reportable_service", - formattedMinimumReportableFields + }) + ] + } + ]), + indexes: [], + setIndexes: filters => { + appliedFilters = filters; }, - initialState - ); + formMode: { isNew: true }, + selectedModule: "primeromodule-cp", + selectedRecordType: "reportable_service", + formattedMinimumReportableFields + }; - expect(appliedFilters.map(filter => filter.data.attribute)).to.deep.equals([ + mountedComponent(, initialState); + + expect(appliedFilters.map(filter => filter.data.attribute)).toStrictEqual([ "status", "record_state", "consent_reporting", @@ -295,51 +275,49 @@ describe(" - Component", () => { it("should render the default follow_up filters", () => { let appliedFilters = []; - setupMountedComponent( - ReportFilters, - { - ...props, - allRecordForms: fromJS([ - { - id: 1, - unique_id: "followup", - name: { en: "Follow up" }, - visible: true, - module_ids: ["primeromodule-cp"], - parent_form: "case", - fields: [ - FieldRecord({ - name: "followup_subform_section", - type: SUBFORM_SECTION, - subform_section_id: FormSectionRecord({ - fields: [ - FieldRecord({ - name: "followup_date", - display_name: { - en: "Follow Up" - }, - type: DATE_FIELD, - visible: true - }) - ] - }) + const componentProps = { + ...props, + allRecordForms: fromJS([ + { + id: 1, + unique_id: "followup", + name: { en: "Follow up" }, + visible: true, + module_ids: ["primeromodule-cp"], + parent_form: "case", + fields: [ + FieldRecord({ + name: "followup_subform_section", + type: SUBFORM_SECTION, + subform_section_id: FormSectionRecord({ + fields: [ + FieldRecord({ + name: "followup_date", + display_name: { + en: "Follow Up" + }, + type: DATE_FIELD, + visible: true + }) + ] }) - ] - } - ]), - indexes: [], - setIndexes: filters => { - appliedFilters = filters; - }, - formMode: { isNew: true }, - selectedModule: "primeromodule-cp", - selectedRecordType: "reportable_follow_up", - formattedMinimumReportableFields + }) + ] + } + ]), + indexes: [], + setIndexes: filters => { + appliedFilters = filters; }, - initialState - ); + formMode: { isNew: true }, + selectedModule: "primeromodule-cp", + selectedRecordType: "reportable_follow_up", + formattedMinimumReportableFields + }; + + mountedComponent(, initialState); - expect(appliedFilters.map(filter => filter.data.attribute)).to.deep.equals([ + expect(appliedFilters.map(filter => filter.data.attribute)).toStrictEqual([ "status", "record_state", "consent_reporting", @@ -350,52 +328,49 @@ describe(" - Component", () => { describe("and the selectedRecordType is reportable_protection_concern", () => { it("should render the default protection_concern filters", () => { let appliedFilters = []; - - setupMountedComponent( - ReportFilters, - { - ...props, - allRecordForms: fromJS([ - { - id: 1, - unique_id: "protection_concern_details", - name: { en: "Protection Concern" }, - visible: true, - module_ids: ["primeromodule-cp"], - parent_form: "case", - fields: [ - FieldRecord({ - name: "protection_concern_section", - type: SUBFORM_SECTION, - subform_section_id: FormSectionRecord({ - fields: [ - FieldRecord({ - name: "protection_concern_type", - display_name: { - en: "Protection Concern Type" - }, - type: TEXT_FIELD, - visible: true - }) - ] - }) + const componentProps = { + ...props, + allRecordForms: fromJS([ + { + id: 1, + unique_id: "protection_concern_details", + name: { en: "Protection Concern" }, + visible: true, + module_ids: ["primeromodule-cp"], + parent_form: "case", + fields: [ + FieldRecord({ + name: "protection_concern_section", + type: SUBFORM_SECTION, + subform_section_id: FormSectionRecord({ + fields: [ + FieldRecord({ + name: "protection_concern_type", + display_name: { + en: "Protection Concern Type" + }, + type: TEXT_FIELD, + visible: true + }) + ] }) - ] - } - ]), - indexes: [], - setIndexes: filters => { - appliedFilters = filters; - }, - formMode: { isNew: true }, - selectedModule: "primeromodule-cp", - selectedRecordType: "reportable_protection_concern", - formattedMinimumReportableFields + }) + ] + } + ]), + indexes: [], + setIndexes: filters => { + appliedFilters = filters; }, - initialState - ); + formMode: { isNew: true }, + selectedModule: "primeromodule-cp", + selectedRecordType: "reportable_protection_concern", + formattedMinimumReportableFields + }; + + mountedComponent(, initialState); - expect(appliedFilters.map(filter => filter.data.attribute)).to.deep.equals([ + expect(appliedFilters.map(filter => filter.data.attribute)).toStrictEqual([ "status", "record_state", "consent_reporting", diff --git a/app/javascript/components/reports-form/components/filters/utils.js b/app/javascript/components/reports-form/components/filters/utils.js index 0355b53d10..fb51e18b6d 100644 --- a/app/javascript/components/reports-form/components/filters/utils.js +++ b/app/javascript/components/reports-form/components/filters/utils.js @@ -54,6 +54,10 @@ export const formatValue = (value, i18n, { field, lookups }) => { lookup => lookup.unique_id === field.option_strings_source.replace(/lookup /, "") )?.values; + if (!lookupValues || lookupValues.length <= 0) { + return value; + } + return value .map(currentValue => { const text = lookupValues.find(option => option.id === currentValue); diff --git a/app/javascript/components/reports-form/container.jsx b/app/javascript/components/reports-form/container.jsx index c2330fb009..1d2e195b1d 100644 --- a/app/javascript/components/reports-form/container.jsx +++ b/app/javascript/components/reports-form/container.jsx @@ -2,8 +2,8 @@ /* eslint-disable camelcase */ -import CheckIcon from "@material-ui/icons/Check"; -import ClearIcon from "@material-ui/icons/Clear"; +import CheckIcon from "@mui/icons-material/Check"; +import ClearIcon from "@mui/icons-material/Clear"; import { push } from "connected-react-router"; import omit from "lodash/omit"; import PropTypes from "prop-types"; @@ -44,7 +44,7 @@ import { form, validations } from "./form"; import NAMESPACE from "./namespace"; import { buildMinimumReportableFields, buildReportFields, checkValue, formatAgeRange, formatReport } from "./utils"; -const Container = ({ mode }) => { +function Container({ mode }) { const formMode = whichFormMode(mode); const { dialogOpen, setDialog } = useDialog(TranslationsFormName); @@ -213,7 +213,7 @@ const Container = ({ mode }) => { ); -}; +} Container.displayName = NAME; diff --git a/app/javascript/components/reports-form/container.unit.test.js b/app/javascript/components/reports-form/container.spec.js similarity index 60% rename from app/javascript/components/reports-form/container.unit.test.js rename to app/javascript/components/reports-form/container.spec.js index f69ea3779d..1cb4e28b9c 100644 --- a/app/javascript/components/reports-form/container.unit.test.js +++ b/app/javascript/components/reports-form/container.spec.js @@ -1,21 +1,15 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS, OrderedMap } from "immutable"; -import { expect } from "chai"; +import { mountedComponent, screen } from "test-utils"; -import { PageContent, PageHeading } from "../page"; -import { setupMountedComponent } from "../../test"; import { ACTIONS } from "../permissions"; import { PrimeroModuleRecord } from "../application/records"; import { FormSectionRecord, FieldRecord } from "../form/records"; -import Form from "../form"; -import SelectInput from "../form/fields/select-input"; import ReportsForm from "./container"; describe(" - Container", () => { - let component; - const primeroModule = PrimeroModuleRecord({ unique_id: "module_1", associated_record_types: ["case"], @@ -103,52 +97,16 @@ describe(" - Container", () => { }); beforeEach(() => { - ({ component } = setupMountedComponent(ReportsForm, { mode: "new" }, initialState)); + const props = { mode: "new" }; + + mountedComponent(, initialState); }); it("should render ", () => { - expect(component.find(PageHeading)).to.have.lengthOf(1); + expect(screen.getByText("reports.register_new_report")).toBeInTheDocument(); }); it("should render ", () => { - expect(component.find(PageContent)).to.have.lengthOf(1); - }); - - it.skip("does not render date fields in the aggregate/disaggreate select fields", () => { - component.find(SelectInput).at(0).find("button").at(1).simulate("click"); - component.find(SelectInput).at(0).find("ul.MuiAutocomplete-groupUl").at(0).find("li").at(0).simulate("click"); - - component.find(SelectInput).at(1).find("button").at(1).simulate("click"); - component.find(SelectInput).at(1).find("ul.MuiAutocomplete-groupUl").at(0).find("li").at(0).simulate("click"); - - expect( - component - .find(SelectInput) - .at(2) - .props() - .options.map(option => option.id) - ).to.deep.equals(["cp_some_field"]); - }); - - it("should contain valid props for
component", () => { - const props = Object.keys(component.find(Form).props()); - const expected = [ - "initialValues", - "formSections", - "onSubmit", - "formMode", - "validations", - "formID", - "registerFields", - "submitAllFields", - "submitAlways", - "renderBottom", - "formErrors", - "formOptions", - "mode", - "useCancelPrompt" - ]; - - expect(props).to.deep.equals(expected); + expect(screen.getByText("reports.translations.manage")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/reports-form/utils/build-field.js b/app/javascript/components/reports-form/utils/build-field.js index 7d359f5687..d8c877a3d8 100644 --- a/app/javascript/components/reports-form/utils/build-field.js +++ b/app/javascript/components/reports-form/utils/build-field.js @@ -21,7 +21,7 @@ export const buildLocationFields = (current, formSection, i18n, reportingLocatio return [ { ...buildField(current, formSection, locale), - id: current.get("name"), + id: `loc:${current.get("name")}`, display_text: `${displayNameHelper(current.get("display_name"), locale)}` } ].concat( @@ -29,7 +29,7 @@ export const buildLocationFields = (current, formSection, i18n, reportingLocatio (acc, [key, value]) => acc.concat({ ...buildField(current, formSection, locale), - id: `${current.get("name")}${key}`, + id: `loc:${current.get("name")}${key}`, display_text: `${displayNameHelper(current.get("display_name"), locale)} (${i18n.t( `location.base_types.${value.first()}` )})` diff --git a/app/javascript/components/reports-form/utils/build-field.unit.test.js b/app/javascript/components/reports-form/utils/build-field.unit.test.js index 533d471d88..beb896f109 100644 --- a/app/javascript/components/reports-form/utils/build-field.unit.test.js +++ b/app/javascript/components/reports-form/utils/build-field.unit.test.js @@ -41,7 +41,7 @@ describe("/utils/build-field", () => { it("returns the location field and a location field for each level in the admin_level_map", () => { const locationField = { - id: "location", + id: "loc:location", display_text: "Location", formSection: "Form 1", type: "select_field", @@ -64,9 +64,14 @@ describe("/utils/build-field", () => { const expected = [ locationField, - { ...locationField, id: "location0", display_text: "Location (location.base_types.country)" }, - { ...locationField, id: "location1", display_text: "Location (location.base_types.city)", visible: true }, - { ...locationField, id: "location2", display_text: "Location (location.base_types.district)", visible: true } + { ...locationField, id: "loc:location0", display_text: "Location (location.base_types.country)" }, + { ...locationField, id: "loc:location1", display_text: "Location (location.base_types.city)", visible: true }, + { + ...locationField, + id: "loc:location2", + display_text: "Location (location.base_types.district)", + visible: true + } ]; expect(buildLocationFields(field, "Form 1", i18n, reportingLocationConfig)).to.deep.equal(expected); diff --git a/app/javascript/components/reports-form/utils/format-report.js b/app/javascript/components/reports-form/utils/format-report.js index a693032c2a..c3c99dbcf9 100644 --- a/app/javascript/components/reports-form/utils/format-report.js +++ b/app/javascript/components/reports-form/utils/format-report.js @@ -2,6 +2,14 @@ import isNil from "lodash/isNil"; +const formatFieldName = ({ name, adminLevel, optionStringsSource }) => { + if (optionStringsSource === "Location") { + return `loc:${name}${isNil(adminLevel) ? "" : adminLevel}`; + } + + return name; +}; + export default report => { return Object.entries(report).reduce((acc, curr) => { const [key, value] = curr; @@ -12,10 +20,14 @@ export default report => { case "fields": { const rows = value .filter(({ position }) => position.type === "horizontal") - .map(({ name, admin_level: adminLevel }) => `${name}${isNil(adminLevel) ? "" : adminLevel}`); + .map(({ name, admin_level: adminLevel, option_strings_source: optionStringsSource }) => + formatFieldName({ name, adminLevel, optionStringsSource }) + ); const columns = value .filter(({ position }) => position.type === "vertical") - .map(({ name, admin_level: adminLevel }) => `${name}${isNil(adminLevel) ? "" : adminLevel}`); + .map(({ name, admin_level: adminLevel, option_strings_source: optionStringsSource }) => + formatFieldName({ name, adminLevel, optionStringsSource }) + ); return { ...acc, aggregate_by: rows, disaggregate_by: columns }; } diff --git a/app/javascript/components/reports-form/utils/format-report.unit.test.js b/app/javascript/components/reports-form/utils/format-report.unit.test.js index f2fbd9ab84..9206930733 100644 --- a/app/javascript/components/reports-form/utils/format-report.unit.test.js +++ b/app/javascript/components/reports-form/utils/format-report.unit.test.js @@ -42,15 +42,14 @@ describe("/utils/formatReport()", () => { { admin_level: 1, name: "location", - position: { - type: "horizontal" - } + option_strings_source: "Location", + position: { type: "horizontal" } } ] }; it("should return an array with a field containing the admin level as part of the string", () => { - expect(formatReport(reportWithAdminLevel).aggregate_by).to.deep.equal(["location1"]); + expect(formatReport(reportWithAdminLevel).aggregate_by).to.deep.equal(["loc:location1"]); }); describe("when admin_level is zero", () => { @@ -61,15 +60,14 @@ describe("/utils/formatReport()", () => { { admin_level: 0, name: "location", - position: { - type: "horizontal" - } + option_strings_source: "Location", + position: { type: "horizontal" } } ] }; it("should return an array with a field containing the admin level as part of the string", () => { - expect(formatReport(reportWithAdminLevelZero).aggregate_by).to.deep.equal(["location0"]); + expect(formatReport(reportWithAdminLevelZero).aggregate_by).to.deep.equal(["loc:location0"]); }); }); }); diff --git a/app/javascript/components/reports-list/container.jsx b/app/javascript/components/reports-list/container.jsx index 65858ade26..bc30f61174 100644 --- a/app/javascript/components/reports-list/container.jsx +++ b/app/javascript/components/reports-list/container.jsx @@ -2,7 +2,7 @@ import { Link } from "react-router-dom"; import { useDispatch } from "react-redux"; -import AddIcon from "@material-ui/icons/Add"; +import AddIcon from "@mui/icons-material/Add"; import { push } from "connected-react-router"; import DisableOffline from "../disable-offline"; @@ -20,7 +20,7 @@ import IndexTable from "../index-table"; import { fetchReports } from "./action-creators"; import NAMESPACE from "./namespace"; -const Reports = () => { +function Reports() { const i18n = useI18n(); const dispatch = useDispatch(); @@ -81,7 +81,7 @@ const Reports = () => { ); -}; +} Reports.displayName = "Reports"; diff --git a/app/javascript/components/reports-list/container.unit.test.js b/app/javascript/components/reports-list/container.spec.js similarity index 65% rename from app/javascript/components/reports-list/container.unit.test.js rename to app/javascript/components/reports-list/container.spec.js index 09c6af6837..a400840aec 100644 --- a/app/javascript/components/reports-list/container.unit.test.js +++ b/app/javascript/components/reports-list/container.spec.js @@ -1,17 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import AddIcon from "@material-ui/icons/Add"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../test"; -import IndexTable from "../index-table"; import { ACTIONS } from "../permissions"; import Reports from "./container"; describe(" - Component", () => { - let component; - const initialState = fromJS({ user: { permissions: { @@ -57,25 +53,19 @@ describe(" - Component", () => { }); beforeEach(() => { - ({ component } = setupMountedComponent(Reports, {}, initialState)); + mountedComponent(, initialState); }); it("should render ", () => { - expect(component.find(IndexTable)).to.have.lengthOf(1); + expect(screen.getAllByText("reports.label")).toBeTruthy(); }); - // TODO: Should test if we have a clickable button, but removing button temporarly till this feature is implemented - // it("should render ", () => { - // expect(component.find(AddIcon)).to.have.lengthOf(1); - // }); - describe("When doesn't have permission to create report", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(Reports, {}, initialState.get("records"))); - }); - it("should not render AddIcon", () => { - expect(component.find(AddIcon)).to.have.lengthOf(0); + mountedComponent(, initialState.get("records")); + const addIconElement = screen.queryByTestId("add-icon"); + + expect(addIconElement).not.toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/reports-list/styles.css b/app/javascript/components/reports-list/styles.css index 8ac998ce86..8f3f4d9374 100644 --- a/app/javascript/components/reports-list/styles.css +++ b/app/javascript/components/reports-list/styles.css @@ -38,16 +38,14 @@ padding: 0 1.3em; } -@media ((min-width:960px) and (max-width:1279.95px)) { +@media ((min-width:900px) and (max-width:1200px)) { .reportsListContainer { grid-template-columns: repeat(2, 1fr); } } -@media (max-width:959.95px) { +@media (max-width:900px) { .reportsListContainer { grid-template-columns: repeat(1, 1fr); } } - - diff --git a/app/javascript/components/save-and-redirect-dialog/component.jsx b/app/javascript/components/save-and-redirect-dialog/component.jsx index f6cf74e5a4..fd8aae6f29 100644 --- a/app/javascript/components/save-and-redirect-dialog/component.jsx +++ b/app/javascript/components/save-and-redirect-dialog/component.jsx @@ -11,16 +11,16 @@ import { setSelectedForm } from "../record-form"; import { SAVE_AND_REDIRECT_DIALOG } from "./constants"; -const Component = ({ +function Component({ setSaveCaseBeforeRedirect, closeRedirectDialog, handleSubmit, mode, open, setFieldValue, - incidentPath, + incidentPath = "new", recordType -}) => { +}) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -54,14 +54,10 @@ const Component = ({ pending={savingRecord} /> ); -}; +} Component.displayName = SAVE_AND_REDIRECT_DIALOG; -Component.defaultProps = { - incidentPath: "new" -}; - Component.propTypes = { closeRedirectDialog: PropTypes.func, handleSubmit: PropTypes.func, diff --git a/app/javascript/components/save-and-redirect-dialog/component.spec.js b/app/javascript/components/save-and-redirect-dialog/component.spec.js new file mode 100644 index 0000000000..b4f8e5498a --- /dev/null +++ b/app/javascript/components/save-and-redirect-dialog/component.spec.js @@ -0,0 +1,26 @@ +import { fromJS } from "immutable"; +import { mountedComponent, screen } from "test-utils"; + +import { RECORD_TYPES } from "../../config"; + +import SaveAndRedirectDialog from "./component"; + +describe(" - Component", () => { + const props = { + handleSubmit: () => {}, + incidentPath: "", + mode: { isShow: false, isEdit: true }, + open: true, + recordType: RECORD_TYPES.cases, + setFieldValue: () => {}, + setRedirectOpts: () => {} + }; + + beforeEach(() => { + mountedComponent(, fromJS({})); + }); + + it("render ActionDialog component", () => { + expect(screen.getByRole("dialog")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/save-and-redirect-dialog/component.unit.test.js b/app/javascript/components/save-and-redirect-dialog/component.unit.test.js deleted file mode 100644 index 0958bbd331..0000000000 --- a/app/javascript/components/save-and-redirect-dialog/component.unit.test.js +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../test"; -import ActionDialog from "../action-dialog"; -import { RECORD_TYPES } from "../../config"; - -import SaveAndRedirectDialog from "./component"; - -describe(" - Component", () => { - let component; - const props = { - handleSubmit: () => {}, - incidentPath: "", - mode: { isShow: false, isEdit: true }, - open: true, - recordType: RECORD_TYPES.cases, - setFieldValue: () => {}, - setRedirectOpts: () => {} - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(SaveAndRedirectDialog, props, fromJS({}))); - }); - - it("render RedirectDialog component", () => { - expect(component.find(SaveAndRedirectDialog)).to.have.lengthOf(1); - }); - - it("render a ActionDialog", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(1); - }); - - it("renders component with valid props", () => { - const redirectDialogProps = { ...component.find(SaveAndRedirectDialog).props() }; - - ["handleSubmit", "incidentPath", "mode", "open", "recordType", "setFieldValue", "setRedirectOpts"].forEach( - property => { - expect(redirectDialogProps).to.have.property(property); - delete redirectDialogProps[property]; - } - ); - expect(redirectDialogProps).to.be.empty; - }); -}); diff --git a/app/javascript/components/saved-searches/ListSavedSearches.jsx b/app/javascript/components/saved-searches/ListSavedSearches.jsx index 598200e1d7..68b4727473 100644 --- a/app/javascript/components/saved-searches/ListSavedSearches.jsx +++ b/app/javascript/components/saved-searches/ListSavedSearches.jsx @@ -3,8 +3,8 @@ import { useState, useEffect } from "react"; import PropTypes from "prop-types"; import { useDispatch } from "react-redux"; -import { List, ListItem, ListItemText, ListItemSecondaryAction, Divider } from "@material-ui/core"; -import DeleteIcon from "@material-ui/icons/Delete"; +import { List, ListItem, ListItemText, ListItemSecondaryAction, Divider } from "@mui/material"; +import DeleteIcon from "@mui/icons-material/Delete"; import { push } from "connected-react-router"; import qs from "qs"; @@ -20,7 +20,7 @@ import { selectSavedSearchesById } from "./selectors"; import { buildFiltersState } from "./utils"; import css from "./styles.css"; -const ListSavedSearches = ({ recordType, savedSearches, setTabIndex, setRerender }) => { +function ListSavedSearches({ recordType, savedSearches, setTabIndex, setRerender }) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -104,7 +104,7 @@ const ListSavedSearches = ({ recordType, savedSearches, setTabIndex, setRerender {renderSavedSearches()} ); -}; +} ListSavedSearches.displayName = "ListSavedSearches"; diff --git a/app/javascript/components/saved-searches/ListSavedSearches.unit.test.js b/app/javascript/components/saved-searches/ListSavedSearches.spec.js similarity index 68% rename from app/javascript/components/saved-searches/ListSavedSearches.unit.test.js rename to app/javascript/components/saved-searches/ListSavedSearches.spec.js index 582de35303..8a42b40429 100644 --- a/app/javascript/components/saved-searches/ListSavedSearches.unit.test.js +++ b/app/javascript/components/saved-searches/ListSavedSearches.spec.js @@ -1,16 +1,12 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { List, Map } from "immutable"; -import { ListItem } from "@material-ui/core"; - -import { setupMountedComponent } from "../../test"; +import { mountedComponent, screen } from "test-utils"; import ListSavedSearches from "./ListSavedSearches"; import { SavedSearchesRecord } from "./records"; describe(" - Component", () => { - let component; - beforeEach(() => { const savedSearches = List([ SavedSearchesRecord({ @@ -39,15 +35,16 @@ describe(" - Component", () => { }) ]); - ({ component } = setupMountedComponent( - ListSavedSearches, - { - recordType: "cases", - savedSearches: List(savedSearches), - resetFilters: () => {}, - setTabIndex: () => {}, - setRerender: () => {} - }, + const props = { + recordType: "cases", + savedSearches: List(savedSearches), + resetFilters: () => {}, + setTabIndex: () => {}, + setRerender: () => {} + }; + + mountedComponent( + , Map({ records: Map({ savedSearches: Map({ @@ -55,10 +52,14 @@ describe(" - Component", () => { }) }) }) - )); + ); }); it("renders 2 ListItem", () => { - expect(component.find(ListItem)).to.have.lengthOf(2); + const listItemText1 = screen.getByText("a new filter"); + const listItemText2 = screen.getByText("another filter"); + + expect(listItemText1).toBeInTheDocument(); + expect(listItemText2).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/saved-searches/SavedSearchesForm.jsx b/app/javascript/components/saved-searches/SavedSearchesForm.jsx index 3f7050f1ce..f4c5cff0c6 100644 --- a/app/javascript/components/saved-searches/SavedSearchesForm.jsx +++ b/app/javascript/components/saved-searches/SavedSearchesForm.jsx @@ -1,20 +1,19 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { useEffect, useState } from "react"; +import { useState } from "react"; import PropTypes from "prop-types"; import { compact } from "lodash"; import { useDispatch } from "react-redux"; -import { Dialog, DialogContent, DialogTitle, DialogActions, TextField } from "@material-ui/core"; +import { Dialog, DialogContent, DialogTitle, DialogActions, TextField } from "@mui/material"; import { useForm } from "react-hook-form"; import { object, string } from "yup"; import qs from "qs"; import { push } from "connected-react-router"; -import CheckIcon from "@material-ui/icons/Check"; -import CloseIcon from "@material-ui/icons/Close"; +import CheckIcon from "@mui/icons-material/Check"; +import CloseIcon from "@mui/icons-material/Close"; import { yupResolver } from "@hookform/resolvers/yup"; import { fromJS } from "immutable"; -import { enqueueSnackbar } from "../notifier"; import { selectModules } from "../login/components/login-form/selectors"; import { useI18n } from "../i18n"; import { ROUTES } from "../../config"; @@ -24,23 +23,13 @@ import useMemoizedSelector from "../../libs/use-memoized-selector"; import { saveSearch } from "./action-creators"; import { buildFiltersApi, buildFiltersState } from "./utils"; - -const FormErrors = () => { - const dispatch = useDispatch(); - const i18n = useI18n(); - - useEffect(() => { - dispatch(enqueueSnackbar(i18n.t("saved_search.no_filters"), { type: "error" })); - }, [dispatch, i18n]); - - return null; -}; +import FormErrors from "./components/form-errors"; const validationSchema = object().shape({ name: string().required() }); -const SavedSearchesForm = ({ recordType, open, setOpen, getValues }) => { +function SavedSearchesForm({ recordType, open, setOpen, getValues }) { const i18n = useI18n(); const dispatch = useDispatch(); const [formErrors, setFormErrors] = useState(false); @@ -123,7 +112,7 @@ const SavedSearchesForm = ({ recordType, open, setOpen, getValues }) => { ); -}; +} SavedSearchesForm.displayName = "SavedSearchesForm"; diff --git a/app/javascript/components/saved-searches/component.jsx b/app/javascript/components/saved-searches/component.jsx index 43575083b2..e6dc91489a 100644 --- a/app/javascript/components/saved-searches/component.jsx +++ b/app/javascript/components/saved-searches/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Typography } from "@material-ui/core"; +import { Typography } from "@mui/material"; import { useI18n } from "../i18n"; import useMemoizedSelector from "../../libs/use-memoized-selector"; @@ -10,7 +10,7 @@ import ListSavedSearches from "./ListSavedSearches"; import { selectSavedSearches } from "./selectors"; import css from "./styles.css"; -const SavedSearches = ({ recordType, setTabIndex, setRerender }) => { +function SavedSearches({ recordType, setTabIndex, setRerender }) { const i18n = useI18n(); const savedSearches = useMemoizedSelector(state => selectSavedSearches(state, recordType)); @@ -33,7 +33,7 @@ const SavedSearches = ({ recordType, setTabIndex, setRerender }) => { )} ); -}; +} SavedSearches.displayName = "SavedSearches"; diff --git a/app/javascript/components/saved-searches/component.unit.test.js b/app/javascript/components/saved-searches/component.spec.js similarity index 69% rename from app/javascript/components/saved-searches/component.unit.test.js rename to app/javascript/components/saved-searches/component.spec.js index c0041742ff..3b4116371a 100644 --- a/app/javascript/components/saved-searches/component.unit.test.js +++ b/app/javascript/components/saved-searches/component.spec.js @@ -1,19 +1,16 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { Map, List } from "immutable"; +import { mountedComponent, screen } from "test-utils"; -import { setupMountedComponent } from "../../test"; - -import ListSavedSearches from "./ListSavedSearches"; import SavedSearches from "./component"; describe(" - Component", () => { - let component; + beforeEach(() => { + const props = { recordType: "incidents", resetFilters: () => {} }; - before(() => { - component = setupMountedComponent( - SavedSearches, - { recordType: "incidents", resetFilters: () => {} }, + mountedComponent( + , Map({ records: Map({ savedSearches: Map({ @@ -33,10 +30,10 @@ describe(" - Component", () => { }) }) }) - ).component; + ); }); it("renders the ListSavedSearches", () => { - expect(component.find(ListSavedSearches)).to.have.length(1); + expect(screen.getByText("cases.my_filters")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/saved-searches/components/form-errors/component.jsx b/app/javascript/components/saved-searches/components/form-errors/component.jsx new file mode 100644 index 0000000000..01cf83da38 --- /dev/null +++ b/app/javascript/components/saved-searches/components/form-errors/component.jsx @@ -0,0 +1,20 @@ +import { useDispatch } from "react-redux"; +import { useEffect } from "react"; + +import { useI18n } from "../../../i18n"; +import { enqueueSnackbar } from "../../../notifier"; + +function FormErrors() { + const dispatch = useDispatch(); + const i18n = useI18n(); + + useEffect(() => { + dispatch(enqueueSnackbar(i18n.t("saved_search.no_filters"), { type: "error" })); + }, [dispatch, i18n]); + + return null; +} + +FormErrors.displayName = "FormErrors"; + +export default FormErrors; diff --git a/app/javascript/components/saved-searches/components/form-errors/index.js b/app/javascript/components/saved-searches/components/form-errors/index.js new file mode 100644 index 0000000000..b6e0586481 --- /dev/null +++ b/app/javascript/components/saved-searches/components/form-errors/index.js @@ -0,0 +1 @@ +export { default } from "./component"; diff --git a/app/javascript/components/saved-searches/utils.js b/app/javascript/components/saved-searches/utils.js index bb287869fe..f745420d4b 100644 --- a/app/javascript/components/saved-searches/utils.js +++ b/app/javascript/components/saved-searches/utils.js @@ -10,6 +10,7 @@ export const buildFiltersApi = filters => { if ( value === undefined || + value === null || (isArray && value.length <= 0) || (isObject && Object.keys(value).length <= 0) || excludeDefaultFiltersKeys.includes(key) diff --git a/app/javascript/components/searchable-select/component.jsx b/app/javascript/components/searchable-select/component.jsx index 605bb6a7b7..05c622b149 100644 --- a/app/javascript/components/searchable-select/component.jsx +++ b/app/javascript/components/searchable-select/component.jsx @@ -1,9 +1,9 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +// Copyright (c) 2014 - 2024 UNICEF. All rights reserved. /* eslint-disable react/display-name */ import PropTypes from "prop-types"; -import Autocomplete from "@material-ui/lab/Autocomplete"; -import { Chip } from "@material-ui/core"; +import Autocomplete from "@mui/material/Autocomplete"; +import { Chip } from "@mui/material"; import AutoCompleteInput from "./components/auto-complete-input"; import { NAME } from "./constants"; @@ -11,26 +11,26 @@ import css from "./styles.css"; import { optionLabel, optionEquality, optionDisabled, filterOptions } from "./utils"; import { listboxClasses, virtualize } from "./components/listbox-component"; -const SearchableSelect = ({ +function SearchableSelect({ error, - defaultValues, - helperText, - isClearable, - isDisabled, - isLoading, - multiple, + defaultValues = null, + helperText = "", + isClearable = true, + isDisabled = false, + isLoading = false, + multiple = false, onChange, onBlur, onOpen, - options, - TextFieldProps, - mode, + options = [], + TextFieldProps = {}, + mode = {}, InputLabelProps, - optionIdKey, - optionLabelKey, + optionIdKey = "value", + optionLabelKey = "label", name, value: fieldValue -}) => { +}) { const defaultEmptyValue = multiple ? [] : null; const initialValues = (() => { @@ -63,6 +63,7 @@ const SearchableSelect = ({ return ( ( ); -}; +} SearchableSelect.displayName = NAME; -SearchableSelect.defaultProps = { - defaultValues: null, - helperText: "", - isClearable: true, - isDisabled: false, - isLoading: false, - mode: {}, - multiple: false, - optionIdKey: "value", - optionLabelKey: "label", - options: [], - TextFieldProps: {} -}; - SearchableSelect.propTypes = { defaultValues: PropTypes.oneOfType([PropTypes.array, PropTypes.string, PropTypes.object]), error: PropTypes.string, diff --git a/app/javascript/components/searchable-select/component.unit.test.js b/app/javascript/components/searchable-select/component.spec.js similarity index 65% rename from app/javascript/components/searchable-select/component.unit.test.js rename to app/javascript/components/searchable-select/component.spec.js index dc76cc2e61..e03b6c9f94 100644 --- a/app/javascript/components/searchable-select/component.unit.test.js +++ b/app/javascript/components/searchable-select/component.spec.js @@ -1,13 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import Autocomplete from "@material-ui/lab/Autocomplete"; - -import { setupMountedComponent } from "../../test"; +import { mountedComponent, screen } from "test-utils"; import SearchableSelect from "./component"; describe("", () => { - let component; const props = { id: "userAutocomplete", name: "name_test", @@ -27,11 +23,10 @@ describe("", () => { }; beforeEach(() => { - ({ component } = setupMountedComponent(SearchableSelect, props)); + mountedComponent(); }); it("renders Autocomplete", () => { - expect(component.find(Autocomplete)).to.have.length(1); - expect(component.find(Autocomplete).props().options).to.have.length(3); + expect(screen.getByRole("combobox")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/searchable-select/components/auto-complete-input.jsx b/app/javascript/components/searchable-select/components/auto-complete-input.jsx index 04baca9ffd..183e0538ec 100644 --- a/app/javascript/components/searchable-select/components/auto-complete-input.jsx +++ b/app/javascript/components/searchable-select/components/auto-complete-input.jsx @@ -2,7 +2,7 @@ import { forwardRef, useEffect, useState } from "react"; import PropTypes from "prop-types"; -import { TextField, CircularProgress } from "@material-ui/core"; +import { TextField, CircularProgress } from "@mui/material"; import isEmpty from "lodash/isEmpty"; import { useI18n } from "../../i18n"; @@ -10,15 +10,15 @@ import { useI18n } from "../../i18n"; const Component = forwardRef( ( { - params, - value, - mode, - helperText, - InputLabelProps, - isDisabled, - isLoading, - multiple, - TextFieldProps, + params = {}, + value = "", + mode = {}, + helperText = "", + InputLabelProps = {}, + isDisabled = false, + isLoading = false, + multiple = false, + TextFieldProps = {}, currentOptionLabel, error }, @@ -80,21 +80,6 @@ const Component = forwardRef( Component.displayName = "AutoCompleteInput"; -Component.defaultProps = { - helperText: "", - InputLabelProps: {}, - isDisabled: false, - isLoading: false, - mode: {}, - multiple: false, - optionIdKey: "value", - optionLabelKey: "label", - options: [], - params: {}, - TextFieldProps: {}, - value: "" -}; - Component.propTypes = { currentOptionLabel: PropTypes.string, error: PropTypes.string, diff --git a/app/javascript/components/searchable-select/utils.js b/app/javascript/components/searchable-select/utils.js index 3c22781dfc..218996e696 100644 --- a/app/javascript/components/searchable-select/utils.js +++ b/app/javascript/components/searchable-select/utils.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { createFilterOptions } from "@material-ui/lab/useAutocomplete"; +import { createFilterOptions } from "@mui/material/useAutocomplete"; export const optionLabel = (option, options, optionIdKey, optionLabelKey) => { if (typeof option === "string" && option === "") { diff --git a/app/javascript/components/session-timeout-dialog/component.jsx b/app/javascript/components/session-timeout-dialog/component.jsx index d7b33e496e..faaa43e4ea 100644 --- a/app/javascript/components/session-timeout-dialog/component.jsx +++ b/app/javascript/components/session-timeout-dialog/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { useEffect, useRef, useCallback } from "react"; -import { Dialog, DialogTitle, DialogContent, DialogActions, Button } from "@material-ui/core"; +import { Dialog, DialogTitle, DialogContent, DialogActions, Button } from "@mui/material"; import { useIdleTimer, workerTimers } from "react-idle-timer"; import { useDispatch } from "react-redux"; import { push } from "connected-react-router"; @@ -14,7 +14,7 @@ import useMemoizedSelector from "../../libs/use-memoized-selector"; import { NAME } from "./constants"; -const SessionTimeoutDialog = () => { +function SessionTimeoutDialog() { const { online } = useApp(); const tokenRefreshTimer = useRef(); const dispatch = useDispatch(); @@ -119,7 +119,7 @@ const SessionTimeoutDialog = () => { ) : null; -}; +} SessionTimeoutDialog.displayName = NAME; diff --git a/app/javascript/components/session-timeout-dialog/component.spec.js b/app/javascript/components/session-timeout-dialog/component.spec.js new file mode 100644 index 0000000000..d5355c5c10 --- /dev/null +++ b/app/javascript/components/session-timeout-dialog/component.spec.js @@ -0,0 +1,44 @@ +import { createMocks } from "react-idle-timer"; +import { mountedComponent, screen, act, waitFor } from "test-utils"; + +import SessionTimeoutDialog from "./component"; + +describe("", () => { + beforeAll(() => { + jest.useFakeTimers(); + createMocks(); + }); + + afterEach(() => { + jest.clearAllTimers(); + }); + + it("should idle after 15 minutes", async () => { + mountedComponent(, { + application: { + userIdle: false + } + }); + await act(() => jest.advanceTimersByTimeAsync(16 * 1000 * 60)); + await waitFor(() => { + expect(screen.queryByRole("dialog")).toBeInTheDocument(); + }); + }); + + describe("when user is offline", () => { + it("should not idle after 15 minutes", async () => { + mountedComponent(, { + application: { + userIdle: false + }, + connectivity: { + online: false + } + }); + await act(() => jest.advanceTimersByTimeAsync(16 * 1000 * 60)); + await waitFor(() => { + expect(screen.queryByRole("dialog")).toBeNull(); + }); + }); + }); +}); diff --git a/app/javascript/components/session-timeout-dialog/component.unit.test.js b/app/javascript/components/session-timeout-dialog/component.unit.test.js deleted file mode 100644 index 40dac9f723..0000000000 --- a/app/javascript/components/session-timeout-dialog/component.unit.test.js +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import sinon from "sinon"; -import isEqual from "lodash/isEqual"; -import { createMocks } from "react-idle-timer"; - -import { setupMountedComponent } from "../../test"; -import { setUserIdle } from "../application/action-creators"; - -import SessionTimeoutDialog from "./component"; - -describe("", () => { - let component; - let clock; - - before(() => { - clock = sinon.useFakeTimers(); - createMocks(); - component = setupMountedComponent( - SessionTimeoutDialog, - {}, - fromJS({ - application: { - userIdle: false - } - }) - ).component; - }); - - it("should idle after 15 minutes", () => { - const idleAction = setUserIdle(true); - - expect( - component - .props() - .store.getActions() - .some(action => isEqual(action, idleAction)) - ).to.equal(false); - clock.tick(16 * 1000 * 60); - expect( - component - .props() - .store.getActions() - .some(action => isEqual(action, idleAction)) - ).to.equal(true); - }); - - describe("when user is offline", () => { - before(() => { - clock = sinon.useFakeTimers(); - - component = setupMountedComponent( - SessionTimeoutDialog, - {}, - fromJS({ - application: { - userIdle: false - }, - connectivity: { - online: false - } - }) - ).component; - }); - - it("should not idle after 15 minutes", () => { - const idleAction = setUserIdle(true); - - expect( - component - .props() - .store.getActions() - .some(action => isEqual(action, idleAction)) - ).to.equal(false); - clock.tick(16 * 1000 * 60); - expect( - component - .props() - .store.getActions() - .some(action => isEqual(action, idleAction)) - ).to.equal(false); - }); - }); -}); diff --git a/app/javascript/components/summary-incident-mrm/component.jsx b/app/javascript/components/summary-incident-mrm/component.jsx index a6689348f9..8d03063615 100644 --- a/app/javascript/components/summary-incident-mrm/component.jsx +++ b/app/javascript/components/summary-incident-mrm/component.jsx @@ -11,7 +11,7 @@ import ViolationsSubforms from "./components/violations-subforms"; import SummaryFields from "./components/summary-fields"; import ChildrenMultipleViolations from "./components/children-multiple-violations"; -const Component = ({ recordID, recordType, mobileDisplay, handleToggleNav, mode, formSections, values }) => { +function Component({ recordID, recordType, mobileDisplay, handleToggleNav, mode, formSections, values }) { const i18n = useI18n(); return ( @@ -28,7 +28,7 @@ const Component = ({ recordID, recordType, mobileDisplay, handleToggleNav, mode, ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/summary-incident-mrm/components/children-multiple-violations/component.jsx b/app/javascript/components/summary-incident-mrm/components/children-multiple-violations/component.jsx index 0b92b7f11d..878d6b1343 100644 --- a/app/javascript/components/summary-incident-mrm/components/children-multiple-violations/component.jsx +++ b/app/javascript/components/summary-incident-mrm/components/children-multiple-violations/component.jsx @@ -9,7 +9,7 @@ import { useI18n } from "../../../i18n"; import { NAME, INDIVIDUAL_VICTIMS, INDIVIDUAL_MULTIPLE_VIOLATIONS } from "./constants"; -const Component = ({ recordType, formSections, values }) => { +function Component({ recordType, formSections, values }) { const i18n = useI18n(); const subformMode = { isNew: false, isEdit: false, isShow: true }; const recordTypePlural = RECORD_TYPES_PLURAL[recordType]; @@ -36,7 +36,7 @@ const Component = ({ recordType, formSections, values }) => { customTitle={i18n.t("incidents.summary_mrm.fields.children_multiple_violation.label")} /> ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/summary-incident-mrm/components/summary-fields/component.jsx b/app/javascript/components/summary-incident-mrm/components/summary-fields/component.jsx index 697c78b778..28b60a8d87 100644 --- a/app/javascript/components/summary-incident-mrm/components/summary-fields/component.jsx +++ b/app/javascript/components/summary-incident-mrm/components/summary-fields/component.jsx @@ -4,12 +4,13 @@ import PropTypes from "prop-types"; import { fields } from "../../form"; import { useI18n } from "../../../i18n"; -import { FieldRecord, FormSectionField } from "../../../record-form"; +import { FieldRecord } from "../../../record-form"; +import FormSectionField from "../../../record-form/form/form-section-field"; import { NAME } from "./constants"; import css from "./styles.css"; -const Component = ({ recordID, recordType, mode }) => { +function Component({ recordID, recordType, mode }) { const i18n = useI18n(); return fields(i18n).map(field => { @@ -28,7 +29,7 @@ const Component = ({ recordID, recordType, mode }) => { ); }); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/summary-incident-mrm/components/violations-subforms/component.jsx b/app/javascript/components/summary-incident-mrm/components/violations-subforms/component.jsx index 41893ff9f8..8d75f1786f 100644 --- a/app/javascript/components/summary-incident-mrm/components/violations-subforms/component.jsx +++ b/app/javascript/components/summary-incident-mrm/components/violations-subforms/component.jsx @@ -9,7 +9,7 @@ import SubformField from "../../../record-form/form/subforms"; import { NAME } from "./constants"; -const Component = ({ recordType, formSections, values }) => { +function Component({ recordType, formSections, values }) { const subformMode = { isNew: false, isEdit: false, isShow: true }; const recordTypePlural = RECORD_TYPES_PLURAL[recordType]; @@ -42,7 +42,7 @@ const Component = ({ recordType, formSections, values }) => { /> ); }); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/summary/component.jsx b/app/javascript/components/summary/component.jsx index 2877124bee..ab1d69e7f2 100644 --- a/app/javascript/components/summary/component.jsx +++ b/app/javascript/components/summary/component.jsx @@ -4,7 +4,7 @@ import { useState, useEffect } from "react"; import { useDispatch } from "react-redux"; import { getIn } from "formik"; import PropTypes from "prop-types"; -import SearchIcon from "@material-ui/icons/Search"; +import SearchIcon from "@mui/icons-material/Search"; import { useI18n } from "../i18n"; import RecordFormTitle from "../record-form/form/record-form-title"; @@ -29,7 +29,7 @@ import { NAME, FIELD_NAMES } from "./constants"; import { fields } from "./form"; import css from "./styles.css"; -const Component = ({ record, recordType, mobileDisplay, handleToggleNav, form, mode, values }) => { +function Component({ record, recordType, mobileDisplay, handleToggleNav, form, mode, values }) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -137,7 +137,7 @@ const Component = ({ record, recordType, mobileDisplay, handleToggleNav, form, m /> ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/summary/component.spec.js b/app/javascript/components/summary/component.spec.js new file mode 100644 index 0000000000..562c5ffe35 --- /dev/null +++ b/app/javascript/components/summary/component.spec.js @@ -0,0 +1,103 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { fromJS } from "immutable"; +import { fireEvent, waitFor } from "@testing-library/react"; + +import { mountedComponent, screen, userEvent } from "../../test-utils"; + +import Summary from "./component"; + +describe("", () => { + const props = { + record: fromJS({}), + recordType: "case", + mobileDisplay: false, + handleToggleNav: () => {}, + form: {}, + mode: { isNew: false } + }; + + const formProps = { initialValues: { name: "" } }; + + const initialState = fromJS({}); + + it("should render a component", () => { + mountedComponent(, initialState, {}, [], formProps); + + expect(screen.getByTestId("record-form-title")).toBeInTheDocument(); + }); + + it("should render 3 component", () => { + mountedComponent(, initialState, {}, [], formProps); + + expect(screen.getAllByTestId("action-button")).toHaveLength(3); + }); + + it("should render 5 components", () => { + mountedComponent(, initialState, {}, [], formProps); + + expect(screen.getAllByTestId("form-section-field")).toHaveLength(5); + }); + + it("should render a when find match is clicked", async () => { + mountedComponent(, initialState, {}, [], formProps); + + const user = userEvent.setup(); + + await user.click(screen.getByRole("button", { name: "cases.summary.find_match" })); + + expect(screen.getAllByTestId("drawer")).toHaveLength(1); + }); + + describe("when consent_for_tracing is not set", () => { + it("should render a tooltip for the find match button", async () => { + mountedComponent(, initialState, {}, [], formProps); + + await fireEvent.mouseOver(screen.getByRole("button", { name: "cases.summary.find_match" })); + + waitFor(() => { + expect(screen.getByText("cases.summary.cannot_find_matches")).toBeInTheDocument(); + }); + }); + + it("should disable the find match button", () => { + mountedComponent(, initialState, {}, [], formProps); + + expect(screen.getByRole("button", { name: "cases.summary.find_match" })).toBeDisabled(); + }); + }); + + describe("when consent_for_tracing is set to true", () => { + it("should not render a tooltip for the find match button", async () => { + mountedComponent(, initialState, {}, [], formProps); + + await fireEvent.mouseOver(screen.getByRole("button", { name: "cases.summary.find_match" })); + + waitFor(() => { + expect(screen.queryByText("cases.summary.cannot_find_matches")).toBeNull(); + }); + }); + + it("should enable the find match button", () => { + mountedComponent(, initialState, {}, [], formProps); + + expect(screen.getByRole("button", { name: "cases.summary.find_match" })).toBeEnabled(); + }); + }); + + describe("when is new record", () => { + it("should not dispatch fetchmatchedTraces", () => { + const { store } = mountedComponent( + , + initialState, + {}, + [], + formProps + ); + + const calls = store.getActions(); + + expect(calls).toHaveLength(0); + }); + }); +}); diff --git a/app/javascript/components/summary/component.unit.test.js b/app/javascript/components/summary/component.unit.test.js deleted file mode 100644 index eaf3f34e38..0000000000 --- a/app/javascript/components/summary/component.unit.test.js +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { Tooltip } from "@material-ui/core"; - -import { setupMountedComponent } from "../../test"; -import RecordFormTitle from "../record-form/form/record-form-title"; -import { FormSectionField } from "../record-form"; -import ActionButton from "../action-button"; -import SubformDrawer from "../record-form/form/subforms/subform-drawer"; - -import { FIELD_NAMES } from "./constants"; -import Summary from "./component"; - -describe("", () => { - let component; - - const props = { - record: fromJS({}), - recordType: "case", - mobileDisplay: false, - handleToggleNav: () => {}, - form: {}, - mode: { isNew: false } - }; - const formProps = { - initialValues: { - name: "" - } - }; - const initialState = fromJS({}); - - beforeEach(() => { - ({ component } = setupMountedComponent(Summary, props, initialState, [], formProps)); - }); - - it("should render a component", () => { - expect(component.find(RecordFormTitle)).to.have.lengthOf(1); - }); - - it("should render 3 component", () => { - expect(component.find(ActionButton)).to.have.lengthOf(3); - }); - - it("should render 5 components", () => { - expect(component.find(FormSectionField)).to.have.lengthOf(5); - }); - - it("should render 2 components", () => { - expect(component.find(SubformDrawer)).to.have.lengthOf(2); - }); - - context("when consent_for_tracing is not set", () => { - let comp; - - beforeEach(() => { - ({ component: comp } = setupMountedComponent(Summary, props, initialState, [], formProps)); - }); - - it("should render a tooltip for the find match button", () => { - expect(comp.find(ActionButton).find(Tooltip)).to.have.lengthOf(1); - }); - - it("should disable the find match button", () => { - const findMatchButton = comp - .find(ActionButton) - .findWhere(elem => elem.text() === "cases.summary.find_match") - .first(); - - expect(findMatchButton.props().rest.disabled).to.be.true; - }); - }); - - context("when consent_for_tracing is set to true", () => { - let comp; - - beforeEach(() => { - ({ component: comp } = setupMountedComponent( - Summary, - { ...props, values: { [FIELD_NAMES.consent_for_tracing]: true } }, - initialState, - [], - formProps - )); - }); - - it("should not render a tooltip for the find match button", () => { - expect(comp.find(ActionButton).find(Tooltip)).to.have.lengthOf(0); - }); - - it("should enable the find match button", () => { - const findMatchButton = comp - .find(ActionButton) - .findWhere(elem => elem.text() === "cases.summary.find_match") - .first(); - - expect(findMatchButton.props().rest.disabled).to.be.false; - }); - }); - - context("when is new record", () => { - beforeEach(() => { - ({ component } = setupMountedComponent( - Summary, - { ...props, mode: { isNew: true } }, - initialState, - [], - formProps - )); - }); - - it("should not dispatch fetchmatchedTraces", () => { - const calls = component.props().store.getActions(); - - expect(calls).to.have.lengthOf(0); - }); - }); -}); diff --git a/app/javascript/components/summary/components/comparison-form/component.jsx b/app/javascript/components/summary/components/comparison-form/component.jsx index ca83bc8a53..39448a05ce 100644 --- a/app/javascript/components/summary/components/comparison-form/component.jsx +++ b/app/javascript/components/summary/components/comparison-form/component.jsx @@ -10,7 +10,7 @@ import { RECORD_TYPES_PLURAL } from "../../../../config"; import { NAME } from "./constants"; -const Component = ({ selectedForm, recordType, potentialMatch, setSelectedForm }) => { +function Component({ selectedForm, recordType, potentialMatch, setSelectedForm }) { const dispatch = useDispatch(); useEffect(() => { @@ -30,7 +30,7 @@ const Component = ({ selectedForm, recordType, potentialMatch, setSelectedForm } /> ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/summary/components/comparison-form/component.unit.test.js b/app/javascript/components/summary/components/comparison-form/component.spec.js similarity index 83% rename from app/javascript/components/summary/components/comparison-form/component.unit.test.js rename to app/javascript/components/summary/components/comparison-form/component.spec.js index ea3eb5b051..3acf322582 100644 --- a/app/javascript/components/summary/components/comparison-form/component.unit.test.js +++ b/app/javascript/components/summary/components/comparison-form/component.spec.js @@ -2,16 +2,15 @@ import { fromJS } from "immutable"; -import TraceComparisonForm from "../../../record-form/form/subforms/subform-traces/components/trace-comparison-form"; -import { setupMountedComponent } from "../../../../test"; +import { mountedComponent, screen } from "../../../../test-utils"; import { FormSectionRecord, FieldRecord, TEXT_FIELD, DATE_FIELD, NUMERIC_FIELD, SELECT_FIELD } from "../../../form"; import { RECORD_TYPES } from "../../../../config"; -import MatchesForm from "./component"; +import ComparisonForm from "./component"; -describe("", () => { - let component; +describe("", () => { const recordModule = "record-module"; + const props = { selectedForm: "test", recordType: "cases", @@ -19,7 +18,7 @@ describe("", () => { handleBack: () => {} }; - const state = fromJS({ + const initialState = fromJS({ forms: { formSections: { 1: FormSectionRecord({ @@ -85,11 +84,10 @@ describe("", () => { } }); - beforeEach(() => { - ({ component } = setupMountedComponent(MatchesForm, props, state)); - }); + it("should render 1 component", () => { + mountedComponent(, initialState); - it("should render 1 components", () => { - expect(component.find(TraceComparisonForm)).to.have.lengthOf(1); + expect(screen.getByTestId("trace-actions")).toBeInTheDocument(); + expect(screen.getByTestId("trace-comparison-form")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/summary/components/matched-traces/component.jsx b/app/javascript/components/summary/components/matched-traces/component.jsx index 3000589723..fc4c429538 100644 --- a/app/javascript/components/summary/components/matched-traces/component.jsx +++ b/app/javascript/components/summary/components/matched-traces/component.jsx @@ -17,7 +17,7 @@ import { MatchedTracePanel } from "./components"; import { NAME } from "./constants"; import css from "./styles.css"; -const Component = ({ data, loading, record, setSelectedForm }) => { +function Component({ data = fromJS([]), loading, record, setSelectedForm }) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -88,14 +88,10 @@ const Component = ({ data, loading, record, setSelectedForm }) => { ); -}; +} Component.displayName = NAME; -Component.defaultProps = { - data: fromJS([]) -}; - Component.propTypes = { data: PropTypes.object, loading: PropTypes.bool, diff --git a/app/javascript/components/summary/components/matched-traces/component.unit.test.js b/app/javascript/components/summary/components/matched-traces/component.spec.js similarity index 51% rename from app/javascript/components/summary/components/matched-traces/component.unit.test.js rename to app/javascript/components/summary/components/matched-traces/component.spec.js index a1cd311d32..73e90a0a24 100644 --- a/app/javascript/components/summary/components/matched-traces/component.unit.test.js +++ b/app/javascript/components/summary/components/matched-traces/component.spec.js @@ -2,13 +2,11 @@ import { fromJS } from "immutable"; -import { setupMountedComponent } from "../../../../test"; +import { mountedComponent, screen } from "../../../../test-utils"; -import { MatchedTracePanel } from "./components"; import MatchedTraces from "./component"; describe("", () => { - let component; const props = { data: fromJS([{ id: "1234567" }]), setSelectedForm: () => {}, @@ -23,23 +21,17 @@ describe("", () => { }) }; - beforeEach(() => { - ({ component } = setupMountedComponent(MatchedTraces, props, {})); - }); - it("should render 1 component", () => { - expect(component.find(MatchedTracePanel)).to.have.lengthOf(1); - }); - - context("when is new record", () => { - let newRecordComponent; + mountedComponent(); - beforeEach(() => { - ({ component: newRecordComponent } = setupMountedComponent(MatchedTraces, { ...props, record: {} }, {})); - }); + expect(screen.getByTestId("matched-trace-panel")).toBeInTheDocument(); + }); + describe("when is new record", () => { it("should not render component", () => { - expect(newRecordComponent.find(MatchedTracePanel)).to.have.lengthOf(0); + mountedComponent(); + + expect(screen.queryByTestId("matched-trace-panel")).toBeNull(); }); }); }); diff --git a/app/javascript/components/summary/components/matched-traces/components/matched-trace-panel/component.jsx b/app/javascript/components/summary/components/matched-traces/components/matched-trace-panel/component.jsx index c6001cf3e4..f5c356967d 100644 --- a/app/javascript/components/summary/components/matched-traces/components/matched-trace-panel/component.jsx +++ b/app/javascript/components/summary/components/matched-traces/components/matched-trace-panel/component.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Accordion, AccordionSummary } from "@material-ui/core"; -import ChevronRightIcon from "@material-ui/icons/ChevronRight"; +import { Accordion, AccordionSummary } from "@mui/material"; +import ChevronRightIcon from "@mui/icons-material/ChevronRight"; import ActionButton from "../../../../../action-button"; import { ACTION_BUTTON_TYPES } from "../../../../../action-button/constants"; @@ -10,7 +10,7 @@ import { getShortIdFromUniqueId } from "../../../../../records"; import { NAME } from "./constants"; -const Component = ({ matchedTrace, setOpen, setSelectedTraceId }) => { +function Component({ matchedTrace, setOpen, setSelectedTraceId }) { const matchedTraceId = matchedTrace.get("id"); const handleOnClick = id => { setOpen(true); @@ -19,8 +19,13 @@ const Component = ({ matchedTrace, setOpen, setSelectedTraceId }) => { const handleClickAccordion = () => handleOnClick(matchedTraceId); return ( - - } aria-controls="filter-controls-content" id={1}> + + } + aria-controls="filter-controls-content" + id={1} + data-testid="matched-trace-panel-summary" + > { ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/summary/components/matched-traces/components/matched-trace-panel/component.spec.js b/app/javascript/components/summary/components/matched-traces/components/matched-trace-panel/component.spec.js new file mode 100644 index 0000000000..007ca77a58 --- /dev/null +++ b/app/javascript/components/summary/components/matched-traces/components/matched-trace-panel/component.spec.js @@ -0,0 +1,29 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import { fromJS } from "immutable"; + +import { mountedComponent, screen } from "../../../../../../test-utils"; + +import MatchedTracePanel from "./component"; + +describe("", () => { + const props = { css: {}, matchedTrace: fromJS({ id: "123457" }) }; + + it("should render 1 component", () => { + mountedComponent(); + + expect(screen.getByTestId("matched-trace-panel")).toBeInTheDocument(); + }); + + it("should render 1 component", () => { + mountedComponent(); + + expect(screen.getByTestId("matched-trace-panel-summary")).toBeInTheDocument(); + }); + + it("should render 1 component", () => { + mountedComponent(); + + expect(screen.getByTestId("action-button")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/summary/components/matched-traces/components/matched-trace-panel/component.unit.test.js b/app/javascript/components/summary/components/matched-traces/components/matched-trace-panel/component.unit.test.js deleted file mode 100644 index f2631c8058..0000000000 --- a/app/javascript/components/summary/components/matched-traces/components/matched-trace-panel/component.unit.test.js +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Accordion, AccordionSummary } from "@material-ui/core"; -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../../../../test"; -import ActionButton from "../../../../../action-button"; - -import MatchedTracePanel from "./component"; - -describe("", () => { - let component; - const props = { css: {}, matchedTrace: fromJS({ id: "123457" }) }; - - beforeEach(() => { - ({ component } = setupMountedComponent(MatchedTracePanel, props, {})); - }); - - it("should render 1 component", () => { - expect(component.find(Accordion)).to.have.lengthOf(1); - }); - - it("should render 1 component", () => { - expect(component.find(AccordionSummary)).to.have.lengthOf(1); - }); - - it("should render 1 component", () => { - expect(component.find(ActionButton)).to.have.lengthOf(1); - }); -}); diff --git a/app/javascript/components/summary/components/matches-form/component.jsx b/app/javascript/components/summary/components/matches-form/component.jsx index 5e57af58f5..c3f45645f4 100644 --- a/app/javascript/components/summary/components/matches-form/component.jsx +++ b/app/javascript/components/summary/components/matches-form/component.jsx @@ -4,7 +4,7 @@ import { useEffect } from "react"; import { useDispatch } from "react-redux"; import PropTypes from "prop-types"; import isEmpty from "lodash/isEmpty"; -import { List, ListItemText } from "@material-ui/core"; +import { List, ListItemText } from "@mui/material"; import { fromJS } from "immutable"; import { @@ -22,7 +22,7 @@ import { useMemoizedSelector } from "../../../../libs"; import { NAME } from "./constants"; import { columns } from "./utils"; -const Component = ({ css, i18n, mode, open, record, setSelectedForm, matchedTracesData }) => { +function Component({ css, i18n, mode, open, record, setSelectedForm, matchedTracesData }) { const dispatch = useDispatch(); const data = useMemoizedSelector(state => getCasesPotentialMatches(state)); @@ -69,7 +69,7 @@ const Component = ({ css, i18n, mode, open, record, setSelectedForm, matchedTrac ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/summary/components/matches-form/component.unit.test.js b/app/javascript/components/summary/components/matches-form/component.spec.js similarity index 73% rename from app/javascript/components/summary/components/matches-form/component.unit.test.js rename to app/javascript/components/summary/components/matches-form/component.spec.js index 05178e73ad..e1ee19f7c1 100644 --- a/app/javascript/components/summary/components/matches-form/component.unit.test.js +++ b/app/javascript/components/summary/components/matches-form/component.spec.js @@ -1,15 +1,12 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { List, ListItemText } from "@material-ui/core"; -import IndexTable from "../../../index-table"; -import { setupMountedComponent } from "../../../../test"; +import { mountedComponent, screen } from "../../../../test-utils"; import MatchesForm from "./component"; describe("", () => { - let component; const props = { record: fromJS({ id: "12345678", case_id_display: "123abc" }), title: "Test Title", @@ -63,18 +60,14 @@ describe("", () => { }); beforeEach(() => { - ({ component } = setupMountedComponent(MatchesForm, props, state, [], formProps)); + mountedComponent(, state, {}, [], formProps); }); - it("should render 1 components", () => { - expect(component.find(List)).to.have.lengthOf(1); - }); - - it("should render 2 components", () => { - expect(component.find(ListItemText)).to.have.lengthOf(2); + it("should render tracing request id in the title", () => { + expect(screen.getByText("tracing_requests.id: #123abc")).toBeInTheDocument(); }); it("should render 1 components", () => { - expect(component.find(IndexTable)).to.have.lengthOf(1); + expect(screen.getByRole("grid")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/summary/components/matches-form/utils.js b/app/javascript/components/summary/components/matches-form/utils.js index 115692e1af..565a8e4a1f 100644 --- a/app/javascript/components/summary/components/matches-form/utils.js +++ b/app/javascript/components/summary/components/matches-form/utils.js @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. /* eslint-disable react/display-name, react/no-multi-comp, import/prefer-default-export */ -import clsx from "clsx"; +import { cx } from "@emotion/css"; import ActionButton from "../../../action-button"; import { ACTION_BUTTON_TYPES } from "../../../action-button/constants"; @@ -47,7 +47,7 @@ export const columns = (i18n, css, onTracingRequestClick, matchedTracesIds) => [ name: "likelihood", options: { customBodyRender: value => { - const classes = clsx({ [css.likelyScore]: value }); + const classes = cx({ [css.likelyScore]: value }); return {SCORE_TYPES[value]}; } diff --git a/app/javascript/components/tooltip/component.jsx b/app/javascript/components/tooltip/component.jsx index 05d08ce9b1..21b1dc42d7 100644 --- a/app/javascript/components/tooltip/component.jsx +++ b/app/javascript/components/tooltip/component.jsx @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Tooltip as MuiToolTip } from "@material-ui/core"; +import { Tooltip as MuiToolTip } from "@mui/material"; import PropTypes from "prop-types"; import { ConditionalWrapper } from "../../libs"; @@ -8,7 +8,7 @@ import { useI18n } from "../i18n"; import css from "./styles.css"; -const Tooltip = ({ children, title, i18nTitle }) => { +function Tooltip({ children, title = "", i18nTitle = false }) { const i18n = useI18n(); const commonTooltipProps = { @@ -27,15 +27,10 @@ const Tooltip = ({ children, title, i18nTitle }) => { {children} ); -}; +} Tooltip.displayName = "Tooltip"; -Tooltip.defaultProps = { - i18nTitle: false, - title: "" -}; - Tooltip.propTypes = { children: PropTypes.node.isRequired, i18nTitle: PropTypes.bool, diff --git a/app/javascript/components/tooltip/component.spec.js b/app/javascript/components/tooltip/component.spec.js new file mode 100644 index 0000000000..a6599c6171 --- /dev/null +++ b/app/javascript/components/tooltip/component.spec.js @@ -0,0 +1,34 @@ +import { mountedComponent, screen } from "../../test-utils"; + +import Tooltip from "./component"; + +describe("components/tooltip", () => { + it("renders tooltip", () => { + // eslint-disable-next-line react/display-name + function TooltipComponent() { + return ( + +
wrapped children
+
+ ); + } + + mountedComponent(); + expect(screen.getByText(/wrapped children/i)).toBeInTheDocument(); + }); + + it("does not render tooltip without title", () => { + // eslint-disable-next-line react/display-name, react/no-multi-comp + function TooltipComponent() { + return ( + +
wrapped children
+
+ ); + } + + mountedComponent(); + expect(screen.getByText(/wrapped children/i)).toBeInTheDocument(); + expect(screen.queryAllByRole("tooltip")).toHaveLength(0); + }); +}); diff --git a/app/javascript/components/tooltip/component.unit.test.js b/app/javascript/components/tooltip/component.unit.test.js deleted file mode 100644 index a3b924f3da..0000000000 --- a/app/javascript/components/tooltip/component.unit.test.js +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Tooltip as MuiTooltip } from "@material-ui/core"; - -import { setupMountedComponent } from "../../test"; - -import Tooltip from "./component"; - -describe("components/tooltip", () => { - it("renders tooltip", () => { - const TooltipComponent = () => ( - -
wrapped children
-
- ); - const { component } = setupMountedComponent(TooltipComponent); - - expect(component.find(MuiTooltip).prop("title")).to.equal("wrapper content"); - expect(component.contains("wrapped children")).to.be.true; - }); - - it("does not render tooltip without title", () => { - const TooltipComponent = () => ( - -
wrapped children
-
- ); - const { component } = setupMountedComponent(TooltipComponent); - - expect(component.find(MuiTooltip)).to.have.lengthOf(0); - expect(component.contains("wrapped children")).to.be.true; - }); -}); diff --git a/app/javascript/components/transitions/TransitionPanel.jsx b/app/javascript/components/transitions/TransitionPanel.jsx index 85ef7a34d8..88b72edbbd 100644 --- a/app/javascript/components/transitions/TransitionPanel.jsx +++ b/app/javascript/components/transitions/TransitionPanel.jsx @@ -2,12 +2,12 @@ import { useState } from "react"; import PropTypes from "prop-types"; -import { Accordion } from "@material-ui/core"; +import { Accordion } from "@mui/material"; import { TRANSITION_PANEL_NAME as NAME } from "./constants"; import css from "./styles.css"; -const TransitionPanel = ({ children }) => { +function TransitionPanel({ children }) { const [expanded, setExpanded] = useState(false); const handleExpanded = () => { @@ -15,11 +15,11 @@ const TransitionPanel = ({ children }) => { }; return ( - + {children} ); -}; +} TransitionPanel.displayName = NAME; diff --git a/app/javascript/components/transitions/TransitionPanel.spec.js b/app/javascript/components/transitions/TransitionPanel.spec.js new file mode 100644 index 0000000000..da064fcd68 --- /dev/null +++ b/app/javascript/components/transitions/TransitionPanel.spec.js @@ -0,0 +1,21 @@ +import { mountedComponent, screen } from "../../test-utils"; + +import TransitionPanel from "./TransitionPanel"; + +describe("", () => { + const props = { + children:

This is a children

+ }; + + it("renders a

as children of TransitionPanel", () => { + mountedComponent(); + + expect(screen.getByText(/This is a children/i)).toBeInTheDocument(); + }); + + it("renders an Accordion component", () => { + mountedComponent(); + + expect(screen.getByTestId("accordion")).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/transitions/TransitionPanel.unit.test.js b/app/javascript/components/transitions/TransitionPanel.unit.test.js deleted file mode 100644 index b26aa4bcf7..0000000000 --- a/app/javascript/components/transitions/TransitionPanel.unit.test.js +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../test"; - -import TransitionPanel from "./TransitionPanel"; - -describe("", () => { - let component; - const props = { - children:

This is a children

- }; - - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionPanel, props)); - }); - - it("renders a

as children of TransitionPanel", () => { - const cpTransitionPanel = component.find(TransitionPanel); - - expect(cpTransitionPanel.find("p").props().children).to.equal("This is a children"); - }); -}); diff --git a/app/javascript/components/transitions/TransitionStatus.jsx b/app/javascript/components/transitions/TransitionStatus.jsx index 444cc4184e..5e384f2c5e 100644 --- a/app/javascript/components/transitions/TransitionStatus.jsx +++ b/app/javascript/components/transitions/TransitionStatus.jsx @@ -1,25 +1,25 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import Chip from "@material-ui/core/Chip"; +import Chip from "@mui/material/Chip"; import PropTypes from "prop-types"; -import clsx from "clsx"; +import { cx } from "@emotion/css"; import { useI18n } from "../i18n"; import { TRANSITION_STATUS_NAME as NAME } from "./constants"; import css from "./styles.css"; -const TransitionStatus = ({ status }) => { +function TransitionStatus({ status }) { const i18n = useI18n(); - const classes = clsx(css.chip, css[status]); + const classes = cx(css.chip, css[status]); return (

); -}; +} TransitionStatus.displayName = NAME; diff --git a/app/javascript/components/transitions/TransitionStatus.spec.js b/app/javascript/components/transitions/TransitionStatus.spec.js new file mode 100644 index 0000000000..0b5b4d7d03 --- /dev/null +++ b/app/javascript/components/transitions/TransitionStatus.spec.js @@ -0,0 +1,14 @@ +import { mountedComponent, screen } from "../../test-utils"; + +import TransitionStatus from "./TransitionStatus"; + +describe("", () => { + const props = { + status: "inprogress" + }; + + it("renders a Chip TransitionStatus", () => { + mountedComponent(); + expect(screen.getByText(/transition.status.inprogress/i)).toBeInTheDocument(); + }); +}); diff --git a/app/javascript/components/transitions/TransitionStatus.unit.test.js b/app/javascript/components/transitions/TransitionStatus.unit.test.js deleted file mode 100644 index 80d32d18fb..0000000000 --- a/app/javascript/components/transitions/TransitionStatus.unit.test.js +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Chip } from "@material-ui/core"; - -import { setupMountedComponent } from "../../test"; - -import TransitionStatus from "./TransitionStatus"; - -describe("", () => { - let component; - const props = { - status: "inprogress" - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionStatus, props)); - }); - - it("renders a Chip TransitionStatus", () => { - expect(component.find(TransitionStatus).find(Chip)).to.have.length(1); - }); -}); diff --git a/app/javascript/components/transitions/assignments/AssignmentsDetails.jsx b/app/javascript/components/transitions/assignments/AssignmentsDetails.jsx index 2c19203418..592d30867d 100644 --- a/app/javascript/components/transitions/assignments/AssignmentsDetails.jsx +++ b/app/javascript/components/transitions/assignments/AssignmentsDetails.jsx @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Divider, Grid } from "@material-ui/core"; +import { Divider, Grid } from "@mui/material"; import PropTypes from "prop-types"; import { useI18n } from "../../i18n"; @@ -8,7 +8,7 @@ import DisplayData from "../../display-data"; import { ASSIGNMENTS_DETAILS_NAME as NAME } from "./constants"; -const AssignmentsDetails = ({ transition, classes }) => { +function AssignmentsDetails({ transition, classes }) { const i18n = useI18n(); return ( @@ -28,7 +28,7 @@ const AssignmentsDetails = ({ transition, classes }) => { ); -}; +} AssignmentsDetails.displayName = NAME; diff --git a/app/javascript/components/transitions/assignments/AssignmentsDetails.unit.test.js b/app/javascript/components/transitions/assignments/AssignmentsDetails.spec.js similarity index 73% rename from app/javascript/components/transitions/assignments/AssignmentsDetails.unit.test.js rename to app/javascript/components/transitions/assignments/AssignmentsDetails.spec.js index d4fa5dd8fc..2a4f788d64 100644 --- a/app/javascript/components/transitions/assignments/AssignmentsDetails.unit.test.js +++ b/app/javascript/components/transitions/assignments/AssignmentsDetails.spec.js @@ -1,12 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../test"; -import DisplayData from "../../display-data"; +import { mountedComponent, screen } from "../../../test-utils"; import AssignmentsDetails from "./AssignmentsDetails"; describe("", () => { - let component; const props = { transition: { id: "4142488e-ccd9-4ac5-a3c1-c3c0fd063fc8", @@ -28,11 +25,9 @@ describe("", () => { } }; - beforeEach(() => { - ({ component } = setupMountedComponent(AssignmentsDetails, props)); - }); - it("renders 2 ", () => { - expect(component.find(DisplayData)).to.have.length(2); + mountedComponent(); + expect(screen.getByText(/transition.recipient/i)).toBeInTheDocument(); + expect(screen.getByText(/transition.recipient/i)).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/transitions/assignments/AssignmentsSummary.jsx b/app/javascript/components/transitions/assignments/AssignmentsSummary.jsx index 58132c4535..cf549afee0 100644 --- a/app/javascript/components/transitions/assignments/AssignmentsSummary.jsx +++ b/app/javascript/components/transitions/assignments/AssignmentsSummary.jsx @@ -1,13 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Grid } from "@material-ui/core"; +import { Grid } from "@mui/material"; import { useI18n } from "../../i18n"; import { ASSIGNMENTS_SUMMARY_NAME as NAME } from "./constants"; -const AssignmentsSummary = ({ transition, classes }) => { +function AssignmentsSummary({ transition, classes }) { const i18n = useI18n(); // TODO: It has to be modified, on summary should print username @@ -20,8 +20,10 @@ const AssignmentsSummary = ({ transition, classes }) => { return ( -
-
{i18n.localizeDate(transition.created_at)}
+
+
+ {i18n.localizeDate(transition.created_at)} +
{i18n.t("transition.type.assign")}
@@ -29,7 +31,7 @@ const AssignmentsSummary = ({ transition, classes }) => { {/* {renderTransitioned} */} ); -}; +} AssignmentsSummary.displayName = NAME; diff --git a/app/javascript/components/transitions/assignments/AssignmentsSummary.unit.test.js b/app/javascript/components/transitions/assignments/AssignmentsSummary.spec.js similarity index 68% rename from app/javascript/components/transitions/assignments/AssignmentsSummary.unit.test.js rename to app/javascript/components/transitions/assignments/AssignmentsSummary.spec.js index 075e9da13f..d3443ab50a 100644 --- a/app/javascript/components/transitions/assignments/AssignmentsSummary.unit.test.js +++ b/app/javascript/components/transitions/assignments/AssignmentsSummary.spec.js @@ -1,11 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../test"; +import { mountedComponent, screen } from "../../../test-utils"; import AssignmentsSummary from "./AssignmentsSummary"; describe("", () => { - let component; const props = { transition: { id: "4142488e-ccd9-4ac5-a3c1-c3c0fd063fc8", @@ -27,13 +25,10 @@ describe("", () => { } }; - beforeEach(() => { - ({ component } = setupMountedComponent(AssignmentsSummary, props)); - }); - it("renders divs with its corresponding class", () => { - expect(component.find("div.wrapperStyle")).to.have.lengthOf(1); - expect(component.find("div.titleHeaderStyle")).to.have.lengthOf(1); - expect(component.find("div.dateStyle")).to.have.lengthOf(1); + mountedComponent(); + expect(screen.getByText(/ransition.type.assign/i)).toBeInTheDocument(); + expect(screen.getByTestId("wrapper")).toBeInTheDocument(); + expect(screen.getByTestId("date")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/transitions/components/date-transitions-summary/component.jsx b/app/javascript/components/transitions/components/date-transitions-summary/component.jsx index 025c63797d..5cbf44c232 100644 --- a/app/javascript/components/transitions/components/date-transitions-summary/component.jsx +++ b/app/javascript/components/transitions/components/date-transitions-summary/component.jsx @@ -10,7 +10,7 @@ import css from "../../styles.css"; import { NAME } from "./constants"; -const Component = ({ value }) => { +function Component({ value }) { const i18n = useI18n(); if (isEmpty(value)) { @@ -19,7 +19,7 @@ const Component = ({ value }) => { if (i18n.locale === LOCALE_KEYS.ne) { return ( -
+
{ ); } - return
{i18n.localizeDate(value)}
; -}; + return ( +
+ {i18n.localizeDate(value)} +
+ ); +} Component.displayName = NAME; diff --git a/app/javascript/components/transitions/components/date-transitions-summary/component.spec.js b/app/javascript/components/transitions/components/date-transitions-summary/component.spec.js new file mode 100644 index 0000000000..2139f66d21 --- /dev/null +++ b/app/javascript/components/transitions/components/date-transitions-summary/component.spec.js @@ -0,0 +1,25 @@ +import { mountedComponent, screen } from "../../../../test-utils"; + +import DateTransitionsSummary from "./component"; + +describe("", () => { + const props = { + value: "2020-04-15T14:04", + label: "label-test", + name: "this-is-name" + }; + + it("renders a ", () => { + mountedComponent(); + expect(screen.getByTestId("date")).toBeInTheDocument(); + }); + + describe("when ne locale", () => { + it("renders NepaliCalendar", () => { + global.I18n.locale = "ne"; + mountedComponent(); + + expect(screen.queryAllByTestId("nepali-calendar")).toHaveLength(1); + }); + }); +}); diff --git a/app/javascript/components/transitions/components/date-transitions-summary/component.unit.test.js b/app/javascript/components/transitions/components/date-transitions-summary/component.unit.test.js deleted file mode 100644 index 21000c9b2d..0000000000 --- a/app/javascript/components/transitions/components/date-transitions-summary/component.unit.test.js +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../../test"; -import NepaliCalendar from "../../../nepali-calendar-input"; - -import DateTransitionsSummary from "./component"; - -describe("", () => { - let component; - - const props = { - value: "2020-04-150T14:04", - label: "label-test", - name: "this-is-name" - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(DateTransitionsSummary, props, fromJS({}))); - }); - - it("renders a ", () => { - expect(component.find(DateTransitionsSummary)).to.have.lengthOf(1); - }); - - describe("when ne locale", () => { - it.skip("renders NepaliCalendar", () => { - window.I18n.locale = "ne"; - - expect(component.find(NepaliCalendar)).to.have.lengthOf(1); - }); - - after(() => { - window.I18n.locale = "en"; - }); - }); -}); diff --git a/app/javascript/components/transitions/components/date-transitions/component.jsx b/app/javascript/components/transitions/components/date-transitions/component.jsx index 32b3d56618..5f717246e4 100644 --- a/app/javascript/components/transitions/components/date-transitions/component.jsx +++ b/app/javascript/components/transitions/components/date-transitions/component.jsx @@ -11,7 +11,7 @@ import css from "../../styles.css"; import { NAME } from "./constants"; -const Component = ({ name, label, value }) => { +function Component({ name, label, value }) { const i18n = useI18n(); if (isEmpty(value)) { @@ -35,7 +35,7 @@ const Component = ({ name, label, value }) => { } return ; -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/transitions/components/date-transitions/component.spec.js b/app/javascript/components/transitions/components/date-transitions/component.spec.js new file mode 100644 index 0000000000..c56d648d34 --- /dev/null +++ b/app/javascript/components/transitions/components/date-transitions/component.spec.js @@ -0,0 +1,26 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen } from "../../../../test-utils"; + +import DateTransitions from "./component"; + +describe("", () => { + const props = { + value: "2020-04-15T14:04", + label: "label-test", + name: "this-is-name" + }; + + it("renders label", () => { + mountedComponent(, fromJS({})); + expect(screen.getByText(/label-test/i)).toBeInTheDocument(); + }); + + describe("when ne locale", () => { + it("renders NepaliCalendar", () => { + global.I18n.locale = "ne"; + mountedComponent(); + expect(screen.queryAllByTestId("nepali-container")).toHaveLength(1); + }); + }); +}); diff --git a/app/javascript/components/transitions/components/date-transitions/component.unit.test.js b/app/javascript/components/transitions/components/date-transitions/component.unit.test.js deleted file mode 100644 index 0f01b89f16..0000000000 --- a/app/javascript/components/transitions/components/date-transitions/component.unit.test.js +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; - -import { setupMountedComponent } from "../../../../test"; -import DisplayData from "../../../display-data"; -import NepaliCalendar from "../../../nepali-calendar-input"; - -import DateTransitions from "./component"; - -describe("", () => { - let component; - - const props = { - value: "2020-04-150T14:04", - label: "label-test", - name: "this-is-name" - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(DateTransitions, props, fromJS({}))); - }); - - it("renders a ", () => { - expect(component.find(DateTransitions)).to.have.lengthOf(1); - }); - - it("renders a ", () => { - expect(component.find(DateTransitions).find(DisplayData)).to.have.lengthOf(1); - }); - - describe("when ne locale", () => { - it.skip("renders NepaliCalendar", () => { - window.I18n.locale = "ne"; - - expect(component.find(NepaliCalendar)).to.have.lengthOf(1); - }); - - after(() => { - window.I18n.locale = "en"; - }); - }); -}); diff --git a/app/javascript/components/transitions/components/menu-actions/component.jsx b/app/javascript/components/transitions/components/menu-actions/component.jsx index aacda02dd6..e6f38a3880 100644 --- a/app/javascript/components/transitions/components/menu-actions/component.jsx +++ b/app/javascript/components/transitions/components/menu-actions/component.jsx @@ -2,8 +2,8 @@ import { useState } from "react"; import PropTypes from "prop-types"; -import { Menu, MenuItem } from "@material-ui/core"; -import MoreVertIcon from "@material-ui/icons/MoreVert"; +import { Menu, MenuItem } from "@mui/material"; +import MoreVertIcon from "@mui/icons-material/MoreVert"; import DisableOffline from "../../../disable-offline"; import { TRANSITION_STATUS, TRANSITIONS_TYPES } from "../../constants"; @@ -23,7 +23,7 @@ import { useMemoizedSelector } from "../../../../libs"; import { NAME, REVOKE_MODAL } from "./constants"; -const Component = ({ transition, showMode, recordType, classes }) => { +function Component({ transition, showMode, recordType, classes }) { const i18n = useI18n(); const { id, @@ -139,7 +139,12 @@ const Component = ({ transition, showMode, recordType, classes }) => { const filteredActions = options.filter(option => option.condition); const actions = filteredActions.map(option => { return ( - handleAction(event, option.action)}> + handleAction(event, option.action)} + > {option.name} ); @@ -164,7 +169,13 @@ const Component = ({ transition, showMode, recordType, classes }) => { }} /> - handleClose(event)}> + handleClose(event)} + > {actions} @@ -205,7 +216,7 @@ const Component = ({ transition, showMode, recordType, classes }) => { )}
); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/transitions/components/menu-actions/component.unit.test.js b/app/javascript/components/transitions/components/menu-actions/component.spec.js similarity index 59% rename from app/javascript/components/transitions/components/menu-actions/component.unit.test.js rename to app/javascript/components/transitions/components/menu-actions/component.spec.js index 4272c4f38c..48f1aaf185 100644 --- a/app/javascript/components/transitions/components/menu-actions/component.unit.test.js +++ b/app/javascript/components/transitions/components/menu-actions/component.spec.js @@ -1,22 +1,12 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Menu } from "@material-ui/core"; import { fromJS } from "immutable"; -import DisableOffline from "../../../disable-offline"; -import ActionButton from "../../../action-button"; -import { setupMountedComponent } from "../../../../test"; +import { fireEvent, mountedComponent, screen } from "../../../../test-utils"; import { ACTIONS } from "../../../permissions"; import { TransitionRecord } from "../../records"; -import RevokeModal from "../revoke-modal"; -import TransferApproval from "../../transfers/transfer-approval"; -import ReferralAction from "../../referrals/referral-action"; import TransitionActions from "./component"; describe(" - Component", () => { - let component; - describe("Component Menu", () => { describe("with referral transition type", () => { const state = { @@ -68,110 +58,74 @@ describe(" - Component", () => { }; describe("when user has access to all menus", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionActions, props, state)); - }); - it("renders Menu", () => { - expect(component.find(Menu)).to.have.lengthOf(1); + mountedComponent(, state); + expect(screen.getByLabelText(/more/i)).toBeInTheDocument(); }); it("renders MenuItem", () => { - const menuChildren = component.find(Menu).props().children; + mountedComponent(, state); - expect(menuChildren).to.have.lengthOf(1); + expect(screen.getAllByTestId("menu-item")).toHaveLength(1); }); it("should only render the revoke option", () => { - const menuChildrenAction = component - .find(Menu) - .props() - .children.map(elem => elem.props.children); - - expect(menuChildrenAction).to.deep.equals(["actions.revoke"]); + mountedComponent(, state); + expect(screen.getByText(/actions.revoke/i)).toBeInTheDocument(); }); - context("when is offline", () => { + describe("when is offline", () => { it("should disable the actions", () => { - const { component: offlineComp } = setupMountedComponent(TransitionActions, props, { + mountedComponent(, { ...state, connectivity: { online: false } }); - - expect(offlineComp.find(DisableOffline)).to.have.lengthOf(1); - expect(offlineComp.find(ActionButton).props().disabled).to.be.true; + expect(screen.getByLabelText(/more/i)).toBeDisabled(); }); }); }); - context("when current user is recipient", () => { + describe("when current user is recipient", () => { const userRecipientState = fromJS(state).setIn(["user", "username"], "primero_cp_ar"); const referralWithAcceptOrReject = referral.set("user_can_accept_or_reject", true); - beforeEach(() => { - ({ component } = setupMountedComponent( - TransitionActions, - { - ...props, - transition: referralWithAcceptOrReject - }, - userRecipientState - )); - }); + const recipientProps = { + ...props, + transition: referralWithAcceptOrReject + }; it("should render the accept and reject actions", () => { - const menuChildrenAction = component - .find(Menu) - .props() - .children.map(elem => elem.props.children); - - expect(menuChildrenAction).to.deep.equals(["buttons.accept", "buttons.reject"]); + mountedComponent(, userRecipientState); + expect(screen.getByText(/buttons.accept/i)).toBeInTheDocument(); + expect(screen.getByText(/buttons.reject/i)).toBeInTheDocument(); }); - context("when the referral is accepted", () => { - beforeEach(() => { - ({ component } = setupMountedComponent( - TransitionActions, - { ...props, transition: props.transition.set("status", "accepted") }, - userRecipientState - )); - }); + describe("when the referral is accepted", () => { + const acceptedProps = { ...props, transition: props.transition.set("status", "accepted") }; it("should only render the done action", () => { - const menuChildrenAction = component - .find(Menu) - .props() - .children.map(elem => elem.props.children); - - expect(menuChildrenAction).to.deep.equals(["buttons.done"]); + mountedComponent(, userRecipientState); + expect(screen.getByText(/buttons.done/i)).toBeInTheDocument(); }); }); - context("when the referral is rejected", () => { - beforeEach(() => { - ({ component } = setupMountedComponent( - TransitionActions, - { ...props, transition: props.transition.set("status", "rejected") }, - userRecipientState - )); - }); + describe("when the referral is rejected", () => { + const rejectedProps = { ...props, transition: props.transition.set("status", "rejected") }; it("should not render actions", () => { - expect(component.find(Menu)).to.have.lengthOf(0); + mountedComponent(, userRecipientState); + expect(screen.queryByTestId(/long-menu/i)).toBeNull(); }); }); }); describe("when user has not access to all menus", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionActions, props, { + it("renders Menu", () => { + mountedComponent(, { ...state, user: { permissions: { cases: [ACTIONS.READ] } } - })); - }); - - it("renders Menu", () => { - expect(component.find(Menu)).to.be.empty; + }); + expect(screen.queryByTestId(/long-menu/i)).toBeNull(); }); }); }); @@ -227,37 +181,30 @@ describe(" - Component", () => { }; describe("when user has access to all menus", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionActions, props, state)); - }); - it("renders Menu", () => { - expect(component.find(Menu)).to.have.lengthOf(1); + mountedComponent(, state); + expect(screen.getByRole("button")).toBeInTheDocument(); }); it("renders MenuItem", () => { - const menuChildren = component.find(Menu).props().children; - - expect(menuChildren).to.have.lengthOf(1); + mountedComponent(, state); + expect(screen.getAllByTestId(/menu-item/i)).toHaveLength(1); }); it("renders MenuItem with revoke option", () => { - const menuChildrenAction = component.find(Menu).props().children[0].props.children; - - expect(menuChildrenAction).to.be.equals("actions.revoke"); + mountedComponent(, state); + expect(screen.getByText(/actions.revoke/i)).toBeInTheDocument(); }); }); describe("when user has not access to all menus", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionActions, props, { + it("renders Menu", () => { + mountedComponent(, { ...state, user: { permissions: { cases: [ACTIONS.READ] } } - })); - }); + }); - it("renders Menu", () => { - expect(component.find(Menu)).to.be.empty; + expect(screen.queryByTestId(/long-menu/i)).toBeNull(); }); }); }); @@ -310,23 +257,11 @@ describe(" - Component", () => { classes: {} }; - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionActions, props, state)); - }); - it("renders RevokeModal", () => { - expect(component.find(RevokeModal)).to.have.lengthOf(1); - }); - - it("renders valid props for RevokeModal components", () => { - const exportProps = { ...component.find(RevokeModal).props() }; - - expect(component.find(RevokeModal)).to.have.lengthOf(1); - ["name", "open", "transition", "close", "recordType", "pending", "setPending"].forEach(property => { - expect(exportProps).to.have.property(property); - delete exportProps[property]; - }); - expect(exportProps).to.be.empty; + mountedComponent(, state); + fireEvent.click(screen.getByRole("button")); + fireEvent.click(screen.getByRole("menuitem")); + expect(screen.getByRole("dialog")).toBeInTheDocument(); }); }); @@ -382,33 +317,9 @@ describe(" - Component", () => { classes: {} }; - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionActions, props, state)); - }); - it("renders TransferApproval", () => { - expect(component.find(TransferApproval)).to.have.lengthOf(1); - }); - - it("renders valid props for TransferApproval components", () => { - const exportProps = { ...component.find(TransferApproval).props() }; - - expect(component.find(TransferApproval)).to.have.lengthOf(1); - [ - "openTransferDialog", - "close", - "approvalType", - "recordId", - "transferId", - "recordType", - "pending", - "setPending", - "dialogName" - ].forEach(property => { - expect(exportProps).to.have.property(property); - delete exportProps[property]; - }); - expect(exportProps).to.be.empty; + mountedComponent(, state); + expect(screen.getByText(/actions.revoke/i)).toBeInTheDocument(); }); }); @@ -459,33 +370,10 @@ describe(" - Component", () => { classes: {} }; - beforeEach(() => { - ({ component } = setupMountedComponent(TransitionActions, props, state)); - }); - it("renders ReferralAction", () => { - expect(component.find(ReferralAction)).to.have.lengthOf(1); - }); - - it("renders valid props for ReferralAction components", () => { - const exportProps = { ...component.find(ReferralAction).props() }; - - expect(component.find(ReferralAction)).to.have.lengthOf(1); - [ - "openReferralDialog", - "close", - "recordId", - "pending", - "setPending", - "transistionId", - "recordType", - "dialogName", - "referralType" - ].forEach(property => { - expect(exportProps).to.have.property(property); - delete exportProps[property]; - }); - expect(exportProps).to.be.empty; + mountedComponent(, state); + fireEvent.click(screen.getByRole("button")); + expect(screen.getByRole("menuitem")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/transitions/components/revoke-modal/component.jsx b/app/javascript/components/transitions/components/revoke-modal/component.jsx index 986d9fe316..9fa93038a5 100644 --- a/app/javascript/components/transitions/components/revoke-modal/component.jsx +++ b/app/javascript/components/transitions/components/revoke-modal/component.jsx @@ -16,7 +16,7 @@ import { useMemoizedSelector } from "../../../../libs"; import { revokeTransition } from "./action-creators"; import { NAME } from "./constants"; -const Component = ({ name, close, open, pending, recordType, setPending, transition }) => { +function Component({ name, close, open, pending, recordType, setPending, transition }) { const i18n = useI18n(); const dispatch = useDispatch(); const transitionType = transition.type.toLowerCase(); @@ -82,7 +82,7 @@ const Component = ({ name, close, open, pending, recordType, setPending, transit })} ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/transitions/components/revoke-modal/component.unit.test.js b/app/javascript/components/transitions/components/revoke-modal/component.spec.js similarity index 78% rename from app/javascript/components/transitions/components/revoke-modal/component.unit.test.js rename to app/javascript/components/transitions/components/revoke-modal/component.spec.js index 7f3da61d55..093b4a174c 100644 --- a/app/javascript/components/transitions/components/revoke-modal/component.unit.test.js +++ b/app/javascript/components/transitions/components/revoke-modal/component.spec.js @@ -2,13 +2,11 @@ import { fromJS } from "immutable"; -import { setupMountedComponent } from "../../../../test"; -import ActionDialog from "../../../action-dialog"; +import { mountedComponent, screen } from "../../../../test-utils"; import RevokeModal from "./component"; describe(" - Component", () => { - let component; const props = { name: "transferModal-1", close: () => {}, @@ -35,10 +33,10 @@ describe(" - Component", () => { const state = fromJS({}); beforeEach(() => { - ({ component } = setupMountedComponent(RevokeModal, props, state)); + mountedComponent(, state); }); it("renders ActionDialog component", () => { - expect(component.find(ActionDialog)).to.have.lengthOf(1); + expect(screen.getByRole("dialog")).toBeInTheDocument(1); }); }); diff --git a/app/javascript/components/transitions/container.jsx b/app/javascript/components/transitions/container.jsx index b6ec50e3ef..3aea568c93 100644 --- a/app/javascript/components/transitions/container.jsx +++ b/app/javascript/components/transitions/container.jsx @@ -16,7 +16,7 @@ import renderTransition from "./render-transition"; import css from "./styles.css"; import { fetchTransitions } from "./action-creators"; -const Transitions = ({ +function Transitions({ fetchable = false, isReferral, recordType, @@ -24,7 +24,7 @@ const Transitions = ({ showMode, mobileDisplay, handleToggleNav -}) => { +}) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -47,7 +47,7 @@ const Transitions = ({ }, []); return ( -
+
{renderDataTransitions}
); -}; +} Transitions.displayName = TRANSITIONS_NAME; diff --git a/app/javascript/components/transitions/container.unit.test.js b/app/javascript/components/transitions/container.spec.js similarity index 61% rename from app/javascript/components/transitions/container.unit.test.js rename to app/javascript/components/transitions/container.spec.js index da9db4ead2..7677581329 100644 --- a/app/javascript/components/transitions/container.unit.test.js +++ b/app/javascript/components/transitions/container.spec.js @@ -1,21 +1,10 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - import { Map, List } from "immutable"; -import { AccordionDetails, AccordionSummary } from "@material-ui/core"; -import { setupMountedComponent } from "../../test"; +import { mountedComponent, screen } from "../../test-utils"; import Transitions from "./container"; -import TransitionPanel from "./TransitionPanel"; -import AssignmentsSummary from "./assignments/AssignmentsSummary"; -import AssignmentsDetails from "./assignments/AssignmentsDetails"; -import TransferSummary from "./transfers/TransferDetails"; -import TransferDetails from "./transfers/TransferSummary"; -import TransferRequestSummary from "./transfer_requests/summary"; -import TransferRequestDetails from "./transfer_requests/details"; describe(" - Component", () => { - let component; const props = { fetchable: true, recordType: "cases", @@ -71,32 +60,31 @@ describe(" - Component", () => { }) }); - beforeEach(() => { - ({ component } = setupMountedComponent(Transitions, props, initialState)); - }); - it("renders Transitions component", () => { - expect(component.find(Transitions)).to.have.length(1); + mountedComponent(, initialState); + expect(screen.getByTestId("transitions")).toBeInTheDocument(); }); it("renders 2 TransitionPanel", () => { - expect(component.find(TransitionPanel)).to.have.lengthOf(3); - expect(component.find(AccordionDetails)).to.have.lengthOf(3); - expect(component.find(AccordionSummary)).to.have.lengthOf(3); + mountedComponent(, initialState); + expect(screen.getAllByTestId("accordion")).toHaveLength(3); }); it("renders a Assignments components", () => { - expect(component.find(AssignmentsSummary)).to.have.length(1); - expect(component.find(AssignmentsDetails)).to.have.length(1); + mountedComponent(, initialState); + expect(screen.getByText(/transition.type.assign/i)).toBeInTheDocument(); + expect(screen.getAllByText(/transition.notes/i)).toHaveLength(3); }); it("renders a Transfers components", () => { - expect(component.find(TransferSummary)).to.have.length(1); - expect(component.find(TransferDetails)).to.have.length(1); + mountedComponent(, initialState); + expect(screen.getByText(/transition.no_consent_share/i)).toBeInTheDocument(); + expect(screen.getByText(/transition.type.transferRequest/i)).toBeInTheDocument(); }); it("renders TransferRequests components", () => { - expect(component.find(TransferRequestSummary)).to.have.lengthOf(1); - expect(component.find(TransferRequestDetails)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(screen.getByText(/transition.type.transferRequest/i)).toBeInTheDocument(); + expect(screen.getAllByText(/transition.recipient/i)).toHaveLength(3); }); }); diff --git a/app/javascript/components/transitions/referrals/details.jsx b/app/javascript/components/transitions/referrals/details.jsx index 3ea7d87179..b4b05ebac1 100644 --- a/app/javascript/components/transitions/referrals/details.jsx +++ b/app/javascript/components/transitions/referrals/details.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. /* eslint-disable no-nested-ternary */ -import { Divider, Grid, FormControlLabel } from "@material-ui/core"; +import { Divider, Grid, FormControlLabel } from "@mui/material"; import PropTypes from "prop-types"; import { getOption } from "../../record-form"; @@ -17,7 +17,7 @@ import DateTransitions from "../components/date-transitions"; import renderIconValue from "./render-icon-value"; import { referralAgencyName } from "./utils"; -const Details = ({ transition, classes }) => { +function Details({ transition, classes }) { const i18n = useI18n(); const service = useMemoizedSelector(state => { @@ -79,7 +79,7 @@ const Details = ({ transition, classes }) => { {renderRejected} - + {transition.rejection_note && ( @@ -90,7 +90,7 @@ const Details = ({ transition, classes }) => { )} ); -}; +} Details.displayName = REFERRAL_DETAILS_NAME; diff --git a/app/javascript/components/transitions/referrals/details.spec.js b/app/javascript/components/transitions/referrals/details.spec.js new file mode 100644 index 0000000000..78adbb7360 --- /dev/null +++ b/app/javascript/components/transitions/referrals/details.spec.js @@ -0,0 +1,106 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen } from "../../../test-utils"; + +import ReferralDetail from "./details"; + +describe("", () => { + // TODO: fromJS() must be used in here once options been used with Immutable + const initialState = fromJS({ + forms: { + options: { + lookups: [ + { + id: 1, + unique_id: "lookup-service-type", + values: [{ id: "health", display_text: { en: "Health", es: "Salud" } }] + } + ] + } + } + }); + const props = { + transition: { + id: "4142488e-ccd9-4ac5-a3c1-c3c0fd063fc8", + record_id: "6b0018e7-d421-4d6b-80bf-ca4cbf488907", + record_type: "case", + created_at: "2019-10-21T16:13:33.890Z", + notes: "This is a note for Referral", + status: "done", + type: "Referral", + consent_overridden: false, + consent_individual_transfer: true, + transitioned_by: "primero", + transitioned_to: "primero_mgr_cp" + }, + classes: { + spaceGrid: "testStyle", + transtionLabel: "testStyle", + transtionValue: "testStyle" + } + }; + + it("renders 2 ", () => { + mountedComponent(, initialState); + expect(screen.getAllByTestId("display-data")).toHaveLength(6); + }); + + it("renders a ", () => { + mountedComponent(, initialState); + expect(screen.getAllByTestId("divider")).toHaveLength(1); + }); + + describe("with status", () => { + describe("when is rejected", () => { + const rejectedProps = { ...props, ...{ transition: { ...props.transition, status: "rejected" } } }; + + it("should render rejected reason", () => { + mountedComponent(, initialState); + expect(screen.getAllByTestId("display-data")).toHaveLength(7); + expect(screen.queryByText("transition.rejected")).toBeInTheDocument(); + }); + }); + describe("when is pending, done, in_progress, accepted", () => { + it("should render rejected reason", () => { + mountedComponent(, initialState); + expect(screen.getAllByTestId("display-data")).toHaveLength(6); + }); + }); + }); + + describe("when rejection_note is set", () => { + it("should render the rejection_note", () => { + const notesFromProvider = "Some notes"; + const noteProps = { + ...props, + ...{ + transition: { + transitioned_to: "to_some_user", + transitioned_by: "by_some_user", + rejection_note: notesFromProvider + } + } + }; + + mountedComponent(, initialState); + expect(screen.getByText(/referral.note_on_referral_from_provider/i)).toBeInTheDocument(); + }); + }); + + describe("with responded at", () => { + it("should render responded_at", () => { + const respondedProps = { + ...props, + ...{ transition: { ...props.transition, responded_at: "2020-04-150T14:04" } } + }; + + mountedComponent(, initialState); + expect(screen.getByText(/transition.responded_at/i)).toBeInTheDocument(); + }); + + it("should render DateTransitions component", () => { + mountedComponent(, initialState); + expect(screen.getAllByTestId("display-data")).toHaveLength(6); + }); + }); +}); diff --git a/app/javascript/components/transitions/referrals/details.unit.test.js b/app/javascript/components/transitions/referrals/details.unit.test.js deleted file mode 100644 index f0bd0185c4..0000000000 --- a/app/javascript/components/transitions/referrals/details.unit.test.js +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Divider } from "@material-ui/core"; -import { fromJS } from "immutable"; - -import DisplayData from "../../display-data"; -import { setupMountedComponent } from "../../../test"; -import DateTransitions from "../components/date-transitions"; - -import ReferralDetail from "./details"; - -describe("", () => { - let component; - // TODO: fromJS() must be used in here once options been used with Immutable - const initialState = fromJS({ - forms: { - options: { - lookups: [ - { - id: 1, - unique_id: "lookup-service-type", - values: [{ id: "health", display_text: { en: "Health", es: "Salud" } }] - } - ] - } - } - }); - const props = { - transition: { - id: "4142488e-ccd9-4ac5-a3c1-c3c0fd063fc8", - record_id: "6b0018e7-d421-4d6b-80bf-ca4cbf488907", - record_type: "case", - created_at: "2019-10-21T16:13:33.890Z", - notes: "This is a note for Referral", - status: "done", - type: "Referral", - consent_overridden: false, - consent_individual_transfer: true, - transitioned_by: "primero", - transitioned_to: "primero_mgr_cp" - }, - classes: { - spaceGrid: "testStyle", - transtionLabel: "testStyle", - transtionValue: "testStyle" - } - }; - - beforeEach(() => { - ({ component } = setupMountedComponent(ReferralDetail, props, initialState)); - }); - - it("renders 2 ", () => { - expect(component.find(DisplayData)).to.have.lengthOf(6); - }); - - it("renders a ", () => { - expect(component.find(Divider)).to.have.lengthOf(1); - }); - - describe("with status", () => { - describe("when is rejected", () => { - beforeEach(() => { - ({ component } = setupMountedComponent( - ReferralDetail, - { - ...props, - ...{ transition: { ...props.transition, status: "rejected" } } - }, - initialState - )); - }); - it("should render rejected reason", () => { - expect(component.find(ReferralDetail).find(DisplayData)).to.have.lengthOf(7); - }); - }); - describe("when is pending, done, in_progress, accepted", () => { - it("should render rejected reason", () => { - expect(component.find(ReferralDetail).find(DisplayData)).to.have.lengthOf(6); - }); - }); - }); - - context("when rejection_note is set", () => { - it("should render the rejection_note", () => { - const notesFromProvider = "Some notes"; - const { component: compWithNoteFromProvider } = setupMountedComponent( - ReferralDetail, - { - ...props, - ...{ - transition: { - transitioned_to: "to_some_user", - transitioned_by: "by_some_user", - rejection_note: notesFromProvider - } - } - }, - initialState - ); - - expect( - compWithNoteFromProvider - .find(DisplayData) - .last() - .find("div div") - .map(elem => elem.text()) - ).to.deep.equal(["referral.note_on_referral_from_provider", notesFromProvider]); - }); - }); - - describe("with responded at", () => { - beforeEach(() => { - ({ component } = setupMountedComponent( - ReferralDetail, - { - ...props, - ...{ transition: { ...props.transition, responded_at: "2020-04-150T14:04" } } - }, - initialState - )); - }); - - it("should render responded_at", () => { - expect(component.find(ReferralDetail).find(DisplayData).at(5).children("div").childAt(0).text()).to.equal( - "transition.responded_at" - ); - }); - - it("should render DateTransitions component", () => { - expect(component.find(ReferralDetail).find(DateTransitions)).to.have.lengthOf(1); - }); - }); -}); diff --git a/app/javascript/components/transitions/referrals/referral-action-menu.js b/app/javascript/components/transitions/referrals/referral-action-menu.js index 2ece000e00..b12902084e 100644 --- a/app/javascript/components/transitions/referrals/referral-action-menu.js +++ b/app/javascript/components/transitions/referrals/referral-action-menu.js @@ -2,8 +2,8 @@ import { useState } from "react"; import PropTypes from "prop-types"; -import { IconButton, Menu, MenuItem } from "@material-ui/core"; -import MoreVertIcon from "@material-ui/icons/MoreVert"; +import { IconButton, Menu, MenuItem } from "@mui/material"; +import MoreVertIcon from "@mui/icons-material/MoreVert"; import { useI18n } from "../../i18n"; import { useDialog } from "../../action-dialog"; @@ -11,7 +11,7 @@ import { useDialog } from "../../action-dialog"; import { DONE, REFERRAL_DONE_DIALOG, REFERRAL_ACTION_MENU_NAME as NAME } from "./constants"; import ReferralAction from "./referral-action"; -const ReferralActionMenu = ({ transition, recordType }) => { +function ReferralActionMenu({ transition, recordType }) { const i18n = useI18n(); const [referralMenu, setReferralMenu] = useState(null); const [referralType, setReferralType] = useState(DONE); @@ -40,7 +40,13 @@ const ReferralActionMenu = ({ transition, recordType }) => { return ( <> - + { /> ); -}; +} ReferralActionMenu.displayName = NAME; diff --git a/app/javascript/components/transitions/referrals/referral-action/action-creators.unit.test.js b/app/javascript/components/transitions/referrals/referral-action/action-creators.unit.test.js index 5c1cb243f5..2ef3ded0f1 100644 --- a/app/javascript/components/transitions/referrals/referral-action/action-creators.unit.test.js +++ b/app/javascript/components/transitions/referrals/referral-action/action-creators.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub } from "../../../../test"; +import { stub } from "../../../../test-utils"; import { ACCEPTED, REJECTED } from "../../../../config"; import { ENQUEUE_SNACKBAR, generate } from "../../../notifier"; import { CLEAR_DIALOG, SET_DIALOG_PENDING } from "../../../action-dialog"; diff --git a/app/javascript/components/transitions/referrals/referral-action/component.jsx b/app/javascript/components/transitions/referrals/referral-action/component.jsx index 7cfcc9576d..7d5796fcda 100644 --- a/app/javascript/components/transitions/referrals/referral-action/component.jsx +++ b/app/javascript/components/transitions/referrals/referral-action/component.jsx @@ -17,8 +17,8 @@ import { DONE } from "../constants"; import { referralAccepted, referralDone, referralRejected } from "./action-creators"; import { NAME, FORM_ID, FORM_NOTE_FIELD_ID } from "./constants"; -const Component = ({ - openReferralDialog, +function Component({ + openReferralDialog = false, close, dialogName, pending, @@ -27,7 +27,7 @@ const Component = ({ recordType, transistionId, referralType -}) => { +}) { const i18n = useI18n(); const dispatch = useDispatch(); @@ -194,14 +194,10 @@ const Component = ({ {dialogContent} ); -}; +} Component.displayName = NAME; -Component.defaultProps = { - openReferralDialog: false -}; - Component.propTypes = { close: PropTypes.func, dialogName: PropTypes.string, diff --git a/app/javascript/components/transitions/referrals/referral-action/component.unit.test.js b/app/javascript/components/transitions/referrals/referral-action/component.spec.js similarity index 52% rename from app/javascript/components/transitions/referrals/referral-action/component.unit.test.js rename to app/javascript/components/transitions/referrals/referral-action/component.spec.js index 8a8be157cf..bf67faf3b6 100644 --- a/app/javascript/components/transitions/referrals/referral-action/component.unit.test.js +++ b/app/javascript/components/transitions/referrals/referral-action/component.spec.js @@ -2,14 +2,12 @@ import { fromJS } from "immutable"; -import TextInput from "../../../form/fields/text-input"; -import { setupMountedComponent } from "../../../../test"; +import { mountedComponent, screen } from "../../../../test-utils"; import { DONE } from "../constants"; import ReferralAction from "./component"; describe(" - Component", () => { - let component; const initialState = fromJS({}); const props = { @@ -21,29 +19,22 @@ describe(" - Component", () => { referralType: DONE }; - beforeEach(() => { - ({ component } = setupMountedComponent(ReferralAction, props, initialState)); - }); - it("renders ReferralAction component", () => { - expect(component.find(ReferralAction)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(screen.getByRole("dialog")).toBeInTheDocument(); }); it("renders a text field for note_on_referral_from_provider ", () => { - expect(component.find(TextInput)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(screen.getByRole("textbox")).toBeInTheDocument(); }); describe("with rejected status", () => { - beforeEach(() => { - ({ component } = setupMountedComponent( - ReferralAction, - { ...props, openReferralDialog: true, referralType: "rejected" }, - initialState - )); - }); + const rejectedProps = { ...props, openReferralDialog: true, referralType: "rejected" }; it("should render the rejected reason text field", () => { - expect(component.find(TextInput)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(screen.getByRole("textbox")).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/transitions/referrals/render-icon-value.jsx b/app/javascript/components/transitions/referrals/render-icon-value.jsx index 66e98497d6..d1ede938f9 100644 --- a/app/javascript/components/transitions/referrals/render-icon-value.jsx +++ b/app/javascript/components/transitions/referrals/render-icon-value.jsx @@ -1,7 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +/* eslint-disable react/function-component-definition */ -import Cancel from "@material-ui/icons/Cancel"; -import CheckCircleIcon from "@material-ui/icons/CheckCircle"; +import Cancel from "@mui/icons-material/Cancel"; +import CheckCircleIcon from "@mui/icons-material/CheckCircle"; // eslint-disable-next-line react/display-name export default (value, successIcon) => { diff --git a/app/javascript/components/transitions/referrals/summary.jsx b/app/javascript/components/transitions/referrals/summary.jsx index 9551b49221..18175f1592 100644 --- a/app/javascript/components/transitions/referrals/summary.jsx +++ b/app/javascript/components/transitions/referrals/summary.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Grid } from "@material-ui/core"; +import { Grid } from "@mui/material"; import TransitionActions from "../components/menu-actions"; import TransitionStatus from "../TransitionStatus"; @@ -9,7 +9,7 @@ import { useI18n } from "../../i18n"; import { REFERRAL_SUMMARY_NAME } from "../constants"; import DateTransitionsSummary from "../components/date-transitions-summary"; -const Summary = ({ transition, classes, showMode, recordType }) => { +function Summary({ transition, classes, showMode, recordType }) { const i18n = useI18n(); const transitionStatus = transition.status ? ( @@ -31,7 +31,7 @@ const Summary = ({ transition, classes, showMode, recordType }) => { {transitionStatus} ); -}; +} Summary.displayName = REFERRAL_SUMMARY_NAME; diff --git a/app/javascript/components/transitions/referrals/summary.unit.test.js b/app/javascript/components/transitions/referrals/summary.spec.js similarity index 62% rename from app/javascript/components/transitions/referrals/summary.unit.test.js rename to app/javascript/components/transitions/referrals/summary.spec.js index 78409a3da0..dcfbabc37d 100644 --- a/app/javascript/components/transitions/referrals/summary.unit.test.js +++ b/app/javascript/components/transitions/referrals/summary.spec.js @@ -1,12 +1,10 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { setupMountedComponent } from "../../../test"; -import DateTransitionsSummary from "../components/date-transitions-summary"; +import { mountedComponent, screen } from "../../../test-utils"; import ReferralSummary from "./summary"; describe("", () => { - let component; const props = { transition: { id: "4142488e-ccd9-4ac5-a3c1-c3c0fd063fc8", @@ -28,13 +26,10 @@ describe("", () => { } }; - beforeEach(() => { - ({ component } = setupMountedComponent(ReferralSummary, props)); - }); - it("renders divs with its corresponding class", () => { - expect(component.find("div.wrapperStyle")).to.have.lengthOf(1); - expect(component.find("div.titleHeaderStyle")).to.have.lengthOf(1); - expect(component.find(DateTransitionsSummary)).to.have.lengthOf(1); + mountedComponent(); + expect(screen.getByText(/transition.status.done/i)).toBeInTheDocument(); + expect(screen.getByText(/transition.type.referral/i)).toBeInTheDocument(); + expect(screen.getByTestId("date")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/transitions/render-details.jsx b/app/javascript/components/transitions/render-details.jsx index 8d7876013b..bccb1429d4 100644 --- a/app/javascript/components/transitions/render-details.jsx +++ b/app/javascript/components/transitions/render-details.jsx @@ -1,4 +1,5 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +/* eslint-disable react/function-component-definition */ import AssignmentsDetails from "./assignments/AssignmentsDetails"; import ReferralDetails from "./referrals/details"; diff --git a/app/javascript/components/transitions/render-summary.jsx b/app/javascript/components/transitions/render-summary.jsx index 42b2844650..ac35bec1fc 100644 --- a/app/javascript/components/transitions/render-summary.jsx +++ b/app/javascript/components/transitions/render-summary.jsx @@ -1,4 +1,5 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +/* eslint-disable react/function-component-definition */ import AssignmentsSummary from "./assignments/AssignmentsSummary"; import ReferralSummary from "./referrals/summary"; diff --git a/app/javascript/components/transitions/render-transition.jsx b/app/javascript/components/transitions/render-transition.jsx index a4dc6967d0..4afa4cb455 100644 --- a/app/javascript/components/transitions/render-transition.jsx +++ b/app/javascript/components/transitions/render-transition.jsx @@ -1,7 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +/* eslint-disable react/function-component-definition */ -import { AccordionSummary, AccordionDetails } from "@material-ui/core"; -import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; +import { AccordionSummary, AccordionDetails } from "@mui/material"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import renderDetails from "./render-details"; import renderSummary from "./render-summary"; diff --git a/app/javascript/components/transitions/styles.css b/app/javascript/components/transitions/styles.css index ddf51e962a..0308697b35 100644 --- a/app/javascript/components/transitions/styles.css +++ b/app/javascript/components/transitions/styles.css @@ -139,7 +139,7 @@ height: 36px; } -@media (max-width:959.95px) { +@media (max-width:900px) { .date { font-size: var(--fs-12); } diff --git a/app/javascript/components/transitions/transfer_requests/details.jsx b/app/javascript/components/transitions/transfer_requests/details.jsx index fc2f839e0f..7a90b01cfc 100644 --- a/app/javascript/components/transitions/transfer_requests/details.jsx +++ b/app/javascript/components/transitions/transfer_requests/details.jsx @@ -1,13 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Divider, Grid } from "@material-ui/core"; +import { Divider, Grid } from "@mui/material"; import PropTypes from "prop-types"; import { TRANSFER_REQUEST_DETAILS_NAME } from "../constants"; import DisplayData from "../../display-data"; import css from "../styles.css"; -const Details = ({ transition }) => { +function Details({ transition }) { return ( @@ -17,12 +17,12 @@ const Details = ({ transition }) => { - + ); -}; +} Details.displayName = TRANSFER_REQUEST_DETAILS_NAME; diff --git a/app/javascript/components/transitions/transfer_requests/details.unit.test.js b/app/javascript/components/transitions/transfer_requests/details.spec.js similarity index 63% rename from app/javascript/components/transitions/transfer_requests/details.unit.test.js rename to app/javascript/components/transitions/transfer_requests/details.spec.js index 828d00e3b0..d1ae0d83e8 100644 --- a/app/javascript/components/transitions/transfer_requests/details.unit.test.js +++ b/app/javascript/components/transitions/transfer_requests/details.spec.js @@ -1,15 +1,12 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Divider } from "@material-ui/core"; import { fromJS } from "immutable"; -import DisplayData from "../../display-data"; -import { setupMountedComponent } from "../../../test"; +import { mountedComponent, screen } from "../../../test-utils"; import ReferralDetail from "./details"; describe("", () => { - let component; // TODO: fromJS() must be used in here once options been used with Immutable const initialState = fromJS({ forms: { @@ -42,38 +39,33 @@ describe("", () => { } }; - beforeEach(() => { - ({ component } = setupMountedComponent(ReferralDetail, props, initialState)); - }); - it("renders 2 ", () => { - expect(component.find(DisplayData)).to.have.lengthOf(3); + mountedComponent(, initialState); + expect(screen.getAllByTestId("display-data")).toHaveLength(3); }); it("renders a ", () => { - expect(component.find(Divider)).to.have.lengthOf(1); + mountedComponent(, initialState); + expect(screen.getAllByTestId("divider")).toHaveLength(1); }); describe("with status", () => { + const rejectedProps = { + ...props, + ...{ transition: { status: "rejected" } } + }; + describe("when is rejected", () => { - beforeEach(() => { - ({ component } = setupMountedComponent( - ReferralDetail, - { - ...props, - ...{ transition: { status: "rejected" } } - }, - initialState - )); - }); it("should render rejected reason", () => { - expect(component.find(ReferralDetail).find(DisplayData)).to.have.lengthOf(3); + mountedComponent(, initialState); + expect(screen.getAllByTestId("display-data")).toHaveLength(3); }); }); describe("when is pending, done, in_progress, accepted", () => { it("should render rejected reason", () => { - expect(component.find(ReferralDetail).find(DisplayData)).to.have.lengthOf(3); + mountedComponent(, initialState); + expect(screen.getAllByTestId("display-data")).toHaveLength(3); }); }); }); diff --git a/app/javascript/components/transitions/transfer_requests/summary.jsx b/app/javascript/components/transitions/transfer_requests/summary.jsx index 9719109fad..cc14986a18 100644 --- a/app/javascript/components/transitions/transfer_requests/summary.jsx +++ b/app/javascript/components/transitions/transfer_requests/summary.jsx @@ -1,13 +1,13 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import PropTypes from "prop-types"; -import { Grid } from "@material-ui/core"; +import { Grid } from "@mui/material"; import TransitionStatus from "../TransitionStatus"; import { useI18n } from "../../i18n"; import { TRANSFER_REQUEST_SUMMARY_NAME } from "../constants"; -const Summary = ({ transition, classes }) => { +function Summary({ transition, classes }) { const i18n = useI18n(); const transitionStatus = transition.status ? ( @@ -18,17 +18,19 @@ const Summary = ({ transition, classes }) => { return ( -
+
{i18n.t("transition.type.transferRequest")}
{/* TODO: The date should be localized */} -
{i18n.localizeDate(transition.created_at)}
+
+ {i18n.localizeDate(transition.created_at)} +
{transitionStatus} ); -}; +} Summary.displayName = TRANSFER_REQUEST_SUMMARY_NAME; diff --git a/app/javascript/components/transitions/transfer_requests/summary.unit.test.js b/app/javascript/components/transitions/transfer_requests/summary.spec.js similarity index 62% rename from app/javascript/components/transitions/transfer_requests/summary.unit.test.js rename to app/javascript/components/transitions/transfer_requests/summary.spec.js index 61e302b7ac..02b5493545 100644 --- a/app/javascript/components/transitions/transfer_requests/summary.unit.test.js +++ b/app/javascript/components/transitions/transfer_requests/summary.spec.js @@ -1,11 +1,8 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../test"; +import { mountedComponent, screen } from "../../../test-utils"; import TransferRequestSummary from "./summary"; describe("", () => { - let component; const props = { transition: { id: "4142488e-ccd9-4ac5-a3c1-c3c0fd063fc8", @@ -27,13 +24,10 @@ describe("", () => { } }; - beforeEach(() => { - ({ component } = setupMountedComponent(TransferRequestSummary, props)); - }); - it("renders divs with its corresponding class", () => { - expect(component.find("div.wrapperStyle")).to.have.lengthOf(1); - expect(component.find("div.titleHeaderStyle")).to.have.lengthOf(1); - expect(component.find("div.dateStyle")).to.have.lengthOf(1); + mountedComponent(); + expect(screen.getByTestId("wrapper")).toBeInTheDocument(); + expect(screen.getByText("transition.type.transferRequest")).toBeInTheDocument(); + expect(screen.getByTestId("date")).toBeInTheDocument(); }); }); diff --git a/app/javascript/components/transitions/transfers/TransferDetails.jsx b/app/javascript/components/transitions/transfers/TransferDetails.jsx index 5c2dca43c7..f0eb7d8eb3 100644 --- a/app/javascript/components/transitions/transfers/TransferDetails.jsx +++ b/app/javascript/components/transitions/transfers/TransferDetails.jsx @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Divider, Grid, FormControlLabel } from "@material-ui/core"; +import { Divider, Grid, FormControlLabel } from "@mui/material"; import PropTypes from "prop-types"; import { useI18n } from "../../i18n"; @@ -11,7 +11,7 @@ import DateTransitions from "../components/date-transitions"; import { NAME } from "./constants"; import renderIconValue from "./render-icon-value"; -const TransferDetails = ({ transition }) => { +function TransferDetails({ transition }) { const i18n = useI18n(); const renderRejected = @@ -76,12 +76,12 @@ const TransferDetails = ({ transition }) => { {renderRejected} - + ); -}; +} TransferDetails.displayName = NAME; diff --git a/app/javascript/components/transitions/transfers/TransferDetails.unit.test.js b/app/javascript/components/transitions/transfers/TransferDetails.spec.js similarity index 60% rename from app/javascript/components/transitions/transfers/TransferDetails.unit.test.js rename to app/javascript/components/transitions/transfers/TransferDetails.spec.js index 9fff293087..485a3d029b 100644 --- a/app/javascript/components/transitions/transfers/TransferDetails.unit.test.js +++ b/app/javascript/components/transitions/transfers/TransferDetails.spec.js @@ -1,14 +1,10 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Divider } from "@material-ui/core"; - -import { setupMountedComponent } from "../../../test"; -import DisplayData from "../../display-data"; +import { mountedComponent, screen } from "../../../test-utils"; import TransferDetails from "./TransferDetails"; describe("", () => { - let component; const props = { transition: { id: "4142488e-ccd9-4ac5-a3c1-c3c0fd063fc8", @@ -30,33 +26,32 @@ describe("", () => { } }; - beforeEach(() => { - ({ component } = setupMountedComponent(TransferDetails, props)); - }); - it("renders 2 ", () => { - expect(component.find(DisplayData)).to.have.length(5); + mountedComponent(); + expect(screen.getAllByTestId("display-data")).toHaveLength(5); }); it("renders a ", () => { - expect(component.find(Divider)).to.have.length(1); + mountedComponent(); + expect(screen.getAllByTestId("divider")).toHaveLength(1); }); describe("with status", () => { describe("when is rejected", () => { - beforeEach(() => { - ({ component } = setupMountedComponent(TransferDetails, { - ...props, - ...{ transition: { status: "rejected" } } - })); - }); + const rejectedProps = { + ...props, + ...{ transition: { status: "rejected" } } + }; + it("should render rejected reason", () => { - expect(component.find(TransferDetails).find(DisplayData)).to.have.length(6); + mountedComponent(); + expect(screen.getAllByTestId("display-data")).toHaveLength(6); }); }); describe("when is pending, done, in_progress, accepted", () => { it("should render rejected reason", () => { - expect(component.find(TransferDetails).find(DisplayData)).to.have.length(5); + mountedComponent(); + expect(screen.getAllByTestId("display-data")).toHaveLength(5); }); }); }); diff --git a/app/javascript/components/transitions/transfers/TransferSummary.jsx b/app/javascript/components/transitions/transfers/TransferSummary.jsx index b1580b5a27..bbdad4aff8 100644 --- a/app/javascript/components/transitions/transfers/TransferSummary.jsx +++ b/app/javascript/components/transitions/transfers/TransferSummary.jsx @@ -2,14 +2,14 @@ /* eslint-disable react/display-name */ import PropTypes from "prop-types"; -import { Grid } from "@material-ui/core"; +import { Grid } from "@mui/material"; import { useI18n } from "../../i18n"; import TransitionStatus from "../TransitionStatus"; import TransitionActions from "../components/menu-actions"; import DateTransitionsSummary from "../components/date-transitions-summary"; -const TransferSummary = ({ transition, classes, showMode, recordType }) => { +function TransferSummary({ transition, classes, showMode, recordType }) { const i18n = useI18n(); const transitionStatus = transition.status ? ( @@ -29,7 +29,7 @@ const TransferSummary = ({ transition, classes, showMode, recordType }) => { {transitionStatus} ); -}; +} TransferSummary.propTypes = { classes: PropTypes.object.isRequired, diff --git a/app/javascript/components/transitions/transfers/TransferSummary.unit.test.js b/app/javascript/components/transitions/transfers/TransferSummary.spec.js similarity index 64% rename from app/javascript/components/transitions/transfers/TransferSummary.unit.test.js rename to app/javascript/components/transitions/transfers/TransferSummary.spec.js index 22438126fd..33be0f2a8c 100644 --- a/app/javascript/components/transitions/transfers/TransferSummary.unit.test.js +++ b/app/javascript/components/transitions/transfers/TransferSummary.spec.js @@ -1,12 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { setupMountedComponent } from "../../../test"; -import DateTransitionsSummary from "../components/date-transitions-summary"; +import { mountedComponent, screen } from "../../../test-utils"; import TransferSummary from "./TransferSummary"; describe("", () => { - let component; const props = { transition: { id: "4142488e-ccd9-4ac5-a3c1-c3c0fd063fc8", @@ -29,13 +26,10 @@ describe("", () => { currentUser: "primero" }; - beforeEach(() => { - ({ component } = setupMountedComponent(TransferSummary, props)); - }); - it("renders divs with it correponds class", () => { - expect(component.find("div.wrapperStyle")).to.have.lengthOf(1); - expect(component.find("div.titleHeaderStyle")).to.have.lengthOf(1); - expect(component.find(DateTransitionsSummary)).to.have.lengthOf(1); + mountedComponent(); + expect(screen.getByText(/transition.status.done/i)).toBeInTheDocument(); + expect(screen.getByText(/transition.type.transfer/i)).toBeInTheDocument(); + expect(screen.queryByTestId("date")).toBeNull(); }); }); diff --git a/app/javascript/components/transitions/transfers/render-icon-value.jsx b/app/javascript/components/transitions/transfers/render-icon-value.jsx index 66e98497d6..d1ede938f9 100644 --- a/app/javascript/components/transitions/transfers/render-icon-value.jsx +++ b/app/javascript/components/transitions/transfers/render-icon-value.jsx @@ -1,7 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +/* eslint-disable react/function-component-definition */ -import Cancel from "@material-ui/icons/Cancel"; -import CheckCircleIcon from "@material-ui/icons/CheckCircle"; +import Cancel from "@mui/icons-material/Cancel"; +import CheckCircleIcon from "@mui/icons-material/CheckCircle"; // eslint-disable-next-line react/display-name export default (value, successIcon) => { diff --git a/app/javascript/components/transitions/transfers/transfer-action-menu.jsx b/app/javascript/components/transitions/transfers/transfer-action-menu.jsx index c0b669bc29..b10fe1603a 100644 --- a/app/javascript/components/transitions/transfers/transfer-action-menu.jsx +++ b/app/javascript/components/transitions/transfers/transfer-action-menu.jsx @@ -2,8 +2,8 @@ import { useState } from "react"; import PropTypes from "prop-types"; -import { IconButton, Menu, MenuItem } from "@material-ui/core"; -import MoreVertIcon from "@material-ui/icons/MoreVert"; +import { IconButton, Menu, MenuItem } from "@mui/material"; +import MoreVertIcon from "@mui/icons-material/MoreVert"; import { useI18n } from "../../i18n"; import { ACCEPTED, REJECTED, REJECT } from "../../../config"; @@ -12,7 +12,7 @@ import { useDialog } from "../../action-dialog"; import { APPROVE, TRANSFER_APPROVAL_DIALOG, TRANSFER_ACTION_MENU_NAME as NAME } from "./constants"; import TransferApproval from "./transfer-approval"; -const TransferActionMenu = ({ transition, recordType }) => { +function TransferActionMenu({ transition, recordType }) { const i18n = useI18n(); const [transferMenu, setTransferMenu] = useState(null); const [approvalType, setApprovalType] = useState(ACCEPTED); @@ -48,7 +48,13 @@ const TransferActionMenu = ({ transition, recordType }) => { return ( <> - + { /> ); -}; +} TransferActionMenu.displayName = NAME; diff --git a/app/javascript/components/transitions/transfers/transfer-approval/action-creators.unit.test.js b/app/javascript/components/transitions/transfers/transfer-approval/action-creators.unit.test.js index f10e2ba88b..fbc23a49b8 100644 --- a/app/javascript/components/transitions/transfers/transfer-approval/action-creators.unit.test.js +++ b/app/javascript/components/transitions/transfers/transfer-approval/action-creators.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub } from "../../../../test"; +import { stub } from "../../../../test-utils"; import { ENQUEUE_SNACKBAR, generate } from "../../../notifier"; import { CLEAR_DIALOG, SET_DIALOG_PENDING } from "../../../action-dialog"; diff --git a/app/javascript/components/transitions/transfers/transfer-approval/component.js b/app/javascript/components/transitions/transfers/transfer-approval/component.js index 6008de2c61..f17bf9cef8 100644 --- a/app/javascript/components/transitions/transfers/transfer-approval/component.js +++ b/app/javascript/components/transitions/transfers/transfer-approval/component.js @@ -16,8 +16,8 @@ import { getTransitionById } from "../../selectors"; import { approvalTransfer } from "./action-creators"; import { FORM_ID, NAME } from "./constants"; -const Component = ({ - openTransferDialog, +function Component({ + openTransferDialog = false, close, approvalType, dialogName, @@ -26,7 +26,7 @@ const Component = ({ pending, setPending, transferId -}) => { +}) { const i18n = useI18n(); const dispatch = useDispatch(); const { currentUserName } = useApp(); @@ -129,14 +129,10 @@ const Component = ({ {dialogContent} ); -}; +} Component.displayName = NAME; -Component.defaultProps = { - openTransferDialog: false -}; - Component.propTypes = { approvalType: PropTypes.string, close: PropTypes.func, diff --git a/app/javascript/components/transitions/transfers/transfer-approval/component.unit.test.js b/app/javascript/components/transitions/transfers/transfer-approval/component.spec.js similarity index 66% rename from app/javascript/components/transitions/transfers/transfer-approval/component.unit.test.js rename to app/javascript/components/transitions/transfers/transfer-approval/component.spec.js index 22ac965992..63f4c4c20c 100644 --- a/app/javascript/components/transitions/transfers/transfer-approval/component.unit.test.js +++ b/app/javascript/components/transitions/transfers/transfer-approval/component.spec.js @@ -1,16 +1,14 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import { Button } from "@material-ui/core"; -import { setupMountedComponent, spy } from "../../../../test"; +import { mountedComponent, screen } from "../../../../test-utils"; import { TransitionRecord } from "../../records"; -import { ACCEPTED } from "../../../../config"; import TransferApproval from "./component"; -import actions from "./actions"; describe(" - Component", () => { + const mockSetPending = jest.fn(); const props = { openTransferDialog: true, close: () => {}, @@ -18,7 +16,7 @@ describe(" - Component", () => { recordId: "2fe3312b-8de2-4bd0-ab39-cdfc020f86b3", transferId: "be62e823-4d9d-402e-aace-8e4865a4882e", recordType: "cases", - setPending: spy() + setPending: mockSetPending }; const initialState = fromJS({ records: { @@ -81,33 +79,23 @@ describe(" - Component", () => { }); it("renders Transitions component", () => { - const { component } = setupMountedComponent(TransferApproval, props, initialState); + mountedComponent(, initialState); - expect(component.find(TransferApproval)).to.have.length(1); + expect(screen.getByRole("dialog")).toBeInTheDocument(); }); - context("when the current_user is not the recipient", () => { + describe("when the current_user is not the recipient", () => { it("renders the managed user message", () => { - const { component } = setupMountedComponent( - TransferApproval, - props, - initialState.setIn(["user", "username"], "primero_mgr_cp") - ); + mountedComponent(, initialState.setIn(["user", "username"], "primero_mgr_cp")); - expect(component.find(TransferApproval).find("p").text()).to.equal("cases.transfer_managed_user_accepted"); + expect(screen.getByText(/cases.transfer_managed_user_accepted/i)).toBeInTheDocument(); }); }); - context("when transfer is approved", () => { - it("renders the managed user message", () => { - const { component } = setupMountedComponent(TransferApproval, props, initialState); - const buttons = component.find(Button); - - buttons.first().simulate("click"); - - expect(props.setPending).to.have.been.called; - expect(component.props().store.getActions()[0].type).to.deep.equals(actions.APPROVE_TRANSFER); - expect(component.props().store.getActions()[0].api.body.data.status).to.deep.equals(ACCEPTED); + describe("when transfer is approved", () => { + it("renders the managed user message", async () => { + mountedComponent(, initialState); + expect(screen.getByText(/buttons.accept/i)).toBeInTheDocument(); }); }); }); diff --git a/app/javascript/components/translations-dialog/component.jsx b/app/javascript/components/translations-dialog/component.jsx index 344b804015..3f8e1b4c27 100644 --- a/app/javascript/components/translations-dialog/component.jsx +++ b/app/javascript/components/translations-dialog/component.jsx @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import CheckIcon from "@material-ui/icons/Check"; +import CheckIcon from "@mui/icons-material/Check"; import PropTypes from "prop-types"; import first from "lodash/first"; import get from "lodash/get"; @@ -15,7 +15,7 @@ import { translationsForm, validationSchema } from "./form"; import { localesToRender } from "./utils"; import css from "./styles.css"; -const Component = ({ formMethods, mode, dialogTitle }) => { +function Component({ formMethods, mode, dialogTitle }) { const i18n = useI18n(); const validations = validationSchema(i18n); const currentValues = formMethods.getValues({ nest: true }); @@ -80,7 +80,7 @@ const Component = ({ formMethods, mode, dialogTitle }) => { /> ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/translations-dialog/component.spec.js b/app/javascript/components/translations-dialog/component.spec.js new file mode 100644 index 0000000000..449213ec6b --- /dev/null +++ b/app/javascript/components/translations-dialog/component.spec.js @@ -0,0 +1,30 @@ +import { fromJS } from "immutable"; + +import { mountedFormComponent, screen } from "../../test-utils"; + +import ReportTranslationsDialog from "./component"; +import { NAME } from "./constants"; + +describe("/components/ - Container", () => { + const state = fromJS({ + ui: { dialogs: { dialog: NAME, open: true } }, + application: { primero: { locales: ["en", "fr", "ar"] } } + }); + + it("should render with fields for the selected locale", async () => { + await mountedFormComponent(, { + props: { mode: "edit" }, + state, + includeFormMethods: true + }); + + expect(screen.getAllByRole("dialog")).toHaveLength(1); + expect(document.getElementById("locale_id")).toBeInTheDocument(); + expect( + screen + .getAllByRole("textbox") + .map(input => input.getAttribute("name")) + .filter(input => input) + ).toStrictEqual(["name.fr", "description.fr"]); + }); +}); diff --git a/app/javascript/components/translations-dialog/component.unit.test.js b/app/javascript/components/translations-dialog/component.unit.test.js deleted file mode 100644 index d3ab7d52ea..0000000000 --- a/app/javascript/components/translations-dialog/component.unit.test.js +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { TextField } from "@material-ui/core"; -import Autocomplete from "@material-ui/lab/Autocomplete"; -import { expect } from "chai"; -import { fromJS } from "immutable"; - -import { setupMockFormComponent } from "../../test"; - -import ReportTranslationsDialog from "./component"; -import { NAME } from "./constants"; - -describe("/components/ - Container", () => { - const state = fromJS({ - ui: { dialogs: { dialog: NAME, open: true } }, - application: { primero: { locales: ["en", "fr", "ar"] } } - }); - - it("should render with fields for the selected locale", () => { - const { component } = setupMockFormComponent(ReportTranslationsDialog, { - props: { mode: "edit" }, - state, - includeFormMethods: true - }); - - const dialog = component.find(ReportTranslationsDialog); - const autoComplete = dialog.find(Autocomplete); - const textFields = dialog.find(TextField); - - expect(component.find(ReportTranslationsDialog)).to.have.lengthOf(1); - expect(autoComplete).to.have.lengthOf(1); - expect(autoComplete.props().value).to.equal("fr"); - expect(textFields.at(1).props().name).to.equal("name.fr"); - expect(textFields.at(2).props().name).to.equal("description.fr"); - }); -}); diff --git a/app/javascript/components/translations-toggle/component.jsx b/app/javascript/components/translations-toggle/component.jsx index 620d741b67..98e04c20a8 100644 --- a/app/javascript/components/translations-toggle/component.jsx +++ b/app/javascript/components/translations-toggle/component.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { Menu, MenuItem, Button } from "@material-ui/core"; -import LanguageIcon from "@material-ui/icons/Language"; +import { Menu, MenuItem, Button } from "@mui/material"; +import LanguageIcon from "@mui/icons-material/Language"; import { useState } from "react"; import { DropdownDoubleIcon } from "../../images/primero-icons"; @@ -13,7 +13,7 @@ import { useApp } from "../application"; import css from "./styles.css"; import { NAME } from "./constants"; -const TranslationsToggle = () => { +function TranslationsToggle() { const { changeLocale, locale, ...i18n } = useI18n(); const [anchorEl, setAnchorEl] = useState(null); const { useContainedNavStyle } = useApp(); @@ -63,7 +63,7 @@ const TranslationsToggle = () => { aria-haspopup="true" aria-owns={anchorEl ? "simple-menu" : undefined} > - +
{i18n.t(`home.${locale}`)}
@@ -87,7 +87,7 @@ const TranslationsToggle = () => {
); -}; +} TranslationsToggle.displayName = NAME; diff --git a/app/javascript/components/translations-toggle/styles.css b/app/javascript/components/translations-toggle/styles.css index ab368178a7..2767b4b8cd 100644 --- a/app/javascript/components/translations-toggle/styles.css +++ b/app/javascript/components/translations-toggle/styles.css @@ -7,18 +7,16 @@ padding: 0 16px; background-color: white; - & > span { - & div { - flex: 1; - text-align: left; - padding: 0.85em; - text-transform: initial; - } + & div { + flex: 1; + text-align: left; + padding: 0.85em; + text-transform: initial; + } - & svg { - color: var(--c-black); - width: 24px; - } + & svg { + color: var(--c-black); + width: 24px; } } @@ -32,12 +30,12 @@ } &:after { - border: 1px solid var(--c-sold-black); + border: 1px solid var(--c-solid-black); } } -@media ((min-width:600px) and (max-width:1279.95px)) { - .button > span svg { +@media ((min-width:600px) and (max-width:1200px)) { + .button > svg { margin: 0 .3em } } diff --git a/app/javascript/components/user-actions/component.jsx b/app/javascript/components/user-actions/component.jsx index dd3bedd997..0f938f0c39 100644 --- a/app/javascript/components/user-actions/component.jsx +++ b/app/javascript/components/user-actions/component.jsx @@ -13,7 +13,7 @@ import useMemoizedSelector from "../../libs/use-memoized-selector"; import { NAME } from "./constants"; -const Component = ({ id }) => { +function Component({ id }) { const i18n = useI18n(); const dispatch = useDispatch(); const { setDialog, dialogOpen, dialogClose } = useDialog(DIALOG_NAME); @@ -44,7 +44,7 @@ const Component = ({ id }) => { )} ); -}; +} Component.displayName = NAME; diff --git a/app/javascript/components/user-actions/component.spec.js b/app/javascript/components/user-actions/component.spec.js new file mode 100644 index 0000000000..8a6c7be7af --- /dev/null +++ b/app/javascript/components/user-actions/component.spec.js @@ -0,0 +1,37 @@ +import { fromJS } from "immutable"; + +import { mountedComponent, screen } from "../../test-utils"; + +import UserActions from "./component"; + +describe("", () => { + describe("when idp is not used", () => { + const props = { + id: "1" + }; + + it("should render the Menu", () => { + mountedComponent(, fromJS({})); + expect(screen.getByTestId("long-menu")).toBeInTheDocument(); + }); + + it("should render the Password Reset MenuItem", () => { + mountedComponent(, fromJS({})); + expect(screen.getByText("user.password_reset_request")).toBeInTheDocument(); + }); + }); + + describe("when idp is used", () => { + const props = { id: "1" }; + + it("should render the Menu", () => { + mountedComponent(, fromJS({ idp: { use_identity_provider: true } })); + expect(screen.getByTestId("long-menu")).toBeInTheDocument(); + }); + + it("should not render the Password Reset MenuItem", () => { + mountedComponent(, fromJS({ idp: { use_identity_provider: true } })); + expect(screen.queryByText(/user.password_reset_request/i)).toBeNull(); + }); + }); +}); diff --git a/app/javascript/components/user-actions/component.unit.test.js b/app/javascript/components/user-actions/component.unit.test.js deleted file mode 100644 index d2a131531b..0000000000 --- a/app/javascript/components/user-actions/component.unit.test.js +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fromJS } from "immutable"; -import { MenuItem } from "@material-ui/core"; - -import { setupMountedComponent } from "../../test"; -import Menu from "../menu"; - -import UserActions from "./component"; - -describe("", () => { - describe("when idp is not used", () => { - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent(UserActions, { id: "1" }, fromJS({}))); - }); - - it("should render the Menu", () => { - expect(component.find(Menu)).to.have.lengthOf(1); - }); - - it("should render the Password Reset MenuItem", () => { - expect( - component - .find(MenuItem) - .map(node => node.text()) - .includes("user.password_reset_request") - ).to.be.true; - }); - }); - - describe("when idp is used", () => { - let component; - - beforeEach(() => { - ({ component } = setupMountedComponent( - UserActions, - { id: "1" }, - fromJS({ idp: { use_identity_provider: true } }) - )); - }); - - it("should render the Menu", () => { - expect(component.find(Menu)).to.have.lengthOf(1); - }); - - it("should not render the Password Reset MenuItem", () => { - expect( - component - .find(MenuItem) - .map(node => node.text()) - .includes("user.password_reset_request") - ).to.be.false; - }); - }); -}); diff --git a/app/javascript/components/user/action-creators.js b/app/javascript/components/user/action-creators.js index 852dc75f1f..c52d8fb4aa 100644 --- a/app/javascript/components/user/action-creators.js +++ b/app/javascript/components/user/action-creators.js @@ -7,11 +7,13 @@ import { DB_COLLECTIONS_NAMES } from "../../db"; import { fetchSandboxUI, loadApplicationResources } from "../application/action-creators"; import { SET_USER_LOCALE } from "../i18n"; import { SET_DIALOG } from "../action-dialog/actions"; -import { LOGIN_DIALOG } from "../login-dialog"; +import { LOGIN_DIALOG } from "../login-dialog/constants"; import { QUEUE_READY } from "../../libs/queue/constants"; import connectivityActions from "../connectivity/actions"; -import { ENQUEUE_SNACKBAR, SNACKBAR_VARIANTS, generate } from "../notifier"; -import { loginSystemSettings } from "../login"; +import { generate } from "../notifier/utils"; +import { SNACKBAR_VARIANTS } from "../notifier/constants"; +import { ENQUEUE_SNACKBAR } from "../notifier/actions"; +import { loginSystemSettings } from "../login/action-creators"; import actions from "./actions"; diff --git a/app/javascript/components/user/action-creators.unit.test.js b/app/javascript/components/user/action-creators.unit.test.js index 6bc012e461..7eaca10c20 100644 --- a/app/javascript/components/user/action-creators.unit.test.js +++ b/app/javascript/components/user/action-creators.unit.test.js @@ -4,7 +4,7 @@ import configureStore from "redux-mock-store"; import thunk from "redux-thunk"; import { METHODS, RECORD_PATH, ROUTES } from "../../config"; -import { spy, stub } from "../../test"; +import { spy, stub } from "../../test-utils"; import * as idpSelection from "../login/components/idp-selection"; import { ENQUEUE_SNACKBAR, SNACKBAR_VARIANTS, generate } from "../notifier"; import { QUEUE_READY } from "../../libs/queue"; diff --git a/app/javascript/components/user/actions.js b/app/javascript/components/user/actions.js index a7119df841..6eafa36b1d 100644 --- a/app/javascript/components/user/actions.js +++ b/app/javascript/components/user/actions.js @@ -5,6 +5,7 @@ import { namespaceActions } from "../../libs"; import NAMESPACE from "./namespace"; export default namespaceActions(NAMESPACE, [ + "LOGIN", "FETCH_USER_DATA", "FETCH_USER_DATA_SUCCESS", "LOGOUT", diff --git a/app/javascript/components/user/actions.unit.test.js b/app/javascript/components/user/actions.unit.test.js index d1360b7421..d931d81593 100644 --- a/app/javascript/components/user/actions.unit.test.js +++ b/app/javascript/components/user/actions.unit.test.js @@ -7,6 +7,7 @@ describe("User - Actions", () => { const cloneActions = { ...Actions }; [ + "LOGIN", "FETCH_USER_DATA", "FETCH_USER_DATA_SUCCESS", "LOGOUT", diff --git a/app/javascript/components/user/selectors.js b/app/javascript/components/user/selectors.js index 5577289cfb..238d6436e7 100644 --- a/app/javascript/components/user/selectors.js +++ b/app/javascript/components/user/selectors.js @@ -2,7 +2,7 @@ import { List, fromJS } from "immutable"; -import { SAVING } from "../../config/constants"; +import { SAVING } from "../../config"; import { MANAGED_REPORT_SCOPE } from "../permissions/constants"; import NAMESPACE from "./namespace"; diff --git a/app/javascript/components/user/selectors.unit.test.js b/app/javascript/components/user/selectors.unit.test.js index 5f26cf4be6..fc3514246d 100644 --- a/app/javascript/components/user/selectors.unit.test.js +++ b/app/javascript/components/user/selectors.unit.test.js @@ -4,7 +4,7 @@ import { fromJS } from "immutable"; import { format, parseISO } from "date-fns"; import { ACTIONS } from "../permissions"; -import { CODE_OF_CONDUCT_DATE_FORMAT } from "../../config/constants"; +import { CODE_OF_CONDUCT_DATE_FORMAT } from "../../config"; import { MANAGED_REPORT_SCOPE } from "../permissions/constants"; import * as selectors from "./selectors"; diff --git a/app/javascript/components/user/use-refresh-token.js b/app/javascript/components/user/use-refresh-token.js index 21b7012a77..c43f83ae31 100644 --- a/app/javascript/components/user/use-refresh-token.js +++ b/app/javascript/components/user/use-refresh-token.js @@ -14,10 +14,10 @@ import { SELECTED_IDP } from "./constants"; export default () => { const dispatch = useDispatch(); const history = useHistory(); - const selectedIDP = localStorage.getItem(SELECTED_IDP); + const selectedIDP = JSON.parse(sessionStorage.getItem(SELECTED_IDP)); const isAuthenticated = useMemoizedSelector(state => getIsAuthenticated(state)); const isIDP = useMemoizedSelector(state => getUseIdentityProvider(state)); - const idp = useMemoizedSelector(state => getSelectedIDP(state, selectedIDP)); + const idp = useMemoizedSelector(state => getSelectedIDP(state, selectedIDP?.unique_id)); return { refreshUserToken: checkUserAuth => { diff --git a/app/javascript/components/user/use-refresh-token.unit.test.js b/app/javascript/components/user/use-refresh-token.unit.test.js index b3c5900150..1d6356f2a9 100644 --- a/app/javascript/components/user/use-refresh-token.unit.test.js +++ b/app/javascript/components/user/use-refresh-token.unit.test.js @@ -2,7 +2,7 @@ import { expect } from "chai"; -import { setupHook, spy, stub } from "../../test"; +import { setupHook, spy, stub } from "../../test-utils"; import * as authProvider from "../login/components/idp-selection/auth-provider"; import useRefreshToken from "./use-refresh-token"; @@ -47,7 +47,7 @@ describe("user/use-refresh-token.js", () => { it("refreshes idp token", () => { const idpTokenSpy = spy(authProvider, "refreshIdpToken"); - stub(global.localStorage, "getItem").returns("provider"); + stub(global.sessionStorage, "getItem").returns(JSON.stringify({ unique_id: "provider" })); const { act, result } = setupHook(() => useRefreshToken(), { idp: { @@ -65,8 +65,8 @@ describe("user/use-refresh-token.js", () => { expect(idpTokenSpy).to.have.been.called; - if (global.localStorage.getItem.restore) { - global.localStorage.getItem.restore(); + if (global.sessionStorage.getItem.restore) { + global.sessionStorage.getItem.restore(); } }); }); diff --git a/app/javascript/config/constants.js b/app/javascript/config.js similarity index 63% rename from app/javascript/config/constants.js rename to app/javascript/config.js index 39ce8bf44a..8cec2a2f22 100644 --- a/app/javascript/config/constants.js +++ b/app/javascript/config.js @@ -20,49 +20,49 @@ import { READ_MANAGED_REPORTS, READ_REGISTRY_RECORD, READ_FAMILY_RECORD -} from "../components/permissions/constants"; -import getAdminResources from "../components/pages/admin/utils/get-admin-resources"; +} from "./components/permissions/constants"; +import getAdminResources from "./components/pages/admin/utils/get-admin-resources"; -export const API_BASE_PATH = "/api/v2"; +const API_BASE_PATH = "/api/v2"; -export const PASSWORD_MIN_LENGTH = 8; +const PASSWORD_MIN_LENGTH = 8; // Max allowed image size for attachments -export const MAX_IMAGE_SIZE = 600; +const MAX_IMAGE_SIZE = 600; // Max allowed size for attachments -export const MAX_ATTACHMENT_SIZE = 20971520; +const MAX_ATTACHMENT_SIZE = 20971520; // Time (ms) when fetch request will timeout -export const FETCH_TIMEOUT = 90000; +const FETCH_TIMEOUT = 90000; // IndexedDB database name -export const DATABASE_NAME = "primero"; +const DATABASE_NAME = "primero"; // Time (ms) when the idle dialog will activate when a user is inactive -export const IDLE_TIMEOUT = 15 * 1000 * 60; +const IDLE_TIMEOUT = 15 * 1000 * 60; // Time (ms) user has to respond to idle dialog before logged out -export const IDLE_LOGOUT_TIMEOUT = 5 * 1000 * 60; +const IDLE_LOGOUT_TIMEOUT = 5 * 1000 * 60; // Time (ms) how often the backend is pinged to refresh the user's token -export const TOKEN_REFRESH_INTERVAL = 30 * 1000 * 60; +const TOKEN_REFRESH_INTERVAL = 30 * 1000 * 60; -export const PUSH_NOTIFICATION_SUBSCRIPTION_REFRESH_INTERVAL = 15 * 1000 * 60; +const PUSH_NOTIFICATION_SUBSCRIPTION_REFRESH_INTERVAL = 15 * 1000 * 60; -export const CASE = "case"; -export const CASES = "cases"; -export const TRACING_REQUEST = "tracing_request"; -export const TRACING_REQUESTS = "tracing_requests"; -export const INCIDENT = "incident"; -export const INCIDENTS = "incidents"; -export const REGISTRY_RECORD = "registry_record"; -export const REGISTRY_RECORDS = "registry_records"; -export const FAMILIES = "families"; -export const FAMILY = "family"; +const CASE = "case"; +const CASES = "cases"; +const TRACING_REQUEST = "tracing_request"; +const TRACING_REQUESTS = "tracing_requests"; +const INCIDENT = "incident"; +const INCIDENTS = "incidents"; +const REGISTRY_RECORD = "registry_record"; +const REGISTRY_RECORDS = "registry_records"; +const FAMILIES = "families"; +const FAMILY = "family"; // Type of records available singular (key): plural (value) -export const RECORD_TYPES = { +const RECORD_TYPES = { [CASES]: CASE, [TRACING_REQUESTS]: TRACING_REQUEST, [INCIDENTS]: INCIDENT, @@ -71,7 +71,7 @@ export const RECORD_TYPES = { all: "all" }; -export const RECORD_TYPES_PLURAL = { +const RECORD_TYPES_PLURAL = { [CASE]: CASES, [TRACING_REQUEST]: TRACING_REQUESTS, [INCIDENT]: INCIDENTS, @@ -80,39 +80,39 @@ export const RECORD_TYPES_PLURAL = { }; // Max Age allowed in age ranges -export const AGE_MAX = 999; +const AGE_MAX = 999; -export const MODULES = Object.freeze({ +const MODULES = Object.freeze({ CP: "primeromodule-cp", GBV: "primeromodule-gbv", MRM: "primeromodule-mrm" }); -export const MODULE_TYPE_FIELD = "module_id"; +const MODULE_TYPE_FIELD = "module_id"; -export const USER_NAME_FIELD = "user_name"; +const USER_NAME_FIELD = "user_name"; -export const STRING_SOURCES_TYPES = Object.freeze({ +const STRING_SOURCES_TYPES = Object.freeze({ LOCATION: "Location", AGENCY: "Agency", USER: "user" }); -export const ID_FIELD = "id"; -export const UNIQUE_ID_FIELD = "unique_id"; -export const DISPLAY_TEXT_FIELD = "display_text"; -export const NAME_FIELD = "name"; -export const CODE_FIELD = "code"; -export const INCIDENT_CASE_ID_FIELD = "incident_case_id"; -export const INCIDENT_CASE_ID_DISPLAY_FIELD = "case_id_display"; -export const INCIDENT_SHORT_ID_FIELD = "short_id"; +const ID_FIELD = "id"; +const UNIQUE_ID_FIELD = "unique_id"; +const DISPLAY_TEXT_FIELD = "display_text"; +const NAME_FIELD = "name"; +const CODE_FIELD = "code"; +const INCIDENT_CASE_ID_FIELD = "incident_case_id"; +const INCIDENT_CASE_ID_DISPLAY_FIELD = "case_id_display"; +const INCIDENT_SHORT_ID_FIELD = "short_id"; -export const CONSENT_GIVEN_FIELD_BY_MODULE = Object.freeze({ +const CONSENT_GIVEN_FIELD_BY_MODULE = Object.freeze({ [MODULES.CP]: ["consent_for_services", "disclosure_other_orgs"], [MODULES.GBV]: ["consent_for_services"] }); -export const RECORD_PATH = { +const RECORD_PATH = { account: "account", agencies: "agencies", alerts: "alerts", @@ -140,36 +140,36 @@ export const RECORD_PATH = { webpush_config: "webpush/config" }; -export const RECORD_INFORMATION_GROUP = "record_information"; +const RECORD_INFORMATION_GROUP = "record_information"; -export const IDENTIFICATION_REGISTRATION = "identification_registration"; +const IDENTIFICATION_REGISTRATION = "identification_registration"; -export const VIOLATION_GROUP = "violations"; +const VIOLATION_GROUP = "violations"; -export const RECORD_OWNER = "record_owner"; +const RECORD_OWNER = "record_owner"; -export const TRANSFERS_ASSIGNMENTS = "transfers_assignments"; -export const INCIDENT_TRANSFERS_ASSIGNMENTS = "incident_transfers_assignments"; +const TRANSFERS_ASSIGNMENTS = "transfers_assignments"; +const INCIDENT_TRANSFERS_ASSIGNMENTS = "incident_transfers_assignments"; -export const REFERRAL = "referral"; +const REFERRAL = "referral"; -export const APPROVALS = "approvals"; +const APPROVALS = "approvals"; -export const INCIDENT_FROM_CASE = "incident_from_case"; +const INCIDENT_FROM_CASE = "incident_from_case"; -export const REGISTRY_FROM_CASE = "registry_from_case"; +const REGISTRY_FROM_CASE = "registry_from_case"; -export const CHANGE_LOGS = "change_logs"; +const CHANGE_LOGS = "change_logs"; -export const SUMMARY = "summary"; +const SUMMARY = "summary"; -export const SUMMARY_INCIDENT_MRM = "mrm_summary_page"; +const SUMMARY_INCIDENT_MRM = "mrm_summary_page"; -export const TRANSITION_TYPE = [TRANSFERS_ASSIGNMENTS, REFERRAL]; +const TRANSITION_TYPE = [TRANSFERS_ASSIGNMENTS, REFERRAL]; -export const RECORD_INFORMATION = [APPROVALS, RECORD_OWNER, REFERRAL, TRANSFERS_ASSIGNMENTS]; +const RECORD_INFORMATION = [APPROVALS, RECORD_OWNER, REFERRAL, TRANSFERS_ASSIGNMENTS]; -export const ROUTES = { +const ROUTES = { account: "/account", admin: "/admin", admin_agencies: "/admin/agencies", @@ -218,7 +218,7 @@ export const ROUTES = { subscriptions_current: "/webpush/subscriptions/current" }; -export const PERMITTED_URL = [ +const PERMITTED_URL = [ ROUTES.account, ROUTES.dashboard, ROUTES.login, @@ -237,35 +237,35 @@ export const PERMITTED_URL = [ ROUTES.password_reset_request ]; -export const DATE_FORMAT = "dd-MMM-yyyy"; +const DATE_FORMAT = "dd-MMM-yyyy"; -export const DATE_FORMAT_NE = "DD-MM-YYYY"; +const DATE_FORMAT_NE = "DD-MM-YYYY"; -export const MONTH_AND_YEAR_FORMAT = "MMM-yyyy"; +const MONTH_AND_YEAR_FORMAT = "MMM-yyyy"; -export const API_DATE_FORMAT = "yyyy-MM-dd"; +const API_DATE_FORMAT = "yyyy-MM-dd"; -export const API_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; +const API_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; -export const TRANSITIONS_DATE_FORMAT = "MMM dd,yyyy"; +const TRANSITIONS_DATE_FORMAT = "MMM dd,yyyy"; -export const DATE_TIME_FORMAT = "dd-MMM-yyyy HH:mm"; +const DATE_TIME_FORMAT = "dd-MMM-yyyy HH:mm"; -export const ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/; +const ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/; // eslint-disable-next-line max-len -export const ISO_DATE_TIME_REGEX = +const ISO_DATE_TIME_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?)$/; -export const CODE_OF_CONDUCT_DATE_FORMAT = "MMMM dd, yyyy"; +const CODE_OF_CONDUCT_DATE_FORMAT = "MMMM dd, yyyy"; -export const MODES = { +const MODES = { edit: "edit", new: "new", show: "show" }; -export const LOOKUPS = { +const LOOKUPS = { agency_office: "lookup-agency-office", risk_level: "lookup-risk-level", workflow: "lookup-workflow", @@ -284,7 +284,7 @@ export const LOOKUPS = { armed_force_group_or_other_party: "lookup-armed-force-group-or-other-party" }; -export const ADMIN_NAV = [ +const ADMIN_NAV = [ { to: "/users", label: "settings.navigation.users", @@ -356,7 +356,7 @@ export const ADMIN_NAV = [ } ]; -export const APPLICATION_NAV = (permissions, userId) => { +const APPLICATION_NAV = (permissions, userId) => { const adminResources = getAdminResources(permissions); const adminForm = adminResources[0] || ADMIN_RESOURCES.contact_information; const adminSettingsOption = `/admin/${adminForm === RESOURCES.metadata ? RESOURCES.forms : adminForm}`; @@ -484,9 +484,9 @@ export const APPLICATION_NAV = (permissions, userId) => { ]; }; -export const LOCATION_PATH = "/locations"; +const LOCATION_PATH = "/locations"; -export const METHODS = Object.freeze({ +const METHODS = Object.freeze({ DELETE: "DELETE", GET: "GET", PATCH: "PATCH", @@ -494,21 +494,21 @@ export const METHODS = Object.freeze({ PUT: "PUT" }); -export const SAVE_METHODS = Object.freeze({ +const SAVE_METHODS = Object.freeze({ new: "new", update: "update" }); -export const ACCEPTED = "accepted"; -export const ACCEPT = "accept"; -export const REJECTED = "rejected"; -export const REVOKED = "revoked"; -export const DONE = "done"; -export const REJECT = "reject"; -export const SAVING = "saving"; -export const INPROGRESS = "in_progress"; +const ACCEPTED = "accepted"; +const ACCEPT = "accept"; +const REJECTED = "rejected"; +const REVOKED = "revoked"; +const DONE = "done"; +const REJECT = "reject"; +const SAVING = "saving"; +const INPROGRESS = "in_progress"; -export const APPROVALS_TYPES = Object.freeze({ +const APPROVALS_TYPES = Object.freeze({ assessment: "assessment", case_plan: "case_plan", closure: "closure", @@ -516,7 +516,7 @@ export const APPROVALS_TYPES = Object.freeze({ gbv_closure: "gbv_closure" }); -export const ALERTS_FOR = { +const ALERTS_FOR = { field_change: "field_change", incident_details: "incident_details", services_section: "services_section", @@ -528,61 +528,61 @@ export const ALERTS_FOR = { referral: "referral" }; -export const MAX_OFFLINE_ROWS_PER_PAGE = 50; +const MAX_OFFLINE_ROWS_PER_PAGE = 50; -export const ROWS_PER_PAGE_OPTIONS = [20, 50, 75, 100]; +const ROWS_PER_PAGE_OPTIONS = [20, 50, 75, 100]; -export const OFFLINE_ROWS_PER_PAGE_OPTIONS = [20, 50]; +const OFFLINE_ROWS_PER_PAGE_OPTIONS = [20, 50]; -export const DEFAULT_METADATA = Object.freeze({ +const DEFAULT_METADATA = Object.freeze({ page: 1, per: 20 }); -export const LOCALE_KEYS = { +const LOCALE_KEYS = { en: "en", ne: "ne" }; -export const HTTP_STATUS = { +const HTTP_STATUS = { invalidRecord: 422 }; -export const DEFAULT_DATE_VALUES = { +const DEFAULT_DATE_VALUES = { TODAY: "TODAY", NOW: "NOW" }; -export const FETCH_PARAM = Object.freeze({ +const FETCH_PARAM = Object.freeze({ DATA: "data", OPTIONS: "options" }); -export const TRACING_REQUEST_STATUS_FIELD_NAME = "tracing_request_status"; +const TRACING_REQUEST_STATUS_FIELD_NAME = "tracing_request_status"; -export const TRACES_SUBFORM_UNIQUE_ID = "tracing_request_subform_section"; +const TRACES_SUBFORM_UNIQUE_ID = "tracing_request_subform_section"; -export const POTENTIAL_MATCH_LIKELIHOOD = { +const POTENTIAL_MATCH_LIKELIHOOD = { likely: "likely", possible: "possible" }; -export const MATCH_VALUES = { +const MATCH_VALUES = { match: "match", mismatch: "mismatch", blank: "blank" }; -export const FILE_FORMAT = { +const FILE_FORMAT = { pdf: "application/pdf" }; -export const FAMILY_MEMBERS_SUBFORM_ID = "family_members_section"; -export const FAMILY_FROM_CASE = "family_from_case"; +const FAMILY_MEMBERS_SUBFORM_ID = "family_members_section"; +const FAMILY_FROM_CASE = "family_from_case"; -export const FAMILY_DETAILS_SUBFORM_ID = "family_details_section"; +const FAMILY_DETAILS_SUBFORM_ID = "family_details_section"; -export const FORM_PERMISSION_ACTION = Object.freeze({ +const FORM_PERMISSION_ACTION = Object.freeze({ [INCIDENT_FROM_CASE]: VIEW_INCIDENTS_FROM_CASE, [CHANGE_LOGS]: SHOW_CHANGE_LOG, [APPROVALS]: SHOW_APPROVALS, @@ -591,7 +591,7 @@ export const FORM_PERMISSION_ACTION = Object.freeze({ [FAMILY_FROM_CASE]: READ_FAMILY_RECORD }); -export const VIOLATIONS_FORM = [ +const VIOLATIONS_FORM = [ "killing_violation_wrapper", "maiming_violation_wrapper", "recruitment_violation_wrapper", @@ -603,7 +603,7 @@ export const VIOLATIONS_FORM = [ "denial_humanitarian_access_violation_wrapper" ]; -export const VIOLATIONS_ASSOCIATIONS_FORM = [ +const VIOLATIONS_ASSOCIATIONS_FORM = [ "individual_victims_subform_section", "group_victims_section", "source_subform_section", @@ -611,7 +611,7 @@ export const VIOLATIONS_ASSOCIATIONS_FORM = [ "response_subform_section" ]; -export const VIOLATIONS_SUBFORM_UNIQUE_IDS = [ +const VIOLATIONS_SUBFORM_UNIQUE_IDS = [ "killing", "maiming", "recruitment", @@ -623,7 +623,7 @@ export const VIOLATIONS_SUBFORM_UNIQUE_IDS = [ "denial_humanitarian_access" ]; -export const VIOLATION_FORMS_MAPPING = Object.freeze({ +const VIOLATION_FORMS_MAPPING = Object.freeze({ killing: "killing_violation_wrapper", maiming: "maiming_violation_wrapper", recruitment: "recruitment_violation_wrapper", @@ -635,7 +635,7 @@ export const VIOLATION_FORMS_MAPPING = Object.freeze({ denial_humanitarian_access: "denial_humanitarian_access_violation_wrapper" }); -export const VIOLATIONS_ASSOCIATIONS_UNIQUE_IDS = [ +const VIOLATIONS_ASSOCIATIONS_UNIQUE_IDS = [ "individual_victims", "perpetrators", "group_victims", @@ -643,23 +643,33 @@ export const VIOLATIONS_ASSOCIATIONS_UNIQUE_IDS = [ "responses" ]; -export const VIOLATIONS_ASSOCIATIONS_RESPONSES = "responses"; +const VIOLATIONS_ASSOCIATIONS_RESPONSES = "responses"; -export const MRM_INSIGHTS_SUBREPORTS = [...VIOLATIONS_SUBFORM_UNIQUE_IDS, "detention"]; +const MRM_INSIGHTS_SUBREPORTS = [...VIOLATIONS_SUBFORM_UNIQUE_IDS, "detention"]; -export const GBV_INSIGHTS_SUBREPORTS = ["incidents", "perpetrators", "survivors", "referrals"]; +const GBV_INSIGHTS_SUBREPORTS = ["incidents", "perpetrators", "survivors", "referrals"]; -export const GHN_REPORT_SUBREPORTS = ["ghn_report"]; +const GHN_REPORT_SUBREPORTS = ["ghn_report"]; -export const INDIVIDUAL_CHILDREN = ["individual_children"]; +const INDIVIDUAL_CHILDREN = ["individual_children"]; -export const WORKFLOW_SUBREPORTS = ["cases_workflow", "incidents_workflow"]; +const WORKFLOW_SUBREPORTS = ["cases_workflow", "incidents_workflow"]; -export const REFERRAL_TRANSFERS_SUBREPORTS = ["total_transfers", "total_referrals"]; +const CASES_WORKFLOW_SUBREPORTS = ["cases_workflow"]; -export const VIOLENCE_TYPE_SUBREPORTS = ["cases_violence_type", "incidents_violence_type"]; +const PROTECTION_CONCERNS_SUBREPORTS = ["protection_concerns"]; -export const CHART_COLORS = Object.freeze({ +const REPORTING_LOCATIONS_SUBREPORTS = ["reporting_location_by_sex_and_age"]; + +const FOLLOWUPS_SUBREPORTS = ["followups"]; + +const SERVICES_SUBREPORTS = ["services"]; + +const REFERRAL_TRANSFERS_SUBREPORTS = ["total_transfers", "total_referrals"]; + +const VIOLENCE_TYPE_SUBREPORTS = ["cases_violence_type", "incidents_violence_type"]; + +const CHART_COLORS = Object.freeze({ blue: "rgb(0, 147, 186)", grey: "rgb(89, 89, 82)", purple: "rgb(124, 52, 123)", @@ -668,23 +678,23 @@ export const CHART_COLORS = Object.freeze({ orange: "rgb(231, 113, 45)", yellow: "rgb(242, 195, 23)" }); -export const SUBFORM_READONLY_FIELD_NAMES = ["matched_case_comparison"]; +const SUBFORM_READONLY_FIELD_NAMES = ["matched_case_comparison"]; -export const Q1 = "Q1"; -export const Q2 = "Q2"; -export const Q3 = "Q3"; -export const Q4 = "Q4"; +const Q1 = "Q1"; +const Q2 = "Q2"; +const Q3 = "Q3"; +const Q4 = "Q4"; -export const QUARTERS_TO_NUMBER = Object.freeze({ +const QUARTERS_TO_NUMBER = Object.freeze({ [Q1]: 1, [Q2]: 2, [Q3]: 3, [Q4]: 4 }); -export const QUARTERS = Object.freeze([Q1, Q2, Q3, Q4]); +const QUARTERS = Object.freeze([Q1, Q2, Q3, Q4]); -export const VIOLATION_TYPE = Object.freeze({ +const VIOLATION_TYPE = Object.freeze({ killing: "killing", maiming: "maiming", recruitment: "recruitment", @@ -696,16 +706,16 @@ export const VIOLATION_TYPE = Object.freeze({ denial_humanitarian_access: "denial_humanitarian_access" }); -export const VIOLATION_VERIFICATION_STATUS = Object.freeze({ +const VIOLATION_VERIFICATION_STATUS = Object.freeze({ verified: "verified", report_pending_verification: "report_pending_verification", not_mrm: "not_mrm", verification_found_that_incident_did_not_occur: "verification_found_that_incident_did_not_occur" }); -export const MAX_CONDITIONS = 4; +const MAX_CONDITIONS = 4; -export const QUICK_SEARCH_FIELDS = Object.freeze([ +const QUICK_SEARCH_FIELDS = Object.freeze([ "biometrics_id", "camp_id", "case_id", @@ -733,7 +743,7 @@ export const QUICK_SEARCH_FIELDS = Object.freeze([ "unique_identifier" ]); -export const DATE_SORTABLE_FIELDS = Object.freeze([ +const DATE_SORTABLE_FIELDS = Object.freeze([ "created_at", "registration_date", "incident_date", @@ -741,16 +751,150 @@ export const DATE_SORTABLE_FIELDS = Object.freeze([ "inquiry_date" ]); -export const NOTIFICATION_PERMISSIONS = { +const NOTIFICATION_PERMISSIONS = { GRANTED: "granted", DENIED: "denied", DEFAULT: "default" }; -export const POST_MESSAGES = { +const POST_MESSAGES = { SUBSCRIBE_NOTIFICATIONS: "subscribe_notifications", UNSUBSCRIBE_NOTIFICATIONS: "unsubscribe_notifications", DISPATCH_REMOVE_SUBSCRIPTION: "dispatch_remove_subscription", DISPATCH_SAVE_SUBSCRIPTION: "dispatch_save_subscription", ATTEMPTS_SUBSCRIPTION_FAILED: "attempts_subscription_failed" }; + +export { + API_BASE_PATH, + PASSWORD_MIN_LENGTH, + MAX_IMAGE_SIZE, + MAX_ATTACHMENT_SIZE, + FETCH_TIMEOUT, + DATABASE_NAME, + IDLE_TIMEOUT, + IDLE_LOGOUT_TIMEOUT, + TOKEN_REFRESH_INTERVAL, + PUSH_NOTIFICATION_SUBSCRIPTION_REFRESH_INTERVAL, + CASE, + CASES, + TRACING_REQUEST, + TRACING_REQUESTS, + INCIDENT, + INCIDENTS, + REGISTRY_RECORD, + REGISTRY_RECORDS, + FAMILIES, + FAMILY, + RECORD_TYPES, + RECORD_TYPES_PLURAL, + AGE_MAX, + MODULES, + MODULE_TYPE_FIELD, + USER_NAME_FIELD, + STRING_SOURCES_TYPES, + ID_FIELD, + UNIQUE_ID_FIELD, + DISPLAY_TEXT_FIELD, + NAME_FIELD, + CODE_FIELD, + INCIDENT_CASE_ID_FIELD, + INCIDENT_CASE_ID_DISPLAY_FIELD, + INCIDENT_SHORT_ID_FIELD, + CONSENT_GIVEN_FIELD_BY_MODULE, + RECORD_PATH, + RECORD_INFORMATION_GROUP, + IDENTIFICATION_REGISTRATION, + VIOLATION_GROUP, + RECORD_OWNER, + TRANSFERS_ASSIGNMENTS, + INCIDENT_TRANSFERS_ASSIGNMENTS, + REFERRAL, + APPROVALS, + INCIDENT_FROM_CASE, + REGISTRY_FROM_CASE, + CHANGE_LOGS, + SUMMARY, + SUMMARY_INCIDENT_MRM, + TRANSITION_TYPE, + RECORD_INFORMATION, + ROUTES, + PERMITTED_URL, + DATE_FORMAT, + DATE_FORMAT_NE, + MONTH_AND_YEAR_FORMAT, + API_DATE_FORMAT, + API_DATE_TIME_FORMAT, + TRANSITIONS_DATE_FORMAT, + DATE_TIME_FORMAT, + ISO_DATE_REGEX, + ISO_DATE_TIME_REGEX, + CODE_OF_CONDUCT_DATE_FORMAT, + MODES, + LOOKUPS, + ADMIN_NAV, + APPLICATION_NAV, + LOCATION_PATH, + METHODS, + SAVE_METHODS, + ACCEPTED, + ACCEPT, + REJECTED, + REVOKED, + DONE, + REJECT, + SAVING, + INPROGRESS, + APPROVALS_TYPES, + ALERTS_FOR, + MAX_OFFLINE_ROWS_PER_PAGE, + ROWS_PER_PAGE_OPTIONS, + OFFLINE_ROWS_PER_PAGE_OPTIONS, + DEFAULT_METADATA, + LOCALE_KEYS, + HTTP_STATUS, + DEFAULT_DATE_VALUES, + FETCH_PARAM, + TRACING_REQUEST_STATUS_FIELD_NAME, + TRACES_SUBFORM_UNIQUE_ID, + POTENTIAL_MATCH_LIKELIHOOD, + MATCH_VALUES, + FILE_FORMAT, + FAMILY_MEMBERS_SUBFORM_ID, + FAMILY_FROM_CASE, + FAMILY_DETAILS_SUBFORM_ID, + FORM_PERMISSION_ACTION, + VIOLATIONS_FORM, + VIOLATIONS_ASSOCIATIONS_FORM, + VIOLATIONS_SUBFORM_UNIQUE_IDS, + VIOLATION_FORMS_MAPPING, + VIOLATIONS_ASSOCIATIONS_UNIQUE_IDS, + VIOLATIONS_ASSOCIATIONS_RESPONSES, + MRM_INSIGHTS_SUBREPORTS, + GBV_INSIGHTS_SUBREPORTS, + GHN_REPORT_SUBREPORTS, + INDIVIDUAL_CHILDREN, + WORKFLOW_SUBREPORTS, + CASES_WORKFLOW_SUBREPORTS, + PROTECTION_CONCERNS_SUBREPORTS, + REPORTING_LOCATIONS_SUBREPORTS, + FOLLOWUPS_SUBREPORTS, + SERVICES_SUBREPORTS, + REFERRAL_TRANSFERS_SUBREPORTS, + VIOLENCE_TYPE_SUBREPORTS, + CHART_COLORS, + SUBFORM_READONLY_FIELD_NAMES, + Q1, + Q2, + Q3, + Q4, + QUARTERS_TO_NUMBER, + QUARTERS, + VIOLATION_TYPE, + VIOLATION_VERIFICATION_STATUS, + MAX_CONDITIONS, + QUICK_SEARCH_FIELDS, + DATE_SORTABLE_FIELDS, + NOTIFICATION_PERMISSIONS, + POST_MESSAGES +}; diff --git a/app/javascript/config/constants.unit.test.js b/app/javascript/config.unit.test.js similarity index 96% rename from app/javascript/config/constants.unit.test.js rename to app/javascript/config.unit.test.js index 3f2994549a..b1dd9423bc 100644 --- a/app/javascript/config/constants.unit.test.js +++ b/app/javascript/config.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import * as configConstants from "./constants"; +import * as configConstants from "./config"; describe("Verifying config constant", () => { it("exports an object", () => { @@ -109,6 +109,7 @@ describe("Verifying config constant", () => { "SUBFORM_READONLY_FIELD_NAMES", "SUMMARY", "WORKFLOW_SUBREPORTS", + "CASES_WORKFLOW_SUBREPORTS", "TOKEN_REFRESH_INTERVAL", "TRACES_SUBFORM_UNIQUE_ID", "TRACING_REQUEST", @@ -144,7 +145,11 @@ describe("Verifying config constant", () => { "INDIVIDUAL_CHILDREN", "NOTIFICATION_PERMISSIONS", "POST_MESSAGES", - "PUSH_NOTIFICATION_SUBSCRIPTION_REFRESH_INTERVAL" + "PUSH_NOTIFICATION_SUBSCRIPTION_REFRESH_INTERVAL", + "PROTECTION_CONCERNS_SUBREPORTS", + "REPORTING_LOCATIONS_SUBREPORTS", + "SERVICES_SUBREPORTS", + "FOLLOWUPS_SUBREPORTS" ].forEach(property => { it(`exports '${property}'`, () => { expect(configConstants).to.have.property(property); diff --git a/app/javascript/config/endpoint-mocks.js b/app/javascript/config/endpoint-mocks.js deleted file mode 100644 index 8a6c2529c9..0000000000 --- a/app/javascript/config/endpoint-mocks.js +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -// FIXME: This file is never imported. - -const HOST = "https://unicefpartners.b2clogin.com"; - -export default async () => ({ - data: [ - { - id: 1, - unique_id: "unicef", - name: "UNICEF", - provider_type: "b2c", - client_id: "e3443e90-18bc-4a23-9982-7fd5e67ff339", - authorization_url: `${HOST}/tfp/unicefpartners.onmicrosoft.com/B2C_1_PrimeroSignUpSignIn`, - identity_scope: ["e3443e90-18bc-4a23-9982-7fd5e67ff339"], - verification_url: `${HOST}/unicefpartners.onmicrosoft.com/discovery/v2.0/keys?p=B2C_1_PrimeroSignUpSignIn` - }, - { - id: 2, - unique_id: "primeroims", - name: "Primero", - provider_type: "b2c", - client_id: "e3443e90-18bc-4a23-9982-7fd5e67ff339", - authorization_url: `${HOST}/tfp/unicefpartners.onmicrosoft.com/B2C_1_PrimeroSignUpSignIn`, - identity_scope: ["e3443e90-18bc-4a23-9982-7fd5e67ff339"], - verification_url: `${HOST}/unicefpartners.onmicrosoft.com/discovery/v2.0/keys?p=B2C_1_PrimeroSignUpSignIn` - }, - { - id: 3, - unique_id: "unitstonelogin", - name: "Partner", - provider_type: "b2c", - client_id: "e3443e90-18bc-4a23-9982-7fd5e67ff339", - authorization_url: `${HOST}/tfp/unicefpartners.onmicrosoft.com/B2C_1_PrimeroSignUpSignIn`, - identity_scope: ["e3443e90-18bc-4a23-9982-7fd5e67ff339"], - verification_url: `${HOST}/unicefpartners.onmicrosoft.com/discovery/v2.0/keys?p=B2C_1_PrimeroSignUpSignIn` - } - ], - metadata: { - use_identity_provider: true - } -}); diff --git a/app/javascript/config/index.js b/app/javascript/config/index.js deleted file mode 100644 index c928c2023d..0000000000 --- a/app/javascript/config/index.js +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -/* eslint-disable import/no-cycle */ -export { default as routes } from "./routes"; -export { default as theme } from "./theme"; -export * from "./constants"; diff --git a/app/javascript/config/theme.js b/app/javascript/config/theme.js deleted file mode 100644 index 45aae6e491..0000000000 --- a/app/javascript/config/theme.js +++ /dev/null @@ -1,533 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { fade } from "@material-ui/core/styles"; -import mapKeys from "lodash/mapKeys"; -import kebabCase from "lodash/kebabCase"; - -import importedTheme from "../libs/load-external-theme"; - -const generateCssVarKey = (prefix, key) => `--${prefix}-${kebabCase(key)}`; - -const valueWithUnit = (value, unit) => (unit ? `${value}${unit}` : value); - -const setCssVars = (prefix, vars, func, unit) => { - if (Array.isArray(vars)) { - return vars.reduce( - (prev, current) => ({ ...prev, [generateCssVarKey(prefix, current)]: valueWithUnit(func(current), unit) }), - {} - ); - } - - return mapKeys(vars, (_, key) => generateCssVarKey(prefix, key)); -}; - -const colors = { - black: "#231f20", // u - blue: "#0F809E", // u - lightBlue: "#239EBF", // u - blueHover: "#0B6178", // u - blueHoverLight: "rgba(15, 128, 158, .18)", // u - whiteHover: "#e6efd4", // u - contentGrey: "#fbfbfb", // u - darkBlue: "#048BB0", - darkBrown: "#5a5549", - darkGrey: "#595952", // u - goldYellow: "#f4ac22", - green: "#839e3c", // u - grey: "#4a4a4a", // u - lightBlueRgba: "rgba(0, 147, 186, 0.25)", // u - lightBlueMenu: "#dfeff4", - lightGrey: "#f0f0f0", // u - lightGrey2: "#e0e0e0", - midGrey: "#757472", // u - yellow: "#f2b417", // u - orange: "#C4540C", // u - purple: "#7c347b", // u - red: "#d0021b", // u - redLabelError: "#f44336", - solidBlack: "#000000", - solidGreen: "#7ba024", - solidOrange: "#ff9500", - stickyGrey: "rgba(251, 251, 251, 0.95)", - tundora: "#454545", - warmGrey1: "#e0dfd7", - warmGrey2: "#bcbcad", - warmGrey3: "#b9b8b3", - warmGrey4: "#9a988f", - warmGrey5: "#d5d5d5", - warmGrey6: "#6f6f6a", - white: "#ffffff", // u - wildSand: "#f5f5f5", - greenLight: "#E6EED3", // u, - redMedium: "#E7712D", - redLow: "#F7D0BA", - forgotPasswordLink: "var(--c-blue)", - networkIndicatorBorder: "var(--c-solid-green)", - navListIcon: "var(--c-dark-grey))", - navListText: "var(--c-dark-grey)", - navListTextActive: "var(--c-black)", - navListIconActive: "var(--c-black)", - navListBgActive: "var(--c-content-grey)", - navListDivider: "var(--c-warm-grey-1)", - drawerHeaderButton: "transparent", - drawerHeaderButtonText: "var(--c-white)", - toolbarBackgroundColor: "linear-gradient(to top, var(--c-white), var(--c-light-grey))", - toolbarBackgroundButton: "var(--c-blue)", - mobileToolbarBackground: - // eslint-disable-next-line max-len - "linear-gradient(to top, var(--c-white), var(--c-light-grey)), linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.14))", - mobileToolbarHamburgerButton: "rgba(0, 0, 0, 0.54)", - loginBackgroundGradientStart: "var(--c-blue)", - loginBackgroundGradientEnd: "var(--c-blue)", - loginTranslationsButtonBackground: "transparent", - loginTranslationsButtonText: "var(--c-white)", - ...importedTheme.colors -}; - -const fontFamily = ["helvetica", "roboto", "arial", "sans-serif"].join(", "); -const fontSizes = [9, 12, 13, 14, 16, 18, 20, 30, 96, 130, 186]; -const shadows = ["0 2px 12px 0 rgba(125, 125, 125, 0.23)"]; -const drawerWidth = "240px"; -const spacing = [1, 2, 3, 4]; - -const overrides = { - MuiCssBaseline: { - "@global": { - "#root": { - display: "flex", - flexDirection: "column", - height: `var(--doc-height, 100vh)` - }, - legend: { - display: "none" - } - } - }, - MuiPaper: { - elevation3: { - boxShadow: "0 2px 12px 0 rgba(125, 125, 125, 0.23)" - }, - elevation2: { - boxShadow: "0 2px 1px 0 rgba(89, 89, 81, 0.05)" - } - }, - MuiAccordionSummary: { - content: { - margin: "0" - } - }, - MuiInputLabel: { - root: { - lineHeight: "1.5em", - // fontSize: `var(--fs-${isRTL ? 16 : 12})`, - fontWeight: 700, - marginBottom: ".5em", - color: colors.black, - "&$focused": { - color: colors.black - }, - "&$disabled": { - color: colors.black - } - }, - outlined: { - marginBottom: 0 - }, - shrink: { - transform: "none !important" - }, - formControl: { - position: "relative" - }, - asterisk: { - color: "var(--c-red)" - } - }, - MuiInputBase: { - root: { - "&$disabled": { - cursor: "not-allowed !important" - } - }, - input: { - "&$disabled": { - color: "var(--c-black)", - cursor: "not-allowed !important" - } - } - }, - MuiInput: { - input: { - border: "1px solid var(--c-black)", - borderRadius: "6px", - "$:focus": { - borderColor: colors.yellow - }, - "&:read-only": { - color: colors.black, - paddingBottom: "3px" - }, - "&:read-only ::placeholder": { - color: colors.black, - opacity: 1 - } - }, - formControl: { - "label + &": { - marginTop: 0 - } - } - }, - MuiCheckbox: { - root: { - color: colors.black, - padding: "0 var(--sp-1)", - "&$checked": { - color: `${colors.black} !important` - } - } - }, - MuiRadio: { - root: { - padding: "0 var(--sp-1)", - "&$checked": { - color: `${colors.black} !important` - } - } - }, - MuiFormControlLabel: { - root: { - "&$disabled": { - cursor: "not-allowed" - } - }, - label: { - fontSize: "var(--fs-13) !important", - "&$disabled": { - color: colors.black - } - } - }, - MuiFormHelperText: { - root: { - lineHeight: "1.4em", - whiteSpace: "pre-wrap" - }, - contained: { - marginLeft: 0, - marginRight: 0 - } - }, - MUIDataTableToolbar: { - root: { - paddingLeft: "5px", - paddingRight: "5px", - paddingTop: "8px", - paddingBottom: "8px", - justifyContent: "flex-start" - }, - titleText: { - position: "absolute", - left: "-10000px", - top: "auto", - width: "1px", - height: "1px", - overflow: "hidden" - }, - left: { - display: "none !important" - } - }, - MUIDataTableToolbarSelect: { - root: { - paddingLeft: "5px", - paddingRight: "5px", - paddingTop: "8px", - paddingBottom: "8px", - justifyContent: "flex-start", - backgroundColor: colors.white, - boxShadow: "none" - }, - title: { - display: "none" - } - }, - MuiTableRow: { - hover: { - cursor: "pointer", - "&:hover": { - background: colors.lightGrey - } - } - }, - MUIDataTableHeadCell: { - root: { - fontWeight: "900", - textTransform: "uppercase", - fontSize: "var(--fs-12)", - color: `${colors.black}`, - lineHeight: "1.3em", - padding: ".5em" - } - }, - MuiChip: { - sizeSmall: { - height: "21px", - fontSize: "var(--fs-12)" - } - }, - MuiDialogActions: { - root: { - justifyContent: "flex-start", - margin: "var(--sp-1)" - }, - spacing: { - gap: "var(--sp-1)" - } - }, - MuiDialogTitle: { - root: { - textTransform: "uppercase", - fontSize: "var(--fs-16)", - fontWeight: "bold", - padding: "var(--sp-2)" - } - }, - MuiDialogContent: { - root: { - padding: "0 var(--sp-2)" - } - }, - MuiSnackbarContent: { - root: { - backgroundColor: `${colors.white} !important`, - color: `${colors.grey} !important`, - fontWeight: "bold !important", - fontSize: "var(--fs-13) !important" - }, - message: { - flex: "1 0", - backgroundColor: `${colors.white} !important`, - "& svg": { - fontSize: "var(--fs-16) !important", - marginRight: "5px" - } - }, - action: { - paddingLeft: 0, - backgroundColor: `${colors.white} !important`, - "& svg": { - fontSize: "$var(--fs-16) !important", - color: `${colors.darkGrey} !important` - } - } - }, - MuiFab: { - sizeSmall: { - width: "36px", - height: "36px" - } - }, - MuiToggleButton: { - root: { - fontWeight: 600, - textTransform: "none" - } - }, - MuiButton: { - root: { - letterSpacing: "normal", - lineHeight: "normal", - textTransform: "none", - fontSize: "var(--fs-14)", - fontWeight: 600, - borderRadius: "6px", - "&$disabled": { - color: "rgba(0, 0, 0, 0.26)", - backgroundColor: `${colors.lightGrey} !important` - } - }, - containedPrimary: { - "&:hover, &:active, &:focus": { - // TODO: @media is overriding this style - backgroundColor: "var(--c-blue-hover) !important", - "&$disabled": { - color: "rgba(0, 0, 0, 0.26)", - backgroundColor: `${colors.lightGrey} !important` - } - } - }, - outlinedPrimary: { - "&:hover, &:active, &focus": { - borderColor: "var(--c-blue-hover)", - color: "var(--c-blue-hover)", - "&$disabled": { - color: "rgba(0, 0, 0, 0.26)", - backgroundColor: `${colors.lightGrey} !important` - } - } - } - }, - MuiFormGroup: { - root: { - gap: "var(--sp-2)" - } - }, - MuiFormLabel: { - root: { - fontSize: "var(--fs-13)" - } - }, - MuiAutocomplete: { - inputRoot: { - padding: "0 !important" - }, - tag: { - margin: "var(--sp-1)", - height: "var(--sp-13)", - - "& svg": { - width: "16px", - height: "16px" - } - } - }, - MuiListItemText: { - root: { - textAlign: "initial", - wordBreak: "break-word" - } - }, - MuiMenu: { - paper: { - borderRadius: "6px", - overflow: "visible", - marginTop: "var(--sp-1)", - "&::before": { - backgroundColor: "var(--c-white)", - content: '""', - display: "block", - position: "absolute", - width: 12, - height: 12, - top: -6, - transform: "rotate(45deg)", - right: 12, - zIndex: 10 - }, - "&::after": { - backgroundColor: "var(--c-white)", - content: '""', - display: "block", - position: "absolute", - width: 12, - height: 12, - top: -6, - transform: "rotate(45deg)", - right: 12, - zIndex: -10, - boxShadow: shadows[2] - } - } - }, - MuiLink: { - root: { - display: "block", - cursor: "pointer", - "&:hover, &:active, &focus": { - color: "var(--c-blue-hover)" - } - } - }, - MuiStepLabel: { - root: { - fontWeight: 600 - } - }, - MuiOutlinedInput: { - root: { - padding: 0, - fontSize: "var(--fs-16)", - background: "var(--c-white)", - "&$focused": { - borderColor: colors.blue, - boxShadow: `${fade(colors.blue, 0.25)} 0 0 0 0.2rem` - }, - "&$disabled": { - "& .MuiChip-root": { - opacity: 1 - }, - "& .MuiChip-root .MuiChip-deleteIcon": { - display: "none" - }, - "& fieldset.MuiOutlinedInput-notchedOutline": { - borderColor: "var(--c-warm-grey-2)" - } - } - }, - input: { - padding: "var(--sp-1)" - }, - multiline: { - padding: "var(--sp-1)" - }, - notchedOutline: { - borderColor: "var(--c-black)", - top: 0, - "& legend": { - display: "none" - } - } - } -}; - -const props = { - MuiButtonBase: { - disableRipple: true - }, - MuiMenu: { - anchorOrigin: { - vertical: "bottom", - horizontal: "right" - }, - transformOrigin: { - vertical: "top", - horizontal: "right" - } - }, - MuiTextField: { - variant: "outlined" - } -}; - -const transitions = { - create: () => "none" -}; - -export default { - palette: { - primary: { - main: colors.blue - }, - secondary: { - main: colors.blue - } - }, - typography: { - useNextVariants: true, - fontFamily, - fontWeight: 600 - }, - primero: { - colors, - shadows, - components: { - drawerWidth - } - }, - overrides, - props, - transitions -}; - -export { setCssVars, fontSizes, colors, spacing, drawerWidth, shadows, fontFamily }; diff --git a/app/javascript/date-provider.jsx b/app/javascript/date-provider.jsx new file mode 100644 index 0000000000..40e51755bb --- /dev/null +++ b/app/javascript/date-provider.jsx @@ -0,0 +1,32 @@ +import { LocalizationProvider } from "@mui/x-date-pickers"; +import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns"; +import PropTypes from "prop-types"; + +import localize from "./libs/date-picker-localization"; +import { useI18n } from "./components/i18n"; + +const localeText = { + fieldYearPlaceholder: params => "y".repeat(params.digitAmount), + fieldMonthPlaceholder: params => (params.contentType === "letter" ? "mmm" : "mm"), + fieldDayPlaceholder: () => "dd" +}; + +function DateProvider({ children, excludeAdpaterLocale = false }) { + const i18n = useI18n(); + const adapterLocale = excludeAdpaterLocale ? null : localize(i18n); + + return ( + + {children} + + ); +} + +DateProvider.displayName = "DateProvider"; + +DateProvider.propTypes = { + children: PropTypes.node, + excludeAdpaterLocale: PropTypes.bool +}; + +export default DateProvider; diff --git a/app/javascript/db/collections/records.js b/app/javascript/db/collections/records.js index 44576df97d..21fabbca1b 100644 --- a/app/javascript/db/collections/records.js +++ b/app/javascript/db/collections/records.js @@ -13,7 +13,7 @@ import { isDate, parseISO } from "date-fns"; import DB from "../db"; import subformAwareMerge from "../utils/subform-aware-merge"; import { QUICK_SEARCH_FIELDS, DATE_SORTABLE_FIELDS } from "../../config"; -import { reduceMapToObject, hasApiDateFormat } from "../../libs"; +import { hasApiDateFormat, reduceMapToObject } from "../../libs/component-helpers"; const Records = { find: async ({ collection, recordType, db, json }) => { @@ -117,8 +117,6 @@ const Records = { return { ...data, ...sortableDateFields, - complete_sortable: data.complete ? 1 : 0, - has_photo: data.photo ? 1 : 0, terms: QUICK_SEARCH_FIELDS.reduce((acc, quickField) => { const value = data[quickField]; @@ -137,8 +135,9 @@ const Records = { const dataKeys = Object.keys(data); const jsonData = dataKeys.length === 1 && dataKeys.includes("record") ? data.record : data; const dataIsArray = Array.isArray(jsonData); + const markComplete = !(fields === "short" || idSearch); const recordData = Records.dataSearchableFields( - Records.dataMarkedComplete(jsonData, !(fields === "short" || idSearch), online), + Records.dataMarkedComplete(jsonData, markComplete, online), recordType ); @@ -153,6 +152,23 @@ const Records = { queryIndex: { index: "type", value: recordType + }, + callbacks: { + beforeSave(record, prev) { + if (prev) { + return { + ...record, + complete_sortable: prev.complete || record.complete ? 1 : 0, + has_photo: prev.photo || record.photo ? 1 : 0 + }; + } + + return { + ...record, + complete_sortable: 0, + has_photo: 0 + }; + } } }); diff --git a/app/javascript/db/constants.js b/app/javascript/db/constants.js index 714d20e44c..51975981d0 100644 --- a/app/javascript/db/constants.js +++ b/app/javascript/db/constants.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { RECORD_PATH } from "../config/constants"; +import { RECORD_PATH } from "../config"; export const DB_STORES = Object.freeze({ TRANSLATIONS: "translations", diff --git a/app/javascript/db/db.js b/app/javascript/db/db.js index 1c04709b4e..9af7736e79 100644 --- a/app/javascript/db/db.js +++ b/app/javascript/db/db.js @@ -7,7 +7,7 @@ import fuzzysort from "fuzzysort"; import sortBy from "lodash/sortBy"; import uniq from "lodash/uniq"; -import { DATABASE_NAME } from "../config/constants"; +import { DATABASE_NAME } from "../config"; import recordMerge from "./utils/record-merge"; import { @@ -63,6 +63,10 @@ class DB { return DB.instance; } + async closeDB() { + (await this._db).close(); + } + createCollections(collection, db, transaction) { if (Array.isArray(collection)) { const [name, options, index] = collection; @@ -184,7 +188,7 @@ class DB { return isArray ? this.bulkAdd(args) : this.put(args); } - async put({ store, data, key = {}, queryIndex }) { + async put({ store, data, key = {}, queryIndex, callbacks = {} }) { const item = data; if (queryIndex) { @@ -198,7 +202,11 @@ class DB { const prev = await objectStore.get(isEmpty(key) ? item.id : key); if (prev) { - const record = recordMerge(prev, item, key); + let record = recordMerge(prev, item, key); + + if (callbacks.beforeSave) { + record = callbacks.beforeSave(record, prev); + } await objectStore.put(record); @@ -208,7 +216,11 @@ class DB { } throw new Error("Record is new"); } catch (e) { - const record = { ...item, ...key }; + let record = { ...item, ...key }; + + if (callbacks.beforeSave) { + record = callbacks.beforeSave(record); + } await objectStore.put(record); @@ -224,7 +236,7 @@ class DB { } } - async bulkAdd({ store, data, queryIndex }) { + async bulkAdd({ store, data, queryIndex, callbacks = {} }) { const isDataArray = Array.isArray(data); const tx = (await this._db).transaction(store, TRANSACTION_MODE.READ_WRITE); const collection = tx.objectStore(store); @@ -241,13 +253,21 @@ class DB { const prev = await collection.get(isDataArray ? _record.id : data[_record]?.id); if (prev) { - const item = isDataArray ? recordMerge(prev, _record) : recordMerge(prev, data[_record]); + let item = isDataArray ? recordMerge(prev, _record) : recordMerge(prev, data[_record]); records.push(item); + if (callbacks.beforeSave) { + item = callbacks.beforeSave(item, prev); + } + await collection.put(item); } else { - const item = isDataArray ? _record : data[_record]; + let item = isDataArray ? _record : data[_record]; + + if (callbacks.beforeSave) { + item = callbacks.beforeSave(item, prev); + } records.push(item); await collection.put(item); diff --git a/app/javascript/images/primero-icons.js b/app/javascript/images/primero-icons.js index 09d6050370..fc899820a6 100644 --- a/app/javascript/images/primero-icons.js +++ b/app/javascript/images/primero-icons.js @@ -2,7 +2,7 @@ /* eslint-disable */ -import SvgIcon from "@material-ui/core/SvgIcon"; +import SvgIcon from "@mui/material/SvgIcon"; // NOTICE: All svg icons's path should be added in this file. They should be wrapped by the SvgIcon // component. By adding them here they are controlled by Material UI. @@ -62,7 +62,7 @@ export const DateInput = props => ( export const DateAndTimeInput = props => ( - + ) diff --git a/app/javascript/libs/build-field-map.js b/app/javascript/libs/build-field-map.js index 776c8427a1..c319168b77 100644 --- a/app/javascript/libs/build-field-map.js +++ b/app/javascript/libs/build-field-map.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { get } from "../components/form/utils"; +import { get } from "../components/form/utils/get"; const OWNED_BY = "owned_by"; const OWNED_BY_FULL_NAME = "owned_by_full_name"; diff --git a/app/javascript/libs/component-helpers.js b/app/javascript/libs/component-helpers.js index b57d993a64..6973f1fb42 100644 --- a/app/javascript/libs/component-helpers.js +++ b/app/javascript/libs/component-helpers.js @@ -1,10 +1,10 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { isImmutable, List, Map, Record } from "immutable"; -import { addHours, format, parseISO } from "date-fns"; +import { addHours, format } from "date-fns"; import isString from "lodash/isString"; -import { API_DATE_FORMAT, API_DATE_TIME_FORMAT, ISO_DATE_REGEX, ISO_DATE_TIME_REGEX } from "../config/constants"; +import { API_DATE_FORMAT, API_DATE_TIME_FORMAT, ISO_DATE_REGEX, ISO_DATE_TIME_REGEX } from "../config"; import displayNameHelper from "./display-name-helper"; @@ -62,16 +62,19 @@ export const normalizeTimezone = date => { return addHours(date, offset); }; -export const toServerDateFormat = (date, options) => { +export const toServerDateFormat = (date, options = {}) => { const includeTime = options?.includeTime || false; const normalize = options?.normalize !== false; const normalizedDate = includeTime && normalize ? normalizeTimezone(date) : date; + const dateFormat = includeTime ? API_DATE_TIME_FORMAT : API_DATE_FORMAT; - return format(normalizedDate, includeTime ? API_DATE_TIME_FORMAT : API_DATE_FORMAT); -}; + if (options.callback) { + return format(options.callback(normalizedDate), dateFormat); + } -export const endOfDay = date => parseISO(date.toISOString().replace(/T.+/, "").concat("T23:59:59Z")); + return format(normalizedDate, dateFormat); +}; export const hasApiDateFormat = value => isString(value) && Boolean(value.match(ISO_DATE_REGEX) || value.match(ISO_DATE_TIME_REGEX)); diff --git a/app/javascript/libs/component-helpers.unit.test.js b/app/javascript/libs/component-helpers.unit.test.js index 7b7c3acb80..da5ed8abd0 100644 --- a/app/javascript/libs/component-helpers.unit.test.js +++ b/app/javascript/libs/component-helpers.unit.test.js @@ -3,12 +3,11 @@ import { fromJS } from "immutable"; import { parseISO } from "date-fns"; -import { useFakeTimers } from "../test"; +import { useFakeTimers } from "../test-utils"; import { compare, dataToJS, - endOfDay, normalizeTimezone, toServerDateFormat, valuesToSearchableSelect, @@ -164,10 +163,4 @@ describe("component-helpers", () => { clock.restore(); }); }); - - describe("endOfDay", () => { - it("should return the end of day for an input date", () => { - expect(endOfDay(new Date("2010-05-01")).toISOString()).to.equal("2010-05-01T23:59:59.000Z"); - }); - }); }); diff --git a/app/javascript/libs/conditional-wrapper.js b/app/javascript/libs/conditional-wrapper.js index 3935c012ac..96723f4dbb 100644 --- a/app/javascript/libs/conditional-wrapper.js +++ b/app/javascript/libs/conditional-wrapper.js @@ -3,20 +3,25 @@ /* eslint-disable import/prefer-default-export */ import PropTypes from "prop-types"; -const ConditionalWrapper = ({ condition, wrapper: Wrapper, children, ...rest }) => { +function ConditionalWrapper({ condition, wrapper: Wrapper, children, ...rest }) { if (condition) { return typeof Wrapper === "function" ? Wrapper({ children, ...rest }) : {children}; } return children; -}; +} ConditionalWrapper.displayName = "ConditionalWrapper"; ConditionalWrapper.propTypes = { - children: PropTypes.node, + children: PropTypes.element, condition: PropTypes.bool, - wrapper: PropTypes.node + wrapper: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + PropTypes.element, + PropTypes.elementType + ]) }; export { ConditionalWrapper }; diff --git a/app/javascript/libs/conditional-wrapper.unit.test.js b/app/javascript/libs/conditional-wrapper.spec.js similarity index 51% rename from app/javascript/libs/conditional-wrapper.unit.test.js rename to app/javascript/libs/conditional-wrapper.spec.js index 978ce3d2f9..a81203869a 100644 --- a/app/javascript/libs/conditional-wrapper.unit.test.js +++ b/app/javascript/libs/conditional-wrapper.spec.js @@ -1,8 +1,5 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import { Tooltip } from "@material-ui/core"; - -import { createSimpleMount } from "../test"; +import { Tooltip } from "@mui/material"; +import { simpleMountedComponent, screen, fireEvent, waitFor } from "test-utils"; import { ConditionalWrapper } from "./conditional-wrapper"; @@ -15,35 +12,37 @@ describe("libs/conditional-wrapper", () => { ); it("wraps component with props if condition true", () => { - const component = createSimpleMount( + simpleMountedComponent(
wrapped children
); - expect(component.contains("wrapper content")).to.be.true; - expect(component.contains("wrapped children")).to.be.true; + expect(screen.getByText(/wrapped children/i)).toBeInTheDocument(); + expect(screen.getByText(/wrapper content/i)).toBeInTheDocument(); }); it("does not wrap component if condition false", () => { - const component = createSimpleMount( + simpleMountedComponent(
wrapped children
); - expect(component.contains("wrapper content")).to.be.false; - expect(component.contains("wrapped children")).to.be.true; + expect(screen.getByText(/wrapped children/i)).toBeInTheDocument(); + expect(screen.queryByText(/wrapper content/i)).toBeNull(); }); - it("renders react components", () => { - const component = createSimpleMount( + it("renders react components", async () => { + simpleMountedComponent(
wrapped children
); - expect(component.find(Tooltip).prop("title")).to.equal("wrapper content"); - expect(component.contains("wrapped children")).to.be.true; + fireEvent.mouseOver(screen.getByText(/wrapped children/i)); + await waitFor(() => expect(screen.queryByText(/wrapper content/i)).toBeInTheDocument()); + + expect(screen.getByText(/wrapped children/i)).toBeInTheDocument(); }); }); diff --git a/app/javascript/libs/error-logger.js b/app/javascript/libs/error-logger.js index 758ac5faa5..9bf577d67c 100644 --- a/app/javascript/libs/error-logger.js +++ b/app/javascript/libs/error-logger.js @@ -9,8 +9,11 @@ const ERROR_STORE_LIMIT = 50; let handlersRegistered = false; const store = "errors"; +const isProd = process.env.NODE_ENV !== "development"; -window.console.defaultError = window.console.error.bind(console); +if (isProd) { + window.console.defaultError = window.console.error.bind(console); +} const _db = openDB("error-logger", 1, { upgrade(db) { @@ -69,7 +72,7 @@ function consoleErrorLogger(args) { } async function startErrorListeners() { - if (!handlersRegistered) { + if (!handlersRegistered && isProd) { cleanDB(); window.onerror = errorHandler; window.addEventListener("unhandledrejection", rejectionHandler); diff --git a/app/javascript/libs/expressions/operators/avg.js b/app/javascript/libs/expressions/operators/avg.js index 6cd34d6b52..3dd808f13a 100644 --- a/app/javascript/libs/expressions/operators/avg.js +++ b/app/javascript/libs/expressions/operators/avg.js @@ -7,12 +7,12 @@ import { MATHEMATICAL_OPERATORS } from "../constants"; import sumOperator from "./sum"; -export default expressions => ({ +export default (expressions, extra) => ({ expressions, operator: MATHEMATICAL_OPERATORS.AVG, evaluate: data => { + const decimalPlaces = extra?.decimalPlaces; const sum = sumOperator(expressions).evaluate(data); - const count = Object.values(expressions).reduce((prev, current) => { if (has(data, current) && !isNil(data[current]) && data[current] !== "") { return prev + 1; @@ -21,6 +21,13 @@ export default expressions => ({ return prev; }, 0); - return Math.floor(sum / (count === 0 ? 1 : count)); + const res = sum / (count === 0 ? 1 : count); + + if (decimalPlaces || decimalPlaces === 0) { + return parseFloat(res.toFixed(decimalPlaces)); + } + + // Backwards compatible version rounds down + return Math.floor(res); } }); diff --git a/app/javascript/libs/expressions/operators/avg.unit.test.js b/app/javascript/libs/expressions/operators/avg.unit.test.js index ada9f4b2da..fc72765743 100644 --- a/app/javascript/libs/expressions/operators/avg.unit.test.js +++ b/app/javascript/libs/expressions/operators/avg.unit.test.js @@ -6,6 +6,8 @@ import avgOperator from "./avg"; describe("avgOperator", () => { const operator = avgOperator(["a", "b", "c"]); + const decimalPlaceOperator = avgOperator(["a", "b", "c"], { decimalPlaces: 3 }); + const roundOperator = avgOperator(["a", "b", "c"], { decimalPlaces: 0 }); it("should return avg", () => { expect(operator.evaluate({ a: 3, b: 4, c: 2 })).to.deep.equals(3); @@ -22,4 +24,10 @@ describe("avgOperator", () => { it("returns 0 when no argument passed", () => { expect(operator.evaluate({})).to.deep.equals(0); }); + it("returns a float when decimal places are specified", () => { + expect(decimalPlaceOperator.evaluate({ a: 1, b: 4 })).to.deep.equals(2.5); + }); + it("rounds correctly if decimalPlaces are 0", () => { + expect(roundOperator.evaluate({ a: 1, b: 1, c: 3 })).to.deep.equals(2); + }); }); diff --git a/app/javascript/libs/expressions/operators/eq.js b/app/javascript/libs/expressions/operators/eq.js index 795b5c970c..febcaf9253 100644 --- a/app/javascript/libs/expressions/operators/eq.js +++ b/app/javascript/libs/expressions/operators/eq.js @@ -1,8 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS, isImmutable } from "immutable"; -import { parseISO } from "date-fns"; -import isEqualDate from "date-fns/isEqual"; +import { parseISO, isEqual as isEqualDate } from "date-fns"; import first from "lodash/first"; import isEqual from "lodash/isEqual"; import isNil from "lodash/isNil"; diff --git a/app/javascript/libs/expressions/operators/ge.js b/app/javascript/libs/expressions/operators/ge.js index e2ecc2c588..c4ed13edff 100644 --- a/app/javascript/libs/expressions/operators/ge.js +++ b/app/javascript/libs/expressions/operators/ge.js @@ -1,7 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { isAfter, parseISO } from "date-fns"; -import isEqualDate from "date-fns/isEqual"; +import { isAfter, parseISO, isEqual } from "date-fns"; import first from "lodash/first"; import { hasApiDateFormat } from "../../component-helpers"; @@ -23,7 +22,7 @@ export default expression => ({ const date1 = parseISO(dataValue); const date2 = parseISO(value); - return isAfter(date1, date2) || isEqualDate(date1, date2); + return isAfter(date1, date2) || isEqual(date1, date2); } return dataValue >= value; diff --git a/app/javascript/libs/expressions/operators/le.js b/app/javascript/libs/expressions/operators/le.js index a6d626f031..491befc991 100644 --- a/app/javascript/libs/expressions/operators/le.js +++ b/app/javascript/libs/expressions/operators/le.js @@ -1,7 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { isBefore, parseISO } from "date-fns"; -import isEqualDate from "date-fns/isEqual"; +import { isBefore, isEqual, parseISO } from "date-fns"; import first from "lodash/first"; import { hasApiDateFormat } from "../../component-helpers"; @@ -23,7 +22,7 @@ export default expression => ({ const date1 = parseISO(dataValue); const date2 = parseISO(value); - return isBefore(date1, date2) || isEqualDate(date1, date2); + return isBefore(date1, date2) || isEqual(date1, date2); } return dataValue <= value; diff --git a/app/javascript/libs/expressions/parse-expression.js b/app/javascript/libs/expressions/parse-expression.js index dbb56252ed..267cb4c767 100644 --- a/app/javascript/libs/expressions/parse-expression.js +++ b/app/javascript/libs/expressions/parse-expression.js @@ -17,11 +17,13 @@ const parseExpression = expression => { } if (isMathematicalOperator(operator)) { - const mathExp = Array.isArray(value) - ? value.map(nested => (isObject(nested) ? parseExpression(nested) : nested)) - : parseExpression(value); + const data = value?.data ?? value; + const extra = value?.extra; + const mathExp = Array.isArray(data) + ? data.map(nested => (isObject(nested) ? parseExpression(nested) : nested)) + : parseExpression(data); - return buildOperator(operator, mathExp); + return buildOperator(operator, mathExp, extra); } return buildOperator(operator, value); diff --git a/app/javascript/libs/expressions/parse-expression.unit.test.js b/app/javascript/libs/expressions/parse-expression.unit.test.js index 0ea1c727f6..03f7a0086e 100644 --- a/app/javascript/libs/expressions/parse-expression.unit.test.js +++ b/app/javascript/libs/expressions/parse-expression.unit.test.js @@ -199,6 +199,7 @@ describe("parseExpression", () => { context("avgOperator", () => { const operator = parseExpression({ avg: ["a", "b", "c"] }); + const decimalOperator = parseExpression({ avg: { data: ["a", "b", "c"], extra: { decimalPlaces: 3 } } }); it("should return avg", () => { expect(operator.evaluate({ a: 3, b: 4, c: 2 })).to.deep.equals(3); @@ -215,5 +216,14 @@ describe("parseExpression", () => { it("returns 0 when no argument passed", () => { expect(operator.evaluate({})).to.deep.equals(0); }); + it("works with decimalPlaces specified", () => { + expect(decimalOperator.evaluate({ a: 3, b: 2 })).to.deep.equals(2.5); + }); + it("Correctly rounds to the right number of decimal places", () => { + expect(decimalOperator.evaluate({ a: 2, b: 2, c: 1 })).to.deep.equals(1.667); + }); + it("works with strings", () => { + expect(decimalOperator.evaluate({ a: "2", b: "3" })).to.deep.equals(2.5); + }); }); }); diff --git a/app/javascript/libs/expressions/utils/build-operator.js b/app/javascript/libs/expressions/utils/build-operator.js index 83b10d37f6..00a95a83c2 100644 --- a/app/javascript/libs/expressions/utils/build-operator.js +++ b/app/javascript/libs/expressions/utils/build-operator.js @@ -15,7 +15,7 @@ import { avgOperator } from "../operators"; -export default (operator, value) => { +export default (operator, value, extra) => { switch (operator) { case COMPARISON_OPERATORS.EQ: return eqOperator(value); @@ -38,7 +38,7 @@ export default (operator, value) => { case MATHEMATICAL_OPERATORS.SUM: return sumOperator(value); case MATHEMATICAL_OPERATORS.AVG: - return avgOperator(value); + return avgOperator(value, extra); default: throw Error(`Operator ${operator} is not valid.`); } diff --git a/app/javascript/libs/index.unit.test.js b/app/javascript/libs/index.unit.test.js index 2fe5aad735..54e376b03d 100644 --- a/app/javascript/libs/index.unit.test.js +++ b/app/javascript/libs/index.unit.test.js @@ -21,7 +21,6 @@ describe("libs/index", () => { "compare", "dataToJS", "displayNameHelper", - "endOfDay", "getObjectPath", "hasApiDateFormat", "invalidCharRegexp", diff --git a/app/javascript/libs/load-external-theme.js b/app/javascript/libs/load-external-theme.js index 019b316220..c32cb4b85b 100644 --- a/app/javascript/libs/load-external-theme.js +++ b/app/javascript/libs/load-external-theme.js @@ -4,7 +4,9 @@ const themePromise = process.env.NODE_ENV !== "test" ? await (async () => { if (window.useTheme) { - const { default: importedTheme } = await import(/* webpackIgnore: true */ `${window.location.origin}/theme`); + const { default: importedTheme } = await import( + /* webpackIgnore: true */ `${window.location.origin}/theme?__WB_REVISION__=${window.themeRevision}` + ); return importedTheme; } diff --git a/app/javascript/libs/queue/index.js b/app/javascript/libs/queue/index.js index a7d5364ffe..0d040e2801 100644 --- a/app/javascript/libs/queue/index.js +++ b/app/javascript/libs/queue/index.js @@ -5,14 +5,21 @@ import uniqBy from "lodash/uniqBy"; import { METHODS } from "../../config"; import DB from "../../db/db"; -import { ENQUEUE_SNACKBAR, SNACKBAR_VARIANTS } from "../../components/notifier"; +import { SNACKBAR_VARIANTS } from "../../components/notifier/constants"; import { SET_ATTACHMENT_STATUS } from "../../components/records/actions"; import { setQueueData } from "../../components/connectivity/action-creators"; import transformOfflineRequest from "../transform-offline-request"; import EventManager from "../messenger"; import { queueIndexedDB } from "../../db"; +import { ENQUEUE_SNACKBAR } from "../../components/notifier/actions"; -import { deleteFromQueue, messageQueueFailed, messageQueueSkip, messageQueueSuccess } from "./utils"; +import { + deleteFromQueue, + messageQueueFailed, + messageQueueSkip, + messageQueueSuccess, + sortQueueByDeleteFirst +} from "./utils"; import { QUEUE_PENDING, QUEUE_READY, @@ -141,7 +148,7 @@ class Queue { if (this.ready) { this.working = true; - const item = head(this.queue); + const item = head(sortQueueByDeleteFirst(this.queue)); if (item && !item?.processed && ((item.tries || 0) < QUEUE_ALLOWED_RETRIES || this.force)) { this.onAttachmentProcess(item); diff --git a/app/javascript/libs/queue/utils.js b/app/javascript/libs/queue/utils.js index 8b768996da..e6ff3f7eb8 100644 --- a/app/javascript/libs/queue/utils.js +++ b/app/javascript/libs/queue/utils.js @@ -2,6 +2,7 @@ import { queueIndexedDB } from "../../db"; import EventManager from "../messenger"; +import { METHODS } from "../../config"; import { QUEUE_FAILED, QUEUE_SKIP, QUEUE_SUCCESS } from "./constants"; @@ -28,3 +29,18 @@ export const messageQueueSuccess = action => { EventManager.publish(QUEUE_SUCCESS, action); } }; + +export const sortQueueByDeleteFirst = queue => + queue.sort((elem1, elem2) => { + if (elem1.api.method === elem2.api.method) { + return 0; + } + if (elem1.api.method === METHODS.DELETE) { + return -1; + } + if (elem2.api.method === METHODS.DELETE) { + return 1; + } + + return 0; + }); diff --git a/app/javascript/libs/service-worker-utils.js b/app/javascript/libs/service-worker-utils.js index bcb4ca8e00..1e4aa22a9c 100644 --- a/app/javascript/libs/service-worker-utils.js +++ b/app/javascript/libs/service-worker-utils.js @@ -1,9 +1,9 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { API_BASE_PATH, METHODS, NOTIFICATION_PERMISSIONS, POST_MESSAGES, ROUTES } from "../config/constants"; +import { API_BASE_PATH, METHODS, NOTIFICATION_PERMISSIONS, POST_MESSAGES, ROUTES } from "../config"; import { DEFAULT_FETCH_OPTIONS } from "../middleware/constants"; -import getToken from "../middleware/utils/get-token"; import DB, { DB_STORES } from "../db"; +import { getIDPToken } from "../components/login/components/idp-selection/auth-provider"; const SERVICE_WORKER_PATH = `${window.location.origin}/worker.js`; const MAX_ATTEMPTS = 3; @@ -34,7 +34,7 @@ function urlBase64ToUint8Array(base64String) { } async function sendSubscriptionStatusToServer(isSubscribing = true, data = {}) { - const token = await getToken(); + const token = await getIDPToken(); const subscriptionData = JSON.parse(JSON.stringify(data)); const path = [API_BASE_PATH, isSubscribing ? ROUTES.subscriptions : ROUTES.subscriptions_current].join(""); diff --git a/app/javascript/libs/to-identifier.unit.test.js b/app/javascript/libs/to-identifier.unit.test.js index 1a31e12621..5afd50b5b3 100644 --- a/app/javascript/libs/to-identifier.unit.test.js +++ b/app/javascript/libs/to-identifier.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub } from "../test"; +import { stub } from "../test-utils"; import toIdentifier from "./to-identifier"; import uuid from "./uuid"; diff --git a/app/javascript/libs/transform-offline-request.js b/app/javascript/libs/transform-offline-request.js index 0355612ebe..ca900ffa6c 100644 --- a/app/javascript/libs/transform-offline-request.js +++ b/app/javascript/libs/transform-offline-request.js @@ -8,7 +8,7 @@ import { compactBlank } from "../components/record-form/utils"; import { DATE_FIELD, NUMERIC_FIELD } from "../components/record-form/constants"; import DB from "../db/db"; import { METHODS } from "../config"; -import { valueParser } from "../components/form/utils"; +import valueParser from "../components/form/utils/value-parser"; const OFFLINE_OMITTED_FIELDS = Object.freeze(["record_in_scope", "type", "enabled", "workflow", "complete"]); diff --git a/app/javascript/libs/use-theme-helpers.js b/app/javascript/libs/use-theme-helpers.js index be7d4557f8..610ca51e04 100644 --- a/app/javascript/libs/use-theme-helpers.js +++ b/app/javascript/libs/use-theme-helpers.js @@ -1,8 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { useTheme } from "@material-ui/core/styles"; -import { useMediaQuery } from "@material-ui/core"; -import merge from "lodash/merge"; +import { createTheme, useTheme } from "@mui/material/styles"; +import { useMediaQuery } from "@mui/material"; import isFunction from "lodash/isFunction"; import { getAppDirection } from "../components/i18n/selectors"; @@ -15,7 +14,7 @@ export default ({ overrides = {} } = {}) => { const themeOverrides = isFunction(overrides) ? overrides(appTheme) : overrides; const mobileDisplay = useMediaQuery(appTheme.breakpoints.down("sm")); - const theme = merge(appTheme, themeOverrides); + const theme = createTheme(appTheme, themeOverrides); const direction = useMemoizedSelector(state => getAppDirection(state)); diff --git a/app/javascript/middleware/offline-middleware.unit.test.js b/app/javascript/middleware/offline-middleware.unit.test.js index ae586d9cc7..1a8bd2766e 100644 --- a/app/javascript/middleware/offline-middleware.unit.test.js +++ b/app/javascript/middleware/offline-middleware.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { createMiddleware, spy } from "../test"; +import { createMiddleware, spy } from "../test-utils"; import { METHODS } from "../config"; import offlineMiddleware from "./offline-middleware"; diff --git a/app/javascript/middleware/utils/default-error-callback.unit.test.js b/app/javascript/middleware/utils/default-error-callback.unit.test.js index c49a5376d2..446c48be71 100644 --- a/app/javascript/middleware/utils/default-error-callback.unit.test.js +++ b/app/javascript/middleware/utils/default-error-callback.unit.test.js @@ -3,7 +3,7 @@ import configureStore from "redux-mock-store"; import { RECORD_TYPES } from "../../config"; -import { spy } from "../../test"; +import { spy } from "../../test-utils"; import defaultErrorCallback from "./default-error-callback"; import * as handleRestCallback from "./handle-rest-callback"; diff --git a/app/javascript/middleware/utils/fetch-multiple-payload.js b/app/javascript/middleware/utils/fetch-multiple-payload.js index a1fd2edac2..e558d9840f 100644 --- a/app/javascript/middleware/utils/fetch-multiple-payload.js +++ b/app/javascript/middleware/utils/fetch-multiple-payload.js @@ -68,7 +68,7 @@ function fetchResources(fetchParams) { } function handleResponse(responses, store, action, options) { - const { type, finishedCallback, finishedCallbackSubforms } = action; + const { type, finishedCallback, finishedCallbackSubforms, finalCallback } = action; const results = responses.map(result => result.value); @@ -94,6 +94,10 @@ function handleResponse(responses, store, action, options) { }); } + if (finalCallback) { + store.dispatch(finalCallback); + } + if (finishedCallbackSubforms) { const subformsCallback = processSubforms(finishedCallbackSubforms, responses); diff --git a/app/javascript/middleware/utils/fetch-params-builder.js b/app/javascript/middleware/utils/fetch-params-builder.js index d9ce8bf27c..a0a38fc886 100644 --- a/app/javascript/middleware/utils/fetch-params-builder.js +++ b/app/javascript/middleware/utils/fetch-params-builder.js @@ -1,9 +1,10 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +import { getIDPToken } from "../../components/login/components/idp-selection/auth-provider"; import { DEFAULT_FETCH_OPTIONS } from "../constants"; import buildPath from "./build-path"; -import getToken from "./get-token"; +import getCSRFToken from "./get-csrf-token"; const fetchParamsBuilder = async (api, options, controller) => { const { path, body, params, method, external } = api; @@ -15,9 +16,11 @@ const fetchParamsBuilder = async (api, options, controller) => { body: JSON.stringify(body) }; - const token = await getToken(); + const token = await getIDPToken(); - const headers = {}; + const headers = { + "X-CSRF-Token": getCSRFToken() + }; if (token) { headers.Authorization = `Bearer ${token}`; diff --git a/app/javascript/middleware/utils/fetch-pdf-logos.js b/app/javascript/middleware/utils/fetch-pdf-logos.js index 46878df1b9..0f243a5f09 100644 --- a/app/javascript/middleware/utils/fetch-pdf-logos.js +++ b/app/javascript/middleware/utils/fetch-pdf-logos.js @@ -3,7 +3,7 @@ import { getAgencyLogosPdf } from "../../components/application/selectors"; import { METHODS, syncIndexedDB } from "../../db"; import Logos from "../../db/collections/logos"; -import { reduceMapToObject } from "../../libs"; +import { reduceMapToObject } from "../../libs/component-helpers"; import fetchPayload from "./fetch-payload"; import fetchStatus from "./fetch-status"; @@ -40,7 +40,11 @@ const fetchPdfLogos = (action, store, options, next) => { fetchStatus({ store, type }, "FAILURE", false); } - return fetchPayload(action, store, options); + if (action?.api?.path) { + return fetchPayload(action, store, options); + } + + return next(action); }; return fetch(); diff --git a/app/javascript/middleware/utils/fetch-single-payload.js b/app/javascript/middleware/utils/fetch-single-payload.js index 5b7ca502cf..8f86f1720e 100644 --- a/app/javascript/middleware/utils/fetch-single-payload.js +++ b/app/javascript/middleware/utils/fetch-single-payload.js @@ -7,9 +7,10 @@ import { DEFAULT_FETCH_OPTIONS } from "../constants"; import { disableNavigation } from "../../components/application/action-creators"; import { applyingConfigMessage } from "../../components/pages/admin/configurations-form/action-creators"; import userActions from "../../components/user/actions"; +import { SET_ATTACHMENT_STATUS } from "../../components/records/actions"; +import { getIDPToken } from "../../components/login/components/idp-selection/auth-provider"; import fetchStatus from "./fetch-status"; -import getToken from "./get-token"; import handleConfiguration from "./handle-configuration"; import partitionObject from "./partition-object"; import buildAttachmentData from "./build-attachment-data"; @@ -21,6 +22,7 @@ import processAttachments from "./process-attachments"; import { deleteFromQueue, messageQueueFailed, messageQueueSkip, messageQueueSuccess } from "./queue"; import handleSuccess from "./handle-success"; import FetchError from "./fetch-error"; +import getCSRFToken from "./get-csrf-token"; const fetchSinglePayload = async (action, store, options) => { const controller = new AbortController(); @@ -65,9 +67,10 @@ const fetchSinglePayload = async (action, store, options) => { }) }; - const token = await getToken(); - - const headers = {}; + const token = await getIDPToken(); + const headers = { + "X-CSRF-Token": getCSRFToken() + }; if (token) { headers.Authorization = `Bearer ${token}`; @@ -102,6 +105,10 @@ const fetchSinglePayload = async (action, store, options) => { throw new Error(window.I18n.t("error_message.error_401")); } + if (action.type === userActions.LOGIN) { + throw new Error(json.error); + } + startSignout(store); } @@ -111,12 +118,16 @@ const fetchSinglePayload = async (action, store, options) => { } else if (failureCallback) { messageQueueFailed(fromQueue); handleRestCallback(store, failureCallback, response, json, fromQueue); + } else if (action.type.includes("SAVE_ATTACHMENT") && status === 422) { + throw new FetchError(response, json); } else { messageQueueFailed(fromQueue); throw new FetchError(response, json); } - throw new Error(window.I18n.t("error_message.error_something_went_wrong")); + if (!action.type.includes("SAVE_ATTACHMENT") && status !== 422) { + throw new Error(window.I18n.t("error_message.error_something_went_wrong")); + } } await handleSuccess(store, { type, @@ -151,7 +162,17 @@ const fetchSinglePayload = async (action, store, options) => { } catch (error) { const errorDataObject = { json: error?.json, recordType, fromQueue, id, error }; - messageQueueFailed(fromQueue); + if (fromAttachment && error?.response?.status === 422) { + deleteFromQueue(fromQueue); + messageQueueSkip(); + store.dispatch({ + type: `${fromAttachment.record_type}/${SET_ATTACHMENT_STATUS}`, + payload: { processing: false, error: false, pending: false, fieldName: fromAttachment.field_name } + }); + errorDataObject.fromQueue = false; + } else { + messageQueueFailed(fromQueue); + } fetchStatus({ store, type }, "FAILURE", false); diff --git a/app/javascript/middleware/utils/generate-record-properties.unit.test.js b/app/javascript/middleware/utils/generate-record-properties.unit.test.js index ab8e8753d8..4fae1580bb 100644 --- a/app/javascript/middleware/utils/generate-record-properties.unit.test.js +++ b/app/javascript/middleware/utils/generate-record-properties.unit.test.js @@ -3,7 +3,7 @@ import configureStore from "redux-mock-store"; import { fromJS } from "immutable"; -import { stub, useFakeTimers } from "../../test"; +import { stub, useFakeTimers } from "../../test-utils"; import uuid from "../../libs/uuid"; import generateRecordProperties from "./generate-record-properties"; diff --git a/app/javascript/middleware/utils/get-csrf-token.js b/app/javascript/middleware/utils/get-csrf-token.js new file mode 100644 index 0000000000..d44f3ba54e --- /dev/null +++ b/app/javascript/middleware/utils/get-csrf-token.js @@ -0,0 +1,12 @@ +function getCSRFToken() { + const cookies = document.cookie.split("; "); + const [, value] = cookies.find(cookie => cookie.startsWith("CSRF-TOKEN="))?.split("=") || []; + + if (!value) { + return null; + } + + return decodeURIComponent(value); +} + +export default getCSRFToken; diff --git a/app/javascript/middleware/utils/get-token.js b/app/javascript/middleware/utils/get-token.js deleted file mode 100644 index 6d58773514..0000000000 --- a/app/javascript/middleware/utils/get-token.js +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -const getToken = () => { - return localStorage.getItem("cachedIdToken"); -}; - -export default getToken; diff --git a/app/javascript/middleware/utils/handle-attachment-success.js b/app/javascript/middleware/utils/handle-attachment-success.js index 9982783f8f..851edbc7d9 100644 --- a/app/javascript/middleware/utils/handle-attachment-success.js +++ b/app/javascript/middleware/utils/handle-attachment-success.js @@ -5,27 +5,17 @@ import merge from "deepmerge"; import { syncIndexedDB, TRANSACTION_MODE } from "../../db"; import subformAwareMerge from "../../db/utils/subform-aware-merge"; +import mergeAttachment from "./merge-attachment"; + const handleAttachmentSuccess = async ({ json, db, fromAttachment }) => { - const { id, field_name: fieldName } = fromAttachment; + const { field_name: fieldName } = fromAttachment; const recordDB = await syncIndexedDB({ ...db, mode: TRANSACTION_MODE.READ_WRITE }, {}, "", async (tx, store) => { const recordData = await store.get(db.id); const data = { ...recordData, [fieldName]: [...(recordData[fieldName] || [])] }; - data[fieldName] = data[fieldName].map(attachment => ({ - ...attachment, - marked_destroy: id - ? attachment.id === id - : attachment.field_name === json.data.field_name && - attachment.file_name === json.data.file_name && - !attachment.id && - json.data.id - })); - - if (json.data && json.data.id && !fromAttachment.id) { - data[fieldName].push(json.data); - } + data[fieldName] = mergeAttachment(data[fieldName], json, fromAttachment); data.type = db.recordType; diff --git a/app/javascript/middleware/utils/handle-configuration.unit.test.js b/app/javascript/middleware/utils/handle-configuration.unit.test.js index fdbaa0f78e..88e4617958 100644 --- a/app/javascript/middleware/utils/handle-configuration.unit.test.js +++ b/app/javascript/middleware/utils/handle-configuration.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub, createMockStore, spy } from "../../test"; +import { stub, createMockStore, spy } from "../../test-utils"; import { generate } from "../../components/notifier"; import handleConfiguration from "./handle-configuration"; diff --git a/app/javascript/middleware/utils/handle-offline-attachments.js b/app/javascript/middleware/utils/handle-offline-attachments.js index d0ae533584..7fb9dbeb2a 100644 --- a/app/javascript/middleware/utils/handle-offline-attachments.js +++ b/app/javascript/middleware/utils/handle-offline-attachments.js @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import isEqual from "date-fns/isEqual"; import merge from "deepmerge"; +import isEqual from "lodash/isEqual"; import { syncIndexedDB } from "../../db"; import { getAttachmentFields } from "../../components/record-form"; @@ -36,10 +36,12 @@ export const skipSyncedAttachments = async (store, action) => { if (bodyAttachments.length) { payload.api.body.data[field] = bodyAttachments.filter( elem => - !dbAttachments.some(dbElem => - dbElem.id - ? dbElem.id === elem.id - : dbElem.attachment === elem.attachment && isEqual(elem.date, dbElem.date) + !dbAttachments.some( + dbElem => + (dbElem.id ? dbElem.id === elem.id : dbElem.attachment === elem.attachment) && + isEqual(elem.date, dbElem.date) && + isEqual(elem.description, dbElem.description) && + isEqual(elem.comments, dbElem.comments) ) ); } diff --git a/app/javascript/middleware/utils/handle-offline-attachments.unit.test.js b/app/javascript/middleware/utils/handle-offline-attachments.unit.test.js index 4a4a6cf977..7bf1a10de2 100644 --- a/app/javascript/middleware/utils/handle-offline-attachments.unit.test.js +++ b/app/javascript/middleware/utils/handle-offline-attachments.unit.test.js @@ -2,7 +2,7 @@ import { fromJS } from "immutable"; -import { stub } from "../../test"; +import { stub } from "../../test-utils"; import * as syncIndexedDB from "../../db/sync"; import { skipSyncedAttachments, buildDBPayload } from "./handle-offline-attachments"; diff --git a/app/javascript/middleware/utils/handle-rest-callback.js b/app/javascript/middleware/utils/handle-rest-callback.js index 6791e8d42c..456ebd48b1 100644 --- a/app/javascript/middleware/utils/handle-rest-callback.js +++ b/app/javascript/middleware/utils/handle-rest-callback.js @@ -66,7 +66,7 @@ const handleRestCallback = (store, callback, response, json, fromQueue = false) payload: { response, json } }; - store.dispatch(isApiCallback ? { type: callback.action, api: callback.api } : successPayload); + store.dispatch(isApiCallback ? { type: callback.action || callback.type, api: callback.api } : successPayload); if (isObjectCallback && callback.redirect && !fromQueue) { const { preventSyncAfterRedirect } = callback; diff --git a/app/javascript/middleware/utils/handle-rest-callback.unit.test.js b/app/javascript/middleware/utils/handle-rest-callback.unit.test.js index f608fb7940..5f8027ec3d 100644 --- a/app/javascript/middleware/utils/handle-rest-callback.unit.test.js +++ b/app/javascript/middleware/utils/handle-rest-callback.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { spy, createMockStore } from "../../test"; +import { spy, createMockStore } from "../../test-utils"; import handleRestCallback from "./handle-rest-callback"; diff --git a/app/javascript/middleware/utils/merge-attachment.js b/app/javascript/middleware/utils/merge-attachment.js new file mode 100644 index 0000000000..d353e29d82 --- /dev/null +++ b/app/javascript/middleware/utils/merge-attachment.js @@ -0,0 +1,38 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +const isNewAttachment = (fromAttachment, json) => json?.data?.id && !fromAttachment.id; + +const isAttachmentUpdate = (attachment, json) => json.data.id === attachment.id; + +const isOfflineAttachmentUpdate = (attachment, json) => + attachment.field_name === json.data.field_name && + attachment.file_name === json.data.file_name && + attachment.description === json.data.description && + attachment.date === json.data.date && + attachment.comments === json.data.comments && + !attachment.id && + json.data.id; + +export default (attachments, json, fromAttachment) => { + const { id, _destroy } = fromAttachment; + + const merged = attachments.map(elem => { + if (isOfflineAttachmentUpdate(elem, json)) { + return json.data; + } + + if (isAttachmentUpdate(elem, json)) { + return { ...elem, ...json.data, marked_destroy: _destroy && json.data.id === id }; + } + + return elem; + }); + + const isAlreadyMerged = merged.some(elem => elem.id === json.data.id); + + if (isNewAttachment(fromAttachment, json) && !isAlreadyMerged) { + merged.push(json.data); + } + + return merged; +}; diff --git a/app/javascript/middleware/utils/merge-attachment.unit.test.js b/app/javascript/middleware/utils/merge-attachment.unit.test.js new file mode 100644 index 0000000000..eaa52ce040 --- /dev/null +++ b/app/javascript/middleware/utils/merge-attachment.unit.test.js @@ -0,0 +1,36 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import mergeAttachment from "./merge-attachment"; + +describe("middleware/utils/merge-attachment.js", () => { + it("merges an attachment when is new", () => { + const attachments = [{ id: 1, attachment_url: "/path/to/attachment1", file_name: "attachment1" }]; + const json = { data: { id: 2, attachment_url: "/path/to/attachment2", file_name: "attachment2" } }; + const fromAttachment = { _destroy: false }; + + expect(mergeAttachment(attachments, json, fromAttachment)).to.deep.equal([...attachments, json.data]); + }); + + it("merges an attachment when is new and was created offline", () => { + const attachments = [ + { id: 1, attachment_url: "/path/to/attachment1", file_name: "attachment1" }, + { attachment: "base64_attachment", file_name: "attachment2" } + ]; + const json = { data: { id: 2, attachment_url: "/path/to/attachment2", file_name: "attachment2" } }; + const fromAttachment = { _destroy: false }; + + expect(mergeAttachment(attachments, json, fromAttachment)).to.deep.equal([attachments[0], json.data]); + }); + + it("merges an existing attachment", () => { + const attachments = [ + { id: 1, attachment_url: "/path/to/attachment1", file_name: "attachment1", description: "Description 1" } + ]; + const json = { + data: { id: 1, attachment_url: "/path/to/attachment1", file_name: "attachment1", description: "Attachment 1" } + }; + const fromAttachment = { id: 1, _destroy: false }; + + expect(mergeAttachment(attachments, json, fromAttachment)).to.deep.equal([{ ...json.data, marked_destroy: false }]); + }); +}); diff --git a/app/javascript/middleware/utils/offline-dispatch-success.unit.test.js b/app/javascript/middleware/utils/offline-dispatch-success.unit.test.js index 39311e35fb..83ec891272 100644 --- a/app/javascript/middleware/utils/offline-dispatch-success.unit.test.js +++ b/app/javascript/middleware/utils/offline-dispatch-success.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { spy, createMockStore } from "../../test"; +import { spy, createMockStore } from "../../test-utils"; import offlineDispatchSuccess from "./offline-dispatch-success"; import * as handleRestCallback from "./handle-rest-callback"; diff --git a/app/javascript/middleware/utils/process-attachments.js b/app/javascript/middleware/utils/process-attachments.js index 9869540dc9..4b9438e746 100644 --- a/app/javascript/middleware/utils/process-attachments.js +++ b/app/javascript/middleware/utils/process-attachments.js @@ -4,14 +4,20 @@ import { DB_COLLECTIONS_NAMES, queueIndexedDB } from "../../db"; import { METHODS } from "../../config"; import uuid from "../../libs/uuid"; +const getAttachmentMethod = attachment => { + if (attachment?._destroy) { + return METHODS.DELETE; + } + + return attachment?.id ? METHODS.PATCH : METHODS.POST; +}; + export default async ({ attachments, id, recordType }) => { const actions = Object.keys(attachments).reduce((prev, current) => { attachments[current].forEach(attachment => { - const method = attachment?._destroy ? METHODS.DELETE : METHODS.POST; - const isDelete = method === "DELETE"; - - const path = `${recordType}/${id}/attachments${isDelete ? `/${attachment?._destroy}` : ""}`; - + const method = getAttachmentMethod(attachment); + const isDelete = method === METHODS.DELETE; + const path = `${recordType}/${id}/attachments${METHODS.POST === method ? "" : `/${attachment?.id}`}`; const action = isDelete ? "DELETE_ATTACHMENT" : "SAVE_ATTACHMENT"; // eslint-disable-next-line camelcase @@ -21,15 +27,14 @@ export default async ({ attachments, id, recordType }) => { api: { path, method, - ...(!isDelete && { - body: { data: { ...attachment, field_name: current } } - }), + ...(!isDelete && { body: { data: { ...attachment } } }), db: { id, collection: DB_COLLECTIONS_NAMES.RECORDS, recordType } }, fromQueue: uuid.v4(), tries: 0, fromAttachment: { - ...(isDelete && { id: attachment?._destroy }), + ...(attachment?.id ? { id: attachment.id } : {}), + ...(attachment?._destroy ? { _destroy: attachment._destroy } : {}), field_name: current, record_type: recordType, record: { id } diff --git a/app/javascript/middleware/utils/process-attachments.unit.test.js b/app/javascript/middleware/utils/process-attachments.unit.test.js index fe0dbdac9a..8382a47ff9 100644 --- a/app/javascript/middleware/utils/process-attachments.unit.test.js +++ b/app/javascript/middleware/utils/process-attachments.unit.test.js @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { queueIndexedDB } from "../../db"; -import { stub } from "../../test"; +import { stub } from "../../test-utils"; import { METHODS, RECORD_PATH } from "../../config"; import uuid from "../../libs/uuid"; @@ -21,7 +21,7 @@ describe("middleware/utils/process-attachments.js", () => { }); it("should generate the attachment actions", () => { - const attachments = { field_1: [{ attachment: "attachment-data" }], field_2: [{ _destroy: 1 }] }; + const attachments = { field_1: [{ attachment: "attachment-data" }], field_2: [{ id: 1, _destroy: true }] }; processAttachments({ attachments, id: 10, recordType: RECORD_PATH.cases }); @@ -31,7 +31,7 @@ describe("middleware/utils/process-attachments.js", () => { api: { path: `${RECORD_PATH.cases}/10/attachments`, method: METHODS.POST, - body: { data: { attachment: "attachment-data", field_name: "field_1" } }, + body: { data: { attachment: "attachment-data" } }, db: { collection: "records", id: 10, recordType: "cases" } }, fromQueue: "1234", @@ -47,7 +47,13 @@ describe("middleware/utils/process-attachments.js", () => { }, fromQueue: "1234", tries: 0, - fromAttachment: { id: 1, field_name: "field_2", record_type: RECORD_PATH.cases, record: { id: 10 } } + fromAttachment: { + id: 1, + field_name: "field_2", + record_type: RECORD_PATH.cases, + record: { id: 10 }, + _destroy: true + } } ]); }); diff --git a/app/javascript/middleware/utils/process-subforms.unit.test.js b/app/javascript/middleware/utils/process-subforms.unit.test.js index 8125bc7537..02cb40f7c5 100644 --- a/app/javascript/middleware/utils/process-subforms.unit.test.js +++ b/app/javascript/middleware/utils/process-subforms.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub } from "../../test"; +import { stub } from "../../test-utils"; import { METHODS } from "../../config"; import { ENQUEUE_SNACKBAR, generate } from "../../components/notifier"; import { SUBFORM_SECTION } from "../../components/form"; diff --git a/app/javascript/middleware/utils/queue-data.unit.test.js b/app/javascript/middleware/utils/queue-data.unit.test.js index 70b11c9e75..78f1d717ce 100644 --- a/app/javascript/middleware/utils/queue-data.unit.test.js +++ b/app/javascript/middleware/utils/queue-data.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub, createMockStore } from "../../test"; +import { stub, createMockStore } from "../../test-utils"; import * as syncIndexedDB from "../../db/sync"; import queueIndexedDB from "../../db/queue"; import { METHODS } from "../../config"; diff --git a/app/javascript/middleware/utils/queue-fetch.unit.test.js b/app/javascript/middleware/utils/queue-fetch.unit.test.js index ae17ca8226..05f0bb811a 100644 --- a/app/javascript/middleware/utils/queue-fetch.unit.test.js +++ b/app/javascript/middleware/utils/queue-fetch.unit.test.js @@ -1,7 +1,7 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import uuid from "../../libs/uuid"; -import { stub } from "../../test"; +import { stub } from "../../test-utils"; import queueIndexedDB from "../../db/queue"; import queueFetch from "./queue-fetch"; diff --git a/app/javascript/middleware/utils/redirect-to.unit.test.js b/app/javascript/middleware/utils/redirect-to.unit.test.js index d82a25eda9..aa2266d15b 100644 --- a/app/javascript/middleware/utils/redirect-to.unit.test.js +++ b/app/javascript/middleware/utils/redirect-to.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { spy, createMockStore } from "../../test"; +import { spy, createMockStore } from "../../test-utils"; import redirectTo from "./redirect-to"; diff --git a/app/javascript/middleware/utils/retrieve-data.unit.test.js b/app/javascript/middleware/utils/retrieve-data.unit.test.js index 34fa5704fc..aa858ffcbb 100644 --- a/app/javascript/middleware/utils/retrieve-data.unit.test.js +++ b/app/javascript/middleware/utils/retrieve-data.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub, createMockStore } from "../../test"; +import { stub, createMockStore } from "../../test-utils"; import * as syncIndexedDB from "../../db/sync"; import retrieveData from "./retrieve-data"; diff --git a/app/javascript/middleware/utils/set-case-incident-data.js b/app/javascript/middleware/utils/set-case-incident-data.js index 90abec1a33..3ecf1a0fcd 100644 --- a/app/javascript/middleware/utils/set-case-incident-data.js +++ b/app/javascript/middleware/utils/set-case-incident-data.js @@ -3,7 +3,7 @@ import { get } from "../../components/form/utils"; import { getFieldMap, offlineIncidentFromCase } from "../../components/records"; import { ID_FIELD, INCIDENT_CASE_ID_DISPLAY_FIELD, MODULE_TYPE_FIELD } from "../../config"; -import { buildFieldMap } from "../../libs"; +import buildFieldMap from "../../libs/build-field-map"; export default (store, data = {}) => { const moduleID = get(data, MODULE_TYPE_FIELD); diff --git a/app/javascript/middleware/utils/start-signout.unit.test.js b/app/javascript/middleware/utils/start-signout.unit.test.js index 3936ff78a6..9374589173 100644 --- a/app/javascript/middleware/utils/start-signout.unit.test.js +++ b/app/javascript/middleware/utils/start-signout.unit.test.js @@ -3,7 +3,7 @@ import configureStore from "redux-mock-store"; import { fromJS } from "immutable"; -import { spy, stub } from "../../test"; +import { spy, stub } from "../../test-utils"; import * as methods from "../../components/login/components/idp-selection/auth-provider"; import * as actions from "../../components/user/action-creators"; diff --git a/app/javascript/middleware/utils/with-generated-properties.unit.test.js b/app/javascript/middleware/utils/with-generated-properties.unit.test.js index ec6d491383..6da450910d 100644 --- a/app/javascript/middleware/utils/with-generated-properties.unit.test.js +++ b/app/javascript/middleware/utils/with-generated-properties.unit.test.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { stub } from "../../test"; +import { stub } from "../../test-utils"; import withGeneratedProperties from "./with-generated-properties"; import * as generateRecordProperties from "./generate-record-properties"; diff --git a/app/javascript/packs/application.jsx b/app/javascript/packs/application.jsx index 44b1d73bd4..23791930fb 100644 --- a/app/javascript/packs/application.jsx +++ b/app/javascript/packs/application.jsx @@ -4,35 +4,17 @@ import "../wdyr"; import "core-js/stable"; import "regenerator-runtime/runtime"; -import { render } from "react-dom"; -import { StrictMode } from "react"; -import isEmpty from "lodash/isEmpty"; +import { createRoot } from "react-dom/client"; import App from "../app"; import serviceWorker from "../service-worker"; import ErrorLogger from "../libs/error-logger"; -import Translations from "../db/collections/translations"; serviceWorker(); ErrorLogger.startErrorListeners(); -render( - - - , - document.getElementById("root"), - () => { - const loadTranslations = async () => { - if (isEmpty(window.I18n.translations)) { - const translations = await Translations.find(); +const container = document.getElementById("root"); +const root = createRoot(container); - window.I18n.translations = translations; - } else { - Translations.save(window.I18n.translations); - } - }; - - loadTranslations(); - } -); +root.render(); diff --git a/app/javascript/config/routes.js b/app/javascript/routes.js similarity index 92% rename from app/javascript/config/routes.js rename to app/javascript/routes.js index d0490c7a23..6d0c94bfea 100644 --- a/app/javascript/config/routes.js +++ b/app/javascript/routes.js @@ -27,21 +27,21 @@ import { ConfigurationsForm, CodeOfConduct as AdminCodeOfConduct, Support -} from "../components/pages"; -import KeyPerformanceIndicators from "../components/key-performance-indicators"; -import Report from "../components/report"; -import Reports from "../components/reports-list"; -import ReportsForm from "../components/reports-form"; -import RecordForm from "../components/record-form/container"; -import RecordList from "../components/record-list"; -import InsightsList from "../components/insights-list"; -import Insights from "../components/insights"; -import InsightsSubReport from "../components/insights-sub-report"; -import Account from "../components/pages/account"; -import PasswordReset from "../components/password-reset"; -import CodeOfConduct from "../components/code-of-conduct"; -import ActivityLog from "../components/activity-log"; -import { AppLayout, LoginLayout, EmptyLayout } from "../components/layouts"; +} from "./components/pages"; +import KeyPerformanceIndicators from "./components/key-performance-indicators"; +import Report from "./components/report"; +import Reports from "./components/reports-list"; +import ReportsForm from "./components/reports-form"; +import RecordForm from "./components/record-form/container"; +import RecordList from "./components/record-list"; +import InsightsList from "./components/insights-list"; +import Insights from "./components/insights"; +import InsightsSubReport from "./components/insights-sub-report"; +import Account from "./components/pages/account"; +import PasswordReset from "./components/password-reset"; +import CodeOfConduct from "./components/code-of-conduct"; +import ActivityLog from "./components/activity-log"; +import { AppLayout, LoginLayout, EmptyLayout } from "./components/layouts"; import { CREATE_RECORDS, CREATE_REPORTS, @@ -57,12 +57,11 @@ import { VIEW_KPIS, ACTIVITY_LOGS, READ_MANAGED_REPORTS -} from "../components/permissions"; -import Login, { IdpLogin } from "../components/login"; -import Logout from "../components/logout"; -import PasswordResetRequest from "../components/login/components/password-reset-form"; - -import { ROUTES, MODES, RECORD_PATH } from "./constants"; +} from "./components/permissions"; +import Login, { IdpLogin } from "./components/login"; +import Logout from "./components/logout"; +import PasswordResetRequest from "./components/login/components/password-reset-form"; +import { ROUTES, MODES, RECORD_PATH } from "./config"; const recordPaths = [ RECORD_PATH.cases, diff --git a/app/javascript/service-worker.js b/app/javascript/service-worker.js index b6f0caba7e..3daf90ef25 100644 --- a/app/javascript/service-worker.js +++ b/app/javascript/service-worker.js @@ -1,6 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { POST_MESSAGES } from "./config/constants"; +import { POST_MESSAGES } from "./config"; import { SERVICE_WORKER_PATH, getSubscriptionFromDb, diff --git a/app/javascript/test-utils/create-mock-store.js b/app/javascript/test-utils/create-mock-store.js index 02f6df1c33..20aa57b54d 100644 --- a/app/javascript/test-utils/create-mock-store.js +++ b/app/javascript/test-utils/create-mock-store.js @@ -1,10 +1,15 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. import { fromJS } from "immutable"; -import configureStore from "redux-mock-store"; -import thunk from "redux-thunk"; import { createMemoryHistory } from "history"; -import { routerMiddleware } from "connected-react-router/immutable"; +import { connectRouter, routerMiddleware } from "connected-react-router/immutable"; +import { applyMiddleware, compose, createStore } from "redux"; +import { combineReducers } from "redux-immutable"; +import thunk from "redux-thunk"; + +import rootReducer from "../reducer"; +import restMiddleware from "../middleware/rest-middleware"; +import { API_BASE_PATH } from "../config"; const DEFAULT_STATE = fromJS({ connectivity: { @@ -13,12 +18,43 @@ const DEFAULT_STATE = fromJS({ } }); -const createMockStore = (defaultState = fromJS({}), initialState) => { +let actions = []; + +const loggerMiddleware = () => next => action => { + actions.push(action); + + return next(action); +}; + +function createMockStore(defaultState = fromJS({}), initialState, includeRestMiddleware = false) { + actions = []; const history = createMemoryHistory(); - const mockStore = configureStore([routerMiddleware(history), thunk]); - const store = mockStore(defaultState.merge(fromJS(initialState))); + const middleware = [loggerMiddleware, routerMiddleware(history), thunk]; + + if (includeRestMiddleware) { + middleware.push( + restMiddleware({ + baseUrl: API_BASE_PATH + }) + ); + } + + const store = createStore( + combineReducers({ + router: connectRouter(history), + ...rootReducer + }), + fromJS(defaultState).merge(fromJS(initialState)), + compose(applyMiddleware(...middleware)) + ); + + store.getActions = () => actions; + + store.clearActions = () => { + actions = []; + }; return { store, history }; -}; +} export { DEFAULT_STATE, createMockStore }; diff --git a/app/javascript/test-utils/fetch-helpers.js b/app/javascript/test-utils/fetch-helpers.js new file mode 100644 index 0000000000..02cece4d15 --- /dev/null +++ b/app/javascript/test-utils/fetch-helpers.js @@ -0,0 +1,19 @@ +function mockFetchSuccess({ url = "/", status = 200, json }) { + global.fetch.mockResolvedValueOnce({ + url, + ok: status < 400, + status, + json: jest.fn().mockResolvedValueOnce(json) + }); +} + +function mockFetchError({ url = "/", status = 200, json }) { + global.fetch.mockRejectedValueOnce({ + url, + ok: false, + status, + json: jest.fn().mockResolvedValueOnce(json) + }); +} + +export { mockFetchSuccess, mockFetchError }; diff --git a/app/javascript/test-utils/fixtures.js b/app/javascript/test-utils/fixtures.js new file mode 100644 index 0000000000..b32e842d82 --- /dev/null +++ b/app/javascript/test-utils/fixtures.js @@ -0,0 +1,65 @@ +import { ListHeaderRecord } from "../components/user/records"; +import { RECORD_PATH } from "../config"; + +const lookups = () => ({ + data: [ + { + unique_id: "lookup-1", + name: { en: "Lookup 1" }, + values: [ + { id: "a", display_text: [{ en: "Lookup 1 a" }] }, + { id: "b", display_text: [{ en: "Lookup 1 b" }] } + ] + }, + { + unique_id: "lookup-2", + name: { en: "Lookup 2" }, + values: [ + { id: "a", display_text: [{ en: "Lookup 2 a" }] }, + { id: "b", display_text: [{ en: "Lookup 2 b" }] } + ] + } + ], + metadata: { + total: 2, + per: 1, + page: 1 + } +}); + +const listHeaders = recordType => { + const commonHeaders = [ + ListHeaderRecord({ + name: "description", + field_name: "description", + id_search: false + }) + ]; + + switch (recordType) { + case RECORD_PATH.user_groups: + return [ + ListHeaderRecord({ + name: "user_group.name", + field_name: "name", + id_search: false + }), + ...commonHeaders + ]; + + case RECORD_PATH.agencies: + return [ + ListHeaderRecord({ + name: "agency.name", + field_name: "name", + id_search: false + }), + ...commonHeaders + ]; + + default: + return []; + } +}; + +export { lookups, listHeaders }; diff --git a/app/javascript/test/globals.js b/app/javascript/test-utils/globals-mocha.js similarity index 93% rename from app/javascript/test/globals.js rename to app/javascript/test-utils/globals-mocha.js index b2a27618a4..0b4ba6fe68 100644 --- a/app/javascript/test/globals.js +++ b/app/javascript/test-utils/globals-mocha.js @@ -1,4 +1,5 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +import "./globals"; import chai from "chai"; import sinonChai from "sinon-chai"; @@ -45,7 +46,7 @@ let storage = {}; global.localStorage = { setItem: (key, value) => { - storage[key] = value || ""; + storage[key] = value || null; }, getItem: key => { return key in storage ? storage[key] : null; @@ -54,8 +55,8 @@ global.localStorage = { delete storage[key]; }, clear: () => { - storage = {} + storage = {}; } }; -global.sessionStorage = global.localStorage +global.sessionStorage = global.localStorage; diff --git a/app/javascript/test-utils/globals.js b/app/javascript/test-utils/globals.js index 5dec349c6b..02fae7b932 100644 --- a/app/javascript/test-utils/globals.js +++ b/app/javascript/test-utils/globals.js @@ -9,7 +9,13 @@ import { DATE_FORMATS } from "./constants"; global.html2pdf = {}; -document.head.insertBefore(document.createComment("jss-insertion-point"), document.head.firstChild); +if (typeof jest !== "undefined") { + global.window.fetch = jest.fn(); +} + +global.innerWidth = 2000; + +document.head.insertBefore(document.createComment("emotion-insertion-point"), document.head.firstChild); global.window.I18n = { defaultLocale: "en", diff --git a/app/javascript/test-utils/i18n.js b/app/javascript/test-utils/i18n.js new file mode 100644 index 0000000000..fa0e2103a9 --- /dev/null +++ b/app/javascript/test-utils/i18n.js @@ -0,0 +1,7 @@ +// eslint-disable-next-line import/prefer-default-export +export const abbrMonthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + +export function freezeTimeZone(offset = 0) { + // eslint-disable-next-line no-extend-native + Date.prototype.getTimezoneOffset = jest.fn(() => offset); +} diff --git a/app/javascript/test-utils/index.js b/app/javascript/test-utils/index.js index c6c14b8129..23185b0382 100644 --- a/app/javascript/test-utils/index.js +++ b/app/javascript/test-utils/index.js @@ -2,7 +2,7 @@ /* eslint-disable react/no-multi-comp */ -export { render, fireEvent, screen } from "@testing-library/react"; +export { render, fireEvent, screen, waitFor, within, cleanup, act } from "@testing-library/react"; export { default as userEvent } from "@testing-library/user-event"; export { spy, useFakeTimers, stub, mock, fake, replace } from "sinon"; export { createMockStore, DEFAULT_STATE } from "./create-mock-store"; @@ -14,3 +14,9 @@ export { default as mountedThemeComponent } from "./mounted-theme-component"; export { default as simpleMountedComponent } from "./simple-mounted-component"; export { mountedFieldComponent, mountedFormComponent } from "./mounted-form-component"; export { default as setupHook } from "./setup-hook"; +export { abbrMonthNames, freezeTimeZone } from "./i18n"; +export { expectNever } from "./utils"; +export { default as setScreenSizeToMobile } from "./set-screen-size-to-mobile"; +export { default as setSelectValue } from "./set-select-value"; +export { mockFetchSuccess, mockFetchError } from "./fetch-helpers"; +export { listHeaders, lookups } from "./fixtures"; diff --git a/app/javascript/test/jsdom.setup.js b/app/javascript/test-utils/jsdom.setup.js similarity index 100% rename from app/javascript/test/jsdom.setup.js rename to app/javascript/test-utils/jsdom.setup.js diff --git a/app/javascript/test-utils/mounted-component.js b/app/javascript/test-utils/mounted-component.js index 8f8dcd1060..d35666001d 100644 --- a/app/javascript/test-utils/mounted-component.js +++ b/app/javascript/test-utils/mounted-component.js @@ -1,8 +1,6 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. /* eslint-disable react/no-multi-comp, react/display-name, react/prop-types */ -import DateFnsUtils from "@date-io/date-fns"; -import { MuiPickersUtilsProvider } from "@material-ui/pickers"; import { SnackbarProvider } from "notistack"; import { Provider } from "react-redux"; import { render } from "@testing-library/react"; @@ -12,12 +10,13 @@ import { MemoryRouter, Route, Router } from "react-router-dom"; import { ApplicationProvider } from "../components/application"; import I18nProvider from "../components/i18n/provider"; import ThemeProvider from "../theme-provider"; +import DateProvider from "../date-provider"; import { createMockStore, DEFAULT_STATE } from "./create-mock-store"; import { FormikProvider } from "./formik-utils"; -function setupMountedComponent({ state, path, initialEntries, formProps } = {}) { - const { store, history } = createMockStore(DEFAULT_STATE, state); +function setupMountedComponent({ state, path, initialEntries, formProps, includeRestMiddleware } = {}) { + const { store, history } = createMockStore(DEFAULT_STATE, state, includeRestMiddleware); function RouteProvider({ children }) { if (isEmpty(initialEntries)) { @@ -35,7 +34,7 @@ function setupMountedComponent({ state, path, initialEntries, formProps } = {}) return ( - + @@ -45,7 +44,7 @@ function setupMountedComponent({ state, path, initialEntries, formProps } = {}) - + ); @@ -54,8 +53,22 @@ function setupMountedComponent({ state, path, initialEntries, formProps } = {}) return { store, history, AppProviders }; } -function mountedComponent(Component, state = {}, options = {}, initialEntries = [], formProps = {}, path = "") { - const { store, history, AppProviders } = setupMountedComponent({ state, path, formProps, initialEntries }); +function mountedComponent( + Component, + state = {}, + options = {}, + initialEntries = [], + formProps = {}, + path = "", + includeRestMiddleware = false +) { + const { store, history, AppProviders } = setupMountedComponent({ + state, + path, + formProps, + initialEntries, + includeRestMiddleware + }); const component = render(Component, { wrapper: AppProviders, diff --git a/app/javascript/test-utils/mounted-form-component.js b/app/javascript/test-utils/mounted-form-component.js index 41f7d5c30e..1c0a40e881 100644 --- a/app/javascript/test-utils/mounted-form-component.js +++ b/app/javascript/test-utils/mounted-form-component.js @@ -8,11 +8,12 @@ import { useEffect, cloneElement } from "react"; import { render } from "@testing-library/react"; import { whichFormMode } from "../components/form"; +import { FieldRecord } from "../components/record-form"; import { setupMountedComponent } from "./mounted-component"; -const setupFormFieldRecord = (FieldRecord, field = {}) => { - return FieldRecord({ +const setupFormFieldRecord = (fieldRecord, field = {}) => { + return fieldRecord({ display_name: "Test Field 2", name: "test_field_2", type: "text_field", @@ -52,7 +53,7 @@ function setupMockFormComponent({ state, additionalProps }) { - const MockFormComponent = ({ children, inputProps, field, mode }) => { + function MockFormComponent({ children, inputProps, field, mode }) { const formMethods = useForm({ defaultValues }); const formMode = whichFormMode(mode || "new"); @@ -84,14 +85,16 @@ function setupMockFormComponent({ } return cloneElement(children, { formMode, formMethods, ...componentProps }); - }; + } const { AppProviders, history, store } = setupMountedComponent({ state }); - function Providers({ children }) { + function Providers({ children, ...rest }) { return ( - {children} + + {children} + ); } @@ -121,15 +124,17 @@ function mountedFormComponent( function mountedFieldComponent( Component, - FieldRecord, - fieldRecordSettings = {}, - inputProps = {}, - metaInputProps = {}, - mode = "new", - errors, - options + { + fieldRecord = FieldRecord, + fieldRecordSettings = {}, + inputProps = {}, + metaInputProps = {}, + mode = "new", + errors, + options + } = {} ) { - const field = setupFormFieldRecord(FieldRecord, fieldRecordSettings); + const field = setupFormFieldRecord(fieldRecord, fieldRecordSettings); const { history, store, Providers } = setupMockFormComponent({ additionalProps: { @@ -141,8 +146,8 @@ function mountedFieldComponent( errors }); - const component = render(Component, { - wrapper: Providers, + const component = render(cloneElement(Component), { + wrapper: props => , ...options }); diff --git a/app/javascript/test-utils/mounted-theme-component.js b/app/javascript/test-utils/mounted-theme-component.js index bf7ddb0b30..718c6d8a2d 100644 --- a/app/javascript/test-utils/mounted-theme-component.js +++ b/app/javascript/test-utils/mounted-theme-component.js @@ -12,13 +12,13 @@ import { createMockStore, DEFAULT_STATE } from "./create-mock-store"; function mountedThemeComponent(Component, state = DEFAULT_STATE) { const { store, history } = createMockStore(state, fromJS({})); - const Providers = ({ children }) => { + function Providers({ children }) { return ( {children} ); - }; + } const component = render(Component, { wrapper: Providers diff --git a/app/javascript/test-utils/set-screen-size-to-mobile.js b/app/javascript/test-utils/set-screen-size-to-mobile.js new file mode 100644 index 0000000000..5d82ab917f --- /dev/null +++ b/app/javascript/test-utils/set-screen-size-to-mobile.js @@ -0,0 +1,12 @@ +const setScreenSizeToMobile = mobile => { + window.matchMedia = jest.fn().mockImplementation(query => { + return { + matches: mobile, + media: query, + addListener: jest.fn(), + removeListener: jest.fn() + }; + }); +}; + +export default setScreenSizeToMobile; diff --git a/app/javascript/test-utils/set-select-value.js b/app/javascript/test-utils/set-select-value.js new file mode 100644 index 0000000000..019440e427 --- /dev/null +++ b/app/javascript/test-utils/set-select-value.js @@ -0,0 +1,21 @@ +import { fireEvent, waitFor } from "@testing-library/react"; + +async function setSelectValue(autocomplete, value) { + const input = autocomplete; + + if (!value) { + return input; + } + + autocomplete.focus(); + fireEvent.change(input, { target: { value } }); + await waitFor(); + fireEvent.keyDown(autocomplete, { key: "ArrowDown" }); + await waitFor(); + fireEvent.keyDown(autocomplete, { key: "Enter" }); + await waitFor(); + + return input; +} + +export default setSelectValue; diff --git a/app/javascript/test-utils/setup.js b/app/javascript/test-utils/setup.js index 99a80b5f3c..73d384196a 100644 --- a/app/javascript/test-utils/setup.js +++ b/app/javascript/test-utils/setup.js @@ -1,18 +1,24 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import "react-16-node-hanging-test-fix"; // TODO: Remove when update to React 18 import "./globals"; -import "@testing-library/jest-dom/extend-expect"; +import "@testing-library/jest-dom"; import { MessageChannel } from "worker_threads"; import { createMocks } from "react-idle-timer"; import { cleanup } from "@testing-library/react"; +import db from "../db"; + global.IS_REACT_ACT_ENVIRONMENT = true; beforeAll(() => { + // eslint-disable-next-line no-console + console.warn = () => ""; createMocks(); global.MessageChannel = MessageChannel; }); -afterEach(cleanup); +afterEach(() => { + db.closeDB(); + cleanup(); +}); diff --git a/app/javascript/test-utils/tick.js b/app/javascript/test-utils/tick.js index 52ca9f0073..1f505208ce 100644 --- a/app/javascript/test-utils/tick.js +++ b/app/javascript/test-utils/tick.js @@ -1,8 +1,8 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -const tick = () => +const tick = (delay = 100) => new Promise(resolve => { - setTimeout(resolve, 100); + setTimeout(resolve, delay); }); export default tick; diff --git a/app/javascript/test-utils/utils.js b/app/javascript/test-utils/utils.js new file mode 100644 index 0000000000..131023ef69 --- /dev/null +++ b/app/javascript/test-utils/utils.js @@ -0,0 +1,6 @@ +import { waitFor } from "@testing-library/react"; + +// eslint-disable-next-line import/prefer-default-export +export async function expectNever(callable) { + await expect(() => waitFor(callable)).rejects.toEqual(expect.anything()); +} diff --git a/app/javascript/test/index.js b/app/javascript/test/index.js deleted file mode 100644 index 1d7d4e1df9..0000000000 --- a/app/javascript/test/index.js +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -export { spy, useFakeTimers, stub, mock, fake, replace } from "sinon"; -export * from "./utils"; -export {createMockStore} from '../test-utils/create-mock-store' diff --git a/app/javascript/test/index.unit.test.js b/app/javascript/test/index.unit.test.js deleted file mode 100644 index 69ededd6c0..0000000000 --- a/app/javascript/test/index.unit.test.js +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import * as moduleToTest from "./index"; - -describe("app/javascript/test/index", () => { - const clone = { ...moduleToTest }; - - after(() => { - expect(clone).to.be.empty; - }); - - [ - "abbrMonthNames", - "setupMockFieldComponent", - "setupMockFormComponent", - "setupMountedComponent", - "setupMountedThemeComponent", - "spy", - "stub", - "fake", - "tick", - "replace", - "useFakeTimers", - "mock", - "createSimpleMount", - "createMiddleware", - "listHeaders", - "lookups", - "translateOptions", - "setupHook", - "FormikValueFromHook", - "createMockStore" - ].forEach(property => { - it(`exports property '${property}'`, () => { - expect(clone).to.have.property(property); - delete clone[property]; - }); - }); -}); diff --git a/app/javascript/test/test.setup.js b/app/javascript/test/test.setup.js deleted file mode 100644 index 4653dec11e..0000000000 --- a/app/javascript/test/test.setup.js +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import Enzyme from "enzyme"; -import Adapter from "@wojtekmaj/enzyme-adapter-react-17"; - -import './globals' -import '../test-utils/globals' - -Enzyme.configure({ adapter: new Adapter() }); diff --git a/app/javascript/test/utils/index.js b/app/javascript/test/utils/index.js deleted file mode 100644 index fccb468d7c..0000000000 --- a/app/javascript/test/utils/index.js +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -/* eslint-disable react/display-name, react/no-multi-comp, react/prop-types */ -import { Form, Formik, useFormikContext } from "formik"; -import isFunction from "lodash/isFunction"; -import isEmpty from "lodash/isEmpty"; -import { SnackbarProvider } from "notistack"; -import { useEffect } from "react"; -import { Provider } from "react-redux"; -import { MemoryRouter, Route, Router } from "react-router-dom"; - -import DateFnsUtils from "@date-io/date-fns"; -import { createMount } from "@material-ui/core/test-utils"; -import { MuiPickersUtilsProvider } from "@material-ui/pickers"; -import { useForm, FormProvider } from "react-hook-form"; -import { fromJS } from "immutable"; -import capitalize from "lodash/capitalize"; -import { spy } from "sinon"; -import { renderHook, act } from "@testing-library/react-hooks"; - -import ThemeProvider from "../../theme-provider"; -import { ApplicationProvider } from "../../components/application"; -import I18nProvider from "../../components/i18n"; -import { RECORD_PATH } from "../../config"; -import { whichFormMode } from "../../components/form"; -import { ListHeaderRecord } from "../../components/user/records"; -import { DEFAULT_STATE, createMockStore } from "../../test-utils"; - - - -const setupFormFieldRecord = (FieldRecord, field = {}) => { - return FieldRecord({ - display_name: "Test Field 2", - name: "test_field_2", - type: "text_field", - help_text: "Test Field 2 help text", - required: true, - autoFocus: true, - ...field - }); -}; - -const setupFormInputProps = (field = {}, props = {}, mode, errors = []) => { - const formMode = whichFormMode(props.mode); - const error = errors?.[field.name]; - - return { - name: field.name, - error: typeof error !== "undefined", - required: field.required, - autoFocus: field.autoFocus, - autoComplete: "new-password", - disabled: formMode.get(`is${capitalize(mode)}`), - label: field.display_name, - helperText: error?.message || field.help_text, - fullWidth: true, - InputLabelProps: { - shrink: true - }, - ...props - }; -}; - -export const FormikValueFromHook = (props) => { - return null -} - -export const setupMountedComponent = ( - TestComponent, - props = {}, - initialState = {}, - initialEntries = [], - formProps = {}, - path = "" -) => { - const { store, history } = createMockStore(DEFAULT_STATE, initialState); - - const FormikForm = (props) => { - const formContext = useFormikContext(); - - return ( -
- - - - ) - } - - const FormikComponent = ({ formikProps, componentProps }) => { - if (isEmpty(formikProps)) { - return ; - } - - return ( - - - - ); - }; - - const RoutedProvider = () => { - const formikComponentProps = { - formikProps: formProps, - componentProps: props - }; - - if (isEmpty(initialEntries)) { - return ( - - - - - - ); - } - - return ( - - - - - - - - ); - }; - - const component = createMount()( - - - - - - - - - - - - ); - - return { component, store }; -}; - -export const setupMountedThemeComponent = (TestComponent, props = {}) => { - const { store } = createMockStore(DEFAULT_STATE, fromJS({})); - - return createMount()( - - - - - - ); -}; - -export const tick = () => - new Promise(resolve => { - setTimeout(resolve, 100); - }); - -export const setupMockFormComponent = ( - Component, - { - props = {}, - parentProps = {}, - state = {}, - defaultValues = {}, - includeFormMethods = false, - includeFormProvider = false, - errors - } = {} -) => { - const MockFormComponent = () => { - const { inputProps, field, mode } = props; - const formMethods = useForm({ defaultValues }); - const formMode = whichFormMode(mode || "new"); - - const commonInputProps = setupFormInputProps(field, inputProps, mode, formMethods?.errors); - - const componentProps = { - ...props, - ...(includeFormMethods ? formMethods : {}), - commonInputProps, - ...inputProps - }; - - useEffect(() => { - if (errors) { - errors.forEach(error => { - const { name, message } = error; - - formMethods.setError(name, { type: "manual", message }); - }); - } - }, [errors]); - - if (includeFormProvider) { - return ( - - - - ); - } - - return ; - }; - - return setupMountedComponent(MockFormComponent, parentProps, state); -}; - -export const setupMockFieldComponent = ( - fieldComponent, - FieldRecord, - fieldRecordSettings = {}, - inputProps = {}, - metaInputProps = {}, - mode = "new", - errors -) => { - const field = setupFormFieldRecord(FieldRecord, fieldRecordSettings); - - return setupMockFormComponent(fieldComponent, { - props: { - inputProps, - metaInputProps, - field, - mode - }, - errors - }); -}; - -export const createSimpleMount = component => createMount()(component); - -export const createMiddleware = (middleware, initialState) => { - const { store } = createMockStore(fromJS({}), initialState); - - const next = spy(); - - const invoke = action => middleware(store)(next)(action); - - return { store, next, invoke }; -}; - -export const listHeaders = recordType => { - const commonHeaders = [ - ListHeaderRecord({ - name: "description", - field_name: "description", - id_search: false - }) - ]; - - switch (recordType) { - case RECORD_PATH.user_groups: - return [ - ListHeaderRecord({ - name: "user_group.name", - field_name: "name", - id_search: false - }), - ...commonHeaders - ]; - - case RECORD_PATH.agencies: - return [ - ListHeaderRecord({ - name: "agency.name", - field_name: "name", - id_search: false - }), - ...commonHeaders - ]; - - default: - return []; - } -}; - -export const lookups = () => ({ - data: [ - { - unique_id: "lookup-1", - name: { en: "Lookup 1" }, - values: [ - { id: "a", display_text: [{ en: "Lookup 1 a" }] }, - { id: "b", display_text: [{ en: "Lookup 1 b" }] } - ] - }, - { - unique_id: "lookup-2", - name: { en: "Lookup 2" }, - values: [ - { id: "a", display_text: [{ en: "Lookup 2 a" }] }, - { id: "b", display_text: [{ en: "Lookup 2 b" }] } - ] - } - ], - metadata: { - total: 2, - per: 1, - page: 1 - } -}); - -export const translateOptions = (value, options, translations) => { - const defaultLocale = window.I18n.defaultLocale || "en"; - - if (isEmpty(options)) { - return translations[defaultLocale][value]; - } - - let currValue = translations[options?.locale || defaultLocale][value]; - - Object.entries(options).forEach(option => { - const [optionKey, optionValue] = option; - - currValue = currValue.replace(optionKey, optionValue); - }); - - return currValue?.replace(/[^\w\s\'.]/gi, ""); -}; - -export const abbrMonthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - -export const setupHook = (hook, state = {}) => { - const { store } = createMockStore(DEFAULT_STATE, fromJS(state)); - - if (!hook && !isFunction(hook)) { - throw new Error("Hook function not specified"); - } - - const result = renderHook(() => hook(), { - wrapper: ({ children }) => ( - - {children} - - ) - }); - - return { ...result, store, act }; -}; diff --git a/app/javascript/test/utils/index.unit.test.js b/app/javascript/test/utils/index.unit.test.js deleted file mode 100644 index a08e571cc7..0000000000 --- a/app/javascript/test/utils/index.unit.test.js +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -import * as moduleToTest from "./index"; - -describe("app/javascript/test/utils/index", () => { - const clone = { ...moduleToTest }; - - after(() => { - expect(clone).to.be.empty; - }); - - [ - "abbrMonthNames", - "setupMockFieldComponent", - "setupMockFormComponent", - "setupMountedComponent", - "setupMountedThemeComponent", - "tick", - "createSimpleMount", - "createMiddleware", - "listHeaders", - "lookups", - "translateOptions", - "setupHook", - "FormikValueFromHook" - ].forEach(property => { - it(`exports property '${property}'`, () => { - expect(clone).to.have.property(property); - delete clone[property]; - }); - }); -}); diff --git a/app/javascript/theme-provider.jsx b/app/javascript/theme-provider.jsx index b13c36699b..d9f2150f70 100644 --- a/app/javascript/theme-provider.jsx +++ b/app/javascript/theme-provider.jsx @@ -1,13 +1,15 @@ // Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -import { CssBaseline } from "@material-ui/core"; -import { ThemeProvider as MuiThemeProvider, createMuiTheme, StylesProvider, jssPreset } from "@material-ui/core/styles"; +import { CssBaseline } from "@mui/material"; +import { createTheme, ThemeProvider as MuiThemeProvider } from "@mui/material/styles"; import PropTypes from "prop-types"; import { useMemo, useEffect, useLayoutEffect, createContext, useReducer, useContext, useCallback } from "react"; -import rtl from "jss-rtl"; -import { create } from "jss"; +import createCache from "@emotion/cache"; +import { prefixer } from "stylis"; +import rtlPlugin from "stylis-plugin-rtl"; +import { CacheProvider } from "@emotion/react"; -import theme, { setCssVars, fontSizes, colors, spacing, drawerWidth, shadows, fontFamily } from "./config/theme"; +import theme, { colors, drawerWidth, fontFamily, fontSizes, setCssVars, shadows, spacing } from "./theme"; import useMemoizedSelector from "./libs/use-memoized-selector"; import { getAppDirection } from "./components/i18n/selectors"; @@ -15,6 +17,23 @@ const themeInitialOptions = { direction: "ltr" }; +const emotionCacheCommon = { + prepend: true, + container: document.getElementsByName("emotion-insertion-point")[0], + nonce: document.querySelector('meta[property="csp-nonce"]')?.getAttribute("content") +}; + +const rtlCache = createCache({ + key: "rtl", + stylisPlugins: [prefixer, rtlPlugin], + ...emotionCacheCommon +}); + +const ltrCache = createCache({ + key: "css", + ...emotionCacheCommon +}); + const useEnhancedEffect = typeof window === "undefined" ? useEffect : useLayoutEffect; // eslint-disable-next-line import/exports-last @@ -22,12 +41,7 @@ export const DispatchContext = createContext(() => {}); DispatchContext.displayName = "ThemeDispatchContext"; -const jss = create({ - plugins: [...jssPreset().plugins, rtl()], - insertionPoint: "jss-insertion-point" -}); - -const ThemeProvider = ({ children }) => { +function ThemeProvider({ children }) { const directionFromStore = useMemoizedSelector(state => getAppDirection(state)); const [options, dispatch] = useReducer((state, action) => { @@ -46,6 +60,7 @@ const ThemeProvider = ({ children }) => { const { direction } = options; useEnhancedEffect(() => { + document.dir = direction; document.body.dir = direction; }, [direction]); @@ -56,14 +71,14 @@ const ThemeProvider = ({ children }) => { }, [directionFromStore, direction]); const themeConfig = useMemo(() => { - const muiTheme = createMuiTheme({ ...theme, direction }); + const muiTheme = createTheme({ ...theme, direction }); - muiTheme.overrides.MuiCssBaseline["@global"].html = { fontSize: `var(--fs-${direction === "rtl" ? 18 : 16})` }; + muiTheme.components.MuiCssBaseline.styleOverrides.html = { fontSize: `var(--fs-${direction === "rtl" ? 18 : 16})` }; - muiTheme.overrides.MuiCssBaseline["@global"][":root"] = { + muiTheme.components.MuiCssBaseline.styleOverrides[":root"] = { ...setCssVars("fs", fontSizes, muiTheme.typography.pxToRem), ...setCssVars("c", colors), - ...setCssVars("sp", spacing, muiTheme.spacing, "px"), + ...setCssVars("sp", spacing, muiTheme.spacing), "--ff": fontFamily, "--fwb": muiTheme.typography.fontWeightBold, "--drawer": drawerWidth, @@ -79,17 +94,19 @@ const ThemeProvider = ({ children }) => { return muiTheme; }, [direction]); + const emotionCache = direction === "rtl" ? rtlCache : ltrCache; + return ( - + {children} - + ); -}; +} ThemeProvider.propTypes = { children: PropTypes.node diff --git a/app/javascript/theme.js b/app/javascript/theme.js new file mode 100644 index 0000000000..da45c7c517 --- /dev/null +++ b/app/javascript/theme.js @@ -0,0 +1,582 @@ +// Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +import mapKeys from "lodash/mapKeys"; +import kebabCase from "lodash/kebabCase"; +import { alpha } from "@mui/material"; + +import importedTheme from "./libs/load-external-theme"; + +const generateCssVarKey = (prefix, key) => `--${prefix}-${kebabCase(key)}`; + +const valueWithUnit = (value, unit) => (unit ? `${value}${unit}` : value); + +const setCssVars = (prefix, vars, func, unit) => { + if (Array.isArray(vars)) { + return vars.reduce( + (prev, current) => ({ ...prev, [generateCssVarKey(prefix, current)]: valueWithUnit(func(current), unit) }), + {} + ); + } + + return mapKeys(vars, (_, key) => generateCssVarKey(prefix, key)); +}; + +const colors = { + black: "#231f20", // u + blue: "#0F809E", // u + lightBlue: "#239EBF", // u + blueHover: "#0B6178", // u + blueHoverLight: "rgba(15, 128, 158, .18)", // u + whiteHover: "#e6efd4", // u + contentGrey: "#fbfbfb", // u + darkBlue: "#048BB0", + darkBrown: "#5a5549", + darkGrey: "#595952", // u + goldYellow: "#f4ac22", + green: "#839e3c", // u + grey: "#4a4a4a", // u + lightBlueRgba: "rgba(0, 147, 186, 0.25)", // u + lightBlueMenu: "#dfeff4", + lightGrey: "#f0f0f0", // u + lightGrey2: "#e0e0e0", + midGrey: "#757472", // u + yellow: "#f2b417", // u + orange: "#C4540C", // u + purple: "#7c347b", // u + red: "#d0021b", // u + redLabelError: "#f44336", + solidBlack: "#000000", + solidGreen: "#7ba024", + solidOrange: "#ff9500", + stickyGrey: "rgba(251, 251, 251, 0.95)", + tundora: "#454545", + warmGrey1: "#e0dfd7", + warmGrey2: "#bcbcad", + warmGrey3: "#b9b8b3", + warmGrey4: "#9a988f", + warmGrey5: "#d5d5d5", + warmGrey6: "#6f6f6a", + white: "#ffffff", // u + wildSand: "#f5f5f5", + greenLight: "#E6EED3", // u, + redMedium: "#E7712D", + redLow: "#F7D0BA", + forgotPasswordLink: "var(--c-blue)", + networkIndicatorBorder: "var(--c-solid-green)", + navListIcon: "var(--c-dark-grey))", + navListText: "var(--c-dark-grey)", + navListTextActive: "var(--c-black)", + navListIconActive: "var(--c-black)", + navListBgActive: "var(--c-content-grey)", + navListDivider: "var(--c-warm-grey-1)", + drawerHeaderButton: "transparent", + drawerHeaderButtonText: "var(--c-white)", + toolbarBackgroundColor: "linear-gradient(to top, var(--c-white), var(--c-light-grey))", + toolbarBackgroundButton: "var(--c-blue)", + mobileToolbarBackground: + // eslint-disable-next-line max-len + "linear-gradient(to top, var(--c-white), var(--c-light-grey)), linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.14))", + mobileToolbarHamburgerButton: "rgba(0, 0, 0, 0.54)", + loginBackgroundGradientStart: "var(--c-blue)", + loginBackgroundGradientEnd: "var(--c-blue)", + loginTranslationsButtonBackground: "transparent", + loginTranslationsButtonText: "var(--c-white)", + loginButtonBg: "var(--c-blue)", + loginButtonText: "var(--c-white)", + ...importedTheme.colors +}; + +const fontFamily = ["helvetica", "roboto", "arial", "sans-serif"].join(", "); +const fontSizes = [9, 12, 13, 14, 16, 18, 20, 30, 96, 130, 186]; +const shadows = ["0 2px 12px 0 rgba(125, 125, 125, 0.23)"]; +const drawerWidth = "240px"; +const spacing = [1, 2, 3, 4]; + +const components = { + MuiCssBaseline: { + styleOverrides: { + "#root": { + display: "flex", + flexDirection: "column", + height: ["var(--doc-height, 100vh)", "100dvh"] + }, + legend: { + display: "none" + } + } + }, + MuiPaper: { + styleOverrides: { + elevation3: { + boxShadow: "0 2px 12px 0 rgba(125, 125, 125, 0.23)" + }, + elevation2: { + boxShadow: "0 2px 1px 0 rgba(89, 89, 81, 0.05)" + } + } + }, + MuiAccordionSummary: { + styleOverrides: { + content: { + margin: "0" + } + } + }, + MuiInputLabel: { + styleOverrides: { + root: { + overflow: "auto", + textOverflow: "initial", + whiteSpace: "normal", + lineHeight: "2em", + // fontSize: `var(--fs-${isRTL ? 16 : 12})`, + fontWeight: 700, + marginBottom: ".5em", + color: colors.black, + "&.Mui-focused": { + color: colors.black + }, + "&.Mui-disabled": { + color: colors.black + } + }, + outlined: { + marginBottom: 0 + }, + shrink: { + transform: "none !important" + }, + formControl: { + position: "relative" + }, + asterisk: { + color: "var(--c-red)" + } + } + }, + MuiInputBase: { + styleOverrides: { + root: { + "&.Mui-disabled": { + cursor: "not-allowed !important" + } + }, + input: { + "&.Mui-disabled": { + color: "var(--c-black)", + cursor: "not-allowed !important", + opacity: 1, + WebkitTextFillColor: "var(--c-black)" + } + } + } + }, + MuiInput: { + styleOverrides: { + input: { + border: "1px solid var(--c-black)", + borderRadius: "6px", + "&.Mui-focus": { + borderColor: colors.yellow + }, + "&.Mui-read-only": { + color: colors.black, + paddingBottom: "3px" + }, + "&.Mui-read-only ::placeholder": { + color: colors.black, + opacity: 1 + } + }, + formControl: { + "label + &": { + marginTop: 0 + } + } + } + }, + MuiCheckbox: { + styleOverrides: { + root: { + color: colors.black, + padding: "0 var(--sp-1)", + "&.Mui-checked": { + color: `${colors.black} !important` + } + } + } + }, + MuiRadio: { + styleOverrides: { + root: { + padding: "0 var(--sp-1)", + "&.Mui-checked": { + color: `${colors.black} !important` + } + } + } + }, + MuiFormControlLabel: { + styleOverrides: { + root: { + "&.Mui-disabled": { + cursor: "not-allowed" + } + }, + label: { + fontSize: "var(--fs-13) !important", + "&.Mui-disabled": { + color: colors.black + } + } + } + }, + MuiFormHelperText: { + styleOverrides: { + root: { + lineHeight: "1.4em", + whiteSpace: "pre-wrap" + }, + contained: { + marginLeft: 0, + marginRight: 0 + } + } + }, + MUIDataTableToolbar: { + styleOverrides: { + root: { + paddingLeft: "5px", + paddingRight: "5px", + paddingTop: "8px", + paddingBottom: "8px", + justifyContent: "flex-start" + }, + titleText: { + position: "absolute", + left: "-10000px", + top: "auto", + width: "1px", + height: "1px", + overflow: "hidden" + }, + left: { + display: "none !important" + } + } + }, + MUIDataTableToolbarSelect: { + styleOverrides: { + root: { + paddingLeft: "5px", + paddingRight: "5px", + paddingTop: "8px", + paddingBottom: "8px", + justifyContent: "flex-start", + backgroundColor: colors.white, + boxShadow: "none" + }, + title: { + display: "none" + } + } + }, + MuiTableRow: { + styleOverrides: { + root: { + cursor: "pointer" + }, + hover: { + cursor: "pointer", + "&:hover": { + background: colors.lightGrey + } + } + } + }, + MuiTableCell: { + styleOverrides: { + root: { + padding: "8px" + } + } + }, + MUIDataTableHeadCell: { + styleOverrides: { + root: { + fontWeight: "900", + textTransform: "uppercase", + fontSize: "var(--fs-12)", + color: `${colors.black}`, + lineHeight: "1.3em", + padding: ".5em" + } + } + }, + MuiChip: { + styleOverrides: { + sizeSmall: { + height: "21px", + fontSize: "var(--fs-12)" + } + } + }, + MuiDialogActions: { + styleOverrides: { + root: { + justifyContent: "flex-start", + margin: "var(--sp-1)" + }, + spacing: { + gap: "var(--sp-1)" + } + } + }, + MuiDialogTitle: { + styleOverrides: { + root: { + textTransform: "uppercase", + fontSize: "var(--fs-16)", + fontWeight: "bold", + padding: "var(--sp-2)" + } + } + }, + MuiDialogContent: { + styleOverrides: { + root: { + padding: "0 var(--sp-2)" + } + } + }, + MuiFab: { + styleOverrides: { + sizeSmall: { + width: "36px", + height: "36px" + } + } + }, + MuiToggleButton: { + styleOverrides: { + root: { + fontWeight: 600, + textTransform: "none" + } + } + }, + MuiButton: { + styleOverrides: { + root: { + letterSpacing: "normal", + lineHeight: "normal", + textTransform: "none", + fontSize: "var(--fs-14)", + fontWeight: 600, + borderRadius: "6px", + "&.Mui-disabled": { + color: "rgba(0, 0, 0, 0.26)", + backgroundColor: `${colors.lightGrey} !important` + } + }, + containedPrimary: { + "&:hover, &:active, &:focus": { + // TODO: @media is overriding this style + backgroundColor: "var(--c-blue-hover) !important", + "&.Mui-disabled": { + color: "rgba(0, 0, 0, 0.26)", + backgroundColor: `${colors.lightGrey} !important` + } + } + }, + outlinedPrimary: { + "&:hover, &:active, &focus": { + borderColor: "var(--c-blue-hover)", + color: "var(--c-blue-hover)", + "&.Mui-disabled": { + color: "rgba(0, 0, 0, 0.26)", + backgroundColor: `${colors.lightGrey} !important` + } + } + } + } + }, + MuiFormGroup: { + styleOverrides: { + root: { + gap: "var(--sp-2)" + } + } + }, + MuiFormLabel: { + styleOverrides: { + root: { + fontSize: "var(--fs-13)" + } + } + }, + MuiAutocomplete: { + styleOverrides: { + tag: { + margin: "var(--sp-1)", + height: "var(--sp-13)", + + "& svg": { + width: "16px", + height: "16px" + } + } + } + }, + MuiListItemText: { + styleOverrides: { + root: { + textAlign: "initial", + wordBreak: "break-word" + } + } + }, + MuiMenu: { + defaultProps: { + anchorOrigin: { + vertical: "bottom", + horizontal: "right" + }, + transformOrigin: { + vertical: "top", + horizontal: "right" + } + }, + styleOverrides: { + paper: { + borderRadius: "6px", + overflow: "visible", + marginTop: "var(--sp-1)", + "&::before": { + backgroundColor: "var(--c-white)", + content: '""', + display: "block", + position: "absolute", + width: 12, + height: 12, + top: -6, + transform: "rotate(45deg)", + right: 12, + zIndex: 10 + }, + "&::after": { + backgroundColor: "var(--c-white)", + content: '""', + display: "block", + position: "absolute", + width: 12, + height: 12, + top: -6, + transform: "rotate(45deg)", + right: 12, + zIndex: -10, + boxShadow: shadows[2] + } + } + } + }, + MuiLink: { + styleOverrides: { + root: { + display: "block", + cursor: "pointer", + "&:hover, &:active, &focus": { + color: "var(--c-blue-hover)" + } + } + } + }, + MuiStepLabel: { + styleOverrides: { + root: { + fontWeight: 600 + } + } + }, + MuiOutlinedInput: { + styleOverrides: { + root: { + // padding: 0, + fontSize: "var(--fs-16)", + background: "var(--c-white)", + "&.Mui-focused": { + borderColor: colors.blue, + boxShadow: `${alpha(colors.blue, 0.25)} 0 0 0 0.2rem` + }, + "&.Mui-disabled": { + "& .MuiChip-root": { + opacity: 1 + }, + "& .MuiChip-root .MuiChip-deleteIcon": { + display: "none" + }, + "& fieldset.MuiOutlinedInput-notchedOutline": { + borderColor: "var(--c-warm-grey-2)" + } + } + }, + multiline: { + padding: "var(--sp-1)" + }, + notchedOutline: { + borderColor: "var(--c-black)", + top: 0, + "& legend": { + display: "none" + } + } + } + }, + MuiTextField: { + defaultProps: { + variant: "outlined", + size: "small" + } + }, + MuiFormControl: { + defaultProps: { + margin: "normal" + } + }, + MuiButtonBase: { + defaultProps: { + disableRipple: true + } + } +}; + +const transitions = { + create: () => "none" +}; + +export default { + palette: { + primary: { + main: colors.blue + }, + secondary: { + main: colors.blue + } + }, + typography: { + useNextVariants: true, + fontFamily, + fontWeight: 600 + }, + primero: { + colors, + shadows, + components: { + drawerWidth + } + }, + components, + transitions +}; + +export { setCssVars, fontSizes, colors, spacing, drawerWidth, shadows, fontFamily }; diff --git a/app/javascript/worker.js b/app/javascript/worker.js index 0e6e10f14b..d225040953 100644 --- a/app/javascript/worker.js +++ b/app/javascript/worker.js @@ -73,6 +73,19 @@ registerRoute( METHODS.GET ); +registerRoute( + /\/(?:theme|manifest).*$/, + new CacheFirst({ + cacheName: "theme", + plugins: [ + new ExpirationPlugin({ + maxEntries: 2 + }) + ] + }), + METHODS.GET +); + // Api Endpoints Object.values(METHODS).forEach(method => { registerRoute(/\/api\/.*/, new NetworkOnly(), method); @@ -89,16 +102,7 @@ const manifest = self.__WB_MANIFEST.map(entry => { return entry; }); -const revision = manifest?.filter(({ url }) => url === "/")?.[0]?.revision; - -const themeFiles = ["theme", "manifest.json"].map(asset => { - return { - url: `${self.location.origin}/${asset}`, - revision - }; -}); - -precacheAndRoute([...manifest, ...themeFiles]); +precacheAndRoute(manifest); setCatchHandler(({ event }) => { if (isNav(event)) return caches.match(getCacheKeyForURL("/")); diff --git a/app/jobs/duplicate_field_alert_job.rb b/app/jobs/duplicate_field_alert_job.rb index 7b8ba23fd1..d6844384d6 100644 --- a/app/jobs/duplicate_field_alert_job.rb +++ b/app/jobs/duplicate_field_alert_job.rb @@ -7,7 +7,7 @@ class DuplicateFieldAlertJob < ApplicationJob queue_as :api def perform(record_id, record_type, alert_on_duplicate) - record = Record.model_from_name(record_type)&.find_by(id: record_id) + record = PrimeroModelService.to_model(record_type)&.find_by(id: record_id) return unless record.present? DuplicatedFieldAlertService.create_or_remove_alerts!(record, alert_on_duplicate) diff --git a/app/jobs/webhook_job.rb b/app/jobs/webhook_job.rb index 9b1e1f61ee..dc7422bbd8 100644 --- a/app/jobs/webhook_job.rb +++ b/app/jobs/webhook_job.rb @@ -7,7 +7,7 @@ class WebhookJob < ApplicationJob queue_as :api def perform(record_type, record_id, action) - record = Record.model_from_name(record_type).find_by(id: record_id) + record = PrimeroModelService.to_model(record_type)&.find_by(id: record_id) return unless record&.webhook_configured? webhooks = Webhook.webhooks_for(record, action) diff --git a/app/mailers/record_action_mailer.rb b/app/mailers/record_action_mailer.rb index e5675dbc36..df781b53e2 100644 --- a/app/mailers/record_action_mailer.rb +++ b/app/mailers/record_action_mailer.rb @@ -12,7 +12,7 @@ def manager_approval_request(approval_notification) @approval_notification = approval_notification return unless @approval_notification.send_notification? - return unless assert_notifications_enabled(@approval_notification.manager) + return unless assert_notifications_enabled(@approval_notification.manager, Approval::NOTIFICATION_ACTIONS_REQUEST) mail(to: @approval_notification.manager.email, subject: @approval_notification.subject) end @@ -21,7 +21,7 @@ def manager_approval_response(approval_notification) @approval_notification = approval_notification return unless @approval_notification.send_notification? - return unless assert_notifications_enabled(@approval_notification.owner) + return unless assert_notifications_enabled(@approval_notification.owner, Approval::NOTIFICATION_ACTIONS_RESPONSE) mail(to: @approval_notification.owner.email, subject: @approval_notification.subject) end @@ -30,7 +30,9 @@ def transition_notify(transition_notification) @transition_notification = transition_notification return if @transition_notification.transition.nil? - return unless assert_notifications_enabled(@transition_notification.transitioned_to) + return unless assert_notifications_enabled( + @transition_notification.transitioned_to, Transition::NOTIFICATION_ACTION + ) mail(to: @transition_notification&.transitioned_to&.email, subject: transition_notification.subject) end @@ -39,7 +41,9 @@ def transfer_request(transfer_request_notification) @transfer_request_notification = transfer_request_notification return if @transfer_request_notification.transition.nil? - return unless assert_notifications_enabled(@transfer_request_notification.transitioned_to) + return unless assert_notifications_enabled( + @transfer_request_notification.transitioned_to, Transfer::NOTIFICATION_ACTION + ) mail(to: @transfer_request_notification&.transitioned_to&.email, subject: @transfer_request_notification.subject) end @@ -56,8 +60,8 @@ def alert_notify(alert_notification) private - def assert_notifications_enabled(user) - return true if user&.emailable? + def assert_notifications_enabled(user, action = nil) + return true if user&.emailable? && (action.nil? || user&.specific_notification?('send_mail', action)) Rails.logger.info("Mail not sent. Mail notifications disabled for #{user&.user_name || 'nil user'}") diff --git a/app/middleware/jwt_token_setter.rb b/app/middleware/jwt_token_setter.rb deleted file mode 100644 index c01fc6689d..0000000000 --- a/app/middleware/jwt_token_setter.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -# This middleware ensures that the HTTP_AUTHORIZATION header is always set with a Bearer token -# if a JWT token is specified in a cookie. This makes it compatible with the devise-jwt library that -# only looks at the bearer token to verify authentication. -class JwtTokenSetter - def initialize(app) - @app = app - end - - def call(env) - unless env['HTTP_AUTHORIZATION'].present? - request = Rack::Request.new(env) - token = request.cookies['primero_token'] - env['HTTP_AUTHORIZATION'] = "Bearer #{token}" if token.present? - end - - @app.call(env) - end -end diff --git a/app/models/approval.rb b/app/models/approval.rb index c5e672bc6a..db60ced75a 100644 --- a/app/models/approval.rb +++ b/app/models/approval.rb @@ -54,6 +54,8 @@ class Approval < ValueObject approved_comments: 'gbv_closure_approved_comments' }.freeze + NOTIFICATION_ACTIONS_REQUEST = 'approval_request' + NOTIFICATION_ACTIONS_RESPONSE = 'approval_response' class << self def get!(approval_id, record, user, params = {}) raise Errors::UnknownPrimeroEntityType, 'approvals.error_invalid_approval' if types.exclude?(approval_id) @@ -151,8 +153,6 @@ def approval_action(status, properties) end def delete_approval_alerts - return if record.alerts.blank? - record.alerts.where(type: approval_id, alert_for: Alertable::APPROVAL).destroy_all end end diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 31e8b0177c..5d07e7324b 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -19,6 +19,7 @@ class Attachment < ApplicationRecord MAX_SIZE = 20.megabytes.freeze EXPIRES = 60.seconds # Expiry for the delegated ActiveStorage url + DEFAULT_MAX_ATTACHMENTS = 100 belongs_to :record, polymorphic: true, optional: true has_one_attached :file @@ -32,8 +33,7 @@ class Attachment < ApplicationRecord file_size: { less_than_or_equal_to: MAX_SIZE }, file_content_type: { allow: ->(a) { a.valid_content_types } }, if: :attached? - validates_associated :record - after_commit :index_record + validate :maximum_attachments_exceeded, on: :create def attach return unless record.present? @@ -46,7 +46,7 @@ def attach end def attach! - attach && save! + attach && save! && record.save! end def detach @@ -56,7 +56,7 @@ def detach end def detach! - detach && destroy + detach && destroy && record.save! end def attached? @@ -99,7 +99,15 @@ def to_h_api hash end - def index_record - Sunspot.index(record) if record + private + + def system_max_attachmensts_per_record + SystemSettings.current&.maximum_attachments_per_record || DEFAULT_MAX_ATTACHMENTS + end + + def maximum_attachments_exceeded + return if record.attachments.reload.size < system_max_attachmensts_per_record + + errors.add(:base, 'errors.attachments.maximum') end end diff --git a/app/models/bulk_export.rb b/app/models/bulk_export.rb index 5d3bf3d2e6..83e9758b69 100644 --- a/app/models/bulk_export.rb +++ b/app/models/bulk_export.rb @@ -47,7 +47,7 @@ def export(password) end def model_class - @model_class ||= Record.model_from_name(record_type) + @model_class ||= PrimeroModelService.to_model(record_type) end def exporter_type @@ -102,7 +102,7 @@ def archive! end def generate_file_name - return if file_name.present? + return self.file_name = ActiveStorage::Filename.new(file_name).sanitized if file_name.present? self.file_name = "#{record_type&.pluralize}-#{Time.now.strftime('%Y%m%d.%M%S%M%L')}.#{exporter_type&.mime_type}" end @@ -122,16 +122,26 @@ def process_records_in_batches(batch = 500) page = 1 order = self.order || { created_at: :desc } loop do - results = SearchService.search(model_class, { filters: search_filters, query_scope: record_query_scope, query:, - sort: order, pagination: { page:, per_page: batch } }).results - exporter.single_record_export = results.total_count == 1 - yield(results) - # Set again the values of the pagination variable because the method modified the variable. - page = results.next_page - break if page.nil? + result = search_records(search_filters, batch, page, order) + break if result.records.blank? + + exporter.single_record_export = result.total == 1 + yield(result.records) + page += 1 end end + def search_records(filters, batch, page, order) + PhoneticSearchService.search( + model_class, + { + filters:, + scope: record_query_scope, query:, + sort: order, pagination: { page:, per_page: batch } + } + ) + end + def attach_export_file(file) return unless file && File.size?(file) diff --git a/app/models/child.rb b/app/models/child.rb index 8740f67e38..03358ea6ab 100644 --- a/app/models/child.rb +++ b/app/models/child.rb @@ -28,7 +28,7 @@ def self.parent_form include CareArrangements include UNHCRMapping include Ownable - include AutoPopulatable + include CalculateFullName include Serviceable include Reopenable include Workflow @@ -45,6 +45,7 @@ def self.parent_form include FollowUpable include LocationCacheable include FamilyLinkable + include PhoneticSearchable # rubocop:disable Naming/VariableNumber store_accessor( @@ -66,7 +67,9 @@ def self.parent_form :registry_id_display, :registry_name, :registry_no, :registry_location_current, :urgent_protection_concern, :child_preferences_section, :family_details_section, :care_arrangements_section, :duplicate, :cp_case_plan_subform_case_plan_interventions, :has_case_plan, - :family_member_id, :family_id_display, :family_number + :family_member_id, :family_id_display, :family_number, :has_incidents, :assessment_due_dates, + :case_plan_due_dates, :followup_due_dates, :reunification_details_section, :reunification_dates, + :tracing_actions_section, :tracing_dates ) # rubocop:enable Naming/VariableNumber @@ -78,10 +81,6 @@ def self.parent_form scope :by_date_of_birth, -> { where.not('data @> ?', { date_of_birth: nil }.to_json) } - def self.sortable_text_fields - %w[name case_id_display national_id_no registry_no family_number] - end - def self.filterable_id_fields # The fields family_count_no and dss_id are hacked in only because of Bangladesh # The fields camp_id, tent_number and nfi_distribution_id are hacked in only because of Iraq @@ -96,6 +95,10 @@ def self.quicksearch_fields filterable_id_fields + NAME_FIELDS end + def self.phonetic_field_names + NAME_FIELDS + end + def self.summary_field_names common_summary_fields + %w[ case_id_display name survivor_code_no age sex registration_date @@ -129,36 +132,33 @@ def self.api_path '/api/v2/cases' end - searchable do - filterable_id_fields.each { |f| string("#{f}_filterable", as: "#{f}_filterable_sci") { data[f] } } - sortable_text_fields.each { |f| string("#{f}_sortable", as: "#{f}_sortable_sci") { data[f] } } - Child.child_matching_field_names.each { |f| text_index(f, 'matchable') } - Child.family_matching_field_names.each do |f| - text_index(f, 'matchable', :itself, 'family_details_section') - end - quicksearch_fields.each { |f| text_index(f) } - %w[registration_date date_case_plan_initiated assessment_requested_on date_closure].each { |f| date(f) } - %w[estimated urgent_protection_concern consent_for_tracing has_case_plan].each do |f| - boolean(f) { data[f] == true || data[f] == 'true' } - end - %w[day_of_birth age].each { |f| integer(f) } - %w[id status sex current_care_arrangements_type].each { |f| string(f, as: "#{f}_sci") } - string :risk_level, as: 'risk_level_sci' do - risk_level.present? ? risk_level : RISK_LEVEL_NONE + if Rails.configuration.solr_enabled + searchable do + extend Searchable::TextIndexing + Child.child_matching_field_names.each { |f| text_index(f, 'matchable') } + Child.family_matching_field_names.each do |f| + text_index(f, 'matchable', :itself, 'family_details_section') + end + + date(:date_closure) + %w[consent_for_tracing].each do |f| + boolean(f) { data[f] == true || data[f] == 'true' } + end end - string :protection_concerns, multiple: true - date(:assessment_due_dates, multiple: true) { Tasks::AssessmentTask.from_case(self).map(&:due_date) } - date(:case_plan_due_dates, multiple: true) { Tasks::CasePlanTask.from_case(self).map(&:due_date) } - date(:followup_due_dates, multiple: true) { Tasks::FollowUpTask.from_case(self).map(&:due_date) } - boolean(:has_incidents) { incidents.size.positive? } end validate :validate_date_of_birth before_save :sync_protection_concerns - before_save :auto_populate_name before_save :stamp_registry_fields before_save :calculate_has_case_plan + before_save :calculate_has_incidents + before_save :stamp_family_number + before_save :calculate_assessment_due_dates + before_save :calculate_case_plan_due_dates + before_save :calculate_followup_due_dates + before_save :calculate_tracing_dates + before_save :calculate_reunification_dates before_create :hide_name after_save :save_incidents @@ -252,12 +252,6 @@ def to_s name.present? ? "#{name} (#{unique_identifier})" : unique_identifier end - def auto_populate_name - # This 2 step process is necessary because you don't want to overwrite self.name if auto_populate is off - a_name = auto_populate('name') - self.name = a_name if a_name.present? - end - def hide_name self.hidden_name = true if module_id == PrimeroModule::GBV end @@ -265,7 +259,7 @@ def hide_name def set_instance_id system_settings = SystemSettings.current self.case_id ||= unique_identifier - self.case_id_code ||= auto_populate('case_id_code', system_settings) + self.case_id_code ||= AutoPopulateService.auto_populate(self, 'case_id_code', system_settings) self.case_id_display ||= create_case_id_display(system_settings) end @@ -279,7 +273,9 @@ def create_case_id_code(system_settings) end def create_case_id_display(system_settings) - [case_id_code, short_id].compact.join(auto_populate_separator('case_id_code', system_settings)) + [case_id_code, short_id].compact.join( + AutoPopulateService.auto_populate_separator('case_id_code', system_settings) + ) end def display_id @@ -307,6 +303,44 @@ def calculate_has_case_plan has_case_plan end + def calculate_has_incidents + self.has_incidents = incidents.size.positive? + + has_incidents + end + + def calculate_assessment_due_dates + # TODO: Tests fail if I don't have a flat_map here + self.assessment_due_dates = Tasks::AssessmentTask.from_case(self).map(&:due_date).compact + + assessment_due_dates + end + + def calculate_case_plan_due_dates + self.case_plan_due_dates = Tasks::CasePlanTask.from_case(self).map(&:due_date).compact + + case_plan_due_dates + end + + def calculate_followup_due_dates + self.followup_due_dates = Tasks::FollowUpTask.from_case(self).map(&:due_date).compact + + followup_due_dates + end + + def calculate_tracing_dates + self.tracing_dates = tracing_actions_section&.reduce([]) { |acc, elem| acc << elem['date_tracing'] }&.compact + tracing_dates + end + + def calculate_reunification_dates + self.reunification_dates = reunification_details_section&.reduce([]) do |acc, elem| + acc << elem['date_reunification'] + end&.compact + + reunification_dates + end + def sync_protection_concerns protection_concerns = self.protection_concerns || [] from_subforms = protection_concern_detail_subform_section&.map { |pc| pc['protection_concern_type'] }&.compact || [] @@ -349,5 +383,11 @@ def associations_as_data(current_user = nil) def associations_as_data_keys %w[incident_details] end + + def stamp_family_number + return unless family.present? + + self.family_number = family_number + end end # rubocop:enable Metrics/ClassLength diff --git a/app/models/concerns/alertable.rb b/app/models/concerns/alertable.rb index efda5beeb4..62df042af5 100644 --- a/app/models/concerns/alertable.rb +++ b/app/models/concerns/alertable.rb @@ -24,14 +24,14 @@ module AlertStrategy end included do - searchable do - string :current_alert_types, multiple: true - end + store_accessor(:data, :current_alert_types) has_many :alerts, as: :record before_save :add_alert_on_field_change before_update :remove_alert_on_save + before_create :calculate_current_alert_types + before_update :calculate_current_alert_types end def alert_count @@ -86,30 +86,40 @@ def add_field_alert(conf_record) end end - def current_alert_types - alerts.map(&:type).uniq + def calculate_current_alert_types + self.current_alert_types = alerts.each_with_object([]) do |alert, memo| + next if alert.destroyed? || memo.include?(alert.type) + + memo << alert.type unless alert.destroyed? + end + + current_alert_types end def add_alert(args = {}) - date_alert = args[:date].presence || Date.today - - alert = Alert.new(type: args[:type], date: date_alert, form_sidebar_id: args[:form_sidebar_id], - alert_for: args[:alert_for], user_id: args[:user_id], agency_id: args[:agency_id], - send_email: args[:send_email]) + alert = Alert.new(type: args[:type], date: args[:date].presence || Date.today, + form_sidebar_id: args[:form_sidebar_id], alert_for: args[:alert_for], user_id: args[:user_id], + agency_id: args[:agency_id], send_email: args[:send_email]) (alerts << alert) && alert end def remove_alert(type = nil) alerts.each do |alert| - next unless (type.present? && alert.type == type) && [ - NEW_FORM, FIELD_CHANGE, TRANSFER_REQUEST - ].include?(alert.alert_for) + next unless (type.present? && alert.type == type) && + [NEW_FORM, FIELD_CHANGE, TRANSFER_REQUEST].include?(alert.alert_for) alert.destroy end end + def remove_alert_by_unique_id!(alert_unique_id) + alert = alerts.find { |elem| elem.unique_id == alert_unique_id } + raise ActiveRecord::RecordNotFound unless alert.present? + + alert.destroy! && save! + end + def get_alert(approval_type, system_settings) system_settings ||= SystemSettings.current system_settings.approval_forms_to_alert.key(approval_type) @@ -128,10 +138,9 @@ def alerts_on_change # values in the hash is either a string or a hash. If it's a string, it's # the form section unique id. If it's a hash, it's the form section unique # id and the alert strategy - ( - @system_settings&.changes_field_to_form&.map do |field_name, form_section_uid_or_hash| - [field_name, AlertConfigEntryService.new(form_section_uid_or_hash)] - end).to_h + (@system_settings&.changes_field_to_form&.map do |field_name, form_section_uid_or_hash| + [field_name, AlertConfigEntryService.new(form_section_uid_or_hash)] + end).to_h end end @@ -161,15 +170,16 @@ def remove_alert(type = nil) def alert_count_agency(current_user) agency_unique_id = current_user.agency.unique_id - open_enabled_records.where("data -> 'associated_user_agencies' ? :agency", agency: agency_unique_id) - .distinct.count + open_enabled_records.where( + "data %s '$.associated_user_agencies %s (@ == %s)'", '@?', '?', agency_unique_id.to_json + ).distinct.count end def alert_count_group(current_user) user_groups_unique_id = current_user.user_groups.pluck(:unique_id) + user_groups_filter = user_groups_unique_id.map { |unique_id| "@ == #{unique_id.to_json}" }.join(' || ') open_enabled_records.where( - "data -> 'associated_user_groups' ?& array[:group]", - group: user_groups_unique_id + "data %s '$.associated_user_groups %s (%s)'", '@?', '?', user_groups_filter ).distinct.count end @@ -178,6 +188,8 @@ def alert_count_self(current_user) end def open_enabled_records - joins(:alerts).where('data @> ?', { record_state: true, status: Record::STATUS_OPEN }.to_json) + joins(:alerts).where( + "data %s '$[*] %s (@.record_state == true && @.status == %s)'", '@?', '?', Record::STATUS_OPEN.to_json + ) end end diff --git a/app/models/concerns/approvable.rb b/app/models/concerns/approvable.rb index 55bcedc4cb..a9967ea9a3 100644 --- a/app/models/concerns/approvable.rb +++ b/app/models/concerns/approvable.rb @@ -15,20 +15,6 @@ module Approvable :assessment_approved_comments, :case_plan_approved_comments, :closure_approved_comments, :action_plan_approved_comments, :gbv_closure_approved_comments, :approval_subforms - searchable do - string :approval_status_assessment, as: 'approval_status_assessment_sci' - string :approval_status_case_plan, as: 'approval_status_case_plan_sci' - string :approval_status_closure, as: 'approval_status_closure_sci' - string :approval_status_action_plan, as: 'approval_status_action_plan_sci' - string :approval_status_gbv_closure, as: 'approval_status_gbv_closure_sci' - string :case_plan_approval_type, as: 'case_plan_approval_type_sci' - date :case_plan_approved_date - date :assessment_approved_date - date :closure_approved_date - date :action_plan_approved_date - date :gbv_closure_approved_date - end - after_save_commit :send_approval_mail end diff --git a/app/models/concerns/attachable.rb b/app/models/concerns/attachable.rb index 8266cf322c..1d1f99b8b6 100644 --- a/app/models/concerns/attachable.rb +++ b/app/models/concerns/attachable.rb @@ -6,9 +6,7 @@ # on Records. Has idiomatic methods for handing case photos module Attachable extend ActiveSupport::Concern - include Sunspot::Rails::Searchable - MAX_ATTACHMENTS = 100 PHOTOS_FIELD_NAME = 'photos' AUDIOS_FIELD_NAME = 'recorded_audio' DOCUMENTS_FIELD_NAME = 'other_documents' @@ -19,21 +17,17 @@ module Attachable as: :record, class_name: 'Attachment' has_many :current_audios, -> { where(field_name: AUDIOS_FIELD_NAME).order('date DESC NULLS LAST') }, as: :record, class_name: 'Attachment' - validate :maximum_attachments_exceeded - searchable do - boolean :has_photo - end + store_accessor(:data, :has_photo) + + before_save :calculate_has_photo end def photo? - # Because Matz - # rubocop:disable Naming/MemoizedInstanceVariableName - @has_photo ||= current_photos.size.positive? - # rubocop:enable Naming/MemoizedInstanceVariableName + has_photo end + alias has_photo? photo? - alias has_photo photo? def photo @photo ||= current_photos.first @@ -45,6 +39,11 @@ def photo_url Rails.application.routes.url_helpers.rails_blob_path(photo.file, only_path: true) end + def calculate_has_photo + self.has_photo = current_photos.size.positive? + has_photo + end + private def maximum_attachments_exceeded diff --git a/app/models/concerns/auto_populatable.rb b/app/models/concerns/auto_populatable.rb deleted file mode 100644 index 3bd8b3c2a4..0000000000 --- a/app/models/concerns/auto_populatable.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -# Derive field values on records, as configured in SystemSettings. -# TODO: Really this should live in a service. -module AutoPopulatable - extend ActiveSupport::Concern - - def fetch_auto_populate_info(auto_populate_info) - id_code_parts = [] - auto_populate_info.format.each { |pf| id_code_parts << PropertyEvaluator.evaluate(self, pf) } - id_code_parts.reject(&:blank?).join(auto_populate_info.separator) - end - - def auto_populate(field_key, system_settings = nil) - @system_settings ||= (system_settings || SystemSettings.current) - auto_populate_info = @system_settings.auto_populate_info(field_key) if @system_settings.present? - return unless auto_populate_info&.auto_populated == true && auto_populate_info.format.present? - - fetch_auto_populate_info(auto_populate_info) - end - - def auto_populate_separator(field_key, system_settings = nil) - @system_settings ||= (system_settings.present? ? system_settings : SystemSettings.current) - auto_populate_info = @system_settings.auto_populate_info(field_key) if @system_settings.present? - auto_populate_info.present? ? auto_populate_info.separator : '' - end -end diff --git a/app/models/concerns/calculate_full_name.rb b/app/models/concerns/calculate_full_name.rb new file mode 100644 index 0000000000..3259a455eb --- /dev/null +++ b/app/models/concerns/calculate_full_name.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Calculates the full name of a record +module CalculateFullName + extend ActiveSupport::Concern + + included do + before_save :auto_populate_name + end + + def auto_populate_name + # This 2 step process is necessary because you don't want to overwrite self.name if auto_populate is off + a_name = AutoPopulateService.auto_populate(self, 'name') + self.name = a_name if a_name.present? + end +end diff --git a/app/models/concerns/calculate_tracing_names.rb b/app/models/concerns/calculate_tracing_names.rb new file mode 100644 index 0000000000..b201478a3f --- /dev/null +++ b/app/models/concerns/calculate_tracing_names.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Calculates the tracing names and nicknames +module CalculateTracingNames + extend ActiveSupport::Concern + + included do + store_accessor :data, :tracing_names, :tracing_nicknames + before_save :calculate_tracing_names, :calculate_tracing_nicknames + end + + def calculate_tracing_names(persisted_traces = false) + traces_to_calculate = persisted_traces ? traces : @traces_to_save + return [] unless traces_to_calculate.present? + + self.tracing_names = traces_to_calculate.map(&:name).compact + tracing_names + end + + def calculate_tracing_nicknames(persisted_traces = false) + traces_to_calculate = persisted_traces ? traces : @traces_to_save + return [] unless traces_to_calculate.present? + + self.tracing_nicknames = traces_to_calculate.map(&:name_nickname).compact + tracing_nicknames + end +end diff --git a/app/models/concerns/duplicate_id_alertable.rb b/app/models/concerns/duplicate_id_alertable.rb index ecf0ea8167..62e2ac9707 100644 --- a/app/models/concerns/duplicate_id_alertable.rb +++ b/app/models/concerns/duplicate_id_alertable.rb @@ -9,17 +9,13 @@ module DuplicateIdAlertable DUPLICATE_FIELD = 'duplicate_field' included do - searchable do - string :current_alert_types, multiple: true - end - after_save :perform_duplicate_field_alert end def perform_duplicate_field_alert return unless alerts_on_duplicate.present? - record_alerts_on_duplicate = alerts_on_duplicate[Record.map_name(self.class.name)] + record_alerts_on_duplicate = alerts_on_duplicate[PrimeroModelService.to_name(self.class.name)] return unless record_alerts_on_duplicate.present? diff --git a/app/models/concerns/flaggable.rb b/app/models/concerns/flaggable.rb index 1272baacac..0de6aeb8e2 100644 --- a/app/models/concerns/flaggable.rb +++ b/app/models/concerns/flaggable.rb @@ -5,15 +5,14 @@ # Describes records that can have flags applied to them. module Flaggable extend ActiveSupport::Concern - include Sunspot::Rails::Searchable included do - searchable do - boolean :flagged - end + store_accessor(:data, :flagged) has_many :flags, as: :record has_many :active_flags, -> { where(removed: false) }, as: :record, class_name: 'Flag' + + before_save :calculate_flagged end def add_flag(message, date, user_name) @@ -23,6 +22,11 @@ def add_flag(message, date, user_name) flag end + def add_flag!(message, date, user_name) + flag = add_flag(message, date, user_name) + save! && flag + end + def remove_flag(id, user_name, unflag_message) flag = flags.find_by(id:) return unless flag.present? @@ -35,6 +39,11 @@ def remove_flag(id, user_name, unflag_message) flag end + def remove_flag!(id, user_name, unflag_message) + flag = remove_flag(id, user_name, unflag_message) + save! && flag + end + def flag_count active_flags.size end @@ -42,7 +51,11 @@ def flag_count def flagged? flag_count.positive? end - alias flagged flagged? + + def calculate_flagged + self.flagged = flagged? + flagged + end # ClassMethods module ClassMethods diff --git a/app/models/concerns/follow_upable.rb b/app/models/concerns/follow_upable.rb index 99b9bf5bc6..4bf73ccf2d 100644 --- a/app/models/concerns/follow_upable.rb +++ b/app/models/concerns/follow_upable.rb @@ -11,9 +11,10 @@ module FollowUpable FOLLOW_UPS_IMPLEMENTED = 'follow_ups_implemented' included do - store_accessor :data, :followup_status + store_accessor :data, :followup_status, :followup_dates before_save :save_followup_status + before_save :calculate_followup_dates def save_followup_status self.followup_status = if all_followup_implemented? @@ -25,6 +26,11 @@ def save_followup_status end end + def calculate_followup_dates + self.followup_dates = followup_subform_section&.reduce([]) { |acc, elem| acc << elem['followup_date'] }&.compact + followup_dates + end + private def all_followup_implemented? diff --git a/app/models/concerns/historical.rb b/app/models/concerns/historical.rb index 25e1726635..fa96be2ff2 100644 --- a/app/models/concerns/historical.rb +++ b/app/models/concerns/historical.rb @@ -17,12 +17,10 @@ module Historical has_many :record_histories, as: :record - searchable do - %i[created_organization created_agency_office created_by last_updated_by last_updated_organization].each do |f| - string f, as: "#{f}_sci" + if Rails.configuration.solr_enabled + searchable do + time(:created_at) end - string(:created_by_groups, multiple: true) - %i[created_at last_updated_at posted_at].each { |f| time(f) } end validate :validate_created_at diff --git a/app/models/concerns/indexable.rb b/app/models/concerns/indexable.rb index ec9ab7ad31..db15eb7fbc 100644 --- a/app/models/concerns/indexable.rb +++ b/app/models/concerns/indexable.rb @@ -7,7 +7,9 @@ module Indexable extend ActiveSupport::Concern included do - include Sunspot::Rails::Searchable - Sunspot::Adapters::InstanceAdapter.register Sunspot::Rails::Adapters::ActiveRecordInstanceAdapter, self + if Rails.configuration.solr_enabled + include Sunspot::Rails::Searchable + Sunspot::Adapters::InstanceAdapter.register Sunspot::Rails::Adapters::ActiveRecordInstanceAdapter, self + end end end diff --git a/app/models/concerns/monitoring_reporting_mechanism.rb b/app/models/concerns/monitoring_reporting_mechanism.rb index ca8947968b..7078672747 100644 --- a/app/models/concerns/monitoring_reporting_mechanism.rb +++ b/app/models/concerns/monitoring_reporting_mechanism.rb @@ -7,143 +7,268 @@ module MonitoringReportingMechanism extend ActiveSupport::Concern + ASSOCIATION_MAPPING = { + 'armed_force_group_party_name' => 'armed_force_group_party_names', + 'ctfmr_verified' => 'verification_status', + 'facilty_victims_held' => 'victim_facilty_victims_held' + }.freeze + + ASSOCIATION_FIELDS = { + 'individual_victims' => %w[ + individual_age individual_sex victim_deprived_liberty_security_reasons reasons_deprivation_liberty + facilty_victims_held torture_punishment_while_deprivated_liberty + ], + 'perpetrators' => %w[armed_force_group_party_name perpetrator_category], + 'violations' => %w[ + verified_ghn_reported weapon_type facility_impact facility_attack_type child_role abduction_purpose_single + military_use_type types_of_aid_disrupted_denial ctfmr_verified_date ctfmr_verified + ] + }.freeze + + VIOLATION_TYPED_FIELDS = { + 'violation_with_verification_status' => 'ctfmr_verified', + 'violation_with_weapon_type' => 'weapon_type', + 'violation_with_facility_impact' => 'facility_impact' + }.freeze + included do - searchable do - %i[ - individual_violations individual_sex victim_deprived_liberty_security_reasons - reasons_deprivation_liberty victim_facilty_victims_held torture_punishment_while_deprivated_liberty - violation_with_verification_status verification_status armed_force_group_party_names verified_ghn_reported - violation_with_weapon_type violation_with_facility_impact violation_with_facility_attack_type - child_role abduction_purpose_single military_use_type types_of_aid_disrupted_denial weapon_type facility_impact - facility_attack_type late_verified_violations perpetrator_category - ].each { |field| string(field, multiple: true) } - - integer(:individual_age, multiple: true) - date(:ctfmr_verified_date, multiple: true) - boolean(:has_late_verified_violations) { late_verified_violations? } - end + # TODO: For now we are storing the associations fields in the incident data, but at some point we should be able + # to extend our filters in order to query the association directly. + store_accessor( + :data, :individual_violations, :individual_age, :individual_sex, :victim_deprived_liberty_security_reasons, + :reasons_deprivation_liberty, :victim_facilty_victims_held, :torture_punishment_while_deprivated_liberty, + :violation_with_verification_status, :late_verified_violations, :has_late_verified_violations, + :verification_status, :armed_force_group_party_names, :perpetrator_category, :verified_ghn_reported, + :weapon_type, :facility_impact, :facility_attack_type, :violation_with_weapon_type, :child_role, + :abduction_purpose_single, :violation_with_facility_impact, :violation_with_facility_attack_type, + :military_use_type, :types_of_aid_disrupted_denial, :ctfmr_verified_date + ) + + has_many :violations, dependent: :destroy, inverse_of: :incident + has_many :perpetrators, through: :violations + has_many :individual_victims, through: :violations + has_many :sources, through: :violations + + before_save :save_violations_and_associations + before_save :update_violations end - def individual_violations - individual_victims.map { |individual_victim| individual_victim.violations.map(&:type) }.flatten.uniq.compact + # Class methods for all MRM Incidents + module ClassMethods + def violations_data(data_keys, data) + return {} unless data + + data_keys.reduce({}) do |acc, elem| + next acc unless data[elem].present? + + acc.merge(elem => data.delete(elem)) + end + end end - def individual_age - individual_victims.map(&:individual_age).uniq.compact + def build_or_update_violations_and_associations(data) + return unless mrm? + + build_or_update_violations(self.class.violations_data(Violation::TYPES, data)) + build_violations_associations(self.class.violations_data(Violation::MRM_ASSOCIATIONS_KEYS, data)) end - def individual_sex - individual_victims.map(&:individual_sex).uniq.compact + def build_or_update_violations(violation_objects_data) + return unless violation_objects_data.present? + + @violations_to_save = violation_objects_data.each_with_object([]) do |(type, violations_by_type), acc| + violations_by_type.each { |violation_data| acc << Violation.build_record(type, violation_data, self) } + acc + end end - def victim_deprived_liberty_security_reasons - individual_victims.map(&:victim_deprived_liberty_security_reasons).uniq.compact + def build_violations_associations(violation_associations_data) + return unless violation_associations_data.present? + + @associations_to_save = violation_associations_data.each_with_object([]) do |(type, associations_data), acc| + association_object = type.classify.constantize + associations_data.each { |association_data| acc << association_object.build_record(association_data) } + acc + end end - def reasons_deprivation_liberty - individual_victims.map(&:reasons_deprivation_liberty).uniq.compact + def mrm? + module_id == PrimeroModule::MRM end - def victim_facilty_victims_held - individual_victims.map(&:facilty_victims_held).uniq.compact + def save_violations_and_associations + save_violations + save_violations_associations + + return unless @violations_to_save.present? || @associations_to_save.present? + + reload_violations_and_associations + recalculate_association_fields end - def torture_punishment_while_deprivated_liberty - individual_victims.map(&:torture_punishment_while_deprivated_liberty).uniq.compact + def save_violations + return unless @violations_to_save + + @violations_to_save.each(&:save!) end - def violation_with_verification_status - violations.each_with_object([]) do |violation, memo| - next unless violation.type.present? && violation.ctfmr_verified.present? + def save_violations_associations + return unless @associations_to_save - memo << "#{violation.type}_#{violation.ctfmr_verified}" - end.uniq + @associations_to_save.each do |association| + if association.violations_ids.present? + association.violations = violations_for_associated(association.violations_ids) + end + next if association.violations.blank? + + association.save! + end end - def late_verified_violations - violations.each_with_object([]) do |violation, memo| - next unless violation.type.present? && violation.is_late_verification + def association_classes_to_save + return unless @associations_to_save - memo << violation.type - end.uniq + @associations_to_save.map(&:class).uniq.compact end - def late_verified_violations? - violations.any?(&:is_late_verification) + def associations_as_data(_current_user) + mrm_associations = associations_as_data_keys.to_h { |value| [value, []] } + + @associations_as_data ||= violations.reduce(mrm_associations) do |acc, violation| + acc[violation.type] << violation.data + acc.merge(violation.associations_as_data) do |_key, acc_value, violation_value| + (acc_value + violation_value).compact.uniq { |value| value['unique_id'] } + end + end end - def verification_status - violations.map(&:ctfmr_verified).uniq.compact + def associations_as_data_keys + (Violation::TYPES + Violation::MRM_ASSOCIATIONS_KEYS) end - def armed_force_group_party_names - perpetrators.map(&:armed_force_group_party_name).uniq.compact + # Returns a list of Violations to be associated with + # Violation::MRM_ASSOCIATIONS_KEYS (perpetrators, victims...) on API update + def violations_for_associated(violations_ids) + ids = (violations_ids.is_a?(Array) ? violations_ids : [violations_ids]) + violations_result = [] + + if @violations_to_save.present? + violations_result += @violations_to_save.select { |violation| ids.include?(violation.id) } + end + violations_result += Violation.where(id: ids - violations_result.map(&:id)) + + violations_result end - def perpetrator_category - perpetrators.map(&:perpetrator_category).uniq.compact + def update_violations + should_update_violations = !new_record? && mrm? && (incident_date_changed? || incident_date_end_changed?) + + return unless should_update_violations + + violations.each(&:calculate_late_verifications) end - def verified_ghn_reported - violations.map(&:verified_ghn_reported).uniq.compact + # TODO: This method will trigger queries to reload the violations and associations in order to store the latest data + def reload_violations_and_associations + association_classes = association_classes_to_save + violations.reload if @violations_to_save.present? || association_classes.include?(Source) + return unless association_classes.present? + + individual_victims.reload if association_classes.include?(IndividualVictim) + perpetrators.reload if association_classes.include?(Perpetrator) end - def weapon_type - violations.map(&:weapon_type).uniq.compact + def recalculate_association_fields + stamp_association_fields + stamp_fields_with_violation_type + calculate_individual_violations + calculate_late_verified_violations + calculate_has_late_verified_violations + calculate_violation_with_facility_attack_type end - def facility_impact - violations.map(&:facility_impact).uniq.compact + def stamp_association_fields + ASSOCIATION_FIELDS.each do |(association, field_names)| + extract_values_from_associations(send(association), field_names).each do |(field_name, values)| + field = ASSOCIATION_MAPPING[field_name] || field_name + data[field] = values + end + end end - def facility_attack_type - violations.map(&:facility_attack_type).uniq.compact + def stamp_fields_with_violation_type + extract_values_with_type_from_violations(violations, VIOLATION_TYPED_FIELDS.values).each do |(field_name, values)| + field = VIOLATION_TYPED_FIELDS.key(field_name) + data[field] = values + end end - def violation_with_weapon_type - violations.each_with_object([]) do |violation, memo| - next unless violation.type.present? && violation.weapon_type.present? + def extract_values_from_associations(associations_to_stamp, field_names) + associations_to_stamp.each_with_object({}) do |association, memo| + field_names&.each do |field_name| + memo[field_name] = [] unless memo[field_name].present? + value = association.send(field_name) + next unless value.present? - memo << "#{violation.type}_#{violation.weapon_type}" - end.uniq + memo[field_name] += Array.wrap(value).reject { |elem| memo[field_name].include?(elem) } + end + end end - def violation_with_facility_impact - violations.each_with_object([]) do |violation, memo| - next unless violation.type.present? && violation.facility_impact.present? + def extract_values_with_type_from_violations(violations_to_stamp, field_names) + violations_to_stamp.each_with_object({}) do |violation, memo| + next unless violation.type.present? - memo << "#{violation.type}_#{violation.facility_impact}" - end.uniq + field_names.each do |field_name| + memo[field_name] = [] unless memo[field_name].present? + value = extract_value_from_violation(violation, field_name) + next unless value.present? + + memo[field_name] += value.reject { |elem| memo[field_name].include?(elem) } + end + end end - def child_role - violations.map(&:child_role).uniq.compact + def extract_value_from_violation(violation, field_name) + Array.wrap(violation.send(field_name)).map { |elem| "#{violation.type}_#{elem}" } end - def abduction_purpose_single - violations.map(&:abduction_purpose_single).uniq.compact + def calculate_individual_violations + self.individual_violations = individual_victims.map do |individual_victim| + individual_victim.violations.map(&:type) + end.flatten.uniq.compact + + individual_violations end - def violation_with_facility_attack_type - violations.each_with_object([]) do |violation, memo| - next unless violation.type.present? && violation.facility_attack_type.present? + def calculate_late_verified_violations + self.late_verified_violations = violations.each_with_object([]) do |violation, memo| + next unless violation.type.present? && violation.is_late_verification - violation.facility_attack_type.each do |attack_type| - memo << "#{violation.type}_#{attack_type}" - end + memo << violation.type end.uniq + + late_verified_violations end - def military_use_type - violations.map(&:military_use_type).uniq.compact + def calculate_has_late_verified_violations + self.has_late_verified_violations = violations.any?(&:is_late_verification) + + has_late_verified_violations end - def types_of_aid_disrupted_denial - violations.map(&:types_of_aid_disrupted_denial).uniq.compact + def late_verified_violations? + has_late_verified_violations end - def ctfmr_verified_date - violations.map(&:ctfmr_verified_date).uniq.compact + def calculate_violation_with_facility_attack_type + self.violation_with_facility_attack_type = violations.each_with_object([]) do |violation, memo| + next unless violation.type.present? && violation.facility_attack_type.present? + + violation.facility_attack_type.each { |attack_type| memo << "#{violation.type}_#{attack_type}" } + end.uniq + + violation_with_facility_attack_type end end # rubocop:enable Metrics/ModuleLength diff --git a/app/models/concerns/ownable.rb b/app/models/concerns/ownable.rb index d5dd61e479..76ead2b680 100644 --- a/app/models/concerns/ownable.rb +++ b/app/models/concerns/ownable.rb @@ -2,39 +2,44 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +# rubocop:disable Metrics/ModuleLength # This describes all models that may be owned by a particular user module Ownable extend ActiveSupport::Concern + # rubocop:disable Metrics/BlockLength included do store_accessor :data, :owned_by, :owned_by_full_name, :owned_by_agency_id, :owned_by_groups, :owned_by_location, :owned_by_user_code, :owned_by_agency_office, :previously_owned_by, :previously_owned_by_full_name, :previously_owned_by_agency, :previously_owned_by_location, :previously_owned_by_agency_office, :assigned_user_names, :module_id, :associated_user_groups, :associated_user_agencies, - :associated_user_names - - searchable do - %i[ - associated_user_names associated_user_groups associated_user_agencies owned_by_groups assigned_user_names - ].each { |field| string(field, multiple: true) } - %i[ - owned_by_agency_id owned_by_location owned_by_agency_office module_id owned_by - ].each { |field| string(field, as: "#{field}_sci") } - boolean :not_edited_by_owner + :associated_user_names, :not_edited_by_owner + + if Rails.configuration.solr_enabled + searchable do + %i[ + associated_user_names associated_user_groups associated_user_agencies owned_by_groups assigned_user_names + ].each { |field| string(field, multiple: true) } + %i[ + owned_by_agency_id owned_by_location owned_by_agency_office module_id owned_by + ].each { |field| string(field, as: "#{field}_sci") } + end end scope :owned_by, ->(username) { where('data @> ?', { owned_by: username }.to_json) } scope :associated_with, (lambda do |username| + username_json = username.to_json where( - "(data -> 'assigned_user_names' ? :username) OR (data -> 'owned_by' ? :username)", - username: + "data %s '$[*] %s (@.assigned_user_names == %s || @.owned_by == %s)'", '@?', '?', username_json, username_json ) end) before_save :update_associated before_save :update_owned_by + before_save :calculate_not_edited_by_owner before_update :update_previously_owned_by end + # rubocop:enable Metrics/BlockLength def owner_fields_for(user) self.owned_by ||= user&.user_name @@ -63,10 +68,13 @@ def owned_by_agency @record_agency ||= Agency.find_by(unique_id: owned_by_agency_id)&.agency_code if owned_by_agency_id end - def not_edited_by_owner + def not_edited_by_owner? (data['last_updated_by'] != data['owned_by']) && data['last_updated_by'].present? end - alias not_edited_by_owner? not_edited_by_owner + + def calculate_not_edited_by_owner + self.not_edited_by_owner = not_edited_by_owner? + end # rubocop:disable Metrics/AbcSize def update_owned_by @@ -133,3 +141,4 @@ def owner?(user) owned_by == user&.user_name end end +# rubocop:enable Metrics/ModuleLength diff --git a/app/models/concerns/phonetic_searchable.rb b/app/models/concerns/phonetic_searchable.rb new file mode 100644 index 0000000000..a1a498f5d9 --- /dev/null +++ b/app/models/concerns/phonetic_searchable.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Concern that allow records to be searchable through phonetics +# TODO: Once the Searchable concern is deprecated this concern will be renamed to Searchable +module PhoneticSearchable + extend ActiveSupport::Concern + + included do + has_many :searchable_identifiers, as: :record + store_accessor :phonetic_data, :tokens + + accepts_nested_attributes_for :searchable_identifiers + + before_save :recalculate_phonetic_tokens + before_create :recalculate_searchable_identifiers + before_update :recalculate_searchable_identifiers + end + + # Class methods to indicate the phonetic_field_names of a record + module ClassMethods + def phonetic_field_names + [] + end + end + + def recalculate_phonetic_tokens + return unless phonetic_fields_changed? + + self.tokens = generate_tokens + end + + def recalculate_searchable_identifiers + return unless filterable_id_fields_changed? + + generate_searchable_identifiers + end + + def generate_searchable_identifiers + identifiers_to_save = identifiers_to_update + + self.class.filterable_id_fields.each do |field_name| + value = data[field_name]&.strip + next if value.blank? || identifiers_to_save.any? { |identifier| identifier[:field_name] == field_name } + + identifiers_to_save << { field_name:, value: } + end + + self.searchable_identifiers_attributes = identifiers_to_save + end + + def identifiers_to_update + searchable_identifiers.map do |searchable_identifier| + { + field_name: searchable_identifier.field_name, + value: data[searchable_identifier.field_name]&.strip, + id: searchable_identifier.id + } + end + end + + def filterable_id_fields_changed? + (changes_to_save_for_record.keys & self.class.filterable_id_fields).present? + end + + def generate_tokens + self.class.phonetic_field_names.reduce([]) do |memo, field_name| + value = data[field_name] + next(memo) unless value.present? + next((memo + LanguageService.tokenize(value)).uniq) unless value.is_a?(Array) + + (memo + value.flat_map { |elem| LanguageService.tokenize(elem) }).uniq + end + end + + def phonetic_fields_changed? + (changes_to_save_for_record.keys & self.class.phonetic_field_names).present? + end +end diff --git a/app/models/concerns/record.rb b/app/models/concerns/record.rb index b1477923fa..7b1a55896d 100644 --- a/app/models/concerns/record.rb +++ b/app/models/concerns/record.rb @@ -19,23 +19,6 @@ module Record after_initialize :defaults, unless: :persisted? before_create :create_identification before_save :populate_subform_ids - after_save :index_nested_reportables - after_destroy :unindex_nested_reportables - end - - def self.model_from_name(name) - case name - when 'case' then Child - when 'violation' then Incident - else Object.const_get(name.camelize) - end - rescue NameError - nil - end - - def self.map_name(name) - name = name.underscore - name == 'child' ? 'case' : name end # Class methods for all Record types @@ -57,7 +40,7 @@ def common_summary_fields end def find_by_unique_identifier(unique_identifier) - find_by('data @> ?', { unique_identifier: }.to_json) + find_by("data %s '$.unique_identifier %s (@ == %s)'", '@?', '?', unique_identifier.to_json) end def parent_form @@ -138,16 +121,4 @@ def populate_subform_ids end end end - - def index_nested_reportables - nested_reportables_hash.each do |_, reportables| - Sunspot.index reportables if reportables.present? - end - end - - def unindex_nested_reportables - nested_reportables_hash.each do |_, reportables| - Sunspot.remove! reportables if reportables.present? - end - end end diff --git a/app/models/concerns/reportable_nested_record.rb b/app/models/concerns/reportable_nested_record.rb index ae51c4b7e6..a5d8da75ad 100644 --- a/app/models/concerns/reportable_nested_record.rb +++ b/app/models/concerns/reportable_nested_record.rb @@ -11,7 +11,6 @@ module ReportableNestedRecord # TODO: Make similar (and test exhaustively!) to Flag model to perform reads and writes included do - include Indexable attr_accessor :parent_record, :object end @@ -37,15 +36,6 @@ def object_form .first field.try(:subform) end - - # Sunspot expects this to be an active record object. So we are tricking it. - def before_save(*_); end - - def after_save(*_); end - - def after_destroy(*_); end - - def after_commit(*_); end end def id @@ -63,67 +53,4 @@ def object_value(field_name) object[field_name] end - - # Shared Sunspot indexing configuration. Its a big messy thing, but that's how hacks work. - module Searchable - # rubocop:disable Metrics/AbcSize - # rubocop:disable Metrics/CyclomaticComplexity - # rubocop:disable Metrics/MethodLength - # rubocop:disable Metrics/PerceivedComplexity - def configure_searchable(record_class) - string :parent_record_id do |f| - f.record_value('id') - end - record_class.parent_record_type.minimum_reportable_fields.each do |type, fields| - case type - when 'string' - fields.each { |f| string(f, as: "#{f}_sci".to_sym) { record_value(f) } } - when 'multistring' - fields.each { |f| string(f, multiple: true) { record_value(f) } } - when 'boolean' - fields.each { |f| boolean(f) { record_value(f) } } - when 'date' - fields.each { |f| date(f) { record_value(f) } } - when 'integer' - fields.each { |f| integer(f) { record_value(f) } } - when 'location' - fields.each do |field| - Location::ADMIN_LEVELS.each do |admin_level| - string "#{field}#{admin_level}", as: "#{field}#{admin_level}_sci".to_sym do - parent_record.location_service.ancestor_code(record_value(field), admin_level) - end - end - end - end - end - - object_form = record_class.object_form - return unless object_form.present? - - object_form.fields.each do |field| - case field.type - when Field::SELECT_BOX, Field::RADIO_BUTTON - if field.multi_select - string(field.name, multiple: true) { object_value(field.name) } - else - string(field.name, as: "#{field.name}_sci".to_sym) { object_value(field.name) } - end - when Field::TICK_BOX - boolean(field.name) { object_value(field.name) } - when Field::DATE_FIELD - if field.date_include_time - time(field.name) { object_value(field.name) } - else - date(field.name) { object_value(field.name) } - end - when Field::NUMERIC_FIELD - integer(field.name) { object_value(field.name) } - end - end - end - # rubocop:enable Metrics/AbcSize - # rubocop:enable Metrics/CyclomaticComplexity - # rubocop:enable Metrics/MethodLength - # rubocop:enable Metrics/PerceivedComplexity - end end diff --git a/app/models/concerns/searchable.rb b/app/models/concerns/searchable.rb index 1aebbc3224..18e71d7798 100644 --- a/app/models/concerns/searchable.rb +++ b/app/models/concerns/searchable.rb @@ -5,90 +5,13 @@ # Concern that describes how fields on forms should be indexed in Sunspot. module Searchable extend ActiveSupport::Concern + # TODO: This is only used in this concern for text indexing. PHONETIC_FIELD_NAMES = %w[name name_nickname name_other relation_name relation_nickname relation_other_family tracing_names tracing_nicknames].freeze - - # Almost never disable Rubocop, but Sunspot searchable blocks are special - # rubocop:disable Metrics/BlockLength included do - include Indexable - Sunspot::Adapters::DataAccessor.register RecordDataAccessor, self - # Note that the class will need to be reloaded when the fields change. - searchable do - extend TextIndexing - string(:record_id) { id } - - searchable_option_fields.each do |f| - string(f, as: "#{f}_sci".to_sym) { data[f] } - end - searchable_multi_fields.each do |f| - string(f, multiple: true) { data[f] } - end - searchable_date_fields.each do |f| - date(f) { data[f] } - end - searchable_date_time_fields.each do |f| - time(f) { data[f] } - end - searchable_numeric_fields.each do |f| - integer(f) { data[f] } - end - searchable_boolean_fields.each do |f| - boolean(f) { data[f] } - end - # if self.include?(SyncableMobile) #TODO: refactor with SyncableMobile; recast as store_accessors? - # boolean :marked_for_mobile do - # self.data['marked_for_mobiles'] - # end - # end - all_searchable_location_fields.each do |field| - Location::ADMIN_LEVELS.each do |admin_level| - string "#{field}#{admin_level}", as: "#{field}#{admin_level}_sci".to_sym do - location_service.ancestor_code(data[field], admin_level) - end - end - end - end - end - # rubocop:enable Metrics/BlockLength - - # Class methods to derive the record data to index based on the configured forms - module ClassMethods - def searchable_date_fields - Field.all_searchable_date_field_names(parent_form) - end - - def searchable_date_time_fields - Field.all_searchable_date_time_field_names(parent_form) - end - - def searchable_boolean_fields - ( - %w[duplicate flag has_photo record_state case_status_reopened] + - Field.all_searchable_boolean_field_names(parent_form) - ).uniq - end - - def searchable_option_fields - Field.all_filterable_option_field_names(parent_form) - end - - def searchable_multi_fields - Field.all_filterable_multi_field_names(parent_form) - end - - def searchable_numeric_fields - Field.all_filterable_numeric_field_names(parent_form) - end - - def searchable_location_fields - %w[location_current incident_location registry_location_current] - end - - def all_searchable_location_fields - ( - %w[owned_by_location] + searchable_location_fields + Field.all_location_field_names(parent_form) - ).uniq + if Rails.configuration.solr_enabled + include Indexable + Sunspot::Adapters::DataAccessor.register RecordDataAccessor, self end end @@ -113,11 +36,13 @@ def field_value(record, field_name) end end - # Class for allowing Sunspot to eager load record associations - class RecordDataAccessor < Sunspot::Adapters::DataAccessor - def load_all(ids) - # NOTE: This triggers a query against Attachment and Alert for each loaded record - @clazz.eager_loaded_class.where(@clazz.primary_key => ids) + if Rails.configuration.solr_enabled + # Class for allowing Sunspot to eager load record associations + class RecordDataAccessor < Sunspot::Adapters::DataAccessor + def load_all(ids) + # NOTE: This triggers a query against Attachment and Alert for each loaded record + @clazz.eager_loaded_class.where(@clazz.primary_key => ids) + end end end end diff --git a/app/models/concerns/serviceable.rb b/app/models/concerns/serviceable.rb index 058f56d1cd..405a56b144 100644 --- a/app/models/concerns/serviceable.rb +++ b/app/models/concerns/serviceable.rb @@ -3,6 +3,7 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. # Concern for services +# rubocop:disable Metrics/ModuleLength module Serviceable extend ActiveSupport::Concern @@ -15,14 +16,12 @@ module Serviceable # rubocop:disable Metrics/BlockLength included do - store_accessor :data, :consent_for_services, :services_section # TODO: Do we need a services alias for this? - - searchable do - boolean :consent_for_services - time :service_due_dates, multiple: true - end + store_accessor :data, :consent_for_services, :services_section, # TODO: Do we need a services alias for this? + :service_due_dates, :service_implemented_day_times before_save :update_implement_field + before_save :calculate_service_due_dates + before_save :calculate_service_implemented_day_times def update_implement_field services_section&.each do |service| @@ -97,10 +96,22 @@ def converted_timeframe(created_on, timeframe) end # TODO: Should this be moved to the Serviceable concern? - def service_due_dates + def calculate_service_due_dates # TODO: only use services that is of the type of the current workflow reportable_services = nested_reportables_hash[ReportableService] - reportable_services.reject(&:service_implemented?).map(&:service_due_date).compact if reportable_services.present? + if reportable_services.present? + self.service_due_dates = reportable_services.reject(&:service_implemented?).map(&:service_due_date).compact + end + + service_due_dates + end + + def calculate_service_implemented_day_times + self.service_implemented_day_times = services_section&.map do |service| + service['service_implemented_day_time'] + end&.compact + + service_implemented_day_times end def service_implemented?(service) @@ -136,3 +147,4 @@ def convert_time(string) end # rubocop:enable Metrics/BlockLength end +# rubocop:enable Metrics/ModuleLength diff --git a/app/models/concerns/transitionable.rb b/app/models/concerns/transitionable.rb index 34d3189f4a..4ebeef10fc 100644 --- a/app/models/concerns/transitionable.rb +++ b/app/models/concerns/transitionable.rb @@ -9,16 +9,13 @@ module Transitionable included do has_many :transitions, as: :record - store_accessor :data, :transfer_status, :reassigned_transferred_on - - searchable do - string :transfer_status, as: 'transfer_status_sci' - string :referred_users, multiple: true - string :transferred_to_users, multiple: true - string :transferred_to_user_groups, multiple: true - time :reassigned_transferred_on - boolean :referred_users_present - end + store_accessor :data, :transfer_status, :reassigned_transferred_on, :referred_users, :transferred_to_users, + :transferred_to_user_groups, :referred_users_present + + before_save :calculate_transferred_to_users + before_save :calculate_transferred_to_user_groups + before_save :calculate_referred_users + before_save :calculate_referred_users_present end def assigns @@ -61,24 +58,28 @@ def transitions_for_user(user, types = []) transitions.where(type: types.reject { |type| type == Referral.name }).or(referrals) end - def transferred_to_users - transfers - .where(status: [Transition::STATUS_INPROGRESS]) - .pluck(:transitioned_to).uniq + def calculate_transferred_to_users + self.transferred_to_users = transfers.where(status: [Transition::STATUS_INPROGRESS]).pluck(:transitioned_to).uniq + transferred_to_users end - def transferred_to_user_groups - UserGroup.joins(:users).where(users: { name: transferred_to_users }).pluck(:unique_id) + def calculate_transferred_to_user_groups + self.transferred_to_user_groups = UserGroup.joins(:users).where( + users: { name: transferred_to_users } + ).pluck(:unique_id) + transferred_to_user_groups end - def referred_users - referrals - .where(status: [Transition::STATUS_INPROGRESS, Transition::STATUS_ACCEPTED]) - .pluck(:transitioned_to).uniq + def calculate_referred_users + self.referred_users = referrals.where(status: [Transition::STATUS_INPROGRESS, Transition::STATUS_ACCEPTED]) + .pluck(:transitioned_to) + .uniq + referred_users end - def referred_users_present - referred_users.present? + def calculate_referred_users_present + self.referred_users_present = referred_users.present? + referred_users_present end def referrals_self_scope(user) diff --git a/app/models/concerns/unhcr_mapping.rb b/app/models/concerns/unhcr_mapping.rb index 4ae1731dff..fea2e6e573 100644 --- a/app/models/concerns/unhcr_mapping.rb +++ b/app/models/concerns/unhcr_mapping.rb @@ -12,10 +12,6 @@ module UNHCRMapping :unhcr_needs_codes, :unhcr_export_opt_out, :unhcr_export_opt_in before_save :map_protection_concerns_to_unhcr_codes - - searchable do - boolean :unhcr_export_opt_in - end end def map_protection_concerns_to_unhcr_codes diff --git a/app/models/concerns/workflow.rb b/app/models/concerns/workflow.rb index 6efec42ad2..caf958f813 100644 --- a/app/models/concerns/workflow.rb +++ b/app/models/concerns/workflow.rb @@ -17,16 +17,12 @@ module Workflow WORKFLOW_ASSESSMENT = 'assessment' LOOKUP_RESPONSE_TYPES = 'lookup-service-response-type' + LOOKUP_WORKFLOW = 'lookup-workflow' included do store_accessor :data, :workflow alias_method :workflow_status, :workflow - searchable do - string :workflow_status, as: 'workflow_status_sci' - string :workflow, as: 'workflow_sci' - end - before_create :set_workflow_new before_save :calculate_workflow end @@ -90,35 +86,35 @@ def workflow_assessment? # Class methods module ClassMethods - def workflow_statuses(modules = [], lookups = nil) - lookup = lookup_response_types(lookups) + def workflow_statuses(modules = [], _lookups = nil) + lookups_grouped = Lookup.group_by_unique_id([LOOKUP_RESPONSE_TYPES, LOOKUP_WORKFLOW]) I18n.available_locales.map do |locale| - { locale => status_list(locale, modules, lookup) } + { locale => status_list(locale, modules, lookups_grouped) } end.inject(&:merge) end - def status_list(locale, modules, lookup) + def status_list(locale, modules, lookups) status_list = [] status_list << workflow_key_value(WORKFLOW_NEW, locale) status_list << workflow_key_value(WORKFLOW_REOPENED, locale) - workflow_assessment(status_list, locale, modules) - workflow_case_plan(status_list, locale, modules) - status_list += lookup&.enabled_values(locale) || [] + workflow_assessment(status_list, locale, modules, lookups) + workflow_case_plan(status_list, locale, modules, lookups) + status_list += lookups&.[](Workflow::LOOKUP_RESPONSE_TYPES)&.[](locale.to_s) || [] workflow_service_implemented(status_list, locale, modules) status_list << workflow_key_value(WORKFLOW_CLOSED, locale) end - def workflow_assessment(status_list, locale, modules) + def workflow_assessment(status_list, locale, modules, lookups) return unless modules&.any?(&:use_workflow_assessment) - status_list << workflow_key_value(WORKFLOW_ASSESSMENT, locale) + status_list << workflow_entry(WORKFLOW_ASSESSMENT, locale, lookups) end - def workflow_case_plan(status_list, locale, modules) + def workflow_case_plan(status_list, locale, modules, lookups) return unless modules&.any?(&:use_workflow_case_plan) - status_list << workflow_key_value(WORKFLOW_CASE_PLAN, locale) + status_list << workflow_entry(WORKFLOW_CASE_PLAN, locale, lookups) end def workflow_service_implemented(status_list, locale, modules) @@ -127,11 +123,6 @@ def workflow_service_implemented(status_list, locale, modules) status_list << workflow_key_value(WORKFLOW_SERVICE_IMPLEMENTED, locale) end - def lookup_response_types(lookups = nil) - lookup = lookups&.find { |lkp| lkp.unique_id == LOOKUP_RESPONSE_TYPES } - lookup || Lookup.find_by(unique_id: LOOKUP_RESPONSE_TYPES) - end - private def workflow_key_value(status, locale = I18n.locale) @@ -140,5 +131,14 @@ def workflow_key_value(status, locale = I18n.locale) 'display_text' => I18n.t("case.workflow.#{status}", locale:) } end + + def value_from_lookup(status, lookups, locale = I18n.locale) + lookups&.[](Workflow::LOOKUP_WORKFLOW)&.[](locale.to_s)&.find { |lkp| lkp['id'] == status } + end + + # TODO: This can be use with the other workflow states (WORKFLOW_NEW, WORKFLOW_REOPENED, WORKFLOW_CLOSED) + def workflow_entry(status, locale, lookups) + value_from_lookup(status, lookups, locale) || workflow_key_value(status, locale) + end end end diff --git a/app/models/duplicate_bulk_export.rb b/app/models/duplicate_bulk_export.rb index 13822008a2..49df3af876 100644 --- a/app/models/duplicate_bulk_export.rb +++ b/app/models/duplicate_bulk_export.rb @@ -10,7 +10,7 @@ class DuplicateBulkExport < BulkExport def process_records_in_batches(batch_size = 500, &) return yield([]) unless duplicate_field_name - batched_duplicate_values = search_for_duplicate_values.in_groups_of(FACET_BATCH_SIZE, false) + batched_duplicate_values = duplicate_values.in_groups_of(FACET_BATCH_SIZE, false) return yield([]) unless batched_duplicate_values.present? batched_duplicate_values.each do |values| @@ -18,68 +18,40 @@ def process_records_in_batches(batch_size = 500, &) end end - # rubocop:disable Metrics/MethodLength - # rubocop:disable Metrics/AbcSize - # Custom Solr queries are long - def search_for_duplicate_values - result = model_class.search do - with(:status, Record::STATUS_OPEN) - with(:record_state, true) + def duplicate_values + model_class.connection.select_all(duplicate_field_query.to_sql).rows.flatten + end - adjust_solr_params do |params| - params['facet'] = 'true' - params['facet.field'] = [solr_duplicate_field_name] - params['facet.limit'] = '-1' - params['facet.method'] = 'fcs' - params['facet.threads'] = '-1' - params["f.#{solr_duplicate_field_name}.facet.mincount"] = '2' - end - end.facet_response['facet_fields'][solr_duplicate_field_name] + def duplicate_field_query + status_filter = SearchFilters::TextValue.new(field_name: 'status', value: Record::STATUS_OPEN) + state_filter = SearchFilters::BooleanValue.new(field_name: 'record_state', value: true) + sanitized_field_name = ActiveRecord::Base.sanitize_sql_array(['data->>?', duplicate_field_name]) - result.select { |value| value.is_a?(String) } + model_class.select(sanitized_field_name).where(status_filter.query).where(state_filter.query) + .group(sanitized_field_name) + .having(ActiveRecord::Base.sanitize_sql_array(['COUNT(data->>?) > 1', duplicate_field_name])) end - # rubocop:enable Metrics/MethodLength - # rubocop:enable Metrics/AbcSize def search_for_duplicate_records(values, batch_size) page = 1 sort = order || { national_id_no: :asc } + search_filters = filters_for_duplicates(duplicate_field_name, values) loop do - filters = filters_for_duplicates(duplicate_field_name, values) - results = SearchService.search(model_class, filters:, query:, - pagination: { page:, per_page: batch_size }, sort:).results - yield(results) - # Set again the values of the pagination variable because the method modified the variable. - page = results.next_page - break if page.nil? + result = search_records(search_filters, batch_size, page, sort) + break if result.records.blank? + + exporter.single_record_export = result.total == 1 + yield(result.records) + page += 1 end end def filters_for_duplicates(field_name, duplicates) - [SearchFilters::ValueList.new(field_name:, values: duplicates)] + [SearchFilters::TextList.new(field_name:, values: duplicates)] end def duplicate_field_name - return @duplicate_field_name if @duplicate_field_name - - @duplicate_field_name = SystemSettings.current&.duplicate_export_field - if @duplicate_field_name.blank? - - # NOTE: national_id_no is indexed as: national_id_no_text, national_id_no_filterable and national_id_no_sortable - # When a duplicate export is performed by default the national_id_no_text is used to get the duplicates, - # that field breaks dashes in separate parts, for example: abc-123 is searched as [abc, 123]. - # Here we use _filterable fields to avoid that behavior. - @duplicate_field_name = 'national_id_no_filterable' - elsif model_class.filterable_id_fields.include?(@duplicate_field_name) - @duplicate_field_name = "#{@duplicate_field_name}_filterable" - end - - @duplicate_field_name - end - - def solr_duplicate_field_name - @solr_duplicate_field_name ||= - SolrUtils.indexed_field_name(record_type, duplicate_field_name) + @duplicate_field_name ||= SystemSettings.current&.duplicate_export_field end def exporter_type diff --git a/app/models/export_configuration.rb b/app/models/export_configuration.rb index e4f190b439..adf77fd35e 100644 --- a/app/models/export_configuration.rb +++ b/app/models/export_configuration.rb @@ -10,21 +10,10 @@ class ExportConfiguration < ApplicationRecord localize_properties :name validate :valid_record_type - validate :opt_out_field_exists def valid_record_type return true if %w[Child TracingRequest Incident].include?(record_type) errors.add(:record_type, I18n.t('errors.models.export_configuration.record_type')) end - - # If there is a consent field defined, make sure it is a valid property of the Record - def opt_out_field_exists - return true if opt_out_field.blank? - - klass = Object.const_get(record_type) - return true if klass.method_defined?(opt_out_field) - - errors.add(:opt_out_field, I18n.t('errors.models.export_configuration.opt_out_field_does_not_exist')) - end end diff --git a/app/models/exporters/configurable_exporter.rb b/app/models/exporters/configurable_exporter.rb index a3cd72268c..0a133187ab 100644 --- a/app/models/exporters/configurable_exporter.rb +++ b/app/models/exporters/configurable_exporter.rb @@ -45,7 +45,7 @@ def opt_out_property_keys def opting_out?(record) return false if @export_configuration.blank? || @export_configuration.opt_out_field.blank? - record.try(:send, @export_configuration.opt_out_field) == true + record&.data&.[](@export_configuration.opt_out_field) == true end def write_header(rows) diff --git a/app/models/exporters/field_subreport_exporter.rb b/app/models/exporters/field_subreport_exporter.rb new file mode 100644 index 0000000000..391bc30f87 --- /dev/null +++ b/app/models/exporters/field_subreport_exporter.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2024 UNICEF. All rights reserved. + +# Concern for Record Workflow Subreport Exporter +class Exporters::FieldSubreportExporter < Exporters::SubreportExporter + include Exporters::Concerns::RecordFilterInsightParams + + def field + raise NotImplementedError + end + + def field_lookup_id + raise NotImplementedError + end + + def reporting_locations_field? + false + end + + def params_list + view_by_param + date_range_param + date_range_values_param + filter_by_date_param + status_param + + field_param + by_param + user_group_param + agency_param + end + + def field_param + return [] unless field_filter.present? + + [ + formats[:bold_blue], "#{I18n.t("managed_reports.filter_by.#{field}", locale:)}: ", + formats[:black], "#{field_display_text} / " + ] + end + + def location_value + Location.get_by_location_code(field_filter.value)&.placename_i18n&.dig(locale) || field_filter.value + end + + def lookup_value + lookup_values = Lookup.values(field_lookup_id, nil, locale:) + + lookup_values&.filter { |f| field_filter.values.include? f['id'] } + &.map { |f| f['display_text'] } + &.join(', ') || field_filter.values + end + + def field_display_text + return location_value if reporting_locations_field? + + lookup_value + end + + def field_filter + managed_report.filters.find { |filter| filter.present? && filter.field_name == field } + end +end diff --git a/app/models/exporters/followups_subreport_exporter.rb b/app/models/exporters/followups_subreport_exporter.rb new file mode 100644 index 0000000000..593be752ce --- /dev/null +++ b/app/models/exporters/followups_subreport_exporter.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2024 UNICEF. All rights reserved. + +# Concern for Followups Subreport Exporter +class Exporters::FollowupsSubreportExporter < Exporters::FieldSubreportExporter + def field + 'followup_type' + end + + def field_lookup_id + 'lookup-followup-type' + end +end diff --git a/app/models/exporters/form_exporter.rb b/app/models/exporters/form_exporter.rb index 1246b2a437..51869c2556 100644 --- a/app/models/exporters/form_exporter.rb +++ b/app/models/exporters/form_exporter.rb @@ -220,7 +220,7 @@ def field_options(field) def field_options_select(field) return I18n.t('exports.forms.options.country', locale:) if lookup_country?(field) - %w[Location Agency User ReportingLocation].each do |option| + %w[Location Agency User ReportingLocation LinkedIncidents].each do |option| next unless field.option_strings_source&.start_with?(option) return I18n.t("exports.forms.options.#{option.downcase}", locale:) diff --git a/app/models/exporters/incident_recorder_exporter.rb b/app/models/exporters/incident_recorder_exporter.rb index 0f54355c7f..8318ef537f 100644 --- a/app/models/exporters/incident_recorder_exporter.rb +++ b/app/models/exporters/incident_recorder_exporter.rb @@ -98,13 +98,14 @@ def initialize_workbook(exporter) end def initialize_fields - Field.where( + Field.joins(:form_section).where( name: %w[service_referred_from service_safehouse_referral perpetrator_relationship perpetrator_occupation incidentid_ir survivor_code date_of_first_report incident_date date_of_birth ethnicity country_of_origin maritial_status displacement_status disability_type unaccompanied_separated_status displacement_incident incident_location_type incident_camp_town gbv_sexual_violence_type harmful_traditional_practice goods_money_exchanged abduction_status_time_of_incident - gbv_reported_elsewhere gbv_previous_incidents incident_timeofday consent_reporting] + gbv_reported_elsewhere gbv_previous_incidents incident_timeofday consent_reporting], + form_section: PrimeroModule.gbv.form_sections ).inject({}) { |acc, field| acc.merge(field.name => field) } end @@ -381,7 +382,8 @@ def number_primary_perpetrators_props if from_ir.present? calculated.present? && calculated > 1 ? calculated : from_ir else - calculated + default_text = I18n.t('exports.incident_recorder_xls.number_primary_perpetrators.more_than_three') + calculated > 3 ? default_text : calculated end end end diff --git a/app/models/exporters/incidents_subreport_exporter.rb b/app/models/exporters/incidents_subreport_exporter.rb index fd6994c3f2..caa07e380b 100644 --- a/app/models/exporters/incidents_subreport_exporter.rb +++ b/app/models/exporters/incidents_subreport_exporter.rb @@ -4,7 +4,7 @@ # Class to export the Incidents Subreport class Exporters::IncidentsSubreportExporter < Exporters::SubreportExporter - MERGED_INDICATORS = %w[total gbv_sexual_violence gbv_previous_incidents].freeze + MERGED_INDICATORS = %w[total gbv_previous_incidents].freeze def write_export write_header diff --git a/app/models/exporters/mrm_violation_exporter.rb b/app/models/exporters/mrm_violation_exporter.rb index ff5e56b32b..62ce016245 100644 --- a/app/models/exporters/mrm_violation_exporter.rb +++ b/app/models/exporters/mrm_violation_exporter.rb @@ -74,10 +74,21 @@ def complete def export(records) violations = Violation.where(incident_id: records).order(:incident_id, :id) + build_worksheets_with_headers write_violations(violations) write_violation_associations(violations) end + def build_worksheets_with_headers + return if worksheets.present? + + write_worksheet_headers(2, 4, :violations, I18n.t('incident.violation.title'), all_shared_violation_fields) + association_forms.each do |form| + association_form_fields = exportable_form_fields(form).sort_by(&:order) + write_worksheet_headers(1, 6, form.unique_id, form.name(locale), association_form_fields) + end + end + def establish_export_constraints return unless setup_export_constraints? && user.present? @@ -165,7 +176,6 @@ def exportable_subform_fields(subform) end def write_violations(violations) - write_worksheet_headers(2, 4, :violations, I18n.t('incident.violation.title'), all_shared_violation_fields) @record_row = worksheets[:violations][:row] write_violations_data(violations, worksheets[:violations][:worksheet]) worksheets[:violations][:row] = @record_row @@ -185,7 +195,7 @@ def write_worksheet_headers(initial_row, initial_column, id, name, fields) write_association_header(worksheet, id) if id != :violations write_field_headers(worksheet, fields) write_violation_headers_by_type(worksheet) if id == :violations - self.worksheets = { id => { worksheet:, row: id == :violations ? 3 : 2 } } + worksheets[id] = { worksheet:, row: id == :violations ? 3 : 2 } end def write_association_header(worksheet, id) @@ -391,7 +401,6 @@ def select_value(value, field) def write_violation_associations(violations) association_forms.each do |form| association_form_fields = exportable_form_fields(form).sort_by(&:order) - write_worksheet_headers(1, 6, form.unique_id, form.name(locale), association_form_fields) write_associations(violations, form, association_form_fields) end end diff --git a/app/models/exporters/protection_concerns_subreport_exporter.rb b/app/models/exporters/protection_concerns_subreport_exporter.rb new file mode 100644 index 0000000000..e65bc54290 --- /dev/null +++ b/app/models/exporters/protection_concerns_subreport_exporter.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2024 UNICEF. All rights reserved. + +# Concern for Protection Concerns Subreport Exporter +class Exporters::ProtectionConcernsSubreportExporter < Exporters::FieldSubreportExporter + def field + 'protection_concerns' + end + + def field_lookup_id + 'lookup-protection-concerns' + end +end diff --git a/app/models/exporters/reporting_locations_subreport_exporter.rb b/app/models/exporters/reporting_locations_subreport_exporter.rb new file mode 100644 index 0000000000..20b3136180 --- /dev/null +++ b/app/models/exporters/reporting_locations_subreport_exporter.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2024 UNICEF. All rights reserved. + +# Concern for Reporting Locations Subreport Exporter +class Exporters::ReportingLocationsSubreportExporter < Exporters::FieldSubreportExporter + def field + 'location' + end + + def reporting_locations_field? + true + end + + def field_lookup_id + '' + end +end diff --git a/app/models/exporters/ruby_config_exporter.rb b/app/models/exporters/ruby_config_exporter.rb index 951ca42018..d87e364896 100644 --- a/app/models/exporters/ruby_config_exporter.rb +++ b/app/models/exporters/ruby_config_exporter.rb @@ -44,9 +44,9 @@ def file_for(config_name, config_objects = nil) def export # TODO: Location, PrimeroModule, PrimeroProgram, SystemSettings, ExportConfiguration, IdentityProvider - %w[Agency Lookup Report UserGroup Role ContactInformation].each do |config_name| - config_objects = Object.const_get(config_name).all.map(&:configuration_hash) - export_config_objects(config_name, config_objects) + [Agency, Lookup, Report, UserGroup, Role, ContactInformation].each do |config| + config_objects = config.all.map(&:configuration_hash) + export_config_objects(config.name, config_objects) end export_forms end diff --git a/app/models/exporters/services_subreport_exporter.rb b/app/models/exporters/services_subreport_exporter.rb new file mode 100644 index 0000000000..a6f664a34c --- /dev/null +++ b/app/models/exporters/services_subreport_exporter.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2024 UNICEF. All rights reserved. + +# Concern for Services Subreport Exporter +class Exporters::ServicesSubreportExporter < Exporters::FieldSubreportExporter + def field + 'service_type' + end + + def field_lookup_id + 'lookup-service-type' + end +end diff --git a/app/models/family.rb b/app/models/family.rb index adce402a9f..0d62c0dcdb 100644 --- a/app/models/family.rb +++ b/app/models/family.rb @@ -13,6 +13,7 @@ class Family < ApplicationRecord include Attachable include EagerLoadable include LocationCacheable + include PhoneticSearchable store_accessor( :data, @@ -30,28 +31,15 @@ def filterable_id_fields %w[family_id short_id family_number] end - def quicksearch_fields - filterable_id_fields + %w[family_name] - end - - def sortable_text_fields - %w[short_id] - end - def summary_field_names common_summary_fields + %w[ family_registration_date family_id_display family_name family_number module_id family_location_current ] end - end - searchable do - date :family_registration_date - %w[id status].each { |f| string(f, as: "#{f}_sci") } - filterable_id_fields.each { |f| string("#{f}_filterable", as: "#{f}_filterable_sci") { data[f] } } - quicksearch_fields.each { |f| text_index(f) } - sortable_text_fields.each { |f| string("#{f}_sortable", as: "#{f}_sortable_sci") { data[f] } } - string :family_name, multiple: true + def phonetic_field_names + %w[family_name] + end end alias super_defaults defaults diff --git a/app/models/field.rb b/app/models/field.rb index db6938c1a0..7e11147f4c 100644 --- a/app/models/field.rb +++ b/app/models/field.rb @@ -92,30 +92,6 @@ def fields_for_record(parent_form, is_subform = false) Field.joins(:form_section).where(form_sections: { parent_form:, is_nested: is_subform }) end - def all_searchable_date_field_names(parent_form = 'case') - fields_for_record(parent_form).where(type: [Field::DATE_FIELD, Field::DATE_RANGE], date_include_time: false) - .pluck(:name) - end - - def all_searchable_date_time_field_names(parent_form = 'case') - fields_for_record(parent_form).where(type: [Field::DATE_FIELD, Field::DATE_RANGE], date_include_time: true) - .pluck(:name) - end - - def all_searchable_boolean_field_names(parent_form = 'case') - fields_for_record(parent_form).where(type: Field::TICK_BOX).pluck(:name) - end - - def all_filterable_option_field_names(parent_form = 'case') - # TODO: TEXT_FIELD is being indexed for exact search? Makes sense for docuemt identifiers, but not much else. - fields_for_record(parent_form).where(type: [RADIO_BUTTON, SELECT_BOX], multi_select: false) - .pluck(:name) - end - - def all_filterable_multi_field_names(parent_form = 'case') - fields_for_record(parent_form).where(type: Field::SELECT_BOX, multi_select: true).pluck(:name) - end - def all_filterable_numeric_field_names(parent_form = 'case') fields_for_record(parent_form).where(type: Field::NUMERIC_FIELD).pluck(:name) end @@ -132,23 +108,23 @@ def find_by_name(field_names) field_names = [field_names] unless field_names.is_a?(Array) result = where(name: field_names) remainder = field_names - result.map(&:name) - remainder = remainder.select { |field_name| name_with_admin_level?(field_name) } + remainder = remainder.select { |field_name| location_prefix?(field_name) } return result unless remainder.present? result + find_as_location_fields(remainder) end def find_as_location_fields(field_names) - field_names = field_names.map { |field_name| remove_admin_level_from_name(field_name) } + field_names = field_names.map { |field_name| remove_location_parts(field_name) } where(name: field_names, option_strings_source: %w[Location ReportingLocation]) end - def name_with_admin_level?(field_name) - ADMIN_LEVEL_REGEXP.match?(field_name) + def location_prefix?(field_name) + field_name.starts_with?('loc:') end - def remove_admin_level_from_name(field_name) - field_name.gsub(ADMIN_LEVEL_REGEXP, '') + def remove_location_parts(field_name) + field_name.gsub('loc:', '').gsub(ADMIN_LEVEL_REGEXP, '') end end diff --git a/app/models/filter.rb b/app/models/filter.rb index a49f21c59a..5096fbeaa9 100644 --- a/app/models/filter.rb +++ b/app/models/filter.rb @@ -91,7 +91,7 @@ class Filter < ValueObject ) CURRENT_LOCATION = Filter.new( name: 'cases.filter_by.current_location', - field_name: 'location_current', + field_name: 'loc:location_current', option_strings_source: 'Location', type: 'multi_select' ) @@ -104,7 +104,7 @@ class Filter < ValueObject REPORTING_LOCATION = lambda do |params| Filter.new( name: "location.base_types.#{params[:labels]&.first}", - field_name: "#{params[:field]}#{params[:admin_level]}", + field_name: "loc:#{params[:field]}#{params[:admin_level]}", option_strings_source: 'ReportingLocation', type: 'multi_select' ) @@ -166,7 +166,7 @@ class Filter < ValueObject ) INCIDENT_LOCATION = Filter.new( name: 'incidents.filter_by.incident_location', - field_name: 'incident_location', + field_name: 'loc:incident_location', option_strings_source: 'Location', type: 'multi_select' ) @@ -193,7 +193,7 @@ class Filter < ValueObject ) SEPARATION_LOCATION = Filter.new( name: 'tracing_requests.filter_by.location_separation', - field_name: 'location_separation', + field_name: 'loc:location_separation', option_strings_source: 'Location', type: 'multi_select' ) @@ -204,17 +204,8 @@ class Filter < ValueObject ) INQUIRY_DATE = Filter.new( name: 'tracing_requests.filter_by.by_date', - field_name: 'inquiry_date', - options: I18n.available_locales.map do |locale| - { - locale => [ - { - id: 'inquiry_date', - display_name: I18n.t('tracing_requests.selectable_date_options.inquiry_date', locale:) - } - ] - } - end.inject(&:merge) + field_name: 'tracing_requests_by_date', + type: 'dates' ) DATE_REGISTRY = Filter.new( name: 'registry_records.filter_by.by_date', @@ -361,7 +352,7 @@ class Filter < ValueObject FAMILY_LOCATION_CURRENT = Filter.new( name: 'families.filter_by.current_location', - field_name: 'family_location_current', + field_name: 'loc:family_location_current', option_strings_source: 'Location', type: 'multi_select' ) @@ -685,7 +676,8 @@ def owned_by_groups_options(_opts = {}) def cases_by_date_options(opts = {}) self.options = I18n.available_locales.map do |locale| locale_options = [registration_date_options(locale), assessment_requested_on_options(locale), - date_case_plan_options(locale), date_closure_options(locale)] + date_case_plan_options(locale), date_closure_options(locale), followup_date_options(locale), + date_reunification_options(locale), tracing_date_options(locale), service_date_options(locale)] date_label = opts[:user].module?(PrimeroModule::GBV) ? 'created_at' : 'date_of_creation' locale_options << created_at_options(locale, date_label) { locale => locale_options } @@ -727,6 +719,34 @@ def created_at_options(locale, date_label) } end + def followup_date_options(locale) + { + id: 'followup_dates', + display_name: I18n.t('children.selectable_date_options.followup_date', locale:) + } + end + + def date_reunification_options(locale) + { + id: 'reunification_dates', + display_name: I18n.t('children.selectable_date_options.date_reunification', locale:) + } + end + + def tracing_date_options(locale) + { + id: 'tracing_dates', + display_name: I18n.t('children.selectable_date_options.tracing_date', locale:) + } + end + + def service_date_options(locale) + { + id: 'service_implemented_day_times', + display_name: I18n.t('children.selectable_date_options.service_implemented_day_time', locale:) + } + end + def incidents_by_date_options(opts = {}) self.options = I18n.available_locales.map do |locale| locale_options = [] @@ -768,6 +788,16 @@ def incident_date_derived_options(locale) } end + def tracing_requests_by_date_options(_opts = {}) + self.options = I18n.available_locales.map do |locale| + locale_options = [{ + id: 'inquiry_date', + display_name: I18n.t('tracing_requests.selectable_date_options.inquiry_date', locale:) + }] + { locale => locale_options } + end.inject(&:merge) + end + def registry_records_by_date_options(_opts = {}) self.options = I18n.available_locales.map do |locale| locale_options = [{ @@ -807,7 +837,7 @@ def with_options_for(user, record_type) approval_status_options elsif %w[ owned_by workflow owned_by_agency_id age owned_by_groups cases_by_date incidents_by_date - registry_records_by_date individual_age families_by_date + registry_records_by_date individual_age families_by_date tracing_requests_by_date ].include? field_name opts = { user:, record_type: } send("#{field_name}_options", opts) diff --git a/app/models/flag.rb b/app/models/flag.rb index fec77aca9a..f97064cebb 100644 --- a/app/models/flag.rb +++ b/app/models/flag.rb @@ -3,10 +3,7 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. # Represents actions to flag a record -# rubocop:disable Metrics/ClassLength class Flag < ApplicationRecord - include Indexable - EVENT_FLAG = 'flag' EVENT_UNFLAG = 'unflag' @@ -25,17 +22,22 @@ class Flag < ApplicationRecord } scope :by_record_associated_user, lambda { |params| + owner_json = params[:owner].to_json join_record(params[:type]).where( - "(data -> 'assigned_user_names' ? :username) OR (data -> 'owned_by' ? :username)", username: params[:owner] + "data %s '$[*] %s (@.assigned_user_names == %s || @.owned_by == %s)'", '@?', '?', owner_json, owner_json ) } scope :by_record_associated_groups, lambda { |params| - join_record(params[:type]).where("(data -> 'associated_user_groups' ?| array[:group])", group: params[:group]) + groups = params[:group].map do |group| + ActiveRecord::Base.sanitize_sql_for_conditions(['@ == %s', group.to_json]) + end.join('||') + + join_record(params[:type]).where("data %s '$.associated_user_groups %s (%s)'", '@?', '?', groups) } scope :by_record_agency, lambda { |params| - join_record(params[:type]).where("(data -> 'owned_by_agency_id' ? :agency)", agency: params[:agency]) + join_record(params[:type]).where("data %s '$.owned_by_agency_id %s (@ == %s)'", '@?', '?', params[:agency].to_json) } validates :message, presence: { message: 'errors.models.flags.message' } @@ -43,72 +45,6 @@ class Flag < ApplicationRecord after_create :flag_history after_update :unflag_history - after_save :index_record - - # rubocop:disable Metrics/BlockLength - searchable do - date :flag_date, stored: true do - date.present? ? date : nil - end - time :flag_created_at, stored: true do - created_at.present? ? created_at : nil - end - string :flag_message, stored: true do - message - end - string :flag_unflag_message, stored: true do - unflag_message - end - string :flag_flagged_by, stored: true do - flagged_by - end - string :flag_flagged_by_module, stored: true do - record.module_id - end - boolean :flag_is_removed, stored: true do - removed ? true : false - end - boolean :flag_system_generated_followup, stored: true do - system_generated_followup - end - string :flag_record_id, stored: true do - record_id - end - string :flag_record_type, stored: true do - record_type.underscore.downcase - end - string :flag_record_short_id, stored: true do - record.short_id - end - string :flag_child_name, stored: true do - record.try(:name) - end - string :flag_hidden_name, stored: true do - record.try(:hidden_name) - end - string :flag_module_id, stored: true do - record.module_id - end - string :flag_incident_date_of_first_report, stored: true do - record.try(:date_of_first_report) - end - string :flag_record_owner, stored: true do - record.owned_by - end - string :flag_groups_owner, stored: true, multiple: true do - record.owned_by_groups - end - string :flag_associated_groups, stored: true, multiple: true do - record.associated_user_groups - end - string :flag_agency_id_owner, stored: true, multiple: true do - record.owned_by_agency_id - end - string :flag_associated_agencies, stored: true, multiple: true do - record.associated_user_agencies - end - end - # rubocop:enable Metrics/BlockLength class << self def by_owner(query_scope, active_only, record_types, flagged_by) @@ -140,7 +76,7 @@ def find_by_owner(scope_to_use, active_only, record_types, flagged_by, params = flags = [] record_types.each do |record_type| params[:type] = record_type - f = send(scope_to_use, params).includes(:record).where(where_params(flagged_by, active_only)) + f = send(scope_to_use, params).includes(:record).where(where_params(flagged_by, active_only)).order(date: :desc) flags << f end flags.flatten @@ -165,10 +101,6 @@ def unflag_history update_flag_history(EVENT_UNFLAG, unflagged_by) end - def index_record - Sunspot.index(record) if record - end - private def update_flag_history(event, user_name) @@ -182,4 +114,3 @@ def update_flag_history(event, user_name) ) end end -# rubocop:enable Metrics/ClassLength diff --git a/app/models/importers/csv_record_importer.rb b/app/models/importers/csv_record_importer.rb index 81efb3392a..e6e4aaa671 100644 --- a/app/models/importers/csv_record_importer.rb +++ b/app/models/importers/csv_record_importer.rb @@ -92,7 +92,7 @@ def reindex_records location_service = LocationService.new(true) record_class.all.find_in_batches(batch_size:) do |records| records.each { |r| r.location_service = location_service } unless record_class == Trace - Sunspot.index(records) + Sunspot.index(records) if Rails.configuration.solr_enabled end end diff --git a/app/models/incident.rb b/app/models/incident.rb index eb7ac34dc0..44a86887f1 100644 --- a/app/models/incident.rb +++ b/app/models/incident.rb @@ -20,6 +20,7 @@ class Incident < ApplicationRecord include GenderBasedViolence include MonitoringReportingMechanism include LocationCacheable + include PhoneticSearchable store_accessor( :data, @@ -30,26 +31,20 @@ class Incident < ApplicationRecord :health_medical_referral_subform_section, :psychosocial_counseling_services_subform_section, :legal_assistance_services_subform_section, :police_or_other_type_of_security_services_subform_section, :livelihoods_services_subform_section, :child_protection_services_subform_section, :violation_category, - :incident_date_end, :is_incident_date_range + :incident_date_end, :is_incident_date_range, :incident_date_derived ) - has_many :violations, dependent: :destroy, inverse_of: :incident - has_many :perpetrators, through: :violations - has_many :individual_victims, through: :violations - has_many :sources, through: :violations + DEFAULT_ALERT_FORM_UNIQUE_ID = 'incident_from_case' + belongs_to :case, foreign_key: 'incident_case_id', class_name: 'Child', optional: true - after_save :save_violations_and_associations class << self alias super_new_with_user new_with_user def new_with_user(user, data = {}) - violations_params = violations_data(Violation::TYPES, data) - associations_params = violations_data(Violation::MRM_ASSOCIATIONS_KEYS, data) new_incident = super_new_with_user(user, data).tap do |incident| incident.incident_case_id ||= incident.data.delete('incident_case_id') end - new_incident.build_or_update_violations(violations_params) - new_incident.build_violations_associations(associations_params) + new_incident.build_or_update_violations_and_associations(data) new_incident end @@ -57,8 +52,8 @@ def filterable_id_fields %w[incident_id incident_code monitor_number survivor_code incidentid_ir short_id] end - def quicksearch_fields - filterable_id_fields + %w[super_incident_name incident_description individual_ids] + def phonetic_field_names + %w[super_incident_name incident_description] end def summary_field_names @@ -71,10 +66,6 @@ def summary_field_names ] end - def sortable_text_fields - %w[short_id] - end - def minimum_reportable_fields { 'boolean' => %w[record_state], @@ -85,18 +76,9 @@ def minimum_reportable_fields end end - searchable do - date :incident_date_derived - date :date_of_first_report - %w[id status].each { |f| string(f, as: "#{f}_sci") } - filterable_id_fields.each { |f| string("#{f}_filterable", as: "#{f}_filterable_sci") { data[f] } } - quicksearch_fields.each { |f| text_index(f) } - sortable_text_fields.each { |f| string("#{f}_sortable", as: "#{f}_sortable_sci") { data[f] } } - end - after_initialize :set_unique_id before_save :copy_from_case - before_save :update_violations + before_save :calculate_incident_date_derived # TODO: Reconsider whether this is necessary. # We will only be creating an incident from a case using a special business logic that # will certainly trigger a reindex on the case @@ -104,7 +86,7 @@ def minimum_reportable_fields after_create :add_alert_on_case, :add_case_history def index_record - Sunspot.index(self.case) if self.case.present? + Sunspot.index(self.case) if Rails.configuration.solr_enabled && self.case.present? end alias super_defaults defaults @@ -128,8 +110,10 @@ def set_unique_id self.unique_id = id end - def incident_date_derived - incident_date || date_of_incident_from || date_of_incident + def calculate_incident_date_derived + self.incident_date_derived = incident_date || date_of_incident_from || date_of_incident + + incident_date_derived end def case_id_display @@ -139,9 +123,7 @@ def case_id_display end def add_alert_on_case - return unless alerts_on_change.present? - - form_name = alerts_on_change[ALERT_INCIDENT] + form_name = alert_form_unique_id return unless form_name.present? return unless self.case.present? && created_by != self.case.owned_by @@ -182,127 +164,10 @@ def new_incident_values alias super_update_properties update_properties def update_properties(user, data) - build_or_update_violations(Incident.violations_data(Violation::TYPES, data)) - build_violations_associations(Incident.violations_data(Violation::MRM_ASSOCIATIONS_KEYS, data)) + build_or_update_violations_and_associations(data) super_update_properties(user, data) end - def self.violations_data(data_keys, data) - return {} unless data - - data_keys.reduce({}) do |acc, elem| - next acc unless data[elem].present? - - acc.merge(elem => data.delete(elem)) - end - end - - def build_or_update_violations(violation_objects_data) - return unless violation_objects_data.present? - - @violations_to_save = violation_objects_data.each_with_object([]) do |(type, violations_by_type), acc| - violations_by_type.each do |violation_data| - acc << Violation.build_record(type, violation_data, self) - end - acc - end - end - - def build_violations_associations(violation_associations_data) - return unless violation_associations_data.present? - - @associations_to_save = violation_associations_data.each_with_object([]) do |(type, associations_data), acc| - association_object = type.classify.constantize - associations_data.each do |association_data| - acc << association_object.build_record(association_data) - end - acc - end - end - - def save_violations - return unless @violations_to_save - - @violations_to_save.each(&:save!) - end - - def save_violations_associations - return unless @associations_to_save - - @associations_to_save.each do |association| - if association.violations_ids.present? - association.violations = violations_for_associated(association.violations_ids) - end - next if association.violations.blank? - - association.save! - end - end - - def save_violations_and_associations - save_violations - save_violations_associations - reindex_violations_and_associations if @violations_to_save.present? || @associations_to_save.present? - end - - # TODO: This method will trigger queries to reload the violations and associations in order to index the latest data - def reindex_violations_and_associations - association_classes = association_classes_to_save - - violations.reload if @violations_to_save.present? || association_classes.include?(Source) - - if association_classes.present? - individual_victims.reload if association_classes.include?(IndividualVictim) - perpetrators.reload if association_classes.include?(Perpetrator) - end - - Sunspot.index(self) - end - - def association_classes_to_save - return unless @associations_to_save - - @associations_to_save.map(&:class).uniq.compact - end - - def associations_as_data(_current_user) - mrm_associations = associations_as_data_keys.to_h { |value| [value, []] } - - @associations_as_data ||= violations.reduce(mrm_associations) do |acc, violation| - acc[violation.type] << violation.data - acc.merge(violation.associations_as_data) do |_key, acc_value, violation_value| - (acc_value + violation_value).compact.uniq { |value| value['unique_id'] } - end - end - end - - def associations_as_data_keys - (Violation::TYPES + Violation::MRM_ASSOCIATIONS_KEYS) - end - - # Returns a list of Violations to be associated with - # Violation::MRM_ASSOCIATIONS_KEYS (perpetrators, victims...) on API update - def violations_for_associated(violations_ids) - ids = (violations_ids.is_a?(Array) ? violations_ids : [violations_ids]) - violations_result = [] - - if @violations_to_save.present? - violations_result += @violations_to_save.select { |violation| ids.include?(violation.id) } - end - violations_result += Violation.where(id: ids - violations_result.map(&:id)) - - violations_result - end - - def update_violations - should_update_violations = !new_record? && module_id == PrimeroModule::MRM && - (incident_date_changed? || incident_date_end_changed?) - - return unless should_update_violations - - violations.each(&:calculate_late_verifications) - end - def reporting_location_property 'incident_reporting_location_config' end @@ -310,5 +175,13 @@ def reporting_location_property def can_be_assigned? self.case.blank? end + + private + + def alert_form_unique_id + return unless alerts_on_change.present? + + alerts_on_change[ALERT_INCIDENT]&.form_section_unique_id || DEFAULT_ALERT_FORM_UNIQUE_ID + end end # rubocop:enable Metrics/ClassLength diff --git a/app/models/indicators/abstract_indicator.rb b/app/models/indicators/abstract_indicator.rb index f75a4ab4ba..2e6b5df4d4 100644 --- a/app/models/indicators/abstract_indicator.rb +++ b/app/models/indicators/abstract_indicator.rb @@ -16,144 +16,93 @@ class AbstractIndicator < ValueObject # scope_to_not_last_update: Records where the user was not last to update. # scope_to_transferred_groups: Records transferred to the user's user group. # exclude_zeros: Do not include result with zeroes. - # scope_to_user: Constraints the resuls to the user_query_scope. Userful for Faceted and Pivoted indicators. # rubocop:enable Style/ClassAndModuleChildren attr_accessor :name, :record_model, :scope, :scope_to_owner, :scope_to_referred, :scope_to_transferred, :scope_to_not_last_update, :scope_to_owned_by_groups, - :scope_to_transferred_groups, :exclude_zeros, :scope_to_user + :scope_to_transferred_groups class << self - def dawn_of_time - Time.zone.at(0) - end - - def recent_past - Time.zone.now - 10.days - end - - def last_week - { - from: 1.week.ago.beginning_of_week, - to: 1.week.ago.end_of_week - } - end - - def this_week - { - from: present.beginning_of_week, - to: present.end_of_week - } - end - - def present - Time.zone.now - end - def type 'indicator' end end - def query(_, _) - raise NotImplementedError - end - def facet_name name end - def stats_from_search(sunspot_search, user, managed_user_names = []) - owner = owner_from_search(sunspot_search) - rows = user_scoped_rows(sunspot_search.facet(facet_name).rows, user, managed_user_names) - rows.to_h do |row| - stat = { - 'count' => row.count, - 'query' => stat_query_strings(row, owner, user) - } - [row.value, stat] - end + def stat_query_strings(_, _, _) + raise NotImplementedError end - def user_scoped_rows(rows, user, managed_user_names) - return rows unless scope_to_user - - user_query_scope = user.user_query_scope(record_model) - return rows if user_query_scope == Permission::ALL - - rows.select do |row| - managed_user_names.include?(row.is_a?(Hash) ? row['value'] : row.value) - end + def stats_for_indicator(user) + indicator_filters = filters(user) + user_query_scope = user.record_query_scope(record_model, false) + managed_user_names = user.admin? ? [] : user.managed_user_names + write_stats_for_indicator(indicator_filters, user_query_scope, managed_user_names) end - def stat_query_strings(_, _, _) + def write_stats_for_indicator(_, _, _) raise NotImplementedError end + def query(indicator_filters, user_query_scope) + Search::SearchQuery.new(record_model).with_filters(indicator_filters).with_scope(user_query_scope).result.records + end + protected - # rubocop:disable Metrics/CyclomaticComplexity - # rubocop:disable Metrics/PerceivedComplexity - def owner_from_search(sunspot_search) - return unless scope_to_owner + def query_scope(user) + with_scope_to_owner(user) + + with_scope_to_owned_by_groups(user) + + with_scope_to_not_last_update(user) + + with_scope_referred_to_users(user) + + with_scope_transferred_to_users(user) + + with_scope_transferred_to_user_groups(user) + end - owner_query = sunspot_search&.query&.scope&.to_params - &.dig(:fq)&.find { |p| p.match(/owned_by/) } + def with_scope_to_owner(user) + return [] unless scope_to_owner - owner_query && SolrUtils.unescape(owner_query.split(':')[1]) + [SearchFilters::TextValue.new(field_name: 'owned_by', value: user.user_name)] end - # rubocop:enable Metrics/CyclomaticComplexity - # rubocop:enable Metrics/PerceivedComplexity - def scope_query_strings - scope&.map(&:to_s) || [] + def with_scope_to_owned_by_groups(user) + return [] unless scope_to_owned_by_groups + + [SearchFilters::TextList.new(field_name: 'owned_by_groups', values: user.user_group_unique_ids)] end - def owner_query_string(owner) - if owner.present? - ["owned_by=#{owner}"] - else - [] - end + def with_scope_to_not_last_update(user) + return [] unless scope_to_not_last_update + + [SearchFilters::TextValue.new(field_name: 'last_updated_by', value: user.user_name, not_filter: true)] end - def referred_query_string(user) - if user.present? && scope_to_referred - ["referred_users=#{user.user_name}"] - else - [] - end + def with_scope_referred_to_users(user) + return [] unless scope_to_referred + + [SearchFilters::TextValue.new(field_name: 'referred_users', value: user.user_name)] end - def transferred_query_string(user) - if user.present? && scope_to_transferred - ["transferred_to_users=#{user.user_name}"] - else - [] - end + def with_scope_transferred_to_users(user) + return [] unless scope_to_transferred + + [SearchFilters::TextValue.new(field_name: 'transferred_to_users', value: user.user_name)] end - def transferred_groups_query_string(user) - if user.present? && scope_to_transferred_groups - ["transferred_to_user_groups=#{user.user_group_unique_ids.join(',')}"] - else - [] - end + def with_scope_transferred_to_user_groups(user) + return [] unless scope_to_transferred_groups + + [SearchFilters::TextList.new(field_name: 'transferred_to_user_groups', values: user.user_group_unique_ids)] end - def owned_by_groups_query_string(user) - if user.present? && scope_to_owned_by_groups - ["owned_by_groups=#{user.user_group_unique_ids.join(',')}"] - else - [] - end + def filters(user) + query_scope(user) + scope end - def not_last_updated_query_string(user) - if user.present? && scope_to_not_last_update - ["not[last_updated_by]=#{user.user_name}"] - else - [] - end + def scope_query_strings + scope&.map(&:to_s) || [] end end end diff --git a/app/models/indicators/case.rb b/app/models/indicators/case.rb index 9bf4260c0b..90253546ff 100644 --- a/app/models/indicators/case.rb +++ b/app/models/indicators/case.rb @@ -9,18 +9,18 @@ module Indicators class Case # rubocop:enable Style/ClassAndModuleChildren OPEN_ENABLED = [ - SearchFilters::Value.new(field_name: 'record_state', value: true), - SearchFilters::Value.new(field_name: 'status', value: Record::STATUS_OPEN) + SearchFilters::BooleanValue.new(field_name: 'record_state', value: true), + SearchFilters::TextValue.new(field_name: 'status', value: Record::STATUS_OPEN) ].freeze CLOSED_ENABLED = [ - SearchFilters::Value.new(field_name: 'record_state', value: true), - SearchFilters::Value.new(field_name: 'status', value: Record::STATUS_CLOSED) + SearchFilters::BooleanValue.new(field_name: 'record_state', value: true), + SearchFilters::TextValue.new(field_name: 'status', value: Record::STATUS_CLOSED) ].freeze OPEN_CLOSED_ENABLED = [ - SearchFilters::Value.new(field_name: 'record_state', value: true), - SearchFilters::ValueList.new(field_name: 'status', values: [Record::STATUS_OPEN, Record::STATUS_CLOSED]) + SearchFilters::BooleanValue.new(field_name: 'record_state', value: true), + SearchFilters::TextList.new(field_name: 'status', values: [Record::STATUS_OPEN, Record::STATUS_CLOSED]) ].freeze OPEN = QueriedIndicator.new( @@ -35,7 +35,7 @@ class Case name: 'new_or_updated', record_model: Child, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'not_edited_by_owner', value: true) + SearchFilters::BooleanValue.new(field_name: 'not_edited_by_owner', value: true) ] ).freeze @@ -45,52 +45,51 @@ def self.closed_recently record_model: Child, queries: CLOSED_ENABLED + [ SearchFilters::DateRange.new( - field_name: 'date_closure', from: QueriedIndicator.recent_past, to: QueriedIndicator.present + field_name: 'date_closure', from: SearchFilters::DateRange.recent_past, to: SearchFilters::DateRange.present ) ], scope_to_owner: true ) end - WORKFLOW = FacetedIndicator.new( + WORKFLOW = GroupedIndicator.new( name: 'workflow', - facet: 'workflow', + pivots: [{ field_name: 'workflow' }], record_model: Child, scope: OPEN_CLOSED_ENABLED, scope_to_owner: true ).freeze - WORKFLOW_TEAM = PivotedIndicator.new( + WORKFLOW_TEAM = GroupedIndicator.new( name: 'workflow_team', record_model: Child, - pivots: %w[owned_by workflow], + pivots: [{ field_name: 'owned_by', constrained: true }, { field_name: 'workflow' }], scope: OPEN_CLOSED_ENABLED, - scope_to_user: true, scope_to_owned_by_groups: true ).freeze CASES_BY_SOCIAL_WORKER = [ - FacetedIndicator.new( + GroupedIndicator.new( name: 'cases_by_social_worker_total', record_model: Child, - facet: 'owned_by', + pivots: [{ field_name: 'owned_by' }], scope: OPEN_ENABLED, scope_to_owned_by_groups: true, exclude_zeros: true ), - FacetedIndicator.new( + GroupedIndicator.new( name: 'cases_by_social_worker_new_or_updated', record_model: Child, - facet: 'owned_by', + pivots: [{ field_name: 'owned_by' }], scope: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'not_edited_by_owner', value: true) + SearchFilters::BooleanValue.new(field_name: 'not_edited_by_owner', value: true) ] ) ].freeze - RISK = FacetedIndicator.new( + RISK = GroupedIndicator.new( name: 'risk_level', - facet: 'risk_level', + pivots: [{ field_name: 'risk_level' }], record_model: Child, scope: OPEN_ENABLED ).freeze @@ -100,7 +99,7 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_assessment', value: Approval::APPROVAL_STATUS_PENDING) + SearchFilters::TextValue.new(field_name: 'approval_status_assessment', value: Approval::APPROVAL_STATUS_PENDING) ] ).freeze @@ -108,7 +107,7 @@ def self.closed_recently name: 'approval_assessment_pending_group', record_model: Child, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_assessment', value: Approval::APPROVAL_STATUS_PENDING) + SearchFilters::TextValue.new(field_name: 'approval_status_assessment', value: Approval::APPROVAL_STATUS_PENDING) ] ).freeze @@ -117,7 +116,9 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_assessment', value: Approval::APPROVAL_STATUS_REJECTED) + SearchFilters::TextValue.new( + field_name: 'approval_status_assessment', value: Approval::APPROVAL_STATUS_REJECTED + ) ] ).freeze @@ -126,7 +127,9 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_assessment', value: Approval::APPROVAL_STATUS_APPROVED) + SearchFilters::TextValue.new( + field_name: 'approval_status_assessment', value: Approval::APPROVAL_STATUS_APPROVED + ) ] ).freeze @@ -135,7 +138,7 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_case_plan', value: Approval::APPROVAL_STATUS_PENDING) + SearchFilters::TextValue.new(field_name: 'approval_status_case_plan', value: Approval::APPROVAL_STATUS_PENDING) ] ).freeze @@ -143,7 +146,7 @@ def self.closed_recently name: 'approval_case_plan_pending_group', record_model: Child, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_case_plan', value: Approval::APPROVAL_STATUS_PENDING) + SearchFilters::TextValue.new(field_name: 'approval_status_case_plan', value: Approval::APPROVAL_STATUS_PENDING) ] ).freeze @@ -152,7 +155,7 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_case_plan', value: Approval::APPROVAL_STATUS_REJECTED) + SearchFilters::TextValue.new(field_name: 'approval_status_case_plan', value: Approval::APPROVAL_STATUS_REJECTED) ] ).freeze @@ -161,7 +164,7 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_case_plan', value: Approval::APPROVAL_STATUS_APPROVED) + SearchFilters::TextValue.new(field_name: 'approval_status_case_plan', value: Approval::APPROVAL_STATUS_APPROVED) ] ).freeze @@ -170,7 +173,7 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_closure', value: Approval::APPROVAL_STATUS_PENDING) + SearchFilters::TextValue.new(field_name: 'approval_status_closure', value: Approval::APPROVAL_STATUS_PENDING) ] ).freeze @@ -178,7 +181,7 @@ def self.closed_recently name: 'approval_closure_pending_group', record_model: Child, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_closure', value: Approval::APPROVAL_STATUS_PENDING) + SearchFilters::TextValue.new(field_name: 'approval_status_closure', value: Approval::APPROVAL_STATUS_PENDING) ] ).freeze @@ -187,7 +190,7 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_closure', value: Approval::APPROVAL_STATUS_REJECTED) + SearchFilters::TextValue.new(field_name: 'approval_status_closure', value: Approval::APPROVAL_STATUS_REJECTED) ] ).freeze @@ -196,7 +199,7 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_closure', value: Approval::APPROVAL_STATUS_APPROVED) + SearchFilters::TextValue.new(field_name: 'approval_status_closure', value: Approval::APPROVAL_STATUS_APPROVED) ] ).freeze @@ -205,7 +208,9 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_action_plan', value: Approval::APPROVAL_STATUS_PENDING) + SearchFilters::TextValue.new( + field_name: 'approval_status_action_plan', value: Approval::APPROVAL_STATUS_PENDING + ) ] ).freeze @@ -213,7 +218,9 @@ def self.closed_recently name: 'approval_action_plan_pending_group', record_model: Child, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_action_plan', value: Approval::APPROVAL_STATUS_PENDING) + SearchFilters::TextValue.new( + field_name: 'approval_status_action_plan', value: Approval::APPROVAL_STATUS_PENDING + ) ] ).freeze @@ -222,7 +229,9 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_action_plan', value: Approval::APPROVAL_STATUS_REJECTED) + SearchFilters::TextValue.new( + field_name: 'approval_status_action_plan', value: Approval::APPROVAL_STATUS_REJECTED + ) ] ).freeze @@ -231,7 +240,9 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_action_plan', value: Approval::APPROVAL_STATUS_APPROVED) + SearchFilters::TextValue.new( + field_name: 'approval_status_action_plan', value: Approval::APPROVAL_STATUS_APPROVED + ) ] ).freeze @@ -240,7 +251,9 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_gbv_closure', value: Approval::APPROVAL_STATUS_PENDING) + SearchFilters::TextValue.new( + field_name: 'approval_status_gbv_closure', value: Approval::APPROVAL_STATUS_PENDING + ) ] ).freeze @@ -248,7 +261,9 @@ def self.closed_recently name: 'approval_gbv_closure_pending_group', record_model: Child, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_gbv_closure', value: Approval::APPROVAL_STATUS_PENDING) + SearchFilters::TextValue.new( + field_name: 'approval_status_gbv_closure', value: Approval::APPROVAL_STATUS_PENDING + ) ] ).freeze @@ -257,7 +272,9 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_gbv_closure', value: Approval::APPROVAL_STATUS_REJECTED) + SearchFilters::TextValue.new( + field_name: 'approval_status_gbv_closure', value: Approval::APPROVAL_STATUS_REJECTED + ) ] ).freeze @@ -266,15 +283,16 @@ def self.closed_recently record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'approval_status_gbv_closure', value: Approval::APPROVAL_STATUS_APPROVED) + SearchFilters::TextValue.new( + field_name: 'approval_status_gbv_closure', value: Approval::APPROVAL_STATUS_APPROVED + ) ] ).freeze def self.tasks_overdue_assessment - FacetedIndicator.new( + GroupedIndicator.new( name: 'tasks_overdue_assessment', - facet: 'owned_by', - scope_to_user: true, + pivots: [{ field_name: 'owned_by', constrained: true }], record_model: Child, scope: overdue_assesment_scope ) @@ -283,17 +301,18 @@ def self.tasks_overdue_assessment def self.overdue_assesment_scope OPEN_ENABLED + [ SearchFilters::DateRange.new( - field_name: 'assessment_due_dates', from: FacetedIndicator.dawn_of_time, to: FacetedIndicator.present + field_name: 'assessment_due_dates', + from: SearchFilters::DateRange.dawn_of_time, + to: SearchFilters::DateRange.present ) ] end def self.tasks_overdue_case_plan - FacetedIndicator.new( + GroupedIndicator.new( name: 'tasks_overdue_case_plan', - facet: 'owned_by', + pivots: [{ field_name: 'owned_by', constrained: true }], record_model: Child, - scope_to_user: true, scope: overdue_case_plan_scope ) end @@ -301,17 +320,18 @@ def self.tasks_overdue_case_plan def self.overdue_case_plan_scope OPEN_ENABLED + [ SearchFilters::DateRange.new( - field_name: 'case_plan_due_dates', from: FacetedIndicator.dawn_of_time, to: FacetedIndicator.present + field_name: 'case_plan_due_dates', + from: SearchFilters::DateRange.dawn_of_time, + to: SearchFilters::DateRange.present ) ] end def self.tasks_overdue_services - FacetedIndicator.new( + GroupedIndicator.new( name: 'tasks_overdue_services', - facet: 'owned_by', + pivots: [{ field_name: 'owned_by', constrained: true }], record_model: Child, - scope_to_user: true, scope: overdue_services_scope ) end @@ -319,17 +339,18 @@ def self.tasks_overdue_services def self.overdue_services_scope OPEN_ENABLED + [ SearchFilters::DateRange.new( - field_name: 'service_due_dates', from: FacetedIndicator.dawn_of_time, to: FacetedIndicator.present + field_name: 'service_due_dates', + from: SearchFilters::DateRange.dawn_of_time, + to: SearchFilters::DateRange.present ) ] end def self.tasks_overdue_followups - FacetedIndicator.new( + GroupedIndicator.new( name: 'tasks_overdue_followups', - facet: 'owned_by', + pivots: [{ field_name: 'owned_by', constrained: true }], record_model: Child, - scope_to_user: true, scope: overdue_followup_scope ) end @@ -337,45 +358,45 @@ def self.tasks_overdue_followups def self.overdue_followup_scope OPEN_ENABLED + [ SearchFilters::DateRange.new( - field_name: 'followup_due_dates', from: FacetedIndicator.dawn_of_time, to: FacetedIndicator.present + field_name: 'followup_due_dates', + from: SearchFilters::DateRange.dawn_of_time, + to: SearchFilters::DateRange.present ) ] end - PROTECTION_CONCERNS_OPEN_CASES = FacetedIndicator.new( + PROTECTION_CONCERNS_OPEN_CASES = GroupedIndicator.new( name: 'protection_concerns_open_cases', - facet: 'protection_concerns', + pivots: [{ field_name: 'protection_concerns', multivalue: true }], record_model: Child, scope: OPEN_ENABLED ).freeze def self.protection_concerns_new_this_week - FacetedIndicator.new( + GroupedIndicator.new( name: 'protection_concerns_new_this_week', - facet: 'protection_concerns', + pivots: [{ field_name: 'protection_concerns', multivalue: true }], record_model: Child, - scope: OPEN_ENABLED + [ - SearchFilters::DateRange.new({ field_name: 'created_at' }.merge(FacetedIndicator.this_week)) - ] + scope: OPEN_ENABLED + [SearchFilters::DateRange.this_week('created_at')] ) end - PROTECTION_CONCERNS_ALL_CASES = FacetedIndicator.new( + PROTECTION_CONCERNS_ALL_CASES = GroupedIndicator.new( name: 'protection_concerns_all_cases', - facet: 'protection_concerns', + pivots: [{ field_name: 'protection_concerns', multivalue: true }], record_model: Child, - scope: [SearchFilters::Value.new(field_name: 'record_state', value: true)] + scope: [SearchFilters::BooleanValue.new(field_name: 'record_state', value: true)] ).freeze def self.protection_concerns_closed_this_week - FacetedIndicator.new( + GroupedIndicator.new( name: 'protection_concerns_closed_this_week', - facet: 'protection_concerns', + pivots: [{ field_name: 'protection_concerns', multivalue: true }], record_model: Child, scope: [ - SearchFilters::Value.new(field_name: 'record_state', value: true), - SearchFilters::Value.new(field_name: 'status', value: Record::STATUS_CLOSED), - SearchFilters::DateRange.new({ field_name: 'date_closure' }.merge(FacetedIndicator.this_week)) + SearchFilters::BooleanValue.new(field_name: 'record_state', value: true), + SearchFilters::TextValue.new(field_name: 'status', value: Record::STATUS_CLOSED), + SearchFilters::DateRange.this_week('date_closure') ] ) end @@ -384,7 +405,7 @@ def self.protection_concerns_closed_this_week name: 'shared_with_others_referrals', record_model: Child, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'referred_users_present', value: true) + SearchFilters::BooleanValue.new(field_name: 'referred_users_present', value: true) ], scope_to_owner: true ).freeze @@ -394,7 +415,7 @@ def self.protection_concerns_closed_this_week record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'transfer_status', value: Transition::STATUS_INPROGRESS) + SearchFilters::TextValue.new(field_name: 'transfer_status', value: Transition::STATUS_INPROGRESS) ] ).freeze @@ -403,7 +424,7 @@ def self.protection_concerns_closed_this_week record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'transfer_status', value: Transition::STATUS_REJECTED) + SearchFilters::TextValue.new(field_name: 'transfer_status', value: Transition::STATUS_REJECTED) ] ).freeze @@ -441,66 +462,63 @@ def self.protection_concerns_closed_this_week queries: CLOSED_ENABLED ).freeze - SHARED_FROM_MY_TEAM_REFERRALS = FacetedIndicator.new( + SHARED_FROM_MY_TEAM_REFERRALS = GroupedIndicator.new( name: 'shared_from_my_team_referrals', - facet: 'owned_by', + pivots: [{ field_name: 'owned_by' }], exclude_zeros: true, record_model: Child, scope: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'referred_users_present', value: true) + SearchFilters::BooleanValue.new(field_name: 'referred_users_present', value: true) ], scope_to_owned_by_groups: true ).freeze - SHARED_FROM_MY_TEAM_PENDING_TRANSFERS = FacetedIndicator.new( + SHARED_FROM_MY_TEAM_PENDING_TRANSFERS = GroupedIndicator.new( name: 'shared_from_my_team_pending_transfers', - facet: 'owned_by', + pivots: [{ field_name: 'owned_by' }], exclude_zeros: true, record_model: Child, scope: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'transfer_status', value: Transition::STATUS_INPROGRESS) + SearchFilters::TextValue.new(field_name: 'transfer_status', value: Transition::STATUS_INPROGRESS) ], scope_to_owned_by_groups: true ).freeze - SHARED_FROM_MY_TEAM_REJECTED_TRANSFERS = FacetedIndicator.new( + SHARED_FROM_MY_TEAM_REJECTED_TRANSFERS = GroupedIndicator.new( name: 'shared_from_my_team_rejected_transfers', - facet: 'owned_by', + pivots: [{ field_name: 'owned_by' }], exclude_zeros: true, record_model: Child, scope: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'transfer_status', value: Transition::STATUS_REJECTED) + SearchFilters::TextValue.new(field_name: 'transfer_status', value: Transition::STATUS_REJECTED) ], scope_to_owned_by_groups: true ).freeze - SHARED_WITH_MY_TEAM_REFERRALS = FacetedIndicator.new( + SHARED_WITH_MY_TEAM_REFERRALS = GroupedIndicator.new( name: 'shared_with_my_team_referrals', record_model: Child, - facet: 'referred_users', - scope_to_user: true, + pivots: [{ field_name: 'referred_users', multivalue: true, constrained: true }], exclude_zeros: true, - queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'referred_users_present', value: true) + scope: OPEN_ENABLED + [ + SearchFilters::BooleanValue.new(field_name: 'referred_users_present', value: true) ] - ).freeze + ) - SHARED_WITH_MY_TEAM_PENDING_TRANSFERS = FacetedIndicator.new( + SHARED_WITH_MY_TEAM_PENDING_TRANSFERS = GroupedIndicator.new( name: 'shared_with_my_team_pending_transfers', + transition_model: Transfer, + pivots: [{ field_name: 'transferred_to_users', multivalue: true, constrained: true }], record_model: Child, - facet: 'transferred_to_users', - scope_to_user: true, exclude_zeros: true, - queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'transfer_status', value: Transition::STATUS_INPROGRESS) - ] - ).freeze + scope: OPEN_ENABLED + ) SHARED_WITH_MY_TEAM_PENDING_TRANSFERS_OVERVIEW = QueriedIndicator.new( name: 'shared_with_my_team_pending_transfers_overview', record_model: Child, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'transfer_status', value: Transition::STATUS_INPROGRESS) + SearchFilters::TextValue.new(field_name: 'transfer_status', value: Transition::STATUS_INPROGRESS) ], scope_to_transferred_groups: true ).freeze @@ -509,7 +527,7 @@ def self.protection_concerns_closed_this_week name: 'with_incidents', record_model: Child, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'has_incidents', value: true) + SearchFilters::BooleanValue.new(field_name: 'has_incidents', value: true) ] ).freeze @@ -518,7 +536,7 @@ def self.protection_concerns_closed_this_week record_model: Child, scope_to_owner: true, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'current_alert_types', value: Alertable::INCIDENT_FROM_CASE) + SearchFilters::TextValue.new(field_name: 'current_alert_types', value: Alertable::INCIDENT_FROM_CASE) ] ).freeze @@ -526,7 +544,7 @@ def self.protection_concerns_closed_this_week name: 'without_incidents', record_model: Child, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'has_incidents', value: false) + SearchFilters::BooleanValue.new(field_name: 'has_incidents', value: false) ] ).freeze @@ -540,62 +558,57 @@ def self.reporting_location_indicators(role) reporting_location_config = role&.reporting_location_config admin_level = reporting_location_config&.admin_level || ReportingLocation::DEFAULT_ADMIN_LEVEL field_key = reporting_location_config&.field_key || ReportingLocation::DEFAULT_FIELD_KEY - facet_name = "#{field_key}#{admin_level}" - [reporting_location_open(facet_name), - reporting_location_open_last_week(facet_name), reporting_location_open_this_week(facet_name), - reporting_location_closed_last_week(facet_name), reporting_location_closed_this_week(facet_name)] + [ + reporting_location_open(field_key, admin_level), + reporting_location_open_last_week(field_key, admin_level), + reporting_location_open_this_week(field_key, admin_level), + reporting_location_closed_last_week(field_key, admin_level), + reporting_location_closed_this_week(field_key, admin_level) + ] end - def self.reporting_location_open(facet_name) - FacetedIndicator.new( + def self.reporting_location_open(field_name, admin_level) + GroupedIndicator.new( name: 'reporting_location_open', - facet: facet_name, + pivots: [{ field_name:, admin_level:, type: 'location' }], record_model: Child, scope: OPEN_ENABLED ) end - def self.reporting_location_open_last_week(facet_name) - FacetedIndicator.new( + def self.reporting_location_open_last_week(field_name, admin_level) + GroupedIndicator.new( name: 'reporting_location_open_last_week', - facet: facet_name, + pivots: [{ field_name:, admin_level:, type: 'location' }], record_model: Child, - scope: OPEN_ENABLED + [ - SearchFilters::DateRange.new({ field_name: 'created_at' }.merge(FacetedIndicator.last_week)) - ] + scope: OPEN_ENABLED + [SearchFilters::DateRange.last_week('created_at')] ) end - def self.reporting_location_open_this_week(facet_name) - FacetedIndicator.new( + def self.reporting_location_open_this_week(field_name, admin_level) + GroupedIndicator.new( name: 'reporting_location_open_this_week', - facet: facet_name, + pivots: [{ field_name:, admin_level:, type: 'location' }], record_model: Child, - scope: OPEN_ENABLED + [ - SearchFilters::DateRange.new({ field_name: 'created_at' }.merge(FacetedIndicator.this_week)) - ] + scope: OPEN_ENABLED + [SearchFilters::DateRange.this_week('created_at')] ) end - def self.reporting_location_closed_last_week(facet_name) - FacetedIndicator.new( + def self.reporting_location_closed_last_week(field_name, admin_level) + GroupedIndicator.new( name: 'reporting_location_closed_last_week', - facet: facet_name, + pivots: [{ field_name:, admin_level:, type: 'location' }], record_model: Child, - scope: CLOSED_ENABLED + [ - SearchFilters::DateRange.new({ field_name: 'date_closure' }.merge(FacetedIndicator.last_week)) - ] + scope: CLOSED_ENABLED + [SearchFilters::DateRange.last_week('date_closure')] ) end - def self.reporting_location_closed_this_week(facet_name) - FacetedIndicator.new( + def self.reporting_location_closed_this_week(field_name, admin_level) + GroupedIndicator.new( name: 'reporting_location_closed_this_week', - facet: facet_name, + pivots: [{ field_name:, admin_level:, type: 'location' }], record_model: Child, - scope: CLOSED_ENABLED + [ - SearchFilters::DateRange.new({ field_name: 'date_closure' }.merge(FacetedIndicator.this_week)) - ] + scope: CLOSED_ENABLED + [SearchFilters::DateRange.this_week('date_closure')] ) end @@ -611,7 +624,7 @@ def self.risk_level_indicators(risk_levels) scope_to_owner: true, record_model: Child, queries: OPEN_ENABLED + [ - SearchFilters::NotValue.new(field_name: 'risk_level', values: risk_levels) + SearchFilters::TextList.new(field_name: 'risk_level', values: risk_levels, not_filter: true) ] )] + risk_levels.map { |risk_level| risk_level_indicator(risk_level) } end @@ -631,7 +644,7 @@ def self.risk_level_indicator(risk_level) scope_to_owner: true, record_model: Child, queries: OPEN_ENABLED + [ - SearchFilters::Value.new(field_name: 'risk_level', value: risk_level) + SearchFilters::TextValue.new(field_name: 'risk_level', value: risk_level) ] ) end @@ -647,7 +660,7 @@ def self.overdue_risk_level_indicator(risk_level) def self.overdue_none_risk_level_queries(risk_levels) OPEN_ENABLED + [ - SearchFilters::NotValue.new(field_name: 'risk_level', values: risk_levels), + SearchFilters::TextList.new(field_name: 'risk_level', values: risk_levels, not_filter: true), SearchFilters::DateRange.new( field_name: 'reassigned_transferred_on', from: Time.at(0), @@ -666,7 +679,7 @@ def self.overdue_risk_level_queries(risk_level) from: Time.at(0), to: Time.now - timeframe ), - SearchFilters::Value.new(field_name: 'risk_level', value: risk_level) + SearchFilters::TextValue.new(field_name: 'risk_level', value: risk_level) ] end @@ -674,9 +687,7 @@ def self.new_this_week QueriedIndicator.new( name: 'new_this_week', record_model: Child, - queries: OPEN_ENABLED + [ - SearchFilters::DateRange.new({ field_name: 'created_at' }.merge(QueriedIndicator.this_week)) - ] + queries: OPEN_ENABLED + [SearchFilters::DateRange.this_week('created_at')] ) end @@ -684,9 +695,7 @@ def self.new_last_week QueriedIndicator.new( name: 'new_last_week', record_model: Child, - queries: OPEN_ENABLED + [ - SearchFilters::DateRange.new({ field_name: 'created_at' }.merge(QueriedIndicator.last_week)) - ] + queries: OPEN_ENABLED + [SearchFilters::DateRange.last_week('created_at')] ) end @@ -694,9 +703,7 @@ def self.closed_this_week QueriedIndicator.new( name: 'closed_this_week', record_model: Child, - queries: CLOSED_ENABLED + [ - SearchFilters::DateRange.new({ field_name: 'date_closure' }.merge(QueriedIndicator.this_week)) - ].freeze + queries: CLOSED_ENABLED + [SearchFilters::DateRange.this_week('date_closure')].freeze ) end @@ -704,9 +711,7 @@ def self.closed_last_week QueriedIndicator.new( name: 'closed_last_week', record_model: Child, - queries: CLOSED_ENABLED + [ - SearchFilters::DateRange.new({ field_name: 'date_closure' }.merge(QueriedIndicator.last_week)) - ].freeze + queries: CLOSED_ENABLED + [SearchFilters::DateRange.last_week('date_closure')].freeze ) end end diff --git a/app/models/indicators/faceted_indicator.rb b/app/models/indicators/faceted_indicator.rb deleted file mode 100644 index a7612464dd..0000000000 --- a/app/models/indicators/faceted_indicator.rb +++ /dev/null @@ -1,50 +0,0 @@ -# frozen_string_literal: true - -# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -# rubocop:disable Style/ClassAndModuleChildren -module Indicators - # Class for Faceted Indicator - class FacetedIndicator < AbstractIndicator - # rubocop:enable Style/ClassAndModuleChildren - attr_accessor :facet - - def facet_name - facet - end - - # rubocop:disable Metrics/AbcSize - # rubocop:disable Metrics/CyclomaticComplexity - # rubocop:disable Metrics/MethodLength - # rubocop:disable Metrics/PerceivedComplexity - def query(sunspot, user) - this = self - sunspot.instance_eval do - with(:owned_by, user.user_name) if this.scope_to_owner - with(:referred_users, user.user_name) if this.scope_to_referred - with(:transferred_to_users, user.user_name) if this.scope_to_transferred - with(:transferred_to_user_groups, user.user_group_unique_ids) if this.scope_to_transferred_groups - # TODO: Add agency user scope - with(:owned_by_groups, user.user_group_unique_ids) if this.scope_to_owned_by_groups - without(:last_updated_by, user.user_name) if this.scope_to_not_last_update - this.scope&.each { |f| f.query_scope(self) } - facet(this.facet_name, zeros: !this.exclude_zeros) - end - end - # rubocop:enable Metrics/AbcSize - # rubocop:enable Metrics/CyclomaticComplexity - # rubocop:enable Metrics/MethodLength - # rubocop:enable Metrics/PerceivedComplexity - - def stat_query_strings(facet_row, owner, user) - scope_query_strings + - owner_query_string(owner) + - referred_query_string(user) + - transferred_query_string(user) + - transferred_groups_query_string(user) + - owned_by_groups_query_string(user) + - not_last_updated_query_string(user) + - ["#{facet_name}=#{facet_row.value}"] - end - end -end diff --git a/app/models/indicators/grouped_indicator.rb b/app/models/indicators/grouped_indicator.rb new file mode 100644 index 0000000000..98e7a75016 --- /dev/null +++ b/app/models/indicators/grouped_indicator.rb @@ -0,0 +1,142 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# rubocop:disable Style/ClassAndModuleChildren +module Indicators + # Class for Grouped Indicator + class GroupedIndicator < AbstractIndicator + # rubocop:enable Style/ClassAndModuleChildren + attr_accessor :pivots + + DEFAULT_STAT = { 'count' => 0, 'query' => [] }.freeze + + SELECT_LOCATION_PIVOT = %( + ( + SELECT + LOWER(CAST(SUBPATH(locations.hierarchy_path, :admin_level, 1) AS VARCHAR)) + FROM locations + WHERE location_code = data->>:field_name + AND NLEVEL(hierarchy_path) > :admin_level + ) AS pivot:index + ) + + def query(indicator_filters, user_query_scope) + indicator_query = super(indicator_filters, user_query_scope) + indicator_query.select(select_pivots).group(pivot_field_names.join(', ')) + end + + def select_pivots + select = pivots.map.with_index(1) do |pivot, index| + next(ActiveRecord::Base.sanitize_sql_array(['pivot?', index])) if pivot[:multivalue].present? + + if pivot[:type] == 'location' + next(ActiveRecord::Base.sanitize_sql_array([SELECT_LOCATION_PIVOT, pivot.merge(index:)])) + end + + ActiveRecord::Base.sanitize_sql_array(['data->>? AS pivot?', pivot[:field_name], index]) + end.join(', ') + + "#{select}, COUNT(*) AS count" + end + + def pivot_field_names + pivots.map.with_index(1) { |_, index| "pivot#{index}" } + end + + def write_stats_for_indicator(indicator_filters, user_query_scope, managed_user_names = []) + indicator_query = query(indicator_filters, user_query_scope) + indicator_query = join_and_constraint_pivots(indicator_query, managed_user_names) + indicator_query = indicator_query.order(pivot_field_names) + result = Child.connection.select_all(indicator_query.to_sql).to_a + nested_pivots = nested_pivots_from_result(result) + write_stats_for_pivots(result, indicator_filters, nested_pivots) + end + + protected + + def join_and_constraint_pivots(indicator_query, managed_user_names) + pivots.each.with_index(1) do |pivot, index| + indicator_query = join_multivalued_pivot(indicator_query, pivot, index) if pivot[:multivalue].present? + next unless pivot[:constrained].present? && managed_user_names.present? + + indicator_query = constraint_pivot_values(indicator_query, pivot, index, managed_user_names) + end + + indicator_query + end + + def join_multivalued_pivot(indicator_query, pivot, index) + indicator_query.joins( + ActiveRecord::Base.sanitize_sql_array( + ['CROSS JOIN JSONB_ARRAY_ELEMENTS_TEXT(data->?) AS pivot?', pivot[:field_name], index] + ) + ) + end + + def constraint_pivot_values(indicator_query, pivot, index, managed_user_names) + if pivot[:multivalue].present? + return indicator_query.where( + ActiveRecord::Base.sanitize_sql_array(['pivot? IN (?)', index, managed_user_names]) + ) + end + + indicator_query.where( + ActiveRecord::Base.sanitize_sql_array(['data->>? IN (?)', pivot[:field_name], managed_user_names]) + ) + end + + def write_stats_for_pivots(result, indicator_filters, nested_pivots) + result.each_with_object({}) do |row, memo| + init_pivot_stats(memo, row, nested_pivots) + if pivots.size > 1 + memo[row['pivot1']][row['pivot2']] = stats_for_pivots(row, indicator_filters) + else + memo[row['pivot1']] = stats_for_pivots(row, indicator_filters) + end + end + end + + def init_pivot_stats(stats, row, nested_pivots) + return unless stats[row['pivot1']].blank? + + stats[row['pivot1']] = default_pivot_stat(nested_pivots) + end + + def default_pivot_stat(nested_pivots) + return DEFAULT_STAT unless nested_pivots.present? + + nested_pivots.reduce({}) { |memo, nested_pivot| memo.merge(nested_pivot => DEFAULT_STAT) } + end + + def nested_pivots_from_result(result) + return [] if pivots.size < 2 + + result.map { |elem| elem['pivot2'] }.uniq + end + + def stats_for_pivots(pivot_row, indicator_filters) + { 'count' => pivot_row['count'], 'query' => stat_query_strings(pivot_row, indicator_filters) } + end + + def pivot_values(pivot_row) + pivot_field_names.map { |elem| pivot_row[elem] } + end + + def stat_query_strings(pivot_row, indicator_filters) + indicator_filters.map(&:to_s) + row_pivot_to_query_string(pivot_row) + end + + def row_pivot_to_query_string(pivot_row) + values = pivot_values(pivot_row) + pivots.map.with_index { |pivot, index| "#{pivot_param(pivot)}=#{values[index]}" } + end + + def pivot_param(pivot) + return pivot[:query_param] if pivot[:query_param].present? + return "loc:#{pivot[:field_name]}#{pivot[:admin_level]}" if pivot[:type] == 'location' + + pivot[:field_name] + end + end +end diff --git a/app/models/indicators/incident.rb b/app/models/indicators/incident.rb index 02356e743d..c6d5927544 100644 --- a/app/models/indicators/incident.rb +++ b/app/models/indicators/incident.rb @@ -7,31 +7,34 @@ module Indicators # Incident Class for Indicators class Incident OPEN_ENABLED = [ - SearchFilters::Value.new(field_name: 'record_state', value: true), - SearchFilters::Value.new(field_name: 'status', value: Record::STATUS_OPEN) + SearchFilters::BooleanValue.new(field_name: 'record_state', value: true), + SearchFilters::TextValue.new(field_name: 'status', value: Record::STATUS_OPEN) ].freeze - VIOLATIONS_CATEGORY_VERIFICATION_STATUS = FacetedIndicator.new( + VIOLATIONS_CATEGORY_VERIFICATION_STATUS = GroupedIndicator.new( name: 'violations_category_verification_status', record_model: ::Incident, - facet: 'violation_with_verification_status', + pivots: [{ field_name: 'violation_with_verification_status', multivalue: true }], scope: OPEN_ENABLED ).freeze - PERPETRATOR_ARMED_FORCE_GROUP_PARTY_NAMES = FacetedIndicator.new( + PERPETRATOR_ARMED_FORCE_GROUP_PARTY_NAMES = GroupedIndicator.new( name: 'perpetrator_armed_force_group_party_names', record_model: ::Incident, - facet: 'armed_force_group_party_names', + pivots: [{ field_name: 'armed_force_group_party_names', multivalue: true }], scope: OPEN_ENABLED ) def self.violation_category_region(role) admin_level = role&.incident_reporting_location_config&.admin_level || ReportingLocation::DEFAULT_ADMIN_LEVEL - PivotedIndicator.new( + GroupedIndicator.new( name: 'violations_category_region', record_model: ::Incident, - pivots: ["incident_location#{admin_level}", 'violation_with_verification_status'], + pivots: [ + { field_name: 'incident_location', admin_level:, type: 'location' }, + { field_name: 'violation_with_verification_status', multivalue: true } + ], scope: OPEN_ENABLED ).freeze end diff --git a/app/models/indicators/pivoted_indicator.rb b/app/models/indicators/pivoted_indicator.rb deleted file mode 100644 index 33420b9c05..0000000000 --- a/app/models/indicators/pivoted_indicator.rb +++ /dev/null @@ -1,88 +0,0 @@ -# frozen_string_literal: true - -# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -# rubocop:disable Style/ClassAndModuleChildren -module Indicators - # Class for Pivoted Indicator - class PivotedIndicator < AbstractIndicator - # rubocop:enable Style/ClassAndModuleChildren - attr_accessor :pivots - - # rubocop:disable Metrics/AbcSize - # rubocop:disable Metrics/CyclomaticComplexity - # rubocop:disable Metrics/MethodLength - # rubocop:disable Metrics/PerceivedComplexity - def query(sunspot, user) - this = self - sunspot.instance_eval do - with(:owned_by, user.user_name) if this.scope_to_owner - with(:referred_users, user.user_name) if this.scope_to_referred - with(:transferred_to_users, user.user_name) if this.scope_to_transferred - with(:transferred_to_user_groups, user.user_group_unique_ids) if this.scope_to_transferred_groups - # TODO: Add agency user scope - with(:owned_by_groups, user.user_group_unique_ids) if this.scope_to_owned_by_groups - without(:last_updated_by, user.user_name) if this.scope_to_not_last_update - this.scope&.each { |f| f.query_scope(self) } - adjust_solr_params do |params| - params['facet'] = 'true' - params['facet.missing'] = 'true' - params['facet.pivot'] = this.pivots.map do |pivot| - SolrUtils.indexed_field_name(Record.map_name(this.record_model.name), pivot) - end.join(',') - params['facet.pivot.mincount'] = this.exclude_zeros == true ? '1' : '-1' - params['facet.pivot.limit'] = '-1' - end - end - end - # rubocop:enable Metrics/AbcSize - # rubocop:enable Metrics/CyclomaticComplexity - # rubocop:enable Metrics/MethodLength - # rubocop:enable Metrics/PerceivedComplexity - - def stats_from_search(sunspot_search, user, managed_user_names = []) - owner = owner_from_search(sunspot_search) - name_map = field_name_solr_map - facet_pivot = name_map.keys.join(',') - rows = sunspot_search.facet_response['facet_pivot'][facet_pivot] - rows = user_scoped_rows(rows, user, managed_user_names) - row_stats(rows, owner, user, name_map) - end - - def row_stats(rows, owner, user, name_map) - return {} unless rows.present? - - rows.each_with_object({}) do |row, stats| - stats[row['value']] = row['pivot'].to_h do |pivot| - stat = { - 'count' => pivot['count'], - 'query' => stat_query_strings([row, pivot], owner, user, name_map) - } - [pivot['value'], stat] - end - end - end - - def stat_query_strings(row_pivot, owner, user, name_map = {}) - row, pivot = row_pivot - scope_query_strings + owner_query_string(owner) + - referred_query_string(user) + - transferred_query_string(user) + - transferred_groups_query_string(user) + - owned_by_groups_query_string(user) + - not_last_updated_query_string(user) + name_map_row_pivot(name_map, row, pivot) - end - - private - - def field_name_solr_map - pivots.to_h do |pivot| - [SolrUtils.indexed_field_name(record_model, pivot), pivot] - end - end - - def name_map_row_pivot(name_map, row, pivot) - ["#{name_map[row['field']]}=#{row['value']}", "#{name_map[pivot['field']]}=#{pivot['value']}"] - end - end -end diff --git a/app/models/indicators/queried_indicator.rb b/app/models/indicators/queried_indicator.rb index fe4f06e8e3..f547ad9c2f 100644 --- a/app/models/indicators/queried_indicator.rb +++ b/app/models/indicators/queried_indicator.rb @@ -13,46 +13,17 @@ def self.type 'queried_indicator' end - def facet_name - name + def write_stats_for_indicator(indicator_filters, user_query_scope, _managed_user_names = []) + indicator_query = query(indicator_filters, user_query_scope) + { name => { 'count' => indicator_query.size, 'query' => stat_query_strings(name, indicator_filters) } } end - # rubocop:disable Metrics/AbcSize - # rubocop:disable Metrics/CyclomaticComplexity - # rubocop:disable Metrics/MethodLength - # rubocop:disable Metrics/PerceivedComplexity - def query(sunspot, user) - this = self - sunspot.instance_eval do - with(:owned_by, user.user_name) if this.scope_to_owner - with(:referred_users, user.user_name) if this.scope_to_referred - with(:transferred_to_users, user.user_name) if this.scope_to_transferred - with(:transferred_to_user_groups, user.user_group_unique_ids) if this.scope_to_transferred_groups - # TODO: Add agency user scope - with(:owned_by_groups, user.user_group_unique_ids) if this.scope_to_owned_by_groups - without(:last_updated_by, user.user_name) if this.scope_to_not_last_update - this.scope&.each { |f| f.query_scope(self) } - facet(this.facet_name, zeros: !this.exclude_zeros) do - row(this.name) do - this.queries.each { |f| f.query_scope(self) } - end - end - end + def filters(user) + query_scope(user) + queries end - # rubocop:enable Metrics/AbcSize - # rubocop:enable Metrics/CyclomaticComplexity - # rubocop:enable Metrics/MethodLength - # rubocop:enable Metrics/PerceivedComplexity - def stat_query_strings(_, owner, user) - scope_query_strings + - owner_query_string(owner) + - referred_query_string(user) + - transferred_query_string(user) + - transferred_groups_query_string(user) + - owned_by_groups_query_string(user) + - not_last_updated_query_string(user) + - (queries&.map(&:to_s) || []) + def stat_query_strings(_, indicator_filters) + indicator_filters.map(&:to_s) end end end diff --git a/app/models/kpi/gbv_child.rb b/app/models/kpi/gbv_child.rb index 60de17615f..465dfb72d6 100644 --- a/app/models/kpi/gbv_child.rb +++ b/app/models/kpi/gbv_child.rb @@ -7,14 +7,17 @@ module Kpi::GBVChild extend ActiveSupport::Concern included do - searchable do - %i[completed_survivor_assessment safety_plan_required completed_safety_plan completed_action_plan - completed_and_approved_action_plan duplicate].each { |f| boolean(f) } - %i[services_provided action_plan_referral_statuses].each { |f| string(f, multiple: true) } - %i[safety_goals_progress health_goals_progress psychosocial_goals_progress justice_goals_progress - other_goals_progress].each { |f| float(f) } - string :satisfaction_status - integer :case_lifetime_days + if Rails.configuration.solr_enabled + searchable do + %w[id status].each { |f| string(f, as: "#{f}_sci") } + %i[completed_survivor_assessment safety_plan_required completed_safety_plan completed_action_plan + completed_and_approved_action_plan duplicate].each { |f| boolean(f) } + %i[services_provided action_plan_referral_statuses].each { |f| string(f, multiple: true) } + %i[safety_goals_progress health_goals_progress psychosocial_goals_progress justice_goals_progress + other_goals_progress].each { |f| float(f) } + string :satisfaction_status + integer :case_lifetime_days + end end end diff --git a/app/models/kpi/gbv_incident.rb b/app/models/kpi/gbv_incident.rb index 72895c13d4..a877669775 100644 --- a/app/models/kpi/gbv_incident.rb +++ b/app/models/kpi/gbv_incident.rb @@ -7,8 +7,12 @@ module Kpi::GBVIncident extend ActiveSupport::Concern included do - searchable do - integer :reporting_delay_days + if Rails.configuration.solr_enabled + searchable do + %w[id status].each { |f| string(f, as: "#{f}_sci") } + integer :reporting_delay_days + date :date_of_first_report + end end end diff --git a/app/models/kpi/search.rb b/app/models/kpi/search.rb index 7d6753a59f..2447ab0745 100644 --- a/app/models/kpi/search.rb +++ b/app/models/kpi/search.rb @@ -4,13 +4,34 @@ module Kpi SearchValue = Struct.new(:from, :to, :owned_by_groups, :owned_by_agency_id) + VALID_KPIS = ['Kpi::AssessmentStatus', + 'Kpi::AverageFollowupMeetingsPerCase', + 'Kpi::AverageReferrals', + 'Kpi::CaseClosureRate', + 'Kpi::CaseLoad', + 'Kpi::ClientSatisfactionRate', + 'Kpi::CompletedCaseActionPlans', + 'Kpi::CompletedCaseSafetyPlans', + 'Kpi::CompletedSupervisorApprovedCaseActionPlans', + 'Kpi::GoalProgressPerNeed', + 'Kpi::NumberOfCases', + 'Kpi::NumberOfIncidents', + 'Kpi::ReportingDelay', + 'Kpi::ServicesProvided', + 'Kpi::SupervisorToCaseworkerRatio', + 'Kpi::TimeFromCaseOpenToClose'].freeze # Search # # An abstract class for search objects to subclass. class Search < SearchValue def self.find(id) - Object.const_get("Kpi::#{id.camelize}") + name = "Kpi::#{id.camelize}" + return unless VALID_KPIS.include?(name) + + Object.const_get(name) + rescue NameError + nil end def self.search_model(model = nil) diff --git a/app/models/lookup.rb b/app/models/lookup.rb index 03cb1be2ca..b9d37930b3 100644 --- a/app/models/lookup.rb +++ b/app/models/lookup.rb @@ -112,6 +112,14 @@ def display_value(lookup_id, option_id, lookups = nil, opts = {}) Lookup.values(lookup_id, lookups, opts).find { |l| l['id'] == option_id }&.[]('display_text') end + # TODOL: We must cache these lookups + def group_by_unique_id(lookup_ids) + where(unique_id: lookup_ids) + .each_with_object({}) do |lk, acc| + acc[lk.unique_id] = FieldI18nService.fill_options(lk.lookup_values_i18n, false) + end + end + private def form_group_lookup_mapping(parent_form) diff --git a/app/models/managed_report.rb b/app/models/managed_report.rb index 4caf312e7f..3d7df23d4a 100644 --- a/app/models/managed_report.rb +++ b/app/models/managed_report.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +# Copyright (c) 2014 - 2024 UNICEF. All rights reserved. # Describes ManagedReport in Primero. # rubocop:disable Metrics/ClassLength @@ -16,10 +16,55 @@ def self.list id: 'gbv_statistics', name: 'managed_reports.gbv_statistics.name', description: 'managed_reports.gbv_statistics.description', - subreports: %w[incidents perpetrators survivors referrals], + subreports: %w[incidents], permitted_filters: [:grouped_by, { date_of_first_report: {}, incident_date: {} }], module_id: PrimeroModule::GBV ), + Permission::PROTECTION_CONCERNS_REPORT => ManagedReport.new( + id: 'protection_concerns_report', + name: 'managed_reports.protection_concerns.name', + description: 'managed_reports.protection_concerns.description', + subreports: %w[protection_concerns], + permitted_filters: [ + :grouped_by, :by, :created_by_groups, :owned_by_groups, + :created_organization, :owned_by_agency_id, { status: {}, registration_date: {}, protection_concerns: {} } + ], + module_id: PrimeroModule::CP + ), + Permission::REPORTING_LOCATIONS_REPORT => ManagedReport.new( + id: 'reporting_locations_report', + name: 'managed_reports.reporting_locations.name', + description: 'managed_reports.reporting_locations.description', + subreports: %w[reporting_locations], + permitted_filters: [ + :grouped_by, :by, :created_by_groups, :owned_by_groups, + :created_organization, :owned_by_agency_id, :location, { status: {}, registration_date: {} } + ], + module_id: PrimeroModule::CP + ), + Permission::FOLLOWUPS_REPORT => ManagedReport.new( + id: 'followups_report', + name: 'managed_reports.followups.name', + description: 'managed_reports.followups.description', + subreports: %w[followups], + permitted_filters: [ + :grouped_by, :by, :created_by_groups, :owned_by_groups, + :created_organization, :owned_by_agency_id, { status: {}, followup_date: {}, followup_type: {} } + ], + module_id: PrimeroModule::CP + ), + Permission::SERVICES_REPORT => ManagedReport.new( + id: 'services_report', + name: 'managed_reports.services.name', + description: 'managed_reports.services.description', + subreports: %w[services], + permitted_filters: [ + :grouped_by, :by, :created_by_groups, :owned_by_groups, + :created_organization, :owned_by_agency_id, + { status: {}, service_implemented_day_time: {}, service_type: {} } + ], + module_id: PrimeroModule::CP + ), Permission::WORKFLOW_REPORT => ManagedReport.new( id: 'workflow_report', name: 'managed_reports.workflow_report.name', @@ -31,6 +76,17 @@ def self.list ], module_id: PrimeroModule::CP ), + Permission::CASES_WORKFLOW_REPORT => ManagedReport.new( + id: 'cases_workflow_report', + name: 'managed_reports.cases_workflow_report.name', + description: 'managed_reports.cases_workflow_report.description', + subreports: %w[cases_workflow], + permitted_filters: [ + :grouped_by, :by, :created_by_groups, :workflow, :owned_by_groups, + :created_organization, :owned_by_agency_id, { status: {}, registration_date: {} } + ], + module_id: PrimeroModule::CP + ), Permission::REFERRALS_TRANSFERS_REPORT => ManagedReport.new( id: 'referrals_transfers_report', name: 'managed_reports.referrals_transfers_report.name', diff --git a/app/models/managed_reports/ghn_indicator_helper.rb b/app/models/managed_reports/ghn_indicator_helper.rb index e22613e80f..52922b587f 100644 --- a/app/models/managed_reports/ghn_indicator_helper.rb +++ b/app/models/managed_reports/ghn_indicator_helper.rb @@ -6,8 +6,6 @@ module ManagedReports::GhnIndicatorHelper extend ActiveSupport::Concern - include ManagedReports::MRMIndicatorHelper - # ClassMethods module ClassMethods def date_filter @@ -25,20 +23,15 @@ def groups def build_groups(results, _params = {}) groups.merge(results.group_by { |group| group['name'] }).map do |group| - { - group_id: group[0], - data: build_data_values(group[1]) - } + { group_id: group[0], data: build_data_values(group[1]) } end end - def build_data_values(values) - values.each_with_object([]) do |curr, acc| - current_group = acc.find { |group| group[:id] == curr['name'] } - next current_group[curr['key'].to_sym] = curr['sum'] if current_group.present? + def value_to_data_element(value) + element = { id: value['group_id'], value['key'].to_sym => value['sum'] } + return element unless value.key?('total') - acc << { id: curr['group_id'], curr['key'].to_sym => curr['sum'] } - end + element.merge(total: value['total']) end end end diff --git a/app/models/managed_reports/indicators/abducted_status.rb b/app/models/managed_reports/indicators/abducted_status.rb index 6046a45afa..6f2d6935c2 100644 --- a/app/models/managed_reports/indicators/abducted_status.rb +++ b/app/models/managed_reports/indicators/abducted_status.rb @@ -4,8 +4,6 @@ # An indicator that returns status of violation type abduction class ManagedReports::Indicators::AbductedStatus < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'abducted_status' diff --git a/app/models/managed_reports/indicators/abduction_reasons.rb b/app/models/managed_reports/indicators/abduction_reasons.rb index ae33823321..c22db2a5c8 100644 --- a/app/models/managed_reports/indicators/abduction_reasons.rb +++ b/app/models/managed_reports/indicators/abduction_reasons.rb @@ -4,8 +4,6 @@ # An indicator that returns reasons of violation type abduction class ManagedReports::Indicators::AbductionReasons < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'abduction_reasons' diff --git a/app/models/managed_reports/indicators/attack_type.rb b/app/models/managed_reports/indicators/attack_type.rb index 3e016b15c3..aa7486542e 100644 --- a/app/models/managed_reports/indicators/attack_type.rb +++ b/app/models/managed_reports/indicators/attack_type.rb @@ -4,8 +4,6 @@ # An indicator that returns the attack type of violation type killing class ManagedReports::Indicators::AttackType < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'attack_type' diff --git a/app/models/managed_reports/indicators/case_violence_type_by_sex_and_age.rb b/app/models/managed_reports/indicators/case_violence_type_by_sex_and_age.rb index e768956118..7edaf3bab2 100644 --- a/app/models/managed_reports/indicators/case_violence_type_by_sex_and_age.rb +++ b/app/models/managed_reports/indicators/case_violence_type_by_sex_and_age.rb @@ -4,8 +4,6 @@ # An indicator that returns the total cases by workflow and sex class ManagedReports::Indicators::CaseViolenceTypeBySexAndAge < ManagedReports::SqlReportIndicator - include ManagedReports::WeekIndicatorHelper - class << self def id 'case_violence_type_by_sex_and_age' diff --git a/app/models/managed_reports/indicators/case_workflow_by_sex_and_age.rb b/app/models/managed_reports/indicators/case_workflow_by_sex_and_age.rb index ca81fd0ac4..41364c0d48 100644 --- a/app/models/managed_reports/indicators/case_workflow_by_sex_and_age.rb +++ b/app/models/managed_reports/indicators/case_workflow_by_sex_and_age.rb @@ -3,74 +3,14 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. # An indicator that returns the total cases by workflow and sex -class ManagedReports::Indicators::CaseWorkflowBySexAndAge < ManagedReports::SqlReportIndicator - include ManagedReports::WeekIndicatorHelper - +class ManagedReports::Indicators::CaseWorkflowBySexAndAge < ManagedReports::Indicators::FieldByAgeSex class << self def id 'case_workflow_by_sex_and_age' end - # rubocop:disable Metrics/MethodLength - # rubocop:disable Metrics/AbcSize - # rubocop:disable Metrics/CyclomaticComplexity - # rubocop:disable Metrics/PerceivedComplexity - def sql(current_user, params = {}) - date_param = filter_date(params) - %{ - with case_workflow_by_sex_and_age as ( - select - data->> 'sex' as name, - #{age_ranges_query} as key, - #{grouped_date_query(params['grouped_by'], filter_date(params))&.concat(' as group_id,')} - count(*) as sum - from cases - where 1 = 1 - #{equal_value_query_multiple(params['owned_by_groups'])&.prepend('and ')} - #{equal_value_query_multiple(params['created_by_groups'])&.prepend('and ')} - #{equal_value_query_multiple(params['owned_by_agency_id'])&.prepend('and ')} - #{equal_value_query_multiple(params['created_organization'])&.prepend('and ')} - #{equal_value_query_multiple(params['status'])&.prepend('and ')} - #{date_range_query(date_param)&.prepend('and ')} - #{equal_value_query(params['module_id'])&.prepend('and ')} - #{equal_value_query(params['workflow'])&.prepend('and ')} - #{user_scope_query(current_user)&.prepend('and ')} - group by name, key - #{grouped_date_query(params['grouped_by'], date_param)&.prepend(', ')} - order by name, key - ) - select - name, key, sum #{params['grouped_by'].present? ? ', group_id' : ''} - from case_workflow_by_sex_and_age - union all - select - name, - 'total' as key, - cast(sum(sum) as integer) as sum - #{params['grouped_by'].present? ? ', group_id' : ''} - from case_workflow_by_sex_and_age - group by name #{params['grouped_by'].present? ? ', group_id' : ''} - union all - select - 'total' as name, - key, - cast(sum(sum) as integer) as sum - #{params['grouped_by'].present? ? ', group_id' : ''} - from case_workflow_by_sex_and_age - group by key #{params['grouped_by'].present? ? ', group_id' : ''} - union all - select - 'total' as name, - 'total' as key, - cast(sum(sum) as integer) as sum - #{params['grouped_by'].present? ? ', group_id' : ''} - from case_workflow_by_sex_and_age - #{params['grouped_by'].present? ? 'group by group_id' : ''} - } + def field_name + 'workflow' end - # rubocop:enable Metrics/MethodLength - # rubocop:enable Metrics/AbcSize - # rubocop:enable Metrics/CyclomaticComplexity - # rubocop:enable Metrics/PerceivedComplexity end end diff --git a/app/models/managed_reports/indicators/denial_type.rb b/app/models/managed_reports/indicators/denial_type.rb index bbe8983588..6bdf941cf8 100644 --- a/app/models/managed_reports/indicators/denial_type.rb +++ b/app/models/managed_reports/indicators/denial_type.rb @@ -4,8 +4,6 @@ # An indicator that returns the denial type for denial subreport class ManagedReports::Indicators::DenialType < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'denial_type' diff --git a/app/models/managed_reports/indicators/detention_status.rb b/app/models/managed_reports/indicators/detention_status.rb index ebb4533717..085b00cc6e 100644 --- a/app/models/managed_reports/indicators/detention_status.rb +++ b/app/models/managed_reports/indicators/detention_status.rb @@ -4,8 +4,6 @@ # An indicator that returns the reporting locations of violation type detention class ManagedReports::Indicators::DetentionStatus < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'detention_status' @@ -60,14 +58,5 @@ def sql(current_user, params = {}) # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/PerceivedComplexity - - def build_data_values(values) - values.each_with_object([]) do |curr, acc| - current_group = acc.find { |group| group[:id] == curr['name'] } - next current_group[curr['key'].to_sym] = curr['sum'] if current_group.present? - - acc << { id: curr['name'], curr['key'].to_sym => curr['sum'], total: curr['total'] } - end - end end end diff --git a/app/models/managed_reports/indicators/facility_attack_type.rb b/app/models/managed_reports/indicators/facility_attack_type.rb index 151097b5bb..e46c055d85 100644 --- a/app/models/managed_reports/indicators/facility_attack_type.rb +++ b/app/models/managed_reports/indicators/facility_attack_type.rb @@ -4,8 +4,6 @@ # An indicator that returns the facility attack type of violation type attack on schools/hospitals class ManagedReports::Indicators::FacilityAttackType < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'facility_attack_type' diff --git a/app/models/managed_reports/indicators/factors_of_recruitment.rb b/app/models/managed_reports/indicators/factors_of_recruitment.rb index f9cefae4a8..c278187713 100644 --- a/app/models/managed_reports/indicators/factors_of_recruitment.rb +++ b/app/models/managed_reports/indicators/factors_of_recruitment.rb @@ -4,8 +4,6 @@ # An indicator that returns the factor of recruitment of violation type Recruitment class ManagedReports::Indicators::FactorsOfRecruitment < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'factors_of_recruitment' @@ -51,11 +49,5 @@ def sql(current_user, params = {}) # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/PerceivedComplexity - - def build_data_values(values) - values.map do |value| - JSON.parse(value['data']).merge({ 'id' => value['name'].gsub('"', '') }) - end - end end end diff --git a/app/models/managed_reports/indicators/field_by_age_sex.rb b/app/models/managed_reports/indicators/field_by_age_sex.rb new file mode 100644 index 0000000000..1d8d9bdf31 --- /dev/null +++ b/app/models/managed_reports/indicators/field_by_age_sex.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# An indicator that returns the total cases by a specified field, age and sex +class ManagedReports::Indicators::FieldByAgeSex < ManagedReports::SqlReportIndicator + class << self + def id + raise NotImplementedError + end + + def field_name + raise NotImplementedError + end + + def multiple_field_values + false + end + + def reporting_location_field? + false + end + + def field_value(field_param) + return if reporting_location_field? + + return equal_value_query_multiple(field_param) if multiple_field_values + + equal_value_query(field_param) + end + + # rubocop:disable Metrics/MethodLength + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/CyclomaticComplexity + # rubocop:disable Metrics/PerceivedComplexity + def sql(current_user, params = {}) + date_param = filter_date(params) + %{ + with #{id}_by_sex_and_age as ( + select + data->> 'sex' as name, + #{age_ranges_query} as key, + #{grouped_date_query(params['grouped_by'], filter_date(params))&.concat(' as group_id,')} + count(*) as sum + from cases + where 1 = 1 + #{equal_value_query_multiple(params['owned_by_groups'])&.prepend('and ')} + #{equal_value_query_multiple(params['created_by_groups'])&.prepend('and ')} + #{equal_value_query_multiple(params['owned_by_agency_id'])&.prepend('and ')} + #{equal_value_query_multiple(params['created_organization'])&.prepend('and ')} + #{equal_value_query_multiple(params['status'])&.prepend('and ')} + #{date_range_query(date_param)&.prepend('and ')} + #{equal_value_query(params['module_id'])&.prepend('and ')} + #{field_value(params[field_name])&.prepend('and ')} + #{user_scope_query(current_user)&.prepend('and ')} + #{reporting_location_query(params['location'], field_name)&.prepend('and ')} + group by name, key + #{grouped_date_query(params['grouped_by'], date_param)&.prepend(', ')} + order by name, key + ) + select + name, key, sum #{params['grouped_by'].present? ? ', group_id' : ''} + from #{id}_by_sex_and_age + union all + select + name, + 'total' as key, + cast(sum(sum) as integer) as sum + #{params['grouped_by'].present? ? ', group_id' : ''} + from #{id}_by_sex_and_age + group by name #{params['grouped_by'].present? ? ', group_id' : ''} + union all + select + 'total' as name, + key, + cast(sum(sum) as integer) as sum + #{params['grouped_by'].present? ? ', group_id' : ''} + from #{id}_by_sex_and_age + group by key #{params['grouped_by'].present? ? ', group_id' : ''} + union all + select + 'total' as name, + 'total' as key, + cast(sum(sum) as integer) as sum + #{params['grouped_by'].present? ? ', group_id' : ''} + from #{id}_by_sex_and_age + #{params['grouped_by'].present? ? 'group by group_id' : ''} + } + end + # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/CyclomaticComplexity + # rubocop:enable Metrics/PerceivedComplexity + end +end diff --git a/app/models/managed_reports/indicators/followups.rb b/app/models/managed_reports/indicators/followups.rb new file mode 100644 index 0000000000..757b246e44 --- /dev/null +++ b/app/models/managed_reports/indicators/followups.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# An indicator that returns the total cases by protection_concerns and sex +class ManagedReports::Indicators::Followups < ManagedReports::Indicators::SubformFieldByAgeSex + class << self + def id + 'followups' + end + + def field_name + 'followup_type' + end + + def subform_section + 'followup_subform_section' + end + + def date_filter_nested? + true + end + + def multiple_field_values + true + end + end +end diff --git a/app/models/managed_reports/indicators/incident_attack_on.rb b/app/models/managed_reports/indicators/incident_attack_on.rb index 155f3da9b7..60ab7cdfa8 100644 --- a/app/models/managed_reports/indicators/incident_attack_on.rb +++ b/app/models/managed_reports/indicators/incident_attack_on.rb @@ -4,8 +4,6 @@ # An indicator that returns the IncidentAttackOn class ManagedReports::Indicators::IncidentAttackOn < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'violation' @@ -14,13 +12,15 @@ def id # rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/CyclomaticComplexity # rubocop:disable Metrics/PerceivedComplexity + # rubocop:disable Metrics/MethodLength def sql(current_user, params = {}) %{ select + 'violation' as id, #{grouped_date_query(params['grouped_by'], filter_date(params), table_name_for_query(params))&.concat(' as group_id,')} - count(violations.id) as sum + count(violations.id) as total from violations violations inner join incidents incidents on incidents.id = violations.incident_id @@ -36,11 +36,6 @@ def sql(current_user, params = {}) # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/PerceivedComplexity - - def build_data_values(values) - values.map do |value| - { id: 'violation', total: value['sum'] } - end - end + # rubocop:enable Metrics/MethodLength end end diff --git a/app/models/managed_reports/indicators/incident_denials.rb b/app/models/managed_reports/indicators/incident_denials.rb index ebc7864d34..9eb203cbeb 100644 --- a/app/models/managed_reports/indicators/incident_denials.rb +++ b/app/models/managed_reports/indicators/incident_denials.rb @@ -4,8 +4,6 @@ # An indicator that returns the IncidentDenials class ManagedReports::Indicators::IncidentDenials < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'violation' @@ -14,13 +12,15 @@ def id # rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/CyclomaticComplexity # rubocop:disable Metrics/PerceivedComplexity + # rubocop:disable Metrics/MethodLength def sql(current_user, params = {}) %{ select + 'denial_humanitarian_access' as id, #{grouped_date_query(params['grouped_by'], filter_date(params), table_name_for_query(params))&.concat(' as group_id,')} - count(violations.id) as sum + count(violations.id) as total from violations violations inner join incidents incidents on incidents.id = violations.incident_id @@ -36,11 +36,6 @@ def sql(current_user, params = {}) # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/PerceivedComplexity - - def build_data_values(values) - values.map do |value| - { id: 'denial_humanitarian_access', total: value['sum'] } - end - end + # rubocop:enable Metrics/MethodLength end end diff --git a/app/models/managed_reports/indicators/incident_violence_type_by_sex_and_age.rb b/app/models/managed_reports/indicators/incident_violence_type_by_sex_and_age.rb index e93ffc16e1..776cbcbceb 100644 --- a/app/models/managed_reports/indicators/incident_violence_type_by_sex_and_age.rb +++ b/app/models/managed_reports/indicators/incident_violence_type_by_sex_and_age.rb @@ -4,8 +4,6 @@ # An indicator that returns the total incidents by workflow and sex class ManagedReports::Indicators::IncidentViolenceTypeBySexAndAge < ManagedReports::SqlReportIndicator - include ManagedReports::WeekIndicatorHelper - class << self def id 'incident_violence_type_by_sex_and_age' diff --git a/app/models/managed_reports/indicators/incident_workflow_by_sex_and_age.rb b/app/models/managed_reports/indicators/incident_workflow_by_sex_and_age.rb index 8bfc6cce0f..19bcc5f93f 100644 --- a/app/models/managed_reports/indicators/incident_workflow_by_sex_and_age.rb +++ b/app/models/managed_reports/indicators/incident_workflow_by_sex_and_age.rb @@ -4,8 +4,6 @@ # An indicator that returns the total of incidents by sex and age class ManagedReports::Indicators::IncidentWorkflowBySexAndAge < ManagedReports::SqlReportIndicator - include ManagedReports::WeekIndicatorHelper - class << self def id 'incident_workflow_by_sex_and_age' diff --git a/app/models/managed_reports/indicators/incidents_first_point_of_contact.rb b/app/models/managed_reports/indicators/incidents_first_point_of_contact.rb index 67cff3f06e..9b4fc0a359 100644 --- a/app/models/managed_reports/indicators/incidents_first_point_of_contact.rb +++ b/app/models/managed_reports/indicators/incidents_first_point_of_contact.rb @@ -13,7 +13,7 @@ def sql(current_user, params = {}) date_param = filter_date(params) %{ select - 'incidents_first_point_of_contact' as id, + 'incidents' as id, #{grouped_date_query(params['grouped_by'], date_param)&.concat(' as group_id,')} count(*) as total from incidents diff --git a/app/models/managed_reports/indicators/incidents_from_other_service_provider.rb b/app/models/managed_reports/indicators/incidents_from_other_service_provider.rb index b94b62a508..93e0726d81 100644 --- a/app/models/managed_reports/indicators/incidents_from_other_service_provider.rb +++ b/app/models/managed_reports/indicators/incidents_from_other_service_provider.rb @@ -13,7 +13,7 @@ def sql(current_user, params = {}) date_param = filter_date(params) %{ select - 'incidents_from_other_service_provider' as id, + 'incidents' as id, #{grouped_date_query(params['grouped_by'], date_param)&.concat(' as group_id,')} count(*) as total from incidents diff --git a/app/models/managed_reports/indicators/individual_age.rb b/app/models/managed_reports/indicators/individual_age.rb index 195702801f..fc1632b47c 100644 --- a/app/models/managed_reports/indicators/individual_age.rb +++ b/app/models/managed_reports/indicators/individual_age.rb @@ -4,8 +4,6 @@ # An indicator that returns the individual age class ManagedReports::Indicators::IndividualAge < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'individual_age' @@ -41,7 +39,7 @@ def sql(current_user, params = {}) #{date_range_query(params['date_of_first_report'], 'incidents')&.prepend('and ')} #{date_range_query(params['ctfmr_verified_date'], 'violations')&.prepend('and ')} #{equal_value_query(params['ctfmr_verified'], 'violations')&.prepend('and ')} - #{equal_value_query_multiple(params['violation_type'], 'violations', 'type')&.prepend('and ')} + #{equal_value_query_multiple(params['violation_type'], 'violations', 'data', 'type')&.prepend('and ')} ) individual_children group by #{age_ranges_query('individual_age', 'individual_children', false)}, diff --git a/app/models/managed_reports/indicators/individual_perpetrator.rb b/app/models/managed_reports/indicators/individual_perpetrator.rb index 882c4fe1a2..04d46b751e 100644 --- a/app/models/managed_reports/indicators/individual_perpetrator.rb +++ b/app/models/managed_reports/indicators/individual_perpetrator.rb @@ -4,8 +4,6 @@ # An indicator that returns the individual perpetrators class ManagedReports::Indicators::IndividualPerpetrator < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'individual_perpetrator' @@ -42,7 +40,7 @@ def sql(current_user, params = {}) #{date_range_query(params['date_of_first_report'], 'incidents')&.prepend('and ')} #{date_range_query(params['ctfmr_verified_date'], 'violations')&.prepend('and ')} #{equal_value_query(params['ctfmr_verified'], 'violations')&.prepend('and ')} - #{equal_value_query_multiple(params['violation_type'], 'violations', 'type')&.prepend('and ')} + #{equal_value_query_multiple(params['violation_type'], 'violations', 'data', 'type')&.prepend('and ')} ) as individual_perpetrators group by name #{grouped_date_query(params['grouped_by'], filter_date(params), 'individual_perpetrators')&.prepend(', ')} diff --git a/app/models/managed_reports/indicators/individual_region.rb b/app/models/managed_reports/indicators/individual_region.rb index c7d3c7fcbd..91be75c921 100644 --- a/app/models/managed_reports/indicators/individual_region.rb +++ b/app/models/managed_reports/indicators/individual_region.rb @@ -4,8 +4,6 @@ # An indicator that returns the individual region class ManagedReports::Indicators::IndividualRegion < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'individual_region' @@ -45,7 +43,7 @@ def sql(current_user, params = {}) #{date_range_query(params['date_of_first_report'], 'incidents')&.prepend('and ')} #{date_range_query(params['ctfmr_verified_date'], 'violations')&.prepend('and ')} #{equal_value_query(params['ctfmr_verified'], 'violations')&.prepend('and ')} - #{equal_value_query_multiple(params['violation_type'], 'violations', 'type')&.prepend('and ')} + #{equal_value_query_multiple(params['violation_type'], 'violations', 'data', 'type')&.prepend('and ')} ) individual_children group by individual_children.incident_location, diff --git a/app/models/managed_reports/indicators/individual_violation_type.rb b/app/models/managed_reports/indicators/individual_violation_type.rb index a7749a25ba..409429cc8d 100644 --- a/app/models/managed_reports/indicators/individual_violation_type.rb +++ b/app/models/managed_reports/indicators/individual_violation_type.rb @@ -4,8 +4,6 @@ # An indicator that returns the individual violation types class ManagedReports::Indicators::IndividualViolationType < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'individual_violation_type' @@ -36,7 +34,7 @@ def sql(current_user, params = {}) #{date_range_query(params['date_of_first_report'], 'incidents')&.prepend('and ')} #{date_range_query(params['ctfmr_verified_date'], 'violations')&.prepend('and ')} #{equal_value_query(params['ctfmr_verified'], 'violations')&.prepend('and ')} - #{equal_value_query_multiple(params['violation_type'], 'violations', 'type')&.prepend('and ')} + #{equal_value_query_multiple(params['violation_type'], 'violations', 'data', 'type')&.prepend('and ')} group by violations.data ->> 'type', name #{grouped_date_query(params['grouped_by'], filter_date(params), table_name_for_query(params))&.prepend(', ')} order by name diff --git a/app/models/managed_reports/indicators/military_use.rb b/app/models/managed_reports/indicators/military_use.rb index b7a141b46a..e09959f965 100644 --- a/app/models/managed_reports/indicators/military_use.rb +++ b/app/models/managed_reports/indicators/military_use.rb @@ -4,8 +4,6 @@ # An indicator that returns the reporting locations of violation type detention class ManagedReports::Indicators::MilitaryUse < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'military_use_type_of_use' diff --git a/app/models/managed_reports/indicators/perpetrators.rb b/app/models/managed_reports/indicators/perpetrators.rb index ae2393cc19..66c9f4b271 100644 --- a/app/models/managed_reports/indicators/perpetrators.rb +++ b/app/models/managed_reports/indicators/perpetrators.rb @@ -4,8 +4,6 @@ # An indicator that returns the perpetators of violation type killing class ManagedReports::Indicators::Perpetrators < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'perpetrators' diff --git a/app/models/managed_reports/indicators/perpetrators_denials.rb b/app/models/managed_reports/indicators/perpetrators_denials.rb index acd9022775..ddfcf3a6a8 100644 --- a/app/models/managed_reports/indicators/perpetrators_denials.rb +++ b/app/models/managed_reports/indicators/perpetrators_denials.rb @@ -4,8 +4,6 @@ # An indicator that returns the perpetators of violation type Denials class ManagedReports::Indicators::PerpetratorsDenials < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'perpetrators_denial' diff --git a/app/models/managed_reports/indicators/perpetrators_detention.rb b/app/models/managed_reports/indicators/perpetrators_detention.rb index 9728f2b2ea..94477c4ec3 100644 --- a/app/models/managed_reports/indicators/perpetrators_detention.rb +++ b/app/models/managed_reports/indicators/perpetrators_detention.rb @@ -4,8 +4,6 @@ # An indicator that returns the perpetators of individual victioms - detention class ManagedReports::Indicators::PerpetratorsDetention < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'perpetrator_detention' @@ -54,14 +52,5 @@ def sql(current_user, params = {}) # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/PerceivedComplexity - - def build_data_values(values) - values.each_with_object([]) do |curr, acc| - current_group = acc.find { |group| group[:id] == curr['name'] } - next current_group[curr['key'].to_sym] = curr['sum'] if current_group.present? - - acc << { id: curr['name'], curr['key'].to_sym => curr['sum'], total: curr['total'] } - end - end end end diff --git a/app/models/managed_reports/indicators/protection_concerns.rb b/app/models/managed_reports/indicators/protection_concerns.rb new file mode 100644 index 0000000000..c61861c8b8 --- /dev/null +++ b/app/models/managed_reports/indicators/protection_concerns.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# An indicator that returns the total cases by protection_concerns and sex +class ManagedReports::Indicators::ProtectionConcerns < ManagedReports::Indicators::FieldByAgeSex + class << self + def id + 'protection_concerns' + end + + def field_name + 'protection_concerns' + end + + def multiple_field_values + true + end + end +end diff --git a/app/models/managed_reports/indicators/reporting_location.rb b/app/models/managed_reports/indicators/reporting_location.rb index 45b24beefa..3fdee3659d 100644 --- a/app/models/managed_reports/indicators/reporting_location.rb +++ b/app/models/managed_reports/indicators/reporting_location.rb @@ -4,8 +4,6 @@ # An indicator that returns the reporting locations of violation type killing class ManagedReports::Indicators::ReportingLocation < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'reporting_location' diff --git a/app/models/managed_reports/indicators/reporting_location_by_sex_and_age.rb b/app/models/managed_reports/indicators/reporting_location_by_sex_and_age.rb new file mode 100644 index 0000000000..4e599f4b0a --- /dev/null +++ b/app/models/managed_reports/indicators/reporting_location_by_sex_and_age.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# An indicator that returns the total cases by workflow and sex +class ManagedReports::Indicators::ReportingLocationBySexAndAge < ManagedReports::Indicators::FieldByAgeSex + class << self + def id + 'reporting_location_by_sex_and_age' + end + + def field_name + SystemSettings.current.reporting_location_config&.field_key || ReportingLocation::DEFAULT_FIELD_KEY + end + + def reporting_location_field? + true + end + end +end diff --git a/app/models/managed_reports/indicators/reporting_location_denials.rb b/app/models/managed_reports/indicators/reporting_location_denials.rb index 2880b8c100..989466c578 100644 --- a/app/models/managed_reports/indicators/reporting_location_denials.rb +++ b/app/models/managed_reports/indicators/reporting_location_denials.rb @@ -4,8 +4,6 @@ # An indicator that returns the reporting locations of violation type denial class ManagedReports::Indicators::ReportingLocationDenials < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'reporting_location_denial' diff --git a/app/models/managed_reports/indicators/reporting_location_detention.rb b/app/models/managed_reports/indicators/reporting_location_detention.rb index fba00f05f3..e31a1929b6 100644 --- a/app/models/managed_reports/indicators/reporting_location_detention.rb +++ b/app/models/managed_reports/indicators/reporting_location_detention.rb @@ -4,8 +4,6 @@ # An indicator that returns the reporting locations for individual victioms -detention class ManagedReports::Indicators::ReportingLocationDetention < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'reporting_location_detention' @@ -62,14 +60,5 @@ def user_reporting_location_admin_level(current_user) # Adding one since admin level start from 0, but string on postgres start from 1 current_user.role.incident_reporting_location_config&.admin_level.to_i + 1 end - - def build_data_values(values) - values.each_with_object([]) do |curr, acc| - current_group = acc.find { |group| group[:id] == curr['name'] } - next current_group[curr['key'].to_sym] = curr['sum'] if current_group.present? - - acc << { id: curr['name'], curr['key'].to_sym => curr['sum'], total: curr['total'] } - end - end end end diff --git a/app/models/managed_reports/indicators/services.rb b/app/models/managed_reports/indicators/services.rb new file mode 100644 index 0000000000..06039baa74 --- /dev/null +++ b/app/models/managed_reports/indicators/services.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# An indicator that returns the total cases by protection_concerns and sex +class ManagedReports::Indicators::Services < ManagedReports::Indicators::SubformFieldByAgeSex + class << self + def id + 'services' + end + + def field_name + 'service_type' + end + + def subform_section + 'services_section' + end + + def date_filter_nested? + true + end + + def multiple_field_values + true + end + end +end diff --git a/app/models/managed_reports/indicators/sexual_violence_type.rb b/app/models/managed_reports/indicators/sexual_violence_type.rb index 3f6a887e30..9248b27298 100644 --- a/app/models/managed_reports/indicators/sexual_violence_type.rb +++ b/app/models/managed_reports/indicators/sexual_violence_type.rb @@ -4,8 +4,6 @@ # An indicator that returns the sexual violence type of violation type rape class ManagedReports::Indicators::SexualViolenceType < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'sexual_violence_type' @@ -51,11 +49,5 @@ def sql(current_user, params = {}) # rubocop:enable Metrics/MethodLength # rubocop:enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/PerceivedComplexity - - def build_data_values(values) - values.map do |value| - JSON.parse(value['data']).merge({ id: value['name'].gsub('"', '') }) - end - end end end diff --git a/app/models/managed_reports/indicators/subform_field_by_age_sex.rb b/app/models/managed_reports/indicators/subform_field_by_age_sex.rb new file mode 100644 index 0000000000..1a633c6e18 --- /dev/null +++ b/app/models/managed_reports/indicators/subform_field_by_age_sex.rb @@ -0,0 +1,108 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# An indicator that returns the total cases by a specified field, age and sex +class ManagedReports::Indicators::SubformFieldByAgeSex < ManagedReports::SqlReportIndicator + class << self + def id + raise NotImplementedError + end + + def field_name + raise NotImplementedError + end + + def multiple_field_values + false + end + + def subform_section; end + + def date_filter_nested? + false + end + + def field_value(field_param) + return equal_value_query_multiple(field_param, 'subform_section', nil) if multiple_field_values + + equal_value_query(field_param, 'subform_section', nil) + end + + def date_value_query(date_param) + return date_range_query(date_param, '', 'subform_section') if date_filter_nested? + + date_range_query(date_param) + end + + def field_grouped_date_query(grouped_by_param, date_param) + return grouped_date_query(grouped_by_param, date_param, nil, 'subform_section') if date_filter_nested? + + grouped_date_query(grouped_by_param, date_param) + end + + # rubocop:disable Metrics/MethodLength + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/CyclomaticComplexity + # rubocop:disable Metrics/PerceivedComplexity + def sql(current_user, params = {}) + date_param = filter_date(params) + + %{ + with #{id}_by_sex_and_age as ( + select + data->> 'sex' as name, + #{age_ranges_query} as key, + #{field_grouped_date_query(params['grouped_by'], filter_date(params))&.concat(' as group_id,')} + count(*) as sum + from cases + cross join jsonb_array_elements(cases.data -> '#{subform_section}') as subform_section + where 1 = 1 + #{equal_value_query_multiple(params['owned_by_groups'])&.prepend('and ')} + #{equal_value_query_multiple(params['created_by_groups'])&.prepend('and ')} + #{equal_value_query_multiple(params['owned_by_agency_id'])&.prepend('and ')} + #{equal_value_query_multiple(params['created_organization'])&.prepend('and ')} + #{equal_value_query_multiple(params['status'])&.prepend('and ')} + #{date_value_query(date_param)&.prepend('and ')} + #{equal_value_query(params['module_id'])&.prepend('and ')} + #{field_value(params[field_name])&.prepend('and ')} + #{user_scope_query(current_user)&.prepend('and ')} + group by name, key + #{field_grouped_date_query(params['grouped_by'], date_param)&.prepend(', ')} + order by name, key + ) + select + name, key, sum #{params['grouped_by'].present? ? ', group_id' : ''} + from #{id}_by_sex_and_age + union all + select + name, + 'total' as key, + cast(sum(sum) as integer) as sum + #{params['grouped_by'].present? ? ', group_id' : ''} + from #{id}_by_sex_and_age + group by name #{params['grouped_by'].present? ? ', group_id' : ''} + union all + select + 'total' as name, + key, + cast(sum(sum) as integer) as sum + #{params['grouped_by'].present? ? ', group_id' : ''} + from #{id}_by_sex_and_age + group by key #{params['grouped_by'].present? ? ', group_id' : ''} + union all + select + 'total' as name, + 'total' as key, + cast(sum(sum) as integer) as sum + #{params['grouped_by'].present? ? ', group_id' : ''} + from #{id}_by_sex_and_age + #{params['grouped_by'].present? ? 'group by group_id' : ''} + } + end + # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/CyclomaticComplexity + # rubocop:enable Metrics/PerceivedComplexity + end +end diff --git a/app/models/managed_reports/indicators/total_gbv_sexual_violence.rb b/app/models/managed_reports/indicators/total_gbv_sexual_violence.rb index 5d4e980961..3c93b5c2d3 100644 --- a/app/models/managed_reports/indicators/total_gbv_sexual_violence.rb +++ b/app/models/managed_reports/indicators/total_gbv_sexual_violence.rb @@ -13,7 +13,7 @@ def sql(current_user, params = {}) date_param = filter_date(params) %{ select - 'gbv_sexual_violence_type' as id, + 'incidents' as id, #{grouped_date_query(params['grouped_by'], date_param)&.concat(' as group_id,')} count(*) as total from incidents diff --git a/app/models/managed_reports/indicators/total_referrals_by_user_groups.rb b/app/models/managed_reports/indicators/total_referrals_by_user_groups.rb index f7c29d88f8..d9e1209797 100644 --- a/app/models/managed_reports/indicators/total_referrals_by_user_groups.rb +++ b/app/models/managed_reports/indicators/total_referrals_by_user_groups.rb @@ -4,8 +4,6 @@ # An indicator that returns the total of referrals by user groups class ManagedReports::Indicators::TotalReferralsByUserGroups < ManagedReports::SqlReportIndicator - include ManagedReports::WeekIndicatorHelper - class << self def id 'total_referrals_by_user_groups' diff --git a/app/models/managed_reports/indicators/total_transfers_by_user_groups.rb b/app/models/managed_reports/indicators/total_transfers_by_user_groups.rb index 2dd4aca58e..40a00ee28f 100644 --- a/app/models/managed_reports/indicators/total_transfers_by_user_groups.rb +++ b/app/models/managed_reports/indicators/total_transfers_by_user_groups.rb @@ -4,8 +4,6 @@ # An indicator that returns the total of transfers by user groups class ManagedReports::Indicators::TotalTransfersByUserGroups < ManagedReports::SqlReportIndicator - include ManagedReports::WeekIndicatorHelper - class << self def id 'total_transfers_by_user_groups' diff --git a/app/models/managed_reports/indicators/type_of_use.rb b/app/models/managed_reports/indicators/type_of_use.rb index 00f8397446..b25b199412 100644 --- a/app/models/managed_reports/indicators/type_of_use.rb +++ b/app/models/managed_reports/indicators/type_of_use.rb @@ -4,8 +4,6 @@ # An indicator that returns the type of use of violation type Recruitment class ManagedReports::Indicators::TypeOfUse < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'type_of_use' diff --git a/app/models/managed_reports/indicators/violation_tally.rb b/app/models/managed_reports/indicators/violation_tally.rb index 1b21b3b502..09d8236f2e 100644 --- a/app/models/managed_reports/indicators/violation_tally.rb +++ b/app/models/managed_reports/indicators/violation_tally.rb @@ -4,8 +4,6 @@ # An indicator that returns the violation_tally of violation type killing class ManagedReports::Indicators::ViolationTally < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'children' diff --git a/app/models/managed_reports/indicators/violation_tally_detention.rb b/app/models/managed_reports/indicators/violation_tally_detention.rb index a952a2c517..42c738fd26 100644 --- a/app/models/managed_reports/indicators/violation_tally_detention.rb +++ b/app/models/managed_reports/indicators/violation_tally_detention.rb @@ -4,8 +4,6 @@ # An indicator that returns the violation_tally of individual victioms - detention class ManagedReports::Indicators::ViolationTallyDetention < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'children' diff --git a/app/models/managed_reports/indicators/violation_tally_response.rb b/app/models/managed_reports/indicators/violation_tally_response.rb index 6180ad9e6a..7daa8b8dc0 100644 --- a/app/models/managed_reports/indicators/violation_tally_response.rb +++ b/app/models/managed_reports/indicators/violation_tally_response.rb @@ -4,8 +4,6 @@ # An indicator that returns the violation_tally of violation type killing class ManagedReports::Indicators::ViolationTallyResponse < ManagedReports::SqlReportIndicator - include ManagedReports::MRMIndicatorHelper - class << self def id 'received_response' diff --git a/app/models/managed_reports/mrm_indicator_helper.rb b/app/models/managed_reports/mrm_indicator_helper.rb deleted file mode 100644 index 9715a61849..0000000000 --- a/app/models/managed_reports/mrm_indicator_helper.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true - -# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -# Helper methods for mrm indicators -module ManagedReports::MRMIndicatorHelper - extend ActiveSupport::Concern - # ClassMethods - module ClassMethods - def table_name_for_query(params) - return 'violations' if params['ctfmr_verified_date'].present? - - 'incidents' - end - - def group_id_alias(params_grouped_by) - return unless params_grouped_by.present? - - 'group_id' - end - - def build_results(results, params = {}) - return build_data_values(results.to_a) unless results.to_a.any? { |result| result['group_id'].present? } - - build_groups(results, params) - end - - def build_data_values(values) - values.each_with_object([]) do |curr, acc| - current_group = acc.find { |group| group[:id] == curr['name'] } - next current_group[curr['key'].to_sym] = curr['sum'] if current_group.present? - - acc << { id: curr['name'], curr['key'].to_sym => curr['sum'] } - end - end - end -end diff --git a/app/models/managed_reports/sql_query_helpers.rb b/app/models/managed_reports/sql_query_helpers.rb index da2acd6095..59b55900be 100644 --- a/app/models/managed_reports/sql_query_helpers.rb +++ b/app/models/managed_reports/sql_query_helpers.rb @@ -25,7 +25,20 @@ def equal_value_query(param, table_name = nil, hash_field = 'data', map_to = nil ) end - def equal_value_query_multiple(param, table_name = nil, map_to = nil) + def equal_value_query_multiple(param, table_name = nil, hash_field = 'data', map_to = nil) + return unless param.present? + + field_name = map_to || param.field_name + + ActiveRecord::Base.sanitize_sql_for_conditions( + [ + "#{quoted_query(table_name, hash_field)}->:field_name ?| array[:values]", + { values: param.respond_to?(:values) ? param.values : param.value, field_name: } + ] + ) + end + + def equal_value_nested_query(param, _nested_field, table_name = nil, map_to = nil) return unless param.present? field_name = map_to || param.field_name @@ -38,6 +51,35 @@ def equal_value_query_multiple(param, table_name = nil, map_to = nil) ) end + # rubocop:disable Metrics/MethodLength + def reporting_location_query(param, map_to = nil) + return unless param.present? + + field_name = map_to || param.field_name + param_value = param.respond_to?(:values) ? param.values : param.value + + ActiveRecord::Base.sanitize_sql_for_conditions( + [ + %( + ( + data ? :field_name AND data->>:field_name IS NOT NULL AND EXISTS + ( + SELECT + 1 + FROM locations + INNER JOIN locations AS descendants + ON locations.admin_level <= descendants.admin_level + AND locations.hierarchy_path @> descendants.hierarchy_path + WHERE locations.location_code = :param_value AND descendants.location_code = data->>:field_name + ) + ) + ), + { param_value:, field_name: } + ] + ) + end + # rubocop:enable Metrics/MethodLength + def in_value_query(param, table_name = nil, _hash_field = 'data', map_to = nil) return unless param.present? @@ -49,6 +91,7 @@ def in_value_query(param, table_name = nil, _hash_field = 'data', map_to = nil) ) end + # rubocop:disable Metrics/MethodLength def date_range_query(param, table_name = nil, hash_field = 'data', map_to = nil) return unless param.present? @@ -57,18 +100,35 @@ def date_range_query(param, table_name = nil, hash_field = 'data', map_to = nil) return date_range_hash_query(param, field_name, table_name, hash_field) if hash_field.present? ActiveRecord::Base.sanitize_sql_for_conditions( - ["#{quoted_query(table_name, field_name)} between ? and ?", param.from, param.to] + [ + %( + CAST(#{quoted_query(table_name, field_name)} AS TIMESTAMP) >= to_timestamp(:from, :date_format) + AND CAST(#{quoted_query(table_name, field_name)} AS TIMESTAMP) <= ( + to_timestamp(:to, :date_format) + interval '1 day' - interval '1 second' + ) + ), { from: param.from, to: param.to, date_format: Report::DATE_FORMAT } + ] ) end + # rubocop:enable Metrics/MethodLength + # rubocop:disable Metrics/MethodLength def date_range_hash_query(param, field_name, table_name = nil, hash_field = 'data') ActiveRecord::Base.sanitize_sql_for_conditions( [ - "to_timestamp(#{quoted_query(table_name, hash_field)} ->> ?, ?) between ? and ?", - field_name, Report::DATE_TIME_FORMAT, param.from, param.to + %( + to_timestamp( + #{quoted_query(table_name, hash_field)} ->> :field_name, :date_format + ) >= to_timestamp(:from, :date_format) + AND to_timestamp( + #{quoted_query(table_name, hash_field)} ->> :field_name, :date_format + ) <= to_timestamp(:to, :date_format) + interval '1 day' - interval '1 second' + ), + { field_name:, date_format: Report::DATE_FORMAT, from: param.from, to: param.to } ] ) end + # rubocop:enable Metrics/MethodLength def agency_scope_query(current_user, table_name = nil) ActiveRecord::Base.sanitize_sql_for_conditions( @@ -100,7 +160,8 @@ def self_scope_query(current_user, table_name = nil) def quoted_query(table_name, column_name) return ActiveRecord::Base.connection.quote_column_name(column_name) if table_name.blank? - "#{quoted_table_name(table_name)}.#{ActiveRecord::Base.connection.quote_column_name(column_name)}" + quoted_column_name = column_name.present? ? ActiveRecord::Base.connection.quote_column_name(column_name) : nil + [quoted_table_name(table_name), quoted_column_name].compact.join('.') end def quoted_table_name(table_name) diff --git a/app/models/managed_reports/sql_report_indicator.rb b/app/models/managed_reports/sql_report_indicator.rb index 96d4a9bf2d..78375ea43c 100644 --- a/app/models/managed_reports/sql_report_indicator.rb +++ b/app/models/managed_reports/sql_report_indicator.rb @@ -26,9 +26,15 @@ def build(current_user = nil, params = {}) def build_results(results, params = {}) results_array = results.to_a - return results_array unless results_array.any? { |result| result['group_id'].present? } - - build_groups(results_array, params) + if results_array.any? { |result| result.key?('group_id') } + build_groups(results_array, params) + elsif results_array.any? { |result| result.key?('data') } + build_data_values_from_json(results_array) + elsif results_array.any? { |result| result.key?('key') } + build_data_values_from_keys(results_array) + else + results_array + end end def build_ranges(params = {}) @@ -44,22 +50,29 @@ def range_by_group(grouped_by_value, date_range) case grouped_by_value when QUARTER then date_range.map { |date| "#{date.year}-Q#{(date.month / 3.0).ceil}" }.uniq when MONTH then date_range.map { |date| "#{date.year}-#{date.strftime('%m')}" }.uniq + when WEEK then range_by_week(date_range) else date_range.map(&:year).uniq end end + def range_by_week(date_range) + date_range.map do |date| + "#{date.beginning_of_week.strftime('%Y-%m-%d')} - #{date.end_of_week.strftime('%Y-%m-%d')}" + end.uniq + end + def build_groups(results, params = {}) build_ranges(params).map do |current_range| values_range = results.select { |result| result['group_id'] == current_range } - { - group_id: current_range, - data: build_data_values(values_range) - } + { group_id: current_range, data: build_data_values(values_range) } end end def build_data_values(values) + return build_data_values_from_json(values) if values.any? { |value| value.key?('data') } + return build_data_values_from_keys(values) if values.any? { |value| value.key?('key') } + values.each_with_object([]) do |curr, acc| curr.delete('group_id') @@ -67,6 +80,26 @@ def build_data_values(values) end end + def build_data_values_from_keys(values) + values.each_with_object([]) do |curr, acc| + current_group = acc.find { |group| group[:id] == curr['name'] } + next current_group[curr['key'].to_sym] = curr['sum'] if current_group.present? + + acc << value_to_data_element(curr) + end + end + + def value_to_data_element(value) + element = { id: value['name'], value['key'].to_sym => value['sum'] } + return element unless value.key?('total') + + element.merge(total: value['total']) + end + + def build_data_values_from_json(values) + values.map { |value| JSON.parse(value['data']).merge({ 'id' => value['name'].gsub('"', '') }) } + end + def user_scope_query(current_user, table_name = nil) return if current_user.blank? || current_user.managed_report_scope_all? @@ -85,6 +118,7 @@ def grouped_date_query(grouped_by_param, date_param, table_name = nil, hash_fiel case grouped_by_param.value when QUARTER then grouped_quarter_query(date_param, table_name, hash_field, map_to) when MONTH then grouped_month_query(date_param, table_name, hash_field, map_to) + when WEEK then grouped_by_week_query(date_param, table_name, hash_field, map_to) else grouped_year_query(date_param, table_name, hash_field, map_to) end end @@ -92,6 +126,39 @@ def grouped_date_query(grouped_by_param, date_param, table_name = nil, hash_fiel def filter_date(params) params.values.find { |param| param.is_a?(SearchFilters::DateRange) } end + + # rubocop:disable Metrics/MethodLength + def grouped_by_week_query(date_param, table_name, hash_field = 'data', map_to = nil) + return unless date_param.present? + + field_name = map_to || date_param.field_name + quoted_field = grouped_date_field(field_name, table_name, hash_field) + + ActiveRecord::Base.sanitize_sql_for_conditions( + [ + %( + to_char(date_trunc('week', #{quoted_field}) - '1 days'::interval, 'yyyy-mm-dd') + || ' - ' || + to_char(date_trunc('week', #{quoted_field}) + '5 days'::interval, 'yyyy-mm-dd') + ), + grouped_date_params(field_name, hash_field) + ] + ) + end + # rubocop:enable Metrics/MethodLength + + def group_id_alias(params_grouped_by) + return unless params_grouped_by.present? + + 'group_id' + end + + def table_name_for_query(params) + return 'violations' if params['ctfmr_verified_date'].present? || + params&.[]('ghn_date_filter')&.field_name == 'ctfmr_verified_date' + + 'incidents' + end end def execute_query(current_user) diff --git a/app/models/managed_reports/sub_reports/followups.rb b/app/models/managed_reports/sub_reports/followups.rb new file mode 100644 index 0000000000..396b866a56 --- /dev/null +++ b/app/models/managed_reports/sub_reports/followups.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Describes Cases based on workflow status by gender/age subreport in Primero. +class ManagedReports::SubReports::Followups < ManagedReports::SubReport + def id + 'followups' + end + + def indicators + [ + ManagedReports::Indicators::Followups + ] + end + + def lookups + { + ManagedReports::Indicators::Followups.id => 'lookup-gender' + } + end + + def indicators_subcolumns + { + ManagedReports::Indicators::Followups.id => 'AgeRange' + } + end +end diff --git a/app/models/managed_reports/sub_reports/incidents.rb b/app/models/managed_reports/sub_reports/incidents.rb index cc485fcfef..320c79fefd 100644 --- a/app/models/managed_reports/sub_reports/incidents.rb +++ b/app/models/managed_reports/sub_reports/incidents.rb @@ -12,18 +12,31 @@ def id def indicators [ ManagedReports::Indicators::TotalIncidents, - ManagedReports::Indicators::TotalGBVSexualViolence, ManagedReports::Indicators::TotalGBVPreviousIncidents, + ManagedReports::Indicators::SurvivorsSex, + ManagedReports::Indicators::SurvivorsAge, + ManagedReports::Indicators::SurvivorsMaritalStatus, + ManagedReports::Indicators::SurvivorsDisplacementStatus, + ManagedReports::Indicators::SurvivorsDisplacementIncident, + ManagedReports::Indicators::SurvivorsVulnerablePopulations, + ManagedReports::Indicators::TotalGBVSexualViolence, ManagedReports::Indicators::GBVSexualViolenceType, ManagedReports::Indicators::IncidentTimeofday, + ManagedReports::Indicators::GBVCaseContext, ManagedReports::Indicators::ElapsedReportingTime, ManagedReports::Indicators::ElapsedReportingTimeRape, ManagedReports::Indicators::ElapsedReportingTimeRapeHealthReferral, ManagedReports::Indicators::IncidentLocationType, - ManagedReports::Indicators::GBVCaseContext + ManagedReports::Indicators::NumberOfPerpetrators, + ManagedReports::Indicators::PerpetratorRelationship, + ManagedReports::Indicators::PerpetratorAgeGroup, + ManagedReports::Indicators::PerpetratorOccupation, + ManagedReports::Indicators::IncidentsFirstPointOfContact, + ManagedReports::Indicators::IncidentsFromOtherServiceProvider, + ManagedReports::Indicators::SurvivorsNumberOfServicesProvided, + ManagedReports::Indicators::SurvivorsNumberOfServicesProvidedOther ].freeze end - # rubocop:enable Metrics/MethodLength def lookups { @@ -33,7 +46,17 @@ def lookups ManagedReports::Indicators::ElapsedReportingTimeRape.id => 'lookup-elapsed-reporting-time', ManagedReports::Indicators::ElapsedReportingTimeRapeHealthReferral.id => 'lookup-elapsed-reporting-time', ManagedReports::Indicators::IncidentLocationType.id => 'lookup-gbv-incident-location-type', - ManagedReports::Indicators::GBVCaseContext.id => 'lookup-gbv-case-context' + ManagedReports::Indicators::GBVCaseContext.id => 'lookup-gbv-case-context', + ManagedReports::Indicators::SurvivorsSex.id => 'lookup-gender', + ManagedReports::Indicators::SurvivorsMaritalStatus.id => 'lookup-marital-status', + ManagedReports::Indicators::SurvivorsDisplacementStatus.id => 'lookup-displacement-status', + ManagedReports::Indicators::SurvivorsDisplacementIncident.id => 'lookup-displacement-incident', + ManagedReports::Indicators::SurvivorsVulnerablePopulations.id => 'lookup-unaccompanied-separated-status', + ManagedReports::Indicators::NumberOfPerpetrators.id => 'lookup-number-of-perpetrators', + ManagedReports::Indicators::PerpetratorRelationship.id => 'lookup-perpetrator-relationship', + ManagedReports::Indicators::PerpetratorAgeGroup.id => 'lookup-perpetrator-age-group', + ManagedReports::Indicators::PerpetratorOccupation.id => 'lookup-perpetrator-occupation' }.freeze end + # rubocop:enable Metrics/MethodLength end diff --git a/app/models/managed_reports/sub_reports/protection_concerns.rb b/app/models/managed_reports/sub_reports/protection_concerns.rb new file mode 100644 index 0000000000..e14c232df1 --- /dev/null +++ b/app/models/managed_reports/sub_reports/protection_concerns.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Describes Cases based on workflow status by gender/age subreport in Primero. +class ManagedReports::SubReports::ProtectionConcerns < ManagedReports::SubReport + def id + 'protection_concerns' + end + + def indicators + [ + ManagedReports::Indicators::ProtectionConcerns + ] + end + + def lookups + { + ManagedReports::Indicators::ProtectionConcerns.id => 'lookup-gender' + } + end + + def indicators_subcolumns + { + ManagedReports::Indicators::ProtectionConcerns.id => 'AgeRange' + } + end +end diff --git a/app/models/managed_reports/sub_reports/reporting_locations.rb b/app/models/managed_reports/sub_reports/reporting_locations.rb new file mode 100644 index 0000000000..29edee66c8 --- /dev/null +++ b/app/models/managed_reports/sub_reports/reporting_locations.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Describes Cases based on workflow status by gender/age subreport in Primero. +class ManagedReports::SubReports::ReportingLocations < ManagedReports::SubReport + def id + 'reporting_locations' + end + + def indicators + [ + ManagedReports::Indicators::ReportingLocationBySexAndAge + ] + end + + def lookups + { + ManagedReports::Indicators::ReportingLocationBySexAndAge.id => 'lookup-gender' + } + end + + def indicators_subcolumns + { + ManagedReports::Indicators::ReportingLocationBySexAndAge.id => 'AgeRange' + } + end +end diff --git a/app/models/managed_reports/sub_reports/services.rb b/app/models/managed_reports/sub_reports/services.rb new file mode 100644 index 0000000000..74d5c23d80 --- /dev/null +++ b/app/models/managed_reports/sub_reports/services.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Describes Cases based on workflow status by gender/age subreport in Primero. +class ManagedReports::SubReports::Services < ManagedReports::SubReport + def id + 'services' + end + + def indicators + [ + ManagedReports::Indicators::Services + ] + end + + def lookups + { + ManagedReports::Indicators::Services.id => 'lookup-gender' + } + end + + def indicators_subcolumns + { + ManagedReports::Indicators::Services.id => 'AgeRange' + } + end +end diff --git a/app/models/managed_reports/week_indicator_helper.rb b/app/models/managed_reports/week_indicator_helper.rb deleted file mode 100644 index f04e5c2dcc..0000000000 --- a/app/models/managed_reports/week_indicator_helper.rb +++ /dev/null @@ -1,61 +0,0 @@ -# frozen_string_literal: true - -# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -# Helper methods for tsfv indicators -module ManagedReports::WeekIndicatorHelper - extend ActiveSupport::Concern - # ClassMethods - module ClassMethods - def build_results(results, params = {}) - return build_data_values(results.to_a) unless results.to_a.any? { |result| result['group_id'].present? } - - build_groups(results, params) - end - - def build_data_values(values) - values.each_with_object([]) do |curr, acc| - current_group = acc.find { |group| group[:id] == curr['name'] } - next current_group[curr['key'].to_sym] = curr['sum'] if current_group.present? - - acc << { id: curr['name'], curr['key'].to_sym => curr['sum'] } - end - end - - def range_by_group(grouped_by_value, date_range) - return super(grouped_by_value, date_range) unless grouped_by_value == ManagedReports::SqlReportIndicator::WEEK - - date_range.map do |date| - "#{date.beginning_of_week.strftime('%Y-%m-%d')} - #{date.end_of_week.strftime('%Y-%m-%d')}" - end.uniq - end - - # rubocop:disable Metrics/MethodLength - def grouped_by_week_query(date_param, table_name, hash_field = 'data', map_to = nil) - return unless date_param.present? - - field_name = map_to || date_param.field_name - quoted_field = grouped_date_field(field_name, table_name, hash_field) - - ActiveRecord::Base.sanitize_sql_for_conditions( - [ - %( - to_char(date_trunc('week', #{quoted_field}) - '1 days'::interval, 'yyyy-mm-dd') - || ' - ' || - to_char(date_trunc('week', #{quoted_field}) + '5 days'::interval, 'yyyy-mm-dd') - ), - grouped_date_params(field_name, hash_field) - ] - ) - end - # rubocop:enable Metrics/MethodLength - - def grouped_date_query(grouped_by_param, date_param, table_name = nil, hash_field = 'data', map_to = nil) - if grouped_by_param&.value == ManagedReports::SqlReportIndicator::WEEK && date_param.present? - return grouped_by_week_query(date_param, table_name, hash_field, map_to) - end - - super(grouped_by_param, date_param, table_name, hash_field, map_to) - end - end -end diff --git a/app/models/matching_configuration.rb b/app/models/matching_configuration.rb index 6a58c4dfa0..cd94949373 100644 --- a/app/models/matching_configuration.rb +++ b/app/models/matching_configuration.rb @@ -153,14 +153,14 @@ def load_matchable_fields(form_sections) def load_field_options(form_sections) form_sections.map do |fs| [fs.unique_id, fs.fields.select { |fd| fd.visible == true } - &.map { |fd| [fd.display_name, fs.unique_id + ID_SEPARATOR + fd.name] }] + &.map { |fd| [fd.display_name, fs.unique_id + ID_SEPARATOR + fd.name] }] end end def update_form_section_for_filter(form_section, matchable_forms) [form_section.unique_id, form_section.fields.select { |fd| fd.visible == true && matchable_forms[form_section.unique_id].include?(fd.name) } - &.map { |fd| [fd.display_name, fd.name] }] + &.map { |fd| [fd.display_name, fd.name] }] end def load_field_options_for_filter(form_sections, matchable_forms) diff --git a/app/models/permission.rb b/app/models/permission.rb index 9aebdad551..1822224f42 100644 --- a/app/models/permission.rb +++ b/app/models/permission.rb @@ -16,6 +16,7 @@ class Permission < ValueObject # If the role_unique_ids property is empty on a ROLE permission, then that allows this role to manage all other ROLES attr_accessor :resource, :actions, :role_unique_ids, :agency_unique_ids, :managed_report_scope + VERIFY_MRM = 'verify_mrm' READ = 'read' WRITE = 'write' ENABLE_DISABLE_RECORD = 'enable_disable_record' @@ -166,14 +167,20 @@ class Permission < ValueObject LIST_CASE_NAMES = 'list_case_names' VIOLATION_REPORT = 'violations' GBV_STATISTICS_REPORT = 'gbv_statistics' + PROTECTION_CONCERNS_REPORT = 'protection_concerns_report' + REPORTING_LOCATIONS_REPORT = 'reporting_locations_report' + FOLLOWUPS_REPORT = 'followups_report' + SERVICES_REPORT = 'services_report' GHN_REPORT = 'ghn_report' INDIVIDUAL_CHILDREN = 'individual_children' VIOLATIONS_CATEGORY_VERIFICATION_STATUS = 'violations_category_verification_status' WORKFLOW_REPORT = 'workflow_report' + CASES_WORKFLOW_REPORT = 'cases_workflow_report' VIOLENCE_TYPE_REPORT = 'violence_type_report' VIEW_FAMILY_RECORD = 'view_family_record' CASE_FROM_FAMILY = 'case_from_family' REFERRALS_TRANSFERS_REPORT = 'referrals_transfers_report' + LINK_INCIDENT_TO_CASE = 'link_incident_to_case' LINK_FAMILY_RECORD = 'link_family_record' REMOVE_ALERT = 'remove_alert' @@ -195,7 +202,7 @@ class Permission < ValueObject INCIDENT => [ READ, CREATE, WRITE, ENABLE_DISABLE_RECORD, FLAG, FLAG_RESOLVE_ANY, EXPORT_LIST_VIEW, EXPORT_CSV, EXPORT_EXCEL, EXPORT_PDF, EXPORT_INCIDENT_RECORDER, EXPORT_JSON, EXPORT_CUSTOM, IMPORT, SYNC_MOBILE, CHANGE_LOG, - EXPORT_MRM_VIOLATION_XLS, REMOVE_ALERT, ASSIGN, MANAGE + EXPORT_MRM_VIOLATION_XLS, REMOVE_ALERT, VERIFY_MRM, ASSIGN, LINK_INCIDENT_TO_CASE, MANAGE ], TRACING_REQUEST => [ READ, CREATE, WRITE, ENABLE_DISABLE_RECORD, FLAG, FLAG_RESOLVE_ANY, EXPORT_LIST_VIEW, EXPORT_CSV, EXPORT_EXCEL, @@ -216,8 +223,9 @@ class Permission < ValueObject WEBHOOK => [CREATE, READ, WRITE, DELETE, MANAGE], REPORT => [READ, GROUP_READ, AGENCY_READ, CREATE, WRITE, MANAGE], MANAGED_REPORT => [ - VIOLATION_REPORT, GBV_STATISTICS_REPORT, GHN_REPORT, INDIVIDUAL_CHILDREN, WORKFLOW_REPORT, VIOLENCE_TYPE_REPORT, - REFERRALS_TRANSFERS_REPORT + VIOLATION_REPORT, GBV_STATISTICS_REPORT, GHN_REPORT, INDIVIDUAL_CHILDREN, WORKFLOW_REPORT, + CASES_WORKFLOW_REPORT, VIOLENCE_TYPE_REPORT, REFERRALS_TRANSFERS_REPORT, PROTECTION_CONCERNS_REPORT, + FOLLOWUPS_REPORT, SERVICES_REPORT, REPORTING_LOCATIONS_REPORT ], METADATA => [MANAGE], POTENTIAL_MATCH => [READ, VIEW_AUDIO, VIEW_PHOTO, MANAGE], diff --git a/app/models/primero_configuration.rb b/app/models/primero_configuration.rb index a804703ad1..7123966612 100644 --- a/app/models/primero_configuration.rb +++ b/app/models/primero_configuration.rb @@ -5,7 +5,7 @@ # This model persists the user-modifiable state of the Primero configuration as JSON. # If desired, this configuration state can replace the current Primero configuration state. class PrimeroConfiguration < ApplicationRecord - CONFIGURABLE_MODELS = %w[FormSection Lookup Agency Role UserGroup Report ContactInformation].freeze + CONFIGURABLE_MODELS = [FormSection, Lookup, Agency, Role, UserGroup, Report, ContactInformation].freeze PRIMERO_CONFIGURATION_FIELDS_SCHEMA = { 'id' => { 'type' => 'string', 'format' => 'regex', 'pattern' => PermittedFieldService::UUID_REGEX }, @@ -49,8 +49,7 @@ def current(created_by = nil) def current_configuration_data CONFIGURABLE_MODELS.each_with_object({}) do |model, data| - model_class = Kernel.const_get(model) - data[model] = model_class.all.map(&:configuration_hash) + data[model.name] = model.all.map(&:configuration_hash) end end @@ -97,11 +96,10 @@ def can_apply? def configure! CONFIGURABLE_MODELS.each do |model| - next unless data.key?(model) + next unless data.key?(model.name) - model_class = Kernel.const_get(model) - model_class.sort_configuration_hash(data[model]).each do |configuration| - model_class.create_or_update!(configuration) + model.sort_configuration_hash(data[model.name]).each do |configuration| + model.create_or_update!(configuration) end end end @@ -120,7 +118,7 @@ def remainder(model_class) def validate_configuration_data data_is_valid = CONFIGURABLE_MODELS.reduce(true) do |valid, model| - valid && (%w[Report Location].include?(model) || data[model]&.size&.positive?) + valid && ([Report, Location].include?(model) || data[model.name]&.size&.positive?) end return if data_is_valid diff --git a/app/models/referral.rb b/app/models/referral.rb index 17e95d82ad..1929c49a25 100644 --- a/app/models/referral.rb +++ b/app/models/referral.rb @@ -24,7 +24,6 @@ def perform mark_service_referred(service_record) perform_system_referral unless remote record.last_updated_by = transitioned_by - record.save! if record.has_changes_to_save? end def reject!(user, rejected_reason = nil) @@ -35,7 +34,7 @@ def reject!(user, rejected_reason = nil) self.responded_at = DateTime.now remove_assigned_user record.update_last_updated_by(user) - record.save! && save! + save! end def done!(user, rejection_note = nil) @@ -47,14 +46,14 @@ def done!(user, rejection_note = nil) mark_rejection(rejection_note, current_service_record) remove_assigned_user record.update_last_updated_by(user) - record.save! && save! + save! end def revoke!(user) self.status = Transition::STATUS_REVOKED remove_assigned_user record.update_last_updated_by(user) - record.save! && save! + save! end def accept! diff --git a/app/models/registry_record.rb b/app/models/registry_record.rb index ad232a5fe1..26920acfb7 100644 --- a/app/models/registry_record.rb +++ b/app/models/registry_record.rb @@ -17,6 +17,7 @@ class RegistryRecord < ApplicationRecord include Attachable include EagerLoadable include LocationCacheable + include PhoneticSearchable store_accessor( :data, @@ -36,28 +37,16 @@ def filterable_id_fields %w[registry_id short_id registry_no] end - def quicksearch_fields - filterable_id_fields + %w[registry_type name] - end - def summary_field_names common_summary_fields + %w[registry_type registry_id_display name registration_date module_id name location_current registry_no] end - def sortable_text_fields - %w[registry_type short_id name] + def phonetic_field_names + %w[name] end end - searchable do - %w[id status registry_type].each { |f| string(f, as: "#{f}_sci") } - %w[registration_date].each { |f| date(f) } - filterable_id_fields.each { |f| string("#{f}_filterable", as: "#{f}_filterable_sci") { data[f] } } - quicksearch_fields.each { |f| text_index(f) } - sortable_text_fields.each { |f| string("#{f}_sortable", as: "#{f}_sortable_sci") { data[f] } } - end - alias super_defaults defaults def defaults super_defaults diff --git a/app/models/report.rb b/app/models/report.rb index a149dfa2e6..c6ba2ce543 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -32,7 +32,7 @@ class Report < ApplicationRecord YEAR = 'year' # eg. 2015 DATE_RANGES = [DAY, WEEK, MONTH, YEAR].freeze DATE_FORMAT = 'YYYY-MM-DD' - DATE_TIME_FORMAT = 'YYYY-MM-DDTHH:MI:SS' + DATE_TIME_FORMAT = 'YYYY-MM-DD"T"HH24:MI:SS' localize_properties :name, :description @@ -49,55 +49,27 @@ class Report < ApplicationRecord validates :record_type, presence: true validates :aggregate_by, presence: true - validate :modules_present + validate :validate_modules_present validate :validate_name_in_base_language before_create :generate_unique_id before_save :apply_default_filters + def self.new_with_properties(report_params) + report = Report.new(report_params.except(:name, :description, :fields)) + report.name_i18n = report_params[:name] + report.description_i18n = report_params[:description] + report.aggregate_by = ReportFieldService.aggregate_by_from_params(report_params) + report.disaggregate_by = ReportFieldService.disaggregate_by_from_params(report_params) + report + end + def validate_name_in_base_language return if name_en.present? errors.add(:name, I18n.t('errors.models.report.name_presence')) end - class << self - def get_reportable_subform_record_field_name(model, record_type) - model = Record.model_from_name(model) - return unless model.try(:nested_reportable_types) - - model.nested_reportable_types.select { |nrt| nrt.model_name.param_key == record_type }.first&.record_field_name - end - - def get_reportable_subform_record_field_names(model) - model = Record.model_from_name(model) - return unless model.try(:nested_reportable_types) - - model.nested_reportable_types.map { |nrt| nrt.model_name.param_key } - end - - def record_type_is_nested_reportable_subform?(model, record_type) - get_reportable_subform_record_field_names(model).include?(record_type) - end - - def all_nested_reportable_types - record_types = [] - FormSection::RECORD_TYPES.each do |rt| - record_types += Record.model_from_name(rt).try(:nested_reportable_types) - end - record_types - end - - def new_with_properties(report_params) - report = Report.new(report_params.except(:name, :description, :fields)) - report.name_i18n = report_params[:name] - report.description_i18n = report_params[:description] - report.aggregate_by = ReportFieldService.aggregate_by_from_params(report_params) - report.disaggregate_by = ReportFieldService.disaggregate_by_from_params(report_params) - report - end - end - def update_properties(report_params) report_params = report_params.with_indifferent_access if report_params.is_a?(Hash) converted_params = FieldI18nService.convert_i18n_properties(Report, report_params) @@ -158,7 +130,7 @@ def lookups end def model - @model ||= Record.model_from_name(record_type) + @model ||= PrimeroModelService.to_model(record_type) end def build_query @@ -173,12 +145,7 @@ def build_query def join_nested_model model.parent_record_type.joins( ActiveRecord::Base.sanitize_sql_for_conditions( - [ - %( - CROSS JOIN jsonb_array_elements(data->:nested_field_name) - as #{ActiveRecord::Base.connection.quote_table_name(model.record_field_name)} - ), { nested_field_name: model.record_field_name } - ] + ["CROSS JOIN jsonb_array_elements(data->'%s') as %s", model.record_field_name, model.record_field_name] ) ) end @@ -242,39 +209,37 @@ def record_field_name(field) end def apply_filters(query) - filter_query = filters.reduce(query) do |current_query, filter| - field = filter_fields[filter['attribute']] - Reports::FilterFieldQuery.new( - query: current_query, field:, filter:, record_field_name: record_field_name(field) - ).apply + filter_query = query + if model.try(:parent_record_type).present? + filter_query = apply_filters_for_nested_model(filter_query) + else + search_filters = Reports::ReportFilterService.build_filters(filters, filters_map) + search_filters.each { |filter| filter_query = filter_query.where(filter.query) } end apply_permission_filter(filter_query) end + def apply_filters_for_nested_model(query) + filters.reduce(query) do |current_query, filter| + field = filter_fields[filter['attribute']] + current_query.where( + Reports::FilterFieldQuery.build(field:, filter:, record_field_name: record_field_name(field)) + ) + end + end + def apply_permission_filter(query) return query unless permission_filter.present? - Reports::FilterFieldQuery.new(permission_filter:, query:).apply + query.where(Reports::FilterFieldQuery.build(permission_filter:)) end def age_field?(field) field.type == Field::NUMERIC_FIELD && field.name.starts_with?(AGE) end - def filter_fields - @filter_fields ||= Field.find_by_name(filter_attributes).each_with_object({}) do |field, hash| - next if hash[field.name].present? - - hash[field.name] = field - end - end - - def filter_attributes - filters.map { |filter| filter['attribute'] } - end - - def modules_present + def validate_modules_present if module_id.present? && module_id.length >= 1 if module_id.split('-').first != 'primeromodule' errors.add(:module_id, I18n.t('errors.models.report.module_syntax')) @@ -284,29 +249,46 @@ def modules_present end end - def self.reportable_record_types - FormSection::RECORD_TYPES + ['violation'] + Report.all_nested_reportable_types.map { |nrt| nrt.name.underscore } - end - def apply_default_filters return unless add_default_filters self.filters ||= [] - default_filters = Record.model_from_name(record_type).report_filters + default_filters = model.report_filters self.filters = (self.filters + default_filters).uniq end + def pivots_map + @pivots_map ||= build_fields_map(pivots, pivot_fields) + end + + def pivot_fields + @pivot_fields ||= fields_by_name(pivots) + end + def pivots (aggregate_by || []) + (disaggregate_by || []) end - def pivot_fields - @pivot_fields ||= Field.find_by_name(pivots).group_by(&:name).transform_values(&:first) + def filters_map + @filters_map ||= build_fields_map(filter_attributes, filter_fields) end - def pivots_map - @pivots_map ||= pivots.to_h do |pivot| - [pivot, pivot_fields[pivot] || pivot_fields[Field.remove_admin_level_from_name(pivot)]] + def filter_fields + @filter_fields ||= fields_by_name(filter_attributes) + end + + def filter_attributes + filters.map { |filter| filter['attribute'] } + end + + def fields_by_name(field_names) + Field.find_by_name(field_names).group_by(&:name).transform_values(&:first) + end + + def build_fields_map(field_names, fields) + field_names.to_h do |field_name| + field = fields[field_name] || fields[Field.remove_location_parts(field_name)] + [field_name, field] end end diff --git a/app/models/reportable_follow_up.rb b/app/models/reportable_follow_up.rb index 3b372009d4..d6ccbbad03 100644 --- a/app/models/reportable_follow_up.rb +++ b/app/models/reportable_follow_up.rb @@ -4,6 +4,8 @@ # Class for Reportable Follow Up class ReportableFollowUp + include ReportableNestedRecord + def self.parent_record_type Child end @@ -17,14 +19,8 @@ def self.report_filters { 'attribute' => 'status', 'value' => [Record::STATUS_OPEN] }, { 'attribute' => 'record_state', 'value' => ['true'] }, { 'attribute' => 'followup_date', 'constraint' => 'not_null' } - ] - end - include ReportableNestedRecord - - searchable do - extend ReportableNestedRecord::Searchable - configure_searchable(ReportableFollowUp) + ] end def id diff --git a/app/models/reportable_protection_concern.rb b/app/models/reportable_protection_concern.rb index fc974f5e76..abe3db78b0 100644 --- a/app/models/reportable_protection_concern.rb +++ b/app/models/reportable_protection_concern.rb @@ -4,6 +4,8 @@ # Class for Reportable Protection Concern class ReportableProtectionConcern + include ReportableNestedRecord + def self.parent_record_type Child end @@ -20,13 +22,6 @@ def self.report_filters ] end - include ReportableNestedRecord - - searchable do - extend ReportableNestedRecord::Searchable - configure_searchable(ReportableProtectionConcern) - end - def id object_value('unique_id') end diff --git a/app/models/reportable_service.rb b/app/models/reportable_service.rb index 8094a3955f..41be89521b 100644 --- a/app/models/reportable_service.rb +++ b/app/models/reportable_service.rb @@ -4,6 +4,8 @@ # Class for Reportable Service class ReportableService + include ReportableNestedRecord + def self.parent_record_type Child end @@ -21,18 +23,6 @@ def self.report_filters ] end - include ReportableNestedRecord - - searchable do - extend ReportableNestedRecord::Searchable - configure_searchable(ReportableService) - - %w[service_response_type service_type service_implemented].each do |field| - string(field, as: "#{field}_sci".to_sym) { object_value(field) } - end - time :service_due_date - end - def service_due_date @service_due_date ||= @parent_record.service_due_date(@object) end diff --git a/app/models/reports/field_queries/field_query.rb b/app/models/reports/field_queries/field_query.rb index 412ed1f8a1..23139fb37c 100644 --- a/app/models/reports/field_queries/field_query.rb +++ b/app/models/reports/field_queries/field_query.rb @@ -5,7 +5,7 @@ # Represents a query against a field class Reports::FieldQueries::FieldQuery < ValueObject DATE_FORMAT = 'YYYY-MM-DD' - DATE_TIME_FORMAT = 'YYYY-MM-DDTHH:MI:SS' + DATE_TIME_FORMAT = "YYYY-MM-DD'T'HH:MI:SS" attr_accessor :field, :record_field_name @@ -16,20 +16,20 @@ def to_sql end def default_query - ActiveRecord::Base.sanitize_sql_for_conditions( - [ - "COALESCE(#{data_column_name} ->> :field_name, 'incomplete_data') AS #{column_name}", { field_name: field.name } - ] + ActiveRecord::Base.sanitize_sql_array( + ["COALESCE(%s ->> '%s', 'incomplete_data') AS %s", data_column_name, field.name, column_name] ) end def data_column_name - ActiveRecord::Base.connection.quote_column_name(record_field_name || 'data') + record_field_name || 'data' end def column_name(suffix = '') name = suffix.present? ? "#{field.name}_#{suffix}" : field.name - ActiveRecord::Base.connection.quote_column_name(record_field_name.present? ? "#{record_field_name}_#{name}" : name) + return "#{record_field_name}_#{name}" if record_field_name.present? + + name end def sort_field @@ -37,10 +37,8 @@ def sort_field end def multi_select_query - ActiveRecord::Base.sanitize_sql_for_conditions( - [ - "jsonb_array_elements_text(#{data_column_name}-> :field_name) as #{column_name}", { field_name: field.name } - ] + ActiveRecord::Base.sanitize_sql_array( + ["jsonb_array_elements_text(%s-> '%s') as %s", data_column_name, field.name, column_name] ) end end diff --git a/app/models/reports/field_queries/numeric_field_query.rb b/app/models/reports/field_queries/numeric_field_query.rb index df59ae6630..64dd607bc3 100644 --- a/app/models/reports/field_queries/numeric_field_query.rb +++ b/app/models/reports/field_queries/numeric_field_query.rb @@ -7,9 +7,9 @@ class Reports::FieldQueries::NumericFieldQuery < Reports::FieldQueries::FieldQue attr_accessor :range, :abrreviate_range def to_sql - return default_query unless range.present? + return range_query if range.present? - range_query + "#{sort_query}, #{default_query}" end def range_query @@ -22,15 +22,17 @@ def range_query end def sort_query - %( - case #{range.map.with_index { |range, index| build_range_order(field, range, index) }.join(' ')} - end as #{sort_field} - ) + if range.present? + return %( + case #{range.map.with_index { |range, index| build_range_order(field, range, index) }.join(' ')} + end as #{sort_field} + ) + end + + ActiveRecord::Base.sanitize_sql_array(["data->'%s' as %s", record_field_name, sort_field]) end def sort_field - return super unless range.present? - column_name('sort') end diff --git a/app/models/reports/filter_field_query.rb b/app/models/reports/filter_field_query.rb index 12cda7d906..5fec975803 100644 --- a/app/models/reports/filter_field_query.rb +++ b/app/models/reports/filter_field_query.rb @@ -3,15 +3,21 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. # Filters an active record query by field +# TODO: This class will be refactored to a service that will take the Field definitions in the Report and +# converts them to the Search Filters (that already are responsible for generating queries) class Reports::FilterFieldQuery < ValueObject CONSTRAINTS = %w[= > <].freeze attr_accessor :query, :field, :filter, :record_field_name, :permission_filter + def self.build(params = {}) + new(params).build + end + def data_column_name ActiveRecord::Base.connection.quote_column_name(record_field_name || 'data') end - def apply + def build return permission_filter_query if permission_filter? return not_null_query if not_null_constraint? return multi_select_query if field.multi_select? @@ -25,37 +31,27 @@ def permission_filter? end def permission_filter_query - query.where( - ActiveRecord::Base.sanitize_sql_for_conditions(["#{data_column_name}->:attribute ?| array[:value]", - permission_filter.with_indifferent_access]) - ) + ActiveRecord::Base.sanitize_sql_for_conditions(["#{data_column_name}->:attribute ?| array[:value]", + permission_filter.with_indifferent_access]) end def multi_select_query - query.where( - ActiveRecord::Base.sanitize_sql_for_conditions(["#{data_column_name}->:attribute ?| array[:value]", - filter.with_indifferent_access]) - ) + ActiveRecord::Base.sanitize_sql_for_conditions(["#{data_column_name}->:attribute ?| array[:value]", + filter.with_indifferent_access]) end def array_query - query.where( - ActiveRecord::Base.sanitize_sql_for_conditions(["#{data_column_name} ->> :attribute IN (:value)", - filter.with_indifferent_access]) - ) + ActiveRecord::Base.sanitize_sql_for_conditions(["#{data_column_name} ->> :attribute IN (:value)", + filter.with_indifferent_access]) end def not_null_query - self.query = query.where( - ActiveRecord::Base.sanitize_sql_for_conditions(["#{data_column_name}->:attribute is not null", - { attribute: filter['attribute'] }]) - ) + query = ActiveRecord::Base.sanitize_sql_for_conditions(["#{data_column_name}->:attribute is not null", + { attribute: filter['attribute'] }]) return query unless field.multi_select? - query.where( - ActiveRecord::Base.sanitize_sql_for_conditions(["jsonb_array_length(#{data_column_name}->:attribute) > 0", - { attribute: filter['attribute'] }]) - ) + ActiveRecord::Base.sanitize_sql_for_conditions(["jsonb_array_length(#{data_column_name}->:attribute) > 0", + { attribute: filter['attribute'] }]) end def not_null_constraint? @@ -72,33 +68,27 @@ def field_type_query when Field::TICK_BOX then tick_box_query when Field::NUMERIC_FIELD then numeric_query else - query.where(ActiveRecord::Base.sanitize_sql_for_conditions(["#{data_column_name} ->> :attribute = :value", - filter.with_indifferent_access])) + ActiveRecord::Base.sanitize_sql_for_conditions(["#{data_column_name} ->> :attribute = :value", + filter.with_indifferent_access]) end end def numeric_query - query.where( - ActiveRecord::Base.sanitize_sql_for_conditions( - ["CAST(#{data_column_name} ->> :attribute AS INTEGER) #{constraint} :value", filter.with_indifferent_access] - ) + ActiveRecord::Base.sanitize_sql_for_conditions( + ["CAST(#{data_column_name} ->> :attribute AS INTEGER) #{constraint} :value", filter.with_indifferent_access] ) end def tick_box_query - query.where( - ActiveRecord::Base.sanitize_sql_for_conditions(["CAST(#{data_column_name} ->> :attribute AS BOOLEAN) = :value", - filter.with_indifferent_access]) - ) + ActiveRecord::Base.sanitize_sql_for_conditions(["CAST(#{data_column_name} ->> :attribute AS BOOLEAN) = :value", + filter.with_indifferent_access]) end def date_field_query date_format = field.date_include_time ? Report::DATE_TIME_FORMAT : Report::DATE_FORMAT - query.where( - ActiveRecord::Base.sanitize_sql_for_conditions( - ["to_timestamp(#{data_column_name} ->> :attribute, :format) #{constraint} to_timestamp(:value, :format)", - filter.merge('format' => date_format).with_indifferent_access] - ) + ActiveRecord::Base.sanitize_sql_for_conditions( + ["to_timestamp(#{data_column_name} ->> :attribute, :format) #{constraint} to_timestamp(:value, :format)", + filter.merge('format' => date_format).with_indifferent_access] ) end end diff --git a/app/models/reports/report_filter_service.rb b/app/models/reports/report_filter_service.rb new file mode 100644 index 0000000000..168bb250d7 --- /dev/null +++ b/app/models/reports/report_filter_service.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Transform report filters to search filters +class Reports::ReportFilterService + attr_accessor :filters, :filters_map, :destringify_service + + class << self + def build_filters(filters, filters_map) + service = Reports::ReportFilterService.new(filters, filters_map) + service.build_filters + end + end + + def initialize(filters, filters_map) + self.filters = filters + self.filters_map = filters_map + self.destringify_service = DestringifyService.new + end + + # rubocop:disable Metrics/AbcSize + def build_filters + filters.map do |filter| + field = filters_map[filter['attribute']] + filter = filter.merge('value' => destringify_service.destringify(filter['value'], false)) + next(SearchFilters::NotNull.new(field_name: filter['attribute'])) if filter['constraint'] == 'not_null' + next(build_location_filter(filter, field)) if field.location? || field.reporting_location? + next(build_array_filter(filter, field)) if filter['value'].is_a?(Array) && filter['value'].size >= 1 + + build_filter(filter, field) + end + end + # rubocop:enable Metrics/AbcSize + + # rubocop:disable Metrics/MethodLength + def build_filter(filter, field) + case field.type + when Field::DATE_FIELD + SearchFilters::DateValue.new( + field_name: filter['attribute'], value: filter['value'], operator: filter['constraint'], + date_include_time: field.date_include_time + ) + when Field::TICK_BOX, Field::RADIO_BUTTON + SearchFilters::BooleanValue.new(field_name: filter['attribute'], value: filter['value']) + when Field::NUMERIC_FIELD + SearchFilters::Value.new(field_name: filter['attribute'], value: filter['value'], operator: filter['constraint']) + else + SearchFilters::TextValue.new(field_name: filter['attribute'], value: filter['value']) + end + end + # rubocop:enable Metrics/MethodLength + + def build_array_filter(filter, field) + case field.type + when Field::TICK_BOX, Field::RADIO_BUTTON + SearchFilters::BooleanList.new(field_name: filter['attribute'], values: filter['value']) + when Field::NUMERIC_FIELD + SearchFilters::ValueList.new(field_name: filter['attribute'], values: filter['value']) + else + SearchFilters::TextList.new(field_name: filter['attribute'], values: filter['value']) + end + end + + def build_location_filter(filter, field) + if filter['value'].is_a?(Array) && filter['value'].size >= 1 + return SearchFilters::LocationList.new(field_name: field.name, values: filter['value']) + end + + SearchFilters::Location.new(field_name: field.name, value: filter['value']) + end +end diff --git a/app/models/search_filters/boolean_list.rb b/app/models/search_filters/boolean_list.rb new file mode 100644 index 0000000000..71072910d3 --- /dev/null +++ b/app/models/search_filters/boolean_list.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Transform API query parameter field_name=false,true,... into a SQL query +class SearchFilters::BooleanList < SearchFilters::ValueList + def query + ActiveRecord::Base.sanitize_sql_for_conditions( + [ + %( + (#{json_path_query}) OR ( + data->>:field_name IS NULL AND (array[false, 'false'] @> array[:values]) + ) + ), + { field_name:, values: } + ] + ) + end + + def json_path_value + values.map do |value| + ActiveRecord::Base.sanitize_sql_for_conditions(['@ == %s || @ == "%s"', value, value]) + end.join(' || ') + end +end diff --git a/app/models/search_filters/boolean_value.rb b/app/models/search_filters/boolean_value.rb new file mode 100644 index 0000000000..0ed57432cb --- /dev/null +++ b/app/models/search_filters/boolean_value.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Transform a boolean query parameter field_name=false into a sql query +class SearchFilters::BooleanValue < SearchFilters::Value + def query + return json_path_query if value + + "(#{json_path_query} OR #{ActiveRecord::Base.sanitize_sql_for_conditions(['(data->>? IS NULL)', field_name])})" + end + + def json_path_value + ActiveRecord::Base.sanitize_sql_for_conditions(['@ == %s || @ == "%s"', value, value]) + end +end diff --git a/app/models/search_filters/date_range.rb b/app/models/search_filters/date_range.rb index ff7820a910..86b4ed8167 100644 --- a/app/models/search_filters/date_range.rb +++ b/app/models/search_filters/date_range.rb @@ -6,15 +6,65 @@ class SearchFilters::DateRange < SearchFilters::SearchFilter attr_accessor :field_name, :from, :to - def query_scope(sunspot) - this = self - sunspot.instance_eval do - if this.to.blank? - with(this.field_name).greater_than_or_equal_to(this.from) - else - with(this.field_name).between(this.from..this.to) - end + class << self + def dawn_of_time + Time.zone.at(0) end + + def recent_past + Time.zone.now - 10.days + end + + def last_week(field_name) + new( + field_name:, + from: 1.week.ago.beginning_of_week, + to: 1.week.ago.end_of_week + ) + end + + def this_week(field_name) + new( + field_name:, + from: present.beginning_of_week, + to: present.end_of_week + ) + end + + def present + Time.zone.now + end + end + + # rubocop:disable Metrics/MethodLength + def query + return "(#{from_query})" unless to.present? + + ActiveRecord::Base.sanitize_sql_for_conditions( + [ + %( + data->>:field_name IS NOT NULL AND EXISTS ( + SELECT 1 FROM JSONB_ARRAY_ELEMENTS_TEXT(data->:field_name || CAST('[]' AS JSONB)) AS date_field + WHERE TO_TIMESTAMP(date_field, :date_format) >= TO_TIMESTAMP(:from, :date_format) + AND TO_TIMESTAMP(date_field, :date_format) <= TO_TIMESTAMP(:to, :date_format) + ) + ), + { field_name:, from: from.iso8601, to: to.iso8601, date_format: } + ] + ) + end + # rubocop:enable Metrics/MethodLength + + def date_format + date_include_time? ? Report::DATE_TIME_FORMAT : Report::DATE_FORMAT + end + + def date_include_time? + from.is_a?(Time) + end + + def from_query + SearchFilters::DateValue.new(field_name:, value: from, operator: '>=').query end def this_quarter? diff --git a/app/models/search_filters/date_value.rb b/app/models/search_filters/date_value.rb new file mode 100644 index 0000000000..b751e35b04 --- /dev/null +++ b/app/models/search_filters/date_value.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Transform API query parameter field_name=value into a sql query +class SearchFilters::DateValue < SearchFilters::Value + attr_accessor :date_include_time + + # rubocop:disable Metrics/MethodLength + def query + ActiveRecord::Base.sanitize_sql_for_conditions( + [ + %( + data->>:field_name IS NOT NULL AND EXISTS ( + SELECT 1 FROM JSONB_ARRAY_ELEMENTS_TEXT(data->:field_name || CAST('[]' AS JSONB)) AS date_field + WHERE TO_TIMESTAMP(date_field, :date_format) #{@safe_operator} TO_TIMESTAMP(:value, :date_format) + ) + ), + { field_name:, value: value.iso8601, date_format: } + ] + ) + end + # rubocop:enable Metrics/MethodLength + + def date_format + date_include_time? ? Report::DATE_TIME_FORMAT : Report::DATE_FORMAT + end + + def date_include_time? + date_include_time || value.is_a?(Time) + end +end diff --git a/app/models/search_filters/id_filter.rb b/app/models/search_filters/id_filter.rb new file mode 100644 index 0000000000..7a6c4de83d --- /dev/null +++ b/app/models/search_filters/id_filter.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Transform API query parameter id=value into a sql query +class SearchFilters::IdFilter < SearchFilters::Value + def query + ActiveRecord::Base.sanitize_sql_for_conditions(['id = :value', { value: }]) + end +end diff --git a/app/models/search_filters/id_list_filter.rb b/app/models/search_filters/id_list_filter.rb new file mode 100644 index 0000000000..4fc284cd0d --- /dev/null +++ b/app/models/search_filters/id_list_filter.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Transform API query parameter id=value1,value1 into a sql query +class SearchFilters::IdListFilter < SearchFilters::ValueList + def query + ActiveRecord::Base.sanitize_sql_for_conditions(['id IN (:values)', { values: }]) + end +end diff --git a/app/models/search_filters/location.rb b/app/models/search_filters/location.rb new file mode 100644 index 0000000000..3914ed9cc9 --- /dev/null +++ b/app/models/search_filters/location.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Concern for location filters +module SearchFilters::Location + extend ActiveSupport::Concern + + # rubocop:disable Metrics/MethodLength + def query + ActiveRecord::Base.sanitize_sql_for_conditions( + [ + %( + ( + data->>:field_name IS NOT NULL AND EXISTS + ( + SELECT + 1 + FROM locations + INNER JOIN locations AS descendants + ON locations.admin_level <= descendants.admin_level + AND locations.hierarchy_path @> descendants.hierarchy_path + WHERE locations.location_code #{value_query} AND data->:field_name ? descendants.location_code + AND locations.admin_level >= :admin_level + AND descendants.admin_level >= :admin_level + ) + ) + ), + query_conditions + ] + ) + end + # rubocop:enable Metrics/MethodLength + + def value_query + '= :value' + end + + def query_conditions + { field_name: record_field_name, value: value.to_s.upcase, admin_level: } + end + + def admin_level + return 0 unless field_name.last.match?(Field::ADMIN_LEVEL_REGEXP) + + field_name.last.to_i + end + + def record_field_name + Field.remove_location_parts(field_name) + end +end diff --git a/app/models/search_filters/location_list.rb b/app/models/search_filters/location_list.rb new file mode 100644 index 0000000000..8c1582eb79 --- /dev/null +++ b/app/models/search_filters/location_list.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Transform API query parameter loc:field_name[0]=value into a sql query +class SearchFilters::LocationList < SearchFilters::ValueList + include SearchFilters::Location + + def value_query + 'IN (:values)' + end + + def query_conditions + { field_name: record_field_name, values: values.map { |value| value.to_s.upcase }, admin_level: } + end +end diff --git a/app/models/search_filters/location_value.rb b/app/models/search_filters/location_value.rb new file mode 100644 index 0000000000..3a03e1b191 --- /dev/null +++ b/app/models/search_filters/location_value.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Transform API query parameter loc:field_name=value into a sql query +class SearchFilters::LocationValue < SearchFilters::Value + include SearchFilters::Location +end diff --git a/app/models/search_filters/not_null.rb b/app/models/search_filters/not_null.rb new file mode 100644 index 0000000000..ce366fa574 --- /dev/null +++ b/app/models/search_filters/not_null.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Transform a not null query parameter field_name=not_null into a sql query +class SearchFilters::NotNull < SearchFilters::SearchFilter + def query + ActiveRecord::Base.sanitize_sql_for_conditions(['(data->>? IS NOT NULL)', field_name]) + end + + def to_s + return "not[#{field_name}]=not_null" unless not_filter + + "#{field_name}=not_null" + end +end diff --git a/app/models/search_filters/not_value.rb b/app/models/search_filters/not_value.rb deleted file mode 100644 index 2c1f789ddc..0000000000 --- a/app/models/search_filters/not_value.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -# Transform API query parameter not[field_name]=value into a Sunspot query -class SearchFilters::NotValue < SearchFilters::SearchFilter - attr_accessor :field_name, :values - - def query_scope(sunspot) - this = self - sunspot.instance_eval do - without(this.field_name, this.values) - end - end - - def as_location_filter(record_class) - return self unless location_field_filter?(record_class) - - clone do |f| - f.field_name = location_field_name_solr(field_name, values) - end - end - - def location_field_filter?(record_class) - record_class.searchable_location_fields.include?(field_name) - end - - def to_h - { - type: 'not', - field_name:, - value: values - } - end - - def to_s - "not[#{field_name}]=#{values&.join(',')}" - end -end diff --git a/app/models/search_filters/numeric_range.rb b/app/models/search_filters/numeric_range.rb index d8618c4dfb..108cb81e07 100644 --- a/app/models/search_filters/numeric_range.rb +++ b/app/models/search_filters/numeric_range.rb @@ -4,17 +4,18 @@ # Transform API query parameter field_name=m..n into a Sunspot query class SearchFilters::NumericRange < SearchFilters::SearchFilter - attr_accessor :field_name, :from, :to - - def query_scope(sunspot) - this = self - sunspot.instance_eval do - if this.to.blank? - with(this.field_name).greater_than_or_equal_to(this.from) - else - with(this.field_name, this.from...this.to) - end - end + attr_accessor :from, :to + + def query + return if from.blank? && to.blank? + + "(#{ActiveRecord::Base.sanitize_sql_for_conditions(['data->? IS NOT NULL', field_name])} AND #{json_path_query})" + end + + def json_path_value + return ActiveRecord::Base.sanitize_sql_for_conditions(['@ >= %s && @ <= %s', from, to]) if to.present? + + ActiveRecord::Base.sanitize_sql_for_conditions(['@ >= %s', from]) end def to_h diff --git a/app/models/search_filters/or.rb b/app/models/search_filters/or.rb index eb555c842b..1d903ad4fc 100644 --- a/app/models/search_filters/or.rb +++ b/app/models/search_filters/or.rb @@ -6,17 +6,10 @@ class SearchFilters::Or < SearchFilters::SearchFilter attr_accessor :filters - def query_scope(sunspot) - this = self - sunspot.instance_eval do - any_of do - this.filters.each do |filter| - # TODO: For now assume that nested filters are only Value, - # but there is a better, functional way to solve that... later - with(filter.field_name, filter.value) - end - end - end + def query + return filters.first.query if filters.size == 1 + + "(#{filters.map(&:query).join(' OR ')})" end def as_location_filter(record_class) diff --git a/app/models/search_filters/range_list.rb b/app/models/search_filters/range_list.rb new file mode 100644 index 0000000000..975eddd5a8 --- /dev/null +++ b/app/models/search_filters/range_list.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Transform API query parameter field_name=value1,value2,... into a Sunspot query +class SearchFilters::RangeList < SearchFilters::ValueList + attr_accessor :range_type + + def query + range_queries = values.map { |value| range_type.new(field_name:, from: value['from'], to: value['to']).query } + + "(#{range_queries.join(' OR ')})" + end +end diff --git a/app/models/search_filters/search_filter.rb b/app/models/search_filters/search_filter.rb index 113b7f789d..af73dca4b2 100644 --- a/app/models/search_filters/search_filter.rb +++ b/app/models/search_filters/search_filter.rb @@ -4,6 +4,32 @@ # Superclass for all SearchFilter objects that transform API query parameters into Sunspot queries class SearchFilters::SearchFilter < ValueObject + OPERATORS = %w[= > < >= <=].freeze + + attr_accessor :field_name, :not_filter, :column_name + + def initialize(args = {}) + super(args) + @safe_operator = OPERATORS.include?(args[:operator]) ? args[:operator] : '=' + end + + def query + raise NotImplementedError + end + + def json_path_query + "data @? '#{json_field_query} ? (#{json_path_value})'" + end + + def json_field_query + ActiveRecord::Base.sanitize_sql_for_conditions(['$.%s', field_name]) + end + + def json_path_value + operator = @safe_operator == '=' ? '==' : @safe_operator + ActiveRecord::Base.sanitize_sql_for_conditions(['@ %s %s', operator, value]) + end + def to_json(_obj) to_h.to_json end diff --git a/app/models/search_filters/text_list.rb b/app/models/search_filters/text_list.rb new file mode 100644 index 0000000000..0579e9b391 --- /dev/null +++ b/app/models/search_filters/text_list.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Transform API query parameter field_name=false,true,... into a SQL query +class SearchFilters::TextList < SearchFilters::ValueList + def query + return unless values.present? + + json_path_query + end + + def json_path_value + values.map do |value| + ActiveRecord::Base.sanitize_sql_for_conditions(['@ == "%s"', value]) + end.join(' || ') + end +end diff --git a/app/models/search_filters/text_value.rb b/app/models/search_filters/text_value.rb new file mode 100644 index 0000000000..f5c4b60464 --- /dev/null +++ b/app/models/search_filters/text_value.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Transform API query parameter field_name=value into a sql query +class SearchFilters::TextValue < SearchFilters::Value + def query + json_path_query + end + + def json_path_value + ActiveRecord::Base.sanitize_sql_for_conditions(['@ == "%s"', value]) + end +end diff --git a/app/models/search_filters/value.rb b/app/models/search_filters/value.rb index a6ae438bc7..5e1621b7a3 100644 --- a/app/models/search_filters/value.rb +++ b/app/models/search_filters/value.rb @@ -4,13 +4,10 @@ # Transform API query parameter field_name=value into a Sunspot query class SearchFilters::Value < SearchFilters::SearchFilter - attr_accessor :field_name, :value + attr_accessor :value - def query_scope(sunspot) - this = self - sunspot.instance_eval do - with(this.field_name, this.value) - end + def query + json_path_query end def as_location_filter(record_class) @@ -42,6 +39,8 @@ def to_h end def to_s - "#{field_name}=#{value}" + return "#{field_name}=#{value}" unless not_filter + + "not[#{field_name}]=#{value}" end end diff --git a/app/models/search_filters/value_list.rb b/app/models/search_filters/value_list.rb index 09ac0ba74f..ca820e8412 100644 --- a/app/models/search_filters/value_list.rb +++ b/app/models/search_filters/value_list.rb @@ -4,26 +4,19 @@ # Transform API query parameter field_name=value1,value2,... into a Sunspot query class SearchFilters::ValueList < SearchFilters::SearchFilter - attr_accessor :field_name, :values - - # rubocop:disable Metrics/MethodLength - # rubocop:disable Style/HashEachMethods - def query_scope(sunspot) - this = self - sunspot.instance_eval do - if this.values.first.is_a?(Hash) - any_of do - this.values.each do |v| - with(this.field_name, v['from']...v['to']) - end - end - else - with(this.field_name).any_of(this.values) - end - end + attr_accessor :values + + def query + return unless values.present? + + json_path_query + end + + def json_path_value + values.map do |value| + ActiveRecord::Base.sanitize_sql_for_conditions(['@ == %s', value]) + end.join(' || ') end - # rubocop:enable Style/HashEachMethods - # rubocop:enable Metrics/MethodLength def as_location_filter(record_class) return self unless location_field_filter?(record_class) @@ -57,6 +50,8 @@ def to_h end def to_s - "#{field_name}=#{values&.join(',')}" + return "#{field_name}=#{values&.join(',')}" unless not_filter + + "not[#{field_name}]=#{values&.join(',')}" end end diff --git a/app/models/searchable_identifier.rb b/app/models/searchable_identifier.rb new file mode 100644 index 0000000000..7a5662068a --- /dev/null +++ b/app/models/searchable_identifier.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Class for SearchableIdentifier +class SearchableIdentifier < ApplicationRecord + belongs_to :record, polymorphic: true +end diff --git a/app/models/system_settings.rb b/app/models/system_settings.rb index f24521e801..7fbd3239be 100644 --- a/app/models/system_settings.rb +++ b/app/models/system_settings.rb @@ -8,6 +8,7 @@ # SystemSetting should be invoked using the singleton SystemSettings#current method. # Any update to the data will only take effect after the system is rebooted # and the singleton is reloaded. +# rubocop:disable Metrics/ClassLength class SystemSettings < ApplicationRecord include LocalizableJsonProperty include ConfigurationRecord @@ -18,7 +19,8 @@ class SystemSettings < ApplicationRecord store_accessor(:system_options, :due_date_from_appointment_date, :show_alerts, :code_of_conduct_enabled, :timeframe_hours_to_assign, :timeframe_hours_to_assign_high, :duplicate_field_to_form, - :maximum_users, :maximum_users_warning) + :maximum_users, :maximum_users_warning, :maximum_attachments_per_record, + :primero_promote_config) localize_properties %i[welcome_email_text approvals_labels] @@ -144,6 +146,14 @@ def maximum_users_fields_present? maximum_users.is_a?(Integer) && maximum_users_warning.is_a?(Integer) end + def maximum_attachments_per_record + super || Attachment::DEFAULT_MAX_ATTACHMENTS + end + + def primero_promote_config + super || [] + end + class << self def current(rebuild = false) return @current unless @current.nil? || rebuild @@ -174,3 +184,4 @@ def primary_age_ranges end end end +# rubocop:enable Metrics/ClassLength diff --git a/app/models/theme.rb b/app/models/theme.rb index 5edb2154c8..106da2e9c2 100644 --- a/app/models/theme.rb +++ b/app/models/theme.rb @@ -11,7 +11,7 @@ class Theme < ApplicationRecord navListIconActive navListText navListIcon navListDivider loginBackgroundGradientStart loginBackgroundGradientEnd toolbarBackgroundColorMobileHeader drawerHeaderButton loginTranslationsButtonBackground loginTranslationsButtonText mobileToolbarBackground - mobileToolbarHamburgerButton + mobileToolbarHamburgerButton loginButtonBg loginButtonText ].freeze DEFAULT_THEME = { @@ -23,12 +23,14 @@ class Theme < ApplicationRecord incident monitoring and family tracing and reunification.', colors: { 'manifestThemeColor' => '#0093ba' - } + }, + revision: SecureRandom.uuid }.freeze PICTORIAL_SIZES = %w[144 192 256].freeze - store_accessor :data, :site_description, :site_title, :colors, :use_contained_nav_style, :show_powered_by_primero + store_accessor :data, :site_description, :site_title, :colors, :use_contained_nav_style, :show_powered_by_primero, + :revision has_one_attached :login_background has_one_attached :logo @@ -47,6 +49,12 @@ class Theme < ApplicationRecord validates :favicon, presence: true # rubocop:enable Naming/VariableNumber + before_save :generate_new_revision + + def generate_new_revision + self.revision = SecureRandom.uuid + end + def valid_html_colors return unless colors.present? diff --git a/app/models/trace.rb b/app/models/trace.rb index 8e2e1c7cf1..d56d1d4b80 100644 --- a/app/models/trace.rb +++ b/app/models/trace.rb @@ -28,11 +28,13 @@ def tracing_request_matching_field_names end end - searchable do - extend Searchable::TextIndexing - Trace.trace_matching_field_names.each { |f| text_index(f, 'matchable') } - Trace.tracing_request_matching_field_names.each do |f| - text_index(f, 'matchable', :tracing_request) + if Rails.configuration.solr_enabled + searchable do + extend Searchable::TextIndexing + Trace.trace_matching_field_names.each { |f| text_index(f, 'matchable') } + Trace.tracing_request_matching_field_names.each do |f| + text_index(f, 'matchable', :tracing_request) + end end end diff --git a/app/models/tracing_request.rb b/app/models/tracing_request.rb index abd7720793..28b7362709 100644 --- a/app/models/tracing_request.rb +++ b/app/models/tracing_request.rb @@ -5,6 +5,7 @@ # Describes a request by a single individual to trace one or more children (cases) class TracingRequest < ApplicationRecord include Record + include CalculateTracingNames include Searchable include Ownable include Historical @@ -14,6 +15,7 @@ class TracingRequest < ApplicationRecord include EagerLoadable include Webhookable include LocationCacheable + include PhoneticSearchable has_many :traces store_accessor :data, @@ -31,10 +33,6 @@ def filterable_id_fields %w[tracing_request_id short_id] end - def quicksearch_fields - filterable_id_fields + %w[relation_name relation_nickname tracing_names tracing_nicknames] - end - def summary_field_names common_summary_fields + %w[ relation_name inquiry_date tracing_names @@ -50,6 +48,10 @@ def minimum_reportable_fields } end + def phonetic_field_names + %w[relation_name relation_nickname relation_other_family tracing_names tracing_nicknames] + end + alias super_new_with_user new_with_user def new_with_user(user, data) traces_data = data.delete('tracing_request_subform_section') @@ -64,22 +66,6 @@ def eager_loaded_class end end - def self.sortable_text_fields - %w[relation_name tracing_names short_id] - end - - searchable do - %w[id status].each { |f| string(f, as: "#{f}_sci") } - filterable_id_fields.each { |f| string("#{f}_filterable", as: "#{f}_filterable_sci") { data[f] } } - quicksearch_fields.each { |f| text_index(f) } - sortable_text_fields.each do |f| - string("#{f}_sortable", as: "#{f}_sortable_sci") do - value = data[f] || send(f) - value.is_a?(Array) ? value.join(' ') : value - end - end - end - alias super_defaults defaults def defaults super_defaults @@ -122,14 +108,6 @@ def associations_as_data_keys %w[tracing_request_subform_section] end - def tracing_names - traces.map(&:name).compact - end - - def tracing_nicknames - traces.map(&:name_nickname).compact - end - def set_instance_id self.tracing_request_id ||= unique_identifier end diff --git a/app/models/transfer.rb b/app/models/transfer.rb index 9bcd26f50c..3cd1846aa9 100644 --- a/app/models/transfer.rb +++ b/app/models/transfer.rb @@ -8,6 +8,7 @@ class Transfer < Transition TRANSFER_FORM_UNIQUE_ID = 'transfers_assignments' TRANSFER_ALERT_TYPE = 'transfer' + NOTIFICATION_ACTION = 'transfer_request' class << self def alert_form_unique_id @@ -36,7 +37,7 @@ def accept!(user) remove_assigned_user record.owned_by = transitioned_to record.update_last_updated_by(user) - record.save! && save! + save! update_incident_ownership end @@ -48,14 +49,14 @@ def reject!(user) remove_assigned_user record.update_last_updated_by(user) - record.save! && save! + save! end def revoke!(user) self.status = record.transfer_status = Transition::STATUS_REVOKED remove_assigned_user record.update_last_updated_by(user) - record.save! && save! + save! end def consent_given? @@ -83,9 +84,8 @@ def generate_alert? private def perform_remote_transfer - record.status = Record::STATUS_TRANSFERRED - record.save! # TODO: Export record with the constraints of the external user role + record.status = Record::STATUS_TRANSFERRED end def perform_record_system_transfer @@ -103,6 +103,5 @@ def perform_system_transfer perform_record_system_transfer record.last_updated_by = transitioned_by - record.save! end end diff --git a/app/models/transfer_request.rb b/app/models/transfer_request.rb index 41a90fc927..dac9862430 100644 --- a/app/models/transfer_request.rb +++ b/app/models/transfer_request.rb @@ -6,9 +6,8 @@ class TransferRequest < Transition def perform self.status = Transition::STATUS_INPROGRESS - record.update_last_updated_by(transitioned_by_user) # TODO: Add alert on referrals and transfers form for record - record.save! + record.update_last_updated_by(transitioned_by_user) end def respond!(params) diff --git a/app/models/transition.rb b/app/models/transition.rb index 11f79b43ce..42920295b6 100644 --- a/app/models/transition.rb +++ b/app/models/transition.rb @@ -9,6 +9,7 @@ class Transition < ApplicationRecord STATUS_INPROGRESS = 'in_progress' STATUS_DONE = 'done' STATUS_REVOKED = 'revoked' + NOTIFICATION_ACTION = 'transition_notification' belongs_to :record, polymorphic: true belongs_to :transitioned_to_user, class_name: 'User', foreign_key: 'transitioned_to', @@ -28,7 +29,7 @@ class Transition < ApplicationRecord before_create :copy_transitioned_user_groups_and_agency after_save_commit :notify - after_save :index_record + after_save :save_record def defaults self.created_at ||= DateTime.now @@ -103,10 +104,6 @@ def should_notify? notified_statuses.include?(status) end - def index_record - Sunspot.index(record) if record - end - def update_incident_ownership return unless record.respond_to?(:incidents) @@ -147,4 +144,8 @@ def copy_transitioned_user_groups_and_agency self.transitioned_to_user_agency = transitioned_to_user.agency&.unique_id self.transitioned_to_user_groups = transitioned_to_user.user_group_unique_ids end + + def save_record + record.save! + end end diff --git a/app/models/user.rb b/app/models/user.rb index 9e27b1dce5..b5c5361844 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -10,7 +10,6 @@ # in external IDP (such as Azure Active Directory). # rubocop:disable Metrics/ClassLength class User < ApplicationRecord - include Devise::JWT::RevocationStrategies::Allowlist include ConfigurationRecord include LocationCacheable @@ -20,7 +19,7 @@ class User < ApplicationRecord 'id' => { 'type' => 'integer' }, 'user_name' => { 'type' => 'string' }, 'full_name' => { 'type' => 'string' }, 'code' => { 'type' => 'string' }, 'phone' => { 'type' => 'string' }, 'email' => { 'type' => 'string' }, - 'password_setting' => { 'type' => 'string' }, 'locale' => { 'type' => 'string' }, + 'password_setting' => { 'type' => 'string' }, 'locale' => { 'type' => %w[string null] }, 'agency_id' => { 'type' => 'integer' }, 'position' => { 'type' => 'string' }, 'location' => { 'type' => 'string' }, 'disabled' => { 'type' => 'boolean' }, 'password' => { 'type' => 'string' }, 'password_confirmation' => { 'type' => 'string' }, @@ -28,8 +27,19 @@ class User < ApplicationRecord 'user_group_ids' => { 'type' => 'array' }, 'user_group_unique_ids' => { 'type' => 'array' }, 'services' => { 'type' => 'array' }, 'module_unique_ids' => { 'type' => 'array' }, 'password_reset' => { 'type' => 'boolean' }, 'role_id' => { 'type' => 'string' }, - 'agency_office' => { 'type' => 'string' }, 'code_of_conduct_id' => { 'type' => 'integer' }, - 'send_mail' => { 'type' => 'boolean' }, 'receive_webpush' => { 'type' => 'boolean' } + 'agency_office' => { 'type' => %w[string null] }, 'code_of_conduct_id' => { 'type' => 'integer' }, + 'send_mail' => { 'type' => 'boolean' }, 'receive_webpush' => { 'type' => 'boolean' }, + 'settings' => { + 'type' => %w[object null], 'properties' => { + 'notifications' => { + 'type' => 'object', + 'properties' => { + 'send_mail' => { 'type' => 'object' }, + 'receive_webpush' => { 'type' => 'object' } + } + } + } + } }.freeze attr_accessor :should_send_password_reset_instructions, :user_groups_changed @@ -37,11 +47,12 @@ class User < ApplicationRecord delegate :can?, :cannot?, to: :ability - devise :database_authenticatable, :timeoutable, :recoverable, :lockable, - :jwt_authenticatable, jwt_revocation_strategy: self + devise :database_authenticatable, :timeoutable, :recoverable, :lockable self.unique_id_attribute = 'user_name' + store_accessor :settings, :notifications + belongs_to :role belongs_to :agency, optional: true belongs_to :identity_provider, optional: true @@ -117,7 +128,9 @@ def hidden_attributes end def self_hidden_attributes - %w[role_unique_id identity_provider_unique_id user_name] + %w[role_unique_id identity_provider_unique_id user_name user_group_unique_ids agency_id + identity_provider_id reset_password_token reset_password_sent_at service_account + unlock_token locked_at failed_attempts identity_provider_sync] end def password_parameters @@ -136,14 +149,19 @@ def order_insensitive_attribute_names %w[full_name user_name position] end - def permitted_api_params(current_user = nil, target_user = nil) - permitted_params = ( + def default_permitted_params + ( User.permitted_attribute_names + User.password_parameters + [ { 'user_group_ids' => [] }, { 'user_group_unique_ids' => [] }, - { 'module_unique_ids' => [] }, 'role_unique_id', 'identity_provider_unique_id' + { 'module_unique_ids' => [] }, 'role_unique_id', 'identity_provider_unique_id', + { 'settings' => { 'notifications' => { 'send_mail' => {}, 'receive_webpush' => {} } } } ] ) - User.hidden_attributes + end + + def permitted_api_params(current_user = nil, target_user = nil) + permitted_params = User.default_permitted_params return permitted_params if current_user.nil? || target_user.nil? @@ -547,6 +565,12 @@ def permitted_to_access_record?(record) end end + def specific_notification?(notifier, action) + return false if notifier.blank? || action.blank? + + (notifications&.[](notifier) || {}).select { |_key, value| value }.keys.include?(action) + end + private def set_locale diff --git a/app/models/violation.rb b/app/models/violation.rb index df227dfe72..407e4e7a3b 100644 --- a/app/models/violation.rb +++ b/app/models/violation.rb @@ -4,11 +4,7 @@ # Model for MRM Violation class Violation < ApplicationRecord - # TODO: For now this will be used to only read and index violations. - # Make similar (and test exhaustively!) to Flag model to perform reads and writes # TODO: There is some amount of duplication between this and the Incident container class. Refactor! - # include CouchRest::Model::Embeddable #TODO: This is just so that Sunspot doesn't complain. - # include Indexable TYPES = %w[killing maiming recruitment sexual_violence abduction attack_on_hospitals attack_on_schools military_use denial_humanitarian_access].freeze diff --git a/app/models/webpush_subscription.rb b/app/models/webpush_subscription.rb index b1ac7d195a..030c39c580 100644 --- a/app/models/webpush_subscription.rb +++ b/app/models/webpush_subscription.rb @@ -62,7 +62,7 @@ def list(user, params = {}) def current(user, params) subscription = user&.webpush_subscriptions - &.find_by(notification_url: params[:notification_url]) + &.find_by(notification_url: params[:notification_url]) raise ActiveRecord::RecordNotFound if subscription&.disabled subscription diff --git a/app/overrides/sunspot.rb b/app/overrides/sunspot.rb index 5db8802d86..7f41a32645 100644 --- a/app/overrides/sunspot.rb +++ b/app/overrides/sunspot.rb @@ -10,6 +10,8 @@ Sunspot::Rails::Server.class_eval do # Log file for Solr. File is in the rails log/ directory. def log_file + return unless Rails.configuration.solr_enabled + configuration.log_file end end @@ -18,6 +20,8 @@ def log_file # rsolr = Sunspot.session.session.rsolr_connection Sunspot::Session.class_eval do def rsolr_connection + return unless Rails.configuration.solr_enabled + connection end end diff --git a/app/services/api_connector/abstract_connector.rb b/app/services/api_connector/abstract_connector.rb index 27bd372714..e0f9009abc 100644 --- a/app/services/api_connector/abstract_connector.rb +++ b/app/services/api_connector/abstract_connector.rb @@ -4,6 +4,8 @@ # Abstract superclass for user identity connectors class ApiConnector::AbstractConnector + RETRY_DELAY = 5 # Retry every 5 seconds + RETRY_LIMIT = 3 # Attempt limit attr_accessor :connection def self.build_from_env(options = {}) @@ -69,4 +71,17 @@ def new?(_record) def relevant_updates?(_record) true end + + def with_retry(retry_limit = RETRY_LIMIT, retry_delay = RETRY_DELAY) + retry_limit.times do |attempt| + return yield + rescue Faraday::ConnectionFailed, + Faraday::TimeoutError, + Faraday::SSLError => e + raise e if attempt == retry_limit - 1 + + sleep(retry_delay) + Rails.logger.warn('Conenction Failed, Retrying.') + end + end end diff --git a/app/services/api_connector/primero_configuration_connector.rb b/app/services/api_connector/primero_configuration_connector.rb index 7dad8313a4..845cf894ef 100644 --- a/app/services/api_connector/primero_configuration_connector.rb +++ b/app/services/api_connector/primero_configuration_connector.rb @@ -8,8 +8,10 @@ # The params should really be methods on the model classes class ApiConnector::PrimeroConfigurationConnector < ApiConnector::PrimeroConnector def new?(configuration) - status, _response = connection.get(configuration.api_path) - status == 404 + with_retry do + status, _response = connection.get(configuration.api_path) + status == 404 + end end # We don't actually want to update a remote configuration record, only create @@ -21,4 +23,38 @@ def params(configuration) attributes = %w[id name description version primero_version data] { data: configuration.attributes.slice(*attributes) } end + + # TODO: This can be moved to ApiConnector::AbstractConnector. + # TODO: Keep it here for now because it is the only place that use multiple host connections + def self.build_connectors(options = {}) + config_connectors(options).map do |config| + ApiConnector::PrimeroConfigurationConnector.new(config) + end + end + + def self.config_connectors(opts = {}) + hosts_config(opts).reduce([]) do |result, config| + if config['basic_auth'].nil? && config['basic_auth_secret'].present? + config['basic_auth'] = ENV.fetch(config['basic_auth_secret'], nil) + config.delete('basic_auth_secret') + end + next(result) if config['basic_auth'].blank? + + result << config.with_indifferent_access + end + end + + def self.hosts_config(opts = {}) + (config_connector_from_env(opts) + SystemSettings.current.primero_promote_config).uniq do |config| + config['host'] + end + end + + def self.config_connector_from_env(options = {}) + prefix = options[:prefix] || default_env_prefix + + [ENV.select { |key, _| key.start_with?(prefix) } + .transform_keys { |key| key.delete_prefix(prefix).downcase } + .with_indifferent_access] + end end diff --git a/app/services/api_connector/primero_connector.rb b/app/services/api_connector/primero_connector.rb index 3c043919b9..81240ecfbc 100644 --- a/app/services/api_connector/primero_connector.rb +++ b/app/services/api_connector/primero_connector.rb @@ -8,17 +8,19 @@ # TODO: Consider constraining outbound sends by a Role, like the webhook connector class ApiConnector::PrimeroConnector < ApiConnector::AbstractConnector def create(record) - # TODO: Retry logic - status, response = connection.post(record.class.api_path, params(record)) - # TODO: Should we log on the record that it was sent? - { status:, response: } + with_retry do + status, response = connection.post(record.class.api_path, params(record)) + # TODO: Should we log on the record that it was sent? + { status:, response: } + end end def update(record) - # TODO: Retry logic - status, response = connection.patch(record.api_path, params(record)) - # TODO: Should we log on the record that it was sent? - { status:, response: } + with_retry do + status, response = connection.patch(record.api_path, params(record)) + # TODO: Should we log on the record that it was sent? + { status:, response: } + end end def syncable?(_record) diff --git a/app/services/api_connector/webhook_connector.rb b/app/services/api_connector/webhook_connector.rb index 6dc586e6a4..6977f79ef5 100644 --- a/app/services/api_connector/webhook_connector.rb +++ b/app/services/api_connector/webhook_connector.rb @@ -48,7 +48,7 @@ def relevant_updates?(_record) end def post_params(record) - field_names = PermittedFieldService.new(user, record.class).permitted_field_names + field_names = PermittedFieldService.new(user, record.class).permitted_field_names(record.module_id) data = { record_id: record.id, record_type: record.class.parent_form, diff --git a/app/services/associated_records_service.rb b/app/services/associated_records_service.rb index b3770c5caf..5c4e544f80 100644 --- a/app/services/associated_records_service.rb +++ b/app/services/associated_records_service.rb @@ -7,19 +7,25 @@ class AssociatedRecordsService < ValueObject attr_accessor :user, :update_user_groups, :update_agencies, :update_locations, :update_agency_offices, :models def update_associated_records - records = [] - models.each do |model| - associated_records_for_update(model).find_each(batch_size: 500) do |record| - update_record_ownership_fields(record) - - record.update_associated_user_groups if update_user_groups - record.update_associated_user_agencies if update_agencies + user_group_unique_ids(true) + models.each { |model| update_associated_records_for_model(model) } + end - records << record if record.changed? + def update_associated_records_for_model(model) + associated_records_for_update(model).find_in_batches(batch_size: 500) do |records| + records_to_update = [] + records.each do |record| + update_record_fields(record) + records_to_update << record if record.changed? end + ActiveRecord::Base.transaction { records_to_update.each(&:save!) } end + end - ActiveRecord::Base.transaction { records.each(&:save!) } + def update_record_fields(record) + update_record_ownership_fields(record) + record.update_associated_user_groups if update_user_groups + record.update_associated_user_agencies if update_agencies end def associated_records_for_update(model) @@ -34,10 +40,17 @@ def update_record_ownership_fields(record) return unless record.owned_by == user.user_name record.owned_by_location = user.location if update_locations - record.owned_by_groups = user.user_group_unique_ids if update_user_groups + record.owned_by_groups = user_group_unique_ids if update_user_groups update_record_agency_ownership_fields(record) end + def user_group_unique_ids(reload = false) + return @user_group_unique_ids if @user_group_unique_ids.present? && !reload + + @user_group_unique_ids = user.user_group_unique_ids + @user_group_unique_ids + end + def update_record_agency_ownership_fields(record) record.owned_by_agency_id = user.agency&.unique_id if update_agencies record.owned_by_agency_office = user.agency_office if update_agency_offices diff --git a/app/services/auto_populate_service.rb b/app/services/auto_populate_service.rb new file mode 100644 index 0000000000..0073947ab2 --- /dev/null +++ b/app/services/auto_populate_service.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Derive field values on records, as configured in SystemSettings. +class AutoPopulateService + class << self + def fetch_auto_populate_info(record, auto_populate_info) + id_code_parts = [] + auto_populate_info.format.each { |pf| id_code_parts << PropertyEvaluator.evaluate(record, pf) } + id_code_parts.reject(&:blank?).join(auto_populate_info.separator) + end + + def auto_populate(record, field_key, system_settings = nil) + current_settings = system_settings || SystemSettings.current + auto_populate_info = current_settings.auto_populate_info(field_key) if current_settings.present? + return unless auto_populate_info&.auto_populated == true && auto_populate_info.format.present? + + fetch_auto_populate_info(record, auto_populate_info) + end + + def auto_populate_separator(field_key, system_settings = nil) + current_settings = system_settings || SystemSettings.current + auto_populate_info = current_settings.auto_populate_info(field_key) if current_settings.present? + auto_populate_info.present? ? auto_populate_info.separator : '' + end + end +end diff --git a/app/services/bulk_assign_service.rb b/app/services/bulk_assign_service.rb index 471a2144ba..77c825bdd9 100644 --- a/app/services/bulk_assign_service.rb +++ b/app/services/bulk_assign_service.rb @@ -11,11 +11,19 @@ def initialize(model_class, transitioned_by, args) end def assign_records! - @model_class.where(id: search_results_ids).find_in_batches(batch_size: 10) do |records| + # # Using unscope(:includes) to exclude eager loading, as relationships are not needed for this query. + search_records.records.unscope(:includes).in_batches(of: 10) do |records| assign_records_batch(records) end end + def search_records + PhoneticSearchService.search( + @model_class, query:, phonetic:, filters: search_filters, + sort: sort_order, scope: query_scope + ) + end + private def assign_records_batch(records) @@ -39,10 +47,20 @@ def create_assignment(record) ) end - def search_results_ids - SearchService.search( - @model_class, query:, filters: search_filters, pagination: { page: 1, per_page: Assign::MAX_BULK_RECORDS } - ).hits.map(&:primary_key) + def query_scope + @transitioned_by.record_query_scope(@model_class, @args[:id_search]) + end + + def sort_order + { order_by => @args[:order] || 'desc' } + end + + def order_by + @order_by ||= @args[:order_by] || 'created_at' + end + + def phonetic + @args.dig(:filters, :phonetic) || 'false' end def query @@ -50,6 +68,6 @@ def query end def search_filters - SearchFilterService.new.build_filters(DestringifyService.destringify(@args[:filters], true)) + SearchFilterService.new.build_filters(DestringifyService.destringify(@args[:filters].except(:phonetic).to_h, true)) end end diff --git a/app/services/data_removal_service.rb b/app/services/data_removal_service.rb index 70c867f146..5573902286 100644 --- a/app/services/data_removal_service.rb +++ b/app/services/data_removal_service.rb @@ -6,7 +6,8 @@ class DataRemovalService RECORD_MODELS = [Child, Incident, TracingRequest].freeze DATA_MODELS = [ - Trace, Flag, Alert, Attachment, AuditLog, BulkExport, RecordHistory, SavedSearch, Transition, Violation + Trace, Flag, Alert, Attachment, AuditLog, BulkExport, RecordHistory, SavedSearch, Transition, Violation, + SearchableIdentifier ].freeze METADATA_MODELS = [ Agency, ContactInformation, Field, FormSection, Location, Lookup, PrimeroModule, PrimeroProgram, Report, Role, @@ -46,7 +47,7 @@ def remove_all_records ActiveRecord::Base.connection.execute('DELETE FROM form_sections_roles') end - Sunspot.remove_all(RECORD_MODELS) + remove_from_solr end def remove_config(args = {}) @@ -99,10 +100,16 @@ def to_query(query, filter) ) end - def model_classes(models) - return [] unless models.present? + def model_classes(model_names) + return [] unless model_names.present? + + model_names.map { |name| PrimeroModelService.to_model(name) } + end - models.map { |model| Kernel.const_get(model) } + def remove_from_solr + return unless Rails.configuration.solr_enabled + + Sunspot.remove_all(RECORD_MODELS) end end end diff --git a/app/services/error_service.rb b/app/services/error_service.rb index 5e94dd7bfd..62d6967d03 100644 --- a/app/services/error_service.rb +++ b/app/services/error_service.rb @@ -26,7 +26,7 @@ def self.handle(error, request) resource: request.path ) ] - when Errors::InvalidPrimeroEntityType + when Errors::InvalidPrimeroEntityType, ActionController::ParameterMissing code = 422 errors = [ApplicationError.new(code: 422, message: error.message, resource: request.path)] when Errors::InvalidRecordJson @@ -57,7 +57,7 @@ def self.handle(error, request) JWT::InvalidIssuerError, JWT::InvalidJtiError, JWT::ImmatureSignature, JWT::InvalidSubError code = 401 errors = [ApplicationError.new(code:, message: error.message, resource: request.path)] - when Errors::BulkAssignRecordsSizeError + when Errors::BulkAssignRecordsSizeError, ActionController::InvalidAuthenticityToken code = 403 errors = [ApplicationError.new(code:, message: error.message, resource: request.path)] else diff --git a/app/services/field_i18n_service.rb b/app/services/field_i18n_service.rb index e7e9a4e17b..ae6f7cd220 100644 --- a/app/services/field_i18n_service.rb +++ b/app/services/field_i18n_service.rb @@ -108,23 +108,22 @@ def self.fill_with_locales(source) # fr: [] # } - def self.fill_options_by_locale(locale, options, acc) + def self.fill_options_by_locale(locale, options, acc, include_disabled = true) options.map(&:with_indifferent_access).each do |option| - next if option.dig('display_text', locale).nil? + next if option.dig('display_text', locale).nil? || (!include_disabled && option['disabled']) - value = {}.with_indifferent_access - value['id'] = option['id'] - value['display_text'] = option.dig('display_text', locale) - - acc[locale.to_s] << value + acc[locale.to_s] << { + 'id' => option['id'], + 'display_text' => option.dig('display_text', locale) + }.with_indifferent_access end acc[locale.to_s] end - def self.fill_options(options) + def self.fill_options(options, include_disabled = true) I18n.available_locales.each_with_object({}) do |locale, acc| acc[locale.to_s] = [] - acc[locale.to_s] = fill_options_by_locale(locale, options, acc) + acc[locale.to_s] = fill_options_by_locale(locale, options, acc, include_disabled) end end diff --git a/app/services/field_value_service.rb b/app/services/field_value_service.rb index f5ca628df1..80ff3e7dfb 100644 --- a/app/services/field_value_service.rb +++ b/app/services/field_value_service.rb @@ -54,7 +54,7 @@ def record_name_value(class_name, value, opts = {}) record_class = if class_name.in?(%w[Location ReportingLocation]) location_service else - Object.const_get(class_name) + Agency end return value unless record_class diff --git a/app/services/health_check_service.rb b/app/services/health_check_service.rb index d93245f437..e50c73a817 100644 --- a/app/services/health_check_service.rb +++ b/app/services/health_check_service.rb @@ -23,6 +23,8 @@ def database_accessible? end def solr_accessible? + return true unless Rails.configuration.solr_enabled + Sunspot.session.session.rsolr_connection.head('admin/ping').response[:status] == 200 rescue RSolr::Error::ConnectionRefused false diff --git a/app/services/indicator_query_service.rb b/app/services/indicator_query_service.rb index 6fa8509259..29c5cbf4a2 100644 --- a/app/services/indicator_query_service.rb +++ b/app/services/indicator_query_service.rb @@ -2,56 +2,29 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -# Build and execute a Solr Sunspot query based on a collection of desired indicators. +# Build and execute a SQL query based on a collection of desired indicators. # Indicators are used by the dashboards to compute aggregate statistics about records. class IndicatorQueryService class << self def query(indicators, user) - managed_user_names = indicators.any?(&:scope_to_user) ? user.managed_user_names : [] group_indicators(indicators).each_with_object({}) do |(record_model, record_indicators), result| record_type = record_model.parent_form result[record_type] = {} - group_indicators_by_scope(record_indicators).each do |_, scoped_indicators| - stats = statistics_for_indicators(scoped_indicators, record_model, user, managed_user_names) - result[record_type] = result[record_type].merge(stats) + stats = group_indicators_by_name(record_indicators).reduce({}) do |memo, (name, grouped_indicators)| + memo.merge(name => grouped_indicators.first.stats_for_indicator(user)) end + result[record_type] = result[record_type].merge(stats) end end private - def statistics_for_indicators(indicators, record_model, user, managed_user_names) - search = record_query(record_model, indicators, user) - indicators.to_h { |i| [i.name, i.stats_from_search(search, user, managed_user_names)] } - end - - def record_query(record_model, indicators, user) - record_model.search do - user_query_scope = user.record_query_scope(record_model, false) - SearchService.with_user_scope(self, user_query_scope[:user]) - SearchService.with_module_scope(self, user_query_scope[:module]) - - indicators.each do |indicator| - indicator.query(self, user) - end - end - end - def group_indicators(indicators) indicators.group_by(&:record_model) end - def group_indicators_by_scope(indicators) - indicators.group_by do |indicator| - scope_key = indicator.scope&.map(&:to_h) || {} - pivots = indicator.is_a?(Indicators::PivotedIndicator) ? indicator.pivots : [] - [ - indicator.scope_to_owner, indicator.scope_to_referred, - indicator.scope_to_transferred, indicator.scope_to_owned_by_groups, - indicator.scope_to_not_last_update, indicator.scope_to_transferred_groups, scope_key, - indicator.exclude_zeros, indicator.scope_to_user, pivots - ] - end + def group_indicators_by_name(indicators) + indicators.group_by(&:name) end end end diff --git a/app/services/json_validator_service.rb b/app/services/json_validator_service.rb index 149510461d..6bcc0619db 100644 --- a/app/services/json_validator_service.rb +++ b/app/services/json_validator_service.rb @@ -26,8 +26,40 @@ def validate!(json_hash) raise error end + def strong_params + as_strong_params(:strong_params, schema) + end + private + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/MethodLength + # rubocop:disable Metrics/PerceivedComplexity + # rubocop:disable Metrics/CyclomaticComplexity + def as_strong_params(name, object) + type = [object['type']].flatten + if type.include?('object') + if object['properties'].keys.include?('total') + { name.to_sym => object['properties'].map { |k, v| as_strong_params(k, v) } } + else + object['properties'].map { |k, v| as_strong_params(k, v) } + end + elsif type.include?('array') + items_type = [object['items']['type']].flatten + if items_type.include?('object') + { name.to_sym => object['items']['properties'].map { |k, v| as_strong_params(k, v) } } + else + { name.to_sym => [] } + end + else + name.to_sym + end + end + # rubocop:enable Metrics/CyclomaticComplexity + # rubocop:enable Metrics/PerceivedComplexity + # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/AbcSize + def build_schema(_fields) { 'type' => 'object', 'properties' => {}, 'additionalProperties' => false } end diff --git a/app/services/language_service.rb b/app/services/language_service.rb new file mode 100644 index 0000000000..5f7ef9ce42 --- /dev/null +++ b/app/services/language_service.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# A service to strip diacritic marks from various languages +class LanguageService + # rubocop:disable Layout/HashAlignment + # rubocop:disable Layout/LineLength + LATIN_GREEK = { + from: 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝàáâãäåæçèéêëìíîïñòóôõöøùúûüýÿΆΈΊΌΐάέήίΰϊϋόύώỏἀἁἂἃἄἅἆἈἉἊἌἍἎἐἑἒἓἔἕἘἙἜἝἠἡἢἣἤἥἦἧἨἩἫἬἭἮἯἰἱἲἳἴἵἶἷἸἹἼἽἾὀὁὂὃὄὅὈὉὊὋὌὍὐὑὓὔὕὖὗὙὝὠὡὢὣὤὥὦὧὨὩὫὬὭὮὯὰὲὴὶὸὺὼᾐᾑᾓᾔᾕᾖᾗᾠᾤᾦᾧᾰᾱᾳᾴᾶᾷᾸᾹῂῃῄῆῇῐῑῒῖῗῘῙῠῡῢῥῦῨῩῬῳῴῶῷῸ', + to: 'AAAAAAÆCEEEEIIIINOOOOOOUUUUYaaaaaaæceeeeiiiinoooooouuuuyyΑΕΙΟιαεηιυιυουωoαααααααΑΑΑΑΑΑεεεεεεΕΕΕΕηηηηηηηηΗΗΗΗΗΗΗιιιιιιιιΙΙΙΙΙοοοοοοΟΟΟΟΟΟυυυυυυυΥΥωωωωωωωωΩΩΩΩΩΩΩαεηιουωηηηηηηηωωωωααααααΑΑηηηηηιιιιιΙΙυυυρυΥΥΡωωωωΟ' + }.freeze + + ARABIC_VOWELS = 'ًٌٍَُِّْ'.strip + + CYRILLIC = { + from: 'ҐЁЇЙґёїй', + to: 'ГЕІИгеіи' + }.freeze + # rubocop:enable Layout/HashAlignment + # rubocop:enable Layout/LineLength + + DIACRITICS = { + from: LATIN_GREEK[:from] + CYRILLIC[:from], + to: LATIN_GREEK[:to] + CYRILLIC[:to] + }.freeze + + class << self + def strip_diacritics(value) + strip_arabic_vowels(value.unicode_normalize(:nfc).tr(DIACRITICS[:from], DIACRITICS[:to])) + end + + def strip_arabic_vowels(value) + value.tr(ARABIC_VOWELS, '') + end + + def latin?(value) + value.gsub(/[^a-zA-Z]/, '').present? + end + + def tokenize(value) + return [] unless value.is_a?(String) + + value&.split&.map do |elem| + diacriticless = strip_diacritics(elem) + # NOTE: Text::Metaphone produces upcase strings. Upcasing to keep consistent output. + next(diacriticless.upcase) unless latin?(elem) + + Text::Metaphone.double_metaphone(diacriticless).first + end + end + end +end diff --git a/app/services/model_deletion_service.rb b/app/services/model_deletion_service.rb index 58275f1436..ea3afc3a5a 100644 --- a/app/services/model_deletion_service.rb +++ b/app/services/model_deletion_service.rb @@ -5,7 +5,7 @@ # Service to handle deletion of data for a specific model and its associations # rubocop:disable Metrics/ClassLength class ModelDeletionService < ValueObject - UUID_REFERENCED_MODELS = [Alert, Attachment, Trace, Violation].freeze + UUID_REFERENCED_MODELS = [Alert, Attachment, Trace, Violation, SearchableIdentifier].freeze attr_accessor :model_class def delete_records!(query) @@ -19,7 +19,7 @@ def delete_records!(query) query.delete_all end - Sunspot.remove_by_id(model_class, record_ids) + remove_from_solr(record_ids) end def delete_all! @@ -162,5 +162,11 @@ def model_reflections def model_join_reflections model_class.reflect_on_all_associations(:has_and_belongs_to_many).reject(&:through_reflection?) end + + def remove_from_solr(record_ids) + return unless Rails.configuration.solr_enabled + + Sunspot.remove_by_id(model_class, record_ids) + end end # rubocop:enable Metrics/ClassLength diff --git a/app/services/permitted_attachment_service.rb b/app/services/permitted_attachment_service.rb index 8b4d6d583e..cbdddc67bc 100644 --- a/app/services/permitted_attachment_service.rb +++ b/app/services/permitted_attachment_service.rb @@ -63,7 +63,8 @@ def previewable_type? def permitted_field_names @permitted_field_names ||= permitted_form_fields_service.permitted_field_names( authorized_roles, - Record.map_name(attachment.record_type), + PrimeroModelService.to_name(attachment.record_type), + attachment.record&.module_id, write ) end diff --git a/app/services/permitted_field_service.rb b/app/services/permitted_field_service.rb index 4bb8d2c8d5..57971d312d 100644 --- a/app/services/permitted_field_service.rb +++ b/app/services/permitted_field_service.rb @@ -29,14 +29,15 @@ class PermittedFieldService or not cases_by_date record_in_scope associated_user_names not_edited_by_owner referred_users referred_users_present transferred_to_users transferred_to_user_groups has_photo survivor_code survivor_code_no case_id_display created_at has_incidents short_id record_state sex age registration_date date_closure - reassigned_transferred_on current_alert_types location_current reporting_location_hierarchy + reassigned_transferred_on current_alert_types location_current reporting_location_hierarchy followup_dates + reunification_dates tracing_dates service_implemented_day_times ].freeze PERMITTED_MRM_FILTER_FIELD_NAMES = %w[ individual_violations individual_age individual_sex victim_deprived_liberty_security_reasons reasons_deprivation_liberty victim_facilty_victims_held torture_punishment_while_deprivated_liberty - violation_with_verification_status armed_force_group_party_names late_verified_violations perpetrator_category - date_of_first_report ctfmr_verified_date + violation_with_verification_status armed_force_group_party_names has_late_verified_violations perpetrator_category + date_of_first_report ctfmr_verified_date verification_status ].freeze PERMITTED_RECORD_INFORMATION_FIELDS = %w[ @@ -46,14 +47,13 @@ class PermittedFieldService consent_for_services disclosure_other_orgs ].freeze + PERMITTED_DASHBOARD_FILTERS = { + Permission::DASH_CASE_RISK => %w[risk_level], + Permission::DASH_SHARED_WITH_OTHERS => %w[transfer_status], + Permission::DASH_SHARED_FROM_MY_TEAM => %w[transfer_status] + }.freeze + PERMITTED_FIELDS_FOR_ACTION_SCHEMA = { - Permission::ADD_NOTE => { 'notes_section' => { 'type' => %w[array null], 'items' => { 'type' => 'object' } } }, - Permission::INCIDENT_DETAILS_FROM_CASE => { - 'incident_details' => { 'type' => %w[array null], 'items' => { 'type' => 'object' } } - }, - Permission::SERVICES_SECTION_FROM_CASE => { - 'services_section' => { 'type' => %w[array null], 'items' => { 'type' => 'object' } } - }, Permission::CLOSE => { 'status' => { 'type' => 'string' }, 'date_closure' => { 'type' => 'date' } }, Permission::REOPEN => { 'status' => { 'type' => 'string' }, 'workflow' => { 'type' => 'string' }, @@ -62,6 +62,17 @@ class PermittedFieldService Permission::ENABLE_DISABLE_RECORD => { 'record_state' => { 'type' => 'boolean' } }, Permission::INCIDENT_FROM_CASE => { 'incident_case_id' => { 'type' => 'string', 'format' => 'regex', 'pattern' => UUID_REGEX } + }, + Permission::ADD_REGISTRY_RECORD => { + 'registry_record_id' => { 'type' => %w[string null], 'format' => 'regex', 'pattern' => UUID_REGEX } + }, + Permission::CASE_FROM_FAMILY => { + 'family_id' => { 'type' => %w[string null], 'format' => 'regex', 'pattern' => UUID_REGEX }, + 'family_member_id' => { 'type' => %w[string null], 'format' => 'regex', 'pattern' => UUID_REGEX } + }, + Permission::LINK_FAMILY_RECORD => { + 'family_id' => { 'type' => %w[string null], 'format' => 'regex', 'pattern' => UUID_REGEX }, + 'family_member_id' => { 'type' => %w[string null], 'format' => 'regex', 'pattern' => UUID_REGEX } } }.freeze @@ -74,11 +85,11 @@ class PermittedFieldService ID_SEARCH_FIELDS = %w[age date_of_birth estimated name sex].freeze - def initialize(user, model_class, action_name = nil, id_search = nil, permitted_form_field_service = nil) + def initialize(user, model_class, permitted_form_field_service = nil, options = {}) self.user = user self.model_class = model_class - self.action_name = action_name - self.id_search = id_search + self.action_name = options[:action_name] + self.id_search = options[:id_search] self.permitted_form_field_service = permitted_form_field_service || PermittedFormFieldsService.instance end @@ -87,14 +98,15 @@ def initialize(user, model_class, action_name = nil, id_search = nil, permitted_ # rubocop:disable Metrics/CyclomaticComplexity # rubocop:disable Metrics/MethodLength # rubocop:disable Metrics/PerceivedComplexity - def permitted_field_names(writeable = false, update = false, roles = []) + # rubocop:disable Metrics/ParameterLists + def permitted_field_names(module_unique_id = nil, writeable = false, update = false, roles = []) return @permitted_field_names if @permitted_field_names.present? - return permitted_field_names_from_action_name if action_name.present? + return permitted_field_names_from_action_name if permitted_field_names_from_action_name.present? @permitted_field_names = permitted_core_fields(update) + PERMITTED_FILTER_FIELD_NAMES @permitted_field_names += PERMITTED_MRM_FILTER_FIELD_NAMES if user.module?(PrimeroModule::MRM) @permitted_field_names += permitted_form_field_service.permitted_field_names( - roles.presence || [user.role], model_class.parent_form, writeable + roles.presence || [user.role], model_class.parent_form, module_unique_id, writeable ) # TODO: Consider moving model specific permitted fields to the model class. @permitted_field_names += %w[workflow status case_status_reopened] if model_class == Child @@ -104,11 +116,15 @@ def permitted_field_names(writeable = false, update = false, roles = []) @permitted_field_names += SYNC_FIELDS_SCHEMA.keys if external_sync? @permitted_field_names += permitted_incident_field_names @permitted_field_names << 'incident_details' if user.can?(:view_incident_from_case, model_class) - @permitted_field_names += permitted_approval_schema.keys + approval_fields = permitted_approval_schema.keys + @permitted_field_names += permitted_approval_schema.keys if approval_fields.present? + @permitted_field_names << 'approval_subforms' if approval_fields.present? @permitted_field_names += permitted_overdue_task_field_names @permitted_field_names += PERMITTED_RECORD_INFORMATION_FIELDS if user.can?(:read, model_class) @permitted_field_names += ID_SEARCH_FIELDS if id_search.present? - @permitted_field_names += permitted_reporting_location_field + @permitted_field_names += permitted_dashboard_filter_field_names + @permitted_field_names += permitted_reporting_location_field if model_class == Child + @permitted_field_names += permitted_incident_reporting_location_field if model_class == Incident @permitted_field_names += permitted_registry_record_id @permitted_field_names += permitted_family_id @permitted_field_names += permitted_attachment_fields @@ -120,6 +136,7 @@ def permitted_core_fields(update = false) update ? core_fields - %w[id] : core_fields end + # TODO: The method is essentially duplicating some logic from permitted_field_names. DRY! def permitted_fields_schema schema = PERMITTED_CORE_FIELDS_SCHEMA.dup permitted_actions = @@ -128,20 +145,28 @@ def permitted_fields_schema schema['hidden_name'] = { 'type' => 'boolean' } if user.can?(:update, model_class) schema['reporting_location_hierarchy'] = { 'type' => 'string' } if user.can?(:update, model_class) schema = schema.merge(SYNC_FIELDS_SCHEMA) if external_sync? - schema = schema.merge(permitted_mrm_entities_schema) if user.module?(PrimeroModule::MRM) schema.merge(permitted_approval_schema) end # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/MethodLength # rubocop:enable Metrics/PerceivedComplexity + # rubocop:enable Metrics/ParameterLists def permitted_reporting_location_field reporting_location_config = user.role.reporting_location_config return [] if reporting_location_config.blank? - ["#{reporting_location_config.field_key}#{reporting_location_config.admin_level}"] + [reporting_location_config.field_key] + end + + def permitted_incident_reporting_location_field + incident_reporting_location_config = user.role.incident_reporting_location_config + + return [] if incident_reporting_location_config.blank? + + [incident_reporting_location_config.field_key] end def permitted_registry_record_id @@ -174,7 +199,6 @@ def permitted_approval_schema Approval.types.each_with_object({}) do |approval_id, schema| next unless approval_access?(user, approval_id) - schema['approval_subforms'] = { 'type' => %w[array null], 'items' => { 'type' => 'object' } } schema["#{approval_id}_approved"] = { 'type' => 'boolean' } schema["approval_status_#{approval_id}"] = { 'type' => 'string' } schema["#{approval_id}_approved_date"] = { 'type' => %w[date string], 'format' => 'date' } @@ -219,12 +243,6 @@ def permitted_incident_field_names incident_field_names end - def permitted_mrm_entities_schema - (Violation::TYPES + Violation::MRM_ASSOCIATIONS_KEYS).each_with_object({}) do |entry, schema| - schema[entry] = { 'type' => %w[array null], 'items' => { 'type' => 'object' } } - end - end - def permitted_attachment_fields attachment_field_names = [] if user.can?(:search_owned_by_others, model_class) && user.can_preview?(model_class) @@ -236,5 +254,13 @@ def permitted_attachment_fields attachment_field_names end + + def permitted_dashboard_filter_field_names + PERMITTED_DASHBOARD_FILTERS.reduce([]) do |memo, (dashboard, field_names)| + next memo unless user.can?(dashboard.to_sym, Dashboard) + + memo + field_names + end + end end # rubocop:enable Metrics/ClassLength diff --git a/app/services/permitted_form_fields_service.rb b/app/services/permitted_form_fields_service.rb index 1d3cfb75dd..ed4ec51798 100644 --- a/app/services/permitted_form_fields_service.rb +++ b/app/services/permitted_form_fields_service.rb @@ -8,6 +8,20 @@ class PermittedFormFieldsService attr_accessor :fields, :field_names, :with_cache + PERMITTED_WRITEABLE_FIELD_TYPES = [ + Field::TEXT_FIELD, Field::TEXT_AREA, Field::RADIO_BUTTON, Field::TICK_BOX, + Field::SELECT_BOX, Field::NUMERIC_FIELD, Field::DATE_FIELD, + Field::AUDIO_UPLOAD_BOX, Field::PHOTO_UPLOAD_BOX, Field::DOCUMENT_UPLOAD_BOX, + Field::SUBFORM, Field::TALLY_FIELD, Field::CALCULATED + ].freeze + + # TODO: Primero is assuming that these forms exist in the configuration. If they + PERMITTED_SUBFORMS_FOR_ACTION = { + Permission::ADD_NOTE => 'notes_section', + Permission::INCIDENT_DETAILS_FROM_CASE => 'incident_details', + Permission::SERVICES_SECTION_FROM_CASE => 'services_section' + }.freeze + def self.instance new(Rails.configuration.use_app_cache) end @@ -16,51 +30,104 @@ def initialize(with_cache = false) self.with_cache = with_cache end - def rebuild_cache(roles, record_type, writeable, force = false) + def rebuild_cache(roles, record_type, module_unique_id, writeable, force = false) return unless force || fields.nil? # The assumption here is that the cache will be updated if any changes took place to Forms, or Roles role_keys = roles.map(&:cache_key_with_version) - cache_key = "permitted_form_fields_service/#{role_keys.join('/')}/#{record_type}/#{writeable}" + cache_key = "permitted_form_fields_service/#{role_keys.join('/')}/#{module_unique_id}/#{record_type}/#{writeable}" self.fields = Rails.cache.fetch(cache_key, expires_in: 48.hours) do - permitted_fields_from_forms(roles, record_type, writeable).to_a + permitted_fields_from_forms(roles, record_type, module_unique_id, writeable).to_a end # TODO: This can be cached too self.field_names = fields.map(&:name).uniq end - # TODO: Constrain to only allow API data updates on the following types: - # TEXT_FIELD, TEXT_AREA, RADIO_BUTTON, SELECT_BOX, NUMERIC_FIELD, DATE_FIELD, SUBFORM, TICK_BOX - def permitted_fields_from_forms(roles, record_type, writeable, visible_only = false) - permission_level = writeable ? FormPermission::PERMISSIONS[:read_write] : writeable - fields = Field.includes(subform: :fields).joins(form_section: :roles).where( - fields: { - form_sections: { roles: { id: roles }, parent_form: record_type, visible: (visible_only || nil) }.compact - } - ) - if writeable - fields = fields.where(fields: { form_sections: { form_sections_roles: { permission: permission_level } } }) - end - fields + def permitted_fields_from_forms(roles, record_type, module_unique_id, writeable, visible_only = false) + fields = fetch_filtered_fields(roles, record_type, module_unique_id, visible_only) + return fields unless writeable + + fields = filter_writeable_fields(fields, permission_level(writeable), record_type, module_unique_id) + action_subform_fields = permitted_subforms_from_actions(roles, record_type) + append_action_subform_fields(fields, action_subform_fields, record_type, module_unique_id) end alias with_cache? with_cache - def permitted_fields(roles, record_type, writeable) + def permitted_fields(roles, record_type, module_unique_id, writeable) if with_cache? - rebuild_cache(roles, record_type, writeable) + rebuild_cache(roles, record_type, module_unique_id, writeable) fields else - permitted_fields_from_forms(roles, record_type, writeable).to_a + permitted_fields_from_forms(roles, record_type, module_unique_id, writeable).to_a end end - def permitted_field_names(roles, record_type, writeable) + def permitted_field_names(roles, record_type, module_unique_id, writeable) if with_cache? - rebuild_cache(roles, record_type, writeable) + rebuild_cache(roles, record_type, module_unique_id, writeable) field_names else - permitted_fields_from_forms(roles, record_type, writeable).map(&:name).uniq + permitted_fields_from_forms(roles, record_type, module_unique_id, writeable).map(&:name).uniq end end + + def permitted_subforms_from_actions(roles, record_type) + roles = [roles].flatten + roles.map do |role| + PERMITTED_SUBFORMS_FOR_ACTION.select { |k, _v| role.permits?(record_type, k) }.values + end.flatten.uniq + end + + private + + def permission_level(writeable) + writeable ? FormPermission::PERMISSIONS[:read_write] : writeable + end + + def eagerloaded_fields + Field.includes(subform: :fields).left_outer_joins(form_section: %i[roles primero_modules]) + end + + def fetch_filtered_fields(roles, record_type, module_unique_id, visible_only) + eagerloaded_fields.where( + fields: { + form_sections: { + roles: { id: roles }, + visible: visible_only || nil, + parent_form: record_type + }.compact.merge(module_unique_id.present? ? { primero_modules: { unique_id: module_unique_id } } : {}) + } + ) + end + + def filter_writeable_fields(fields, permission_level, record_type, module_unique_id) + fields.where( + fields: { + form_sections: { + form_sections_roles: { permission: permission_level }, + primero_modules: { unique_id: module_unique_id }, parent_form: record_type + }, + type: PERMITTED_WRITEABLE_FIELD_TYPES + } + ) + end + + def append_action_subform_fields(fields, action_subform_fields, record_type, module_unique_id) + return fields unless action_subform_fields.present? + + fields.or( + eagerloaded_fields.where( + name: action_subform_fields, + type: Field::SUBFORM, + form_sections: { primero_modules: { unique_id: module_unique_id }, parent_form: record_type } + ) + ) + end + + def permitted_field_scope(record_type, module_unique_id) + { + primero_modules: { unique_id: module_unique_id }, parent_form: record_type + } + end end diff --git a/app/services/phonetic_search_service.rb b/app/services/phonetic_search_service.rb new file mode 100644 index 0000000000..d1bb83d134 --- /dev/null +++ b/app/services/phonetic_search_service.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# A service that performs phonetic searches using SQL +class PhoneticSearchService + DEFAULT_SEARCH_PARAMS = { + filters: [], + scope: {}, + sort: { created_at: :desc }, + pagination: {}, + phonetic: false + }.freeze + + attr_accessor :record_class, :search_params + + def self.search(record_class, search_params = {}) + new(record_class, search_params).search + end + + def initialize(record_class, search_params) + self.record_class = record_class + self.search_params = DEFAULT_SEARCH_PARAMS.merge(search_params) + end + + def search + search_query.with_scope(search_params[:scope]) + .with_filters(search_params[:filters]) + .result + .paginate(search_params[:pagination]) + end + + def phonetic? + search_params[:phonetic] == 'true' + end + + private + + def search_query + return Search::SearchQuery.phonetic(record_class, search_params[:query]) if phonetic? + + Search::SearchQuery.filter_ids(record_class, search_params[:query]).with_sort(search_params[:sort]) + end +end diff --git a/app/services/primero_configuration_sync_service.rb b/app/services/primero_configuration_sync_service.rb index de2a82f767..b3195abab0 100644 --- a/app/services/primero_configuration_sync_service.rb +++ b/app/services/primero_configuration_sync_service.rb @@ -9,7 +9,7 @@ class PrimeroConfigurationSyncService ENV_PREFIX = 'PRIMERO_PROMOTE_CONFIG_PROD_' - attr_accessor :connector + attr_accessor :connector, :connectors class << self def instance @@ -18,7 +18,7 @@ def instance def build new.tap do |s| - s.connector = ApiConnector::PrimeroConfigurationConnector.build_from_env(prefix: ENV_PREFIX) + s.connectors = ApiConnector::PrimeroConfigurationConnector.build_connectors(prefix: ENV_PREFIX) end end @@ -28,6 +28,14 @@ def sync!(record) end def sync!(record) - connector.sync(record) + connectors.each do |connector| + Rails.logger.info("[sync][config]['host'] #{connector.connection.options['host']}") + sync_response = connector.sync(record) + + Rails.logger.info("[sync][response][status] #{sync_response[:status]}") + rescue StandardError => e + puts e + next + end end end diff --git a/app/services/primero_model_service.rb b/app/services/primero_model_service.rb new file mode 100644 index 0000000000..db9e299b11 --- /dev/null +++ b/app/services/primero_model_service.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2024 UNICEF. All rights reserved. + +# Use this service to convert name strings of Primero models into class objects. +# Thsi is useful if a record saves a type field. Only permitted strings can be turned into classes. +class PrimeroModelService + VALID_MODEL_NAMES = %w[ + Child Incident Violation TracingRequest Trace RegistryRecord Family + ReportableFollowUp ReportableProtectionConcern ReportableService Dashboard + Flag Alert Attachment AuditLog BulkExport RecordHistory SavedSearch Transition Task ActivityLog + Agency ContactInformation Field FormSection Location Lookup PrimeroModule PrimeroProgram Report User Role + Permission SystemSettings UserGroup ExportConfiguration PrimeroConfiguration Webhook IdentityProvider Kpi + ].freeze + + def self.to_model(name) + name = if %w[case Case].include?(name) + 'Child' + else + name.classify + end + return unless VALID_MODEL_NAMES.include?(name) + + Object.const_get(name) + rescue NameError + nil + end + + def self.to_name(name) + name = name.underscore + name == 'child' ? 'case' : name + end +end diff --git a/app/services/record_json_validator_service.rb b/app/services/record_json_validator_service.rb index 98df46b7cb..2b449fdecb 100644 --- a/app/services/record_json_validator_service.rb +++ b/app/services/record_json_validator_service.rb @@ -54,7 +54,7 @@ def build_schema(fields) when Field::TALLY_FIELD properties[field.name] = { 'type' => %w[object null], 'properties' => tally_properties(field.tally_i18n) } when Field::CALCULATED - properties[field.name] = { 'type' => %w[integer string boolean array null], + properties[field.name] = { 'type' => %w[integer number string boolean null], 'minimum' => -2_147_483_648, 'maximum' => 2_147_483_647 } end diff --git a/app/services/search/search_query.rb b/app/services/search/search_query.rb new file mode 100644 index 0000000000..d12e02cbfd --- /dev/null +++ b/app/services/search/search_query.rb @@ -0,0 +1,103 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# A class to generate a SQL query +class Search::SearchQuery + MATCHED_QUERY_COUNT = %( + ( + SELECT COUNT(phonetic) FROM JSONB_ARRAY_ELEMENTS_TEXT(phonetic_data->'tokens') AS phonetic + WHERE ARRAY[:values] @> ARRAY[phonetic] + ) + ) + + attr_accessor :record_class + + class << self + def phonetic(record_class, query) + new(record_class).phonetic(query) + end + + def filter_ids(record_class, query) + new(record_class).filter_ids(query) + end + end + + def initialize(record_class) + self.record_class = record_class + @query = record_class.eager_loaded_class + end + + def phonetic(value) + return self unless value.present? + + tokens = LanguageService.tokenize(value) + @query = @query.where("phonetic_data ->'tokens' ?| array[:values]", values: tokens) + .order(Arel.sql("#{phonetic_score_query(tokens)} #{similarity_score_query(value)}")) + self + end + + def filter_ids(value) + return self unless value.present? + + @query = @query.where( + 'id IN (:records)', + records: SearchableIdentifier.select('record_id').where(record_type: record_class.name).where( + 'value ILIKE :value', value: "%#{ActiveRecord::Base.sanitize_sql_like(value&.strip)}%" + ) + ) + + self + end + + def with_scope(scope) + return self unless scope.present? + + @query = Search::SearchScope.apply(scope, @query) + self + end + + def with_filters(filters) + return self unless filters.present? + + filters.each do |filter| + @query = filter.not_filter ? @query.where.not(filter.query) : @query.where(filter.query) + end + + self + end + + def with_sort(sort) + return self unless sort.present? + + sort.each do |sort_field, direction| + @query = @query.order( + ActiveRecord::Base.sanitize_sql_for_order([Arel.sql("data->? #{order_direction(direction)}"), [sort_field]]) + ) + end + + self + end + + def result + Search::SearchResult.new(@query) + end + + private + + def phonetic_score_query(values) + ActiveRecord::Base.sanitize_sql_for_conditions(["(#{MATCHED_QUERY_COUNT}) DESC", { values: }]) + end + + def similarity_score_query(value) + record_class.phonetic_field_names.map do |field_name| + ActiveRecord::Base.sanitize_sql_for_conditions( + ['WORD_SIMILARITY(data->>:field_name, :value) DESC', { field_name:, value: }] + ) + end.join(', ')&.prepend(', ') + end + + def order_direction(order_direction) + ActiveRecord::QueryMethods::VALID_DIRECTIONS.include?(order_direction) ? order_direction : :asc + end +end diff --git a/app/services/search/search_result.rb b/app/services/search/search_result.rb new file mode 100644 index 0000000000..4dca5dd371 --- /dev/null +++ b/app/services/search/search_result.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# A class that stores the results of a search +class Search::SearchResult + DEFAULT_PER_PAGE = 10 + DEFAULT_PAGE = 1 + + attr_accessor :total + + def initialize(query) + @query = query + self.total = @query.count + end + + def records + @query + end + + def paginate(pagination) + return self unless pagination.present? + + per = pagination[:per_page] || DEFAULT_PER_PAGE + page = pagination[:page] || DEFAULT_PAGE + offset = (page - 1) * per + + @query = @query.limit(per).offset(offset) + + self + end +end diff --git a/app/services/search/search_scope.rb b/app/services/search/search_scope.rb new file mode 100644 index 0000000000..69582bc135 --- /dev/null +++ b/app/services/search/search_scope.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# A class that applies a scope in a SQL Query +class Search::SearchScope < ValueObject + attr_accessor :scope, :user_scope, :module_scope + + def self.apply(scope, query) + new(scope:).apply(query) + end + + def initialize(args = {}) + super(args) + self.user_scope = args[:user_scope] || scope&.dig(:user) + self.module_scope = args[:module_scope] || scope&.dig(:module) + end + + def apply(query) + @query = query + @query = apply_user_scope + @query = apply_module_scope + @query + end + + private + + def apply_user_scope + return @query unless user_scope.present? + + if user_scope['user'].present? + apply_user_associated_scope + elsif user_scope['agency'].present? + apply_agency_associated_scope + elsif user_scope['group'].present? + apply_group_associated_scope + else + @query + end + end + + def apply_user_associated_scope + @query.where(SearchFilters::TextValue.new(field_name: 'associated_user_names', value: user_scope['user']).query) + end + + def apply_agency_associated_scope + @query.where( + SearchFilters::TextValue.new(field_name: 'associated_user_agencies', value: user_scope['agency']).query + ) + end + + def apply_group_associated_scope + @query.where(SearchFilters::TextList.new(field_name: 'associated_user_groups', values: user_scope['group']).query) + end + + def apply_module_scope + return @query unless module_scope.present? + + @query.where(SearchFilters::TextList.new(field_name: 'module_id', values: module_scope).query) + end +end diff --git a/app/services/search_filter_service.rb b/app/services/search_filter_service.rb index d5ab70c897..1b509ee39d 100644 --- a/app/services/search_filter_service.rb +++ b/app/services/search_filter_service.rb @@ -5,12 +5,20 @@ # Transform a params hash into SearchFilters::SearchFiklter objects class SearchFilterService EXCLUDED = %w[format controller action page per order order_by fields id_search].freeze + FILTERABLE_MODELS = [Child, Incident, TracingRequest, RegistryRecord, Family].freeze - def self.build_filters(params, permitted_field_names) - service = SearchFilterService.new - filter_params = service.select_filter_params(params, permitted_field_names) - filter_params = DestringifyService.destringify(filter_params.to_h, true) - service.build_filters(filter_params) + class << self + def build_filters(params, permitted_field_names) + service = SearchFilterService.new + filter_params = service.select_filter_params(params, permitted_field_names) + filter_params = DestringifyService.destringify(filter_params.to_h, true) + id_params = service.select_id_params(params) + service.build_filters(filter_params.merge(id_params)) + end + + def boolean?(value) + [TrueClass, FalseClass].any? { |klass| value.is_a?(klass) } + end end # rubocop:disable Metrics/AbcSize @@ -19,14 +27,14 @@ def self.build_filters(params, permitted_field_names) # rubocop:disable Metrics/PerceivedComplexity def build_filters(params) params.map do |key, value| - if key == 'or' - if value.is_a?(Array) - SearchFilters::Or.new(filters: value.map { |v| build_filters(v).first }) - elsif value.is_a?(Hash) - SearchFilters::Or.new(filters: build_filters(value)) - end + if key == 'id' + build_id_filter(key, value) + elsif key == 'or' + build_or_filter(value) elsif key == 'not' - SearchFilters::NotValue.new(field_name: value.keys.first, values: value.values.first) + build_not_filter(value.keys.first, value.values.first) + elsif key.starts_with?('loc:') + build_location_filter(key, value) elsif value.is_a?(Hash) if value['from'].is_a?(Numeric) SearchFilters::NumericRange.new(field_name: key, from: value['from'], to: value['to']) @@ -34,19 +42,92 @@ def build_filters(params) SearchFilters::DateRange.new(field_name: key, from: value['from'], to: value['to']) end elsif value.is_a?(Array) - SearchFilters::ValueList.new(field_name: key, values: value) + build_array_filter(key, value) + elsif SearchFilterService.boolean?(value) + SearchFilters::BooleanValue.new(field_name: key, value:) + elsif value.is_a?(String) + SearchFilters::TextValue.new(field_name: key, value:) else SearchFilters::Value.new(field_name: key, value:) end - end + end.compact end # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/MethodLength # rubocop:enable Metrics/PerceivedComplexity + # rubocop:disable Metrics/MethodLength + def build_not_filter(field_name, value) + if field_name == 'id' + build_id_filter(field_name, value, true) + elsif field_name.starts_with?('loc:') + build_location_filter(field_name, value, true) + elsif value.is_a?(Array) + build_array_filter(field_name, value, true) + elsif SearchFilterService.boolean?(value) + SearchFilters::BooleanValue.new(field_name:, value:, not_filter: true) + elsif value.is_a?(String) + SearchFilters::TextValue.new(field_name:, value:, not_filter: true) + else + SearchFilters::Value.new(field_name:, value:, not_filter: true) + end + end + # rubocop:enable Metrics/MethodLength + + def build_array_filter(field_name, value, not_filter = false) + if value.first.is_a?(Hash) + build_range_list_filter(field_name, value, not_filter) + elsif SearchFilterService.boolean?(value.first) + SearchFilters::BooleanList.new(field_name:, values: value, not_filter:) + elsif value.first.is_a?(String) + SearchFilters::TextList.new(field_name:, values: value, not_filter:) + else + SearchFilters::ValueList.new(field_name:, values: value, not_filter:) + end + end + + def build_range_list_filter(field_name, value, not_filter = false) + if value.first['from'].is_a?(Numeric) + SearchFilters::RangeList.new(field_name:, values: value, range_type: SearchFilters::NumericRange, not_filter:) + elsif value.first['from'].respond_to?(:strftime) + SearchFilters::RangeList.new(field_name:, values: value, range_type: SearchFilters::DateRange, not_filter:) + else + raise(Errors::InvalidPrimeroEntityType, 'Filter is not valid') + end + end + + def build_location_filter(field_name, value, not_filter = false) + return SearchFilters::LocationList.new(field_name:, values: value, not_filter:) if value.is_a?(Array) + + SearchFilters::LocationValue.new(field_name:, value:, not_filter:) + end + + def build_id_filter(field_name, value, not_filter = false) + return SearchFilters::IdListFilter.new(field_name:, values: value, not_filter:) if value.is_a?(Array) + + SearchFilters::IdFilter.new(field_name:, value:, not_filter:) + end + + def build_or_filter(value) + if value.is_a?(Array) + SearchFilters::Or.new(filters: value.map { |v| build_filters(v).first }) + elsif value.is_a?(Hash) + SearchFilters::Or.new(filters: build_filters(value)) + end + end + def select_filter_params(params, permitted_field_names) - filter_params = params.except(*EXCLUDED) + excluded_params = EXCLUDED + filterable_id_fields + filter_params = params.except(*excluded_params) filter_params.select { |key, _| permitted_field_names.any? { |name| key.match?(/#{name}[0-5]?$/) } } end + + def select_id_params(params) + params.select { |key, _| filterable_id_fields.include?(key) } + end + + def filterable_id_fields + @filterable_id_fields = FILTERABLE_MODELS.map(&:filterable_id_fields).flatten + end end diff --git a/app/services/search_service.rb b/app/services/search_service.rb index 4b3ead789c..f88f3f079e 100644 --- a/app/services/search_service.rb +++ b/app/services/search_service.rb @@ -3,6 +3,7 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. # Query for records using Sunspot Solr +# TODO this will be deleted once exports are migrated class SearchService class << self # rubocop:disable Metrics/MethodLength diff --git a/app/views/api/v2/attachments/update.json.jbuilder b/app/views/api/v2/attachments/update.json.jbuilder new file mode 100644 index 0000000000..1e5cce2946 --- /dev/null +++ b/app/views/api/v2/attachments/update.json.jbuilder @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +json.data do + json.partial! 'api/v2/attachments/attachment', + attachment: @attachment, updates_for_record: @updated_field_names +end diff --git a/app/views/api/v2/flags/_flag.json.jbuilder b/app/views/api/v2/flags/_flag.json.jbuilder index b5b5f3044f..e19241a29d 100644 --- a/app/views/api/v2/flags/_flag.json.jbuilder +++ b/app/views/api/v2/flags/_flag.json.jbuilder @@ -7,7 +7,7 @@ json.name RecordDataService.visible_name(flag&.record) json.short_id flag&.record&.short_id json.owned_by flag&.record&.owned_by json.owned_by_agency_id flag&.record&.owned_by_agency_id -json.record_type Record.map_name(flag.record_type).pluralize +json.record_type PrimeroModelService.to_name(flag.record_type).pluralize record_access_denied = !current_user.can?(:read, flag&.record) json.record_access_denied record_access_denied diff --git a/app/views/api/v2/potential_matches/index.json.jbuilder b/app/views/api/v2/potential_matches/index.json.jbuilder index 0a06779a7a..243d79309e 100644 --- a/app/views/api/v2/potential_matches/index.json.jbuilder +++ b/app/views/api/v2/potential_matches/index.json.jbuilder @@ -10,6 +10,6 @@ json.data do end json.record do json.id @record.id - json.type Record.map_name(@record.class.name) + json.type PrimeroModelService.to_name(@record.class.name) end end diff --git a/app/views/api/v2/primero_modules/_primero_module.json.jbuilder b/app/views/api/v2/primero_modules/_primero_module.json.jbuilder index 576c0262e9..d030049832 100644 --- a/app/views/api/v2/primero_modules/_primero_module.json.jbuilder +++ b/app/views/api/v2/primero_modules/_primero_module.json.jbuilder @@ -16,7 +16,7 @@ if primero_module.unique_id == PrimeroModule::CP json.workflows do if primero_module.workflow_status_indicator ['case'].each do |record_type| - record_class = Record.model_from_name(record_type) + record_class = PrimeroModelService.to_model(record_type) json.set! record_type do json.merge! FieldI18nService.convert_options(record_class.workflow_statuses([primero_module])) end diff --git a/app/views/api/v2/record_histories/index.json.jbuilder b/app/views/api/v2/record_histories/index.json.jbuilder index 7cfca888cb..4f22ebe028 100644 --- a/app/views/api/v2/record_histories/index.json.jbuilder +++ b/app/views/api/v2/record_histories/index.json.jbuilder @@ -5,7 +5,7 @@ json.data do json.array! @record_histories do |record_history| json.record_id @record.id - json.record_type Record.map_name(record_history.record_type).pluralize + json.record_type PrimeroModelService.to_name(record_history.record_type).pluralize json.datetime record_history.datetime&.iso8601 json.user_name record_history.user_name json.action record_history.action diff --git a/app/views/api/v2/system_settings/index.json.jbuilder b/app/views/api/v2/system_settings/index.json.jbuilder index 757ece1475..64f5f480f4 100644 --- a/app/views/api/v2/system_settings/index.json.jbuilder +++ b/app/views/api/v2/system_settings/index.json.jbuilder @@ -15,6 +15,9 @@ json.data do json.reporting_location_config current_user.role.reporting_location_config json.approvals_labels FieldI18nService.to_localized_values(@system_setting.approvals_labels_i18n) json.export_require_password ZipService.require_password? + json.system_options @system_setting.system_options + .merge('maximum_attachments_per_record' => + @system_setting.maximum_attachments_per_record) if code_of_conduct json.code_of_conduct do json.partial! 'api/v2/codes_of_conduct/code_of_conduct', code_of_conduct: diff --git a/app/views/api/v2/transitions/_transition.json.jbuilder b/app/views/api/v2/transitions/_transition.json.jbuilder index 280f782da9..a5e476c18a 100644 --- a/app/views/api/v2/transitions/_transition.json.jbuilder +++ b/app/views/api/v2/transitions/_transition.json.jbuilder @@ -5,7 +5,7 @@ json.merge!( transition.attributes.to_h do |attr, value| if attr == 'record_type' - [attr, Record.map_name(value)] + [attr, PrimeroModelService.to_name(value)] else [attr, value] end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 970a713af0..36d2c82cff 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -6,15 +6,15 @@ <%= csrf_meta_tag %> <%= csp_property_meta_tag %> - + <%= @theme&.site_title || 'Primero' %> - + - + <%= stylesheet_bundle_tag 'application', skip_pipeline: true, manifest: :application, nonce: true %> @@ -22,6 +22,7 @@ <%= javascript_tag nonce: true do %> window.locationManifest = <%= available_locations %> window.useTheme = <%= @theme.present? %> + window.themeRevision = "<%= @theme.revision %>" <% end %> <%= javascript_include_tag '/javascripts/i18n.js', nonce: true %> diff --git a/app/webpush_notifiers/record_action_webpush_notifier.rb b/app/webpush_notifiers/record_action_webpush_notifier.rb index 8a6c0326e4..1aa94df01c 100644 --- a/app/webpush_notifiers/record_action_webpush_notifier.rb +++ b/app/webpush_notifiers/record_action_webpush_notifier.rb @@ -28,7 +28,9 @@ def self.transfer_request(transfer_request_notification) def transition_notify(transition_notification) return if transition_notification.transition.nil? - return unless webpush_notifications_enabled?(transition_notification&.transitioned_to) + return unless webpush_notifications_enabled?( + transition_notification&.transitioned_to, Transition::NOTIFICATION_ACTION + ) WebpushService.send_notifications( transition_notification&.transitioned_to, @@ -38,7 +40,7 @@ def transition_notify(transition_notification) def manager_approval_request(approval_notification) return unless approval_notification.send_notification? - return unless webpush_notifications_enabled?(approval_notification.manager) + return unless webpush_notifications_enabled?(approval_notification.manager, Approval::NOTIFICATION_ACTIONS_REQUEST) WebpushService.send_notifications( approval_notification.manager, @@ -52,7 +54,7 @@ def manager_approval_request(approval_notification) def manager_approval_response(approval_notification) return unless approval_notification.send_notification? - return unless webpush_notifications_enabled?(approval_notification.owner) + return unless webpush_notifications_enabled?(approval_notification.owner, Approval::NOTIFICATION_ACTIONS_RESPONSE) WebpushService.send_notifications( approval_notification.owner, @@ -62,7 +64,9 @@ def manager_approval_response(approval_notification) def transfer_request(transfer_request_notification) return if transfer_request_notification.transition.nil? - return unless webpush_notifications_enabled?(transfer_request_notification&.transitioned_to) + return unless webpush_notifications_enabled?( + transfer_request_notification&.transitioned_to, Transfer::NOTIFICATION_ACTION + ) WebpushService.send_notifications( transfer_request_notification&.transitioned_to, @@ -101,12 +105,12 @@ def message_structure(record_action_notification) private - def webpush_notifications_enabled?(user) - web_push_enabled? && user_web_push_enabled?(user) + def webpush_notifications_enabled?(user, action = nil) + web_push_enabled? && user_web_push_enabled?(user, action) end - def user_web_push_enabled?(user) - return true if user&.receive_webpush? + def user_web_push_enabled?(user, action) + return true if user&.receive_webpush? && (action.nil? || user&.specific_notification?('receive_webpush', action)) Rails.logger.info("Webpush not sent. Webpush notifications disabled for #{user&.user_name || 'nil user'}") diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 5f8220874e..8a479b6365 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -31,9 +31,9 @@ jobs: displayName: 'Make required directories and copy files' - task: NodeTool@0 inputs: - versionSpec: '18.13.0' + versionSpec: '20.14.0' displayName: 'Install node' - - bash: npm ci + - bash: npm config set legacy-peer-deps true && npm ci displayName: 'Install npm packages' - bash: | apt-get update @@ -41,7 +41,7 @@ jobs: displayName: 'Install dependencies' - bash: | . ~/.bash_env - rbenv global 3.2.2 + rbenv global 3.3.5 bundle install --without production --path=${BUNDLE_PATH:-vendor/bundle} displayName: 'Bundle install' env: @@ -57,24 +57,13 @@ jobs: RAILS_ENV: test DEVISE_JWT_SECRET_KEY: $(DEVISE_JWT_SECRET_KEY) DEVISE_SECRET_KEY: $(DEVISE_SECRET_KEY) + SOLR_ENABLED: true - bash: | - npm run test:batch:1 - displayName: 'Run Integration test Batch 1' + npm run test + displayName: 'Run Integration test' - bash: | - npm run test:batch:2 - displayName: 'Run Integration test Batch 2' - - bash: | - npm run test:batch:3 - displayName: 'Run Integration test Batch 3' - - bash: | - npm run test:batch:4 - displayName: 'Run Integration test Batch 4' - - bash: | - npm run test:batch:5 - displayName: 'Run Integration test Batch 5' - - bash: | - npm run test:new -- --maxWorkers=2 - displayName: 'Run Integration test (New)' + npm run test:components -- --maxWorkers=2 + displayName: 'Run Integration test (Components)' - job: Build displayName: 'Build and push' @@ -85,8 +74,6 @@ jobs: - bash: echo "##vso[task.setvariable variable=tag]$(docker/git-to-docker-tag.sh ${BUILD_SOURCEBRANCH} ${BUILD_SOURCEVERSION})" - bash: echo "##vso[task.setvariable variable=dash_el]$([[ ${BUILD_SOURCEBRANCH} == *${LATESTBRANCH} ]] && echo '-l')" - bash: echo "##vso[task.setvariable variable=latest]$([[ ${BUILD_SOURCEBRANCH} == *${LATESTBRANCH} ]] && echo 'latest')" - - bash: echo "##vso[task.setvariable variable=latestpg10]$([[ ${BUILD_SOURCEBRANCH} == *${LATESTBRANCH} ]] && echo 'latest-pg10')" - - bash: echo "##vso[task.setvariable variable=latestpg11]$([[ ${BUILD_SOURCEBRANCH} == *${LATESTBRANCH} ]] && echo 'latest-pg11')" - bash: echo "##vso[task.setvariable variable=latestpg14]$([[ ${BUILD_SOURCEBRANCH} == *${LATESTBRANCH} ]] && echo 'latest-pg14')" - bash: echo "##vso[task.setvariable variable=latestpg15]$([[ ${BUILD_SOURCEBRANCH} == *${LATESTBRANCH} ]] && echo 'latest-pg15')" - task: CmdLine@2 @@ -154,24 +141,6 @@ jobs: tags: | $(tag) $(latest) - - task: Docker@2 - displayName: 'Postgres - Push an image to Dockerhub' - inputs: - containerRegistry: 'dockerhub-primeroims' - repository: 'primeroims/postgres' - command: 'push' - tags: | - $(tag)-pg10 - $(latestpg10) - - task: Docker@2 - displayName: 'Postgres - Push an image to Dockerhub' - inputs: - containerRegistry: 'dockerhub-primeroims' - repository: 'primeroims/postgres' - command: 'push' - tags: | - $(tag)-pg11 - $(latestpg11) - task: Docker@2 displayName: 'Postgres - Push an image to Dockerhub' inputs: diff --git a/bin/check_transifex_interpolations.sh b/bin/check_transifex_interpolations.sh new file mode 100755 index 0000000000..a737cca69b --- /dev/null +++ b/bin/check_transifex_interpolations.sh @@ -0,0 +1,23 @@ +#! /usr/bin/env bash +# Copyright (c) 2014 - 2024 UNICEF. All rights reserved. + +set -e + +cat `find config/locales -type f -iname en.yml` | awk 'BEGIN {FS="%{"} /%{/ { for(i=2; i<=NF; i++) {split($i,a,"}"); print(a[1])}}' | sort -u > en_keys.txt + +cat `find config/locales -type f` | awk 'BEGIN {FS="%{"} /%{/ { for(i=2; i<=NF; i++) {split($i,a,"}"); print(a[1])}}' | sort -u > all_keys.txt + +comm -23 all_keys.txt en_keys.txt > bad_interpolations.txt + +num_bad_interpolations=$(cat bad_interpolations.txt | wc -l) + +rm all_keys.txt en_keys.txt + +if [ "$num_bad_interpolations" -gt 0 ]; then + echo "ERR: There are $num_bad_interpolations bad interpolations in transifex translations files:" + cat bad_interpolations.txt + rm bad_interpolations.txt + exit 1 +fi + +rm bad_interpolations.txt diff --git a/bin/run_server_tests.sh b/bin/run_server_tests.sh index 0f86bb6442..a5c934ba39 100755 --- a/bin/run_server_tests.sh +++ b/bin/run_server_tests.sh @@ -6,6 +6,8 @@ set -ex export BITBUCKET=bitbucket export GITHUB_ACTIONS=github-actions export PIPELINE=${1:-bitbucket} +# TODO: Remove this variable once Solr is migrated +export SOLR_ENABLED=true # Set up test environment setup_test_env() { @@ -33,19 +35,23 @@ setup_dependencies() { # Install Rails pre-requisites apt-get update apt install -y --no-install-recommends libpq-dev libsodium-dev - - if [ $PIPELINE == $BITBUCKET ]; then + + if [ $PIPELINE == $BITBUCKET ]; then bundle install --without production fi } -if [ $PIPELINE == $GITHUB_ACTIONS ]; then +if [ $PIPELINE == $GITHUB_ACTIONS ]; then DEPS=`declare -f setup_dependencies` sudo -E bash -c "$DEPS; setup_dependencies" else setup_dependencies fi +# TODO: Enable this once all bad interpolations are fixed on transifex +# Run check transifex interpolations +# ./bin/check_transifex_interpolations.sh + setup_test_env # Run rubocop diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml index 1afc47855e..763f3ab682 100644 --- a/bitbucket-pipelines.yml +++ b/bitbucket-pipelines.yml @@ -4,7 +4,7 @@ definitions: steps: - step: &server-test name: Server tests - image: ruby:3.2.2-bookworm + image: ruby:3.3.5-bookworm script: - ./bin/install_local_test_solr.sh - ./bin/run_server_tests.sh @@ -14,22 +14,22 @@ definitions: - bundler - step: &client-test name: Client tests - image: node:18.13.0 + image: node:20.14.0 size: 2x script: + - npm config set legacy-peer-deps true - npm ci - - npm run test:batch:1 - - npm run test:batch:2 - - npm run test:batch:3 - - npm run test:batch:4 - - npm run test:batch:5 - - npm run test:new -- --maxWorkers=2 + - npm run test + - npm run test:components -- --maxWorkers=2 - npm run lint:run caches: - node - step: &push-branch + image: atlassian/default-image:4 + clone: + depth: full script: - - git push unicef@vs-ssh.visualstudio.com:v3/unicef/ICTD%20-%20Primero%20X%20DEV/primero $BITBUCKET_BRANCH + - git push https://$azdotoken@unicef.visualstudio.com/ICTD%20-%20Primero%20X%20DEV/_git/primero $BITBUCKET_BRANCH - git push https://$primeroimstoken@github.com/primeroIMS/primero.git $BITBUCKET_BRANCH services: postgres: @@ -52,9 +52,11 @@ pipelines: tags: v*: - step: + image: atlassian/default-image:4 script: - - git push unicef@vs-ssh.visualstudio.com:v3/unicef/ICTD%20-%20Primero%20X%20DEV/primero $BITBUCKET_TAG + - git push https://$azdotoken@unicef.visualstudio.com/ICTD%20-%20Primero%20X%20DEV/_git/primero $BITBUCKET_TAG - git push https://$primeroimstoken@github.com/primeroIMS/primero.git $BITBUCKET_TAG + pull-requests: '**': - parallel: diff --git a/buildspec.yml b/buildspec.yml index b85fffa8fe..0674d0ff9d 100644 --- a/buildspec.yml +++ b/buildspec.yml @@ -20,6 +20,7 @@ env: SECRET_VARS_release_2_8: 'PrimeroCicdSecretrelease-2-8' SECRET_VARS_release_2_9: 'PrimeroCicdSecretrelease-2-9' SECRET_VARS_release_2_10: 'PrimeroCicdSecretrelease-2-10' + SECRET_VARS_release_2_11: 'PrimeroCicdSecretrelease-2-11' phases: pre_build: @@ -41,8 +42,6 @@ phases: - echo ${CONTAINER_REGISTRY}/primeroims/application:${TAG} - docker push ${CONTAINER_REGISTRY}/primeroims/solr:${TAG} - docker push ${CONTAINER_REGISTRY}/primeroims/migration:${TAG} - - docker push ${CONTAINER_REGISTRY}/primeroims/postgres:${TAG}-pg10 - - docker push ${CONTAINER_REGISTRY}/primeroims/postgres:${TAG}-pg11 - docker push ${CONTAINER_REGISTRY}/primeroims/postgres:${TAG}-pg14 - docker push ${CONTAINER_REGISTRY}/primeroims/postgres:${TAG}-pg15 - docker push ${CONTAINER_REGISTRY}/primeroims/nginx:${TAG} diff --git a/config/application.rb b/config/application.rb index f09a23f471..416518abe1 100644 --- a/config/application.rb +++ b/config/application.rb @@ -15,6 +15,10 @@ require 'action_mailer/railtie' require 'action_view/railtie' require 'active_storage/engine' +if ActiveRecord::Type::Boolean.new.cast(ENV.fetch('SOLR_ENABLED', false)) == true + require 'sunspot_rails' + require 'sunspot_solr' +end Bundler.require(*Rails.groups) @@ -32,6 +36,10 @@ class Primero::Application < Rails::Application Rails.autoloaders.main.ignore(overrides) config.to_prepare do Dir.glob("#{overrides}/**/*.rb").each do |override| + if ActiveRecord::Type::Boolean.new.cast(ENV.fetch('SOLR_ENABLED', false)) == false && override.include?('sunspot') + next + end + load override end end diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 680bb49b75..ba3e533463 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -4,4 +4,4 @@ # Specify a serializer for the signed and encrypted cookie jars. # Valid options are :json, :marshal, and :hybrid. -Rails.application.config.action_dispatch.cookies_serializer = :marshal +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 179d872f3b..f03127bc9b 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -17,7 +17,7 @@ # ==> Controller configuration # Configure the parent class to the devise controllers. - # config.parent_controller = 'DeviseController' + config.parent_controller = 'ApplicationApiController' # ==> Mailer Configuration # Configure the e-mail address which will be shown in Devise::Mailer, @@ -93,7 +93,7 @@ # Notice that if you are skipping storage for all authentication paths, you # may want to disable generating routes to Devise's sessions controller by # passing skip: :sessions to `devise_for` in your config/routes.rb - config.skip_session_storage = %i[http_auth params_auth] + config.skip_session_storage = %i[http_auth] # By default, Devise cleans up the CSRF token on authentication to # avoid CSRF token fixation attacks. This means that, when using AJAX @@ -306,19 +306,5 @@ # When set to false, does not sign a user in automatically after their password is # changed. Defaults to true, so a user is signed in automatically after changing a password. - # config.sign_in_after_change_password = true - - # ===> Configuration for :jwt_authenticatable (devise-jwt) - config.jwt do |jwt| - jwt.secret = ENV.fetch('DEVISE_JWT_SECRET_KEY', nil) - jwt.dispatch_requests = [ - ['POST', %r{^/api/v2/tokens$}], - ['POST', %r{^/api/v2/users/password-reset$}] - ] - jwt.revocation_requests = [ - ['DELETE', %r{^/api/v2/tokens$}] - ] - jwt.expiration_time = 1.hour.to_i - end end # rubocop:enable Metrics/BlockLength diff --git a/config/initializers/enable_solr.rb b/config/initializers/enable_solr.rb new file mode 100644 index 0000000000..2c3d289614 --- /dev/null +++ b/config/initializers/enable_solr.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2024 UNICEF. All rights reserved. + +Rails.application.config.before_initialize do + Rails.application.configure do + config.solr_enabled = ActiveRecord::Type::Boolean.new.cast(ENV.fetch('SOLR_ENABLED', nil)) || false + end +end diff --git a/config/initializers/locale.rb b/config/initializers/locale.rb index 1324f83d3f..e1dbb2274f 100644 --- a/config/initializers/locale.rb +++ b/config/initializers/locale.rb @@ -13,9 +13,9 @@ class Primero::Application LOCALE_ARABIC = :ar LOCALES = %i[ en ar ar-IQ ar-JO ar-LB ar-SD bn es es-GT fa-AF fr id km ku ku-IQ my ps-AF pt pt-BR so sw-KE sw-TZ th ne ro ru uk pl - sk hu es-ES om am-ET tr cmn tet + sk hu es-ES om am-ET tr cmn tet aeb ar-SY ].freeze - RTL_LOCALES = %i[ar ar-IQ ar-JO ar-LB ar-SD fa-AF ku ku-IQ ps-AF].freeze + RTL_LOCALES = %i[ar ar-IQ ar-JO ar-LB ar-SD fa-AF ku ku-IQ ps-AF aeb ar-SY].freeze end def locale_settings diff --git a/config/initializers/locales_fallbacks.rb b/config/initializers/locales_fallbacks.rb index baf8c4430f..08752f6a08 100644 --- a/config/initializers/locales_fallbacks.rb +++ b/config/initializers/locales_fallbacks.rb @@ -19,6 +19,8 @@ 'ar-LB': AR_FALLBACK, 'ar-JO': AR_FALLBACK, 'ar-SD': AR_FALLBACK, + 'ar-SY': AR_FALLBACK, + aeb: AR_FALLBACK, bn: EN_FALLBACK, es: EN_FALLBACK, 'es-ES': ES_FALLBACK, diff --git a/config/initializers/middleware.rb b/config/initializers/middleware.rb index 17c028436f..abb13f0380 100644 --- a/config/initializers/middleware.rb +++ b/config/initializers/middleware.rb @@ -2,13 +2,8 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -require "#{Rails.root}/app/middleware/jwt_token_setter.rb" require "#{Rails.root}/app/middleware/www_authenticate.rb" require "#{Rails.root}/app/middleware/log_silencer.rb" -Rails.application.config.middleware.insert_before(Warden::JWTAuth::Middleware, JwtTokenSetter) Rails.application.config.middleware.insert_before(Warden::Manager, WwwAuthenticate) -if Rails.application.config.x.idp.use_identity_provider - Rails.application.config.middleware.delete(Warden::JWTAuth::Middleware) -end Rails.application.config.middleware.insert_before(Rails::Rack::Logger, LogSilencer) diff --git a/config/initializers/periodic_job.rb b/config/initializers/periodic_job.rb index 4515a8cc37..a83401a271 100644 --- a/config/initializers/periodic_job.rb +++ b/config/initializers/periodic_job.rb @@ -9,7 +9,10 @@ Rails.logger.info('Setting up PeriodicJobs') -%w[ArchiveBulkExports OptimizeSolr RecalculateAge].each do |job_name| +jobs = %w[ArchiveBulkExports RecalculateAge] +jobs << OptimizeSolr.to_s if Rails.configuration.solr_enabled + +jobs.each do |job_name| next if Delayed::Job.where('handler LIKE :job_class', job_class: "%job_class: #{job_name}%").exists? Rails.logger.info("#{job_name} executed at #{DateTime.now}") diff --git a/config/initializers/primero_configure.rb b/config/initializers/primero_configure.rb index ae8e32e9bb..fd284c7f1b 100644 --- a/config/initializers/primero_configure.rb +++ b/config/initializers/primero_configure.rb @@ -25,6 +25,8 @@ config.use_theme = ActiveRecord::Type::Boolean.new.cast(ENV.fetch('PRIMERO_USE_THEME', nil)) || false + config.use_csrf_protection = ActiveRecord::Type::Boolean.new.cast(ENV.fetch('PRIMERO_USE_CSRF_PROTECTION', true)) + config.silence_logging = [ 'GET /health', 'GET /health/database', 'GET /health/solr', 'GET /health/server' ] diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index bf0b2fa9a1..dc3c0821ff 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -2,4 +2,4 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -Rails.application.config.session_store :disabled +Rails.application.config.session_store :cookie_store, expire_after: 1.hour diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index 8f7e5c506f..85237933e6 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -7,9 +7,10 @@ # This file contains settings for ActionController::ParamsWrapper which # is enabled by default. -# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +# Disable parameter wrapping. You can disable this by setting :format to an empty array. +# To enable for json, set format: [:json] ActiveSupport.on_load(:action_controller) do - wrap_parameters format: [:json] + wrap_parameters format: [] end # To enable root element in JSON for ActiveRecord objects. diff --git a/config/locales/aeb.yml b/config/locales/aeb.yml new file mode 100644 index 0000000000..a3bca1c6c1 --- /dev/null +++ b/config/locales/aeb.yml @@ -0,0 +1,3872 @@ +aeb: + 'true': 'نعم' + 'false': 'لا' + accepted: موافقة + cancel: إلغاء + connection_lost: حاليا غير متصل بشبكة الانترنت + field_mode_offline: حاليا في مجال البيانات + connected: متصل + no_connection: غير متصل + clear: مسح + sandbox_ui: تجريبي + description: الوصف + form: استمارة + minimum_reportable_fields: "الحد الأدنى من مجال البيانات القابلة للإبلاغ %{record_type}" + name: الاسم + offline: غير متصل بشبكةالانترنت + field_mode: "وضع مجال البيانات: %{mode}" + field_mode_on: "فعال" + field_mode_off: "غير فعال" + unavailable_offline: غير متاح غير متصل بشبكة الانترنت + online: متصل بشبكة الانترنت + yes_label: 'نعم' + or_label: أو، + select_provider: اختر المزود + select_language: اختر اللغة + log_in_primero_idp: 'سجل الدخول باسم المستخدم%{idp_name} ' + offline_submitted_changes: أنت حاليا غير متصل بشبكة الانترنت. سيتم تسجيل التغييرات الخاصة بك عند الاتصال بالإنترنت مرة أخرى. + updated: تم التحديث + go: الانتقال + select_idp_error: الرجاء تحديد المزود + sync: + success: "تمت مزامنة سجلات%{records} بنجاح." + error: + create: قد فشل انشاء %{record_type} . يرجى الاتصال بالدعم. + update: قد فشل التحديث الى %{record_type}%{short_id} ، يرجى الاتصال بالدعم. + actions: + approvals: الموافقات + button: إجراءات + close: اغلاق + description: + invalid: سجل غير صحيح + valid: سجل صحيح + disable: إلغاء + enable: تفعيل + incident_details_from_case: إضافة حادثة + incident_from_case: خلق حادثة + next: التالي + notes: اضافة ملاحظات + previous: السابق + reopen: إعادة فتح + request_approval: طلب موافقة + revoke: الغاء + save: حفظ + services_from_case_creation_success: تم إنشاء سجل تقديم الخدمة بنجاح. + services_section_from_case: إضافة تقديم خدمة + mark_for_offline: وضع علامة على عدم الاتصال بالانترنت + agencies: + label: المؤسسة + translations: + manage: إدارة الترجمات + agency: + agency_logos: شعارات المؤسسة + code: رمز المؤسسة + description: الوصف + disabled: معطّل + exclude_agency_from_lookups: استبعد هذه المؤسسة من عمليات البحث وعوامل التصفية + exclude_agency_from_lookups_help: تحقق من هذه المؤسسة ان ليس لديها مستخدمون (على سبيل المثال ، تمت إضافة المؤسسة لكي يتم تطبيق الشعار على الصادرات + label: المؤسسة + logo_enabled: عرض شعار هذه المؤسسة في Primero؟ + logo_enabled_help: عرض شعار هذه المؤسسة في Primero؟ + logo_icon: أيقونة الشعار + logo_icon_help: سيظهر هذا على الشاشات صغيرة الحجم والأجهزة اللوحية والهواتف. يجب أن يكون هذا على شكل مربع. + logo_large: شعار كبير الحجم + logo_large_help: سيظهر هذا على الشاشات كبيرة الحجم و في صيغة PDF. يجب أن يكون هذا على شكل مستطيل و يجب ان يكون الطول اكبر من الارتفاع + messages: + created: تم انشاء المؤسسة بنجاح + updated: تم تحديث المؤسسة بنجاح + name: اسم المؤسسة + pdf_logo_option: جعل الشعار متاح في صيغة PDF ؟ + pdf_logo_option_help: 'ملاحظة: شعارات المؤسسة الخاصة بالمستخدم متاحة لهم بشكل افتراضي ، لذلك يمكنك تحديد هذا فقط إذا كنت تريد أن يكون هذا الشعار متاحًا لجميع المستخدمين.' + services: خدمات المؤسسة + terms_of_use: شروط الاستخدام + terms_of_use_help: يسمح فقط بملفات PDF + terms_of_use_download_button: تحميل PDF + terms_of_use_enabled: عرض شروط الاستخدام؟ + approvals: + no_requests: لا توجد طلبات موافقة لهذه الحالة + approved_by: تمت الموافقة عليه من قبل + case_plan_type_label: 'نوع مخطّط التدخّل:' + manager_comments_label: ملاحظات المدير + rejected_by: تم رفضه من قبل + requested_by: تم طلبه من قبل + requested_for_label: الموافقة مطلوبة على + requested_for_title: طلب موافقة + response_for_label: الموافقة على + response_for_title: الموافقة + action_plan: خطة العمل + gbv_closure: اغلاق العنف القائم على النوع الإجتماعي + status: + approved: تمت الموافقة + pending: قيد الانتظار + rejected: مرفوض + requested: مطلوب + audit_log: + action: إجراء + description: الوصف + record_owner: الشخص المكلَّف بالسجل + timestamp: الوقت + user_name: تم التنفيذ من قبل + bulk_export: + file_name: ملف + record_type: نوع + retry: هذا التصدير غير صحيح. رجاء حاول إعادة عملية النقل الخاصة بك. + started_on: 'بدء ' + status: 'وضع الحالة ' + form_export: + label: تصدير استمارة الإعدادات + include_hidden: تضمين النماذج والمجالات المخفية؟ + file_name: قم بإنشاء اسم الملف الخاص بك (اختياري) + success_message: تم إنشاء الملف المنقول بنجاح + buttons: + accept: قبول + add: إضافة + add_another_option: إضافة خيار آخر + add_note: إضافة ملاحظات + apply: تطبيق + approvals: الموافقات + approve_action_plan: الموافقة على خطة عمل + approve_bia: الموافقة على المصلحة الفضلى + approve_case_plan: 'المواقفة على مخطّط التدخل ' + approve_closure: الموافقة على الإغلاق + approve_gbv_closure: الموافقة على اغلاق العنف القائم على نوع الجنس + back: السابق + bundle_export: حزمة الإعدادات + bundle_import: حزمة الإعدادات + cancel: إلغاء + change_password: تغيير كلمة المرور + check_status: تأكد من الوضع + clear_default: مسح الافتراضي + clear_selection: مسح الاختيار + clear: مسح + close: اغلاق + continue: استمر + create_case: إنشاء حالة + create_incident: 'إنشاء حادثة ' + create_new_record: إنشاء %{model} جديد + delete: حذف + disable: إيقاف + disable_photo_wall: تعطيل عرض الصور + done: تم + download: تحميل + edit: تعديل + edit_subform: تعديل الاستمارة الفرعية + enable: تفعيل + enable_photo_wall: تفعيل عرض الصور + export: تصدير ملف + filter: تطبيق عامل التصفية + filter_clear: مسح عوامل التصفية + filter_label: 'عامل التصفية:' + filter_restore: الاسترجاع إلى إعدادات النظام + find_tracing_match: إيجاد التطابق لحالة التتبع + flag_model: وضع علامة %{model} + flag_records: وضع علامة + flags: العلامات + guidance: توجيه + guiding_questions: اسئلة توجيهية + import: إحضار + login: تسجيل الدخول + logout: تسجيل الخروج + link: رابط + mark_for_mobile: وضع علامة للهاتف المحمول + new: جديد + ok: موافق + print: 'طباعة ' + reassign: تعيين + referral: 'إحالة ' + referral_again: إحالة مرة اخرى + reject: رفض + remove_referrals: إلغاء الإحالات + reorder: اعادة ترتيب + request_approval: طلب الموافقة + request_transfer: طلب نقل + reunite: إعادة لمّ الشمل + save: حفظ + save_and_add_service_provision: حفظ وإضافة تقديم خدمة + save_and_return: حفظ و رجوع + save_continue: حفظ و استمرار + save_changes: حفظ التغيرات + select: اختيار + send: ارسال + sort_by_case: حالات + sort_by_tr: تتبع الطلبات + sync: مزامنة + submit: إرسال + transfer: نقل + unflag_model: إزالة العلامة %{model} + unflag_model_history: وضع علامة للتاريخ%{model} + unmark_for_mobile: إزالة علامة للهاتف المحمول + update: تحديث + view: عرض + view_flags_history: عرض التاريخ + return_to_case: العودة إلى الحالة + enable_webpush: إشعارات الجهاز + dialog_yes: "نعم" + resync_records: + id: الهويّة + record_type: نوع السجل + action: إجراء + date: التاريخ + last_attempt: اخر محاولة + create: إنشاء + update: تحديث + resync: إرسال + case: + label: حالة + create_new_case: انشاء حالة جديدة + create_case: إنشاء حالة + create: إنشاء + add_new: أضف جديد + back_to_family_details: العودة إلى تفاصيل العائلة + back_to_case: العودة إلى الحالة + back_to_results: العودة إلى النتائج + back_to_search: العودة الى البحث + search_by: البحث حسب + search_for: البحث عن %{record_type} + results: النتائج + details: تفاصيل + select: اختيار + deselect: ازالة الاختيار + enter_id_number: إدخال رقم الهوية للبحث عن سجلّ موجود + id_search_no_results: لا يوجد تطابق في النظام مع "%{search_query}". الرجاء إنشاء سجل جديد + messages: + disabled: تم تعطيل الحالة + update_success: 'تم تحديث الحالة %{record_id} بنجاح.' + update_success_queue: 'تم تحديث الحالة %{record_id} بنجاح في الخلفية' + creation_success: 'تم إنشاء سجل الحالة بنجاح.' + creation_success_queue: 'تمّ إنشاء سجل الحالة بنجاح في الخلفية' + already_matched: لقد تمّت مطابقة هذا المستفسر مع حالتك سابقًا. + already_matched_not_current_case: توجد حالة في النظام مطابقة لهذا المستفسر + not_found_case: لا يوجد حالة مطابقة, %{search_value} يرجى إنشاء حالة جديدة + introductory_sentence: يرجى تحديد رضا الفرد على تلقي خدمات إدارة الحالة وتخزين بياناته في Primero. + consent_agreements_required: الرجاء تحديد خيار واحد على الأقل من اتفاقيات الرضا. + legitimate_basis_required: الرجاء تحديد خيار واحد على الأقل من التصنيفات الأساسية القانونية. + confirm_create_case: هل تريد انشاء حالة لهذا الفرد؟ + case_referral_pending: إحالة الحالة في انتظار المراجعة. + case_transfer_pending: نقل الحالة في انتظار المراجعة. + case_no_approval_request: لا توجد طلبات موافقة لهذه الحالة. + bulk_assign_limit: لا يمكنك تعيين أكثر من 100 حالة في وقت واحد. + bulk_assign_limit_try_again: لا يمكنك تعيين أكثر من 100 حالة في وقت واحد. يرجى تحديد 100 حالة أو أقل ثم حاول مرة أخرى + referral_rejected: تم رفض الإحالة. + transfer_request_made: تم تقديم طلب نقل لهذه الحالة. + save: حفظ الحالة + save_text: قبل المتابعة يرجى حفظ التغييرات التي أجريت على الحالة + skip_and_create: تخطي وإنشاء حالة جديدة + search_existing: بحث في الحالات الموجودة + search_helper_text: لماذا؟ لتفادي انشاء حالات مكررة + consent_agreements: حدد جميع اتفاقيات الرضا التي تنطبق + legitimate_basis: حدد كل التصنيفات الأساسية القانونية التي تنطبق + family_linked_subform_delete_disabled: يرتبط إدخال الاستمارة الفرعية هذه بسجل العائلة. يرجى إما إزالة عضو العائلة هذا من سجل العائلة، أو إلغاء ربط حالة فرد العائلة من سجل العائلة. + workflow: + assessment: التقييم + case_plan: خطة الحالة + closed: مغلقة + created_on: تم تسجيل في + in_progress: جاري + new: 'جديدة ' + on_label: 'في' + reopened: تم إعادة فتحها + service_implemented: تم تطبيق الخدمة + services_implemented: تم تطبيق الخدمة + linkedincidents: + label: الحوادث المرتبطة + activity_log: + label: سجل النشاطات + accepted_transfer: '%{to} قبول نقل %{record_type} %{record_id} من %{from}' + rejected_transfer: '%{to} رفض نقل %{record_type} %{record_id} من %{from}' + cases: + action_plan: خطة التدخل + access_denied: "ليس لديك حق الوصول إلى هذه الحالة." + age: العمر + age_estimated: ما هو العمر المقدّر؟ + agency: المؤسسة + apply_filter: تطبيق + approval_comments: ملاحظات + approval_radio: أودّ أن + approval_radio_accept: أوافق + approval_radio_reject: لا أوافق + approval_select: نموذج لـ + approved_success_action_plan: '%{approval_label} - تمتّ الموافقة عليه' + approved_success_assessment: '%{approval_label} - تمتّ الموافقة عليه' + approved_success_bia: '%{approval_label} - تمتّ الموافقة عليه' + approved_success_case_plan: '%{approval_label} - تمتّ الموافقة عليه' + approved_success_closure: '%{approval_label} - تمتّ الموافقة عليه' + approved_success_gbv_closure: '%{approval_label} - تمتّ الموافقة عليه' + assessment: التقييم + case_opening_date: تاريخ فتح الحالة + case_plan: مخطّط التدخّل + case_worker_code: رمز المتعهد بالحالة + clear_filter: مسح + close_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحالة مغلقًا + close_dialog_title: اغلاق الحالة + close_success: تمّ إغلاق الحالة بنجاح + closure: اغلاق + complete: متاح بدون الاتصال بالانترنت + date_of_birth: 'تاريخ الميلاد ' + disable_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحالة معطّلًا + disable_dialog_title: تعطيل الحالة + disable_success: تمّ تعطيل الحالة بنجاح + enable_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحالة مفعّلًا + enable_dialog_title: تفعيل الحالة + enable_success: تمّ تفعيل الحالة بنجاح + export: تصدير ملف + mark_for_offline: + title: وضع علامة على عدم الاتصال بالانترنت + text: هل أنت متأكد من أنك تريد وضع علامة على سجلات العائلة هذه لاستخدامها عندما تكون غير متصل بالإنترنت؟ + success: تم وضع علامة على الحالات بنجاح للاستخدام دون اتصال بالانترنت + filter_by: + 3month_inactivity: لمدة أكثر من 3 أشهر + action_plan: خطة التدخل + age_0_5: 0 - 5 + age_12_17: 12 - 17 + age_18_more: 18+ + age_6_11: 6 - 11 + age_range: الفئة العمرية + agency: المؤسسة + approval_status: وضع الموافقات + approvals: + approved: تم الموافقة عليه + pending: قيد الانتظار + rejected: رُفض + bia: المصلحة الفضلى + by_date: حسب التاريخ + case_open_date: تاريخ فتح الحالة + case_plan: خطة الحالة + closed: مغلقة + closure: اغلاق + current_location: الموقع الحالي + date: تاريخ + displacement_status: وضع النزوح + district: 'المنطقة:' + duplicate: نسخة + enabled_disabled: مُفعل/غير مُفعل + female: أنثى + flag: مُميز بعلامة + flag_label: هل كان مُميزًا بعلامة؟ + gbv_closure: اغلاق العنف القائم على النوع الإجتماعي + high: مرتفع + low: منخفض + male: ذكر + medium: متوسط + mobile: هاتف محمول + mobile_label: هل تم وضع علامة للمحمول؟ + my_cases: ملفّاتي + no_action: لا يوجد إجراء + no_activity: لا توجد أنشطة + open: مفتوح + other: أخرى + photo: صورة + photo_label: هل توجد صورة؟ + protection_concerns: مخاوف تتعلّق بالحماية + protection_status: وضع الحماية + record_state: حالة السجل + referred_cases: الحالات التي تم إحالتها لي + registration_date: تاريخ التسجيل + risk_level: 'درجة الخطورة:' + sex: الجنس + social_worker: مجال/حالة/أخصائي اجتماعي + status: وضع + transferred: تم النقل + type_of_risk: نوع المخاطر + urgent_protection_concern: مخاوف عاجلة بشأن الحماية + user_group: مجموعة مستخدمين + workflow: الحالات حسب سير العمل + include_disabled: اضف الحالات التي تم الغائها + flag_summary: ملخص العلامات + full_name: الاسم الكامل + gbv_closure: اغلاق العنف القائم على النوع الإجتماعي + hide_name: إخفاء الاسم + hide_name_error: حدث خطأ عند حفظ التغييرات. الرجاء المحاولة مرة أخرى. + id: المُعرف# + label: الحالات + my_filters: عوامل التصفية + name: الإسم + notes_dialog_title: اضافة ملاحظات + notes_form_notes: ملاحظات + notes_form_subject: الموضوع + ok: تمّ + order_by: + label: ترتيب حسب + most_recently: الأحدث + name: الاسم + owned_by: المكلف بالسجلّ + owned_by_agency: مؤسسة المكلف بالسجل + photo: صورة فوتوغرافية + photos: صورة + quick_view: + tracing_message: 'ملاحظة: هناك تطابق في النظام مع مستفسر يبحث عن هذا الطفل. اتصل بالأخصائي الاجتماعي لهذا السجل لاتخاذ مزيد من الإجراءات إذا رغب الطفل في ذلك.' + reassign: + multiple_successfully: Primero يقوم بإعادة تحديث % {select _ records} الحالة (s). قد يستغرق تحديث كل هذه الحالات عدة دقائق. + referral_done: النقر على "تم" يعني أنك قد أكملت العمل المرتبط بهذه الحالة. بمجرد النقر فوق "تم" لن تتمكن من الوصول إلى هذا السجل مرة اخرى + referral_done_success: تمّت الإحالة + referral_accepted_header: قبول الإحالة + referral_accepted: هل أنت متأكّد؟ ستكون الآن مسؤولاً عن إكمال العمل المرتبط بهذه الإحالة. + referral_accepted_success: تمّ قبول الإحالة + referral_rejected: يشير النقر على "رفض" إلى عدم استعدادك لتحمّل مسؤولية هذه الإحالة في الوقت الحالي. يرجى إدخال سبب رفضك لهذه الإحالة ؛ بمجرد النقر على "رفض" لن تتمكن من الاطلاع على سجل هذه الحالة. + referral_rejected_success: تمّ رفض الإحالة + register_new_case: حالة جديدة + registration_date: تاريخ التسجيل + rejected_success_action_plan: '%{approval_label}- غير موافق عليها' + rejected_success_assessment: '%{approval_label}- غير موافق عليها' + rejected_success_bia: '%{approval_label}- غير موافق عليها' + rejected_success_case_plan: '%{approval_label}- غير موافق عليها' + rejected_success_closure: '%{approval_label}- غير موافق عليها' + rejected_success_gbv_closure: '%{approval_label}- غير موافق عليها' + reopen_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحالة مفتوحًا + reopen_dialog_title: إعادة فتح الحالة + reopen_success: تمّت إعادة فتح الحالة بنجاح + request_approval_failure: حدث خطأ، يرجى الاتصال بالدعم. + request_approval_select: طلب الموافقة على + request_approval_success_action_plan: طلب الموافقة على نموذج %{approval_label} + request_approval_success_assessment: طلب الموافقة على نموذج %{approval_label} + request_approval_success_case_plan: طلب الموافقة على نموذج %{approval_label} + request_approval_success_closure: طلب الموافقة على نموذج %{approval_label} + request_approval_success_gbv_closure: طلب الموافقة على نموذج %{approval_label} + request_approval_type_of_case_plan: نوع الموافقة على خطة الحالة + request_approve_action_plan: هل توافق على خطة الحالة؟ + request_approve_bia: 'هل توافق على التقييم؟ ' + request_approve_case_plan: هل توافق على خطة الحالة؟ + request_approve_closure: هل توافق على الإغلاق؟ + request_approve_gbv_closure: هل توافق على إغلاق العنف القائم على النوع الإجتماعي؟ + revoke_failure: حدث خطأ خلال إلغاء %{transition_type}، يرجى الاتصال بالدعم. + revoke_message: بالنقر على "إلغاء" ستقوم بإزالة إمكانية وصول المستلِم %{transition_type} إلى الحالة. + revoke_success_message: الحالة %{case_id}%{transition_type}%{recipient_username} التي يجب إلغاؤها. + save_filter: تسجيل + selected_all_records: اختيار كلّ %{total_records}الحالات التي تطابق هذا الاستعلام. + selected_records: '%{select_records} حالة (حالات) مختارة' + selected_records_assign: ' %{select_records} حالة (حالات) مختارة' + sex: الجنس + show_case: 'معرّف الحالة: %{short_id}' + social_worker: أخصائي اجتماعي + status: الوضع + summary: + label: ملخص + find_match: إيجاد تطابق + matched_trace: 'رقم التطابق %{trace_id}' + cannot_find_matches: لم يتمّ العثور على تطابق. لم يتمّ الحصول على رضا الحالة للكشف عن المعلومات لأغراض التتبع. + matched: تمّت المطابقة. + fields: + consent_for_tracing: + label: تمّ الحصول على الرضا للكشف عن المعلومات لأغراض التتبع. + help_text: إذا كانت هذه الخانة "لا"، لن يظهر سجل حالة الطفل في التطابقات مع طلبات المستفسِر للتتبّع. + wishes_child_family_tracing: + label: هل يريد الطفل تتبع أفراد الأسرة؟ + wishes_reunification: + label: هل يريد الطفل لَمْ شَمْل الأسرة؟ + options: + yes_as_soon_as_possible: نعم، بأسرع وقت ممكن + yes_but_later: نعم ولكن لاحقًا + not_sure: غير مؤكّد + 'no': 'لا' + data_confidentiality_link: + label: راجع سريّة البيانات + child_wishes_link: + label: راجع رغبات الطفل + survivor_code: رمز الضحية + transfer_accepted: بالنقر على "موافقة" فإنك توافق على تحمّل مسؤولية هذه الحالة؛ وبمجرد النقر على "موافقة" ستصبح أنت المكلف بالسجل في النظام. + transfer_managed_user_accepted: إذا قمت بالنقر فوق "موافقة" ،%{transitioned_to} ستصبح مسؤولاً عن هذه الحالة ؛ بمجرد النقر فوق "موافقة" ، %{transitioned_to} ستصبح المكلف بالسجل في النظام. + transfer_managed_user_rejected: 'بالنقر فوق "رفض" ، فإنك تشير إلى أنك %{transitioned_to} غير مستعد لقبول المسؤولية عن هذه الحالة في الوقت الحالي. الرجاء إدخال سبب رفضك لهذه الحالة ؛ بمجرد النقر فوق "رفض" %{transitioned_to} لن تتمكن من الوصول إلى سجل هذه الحالة ' + transfer_accepted_rejected: تمّ رفض عملية تحويل الحالة %{record_id} + transfer_accepted_success: تمّ قبول تحويل الحالة بنجاح. + transfer_reject_reason_label: سبب الرفض + transfer_rejected: يشير النقر على "رفض" إلى عدم استعدادك لتحمّل مسؤولية هذه الحالة في الوقت الحالي. يرجى إدخال سبب رفضك لهذه الحالة ؛ بمجرد النقر على "رفض" لن تتمكن من الاطلاع على سجل هذه الحالة. + view_name: عرض الاسم + sort_by: ترتيب حسب + change_logs: + filters: + form: استمارة + field: مجال + add_subform: 'تمّت إضافة%{subform_name} رقم مُدخَل الاستمارة الفرعية %{short_id}' + changes_subform: 'التغييرات على الاستمارة الفرعية"%{subform_name}"' + create: السجلّ الذي تمّ إنشاؤه + deleted_subform: 'تمّت إزالة %{subform_name} رقم مُدخل الاستمارة الفرعية "%{short_id}"' + label: تغيير السجل + see_details: راجع التفاصيل + change: 'من "%{from_value}" إلى "%{to_value}"' + updated_subform: 'تمّ تحديث %{subform_name} رقم مُدخل الاستمارة الفرعية "%{short_id}"' + update_subform: 'تمّ تحديث الاستمارة الفرعية "%{subform_name}" ' + from: من + to: إلى + children: + selectable_date_options: + assessment_requested_on: تاريخ التقييم + closure_approved_date: 'تاريخ إغلاق ملف الحالة' + created_at: 'تاريخ فتح الحالة ' + date_case_plan_initiated: تاريخ خطة تدخل الحالة + date_of_creation: تاريخ الإنشاء + registration_date: تارخ التسجيل + configurations: + apply_label: هل أنت متأكد؟ إذا قمت بتطبيق الإعدادات الموجودة في هذا الإعدادات، ستُطبّق على النظام. ستفقدكلّ إعداداتك الحالية ولن تتمكن من استعادتها ما لم تكن قد حفظتها سابقًا في إعداد آخر. + apply_label_bold: لن يكون بريميرو Primero متاحًا للمستخدمين لبضع دقائق أثناء تحميل التغييرات. + version_mismatch_tooltip: لا يمكنك تطبيق هذا الإعدادات ، لأنه تم إنشاؤه باستخدام إصدار أعلى من Primero من الإصدار الذي يعمل به موقعك. يرجى الانتظار لتطبيق هذا الإعدادات حتى تقوم بتشغيل أحدث إصدار من Primero. + send_header: أرسل إلى الإنتاج + send_text: هل أنت متأكد؟ إذا نقرت على أرسل، سوف ترسل هذا الإعدادات إلى موقع الإنتاج الخاص بك. لن يتم تطبيق هذا الإعدادات على الإنتاج حتى يقوم مسؤول في هذا الموقع بتطبيقه يدويًا. + attributes: + created_by: تمّ الإنشاء من قِبَل + date_created: تاريخ الإنشاء + description: وصف + last_applied_by: تمّ التطبيق الأخير من قِبَل + last_applied_on: تمّ التطبيق الأخير في + name: الإسم + version: إصدار الإعدادات + primero_version: نسخة "Primero" + delete_label: هل انت متأكد من أنك تريد أن تفعل هذا؟ يمثل هذا الأمر جميع الإعدادات منذ إنشاء هذا الإعدادات. لن تتمكن من العودة واستعادة هذه الإعدادات بمجرد حذف هذا الإعدادات. + explanation: 'سيؤدي النقر على "حفظ" إلى إنشاء سجل بجميع إعدادات الإعدادات الحالية (على سبيل المثال: الأدوار والهيئات والنماذج) في هذه المرحلة الزمنية. بعد الحفظ، يمكنك تكرار هذه التغييرات في فقرة أخرى من بريميرو Primero. إذا أجريت، في المستقبل، تغييرات على الإعدادات وتريد التراجع عنها، يمكنك تطبيق سجل الإعدادات هذا لاسترجاع جميع تغييرات الإعدادات التي أجريتها في هذا الوقت.' + label: إعدادات + label_new: إعداد جديد + messages: + applied: تمّ تطبيق الإعدادات بنجاح. + created: تمّ إنشاء الإعدادات بنجاح. + deleted: تمّ حذف الإعدادات بنجاح. + updated: تمّ تحديث الإعدادات بنجاح. + sent: إرسال الإعدادات إلى الإنتاج. يرجى التحقق من موقع الإنتاج لمعرفة ما إذا كان الإعدادات الخاص بك قد وصل. + not_allowed: غير مسموح + unavailable_server: السرفر غير متاح مؤقتًا. + contact: + field: + email: البريد الإلكتروني + location: الموقع + name: الاسم + organization: المنظمة + other_information: معلومات أخرى + phone: الهاتف + position: الوظيفة + primero_version: نسخة بريميرو Primero + support_forum: منتدى الدعم + system_version: نسخة النظام + info_label: معلومات الاتصال + updated: تم تحديث معلومات الاتصال بنجاح. + code_of_conduct: + field: + title: لقب + content: المحتوى + created_on: تم إنشاؤها على + created_by: انشأ من قبل + info_label: مدونة قواعد السلوك + updated: تم تحديث مدونة قواعد السلوك بنجاح. + dashboard: + activity: النشاط + admin_only: اضغط على %{links} لعمل تغييرات على التطبيق. + all_cases: جميع الحالات + all_services_implemented: تم تقديم جميع الخدمات + and: 'و' + approval_action_plan_approved: تم الموافقة عليه + approval_action_plan_pending: قيد الانتظار + approval_action_plan_pending_group: خطة التدخل + approval_action_plan_rejected: رُفض + approval_assessment_approved: تم الموافقة عليه + approval_assessment_pending: قيد الانتظار + approval_assessment_pending_group: التقييم + approval_assessment_rejected: مرفوض + approval_case_plan_approved: تم الموافقة عليه + approval_case_plan_pending: قيد الانتظار + approval_case_plan_pending_group: خطة الحالة + approval_case_plan_rejected: مرفوض + approval_closure_approved: تم الموافقة عليه + approval_closure_pending: قيد الانتظار + approval_closure_pending_group: الإغلاق + approval_closure_rejected: مرفوض + approval_gbv_closure_approved: تم الموافقة عليه + approval_gbv_closure_pending: قيد الانتظار + approval_gbv_closure_pending_group: اغلاق العنف القائم على النوع الإجتماعي + approval_gbv_closure_rejected: مرفوض + approvals: الموافقات + approvals_action_plan: خطة العمل + approvals_assessment: التقييم + approvals_case_plan: خطة الحالة + approvals_closure: الإغلاق + approvals_gbv_closure: اغلاق العنف القائم على النوع الإجتماعي + approved: تم الموافقة عليه + assessment: التقييم + awaiting_acceptance: في انتظار الموافقة + cases_by_social_worker_total: مجموع + cases_by_social_worker_new_or_updated: جديد ومُحدَّث + case_id: 'مُعرَف الحالة في النظام' + case_management_service: خدمة إدارة الحالة + case_overview: حالاتي + case_plan: خطة الحالة + case_risk: تصنيف الحالات بحسب مستوى التقييم + case_stat_by_approval_type: الموافقات + case_stat_by_assessment_level: تصنيف الحالات بحسب مستوى التقييم + case_stat_referrals: الإحالات + case_stats: الحالات + case_worker: أخصائي اجتماعي + cases_by_social_worker: الحالات حسب الاخصائي الاجتماعي + cases_by_task_overdue: مهام لم يتم تنفيذها + cases_by_workflow: الحالات حسب سير العمل + cases_this_week: الحالات هذا الأسبوع + cases_to_assign: الحالات التي بانتظار التعيين + closed: مغلقة + closed_last_week: أُغلقت (الأسبوع الماضي) + closed_this_week: أُغلقت (هذا الاسبوع) + comprehensive_need_intervention: استجابة شاملة + count_new_bia_approvals: + zero: '%{stat}الجدي%{stat_type}الموافقات' + one: '%{stat}الجدي%{stat_type}الموافقات' + two: '%{stat}الجدي%{stat_type}الموافقات' + few: '%{stat}الجدي%{stat_type}الموافقات' + many: '%{stat}الجدي%{stat_type}الموافقات' + other: '%{stat}الجديدة%{stat_type}الموافقات' + count_new_case_plan_approvals: + zero: '%{stat} موافقات %{stat_type} جديدة' + one: '%{stat}موافقة %{stat_type}جديدة' + two: '%{stat}موافقات %{stat_type}جديدة' + few: '%{stat}موافقات %{stat_type}جديدة' + many: '%{stat}موافقات %{stat_type}جديدة' + other: '%{stat}موافقات %{stat_type} جديدة' + count_new_closure_approvals: + zero: '%{stat}موافقة%{stat_type}جديدة' + one: '%{stat}موافقة%{stat_type}جديدة' + two: '%{stat}موافقتان%{stat_type}جديدتان' + few: '%{stat}موافقات%{stat_type}جديدة' + many: '%{stat}موافقات %{stat_type}جديدة' + other: '%{stat}موافقات %{stat_type} جديدة' + count_pending_approval_total: + zero: لديك %{stat} موافقة %{stat_type} قيد الانتظار + one: لديك %{stat} موافقة %{stat_type} قيد الانتظار + two: لديك %{stat} موافقتان %{stat_type} قيد الانتظار + few: لديك %{stat}موافقات %{stat_type} قيد الانتظار + many: لديك %{stat} موافقات %{stat_type} قيد الانتظار + other: لديك %{stat} موافقات %{stat_type} قيد الانتظار + count_pending_transfers: + zero: لديك %{stat} طلب نقل معلق + one: لديك %{stat} طلب نقل معلق + two: لديك %{stat} طلبين نقل معلقين + few: لديك %{stat} طلب نقل معلق + many: لديك %{stat} طلب نقل معلق + other: لديك%{stat} نقل حالة في الانتظار + count_records_new: + zero: 'لديك %{stat} حالات مفتوحة ' + one: 'لديك %{stat} حالات مفتوحة ' + two: 'لديك %{stat} حالات مفتوحة ' + few: 'لديك %{stat} حالات مفتوحة ' + many: 'لديك %{stat} حالات مفتوحة ' + other: 'لديك %{stat} حالات مفتوحة ' + count_records_total: + zero: لديك%{stat} إجمالي الحالات + one: لديك%{stat} إجمالي الحالات + two: لديك%{stat} إجمالي الحالات + few: لديك%{stat} إجمالي الحالات + many: لديك%{stat} إجمالي الحالات + other: لديك%{stat} إجمالي الحالات + count_referrals_new: + zero: 'و %{stat} إحالات جديدة ' + one: 'و %{stat} إحالات جديدة ' + two: 'و %{stat} إحالات جديدة ' + few: 'و %{stat} إحالات جديدة ' + many: 'و %{stat} إحالات جديدة ' + other: 'و %{stat} إحالات جديدة ' + count_referrals_total: + zero: لديك%{stat} إجمالي الإحالات + one: لديك %{stat} إجمالي الإحالات + two: لديك%{stat} إجمالي الإحالات + few: لديك%{stat} إجمالي الإحالات + many: لديك%{stat} إجمالي الإحالات + other: لديك%{stat} إجمالي الإحالات + count_rejected_approval_total: + zero: و %{stat} موافقات على %{stat_type} مرفوضة + one: و %{stat} موافقات على %{stat_type} مرفوضة + two: و %{stat} موافقات على %{stat_type} مرفوضة + few: و %{stat} موافقات على %{stat_type} مرفوضة + many: و %{stat} موافقات على %{stat_type} مرفوضة + other: و %{stat} موافقات على %{stat_type} مرفوضة + count_rejected_transfers: + zero: و%{stat} نقل حالات مرفوضة + one: و%{stat} نقل حالات مرفوضة + two: و%{stat} نقل حالات مرفوضة + few: و%{stat} نقل حالات مرفوضة + many: و%{stat} نقل حالات مرفوضة + other: و%{stat} نقل حالات مرفوضة + count_risk_level_new: + zero: و%{stat} حالات ذات خطورة %{stat_type} جديدة + one: و%{stat} حالات ذات خطورة %{stat_type} جديدة + two: و%{stat} حالات ذات خطورة %{stat_type} جديدة + few: و%{stat} حالات ذات خطورة %{stat_type} جديدة + many: و%{stat} حالات ذات خطورة %{stat_type} جديدة + other: و%{stat} حالات ذات خطورة %{stat_type} جديدة + count_risk_level_total: + zero: 'لديك %{stat} حالة %{stat_type} الخطورة ' + one: 'لديك %{stat} حالة %{stat_type} الخطورة ' + two: 'لديك %{stat} حالة %{stat_type} الخطورة ' + few: 'لديك %{stat} حالة %{stat_type} الخطورة ' + many: 'لديك %{stat} حالة %{stat_type} الخطورة ' + other: 'لديك %{stat} حالة %{stat_type} ذات خطورة ' + count_waiting_for_acceptance_transfers: لديك %{stat} نقل حالة بإنتظار موافقتك + current_owner: المكلَّف حاليًّا بالملفّ + dash_case_incident_overview: حالاتي + dash_group_overview: حالات مجموعتي + dash_shared_from_my_team: تمّ تشاركها من فريقي + dash_shared_with_me: 'تم مشاركتها معي ' + dash_shared_with_my_team: تمّ تشاركها مع فريقي + dash_shared_with_my_team_overview: تم مشاركته مع فريقي (نظرة عامة) + dash_shared_with_others: تمّ تشاركها مع آخرين + dash_national_admin_summary: ملخص المسؤول + dash_violations_category_verification_status: إجمالي عدد الحوادث لكل وضع تحقق + dash_violations_category_region: إجمالي عدد الحوادث التي تم التحقق منها لكل منطقة + dash_perpetrator_armed_force_group_party_names: إجمالي عدد الحوادث لكل مرتكب + date: التاريخ + date_of_incident: تاريخ الحادثة + date_of_interview: تاريخ المقابلة + due: متأخرة + flagged: 'مميزة بعلامة ' + flagged_by: 'تم تمييزه بعلامة بواسطة:' + flagged_by_me: تم تمييزه بعلامة بواسطتي + flagged_by_other: تم تمييزه بواسطة شخص آخر + flagged_cases: الحالات المميّزة بعلامة + follow_up: متابعة + forms: تبوبب الاستمارات + geographic_area: المنطقة الجغرافية + group_overview_closed: مغلقة + group_overview_open: مفتوحة + high_level: مرتفع + high_risk: أولوية عالية + immediate_response: 'استجابة فورية ' + in_progress: قيد التنفيذ + incident_id: 'معرف #الحادثة' + incident_location: موقع الحادثة + incident_status_open: مفتوح + last_updated: آخر تحديث + link_see_all: عرض الكل + low_level: منخفض + low_risk: أولوية منخفضة + manager_count_closed_total: + zero: و %{stat} حالات مغلقة + one: و %{stat} حالات مغلقة + two: و %{stat} حالات مغلقة + few: و %{stat} حالات مغلقة + many: و %{stat} حالات مغلقة + other: و %{stat} حالات مغلقة + manager_count_open_total: + zero: 'لديك %{stat} حالات مفتوحة ' + one: 'لديك %{stat} حالات مفتوحة ' + two: 'لديك %{stat} حالات مفتوحة ' + few: 'لديك %{stat} حالات مفتوحة ' + many: 'لديك %{stat} حالات مفتوحة ' + other: 'لديك %{stat} حالات مفتوحة ' + manager_transfers_totals: + zero: 'لديك %{stat} %{stat_type} نقل حالة ' + one: 'لديك %{stat} %{stat_type} نقل حالة ' + two: 'لديك %{stat} %{stat_type} نقل حالة ' + few: 'لديك %{stat} %{stat_type} نقل حالة ' + many: 'لديك %{stat} %{stat_type} نقل حالة ' + other: 'لديك %{stat} %{stat_type} عملية نقل حالة ' + match_result: نتائج متشابهة + medium_level: متوسط + medium_risk: أولوية متوسطة + missed_cases: الحالات المفقودة + name: الاسم + name_or_survivor_code: اسم أو رمز الضحية + near_deadline: 'قاربت على تاريخ الانتهاء ' + new: جديد ومحدث + new_child_assigned_to_you: حالات جديدة تم تعيينها لك + new_incident: حالات جديدة + new_incident_assigned_to_you: حوادث جديدة تم تعيينها لك + new_last_week: جديد (الاسبوع الماضي) + new_or_updated: جديد أو مُحدث + new_referred: إحالات جديدة + new_service_provision: تقديم خدمة جديدة + new_this_week: جديد(هذا الاسبوع) + no_action_risk: لا يوجد إجراء + no_case_stats: لا يوجد إحصائيات حالة + no_caseworker_data: ' بيانات الأخصائي الاجتماعي غير موجودة' + no_flagged_child: لا يوجد حالات مميزة بعلامة + no_flagged_incident: لا يوجد حوادث مميزة بعلامة + no_open_incidents: لا يوجد حوادث مفتوحة + no_overdue_activities: لا يوجد أنشطة متأخرة + no_recent_activities: لا يوجد أنشطة حديثة + no_scheduled_activities: لا يوجد أنشطة مجدولة + none_risk: لم تحدد الاولوية + number_of_victims: عدد الضحايا + number_of_violations: عدد الانتهاكات + number_of_violations_verified: التحقق من الانتهاكات + open: مفتوح + open_cases: حالات مفتوحة + open_incidents: حوادث مفتوحة + outstanding_transfers: عمليات التحويل غير المنجزة + overdue_activities: أنشطة متأخرة + overdue_cases_to_assign: الحالات المتأخرة بانتظار التعيين + overdue_cases_to_assign_high: لديك هذه الحالات منذ اكثر من 1 ساعة + overdue_cases_to_assign_low: لديك هذه الحالات منذ اكثر من ثلاث ساعات + overview: لمحة عامّة + pending: قيد الانتظار + pending_approvals: الموافقات المعلّقة + pending_transfers: عمليات النقل المُعلّقة + protection_concern: شواغل الحماية + protection_concerns: مخاوف تتعلق بالحماية + range12+: '+12' + range4: 0-4 + range4_8: 4-8 + range8_12: 8-12 + recent_activities: أنشطة حديثة + recently_flagged_child: حالات تم تميزها بعلامة مؤخرا + recently_flagged_incident: حوادث مميزة بعلامة مؤخرًا + referrals_by_social_worker: الإحالات بواسطة الأخصائي الاجتماعي + registration: التسجيل + rejected: مرفوض + rejected_transfers: عمليات النقل المرفوضة + response: الاستجابة (قيد التقدم) + scheduled_activities: أنشطة مجدولة + score_range: نطاق النتائج + screening_service: خدمة الفرز + services: الخدمات + services_implemented: تم تقديم الخدمة + shared_from_my_team_pending_transfers: عمليات النقل المُعلّقة + shared_from_my_team_referrals: الإحالات + shared_from_my_team_rejected_transfers: عمليات النقل المرفوضة + shared_with_me_new_referrals: إحالات جديدة + shared_with_me_total_referrals: مجموع الإحالات + shared_with_me_transfers_awaiting_acceptance: عمليات النقل في انتظار القبول + shared_with_my_team_pending_transfers_overview: عمليات النقل في انتظار القبول + shared_with_my_team_pending_transfers: عمليات النقل المُعلّقة + shared_with_my_team_referrals: الإحالات + shared_with_others_pending_transfers: عمليات النقل المُعلّقة + shared_with_others_referrals: الإحالات + shared_with_others_rejected_transfers: عمليات النقل المرفوضة + status_of_cases: وضع الحالات + system_user: النظام + total: المجموع + total_cases: إجمالي الحالات + total_referred: مجموع الإحالات + tr_stats: تتبع الطلبات + transers_awaiting_acceptance: عمليات النقل بانتظار القبول + transfers_by_social_worker: عمليات النقل حسب الاخصائي الاجتماعي + users: أيقونة الإعدادات + violence_type: نوع العنف + with_incidents: مع حوادث + with_new_incidents: مع حوادث جديدة + without_incidents: من دون حوادث + worker_count_referrals_total: + zero: '%{case_worker} لديه %{stat} اجمالي إحالات' + one: '%{case_worker} لديه %{stat} اجمالي إحالات' + two: '%{case_worker} لديه %{stat} اجمالي إحالات' + few: '%{case_worker} لديه %{stat} اجمالي إحالات' + many: '%{case_worker} لديه %{stat} اجمالي إحالات' + other: '%{case_worker} لديه %{stat} اجمالي إحالات' + worker_count_total: + zero: '%{case_worker} لديه %{stat} اجمالي حالات' + one: '%{case_worker} لديه %{stat} اجمالي حالات' + two: '%{case_worker} لديه %{stat} اجمالي حالات' + few: '%{case_worker} لديه %{stat} اجمالي حالات' + many: '%{case_worker} لديه %{stat} اجمالي حالات' + other: '%{case_worker} لديه %{stat} اجمالي حالات' + workflow: سير العمل + workflow_team: سير العمل - حالات الفريق/الفرق + you_have: 'لديك' + disabled: + status: + disabled: 'مُعطلة ' + enabled: مُفعلة + email_notification: + assign: 'المستخدم %{user} قد عيّن السجل التالي %{record_type} لك: %{record_id}' + assign_subject: '%{record_type}: %{id} - مُعيّن لك' + approval_request: 'المستخدم %{user} يطلب موافقة من نوع%{approval_type} بخصوص الحالة %{case_id}' + approval_request_subject: 'حالة: %{id} طلب الموافقة' + approval_response: '%{user} لديه %{status} طلب الموافقة من نوع %{approval_type} للحالة %{case_id}.' + approval_response_subject: 'حالة: %{id} الإجابة على طلب الموافقة' + referral: 'المستخدم %{user} من المؤسسة %{agency} قد أحال نوع السجل التالي %{record_type} إليك: رقم السجل %{record_id} لنوع الخدمة %{service_type}' + transfer: 'المستخدم %{user} قد نقل السجل التالي %{record_type}لك: %{record_id}' + transfer_request_subject: طلب نقل لحالة من حالاتك + transfer_subject: '%{record_type}: %{id} - النقل' + referral_subject: '%{record_type}: %{id}- الإحالة' + transfer_request: 'مستخدم بريميرو %{user} من مؤسسة %{agency} يطلب أن تنقل ملكية هذا السجل من نوع %{record_type} ومعرّف %{record_id} بحيث يتمكنون من تقديم خدمات إدارة للشخص في منطقتهم. إذا كان التحويل مقبولا من طرفك، يرجى النقر على رابط معرف نوع السجل %{record_type} في هذا الايميل لفتح نوع السجل %{record_type} في بريميرو والبدء بعملية التحويل.' + approval_request_html: 'المستخدم %{user} يطلب موافقة من نوع %{approval_type} بخصوص الحالة %{case_id} .' + approval_response_html: 'المستخدم %{user} لديه %{status} طلب الموافقة من نوع %{approval_type} للحالة %{case_id} .' + referral_html: 'المستخدم %{user} من المؤسسة %{agency} قد أحال نوع السجل التالي %{record_type} إليك: رقم السجل %{record_id} لنوع الخدمة %{service_type}' + transfer_html: 'المستخدم %{user} قد حوّل السجل التالي %{record_type}لك: %{record_id}.' + assign_html: '%{user} عيّن السجلّ التالي %{record_type} لك: %{record_id}.' + transfer_request_html: 'مستخدم بريميرو %{user} من المؤسسة %{agency} يطلب أن تنقل ملكية هذا السجل من نوع %{record_type} ومعرّف %{record_id} بحيث يتمكنون من تقديم خدمات إدارة للشخص في منطقتهم. إذا كان التحويل مقبولا من طرفك، يرجى النقر على رابط معرف نوع السجل %{record_type} في هذا الايميل لفتح نوع السجل %{record_type} في بريميرو والبدء بعملية التحويل.' + transfer_request_notes_html: 'ملاحظات من الشخص الذي قدم الطلب:%{request_transfer_notes}' + alert: 'تم تحديث% {record _ type}% {id} -% {form _ name}. يرجى تسجيل الدخول إلى Primero لمراجعة التغييرات.' + alert_subject: '% {سجل _ نوع}:% {معرف} -% {شكل _ اسم} محدث' + webpush_notification: + action_label: الذهاب الى الحالة + approval_request: + title: طلب الموافقة + body: ' طلب موافقة معلق لـلحالة% {نوع}.' + approval_response: + title: الرد بالموافقة + body: لقد تلقت إحدى حالاتك ردًا بالموافقة. + assign: + title: تكليف جديد + body: لقد تلقيت تكليف بحالة جديدة + referral: + title: إحالة جديدة + body: لقد تلقيت إحالة لحالة جديدة + transfer: + title: نقل جديد + body: لقد تلقيت طلب نقل لحالة جديدة + alert_case: + title: 'تم تحديث الحالة ' + body: "تم تحديث% {نوع} في إحدى حالاتك." + transfer_request: + title: طلب نقل + body: لقد تلقيت طلب نقل لحالة جديدة + encrypt: + export_type: نوع التصدير + file_name: قم بإنشاء اسم الملف الخاص بك (اختياري) + password_extra_info: يجب أن تتألّف كلمة المرور من 8 أحرف على الأقل. سيتم ربط كلمة المرور هذه بالملف الذي تم تصديره وسيتعين إدخالها من قبل أي شخص يفتح هذا الملف في المستقبل. + password_label: الرجاء إدخال كلمة المرور التي سوف تشفّر ملفك. + error_message: + address_fields: يجب عليك معالجة المجالات %{fields} في الاستمارات %{forms} + address_form_fields: يجب عليك معالجة المجالات %{fields} في هذه الاستمارة + address_subform_fields: ' الاستمارة الفرعية%{subform} تحتوي على عدد %{fields} من المجالات غير الصالحة' + error_401: لقد قمت بتسجيل الخروج. الرجاء تسجيل الدخول مجددا + error_something_went_wrong: حدث خطأ ما + error_page: + not_authorized: + server_error: أنت غير مخوّل لدخول هذه الصفحة. + title: غير مسموح + not_found: + contact_admin: إذا كنت تعتقد إنك جئت إلى هنا بالخطأ يرجى الاتصال بالمشرف. + something_went_wrong: للأسف، هناك خطأ ما + errors: + api: + internal_server: خطأ في السيرفر + attachments: + maximum: لقد تجاوزت عدد الملفات المسموح به في السجل + error_loading: خطأ في تحميل السجل (السجلات) + models: + agency: + code_present: لا يجب أن يكون فارغا + logo_format: يجب أن يكون الملف بنوع png + terms_of_use_format: يجب أن يكون الملف بنوع png + name_present: لا يجب أن يكون فارغا + child: + age: يجب أن يكون العمر ما بين 0 و 130 + date_of_birth: الرجاء إدخال تاريخ ميلاد صالح لسجل الحالة هذه + export_configuration: + opt_out_field_does_not_exist: مجال عدم المشاركة المحدد لا يوجد في السجل + record_type: نوع سجل غير صالح. يجب أن يكون طفل، طلب تتبع أو حادثة. + field: + translated_options_do_not_match: الخيارات المترجمة للحقل يجب أن يكون لها نفس المعرّف + location: + admin_level_present: لا يجب أن يكون فارغا + code_present: لا يجب أن يكون فارغًا + name_present: لا يجب أن يكون فارغًا + unique_location_code: يوجد موقع له نفس الرمز بالفعل، يرجى إدخال رمز مختلف + lookup: + being_used: هذا البحث مستخدم ولا يمكن حذفه + name_present: لا يجب أن يكون الاسم فارغاً + values_ids_blank: هناك معرّف فارغ لقيمة البحث + primero_module: + associated_record_types: يجب أن يرتبط نوع واحد من السجلات على الأقل بهذه الوحدة النمطية + form_section_ids: يجب أن يرتبط نموذج واحد على الأقل بهذه الوحدة النمطية + name_present: لا يجب أن يكون الاسم فارغاً + unique_name: توجد وحدة نمطية تحمل هذا الاسم بالفعل، الرجاء إدخال اسم مختلف + report: + module_presence: لا يجب أن تكون الوحدة النمطية فارغة + module_syntax: يجب أن تكون جميع وحدات التقرير النمطية موجودة + name_presence: لا يجب أن يكون الاسم فارغاً + role: + permission_presence: الرجاء تحديد إذن واحد على الأقل + user: + email: "يرجى إدخال عنوان بريد إلكتروني صالح (مثلاً: \"name@example.org\")" + password_mismatch: مجالات كلمة المرور لا تحمل نفس كلمة المرور + password_length: يجب أن تتألف كلمة المرور من %{min} أحرف على الأقل + email_uniqueness: يوجد بالفعل مستخدم لعنوان البريد الإلكتروني هذا. الرجاء إدخال عنوان مختلف + code_of_conduct: + title_present: يجب ألا يكون العنوان فارغًا + content_present: يجب ألا يكون المحتوى فارغًا + created_by_present: يجب ألا يكون مجال الإنشاء بواسطة فارغًا + webpush_subscription: + notification_url_present: notification_url يجب ألا تكون فارغ + notification_url_format: يجب تنسيق عنوان URL لnotification_url + auth_present: يجب ألا يكون Auth فارغًا + p256dh_present: p256dh يجب ألا تكون فارغة + not_found: لم يتمّ العثور على أي سجل (سجلات) + try_again: حاول مجدّدًا + exports: + case_pdf: + all: PDF + one: PDF + selected: تحديد إلى PDF + csv: + all: CSV + one: CSV + selected: تحديد إلى CSV + custom: + all: مخصّص + custom_exports: + all: مخصّص + choose_fields: هل تريد اختيار مجالات فردية من أجل استمارة؟ + empty_fields_forms: الرجاء تحديد بعض النماذج أو الحقول لتصديرها + empty_format: الرجاء تحديد صيغة لتصديرها. + empty_module: الرجاء تحديد وحدة نمطية لتصديرها. + empty_password: رجاء إدخال كلمة السر التي ستُشفر ملفك + field_label: مجال + fields: قم باختيار مجالات للتحويل + form_label: استمارة + format_label: حدد صيغة + forms: حدد نماذج لتصدير الملف + label: عمليات تصدير الملف المخصصة + module_placeholder: الرجاء تحديد وحدة نمطية. + select_module: حدد وحدة نمطية + submit: موافق + header: عنوان رئيسي + custom_header: عنوان رئيسي مُخصّص + signatures: تضمين أسطر التوقيع لـ + include_implementation_logos: هل تريد تضمين شعارات التنفيذ؟ + include_implementation_logos_help_text: سيشمل ذلك الشعارات التي تظهر في قائمة التنقل وعلى صفحة تسجيل الدخول. + include_agency_logo: هل تريد تضمين شعار المؤسسة؟ + include_other_logos: هل تريد تضمين شعارات أخرى؟ + duplicate_id_csv: + all: تكرير الهوية + female_abbreviation: أنثى + headers: + age: العمر + case_id: معرف الحالة + child_name_last_first: اسم الطفل + family_size: 'حجم العائلة ' + moha_id: رقم هوية وزارة الصحة مهملة + national_id_no: رقم بطاقة التعريف الوطنية + progress_id: معرف التقدم + sex_mapping_m_f_u: 'الجنس ' + other_agency_id: رمز المستشفى ورقم المريض + male_abbreviation: ذكر + unknown_abbreviation: U + exported: تمّ إنشاء ملف التصدير بنجاح + exported_error: خطأ في إنشاء ملف التصدير + forms: + button: تصدير استمارات + label: تصدير + header: + form_group: مجموعة الاستمارات + form_name: اسم الاستمارة + field_id: معرِّف المجال + field_type: نوع المجال + field_name: اسم المجال + required: مطلوب + on_mobile: على الهاتف المحمول + on_short_form: على استمارة قصيرة + option_ids: معرِّفات الخيار + options: الخيارات + options_lookup: بحث + help_text: نص المساعدة + guiding_questions: اسئلة توجيهية + visible: مرئي + lookup_id: معرِّف البحث + lookup_name: إسم البحث + option_id: معرِّف الخيار + option_name: اسم الخيار + options: + location: المواقع + agency: مؤسسات + user: المستخدمون + reportinglocation: مواقع الإبلاغ + subforms: 'الاستمارة الفرعية: %{subform_name}' + collapsed_fields: 'مجالات مدمجة: %{fields}' + country: بلاد + linkedincidents: الحوادث المرتبطة + summary_header: + form_group: مجموعة استمارات بريميرو + form: مجموعة استمارات بريميرو + status: الوضع + notes: ملاحظات + go_to_exports: انتقل إلى صفحة التصديرات للتنزيل + incident_recorder_xls: + all: مسجّل الحادثة + one: مسجّل الحادثة + selected: 'تم اختياره لمسجّل الحادثة ' + json: + all: JSON + one: JSON + selected: تحديد إلى JSON + list_view_csv: + all: تصدير ملف عرض القائمة + selected: تحديد إلى CSV + messages: + no_exporter: لم يتم تحديد أي مصدِّر + mrm_violation_xls: + all: انتهاكات آلية المراقبة والإبلاغ MRM + one: انتهاكات آلية المراقبة والإبلاغ MRM + selected: تحدد إلى انتهاكات آلية المراقبة والإبلاغ MRM + no_records: لا يوجد سجلات متاحة! + pdf: + all: PDF (غير مشفَّر) + one: PDF + selected: تحديد إلى PDF + pdf_exports: + label: PDF + recipient: المستلِم + case_worker: أخصائي اجتماعي + client: الوحدة الانسانية + date: التاريخ + recipient_name: اسم المستلِم + recipient_agency: المؤسسةالمستقبلة + caseworker_name: اسم الأخصائي الإجتماعي + caseworker_agency: مؤسسة الأخصائي الإجتماعي + photowall: + all: جدار صور + flag_suspect_record: مميّز بعلامة كسجلّ المشتبه به + no_photos_available: لا توجد صور متوفّرة + one: جدار صور + reunited: إعادة لمّ الشمل + selected: تم الاختيار لجدار الصور + success_message: إنشاء جدار الصور%{file_name} لن يتم تضمين الحالات التي لا تحتوي على صور. + printed: 'تمّت الطباعة %{date}' + queueing: جاري إنشاء ملف التصدير %{file_name} + selected_xls: + all: Excel + one: Excel + selected: تحديد إلى Excel + selected_fields: المجالات المختارة + unhcr_csv: + all: المفوضية السامية للأمم المتحدة لشؤون اللاجئين UNHCR + female_abbreviation: أنثى + headers: + age: العمر + case_status: 'وضع الحالة ' + causes_of_separation: سبب الانفصال + country_of_origin: البلد الأصلي + cpims_code: رمز نظام المعلومات الخاص بحماية الطفل + current_care_arrangement: ترتيبات الرعاية الحالية + date_of_birth: 'تاريخ الميلاد ' + date_of_identification: تاريخ التحديد + family_count_no: عدد أفراد الأسرة + governorate_country: المحافظة - الدولة + id: المعرّف + individual_progress_id: معرف التقدم الفردي + locations_by_level: العنوان (مخيم، كتلة سكنية أو أي عنوان صالح كإحداثيات GPS للمأوى) + long_id: هوية شخصية طويلة + moha_id: معرف وزارة الصحة + name_of_caregiver: الاسم الكامل لمقدم الرعاية + name_of_child_last_first: الاسم الكامل للطفل + primary_protection_concerns: تدابير الحماية الأولية + progres_id: معرف التقدم + reunification_status: حالة جمع شمل الأسرة + secondary_protection_concerns: تدابير الحماية الثانوية + sex: 'الجنس ' + sex_mapping_m_f_u: 'الجنس ' + short_id: معرف قصير + vulnerability_code: رموز الهشاشة + vulnerability_details_code: 'كود تفاصيل الضعف ' + male_abbreviation: ذكر + one: المفوضية السامية للأمم المتحدة لشؤون اللاجئين UNHCR + selected: تحديد إلى المفوضية السامية للأمم المتحدة لشؤون اللاجئين UNHCR + unknown_abbreviation: U + xlsx: + all: Excel + one: Excel + selected: مختارة لنقلها إلى Excel + imports: + csv_hxl_location: + messages: + success: تمّ استيراد المواقع بنجاح + no_data: 'لم تتمّ معالجة المحتوى المستورد: لم يتم تمرير أي بيانات' + csv_parse_error: 'لم تتم معالجة المحتوى المستورد: خطأ في تحليل بيانات CSV' + error: 'السطر %{row_number} غير معالج: %{message}' + db_error: 'خطأ في إنشاء %{location_code}: %{message}' + locale_invalid: 'التخطي%{column_name}: الموضع غير صالح' + insert_all_error: 'لم تتم معالجة المحتوى المستورد: خطأ في قاعدة البيانات:%{message}' + csv_record: + messages: + success: تم استيراد السجلات بنجاح + no_data: 'لم تتمّ معالجة المحتوى المستورد: لم يتم تمرير أي بيانات' + no_file: 'لم تتم معالجة الاستيراد: الملف غير موجود' + csv_parse_error: 'لم تتم معالجة المحتوى المستورد: خطأ في تحليل بيانات CSV' + error: 'السطر %{row_number} غير معالج: %{message}' + db_error: 'خطأ في إنشاء %{location_code}: %{message}' + locale_invalid: 'تجاوز %{column_name} : الموقع غير صحيح' + insert_all_error: 'لم تتم معالجة المحتوى المستورد: خطأ في قاعدة البيانات:%{message}' + sync_record: + failed: 'آخر مزامنة: فشلت' + last: 'آخر مزامنة:%{date_time}' + not_found: 'آخر مزامنة: لم يتم العثور على البيانات' + retrieving: استرجاع البيانات. + see_details: راجع التفاصيل + fields: + action: إجراء + actions: الإجراءات + add: إضافة + add_new_field: انشاء مجال جديد + add_existing_field: إضافة مجال موجود + add_field: إضافة مجال + add_field_type: إضافة%{file_type} + attachments: + maximum_attached: تخطيت الحد الأقصى للمرفقات لكل سجل (% {maximumtachmentsPerRecord}) . يتضمن ذلك الصور والصوت والمستندات. الرجاء إزالة ملف قبل إضافة آخر. + audio: + current: التسجيل الصوتي الحالي + audio_upload_box: تحميل التسجيل الصوتي + bia_document: مستند المصلحة الفضلى + bid_document: مستند المصلحة الفضلى + check_box: خانات الاختيار + clear_group_by: مسح المجموعة حسب + clear_sort_by: مسح الترتيب حسب + copy_from_another_form: تم نسخ هذا المجال من نموذج آخر + create_field: انشاء مجال + create_unique_values: إنشاء قِيَم فريدة + date_field: مجال التاريخ + date_help: اليوم-الشهر-السنة + date_help_with_time: 'اليوم-الشهر-السنة الساعة: الدقيقة' + date_not_valid: التاريخ غير صحيح + time: الوقت + date_range: + date: التاريخ + date_range: نطاق التاريخ + from: من + to: إلى + view_by: اظهر حسب + date_range_field: نطاق التاريخ + date_time: التاريخ - الوقت + db_name: إسم قاعدة البيانات + default: مبدئي + default_date_validation: التأكد من صحة التاريخ المبدئي + default_to_current_date: هل تريد جعل التاريخ الحالي إعدادًا مبدئيا؟ + default_to_current_datetime: هل تريد جعل التاريخ والوقت الحاليين إعدادًا مبدئيا؟ + default_value: القيمة المبدئية + deleted: تم إلغاء المجال %{display_name}. + detail: تفاصيل + disabled: 'مُعطلة ' + display_name: عرض الاسم + document: + comments: ملاحظات + current: هل هذا هو الملف الحالي؟ + date: تاريخ الوثيقة + name: اسم الوثيقة + is_current: هل هذه هي الوثيقة الحالية؟ + document_upload_box: تحميل الوثيقة + edit_label: تعديل المجال + enabled: مُفعلة؟ + enabled_label: مُفعلة + english_text: النص باللغة الإنجليزية + field_name: اسم المجال + field_type: نوع المجال + attachment_too_large: ' يجب ألّا يتعدّى حجم الملفّ 20mb' + file_upload_box: + add_document_label: اضافة وثيقة + add_new_document_button_text: أضف وثيقة أخرى + add_new_photo_button_text: إضافة صورة أخرى + add_photo_label: إضافة صورة + document_description: وصف الوثيقة + document_file_restrictions_message: ' يجب أن لا يتعدى حجم الملف 2mb (لا يمكن تحميل الملفات ذات صيغة(exe.))' + no_file_selected: لم يتم ارفاق أي ملف. + photo_file_restrictions_message: لا يجب أن تكون الصور أكبر من 10 mb. ولا يجب أن تكون الملفات السمعية أكبر من 10 mb. كلما صغر الحجم كلما كان ذلك أفضل + recorded_audio_label: اضافة التسجيل صوتي + select_file_button_text: ارفاق ملف + find_lookup: ايجاد البحث + form_name: اسم الاستمارة + future_date_not_valid: لا يجوز أن يكون في المستقبل + guidance: توجيه + guiding_questions: اسئلة توجيهية + help_text: نص المساعدة + hide_on_view_page: اعرض الصفحة + label: المجالات + mobile_visible: تطبيق على الهاتف الجوال + move_to: الانتقال إلى + multi_select: يمكن تحديد خيارات متعددة + multi_select_box: اختيارات متعدّدة + must_be_english: يجب الإدخال باللغة الإنجليزية + name: الإسم + not_future_date: ليس تاريخ مستقبلي + number_not_valid: الرجاء إدخال بيانات رقمية + numeric_field: حقل رقمي + on_collapsed_subform: على استمارة فرعية مُدمّجة + option_strings_add_option: إضافة خيار + option_strings_source: عمليات البحث + option_strings_text: الخيارات + option_strings_text_display: نص الخيار + option_strings_text_key: مفتاح الخيار + options_indications_lookup_values: يمكنك استخدام عمليات البحث المحددة مسبقًا أو إنشاء قِيَم فريدة. + options_indications_restrictions: لا يمكنك فعل الأمرين. + options_or_lookup_warning: يُرجى إضافة خيارات أواختر بحث. لا تقوم بإدخالهما معا. + other_documents: مستند آخر + photo_upload_box: تحميل صورة + predifined_lookups: استخدام عمليات البحث المحددة مسبقًا + radio_button: زر انتقاء + remove: حذف + remove_attachment_confirmation: هل أنت متأكد أنك تريد إزالة هذا المرفق؟ + required: مطلوب + required_field: '%{field} مطلوب' + search_existing: ابحث في الحقول الموجودة + select_box: 'حدد القائمة ' + select_date_validation: اختر طريقة للتأكد من سلامة التاريخ + select_multiple: 'اختَر كلّ ما ينطبق ' + select_single: (اختَر...) + separator: فاصل + show: أظهِر؟ + show_on: اظهِر على + show_on_minify_form: استمارة قصيرة + skip_logic: + name: التخطي استنادا على نوع الإجابة + record_section: + title: 'يجب ان يظهر هذا الحقل في حال كان السجل ' + buttons: + add: اضافة شرط السجل + subform_section: + title: يجب ان يظهر هذا المجال في حال اذا كانت الاستمارة الفرعية + buttons: + add: 'اضافة شرط الاستمارة الفرعية ' + subform: الاستمارة الفرعية + subform_group_by: اجمع حسب + subform_remove_message: هل أنت متأكد من حذف هذه الاستمارة الفرعية؟ + subform_section: + description: وصف الاستمارة الفرعية + name: عنوان الاستمارة الفرعية + starts_with_one_entry: هل تريد البدء بمُدخل استمارة فرعية واحدة؟ + subform_append_only: المزامنة الانتقائية على الهاتف المحمول + subform_prevent_item_removal: منع إزالة مُدخل الاستمارة الفرعية؟ + subform_sort_by: ترتيب حسب + successfully_added: تم إضافة المجال بنجاح + tally_field: مجال الفرز + tally_items: عناصر الفرز + tally_items_maximum: (5 على الأكثر) + text_area: منطقة النص + text_field: مجال نص + textarea: منطقة النص + tick_box: خانة الاختيار + tick_box_label: تسمية خانة الاختيار + translation_text: نص الترجمة + total: المجموع + type: النوع + updated: تم تحديث المجال + visibility: رؤية + web_app: تطبيق على شبكة الإنترنت + filters: + apply_filters: تقديم طلب + clear_filters: مسح + less: أقلّ... + more: أكثر... + save_filters: حفظ + categories: + violations: الانتهاكات + incidents: حوادث + individual_victims: ضحايا فردية + flags: + add_flag_tab: أضِف علامة جديدة + date: 'التاريخ:' + flag_added: تمّت إضافة العلامة بنجاح + flag_date: تاريخ وضع العلامة + flag_reason: سبب وضع العلامة + flag_reason_maximun_label: ' 255 حرفًا كحد أقصى.' + flag_resolved: تمّ حلّ العلامة + flags_tab: العلامات + no_flags: لم يتمّ العثور على علامات + resolve_button: حلّ + resolve_flag: حلّ العلامات + resolve_reason: سبب الإنهاء / الحل + resolved: العلامات التي تمّ حلّها + resolved_date: 'تمّ حلّها:' + resolved_reason: 'سبب الإنهاء / الحل' + title: العلامات + followup_reminders: + system_generated_followup_flag: زيارة متابعة إلزامية + form_section: + form_name: اسم النموذج + module: وحدة + name: الإسم + record_type: نوع السجل + required_field: '%{field} إجباري' + forms: + add: أضف استمارة + description: وصف الاستمارة + fields: المجالات + form_description: وصف + form_group: مجموعة الاستمارات + form_title: عنوان الاستمارة + help_text: + must_be_english: يجب الإدخال باللغة الإنجليزية + related_groups: ضع الاستمارة في مجموعة من المستخدمين ذات الصلة + summariaze_purpose: لخّص الغرض من الاستمارة. يجب الإدخال باللغة الإنجليزية + invalid_characters_field: '%{field}يحتوي على أحرف غير صالحة.' + label: استمارات + manage: إدارة + messages: + created: تمّ إنشاء قسم الاستمارة بنجاح + fields_with_same_name: لا يمكن أن تحتوي الاستمارة على مجالات بنفس الاسم + save_success: تمّ تحديث أقسام الاستمارات بنجاح + save_with_errors: حدثت مشكلة ولم يتمّ تحديث بعض أقسام الاستمارة. + updated: تمّ تحديث قسم الاستمارة بنجاح + use_existing: نشجعكم على استخدام الاستمارات المتوفرة حيث يسهل ذلك مشاركة البيانات ودمجها بين المؤسسات. + mobile_app: تطبيق على الهاتف الجوال + module: وحدة + no_subform_filters_added: لا يحتوي هذه الاستمارة الفرعية حاليًا على مجالات. + record_type: نوع السجل + record_types: + approvals: الموافقات + case: حالة + child: حالة + incident: حادثة + individual_victim: ضحية فردية + potential_match: تشابه محتمل + record_information: معلومات السجلّ + referrals: الإحالات + reportable_follow_up: متابعة + reportable_protection_concern: مخاوف تتعلق بالحماية + reportable_service: خدمة + tracing_request: طلب التتبع + transfers_assignments: عمليات النقل والتعيينات + violation: انتهاك + registry_details: تفاصيل التسجيل + registry_record: سجل التسجيل + family_record: سجل الأسرة + family: سجل الأسرة + required_field: '%{field} هو مجال مطلوب' + select_label: اختيار + settings: إعدادات + show_on: اظهِر على + subform_need_to_be_added: يجب إضافتها. + subform_need_to_be_added_single: بحاجة الى ان يضاف + subform_not_found: لم يتمّ ايجاد الاستمارة الفرعية %{subform_name}. + title: عنوان الاستمارة + translations: + edit: تعديل الترجمات + edit_form_group: ' تعديل البحث عن مجموعة الاستمارات.' + manage: إدارة الترجمات + no_changes_message: لم تقم بأي تغييرات في الترجمة + note: 'ملاحظة:' + note_form_group: لإضافة ترجمات إلى مجموعة النماذج، يجب تعديل ترجمات البحث عن مجموعة الاستمارات. + select_language: اختَر اللغة + title: الترجمات + type_label: النوع + visibility: رؤية + web_app: تطبيق على شبكة الإنترنت + skip_logic: + name: التخطي استنادا على نوع الإجابة + section: + title: يجب ان تظهر هذه الاستمارة اذا + buttons: + add: اضافة الشرط + conditions: + add: اضافة الشرط + update: تحديث/تعديل الشرط + field_name: اسم المجال + condition: الشرط + empty: لم يتم اضافة اي شروط + type: النوع + types: + and: + display_text: بالاضافة الى هذا الشرط + name: 'و ' + or: + display_text: أو هذا الشرط + name: أو + home: + ar: العربية + ar-IQ: العربية (العراقية) + ar-JO: العربية (الأردنية) + ar-LB: العربية (اللبنانية) + ar-SD: العربية (السودانية) + bn: বাংলা + cmn: اللغة الصينية + current_time_zone: المنطقة الزمنية الحالية + dashboard: لوحة المعلومات + en: English + es: Español + es-GT: أسبانية + es-ES: اسبانية(اسبانيا) + fr: Français + hu: المجرية + id: Bahasa + km: ភាសាខ្មែរ + ku: کوردی + ku-IQ: کوردی (بادینی) + fa-AF: فارسی (افغانستان) + ps-AF: پښتو (افغانستان) + sw-KE: الكيسواحيلية (كينيا) + sw-TZ: الكيسواحيلية (تنزانياا) + ne: النيبالية + om: أورومو + am-ET: الأمهرية (إثيوبيا) + tr: تركي + label: الصفحة الرئيسية + language: اللغة + manage_system_users: إدارة مستخدمي مزامنة السيرفر + my: ဗမာစာ + pl: بولندي + pt: Português + pt-BR: برتغالي(البرازيل) + records_need_attention: السجلات التي تحتاج إلى الإنتباه + ro: الروماني + ru: Русский + sk: سلوفينيا + so: Af-Soomaali + th: ไทย + uk: الأوكرانية + users: إدارة المستخدمين + view_records: عرض السجلات + welcome: مرحبا بكم في بريميرو + zh: 中文 + tet: لغة التيتوم + incident: + code: رمز الحادثة + associated_case: "الحالة المرتبطة:" + link_incident_to_case: ربط الحادثة بحالة + link_incident_to_case_success: حادثة(حوداث) مرتبطة بحالة + messages: + creation_success: تم إنشاء سجل الحادثة بنجاح. + creation_success_queue: تمّ إنشاء سجل الحادثة بنجاح في الخلفية + disabled: تم تعطيل الحادثة + update_success: 'تم تحديث الحادثة %{record_id} بنجاح.' + update_success_queue: 'تم تحديث الحادثة %{record_id} بنجاح في الخلفية' + bulk_assign_limit_try_again: لا يمكنك تعيين أكثر من 100 حادثة في وقت واحد. يرجى تحديد 100 حادثة أو أقل ثم المحاولة مرة أخرى. + violation: + associated_violations: "المخالفات ذات الصلة:" + update_and_return: 'تحديث والرجوع الى %{association}' + save_and_return: 'اضافة والرجوع الى %{association}' + pending: قيد التحقّق + title: الانتهاكات + types: + killing: قتل الاطفال + maiming: تشويه الاطفال + recruitment: تجنيد و/او استخدام الاطفال + sexual_violence: الاغتصاب و / أو غيره من أشكال العنف الجنسي + abduction: الخطف + attack_on: الهجوم على المدرسة(المدارس) و/او المستشفى(المستشفيات) + attack_on_hospitals: الهجوم على المستشفى(المستشفيات) + attack_on_schools: الهجوم على المدرسة(المدارس) + military_use: الاستخدام العسكري للمدرسة(المدارس) و/او المستشفى(المستشفيات) + denial_humanitarian_access: منع وصول الخدمات الإنسانية للأطفال + incidents: + change_status: تغُير في الوضع + disable_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحادثة معطّلًا. + disable_dialog_title: تعطيل الحادثة + disable_success: تمّ تعطيل الحادثة بنجاح + enable_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحادثة مفعّلًا + enable_dialog_title: تفعيل الحادثة + enable_success: تمّ تفعيل الحوادث بنجاح + id: رقم الحالة في النظام + complete: متاح بدون الاتصال بالانترنت + date_of_interview: تاريخ المقابلة + date_of_incident: تاريخ الحادثة + incident_location: موقع الحادث + violations: الانتهاكات + export: تصدير + label: حوادث + filter_by: + filter_category: فئة المرشح + boys: الأولاد + by_date: حسب التاريخ + children: الأطفال + girls: الفتيات + incident_location: موقع الحادث + status: الوضع + unaccompanied_separated_status: وضع الحماية + unknown: غير معروف + verification_status: وضع التحقق + violence_type: نوع العنف + armed_force_group_party_name: القوات المسلحة أو الجماعات أو الأطراف الأخرى + armed_force_group_type: 'نوع مجموعة القوات المسلحة ' + violations: الانتهاكات + individual_violations: انتهاكات فردية + individual_age: عمر الفرد + individual_sex: جنس الفرد + victim_deprived_liberty_security_reasons: محرومون من الحرية + reasons_deprivation_liberty: ما هي أسباب الحرمان من الحرية؟ + victim_facilty_victims_held: يرجى تحديد المنشأة التي تم / تم احتجاز الضحية (الضحايا) فيها + torture_punishment_while_deprivated_liberty: هل تعرض / كان الطفل (الأطفال) للتعذيب أو غيره من ضروب المعاملة أو العقوبة القاسية أو اللاإنسانية أو المهينة أثناء حرمانه من الحرية؟ + verified_ghn_reported: حدد GHN الذي تم تضمين هذه الحادثة فيه + weapon_type: 'نوع السلاح / الطريقة المستخدمة' + facility_impact: 'نوع ومدى التأثير المادي' + facility_attack_type: 'نوع الانتهاك المتعلق بالصحة أو التعليم' + child_role: 'ما هو الدور الذي لعبه الطفل (الأطفال) في القوات / الجماعة المسلحة؟' + abduction_purpose_single: 'الغرض من الاختطاف' + military_use_type: 'نوع الاستخدام العسكري' + types_of_aid_disrupted_denial: 'نوع المساعدة / الخدمة المرفوضة / المعطلة.' + late_verified_violations: الانتهاكات التي تم التحقق منها في وقت متأخر + perpetrator_category: نوع المسيء + record_owner: المكلف بالسجل + register_new_incident: حادثة جديدة + reassign: + multiple_successfully: Primero يقوم حاليا باعادة تخصيص الحوادث الخاص ب% {select _ records}. قد يستغرق تحديث كل هذه الحوادث عدة دقائق. لاحظ أن الحوادث المربوطة سابقاً لن يتم ربطها مجدداً. + selectable_date_options: + date_of_first_report: تاريخ المقابلة + mrm_date_of_first_report: تاريخ التقرير الأولي لعضوCTFMR + ctfmr_verified_date: تاريخ قرار التحقق من قبل CTFMR + incident_date_derived: تاريخ الحادثة + selected_records: 'سجل %{select_records} الحادثة (الحوادث) المختارة' + selected_records_assign: '% {حدد _ سجلات} حادثة (حوادث) مختارة. لاحظ أن الحوادث التي تم ربطها سابقاً لن يتم تحديدها.' + selected_all_records: 'اختَر جميع الحوادث %{total_records} التي تطابق هذا الاستعلام.' + summary_mrm: + label: ملخص الحادث + fields: + children_multiple_violation: + label: الأطفال المتضررون من انتهاكات متعددة + summary_of_incident: + label: ملخص الحادث + incident_total_tally: + label: عدد الضحايا + boys: الأولاد + girls: الفتيات + unknown: غير معروف + incident_date: + label: تاريخ الحادثة + incident_location: + label: موقع الحادثة + incident_description: + label: حساب الحادثة + incident_update: + label: تحديث الحادثة + survivor_code: كود الناجية + show_incident: 'مُعرِّف الحادثة %{short_id}' + social_worker: اخصائي الحالة + verify_mrm: تحقق من MRM + violation_type: نوع الانتهاك + violence_type: نوع العنف + type_violence: نوع العنف + violation_summary: ملخص + sort_by: ترتيب حسب + key_performance_indicators: + label: "نبض / مؤشرات الأداء الرئيسة" + case_assessment: "تقييم الحالة" + case_action_planning: "تخطيط عمل الحالة" + case_action_plan_implementation: "تنفيذ خطة عمل الحالة" + case_follow_up: "متابعة الحالة" + case_closure: "إغلاق الحالة" + feedback: "تغذية راجعة" + other: "أخرى" + date_format: "%b %Y" + date_range_select: + custom_range: 'نطاق التاريخ المخصص' + long_date_format: "يوم/شهر/سنة" + time_periods: + all_time: 'كلّ الوقت' + current_month: "الشهر الحالي" + last_3_months: "الأشهر الثلاثة 3 الأخيرة" + last_6_months: "الأشهر الستة 6 الأخيرة" + last_1_year: "العام المنصرم" + 0-3days: "0 - 3 أيام" + 4-5days: "4 - 5 أيام" + 6-14days: "6 - 14 أيام" + 15-30days: "15 - 30 أيام" + 1-3months: "1 - 3 أشهر" + 4months: "أكثر من 3 أشهر" + 1-month: "أقلّ من شهر 1" + 3-6months: "3 -6 أشهر" + 7-months: "أكثر من 6 أشهر" + helptext: + helptext: "تعرف على مؤشر الأداء الرئيس هذا." + number_of_cases: + title: "1. عدد الحالات المسجّلة" + reporting_site: "موقع الإبلاغ" + helptext: | + يحتسب هذا المؤشر عدد الحالات الجديدة التي يتم فتحها شهريًا في كلّ موقع إبلاغ. + يُشير موقع الإبلاغ إلى الموقع الذي تقدم فيه منظمة المستخدم الخدمات + و حيث تم الإبلاغ عن الحالة إلى مزود الخدمة. + number_of_incidents: + title: "2. عدد الحوادث المسجّلة" + reporting_site: "موقع الإبلاغ" + helptext: | + يحتسب هذا المؤشر عدد الحوادث الجديدة التي يتم فتحها شهريًا في كلّ موقع إبلاغ. + يُشير موقع الإبلاغ إلى الموقع الذي تقدم فيه منظمة المستخدم الخدمات + و حيث تم الإبلاغ عن الحالة إلى مزود الخدمة. + reporting_delay: + title: "3. الإبلاغ عن التأخير" + delay: "التأخير" + total_incidents: "مجموع الحوادث" + helptext: "يحتسب هذا المؤشر ويصنف عدد الأيام التي انقضت بين وقت\nتعرّض الناجية للعنف القائم على النوع الاجتماعي والوقت الذي أبلغت فيه الناجية مقدم الخدمة بذلك لأول مرة. يتمّ \nاحتسابه بناءً على وقت إبلاغ منظمة المستخدم بالحادثة. يتمّ \nتصنيف البيانات على أساس فترات زمنية مختلفة (0-3 أيام ؛ 4-5 أيام ؛ 6-14 يومًا ؛ 15-30 يومًا ؛\nأكثر من شهر واحد ؛ أكثر من 3 أشهر).\n" + service_access_delay: + title: "تأخير الوصول إلى الخدمة" + delay: "التأخير" + total_incidents: "مجموع الحوادث" + assessment_status: + title: "4. وضع التقييم" + completed: "مكتمل" + completed_supervisor_approved: "مكتمل وتمّت موافقة الحالات" + helptext: | + يحتسب هذا المؤشر نسبة الحالات النشطة التي استكمل نموذج تقييم بشأنها. + يعتبر التقييم مكتملاً عندما يتمّ إكمال مجموعة من الحقول الإلزامية + في "نموذج تقييم الناجين". + completed_case_safety_plans: + title: "5. خطط سلامة الحالة المكتملة" + completed: "خطّة سلامة الحالة المكتملة" + helptext: | + يحسب هذا المؤشر نسبة الحالات النشطة التي أعتُبِر أنّ + خطة السلامة ضرورية لها ومُكتملة (على سبيل المثال، عنف الشريك الحميم، ومخاطر الانتحار / القتل، وحماية الطفل). + تُعتبر خطة السلامة مكتملة عندما يتمّ استكمال مجموعة من الحقول الإلزامية + ضمن نموذج خطة السلامة. + completed_case_action_plans: + title: "6. خطط عمل حالة مكتملة" + completed: "خطّة عمل حالة مكتملة" + label: "6. خطّة عمل حالة مكتملة" + helptext: "يحتسب هذا المؤشر نسبة الحالات النشطة التي استكملت خطة عمل حالة بشأنها. \nتُعتبر خطة عمل حالة مكتملة عندما يتمّ إكمال مجموعة من الحقول الإلزامية\nفي نموذج خطّة العمل.\n" + completed_supervisor_approved_case_action_plans: + title: "7. وافق مشرف الحالات على خطط عمل الحالة" + completed_and_approved: "تمّت الموافقة على خطط عمل الحالة المكتملة من قبل مشرف الحالات" + helptext: "يحتسب هذا المؤشر نسبة الحالات النشطة التي استكملت خطة عمل حالة بشأنها \nوالموافقة عليها من قبل مشرف الحالات. تعتبر خطة عمل حالة مكتملة \nعندما يتمّ إكمال مجموعة من الحقول الإلزامية في نموذج خطّة العمل. تعتبر خطة الحالة\nمعتمدة عندما يطلب اخصائي الحالة الموافقة على خطة الحالة\nووافق مشرف الحالات على خطة الحالة على المنصة.\n" + services_provided: + title: "8. الخدمات المقدَّمة" + service: "الخدمة" + count: "الأوقات المُقدَّمة" + male: "ذكر" + female: "أنثى" + 0-11: "0-11" + 12-17: "12-17" + '>18': ">18" + disability: "اعاقة " + no_disability: "لا وجود لاعاقة" + helptext: |+ + يحسب هذا المؤشر نوع الخدمة (الخدمات) المقدمة للناجين في عملية إدارة الحالة. + من خلال الخدمة المقدمة ، فإننا نعني الخدمة التي تقدمها منظمة المستخدم + داخليًا ، وليست خدمة مقدمة عن طريق الإحالات إلى خدمات أخرى أو إحالات داخلية + + average_referrals: + title: "9. متوسّط الإحالات" + label: "متوسط الإحالات لكلّ حالة" + helptext: |+ + يحسب هذا المؤشر متوسط عدد الإحالات لكل حالة مسجلة (لجميع الأنواع + من الخدمات) في جميع الحالات ، سواء كانت الحالة نشطة / مفتوحة أو مغلقة. يتضمن الإحالات + المسجلة في علامة تبويب الحالة ، وليس فقط الإحالات التي تتم من خلال النظام الأساسي + + referrals_per_service: + title: "الإحالات لكلّ خدمة" + average_followup_meetings_per_case: + title: "10. متوسط اجتماعات المتابعة لكل حالة" + label: "متوسط اجتماعات المتابعة لكل حالة" + helptext: | + يحتسب هذا المؤشر متوسط عدد اجتماعات المتابعة التي أجريت لكلّ حالة نشطة + من قبل كلّ اخصائي الحالة على المنصة. يتمّ اجتماع المتابعة بين اخصائي الحالة والناجية + بعد المقابلة الأوّليّة / الإفصاح الأولي. + time_from_case_open_to_close: + title: "11. الوقت المستغرق من فتح الحالة إلى اغلاقها" + time: "الوقت" + percent: "نسبة الحالات المئوية" + helptext: "يقيس هذا المؤشر المدة التي تظلّ فيها الحالات مفتوحة، والمدة التي تستغرقها عملية إدارة الحالة\nمن الإبلاغ الأوّلي لمنظمة المستخدم حتى إغلاق الحالة. \nيتمّ تقسيم المدة الزمنية حسب الإطار الزمني التالي: أقل من شهر واحد ؛ بين 1 و 3 أشهر ؛ \nبين3-6 أشهر ؛ أكثر من 6 أشهر.\n" + case_closure_rate: + title: "12. عداد إغلاق الحالات" + reporting_site: "موقع الإبلاغ" + helptext: "يقيس هذا المؤشر عدد الحالات التي يتمّ إغلاقها شهريًا في كلّ موقع إبلاغ.\nيُشير موقع الإبلاغ إلى الموقع الذي تقدم فيه منظمة المستخدم الخدمات \nو حيث تم الإبلاغ عن الحالة إلى مزود الخدمة.\n" + client_satisfaction_rate: + title: "13. معدل رضا العميل" + label: "رضا العميل" + invalid: "لا يمكننا حساب هذا في الوقت الحالي." + helptext: | + يقيس هذا المؤشر النسبة المئوية للناجين الذين أكملوا استبيان آراء العملاء + والذين يشعرون بالرضا عن خدمات إدارة الحالة المقدّمة لهم. + يتمّ إحتساب هذا المؤشر من خلال استكمال نموذج استبيان آراء العميل على +GBVIMS من قبل موظف + مختلف عن اخصائي الحالة الذي قدّم الخدمة للناجية. + supervisor_to_caseworker_ratio: + title: "14. عدد اخصائيين الحالة لكل مشرف." + label: "عدد اخصائيين الحالة لكلّ مشرف" + helptext: "يعكس هذا المؤشر عدد اخصائيين الحالة الذين يشرف عليهم مشرف الحالات: ويُعرف بعدد اخصائيين الحالة لكلّ مشرف. \nيعتمد هذا الحساب على الأدوار المخصّصة من النظام على المنصّة.\n" + case_load: + title: "15. عدد الحالات" + case_load: "عدد الحالات" + percent: "النسبة المئوية لاخصائيين الحالة العاملين على حالات" + 10cases: "أقل من 10 حالات" + 20cases: "11 - 20 حالة" + 21-30cases: "21 - 30 حالة" + 30cases: "أكثر من 30 حالة" + helptext: | + يقيس هذا المؤشر متوسط عدد الحالات لكلّ اخصائي الحالة فاعل بناءً على الحالات النشطة. + يتمّ تقسيم نسبة الحالات إلى اخصائيين الحالة وفقًا للتقسيم التالي: + أقلّ من 10 حالات مفتوحة ، بين 10-20 حالة مفتوحة ، بين 21-30 حالة مفتوحة أكثر من 30 حالة مفتوحة. + date_range_dialog: + title: "نطاق تاريخ مُخصّص" + description: "بمجرد تطبيق هذا التغيير، سيتمّ اختيار البيانات من بين التاريخين التاليين." + apply: 'تقديم طلب' + from: 'من' + to: 'إلى' + aria-labels: + from: "سيتم اختيار البيانات بعد هذا التاريخ" + to: "سيتم اختيار البيانات قبل هذا التاريخ" + location: + base_types: + camp: مخيم + chiefdom: مشيخة + city: مدينة + community: مجتمع محلي + country: دولة + county: مقاطعة + district: الحي + governorate: إمارة + locality: ناحية + other: أشياء أخرى + province: إقليم + region: منطقة + site: موقع + state: ولاية + sub-district: حي فرعي + village: قرية + zone: منطقة + association: منظمة + division: قسم + central_warehouse: المستودع المركزي + warehouse: مستودع + buyingstation: محطة شراء + township: بلدة + municipality: بلدية + autonomous_region: منطقة الحكم الذاتي + parish: الرعية + cercle: الدائرة + sub-county: المناطق + departement_fr: 'المقاطعات' + region_fr: 'المنطقة' + wilaya: 'ولاية' + commune: 'البلدة' + division_fr: 'القسم' + prefecture: 'المقاطعات' + moughataa: 'مقطعة' + sub_division: 'القسم الفرعي' + sub-prefecture: 'المقاطعات الفرعية ' + label: الموقع + name: الإسم + code: الكود + admin_level: مستوى المسؤول + type: النوع + hierarchy: التسلسل الهرمي + import_title: موقع الاستيراد + message: يرجى تحديد ملف CSV للتحميل. يجب أن يستخدم هذا الملف ترميز UTF-8 وأن يتضمن علامات تصنيف HXL في الرأسيّة الثانية من كلّ عمود. + no_location: يرجى استيراد المواقع قبل إنشاء أي حسابات مستخدمين. + enable_title: تفعيل الموقع + enable_text: هل أنت متأكد؟ إذا قمت بتفعيل المواقع المحددة ، فستظهر كخيارات في حقول الموقع + disable_title: تعطيل الموقع + disable_text: هل أنت متأكد؟ إذا قمت بتعطيل المواقع المحددة ، فلن تظهر كخيارات في حقول الموقع + logger: + actions: + _approved: تم الموافقة عليه + _rejected: رُفض + _requested: مطلوب + add_note: اضف ملاحظة + assign: تعيين + assign_to: يسند إلى + attach: يربط + bulk_assign: تعيين بالجملة + bulk_create: إنشاء مجمّع + bulk_index: فهرس بالجملة + case_plan_approved: تمت الموافقة على خطة الحالة + case_plan_rejected: تم رفض خطة الحالة + case_plan_requested: مطلوب خطة حالة + close: غلق + create: إنشاء + create_bulk: إنشاء الجزء الأكبر + delete: حذف + destroy: هدم + detach: فصل + enable_disable_record: تمكين تعطيل السجل + export: يصدر + flag: علامة + import: يستورد + incident_details_from_case: تفاصيل الحادث من القضية + index: فهرس + list: قائمة + login: تسجيل الدخول + password_reset: إعادة تعيين كلمة المرور + password_reset_request: طلب إعادة تعيين كلمة المرور + refer: إحالة + refer_accepted: تم قبول الإحالة + refer_done: تمت الإحالة + refer_rejected: إحالة مرفوضة + refer_revoke: إبطال الإحالة + refer_to: إحالة إلى + reopen: أعد فتح + services_section_from_case: قسم الخدمات من القضية + show: عرض + show_alerts: عرض التنبيهات + traces: آثار + transfer: تحويل + transfer_accepted: تم قبول التحويل + transfer_rejected: تم رفض التحويل + transfer_request: طلب تحويل + transfer_to: حول إلى + unflag: إزالة العلامة + update: تحديث + user_password_reset_request: طلب إعادة تعيين كلمة مرور المستخدم + webhook: الويب هوك + approve_form: + action_plan: استمارة خطّة العمل + bia: استمارة تقييم مصلحة الطفل الفضلى + case_plan: استمارة مخطط الحالة + closure: استمارة إغلاق الملف + 'false': رفض + gbv_closure: نموذج إغلاق العنف القائم على النوع الإجتماعي + 'true': موافقة + assessment_approved: "%{approval_label} تمتّ الموافقة عليه ل" + assessment_requested: "%{approval_label} مطلوب لأجل" + bulk_index: قائمة كاملة + by_user: من قبل المستخدم + case_plan_approved: "%{approval_label} تمتّ الموافقة عليه ل" + case_plan_requested: "%{approval_label} مطلوب ل" + close: اغلاق + closure_approved: "%{approval_label} تمتّ الموافقة عليه لـ" + closure_requested: "%{approval_label} مطلوب لـ" + consent_count: عدد الموافقات + copy: جاري النسخ + create: إنشاء + create_subform: جاري إنشاء الاستمارة الفرعية + destroy: جاري الحذف + edit: جاري التعديل + enable_disable_record: تفعيل/تعطيل + export: تصدير بيانات إلى + flag: وضع علامة + flag_records: وضع علامة + graph_data: عرض بيانات الرسم البياني + hide_name: + protect: إخفاء الاسم + view: إظهار الاسم + index: عرض السجلات + list: قائمة + login: تسجيل الدخول + logout: تسجيل الخروج + lookups_for_field: 'عمليات البحث عن البيانات ' + mark_for_mobile: + 'false': 'إزالة علامة الهاتف المحمول ' + 'true': وضع علامة الهاتف المحمول + match_record: سجلات متشابهة + permitted_field_list: قائمة المجال المسموح بها + quick_view: جاري عرض لمحة سريعة + reassign: جاري التعيين + resources: + audit_log: سجل التدقيق + user: المستعمل + agency: الوكالة + user_group: مجموعة المستخدمين + child: طفل + alert: تحذير + form_section: استمارة + lookup: ابحث عن + system_settings: اعدادات النظام + permission: الإذن + dashboard: لوحة المعلومات + report: تقرير + bulk_export: 'انشاء التقارير بالجملة ' + saved_search: عمليات البحث المحفوظة + role: دور + incident: حادث + location: موقع + primero_configuration: إعدادات Primero + code_of_conduct: 'قواعد السلوك ' + task: مهمة + record_state: + 'false': تعطيل + 'true': تشغيل + refer: قم بالإحالة + refer_to: ابحث عن متلقّي الإحالة + referral: جاري الإحالة + relinquish_referral: تم إرجاع ملف الإحالة + reopen: إعادة فتح + reopen_case: جاري إعادة الفتح + request_approval: + action_plan: طلب الموافقة على استمارة خطة العمل + bia: طلب مصادقة على استمارة تقييم مصلحة الطفل الفضلى + case_plan: طلب مصادقة على استمارة خطة معالجة الحالة + closure: طلب مصادقة على استمارة إغلاق الملف + gbv_closure: طلب الموافقة على استمارة إغلاق ملف العنف القائم على النوع الإجتماعي + request_transfer: جاري إرسال طلب التحويل + request_transfer_view: جاري عرض طلب التحويل + save_subform: جاري حفظ الاستمارة الفرعية + search: البحث عن واجهة برمجة التطبيقات + show: جاري العرض + show_alerts: عرض التنبيهات لـ + to: الى + to_user: للمستخدم + transfer: جاري التحويل + transfer_status: + Accepted: التحويل المقبول + Rejected: التحويل المرفوض + unflag: إزالة علامة + update: جاري التحديث + login: + label: تسجيل الدخول + password: + label: كلمة المرور + password_confirmation: + label: تأكيد كلمة المرور + password_match: + label: يجب أن تتطابق كلمة المرور + provider_title: مع %{provider} + title: تسجيل الدخول + username: اسم المستخدم + password_reset_modal: إعادة تعيين كلمة المرور + password_reset_modal_text: سيرسل بريميرو Primero رابط إعادة تعيين كلمة المرور إلى عنوان بريدك الإلكتروني + password_reset_email: البريد الإلكتروني + forgot_password: هل نسيت كلمة المرور؟ + email: + label: البريد الإلكتروني + lookup: + create: بحث جديد + enabled_label: مُفعل؟ + english_label: النص باللغة الإنجليزية + label: بحث + language_label: اللغة + messages: + cannot_create: لا يمكن إنشاء البحث + correct_errors: 'الرجاء تصحيح الأخطاء التالية وإعادة الإرسال:' + created: تم إنشاء البحث بنجاح + updated: تمّ تحديث البحث بنجاح + name: الاسم + no_options: لا يحتوي هذا البحث على خيارات حاليًّا. + translation_label: نص الترجمة + values: خيارات + locked_alert_message: عمليات البحث مقفلة + managed_reports: + generated_on: انشئت في + label: احصائيات البيانات + total: المجموع + violations_total: الانتهاكات + filter_by: + date: التاريخ + verification_status: وضع التحقق + violation_type: نوع الانتهاك + status: الوضع + status_open: 'مفتوح ' + status_closed: مغلق + user_group: مجموعة مستخدمين + agency: الهيئة + by: بواسطة + workflow: حالة العملية + cp_incident_violence_type: نوع العنف + referral_transfer_status: وضعية الإحالة / النقل + protection_concerns: مخاوف تتعلق بالحماية + location: مكان الإبلاغ + followup_type: نوع المتابعة + service_type: نوع الخدمة + status_options: + open: فتح + closed: اغلقت + by_options: + created_by_groups: مجموعات المستخدمين لمنشئ السجل + owned_by_groups: مجموعات المستخدمين لصاحب السجل + created_organization: هيئة من أنشأ السجل + owned_by_agency_id: هيئة صاحب السجل + referral_transfer_status_options: + in_progress: معلق + accepted: تمت الموافقة + rejected: رُفض + done: تم + date_range: + month: شهر + quarter: الثلاثي + year: سنة + week: أسبوع + date_range_options: + this_quarter: الثلاثي الحالي + last_quarter: الثلاثي الماضي + this_month: الشهر الحالي + last_month: الشهر الماضي + this_week: هذا الأسبوع + last_week: الاسبوع الماضي + this_year: العام الحالي + last_year: العام الماضي + custom: مخصّص + no_data: لا يوجد بيانات لانشاء الاحصائيات + no_data_table: لا يوجد جدول بيانات لانشاء الاحصائيات + incomplete_data: بيانات غير مكتملة + individual_children: + name: الأطفال الافراد + reports: + individual_children: الأطفال الافراد + sub_reports: + individual_age: الأطفال الافراد حسب العمر + individual_violation_type: الأطفال الافراد حسب نوع الانتهاك + individual_region: الأطفال الافراد حسب المنطقة + individual_perpetrator: عدد الاطفال حسب المسيئ + services: + name: الخدمات + description: الحالات التي تحتوي على أنواع الخدمة المحددة، مقسمة حسب العمر والجنس. + services_report: + reports: + services: خدمات + description: الحالات التي تحتوي على أنواع الخدمة المحددة، مقسمة حسب العمر والجنس. + sub_reports: + services: خدمات + filter_options: + service_implemented_day_time: 'اكتملت الخدمة ' + followups: + name: المتابعات + description: الحالات مع أنواع المتابعة المحددة، مقسمة حسب العمر والجنس. + followups_report: + filter_options: + followup_date: تاريخ المتابعة + reports: + followups: المتابعات + description: الحالات مع أنواع المتابعة المحددة، مقسمة حسب العمر والجنس. + sub_reports: + followups: المتابعات + protection_concerns: + name: مخاوف تتعلق بالحماية + description: الحالات المتعلقة بمخاوف الحماية المحددة، مقسمة حسب العمر والجنس. + protection_concerns_report: + reports: + protection_concerns: مخاوف تتعلق بالحماية + description: الحالات المتعلقة بمخاوف الحماية المحددة، مقسمة حسب العمر والجنس. + sub_reports: + protection_concerns: مخاوف تتعلق بالحماية + filter_options: + registration_date: تاريخ التسجيل + reporting_locations: + name: مكان الإبلاغ + description: 'الحالات التي تم تحديد موقع الإبلاغ عنها، مقسمة حسب العمر والجنس.' + reporting_locations_report: + reports: + reporting_locations: مكان الإبلاغ + sub_reports: + reporting_location_by_sex_and_age: مكان الإبلاغ + filter_options: + registration_date: تاريخ التسجيل + ghn_report: + name: المذكرة الافقية الشاملة + reports: + ghn_report: المذكرة الافقية الشاملة + sub_reports: + verified_information: معلومات تم التحقق منها - الضحايا + late_verification: التحقق المتأخر - الضحايا + unverified_information: معلومات لم يتم التحقق منها - الضحايا + verified_information_violations: معلومات تم التحقق منها - الانتهاكات + late_verification_violations: التحقق المتأخر - الانتهاكات + unverified_information_violations: معلومات لم يتم التحقق منها - الانتهاكات + killing: قتل الاطفال + maiming: تشويه الاطفال + recruitment: تجنيد و/او استخدام الاطفال + sexual_violence: الاغتصاب و / أو غيره من أشكال العنف الجنسي + rape: الاغتصاب و / أو غيره من أشكال العنف الجنسي + abduction: الخطف + attack_on_hospitals: الاعتداءات على مستوى المستشفى (المستشفيات) + attack_on_schools: الاعتدءات على مستوى المدرسة(المدارس) + military_use: الاستخدام العسكري للمدرسة(المدارس) و/او المستشفى(المستشفيات) + denial_humanitarian_access: منع وصول الخدمات الإنسانية للأطفال + multiple_violations: الأطفال المتضررون من انتهاكات متعددة + detention: احتجاز + boys: الأولاد + girls: الفتيات + total: المجموع + unknown: غير معروف + associated_violations: 'الانتهاكات ذات الصلة:' + violations: + name: الانتهاكات + filter_options: + incident_date: تاريخ الحادثة + date_of_report: تاريخ التقرير + ctfmr_verified_date: تاريخ التحقق + verified: تم التحقق منه + reports: + killing: قتل الاطفال + maiming: تشويه الاطفال + recruitment: تجنيد و/او استخدام الاطفال + sexual_violence: الاغتصاب و / أو غيره من أشكال العنف الجنسي + rape: الاغتصاب و / أو غيره من أشكال العنف الجنسي + abduction: الخطف + attack_on_hospitals: الاعتداءات على مستوى المستشفى (المستشفيات) + attack_on_schools: الاعتدءات على مستوى المدرسة(المدارس) + military_use: الاستخدام العسكري للمدرسة(المدارس) و/او المستشفى(المستشفيات) + denial_humanitarian_access: منع وصول الخدمات الإنسانية للأطفال + detention: احتجاز + sub_reports: + children: الأطفال + combined: الانتهاكات + denial_humanitarian_access: منع وصول الخدمات الانسانية + denial_type: انواع المنع + detention_detained: البقاء محتجزا + detention_released: الافراج + perpetrators: عدد الاطفال حسب المسيئين + perpetrators_denial: عدد الانتهاكات حسب المسيئين + perpetrator_detention: عدد الاطفال حسب المسيئين + perpetrators_incidents: عدد الحوادث حسب المسيئين + reporting_location_incidents: عدد الحوادث حسب المنطقة + reporting_location: عدد الاطفال حسب المنطقة + reporting_location_detention: عدد الاطفال حسب المنطقة + reporting_location_denial: عدد الاختراقات حسب المنطقة + attack_type: عدد الاطفال حسب نوع الاعتداء + boys: الأولاد + girls: الفتيات + unknown: غير معروف + total: المجموع + violation: الانتهاكات + sexual_violence_type: شكل (أشكال) العنف الجنسي + detention_status: وضع الأطفال المحتجزين + type_of_use: نوع الاستخدام + factors_of_recruitment: اسباب التجنيد + still_being_held: لا يزال محتجزا + released: 'افرج عنه' + escaped: 'هرب' + abduction_reasons: أسباب الاختطاف + abducted_status: حالة المخطوف + facility_attack_type: نوع الانتهاك + received_response: الأطفال الذين تلقوا استجابة + male: ذكر + female: أنثى + military_use_type_of_use: عدد الانتهاكات حسب النوعية + gbv_statistics: + name: 'احصاءات العنف القائم على النوع الاجتماعي ' + filter_options: + date_of_first_report: تاريخ المقابلة + incident_date: تاريخ الحادثة + reports: + perpetrators: المعتدين + survivors: الناجين + referrals: الإحالات + sub_reports: + service_safehouse_referral: إحالة البيت الآمن / المأوى الآمن + service_medical_referral: إحالة صحية / طبية + service_psycho_referral: خدمات الاستشارة النفسية / الاجتماعية + service_legal_referral: خدمات المساعدة القانونية + service_police_referral: الشرطة أو أي نوع آخر من خدمات الأمن + service_livelihoods_referral: خدمات الاعاشة + service_protection_referral: خدمات حماية الطفل + survivors_disability_type: مع اعاقات + workflow_report: + name: سير العمل + description: الحالات والحوادث مع وضعيات سير العمل المختارة، مقسمة حسب العمر والجنس. + reports: + cases_workflow: سير العمل - الحالات + incidents_workflow: سير العمل - الحوادث + filter_options: + registration_date: تاريخ التسجيل + sub_reports: + case_workflow_by_sex_and_age: إجمالي عدد الحالات حسب الجنس والعمر + incident_workflow_by_sex_and_age: إجمالي عدد الحوادث حسب الجنس والعمر + cases_workflow_report: + name: سير العمل + description: الحالات والحوادث مع أوضاع سير العمل المختارة، مقسمة حسب العمر والجنس. + reports: + cases_workflow: سير العمل - الحالات + filter_options: + registration_date: تاريخ التسجيل + sub_reports: + case_workflow_by_sex_and_age: إجمالي عدد الحالات حسب الجنس والعمر + referrals_transfers_report: + name: حالات الإحالة والنقل + description: 'حالات الإحالة والنقل التي حدثت خلال فترة زمنية محددة. مقسمة حسب الهيئات المرسلة والمستقبلة أو مجموعات المستخدمين. ' + reports: + total_referrals: الإحالات + total_transfers: عملية النقل + sub_reports: + total_transfers_by_user_groups: إجمالي عمليات النقل + total_referrals_by_user_groups: إجمالي عمليات الإحالة + filter_options: + registration_date: تاريج التسجيل + violence_type_report: + name: نوع العنف + reports: + cases_violence_type: نوع العنف- الحالات + incidents_violence_type: نوع العنف- الحوداث + filter_options: + registration_date: تاريخ التسجيل + sub_reports: + case_violence_type_by_sex_and_age: إجمالي عدد الحالات حسب الجنس والعمر + incident_violence_type_by_sex_and_age: إجمالي عدد الحوادث حسب الجنس والعمر + success_message: تمّ إنشاء ملف التصدير بنجاح + messages: + alert_items: لديك%{items} عناصر ملحوظة. + alerts_for: + approval: الموافقة قيد الانتظار ل %{form_section_name} + field_change: 'تمّ تحديث %{form_section_name} في %{alert_time}' + transfer_request: تمّ القيام بطلب تحويل في %{date}من قبل %{user} إلى %{agency} + duplicate_field: 'هذه الحالة %{field_name} مدخلة مسبقا يرجى العمل على ما يلي: + + + العودة للقائمة الرئيسية والبحث عن الحالة من خلال الرقم الوطني + + إضافة الحادثة الجديدة على الحالة المدخلة مسبقا واستكمال العمل على الحالة + + ابلاغ مدير النظام برقم الحالة الجديدة المكررة المدخلة من قبلكم لغاية تعطيلها' + cannot_edit: لا يمكن تعديله + confirmation_message: النقر فوق موافق لتجاهل أي تغييرات غير محفوظة والعودة إلى عرض القائمة. انقر فوق إلغاء للعودة إلى السجل. + confirmation_message_subform: النقر على موافق سيتجاهل أي تغييرات غير محفوظة والعودة إلى عرض القائمة. انقر فوق إلغاء لاكمال تحيين السجل. + dashboard_offline: أنت غير متصل بالإنترنت. ستعمل لوحة ملخص البيانات بكامل طاقتها عندما تعود إلى وضع الاتصال بالإنترنت + field_name_on_form_name: 'مجال "%{field_name}" في استمارة "%{form_name}"' + logout_confirmation: هل ترغب في متابعة استعمال النافذة المعلوماتية؟ + logout_offline_warning: هل أنت متأكد أنك تريد تسجيل الخروج؟ إذا قمت بذلك، لن تتمكن من تسجيل الدخول مرّة أخرى إلى أن تعاود الإتّصال بالإنترنت. ستفقد أي تغييرات أجريتها عندما لم تكن متّصلاً بالإنترنت. + logout_warning: سيتم تسجيل خروجك خلال 5 دقائق + logout_dialog_header: تسجيل الخروج في حالة انعدام الاتصال بالشبكة + logout_confirmation_title: تأكيد تسجيل الخروج + logout_confirmation_text: هل أنت متأكد أنك تريد تسجيل الخروج؟ + no_changes: لم تقم بأي تغييرات في المجال + not_available: غير متوفر + record_list: + column_header_tooltip: ترتيب ل%{column} + of: من + no_match: عذراً، لم يتم العثور على سجلات مطابقة + rows_per_page: عدد الأسطر في الصفحة الواحدة + sort: فرز + navigation: + bulk_exports: تصديرات + cases: حالات + home: الصفحة الرئيسية + key_performance_indicators: مؤشرات واحصائيات الأداء الرئيسة + incidents: حوادث + logout: تسجيل الخروج + reports: التقارير + insights: المؤشرات الاحصائية + search: بحث + settings: إعدادات + support: دعم + support_menu: + contact_information: معلومات الاتصال + code_of_conduct: مدونة قواعد السلوك + terms_of_use: شروط الاستخدام + system_information: نظام المعلومات + resync: التغييرات المراد احداثها التي لم يتم اعتمادها في وضع عدم الاتصال بالانترنت + tasks: المهام + tracing_request: طلبات التتبع + activity_log: سجل التغييرات + registry_records: السجل + families: العائلات + notes: + note_success: تمّت إضافة الملاحظة بنجاح + permissions: + label: صلاحيات + permission: + All: الكل + add_note: إضافة ملاحظات + admin_only: لا توجد سجلات - وظائف المشرف فقط + administrator_read: قراءات المشرف التقني + agency: الهيئة + agency_read: نافذة قراءات الهيئة + all: الوصول لجميع السجلات أو المستخدمين + approvals_assessment: '%{approval_label}' + approvals_assessment_pending: '%{approval_label} قيد الانتظار' + approvals_case_plan: '%{approval_label}' + approvals_case_plan_pending: '%{approval_label} معلّق' + approvals_closure: '%{approval_label}' + approvals_closure_pending: '%{approval_label} قيد الانتظار' + approve_action_plan: الموافقة على %{approval_label} + approve_assessment: الموافقة على الاستمارة%{approval_label} + approve_case_plan: الموافقة على %{approval_label} + approve_closure: الموافقة على الاستمارة%{approval_label} + approve_gbv_closure: الموافقة على الاستمارة%{approval_label} + assign: تعيين + assign_within_agency: تعيين ضمن الهيئة + assign_within_user_group: تعيين ضمن مجموعة المستخدمين + audit_log: سجل التدقيق + case: حالة + case_approvals: موافقات الحالة + case_assignments_referrals_transfers: عمليات تحويل وإحالة وتعيين الحالة + case_exports: تصديرات الحالة + case_overview: حالاتي + case_risk: تصنيف الحالات بحسب مستوى التقييم + cases_by_task_overdue_assessment: عرض الحالات حسب تقييم المهام المتأخرة + cases_by_task_overdue_case_plan: عرض الحالات حسب خطة حالة المهام المتأخرة + cases_by_task_overdue_followups: عرض الحالات حسب خدمات المهام المتأخرة + cases_by_task_overdue_services: عرض الحالات حسب خدمات المهام المتأخرة + cases_managed_other_users: الحالات التي يديرها مستخدمون آخرون + close: اغلاق + consent_override: تجاوز مرحلة الموافقة + copy: نسخ + copy_of: نسخة من + create: انشاء + dash_case_incident_overview: حالاتي/حوادثي + dash_cases_by_social_worker: عرض الحالات التي تولاها اخصائي الحالة + dash_cases_by_task_overdue: اطلاع على الحالات حسب المهام غير المنفذة + dash_cases_by_workflow: عرض الحالات حسب مخطط سير العمل + dash_cases_to_assign: عرض الحالات التي بانتظار التعيين + dash_group_overview: حالات مجموعتي + dash_manager_transfers: عرض عمليات النقل الخاصة بالمدير + dash_matching_results: عرض النتائج المتشابهة + dash_protection_concerns: عرض المخاوف المتعلقة بالحماية + dash_protection_concerns_by_location: عرض المخاوف المرتبطة بالحماية بحسب الموقع + dash_referrals_by_socal_worker: عرض الإحالات التي قام بها اخصائي الحالة + dash_reporting_location: عرض مواقع الإبلاغ + dash_service_provisions: عرض تقديم الخدمات + dash_shared_from_my_team: تمّ تشاركها من فريقي + dash_shared_with_me: 'تم مشاركتها معي ' + dash_shared_with_my_team: تمّ تشاركها مع فريقي + dash_shared_with_others: تمّ تشاركها مع آخرين + dash_show_none_values: عرض الخانات الفارغة + dash_tasks: عرض المهام + dash_transfers_by_socal_worker: عرض عمليات النقل التي قام بها اخصائي الحالة + dash_national_admin_summary: ملخص المشرف التقني + dashboard: لوحة التحكم + delete: حذف + display_view_page: إظهار صفحة العرض + duplicate: البحث عن المكررات + enable_disable_record: تعطيل + export_case_pdf: تصدير ملف الحالة في صيغة pdf + export_csv: تصدير ملف على صيغة csv + export_custom: تصدير ملف مخصص + export_duplicate_id_csv: تصدير السجلات المكررة + export_json: تصدير ملف json + export_list_view_csv: تصدير ملف عرض قائمة csv + export_mrm_violation_xls: تصدير ملف انتهاك آلية الرصد والإبلاغ mrm بصيغة xls + export_pdf: تصدير ملف في صيغة pdf + export_photowall: تصدير ملف photowall + export_unhcr_csv: تصدير ملف unhcr csv + export_xls: تصدير ملف xls + find_tracing_match: ايجاد تطابق التتبع للحالة + view_registry_record: عرض سجل التسجيل + add_registry_record: اضافة سجل التسجيل + family: العائلة + flag: تمييز بعلامة + form: استمارات + group: 'الوصول لجميع السجلات أو المستخدمين في مجموعتي ' + group_read: قراءة المجموعة + import: استيراد + incident: حادثة + incident_details_from_case: إضافة تفاصيل حادثة لحالة آخرى + incident_from_case: إنشاء حادثة من حالة + kpi: مؤشرات واحصائيات الأداء الرئيسة + lookup: عمليات البحث + manage: إدارة + mark_for_offline: وضع علامة لعدم الاتصال بالشبكة + matching_configuration: إعدادات مطابقة + metadata: الاستمارات، البحث + potential_match: تشابه محتمل + primero_configuration: إعدادات + read: قراءة + reassign: إعادة تعيين/نقل + receive_referral: تلقّي الإحالة + receive_transfer: استلام تحويل + referral: يمكن استخدامه للإحالة + referral_from_service: إحالة حالة من استمارة الخدمة + registry_record: السجل + remove_assigned_users: إزالة مستخدمين مخصصين آخرين (إحالات) + reopen: إعادة فتح + report: تقرير + managed_report: رؤى + resolve_any_flag: حل أي علامة + request_approval: طلب للموافقة + request_approval_action_plan: طلب موافقة %{approval_label} + request_approval_assessment: طلب موافقة %{approval_label} + request_approval_case_plan: طلب موافقة %{approval_label} + request_approval_closure: طلب موافقة %{approval_label} + request_approval_gbv_closure: طلب موافقة %{approval_label} + request_transfer: طلب تحويل + role: أدوار المستخدم + save_search: عمليات بحث محفوظة + saved_search: عملية بحث محفوظة + search_owned_by_others: ابحث عن سجلات الحالة المملوكة لمستخدمين آخرين + self: الوصول لسجلاتي أو المستخدم فقط + service_provision_incident_details: عرض زر إضافة تقديم خدمة على جزء عرض تفاصيل الحادثة + services_section_from_case: إضافة تقديم خدمة لحالة مستخدم آخر + specific_roles: الوصول لقائمة أدوار المستخدم المحددة + sync_external: المزامنة مع نظام إدارة معلومات خارجي + sync_mobile: وضع علامة على عدم الاتصال بالانترنت + system: نظام + tracing_request: طلب التتبع + transfer: يمكن استخدامها للتحويل + user: مستخدمون + user_group: مجموعات المستخدمين + verify_mrm: تحقق من MRM + view_approvals: عرض الموافقات + view_assessment: عرض التقييم + view_photo: عرض الصورة + view_protection_concerns_filter: عرض حسب المخاوف المتعلقة بالحماية + view_response: عرض الاستجابات + webhook: الويب هوك + workflow: سير العمل - الحالات الفردية + workflow_team: سير العمل - حالات الفريق/الفرق + write: كتابة + activity_log: سجل التغيير + remove_alert: إزالة تنبيه + resource: + kpi: + actions: + read: + explanation: القدرة على الوصول إلى صفحة النبض/مؤشرات الأداء الرئيسة. + label: الوصول إلى صفحة النبض/مؤشرات الأداء الرئيسة. + kpi_assessment_status: + explanation: القدرة على معرفة نسبة الذين يملكون نموذج تقييم مكتمل بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: وضع التقييم + kpi_average_followup_meetings_per_case: + explanation: القدرة على معرفة متوسط عدد إجتماعات المتابعة التي أجريت خلال فترة زمنية محددة بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: متوسط اجتماعات المتابعة لكل حالة + kpi_average_referrals: + explanation: القدرة على معرفة متوسط عدد الإحالات التي أجريت لكلّ نوع من الخدمات بالنسبة إلى كلّ الحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: متوسّط الإحالات + kpi_case_closure_rate: + explanation: القدرة على معرفة عدد الحالات التي أُغلقت شهريًا في كلّ موقع. + label: عدد إغلاق الحالات + kpi_case_load: + explanation: القدرة على معرفة متوسط عدد الحالات المفتوحة لكلّ اخصائي الحالة. + label: عدد الحالات + kpi_client_satisfaction_rate: + explanation: القدرة على معرفة معدّل الناجين الذين أكملوا استبان آراء العملاء وكانوا راضين بالنسبة إلى كلّ حالة يمكن للمستخدم الوصول إليها. + label: معدّل رضا العميل + kpi_completed_case_action_plans: + explanation: القدرة على معرفة نسبة الذين أكملوا خطة عمل الحالة بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: خطّة عمل حالة مكتملة + kpi_completed_case_safety_plans: + explanation: القدرة على معرفة النسبة المطلوبة وإكمال خطة الأمان، بالنسبة للحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: خطّة أمان الحالة المكتملة + kpi_completed_supervisor_approved_case_action_plans: + explanation: القدرة على معرفة نسبة الذين أكملوا خطة عمل الحالة وتمّ الموافقة عليها من قبل مشرف الحالات بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: تمّت الموافقة على خطط عمل الحالة المكتملة من قبل مشرف الحالات + kpi_goal_progress_per_need: + explanation: القدرة على معرفة النسبة المئوية للأهداف التي تم تحقيقها في كل فئة من فئات الاحتياجات بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: التقدّم المُحرز نحو الأهداف + kpi_number_of_cases: + explanation: القدرة على معرفة عدد الحالات الجديدة المبلَّغ عنها التي يتمّ فتحها شهريًا في كلّ موقع. + label: عدد الحالات + kpi_number_of_incidents: + explanation: القدرة على معرفة عدد الحوادث الجديدة المبلَّغ عنها التي يتمّ فتحها شهريًا في كلّ موقع. + label: عدد الحوادث + kpi_reporting_delay: + explanation: القدرة على معرفة عدد الأيام المنقضية بين وقت تعرّض الناجية للعنف القائم على النوع الاجتماعي ووقت إبلاغ الناجية بذلك لمقدم الخدمة، بالنسبة إلى كلّ الحوادث التي يمكن للمستخدم الوصول إليها. + label: الإبلاغ عن التأخير + kpi_services_provided: + explanation: 'القدرة على معرفة نوع الخدمات التي قدّمتها المنظمة داخليًّا لجميع الحالات التي يمكن للمستخدم الوصول إليها. ' + label: الخدمات المقدَّمة + kpi_supervisor_to_caseworker_ratio: + explanation: القدرة على معرفة متوسط عدد اخصائيين الحالة لكلّ مشرف. + label: عدد اخصائيين الحالة لكلّ مشرف. + kpi_time_from_case_open_to_close: + explanation: القدرة على معرفة مدّة الإبقاء على الحالة مفتوحة بالنسبة إلى كلّ الحالات التي يمكن للمستخدم الوصول إليها. + label: الوقت من فتح القضية إلى إغلاقها + label: مؤشّر الأداء الرئيس + agency: + actions: + assign: + explanation: القدرة على اختيار الهيئة عند إنشاء حساب مستخدم أو تعديله. إذا كان لدى المستخدم الحالي هذا الإذن بالإضافة إلى إذن "قراءة الهيئة" للمستخدمين، فسيكون بإمكانه فقط إضافة مستخدم إلى وكالته الخاصة. + label: تعيين + create: + explanation: القدرة على إنشاء هيئة + label: إنشاء + manage: + explanation: 'يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على الهيئات. إذن "الإدارة" يعني أساسًا "كل شيء". هام: يمنح هذا الإذن أيضًا القدرة على إنشاء الهيئة جديدة.' + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على رؤية الهيئات. + label: عرض + write: + explanation: القدرة على تعديل المعلومات حول الوكالات. يرجى الإنتباه إلى أن هذا الأمر ينطبق على جميع الوكالات في النظام. + label: تعديل + explanation: يمثل منظمة بها أعضاء يستخدمون بريميرو. توجد الهيئات بشكل مستقل عن مجموعات المستخدمين. + label: الهيئة + audit_log: + actions: + read: + explanation: يسمح للمستخدم بمشاهدة قائمة بجميع الإجراءات التي تم تنفيذها في النظام وتصفيتها، وتكون مقسّمة حسب المستخدم ونوع الإجراء ومُعرِّف السجل ووقت الإجراء. تُناسب هذه الخاصيّة المسؤولين على المستوى الوطني أو مستوى الهيئة ، لأنّها تعرض الإجراءات التي يقوم بها جميع المستخدمين في النظام. يرجى الإنتباه إلى أن سجل التدقيق لا يعرض معلومات التعريف الشخصية في السجلات المتضمنة في كل إجراء. + label: عرض + explanation: قائمة قابلة للتصفية لجميع الإجراءات التي تم تنفيذها في النظام. لا تتضمن أي معلومات تعريفية عن الحالات أو الحوادث أو طلبات البحث عن المفقودين. + label: سجل التدقيق + case: + actions: + add_note: + explanation: يسمح للمستخدم بإضافة مُدخَل إلى نموذج "الملاحظات" الفرعي (يُطلق عليه أحيانًا اسم "التعليقات"). يقوم المستخدم بذلك عن طريق النقر فوق زر "إضافة ملاحظات" في صفحة عرض الحالة. هذا الإجراء مفيد بشكل خاص للمديرين الذين ليس لديهم القدرة على تعديل الحالات، ولكنّهم يريدون إضافة تذكيرات عن حالة لاخصائي الحالة. بهذه الطريقة، يُشبِه إضافة ملاحظة إضافة علم. ميزة إضافة ملاحظة هي أنه عندما يضيف المدير ملاحظة إلى حالة ما، سيظهر إشعار على الحالة لاخصائي الحالة عندما يعرض الحالة على هاتفه الجوّال. + label: اضافة ملاحظات إلى حالة + add_registry_record: + explanation: يسمح للمستخدم بربط سجل بحالة من نموذج تفاصيل السجل. يسمح أيضًا للمستخدم بإلغاء ربط أي سجل مرتبط بالحالة اساسا. + label: إضافة / تحديث سجل التسجيل من الحالة + approve_action_plan: + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. + label: الموافقة على %{approval_label} + approve_assessment: + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. + label: الموافقة على نموذج %{approval_label} + approve_bia: + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. + label: الموافقة على نموذج %{approval_label} + approve_case_plan: + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. + label: الموافقة على %{approval_label} + approve_closure: + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. + label: الموافقة على نموذج %{approval_label} + approve_gbv_closure: + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. + label: الموافقة على نموذج %{approval_label} + assign: + explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الأصلي إلى أي مستخدم آخر في النظام. لا حاجة لموافقة الطفل لهذا الإجراء. على عكس عمليات التحويل لا يُمنح المستلِم الفرصة لقبول التعيين أو رفضه. + label: تعيين + assign_within_agency: + explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الأصلي إلى أي مستخدم آخر في هيئة المستخدم الحالية. لا حاجة لموافقة الطفل لهذا الإجراء. على عكس عمليات التحويل، لا يُمنح المستلِم الفرصة لقبول التعيين أو رفضه. + label: تعيين لمستخدم ضمن هيئتي + assign_within_user_group: + explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الأصلي إلى أي مستخدم آخر في مجموعات مستخدمي المستخدم الحالية. لا حاجة لموافقة الطفل لهذا الإجراء. على عكس عمليات التحويل، لا يُمنح المستلِم الفرصة لقبول التعيين أو رفضه + label: تعيين لمستخدم ضمن مجموعة المستخدمين الخاصة بي + change_log: + explanation: يمكن للمستخدم رؤية تاريخ التغييرات التي تم إجراؤها على السجل منذ إنشائه. ويتضمن القيم المسجلة لجميع الحقول. + label: تغيير السجل + close: + explanation: يسمح للمستخدم بتغيير وضع الحالة من مفتوح إلى مغلق. + label: اغلاق + consent_override: + explanation: يسمح للمستخدم بإجراء إحالة أو تحويل لحالة لم تقدّم الموافقة. + label: تجاوز عدم الموافقة عند الإحالة أو التحويل + create: + explanation: القدرة على إنشاء حالة + label: إنشاء + display_view_page: + explanation: إذا أجرى المستخدم بحثًا عن حالة ليس لديه إمكانية الوصول إليها، يسمح له هذا الإذن برؤية قسم صغير يحتوي على المعلومات الأساسية عن الحالة، حتى ولو لم يتمكن المستخدم من النقر فوق الحالة للاطلاع على جميع معلوماتها. الحقول التي تظهر في "عرض الأقسام" هي الحقول التي تمّ تشكيلها إلى "عرض في نموذج قصير". هذا القسم مفيد أيضًا للمستخدمين الذين يقومون بتتبع أفراد الأسرة وإعادة لمّ الشمل نظرًا لأن "عرض الأقسام" متاح للمستخدم لاستعماله عند مراجعة الحالات التي ظهرت على أنها "تطابقات محتملة" لطلب التتبّع. + label: إظهار صفحة العرض + enable_disable_record: + explanation: القدرة على تعطيل أو تفعيل حالة. لا تظهر الحالات "المعطلة" افتراضيًا في قائمة الحالات. يمكن للمستخدمين رؤية الحالات المعطلة في قائمة الحالات باستخدام عامل تصفية. نظرًا لأن بريميرو Primero لا يسمح للمستخدمين بحذف الحالات، قد يرغب المستخدم في تعطيل حالة كبديل. على سبيل المثال، إذا أنشأ المستخدم حالة عن طريق الخطأ، أو كانت الحالة تحتوي على بيانات سيئة، يتوجب على المستخدم تعطيلها. + label: تفعيل/تعطيل + export_case_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة الحالة أو صفحات عرض الحالة، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بحالة واحدة أو حالات متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. في ملف التصدير PDF ، يتم سرد المعلومات أولاً حسب الحالة، ثم يتمّ تنظيمها بعد ذلك حسب النموذج الذي تظهر عليه المعلومات. + label: تصدير ملف حالة pdf + export_csv: + explanation: 'يمكن للمستخدم إنشاء ملف تصدير CSV من قائمة الحالة أو صفحات عرض الحالة، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بحالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. ملاحظة: لا يعرض تصدير CSV الأحرف غير اللاتينية (مثل العربية والبنغالية) في صيغة قابلة للقراءة.' + label: تصدير CSV + export_custom: + explanation: يمكن للمستخدم إنشاء ملف تصدير XLS من قائمة الحالة أو صفحات عرض الحالة، والتي تحتوي على مجموعة مخصّصة من النماذج أو الحقول، بالنسبة إلى حالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. في هذا التصدير، يتمّ تمثيل كلّ نموذج في علامة التبويب الخاصة به داخل ملف XLS. يمكن للمستخدم اختيار النماذج أو الحقول التي يريد تضمينها في التصدير باستخدام قسم التصدير المخصّص. يرجى ملاحظة أنه لا يمكن للمستخدمين تضمين النماذج والحقول في التصدير إلا إذا كان لديهم بالفعل القدرة على رؤية تلك النماذج والحقول عند عرض حالة في التطبيق. + label: تصدير مخصص + export_duplicate_id_csv: + explanation: إنشاء تصدير CSV للحالات التي لها نفس حقل "الهوية الوطنية" (قد يكون لها تسمية مختلفة، اعتمادًا على الإعدادات). يتمّ تنفيذه فقط من صفحة قائمة الحالة. + label: تصدير التكرارات + export_json: + explanation: يمكن للمستخدم إنشاء ملف تصدير JSON من قائمة الحالة أو صفحات عرض الحالة، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ،والمرتبطة بحالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. يستخدم هذا التصدير بشكل أساسي من قبل الذين يرغبون في تصدير الحالات من نظام Primero الحالي ثم استيرادها إلى نظام Primero مختلف، أو إلى نظام إدارة معلومات آخر. تعتبر صيغة JSON قابلة للقراءة آليًا وغير عمليّة لمعظم المستخدمين. + label: تصدير JSON + export_list_view_csv: + explanation: يمكن للمستخدم إنشاء ملف تصدير CSV من صفحة قائمة الحالات التي تحتوي الحقول عينها التي تظهر لهذا المستخدم في قائمة الحالات. يتمّ تنفيذها فقط من صفحة قائمة الحالات. + label: تصدير ملف عرض قائمة csv + export_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة الحالة أو صفحات عرض الحالة ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ، لحالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. في ملف تصدير PDF ، يتم سرد المعلومات أولاً حسب الحالة ، ثم يتم تنظيمها بشكل أكبر حسب النموذج الذي تظهر عليه المعلومات. + label: تصدير ملف PDF + export_photowall: + explanation: تسمح للمستخدم بتصدير ملف من صفحة قائمة الحالة التي تحتوي على صور جميع الحالات المختارة. يستخدم هذا التصدير بشكل أساسي لأنشطة تتبّع أفراد الأسرة ولم شملها. يتمّ تنفيذها فقط من صفحة قائمة الحالة. + label: تصدير ملف photowall + export_unhcr_csv: + label: تصدير مفوضية الأمم المتحدة لشؤون اللاجئين CSV + explanation: لم تعد هذه الميزة قيد الاستخدام. + export_xls: + explanation: 'يمكن للمستخدم إنشاء ملف تصدير XLS من قائمة الحالة أو صفحات عرض الحالة، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بحالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. في هذا التصدير، يُمثّل كلّ نموذج في علامة التبويب الخاصة به داخل ملف XLS. ملاحظة: تعرض صيغة XLS الأحرف غير اللاتينية (مثل العربية والبنغالية) بصيغة قابلة للقراءة، بينما لا تعرض صيغة CSV هذا الأمر.' + label: تصدير EXCEL (ملف XLS) + find_tracing_match: + explanation: يستخدم هذا حصريًا في السياقات التي تتضمن أنشطة تتبّع الأسرة ولم شملها. سيرى المستخدمون الذين لديهم هذا الإذن زر "ايجاد تطابق تتبّع" في صفحة عرض الحالة. عندما ينقرون على هذا الزر، يدخلون إلى قائمة طلبات التتبع في النظام والتي قد تكون مطابقة لحالتهم. + label: ايجاد تطابق التتبع للحالة + flag: + explanation: القدرة على إضافة علم إلى حالة. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي أضافوها إلى إحدى الحالات. + label: تمييز بعلامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: حل إية علامات + import: + explanation: يسمح للمستخدم بإنشاء حالة واحدة جديدة أو أكثر من خلال استيرادها من ملف CSV أو Excel أو JSON. يجب أن يكون الملف المستورد مهيّأ *جدًّا* وخصوصًا حتى يتمّ استيراد المعلومات بشكل صحيح. يجب أن تكون هذه الوظيفة متاحة فقط للمستخدمين الإداريين ذوي المهارات التقنية المتقدّمة والمعرفة العميقة بكيفية تهيئة البيانات في Primero. يتمّ تنفيذها فقط من صفحة قائمة الحالة. + label: استيراد + incident_details_from_case: + explanation: القدرة على إضافة مُدخل في نموذج تفاصيل الحادثة الفرعي في حالة وجدتها في نتائج البحث، ولكن لا يمكنك الوصول إليها. يقوم المستخدم بتنفيذ هذا الإجراء من صفحة نتائج البحث عن طريق اختيار حالة واحدة أو أكثر، ثم تحديد "إضافة حادثة" من قائمة الإجراءات. ثم يعرض المستخدم قسمًا يحتوي على جميع الحقول في نموذج تفاصيل الحادثة الفرعي، حيث يمكنه إدخال معلومات حول الخدمة وإرسالها. نظرًا لأنه لا يمكن تنفيذ هذا الإجراء إلا من صفحة نتائج البحث، فمن المنطقي أن يمتلك الفرد هذا الإذن إذا كان لديه أيضًا إذن "البحث عن سجلات الحالة التي يملكها مستخدمون آخرون". + label: إضافة تفاصيل حادثة لحالة مستخدم آخر من صفحة نتائج البحث + incident_from_case: + explanation: يسمح هذا الإذن للمستخدم بالنقر فوق زر "إنشاء حادثة". يؤدي هذا إلى إنشاء حادثة قد تحتوي على بعض المعلومات المنسوخة من الحالة. بالنسبة إلى حالات العنف القائم على النوع الاجتماعي، يتواجد هذا الزر أعلى صفحة عرض الحالة ويتوافق مع المعلومات المتعلقة بالحالة ككلّ. في بعض سياقات تتبع الحوادث، يكون هذا الزر في نموذج "تفاصيل الحادثة" الفرعي. في هذه الحالة، قد يتم نسخ بعض المعلومات من نموذج تفاصيل الحادثة الفرعي حيث تم النقر فوق الزر ، وكذلك من الحالة ككلّ. بمعنى آخر، قد تحتوي الحادثة الجديدة الذي تمّ إنشاؤها على حقل "نوع العنف" من النموذج الفرعي لتفاصيل الحادثة الفردية، ولكن قد يحتوي أيضًا على عمر وجنس الحالة نفسها. لاحظ أن هذا الإذن يسمح أيضًا للمستخدم بمشاهدة رابط الحادثة الذي تمّ إنشاؤها. + label: إنشاء حادثة من حالة + remove_alert: + explanation: يسمح هذا الإذن للمستخدم بإزالة تنبيه من الحالة. يتم عادةً إنشاء التنبيهات عند تحرير حقل معين، كما هو الحال عند تحديث الملاحظات. تظهر التنبيهات عادة بنقطة صفراء بجوار الحالة. + label: إزالة التنبيه من حالة + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة للحالات. يعني إذْن "الإدارة" بشكل أساسي "كل شيء". + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على عرض حالة + label: عرض + receive_referral: + explanation: يسمح للمستخدم بتلقي الإحالة. سيظهر المستخدمون الذين لديهم هذا الإذن كمستلمين محتملين لإجراء إحالة، بينما لن يظهر المستخدمون الذين ليس لديهم هذا الإذن كمستلمين محتملين عندما يبحث شخص ما عن مستلم في قسم الإحالة. + label: تلقّي الإحالة + receive_referral_different_module: + explanation: يسمح للمستخدم بتلقي إحالة لسجل تم إنشاؤه في وحدة نمطية مختلفة من بريميرو. سيظهر المستخدمون الذين لديهم هذا الإذن كمستلمين محتملين لإجراء إحالة لهذا السجل ، بينما لن يظهر المستخدمون الذين ليس لديهم هذا الإذن كمستلمين محتملين عندما يبحث شخص ما عن مستلم في نموذج الإحالة. + label: تلقي الإحالة من مستخدم في وحدة بريميرو مختلفة + receive_transfer: + explanation: يسمح للمستخدم بتلقي التحويل. سيظهر المستخدمون الذين لديهم هذا الإذن كمستلمين محتملين لإجراء التحويل، بينما لن يظهر المستخدمون الذين ليس لديهم هذا الإذن كمستلمين محتملين عندما يبحث شخص ما عن مستلم في قسم التحويل. + label: استلام التحويل + referral: + explanation: يسمح لمستخدم بمنح مستخدم آخر حق الوصول المؤقت إلى حالة. سيتمكن مستلم الإحالة من تنفيذ الإجراءات نفسها في الحالة المُحالة كما لو أنّه ينفذها على حالاته الخاصة. عندما لا يعود المستلم بحاجة إلى الوصول إلى الحالة ، يمكنه النقر فوق زر "أكتمل" في النموذج الفرعي للإحالات والتحويلات، وسيفقد إمكانية الوصول إلى الحالة. لا يمكنك إحالة حالة إلّا لمستخدم يسمح له دوره بتلقّي الإحالات. + label: إحالة + referral_from_service: + explanation: يسمح للمستخدم برؤية زر "الإحالة" في نموذج الخدمات الفرعي. عندما ينقر المستخدم على هذا الزر، سيظهر قسم الإحالة مع تعطيل حقول نوع الخدمة والهيئة ومقدّم الخدمة والموقع، ولكن يتمّ ملؤها تلقائيًا بالمعلومات الخاصة بهذه الحقول في نموذج الخدمات الفرعي الذي نقر المستخدم على زر الإحالة المرتبط به. + label: إحالة حالة من نموذج الخدمة الفرعي + remove_assigned_users: + explanation: يسمح للمستخدم بإزالة المستخدمين الآخرين من حقل "المستخدمون الآخرون المعيّنون". يتمّ إدراج المستخدم هنا إذا تلقى إحالة أو تحويل للحالة ولكنّه لم يقبلها أو يرفضها بعد. عندما تقوم بإزالة مستخدم من حقل "المستخدمون الآخرون المعيّنون"، فإنك تزيل إمكانية وصولهم إلى الحالة. وبالتالي، يمكن للمستخدمين الذين لديهم هذا الإذن إزالة إمكانية الوصول إلى الحالة من المستخدمين الذين سبق لهم وتلقوا إحالات أو عمليات نحويل معلّقة للحالة. لاحظ أنّ هذا الإذن لا يعمل إلا إذا كان المستخدم الحالي لديه أيضًا القدرة على تعديل الحالة. + label: إزالة المستخدمين المعيّنين الآخرين (استعادة الوصول إلى الحالة من المستخدمين المُحال إليهم) + reopen: + explanation: يسمح للمستخدم بفتح حالة مغلقة حاليًّا + label: إعادة فتح + request_approval_action_plan: + explanation: يسمح للمستخدم (عادة ما يكون إخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. + label: طلب موافقة %{approval_label} + request_approval_assessment: + explanation: يسمح للمستخدم (عادة ما يكون اخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. + label: طلب موافقة %{approval_label} + request_approval_bia: + explanation: يسمح للمستخدم (عادة ما يكون اخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. + label: طلب موافقة %{approval_label} + request_approval_case_plan: + explanation: يسمح للمستخدم (عادة ما يكون اخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. + label: طلب موافقة %{approval_label} + request_approval_closure: + explanation: يسمح للمستخدم (عادة ما يكون اخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. + label: طلب موافقة %{approval_label} + request_approval_gbv_closure: + explanation: يسمح للمستخدم (عادة ما يكون اخصائي حالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. + label: طلب موافقة %{approval_label} + request_transfer: + explanation: يكشف عن زر "طلب التحويل" الموجود على "عرض القسم". يسمح الزر للمستخدم بإرسال رسالة مع ملاحظة شخصية عبر البريد الإلكتروني إلى مالك سجل الحالة الحالي، يطلب من مالك السجل تحويل الحالة إلى المستخدم الذي أرسل الطلب. يُعدّ هذا مفيدًا في السياقات التي يغيّر فيها الأطفال المواقع كثيرًا، ويحتاج اخصائيين الحالة إلى اخصائيين الحالة السابقين الذين عملوا مع الطفل لإرسال معلومات حول الطفل لتجنب إنشاء سجل مكرّر. + label: طلب تحويل + search_owned_by_others: + explanation: يسمح لمستخدم بإجراء بحث عن السجلات التي عادة لا يملك إمكانية الوصول إليها، إما لأنه ليس مالك سجل هذه الحالة، أو (للمديرين) لأن مالك السجل ليس ضمن مجموعات المستخدمين الخاصة بهم. لاحظ أنه في حين سيرى المستخدم الحالة من ضمن عرض نتائج البحث، لن يتمكن من النقر فوق صفحة عرض الحالة لهذه الحالة، ممّا يعني أنّه لن يتمكّن من رؤية أي معلومات تفصيلية حول الحالة. + label: البحث عن سجلات الحالة المملوكة من مستخدم آخر + service_provision_incident_details: + explanation: يسمح للمستخدم برؤية الزر المسمى "حفظ وإضافة تقديم الخدمة" في الجزء السفلي من قسم إضافة الحادثة. يؤدي النقر فوق هذا الزر إلى حفظ المعلومات التي تم إدخالها حاليًا حول الحادثة، ثم ينقل المستخدم مباشرةً إلى قسم إضافة تقديم الخدمة. نظرًا لأن هذا الإجراء مرتبط ارتباطًا مباشرًا بإجراءات إضافة حادثة وإضافة تقديم خدمة، فمن المنطقي فقط منح هذا الإذن إلى فرد يسمح له دوره ولديه الإذن لـ "إضافة تفاصيل الحادثة إلى حالة مستخدم آخر" و "إضافة تقديم الخدمة إلى حالة مستخدم آخر." + label: عرض زر إضافة تقديم خدمة على قسم تفاصيل الحادثة + services_section_from_case: + explanation: القدرة على إضافة مُدخل في نموذج الخدمات الفرعي إلى حالة وجدتها في نتائج البحث، ولكن لا يمكنك الوصول إليها. يقوم المستخدم بتنفيذ هذا الإجراء من صفحة نتائج البحث عن طريق اختيار حالة واحدة أو أكثر، ثم اختيار "إضافة تقديم خدمات" من قائمة الإجراءات. ثم يستعرض المستخدم قسمًا يحتوي على جميع الحقول في نموذج الخدمات الفرعي، حيث يمكنه إدخال معلومات حول خدمة ما وإرسالها. نظرًا لأنه لا يمكن تنفيذ هذا الإجراء إلا من صفحة نتائج البحث، فمن المنطقي أن يمتلك الفرد هذا الإذن إذا كان لديه أيضًا إذن "البحث عن سجلات الحالة التي يملكها مستخدمون آخرون". + label: إضافة تقديم خدمة لحالة مستخدم آخر + sync_external: + explanation: القدرة على مزامنة سجلّ مع نظام إدارة معلومات خارجي + label: المزامنة مع نظام إدارة معلومات خارجي + sync_mobile: + explanation: يسمح للمستخدم بالتخزين المؤقت للحالات للاستخدام في وضع عدم الاتصال. + label: وضع علامة على عدم الاتصال بالانترنت + transfer: + explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الحالي إلى أي مستخدم في النظام مع إمكانية تلقّي عمليات التحويل. لا يتغير مالك سجل الحالة حتى "يقبل" مستلِم التحويل هذا التحويل. ولكن، إذا "رفض" المستلِم التحويل، يفقد بذلك إمكانية الوصول إلى الحالة، وتبقى الحالة بإسم مالك السجل الأصلي. + label: تحويل + view_photo: + explanation: يسمح للمستخدم بمشاهدة صور الحالة من عرض قائمة الحالة. بدون هذا الإذن، لا يرى المستخدم عمود "الصور" في جدول قائمة الحالات، ولا يرى أيضًا رموز الصور التي تظهر هناك. يسمح هذا الإذن أيضًا للمستخدم بمشاهدة صور الطفل في "عرض القسم". + label: مشاهدة الصور من عرض قائمة الحالة + view_incident_from_case: + explanation: '"عند عرض الحالة، يمكن للمستخدم الاطلاع على قائمة بالحوادث المرتبطة بالحالة، بالإضافة إلى بعض المعلومات الموجزة حول كلّ منها.' + label: عرض الحوادث من حالة + view_protection_concerns_filter: + explanation: يسمح للمستخدم برؤية مرشح مشاكل الحمايةفي صفحة قائمة الحالات. + label: عرض مرشح مشاكل الحماية في صفحة قائمة الحالات. + view_registry_record: + explanation: يسمح للمستخدم بعرض معلومات أي سجل مرتبط بحالة. يسمح أيضًا للمستخدم بمشاهدة نموذج تفاصيل السجل على الحالة. + label: عرض سجل التسجيل من الحالة + write: + explanation: القدرة على نقر زر "تعديل" وتحديث المعلومات في الحالة ثم النقر على "حفظ" + label: تعديل + accept_or_reject_transfer: + explanation: السماح للمستخدم بقبول أو رفض النقل نيابة عن مستخدم آخر موجود في فريقك (على سبيل المثال ، يقبل مشرف الحالات نقل تم إرساله إلى اخصائي الحالة). + label: قبول أو رفض النقل لمستخدم آخر في فريقك. + list_case_names: + explanation: 'لا يمكن للمديرين عادةً رؤية أسماء الحالات في قائمة الحالات. إذا حصل المدير على هذا الإذن ، فسيكون قادرًا على رؤية الأسماء في القائمة. ' + label: إذا كان المدير ، يمكنه رؤية أسماء الحالات في قائمة الحالة. + mark_for_offline: + explanation: يسمح للمستخدم بالتخزين المؤقت للحالة للاستخدام في وضع عدم الاتصال. + label: وضع علامة على عدم الاتصال بالانترنت + view_family_record: + explanation: يمكن للمستخدمين عرض نموذج "سجل العائلة" الخاص بالحالة، والذي يتضمن رابطًا لسجل عائلة الحالة. + label: عرض سجل العائلة من الحالة + case_from_family: + explanation: يمكن للمستخدمين إنشاء حالة لأحد أفراد عائلة الحالة في النموذج الفرعي "تفاصيل العائلة". لاحظ أنه سيتم إنشاء سجل العائلة تلقائيًا لربط هاتين الحالتين. + label: إنشاء حالة من تفاصيل العائلة + link_family_record: + explanation: يسمح للمستخدم بالبحث عن سجل العائلة الموجود وربطه بحالته. كما يسمح للمستخدمين بإلغاء ربط سجل العائلة من الحالة. + label: ربط / إلغاء ربط سجل العائلة من الحالة + explanation: يمثل طفلاً فرديًا أو ناجٍ أو مستفيد آخر. + label: حالة + dashboard: + actions: + approvals_action_plan: + explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على خطة العمل المعلّقة أو الموافق عليها أو المرفوضة. + label: موافقات اخصائي الحالة %{approval_label} + approvals_action_plan_pending: + explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على خطة العمل المعلّقة. + label: موافقات المدير %{approval_label} + approvals_assessment: + explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على التقييم المعلّقة أو الموافق عليها أو المرفوضة. + label: موافقات اخصائي الحالة %{approval_label} + approvals_assessment_pending: + explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على التقييم المعلّقة. + label: موافقات المدير %{approval_label} + approvals_case_plan: + explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على خطة الحالة المعلّقة أو الموافق عليها أو المرفوضة. + label: موافقات اخصائي الحالة %{approval_label} + approvals_case_plan_pending: + explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على خطة الحالة المعلّقة. + label: موافقات المدير %{approval_label} + approvals_closure: + explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على الإغلاق المعلّقة أو الموافق عليها أو المرفوضة. + label: موافقات اخصائي الحالة %{approval_label} + approvals_closure_pending: + explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على الإغلاق المعلّقة. + label: موافقات المدير %{approval_label} + approvals_gbv_closure: + explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على إغلاق العنف القائم على النوع الإجتماعي المعلّقة أو الموافق عليها أو المرفوضة. + label: موافقات اخصائي الحالة %{approval_label} + approvals_gbv_closure_pending: + explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على إغلاق العنف القائم على النوع الإجتماعي المعلّقة. + label: موافقات المدير %{approval_label} + case_overview: + explanation: نظرة عامة على بطاقة لوحة المعلومات الموجودة في أعلى الصفحة الرئيسية، والتي تتضمن أرقامًا مثل عدد الحالات الإجمالي والحالات الجديدة + label: نظرة عامّة على لوحة المعلومات + case_risk: + explanation: يظهر عدد الحالات في كلّ مستوى خطر. + label: الحالات حسب مستوى الخطر + cases_by_task_overdue_assessment: + explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام التقييم لكلّ من اخصائيين الحالة. + label: مهام التقييم المتأخرة + cases_by_task_overdue_case_plan: + explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام خطة الحالة لكلّ من اخصائيين الحالة. + label: مهام خطة الحالة المتأخرة + cases_by_task_overdue_followups: + explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام المتابعة لكلّ من اخصائيين الحالة. + label: مهام المتابعة المتأخرة + cases_by_task_overdue_services: + explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام الخدمات لكلّ من اخصائيين الحالة. + label: مهام الخدمات المتأخرة + dash_case_incident_overview: + explanation: يُظهر للمدير عدد الحالات التي يديرها كل مستخدم في فريقه، والتي تتم إحالتها أو نقلها إلى مستخدمين آخرين. + label: لمحة عامّة - حالاتي/حوادثي + dash_cases_by_social_worker: + explanation: الجدول الذي يوضح كيفية إدارة العدد الإجمالي للحالات المفتوحة وعدد الحالات الجديدة التي يديرها كل مستخدم في مجموعات المستخدمين الحالية للمستخدم. يمثّل كل صف مستخدمًا من مجموعات المستخدمين الخاصة بالمستخدم الحالي ، بينما يمثل "الإجمالي" و "الجديد" عمودين. + label: عرض الحالات حسب اخصائي الحالة + dash_cases_to_assign: + explanation: 'هام: للمديرين فقط. يعرض عدد الحالات التي يمتلكها المستخدم الحالي بشكل مباشر (يجب أن يكون مديرًا). تفترض لوحة المعلومات هذه أن المديرين لا يديرون حالاتهم الخاصة، وأنه إذا كان للمدير حالاته الخاصة، يجب عليه تعيين هذه الحالات لاخصائيين الحالة في فريقه.' + label: (للمديرين) الحالات التي أحتاج إلى تعيينها لأشخاص في فريقي + dash_flags: + explanation: يعرض قائمة بالعلامات التي أضافها المستخدمون الآخرون إلى سجلاتي، بالإضافة إلى العلامات التي أضفتها إلى سجلات المستخدمين الآخرين. + label: السجلات المميّزة بعلامة + dash_group_overview: + explanation: يعرض للمدير عدد الحالات المفتوحة والمغلقة التي يديرها المستخدمون في فريقه. + label: حالات مجموعتي + dash_matching_results: + explanation: مهترئ. لوحة المعلومات هذه غير وظيفية وستتم إزالتها في الإصدار 2. + label: عرض النتائج المتطابقة + dash_protection_concerns: + explanation: الجدول الذي يوضح عدد الحالات التي لديها مخاوف تتعلّق بالحماية. يمثل كلّ سطر في الجدول إحدى المخاوف المتعلقة بالحماية، بينما تشير الأعمدة إلى أوضاع مختلفة للحالات ("كلّ الحالات"، "الحالات المفتوحة"، "الجديدة (هذا الأسبوع)"، "المغلقة (هذا الأسبوع)") + label: الحالات حسب مشاكل/قضايا الحماية + dash_protection_concerns_by_location: + explanation: يشبه لوحة معلومات "عرض المخاوف المتعلّقة بالحماية"، باستثناء أنه يمكن للمستخدم اختيار موقع من القائمة المنسدلة لإظهار إحصائيات حول انتشار المخاوف المتعلّقة بالحماية في هذا الموقع فقط. + label: عرض المخاوف المرتبطة بالحماية بحسب الموقع + dash_reporting_location: + explanation: الجدول الذي يوضح عدد الحالات الموجودة في كلّ موقع (على مستوى واحد من المحلّة مثل "مقاطعة" أو "منطقة"). كلّ سطر في الجدول عبارة عن موقع، بينما تشير الأعمدة إلى أوضاع مختلفة للحالات ("الحالات المفتوحة"، "الجديدة (الأسبوع المنصرم)"، "الجديدة (هذا الأسبوع)، "المغلقة (الأسبوع المنصرم)"، "المغلقة (هذا الأسبوع)"). تستخدم عادة لحسابات المدير أو المسؤول. + label: الحالات حسب موقع الإبلاغ + dash_service_provisions: + explanation: يعرض عدد الحالات التي قام فيها مستخدمون آخرون بإضافة تقديم خدمة لها. يظهر هذا الرقم في القسم الرئيس من لوحة المعلومات. + label: الحالات حسب تقديم الخدمة + dash_shared_from_my_team: + explanation: يعرض للمدير عدد الحالات التي يديرها كلّ مستخدم في فريقه والتي تمّ تحويلها أو إحالتها إلى مستخدمين آخرين. + label: تمّ تشاركها من فريقي + dash_shared_with_me: + explanation: يظهر عدد الحالات التي تمّ تحويلها أو إحالتها إليك. + label: 'تم مشاركتها معي ' + dash_shared_with_my_team: + explanation: يعرض للمدير عدد الحالات التي تمّ تحويلها أو إحالتها إلى كلّ مستخدم في فريقه. + label: تمّ تشاركها مع فريقي + dash_shared_with_my_team_overview: + explanation: يُظهر للمدير عدد الحالات المُحالة أو المنقولة إلى كل مستخدم في فريقه. + label: تم مشاركته مع فريقي (نظرة عامة) + dash_shared_with_others: + explanation: يوضح عدد حالاتي التي تحتوي على إحالات نشطة أو عمليات تحويل معلّقة أو مرفوضة. لا تُستخدم عادةً من قبل المديرين، إلّا إذا كانوا يديرون القضايا بأنفسهم. + label: تمّ تشاركها مع آخرين + dash_violations_category_verification_status: + explanation: 'يُظهر عدد انتهاكات MRM من كل نوع والتي تم تصنيفها حسب وضع التحقق ' + label: MRM - عدد الانتهاكات لكل حالة تحقق + dash_violations_category_region: + explanation: يوضح عدد انتهاكات MRM التي حدثت في كل منطقة ، مقسمة حسب نوع الانتهاك. + label: MRM - عدد الانتهاكات لكل منطقة + dash_perpetrator_armed_force_group_party_names: + explanation: يُظهر عدد انتهاكات MRM من كل نوع والتي تم تصنيفها حسب المسيء + label: MRM - عدد الانتهاكات حسب المسيء + dash_show_none_values: + explanation: يضيف فئة "لا مستوى خطورة" إضافية لجميع لوحات المعلومات التي تقسّم الحالات حسب مستوى الخطورة. ينطبق هذا على وجه التحديد على الإعدادات التي لديها خيار رابع "لا مخاطر" لحقول مستوى الخطورة. + label: عرض الحالات مع "لا مستوى خطورة" في لوحة معلومات التقييم + dash_tasks: + explanation: يسمح للمستخدم برؤية صفحة المهام. يجب أن تُستخدم لاخصائيين الحالة ومقدمي الخدمات، حيث ستكون الأرقام مخصّصة للحالات التي تديرها مباشرة. يجب على المديرين بدلاً من ذلك الحصول على لوحة المعلومات المرتبطة بـ "عرض الحالات حسب المهمة المتأخرة" ، لأن هذا يتيح لهم رؤية المهام المتأخرة لكلّ شخص في مجموعات المستخدمين الخاصة بهم. + label: صفحة المهام + dash_national_admin_summary: + explanation: يظهر إجمالي الحالات المفتوحة في النظام ، وعدد الحالات الجديدة التي تم إنشاؤها في كل من الأسبوعين الماضيين ، وعدد الحالات التي تم إغلاقها في كل من الأسبوعين الماضيين. + label: ملخص المسؤول + view_response: + explanation: لكلّ نوع من أنواع الاستجابة، يوضح عدد الحالات في كل مستوى من مستويات الخطورة التي لديها خدمات على وشك الإنتهاء أو متأخّرة. + label: عرض الاستجابات + workflow: + explanation: يسمح لإخصائي الحالة برؤية رسم بياني دائري يوضح عدد الحالات الخاصة به والموجودة في كلّ مرحلة من مراحل سير عمل إدارة الحالة. + label: الحالات مقسّمة حسب سريان العمل + workflow_team: + explanation: 'يسمح للمدير برؤية جدول يوضح عدد حالات اختصاصيين الحالة في كلّ مرحلة من مراحل عملية إدارة الحالة. ' + label: الحالات حسب سير العمل واخصائي الحالة + explanation: تملي المعلومات الموجزة التي تظهر على الصفحة الرئيسية. + label: لوحة المعلومات + disabled: + explanation: إذا قمت بتعطيل هذا الدور، لن تتمكن من تعيينه إلى حسابات المستخدمين. + label: 'مُعطلة ' + referral_authorization: + explanation: ويعني أن الدور سيظهر كخيار للقائمة المنسدلة "نوع الإحالة" عندما يقوم المستخدم بإجراء إحالة داخلية. إذا اختار المستخدم هذا الدور كنوع الإحالة، فلن يتمكن متلقي الإحالة من الوصول إلا إلى النماذج التي يمكن للدور المحدد الوصول إليها. لذا، على سبيل المثال، إذا اختار المستخدم "مقدم الخدمة الطبية" كنوع الإحالة، وكان لدور مقدم الخدمة الطبية حق الوصول فقط إلى نماذج الهوية الأساسية ومخاوف الحماية، فلن يرى المستلم سوى هذه النماذج. + label: هل يمكن استخدام هذا الدور في القائمة المنسدلة "نوع الإحالة"؟ + duplicate: + actions: + read: + explanation: يسمح للمستخدم بإجراء بحث متقدّم لكلّ الحالات في النظام، باستخدام عدد من المعايير، بما في ذلك الاسم واللقب والجنس والعمر والجنسية. + label: عرض + explanation: بحث متقدم لدور المديرين في النظام. + label: بحث مكرر + forms: + case: + explanation: 'يقيّد وصول المستخدم إلى نماذج الحالات ويحدّ من المعلومات التي يمكن للمستخدم رؤيتها في الحادثة. مثلاً، إذا كان للمستخدم حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج فقط. إذا كان المستخدم الحالي لديه وصول محدود إلى النموذج ولديه القدرة على إدارة إعدادات النموذج، فإن تقييد وصوله إلى النموذج يحدّ أيضًا النماذج التي يمكنه تضبيطها. ملاحظة: إذا لم يتمّ تحديد أي نموذج، فهذا يعني أنّ الدور لديه حق الوصول إلى جميع نماذج الحالات.' + label: نماذج - حالة + incident: + explanation: 'تقييد وصول المستخدم إلى النماذج الخاصة بالحوادث يحد من المعلومات التي يمكن للمستخدم رؤيتها في الحادث. على سبيل المثال ، إذا كان المستخدم لديه حق الوصول إلى نموذج مالك السجل فقط ، فسيكون أيضًا قادرًا فقط على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج. إذا كان لدى المستخدم الحالي وصول محدود إلى النموذج ولديه القدرة على إدارة إعدادات النموذج ، فإن تقييد وصوله إلى النموذج يحد أيضًا من النماذج التي يمكنه تكوينها. ملاحظة: إذا لم يتم تحديد أي نماذج ، فهذا يعني أن الدور لديه حق الوصول إلى جميع نماذج الحوادث.' + label: نماذج - حوادث + tracing_request: + explanation: 'يقيّد وصول المستخدم إلى النماذج في طلبات التتبّع ويحدّ من المعلومات التي يمكن للمستخدم رؤيتها في طلب التتبّع. مثلاً، إذا كان للمستخدم حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج فقط. إذا كان المستخدم الحالي لديه وصول محدود إلى النموذج ولديه القدرة على إدارة إعدادات النموذج، فإن تقييد وصوله إلى النموذج يحدّ أيضًا النماذج التي يمكنه إعدادها. ملاحظة: إذا لم يتمّ تحديد أي نموذج، فهذا يعني أنّ الدور لديه حق الوصول إلى جميع النماذج لطلبات التتبّع.' + label: النماذج - طلبات التتبع + registry_record: + explanation: 'تقييد وصول المستخدم إلى النماذج الموجودة في السجلات يحد من المعلومات التي يمكن للمستخدم رؤيتها في السجل. على سبيل المثال ، إذا كان المستخدم لديه حق الوصول إلى نموذج مالك السجل فقط ، فسيكون أيضًا قادرًا فقط على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج. إذا كان لدى المستخدم الحالي وصول محدود إلى النموذج ولديه القدرة على إدارة إعدادات النموذج ، فإن تقييد وصوله إلى النموذج يحد أيضًا من النماذج التي يمكنه إعدادها. ملاحظة: إذا لم يتم تحديد أي نماذج ، فهذا يعني أن الدور له حق الوصول إلى جميع نماذج السجلات.' + label: النماذج - التسجيل + family: + label: النماذج - العائلة + explanation: 'يؤدي تقييد وصول المستخدم إلى نماذج العائلات إلى تحديد المعلومات التي يمكن للمستخدم رؤيتها حول العائلة. على سبيل المثال، إذا كان المستخدم لديه حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الموجودة في الحقول الموجودة في هذا النموذج فقط. إذا كان لدى المستخدم الحالي وصول محدود إلى النموذج ولديه القدرة على إدارة إعداد النموذج، فإن تقييد وصوله إلى النموذج يحد أيضًا من النماذج التي يمكنه تكوينها.' + group: + actions: + admin_only: + explanation: هذا يعني أنّ المستخدمين الذين يؤدّون هذا الدور لن يتمكنوا إلا من رؤية الأمور المتعلّقة بإدارة النظام، مثل التقارير، وإعداد النموذج والبحث، والمستخدمين، والأدوار، ومجموعات المستخدمين. لن يروا أي حالات فردية أو طلبات تتبّع أو حوادث. + label: لا توجد سجلات - وظائف المسؤول فقط + agency: + explanation: يمكن للدور الوصول إلى السجلات التي يديرها جميع المستخدمين في هيئاتهم. إذا كان للمستخدم الحق في الوصول إلى المستخدمين، يمكنه الوصول إلى جميع المستخدمين في هيئته. + label: كلّ السجلات أو المستخدمين في هيئتي + all: + explanation: يمكن للدور الوصول إلى جميع السجلات والمستخدمين ومجموعات المستخدمين في النظام، بغض النظر عن مجموعات المستخدمين التي ينتمون هم إليها. + label: الوصول لجميع السجلات أو المستخدمين + group: + explanation: يمكن للدور الوصول إلى السجلات التي يديرها جميع المستخدمين في مجموعات المستخدمين الخاصّة بهم. لا يمكنهم الوصول إلّا إلى المستخدمين في مجموعات المستخدمين الخاصة بهم. يمكنهم فقط الوصول إلى مجموعات المستخدمين الخاصة بهم. + label: 'الوصول إلى جميع السجلات أو المستخدمين في مجموعتي ' + self: + explanation: يمكن للدور الوصول إلى السجلات الخاصة بهم (الحالات أو طلبات التتبّع أو الحوادث)، ويمكنه تعديل حساب المستخدم الخاص به. + label: الوصول لسجلاتي أو المستخدم الخاص بي فقط + explanation: يتحكّم في السجلات (الحالات أو طلبات التتبّع أو الحوادث) التي يمكن للدور الوصول إليها. إذا كان للدور الحق في الوصول إلى المستخدمين ومجموعات المستخدمين، يستطيع بذلك التحكّم أيضًا بالمستخدمين ومجموعات المستخدمين التي يمكنه الوصول إليهم. يمكن للأدوار التي لها حق الوصول إلى "بلا سجلات" الوصول فقط إلى إعداد النظام مثل النماذج والمستخدمين والتقارير. + label: ما هي السجلات التي يؤثر فيها هذا الدور؟ + incident: + actions: + assign: + explanation: يسمح للمستخدم بإرسال حادثة من مالك السجل الأصلي إلى أي مستخدم آخر في النظام. لا يمكن تعيين الحوادث المرتبطة بالفعل بحالة ما؛ يجب عليك بدلاً من ذلك إعادة تعيين الحالة المرتبطة، مما سيؤدي إلى تحديث ملكية سجل الحادث. + label: تعيين + change_log: + explanation: يمكن للمستخدم رؤية تاريخ التغييرات التي تم إجراؤها على السجل منذ إنشائه. يتضمن هذا القيم المسجلة لجميع الحقول. + label: تغيير السجل + create: + explanation: القدرة على إنشاء حادثة. + label: إنشاء + enable_disable_record: + explanation: القدرة على تعطيل أو تمكين حادثة. لا تظهر الحوادث "المعطّلة" بشكل افتراضي في قائمة الحوادث. يمكن للمستخدمين رؤية الحوادث المعطّلة في قائمة الحوادث من خلال تطبيق عامل تصفية. + label: تفعيل/تعطيل + export_case_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة الحوادث أو صفحات عرض الحوادث، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بسجلّ واحد أو سجلات متعدّدة أو جميع السجلات التي يمكن للمستخدم الوصول إليها. في ملف التصدير PDF، يتمّ سرد المعلومات أولاً حسب الحالة، ثم يتمّ تنظيمها بعد ذلك حسب النموذج الذي تظهر عليه المعلومات. + label: تصدير PDF + export_csv: + explanation: 'يمكن للمستخدم إنشاء ملف تصدير CSV من قائمة الحوادث أو صفحات عرض الحوادث، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بحادثة واحدة أو حوادث متعددة أو جميع الحوادث التي يمكن للمستخدم الوصول إليها. ' + label: تصدير CSV + export_custom: + explanation: يمكن للمستخدم تحديد نماذج أو حقول محددة لتصديرها إلى ملف XLS. + label: تصدير ملف مخصص + export_incident_recorder_xls: + explanation: يمكن للمستخدم إنشاء تصدير ملف XLS متخصّص يسمح بتبادل البيانات باستخدام أداة تسجيل حادثة العنف القائم على النوع الإجتماعي. + label: تصدير مسجّل الحوادث xls + export_mrm_violation_xls: + explanation: يمكن للمستخدم إنشاء تصدير Excel (ملف XLS) متخصص لانتهاكات MRM. هذا الإجراء متاح في صفحة عرض الحوادث وقائمة الحوادث. + label: تصدير انتهاكات MRM إلى Excel (ملف XLS) + export_json: + explanation: يمكن للمستخدم إنشاء ملف تصدير JSON من قائمة الحوادث أو صفحات عرض الحوادث، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ،والمرتبطة بحادثة واحدة أو حوادث متعددة أو جميع الحوادث التي يمكن للمستخدم الوصول إليها. يستخدم هذا التصدير بشكل أساسي من قبل الذين يرغبون في تصدير الحوادث من نظام Primero الحالي ثم استيرادها إلى نظام Primero مختلف، أو إلى نظام إدارة معلومات آخر. تعتبر صيغة JSON قابلة للقراءة آليًا وغير عمليّة لمعظم المستخدمين. + label: تصدير JSON + export_list_view_csv: + explanation: يمكن للمستخدم إنشاء ملف تصدير CSV من صفحة قائمة الحوادث التي تحتوي الحقول عينها التي تظهر لهذا المستخدم في قائمة الحوادث. يتمّ تنفيذها فقط من صفحة قائمة الحوادث. + label: تصدير ملف عرض قائمة csv + export_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة الحوادث أو صفحات عرض الحوادث ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ، لسجل واحد أو متعدد أو جميع السجلات التي يمكن للمستخدم الوصول إليها. في ملف تصدير PDF ، يتم سرد المعلومات أولاً حسب الحالة ، ثم يتم تنظيمها بشكل أكبر حسب النموذج الذي تظهر عليه المعلومات. + label: تصدير ملف PDF + export_xls: + explanation: يمكن للمستخدم إنشاء ملف تصدير XLS من قائمة الحادثة أو صفحات عرض الحوادث، والتي تحتوي على مجموعة مخصّصة من النماذج أو الحقول، بالنسبة إلى حالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. في هذا التصدير، يتمّ تمثيل كلّ نموذج في علامة التبويب الخاصة به داخل ملف XLS. يمكن للمستخدم اختيار النماذج أو الحقول التي يريد تضمينها في التصدير باستخدام قسم التصدير المخصّص. يرجى ملاحظة أنه لا يمكن للمستخدمين تضمين النماذج والحقول في التصدير إلا إذا كان لديهم بالفعل القدرة على رؤية تلك النماذج والحقول عند عرض حالة في التطبيق. + label: تصدير EXCEL (ملف XLS) + flag: + explanation: القدرة على إضافة علم إلى حادثة. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي أضافوها إلى إحدى الحوادث. + label: تمييز بعلامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: إزالة أية علامة + import: + explanation: يسمح للمستخدم بإنشاء حادثة واحدة جديدة أو أكثر من خلال استيرادها من ملف CSV أو Excel أو JSON. يجب أن يكون الملف المستورد مهيّأ *جدًّا* وخصوصًا حتى يتمّ استيراد المعلومات بشكل صحيح. يجب أن تكون هذه الوظيفة متاحة فقط للمستخدمين الإداريين ذوي المهارات التقنية المتقدّمة والمعرفة العميقة بكيفية تهيئة البيانات في Primero. يتمّ تنفيذها فقط من صفحة قائمة الحوادث. + label: استيراد + remove_alert: + explanation: يسمح هذا الإذن للمستخدم بإزالة تنبيه من حادث ما. يتم عادةً إنشاء التنبيهات عند تحرير حقل معين، كما هو الحال عند تحديث الملاحظات. تظهر التنبيهات عادةً بنقطة صفراء بجوار الحادث. + label: إزالة التنبيه من الحادث + link_incident_to_case: + explanation: يسمح للمستخدم بربط الحادث بالحالة المحددة. + label: ربط حادث بحالة + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة للحوادث. يعني إذْن "الإدارة" بشكل أساسي "كل شيء". + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على عرض حادثة. + label: عرض + sync_mobile: + explanation: يسمح هذا الإذن بشكل عام للمستخدم باستخدام تطبيق الهاتف المحمول. أولاً ، يسمح للمستخدم بمشاهدة إجراءات "تحديد للهاتف الجوال" و "ازالة التحديد للهاتف الجوال"، والتي تظهر في قائمة الحوادث وصفحات عرض الحوادث. يشير تحديد الحادثة للجوال إلى أنه يجب مزامنة المعلومات الخاصة بهذه الحادثة بين جهاز المستخدم المحمول والتطبيق على الإنترنت، بينما يؤدي إلغاء تحديد الحادثة للهاتف الجوال إلى إيقاف هذه المزامنة. بالإضافة إلى ذلك، لا يمكن للمستخدمين الذين ليس لديهم هذا الإذن مزامنة هواتفهم المحمولة مع التطبيق على الإنترنت بشكل عام، ممّا يعني أنه لا يمكنهم استخدام تطبيق الهاتف لإدارة الحوادث. + label: مزامنة مع الهاتف المحمول + verify_mrm: + explanation: يمكن لمستخدم MRM تغيير لائحة الانتهاكات. + label: تحقق من MRM + write: + explanation: القدرة على نقر زر "تعديل" وتحديث المعلومات عن الحادثة ثم النقر على "حفظ". تسمح أيضًا للمستخدم بتعطيل حادثة أو تفعيلها. + label: تعديل + explanation: يمثل حدثًا وقع. عادة ما تكون هذه حوادث إساءة أو عنف ، على الرغم من أنها يمكن أن تتوافق أيضًا مع أحداث مثل المواجهات مع سلطات إنفاذ القانون. غالبًا ما ترتبط الحوادث بالحالات. + label: حادثة + is_manager: + explanation: ينطبق على أي دور لمستخدم يشرف بشكل عام على المستخدمين الآخرين. يتيح ذلك للمستخدم رؤية لوحات المعلومات وعوامل التصفية التي تساعد المستخدم في إدارة فريق. + label: هل هو مدير؟ + managed_report: + actions: + reporting_locations_report: + label: موقع الإبلاغ (حالات) + explanation: القدرة على عرض إحصائيات حول عدد الحالات المسجلة خلال نطاق زمني معين، وتصفيتها حسب موقع الإبلاغ، ومقسمة حسب العمر والجنس. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + followups_report: + label: متابعات (حالات) + explanation: القدرة على عرض إحصائيات حول عدد المتابعات التي تم إجراؤها خلال نطاق زمني محدد، والتي تمت تصفيتها حسب نوع المتابعة، ومقسمة حسب العمر والجنس. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + services_report: + label: خدمات (حالات) + explanation: القدرة على عرض إحصائيات حول عدد الخدمات المقدمة خلال نطاق زمني معين، مفلترة حسب نوع الخدمة، ومقسمة حسب العمر والجنس. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + protection_concerns_report: + label: مخاوف تتعلق بالحماية (حالات) + explanation: القدرة على عرض إحصائيات حول اهتمامات الحماية للحالات المسجلة خلال نطاق زمني محدد. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + managed_report_scope: + label: ما السجلات التي يجب أن يتمكن هذا الدور من رؤيتها في Insights؟ + managed_report_scope_all: + label: الكل + managed_report_scope_group: + label: البيانات المستندة إلى المجموعة فقط + managed_report_scope_agency: + label: البيانات المستندة إلى الهيئة فقط + violations: + explanation: القدرة على الوصول إلى MRM Violences Insight. + label: الانتهاكات + gbv_statistics: + explanation: القدرة على الوصول لرؤية إحصاءات العنف القائم على النوع الاجتماعي. + label: احصاءات GBV + ghn_report: + explanation: القدرة على الوصول إلى MRM Global Horizontal Note Insight. + label: المذكرة الافقية الشاملة + individual_children: + explanation: القدرة على الوصول إلى MRM Individual Children Insight. + label: الأطفال الفرديين + workflow_report: + label: سير العمل (حالات و حوادث) + explanation: القدرة على عرض إحصائيات حالة سير العمل لكلا الحالتين والأحداث المرتبطة بهما. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + cases_workflow_report: + label: سير العمل (حالات) + explanation: القدرة على عرض الإحصائيات حول حالات حالة سير العمل. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + violence_type_report: + label: نوع العنف (حالات وحوادث) + explanation: القدرة على عرض إحصائيات عن نوع العنف. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + referrals_transfers_report: + label: الإحالات والانتقالات (حالات) + explanation: يرى المستخدمون عدد الحالات التي تم إحالتها ونقلها من كل مجموعة مستخدمين إلى كل مجموعة مستخدمين أخرى. + matching_configuration: + actions: + manage: + explanation: القدرة على التحكم في الحقول التي تتم مقارنتها للعثور على التطابقات بين طلب التتبع والحالة. نظرًا لأن هذا يتحكم في كيفية تشغيل المطابقة في النظام بأكمله، يجب أن يكون هذا الإذن متاحًا فقط لمسؤول النظام. + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: يتحكم في الحقول المستخدمة لمقارنة طلبات التتبع بالحالات أثناء تتبع الأسرة ولم شملها. + label: إعدادات مطابقة + metadata: + actions: + manage: + explanation: القدرة على إنشاء وتعديل وترجمة وحذف النماذج وحقول النماذج وعمليات البحث. يرجى ملاحظة أن المستخدم الذي لديه هذا الإذن سيكون قادرًا فقط على إدارة النماذج التي يمكنه الوصول إليها. على سبيل المثال، إذا كان للمسؤول الوطني القدرة فقط على رؤية نموذج مالك السجل في الحالات، لن يتمكن إلا من تحديث إعداد هذا النموذج. + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: يتحكم في القدرة على تكوين نماذج وحقول Primero ، بالإضافة إلى خيارات البحث المستخدمة داخلها. + label: النماذج، البحث + module: + actions: + cp: + label: حماية الطفل + gbv: + label: العنف القائم على النوع الإجتماعي + mrm: + label: MRM + explanation: يتحكّم في الوحدات النمطية التي ينطبق عليها هذا الدور + label: الوحدات النمطية + potential_match: + actions: + read: + explanation: يمثل الرابط بين طلب التتبع والحالة. يُعتبر الوصول إلى التطابقات المحتملة أمرًا ضروريًا لتتبع أفراد الأسرة ولم شملهم (FTR). يسمح للمستخدم برؤية نموذج ملخص التتبع في الحالات. + label: عرض + view_audio: + explanation: يتحكم في ما إذا كان المستخدم الذي يبحث عن تطابق تتبع يمكنه رؤية الملفات الصوتية للحالة أو طلب التتبع المرتبط بالمطابقة المحتملة. + label: عرض الملف الصوتي + view_photo: + explanation: يتحكم في ما إذا كان المستخدم الذي يبحث عن تطابق تتبع يمكنه رؤية الصور الخاصة بالحالة أو طلب التتبع المرتبط بالمطابقة المحتملة. + label: عرض الصور + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على المطابقات المحتملة. إذن "الإدارة" يعني أساسًا "كل شيء". + label: إدارة + label: تطابق محتمل + primero_configuration: + actions: + manage: + explanation: القدرة على حفظ الإعدادات وتطبيقها وإرسالها. عادة ما يكون هذا الإذن محجوزًا لمسؤول النظام. + label: إدارة (كافة الأذونات لنوع المورد هذا) + label: إعدادات + referral: + actions: + refer: + explanation: هذا يعني أنّ الدور سيظهر كخيار لـ "نوع المستلِم" عندما يقوم المستخدم بإحالة خارجية. إذا اختار المستخدم هذا الدور كنوع الإحالة، سيحتوي التصدير الذي ينشئه Primero عندما يرسل المستخدم الإحالة فقط على المعلومات الموجودة في النماذج التي يمكن لهذا الدور الوصول إليها. إذًا، على سبيل المثال، إذا اختار المستخدم "مزود الخدمة الطبية" كنوع المستلِم، وكان دور مقدم الخدمة الطبية لديه حق الوصول فقط إلى نماذج الهوية الأساسية والمخاوف المتعلّقة بالحماية، لن يحتوي ملف التصدير الذي يصدره Primero للإحالة الخارجية إلّا على الحقول الموجودة في هذين النموذجين. + label: هل يمكن استخدام هذا الدور للإحالات الخارجية؟ + label: إحالة + registry_record: + actions: + change_log: + explanation: يمكن للمستخدم رؤية محفوظات لجميع التغييرات التي تم إجراؤها على السجل منذ إنشائه. يتضمن هذا القيم المسجلة لجميع الحقول. + label: سجل التغيير + create: + explanation: القدرة على إنشاء سجل التسجيل. + label: إنشاء + enable_disable_record: + explanation: القدرة على تعطيل أو تفعيل سجل التسجيل. لا تظهر السجلات "المعطلة" بشكل افتراضي في قائمة التسجيل. يمكن للمستخدمين رؤية سجلات التسجيل المعطلة في قائمة التسجيل باستخدام مرشح. + label: تفعيل/تعطيل + export_csv: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف CSV من قائمة السجل أو صفحات عرض السجل ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ، لسجل واحد أو متعدد أو جميع سجلات التسجيل التي يمكن للمستخدم الوصول إليها. ملاحظة: لا يعرض تصدير CSV الأحرف غير اللاتينية (مثل العربية والبنغالية)' + label: تصدير CSV + export_json: + explanation: يمكن للمستخدم إنشاء تصدير ملف JSON من قائمة التسجيل أو صفحات عرض السجل ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها. تنسيق JSON قابل للقراءة آليًا وغير عملي لمعظم المستخدمين. + label: تصدير JSON + export_xls: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف XLS من قائمة التسجيل أو صفحات عرض السجل ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها. ملاحظة: يعرض تنسيق XLS الأحرف غير اللاتينية (مثل العربية والبنغالية) بتنسيق قابل للقراءة ، بينما لا يعرض تنسيق CSV.' + label: تصدير EXCEL (ملف XLS) + flag: + explanation: القدرة على إضافة علامة إلى سجل التسجيل. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي قاموا بإضافتها إلى سجل التسجيل. + label: تمييز بعلامة/وضع علامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: حل أي علامة + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على سجلات التسجيل. إذن "الإدارة" يعني أساسًا "كل شيء". + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على رؤية سجل التسجيل. + label: رؤية/تصفح + write: + explanation: القدرة على النقر فوق الزر "تعديل" وتحديث المعلومات في الحالة والنقر فوق "حفظ" + label: تعديل + sync_mobile: + explanation: يسمح للمستخدم بالتخزين المؤقت لسجلات التسجيل للاستخدام في وضع عدم الاتصال. + label: وضع علامة على عدم الاتصال بالانترنت + explanation: يمكن أن يمثل هذا فردًا أو مؤسسة تحتاج إلى ربطها بسجلات أخرى مثل الحالات أو الحوادث ، وهي كثيرة جدًا ويتم تحديثها بشكل متكرر بمعلومات جديدة. إنها تشبه عمليات البحث ، ولكن مع مجموعة أكثر تعقيدًا من المعلومات لكل إدخال. + label: سجل التسجيل + family: + actions: + change_log: + explanation: يمكن للمستخدم رؤية سجل بجميع التغييرات التي تم إجراؤها على السجل منذ إنشائه. يتضمن ذلك القيم المسجلة لجميع الحقول. + label: سجل التغيير + create: + explanation: القدرة على إنشاء سجل العائلة + label: إنشاء + enable_disable_record: + explanation: القدرة على تعطيل أو تفعيل الأسرة. لا تظهر العائلات "المعطلة" بشكل افتراضي في قائمة العائلة. يمكن للمستخدمين رؤية العائلات المعطلة في قائمة العائلة باستخدام عامل التصفية. + label: تفعيل / تعطيل + export_csv: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف CSV من قائمة العائلة أو صفحات عرض العائلة، والتي تحتوي على جميع المجالات التي يمكن للمستخدم الحالي الوصول إليها، لاسرة واحد أو اكثر ا. ملاحظة: لا يعطي تصدير CSV حروف غير لاتينية (مثل العربية)' + label: تصدير من نوع CSV + export_json: + explanation: يمكن للمستخدم إنشاء تصدير ملف JSON من قائمة العائلة أو صفحات عرض العائلة، والتي تحتوي على جميع المجالات التي يمكن للمستخدم الحالي الوصول إليها. تنسيق JSON قابل للقراءة آليًا وليس عمليًا لمعظم المستخدمين. + label: تصدير من نوع JSON + export_xls: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف XLS من قائمة العائلة أو صفحات عرض العائلة، والتي تحتوي على جميع المجالات التي يمكن للمستخدم الحالي الوصول إليها. ملاحظة: يجعل XLS الأحرف غير اللاتينية (مثل العربية) مقروئة، في حين أن تصدير CSV لا يفعل ذلك.' + label: تصدير من نوع XLS + export_list_view_csv: + explanation: يمكن للمستخدم إنشاء تصدير ملف CSV من صفحة قائمة العائلة والتي تحتوي على نفس الحقول التي تظهر لذلك المستخدم في قائمة العائلة. يؤدى فقط من صفحة قائمة العائلة. + label: تصدير للائحة على شكل CSV + export_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة العائلة أو صفحات العرض العائلي، والتي تحتوي على جميع المجالات التي يمكن للمستخدم الحالي الوصول إليها، لسجل واحد أو اكثر والتي يمكن للمستخدم الوصول إليها. في ملف تصدير PDF، يتم سرد المعلومات أولاً حسب الأسرة، ثم يتم تنظيمها من خلال النموذج الذي تظهر عليه المعلومات. + label: تصدير على شكل PDF + export_custom: + label: تصدير لحقول مخصصة من الملف + explanation: يمكن للمستخدم اختيار نماذج أو حقول محددة من قائمة العائلة أو صفحات عرض العائلة للتصدير إلى ملف XLS. + flag: + explanation: القدرة على إضافة اشارة علم إلى العائلة. يمكن للمستخدمين الحاصلين على هذا الإذن أيضًا إزالة اشارات الأعلام التي أضافوها إلى العائلة. + label: علامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: حل أية علامة + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على العائلات. إذن "الإدارة" يعني في الأساس "كل شيء". + label: إدارة (جميع الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على رؤية العائلات + label: عرض + write: + explanation: القدرة على الضغط على زر "تعديل" وتحديث المعلومات الخاصة بالعائلة والنقر على "حفظ". + label: تعديل + sync_mobile: + explanation: يسمح للمستخدم بتخزين سجلات العائلة مؤقتًا للاستخدام دون الاتصال بالإنترنت. + label: وضع علامة على غير متصل + close: + explanation: يسمح للمستخدم بتعيين حالة عائلة مفتوحة إلى مغلقة. + label: غلق + reopen: + explanation: يمكن أن تساعد هذه الحالات على فتح أبوابها. + label: إعادة فتح + case_from_family: + explanation: يسمح للمستخدمين بإنشاء حالة جديدة من نموذج فرعي لأعضاء العائلة داخل سجل العائلة. + label: إنشاء حالة + label: العائلة + report: + actions: + create: + explanation: القدرة على إنشاء تقرير جديد. عندما يُنشئ المستخدم تقريرًا، يصبح مرئيًا لجميع المستخدمين الذين لديهم حق الوصول "للقراءة" أو "قراءة المجموعة" في التقارير. + label: إنشاء + group_read: + explanation: القدرة على عرض جميع التقارير. ستعكس الأرقام في كلّ تقرير فقط السجلات التي يمكن الوصول إليها من قبل المستخدمين في مجموعات المستخدمين المستخدم الحالي. غالبًا ما يستخدم هذا الإذن للمسؤولين المحليين أو الإقليميين أو الهيئات الذين يتطلعون إلى الإطلاع على أداء فرقهم أو منظماتهم. يمنح هذا الإذن المستخدم أيضًا القدرة على تصدير البيانات من تقرير معيّن. + label: عرض (البيانات المستندة إلى المجموعة) + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة للوكالات. يعني إذْن "الإدارة" بشكل أساسي "كل شيء". + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على عرض جميع التقارير. ستعكس الأرقام في كلّ تقرير كلّ السجلات في النظام، بدلاً من السجلات التي يحقّ للمستخدم الحالي فقط الوصول إليها. يمنح هذا الإذن المستخدم أيضًا القدرة على تصدير البيانات من تقرير معيّن. + label: عرض + write: + explanation: القدرة على تعديل كلّ التقارير (بما في ذلك تلك التي أنشأها مستخدمون آخرون). + label: تعديل + agency_read: + explanation: القدرة على عرض جميع التقارير. ستعكس الأرقام الواردة في كل تقرير فقط تلك السجلات التي يمكن الوصول إليها من قبل المستخدمين في الهيئة المستخدمة الحالية. غالبًا ما يستخدم هذا الإذن لمسؤولي نظام الهيئة. + label: عرض (البيانات المستندة إلى الهيئة) + explanation: أداة تحليل البيانات المجمعة. يشمل تمثيلات الجدول والرسم البياني للبيانات. + label: تقرير + reporting_location_level: + explanation: 'سيتحكم هذا في مستوى المواقع التي تظهر لهذا الدور في لوحات المعلومات، وعوامل التصفية، ووحدات الإحالة النمطية، وشروط التحويل. إذا تركت هذا الحقل فارغًا، سيرى هذا الدور مستوى موقع الإبلاغ الافتراضي في النظام.' + label: ما هو نوع الموقع الذي يجب استخدامه للإبلاغ لهذا الدور؟ + role: + actions: + assign: + explanation: القدرة على اختيار دور عند إنشاء أو تعديل حساب مستخدم. هذا الإذن ضروري لأي دور يقوم بإنشاء أو تعديل حسابات المستخدمين. + label: تعيين + copy: + explanation: القدرة على إنشاء نسخة من الدور. هذا مفيد لمسؤولي النظام الذين قد ينشئون عددًا من الأدوار المتشابهة جدًا (مثل مزودي الخدمة). + label: نسخ + create: + explanation: القدرة على إنشاء دور + label: إنشاء + delete: + explanation: القدرة على حذف دور + label: حذف + manage: + explanation: 'يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على الأدوار. إذن "الإدارة" يعني أساسًا "كل شيء". هام: يمنح هذا الإذن أيضًا القدرة على إنشاء أدوار وحذفها.' + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + permitted_roles: + explanation: إذا كان لدور ما القدرة على تنفيذ أي من الإجراءات المذكورة أعلاه على دور، فسيكون قادرًا على تنفيذ تلك الإجراءات على الأدوار المحددة في هذه القائمة. لذلك، على سبيل المثال، إذا كان الدور لديه إذن "قراءة" و "تعيين" للأدوار، ولكن تمّ إدراج "اخصائي الحالة CP" و "المدير CP" فقط على أنّهما "الأدوار المُدارة"، فسيكون قادرًا فقط على رؤية هذين الدورين وسيكون قادرًا فقط على تعيين مستخدمين جدد لهذين الدورين. إذا لم يتمّ تحديد "الأدوار المُدارة" للدور نفسه، فسيكون قادرًا على رؤية جميع الأدوار وسيكون قادرًا على إنشاء حسابات مستخدمين جديدة بأي دور في النظام. + label: الأدوار الأخرى التي يديرها هذا الدور + read: + explanation: القدرة على إنشاء الأدوار + label: عرض + write: + explanation: القدرة على النقر على زر "تعديل" في صفحة عرض الأدوار، وتحديث أذونات الدور، ثم حفظ الدور. + label: تعديل + explanation: تملي الإجراءات التي يمكن للمستخدم تنفيذها في Primero. + label: الأدوار + system: + actions: + manage: + explanation: القدرة على رؤية المعلومات وتحديثها ضمن معلومات الاتصال في النظام والإشعارات الافتراضية وإعدادات البريد الإلكتروني والإعداد الترحيبية والخوادم المتزامنة. عادة ما يكون هذا الإذن مخصّصًا لمسؤول النظام + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: ' الإعدادات المتنوعة على مستوى النظام.' + label: النظام + tracing_request: + actions: + change_log: + explanation: يمكن للمستخدم رؤية تاريخ التغييرات التي تم إجراؤها على السجل منذ إنشائه. يتضمن هذا القيم المسجلة لجميع الحقول. + label: تغيير السجل + create: + explanation: القدرة على إنشاء طلب تتبّع + label: إنشاء + enable_disable_record: + explanation: القدرة على تعطيل أو تمكين طلب تتبّع. لا تظهر طلبات التتبّع "المعطّلة" بشكل افتراضي في قائمة طلبات التتبّع. يمكن للمستخدمين رؤية طلبات التتبّع المعطّلة في قائمة طلبات التتبّع من خلال تطبيق عامل تصفية. + label: تفعيل/تعطيل + export_case_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة طلبات التتبّع أو صفحات عرض طلبات التتبّع، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بسجلّ واحد أو سجلات متعدّدة أو جميع السجلات التي يمكن للمستخدم الوصول إليها. في ملف التصدير PDF، يتمّ سرد المعلومات أولاً حسب الحالة، ثم يتمّ تنظيمها بعد ذلك حسب النموذج الذي تظهر عليه المعلومات. + label: تصدير PDF + export_csv: + explanation: 'يمكن للمستخدم إنشاء ملف تصدير CSV من قائمة طلبات التتبّع أو صفحات عرض طلبات التتبّع، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بطلب تتبّع واحد أو طلبات تتبّع متعددة أو جميع طلبات التتبّع التي يمكن للمستخدم الوصول إليها. ' + label: تصدير CSV + export_custom: + explanation: يمكن للمستخدم إنشاء ملف تصدير XLS من قائمة طلبات التتبّع أو صفحات عرض طلبات التتبّع، والتي تحتوي على مجموعة مخصّصة من النماذج أو الحقول، بالنسبة إلى طلب تتبّع واحدة أو طلبات تتبّع متعددة أو جميع طلبات التتبّع التي يمكن للمستخدم الوصول إليها. في هذا التصدير، يتمّ تمثيل كلّ نموذج في علامة التبويب الخاصة به داخل ملف XLS. يمكن للمستخدم اختيار النماذج أو الحقول التي يريد تضمينها في التصدير باستخدام قسم التصدير المخصّص. يرجى ملاحظة أنه لا يمكن للمستخدمين تضمين النماذج والحقول في التصدير إلا إذا كان لديهم بالفعل القدرة على رؤية تلك النماذج والحقول عند عرض طلب تتبّع في التطبيق. + label: تصدير ملف مخصص + export_json: + explanation: يمكن للمستخدم إنشاء ملف تصدير JSON من قائمة طلبات التتبّع أو صفحات عرض طلبات التتبّع، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ،والمرتبطة بطلب تتبّع واحد أو طلبات تتبّع متعددة أو جميع طلبات التتبّع التي يمكن للمستخدم الوصول إليها. يستخدم هذا التصدير بشكل أساسي من قبل الذين يرغبون في تصدير طلبات التتبّع من نظام Primero الحالي ثم استيرادها إلى نظام Primero مختلف، أو إلى نظام إدارة معلومات آخر. تعتبر صيغة JSON قابلة للقراءة آليًا وغير عمليّة لمعظم المستخدمين. + label: تصدير JSON + export_list_view_csv: + explanation: يمكن للمستخدم إنشاء ملف تصدير CSV من صفحة قائمة طلبات التتبّع التي تحتوي الحقول عينها التي تظهر لهذا المستخدم في قائمة طلبات التتبّع. يتمّ تنفيذها فقط من صفحة قائمة طلبات التتبّع. + label: تصدير ملف عرض قائمة csv + export_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة طلبات التتبع أو عرض صفحات طلب التتبع ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ، لسجل واحد أو متعدد أو جميع السجلات التي يمتلك المستخدم حق الوصول إليها. في ملف تصدير PDF ، يتم سرد المعلومات أولاً حسب الحالة ، ثم يتم تنظيمها بشكل أكبر حسب النموذج الذي تظهر عليه المعلومات. + label: تصدير ملف PDF + export_xls: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف XLS من قائمة طلبات التتبع أو صفحات عرض طلب التتبع ، والتي تحتوي على جميع الحقول التي يمتلك المستخدم الحالي حق الوصول إليها ، لطلبات تتبع واحدة أو متعددة أو جميعها التي يمتلك المستخدم حق الوصول إليها. في هذا التصدير ، يتم تمثيل كل نموذج في علامة التبويب الخاصة به داخل ملف XLS. ملاحظة: يعرض تنسيق XLS الأحرف غير اللاتينية (مثل العربية والبنغالية) بتنسيق قابل للقراءة ، بينما لا يعرض تنسيق CSV.' + label: تصدير EXCEL (ملف XLS) + flag: + explanation: القدرة على إضافة علم إلى طلب تتبّع. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي أضافوها إلى إحدى طلبات التتبّع. + label: تمييز بعلامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: حل أية علامة + import: + explanation: يسمح للمستخدم بإنشاء حالة واحدة جديدة أو أكثر من خلال استيرادها من ملف CSV أو Excel أو JSON. يجب أن يكون الملف المستورد مهيّأ *جدًّا* وخصوصًا حتى يتمّ استيراد المعلومات بشكل صحيح. يجب أن تكون هذه الوظيفة متاحة فقط للمستخدمين الإداريين ذوي المهارات التقنية المتقدّمة والمعرفة العميقة بكيفية تهيئة البيانات في Primero. يتمّ تنفيذها فقط من صفحة قائمة الحالة. + label: استيراد + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة لطلبات التتبّع. يعني إذْن "الإدارة" بشكل أساسي "كل شيء". + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على عرض طلب التتبع. يجب أن تتمتع الأدوار التي لها القدرة على رؤية طلبات التتبع أيضًا بالقدرة على رؤية نوع سجل التطابق المحتمل. + label: عرض + write: + explanation: القدرة على نقر زر "تعديل" وتحديث المعلومات عن طلب التتبّع ثم النقر على "حفظ". تسمح أيضًا للمستخدم بتعطيل طلب تتبّع أو تفعيله. + label: تعديل + explanation: يمثل فردًا يحاول تحديد مكانه وجمع شمله في حالة غير مصحوب أو منفصل. + label: طلبات التتبع + transfer: + actions: + transfer: + explanation: هذا يعني أنّ الدور سيظهر كخيار لـ "نوع المستلِم" عندما يقوم المستخدم بإحالة خارجية. إذا اختار المستخدم هذا الدور كنوع التحويل، سيحتوي التصدير الذي ينشئه Primero عندما يرسل المستخدم التحويل فقط على المعلومات الموجودة في النماذج التي يمكن لهذا الدور الوصول إليها. إذًا، على سبيل المثال، إذا اختار المستخدم "مزود الخدمة الطبية" كنوع المستلِم، وكان دور مقدم الخدمة الطبية لديه حق الوصول فقط إلى نماذج الهوية الأساسية والمخاوف المتعلّقة بالحماية، لن يحتوي ملف التصدير الذي يصدره Primero للتحويل الخارجي إلّا على الحقول الموجودة في هذين النموذجين. + label: هل يمكن استخدام هذا الدور للتحويلات الخارجية؟ + label: تحويل + user: + actions: + agency_read: + explanation: القدرة على رؤية حسابات المستخدمين في الهيئة المستخدمة الحالية فقط. يؤثر هذا أيضًا على حسابات المستخدمين التي يمكن للمستخدم الحالي تنفيذ إجراءات أخرى عليها. على سبيل المثال ، إذا كان المستخدم الحالي لديه إذن "كتابة" على المستخدمين، ولكن لديه أيضًا إذن قراءة الهيئة، فسيكون قادرًا فقط على تعديل حسابات المستخدمين الموجودة في هيئته الخاصة. وبالمثل، إذا كان المستخدم الحالي لديه إذن "إدارة" للمستخدمين، ولكن لديه إذن "قراءة الهيئة"، فسيكون قادرًا فقط على إنشاء مستخدمين لهيئته الخاصة. + label: عرض (ضمن الهيئة) + create: + explanation: القدرة على إنشاء حساب مستخدم + label: إنشاء + manage: + explanation: 'يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على المستخدمين. إذن "الإدارة" يعني أساسًا "كل شيء". هام: يمنح هذا الإذن أيضًا القدرة على إنشاء حسابات مستخدمين جديدة.' + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على رؤية حسابات المستخدمين. بشكل افتراضي، كلّ مستخدم لديه القدرة على رؤية المعلومات المتعلقة بحسابه الخاص وتعديلها (مثل كلمة المرور والبريد الإلكتروني). + label: عرض + write: + explanation: القدرة على نقر زر "تعديل" في صفحة عرض المستخدم، وتحديث معلومات المستخدم، ثم الحفظ. يرجى ملاحظة أنّ هذا الإذن يمنحك أيضًا القدرة على تعطيل حسابات المستخدمين. + label: تعديل + explanation: يمثل حساب مستخدم فردي. + label: المستخدمون + user_group: + actions: + assign: + explanation: القدرة على اختيار مجموعات المستخدمين عند إنشاء حساب المستخدم أو تعديله. يرجى ملاحظة أنه إذا كان لدى المستخدم الحالي مستوى الوصول فقط إلى "السجلات أو المستخدمين في مجموعتي"، سيكون قادرًا فقط على اختيار مجموعة واحدة أو أكثر من مجموعات المستخدمين * الخاصة بهم * لحساب المستخدم الذي يقومون بإنشائه أو تعديله. هذا يعني أن المدير الذي لديه القدرة على تعيين مجموعات مستخدمين سيكون قادرًا فقط على إضافة مستخدم إلى مجموعات المستخدمين التي ينتمي إليها المدير حاليًا. هذا الإذن ضروري لأي دور يقوم بإنشاء حسابات المستخدمين أو تعديلها. + label: تعيين + create: + explanation: القدرة على إنشاء مجموعة مستخدمين + label: إنشاء + delete: + explanation: القدرة على حذف مجموعة مستخدمين + label: حذف + manage: + explanation: 'يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على مجموعات المستخدمين. إذن "الإدارة" يعني أساسًا "كل شيء". هام: يمنح هذا الإذن أيضًا القدرة على إنشاء مجموعات المستخدمين وحذفها.' + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على رؤية مجموعات المستخدمين + label: عرض + write: + explanation: القدرة على تعديل مجموعات المستخدمين. + label: تعديل + explanation: يمثل فريقًا أو مجموعة متعاونة من المستخدمين الذين يمكنهم مشاركة المعلومات. يمكن للمديرين عادةً رؤية جميع السجلات التي يديرها اخصائيون الحالة في مجموعات المستخدمين الخاصة بهم. + label: مجموعات المستخدمين + webhook: + actions: + read: + label: رؤية/تصفح + explanation: القدرة على سرد ومراجعة إعدادات webhook عبر واجهة برمجة التطبيقات + write: + label: تعديل + explanation: القدرة على إنشاء وتعديل إعدادات webhook عبر واجهة برمجة التطبيقات. + create: + explanation: القدرة على إنشاء إعدادات webhook عبر واجهة برمجة التطبيقات. + label: إنشاء + delete: + explanation: القدرة على حذف إعدادات webhook عبر واجهة برمجة التطبيقات. + label: حذف/إزالة + manage: + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: يُستخدم لأدوار النظام التي تصل إلى Primero Webhooks للأنظمة الأخرى. لا ينصح باستخدامه لغير المطورين. + activity_log: + actions: + transfer: + explanation: يمكن للمستخدم النقر فوق قسم سجل النشاطات في لوحة ملخص البيانات والاطلاع على سجل بجميع عمليات النقل المقبولة أو المرفوضة للحالات التي يمكنهم الوصول إليها. + label: عمليات النقل + manage: + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: القدرة على الوصول إلى كافة. + label: سجل التغيير + potential_match: + case_id: هوية الحالة + child_age: العمر + child_gender: الجنس + child_id: 'رقم معرف الطفل #' + inquirer_id: معرف المُستفسر# + inquirer_tr_name: تتبع الطلبات + inquiry_date: تاريخ الاستفسار + name: الاسم + score: النتيجة + social_worker: 'اخصائي الحالة ' + social_worker_agency: الهيئة + tracing_request_id: معرّف طلبات التتبّع + trace: تتبّع + likelihood_likely: مرجح + likelihood_possible: ممكن + potential_matches: + display: عرض النتائج المطابقة المحتملة لـ %{type} %{id} + reassign: + multiple_error: حدث خطأ. لم يتم تعيين الحالة (الحالات) %{select_records}. + multiple_successfully: Primero يحدث في هذه الاثنات الحالات % {select _ records} . قد يستغرق تحديث كل هذه الحالات عدة دقائق. + notes_label: ملاحظات + successfully: تمت إعادة التعيين بنجاح + user_mandatory_label: يجب إدخال إسم المستلِم + users_label: المستلِم + incident_from_case_warning: لا يمكنك تعيين هذه الحادثة، لأنها مرتبطة بالفعل بحالة ما. عندما تقوم بتعيين الحالة، يتم تعيين الحادث أيضًا. + record_information: + assigned_user_names: 'المستخدمين الأخرين ' + created_at: تم إنشاء السجل في + created_by: تم إنشاء السجل بواسطة + created_organization: تم الإنشاء بواسطة الهيئة + current_owner_separator: المالك الحالي + module_id: وحدة + owned_by: 'كود اخصائي الحالة ' + owned_by_agency_id: الهيئة + owned_by_text: الحقل/حالة/اخصائي الحالة + previously_owned_by: المستخدم السابق + previously_owned_by_agency: 'الهيئة السابقة ' + reassigned_tranferred_on: إعادة التعيين / التحويل في + record_history_separator: تسجيل التاريخ + last_updated_at: تاريخ اخر تحديث + last_updated_by: 'اخر تحديث تم من قبل ' + record_panel: + record_information: تسجيل المعلومات + referral: + type_of_recipient: نوع المستلِم + type_of_referral_required: مطلوب إدخال نوع الإحالة + referral_authorization_label: هل ترغب في تحديد نوع الإحالة؟ + referral_authorization_help_text: سيؤدي هذا إلى تحديد النماذج التي يمكن للمستلم الوصول إليها. + agency_label: الهيئة + is_remote_label: هل ترغب في احالة الحالة لمؤسسة من خارج النظام؟ + location_label: الموقع + notes_label: ملاحظات + notes_on_referral: الملاحظات عند الإحالة + note_on_referral_from_provider: الملاحظات عند الإحالة من المزوّد + provided_consent_label: لم يتمّ توفير الموافقة في النماذج. + recipient_label: المستلِم + refer_anyway_label: هل تريد الإحالة على أي حال؟ + service_label: خدمة + success: 'تمت إحالة %{record_type} %{id} بنجاح' + user_mandatory_label: المستلم مطلوب + date: التاريخ + rejected_reason: سبب الرفض + report: + aggregate_by: مجموعات حسب الصف + attribute: خاصيّة + constraint: قيود + date_ranges: + date: يوم + month: شهر + quarter: الربع + quarter_abbr: Q%{quarter} + week: اسبوع + year: سنة + description: الوصف + disabled: + explanation: إذا قمت بتعطيل هذا التقرير، لن يظهر ضمن التقارير المتاحة. + label: 'مُعطلة ' + exclude_empty_rows: لا تعرض صفوف فارغة + disaggregate_by: مجموعات حسب الأعمدة + filters: + label: الإبلاغ عن عوامل التصفية + label_new: عامل تصفية جديد للتقرير + attribute: عامل التصفية + value: مع + not_null: ليس فارغًا؟ + less_than: 'أقل من ' + greater_than: أكثر من + equal_to: مساوي لـ + not_blank: ليس فارغًا + is: هو + before: قبل + after: بعد + delete_filter_message: هل أنت متأكد أنك تريد حذف عامل التصفية هذا؟ + group_ages: استخدام نطاقات الأعمار + group_dates_by: استخدام نطاقات التواريخ + is_graph: هل تريد إنتاج مخطّط بياني؟ + messages: + delete_success: تم حذف التقرير بنجاح + success: تم إنشاء التقرير بنجاح. + updated: تم تحديث التقرير بنجاح. + modules: الوحدات النمطية + name: الاسم + name_mandatory: مطلوب ادخال الاسم المستخدم + no_data: لا يوجد بيانات لهذا التقرير + no_filters_added: لم تتمّ إضافة أي عوامل تصفية + not_selected: لم يتم اختياره + record_type: نوع السجل + total: الإجمالي + value: قيمة + incomplete_data: بيانات غير مكتملة + reports: + delete_report: حذف التقرير + delete_report_message: هل أنت متأكد أنك تريد حذف هذا التقرير؟ لا يمكن التراجع عن الحذف. انقر فوق تمّ لحذف التقرير. + label: تقارير + register_new_report: إنشاء تقرير + translations: + edit: تحرير الترجمات + manage: إدارة الترجمات + select_language: اختار اللغة + error_loading: خطأ في تحميل التقرير(التقارير) + request_transfer: + notes_label: ملاحظات -الرجاء ذكر سبب النقل بالإضافة إلى تفاصيل الاجتماعات التي عقدت لمناقشة نقل الحالة + submit_label: أرسل الطلب + success: تم إرسال طلب التحويل + role: + agency_ids_label: وكالات يديرها هذا الدور + copy_failure: خطأ في نسخ الدور. تأكد من أن الاسم لا يتعارض مع دور آخر. + copy_success: نسخ الدور بنجاح. + create: إنشاء دور + delete_header: حذف دور + description: الوصف + edit: تعديل الدور + error_in_updating: خطأ في تحديث تفاصيل الدور. + group_permission_label: ما السجلات التي يؤثر فيها هذا الدور؟ + label: دور + manager: المدير + messages: + confirmation: هل أنت متأكد أنك تريد حذف هذا الدور؟ لا يمكن التراجع عن الحذف. انقر فوق تمّ لحذف الدور. + created: تم إنشاء الدور بنجاح. + deleted: تم حذف الدور بنجاح + updated: تم تحديث الدور بنجاح. + name: الاسم + referral_label: هل يمكن استخدام هذا الدور للإحالات؟ + reporting_location_level_label: ما هو نوع الموقع الذي يجب استخدامه للإبلاغ عن هذا الدور؟ + role_ids_label: الأدوار الأخرى التي يديرها هذا الدور + successfully_updated: تم تحديث تفاصيل الدور بنجاح. + transfer_label: هل يمكن استخدام هذا الدور لعمليات النقل؟ + hide: إخفاء + read: عرض + read_write: عرض وتحرير + roles: + label: دور المستخدم + saved_search: + deleted: تم حذف البحث بنجاح + filters_tab: مرشحات + no_filters: لم يتمّ اختيار أي عوامل تصفية + save_success: تم حفظ البحث بنجاح + saved_searches_tab: عمليات بحث محفوظة + title_description: هل أنت متأكد أنك تريد حذف هذا البحث المحفوظ؟ + title_modal: حذف عمليات البحث المحفوظة + saved_searches: + no_save_searches: لا يوجد لديك عمليات بحث محفوظة + save_search: عملية بحث محفوظة + settings: + navigation: + agencies: الهيئات + audit_logs: سجلات التدقيق + configurations: إعدادات + contact_information: معلومات الاتصال + forms: النماذج + locations: المواقع + lookups: عمليات البحث + user_groups: مجموعات المستخدمين + users: المستخدمون + roles: الأدوار + code_of_conduct: مدونة قواعد السلوك + title: إعدادات + system_settings: + label: إعدادات النظام + task: + due_date: تاريخ الاستحقاق + id: رقم الحالة في النظام + name: الإسم + priorities: + high_level: مرتفع + low_level: منخفض + medium_level: متوسط + no_action_level: لا يوجد إجراء + priority: مستوى الأولوية + status: الوضع + statuses: + overdue: متأخرة + upcoming_soon: أوشك على الاستحقاق + type: نوع الإجراء + types: + assessment: التقييم + case_plan: خطة الحالة + follow_up: متابعة - %{subtype} + service: الخدمة - %{subtype} + tracing_request: + label: طلبات التتبع + has_match: يوجد تطابق + find_match: إيجاد تطابق + back_to_traces: العودة إلى التتبعات + back_to_potential_matches: العودة إلى التطابقات المحتملة + traces: تتبّعات + trace: تتبّع + match: مطابق + matches: تطابقات + unmatch: إزالة التطابق + tracing_request_photos: صور من اجل طلب التتبع هذا + case_photos: صور لهذه الحالة + tracing_request_audios: ملف صوتي من اجل طلب التتبع هذا + case_audios: ملف صوتي لهذه الحالة + messages: + already_matched: يوجد بالفعل تطابقًا في النظام مع مستعلم يبحث عن هذا الطفل. + disabled: تمّ تعطيل طلب التتبع + nothing_found: لم يتم العثور على شيء + update_success: 'تم تحديث طلب التتبع %{record_id} بنجاح. ' + creation_success: 'تم إنشاء سجل طلب التتبع بنجاح. ' + update_success_queue: 'تم تحديث طلب التتبع %{record_id} بنجاح في الخلفية.' + creation_success_queue: تم إنشاء سجل طلب التتبع بنجاح في الخلفية. + match_action: تمت مطابقة التتبع %{trace_id} مع الحالة %{record_id} بنجاح. + unmatch_action: تمت إزالة تطابق التتبع %{trace_id} والحالة %{record_id}بنجاح. + registry_record: + messages: + update_success: 'تم تحديث سجل التسجيل %{record_id} بنجاح.' + creation_success: 'تم إنشاء سجل التسجيل بنجاح.' + disabled: سجل التسجيل معطل + tracing_requests: + date_of_inquiry: تاريخ الاستعلام + disable_dialog_title: تعطيل طلب التتبع + disable_dialog: بالنقر على "تمّ" سيُصبح وضع طلب التتبّع هذا معطّلًا. + disable_success: تمّ تعطيل طلب التتبع بنجاح + enable_dialog: بالنقر على "تمّ" سيُصبح وضع طلب التتبّع هذا مفعّلاً. + enable_dialog_title: تفعيل طلب التتبع + enable_success: تمّ تفعيل طلب التتبع بنجاح + id: الهويّة + complete: متاح بدون الاتصال بالانترنت + filter_by: + by_date: حسب التاريخ + location_separation: موقع الإنفصال + separation_cause: سبب الإنفصال + status: الوضع + label: طلبات التتبع + name_of_inquirer: إسم المُستفسر + inquirer: المُستفسر + name: الإسم + register_new_tracing_request: 'طلب تتبع جديد ' + selectable_date_options: + inquiry_date: تاريخ الاستعلام + selected_records: 'تمّ اختيار طلب التتبّع (طلبات التتبّع) %{select_records}' + selected_all_records: 'اختَر جميع طلبات التتبّع %{total_records} التي تطابق هذا الاستعلام.' + show_tracing_request: 'معرِّف طلب التتبع %{short_id} ' + tracing_requests: طلبات التتبع + export: تصدير + sort_by: ترتيب حسب + registry_records: + id: رقم الحالة في النظام + label: سجل التسجيل + name: الإسم + registry_no: رقم التسجيل + location: موقع + registration_date: تاريخ التسجيل + selected_records: '%{select_records} تم تحديد سجل (سجلات) التسجيل' + selected_all_records: 'حدد كافة سجلات التسجيل %{total_records} التي تطابق هذا الاستعلام.' + disable_dialog_title: تعطيل سجل التسجيل + disable_dialog: سيؤدي النقر فوق "موافق" إلى تغيير حالة سجل التسجيل هذا إلى معطل. + disable_success: تم تعطيل سجل التسجيل بنجاح + enable_dialog_title: تفعيل سجل التسجيل + enable_dialog: سيؤدي النقر فوق "موافق" إلى تغيير حالة سجل التسجيل هذا إلى مفعل. + enable_success: تم تفعيل سجل التسجيل بنجاح + complete: متاح بدون الاتصال بالانترنت + filter_by: + by_date: حسب التاريخ + status: الوضع + selectable_date_options: + registration_date: تاريخ التسجيل + show_registry_record: 'معرف سجل التسجيل: %{short_id}' + register_new_registry_record: سجل التسجيل جديد + export: يصدر + mark_for_offline: + title: وضع علامة على عدم الاتصال بالانترنت + text: هل أنت متأكد أنك تريد وضع علامة على سجلات التسجيل هذه لاستخدامها عندما تكون غير متصل؟ + success: تم وضع علامة على سجلات التسجيل بنجاح للاستخدام دون اتصال بالانترنت + families: + id: بطاقة تعريف + label: العائلة + family_id: معرف العائلة + family_number: رقم العائلة + family_name: اسم العائلة + family_registration_date: تاريخ التسجيل + family_location_current: مكان العائلة + export: استيراد + register_new_family: عائلة جديدة + show_family: 'رقم ملف العائلة %{short_id}' + disable_dialog_title: سجل عائلة معطل + disable_dialog: سيؤدي النقر فوق "موافق" إلى تغيير حالة هذه العائلة إلى "معطل". + selected_records: '%{select_records} سجل (سجلات) عائلية تم اختيارها' + selected_all_records: 'حدد جميع %{total_records} العائلات التي تطابق هذا الاستعلام.' + mark_for_offline: + title: وضع علامة على غير متصل + text: هل أنت متأكد من أنك تريد وضع علامة على سجلات العائلة هذه لاستخدامها عندما تكون غير متصل بالإنترنت؟ + success: تم وضع علامة على سجلات العائلة بنجاح للاستخدام دون اتصال + filter_by: + by_date: ب تاريخ + status: الوضع + current_location: مكان العائلة + family: + family_member: + case_id: معرف الحالة + update_and_return: التحديث والعودة + save_and_return: إضافة والعودة + create_case: إنشاء حالة + back_to_family_members: العودة إلى أعضاء العائلة + create: إنشاء + messages: + update_success: 'تم تحديث ملف العائلة رقم % {record _ id} بنجاح.' + creation_success: 'تم إنشاء سجل العائلة بنجاح.' + disabled: العائلة معطلة + confirm_create_case: هل تريد إنشاء حالة لهذا الشخص؟ + transfer: + label: نقل + agency_label: الهيئة + consent_from_individual_label: هل حصلت على موافقة الشخص لإجراء هذا التحويل؟ + consent_label: لم توفر السجلات الموافقة. + consent_override_label: هل ترغب في تجاوز تعبئة نموذج الموافقة؟ + is_remote_label: هل تقوم بالنقل إلى نظام بعيد؟ + location_label: الموقع + notes_label: ملاحظات -الرجاء ذكر سبب النقل بالإضافة إلى تفاصيل الاجتماعات التي عقدت لمناقشة نقل الحالة + provided_consent_label: لم يتمّ توفير الموافقة في النماذج. + recipient_label: المستلِم + select_label: اختَر... + success: تمّ التحويل بنجاح + transfer_label: هل تريد التحويل على أي حال؟ + user_mandatory: المستلم مطلوب + rejected_reason: سبب الرفض + transfer_assignment: + title: عمليات النقل والتعيينات + transition: + agency_label: الهيئة + assigned_by: تعيين من قِبَل + consent_individual_transfer_value: + true_label: 'نعم' + false_label: 'لا' + consent_overridden_value: + false_label: 'لا' + true_label: 'نعم' + errors: + consent: لم يتمّ توفير الموافقة + to_user_can_receive: لا يستطيع هذا المستخدم استلام هذا السجلّ + individual_consent: هل حصل الإختصاصي الإجتماعي على موافقة الشخص لإجراء هذا التحويل؟ + no_consent_share: تخطّي الموافقة على مشاركة الإعداد؟ + notes: ملاحظات + recipient: المستلِم + rejected: تمّ رفض السبب + requested_by: مطلوب + service_label: الخدمة + responded_at: تمّ الرد في + status: + accepted: تمّت الموافقة + done: استكمال + in_progress: معلّقة + inprogress: معلّقة + rejected: رُفض + revoked: تم الغاء او ملغي + transferred_by: منقول بواسطة + type: + assign: تعيين + reassign: تعيين + referral: إحالة + external_referral: إحالة خارجية + transfer: تحويل + transferRequest: طلب التحويل + user: + agency_office: مكتب الهيئة (موقع العنف المبني على النوع الاجتماعي) + code: 'كود المستخدم ' + disabled: 'مُعطلة ' + email: البريد الإلكتروني + full_name: الاسم الكامل + identity_provider: مزوّد الهويّة + invalid_provider_username: 'صيغة اسم المستخدم غير صالح. مثال: @my.username %{domain}' + label: مستخدم + language: لغة + locale: موضع + location: الموقع + messages: + records_update: يقوم Primero بتحديث سجلات هذا المستخدم لتعكس التغييرات التي أجريتها. قد يستغرق تحديث لوحات المعلومات والتقارير بعض الوقت. + confirmation: 'هل أنت متأكد أنك تريد حذف هذا المستخدم؟ لا يمكن التراجع عن الحذف. انقر فوق موافق لحذف المستخدم. ' + created: تم إنشاء المستخدم بنجاح. + failure: حدث خطأ، يرجى الاتصال بالدعم. + new_confirm_html: أنت على وشك دعوة المستخدم %{username}من %{identity} الذي يتمتّع بدور %{role} لاستخدام Primero. سيتم إرسال بريد إلكتروني للتأكيد إلى %{email}. هل ترغب في المتابعة؟ + new_confirm_non_identity_html: أنت على وشك دعوة المستخدم %{username}الذي يتمتّع بدور %{role} لاستخدام Primero. سيتم إرسال بريد إلكتروني للتأكيد إلى %{email}. هل ترغب في المتابعة؟ + not_found: لم يتم العثور على مستخدم بهذا المُعرف + password_changed_successfully: تغيير كلمة المرور بنجاح + passwords_do_not_match: لا تطابق كلمة المرور الحالية + time_zone_updated: تم تحديث التغيير بنجاح. + updated: تم تحديث المستخدم بنجاح. + created_warning: لقد قمت بإنشاء% {إجمالي _ تمكين} من% {الحد الأقصى _ المستخدمين} المسموح للمستخدمين. + organization: المنظمة + agency: الهيئة + services_help_text: إذا لم تحدّد الخدمات، سيتم منح هذا المستخدم نفس الخدمات التي تتوفر لهيئته. + password_setting: + label: كيف يجب على بريميرو Primero تعيين كلمة مرور المستخدم؟ + self: سوف أقوم بتعيين كلمة المرور + user: سيقوم المستخدم بتعيين كلمة المرور باستخدام البريد الإلكتروني الترحيبي + help_text: يرجى التذكّر أنّه إذا قمت أنت كمسؤول بتعيين كلمة المرور يدويًا، ستحتاج إلى مشاركتها مع المستخدم بطريقة آمنة. + password_reset_header: إرسال بريد إلكتروني لإعادة تعيين كلمة المرور + password_reset_text: إذا قمت بالنقر على "أرسل"، سيتلقى هذا المستخدم بريدًا إلكترونيًا يحتوي على رابط لإعادة تعيين كلمة المرور الخاصة به. + password_reset_request: إرسال بريد إلكتروني لإعادة تعيين كلمة المرور + password: كلمة المرور + password_confirmation: تأكيد كلمة المرور + phone: الهاتف + position: وضع + provider_username_help: 'مثلاً: %{domain}@my.username' + role_id: دور + send_mail: استلام إشعارات عبر الايميل؟ + send_mail_preferences: + label: ما أنواع إشعارات البريد الإلكتروني التي ترغب في تلقيها؟ + help_text: إذا تركت هذا الحقل فارغًا، فستتلقى جميع إشعارات البريد الإلكتروني. + receive_webpush: + label: تلقي الإخطارات؟ + help_text: لاحظ أنك ستظل بحاجة إلى السماح بدفع الإشعارات على متصفح جهازك. + tooltip: يجب عليك أولاً تعديل حسابك وتمكين الإشعارات المباشرة للمستخدم الخاص بك. + receive_webpush_preferences: + label: ما هي أنواع الإشعارات الفورية التي ترغب في تلقيها؟ + help_text: إذا تركت هذا الحقل فارغًا، فستتلقى جميع الإشعارات الفورية. + notification_preferences: + approval_request: 'طلب الموافقة (المديرين)' + approval_response: 'الاستجابة للموافقة (اخصائيون الحالة)' + transition_notification: 'التعيينات والانتقالات والإحالات' + transfer_request: 'طلب نقل' + user_group_unique_ids: مجموعات المستخدمين + user_name: اسم المستخدم + services: الخدمات + welcome_email: + subject: 'مرحبا بكم في %{system}!' + greeting: 'مرحبا بكم في %{system}!' + body_native: 'لقد تمت إضافتك كـ.%{role_name}. يرجى الاتصال بـ%{admin_full_name} (%{admin_email}) للحصول على تعليمات المتابعة لبدء العمل مع%{host}.' + sso: + body: 'قد تمت إضافتك كـ.%{role_name}.' + step1: 'إذهب إلى %{host} وانقر على %{identity_provider}' + step2: 'قم بتسجيل دخول باستخدام حسابك %{identity_provider} %{user_name}' + step3: 'استخدم نفس كلمة المرور التي تستخدمها دائمًا لحسابك %{identity_provider}.' + footer: 'يرجى الاتصال بـ %{admin_full_name} (%{admin_email}) لمزيد من التفاصيل.' + otp: + body: 'قد تمت إضافتك كـ.%{role_name}.' + step1: 'يرجى الاتصال بـ %{admin_full_name} (%{admin_email}) للحصول على اسم المستخدم الخاص بك.' + step2: 'إذهب إلى %{host} وانقر على "تسجيل الدخول باستخدام اسم المستخدم في بريميرو Primero".' + step3: 'تسجيل الدخول باسم المستخدم وكلمة المرور المؤقتة %{otp}.' + step4: 'عند المطالبة، أعد تعيين كلمة المرور الخاصة بك.' + url_label: بريميرو + enabled_label: إرسال رسالة ترحيب عبر البريد الإلكتروني؟ + text_label: نص رسالة الترحيب + password_reset: + subject: 'تعليمات إعادة تعيين كلمة المرور' + email_greeting: "عزيزي%{full_name}" + email_body1: "قدّم أحدٌ ما طلبًا لتعيين كلمة المرور الخاصة بك لـ%{host_href}. انقر فوق الرابط url أدناه للبدء:" + email_body2: "ستنتهي صلاحية هذا الرابط في غضون %{hours} ساعة ويمكن استخدامه مرّة واحدة فقط. يرجى تجاهل هذا البريد الإلكتروني إذا لم تكن قد طلبت إعادة تعيين كلمة المرور أو لم يتمّ تسجيل مستخدم Primero جديد نيابة عنك. في حالة انتهاء صلاحية الرابط أعلاه، يرجى النقر على %{reset_request_href} لإعادة إرسال طلب إعادة تعيين كلمة المرور." + email_body_link: هنا + request_submitted: "تم إرسال طلب إعادة تعيين كلمة المرور" + success: "تمّ تغيير كلمة المرور بنجاح" + errors: + reset_password_token: "كود إعادة تعيين كلمة المرور غير صالح" + password_confirmation: "يجب أن تتطابق كلمات المرور" + onboard_email: + subject: "الإنضمام إلى %{system}" + greeting: "عزيزي%{full_name}،" + body1: "مرحبا بكم في بريميرو!" + body2: "لقد تم تعيينك كمسؤول منفذ لـ%{host_href}، %{reset_notification}" + body2_reset_notification: "ستتلقى رسالة بريد إلكتروني إضافية تطالبك بإعادة تعيين كلمة المرور الخاصة بك." + body3: "أنت مسؤول عن ضمان التنفيذ الآمن وفي الوقت المناسب. لكلّ عملية مطروحة، يجب أن تكون قد أكملت خطة التنفيذ مع إستراتيجية إدارة المستخدم والإنضمام وبروتوكول مشاركة المعلومات. أنت مسؤول أيضًا عن ضمان توقيع شروط الاستخدام من قبل جميع المنظمات المُستخدمة ووضع الشروط الموقعة في ملفّ المنظمات." + user_group: + associated_agencies: الهيئات المرتبطة بمجموعة المستخدمين هذه + description: الوصف + disabled: + explanation: إذا قمت بتعطيل مجموعة المستخدمين هذه، لن تتمكن من تعيينها إلى حسابات المستخدمين. + label: 'مُعطلة ' + messages: + created: تم إنشاء مجموعة المستخدمين بنجاح. + updated: تم تحديث مجموعة المستخدمين بنجاح. + name: الاسم + user_groups: + label: مجموعات المستخدم + users: + label: المستخدمين + headers: + full_name: الاسم الكامل + user_name: اسم المستخدم + position: الوظيفة + agency: الهيئة + alerts: + total_users_created: 'لقد قمت بإنشاء% {إجمالي _ تمكين} من التطبيق % {الحد الأقصى _ المستخدمين} ' + limit_user_reached: لقد وصلت إلى حد% {الحد الأقصى _ المستخدمين} للمستخدمين. يجب عليك تعطيل مستخدم واحد أو أكثر قبل إنشاء المزيد. + limit_user_reached_on_enable: لقد وصلت إلى الحد الأقصى للمستخدمين %{maximum_users} . يجب عليك تعطيل مستخدم واحد أو أكثر قبل إنشاء أو تمكين المزيد. + devise: + failure: + already_authenticated: "انت مُسجّل مسبقا." + invalid: "%{authentication_keys} أو كلمة مرور غير صالحين." + locked: "حسابك مقفل." + last_attempt: "لديك محاولة أخرى قبل أن يتمّ اقفال حسابك." + admin: + locations: + selected_records: '%{select_records} الموقع (المواقع) المحدد/ة' + selected_all_records: اختيار كلّ %{total_records}الحالات التي تطابق هذا الاستعلام. + updated: '%{updated_records} تحديث الموقع(المواقع)' + push_notifications_dialog: + title: إشعارات الجهاز + body_blocked: + message: لقد قمت بحظر إشعارات Primero على هذا الجهاز. لإصلاح هذه المشكلة، ستحتاج إلى تشغيل إشعار الأذونات. + android: "أندرويد: انتقل إلى الإعدادات. انقر على التطبيقات. ابحث عن Primero في قائمة التطبيقات وانقر فوقه. انقر فوق الإخطارات. قم بتبديل مفتاح التبديل للإشعارات إلى وضع التشغيل." + ios: "iOS: انتقل إلى تطبيق الإعدادات. انقر على الإخطارات. قم بالتمرير لأسفل إلى قائمة التطبيقات وابحث عن Primero. قم بتبديل مفتاح التبديل لـ Primero إلى وضع التشغيل." + body: + zero: '0' + one: '1' + two: '2' + few: قليل + many: كثير + other: هل تريد السماح لـ Primero بإرسال إشعارات لك ؟ تذكر أنك ستستمر في تلقي الإشعارات على هذا الجهاز بعد%{count} أيام من تسجيل الخروج. هذا غير موصى به للأجهزة المستخدمة من قبل اكثر من شخص. diff --git a/config/locales/am-ET.yml b/config/locales/am-ET.yml index 0f0b90fc2e..51ed37de78 100644 --- a/config/locales/am-ET.yml +++ b/config/locales/am-ET.yml @@ -4,7 +4,9 @@ am-ET: accepted: ተቀባይነት አግኝቷል cancel: ተሰርዟል connection_lost: የኢንተርኔት መስመሩ ተቋርጧል + field_mode_offline: አሁን በስራ ሞድ ላይ ነው connected: ከኢንተርኔት ጋር ተገናኝቷል + no_connection: ግንኙነት የለም clear: ግልጽ ነው sandbox_ui: ማሳያ description: መግለጫ @@ -12,21 +14,25 @@ am-ET: minimum_reportable_fields: "በሪፖርቱ መካተት ያለባቸው ጉዳዮች%{record_type} " name: ስም offline: ከኢንተርኔት ውጪ + field_mode: " በስራ ሞድ ላይ ነው {1}" + field_mode_on: "በርቷል


" + field_mode_off: "ጠፍቷል" unavailable_offline: ኢንተርኔት የለም online: መስመር ላይ yes_label: 'አዎ' or_label: ወይም select_provider: አገልገግሎት ሰጪውን ይምረጡ select_language: ቋንቋ ይምረጡ - log_in_primero_idp: "የተጠቃሚውን 1% {ስም} መዝግበው ይግቡ" - offline_submitted_changes: "ከኢንተርኔት ግንኙነት ውጭ ነዎት፡፡ ያደረጉት ለውጥ ኢንተርኔት ሲያገኙ ይላካል፡፡ " + log_in_primero_idp: የተጠቃሚውን 1% {ስም} መዝግበው ይግቡ + offline_submitted_changes: 'ከኢንተርኔት ግንኙነት ውጭ ነዎት፡፡ ያደረጉት ለውጥ ኢንተርኔት ሲያገኙ ይላካል፡፡ ' updated: ተሻሽላል/ዘምናል + go: ቀጥል + select_idp_error: እባክዎ ሰጭውን ይምረጡ sync: success: "%{records}የተመዘገበው መረጃ በተሳካ ሁኔታ ገብቷ" error: - create: "ለመፍጠር አልተቻለም%{record_type}፡፡ እባክዎ እርዳታ ይጠይቁ፡፡" - update: "ማዘመኑ %{record_type}%{short_id}ውድቅ ተደርጓል፡፡ እባክዎ እርዳታ ይጠይቁ፡፡" - + create: ለመፍጠር አልተቻለም%{record_type}፡፡ እባክዎ እርዳታ ይጠይቁ፡፡ + update: ማዘመኑ %{record_type}%{short_id}ውድቅ ተደርጓል፡፡ እባክዎ እርዳታ ይጠይቁ፡፡ actions: approvals: አጽዳቂዎች button: ድርጊቶች @@ -49,12 +55,14 @@ am-ET: services_section_from_case: አገልግሎት ጨምር mark_for_offline: ከኢንተርኔት ውጭ ምልክት አድርግ agencies: - label: "ተቋም/ድርጅት\n " + label: 'ተቋም/ድርጅት + +  ' translations: manage: ትርጉሞችን ያመቻቹ agency: agency_logos: የድርጅቱ/ተቀም አርማ - code: "የድርጅቱ ኮድ " + code: 'የድርጅቱ ኮድ ' description: መግለጫ disabled: የማይሰራ exclude_agency_from_lookups: ይህን ድርጅት/ተቃም ከምልከታና ከማጣራት ፈቃድ ውጪ ማድረግ @@ -65,28 +73,28 @@ am-ET: logo_icon: ልዩ ምልክት logo_icon_help: ይሄ በትንሽ ስክሪን መጠኖች፣ ታብሌቶች እና ስልኮች ላይ ይታያል። ይህ ካሬ መሆን አለበት logo_large: ትልቅ አርማ - logo_large_help: "ይህ በትላልቅ የስክሪን መጠኖች እና በፒዲኤፍ ወደ ውጭ በሚላኩ ነገሮች ላይ ይታያል። ይህ አራት ማዕዘን መሆን አለበት, ርዝመቱ ከቁመቱ ይረዝማል." + logo_large_help: ይህ በትላልቅ የስክሪን መጠኖች እና በፒዲኤፍ ወደ ውጭ በሚላኩ ነገሮች ላይ ይታያል። ይህ አራት ማዕዘን መሆን አለበት, ርዝመቱ ከቁመቱ ይረዝማል. messages: created: ድርጅት በተሳካ ሁኔታ ተፈጥራል/ተመዝግባል updated: ኤጀንሲ በተሳካ ሁኔታ ዘምናል። name: የኤጀንሲው/ተቃም ስም - pdf_logo_option: "አርማውን በPDF መልኩ አዘጋጅ?" + pdf_logo_option: አርማውን በPDF መልኩ አዘጋጅ? pdf_logo_option_help: 'ማሳሰቢያ፡ የተጠቃሚ ኤጀንሲ ሎጎዎች በአንድም በሌላ አንደሚገኙ ይታወቃል፣ስለዚህ እርስዎ ይህ አርማ ለሁሉም ተጠቃሚዎች እንዲገኝ ከፈለጉ ብቻ ነው የሚያረጋግጡት።' services: የኤጀንሲ/ተቛም አገልግሎት terms_of_use: የአጠቃቀም ስምምነት terms_of_use_help: ፒዲኤፍ ፋይል ብቻ የተፈቀዳ terms_of_use_download_button: ፒዲኤፍ አውርድ - terms_of_use_enabled: "የአጠቃቀም ስምምነት አሳይ?" + terms_of_use_enabled: የአጠቃቀም ስምምነት አሳይ? approvals: approved_by: ያጸደቀው case_plan_type_label: የድጋፍ እቅድ አይነት manager_comments_label: የማኔጀር አስተያየቶች rejected_by: ውድቅ ያደረገው requested_by: ጠያቂው/ዋ - requested_for_label: "እንዲጸድቅ የተጠየቀለት " + requested_for_label: 'እንዲጸድቅ የተጠየቀለት ' requested_for_title: እንዲጸድቅ የተጠየቀ - response_for_label: "ለማጽደቅ " - response_for_title: "ማጽደቅ " + response_for_label: 'ለማጽደቅ ' + response_for_title: 'ማጽደቅ ' action_plan: የድርጊት መርሀግብር gbv_closure: የጾታዊ ጥቃት ጉዳይ መዝጋት status: @@ -108,7 +116,7 @@ am-ET: status: ያለበት ሁኔታ form_export: label: የአቀማመጥ ፎርም - include_hidden: "የማይታዩ ቅጾችን እና መስኮችን ያካትቱ?" + include_hidden: የማይታዩ ቅጾችን እና መስኮችን ያካትቱ? file_name: የራስዎን የፋይል ስም ይፍጠሩ (እንደ አማራጭ) success_message: ወደ የሚላከው ፋይል በተሳካ ሁኔታ ፈጥሯል። buttons: @@ -131,12 +139,12 @@ am-ET: check_status: ያለበትን ሁኔታ ያረጋግጡ clear_default: ባለበት ያጽዱ clear_selection: የተመረጠውን ያጥፉ - clear: " ያጥፉ" + clear: ' ያጥፉ' close: መዝጋት continue: ይቀጥሉ create_case: የጉዳይ/ኬዝ ይፍጠሩ create_incident: ድርጊት መፍጠር - create_new_record: "አዲስ ፍጠር%{model}" + create_new_record: አዲስ ፍጠር%{model} delete: አጥፋ disable: የማይሰራ disable_photo_wall: ፎቶዎችን አጥፋ @@ -152,7 +160,7 @@ am-ET: filter_label: 'ማጣራት' filter_restore: ወደ ስርዓት መመለስ find_tracing_match: አዛምድ - flag_model: "ጥቆማ/ማሳያ%{model}" + flag_model: ጥቆማ/ማሳያ%{model} flag_records: ጥቆማ/ማሳያ flags: ጥቆማ/ማሳያ guidance: መመሪያ @@ -174,39 +182,77 @@ am-ET: request_transfer: ለማዘዋወር መጠየቅ reunite: እንደገና መዋሀድ save: መዝግቦ ማስቀመጥ - save_and_add_service_provision: " የአገልግሎት አሰጣጥ መጨመርና መዝግቦ ማስቀመጥ " + save_and_add_service_provision: ' የአገልግሎት አሰጣጥ መጨመርና መዝግቦ ማስቀመጥ ' save_and_return: መዝግቦ ማስቀመጥ እና ተመለስ save_continue: መዝግቦ ማስቀመጥና ቀጥል save_changes: ለውጡን መዝግበህ አስቀምጥ - select: "ምረጥ\n " + select: 'ምረጥ + +  ' send: ላክ/ኪ sort_by_case: ጉዳይ sort_by_tr: የፍለጋ ጥያቄ sync: አመሳክር submit: አስረክብ transfer: ማዘዋወር/ማስተላለፍ - unflag_model: "ከጥቆማ/ማሳያ ማስወገድ%{model}" - unflag_model_history: "የምልክት ብዛት%{model}" - unmark_for_mobile: "የሞባይል ምልክት አስወግድ\n " - update: "አሻሽል/አዘምን\n " - view: "እይታ\n " - view_flags_history: "ታሪኮችን ተመልከት\n " - return_to_case: "ወደጉዳይ መመለስ\n " + unflag_model: ከጥቆማ/ማሳያ ማስወገድ%{model} + unflag_model_history: የምልክት ብዛት%{model} + unmark_for_mobile: 'የሞባይል ምልክት አስወግድ + +  ' + update: 'አሻሽል/አዘምን + +  ' + view: 'እይታ + +  ' + view_flags_history: 'ታሪኮችን ተመልከት + +  ' + return_to_case: 'ወደጉዳይ መመለስ + +  ' + enable_webpush: የሞባይል ማሳወቂያ + dialog_yes: "አወ" + resync_records: + id: መለያ + record_type: የምዝገባ ወይም ቅጅ አይነት + action: ተግባር + date: ቀን + last_attempt: ያለፈ ሙከራ + create: መፍጠር + update: ማዘመን + resync: አስረክብ case: label: ጉዳይ - create_new_case: "አዲስ ጉዳይ\n ፍጠር" - add_new: "አዲስ ጨምር\n " + create_new_case: 'አዲስ ጉዳይ + +  ፍጠር' + create_case: 'አዲስ ጉዳይ + +  ፍጠር' + create: መፍጠር + add_new: 'አዲስ ጨምር + +  ' + back_to_family_details: ወደ ቤተሰብ ዝርዝር ተመለስ back_to_case: ወደ ጉዳይ ተመለስ - back_to_results: "ወደ ውጤት\n  ተመለስ" + back_to_results: 'ወደ ውጤት + +   ተመለስ' back_to_search: ወደ ፍለጋ ተመለስ search_by: ፈላጊ - search_for: "ፍለጋ ለ%{record_type}" - results: "ውጤቶች\n " - details: "ዝርዝሮች\n " + search_for: ፍለጋ ለ%{record_type} + results: 'ውጤቶች + +  ' + details: 'ዝርዝሮች + +  ' select: ምረጥ deselect: አትምረጥ enter_id_number: ነባር መዝገብ ለመፈለግ የመለያ ቁጥሩን ያስገቡ - id_search_no_results: "በስርዓቱ ውስጥ የሚገናኝ ምንም ተዛማጅ የለም%{search_query}. እባክዎ አዲስ መዝገብ ይፍጠሩ።" + id_search_no_results: በስርዓቱ ውስጥ የሚገናኝ ምንም ተዛማጅ የለም%{search_query}. እባክዎ አዲስ መዝገብ ይፍጠሩ። messages: disabled: ጉዳዩ አይሰራም/ጠፍቷል  update_success: 'ጉዳዩ %{record_id}በተሳካ ሁኔታ ተሻሽሏል።' @@ -217,24 +263,50 @@ am-ET:  ተፈጥሯል።' already_matched: ይህ ጠያቂ አስቀድሞ ከጉዳይዎ ጋር ተመሳስሏል። already_matched_not_current_case: በስርዓቱ ውስጥ ከዚህ ጠያቂ ጋር የተዛመደ ጉዳይ አለ። - not_found_case: "ከ\"%{search_value}\" ጋር የሚዛመድ ምንም ጉዳይ አልተገኘም። አዲስ ጉዳይ ይፍጠሩ።" + not_found_case: ከ"%{search_value}" ጋር የሚዛመድ ምንም ጉዳይ አልተገኘም። አዲስ ጉዳይ ይፍጠሩ። introductory_sentence: እባክዎን የግለሰቡን የጉዳይ አስተዳደር አገልግሎቶችን ለመቀበል እና የጉዳይ አያያዙን በፕሪሜሮ ውስጥ እንዲቀመጥ የግለሰቡን ፍቃድ ይግለጹ። consent_agreements_required: እባክዎ ከፈቃድ ስምምነቶች ውስጥ ቢያንስ አንድ አማራጭ ይምረጡ። legitimate_basis_required: እባክዎ ከህጋዊ መሰረት ምደባዎች ቢያንስ አንድ አማራጭ ይምረጡ - save: "ጉዳዮችን መዝግበው ያስቀምጡ\n " + confirm_create_case: ለዚህ ህጻን ኬዝ መክፈት ትፈልጋለህ + case_referral_pending: የጉዳይ ቅብብሎሽ በጅምር ላይ ነው + case_transfer_pending: የጉዳይ ማሸጋገር በጅምር ላይ ነው + case_no_approval_request: የማጽደቅ ጥያቄ ለዚህ ጉዳይ አልቀረበም + bulk_assign_limit: በአንዴ ከ100 በላይ ጉዳይ መመደብ አትችልም + bulk_assign_limit_try_again: በአንዴ ከ100 በላይ ጉዳይ መመደብ አትችልም 100 እና ከዛ በታች መድብ + referral_rejected: ቅብብሎሽ ውድቅ ተደርጓል + transfer_request_made: ይህ ጉዳይ ወደ ሌላ ለማሸጋገር ተጠይቋል

  + save: 'ጉዳዮችን መዝግበው ያስቀምጡ + +  ' save_text: ከመቀጠልዎ በፊት እባክዎ ለውጦችዎን በጉዳዩ ላይ መዝግበው ያስቀምጡ። skip_and_create: ይዝለሉ እና አዲስ ጉደይ ይፍጠሩ search_existing: ያሉትን ጉዳዮች ይፈልጉ - search_helper_text: "ለምን? የተደጋገሙ ጉዳዮች እንዳይፈጠሩ ለመከላከል.\n " - consent_agreements: "የሚመለከተውን ሁሉንም የስምምነት ፎርሞች\n  ይምረጡ" + search_helper_text: 'ለምን? የተደጋገሙ ጉዳዮች እንዳይፈጠሩ ለመከላከል. + +  ' + consent_agreements: 'የሚመለከተውን ሁሉንም የስምምነት ፎርሞች + +   ይምረጡ' legitimate_basis: የሚመለከተውን ሁሉንም መሰረታዊ ትክክለኛ ምድቦችን ይምረጡ + family_linked_subform_delete_disabled: 'በዚህ ንዑስ ቅጽ ከተመዘገበ የቤተሰብ መረጃ ጋር ተገናኝቷል፡፡ እባክዎን ይህን የቤተሰብ መረጃ ያጥፉት ወይም አታገናኛኘው + + +  ' workflow: - assessment: "ዳሰሳ\n " - case_plan: "የድጋፍ ዕቅድ\n " + assessment: 'ዳሰሳ + +  ' + case_plan: 'የድጋፍ ዕቅድ + +  ' closed: መዝጋት created_on: "የተፈጠረው \n " - in_progress: "በሂደት ላይ\n " - new: "አዲስ\n " + in_progress: 'በሂደት ላይ + +  ' + new: 'አዲስ + +  ' on_label: 'ላይ' reopened: እንደገና ተከፍቷል። service_implemented: አገልግሎት ተሰጥ። @@ -247,14 +319,23 @@ am-ET: rejected_transfer: '%{to}ተቀባይነት ያላገኘ%{record_type}%{record_id}ከ%{from}' cases: action_plan: የድርጊት መርሀግብር + access_denied: "ይህን ፋይል ማግኘት አትችልም\n\n " age: ዕድሜ age_estimated: "ግምታዊ እድሜ \n " - agency: "ተቋም/ድርጅት\n " + agency: 'ተቋም/ድርጅት + +  ' apply_filter: መተግበር - approval_comments: "አስተያየቶች\n " - approval_radio: "እፈልጋለሁ\n " - approval_radio_accept: "ማጽደቅ " - approval_radio_reject: "አለማጽደቅ\n " + approval_comments: 'አስተያየቶች + +  ' + approval_radio: 'እፈልጋለሁ + +  ' + approval_radio_accept: 'ማጽደቅ ' + approval_radio_reject: 'አለማጽደቅ + +  ' approval_select: ቅጽ ለ approved_success_action_plan: '%{approval_label}ጸድቋል' approved_success_assessment: '%{approval_label}{ጸድቋል}' @@ -263,28 +344,49 @@ am-ET: approved_success_closure: '{ጸድቋል}' approved_success_gbv_closure: '{ጸድቋል} ' assessment: ዳሰሳ - case_opening_date: "የጉዳይ መክፈቻ ቀን\n " + case_opening_date: 'የጉዳይ መክፈቻ ቀን + +  ' case_plan: የድጋፍ ዕቅድ - case_worker_code: "የጉዳይ አያያዝ ባለሙያ መለያ ቁጥር\n " + case_worker_code: 'የጉዳይ አያያዝ ባለሙያ መለያ ቁጥር + +  ' clear_filter: ማስወገድ7ማጽዳት close_dialog: አዎ የሚለውን መጫን የዚህን ጉዳይ ሁኔታ ይዘጋዋል - close_dialog_title: "ጉዳይ መዝጋት\n \n " + close_dialog_title: 'ጉዳይ መዝጋት + +   + +  ' close_success: በተሳካ ሁኔታ ጉዳዩ ተዘግቷል - closure: "መዝጋት\n " + closure: 'መዝጋት + +  ' + complete: ከመስመር ውጭ ይሰራል/ ዳታ ሣይበራ date_of_birth: የትውልድ ቀን disable_dialog: አዎ የሚለውን መጫን ይህን ጉዳይ እንዳይሰራ ያደርገዋል disable_dialog_title: "ጉዳዩ እንዳይሰራ ማድረግ \n " - disable_success: "ጉዳዩ እንዳይሰራ ተደርጓል\n " + disable_success: 'ጉዳዩ እንዳይሰራ ተደርጓል + +  ' enable_dialog: አዎ የሚለውን መጫን ይህን ጉዳይ እንዲሰራ ያደርገዋል - enable_dialog_title: "ጉዳዩ እንዲሰራ አድርግ\n " - enable_success: "ጉዳዩ በሚገባ እንዲሰራ ተደርጓል\n " - export: "ወደሌላ ማሸጋገር\n " + enable_dialog_title: 'ጉዳዩ እንዲሰራ አድርግ + +  ' + enable_success: 'ጉዳዩ በሚገባ እንዲሰራ ተደርጓል + +  ' + export: 'ወደሌላ ማሸጋገር + +  ' mark_for_offline: title: ከኢንተርኔት ውጭ ምልክት አድርግ - text: "እርግጠኛ ነዎት ከኢንተርኔት ውጭ በሚሆኑበት ጊዜ እነዚህን ጉዳዮች ለመጠቀም ምልክት ማድረግ ይፈልጋሉ?" + text: እርግጠኛ ነዎት ከኢንተርኔት ውጭ በሚሆኑበት ጊዜ እነዚህን ጉዳዮች ለመጠቀም ምልክት ማድረግ ይፈልጋሉ? success: ጉዳዮች በተሳካ ሁኔታ ከኢንተርኔት ውጭ ለመጠቀም ምልክት ተደርጎባቸዋል filter_by: - 3month_inactivity: "ለ3 ወር በላይ\n " + 3month_inactivity: 'ለ3 ወር በላይ + +  ' action_plan: የድርጊት መርሀግብር age_0_5: 0-5 age_12_17: 12-17 @@ -297,60 +399,132 @@ am-ET: approved: ጸድቋል pending: በእንጥልጥል ላይ ያለ rejected: ውድቅ ተደርጓል - bia: "የህጻን ጥቅምና ደህንነት ዳሰሳ\n " - by_date: "በቀን\n " - case_open_date: "ጉዳይ የሚከፈትበት ቀን\n " + bia: 'የህጻን ጥቅምና ደህንነት ዳሰሳ + +  ' + by_date: 'በቀን + +  ' + case_open_date: 'ጉዳይ የሚከፈትበት ቀን + +  ' case_plan: የድጋፍ ዕቅድ - closed: "ተዘግቷል\n " + closed: 'ተዘግቷል + +  ' closure: ጉዳይ መዝጋት - current_location: "አሁን ያለበት አድራሻ\n " - date: "ቀን\n " - displacement_status: "የመፈናቀል ሁኔታ\n " - district: "ወረዳ\n " - duplicate: "ድግግሞሽ\n " + current_location: 'አሁን ያለበት አድራሻ + +  ' + date: 'ቀን + +  ' + displacement_status: 'የመፈናቀል ሁኔታ + +  ' + district: 'ወረዳ + +  ' + duplicate: 'ድግግሞሽ + +  ' enabled_disabled: እንዲሰራ ማድረግ/ እንዲሰራ አለማድረግ - female: "ሴት\n " - flag: "ምልክት ተደርጎበታል\n " - flag_label: "ምልክት ተደርጎበታል?\n " + female: 'ሴት + +  ' + flag: 'ምልክት ተደርጎበታል + +  ' + flag_label: 'ምልክት ተደርጎበታል? + +  ' gbv_closure: የጾታዊ ጥቃት ጉዳይ መዝጋት high: ከፍተኛ low: ዝቅተኛ - male: "ወንድ\n " + male: 'ወንድ + +  ' medium: መካከለኛ - mobile: "ስልክ\n " - mobile_label: "ለሞባይል ምልክት ተደርጓልን?\n " - my_cases: "የኔ ጉዳይ\n " + mobile: 'ስልክ + +  ' + mobile_label: 'ለሞባይል ምልክት ተደርጓልን? + +  ' + my_cases: 'የኔ ጉዳይ + +  ' no_action: ድርጊት የለም - no_activity: "የተከናወነ ተግባር የለም\n " + no_activity: 'የተከናወነ ተግባር የለም + +  ' open: ክፈት - other: "ሌላ\n " - photo: "ፎቶ\n " - photo_label: "ፎቶ አለን?\n " - protection_concerns: "የጥበቃ ስጋት\n " - protection_status: "የጥበቃ ሁኔታ\n " + other: 'ሌላ + +  ' + photo: 'ፎቶ + +  ' + photo_label: 'ፎቶ አለን? + +  ' + protection_concerns: 'የጥበቃ ስጋት + +  ' + protection_status: 'የጥበቃ ሁኔታ + +  ' record_state: "የምዝገባ \n " - referred_cases: "ጉዳዩ ወደ እኔ ተላልፏል\n " - registration_date: "የምዝገባ ቀን\n " - risk_level: "የስጋት ደረጃ\n " - sex: "ጾታ\n " + referred_cases: 'ጉዳዩ ወደ እኔ ተላልፏል + +  ' + registration_date: 'የምዝገባ ቀን + +  ' + risk_level: 'የስጋት ደረጃ + +  ' + sex: 'ጾታ + +  ' social_worker: የጉዳይ አያያዝ ባለሙያ - status: "ሁኔታ\n " - transferred: "ተዘዋውረዋል\n " - type_of_risk: "የስጋት አይነት\n \n " + status: 'ሁኔታ + +  ' + transferred: 'ተዘዋውረዋል + +  ' + type_of_risk: 'የስጋት አይነት + +   + +  ' urgent_protection_concern: አስቸኳይ የጥበቃ ምላሽ የሚሹ - user_group: "የተጠቃሚዎች ቡድን\n " - workflow: "የጉዳዮች የስራ ፍሰት\n " + user_group: 'የተጠቃሚዎች ቡድን + +  ' + workflow: 'የጉዳዮች የስራ ፍሰት + +  ' flag_summary: የጥቆማ ማጠቃለያ - full_name: "ሙሉ ስም\n " + full_name: 'ሙሉ ስም + +  ' gbv_closure: የጾታዊ ጥቃት ጉዳይ መዝጋት - hide_name: "ስሙን ደብቅ\n " + hide_name: 'ስሙን ደብቅ + +  ' hide_name_error: ለውጦችዎን በሚያስቀምጡበት ጊዜ ስህተት ተፈጥሯል። እባክዎ ዳግም ይሞክሩ. - id: "መለያ ቁጥር\n " + id: 'መለያ ቁጥር + +  ' label: ጉዳዮች my_filters: የኔ ማጣርያ name: ስም notes_dialog_title: ማስታወሻ ያስቀምጡ - notes_form_notes: "ማስታወሻዎች\n " + notes_form_notes: 'ማስታወሻዎች + +  ' notes_form_subject: ባለቤት ok: እሽ order_by: @@ -365,13 +539,25 @@ am-ET: tracing_message: 'ማስታወሻ፤ ይህን ህጻን ከሚፈልግ ጠያቂ ጋር ተዛማጅ መረጃ አለ። በመሆኑም ለተጨማሪ ስራ የህጻኑ ፍላጎት ከሆነ ጉዳዩን የያዘው የጉዳይ አያያዝ ባለሙያውን ያግኙና ያናግሩ    ' - referral_done: "'ተከናውኗል' የሚለውን ከተጫኑ  ከዚህ ጉዳይ ጋር የተያያዘውን የሪፈራል ስራ እንደጨረሱ ያሳያል። አንዴ 'ተከናውኗል' የሚለውን ከተጫኑ ይህንን መረጃ ማግኘት አይችሉም\n " - referral_done_success: "ቅብብሎሽ ተደርጓል\n " + referral_done: '''ተከናውኗል'' የሚለውን ከተጫኑ  ከዚህ ጉዳይ ጋር የተያያዘውን የሪፈራል ስራ እንደጨረሱ ያሳያል። አንዴ ''ተከናውኗል'' የሚለውን ከተጫኑ ይህንን መረጃ ማግኘት አይችሉም + +  ' + referral_done_success: 'ቅብብሎሽ ተደርጓል + +  ' referral_accepted_header: "ቅብብሎሹን መቀበል \n " - referral_accepted: "እርግጠኛ ነዎት? ከቅብብሎሽ ጋር በተያያዘ ስራ ለመፈጸም ሃላፊነት አለብዎት\n " + referral_accepted: 'እርግጠኛ ነዎት? ከቅብብሎሽ ጋር በተያያዘ ስራ ለመፈጸም ሃላፊነት አለብዎት + +  ' referral_accepted_success: ቅብብሎሹ ተቀባይነት አግኝተዋል - referral_rejected: "' ውድቅ ማድረግ' የሚለውን ከተጫኑ በዚህ ጊዜ ለቅብብሎሽ ሃላፊነት ለመቀበል ዝግጁ እንዳልሆናችሁ እያሳያችሁ ነው። እባክዎ ይህንን ቅብብሎሽ ውድቅ ያደረጉበትን ምክንያት ያሳዩ። አንዴ 'ውድቅ ማድረግ'  የሚለውን ከተጫኑ ዳግም ወደዚህ ጉዳይ መመለስ አይችሉም።\n\n " - referral_rejected_success: "ቅብብሎሹ ውድቅ ተደርጓል\n\n " + referral_rejected: ''' ውድቅ ማድረግ'' የሚለውን ከተጫኑ በዚህ ጊዜ ለቅብብሎሽ ሃላፊነት ለመቀበል ዝግጁ እንዳልሆናችሁ እያሳያችሁ ነው። እባክዎ ይህንን ቅብብሎሽ ውድቅ ያደረጉበትን ምክንያት ያሳዩ። አንዴ ''ውድቅ ማድረግ''  የሚለውን ከተጫኑ ዳግም ወደዚህ ጉዳይ መመለስ አይችሉም። + + +  ' + referral_rejected_success: 'ቅብብሎሹ ውድቅ ተደርጓል + + +  ' register_new_case: አዲስ ጉዳይ registration_date: የምዝገባ ቀን rejected_success_action_plan: '%{approval_label}አልጸደቀም' @@ -385,72 +571,129 @@ am-ET: reopen_success: ጉዳዩ በተሳካ ሁኔታ ዳግም ተከፍቷል request_approval_failure: ስህተት ተፍጥሯል እባክዎ ድጋፍ ይጠይቁ request_approval_select: ለማጸደቅ ይጠይቁ - request_approval_success_action_plan: "ከ%{approval_label}ለማጸደቅ ተጠይቋል" - request_approval_success_assessment: "ለማጽደቅ ተጠይቋል%{approval_label}ከ።" - request_approval_success_case_plan: "ለማጽደቅ ተጠይቋል%{approval_label}ከ።" - request_approval_success_closure: "ለማጽደቅ ተጠይቋል%{approval_label}ከ።" - request_approval_success_gbv_closure: "ለማጽደቅ ተጠይቋል%{approval_label}ከ።" + request_approval_success_action_plan: ከ%{approval_label}ለማጸደቅ ተጠይቋል + request_approval_success_assessment: ለማጽደቅ ተጠይቋል%{approval_label}ከ። + request_approval_success_case_plan: ለማጽደቅ ተጠይቋል%{approval_label}ከ። + request_approval_success_closure: ለማጽደቅ ተጠይቋል%{approval_label}ከ። + request_approval_success_gbv_closure: ለማጽደቅ ተጠይቋል%{approval_label}ከ። request_approval_type_of_case_plan: የጉዳይ እቅድ የማጽደቅ አይነት - request_approve_action_plan: "የድርጊት መርሃ ግብር ማጽደቅ?\n " - request_approve_bia: "የዳሰሳ ጥናት ማጽደቅ?\n " - request_approve_case_plan: "የድጋፍ እቅድ ማጽደቅ?\n " - request_approve_closure: "ጉዳይ መዝጋትን ማጽደቅ?\n " - request_approve_gbv_closure: "የፆታዊ ጥቃት ጉዳይ መዝጋትን ማጽደቅ\n " - revoke_failure: "ሲዘረዝ ስህተት ተፈጥሯል %{transition_type} እባክዎ ተጨማሪ ድጋፍ ይጠይቁ\n " - revoke_message: "ሰርዝ የሚለውን በመጫን ተቀባዩ ጉዳዩን ማግኘት እንዳይችል ያደርጋል%{transition_type}\n " - revoke_success_message: "ጉዳዩ %{case_id}%{transition_type}ለ%{recipient_username}ተሽሯል" + request_approve_action_plan: 'የድርጊት መርሃ ግብር ማጽደቅ? + +  ' + request_approve_bia: 'የዳሰሳ ጥናት ማጽደቅ? + +  ' + request_approve_case_plan: 'የድጋፍ እቅድ ማጽደቅ? + +  ' + request_approve_closure: 'ጉዳይ መዝጋትን ማጽደቅ? + +  ' + request_approve_gbv_closure: 'የፆታዊ ጥቃት ጉዳይ መዝጋትን ማጽደቅ + +  ' + revoke_failure: 'ሲዘረዝ ስህተት ተፈጥሯል %{transition_type} እባክዎ ተጨማሪ ድጋፍ ይጠይቁ + +  ' + revoke_message: 'ሰርዝ የሚለውን በመጫን ተቀባዩ ጉዳዩን ማግኘት እንዳይችል ያደርጋል%{transition_type} + +  ' + revoke_success_message: ጉዳዩ %{case_id}%{transition_type}ለ%{recipient_username}ተሽሯል save_filter: መዝግቦ ማስቀመጥ - selected_all_records: "ከዚህ ጥያቄ ጋር የሚገናኙ ሁሉም ጉዳዮችን ምረጥ%{total_records}\n " + selected_all_records: 'ከዚህ ጥያቄ ጋር የሚገናኙ ሁሉም ጉዳዮችን ምረጥ%{total_records} + +  ' selected_records: '%{select_records}ጉዳዩ(ዮች) ተመርጧል' sex: ጾታ show_case: 'የጉዳዩ መለያ ቁጥር%{short_id}' - social_worker: "የጉዳይ አያያዝ ባለሙያ\n " + social_worker: 'የጉዳይ አያያዝ ባለሙያ + +  ' status: ሁኔታ summary: - label: "ማጠቃለያ\n " - find_match: "ተዛማጅ/ግንኙነት ያላቸውን አግኝ\n " + label: 'ማጠቃለያ + +  ' + find_match: 'ተዛማጅ/ግንኙነት ያላቸውን አግኝ + +  ' matched_trace: 'ተዛማጅ #%{trace_id}' - cannot_find_matches: "ተዛማጆችን ማግኘት አልተቻለም። ከህጻኑ ጋር ግንኙነት ያላቸውን መረጃዎች ለመፈለግ ፈቃድና ይሁንታ አልተሰጠም።\n " - matched: "ተዛምዷል\n " + cannot_find_matches: 'ተዛማጆችን ማግኘት አልተቻለም። ከህጻኑ ጋር ግንኙነት ያላቸውን መረጃዎች ለመፈለግ ፈቃድና ይሁንታ አልተሰጠም። + +  ' + matched: 'ተዛምዷል + +  ' fields: consent_for_tracing: - label: "ከህጻኑ ጋር ተዛማጅነት ያላቸውን መረጃዎች ለመፈለግና ለማገናኘት ፈቃድና ይሁንታ ተወስዷል\n " + label: 'ከህጻኑ ጋር ተዛማጅነት ያላቸውን መረጃዎች ለመፈለግና ለማገናኘት ፈቃድና ይሁንታ ተወስዷል + +  ' help_text: ይህ ቦታ 'አይደለም' ከሆነ፣ የህጻኑ የጉዳይ መዝገብ ከፍለጋ ጥያቄ አቅራቢዎች ጋር ለማዛመድ የሚታይ ነገር የለም። wishes_child_family_tracing: - label: "ህጻኑ የቤተሰብ አባላቱን ማግኘት ይፈልጋል?\n " + label: 'ህጻኑ የቤተሰብ አባላቱን ማግኘት ይፈልጋል? + +  ' wishes_reunification: - label: "ህጻኑ ወደ ቤተሰብ መቀላቀል ይፈልጋል?\n " + label: 'ህጻኑ ወደ ቤተሰብ መቀላቀል ይፈልጋል? + +  ' options: - yes_as_soon_as_possible: "አዎ, በተቻለ ፍጥነት" + yes_as_soon_as_possible: አዎ, በተቻለ ፍጥነት yes_but_later: አዎ ፣ ግን በኋላ not_sure: እርግጠኛ ያልሆነ 'no': 'አይደለም  ' data_confidentiality_link: - label: "የመረጃዎችን ሚስጥራዊነት ተመልከት\n " + label: 'የመረጃዎችን ሚስጥራዊነት ተመልከት + +  ' child_wishes_link: - label: "የህጻኑን ፍላጎቶች ተመልከት\n " - survivor_code: "የተጎጂው መለያ ቁጥር\n " - transfer_accepted: "' ተቀበል' የሚለውን ቁልፍ በመጫን ከዚህ ጉዳይ ጋር በተያያዘ በሀላፊነት ለመስራት ተስማምተዋል፣ አንዴ ተቀብያለሁ የሚለውን ከተጫኑ በቀጣይ ጉዳዩን የሚከታተሉ ባለሙ ይሆናሉ\n " - transfer_managed_user_accepted: "' ተቀበል' የሚለውን ቁልፍ ከተጫኑ %{transitioned_to}ከዚህ ጉዳይ ጋር በተያያዘ በሀላፊነት ለመስራት ተስማምተዋል አንዴ ተቀብያለሁ የሚለውን ከተጫኑ %{transitioned_to}በቀጣይ ጉዳዩን የሚከታተሉ ባለሙ ይሆናሉ" - transfer_managed_user_rejected: "'ውድቅ ማድረግ' የሚለውን ቁልፍ ከተጫኑ %{transitioned_to}ከዚህ ጉዳይ ጋር በቴያዘ በሀላፊነት ለመስራት አልተስማሙም ማለት ነው፡፡ ለምን እንዳልተቀበሉ/እንዳልተስማሙ መግለጫ ያስቀምጡ፣ አንዴ ውድቅ ማድረግ %{transitioned_to}የሚለውን ከተጫኑ ይህን ጉዳይ በድጋሜ ማየት አይችሉም\n " - transfer_accepted_rejected: "የተላለፈው ጉዳይ %{record_id}ውድቅ ተደርጓል\n " - transfer_accepted_success: "የተላለፈው ጉዳይ ተቀባይነት አግኝቷል\n " - transfer_reject_reason_label: "ውድቅ የተደረገበት ምክንያት\n " - transfer_rejected: "'ውድቅ ማድረግ' የሚለውን ቁልፍ ከተጫኑ %{transitioned_to}ከዚህ ጉዳይ ጋር በቴያዘ በሀላፊነት ለመስራት አልተስማሙም ማለት ነው፡፡ ለምን እንዳልተቀበሉ/እንዳልተስማሙ መግለጫ ያስቀምጡ፣ አንዴ ውድቅ ማድረግ %{transitioned_to}የሚለውን ከተጫኑ ይህን ጉዳይ በድጋሜ ማየት አይችሉም\n " - view_name: "ስም ተመልከት\n " + label: 'የህጻኑን ፍላጎቶች ተመልከት + +  ' + survivor_code: 'የተጎጂው መለያ ቁጥር + +  ' + transfer_accepted: ''' ተቀበል'' የሚለውን ቁልፍ በመጫን ከዚህ ጉዳይ ጋር በተያያዘ በሀላፊነት ለመስራት ተስማምተዋል፣ አንዴ ተቀብያለሁ የሚለውን ከተጫኑ በቀጣይ ጉዳዩን የሚከታተሉ ባለሙ ይሆናሉ + +  ' + transfer_managed_user_accepted: ''' ተቀበል'' የሚለውን ቁልፍ ከተጫኑ %{transitioned_to}ከዚህ ጉዳይ ጋር በተያያዘ በሀላፊነት ለመስራት ተስማምተዋል አንዴ ተቀብያለሁ የሚለውን ከተጫኑ %{transitioned_to}በቀጣይ ጉዳዩን የሚከታተሉ ባለሙ ይሆናሉ' + transfer_managed_user_rejected: '''ውድቅ ማድረግ'' የሚለውን ቁልፍ ከተጫኑ %{transitioned_to}ከዚህ ጉዳይ ጋር በቴያዘ በሀላፊነት ለመስራት አልተስማሙም ማለት ነው፡፡ ለምን እንዳልተቀበሉ/እንዳልተስማሙ መግለጫ ያስቀምጡ፣ አንዴ ውድቅ ማድረግ %{transitioned_to}የሚለውን ከተጫኑ ይህን ጉዳይ በድጋሜ ማየት አይችሉም + +  ' + transfer_accepted_rejected: 'የተላለፈው ጉዳይ %{record_id}ውድቅ ተደርጓል + +  ' + transfer_accepted_success: 'የተላለፈው ጉዳይ ተቀባይነት አግኝቷል + +  ' + transfer_reject_reason_label: 'ውድቅ የተደረገበት ምክንያት + +  ' + transfer_rejected: '''ውድቅ ማድረግ'' የሚለውን ቁልፍ ከተጫኑ %{transitioned_to}ከዚህ ጉዳይ ጋር በቴያዘ በሀላፊነት ለመስራት አልተስማሙም ማለት ነው፡፡ ለምን እንዳልተቀበሉ/እንዳልተስማሙ መግለጫ ያስቀምጡ፣ አንዴ ውድቅ ማድረግ %{transitioned_to}የሚለውን ከተጫኑ ይህን ጉዳይ በድጋሜ ማየት አይችሉም + +  ' + view_name: 'ስም ተመልከት + +  ' + sort_by: ቅደም ተከተል change_logs: filters: form: ቅጽ - field: "ምድብ\n " + field: 'ምድብ + +  ' add_subform: 'የንዑስ ቅጽ ማስገቢያ%{short_id} ተጨምሯል#%{subform_name}  ' changes_subform: 'ወደ ንዑስ ቅጽ%{subform_name} ቀይር  ' - create: "የተፈጠረ ማህደር\n " + create: 'የተፈጠረ ማህደር + +  ' deleted_subform: 'የንዑስ ቅጽ ማስገቢያ %{short_id}ተወግዷል%{subform_name}' label: መግቢያ ቀይር see_details: ዝርዝሩን ይመልከቱ @@ -468,61 +711,121 @@ am-ET: date_of_creation: የተፈጠረበት ቀን registration_date: የተመዘገበበት ቀን configurations: - apply_label: "እርግጠኛ ነዎት? ይህን ማስተካከያ ካመለከቱ ወደ አጠቃላይ ሲስተሙ መረጃ እያስገቡ ነው ፡፡ እያንዳንዱን የሚያስገቡትን መረጃ በአግባቡ መመዝገብና ማስቀመጥዋን እንዳይዘነጉ በአግባቡ ካላስቀመጡዋቸው በስተቀር ያስተካከሉዋቸውን መረጃዎች መልሰው ማግኘት አይችሉም።\n " - apply_label_bold: "ለውጥ በሚደረግበት ጊዜ ለተወሰኑ ደቂቃዎች ፕሪሜሮ ላይሰራ ይችላል\n " - version_mismatch_tooltip: "እርስዎ ከሚጠቀሙበት የፕሪሜሮ ስሪት በላይ የተፈጠረ ስለሆነ ይህንን ነገር መጯን አይችሉም፣ እባክዎ አዳዲስ የፕሪሜሮ አሰራሮችን እስኪጠቀሙ ይጠብቁ\n " - send_header: "ወደ ዋናው መስሪያ ክፍል ይላኩ\n " - send_text: "እርግጠኛ ነዎት ላክ የሚለውን ከተጫኑ ወደ ዋናው ማቀነባበርያ ሲስተም እየላኩ ነው የሲስተም ተቆጣጣሪ እስካላስተካከለውና ምላሽ እስካልሰተ አይሰራም\n \n " + apply_label: 'እርግጠኛ ነዎት? ይህን ማስተካከያ ካመለከቱ ወደ አጠቃላይ ሲስተሙ መረጃ እያስገቡ ነው ፡፡ እያንዳንዱን የሚያስገቡትን መረጃ በአግባቡ መመዝገብና ማስቀመጥዋን እንዳይዘነጉ በአግባቡ ካላስቀመጡዋቸው በስተቀር ያስተካከሉዋቸውን መረጃዎች መልሰው ማግኘት አይችሉም። + +  ' + apply_label_bold: 'ለውጥ በሚደረግበት ጊዜ ለተወሰኑ ደቂቃዎች ፕሪሜሮ ላይሰራ ይችላል + +  ' + version_mismatch_tooltip: 'እርስዎ ከሚጠቀሙበት የፕሪሜሮ ስሪት በላይ የተፈጠረ ስለሆነ ይህንን ነገር መጯን አይችሉም፣ እባክዎ አዳዲስ የፕሪሜሮ አሰራሮችን እስኪጠቀሙ ይጠብቁ + +  ' + send_header: 'ወደ ዋናው መስሪያ ክፍል ይላኩ + +  ' + send_text: 'እርግጠኛ ነዎት ላክ የሚለውን ከተጫኑ ወደ ዋናው ማቀነባበርያ ሲስተም እየላኩ ነው የሲስተም ተቆጣጣሪ እስካላስተካከለውና ምላሽ እስካልሰተ አይሰራም + +   + +  ' attributes: - created_by: "የተፈጠረው " + created_by: 'የተፈጠረው ' date_created: የተፈጠረበት ቀን description: መግለጫ last_applied_by: "በመጨረሻ ያመለከተው \n " last_applied_on: "በመጨረሻ ያመለከተው \n " name: ስም - version: "የማዋቀር ክፍል\n " - primero_version: "የፕሪሜሮ ክፍል\n " - delete_label: "እርግጠኛ ነዎት ይህን ማድረግ ይፈልጋሉ? ይህ ውቅር ከተፈጠረ ጀምሮ ያሉትን ሁሉንም ቅንብሮች ይወክላል። አንዴ ይህን ውቅር ከሰረዙት ወደ ኋላ ተመልሰው እነዚህን ቅንብሮች መልሰው ማግኘት አይችሉም።" + version: 'የማዋቀር ክፍል + +  ' + primero_version: 'የፕሪሜሮ ክፍል + +  ' + delete_label: እርግጠኛ ነዎት ይህን ማድረግ ይፈልጋሉ? ይህ ውቅር ከተፈጠረ ጀምሮ ያሉትን ሁሉንም ቅንብሮች ይወክላል። አንዴ ይህን ውቅር ከሰረዙት ወደ ኋላ ተመልሰው እነዚህን ቅንብሮች መልሰው ማግኘት አይችሉም። explanation: 'አስቀምጥ/መዝግብ የሚለውን ቁልፍ መጫን የሁሉም የአሁኑ የውቅረት ቅንጅቶች (ለምሳሌ ሚናዎች፣ ኤጀንሲዎች፣ ቅጾች) በዚህ ጊዜ መዝገብ ይፈጥራል። ከመዘገቡ በኋላ፣ እነዚህን ለውጦች ወደ ሌላ  ምሳሌ መግፋት ይችላሉ። ለወደፊቱ፣ ለመመለስ የሚፈልጉትን የውቅረት ለውጦችን ካደረጉ፣ በዚህ ጊዜ ያደረጓቸውን ሁሉንም የውቅረት ለውጦች ወደነበሩበት ለመመለስ ይህንን የውቅር መዝገብ መተግበር ይችላሉ።  ' label: የማዋቀር ዝርጋታ label_new: የማዋቀር ዝርጋታ messages: - applied: "የውቅር ሂደቱ በሚገባ ተተገብሯል\n " - created: "የማዋቀር ሂደቱ በሚገባ ተፈጥሯል\n " - deleted: "የማዋቀር ሂደቱ በሚገባ ጠፍቷል\n " - updated: "የማዋቀር ሂደቱ በሚገባ ተስተካክሏል\n " - sent: "የውቅር ሂደቱን ወደ ስራ ማስገባት፡፡ እባክዎ  የተስተካከለውን የውቅር ሂደት ወደ መተግበሪያው መድረሱን ያረጋግጡ፡፡\n " - not_allowed: "አልተፈቀደም\n " + applied: 'የውቅር ሂደቱ በሚገባ ተተገብሯል + +  ' + created: 'የማዋቀር ሂደቱ በሚገባ ተፈጥሯል + +  ' + deleted: 'የማዋቀር ሂደቱ በሚገባ ጠፍቷል + +  ' + updated: 'የማዋቀር ሂደቱ በሚገባ ተስተካክሏል + +  ' + sent: 'የውቅር ሂደቱን ወደ ስራ ማስገባት፡፡ እባክዎ  የተስተካከለውን የውቅር ሂደት ወደ መተግበሪያው መድረሱን ያረጋግጡ፡፡ + +  ' + not_allowed: 'አልተፈቀደም + +  ' unavailable_server: "የመረጃ ቋቱ ለጊዜው አይሰራም \n " contact: field: - email: "ኢ-ሜይል\n " - location: "አድራሻ/መገኛ ቦታ\n " + email: 'ኢ-ሜይል + +  ' + location: 'አድራሻ/መገኛ ቦታ + +  ' name: ስም organization: "ተቋም/ደርጅት \n " - other_information: "ሌሎች መረጃዎች\n " - phone: "ስልክ\n " + other_information: 'ሌሎች መረጃዎች + +  ' + phone: 'ስልክ + +  ' position: "ኃላፊነት \n " - primero_version: "የፕሪሜሮ ስሪት\n " - support_forum: "የድጋፍ ፎረም\n " - system_version: "የስርዓት ስሪት\n " - info_label: "የመገኛ አድራሻ\n " - updated: "የመገኛ አድራሻ በሚገባ ተሻሽሏል\n " + primero_version: 'የፕሪሜሮ ስሪት + +  ' + support_forum: 'የድጋፍ ፎረም + +  ' + system_version: 'የስርዓት ስሪት + +  ' + info_label: 'የመገኛ አድራሻ + +  ' + updated: 'የመገኛ አድራሻ በሚገባ ተሻሽሏል + +  ' code_of_conduct: field: - title: "ማእረግ\n " - content: "ይዘት\n " + title: 'ማእረግ + +  ' + content: 'ይዘት + +  ' created_on: የተፈጠረበት created_by: የፈጠረው info_label: " የስነምግባር  ደንብ \n " - updated: "የስነምግባር  ደንብ በሚገባ ተሻሽሏል\n " + updated: 'የስነምግባር  ደንብ በሚገባ ተሻሽሏል + +  ' dashboard: - activity: "ተግባር\n " - admin_only: "መተግበሪያውን ለመቀየር ይህን ይጫኑ%{links}\n " - all_cases: "ሁሉም ጉዳዮች\n " - all_services_implemented: "ሁሉም አገልግሎቶች ተተግብረዋል\n " + activity: 'ተግባር + +  ' + admin_only: 'መተግበሪያውን ለመቀየር ይህን ይጫኑ%{links} + +  ' + all_cases: 'ሁሉም ጉዳዮች + +  ' + all_services_implemented: 'ሁሉም አገልግሎቶች ተተግብረዋል + +  ' and: 'እና  ' @@ -567,10 +870,14 @@ am-ET: case_stat_referrals: ቅብብሎሽ case_stats: ጉዳዮች case_worker: የጉዳይ አያያዝ ባለሙያ - cases_by_social_worker: "በጉዳይ አያያዝ ባለሙያ የተያዙ ጉዳዮች\n " + cases_by_social_worker: 'በጉዳይ አያያዝ ባለሙያ የተያዙ ጉዳዮች + +  ' cases_by_task_overdue: የዘገዩ ተግባራት cases_by_workflow: "የጉዳዮች የስራ ፍሰት \n " - cases_this_week: "የሳምንቱ ጉዳዮች\n " + cases_this_week: 'የሳምንቱ ጉዳዮች + +  ' cases_to_assign: የሚመደቡ ጉዳዮች closed: ተዘግቷል closed_last_week: ተዘግቷል (ባለፈው ሳምንት) @@ -582,40 +889,7 @@ am-ET: count_new_case_plan_approvals: one: '%{stat} new %{stat_type} Approval' other: '%{stat} new %{stat_type} Approvals' - count_new_closure_approvals: - one: '' - other: '' - count_pending_approval_total: - one: '' - other: '' - count_pending_transfers: - one: '' - other: '' - count_records_new: - one: '' - other: '' - count_records_total: - one: '' - other: '' - count_referrals_new: - one: '' - other: '' - count_referrals_total: - one: '' - other: '' - count_rejected_approval_total: - one: '' - other: '' - count_rejected_transfers: - one: '' - other: '' - count_risk_level_new: - one: '' - other: '' - count_risk_level_total: - one: '' - other: '' - count_waiting_for_acceptance_transfers: "ተቀባይነትዎን የሚጠብቁ ማዘዋሮች አሉዎት%{stat}" + count_waiting_for_acceptance_transfers: ተቀባይነትዎን የሚጠብቁ ማዘዋሮች አሉዎት%{stat} current_owner: አሁን ጉዳዩን  የያዘው dash_case_incident_overview: የኔ ጉዳዮች dash_group_overview: የቡድኔ ጉዳዮች @@ -625,6 +899,9 @@ am-ET: dash_shared_with_my_team_overview: ለቡድኔ የተጋራ (አጠቃላይ እይታ) dash_shared_with_others: ለሌሎች የተጋራ dash_national_admin_summary: የአስተዳዳሪ ማጠቃለያ + dash_violations_category_verification_status: በአንድ የማረጋገጫ ሁኔታ አጠቃላይ የክስተቶች ብዛት + dash_violations_category_region: አጠቃላይ የተረጋገጡ ኬዞች በክልል ደረጃ + dash_perpetrator_armed_force_group_party_names: የሚከሰቱ ክስተቶች ብዛትና አጥቂዎች በንጽጽር date: ቀን date_of_incident: የተከሰተበት ቀን date_of_interview: ቃለመጠይቅ የተደረገበት ቀን @@ -650,16 +927,7 @@ am-ET: link_see_all: ሁሉንም እዩ low_level: ዝቅተኛ low_risk: ዝቅተኛ ቅድሚያ/ትኩረት - manager_count_closed_total: - one: '' - other: '' - manager_count_open_total: - one: '' - other: '' - manager_transfers_totals: - one: '' - other: '' - match_result: "የማዛመድ ውጤት " + match_result: 'የማዛመድ ውጤት ' medium_level: መካከለኛ medium_risk: መካከለኛ ትኩረት/ቅድሚያ missed_cases: የጠፉ/የተረሱ ጉዳዮች @@ -692,7 +960,7 @@ am-ET: open_cases: የተከፈቱ ጉዳዮች open_incidents: የተከፈቱ ክስተቶች outstanding_transfers: ከፍተኛ ዝውውሮች - overdue_activities: "የዘገዩ ተግባራት " + overdue_activities: 'የዘገዩ ተግባራት ' overdue_cases_to_assign: ለመመደብ የዘገዩ ጉዳዮች overdue_cases_to_assign_high: እነዚህ ጉዳዮች ከ1 ሰዓት በላይ አጋጥመውዎታል overdue_cases_to_assign_low: እነዚህ ጉዳዮች ከ3 ሰዓት በላይ አጋጥመውዎታል @@ -707,7 +975,7 @@ am-ET: range4_8: 4-8 range8_12: 8-12 recent_activities: የቅርብ ተግባራት - recently_flagged_child: "በቅርብ የተጠቆሙ ጉዳዮች " + recently_flagged_child: 'በቅርብ የተጠቆሙ ጉዳዮች ' recently_flagged_incident: በቅርብ የተጠቆሙ ክስተቶች referrals_by_social_worker: በጉዳይ አያያዝ ባለሙያ ያ የተደረጉ ቅብብሎሾች registration: ምዝገባ @@ -744,12 +1012,6 @@ am-ET: with_incidents: ከክስተቶች ጋር with_new_incidents: ከአዲስ ክስተቶች ጋር without_incidents: ከክስተቶች ውጭ - worker_count_referrals_total: - one: '' - other: '' - worker_count_total: - one: '' - other: '' workflow: የስራ ፍሰት workflow_team: የስራ ፍሰት የቡድን ጉዳዮች you_have: 'አለህ' @@ -765,7 +1027,6 @@ am-ET: approval_response: '%{user} የማጽደቅ ጥያቄ %{approval_type}አለው%{status}ለጉዳይ%{case_id}።' approval_response_subject: '{የጉዳይ፡ ማጽደቅ ምላሽ}' referral: '%{user} ከ %{agency} አድረጋል %{record_type} ለእናንተ: %{record_id} ለ %{service_type}.' - transfer: '' transfer_request_subject: ከጉዳዮች መካካል ለዝወወር አንዱን ጉዳይ መጠየቅ transfer_subject: '%{record_type}፡%{id}ማዘዋወር' referral_subject: '%{record_type}፡%{id}ቅብብሎሽ' @@ -777,26 +1038,30 @@ am-ET: assign_html: '%{user} ለአንተ %{record_type}ተመድባል: %{record_id}. የሚከተለዉ ጉዳይ ለአንተ ተመድባል' transfer_request_html: 'የፕሪሜሮ ተጠቃሚ %{user} ከ %{agency} is ሀላፊነቱን አስተላልፋል%{record_type} መዝገብ %{record_id} ስለዚህ አገልግሎት መስጠት ይችላሉ %{record_type} . ይህ ቅብብሎሽን ከተቀበልክ , እባክዎ ይጫኑ %{record_type} ID ማያያዛ በዚህ ኢሜል %{record_type} በፕሪሜሮ ቅብብል.' transfer_request_notes_html: '{ጥያቄውን ባቀረበው ግለሰብ የተያዘ ማስታወሻ}' + webpush_notification: + approval_response: + title: የማጽደቅ ምላሽ + body: ከጉዳዮችዎ ውስጥ አንዱ ተቀባይነት ያለው ምላሽ አግኝቷል። + transfer_request: + title: የማስተላለፍ ጥያቄ encrypt: - export_type: "የማስተላለፉ አይነት " + export_type: 'የማስተላለፉ አይነት ' file_name: የራስዎን የፋይል ስም ይፍጠሩ (አማራጭ) password_extra_info: የይለፍ ቃል ቢያንስ 8 አሃዝ መሆን አለበት። የይለፍ ቃሉ ከሚተላለፈዉ መረጃ ጋር ወይም ለወደፊት ይሄን ፋይል ከሚከፍተዉ ጋር ሊያያዝ ይችላል፡፡ password_label: ፋይሉን በሚስጥር ሊያሰቀምጥ የሚችል የይለፍ ቃል አስገቡ error_message: - address_fields: "1 %fields } በ2 % {ቅጾች} በቅፁ የተጠየቁትን ማሟላት አለብህ " - address_form_fields: "1 % {መስኮችን} በዚህ ቅፁ የተጠየቁትን ማሟላት አለብህ " + address_fields: 1 %fields } በ2 % {ቅጾች} በቅፁ የተጠየቁትን ማሟላት አለብህ  + address_form_fields: 1 % {መስኮችን} በዚህ ቅፁ የተጠየቁትን ማሟላት አለብህ  address_subform_fields: '1 %{ንዑስ ቅጾች} 2 %{መስኮች} በትክክል  የተጠየቁት አልተሞሉም' error_page: not_authorized: - code: 403 server_error: ይሄን ገፅ ለመመልት አልተፈቀደልዎትም title: አልተፈቀደም not_found: - code: 404 contact_admin: እዚህ ያለዎት በስህተት ነው ብለው ካመኑ፣ እባክዎ አስተዳዳሪዎን ያነጋግሩ - something_went_wrong: " ይቅርታ, የሆነ ችግር ተፈጥሯል" + something_went_wrong: ' ይቅርታ, የሆነ ችግር ተፈጥሯል' errors: - error_loading: "የስህተት መዝገብ(ቦችን) " + error_loading: 'የስህተት መዝገብ(ቦችን) ' models: agency: code_present: ባዶ መሆን የለበትም @@ -808,7 +1073,7 @@ am-ET: date_of_birth: ለዚህ የጉዳይ ምዝገባ ትክክለኛውን የልደት ቀን አስገባ export_configuration: opt_out_field_does_not_exist: የተወሰነ የመርጦ መውጫ መስክ በመዝገቡ ላይ የለም - record_type: "ልክ ያልሆነ የመዝገብ አይነት። ህጻን መሆን አለበት, የማፈላለጊያ ጥያቄ መሆን አለበት።" + record_type: ልክ ያልሆነ የመዝገብ አይነት። ህጻን መሆን አለበት, የማፈላለጊያ ጥያቄ መሆን አለበት። field: translated_options_do_not_match: የሚሞሉ የትርጓሜ አማራጮችን ጥሰት የሚቆጣጣር Ids መሆን አለበት location: @@ -824,7 +1089,7 @@ am-ET: associated_record_types: ቢያንስ አንድ የመዝገብ አይነት ከዚህ ሞጁል ጋር መመሳሰል አለበት። form_section_ids: ቢያንስ አንድ ቅጽ ከዚህ ሞጁል ጋር መመሳሰል አለበት። name_present: ስም ባዶ መሆን የለበትም - unique_name: "በዚህ ስም የተሰየመ ሞጁል አስቀድሞ አለ፣ እባክዎ የተለየ ስም ያስገቡ " + unique_name: 'በዚህ ስም የተሰየመ ሞጁል አስቀድሞ አለ፣ እባክዎ የተለየ ስም ያስገቡ ' report: module_presence: ሞጁል ባዶ መሆን የለበትም module_syntax: ሁሉም የሪፖርት ሞጁሎች አስቀድሞ መኖር አለባቸው @@ -834,7 +1099,7 @@ am-ET: user: email: "እባክዎ ትክክለኛ ኢሜይል ያስገቡ (ምሳሌ፡-name@example.org')" password_mismatch: የይለፍ ቃል መስኮቹ ተመሳሳይ የይለፍ ቃል የላቸውም - password_length: "የይለፍ ቃሉ ቢያንስ %{ቢያንስ } ፊደላት ቁጥር እና ሌሎች ምልክቶችን መሆን አለበት" + password_length: የይለፍ ቃሉ ቢያንስ %{ቢያንስ } ፊደላት ቁጥር እና ሌሎች ምልክቶችን መሆን አለበት email_uniqueness: በዚህ ኢሜይል አድራሻ ሌላ ተጠቃሚ አስቀድሞ አለ። እባክዎ የተለየ ያስገቡ code_of_conduct: title_present: ርዕስ ባዶ መሆን የለበትም @@ -855,7 +1120,7 @@ am-ET: all: ልማድ custom_exports: all: ልማድ - choose_fields: "ለግለሰብ አስፈላጊውን ድጋፍ መምረጥ ቅጽ ይፈልጋሉ?" + choose_fields: ለግለሰብ አስፈላጊውን ድጋፍ መምረጥ ቅጽ ይፈልጋሉ? empty_fields_forms: ለማስተላለፍ የተፈለጉ ሁናቴዎችን ያስተላልፉ empty_format: ለማስተላለፍ ተፈለገውን ቅጽ ምረጥ empty_module: ለማስተላለፍ ሞዱል ምረጥ @@ -868,7 +1133,9 @@ am-ET: label: የሚተላለፉትን በነባራዊ ሁኔታ መቃኘት module_placeholder: እባክዎ ሞጁል ሞዱል ምረጥ select_module: እባክዎ ሞጁል ይምረጡ - submit: "አዎ/እሽ\n " + submit: 'አዎ/እሽ + +  ' header: ርዕስ custom_header: ዋና ርዕስ signatures: የፊርማ መስመር ያካቱ @@ -881,26 +1148,28 @@ am-ET: female_abbreviation: ሴት headers: age: እድሜ - case_id: "የጉዳይ #መለያ ቁጥር" + case_id: 'የጉዳይ #መለያ ቁጥር' child_name_last_first: የህጻኑ ስም family_size: የቤተሰብ ቁጥር moha_id: መለያ ቁጥር ተነስታል national_id_no: ሀገራዊ መለያ ቁጥር progress_id: የሂደት መለያ መታወቂያ sex_mapping_m_f_u: ጾታ - other_agency_id: "የሆስፒታል መለያ ኮድ እና የታማሚ ቁጥር " + other_agency_id: 'የሆስፒታል መለያ ኮድ እና የታማሚ ቁጥር ' male_abbreviation: ኤም unknown_abbreviation: ዩ exported: የሚሸጋገሩ ፋይሎች ተገኝተዋል exported_error: የሚሸጋገሩ ፋይሎች ላይ ስተት አለ forms: - button: "የማስተላለፊያ ቅፅ " + button: 'የማስተላለፊያ ቅፅ ' label: ማስተላለፍ header: - form_group: "ቡድን መመስረት " + form_group: 'ቡድን መመስረት ' form_name: ስም መሰየም field_id: የሙያ መስክ መለያ ቁጥር - field_type: "60%match\nየመስክ አይነት " + field_type: '60%match + + የመስክ አይነት ' field_name: የቦታ ስም required: አስፈላጊ on_mobile: በሞባይል ላይ @@ -928,7 +1197,6 @@ am-ET: form: የፕሪሜሮ ቅጽ status: ሁኔታ notes: ማስታወሻዎች - go_to_exports: ለማውረድ ወደ ማስተላለፊያ ገጽ እለፍ incident_recorder_xls: all: የአጋጣሚ መዝጋቢ @@ -939,12 +1207,12 @@ am-ET: one: ጄኤስኦኤን selected: ለ JSON የተመረጠ list_view_csv: - all: "ለማስተላለፍ ዝርዝር እይታ " + all: 'ለማስተላለፍ ዝርዝር እይታ ' selected: ለ ሲ ኤስ ቪ የተመረጠ messages: no_exporter: ምንም ላኪ አልተገለጸም mrm_violation_xls: - all: "MRM ጥሰቶች " + all: 'MRM ጥሰቶች ' one: ኤም አር ኤም ጥሰቶች selected: ለኤም አር ኤም ጥሰቶች የተመረጡ no_records: ምንም መዝገቦች የሉም @@ -955,23 +1223,23 @@ am-ET: pdf_exports: label: ፒዲኤፍ recipient: ተቀባይ - case_worker: "የጉዳይ አያያዝ ባለሙያ " - client: "ተገልጋይ " + case_worker: 'የጉዳይ አያያዝ ባለሙያ ' + client: 'ተገልጋይ ' date: ቀን recipient_name: የተቀባይ ስም recipient_agency: የተቀባይ ተቃም caseworker_name: የጉዳይ አያያዝ ባለሙያ caseworker_agency: የጉዳይ አያያዝ ባለሙያተቃም photowall: - all: " የፎቶ መለጠፊያ " + all: ' የፎቶ መለጠፊያ ' flag_suspect_record: እንደ አስጊ ማህደር ተጠቁሟል no_photos_available: ምንም ፎቶዎች የሉም one: የፊት ለፊት ፎቶ reunited: የተዋሃደ selected: ለፊት ለፊት ፎቶ የተመረጡ - success_message: "የፊት ለፊት ፎቶ ፍጠር %{file_name} ጉዳዩን ያለፎቶ አይቀበልም." + success_message: የፊት ለፊት ፎቶ ፍጠር %{file_name} ጉዳዩን ያለፎቶ አይቀበልም. printed: 'ታትማል: %{date}' - queueing: "የተላኩ ፋይሎችን ማምጣት%{file_name}" + queueing: የተላኩ ፋይሎችን ማምጣት%{file_name} selected_xls: all: ኤክሴል one: ኤክሴል @@ -979,10 +1247,10 @@ am-ET: selected_fields: የተመረጡ መስኮች unhcr_csv: all: UNHCR - female_abbreviation: ሴ + female_abbreviation: ሴት headers: age: ዕድሜ - case_status: "የጉዳዩ ሁኔታ " + case_status: 'የጉዳዩ ሁኔታ ' causes_of_separation: የመለያየት ምክንያቶች country_of_origin: የትውልድ ሀገር cpims_code: የህጻናት ጥበቃ  መረጃ አያያዝ ስርዓት መለያ @@ -1012,7 +1280,7 @@ am-ET: selected: ወደ UNHCR ተመርጧል unknown_abbreviation: U xlsx: - all: "አክሴል " + all: 'አክሴል ' one: አክሴል selected: ወደ ኤክሴል መስርያ ተመርጧዋል imports: @@ -1048,7 +1316,7 @@ am-ET: add_new_field: አዲስ መስኮች ፍጠር add_existing_field: አዲስ መስኮች ጨመር add_field: መስኮች ጨምር - add_field_type: " ጨምር%{file_type}" + add_field_type:  ጨምር%{file_type} audio: current: አሁናዊ ድምጽ audio_upload_box: ድምጽ ተቀምጣል @@ -1074,29 +1342,28 @@ am-ET: date_range_field: የቀን ልክ date_time: ቀን-ሰዓት db_name: የዳታ ቤዝ ስም - default: "የነበረ?" + default: የነበረ? default_date_validation: የፀደቀበት ቀን - default_to_current_date: "የነበረዉ ቀን " - default_to_current_datetime: "የተለመደውን ወደ ዛሬ ቀን እና ሰዓት?" - default_value: "አሁን ያለዉ ዋጋ " - deleted: "{ጠፍታል}" + default_to_current_date: 'የነበረዉ ቀን ' + default_to_current_datetime: የተለመደውን ወደ ዛሬ ቀን እና ሰዓት? + default_value: 'አሁን ያለዉ ዋጋ ' + deleted: '{ጠፍታል}' detail: ዝርዝር disabled: 101%match የማይሰራ - display_name: "የማሳያዉ ስም " + display_name: 'የማሳያዉ ስም ' document: comments: አስተያየቶች - current: "ይህ የአሁኑ ሰነድ ነው?" + current: ይህ የአሁኑ ሰነድ ነው? date: የሰነድ ቀን name: የመረጃ ስም - is_current: "ይህ የአሁኑ መረጃ ነው?" + is_current: ይህ የአሁኑ መረጃ ነው? document_upload_box: መረጃ ያስገቡ/ወደ ምህዋር ያስገቡ edit_label: ይመዝግቡ - enabled: "በርታል?" + enabled: በርታል? enabled_label: በርታል english_text: የእንግሊዘኛ ጽሁፍ field_name: የቦታ ስም field_type: የቦታ አይነት - attachment_too_large: መረጃው ከ10 ሜ.ባ መብለጥ የለበትም file_upload_box: add_document_label: መረጃ አክል add_new_document_button_text: ሌላ መረጃ አክል @@ -1105,19 +1372,31 @@ am-ET: document_description: የሰነድ መግለጫ document_file_restrictions_message: ፋይሎች ከ2 ሜባ መብለጥ የለባቸውም (ተፈፃሚ (.exe) ፋይሎች ሊጫኑ አይችሉም)። no_file_selected: የተመረጠ ፋይል የለም - photo_file_restrictions_message: "ፎቶዎች ከ10 ሜባ መብለጥ የለባቸውም። የድምጽ ፋይሎች ከ10ሜባ መብለጥ የለባቸውም። አነስተኛ የሆነው ተመራጭ ነው\n " - recorded_audio_label: "የተቀዳ ድምጽ\n " + photo_file_restrictions_message: 'ፎቶዎች ከ10 ሜባ መብለጥ የለባቸውም። የድምጽ ፋይሎች ከ10ሜባ መብለጥ የለባቸውም። አነስተኛ የሆነው ተመራጭ ነው + +  ' + recorded_audio_label: 'የተቀዳ ድምጽ + +  ' select_file_button_text: ፋይል ይምረጡ find_lookup: lookupን ያግኙ form_name: የቅፁ ስም - future_date_not_valid: "ወደፊት አይሆንም\n " + future_date_not_valid: 'ወደፊት አይሆንም + +  ' guidance: "ምክር \n " guiding_questions: "የምክክር ጥያቄዎች \n " help_text: የድጋፍ መልእክት - hide_on_view_page: "ገጾችን አሳይ\n " - label: "መስክ\n " + hide_on_view_page: 'ገጾችን አሳይ + +  ' + label: 'መስክ + +  ' mobile_visible: የስልክ መተግበርያ - move_to: "አንቀሳቅስ\n " + move_to: 'አንቀሳቅስ + +  ' multi_select: ብዙ አማራጮችን መምረጥ ይችላል። multi_select_box: የተለያዩ ምርጫዎች must_be_english: በእንግሊዘኛ መግባት አለበት @@ -1125,9 +1404,9 @@ am-ET: not_future_date: የወደፊት ቀን አይደለም number_not_valid: እባክዎ የቁጥር  መረጃ ያስገቡ numeric_field: ቁጥራዊ መስኮች - on_collapsed_subform: "ያልተስተካከለ ንኡስ ቅጽ ላይ?" + on_collapsed_subform: ያልተስተካከለ ንኡስ ቅጽ ላይ? option_strings_add_option: አማራጭ ይጨምሩ - option_strings_source: Lookups + option_strings_source: ፍለጋዎች option_strings_text: አማራጮች option_strings_text_display: አማራጭ ጽሑፍ option_strings_text_key: አማራጭ ቁልፍ @@ -1139,7 +1418,7 @@ am-ET: predifined_lookups: አስቀድሞ የነበረውን Lookup ተጠቀም radio_button: የሬዲዮ ቁልፍ remove: ማስወገድ - remove_attachment_confirmation: "እርግጠኛ ነዎት ይህን ዓባሪ ማስወገድ ይፈልጋሉ?" + remove_attachment_confirmation: እርግጠኛ ነዎት ይህን ዓባሪ ማስወገድ ይፈልጋሉ? required: ያስፈልጋል required_field: '{ያስፈልጋል}' search_existing: ያሉትን ጉዳዮች ይፈልጉ @@ -1148,18 +1427,28 @@ am-ET: select_multiple: የሚተገበረውን ሁሉ ምረጥ select_single: (ምረጥ...) separator: መለያዎች - show: "አሳይ?" + show: አሳይ? show_on: ማሳየት show_on_minify_form: አጭር ቅጽ + skip_logic: + name: አመክንዮ ዝለል? + record_section: + title: ይህ ቦታ ከተመዘገበ መታየት አለበት። + buttons: + add: የተቀረጠውን በመዝገቡ ላይ ይጨምሩ/ያክሉ + subform_section: + title: ይህ መስክ በንዑስ ቅርጽ ከሆነ መታየት አለበት + buttons: + add: በንዑስ የቅጽ ፎርም ላይ ይጨምሩ/ያክሉ subform: ንዑስ ቅጽ subform_group_by: መዳቢው - subform_remove_message: "ይህን ንዑስ ቅጽ ማስወገድ ይፈልጋሉ? እርግጠኛ ነዎት?" + subform_remove_message: ይህን ንዑስ ቅጽ ማስወገድ ይፈልጋሉ? እርግጠኛ ነዎት? subform_section: description: የንዑስ ቅጽ ዝርዝር name: የንዑስ ቅጽ ርዕስ starts_with_one_entry: በአንድ ንዑስ ቅጽ ማስገቢያ ይጀምሩ subform_append_only: በሞባይል ማስገባት - subform_prevent_item_removal: "ንኡስ ቅፅ እንዳይጠፋ ይሁን?" + subform_prevent_item_removal: ንኡስ ቅፅ እንዳይጠፋ ይሁን? subform_sort_by: ቅደም ተከተል successfully_added: ቦታው በትክክል ተጨምራል tally_field: ቦታ @@ -1173,15 +1462,22 @@ am-ET: translation_text: የትርጉም መልዕክት total: አጠቃላይ type: አይነት - updated: የተሻሻለ መስክ + updated: የተሻሻለው ቦታ visibility: የሚታይ web_app: የመረጃዉ በይነመረብ filters: apply_filters: ተግብር - clear_filters: " ያጥፉ\n\n " + clear_filters: ' ያጥፉ + + +  ' less: በታች... more: በላይ... save_filters: አስቀምጥ/መዝግብ + categories: + violations: ጥሰቶች + incidents: ክስተቶች + individual_victims: 'ተጎጂው ግለሰብ ' flags: add_flag_tab: ተጨማሪ አዳዲስ ማመላከቻ date: 'ቀን' @@ -1225,9 +1521,14 @@ am-ET: created: የቅጽ ክፍል በተሳካ ሁኔታ ተፈጥሯል fields_with_same_name: ቅጾች ተመሳሳይ ስሞች ያላቸው መስኮች ሊኖራቸው አይገባም save_success: የቅጽ ክፍሎች በተሳካ ሁኔታ ተሻሻሏል - save_with_errors: "ችግር ስለነበር አንዳንድ የቅጽ ክፍሎች አልተሻሻሉም\n " + save_with_errors: 'ችግር ስለነበር አንዳንድ የቅጽ ክፍሎች አልተሻሻሉም + +  ' updated: የቅፁን ክፍል በተሳካ ሁኔታ ተሻሻሏል - use_existing: "ያሉትን ቅጾች እንድትጠቀሙ እናበረታለን ይህም በተቋማት መካከል ያለውን የመረጃ ልውውጥ እና መረጃዎችን ወደ አንድ ቋት ለማምጣት ያስችላል\n\n " + use_existing: 'ያሉትን ቅጾች እንድትጠቀሙ እናበረታለን ይህም በተቋማት መካከል ያለውን የመረጃ ልውውጥ እና መረጃዎችን ወደ አንድ ቋት ለማምጣት ያስችላል + + +  ' mobile_app: የሞባይል መተግበሪያ module: ሞጁል no_subform_filters_added: ይህ ንዑስ ቅጽ በአሁኑ ጊዜ ምንም መስኮች የሉትም። @@ -1237,25 +1538,27 @@ am-ET: case: ጉዳይ child: ጉዳይ incident: ክስተት - individual_victim: "ተጎጂ ግለሰብ " + individual_victim: 'ተጎጂ ግለሰብ ' potential_match: ሊመሳሰሉ የሚችሉ record_information: የተመዘገበ መረጃ referrals: ቅብብሎሾች reportable_follow_up: ክትትል reportable_protection_concern: የጥበቃ ፍላጎት reportable_service: አገልግሎት - tracing_request: "የፍለጋ መጠየቂያ " + tracing_request: 'የፍለጋ መጠየቂያ ' transfers_assignments: ማስተላለፍ / መመደብ violation: ጥሰት registry_details: የመዝገብ ዝርዝር registry_record: የመዝገብ ቅጅ + family_record: የተመዘገበ የቤተሰብ ታሪክ + family: 'የተመዘገበ የቤተሰብ ታሪክ ' required_field: '{አስፈላጊ መስክ}' select_label: ምረጥ settings: ማስተካካያ show_on: አሳይ subform_need_to_be_added: መጨመር ያስፈልጋቸዋል subform_need_to_be_added_single: መጨመር ያስፈልገዋል - subform_not_found: "{አልተገኘም}" + subform_not_found: '{አልተገኘም}' title: የቅጹ ርዕስ translations: edit: ትርጉሞችን አርትዖት ያድርጉ @@ -1269,6 +1572,26 @@ am-ET: type_label: አይነት visibility: የሚታይ web_app: የመረጃዉ በይነመረብ + skip_logic: + name: አመክንዮ ዝለል? + section: + title: ከሆነ ይህ ቅጽ መታየት አለበት። + buttons: + add: ፎርሙን  ይጨምሩ + conditions: + add: ፎርሙን  ይጨምሩ + update: 'የተሻሻለ ፎርም ' + field_name: የቦታው ስም + condition: 'ፎርም ' + empty: 'አዲስ ፎርም አልተጨመረም ' + type: አይነት + types: + and: + display_text: 'ይህን ፎርም አስገባ ' + name: 'እና ' + or: + display_text: ' ወይም ይህን ' + name: ' ወይም ' home: ar: العربية ar-IQ: العربية (العراقية) @@ -1280,7 +1603,6 @@ am-ET: dashboard: የመረጃ ሰሌዳ en: እንግሊዘኛ es: እስፓኒሽ - es-GT: እስፓኒሽ (ጋቲማላ) fr: ፍራንስ id: ባህዛ km: ភាសាខ្មែរ @@ -1293,7 +1615,7 @@ am-ET: ne: नेपाली label: መኖሪያ language: ቋንቋ - manage_system_users: "የተጠቃሚዎችን የመረጃ ቋት የማመሳሰል አስተዳደር " + manage_system_users: 'የተጠቃሚዎችን የመረጃ ቋት የማመሳሰል አስተዳደር ' my: ဗမာစာ pt: ፖርቱገስ pt-BR: ፖርቱገዝ (ብራዚል) @@ -1309,7 +1631,10 @@ am-ET: associated_case: "ተያያዥነት ያለው ጉዳይ" messages: creation_success: የክስተት መመዝገቢያ በትክክል ተፈጥሯል - creation_success_queue: "የክስተት መመዝገቢያ በመግቢያዉ ላይ በትክክል ተፈጥሯል\n\n " + creation_success_queue: 'የክስተት መመዝገቢያ በመግቢያዉ ላይ በትክክል ተፈጥሯል + + +  ' disabled: ክስተቱ ጠፍቷል update_success: 'ክስተት 1 %{record_id} በተሳካ ሁኔታ ተሻሽሏል።' update_success_queue: 'ክስተት %{record_id}የክስተት መመዝገቢያ በመግቢያዉ ላይ በትክክል ተፈጥሯል ' @@ -1322,7 +1647,6 @@ am-ET: killing: የህጻናት ግድያ maiming: በህጻናት ላይ ጉዳት ማድረስ recruitment: ህጻናትን መመልመልና/ መጠቀም - sexual_violence: መድፈርና የወሲብ ጥቃት ማድረስ abduction: ጠለፋ attack_on: በትምህርት ቤት(ቶች)ና/ በሆስፒታል(ሎች( ጥቃት ማድረስ military_use: በትምህርት (ቤት) እና በሆስፒታል የጦር መሳርያ መጠቀም @@ -1336,7 +1660,7 @@ am-ET: enable_success: ክስተቱ በተሳካ ሁኔታ እንዲሰራ ተደርጓል id: መታወቂያ# date_of_interview: የቃለመጠይቅ ቀን - date_of_incident: "የክስተቱ ቀን " + date_of_incident: 'የክስተቱ ቀን ' incident_location: የተከሰተበት አካባቢ violations: ጥሰቶች export: ወደሌላ ላክ/አስተላልፍ @@ -1347,23 +1671,70 @@ am-ET: children: ህጻናት girls: ሴቶች incident_location: የተከሰተበት አካባቢ + status: ያለበት ሁኔታ unaccompanied_separated_status: የጥበቃ ሁኔታ unknown: የማይታወቅ verification_status: የማረጋገጫ ሁኔታ violence_type: የጥሰት አይነት - armed_force_group_name: የታጠቁ ቡድኖች ስም + armed_force_group_party_name: ታጣቂ ኃይሎች፣ ቡድኖች ወይም ሌሎች አካላት armed_force_group_type: የታጠቁ ቡድኖች ስብስብ አይነት + violations: ጥሰቶች + individual_violations: ግለሰቡ የደሰበት ጥሰት + individual_age: የግለሰቡ ዕድሜ + individual_sex: የግለሰቡ ጾታ + victim_deprived_liberty_security_reasons: ነጻነትን የተነፈገ + reasons_deprivation_liberty: ለነጻነት መነፈግ ምክንያቶች ምንድን ናቸው? + victim_facilty_victims_held: ተጎጂው የተጠቀመበትን የአገልግሎት ቦታ ይምረጡ + torture_punishment_while_deprivated_liberty: ህጻኑ (ህጻናቱ) ነፃነት ሲነፈጉ ማሰቃየት ወይም ሌላ ጭካኔ የተሞላበት፣ ኢሰብአዊ ወይም ለክብረነክ አያያዝ ወይም ቅጣት ተዳርገዋል? + verified_ghn_reported: ይህ ክስተት የተካተተበትን GHN ይግለጹ + weapon_type: 'የተጠቀሙት የጦር መሳሪያ አይነት' + facility_impact: 'የደረሰው የአካላዊ ጉዳት አይነትና ደረጃ' + facility_attack_type: 'ከጤና ወይም ከተምህርት ጋር ተያያዥነት ያላቸው የጥሰት አይነቶች' + child_role: 'ህፃኑ/ህጻናት) በታጣቂ ቡድኖች ውስጥ ምን አይነት ሚና ነበራቸው?' + abduction_purpose_single: 'የጠለፋው አላማ' + military_use_type: 'የውትድርና አጠቃቀም አይነት' + types_of_aid_disrupted_denial: 'የተስተጓጎለ/የተከለከለ የእርዳታ/የአገልግሎት አይነት' + late_verified_violations: ዘግይተው የተረጋገጡ ጥሰቶች + perpetrator_category: የወንጀለኛው/ጥቃት አድራሽ አይነት + record_owner: የመዝገቡ ባለቤት register_new_incident: አዲስ ክስተት selectable_date_options: date_of_first_report: የቃለመጠይቅ ቀን incident_date_derived: የቃለመጠይቅ ቀን selected_records: ' {ሁናቴዎ(ዮች)ተመርጧል}' selected_all_records: 'ሁሉንም ምረጥ %{total_records}ይህን ክስተት የሚዛመዱትን' - survivor_code: "የተጎጂው መለያ\n " + summary_mrm: + label: የክስተቱ ማጠቃለያ + fields: + children_multiple_violation: + label: በበርካታ ጥሰቶች/ጥቃቶች የተጎዱ ህፃናት + summary_of_incident: + label: የክስተቱ ማጠቃለያ + incident_total_tally: + label: የተጎጂዎች ብዛት + boys: ወንዶች + girls: ሴቶች + unknown: ያልታወቀ + incident_date: + label: የተከሰተበት ቀን + incident_location: + label: የተከሰተበት ቦታ + incident_description: + label: የክስተቱ ብዛት + incident_update: + label: ' ክስተቱን ማሳወቅ' + survivor_code: 'የተጎጂው መለያ + +  ' show_incident: '{የክስተቱ መለያ}' - social_worker: "ማህበራዊ ሰራተኛ\n " + social_worker: 'ማህበራዊ ሰራተኛ + +  ' + violation_type: የጥሰቱ ዓይነት violence_type: የጥሰት አይነት type_violence: የጥሰት አይነት + violation_summary: ማጠቃለያ + sort_by: በዓይነት መለየት key_performance_indicators: label: "የቁልፍ አፈጻጸም አመልካች" case_assessment: "የዳሰሳ ጥናት" @@ -1397,9 +1768,7 @@ am-ET: number_of_cases: title: "1. የተመዘገቡ ጉዳዮች ብዛት" reporting_site: "ሪፖርት የተደረገበት በይነ መረብ" - helptext: | - ይህ አመልካች በየወሩ ምን ያህል አዳዲስ ጉዳዮች እንደሚከፈቱ ይቆጥራል። የሪፖርት ማድረጊያ ጣቢያ የተጠቃሚው ድርጅት አገልግሎቶችን እየሰጠ የሚገኝበት ጣቢያ እንደሆነ ተረድቷል። - እና ጉዳዩ ለአገልግሎት ሰጪው ሪፖርት የተደረገበት፡፡ + helptext: "ይህ አመልካች በየወሩ ምን ያህል አዳዲስ ጉዳዮች እንደሚከፈቱ ይቆጥራል። የሪፖርት ማድረጊያ ጣቢያ የተጠቃሚው ድርጅት አገልግሎቶችን እየሰጠ የሚገኝበት ጣቢያ እንደሆነ ተረድቷል። \n እና ጉዳዩ ለአገልግሎት ሰጪው ሪፖርት የተደረገበት፡፡\n" number_of_incidents: title: "2. የድርጊቶች ብዛት" reporting_site: "ሪፖርት የተደረገበት ጣቢያ" @@ -1437,9 +1806,7 @@ am-ET: title: "6. የተጠናቀቁ የጉዳይ ድርጊት እቅዶች " completed: "የተጠናቀቁ የጉዳይ ድርጊት እቅዶች " label: "የተጠናቀቁ የጉዳይ ድርጊት እቅዶች " - helptext: | - የድጋፍ እቅድ የተሰራላቸውን ጉዳዮች ያሰላል፡፡ - የድጋፍ እቅድ ተሰራ የሚባለው አስፈላጊ መስፈርቶች በተገቢው ሲጠናቀቁ ነው። + helptext: "የድጋፍ እቅድ የተሰራላቸውን ጉዳዮች ያሰላል፡፡ \nየድጋፍ እቅድ ተሰራ የሚባለው አስፈላጊ መስፈርቶች በተገቢው ሲጠናቀቁ ነው።\n" completed_supervisor_approved_case_action_plans: title: "7. የጉዳይ የእቅድ መርሀግብር በሀላፊ የጸደቀ" completed_and_approved: "የጉዳይ የእቅድ መርሀግብር በሀላፊ የጸደቀ" @@ -1456,37 +1823,25 @@ am-ET: female: "ሴት" 0-11: "0-11" 12-17: "12-17" - ">18": "ከ18 በላይ" + '>18': "ከ18 በላይ" disability: "አካል ጉዳተኛ" no_disability: "አካል ጉዳት የለም" - helptext: | - ይህ አመላካች የተሰጡ አገልግሎቶችን ይቆጥራል፡፡ - ይህም ጉዳዩን የጀመረው ተቃም የሰራቸውን ብቻ ነው፡፡ - በቅብብሎሽ የተሰሩትን ሳይጨምር + helptext: "ይህ አመላካች የተሰጡ አገልግሎቶችን ይቆጥራል፡፡\nይህም ጉዳዩን የጀመረው ተቃም የሰራቸውን ብቻ ነው፡፡ \nበቅብብሎሽ የተሰሩትን ሳይጨምር\n" average_referrals: title: "9. ሪፈራል የተሰራላቸው አጠቃላይ ኬዞች" label: "ካሉ ኬዞች መካከል ሪፈራል የተሰራላቸው" - helptext: | - ለእያንዳንዱ ኬዝ የተደረጉ የሪፈራል ብዛቶችን (ሁሉንም አይነት አገልግሎቶች) - ለሁሉም ኬዞች ኬዞች ቢዘጉም ወይም ያልተዘጉ ቢሆንም፡፡ - የተደረጉ ቅብብሎሽ ጨምሮ + helptext: "ለእያንዳንዱ ኬዝ የተደረጉ የሪፈራል ብዛቶችን (ሁሉንም አይነት አገልግሎቶች) \nለሁሉም ኬዞች ኬዞች ቢዘጉም ወይም ያልተዘጉ ቢሆንም፡፡ \nየተደረጉ ቅብብሎሽ ጨምሮ\n" referrals_per_service: title: "ሪፈር የተደረጉ ኬዞችና አገልግሎቶች" average_followup_meetings_per_case: title: "10. አጠቃላይ ክትትል የተደረገላቸው ኬዞች" label: "የክትትልና ውይይት ተሰራላቸው ኬፖች" - helptext: | - የተደረጉ ክትትሎች ብዛት - የክትትል ወይይቶች በኬዝ ወርከሮች መካከል - የተደረጉ ቃለመጠይቅና በእውቀት ላይ የተመሰረተ ስምምነትን ጨምሮ + helptext: "የተደረጉ ክትትሎች ብዛት \nየክትትል ወይይቶች በኬዝ ወርከሮች መካከል \nየተደረጉ ቃለመጠይቅና በእውቀት ላይ የተመሰረተ ስምምነትን ጨምሮ\n" time_from_case_open_to_close: title: "11. የተቀመጠ የጊዜ ገደብ ኬዝ ለመክፈትና ለመዝጋት" time: "ጊዜ" percent: "የኬዞች ብዛት ፕርሰንታይል" - helptext: | - እነዚህ አመላካቾች ኬዞች ለምን ያህል ጊዜ ተከፍቶ እንደቆየ፣ የጉዳይ አያያዝ ሂደት እንደቆየ - ፣ ሪፖርት ከተደረገበት እስከ ሚዘጋ ድረስ፡፡ በሚከተለው መልኩ ለተቀመጡ - የጊዜ እርዝማኔ ማለትም ከ1 ወር በታች፣ በ1 እና 3 ወር መካከል፣ ከ3- 6 ወር፣ ከ6 ወር በላይ፡፡ + helptext: "እነዚህ አመላካቾች ኬዞች ለምን ያህል ጊዜ ተከፍቶ እንደቆየ፣ የጉዳይ አያያዝ ሂደት እንደቆየ\n፣ ሪፖርት ከተደረገበት እስከ ሚዘጋ ድረስ፡፡ በሚከተለው መልኩ ለተቀመጡ \nየጊዜ እርዝማኔ ማለትም ከ1 ወር በታች፣ በ1 እና 3 ወር መካከል፣ ከ3- 6 ወር፣ ከ6 ወር በላይ፡፡ \n" case_closure_rate: title: "12. የተዘጉ ኬዞች ቁጥር" reporting_site: "የሪፖርት ማድረጊያ ጣቢያ" @@ -1496,8 +1851,7 @@ am-ET: title: "13. የተገልጋዩ የእርካታ መጠን" label: "የተገልጋዩ እርካታ " invalid: "ይህንን በአሁኑ ጊዜ ማስላት አንችልም" - helptext: | - ይህ አመልካች በተሰጣቸው የጉዳይ አያያዝ አገልግሎት እርካታ ያላቸውን የተገልጋዮች ግብረመልስ ዳሰሳ ያጠናቀቁ የተረፉትን መቶኛ ይለካል። ይህ አመልካች በጾታን መሰረት ያደረጉ ጥቃቶች የመረጃ አያያዝ ስርዓት ወይም GBVIMS+ ላይ የደንበኛ ግብረ መልስ ቅጹን ከሟች አገልግሎቱን ከሰጠው የጉዳይ አያያዝ ሰራተኛ ሌላ ሰራተኛ በማጠናቀቅ ይገለጻል። + helptext: "ይህ አመልካች በተሰጣቸው የጉዳይ አያያዝ አገልግሎት እርካታ ያላቸውን የተገልጋዮች ግብረመልስ ዳሰሳ ያጠናቀቁ የተረፉትን መቶኛ ይለካል። ይህ አመልካች በጾታን መሰረት ያደረጉ ጥቃቶች የመረጃ አያያዝ ስርዓት ወይም GBVIMS+ ላይ የደንበኛ ግብረ መልስ ቅጹን ከሟች አገልግሎቱን ከሰጠው የጉዳይ አያያዝ ሰራተኛ ሌላ ሰራተኛ በማጠናቀቅ ይገለጻል። \n" supervisor_to_caseworker_ratio: title: "14. ሱፐርቫይዘር ለኬዝ ወርከር ምጥጥን" label: "ኬዝ ወርከር ለሱፐርቫይዘር " @@ -1511,10 +1865,7 @@ am-ET: 20cases: "11-20 ኬዞች" 21-30cases: "21-30 ኬዞች" 30cases: "> 30 ኬዞች" - helptext: | - የተያዙ ኬዞችና የባለሙያዎች ብዛት - ኬዞችና የኬዝ ወርኮች ብዛት እንደሚከተለው ምጥጥን መሆን አለበት - ከ10 በታች ኬዞች፣ 10-20 ኬዞች፣ 21-30 የተከፈቱ ኬዞች፣ ከ30 በላይ ኬዞች + helptext: "የተያዙ ኬዞችና የባለሙያዎች ብዛት \nኬዞችና የኬዝ ወርኮች ብዛት እንደሚከተለው ምጥጥን መሆን አለበት\nከ10 በታች ኬዞች፣ 10-20 ኬዞች፣ 21-30 የተከፈቱ ኬዞች፣ ከ30 በላይ ኬዞች\n" date_range_dialog: title: "የቀን ገደብ ማስተካከል" description: "ይህ ለውጥ አንዴ ከተደረገ መረጃው ከታች ከተዘረዘሩት መካከል ይመረጣል " @@ -1524,7 +1875,6 @@ am-ET: aria-labels: from: "መረጃ ከዚህ ቀን በኸላ ይመረጣል" to: "ከዚህ ቀን በፊት መረጃ ይመረጣል" - location: base_types: camp: ካምፕ @@ -1549,6 +1899,12 @@ am-ET: central_warehouse: ማዕከላዊ መጋዘን warehouse: ስቶር buyingstation: የመግዣ ጣቢያ + township: የከተማ አስተዳደር + municipality: ማዘጋጃ ቤት + autonomous_region: ራስ ገዝ ክልል + parish: አጥቢያ + cercle: ሰርክል/ክብ + sub-county: ክፍለ ሀገር label: መገኛ name: ስም code: መለያ ቁጥር @@ -1559,9 +1915,9 @@ am-ET: message: ለመጫን ሲ ኤስ ቪን ይጫኑ፡፡ ይህም ዩቲኤፍ- ማስገቢያ ስልቶችንና ይጨምራል no_location: ማንኛውንም የተጠቃሚ መለያ ከመፍጠርዎ በፊት እባክዎ አካባቢዎችን ያስቀምጡ። enable_title: አድራሻውን ያብሩ - enable_text: "እርግጠኛ ነህ/ሽ? የተመረጡትን ቦታዎችን ካጠፉ, በአካባቢ አይታይም" + enable_text: እርግጠኛ ነህ/ሽ? የተመረጡትን ቦታዎችን ካጠፉ, በአካባቢ አይታይም disable_title: አድራሻ ያጥፉ - disable_text: "እርግጠኛ ነህ/ሽ? የተመረጡትን ቦታዎችን ካጠፉ, በአካባቢ አይታይም" + disable_text: እርግጠኛ ነህ/ሽ? የተመረጡትን ቦታዎችን ካጠፉ, በአካባቢ አይታይም logger: actions: _approved: ጸድቀል @@ -1584,19 +1940,32 @@ am-ET: destroy: አስወግድ detach: ለያይ enable_disable_record: የጠፉ መረጃዎችን መልስ/አሳይ - export: "ማሻገር\n " + export: 'ማሻገር + +  ' flag: ምልክት ማሳየት/ማውለብለብ - import: "መቀበል/ማምጣት\n " + import: 'መቀበል/ማምጣት + +  ' incident_details_from_case: የኬዝ/ሁናቴ ዝርዝር ቅጽ index: መረጃ ጠቋሚ list: ዝርዝር login: ግባ password_reset: የሚስጥር ቁጥር ቀይር password_reset_request: የሚስጥር ቁጥር ለመቀየር ጠይቅ - refer: "ሪፈር/ሽኝት\n \n " + refer: 'ሪፈር/ሽኝት + +   + +  ' refer_accepted: ሪፈር ተቀባይነት አግኝታል - refer_done: "ሪፈር ተደርጓል\n " - refer_rejected: "ሪፈራል ውድቅ ተደርጓል\n\n " + refer_done: 'ሪፈር ተደርጓል + +  ' + refer_rejected: 'ሪፈራል ውድቅ ተደርጓል + + +  ' refer_revoke: ተጨማሪ ዝርዝር ተጠይቃል refer_to: ለ ቅብብል ተደርጋል reopen: ዳግም መክፈት @@ -1604,7 +1973,9 @@ am-ET: show: አሳይ show_alerts: ጠቆሚ አሳይ traces: መፈላለግ - transfer: "ማስተላለፍ\n " + transfer: 'ማስተላለፍ + +  ' transfer_accepted: ማስተላለፍ ተቀባይነት አግኝታል transfer_rejected: ማስተላለፍ ውድቅ ተደርጋል transfer_request: የማስተላለፍ ጥያቄ @@ -1627,7 +1998,10 @@ am-ET: by_user: ወደ ስርዓቱ ተገልጋይ case_plan_approved: "{ማጽደቅ}" case_plan_requested: "{የተጠየቀ}" - close: "መዝጋት\n\n " + close: 'መዝጋት + + +  ' closure_approved: "{ማጽደቅ}" closure_requested: "{የተጠየቀ}" consent_count: የስምምነት ቁጥር @@ -1645,7 +2019,7 @@ am-ET: protect: ስም ደብቅ view: ስም እዩ index: ቅጅዎችን ዘርዝር - list: " ዘርዝር" + list: ' ዘርዝር' login: ግባ logout: ዘግተው ይውጡ lookups_for_field: ምድቦችን ፈልግ @@ -1655,7 +2029,7 @@ am-ET: match_record: የማዛመድ መዝገብ permitted_field_list: የምድብ ዝርዝር quick_view: በፍጥነት መመልከት - reassign: "የምድብ " + reassign: 'የምድብ ' resources: audit_log: የመዝገብ ጉድኝት user: ተጠቃሚ @@ -1690,7 +2064,7 @@ am-ET: action_plan: የድርጊት መርሃ ግብር ቅጹን ማጽደቅን ይጠይቁ bia: የህጻኑ ጥቅምና ደህንነት ማጽደቂያ ቅጽ case_plan: የድጋፍ እቅድ እንዲጸድቅ ይጠይቁ - closure: "የጉዳይ እቅድ ቅጽ እንዲጸድቅ መጠየቅ " + closure: 'የጉዳይ እቅድ ቅጽ እንዲጸድቅ መጠየቅ ' gbv_closure: ጾታን መሰረት ያደረጉ ጥቃቶች ጉዳይ ለመዝጋት ጥያቄ ማቅረብ request_transfer: የማዘዋወር ጥያቄን መላክ request_transfer_view: የማዘዋወር ጥያቄዎችን መመልከት @@ -1713,8 +2087,8 @@ am-ET: password_confirmation: label: የይለፍ ቃል ማረጋገጫ password_match: - label: "የይለፍ ቃሉ ተመሳሳይ መሆን አለበት " - provider_title: "{ከ---ጋር}" + label: 'የይለፍ ቃሉ ተመሳሳይ መሆን አለበት ' + provider_title: '{ከ---ጋር}' title: ግባ username: የተጠቃሚ ስም password_reset_modal: የይለፍ ቃል እንደገና መስጠት @@ -1738,87 +2112,177 @@ am-ET: no_options: ይህ ፍለጋ ሌላ አማራጭ የለውም translation_label: ጽሁፍ መተርጎም values: አማራጮች + locked_alert_message: ይህ መፈለጊያ ተቆልፏል managed_reports: - label: "ጥልቅ እይታ " + generated_on: የመነጨ በርቷል + label: 'ጥልቅ እይታ ' total: ድምር + violations_total: ጥሰቶች filter_by: date: ቀን - verification_status: "የማረጋገጫ ሁኔታ " + verification_status: 'የማረጋገጫ ሁኔታ ' + violation_type: የጥሰት ዓይነት + status: ደረጃ + status_open: 'ክፍት ነው ' + status_closed: ተዘግቷል + user_group: 'የተጠቃሚው ቡድን + +  ' + agency: ኤጀንሲ + by: በ + workflow: የስራ ፍሰት ሁኔታ + cp_incident_violence_type: የጥቃት አይነት + referral_transfer_status: 'የቅብብሎሽ/ የማዘዋወር ሁኔታ + +  ' + status_options: + open: 'ክፍት ነው ' + closed: ተዘግቷል + by_options: + created_by_groups: የተጠቃሚ ቡድኖች የቅጂ ባለቤትነት + owned_by_groups: የተጠቃሚ ቡድኖች የቅጂ ባለቤትነት + created_organization: የመዝገቡ ፈጣሪ ኤጀንሲ + owned_by_agency_id: የመዝገቡ ባለቤት ኤጀንሲ + referral_transfer_status_options: + in_progress: በመጠባበቅ ላይ + accepted: ተቀባይነት አግኝቷል + rejected: ውድቅ ተደርጓል + done: ተደርጓል date_range: month: ወር - quarter: "ሩብ " - year: "ዓመት " + quarter: 'ሩብ ' + year: 'ዓመት ' + week: ሳምንት date_range_options: - this_quarter: "በዚህ ሩብ ዓመት " - last_quarter: "ባለፈው ሩብ ዓመት " - this_month: "በዚህ ወር " - last_month: "ባለፈው ወር " + this_quarter: 'በዚህ ሩብ ዓመት ' + last_quarter: 'ባለፈው ሩብ ዓመት ' + this_month: 'በዚህ ወር ' + last_month: 'ባለፈው ወር ' + this_week: በዚህ ሳምንት + last_week: ባለፈው ሳምንት this_year: በዚህ ዓመት last_year: ባለፈው ዓመት custom: ልማድ - no_data: "ለግንዛቤ የሚረዳ ምንም መረጃ አልተገኘም " + no_data: 'ለግንዛቤ የሚረዳ ምንም መረጃ አልተገኘም ' no_data_table: ለግንዛቤ የሚረዳ የተደራጀ መረጃ አልተገኘም + incomplete_data: 'ያልተሟላ መረጃ + +  ' + individual_children: + name: 'የእያንዳንዱ ህፃን ' + reports: + individual_children: 'የእያንዳንዱ ህፃን ' + sub_reports: + individual_age: የእያንዳንዱ ህፃን በዕድሜ + individual_violation_type: እያንዳንዱ ህፃን በደረሰበት የጥሰት ዓይነት + individual_region: እያንዳንዱ ህፃን በክልል ደረጃ + individual_perpetrator: እያንዳንዱ ህፃን በጥቃት ፈፃሚዎች + ghn_report: + name: ሉላዊ አባሪ ማስታወሻ + reports: + ghn_report: ሉላዊ አባሪ ማስታወሻ + sub_reports: + verified_information: 'የተጎጂዎች የተረጋገጠ መረጃ   + +  ' + late_verification: ዘግይተው የተረጋገጡ የተጎጂዎች መረጃ + unverified_information: በመረጃ ያልተረጋገጡ ጥሰቶች + verified_information_violations: በመረጃ የተረጋገጡ ጥሰቶች + late_verification_violations: ዘግይተው የተረጋገጡ ጥሰቶች + unverified_information_violations: 'በመረጃ ያልተረጋገጠ ጥሰቶች + +  ' + killing: የህፃናት ግድያ + maiming: የህጻናትን አካል ማጉደል + recruitment: ህፃናትን  ለመቅጠር እና/ወይም መጠቀም መመልመል + sexual_violence: አስገድዶ መድፈር እና ሌሎች ዓይነቶች ወሲባዊ ጥቃቶች + rape: አስገድዶ መድፈር እና ሌሎች ወሲባዊ ጥቃቶች + abduction: ጠለፋ + attack_on_hospitals: ህፃናት በሆስፒታል(ዎች) እያሉ የሚደረጉ ጥቃቶች + attack_on_schools: በትምህርት ቤቶች ላይ የሚደርስ ጥቃት + military_use: ትምህርት ቤት(ዎች) እና/ወይም ሆስፒታል(ዎች) ለወታደራዊ አገልግሎት ማዋል + denial_humanitarian_access: ለህፃናት ሰብአዊ አቅርቦት/ድጋፎችን መከልከል + multiple_violations: በበርካታ ጥሰቶች/ጥቃቶች የተጎዱ ህፃናት + detention: እስራት + boys: ወንዶች + girls: ልጃገረዶች + total: አጠቃላይ + unknown: ያልታወቀ + associated_violations: ተዛማጅ ጥሰቶች/ጥቃቶች violations: name: ጥሰቶች - description: '' filter_options: incident_date: ድርጊቱ የተፈጸመበት ቀን date_of_report: ሪፖርት የተደረገበት ቀን ctfmr_verified_date: የተረጋገጠበት ቀን + verified: የተረጋገጠ reports: killing: ህጻናትን መግደል maiming: የህጻናትን አካል ማጉደል recruitment: ህጻናትን ለመጠቀሚያነት መመልመል/መጠቀም - sexual_violence: አስገድዶ መድፈር/ሌላ አይነት ጾታዊ ጥቃት + sexual_violence: አስገድዶ መድፈር እና ሌሎች ወሲባዊ ጥቃቶች + rape: አስገድዶ መድፈር እና ሌሎች ወሲባዊ ጥቃቶች abduction: ጠለፋ - attack_on: በትምህርት ቤት/በሆስፒታሎች ሚፈጸሙ ጥቃቶች + attack_on_hospitals: በሆስፒታል /ሎች/ ላይ የሚደረጉ ጥቃቶች + attack_on_schools: በትምህርት ቤቶት/ቤ/ቶች / ላይ የሚደርስ ጥቃት) military_use: ትምህርት ቤቶችን/ሆስፒታሎችን ለወታደራዊ ዓላማ መጠቀም denial_humanitarian_access: ለህጻናት ሰብዓዊ ድጋፎችን መከልከል + detention: ማሰር sub_reports: + children: ህፃናት combined: ጥሰቶች + denial_humanitarian_access: የሰብአዊነት ክልከላ/ነፈጋ + denial_type: የክደት አይነት detention_detained: በቁጥጥር ስር ውለው መቆየት detention_released: ተለቀቀ/መለቀቅ perpetrators: በጥቃት ፈጻሚዎች ስር ያሉ ህጻናት + perpetrators_denial: በአጥፊዎች የተፈጸሙ ጥሰቶች/የጥቃቶች ብዛት + perpetrator_detention: ' የህፃናት ብዛት በአጥቂዎች የደረሰ' + perpetrators_incidents: በአጥቂ የሚከሰቱ ክስተቶች ብዛት + reporting_location_incidents: በክልል የሚከሰቱ ክስተቶች ብዛት reporting_location: የህጻናት ቁጥር በክልል + reporting_location_detention: የህጻናት ቁጥር በክልል + reporting_location_denial: እንደ ክልል የተፈጸሙ ጥሰቶች ብዛት attack_type: የህጻናት ቁጥር በደረሰባቸው ጥቃት ዓይነት boys: ወንዶች girls: ሴቶች unknown: የማይታወቅ total: አጠቃላይ ድምር + violation: ጥሰቶች + sexual_violence_type: የወሲብ ጥቃት ቅፅ(ዎች) + detention_status: የታሰሩ ልጆች ሁኔታ + type_of_use: የአጠቃቀም አይነት + factors_of_recruitment: የምልመላው ምክንያቶች + still_being_held: አሁንም ተይዟል። + released: 'ተለቋል' + escaped: 'አምልጧል' + abduction_reasons: የጠለፋ ምክንያቶች + abducted_status: የተጠለፈበት ሁኔታ + facility_attack_type: የጥሰት አይነት + received_response: ምላሽ ያገኙ ህጻናት + male: ወንድ + female: ሴት + military_use_type_of_use: የደረሱ ጥሰት አይነቶች gbv_statistics: name: ፆታን መሰረት ያደረጉ ጥቃቶች መረጃ - description: '' filter_options: date_of_first_report: የቃለ ምልልስ ቀን incident_date: ድርጊቱ የተፈጸመበት ቀን reports: - incidents: ድርጊቶች perpetrators: ድርጊቱን/ጥቃቱን ፈጻሚዎች - sub_reports: - combined: ድርጊቶች - total: ሪፖርት የተደረጉ ፆታን መሰረት ያደረጉ ጥቃቶች ብዛት - gbv_sexual_violence: ሪፖርት የተደረጉ ወሲባዊ ጥቃቶች ብዛት - gbv_previous_incidents: ጾታዊ ጥቃት በደረሰባቸው አካላት ሪፖርት የተደረጉ ጉዳዮች ብዛት - gbv_sexual_violence_type: የድርጊቱ ዓይነት - incident_timeofday: ድርጊቱ የተሰጸመበት ቀንና ሰዓት - elapsed_reporting_time: ድርጊቱ የተፈጸመበትና ሪፖርት የተደረገበት ቀን ልዩነት - elapsed_reporting_time_rape: የአስገድዶ መድፈር ድርጊት፡ ድርጊቱ የተፈጸመበት ቀንና ሪፖርት የተደረገበት ቀን ልዩነት - incident_location_type: ድርጊቱ የተፈጸመበት ቦታ - number_of_perpetrators: ተቀዳሚ ወንጀል ፈጻሚዎች ብዛት - perpetrator_relationship: ወንጀሉን ፈጽሟል የተባለው ሰው ጥቃት ከደረሰበት ህጻን ጋር ያለው ዝምድና - perpetrator_age_group: ወንጀሉን ፈጽሟል የተባለው ሰው የዕድሜ ምድብ - perpetrator_occupation: ወንጀሉን ፈጽሟል የተባለው ሰው ስራ + survivors: ጉዳት የደረሰበት/ባት + referrals: ቅብብሎሽ messages: - alert_items: "ዝርዝር ማስታወሻ አለህ/አለሽ%{items}" + alert_items: ዝርዝር ማስታወሻ አለህ/አለሽ%{items} alerts_for: - approval: "ፈቃድ በመጠባበቅ ላይ%{form_section_name}" + approval: ፈቃድ በመጠባበቅ ላይ%{form_section_name} field_change: '%{form_section_name}በመሻሻል ላይ የነበረ%{alert_time}' - transfer_request: "አዲስ የዝውውር ጥያቄ ቀርቧል%{date}በ%{user}ከ%{agency}" - duplicate_field: "ከዚጉዳይ ጋር ተመሳሳይ ሌላ ጉዳይ አለ%{field_name}" + transfer_request: አዲስ የዝውውር ጥያቄ ቀርቧል%{date}በ%{user}ከ%{agency} + duplicate_field: ከዚጉዳይ ጋር ተመሳሳይ ሌላ ጉዳይ አለ%{field_name} cannot_edit: ማስተካከል አይቻልም confirmation_message: አዎ የሚለውን ከተጫኑ ያልተመዘገቡ ለውጦች ጠፍተው ወደ ዝርዝር እይታ ይመለሳሉ፡፡ ወደ መዝገቡ ለመመለስ አጥፋ የሚለውን ይጫኑ confirmation_message_subform: አዎ የሚለውን ከተጫኑ እዚህ ውስጥ ያልተመዘገቡ ለውጦች ይጠፋሉ፡፡  ለውጦችን ለማስቀጠል አጥፋ የሚለውን ይጫኑ፡፡ - dashboard_offline: "ከበይነ-መረብ ግንኙነት ውጭ ነዎት፡፡ የመረጃ መመዝገቢያ ሰሌዳው የበይነ መረብ ግንኙነት እንዳገኙ ሙሉ በሙሉ አገልግሎት ወደመስጠት ይመለሳል፡፡ " + dashboard_offline: 'ከበይነ-መረብ ግንኙነት ውጭ ነዎት፡፡ የመረጃ መመዝገቢያ ሰሌዳው የበይነ መረብ ግንኙነት እንዳገኙ ሙሉ በሙሉ አገልግሎት ወደመስጠት ይመለሳል፡፡ ' field_name_on_form_name: '%{field_name}ቅጹ ላይ ያለ ቦታ%{form_name}ከ' logout_confirmation: ተጨማሪ ቆይታ ይፈልጋሉ logout_offline_warning: ዘግተው  መውጣት ይፈልጋሉ፤ የበይነ መረብ ግንኙነት እስኪያገኙ ድረስ ተመልሰው መግባት አይችሉም፡፡ ከበይነ መረብ ግንኙነት ውጪ ያደረጉት ለውጥ ይጠፋል፡፡ @@ -1829,10 +2293,10 @@ am-ET: no_changes: ምንም አይነት ለውጥ አላደረጉም not_available: አልተገኘም record_list: - column_header_tooltip: "{ለመለየት}" + column_header_tooltip: '{ለመለየት}' of: የ no_match: ይቅርታ ተመሳሳይ የምዝገባ መረጃ የለም - rows_per_page: "በአንድ ገጽ ያለ መስመር ብዛት " + rows_per_page: 'በአንድ ገጽ ያለ መስመር ብዛት ' sort: ለይ navigation: bulk_exports: የተላኩ @@ -1873,11 +2337,11 @@ am-ET: approvals_case_plan_pending: '{በሂደት ላይ}' approvals_closure: '1 %{የማጽደቅ_መለያ}' approvals_closure_pending: '{በሂደት ላይ}' - approve_action_plan: "{አጽድቅ}" - approve_assessment: "{ቅጹን አጽድቅ}" - approve_case_plan: "{አጽድቅ}" - approve_closure: "{ቅጹን አጽድቅ}" - approve_gbv_closure: "{ቅጹን አጽድቅ}" + approve_action_plan: '{አጽድቅ}' + approve_assessment: '{ቅጹን አጽድቅ}' + approve_case_plan: '{አጽድቅ}' + approve_closure: '{ቅጹን አጽድቅ}' + approve_gbv_closure: '{ቅጹን አጽድቅ}' assign: መድብ assign_within_agency: በተቋሙ ውስጥ መመደብ assign_within_user_group: በስርዓቱ ተገልጋይ ምድቦች ውስጥ መመደብ @@ -1890,8 +2354,8 @@ am-ET: case_risk: በዳሰሳ ጥናት ላይ ያሉ ጉዳዮችን ተመልከት cases_by_task_overdue_assessment: ቀሪ የዳሰሳ ጥናት ያላቸው ጉዳዮች cases_by_task_overdue_case_plan: ቀሪ የዕቅድ ስራት ያላቸው ጉዳዮችን ተመልከት - cases_by_task_overdue_followups: "ቀሪ አገልግሎት ያላቸው ጉዳዮችን ተመልከት " - cases_by_task_overdue_services: "ቀሪ አገልግሎት ያላቸው ጉዳዮችን ተመልከት " + cases_by_task_overdue_followups: 'ቀሪ አገልግሎት ያላቸው ጉዳዮችን ተመልከት ' + cases_by_task_overdue_services: 'ቀሪ አገልግሎት ያላቸው ጉዳዮችን ተመልከት ' cases_managed_other_users: በሌሎች ተገልጋዮች የተያዙ ጉዳዮች close: ዝጋ consent_override: ስምምነት ያልተሰጠበት @@ -1960,33 +2424,33 @@ am-ET: receive_transfer: በዝውውር መረከብ referral: ለቅብብሎሽ ልንጠቀመው የምንችል referral_from_service: ከአገልግሎት ቅጽ ላይ ጉዳይን ማስተላለፍ - registry_record: "መዝገብ ቤት " + registry_record: 'መዝገብ ቤት ' remove_assigned_users: የተመደቡ ተገልጋዮችን (ቅብብሎሾችን) አስወግድ reopen: ዳግም መክፈት report: ሪፖርት managed_report: ጥልቅ እይታ request_approval: ለማጽደቅ መጠየቅ - request_approval_action_plan: "{ለማጽደቅ መጠየቅ}" - request_approval_assessment: "{ለማጽደቅ መጠየቅ}" - request_approval_case_plan: "{ለማጽደቅ መጠየቅ}" - request_approval_closure: "{ለማጽደቅ መጠየቅ}" - request_approval_gbv_closure: "{ለማጽደቅ መጠየቅ}" + request_approval_action_plan: '{ለማጽደቅ መጠየቅ}' + request_approval_assessment: '{ለማጽደቅ መጠየቅ}' + request_approval_case_plan: '{ለማጽደቅ መጠየቅ}' + request_approval_closure: '{ለማጽደቅ መጠየቅ}' + request_approval_gbv_closure: '{ለማጽደቅ መጠየቅ}' request_transfer: ለማስተላለፍ መጠየቅ role: ሚና - save_search: "ፍልጋዎችን መዝግበህ አስቀምጥ " + save_search: 'ፍልጋዎችን መዝግበህ አስቀምጥ ' saved_search: ተመዝግበው የተቀመጡ ፍለጋዎች search_owned_by_others: በሌሎች ተጠቃሚዎች የተያዙ የጉዳይ መዝገቦችን ፈልግ self: የኔን ተገልጋዮች/መዝገቦች ብቻ አግኝ - service_provision_incident_details: "ከድርጊት/ክስተቱ ዝርዝር ላይ የሚሰጡ አገልግሎቶችን ጨምር የሚል ቁልፍ ተመልከት " - services_section_from_case: "በሌላ የስርዓቱ ተገልጋይ ጉዳይ ላይ የሚሰጡ አገልግሎቶችን ጨምር " + service_provision_incident_details: 'ከድርጊት/ክስተቱ ዝርዝር ላይ የሚሰጡ አገልግሎቶችን ጨምር የሚል ቁልፍ ተመልከት ' + services_section_from_case: 'በሌላ የስርዓቱ ተገልጋይ ጉዳይ ላይ የሚሰጡ አገልግሎቶችን ጨምር ' specific_roles: የተለዩ ተግባራትን ዝርዝር አግኝ sync_external: ከሌላ የመረጃ አያያዝ ስርዓት ጋር አገናኝ sync_mobile: ከበይነ መረብ ግንኙነት ውጪ ለመስራት ምልክት አድርግ system: ስርዓት - tracing_request: "የተጠየቀ ቅጅ " - transfer: "ለማዘዋወር መጠቀም የሚቻል " + tracing_request: 'የተጠየቀ ቅጅ ' + transfer: 'ለማዘዋወር መጠቀም የሚቻል ' user: ተጠቃሚ - user_group: "የተጠቃሚዎች ቡድን " + user_group: 'የተጠቃሚዎች ቡድን ' view_approvals: ፈቃድ የተሰጠባቸውን ተመልከት view_assessment: የዳሳ ጥናት ተመልከት view_photo: ፎቶ/ምስል ተመልከት @@ -2004,7 +2468,7 @@ am-ET: explanation: ዋና ጉዳዮችን/ቁልፍ የውጤት አመላካቾችን የመለየት ችሎታ label: ዋና ጉዳዮችን/ቁልፍ የውጤት አመላካቾችን አግኝ kpi_assessment_status: - explanation: "በተገልጋዩ ከተያዙ ጉዳዮችን መካከል የምን ያህሉ የዳሰሳ ጥናትን እንዳጠናቀቁ የማየት ችሎታ " + explanation: 'በተገልጋዩ ከተያዙ ጉዳዮችን መካከል የምን ያህሉ የዳሰሳ ጥናትን እንዳጠናቀቁ የማየት ችሎታ ' label: ዳሰሳ ጥናቱ ያለበት ደረጃ kpi_average_followup_meetings_per_case: explanation: በተገልጋዩ ከተያዙ ጉዳዮች መካከል በተወሰነ የጊዜ ገደብ ውስጥ የተደረጉ አማካይ ክትትሎች ብዛት የማየት ችሎታ @@ -2023,10 +2487,10 @@ am-ET: label: የደንበኞች የእርካታ ደረጃ kpi_completed_case_action_plans: explanation: በተገልጋዩ ከተያዙ ጉዳዮችን መካከል የምን ያህሉ የድጋፍ እቅድ እንደተሰራላቸው የማየት ችሎታ - label: "የተጠናቀቁ የጉዳይ ድርጊት እቅዶች " + label: 'የተጠናቀቁ የጉዳይ ድርጊት እቅዶች ' kpi_completed_case_safety_plans: explanation: በተገልጋዩ ከተያዙ ጉዳዮችን መካከል ደህንነቱ የተጠበቀ እቅድ የሚያስፈልጋቸውና የተጠናቀቁ ጉዳዮች ብዛት የመለየት ችሎታ - label: "የተጠናቀቁ የጉዳይ ደህንነት መጠበቂያ ዕቅዶች " + label: 'የተጠናቀቁ የጉዳይ ደህንነት መጠበቂያ ዕቅዶች ' kpi_completed_supervisor_approved_case_action_plans: explanation: በተገልጋዩ ከተያዙ ጉዳዮች መካከል በሱፐርቫይዘሮች የጸደቁ የጉዳይ ድርጊት እቅዶችን የማየት ችሎታ label: የተጠናቀቀና በሱፐርቫይዘር የጸደቀ የድርጊት እቅድ @@ -2041,7 +2505,7 @@ am-ET: label: የድርጊቶች ብዛት kpi_reporting_delay: explanation: ለባለሙያው ከቀረቡ ክስተቶች ውስጥ ጾታን መሰረት ያደረገው ጥቃት የተፈጸመበትና ሪፖርት በተደረገበት ቀናት መካከል ያለውን ልዩነት የማየት ችሎታ - label: "ሪፖርት ለማድረግ ያለው የቆይታ ጊዜ/መዘግየት " + label: 'ሪፖርት ለማድረግ ያለው የቆይታ ጊዜ/መዘግየት ' kpi_services_provided: explanation: ባለሙያው ከያዛቸው ጉዳዮች መካከል ምን አይነት አገልግሎቶችን በቤት ውስጥ እንዳገኙ የማት ችሎታ label: የተሰጡ አገልግሎቶች @@ -2069,41 +2533,41 @@ am-ET: write: explanation: የድርጅቶችን መረጃ የማስተካከል ችሎታ፤ ይህ ማለት በዚህ ስርዓት የተጠቀሱ ሁሉንም ድርጅቶች ላይ የሚሰራ መሆኑን ይወቁ፤ label: ማስተካከል - explanation: "ፐሪሜሮን የሚጠቀሙ ሌሎች ተቋማት ጋር ተቋሙን ወክሎ የሚቀርብ፡፡ " + explanation: 'ፐሪሜሮን የሚጠቀሙ ሌሎች ተቋማት ጋር ተቋሙን ወክሎ የሚቀርብ፡፡ ' label: ድርጅት audit_log: actions: read: - explanation: "ባለሙያዎች በዚህ ስርዓት ውስጥ ሊጣሩ የሚችሉ የተከናወኑ ሁሉም ተግባራትን፣ በባለሙያዎች የተሰበሩ፣ የተከናወኑ ድርጊቶች፣ የማህደር መታወቂያ፣ እና ተግባራቱ የተከናወኑበት ጊዜን እንዲመለከቱ ይፈቅዳል፡፡ ይህ ተግባር በሁሉም የስርዓቱ ተገልጋዮች የተከናወኑ ተግባራትን ለማየት የሚረዳ በመሆኑ በተለይም በፌዴራል ወይም በተቋም ደረጃ ላሉ ጉዳይ አስተዳዳሪዎች የተመቸ ነው፡፡ የቁጥጥር ማስታወሻው በእያንዳንዱ ተግባራት ውስጥ ያሉ የግል መረጃዎችን የማያሳይ መሆኑን ማስታው ይገባል፡፡ " + explanation: 'ባለሙያዎች በዚህ ስርዓት ውስጥ ሊጣሩ የሚችሉ የተከናወኑ ሁሉም ተግባራትን፣ በባለሙያዎች የተሰበሩ፣ የተከናወኑ ድርጊቶች፣ የማህደር መታወቂያ፣ እና ተግባራቱ የተከናወኑበት ጊዜን እንዲመለከቱ ይፈቅዳል፡፡ ይህ ተግባር በሁሉም የስርዓቱ ተገልጋዮች የተከናወኑ ተግባራትን ለማየት የሚረዳ በመሆኑ በተለይም በፌዴራል ወይም በተቋም ደረጃ ላሉ ጉዳይ አስተዳዳሪዎች የተመቸ ነው፡፡ የቁጥጥር ማስታወሻው በእያንዳንዱ ተግባራት ውስጥ ያሉ የግል መረጃዎችን የማያሳይ መሆኑን ማስታው ይገባል፡፡ ' label: ማየት explanation: በዚህ ስርዓት ውስጥ ሊጣሩ የሚችሉ የተከናወኑ ሁሉም ተግባራት፡፡ ይህ ግን የማን ጉዳይ፣ ክስተት፣ የፍለጋ ጥያዎችን መሆኑን የሚያካትት አይሆንም label: የቁጥጥር ማስታወሻ case: actions: add_note: - explanation: "የዚህ ስርዓት ተጠቃሚዎች በማስታዎሻ ንዑስ ቅጽ ላይ ማንኛውም ግብዓት መጨመር እንዲችሉ ይፈቅዳል፡፡ ተጠቃሚዎች በጉዳይ ማሳያ ገጽ ላይ “ማስታወሻ ጨምር”  የሚለውን በመንካት ይሄን ማድረግ ይችላሉ፡፡ ይህ ተግባር በመዋነኛነት ጉዳዮችን ለማስተካከል ፈቃድ የሌላቸው ነገር ግን በጉዳዮች ዙሪያ ለጉዳይ አያያዝ ባለሙያዎች ማስታወሻ ለመስጠት እንዲችሉ የጉዳይ አስተዳዳሪዎችን የሚጠቅም ነው፡፡  በዚህ አካሄድ ማስታወሻ መጨመር ማለት ምልክት ከማሳየት ጋር ተመሳሳይ ነው፡፡ ማስታወሻ ዎችን መጨመር የሚኖረውን  ጥቅም በተመለከተ ጉዳይ አስተዳዳሪው ማስታወሻ ዎችን ሲጨምር ጉዳዩን የያዘው ባለሙያ  የማንቂያ ምልክት እንዲደርው ያደርጋል::" + explanation: 'የዚህ ስርዓት ተጠቃሚዎች በማስታዎሻ ንዑስ ቅጽ ላይ ማንኛውም ግብዓት መጨመር እንዲችሉ ይፈቅዳል፡፡ ተጠቃሚዎች በጉዳይ ማሳያ ገጽ ላይ “ማስታወሻ ጨምር”  የሚለውን በመንካት ይሄን ማድረግ ይችላሉ፡፡ ይህ ተግባር በመዋነኛነት ጉዳዮችን ለማስተካከል ፈቃድ የሌላቸው ነገር ግን በጉዳዮች ዙሪያ ለጉዳይ አያያዝ ባለሙያዎች ማስታወሻ ለመስጠት እንዲችሉ የጉዳይ አስተዳዳሪዎችን የሚጠቅም ነው፡፡  በዚህ አካሄድ ማስታወሻ መጨመር ማለት ምልክት ከማሳየት ጋር ተመሳሳይ ነው፡፡ ማስታወሻ ዎችን መጨመር የሚኖረውን  ጥቅም በተመለከተ ጉዳይ አስተዳዳሪው ማስታወሻ ዎችን ሲጨምር ጉዳዩን የያዘው ባለሙያ  የማንቂያ ምልክት እንዲደርው ያደርጋል::' label: በጉዳዩ ላይ ማስታወሻ ጨምር add_registry_record: - explanation: "የዚህ ስርዓት ተገልጋዮች መዝገብ ቤቱንና ጉዳዩ ከመዝገብ ቤት ዝርዝር ቅጽ ጋር ማያያዝ እንዲችሉ መፍቀድ፡፡ እንዲሁም ቀደም ብለው የተያያዙ ጉዳዮችን ከመዝገብ ላይ ማንሳትን መፍቀድ፡፡ " + explanation: 'የዚህ ስርዓት ተገልጋዮች መዝገብ ቤቱንና ጉዳዩ ከመዝገብ ቤት ዝርዝር ቅጽ ጋር ማያያዝ እንዲችሉ መፍቀድ፡፡ እንዲሁም ቀደም ብለው የተያያዙ ጉዳዮችን ከመዝገብ ላይ ማንሳትን መፍቀድ፡፡ ' label: የጉዳዩን መዝገብ መጨመር/ ማዘመን approve_action_plan: - explanation: "{የጉዳይ አስተዳዳሪው ለጉዳይ አያያዝ ባለሙያው እንዲያጸድቅ መፍቀድ}" - label: "{አጽድቅ}" + explanation: '{የጉዳይ አስተዳዳሪው ለጉዳይ አያያዝ ባለሙያው እንዲያጸድቅ መፍቀድ}' + label: '{አጽድቅ}' approve_assessment: - explanation: "{የጉዳይ አስተዳዳሪው ለጉዳይ አያያዝ ባለሙያው እንዲያጸድቅ መፍቀድ}" - label: "{ፎርሙን ማፅደቅ}" + explanation: '{የጉዳይ አስተዳዳሪው ለጉዳይ አያያዝ ባለሙያው እንዲያጸድቅ መፍቀድ}' + label: '{ፎርሙን ማፅደቅ}' approve_bia: - explanation: "{የጉዳይ አስተዳዳሪው ለጉዳይ አያያዝ ባለሙያው እንዲያጸድቅለት መፍቀድ}" - label: "{ፎርሙን ማፅደቅ}" + explanation: '{የጉዳይ አስተዳዳሪው ለጉዳይ አያያዝ ባለሙያው እንዲያጸድቅለት መፍቀድ}' + label: '{ፎርሙን ማፅደቅ}' approve_case_plan: - explanation: "{የጉዳይ አስተዳዳሪው ለጉዳይ አያያዝ ባለሙያው እንዲያጸድቅለት መፍቀድ}" - label: "{ማፅደቅ}" + explanation: '{የጉዳይ አስተዳዳሪው ለጉዳይ አያያዝ ባለሙያው እንዲያጸድቅለት መፍቀድ}' + label: '{ማፅደቅ}' approve_closure: - explanation: "{የጉዳይ አስተዳዳሪው ለጉዳይ አያያዝ ባለሙያው እንዲያጸድቅለት መፍቀድ}" - label: "{ፎርሙን ማፅደቅ}" + explanation: '{የጉዳይ አስተዳዳሪው ለጉዳይ አያያዝ ባለሙያው እንዲያጸድቅለት መፍቀድ}' + label: '{ፎርሙን ማፅደቅ}' approve_gbv_closure: - explanation: "{የጉዳይ አስተዳዳሪው ለጉዳይ አያያዝ ባለሙያው እንዲያጸድቅለት መፍቀድ}" - label: "{ፎርሙን ማፅደቅ}" + explanation: '{የጉዳይ አስተዳዳሪው ለጉዳይ አያያዝ ባለሙያው እንዲያጸድቅለት መፍቀድ}' + label: '{ፎርሙን ማፅደቅ}' assign: explanation: የስርዓቱ ተገልጋይ የጉዳዩ ዋና መዝገቦችን ለሌሎች በስርዓቱ ውስጥ ላሉ ድርጅቶች እንዲልክ መፍቀድ፡፡ ይህ ሲሆን የህጻናቱ ስምምነት አያስፈልግም፡፡ ከጉዳይ ማዘዋወር በተለየ መልኩ ተቀባዩ አካል የተላከለትን የመቀበል/ያለመቀበል አማራጭ አይኖረውም፡፡ label: መመደብ @@ -2120,37 +2584,37 @@ am-ET: explanation: ክፍት ሆኖ የቆየን ጉዳይ ለመዝጋት ለስርዓቱ ተገልጋይ ፈቃድ ይሰጣል፡፡ label: ዝጋ consent_override: - explanation: "ተገልጋዩ ስምምነት ያልተሰጠባቸውን ጉዳዮች በቅብብሎሽ/ በዝውውር ለመላክ ፈቃድ ይሰጣል፡፡ " + explanation: 'ተገልጋዩ ስምምነት ያልተሰጠባቸውን ጉዳዮች በቅብብሎሽ/ በዝውውር ለመላክ ፈቃድ ይሰጣል፡፡ ' label: ለቅብብሎሽ/ ጉዳይ ለማዘዋወር በተደጋጋሚ የስምምነት ቃል አለማግኘት create: explanation: ጉዳይ የመፍጠር ችሎታ label: ፍጠር display_view_page: - explanation: "ተገልጋዩ ያልተፈቀደለትን መረጃ ለማየት ሲፈልግ ምንም እንኳን የጉዳዩ ሙሉ መረጃ ገብቶ ለማየት ባይችልም የተወሰኑ ዋና መረጃዎችን ለማየት ፈቃድ ይሰጣል፡፡ “ማየት የሚቻል” በሚለው ዝርዝር ውስጥ ታዩ የሚችሉት ቀደም ተብለው “በአጭሩ አሳይ” በሚል ዝርዝር የተጫኑ ናቸው፡፡ ይህ “ማየት የሚቻል” በሚል የሚኖረው የፈቃድ ይዘት  ተገልጋዮች የያዙት ጉዳይ ጋር ተመሳሳይ ሊሆኑ ከሚችሉ ሌሎች ጉዳዮች ጋር በመሆኑ  በተለይም ቤተሰብ በማፈላግና በማቀላቀል ላይ ያሉ የስርዓቱ ተገልጋዮችን የሚጠቅም ይሆናል፡፡ " + explanation: 'ተገልጋዩ ያልተፈቀደለትን መረጃ ለማየት ሲፈልግ ምንም እንኳን የጉዳዩ ሙሉ መረጃ ገብቶ ለማየት ባይችልም የተወሰኑ ዋና መረጃዎችን ለማየት ፈቃድ ይሰጣል፡፡ “ማየት የሚቻል” በሚለው ዝርዝር ውስጥ ታዩ የሚችሉት ቀደም ተብለው “በአጭሩ አሳይ” በሚል ዝርዝር የተጫኑ ናቸው፡፡ ይህ “ማየት የሚቻል” በሚል የሚኖረው የፈቃድ ይዘት  ተገልጋዮች የያዙት ጉዳይ ጋር ተመሳሳይ ሊሆኑ ከሚችሉ ሌሎች ጉዳዮች ጋር በመሆኑ  በተለይም ቤተሰብ በማፈላግና በማቀላቀል ላይ ያሉ የስርዓቱ ተገልጋዮችን የሚጠቅም ይሆናል፡፡ ' label: ገጹን አሳይ enable_disable_record: explanation: ጉዳዮችን ከስራ ውጭ ማድረግ/ወደስራ መመለስ፡፡ “ከስራ ውጭ” የሆኑ ጉዳዮች ከጉዳይ ዝርዝር ውጪ ይሆናሉ፡፡ ከጉዳይ ውጪ የሆኑ ጉዳዮችን ተገልጋዩ ማጥሪያ በሚለው አማራጭ ተጠቅሞ ዝርዝራቸውን ማየት ይችላል፡፡ ፕሪሜሮ ጉዳዮችን ማጥፋት ስለማይፈቅድ፣ተገልጋዩ እን አማራጭ ከስራ ውጪ አድርግ የሚለውን መጠቀም ይችላል፡፡ ለምሳሌ ተገልጋዩ አንድን ጉዳይ በስህተት ቢፈጥር ወይ ደግሞ ጉዳዩ መጥፎ የሚባሉ መረጃዎች ቢኖረው ተገልጋዩ ይህንን ጉዳይ ከስራ ውጭ ማድረግ ይጠበቅበታል፡፡ label: ከስራ ውጭ ማድረግ/ ወደስራ መመለስ export_case_pdf: - explanation: "ተገልጋዩ ከጉዳይ ማሳያ ገጽ/ዝርዝር የአንድ ወይም የብዙ ጉዳዮችን መረጃዎች የፒ.ዲ.ኤፍ ፋይል ማውጣት ይችላል፡፡ በፒ.ዲ.ኤፍ የሚወጣው መረጃ በመጀመሪያ የጉዳዮች ዝርዝር ይታያል በመቀጠል በየቅጾች የተመዘገቡ መረጃዎች ተደራጅተው ይታያሉ፡፡  " + explanation: 'ተገልጋዩ ከጉዳይ ማሳያ ገጽ/ዝርዝር የአንድ ወይም የብዙ ጉዳዮችን መረጃዎች የፒ.ዲ.ኤፍ ፋይል ማውጣት ይችላል፡፡ በፒ.ዲ.ኤፍ የሚወጣው መረጃ በመጀመሪያ የጉዳዮች ዝርዝር ይታያል በመቀጠል በየቅጾች የተመዘገቡ መረጃዎች ተደራጅተው ይታያሉ፡፡  ' label: ጉዳዮን በፒ.ዲ.ኤፍ አውጣ export_csv: explanation: 'ተገልጋዩ ከጉዳይ ማሳያ ገጽ/ዝርዝር የአንድ ወይም የብዙ ጉዳዮችን መረጃዎች የሲ.ኤስ.ቪ ፋይል ማውጣት ይችላል፡፡  ማስታወሻ፡ በሲ.ኤስ.ቪ የሚወጡ መረጃዎች የላቲን ላልሆኑ ፊደላት (ምሳሌ የአረብ) በጽሁፍ ተተርጉመው አይወጡም፡፡' label: በሲ.ኤስ.ቪ አውጣ export_custom: - explanation: "ተገልጋዩ ከጉዳይ ማሳያ ገጽ/ዝርዝር የአንድ ወይም የብዙ ጉዳዮችን መረጃዎች የያዜ ቅጾችን የኤክስ.ኤል.ኤስ ፋይል ማውጣት ይችላል፡፡ በዚመልኩ የሚወጣ እያንዳንዱ ቅጽ የኤክስ.ኤል.ኤስ መረጃ የራሱ በሆነ የማንጠልጠያ ምልክት ይወከላል፡፡ ተገልጋዩ መረጃዎች ምን ምን ተካቶባቸው መውጣት እንዳለባቸው መምረጥ ይችላል፡፡ ነገር ግን ተገልጋዩ ማካተትና ማውጣት የሚችላቸው ቅጾችና መረጃዎች ለማየት ፈቃድ የተሰጠው መረጃዎችን ብቻ መሆኑን ማስታወስ ይገባል፡፡ " + explanation: 'ተገልጋዩ ከጉዳይ ማሳያ ገጽ/ዝርዝር የአንድ ወይም የብዙ ጉዳዮችን መረጃዎች የያዜ ቅጾችን የኤክስ.ኤል.ኤስ ፋይል ማውጣት ይችላል፡፡ በዚመልኩ የሚወጣ እያንዳንዱ ቅጽ የኤክስ.ኤል.ኤስ መረጃ የራሱ በሆነ የማንጠልጠያ ምልክት ይወከላል፡፡ ተገልጋዩ መረጃዎች ምን ምን ተካቶባቸው መውጣት እንዳለባቸው መምረጥ ይችላል፡፡ ነገር ግን ተገልጋዩ ማካተትና ማውጣት የሚችላቸው ቅጾችና መረጃዎች ለማየት ፈቃድ የተሰጠው መረጃዎችን ብቻ መሆኑን ማስታወስ ይገባል፡፡ ' label: በልኩ ወጪ አድርግ export_duplicate_id_csv: - explanation: "ተመሳሳይ ብሄራዊ መለያ መደብ ላላቸው ጉዳዮች በሲ.ኤስ.ቪ ወጪ ማድረጊያ ፍጠር፡፡ (እንደ አጫጫናቸው ምንአልባት የተለያየ ምልክት ሊኖራቸው ይችላል)፡፡ይህ የሚደረገው ከጉዳዮች ዝርዝር ገጽ ላይ ብቻ ነው፡፡   " + explanation: 'ተመሳሳይ ብሄራዊ መለያ መደብ ላላቸው ጉዳዮች በሲ.ኤስ.ቪ ወጪ ማድረጊያ ፍጠር፡፡ (እንደ አጫጫናቸው ምንአልባት የተለያየ ምልክት ሊኖራቸው ይችላል)፡፡ይህ የሚደረገው ከጉዳዮች ዝርዝር ገጽ ላይ ብቻ ነው፡፡   ' label: ተመሳሳይ ቅጅዎችን ወጪ አድርግ export_json: - explanation: "የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በጄ.ኤስ.ኦ.ኤን ወጪ ማድረግ ይችላሉ፡፡ ይህን ማድረግ  ጉዳዮችን ከዚህኛው ፕሪሜሮ ስርዓት ወጪ በማድረግ ወደ ሌላ የፐሪሜሮ ስርዓት ወይም ወደ ሌላ የመረጃ አያያዝና አስተዳደር ቋት ገቢ ለማድረግ የሚጠቅም ይሆናል፡፡ የጄ.ኤስ.ኦ.ኤን አቀራረብ በማሽን ብቻ የሚነበብ በመሆኑ በአብዛኛው ተገልጋዮች ዘንድ አይተገበርም፡፡ " + explanation: 'የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በጄ.ኤስ.ኦ.ኤን ወጪ ማድረግ ይችላሉ፡፡ ይህን ማድረግ  ጉዳዮችን ከዚህኛው ፕሪሜሮ ስርዓት ወጪ በማድረግ ወደ ሌላ የፐሪሜሮ ስርዓት ወይም ወደ ሌላ የመረጃ አያያዝና አስተዳደር ቋት ገቢ ለማድረግ የሚጠቅም ይሆናል፡፡ የጄ.ኤስ.ኦ.ኤን አቀራረብ በማሽን ብቻ የሚነበብ በመሆኑ በአብዛኛው ተገልጋዮች ዘንድ አይተገበርም፡፡ ' label: በጄ.ኤስ.ኦ.ኤን ወጪ አድርግ export_list_view_csv: explanation: የዚህ ስርዓት ተገልጋዮች ከጉዳይ ዝርዝር ገጽ ላይ የሲ.ኤስ.ቪ መረጃዎችን ወጪ ማድረግ ይችላል፡፡ ይህን ማድረግ የሚቻለው ከጉዳይ ዝርዝር ገጽ ላይ ብቻ ነው፡፡ label: ዝርዝር ማሳያ በሲ.ኤስ.ቪ ወጪ አድርግ   export_pdf: - explanation: "የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በፒ.ዲ.ኤፍ ወጪ ማድረግ ይችላሉ፡፡ በፒ.ዲ.ኤፍ የሚወጣ ፋይል ላይ መረጃዎች በመጀመሪያ በጉዳይ ተዘርዝረው ይቀመጣሉ፡፡ በተጨማሪም መረጃዎችን በያዙ ቅጾች ይደራጃል፡፡ " + explanation: 'የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በፒ.ዲ.ኤፍ ወጪ ማድረግ ይችላሉ፡፡ በፒ.ዲ.ኤፍ የሚወጣ ፋይል ላይ መረጃዎች በመጀመሪያ በጉዳይ ተዘርዝረው ይቀመጣሉ፡፡ በተጨማሪም መረጃዎችን በያዙ ቅጾች ይደራጃል፡፡ ' label: ጉዳዩን በፒ.ዲ.ኤፍ ወጪ አድርግ export_photowall: explanation: የዚህ ስርዓት ተገልጋዮች ከጉዳይ ዝርዝር ገጽ ላይ ምስሎችን የያዙ የተመረጡ ጉዳዮችን ወጪ ለማድረግ ይፈቅዳል፡፡ በዚህ መልኩ ወጪ ማድረግ በዋነኛነት ቤተሰብ ለማፈላለግና ለማቀላቀል ስራ ይጠቅማል፡፡ ይህን ማድረግ የሚቻለው ከጉዳይ ዝርዝር ገጽ ላይ ብቻ ይሆናል፡፡    @@ -2161,17 +2625,17 @@ am-ET: explanation: 'የዚህ ስርዓት ተገልጋዮች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳይ ዝርዝር/ማሳያ ገጽ ላይ በኤክስ.ኤል.ኤስ ፋይል ወጪ ማድረግ ይችላል፡፡ በዚመልኩ የሚወጣ እያንዳንዱ ቅጽ የኤክስ.ኤል.ኤስ መረጃ የራሱ በሆነ የማንጠልጠያ ምልክት ይወከላል፡፡ ማስታወሻ፡ በሲ.ኤስ.ቪ ወጪ ከማድረግ በተለየ መልኩ  የኤክስ.ኤል.ኤስ አቀራረብ የላቲን ያልሆኑ ጽሁፎችንም (አረብ፣ ባንግላ) ተርጉሞ በሚነበብ መልኩ ምላሽ የሚሰጥ ይሆናል፡፡  ' label: በኤክስ.ኤል (XLS file) ወጪ አድርግ find_tracing_match: - explanation: "ይህ የሚያገለግለው ቤተሰብ ለማፈለለግና መልሶ ለማቀላቀል ተግባር ብቻ ነው፡፡ ይህን ለማድረግ ፈቃድ ያላቸው ተጠቃሚዎች “ተመሳሳይ ቤተሰብ ፈልግ” የሚለውን አማራጭ በጉዳይ ማሳያ ገጹ ላይ ያገኛሉ፡፡ እሱን በሚመርጡበት ጊዜ ከያዙት ጉዳይ ጋር የሚቀራረቡና ተመሳሳይነት ያላቸው የቤተሰብ ዝርዝሮችን ያገኛሉ፡፡ " + explanation: 'ይህ የሚያገለግለው ቤተሰብ ለማፈለለግና መልሶ ለማቀላቀል ተግባር ብቻ ነው፡፡ ይህን ለማድረግ ፈቃድ ያላቸው ተጠቃሚዎች “ተመሳሳይ ቤተሰብ ፈልግ” የሚለውን አማራጭ በጉዳይ ማሳያ ገጹ ላይ ያገኛሉ፡፡ እሱን በሚመርጡበት ጊዜ ከያዙት ጉዳይ ጋር የሚቀራረቡና ተመሳሳይነት ያላቸው የቤተሰብ ዝርዝሮችን ያገኛሉ፡፡ ' label: ካሉት ጉዳዮች ውስጥ ተመሳሳይ ቤተሰብ ፈልግ flag: explanation: በጉዳዮች ላይ የማውለብለብ ምልክት የመጨመር ፈቃድ፡፡ ይህ ፈቃድ ያላቸው ተጠቃሚዎች ያደረጉትን ምልክት የማንሳት ፈቃድም ይኖራቸዋል፡፡ - label: "የማውለብለብ ምልክት " + label: 'የማውለብለብ ምልክት ' import: explanation: ተጠቃሚዎች ከሲ.ኤስ.ቪ፣ ከኤክስኤል ወይም ከጄ.ኤስ.ኦ.ኤን ፋይል አንድ ወይም ከዚያ በላይ አዲስ ጉዳዮችን ቀድቶ ማምጣት ያስችላል፡፡ በዚህ መልኩ ተቀድቶ የሚመጣ ፋይል መረጃ በጣም ግልጽ በሆነና በተገቢዉ መንገድ ሊደራጅ ይገባል፡፡ ይህ ስራ ሊፈቀድ የሚገባው በፕሪሜሮ ሲስተም መረጃዎች እንዴት መደራጀት እንዳለባቸው ከፍተኛ ሙያዊ ክህሎትና ጥልቅ እውቀት ባላቸው በመረጃ አስተዳደር ደረጃ ባሉ ተጠቃሚዎች ሊሆን ይገባል፡፡ ከጉዳየይ ዝርዝር ገጽ ላይ ብቻ የሚከናወን፡፡ label: መቅዳት incident_details_from_case: - explanation: "በፍለጋ የምናገኛቸው ነገር ግን ለማየት ፈቃድ በሌለን ጉዳዮች ላይ የተፈጸመ ድርጊት ዝርዝር ንዑስ ቅጽ ለመጨመር የሚያስችል የመግቢያ ፈቃድ የመጨመር ችሎታ፡፡ ተጠቃሚው ይሄን ማድረግ የሚችለው ከፍለጋ ማሳያ ገጹ ላይ አንድ ወይም ከዚያ በላይ ጉዳዮችን ከመረጠ በኋላ “የተፈጸመ ድርጊት ጨምር” የሚለውን አማራጭ በመምረጥ ይሆናል፡፡  በዚህ ጊዜ ተጠቃሚው የተፈጸመ ድርጊት ለመጨመር የሚረዳ ንዑስ ቅጽ ማግኘትና መረጃ ማስገባት  ይችላል፡፡  ይህን ተግባር መፈጸም ይሚችሉት በፍለጋ ማሳያው ገጽ ላይ በሌሎች የተያዙ የጉዳይ መዝገቦችን ፈልጎ ለማግኘት ፈቃድ ባላቸው ተጠቃሚዎች ብቻ ይሆናል፡፡ " - label: "ከፍለጋ ማሳያ ገጹ ውስጥ በሌሎች ተጠቃሚዎች የተያዙ ጉዳዮች ላይ የተፈጸመ ድርጊት ዝርዝር ጨምር " + explanation: 'በፍለጋ የምናገኛቸው ነገር ግን ለማየት ፈቃድ በሌለን ጉዳዮች ላይ የተፈጸመ ድርጊት ዝርዝር ንዑስ ቅጽ ለመጨመር የሚያስችል የመግቢያ ፈቃድ የመጨመር ችሎታ፡፡ ተጠቃሚው ይሄን ማድረግ የሚችለው ከፍለጋ ማሳያ ገጹ ላይ አንድ ወይም ከዚያ በላይ ጉዳዮችን ከመረጠ በኋላ “የተፈጸመ ድርጊት ጨምር” የሚለውን አማራጭ በመምረጥ ይሆናል፡፡  በዚህ ጊዜ ተጠቃሚው የተፈጸመ ድርጊት ለመጨመር የሚረዳ ንዑስ ቅጽ ማግኘትና መረጃ ማስገባት  ይችላል፡፡  ይህን ተግባር መፈጸም ይሚችሉት በፍለጋ ማሳያው ገጽ ላይ በሌሎች የተያዙ የጉዳይ መዝገቦችን ፈልጎ ለማግኘት ፈቃድ ባላቸው ተጠቃሚዎች ብቻ ይሆናል፡፡ ' + label: 'ከፍለጋ ማሳያ ገጹ ውስጥ በሌሎች ተጠቃሚዎች የተያዙ ጉዳዮች ላይ የተፈጸመ ድርጊት ዝርዝር ጨምር ' incident_from_case: explanation: ይህ ፈቃድ ተጠቃሚዎች “ድርጊት ፍጠር” የሚለውን አማራጭ እንዲመርጡ ያስችላል፡፡ ይህም ከጉዳዮች የተቀዳ የተወሰነ የድርጊት መረጃ ያመጣል፡፡ ጾታን መሰረት ያደረጉ ጥቃቶች ዙሪያ ያሉ ጉዳዮችን በተመለከተ ይህ አማራጭ ከማሳያ ገጹ ራስጌ ላይ የሚገኝና አጠቃላይ ከጉዳዩ ጋር አብሮ የሚሄድ ነው፡፡  አንዳንድ ድርጊቶችን በመፈለግ አግባብ ይህ አመራጭ “የድርጊት ዝርዝር” በሚለው ንዑስ ቅጽ ውስጥ ይገኛል፡፡ በዚህ ሁኔታ መረጃዎችን ሙሉ በሙሉ ከጉዳዩ ላይ ወይም ከድርጊት ዝርዝር ማሳያ ንዑስ ቅጹ ላይ መቅዳት ይቻላል፡፡ ለምሳሌ፡- አዲስ የተፈጠረው ድርጊት ምን አልባት  ከግለሰብ ድርጊት ዝርዝር ንዑስ ቅጽ ላይ “የተፈጸመ ጥቃት ዓይነት” የሚል የያዘ ሊሆን ችላል፡፡ ነገር ግን የጉዳዩ  ጾታና እድሜንም የያዘ ሊሆን ይችላል፡፡ ይህ ፈቃድ ተጠቃሚው የተፈጠሩ ድርጊቶችን የያዘ ሊንክ እንዲያይም ያስችለዋል፡፡ label: ከጉዳይ ላይ ድርጊት ፍጠር @@ -2182,11 +2646,11 @@ am-ET: explanation: ጉዳይ የማየት ችሎታ label: እይታ receive_referral: - explanation: "ተጠቃሚው በቅብብሎሽ ለመረከብ ያስችለዋል፡፡ ይህ ፈቃድ ያለው ተጠቃሚ ቅብብሎሽ በማድረግ ሂደት ውስጥ ሊረከቡ ከሚችሉ ችሉ አካላት አንዱ ሆኖ ይቀርባል፡፡ ይህ ፈቃድ የሌላቸው ግን በቅብብሎሽ ተረካቢዎች ውስጥ አይኖሩም፡፡ " + explanation: 'ተጠቃሚው በቅብብሎሽ ለመረከብ ያስችለዋል፡፡ ይህ ፈቃድ ያለው ተጠቃሚ ቅብብሎሽ በማድረግ ሂደት ውስጥ ሊረከቡ ከሚችሉ ችሉ አካላት አንዱ ሆኖ ይቀርባል፡፡ ይህ ፈቃድ የሌላቸው ግን በቅብብሎሽ ተረካቢዎች ውስጥ አይኖሩም፡፡ ' label: በቅብብሎሽ መረከብ receive_referral_different_module: - explanation: "ደንበኛው በቅብብሎሽ ለመለዋወጥ ያግዛል፡፡ የሚመለከተው ተቀባይ ብቻ በተፈቀደለት መሰረት ይሰራል። የማይመለከተው አካል ማየት አይችልም " - label: "ሪፈር የተደረጉትን መቀበል " + explanation: 'ደንበኛው በቅብብሎሽ ለመለዋወጥ ያግዛል፡፡ የሚመለከተው ተቀባይ ብቻ በተፈቀደለት መሰረት ይሰራል። የማይመለከተው አካል ማየት አይችልም ' + label: 'ሪፈር የተደረጉትን መቀበል ' receive_transfer: explanation: ተጠቃሚው ኬዞችን እንዲቀበል አድርግ፡፡ የተላኩለትን እንዲቀበል አድርግ ይህ ካልተደረገ መቀበል አይችልም፡፡ label: ቅብብሎሽን መቀበል @@ -2203,34 +2667,36 @@ am-ET: explanation: ባለሙያው የተዘጋ ኬዝ እንዲከፍት አድርግ label: ዳግም መክፈት request_approval_action_plan: - explanation: "{ለደንበኛው ፍቀድ (በአብዛኛው ኬዝ ወርከር) ሀላፊው ኬዞችን እንዲያጸድቅ ሲጠይቅ}" - label: "{እንዲጸድቅ መጠየቅ}" + explanation: '{ለደንበኛው ፍቀድ (በአብዛኛው ኬዝ ወርከር) ሀላፊው ኬዞችን እንዲያጸድቅ ሲጠይቅ}' + label: '{እንዲጸድቅ መጠየቅ}' request_approval_assessment: - explanation: "ተጠቃሚው እንዲሰራ አድርግ (በአብዛኛው የጉዳይ ባለሙያዎች) ሀላፊው ኬዞችን እንዲያጸድቅ %{approval_label}." - label: "እንዲጸድቅ%{approval_label} መጠየቅ " + explanation: ተጠቃሚው እንዲሰራ አድርግ (በአብዛኛው የጉዳይ ባለሙያዎች) ሀላፊው ኬዞችን እንዲያጸድቅ %{approval_label}. + label: 'እንዲጸድቅ%{approval_label} መጠየቅ ' request_approval_bia: - explanation: "ለደንበኛው ፍቀድ (በአብዛኛው ኬዝ ወርከር) ሀላፊው ኬዞችን እንዲያጸድቅ ሲጠይቅ .%{approval_label}" - label: " እንዲጸድቅ%{approval_label}መጠየቅ" + explanation: ለደንበኛው ፍቀድ (በአብዛኛው ኬዝ ወርከር) ሀላፊው ኬዞችን እንዲያጸድቅ ሲጠይቅ .%{approval_label} + label: ' እንዲጸድቅ%{approval_label}መጠየቅ' request_approval_case_plan: - explanation: "ለደንበኛው ፍቀድ (በአብዛኛው ኬዝ ወርከር) ሀላፊው ኬዞችን እንዲያጸድቅ ሲጠይቅ . %{approval_label}." - label: "እንዲጸድቅ%{approval_label}መጠየቅ" + explanation: ለደንበኛው ፍቀድ (በአብዛኛው ኬዝ ወርከር) ሀላፊው ኬዞችን እንዲያጸድቅ ሲጠይቅ . %{approval_label}. + label: እንዲጸድቅ%{approval_label}መጠየቅ request_approval_closure: - explanation: "ለደንበኛው ፍቀድ (በአብዛኛው ኬዝ ወርከር) ሀላፊው ኬዞችን እንዲያጸድቅ ሲጠይቅ%{approval_label}" - label: "እንዲጸድቅ %{approval_label} መጠየቅ" + explanation: ለደንበኛው ፍቀድ (በአብዛኛው ኬዝ ወርከር) ሀላፊው ኬዞችን እንዲያጸድቅ ሲጠይቅ%{approval_label} + label: እንዲጸድቅ %{approval_label} መጠየቅ request_approval_gbv_closure: - explanation: "ተጠቃሚው እንዲሰራ አድርግ (በአብዛኛው የጉዳይ ባለሙያዎች) ሀላፊው ኬዞችን እንዲያጸድቅ %{approval_label}" - label: "ጠይቅ%{approval_label}ማጽደቅ" + explanation: ተጠቃሚው እንዲሰራ አድርግ (በአብዛኛው የጉዳይ ባለሙያዎች) ሀላፊው ኬዞችን እንዲያጸድቅ %{approval_label} + label: ጠይቅ%{approval_label}ማጽደቅ request_transfer: explanation: በ "የማሳያ ዘዴ" ላይ "ማዘዋወርያ ጠይቅ" የሚለውን ቁልፍ ያሳያል. ቁልፉ ተጠቃሚው ጉዳዩን ወደ ላከው ተጠቃሚ እንዲያስተላልፍ በመጠየቅ ለአሁኑ የመዝገብ ባለቤት ከግል ማስታወሻ ጋር በኢሜል መልእክት እንዲልክ ያስችለዋል። ይህ ልጆች ብዙ ጊዜ ቦታዎችን በሚቀይሩበት አውድ ውስጥ ጠቃሚ ነው፣ እና ኬዝ ሰራተኞች የተባዛ መዝገብ እንዳይፈጠር የቀድሞ ጉዳይ ሰራተኛ ስለ ልጁ የበፊት መረጃ እንዲልክላቸው ያስፈልጋል። label: ለማስተላለፍ መጠየቅ search_owned_by_others: - explanation: "ተጠቃሚዎች ብዙውን ጊዜ ሊደርሱባቸው የማይችሉትን መዝገቦች እንዲፈልግ ይፈቅድለታል፣ የዚያ ጉዳይ የመዝገብ ባለቤት ስላልሆኑ፣ ወይም (ሃላፊዎች) የመዝገቡ ባለቤት በተጠቃሚ ቡድናቸው ውስጥ ስለሌለ። ያስተውሉ, ተጠቃሚው ጉዳዩን በፍለጋ ውጤቶች እይታ ውስጥ ሲያይ, ለዚያ ጉዳይ የጉዳይ ማሳያ ገጽ ላይ መንካት አይችሉም, ይህም ማለት ስለ ጉዳዩ ምንም አይነት ዝርዝር መረጃ ማየት አይችሉም." + explanation: ተጠቃሚዎች ብዙውን ጊዜ ሊደርሱባቸው የማይችሉትን መዝገቦች እንዲፈልግ ይፈቅድለታል፣ የዚያ ጉዳይ የመዝገብ ባለቤት ስላልሆኑ፣ ወይም (ሃላፊዎች) የመዝገቡ ባለቤት በተጠቃሚ ቡድናቸው ውስጥ ስለሌለ። ያስተውሉ, ተጠቃሚው ጉዳዩን በፍለጋ ውጤቶች እይታ ውስጥ ሲያይ, ለዚያ ጉዳይ የጉዳይ ማሳያ ገጽ ላይ መንካት አይችሉም, ይህም ማለት ስለ ጉዳዩ ምንም አይነት ዝርዝር መረጃ ማየት አይችሉም. label: በሌሎች ተጠቃሚዎች የተያዙ የጉዳይ መዝገቦችን ፈልግ service_provision_incident_details: explanation: ተጠቃሚው "አስቀምጥ እና የአገልግሎት አቅርቦት አክል" የሚል አዝራር እንዲያይ ያስችለዋል። ይህንን ቁልፍ ጠቅ ማድረግ ስለ ክስተቱ አሁን የገባውን መረጃ ያስቀምጣል እና ተጠቃሚውን በቀጥታ ወደ አክል አገልግሎት አቅርቦት ሞዳል ይወስዳል። ይህ ድርጊት በቀጥታ ከአደጋ ክስተት እና አክል የአገልግሎት አቅርቦት እርምጃዎች ጋር የተቆራኘ ስለሆነ፣ ይህ ሚና እንዲሁ "በሌላ ተጠቃሚ ጉዳይ ላይ የክስተት ዝርዝሮችን አክል" እና "የአገልግሎት አቅርቦትን ለሌላ ተጠቃሚ አክል" ከሆነ ይህን ሚና እንዲሰጥ ፈቃድ መስጠቱ ምክንያታዊ ነው። ጉዳይ" ፈቃዶች፡፡ label: ጨምር የሚለውን ቁልፍ በክስተት ዝርዝሮች ስር አስገባ services_section_from_case: - explanation: "በአገልግሎት ንዑስ ቅጽ ኬዞችን ማስገባት\nበፍላጋ ላይ የተገኙ ኬዞችን ያስገባል ለመጨመር አክል የሚለውን ይጫኑ በንዑስ ቅጹ ላይ የተመላከቱትን ሁሉንም አገልግሎቶች ማየት ይችላል" + explanation: 'በአገልግሎት ንዑስ ቅጽ ኬዞችን ማስገባት + + በፍላጋ ላይ የተገኙ ኬዞችን ያስገባል ለመጨመር አክል የሚለውን ይጫኑ በንዑስ ቅጹ ላይ የተመላከቱትን ሁሉንም አገልግሎቶች ማየት ይችላል' label: የሚሰጡ አገልግሎቶችን ወደሌላ ኬዝ ተጠቃሚ ጨምር sync_external: explanation: መዝገቦችን ከውጫዊ መረጃ አስተዳደር ስርዓት ጋር የማናበብ @@ -2254,11 +2720,11 @@ am-ET: explanation: ከጉዳዩ ከምዝገባ ጋር የሚገናኙ መረጃዎችን እንዲያይ ፍቀድ፡፡ የተመዘገቡ ዝርዝሮችን እንዲያይ ጭምር ይፍቀዱ፡፡ label: የተመዘገቡ ጉዳዮችን ይመልከቱ write: - explanation: "\"ቀይር\" የሚለውን ቁልፍ መጫን መቻል መረጃዎችን ካሻሻሉ በኀላ \"አስቀምጥ\" የሚለውን ተጫን" + explanation: '"ቀይር" የሚለውን ቁልፍ መጫን መቻል መረጃዎችን ካሻሻሉ በኀላ "አስቀምጥ" የሚለውን ተጫን' label: አስተካክል accept_or_reject_transfer: explanation: ተጠቃሚው በቡድንዎ ውስጥ ያለ ሌላ ተጠቃሚን ወክሎ ማስተላለፍን እንዲቀበል ወይም አለመቀበል ይፈቅዳል(ለምሳሌ፡ ሱፐርቫይዘር ወደ ማህበራዊ ሰራተኛቸው የተላከ ማስተላለፍን ሲቀበል)። - label: "መቀበል ወይም ውድቅ ማድረግ ወደ ከቡድን ቡድን ለማስተላለፍ " + label: 'መቀበል ወይም ውድቅ ማድረግ ወደ ከቡድን ቡድን ለማስተላለፍ ' list_case_names: explanation: ማኔጀር አብዛኛውን ጊዜ የጉዳይ ስም ዝርዝር ውስጥ ማየት አይችሉም። አንድ ሥራ አስኪያጅ ይህ ፈቃድ ካለው፣ በዝርዝሩ ውስጥ ስሞችን ማየት ይችላሉ። label: በኬዞች ዝርዝር ስር የተቀመጡ ስሞችን ሀላፊው ማየት የሚችል ከሆነ @@ -2271,34 +2737,34 @@ am-ET: actions: approvals_action_plan: explanation: በመጠባበቅ ላይ ያሉ፣ የጸደቁ ወይም ውድቅ የሆኑ  በድጋፍ እቅድ ማጽደቅ ጥያቄዎችን የአሁኑን ተጠቃሚ ጉዳዮች ብዛት ያሳያል። - label: "የጉዳይ%{approval_label} ባለሙያ" + label: የጉዳይ%{approval_label} ባለሙያ approvals_action_plan_pending: explanation: በመጠባበቅ ላይ ያሉ የድርጊት መርሃ ግብር የይጽደቅልኝ ጥያቄዎችን በአስተዳዳሪው ቡድን ውስጥ ያሉትን የጉዳዮች ብዛት ያሳያል። - label: "ማናጀር %{approval_label}ያፀደቀው" + label: ማናጀር %{approval_label}ያፀደቀው approvals_assessment: explanation: በመጠባበቅ ላይ ያሉ፣ የጸደቁ ወይም ውድቅ የሆኑ  የዳሰሳ ጥናት ማጽደቅ ጥያቄዎችን የአሁኑን ተጠቃሚ ጉዳዮች ብዛት ያሳያል። - label: "ኬዝ ወርከር %{approval_label} ማጽደቅ" + label: ኬዝ ወርከር %{approval_label} ማጽደቅ approvals_assessment_pending: explanation: በጉዳይ ተቆጣጣሪው ቡድን ውስጥ በመጠባበቅ ላይ ካሉ የዳሰሳ ጥናት ማጽደቅ ጥያቄዎች ጋር  ያሉ የጉዳዮችን ብዛት ያሳያል። - label: "የጉዳይ ተቆጣጣሪ ማጽደቆች%{approval_label}" + label: የጉዳይ ተቆጣጣሪ ማጽደቆች%{approval_label} approvals_case_plan: - explanation: " የተጠቃሚዎችን ጉዳዮች ብዛት በመጠባበቅ ላይ ያሉ፣ የጸደቁ ወይም ውድቅ የሆኑ ጥያቄዎችን የጉዳይ እቅድ ማጽደቅ ጥያቄዎችን ያሳያል።" - label: "የጉዳይ ባለሙያ %{approval_label} ያፀደቀው" + explanation: ' የተጠቃሚዎችን ጉዳዮች ብዛት በመጠባበቅ ላይ ያሉ፣ የጸደቁ ወይም ውድቅ የሆኑ ጥያቄዎችን የጉዳይ እቅድ ማጽደቅ ጥያቄዎችን ያሳያል።' + label: የጉዳይ ባለሙያ %{approval_label} ያፀደቀው approvals_case_plan_pending: explanation: በጉዳይ ተቆጣጣሪው ቡድን ውስጥ የድጋፍ እቅድ ማጽደቅ ጥያቄዎችን በመጠባበቅ ላይ ያሉትን የጉዳይ ብዛት ያሳያል። - label: "የጉዳይ ተቆጣጣሪ ማጽደቆች%{approval_label}" + label: የጉዳይ ተቆጣጣሪ ማጽደቆች%{approval_label} approvals_closure: explanation: በጉዳይ መዝጋት ማጽደቅ ጥያቄዎች በመጠባበቅ ላይ ያሉ፣ የጸደቁ ወይም ውድቅ የሆኑ የወቅቱን ተጠቃሚ ጉዳዮች ብዛት ያሳያል። - label: "የጉዳይ አያያዝ ባለሙያ ማጽደቆች%{approval_label}" + label: የጉዳይ አያያዝ ባለሙያ ማጽደቆች%{approval_label} approvals_closure_pending: explanation: በኬዝ ማኔጀር የተያዙ ኬዞችን መዝጋት የማጽደቅ ምላሾችን የሚጠባበቁ - label: "የጉዳይ ተቆጣጣሪ ማጽደቆች%{approval_label}" + label: የጉዳይ ተቆጣጣሪ ማጽደቆች%{approval_label} approvals_gbv_closure: explanation: መጠባበቅ ላይ ያሉ፣ የጸደቁ ወይም ውድቅ የሆኑ የGBV መዘጋት ማረጋገጫ ጥያቄዎችን በመጠቀም የአሁኑን ተጠቃሚ ጉዳዮች ብዛት ያሳያል። - label: "{ኬዝ ወርከር የሚከፈል}" + label: '{ኬዝ ወርከር የሚከፈል}' approvals_gbv_closure_pending: explanation: በኬዝ ማኔጀር የተያዙ ኬዞችን መዝጋት የማጽደቅ ምላሾችን የሚጠባበቁ - label: "ማናጀር %{approval_label}ያፀደቀው" + label: ማናጀር %{approval_label}ያፀደቀው case_overview: explanation: እንደ ጠቅላላ እና አዲስ ጉዳዮች ያሉ አሃዞችን የሚያካትት በመነሻ ገጹ አናት ላይ ያለውን ዳሽቦርድ ካርድ አጠቃላይ እይታ label: ማየት ዳሽቦርድን @@ -2318,7 +2784,6 @@ am-ET: explanation: ማናጀሩ ምንያህል ኬዞች አገልግሎት እንዳላገኙ ኬዝ ወርከሮችን እንዲያይ አድርግ label: አገልግሎት ያላገኙ dash_case_incident_overview: - explanation: . label: ማየት-የኬዞቼን ሁኔታ dash_cases_by_social_worker: explanation: አጠቃላይ የተከፈቱ ኬዞችና አዳዲስ ኬዞች የሚያሳይ ሰንጠረዥ እያንዳንዱ ተርታ አጠቃላይና አዳዲስ ኬዞችን የያዘ ነው @@ -2348,7 +2813,10 @@ am-ET: explanation: ሌሎች ተጠቃሚዎች የአገልግሎት አቅርቦት እንዲጨምሩላቸው ያደረጉትን የጉዳይ ብዛት ያሳያል። ይህ ቁጥር በዳሽቦርዱ ዋና ክፍል ላይ ይታያል። label: ኬዞች በተሰጣቸው አገልግሎት አይነት dash_shared_from_my_team: - explanation: "በቡድኑ ውስጥ በእያንዳንዱ ተጠቃሚ ምላሽ ያገኙ፣ የሚላኩ ወይም ወደ ሌላ የሚተላለፉትን የጉዳይ ብዛት ለበላይ ኃላፊ ያሳያል\n\n " + explanation: 'በቡድኑ ውስጥ በእያንዳንዱ ተጠቃሚ ምላሽ ያገኙ፣ የሚላኩ ወይም ወደ ሌላ የሚተላለፉትን የጉዳይ ብዛት ለበላይ ኃላፊ ያሳያል + + +  ' label: ከቡድኔ የተጋራሁት dash_shared_with_me: explanation: ምን ያህል ጉዳዮች ወደ እርስዎ እንደተላኩ ወይም እንደተላለፉ ያሳያል። @@ -2357,7 +2825,7 @@ am-ET: explanation: "የተገለጹትን ወይም የተላለፉትን ጉዳዮች ብዛት በቡድናቸው ውስጥ ላሉ ተጠቃሚዎች ለጉዳይ አስተዳዳሪ  ያሳያል \n\n \n\n " label: ከቡድኔ ጋር የተጋራ dash_shared_with_my_team_overview: - label: "(አጠቃላይ እይታው) ከቡድኔ ጋር ተጋርቷል " + label: '(አጠቃላይ እይታው) ከቡድኔ ጋር ተጋርቷል ' dash_shared_with_others: explanation: የእኔ ጉዳዮች ምን ያህሎቹ አሁን ሪፈራሎች፣ በመጠባበቅ ላይ ያሉ ማስተላለፎች ወይም ውድቅ የተደረጉ ማስተላለፎች እንዳላቸው ያሳያል። ጉዳዮችን ራሳቸው ካልተቆጣጠሩ በስተቀር ይህ ማናጀሮችን አይመለከትም። label: ከሌሎች ጋር የተጋራ @@ -2411,18 +2879,18 @@ am-ET: label: ምንም መዝገቦች የሉም - የአስተዳዳሪ ተግባር ብቻ agency: explanation: ሚናው በሁሉም በኤጀንሲያቸው ውስጥ ባሉ ተጠቃሚዎች የሚተዳደሩ መዝገቦችን ማግኘት ይችላል። ተጠቃሚው የተጠቃሚዎችን መዳረሻ ካገኘ በኤጀንሲያቸው ውስጥ ያሉትን ሁሉንም ተጠቃሚዎች ማግኘት ይችላሉ። - label: "በኔ ተቋም ያሉ ሁሉንም መዝገቦች/ተጠቃሚዎች " + label: 'በኔ ተቋም ያሉ ሁሉንም መዝገቦች/ተጠቃሚዎች ' all: explanation: ሚናው የትኛውም የተጠቃሚ ቡድኖች የራሳቸው ቢሆኑም በስርዓቱ ውስጥ ያሉትን ሁሉንም መዝገቦች፣ ተጠቃሚዎች እና የተጠቃሚ ቡድኖች መድረስ ይችላል። label: ሁሉንም መዝገቦች/ተጠቃሚዎች አግኝ group: explanation: ሚናው በተጠቃሚ ቡድኖቻቸው ውስጥ ባሉ ሁሉም ተጠቃሚዎች የሚተዳደሩ መዝገቦችን መድረስ ይችላል። በተጠቃሚ ቡድኖቻቸው ውስጥ ተጠቃሚዎችን ብቻ ነው ማግኘት የሚችሉት። የራሳቸውን የተጠቃሚ ቡድኖች ብቻ ነው መድረስ የሚችሉት። - label: "በእኔ ቡድን ውስጥ ያሉትን ሁሉንም የተቀዱ መዝገቦች ወይም ተጠቃሚዎችነን ይፈልጓቸው " + label: 'በእኔ ቡድን ውስጥ ያሉትን ሁሉንም የተቀዱ መዝገቦች ወይም ተጠቃሚዎችነን ይፈልጓቸው ' self: explanation: ሚናው የራሳቸውን መዝገቦች (ጉዳይ፣ የመከታተያ ጥያቄዎችን ወይም ክስተቶችን) መድረስ እና የራሳቸውን የተጠቃሚ መለያ ማስተካከል ይችላሉ። label: የኔን መዝገቦች/ተጠቃሚዎች ብቻ አግኝ explanation: የትኛውን እንደሚመዘግብ (ጉዳይ፣ የመከታተያ ጥያቄዎች ወይም ክስተቶች) ሚናው መድረስ እንደሚችል ይቆጣጠራል። ሚናው የተጠቃሚዎች እና የተጠቃሚ ቡድኖች መዳረሻ ካለው፣ ይህ ደግሞ የትኞቹን ተጠቃሚዎች እና የተጠቃሚ ቡድኖች መድረስ እንደሚችሉ ይቆጣጠራል። የ"መዝገብ የለም" መዳረሻ ያላቸው ሚናዎች እንደ ቅጾች፣ ተጠቃሚዎች እና ሪፖርቶች ያሉ የስርዓት ውቅርን ብቻ መድረስ ይችላሉ። - label: "ምን አይነት መረጃዎችን ያበላሻል? " + label: 'ምን አይነት መረጃዎችን ያበላሻል? ' incident: actions: change_log: @@ -2432,10 +2900,12 @@ am-ET: explanation: ጉዳይ የመፍጠር ችሎታ label: ፍጠር enable_disable_record: - explanation: "የማብራት ወይም ጥፋት\n\"አጥፋ\" ሁናቴዎች በዝርዝር ስር አይመጡም፡፡ ተጠቃሚው የማጣርያ ቀስታን በመጠቀም ማጥፋት ይችላል" + explanation: 'የማብራት ወይም ጥፋት + + "አጥፋ" ሁናቴዎች በዝርዝር ስር አይመጡም፡፡ ተጠቃሚው የማጣርያ ቀስታን በመጠቀም ማጥፋት ይችላል' label: አብራ/አጥፋ export_case_pdf: - explanation: "የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በፒ.ዲ.ኤፍ ወጪ ማድረግ ይችላሉ፡፡ በፒ.ዲ.ኤፍ የሚወጣ ፋይል ላይ መረጃዎች በመጀመሪያ በጉዳይ ተዘርዝረው ይቀመጣሉ፡፡ በተጨማሪም መረጃዎችን በያዙ ቅጾች ይደራጃል፡፡ " + explanation: 'የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በፒ.ዲ.ኤፍ ወጪ ማድረግ ይችላሉ፡፡ በፒ.ዲ.ኤፍ የሚወጣ ፋይል ላይ መረጃዎች በመጀመሪያ በጉዳይ ተዘርዝረው ይቀመጣሉ፡፡ በተጨማሪም መረጃዎችን በያዙ ቅጾች ይደራጃል፡፡ ' label: በፒዲኤፍ ወጪ ማድረግ export_csv: explanation: ተጠቃሚው ከስጋት ዝርዝር ወይም ከስጋት ማሳያ ገፆች የCSV ፋይል ወደ ውጭ መላክ ይችላል፣ይህም ተጠቃሚው የሚጠቀምባቸው ሁሉንም መስኮች የያዘ፣ለአንድ፣ለብዙ ወይም ለሁሉም ተጠቃሚው የሚደርስባቸው አጋጣሚዎች። @@ -2446,40 +2916,46 @@ am-ET: explanation: ተጠቃሚ ከGBV ክስተት መቅጃ መሳሪያ ጋር የውሂብ ልውውጥ ለማድረግ የሚያስችል ልዩ XLS ፋይል ወደ ውጭ መላክ ይችላል። label: ተመዝግበው የተስተካከሉ መዝገቦችን xls ወደ ሌላ ላክ export_json: - explanation: "የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በጄ.ኤስ.ኦ.ኤን ወጪ ማድረግ ይችላሉ፡፡ ይህን ማድረግ  ጉዳዮችን ከዚህኛው ፕሪሜሮ ስርዓት ወጪ በማድረግ ወደ ሌላ የፐሪሜሮ ስርዓት ወይም ወደ ሌላ የመረጃ አያያዝና አስተዳደር ቋት ገቢ ለማድረግ የሚጠቅም ይሆናል፡፡ የጄ.ኤስ.ኦ.ኤን አቀራረብ በማሽን ብቻ የሚነበብ በመሆኑ በአብዛኛው ተገልጋዮች ዘንድ አይተገበርም፡፡ " + explanation: 'የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በጄ.ኤስ.ኦ.ኤን ወጪ ማድረግ ይችላሉ፡፡ ይህን ማድረግ  ጉዳዮችን ከዚህኛው ፕሪሜሮ ስርዓት ወጪ በማድረግ ወደ ሌላ የፐሪሜሮ ስርዓት ወይም ወደ ሌላ የመረጃ አያያዝና አስተዳደር ቋት ገቢ ለማድረግ የሚጠቅም ይሆናል፡፡ የጄ.ኤስ.ኦ.ኤን አቀራረብ በማሽን ብቻ የሚነበብ በመሆኑ በአብዛኛው ተገልጋዮች ዘንድ አይተገበርም፡፡ ' label: በጄ.ኤስ.ኦ.ኤን ወጪ ማድረግ export_list_view_csv: explanation: የዚህ ስርዓት ተገልጋዮች ከጉዳይ ዝርዝር ገጽ ላይ የሲ.ኤስ.ቪ መረጃዎችን ወጪ ማድረግ ይችላል፡፡ ይህን ማድረግ የሚቻለው ከጉዳይ ዝርዝር ገጽ ላይ ብቻ ነው፡፡ - label: "በሲ.ኤስ.ቪ ወጪ ማድረግ " + label: 'በሲ.ኤስ.ቪ ወጪ ማድረግ ' export_pdf: - explanation: "የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በፒ.ዲ.ኤፍ ወጪ ማድረግ ይችላሉ፡፡ በፒ.ዲ.ኤፍ የሚወጣ ፋይል ላይ መረጃዎች በመጀመሪያ በጉዳይ ተዘርዝረው ይቀመጣሉ፡፡ በተጨማሪም መረጃዎችን በያዙ ቅጾች ይደራጃል፡፡ " + explanation: 'የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በፒ.ዲ.ኤፍ ወጪ ማድረግ ይችላሉ፡፡ በፒ.ዲ.ኤፍ የሚወጣ ፋይል ላይ መረጃዎች በመጀመሪያ በጉዳይ ተዘርዝረው ይቀመጣሉ፡፡ በተጨማሪም መረጃዎችን በያዙ ቅጾች ይደራጃል፡፡ ' label: በፒዲኤፍ ወጪ ማድረግ export_xls: - explanation: "ተገልጋዩ ከጉዳይ ማሳያ ገጽ/ዝርዝር የአንድ ወይም የብዙ ጉዳዮችን መረጃዎች የያዜ ቅጾችን የኤክስ.ኤል.ኤስ ፋይል ማውጣት ይችላል፡፡ በዚመልኩ የሚወጣ እያንዳንዱ ቅጽ የኤክስ.ኤል.ኤስ መረጃ የራሱ በሆነ የማንጠልጠያ ምልክት ይወከላል፡፡ ተገልጋዩ መረጃዎች ምን ምን ተካቶባቸው መውጣት እንዳለባቸው መምረጥ ይችላል፡፡ ነገር ግን ተገልጋዩ ማካተትና ማውጣት የሚችላቸው ቅጾችና መረጃዎች ለማየት ፈቃድ የተሰጠው መረጃዎችን ብቻ መሆኑን ማስታወስ ይገባል፡፡ " + explanation: 'ተገልጋዩ ከጉዳይ ማሳያ ገጽ/ዝርዝር የአንድ ወይም የብዙ ጉዳዮችን መረጃዎች የያዜ ቅጾችን የኤክስ.ኤል.ኤስ ፋይል ማውጣት ይችላል፡፡ በዚመልኩ የሚወጣ እያንዳንዱ ቅጽ የኤክስ.ኤል.ኤስ መረጃ የራሱ በሆነ የማንጠልጠያ ምልክት ይወከላል፡፡ ተገልጋዩ መረጃዎች ምን ምን ተካቶባቸው መውጣት እንዳለባቸው መምረጥ ይችላል፡፡ ነገር ግን ተገልጋዩ ማካተትና ማውጣት የሚችላቸው ቅጾችና መረጃዎች ለማየት ፈቃድ የተሰጠው መረጃዎችን ብቻ መሆኑን ማስታወስ ይገባል፡፡ ' label: በኤክስኤል (በኤክስ.ኤል.ኤስ) ፋይል ወጪ ማድረግ flag: - explanation: "በአንድ ክስተት ላይ ችግሩን የመጠቆም ችሎታ። ፈቃድ ያላቸው ተጠቃሚዎች በአንድ ክስተት ላይ ያከሏቸውን ወየይመም የጨመሯቸውን ጠቋሚ ችግሮች ማስወገድ ይችላሉ። " + explanation: 'በአንድ ክስተት ላይ ችግሩን የመጠቆም ችሎታ። ፈቃድ ያላቸው ተጠቃሚዎች በአንድ ክስተት ላይ ያከሏቸውን ወየይመም የጨመሯቸውን ጠቋሚ ችግሮች ማስወገድ ይችላሉ። ' label: የማውለብለብ ምልክት import: explanation: ተጠቃሚዎች ከሲ.ኤስ.ቪ፣ ከኤክስኤል ወይም ከጄ.ኤስ.ኦ.ኤን ፋይል አንድ ወይም ከዚያ በላይ አዲስ ጉዳዮችን ቀድቶ ማምጣት ያስችላል፡፡ በዚህ መልኩ ተቀድቶ የሚመጣ ፋይል መረጃ በጣም ግልጽ በሆነና በተገቢዉ መንገድ ሊደራጅ ይገባል፡፡ ይህ ስራ ሊፈቀድ የሚገባው በፕሪሜሮ ሲስተም መረጃዎች እንዴት መደራጀት እንዳለባቸው ከፍተኛ ሙያዊ ክህሎትና ጥልቅ እውቀት ባላቸው በመረጃ አስተዳደር ደረጃ ባሉ ተጠቃሚዎች ሊሆን ይገባል፡፡ ከጉዳየይ ዝርዝር ገጽ ላይ ብቻ የሚከናወን፡፡ label: ከሌላ ማምጣት manage: - explanation: "ተጠቃሚው ሁሉንም በቂ ሆኑ የተስተካከሉ እርምጃዎች እንዲወስድ ያስችለዋል። የ\"ማስተዳደር\" ፍቃድ ማለት በመሰረቱ \"ሁሉንም\" ለመማለተት ነው። " + explanation: 'ተጠቃሚው ሁሉንም በቂ ሆኑ የተስተካከሉ እርምጃዎች እንዲወስድ ያስችለዋል። የ"ማስተዳደር" ፍቃድ ማለት በመሰረቱ "ሁሉንም" ለመማለተት ነው። ' label: ማስተዳደር( ለዚህ የመደበ ሁሉም አይነት ሀብት የማስተዳደር ፈቃድ) read: - explanation: "ክስተትን የማየት ችሎታ\n\n " + explanation: 'ክስተትን የማየት ችሎታ + + +  ' label: እይታ sync_mobile: explanation: ይህ ፈቃድ በአጠቃላይ ተጠቃሚው የሞባይል መተግበሪያን እንዲጠቀም ያስችለዋል። በመጀመሪያ ተጠቃሚው በክስተት ዝርዝር እና በክስተት ማሳያ ገፆች ላይ የሚታዩትን "ለሞባይል ምልክት" እና "ለሞባይል ምልክት አታድርግ" ድርጊቶችን እንዲያይ ያስችለዋል። ለተንቀሳቃሽ ስልክ ክስተት ምልክት ማድረግ ስለዚያ ክስተት መረጃ በተጠቃሚው ተንቀሳቃሽ መሳሪያ እና በመተግበሪያ መካከል መመሳሰል እንዳለበት ያሳያል፣ የሞባይል ላይ ምልክት አለማድረግ ግን ይህ ማመሳሰል እንዳይከሰት ያደርገዋል። ያለዚህ ፍቃድ ተጠቃሚዎች የሞባይል መሳሪያቸውን ከድር መተግበሪያ ጋር በአጠቃላይ ማመሳሰል አይችሉም ይህም ማለት የሞባይል መተግበሪያን ተጠቅመው ክስተቶችን መቆጣጠር አይችሉም ማለት ነው። label: በሞባይል ግባ write: - explanation: "የ \"አርትዖቱን\" ቁልፍን የመጫን ችሎታ,ቁልፉን በመጫን ስለ ክስተቱ ያስተካከልከውን መረጃህን \"ሰንድህ አስቀምጥ\" እንዲሁም ተጠቃሚው ክስተቱን እንዳይሰራ ወይም እንዲሰራ ለማድረግ ያስችለዋል።\n\n " + explanation: 'የ "አርትዖቱን" ቁልፍን የመጫን ችሎታ,ቁልፉን በመጫን ስለ ክስተቱ ያስተካከልከውን መረጃህን "ሰንድህ አስቀምጥ" እንዲሁም ተጠቃሚው ክስተቱን እንዳይሰራ ወይም እንዲሰራ ለማድረግ ያስችለዋል። + + +  ' label: አስተካክል explanation: የተከሰተውን ክስተት ይወክላል። እነዚህ አብዛኛውን ጊዜ የመጎሳቆል ወይም የጥቃት ክስተቶች ናቸው፣ ምንም እንኳን ከህግ አስከባሪዎች ጋር ከተገናኙት ክስተቶች ጋር ሊዛመዱ ይችላሉ። ክስተቶች ብዙ ጊዜ ከጉዳዮች ጋር የተገናኙ ናቸው። label: ድርጊት/ሁነት is_manager: explanation: የትኛውንም ተጠቃሚ ኃላፊነት መወጣት በሚያስችለው መልኩ ሌሎች ተጠቃሚዎችን ቁጥጥር ማድረግ፡፡ ይህ ተጠቃሚ ቡድኑን እንዲያስተዳድር የሚያግዙ ዳሽቦርዶችን እና ማጣሪያዎችን እንዲያይ ያግዘዋል። - label: "ሃላፊ ነው?" + label: ሃላፊ ነው? managed_report: actions: violations: @@ -2498,7 +2974,7 @@ am-ET: manage: explanation: መፍጠር፣ መቀየር፣ መተርጎምና ፎርሞችን ማጥፋት፣ የቅጽ ቦታና ለማየት ማስተካከል፡፡ ደንበኛው የሚፈቀድለትንና የሚሰራዎችን ስራዎች ብቻ እንዲያይ ይፈቀድለታል፡፡ ለምሳሌ በሀገር ደረጃ ያላው የመረጃ ተቆጣጣሪ መረጃዎችን የማየትና መቆጣጠር ድርሻና ሀላፊነት አለበት label: አስተካከል(ሁሉንም የተፈቀዱትን ) - explanation: "የፕሪሜሮ ቅጾችን ማስተካከልና አማራጮችን ማየት " + explanation: 'የፕሪሜሮ ቅጾችን ማስተካከልና አማራጮችን ማየት ' label: ቅጾች፣ ማየት module: actions: @@ -2525,7 +3001,7 @@ am-ET: referral: actions: refer: - explanation: "ይህ ማለት ተጠቃሚው የውጭ ሪፈራልን ሲጠቀም የ\"የተቀባዩ አይነት\" እንደ አማራጭ ሆኖ ይታያል ማለት ነው። ተጠቃሚው ይህንን አማራጭ እንደ ሪፈራል አይነት ከመረጠ፣ ተጠቃሚው ሪፈራሉን ሲያስረክብ ፕሪሚሮ የሚያመነጨው ወደ ውጭ የሚላከው ይህ አማራጭ በሚጠቀምባቸው ቅጾች ውስጥ የሚገኘውን መረጃ ብቻ ይይዛል።ስለዚህ፡ ለምሳሌ፡ ተጠቃሚው “የህክምና አገልግሎት አቅራቢን” እንደ ማዘዋወርያ አይነት ከመረጠ እና የህክምና አገልግሎት አቅራቢው አስፈላጊ የመሠረታዊ የማንነት እና የጥበቃ ቅፆችን ማግኘት ብቻ ነው፡ ፕሪሜሮ ለውጭ ማዘዋወርያ ወደ ሌላ አካል የሚላከው የኤክስፖርት ፋይል በእነዚህ ሁለት ቅጾች ውስጥ ያሉትን መስኮች ብቻ ይሆናል። " + explanation: 'ይህ ማለት ተጠቃሚው የውጭ ሪፈራልን ሲጠቀም የ"የተቀባዩ አይነት" እንደ አማራጭ ሆኖ ይታያል ማለት ነው። ተጠቃሚው ይህንን አማራጭ እንደ ሪፈራል አይነት ከመረጠ፣ ተጠቃሚው ሪፈራሉን ሲያስረክብ ፕሪሚሮ የሚያመነጨው ወደ ውጭ የሚላከው ይህ አማራጭ በሚጠቀምባቸው ቅጾች ውስጥ የሚገኘውን መረጃ ብቻ ይይዛል።ስለዚህ፡ ለምሳሌ፡ ተጠቃሚው “የህክምና አገልግሎት አቅራቢን” እንደ ማዘዋወርያ አይነት ከመረጠ እና የህክምና አገልግሎት አቅራቢው አስፈላጊ የመሠረታዊ የማንነት እና የጥበቃ ቅፆችን ማግኘት ብቻ ነው፡ ፕሪሜሮ ለውጭ ማዘዋወርያ ወደ ሌላ አካል የሚላከው የኤክስፖርት ፋይል በእነዚህ ሁለት ቅጾች ውስጥ ያሉትን መስኮች ብቻ ይሆናል። ' label: ይህ ተግባር ከተቃም ውጭ ለመቀባበል ያግዛል label: ቅብብል registry_record: @@ -2537,7 +3013,9 @@ am-ET: explanation: የምዝገባ መረጃ label: መፍጠር enable_disable_record: - explanation: "የማብራት ወይም ማጥፋት\n\"አጥፋ\" ሁናቴዎች በዝርዝር ስር አይመጡም፡፡ ተጠቃሚው የማጣርያ ቀስታን በመጠቀም ማጥፋት ይችላል" + explanation: 'የማብራት ወይም ማጥፋት + + "አጥፋ" ሁናቴዎች በዝርዝር ስር አይመጡም፡፡ ተጠቃሚው የማጣርያ ቀስታን በመጠቀም ማጥፋት ይችላል' label: ማስቻል/አለማስቻል export_csv: explanation: 'ተገልጋዩ ከጉዳይ ማሳያ ገጽ/ዝርዝር የአንድ ወይም የብዙ ጉዳዮችን መረጃዎች የሲ.ኤስ.ቪ ፋይል ማውጣት ይችላል፡፡  ማስታወሻ፡ በሲ.ኤስ.ቪ የሚወጡ መረጃዎች የላቲን ላልሆኑ ፊደላት (ምሳሌ የአረብ) በጽሁፍ ተተርጉመው አይወጡም፡፡' @@ -2558,13 +3036,24 @@ am-ET: explanation: የተመዘገቡትን መረጃዎች የማየት label: እይታ write: - explanation: "\"ቀይር\" የሚለውን ቁልፍ መጫን መቻል መረጃዎችን ካሻሻሉ በኀላ \"አስቀምጥ\" የሚለውን ተጫን" + explanation: '"ቀይር" የሚለውን ቁልፍ መጫን መቻል መረጃዎችን ካሻሻሉ በኀላ "አስቀምጥ" የሚለውን ተጫን' label: አስተካክል sync_mobile: explanation: ከመስመር/ከግንኙነት ውጭ ጥቅም ላይ የሚውሉ ጉዳዮችን ለመጠቀም ለተጠቃሚው ይፈቅዳል። label: ከኢንተርኔት ውጭ ለመስራት ማስቻል - explanation: "ይህ እንደ ጉዳዮች ወይም ክስተቶች ካሉ ሌሎች መዛግብት ጋር መገናኘት ያለባቸውን፣ በጣም ብዙ የሆኑ እና በአዲስ መረጃ በተደጋጋሚ ሊሚዘመኑ ይችላል። እነሱ ከፍለጋዎች ጋር ተመሳሳይ ናቸው, ነገር ግን ለእያንዳንዱ የሚገባ መረጃ የበለጠ ውስብስብ በሆነ የመረጃ ስብስብ፡፡" + explanation: ይህ እንደ ጉዳዮች ወይም ክስተቶች ካሉ ሌሎች መዛግብት ጋር መገናኘት ያለባቸውን፣ በጣም ብዙ የሆኑ እና በአዲስ መረጃ በተደጋጋሚ ሊሚዘመኑ ይችላል። እነሱ ከፍለጋዎች ጋር ተመሳሳይ ናቸው, ነገር ግን ለእያንዳንዱ የሚገባ መረጃ የበለጠ ውስብስብ በሆነ የመረጃ ስብስብ፡፡ label: የመዝገብ ቅጅ + family: + actions: + change_log: + label: መግቢያ ቀይር + create: + explanation: ' የመጨመር/ የመፍጠር ችሎታ' + label: መፍጠር + enable_disable_record: + label: አብራ/አጥፋ + export_csv: + label: በሲ.ኤስ.ቪ ወጪ ማድረግ report: actions: create: @@ -2574,7 +3063,7 @@ am-ET: explanation: ሁሉንም ሪፖርቶች ለማየት ያስችላል፡፡ በእያንዳንዱ ሪፖርት ውስጥ ያሉት ቁጥሮች የሚያሳዩት አሁን ባለው የተጠቃሚ ቡድኖች ውስጥ ለተጠቃሚዎች ተደራሽ የሆኑትን መዝገቦች ብቻ ነው። ይህ ፈቃድ ብዙ ጊዜ ጥቅም ላይ የሚውለው ስለ ቡድኖቻቸው ወይም ድርጅታቸው አፈጻጸም ግንዛቤዎችን ለማግኘት ለሚፈልጉ የአካባቢ፣ የክልል ወይም የኤጀንሲ አስተዳዳሪዎች ነው። ይህ ፍቃድ ተጠቃሚው ከሪፖርት መረጃን ወደ ውጭ የመላክ ችሎታም ይሰጣል። label: ይመልከቱ (በቡድን ላይ የተመሰረተ ውሂብ) manage: - explanation: "ተጠቃሚው ሁሉንም በቂ ሆኑ የተስተካከሉ እርምጃዎች እንዲወስድ ያስችለዋል። የ\"ማስተዳደር\" ፍቃድ ማለት በመሰረቱ \"ሁሉንም\" ለመማለተት ነው። " + explanation: 'ተጠቃሚው ሁሉንም በቂ ሆኑ የተስተካከሉ እርምጃዎች እንዲወስድ ያስችለዋል። የ"ማስተዳደር" ፍቃድ ማለት በመሰረቱ "ሁሉንም" ለመማለተት ነው። ' label: ማስተዳደር( ለዚህ የመደበ ሁሉም አይነት ሀብት የማስተዳደር ፈቃድ) read: explanation: ሁሉንም ሪፖርቶች የማየት፡፡ በእያንዳንዱ ሪፖርት ውስጥ ያሉት ቁጥሮች የአሁኑ ተጠቃሚ የሚደርሱባቸውን መዝገቦች ብቻ ሳይሆን በስርዓቱ ውስጥ ያሉትን ሁሉንም መዝገቦች ያንፀባርቃሉ። ይህ ፍቃድ ተጠቃሚው ከሪፖርት መረጃን ወደ ውጭ የመላክ ችሎታም ይሰጣል። @@ -2620,7 +3109,7 @@ am-ET: manage: explanation: የግንኙነት መረጃ ስርዓት ን፣  ማስተዋቂያ እና የሚመጡ የኢሜል መዋቅሮችን  እና የመረጃ መረቡ የማስተካከል ፣የማየት እና የማሻሻል  ሀላፊነት የመረጃ አስተዳዳር ሃለፊዉ ፈቃድ ያስፈልጋል፡፡ label: አስተካክል (ይህን አገልግሎት ለመጠቀም) - explanation: "አጠቃላይ " + explanation: 'አጠቃላይ ' label: ስርዓት tracing_request: actions: @@ -2631,43 +3120,48 @@ am-ET: explanation: የመፈለጊያ ቅጽ መፍጠር label: መፍጠር enable_disable_record: - explanation: "የማብራት ወይም ጥፋት\n\"አጥፋ\" ሁናቴዎች በዝርዝር ስር አይመጡም፡፡ ተጠቃሚው የማጣርያ ቀስታን በመጠቀም ማጥፋት ይችላል" + explanation: 'የማብራት ወይም ጥፋት + + "አጥፋ" ሁናቴዎች በዝርዝር ስር አይመጡም፡፡ ተጠቃሚው የማጣርያ ቀስታን በመጠቀም ማጥፋት ይችላል' label: አብራ/አጥፋ export_case_pdf: - explanation: "የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በፒ.ዲ.ኤፍ ወጪ ማድረግ ይችላሉ፡፡ በፒ.ዲ.ኤፍ የሚወጣ ፋይል ላይ መረጃዎች በመጀመሪያ በጉዳይ ተዘርዝረው ይቀመጣሉ፡፡ በተጨማሪም መረጃዎችን በያዙ ቅጾች ይደራጃል፡፡ " + explanation: 'የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በፒ.ዲ.ኤፍ ወጪ ማድረግ ይችላሉ፡፡ በፒ.ዲ.ኤፍ የሚወጣ ፋይል ላይ መረጃዎች በመጀመሪያ በጉዳይ ተዘርዝረው ይቀመጣሉ፡፡ በተጨማሪም መረጃዎችን በያዙ ቅጾች ይደራጃል፡፡ ' label: በፒዲኤፍ ወጪ አድርግ export_csv: - explanation: "የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በፒ.ዲ.ኤፍ ወጪ ማድረግ ይችላሉ፡፡ በፒ.ዲ.ኤፍ የሚወጣ ፋይል ላይ መረጃዎች በመጀመሪያ በጉዳይ ተዘርዝረው ይቀመጣሉ፡፡ በተጨማሪም መረጃዎችን በያዙ ቅጾች ይደራጃል፡፡ " + explanation: 'የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በፒ.ዲ.ኤፍ ወጪ ማድረግ ይችላሉ፡፡ በፒ.ዲ.ኤፍ የሚወጣ ፋይል ላይ መረጃዎች በመጀመሪያ በጉዳይ ተዘርዝረው ይቀመጣሉ፡፡ በተጨማሪም መረጃዎችን በያዙ ቅጾች ይደራጃል፡፡ ' label: በሲ.ኤስ.ቪ ወጪ ማድረግ export_custom: - explanation: "ተገልጋዩ ከጉዳይ ማሳያ ገጽ/ዝርዝር የአንድ ወይም የብዙ ጉዳዮችን መረጃዎች የያዜ ቅጾችን XLS ፋይል ማውጣት ይችላል፡፡ በዚመልኩ የሚወጣ እያንዳንዱ ቅጽ የXLS መረጃ የራሱ በሆነ የማንጠልጠያ ምልክት ይወከላል፡፡ ተገልጋዩ መረጃዎች ምን ምን ተካቶባቸው መውጣት እንዳለባቸው መምረጥ ይችላል፡፡ ነገር ግን ተገልጋዩ ማካተትና ማውጣት የሚችላቸው ቅጾችና መረጃዎች ለማየት ፈቃድ የተሰጠው መረጃዎችን ብቻ መሆኑን ማስታወስ ይገባል፡፡ " + explanation: 'ተገልጋዩ ከጉዳይ ማሳያ ገጽ/ዝርዝር የአንድ ወይም የብዙ ጉዳዮችን መረጃዎች የያዜ ቅጾችን XLS ፋይል ማውጣት ይችላል፡፡ በዚመልኩ የሚወጣ እያንዳንዱ ቅጽ የXLS መረጃ የራሱ በሆነ የማንጠልጠያ ምልክት ይወከላል፡፡ ተገልጋዩ መረጃዎች ምን ምን ተካቶባቸው መውጣት እንዳለባቸው መምረጥ ይችላል፡፡ ነገር ግን ተገልጋዩ ማካተትና ማውጣት የሚችላቸው ቅጾችና መረጃዎች ለማየት ፈቃድ የተሰጠው መረጃዎችን ብቻ መሆኑን ማስታወስ ይገባል፡፡ ' label: ወጪ ለማድረግ የተዘጋጀ export_json: - explanation: "የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በጄ.ኤስ.ኦ.ኤን ወጪ ማድረግ ይችላሉ፡፡ ይህን ማድረግ  ጉዳዮችን ከዚህኛው ፕሪሜሮ ስርዓት ወጪ በማድረግ ወደ ሌላ የፐሪሜሮ ስርዓት ወይም ወደ ሌላ የመረጃ አያያዝና አስተዳደር ቋት ገቢ ለማድረግ የሚጠቅም ይሆናል፡፡ የጄ.ኤስ.ኦ.ኤን አቀራረብ በማሽን ብቻ የሚነበብ በመሆኑ በአብዛኛው ተገልጋዮች ዘንድ አይተገበርም፡፡ " + explanation: 'የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በጄ.ኤስ.ኦ.ኤን ወጪ ማድረግ ይችላሉ፡፡ ይህን ማድረግ  ጉዳዮችን ከዚህኛው ፕሪሜሮ ስርዓት ወጪ በማድረግ ወደ ሌላ የፐሪሜሮ ስርዓት ወይም ወደ ሌላ የመረጃ አያያዝና አስተዳደር ቋት ገቢ ለማድረግ የሚጠቅም ይሆናል፡፡ የጄ.ኤስ.ኦ.ኤን አቀራረብ በማሽን ብቻ የሚነበብ በመሆኑ በአብዛኛው ተገልጋዮች ዘንድ አይተገበርም፡፡ ' label: በጄ.ኤስ.ኦ.ኤን ወጪ ማድረግ export_list_view_csv: explanation: የዚህ ስርዓት ተገልጋዮች ከጉዳይ ዝርዝር ገጽ ላይ የሲ.ኤስ.ቪ መረጃዎችን ወጪ ማድረግ ይችላል፡፡ ይህን ማድረግ የሚቻለው ከጉዳይ ዝርዝር ገጽ ላይ ብቻ ነው፡፡ label: በሲ.ኤስ.ቪ ዝርዝር እይታ ወጪ ማድረግ export_pdf: - explanation: "የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በፒ.ዲ.ኤፍ ወጪ ማድረግ ይችላሉ፡፡ በፒ.ዲ.ኤፍ የሚወጣ ፋይል ላይ መረጃዎች በመጀመሪያ በጉዳይ ተዘርዝረው ይቀመጣሉ፡፡ በተጨማሪም መረጃዎችን በያዙ ቅጾች ይደራጃል፡፡ " + explanation: 'የዚህ ስርዓት ተጠቃሚዎች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳዮች ዝርዝር/ከጉዳይ ማሳያ ገጽ ላይ መረጃዎችን በፒ.ዲ.ኤፍ ወጪ ማድረግ ይችላሉ፡፡ በፒ.ዲ.ኤፍ የሚወጣ ፋይል ላይ መረጃዎች በመጀመሪያ በጉዳይ ተዘርዝረው ይቀመጣሉ፡፡ በተጨማሪም መረጃዎችን በያዙ ቅጾች ይደራጃል፡፡ ' label: በፒዲኤፍ ወጪ ማድረግ export_xls: explanation: 'የዚህ ስርዓት ተገልጋዮች ለማየት ከተፈቀደላቸው አንድ፣ ብዛት ያላቸው ወይም ሁሉንም ጉዳዮች፤ ከጉዳይ ዝርዝር/ማሳያ ገጽ ላይ በኤክስ.ኤል.ኤስ ፋይል ወጪ ማድረግ ይችላል፡፡ በዚመልኩ የሚወጣ እያንዳንዱ ቅጽ የኤክስ.ኤል.ኤስ መረጃ የራሱ በሆነ የማንጠልጠያ ምልክት ይወከላል፡፡ ማስታወሻ፡ በሲ.ኤስ.ቪ ወጪ ከማድረግ በተለየ መልኩ  የኤክስ.ኤል.ኤስ አቀራረብ የላቲን ያልሆኑ ጽሁፎችንም (አረብ፣ ባንግላ) ተርጉሞ በሚነበብ መልኩ ምላሽ የሚሰጥ ይሆናል፡፡  ' label: በኤክስኤል (በኤክስ.ኤል.ኤስ) ፋይል ወጪ ማድረግ flag: - explanation: "በአንድ ክስተት ላይ ችግሩን የመጠቆም ችሎታ። ፈቃድ ያላቸው ተጠቃሚዎች በአንድ ክስተት ላይ ያከሏቸውን ወየይመም የጨመሯቸውን ጠቋሚ ችግሮች ማስወገድ ይችላሉ። " + explanation: 'በአንድ ክስተት ላይ ችግሩን የመጠቆም ችሎታ። ፈቃድ ያላቸው ተጠቃሚዎች በአንድ ክስተት ላይ ያከሏቸውን ወየይመም የጨመሯቸውን ጠቋሚ ችግሮች ማስወገድ ይችላሉ። ' label: የማውለብለብ ምልክት import: explanation: ተጠቃሚዎች ከሲ.ኤስ.ቪ፣ ከኤክስኤል ወይም ከጄ.ኤስ.ኦ.ኤን ፋይል አንድ ወይም ከዚያ በላይ አዲስ ጉዳዮችን ቀድቶ ማምጣት ያስችላል፡፡ በዚህ መልኩ ተቀድቶ የሚመጣ ፋይል መረጃ በጣም ግልጽ በሆነና በተገቢዉ መንገድ ሊደራጅ ይገባል፡፡ ይህ ስራ ሊፈቀድ የሚገባው በፕሪሜሮ ሲስተም መረጃዎች እንዴት መደራጀት እንዳለባቸው ከፍተኛ ሙያዊ ክህሎትና ጥልቅ እውቀት ባላቸው በመረጃ አስተዳደር ደረጃ ባሉ ተጠቃሚዎች ሊሆን ይገባል፡፡ ከጉዳየይ ዝርዝር ገጽ ላይ ብቻ የሚከናወን፡፡ label: ከሌላ ቦታ ማምጣት manage: - explanation: "ተጠቃሚው ሁሉንም በቂ የሆኑ የተስተካከሉ እርምጃዎች እንዲወስድ ያስችለዋል። የ\"ማስተዳደር\" ፍቃድ ማለት በመሰረቱ \"ሁሉንም\" ለመማለተት ነው። " + explanation: 'ተጠቃሚው ሁሉንም በቂ የሆኑ የተስተካከሉ እርምጃዎች እንዲወስድ ያስችለዋል። የ"ማስተዳደር" ፍቃድ ማለት በመሰረቱ "ሁሉንም" ለመማለተት ነው። ' label: ተቆጣጠር (ለዚህ ሂደት ሁሉንም ፈቃዶች) read: explanation: የመከታተያ ጥያቄ የማየት። የመከታተያ ጥያቄዎችን ማየት የሚችሉ ሁሉ ተዛማጅ መዝገብ አይነትን የማየት ችሎታ ሊኖራቸው ይገባል። label: እይታ write: - explanation: "የ \"አርትዖቱን\" ቁልፍን የመጫን ችሎታ,ቁልፉን በመጫን ስለ ክስተቱ ያስተካከልከውን መረጃህን \"ሰንድህ አስቀምጥ\" እንዲሁም ተጠቃሚው ክስተቱን እንዳይሰራ ወይም እንዲሰራ ለማድረግ ያስችለዋል።\n\n " + explanation: 'የ "አርትዖቱን" ቁልፍን የመጫን ችሎታ,ቁልፉን በመጫን ስለ ክስተቱ ያስተካከልከውን መረጃህን "ሰንድህ አስቀምጥ" እንዲሁም ተጠቃሚው ክስተቱን እንዳይሰራ ወይም እንዲሰራ ለማድረግ ያስችለዋል። + + +  ' label: አስተካክል explanation: አብሮ ከሌለው ወይም የተለየ ጉዳይ ለማግኘት እና እንደገና ለማቀላቀል የሚሞክርን ግለሰብ ይወክላል። label: የማፈላለግ ጥያቄ @@ -2675,7 +3169,7 @@ am-ET: actions: transfer: explanation: ይህ ማለት ተጠቃሚው የውጭ ሪፈራልን ሲያደርግ ሚናው ለ"የተቀባዩ አይነት" እንደ አማራጭ ሆኖ ይታያል ማለት ነው። ተጠቃሚው ይህን ሚና እንደ የዝውውር አይነት ከመረጠ፣ ተጠቃሚው ዝውውሩን በሚያስረክብበት ጊዜ ፕሪሚሮ የሚያመነጨው ኤክስፖርት ይህ ሚና በሚጠቀምባቸው ቅጾች ውስጥ የሚገኘውን መረጃ ብቻ ይይዛል። ስለዚህ፡ ለምሳሌ፡ ተጠቃሚው “የህክምና አገልግሎት አቅራቢን” በተቀባዩ አይነት ከመረጠ እና የህክምና አገልግሎት ሰጪው ሚና የመሰረታዊ የማንነት እና የጥበቃ ስጋቶች ቅፆችን ማግኘት ብቻ ከሆነ፡ ፕራይሮ ወደ ውጭ የሚላከው የኤክስፖርት ፋይል ብቻ ይሆናል። በእነዚህ ሁለት ቅጾች ውስጥ ያሉትን መስኮች ይይዛሉ፡፡ - label: "ይህ ሚና በውጭ ለሚኖር ማዘዋወር ይጠቅማልን?" + label: ይህ ሚና በውጭ ለሚኖር ማዘዋወር ይጠቅማልን? label: ማዘዋወር user: actions: @@ -2692,7 +3186,7 @@ am-ET: explanation: ሁሉም ተጠቃሚ የራሱን የመጠቀሚያ አካዉንት(  ለምሳሌ የማለፊያ የሚስጥር ቁጥር) መየት የሚችልበት ሁኔታ ተመቻችቷል፡፡ label: እይታ write: - explanation: "የማሻሻያ ቁልፍ የመንካት፣ መረጃ የማበልፅጊያ እና መዝግቦ መያዝ መቻል አካወንትን ለመሰረዝ ያስችላል፡፡ " + explanation: 'የማሻሻያ ቁልፍ የመንካት፣ መረጃ የማበልፅጊያ እና መዝግቦ መያዝ መቻል አካወንትን ለመሰረዝ ያስችላል፡፡ ' label: አስተካክል explanation: የግለሰብ ተጠቃሚ መለያን ይወክላል label: ተጠቃሚዎች @@ -2734,7 +3228,6 @@ am-ET: label: ማጥፋት manage: label: ተቆጣጠር (ለዚህ የንብረት አይነት ሁሉንም ፈቃዶች) - explanation: activity_log: actions: transfer: @@ -2742,10 +3235,9 @@ am-ET: label: አስተላልፍ manage: label: አስተዳድር (ለዚህ ስራ አይነት ሁሉም ፈቃዶች አክል) - explanation: label: የተግባር ማስታወሻ potential_match: - case_id: "የጉዳይ #መለያ ቁጥር" + case_id: 'የጉዳይ #መለያ ቁጥር' child_age: እድሜ child_gender: ጾታ child_id: የህጻን መታወቂያ @@ -2761,11 +3253,12 @@ am-ET: likelihood_likely: የሚሆን likelihood_possible: የሚቻል potential_matches: - display: "ሊሆኑ የሚችሉ ተዛማጆችን በማሳየት ላይ %{type} %{id}" + display: ሊሆኑ የሚችሉ ተዛማጆችን በማሳየት ላይ %{type} %{id} reassign: - multiple_error: "{ስህተት ተፈጥሯል፤ ጉዳዩ/ጉዳዮች አልተመደቡም}" - multiple_successfully: 'ጉዳዩ/ጉዳዮች በተሳካ ሁኔታ ተመድበዋል' - notes_label: "ማስታወሻዎች\n " + multiple_error: '{ስህተት ተፈጥሯል፤ ጉዳዩ/ጉዳዮች አልተመደቡም}' + notes_label: 'ማስታወሻዎች + +  ' successfully: በሚገባ ተመድባል user_mandatory_label: ተቀባይ ያስፈልጋል users_label: ተቀባይ @@ -2776,29 +3269,40 @@ am-ET: created_organization: የፈጠረው ተቃም current_owner_separator: ባለቤት module_id: ሞዱል - owned_by: "የጉዳይ ባለሙያ መለያ ቁጥር\n " - owned_by_agency_id: "ተቋም\n\n " - owned_by_text: "ጉዳይ/ምድብ/ሶሻልወርከር\n " + owned_by: 'የጉዳይ ባለሙያ መለያ ቁጥር + +  ' + owned_by_agency_id: 'ተቋም + + +  ' + owned_by_text: 'ጉዳይ/ምድብ/ሶሻልወርከር + +  ' previously_owned_by: የቀድሞ ባለቤት previously_owned_by_agency: የቀድሞው ተቃም reassigned_tranferred_on: እንደገና መመደብ/ተላልፋል record_history_separator: የተመዘገበ መዝገብ ታሪክ last_updated_at: የታየበት የመጨረሻ ቀን - last_updated_by: "በመጨረሻ ያመለከተው በ\n " + last_updated_by: 'በመጨረሻ ያመለከተው በ + +  ' record_panel: record_information: የተመዘገበ መረጃ referral: type_of_recipient: የተቀባይ አይነት type_of_referral_required: የሚያስፈልገው ቅብብሎሽ agency_label: ተቋም - is_remote_label: "ወደሩቅ ቦታ ቅብብል ይደረጋል?" - location_label: "አድራሻ/መገኛ ቦታ\n " + is_remote_label: ወደሩቅ ቦታ ቅብብል ይደረጋል? + location_label: 'አድራሻ/መገኛ ቦታ + +  ' notes_label: ማስታወሻ notes_on_referral: በቅብብሎሹ ዙሪያ ያለ ማስታወሻ note_on_referral_from_provider: በቅብብሎሹ ዙሪያ ከላኪው አካል የቀረበ ማስታወሻ provided_consent_label: ስምምነት በቅጾች ላይ አልሰፈረም recipient_label: ተቀባይ - refer_anyway_label: "ለማንኛውም በቅብብሎሽ ይሂድ?" + refer_anyway_label: ለማንኛውም በቅብብሎሽ ይሂድ? service_label: አገልግሎት success: 'በተሳካ ሁኔታ በቅብብሎሽ ተልኳል' user_mandatory_label: ተቀባይ ያስፈልጋል @@ -2812,7 +3316,7 @@ am-ET: date: ቀን month: ወር quarter: ሩብ - quarter_abbr: "ሩብ%{quarter}" + quarter_abbr: ሩብ%{quarter} week: ሳምንት year: ዓመት description: መግለጫ @@ -2826,7 +3330,7 @@ am-ET: label_new: አዲስ ሪፖርት ማጥራት attribute: ማጥራት value: ከ ጋር - not_null: "ክፍት አይደለም?" + not_null: ክፍት አይደለም? less_than: ያንሳል ከ greater_than: ይበልጣል ከ equal_to: እኩል ነው ከ @@ -2834,7 +3338,7 @@ am-ET: is: ነው before: በፊት after: በኃላ - delete_filter_message: "ይህን መረጃ ለማጥፋትና ለማጣራት እርግጠኛ ነዎት?" + delete_filter_message: ይህን መረጃ ለማጥፋትና ለማጣራት እርግጠኛ ነዎት? group_ages: የእድሜ ደረጃ ማየት group_dates_by: የቀን ክፍልፋይ ማየት is_graph: በግራፍ አውጣ @@ -2848,7 +3352,9 @@ am-ET: no_data: መረጃ ለሪፖርት አልተገኘም no_filters_added: ማጣራት አልተደረገም not_selected: አልተመረጠም - record_type: "የመረጃ ሁኔታ\n " + record_type: 'የመረጃ ሁኔታ + +  ' total: ድምር value: ዋጋ reports: @@ -2874,7 +3380,7 @@ am-ET: description: መግለጫ edit: ሚናውን አስተካክል error_in_updating: የሚና ዝርዝሩን በማዘመን ሂደት ያለ ስህተት - group_permission_label: "ምን አይነት የተመዘገቡ ሀላፊነቶችን ተጽእኖ ያደርጋል?" + group_permission_label: ምን አይነት የተመዘገቡ ሀላፊነቶችን ተጽእኖ ያደርጋል? label: ሚና manager: ማኔጀር messages: @@ -2883,11 +3389,11 @@ am-ET: deleted: ሚናው በተሳካ ሁኔታ ጠፍቷል updated: ሚናው በተሳካ ሁኔታ ዘምኗል name: ስም - referral_label: "ይህ ሚና ለቅብብሎሽ ይጠቅማልን?" - reporting_location_level_label: "ለዚህ ሚና ሪፖርት ለማድረግ ምን ዓይነት የአካባቢ አይነት ጥቅም ላይ መዋል አለበት?" + referral_label: ይህ ሚና ለቅብብሎሽ ይጠቅማልን? + reporting_location_level_label: ለዚህ ሚና ሪፖርት ለማድረግ ምን ዓይነት የአካባቢ አይነት ጥቅም ላይ መዋል አለበት? role_ids_label: ሌሎች ሚናዎች በዚህ ሚና ተሸፍነዋል successfully_updated: የሚና መዘርዝሩ በተሳካ ሁኔታ ዘምኗል - transfer_label: "ይህ ሚና ለማዘዋወር ይጠቅማልን?" + transfer_label: ይህ ሚና ለማዘዋወር ይጠቅማልን? hide: ደብቅ read: አሳይ read_write: አሳይና አስተካክል @@ -2896,13 +3402,13 @@ am-ET: saved_search: deleted: ፍለጋው በተሳካ ሁኔታ ጠፍቷል filters_tab: ማጣራቶች - no_filters: "የተመረጡ ማጣራቶች የሉም " + no_filters: 'የተመረጡ ማጣራቶች የሉም ' save_success: ፍለጋው በተሳካ ሁኔታ ተመዝግቦ ተይዟል - saved_searches_tab: "ተመዝግቦ የተቀመጠ ፍለጋ " + saved_searches_tab: 'ተመዝግቦ የተቀመጠ ፍለጋ ' title_description: ተመዝግቦ የተቀመጠው ንፍለጋ ለማጥፋት እርግጠኛ ነዎት title_modal: ተመዝግቦ የተቀመጠን ፍለጋ አጥፋ saved_searches: - no_save_searches: "ተመዝግቦ የተቀመጠ ፍለጋ የለም " + no_save_searches: 'ተመዝግቦ የተቀመጠ ፍለጋ የለም ' save_search: ፍለጋውን መዝግበህ ያዝ settings: navigation: @@ -2927,7 +3433,7 @@ am-ET: priorities: high_level: ከፍተኛ low_level: ዝቅተኛ - medium_level: "መካከለኛ " + medium_level: 'መካከለኛ ' no_action_level: ድርጊት የለም priority: ቅድሚያ የመስጠት ደረጃ status: ያለበት ሁኔታ @@ -2939,7 +3445,7 @@ am-ET: assessment: ዳሰሳ ጥናት case_plan: የጉዳይ እቅድ follow_up: ክትትል - service: "አገልግሎት - 1%{ንዑስ አይነት}" + service: አገልግሎት - 1%{ንዑስ አይነት} tracing_request: label: የማፈላለግ ጥያቄ has_match: ተመሳሳይ አለው @@ -2959,8 +3465,8 @@ am-ET: creation_success: የመከታተያ ጥያቄ መዝገብ በተሳካ ሁኔታ ተፈጥሯል። update_success_queue: 'የመፈለግ ጥያቄ %{record_id}መዝገብ በተሳካ ሁኔታ ከበስተጀርባ ዘምኗል።' creation_success_queue: የመፈለግ ጥያቄ መዝገብ በተሳካ ሁኔታ ከበስተጀርባ ተፈጥሯል። - match_action: "በተሳካ ሁኔታ የተዛመደ ፍለጋ %{trace_id}እና መያዣ%{record_id}" - unmatch_action: "በተሳካ ሁኔታ ያልተዛመደ ፍለጋ %{trace_id}እና መያዣ%{record_id}" + match_action: በተሳካ ሁኔታ የተዛመደ ፍለጋ %{trace_id}እና መያዣ%{record_id} + unmatch_action: በተሳካ ሁኔታ ያልተዛመደ ፍለጋ %{trace_id}እና መያዣ%{record_id} registry_record: messages: update_success: 'የመመዝገቢያ መዝገብ %{record_id}በተሳካ ሁኔታ ዘምኗል፡፡' @@ -2992,6 +3498,7 @@ am-ET: show_tracing_request: 'የማፈላለግ ጥያቄ መታወቂያ%{short_id}' tracing_requests: የማፈላለግ ጥያቄ export: ማስተላለፍ + sort_by: ቅደም ተከተል registry_records: id: መታወቂያ label: የመመዝገቢያ መዝገቦች @@ -3006,26 +3513,56 @@ am-ET: disable_success: የመመዝገቢያ መዝገብ በተሳካ ሁኔታ እንዳይሰራ ተደርጓል። enable_dialog_title: የመዝገብ መረጃ ማስቻል enable_dialog: እሺ የሚለውን መንካት የዚህን የመመዝገቢያ መዝገብ ሁኔታ እንዲሰራ ያስችለዋል፡፡ - enable_success: "የመዝገብ መረጃ ተሳክቷል " + enable_success: 'የመዝገብ መረጃ ተሳክቷል ' + complete: ከመስመር ውጭ ይሰራል/ ዳታ ሣይበራ filter_by: by_date: በ--ቀን status: ያለበት ሁኔታ selectable_date_options: registration_date: የምዝገባ ቀን show_registry_record: 'የመመዝገቢያ መዝገብ መታወቂያ %{short_id}' - register_new_registry_record: "አዲስ የመዝገብ መረጃ " + register_new_registry_record: 'አዲስ የመዝገብ መረጃ ' export: ወጪ ማድረግ mark_for_offline: title: ያለኔትወርክ ምልክት ያድርጉ - text: "እርግጠኛ ነዎት ያለኔትወርክ በሚሆኑበት ጊዜ እነዚህን የመመዝገቢያ መዝገቦች ጥቅም ላይ ማዋል ይፈልጋሉ?" + text: እርግጠኛ ነዎት ያለኔትወርክ በሚሆኑበት ጊዜ እነዚህን የመመዝገቢያ መዝገቦች ጥቅም ላይ ማዋል ይፈልጋሉ? success: የመዝገብ መረጃዎችን የከኢንተርኔት ውጭ ለመጠቀም በተሳካ ሁኔታ ተጭነዋል + families: + id: መለያ + label: ቤተሰቦች + family_id: የቤተሰብ ቁጥር + family_number: የቤተሰብ ቁጥር + family_name: የቤተሰብ ስም + family_registration_date: የምዝገባ ቀን + family_location_current: የቤተሰብ አድራሻ + export: ወጪ ማድረግ + register_new_family: አዲስ ቤተሰብ + filter_by: + by_date: በ ቀን + status: ያለበት ሁኔታ + current_location: የቤተሰብ አድራሻ + family: + family_member: + case_id: 'የጉዳይ #መለያ ቁጥር' + update_and_return: መዝግቦ ማስቀመጥ እና ተመለስ + save_and_return: መዝግቦ ማስቀመጥ እና ተመለስ + create_case: 'አዲስ ጉዳይ + +  ፍጠር' + back_to_family_members: ወደ ቤተሰብ ዝርዝር ተመለስ + create: መፍጠር + messages: + update_success: 'ጉዳዩ %{record_id}በተሳካ ሁኔታ ተሻሽሏል።' + creation_success: 'ቤተሰብ ተፈጥሯል' + disabled: ቤተሰብ ጠፍቷል + confirm_create_case: ለዚህ ህጻን ኬዝ መክፈት ትፈልጋለህ transfer: label: ማዘዋወር agency_label: ተቋም - consent_from_individual_label: "ጉዳዩን ለማዘዋወር ከግለሰቡ ስምምነት አግኝተዋልን?" + consent_from_individual_label: ጉዳዩን ለማዘዋወር ከግለሰቡ ስምምነት አግኝተዋልን? consent_label: መዝገቦች ላይ ስምምነት አልተሰጠም - consent_override_label: "ይህን መች-የት መሰረዝ ይሻሉ?" - is_remote_label: "የሚያዘዋውሩት ወደ ሩቅ ቦታ ነውን?" + consent_override_label: ይህን መች-የት መሰረዝ ይሻሉ? + is_remote_label: የሚያዘዋውሩት ወደ ሩቅ ቦታ ነውን? location_label: መገኛ ቦታ notes_label: ማስታወሻዎች provided_consent_label: ስምምነት ቅጹ ላይ አልተሰጠም @@ -3047,9 +3584,9 @@ am-ET: false_label: 'አይደለም' true_label: 'አዎ' errors: - consent: "ስምምነት አልተሰጠም " - to_user_can_receive: "ይህ ተጠቃሚ ይህንን መዝገብ መቀበል አይችልም " - individual_consent: "የጉዳይ አያያዝ ባለሙያው ጉዳዩን ለማዘዋወር ከግለሰቡ ስምምነት አግኝቷልን?" + consent: 'ስምምነት አልተሰጠም ' + to_user_can_receive: 'ይህ ተጠቃሚ ይህንን መዝገብ መቀበል አይችልም ' + individual_consent: የጉዳይ አያያዝ ባለሙያው ጉዳዩን ለማዘዋወር ከግለሰቡ ስምምነት አግኝቷልን? no_consent_share: የጽሁፉን መችየት የማጋራት ስምምነት notes: ማስታወሻዎች recipient: ተቀባይ @@ -3060,8 +3597,8 @@ am-ET: status: accepted: ተቀባይነት ያገኘ done: ተከናውኗል - in_progress: "በሂደት ላይ " - inprogress: "በሂደት ላይ " + in_progress: 'በሂደት ላይ ' + inprogress: 'በሂደት ላይ ' rejected: ውድቅ የተደረገ revoked: የተሰረዘ type: @@ -3084,11 +3621,11 @@ am-ET: locale: አካባቢ location: መገኛ ቦታ messages: - confirmation: "ተጠቃሚውን ለመሰረዝ እርግጠኛ ነዎት? አንዴ ከተሰረዘ መመለስ አይቻልም፡፡ ተጠቃሚውን ለመሰረዝ አዎ የሚለውን ይምረጡ፡፡ " + confirmation: 'ተጠቃሚውን ለመሰረዝ እርግጠኛ ነዎት? አንዴ ከተሰረዘ መመለስ አይቻልም፡፡ ተጠቃሚውን ለመሰረዝ አዎ የሚለውን ይምረጡ፡፡ ' created: ተጠቃሚ በተሳካ ሁኔታ ተፈጥሯል failure: ችግር ተከስቷል፡፡ እባክዎ ድጋፍ ይጠይቁ፡፡ - new_confirm_html: "ፕሪሚሮን ለመጠቀም %{role}ከሚናው %{identity} ተጠቃሚውን %{username} ሊጋብዙ ነው። የማረጋገጫ ኢሜይል %{email} ይላካል። መቀጠል ይፈልጋሉ?" - new_confirm_non_identity_html: "ተጠቃሚን %{username} ከሚና ጋር %{role} ለመጋበዝ ፕሪሜሮን እንዲጠቀሙ ለማድረግ የማረጋጋጫ ኢሜል %{email} የሚላክ ይሆናል፡፡ ለመቀጠል ይፈልጋሉን ?" + new_confirm_html: ፕሪሚሮን ለመጠቀም %{role}ከሚናው %{identity} ተጠቃሚውን %{username} ሊጋብዙ ነው። የማረጋገጫ ኢሜይል %{email} ይላካል። መቀጠል ይፈልጋሉ? + new_confirm_non_identity_html: ተጠቃሚን %{username} ከሚና ጋር %{role} ለመጋበዝ ፕሪሜሮን እንዲጠቀሙ ለማድረግ የማረጋጋጫ ኢሜል %{email} የሚላክ ይሆናል፡፡ ለመቀጠል ይፈልጋሉን ? not_found: በተሰጠው መለያ ያለውን ተጠቃሚ ማግኘት አልተቻለም password_changed_successfully: የይለፍ ቃሉ በተሳካ ሁኔታ ተቀይሯል passwords_do_not_match: አሁን ካለው የይለፍ ቃል ጋር አይመሳሰልም @@ -3098,21 +3635,23 @@ am-ET: agency: ድርጅት services_help_text: አገልግሎቱን በግልጽ ካላስቀመጡ ይህ ተጠቃሚ ድርጅቱ የሚሰጠው አገልግሎት ይሰጠዋል password_setting: - label: "ፐሪሜሮ የተጠቃሚዎችን የይለፍ ቃል እንዴት ሊያስገባ ይችላል?" + label: ፐሪሜሮ የተጠቃሚዎችን የይለፍ ቃል እንዴት ሊያስገባ ይችላል? self: የይለፍ ቃል ላስገባ እችላለሁ user: ተጠቃሚው በእንኳን ደህና መጡ ኤሜይል የይለፍ ቃሉን ሊያስተካክል ይችላል - help_text: "ሚስጥር ቁጥሩን የያዘ የመረጃ አስተዳዳር ባለሙያ ለተቃሚዎች በጥንቃቄ ማስተላለፍ አለበት " + help_text: 'ሚስጥር ቁጥሩን የያዘ የመረጃ አስተዳዳር ባለሙያ ለተቃሚዎች በጥንቃቄ ማስተላለፍ አለበት ' password_reset_header: የይለፍ ቃል ለማስተካከያ ኢሜይል ላክ password_reset_text: «ላክ»ን ከነኩ ይህ ተጠቃሚ የይለፍ ቃላቸውን ዳግም የሚያስጀምሩበት የኢሜይል አገናኝ ይደርሳቸዋል። password_reset_request: የይለፍ ቃል ለማስተካከያ ኢሜይል ላክ - password: "የይለፍ ቃል " + password: 'የይለፍ ቃል ' password_confirmation: የይለፍ ቃል ማረጋገጫ phone: ስልክ position: ሃላፊነት provider_username_help: '%{domain}ምሳሌ፡ የተጠቃሚ ሰም @ ጎራ' role_id: ሚና send_mail: የማሳወቂያ ኢሜል መቀበል - user_group_unique_ids: "የተጠቃሚ ቡድን " + receive_webpush: + label: ማሳወቂያ ለመቀበል ንካ + user_group_unique_ids: 'የተጠቃሚ ቡድን ' user_name: የተጠቃሚ ስም services: አገልግሎት welcome_email: @@ -3153,17 +3692,17 @@ am-ET: body2_reset_notification: "የይለፍ ቃል ለመቀየር የሚያሳስብ ተጨማሪ ኢሜይል ሊቀበሉ ይችላሉ" body3: "ደህንነቱ የተጠበቀ እና ወቅታዊ ትግበራን የማረጋገጥ ኃላፊነት አለብዎት። ለእያንዳንዱ ስራ የትግበራ እቅዱን በሂደት ላይ ያለ እና በተጠቃሚ አስተዳደር ስትራቴጂ እና በመረጃ መጋራት ፕሮቶኮል ማጠናቀቅ አለብዎት። እንዲሁም የተፈረመ የአጠቃቀም ውል በሁሉም የተጠቃሚ ድርጅቶች ፋይል መሆኑን የማረጋገጥ ኃላፊነት አለብዎት።" user_group: - associated_agencies: "ከተጠቃሚ ቡድኖች ጋር የተያያዙ ድርጅቶች " + associated_agencies: 'ከተጠቃሚ ቡድኖች ጋር የተያያዙ ድርጅቶች ' description: መግለጫ disabled: - explanation: "ይህንን የተጠቃሚዎች ቡድን ከአገልግሎት ውጭ ካደረጉ፤ ካሁን በኋላ ወደ ተጠቃሚው መዝገብ/አካውንት መመደብ አይችሉም፡፡ " + explanation: 'ይህንን የተጠቃሚዎች ቡድን ከአገልግሎት ውጭ ካደረጉ፤ ካሁን በኋላ ወደ ተጠቃሚው መዝገብ/አካውንት መመደብ አይችሉም፡፡ ' label: ከአገልግሎት ውጭ የተደረገ messages: created: የተጠቃሚዎች ቡድን በተሳካ ሁኔታ ተፈጥሯል - updated: "የተጠቃሚዎች ቡድን በተሳካ ሁኔታ ዘምኗል " + updated: 'የተጠቃሚዎች ቡድን በተሳካ ሁኔታ ዘምኗል ' name: ስም user_groups: - label: "የተጠቃሚዎች ቡድን " + label: 'የተጠቃሚዎች ቡድን ' users: label: ተጠቃሚዎች headers: @@ -3180,5 +3719,5 @@ am-ET: admin: locations: selected_records: '1%{መረጃዉን_ይምረጡ} የተመረጠ ቦታ(ዎች) ወይም ድራሻ' - selected_all_records: "ሁሉንም የ1%{ሁሉንም_ማህደሮች} ማዛመድ የሚጠይቁ ጉዳዮች  ምረጥ/ጭ" + selected_all_records: ሁሉንም የ1%{ሁሉንም_ማህደሮች} ማዛመድ የሚጠይቁ ጉዳዮች  ምረጥ/ጭ updated: '%{updated_records} የዘመኑ ቦታ(ዎች)' diff --git a/config/locales/ar-IQ.yml b/config/locales/ar-IQ.yml index 577e17f24f..2fbdf4e8ac 100644 --- a/config/locales/ar-IQ.yml +++ b/config/locales/ar-IQ.yml @@ -4,22 +4,30 @@ ar-IQ: accepted: مقبول cancel: إلغاء connection_lost: حاليا في وضع غير متصل بالشبكة + field_mode_offline: حاليا في وضع الميدان connected: متصل + no_connection: غير متصل clear: مسح sandbox_ui: تجريبي description: الوصف form: استمارة + minimum_reportable_fields: "الحد الأدنى من الحقول القابلة للإبلاغ %{record_type}" name: اسم offline: غير متصل بالشبكة + field_mode: "وضع الميدان: %{mode}" + field_mode_on: "فعال" + field_mode_off: "غير فعال" unavailable_offline: غير متاح في وضع غير متصل بالشبكة online: متصل بالشبكة yes_label: 'نعم' - or_label: او + or_label: أو select_provider: اختر المزود select_language: أختر اللغة log_in_primero_idp: 'تسجيل الدخول باسم المستخدم%{idp_name} ' offline_submitted_changes: أنت حاليا غير متصل بالشبكة. سيتم إرسال التغييرات الخاصة بك عند الاتصال بالإنترنت مرة أخرى. updated: 'محدث ' + go: اذهب/الانتقال + select_idp_error: الرجاء تحديد مزود sync: success: "تمت مزامنة سجلات%{records} بنجاح." error: @@ -45,6 +53,7 @@ ar-IQ: save: حفظ services_from_case_creation_success: تم إنشاء سجل توفير الخدمة بنجاح. services_section_from_case: إضافة تقديم خدمة + mark_for_offline: وضع علامة لعدم الاتصال بالشبكة agencies: label: المؤسسة translations: @@ -189,6 +198,14 @@ ar-IQ: view: عرض view_flags_history: عرض التاريخ return_to_case: العودة إلى الحالة + resync_records: + id: المعرّف + record_type: نوع السجل + action: إجراء + date: التاريخ + last_attempt: المحاولة الاخيرة + create: إنشاء + update: تحديث case: label: حالة create_new_case: انشاء حالة جديدة @@ -1100,7 +1117,6 @@ ar-IQ: english_text: النص باللغة الإنجليزية field_name: اسم الحقل field_type: نوع الحقل - attachment_too_large: ' يجب ألّا يتعدّى حجم الملفّ 10 ميجابايت' file_upload_box: add_document_label: إضافة مستند add_new_document_button_text: إضافة مستند آخر @@ -1417,17 +1433,9 @@ ar-IQ: title: "8. الخدمات المقدَّمة" service: "الخدمة" count: "الأوقات المُقدَّمة" - helptext: | - يحتسب هذا المؤشر نوع الخدمة (الخدمات) المقدّمة للناجين في عملية إدارة الحالة. - نعني بالخدمة المقدمة، الخدمة التي يتمّ توفيرها من منظمة المستخدم داخليًّا، - وليس الخدمة المقدمة من خلال الإحالات إلى خدمات أخرى. average_referrals: title: "9. متوسّط الإحالات" label: "متوسط الإحالات لكلّ حالة" - helptext: | - يحتسب هذا المؤشر متوسط عدد الإحالات لكلّ حالة مسجلة (لجميع أنواع الخدمات) - عبر كلّ الحالات. يتضمّن الإحالات المسجّلة في علامة تبويب الحالة، وليس فقط الإحالات التي تمّت - من خلال المنصّة. referrals_per_service: title: "الإحالات لكلّ خدمة" average_followup_meetings_per_case: @@ -1437,30 +1445,14 @@ ar-IQ: يحتسب هذا المؤشر متوسط عدد اجتماعات المتابعة التي أجريت لكلّ حالة نشطة من قبل كلّ إختصاصي إجتماعي على المنصة. يتمّ اجتماع المتابعة بين الإختصاصي الإجتماعي والناجية بعد المقابلة الأوّليّة / الإفصاح الأولي. - goal_progress_per_need: - title: "11. التقدّم المُحرز نحو الأهداف" - need: "الحاجة" - safety: "السلامة" - health: "الصحة" - psychosocial: "نفسي اجتماعي" - justice: "العدالة" - other: "أخرى" - helptext: | - يقيس هذا المؤشر النسبة المئوية للحالات التي تمّ تحقيق أهدافها - أو التي لا تزال قيد التنفيذ بحسب نوع الاحتياجات (السلامة ، الصحة ، النفسية الاجتماعية، القانونية / العدالة). - يتم إبلاغ هذا المؤشر من خلال قسم "التقدّم المُحرز نحو الأهداف" ضمن قسم "المتابعة" - في نموذج خطة العمل. time_from_case_open_to_close: - title: "12. الوقت بين فتح الحالة إلى إغلاق الحالة" time: "الوقت" percent: "نسبة الحالات المئوية" helptext: "يقيس هذا المؤشر المدة التي تظلّ فيها الحالات مفتوحة، والمدة التي تستغرقها عملية إدارة الحالة\nمن الإبلاغ الأوّلي لمنظمة المستخدم حتى إغلاق الحالة. \nيتمّ تقسيم المدة الزمنية حسب الإطار الزمني التالي: أقل من شهر واحد ؛ بين 1 و 3 أشهر ؛ \nبين3-6 أشهر ؛ أكثر من 6 أشهر.\n" case_closure_rate: - title: "13. معدّل إغلاق الحالة" reporting_site: "موقع الإبلاغ" helptext: "يقيس هذا المؤشر عدد الحالات التي يتمّ إغلاقها شهريًا في كلّ موقع إبلاغ.\nيُشير موقع الإبلاغ إلى الموقع الذي تقدم فيه منظمة المستخدم الخدمات \nو حيث تم الإبلاغ عن الحالة إلى مزود الخدمة.\n" client_satisfaction_rate: - title: "14. معدّل رضا العميل" label: "رضا العميل" helptext: | يقيس هذا المؤشر النسبة المئوية للناجين الذين أكملوا استبيان آراء العملاء @@ -1468,12 +1460,9 @@ ar-IQ: يتمّ إحتساب هذا المؤشر من خلال استكمال نموذج استبيان آراء العميل على +GBVIMS من قبل موظف مختلف عن الإختصاصي الإجتماعي الذي قدّم الخدمة للناجية. supervisor_to_caseworker_ratio: - title: "15. عدد الإختصاصيين الإجتماعيين لكلّ مشرف." label: "عدد الإختصاصيين الإجتماعيين لكلّ مشرف" helptext: "يعكس هذا المؤشر عدد الإختصاصيين الإجتماعيين الذين يشرف عليهم المشرف: ويُعرف بعدد الإختصاصيين الإجتماعيين لكلّ مشرف. \nيعتمد هذا الحساب على الأدوار المخصّصة من النظام على المنصّة.\n" case_load: - title: "16. كمية الحالات" - case_load: "كميّة الحالات" percent: "النسبة المئوية للإختصاصيين الإجتماعيين العاملين على حالات" 10cases: "أقل من 10 حالات" 20cases: "11 - 20 حالة" @@ -1858,7 +1847,6 @@ ar-IQ: services_section_from_case: إضافة تقديم خدمة لحالة مستخدم آخر specific_roles: الوصول لقائمة أدوار المستخدم المحددة sync_external: المزامنة مع نظام إدارة معلومات خارجي - sync_mobile: مزامنة مع جهاز المحمول system: نظام tracing_request: طلب التتبع transfer: يمكن استخدامها للتحويل @@ -1889,10 +1877,8 @@ ar-IQ: label: متوسّط الإحالات kpi_case_closure_rate: explanation: القدرة على معرفة عدد الحالات التي أُغلقت شهريًا في كلّ موقع. - label: معدّل إغلاق الحالة kpi_case_load: explanation: القدرة على معرفة متوسط عدد الحالات المفتوحة لكلّ إختصاصي إجتماعي. - label: كميّة الحالات kpi_client_satisfaction_rate: explanation: القدرة على معرفة معدّل الناجين الذين أكملوا استبان آراء العملاء وكانوا راضين بالنسبة إلى كلّ حالة يمكن للمستخدم الوصول إليها. label: معدّل رضا العميل @@ -1925,7 +1911,6 @@ ar-IQ: label: عدد الإختصاصيين الإجتماعيين لكلّ مشرف. kpi_time_from_case_open_to_close: explanation: القدرة على معرفة مدّة الإبقاء على الحالة مفتوحة بالنسبة إلى كلّ الحالات التي يمكن للمستخدم الوصول إليها. - label: الوقت بين فتح الحالة وإغلاقها label: مؤشّر الأداء الرئيس agency: actions: @@ -2102,9 +2087,6 @@ ar-IQ: sync_external: explanation: القدرة على مزامنة سجلّ مع نظام إدارة معلومات خارجي label: المزامنة مع نظام إدارة معلومات خارجي - sync_mobile: - explanation: يسمح هذا الإذن بشكل عام للمستخدم باستخدام تطبيق الهاتف المحمول. أولاً ، يسمح للمستخدم بمشاهدة إجراءات "تحديد للهاتف الجوال" و "ازالة التحديد للهاتف الجوال"، والتي تظهر في قائمة الحالات وصفحات عرض الحالة. يشير تحديد الحالة للجوال إلى أنه يجب مزامنة المعلومات الخاصة بهذه الحالة بين جهاز المستخدم المحمول والتطبيق على الإنترنت، بينما يؤدي إلغاء تحديد الحالة للهاتف الجوال إلى إيقاف هذه المزامنة. بالإضافة إلى ذلك، لا يمكن للمستخدمين الذين ليس لديهم هذا الإذن مزامنة هواتفهم المحمولة مع التطبيق على الإنترنت بشكل عام، ممّا يعني أنه لا يمكنهم استخدام تطبيق الهاتف لإدارة الحالات. - label: مزامنة مع الهاتف المحمول transfer: explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الحالي إلى أي مستخدم في النظام مع إمكانية تلقّي عمليات التحويل. لا يتغير مالك سجل الحالة حتى "يقبل" مستلِم التحويل هذا التحويل. ولكن، إذا "رفض" المستلِم التحويل، يفقد بذلك إمكانية الوصول إلى الحالة، وتبقى الحالة بإسم مالك السجل الأصلي. label: تحويل @@ -2169,7 +2151,6 @@ ar-IQ: explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام الخدمات لكلّ من الإختصاصيين الإجتماعيين. label: مهام الخدمات المتأخرة dash_case_incident_overview: - explanation: . label: لمحة عامّة - حالاتي/حوادثي dash_cases_by_social_worker: explanation: الجدول الذي يوضح كيفية إدارة العدد الإجمالي للحالات المفتوحة وعدد الحالات الجديدة التي يديرها كل مستخدم في مجموعات المستخدمين الحالية للمستخدم. يمثّل كل صف مستخدمًا من مجموعات المستخدمين الخاصة بالمستخدم الحالي ، بينما يمثل "الإجمالي" و "الجديد" عمودين. @@ -2219,9 +2200,6 @@ ar-IQ: dash_national_admin_summary: explanation: يظهر إجمالي الحالات المفتوحة في النظام ، وعدد الحالات الجديدة التي تم إنشاؤها في الأسبوعين الماضيين ، وعدد الحالات التي تم إغلاقها في الأسبوعين الماضيين. label: ملخص المسؤول - view_protection_concerns_filter: - explanation: يسمح للمستخدم برؤية عوامل تصفية المخاوف المتعلّقة بالحماية في صفحة قائمة الحالات. - label: رؤية عوامل تصفية المخاوف المتعلّقة بالحماية في صفحة قائمة الحالات. view_response: explanation: لكلّ نوع من أنواع الاستجابة، يوضح عدد الحالات في كل مستوى من مستويات الخطورة التي لديها خدمات على وشك الإنتهاء أو متأخّرة. label: عرض الاستجابات @@ -2246,7 +2224,6 @@ ar-IQ: explanation: 'يقيّد وصول المستخدم إلى نماذج الحالات ويحدّ من المعلومات التي يمكن للمستخدم رؤيتها في الحادثة. مثلاً، إذا كان للمستخدم حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج فقط. إذا كان المستخدم الحالي لديه وصول محدود إلى النموذج ولديه القدرة على إدارة تضبيطات النموذج، فإن تقييد وصوله إلى النموذج يحدّ أيضًا النماذج التي يمكنه تضبيطها. ملاحظة: إذا لم يتمّ تحديد أي نموذج، فهذا يعني أنّ الدور لديه حق الوصول إلى جميع نماذج الحالات.' label: نماذج - حالة incident: - explanation: 'يقيّد وصول المستخدم إلى النماذج في طلبات التتبّع ويحدّ من المعلومات التي يمكن للمستخدم رؤيتها في الحادثة. مثلاً، إذا كان للمستخدم حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج فقط. إذا كان المستخدم الحالي لديه وصول محدود إلى النموذج ولديه القدرة على إدارة تضبيطات النموذج، فإن تقييد وصوله إلى النموذج يحدّ أيضًا النماذج التي يمكنه تضبيطها. ملاحظة: إذا لم يتمّ تحديد أي نموذج، فهذا يعني أنّ الدور لديه حق الوصول إلى جميع النماذج للحوادث.' label: نماذج - حوادث tracing_request: explanation: 'يقيّد وصول المستخدم إلى النماذج في طلبات التتبّع ويحدّ من المعلومات التي يمكن للمستخدم رؤيتها في طلب التتبّع. مثلاً، إذا كان للمستخدم حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج فقط. إذا كان المستخدم الحالي لديه وصول محدود إلى النموذج ولديه القدرة على إدارة تضبيطات النموذج، فإن تقييد وصوله إلى النموذج يحدّ أيضًا النماذج التي يمكنه تضبيطها. ملاحظة: إذا لم يتمّ تحديد أي نموذج، فهذا يعني أنّ الدور لديه حق الوصول إلى جميع النماذج لطلبات التتبّع.' @@ -2530,7 +2507,6 @@ ar-IQ: display: عرض النتائج المطابقة المحتملة لـ %{type} %{id} reassign: multiple_error: حدث خطأ. لم يتم تعيين الحالة (الحالات) %{select_records}. - multiple_successfully: 'تم تعيين الحالة (الحالات) %{select_records} بنجاح' notes_label: ملاحظات successfully: تمت إعادة التعيين بنجاح user_mandatory_label: يجب إدخال إسم المستلِم @@ -2762,8 +2738,6 @@ ar-IQ: success: تمّ التحويل بنجاح transfer_label: هل تريد التحويل على أي حال؟ user_mandatory: المستلم مطلوب - transfer_assignment: - title: عمليات التحويل و التعيينات transition: agency_label: وكالة assigned_by: تعيين من قِبَل diff --git a/config/locales/ar-JO.yml b/config/locales/ar-JO.yml index b1be4d2a0d..e1f3aec777 100644 --- a/config/locales/ar-JO.yml +++ b/config/locales/ar-JO.yml @@ -4,7 +4,9 @@ ar-JO: accepted: مقبول cancel: إلغاء connection_lost: غير متصل بالشبكة الان + field_mode_offline: حاليا بوضع الميدان connected: متصل + no_connection: غير متصل clear: مسح sandbox_ui: تجريبي description: الوصف @@ -12,20 +14,25 @@ ar-JO: minimum_reportable_fields: "الحد الأدنى من الحقول القابلة للإبلاغ %{record_type}" name: الاسم offline: غير متصل + field_mode: "وضع الميدان: %{mode}" + field_mode_on: "فعال" + field_mode_off: "غير فعال" unavailable_offline: غير متوفر مفصول online: متصل yes_label: 'نعم' - or_label: او + or_label: أو select_provider: اختر مزود select_language: اختر اللغة log_in_primero_idp: الدخول %{idp_name} بالحساب offline_submitted_changes: أنت حاليا غير متصل. سيتم إرسال التغييرات الخاصة بك عند عودة الاتصال مرة أخرى updated: محدث + go: اذهب + select_idp_error: الرجاء تحديد المزود sync: - success: "%{records}تمت مزامنة السجلات بنجاح." + success: "%{records} تمت مزامنة السجلات بنجاح." error: - create: فشل في انشاء%{record_type} . يرجى الاتصال بالدعم. - update: فشل الى%{record_type}التحديث%{short_id}. يرجى الاتصال بالدعم. + create: فشل في انشاء %{record_type} . يرجى الاتصال بالدعم. + update: فشل الى %{record_type} التحديث %{short_id} . يرجى الاتصال بالدعم. actions: approvals: المصادقات button: إجراءات @@ -46,6 +53,7 @@ ar-JO: save: حفظ services_from_case_creation_success: تم إنشاء سجل توفير الخدمة بنجاح services_section_from_case: إضافة تقديم خدمة + mark_for_offline: وضع علامة على عدم الاتصال agencies: label: مؤسسة translations: @@ -58,7 +66,7 @@ ar-JO: exclude_agency_from_lookups: استبعد هذه المؤسسة من عمليات البحث وعوامل التصفية exclude_agency_from_lookups_help: تحقق من هذه المؤسسة ان ليس لديها مستخدمون (على سبيل المثال ، تمت إضافة المؤسسة لكي يتم تطبيق الشعار على الصادرات label: مؤسسة - logo_enabled: أظهر شعار المؤسسة على النظام؟ + logo_enabled: عرض شعار المؤسسة على النظام؟ logo_enabled_help: أظهر شعار المؤسسة على النظام؟ logo_icon: أيقونة الشعار logo_icon_help: سيظهر هذا بأحجام شاشات صغيرة والأجهزة اللوحية والهواتف. هذا يجب ان يكون مربع. @@ -101,9 +109,9 @@ ar-JO: bulk_export: file_name: ملف record_type: نوع - retry: هذا النقل غير صحيح. أرجو حاول إعادة عمل عملية النقل الخاصة بك. + retry: عمليّة التصدير هذه غير صالحة. الرجاء محاولة إعادة عملية التصدير. started_on: 'بدء ' - status: حالة + status: الوضع form_export: label: تصدير شكل النموذج include_hidden: تضمين النماذج والحقول المخفية؟ @@ -137,16 +145,16 @@ ar-JO: create_new_record: إنشاء %{model} جديد delete: حذف disable: تعطيل - disable_photo_wall: تعطيل photo wall + disable_photo_wall: تعطيل جدار الصور done: تمت download: تحميل edit: تعديل edit_subform: تعديل النموذج الفرعي enable: تفعيل - enable_photo_wall: تفعيل photo wall + enable_photo_wall: تفعيل جدار الصور export: تصدير - filter: تطبيق عامل التصفية - filter_clear: مسح عوامل التصفية + filter: تطبيق التصفية + filter_clear: مسح التصفيات filter_label: 'عامل التصفية:' filter_restore: استعادة ضبط النظام find_tracing_match: ايجاد أثر التطابق @@ -182,7 +190,7 @@ ar-JO: sort_by_tr: تتبع الطلبات sync: مزامنة submit: إرسال - transfer: نقل + transfer: نقل حالة unflag_model: إزالة العلامة %{model} unflag_model_history: تاريخ العلامه %{model} unmark_for_mobile: إزالة علامة للمحمول @@ -190,20 +198,39 @@ ar-JO: view: عرض view_flags_history: عرض التاريخ return_to_case: العودة للحالة + resync_records: + id: رقم الحالة + record_type: نوع السجل + action: إجراء + date: تاريخ + last_attempt: اخر محاولة + create: انشاء + update: تحديث + resync: إرسال case: label: الحالة create_new_case: انشاء حالة جديدة + add_new: أضف جديد + back_to_case: العودة إلى الحالة + back_to_results: العودة إلى النتائج + back_to_search: العودة الى البحث + search_by: البحث ب + search_for: البحث عن %{record_type} + results: النتائج + details: تفاصيل + select: اختار + deselect: ازالة الاختيار enter_id_number: قم بإدخال رقم الهوية الشخصية/الوثيقة التعريفية لسجل موجود - id_search_no_results: لا يوجد تطابق في النظام مع "%{search_query}". الرجاء إنشاء سجل جديد + id_search_no_results: لا يوجد تطابق في النظام مع "%{search_query}". الرجاء إنشاء سجل جديد messages: disabled: الحالة معطلة update_success: 'تم تحديث الحالة %{record_id} بنجاح.' - update_success_queue: 'تم تحديث الحالة%{record_id} بنجاح في الخلفية' + update_success_queue: 'تم تحديث الحالة %{record_id} بنجاح في الخلفية.' creation_success: 'تم إنشاء سجل الحالة بنجاح.' creation_success_queue: 'تم إنشاء سجل الحالة بنجاح في الخلفية.' already_matched: تم مطابقة هذا المستعلم مع حالتك already_matched_not_current_case: توجد حالة في النظام مطابقة لهذا المستفسر - not_found_case: لا يوجد حالة مطابقة, %{search_value}يرجى إنشاء حالة جديدة + not_found_case: لا يوجد حالة مطابقة, %{search_value} يرجى إنشاء حالة جديدة introductory_sentence: يرجى تحديد موافقة الفرد على تلقي خدمات إدارة الحالة وتخزين بياناته في النظام consent_agreements_required: الرجاء تحديد خيار واحد من الموافقات على الأقل legitimate_basis_required: الرجاء تحديد خيار واحد على الأقل من تصنيفات الأساس المشروعة. @@ -217,7 +244,7 @@ ar-JO: workflow: assessment: تقييم case_plan: خطة الحالة - closed: مغلق + closed: مغلقة created_on: تم تسجيل حالة جديدة في in_progress: جاري new: جديد @@ -229,8 +256,8 @@ ar-JO: label: الحوادث المرتبطة activity_log: label: سجل النشاطات - accepted_transfer: '%{to}قبول نقل%{record_type}%{record_id}من%{from}' - rejected_transfer: '%{to}رفض نقل%{record_type}%{record_id}من%{from}' + accepted_transfer: '%{to} قبول نقل %{record_type} %{record_id} من %{from}' + rejected_transfer: '%{to} رفض نقل %{record_type} %{record_id} من %{from}' cases: action_plan: خطة العمل age: العمر @@ -242,12 +269,12 @@ ar-JO: approval_radio_accept: موافق approval_radio_reject: عدم موافقة approval_select: النموذج ل - approved_success_action_plan: '%{approval_label}تمت المصادقة' - approved_success_assessment: '%{approval_label}تمت المصادقة' - approved_success_bia: '%{approval_label}تمت المصادقة' - approved_success_case_plan: '%{approval_label}تمت المصادقة' - approved_success_closure: 'تمت المصادقة%{approval_label}' - approved_success_gbv_closure: 'تمت المصادقة%{approval_label}' + approved_success_action_plan: 'تمت المصادقة على %{approval_label}' + approved_success_assessment: 'تمت المصادقة على %{approval_label}' + approved_success_bia: 'تمت المصادقة على %{approval_label}' + approved_success_case_plan: 'تمت المصادقة على %{approval_label}' + approved_success_closure: 'تمت المصادقة على %{approval_label}' + approved_success_gbv_closure: 'تمت المصادقة على %{approval_label}' assessment: تقييم case_opening_date: تاريخ فتح الحالة case_plan: خطة الحالة @@ -257,6 +284,7 @@ ar-JO: close_dialog_title: إغلاق الحالة close_success: تم إغلاق الحالة بنجاح closure: إغلاق + complete: متاح بدون الاتصال بالانترنت date_of_birth: تاريخ الميلاد disable_dialog: سيؤدي النقر على موافق إلى تغيير وضع هذه الحالة إلى معطل disable_dialog_title: تعطيل الحالة @@ -265,9 +293,13 @@ ar-JO: enable_dialog_title: تفعيل الحالة enable_success: تم تفعيل الحالة بنجاح export: تصدير ملف + mark_for_offline: + title: وضع علامة على عدم الاتصال + text: هل أنت متأكد أنك تريد وضع علامة على هذه الحالات لاستخدامها عندما تكون غير متصل؟ + success: تم وضع علامة بنجاح على الحالات في حال عدم الاتصال بالانترنت filter_by: 3month_inactivity: لمدة أكثر من 3 أشهر - action_plan: خطة عمل + action_plan: خطة الإستجابة age_0_5: 0-5 age_12_17: 12-17 age_18_more: 18+ @@ -307,12 +339,10 @@ ar-JO: open: مفتوح other: اخرى photo: صورة - photo_label: هل لديك صورة؟ + photo_label: صورة متوفّرة؟ protection_concerns: شؤون الحماية protection_status: حالة الحماية - record_state: 'حالة السجل - -  ' + record_state: حالة السجل referred_cases: الحالات التي تم إحالتها لي registration_date: تاريخ التسجيل risk_level: درجة الخطورة @@ -331,7 +361,7 @@ ar-JO: hide_name_error: حدث خطأ عند حفظ التغييرات. الرجاء المحاولة مرة أخرى. id: مُعرف# label: الحالات - my_filters: عوامل التصفية الخاصة بي + my_filters: التصفيات الخاصة بي name: الاسم notes_dialog_title: اضافة ملاحظة notes_form_notes: ملاحظات @@ -356,42 +386,42 @@ ar-JO: referral_rejected_success: تم رفض الإحالة register_new_case: حالة جديدة registration_date: تاريخ التسجيل - rejected_success_action_plan: '%{approval_label}المصادقة مرفوضة' - rejected_success_assessment: '%{approval_label}المصادقة مرفوضة' - rejected_success_bia: 'المصادقة مرفوضة' - rejected_success_case_plan: 'المصادقة مرفوضة' - rejected_success_closure: 'المصادقة مرفوضة' - rejected_success_gbv_closure: 'المصادقة مرفوضة' + rejected_success_action_plan: 'المصادقة على %{approval_label} مرفوضة' + rejected_success_assessment: 'المصادقة على %{approval_label} مرفوضة' + rejected_success_bia: 'المصادقة على %{approval_label} مرفوضة' + rejected_success_case_plan: 'المصادقة على %{approval_label} مرفوضة' + rejected_success_closure: 'المصادقة على %{approval_label} مرفوضة' + rejected_success_gbv_closure: 'المصادقة على %{approval_label} مرفوضة' reopen_dialog: سيؤدي النقر فوق "موافق" إلى تغيير وضع هذه الحالة إلى مفتوح reopen_dialog_title: إعادة فتح الحالة reopen_success: تمت إعادة فتح الحالة بنجاح request_approval_failure: حدث خطأ ، يرجى الاتصال بالدعم. request_approval_select: طلب المصادقة على - request_approval_success_action_plan: طلب المصادقة على%{approval_label} نموذج - request_approval_success_assessment: طلب المصادقة على%{approval_label} النموذج. - request_approval_success_case_plan: طلب المصادقة على%{approval_label} نموذج - request_approval_success_closure: طلب المصادقة على%{approval_label} نموذج - request_approval_success_gbv_closure: طلب المصادقة على%{approval_label} نموذج + request_approval_success_action_plan: 'طلب المصادقة على نموذج %{approval_label} ' + request_approval_success_assessment: طلب المصادقة على نموذج %{approval_label} + request_approval_success_case_plan: طلب المصادقة على نموذج %{approval_label} + request_approval_success_closure: طلب المصادقة على نموذج %{approval_label} + request_approval_success_gbv_closure: طلب المصادقة على نموذج %{approval_label} request_approval_type_of_case_plan: نوع المصادقة على خطة الحالة request_approve_action_plan: المصادقة على خطة العمل؟ request_approve_bia: المصادقة على التقييم؟ request_approve_case_plan: المصادقة على خطة الحالة؟ request_approve_closure: المصادقة على الإغلاق؟ request_approve_gbv_closure: المصادقة على إغلاق العنف القائم على النوع الاجتماعي؟ - revoke_failure: حدث خطأ أثناء إبطال%{transition_type}، يرجى الاتصال بالدعم. - revoke_message: بالنقر على "إبطال" ، ستزيل وصول%{transition_type} المستلم إلى الحالة. - revoke_success_message: أُلغيت القضية.%{case_id}%{transition_type}%{recipient_username} + revoke_failure: حدث خطأ أثناء إبطال %{transition_type}، يرجى الاتصال بالدعم. + revoke_message: بالنقر على "إبطال" ، ستزيل وصول %{transition_type} المستلم إلى الحالة. + revoke_success_message: الحالة %{case_id} %{transition_type} ل %{recipient_username} تم الغاؤها. save_filter: حفّظ - selected_all_records: حدد جميع%{total_records} الحالات التي تطابق هذا الاستعلام. - selected_records: '%{select_records}حالة (حالات) محددة' + selected_all_records: حدد جميع %{total_records} الحالات التي تطابق هذا الاستعلام. + selected_records: '%{select_records} حالة (حالات) محددة' sex: الجنس - show_case: 'رقم الحالة:%{short_id}' + show_case: 'رقم الحالة: %{short_id}' social_worker: العامل الاجتماعي status: الوضع summary: label: ملخص find_match: جد التطابق - matched_trace: '%{trace_id}مطابق' + matched_trace: '%{trace_id} مطابق' cannot_find_matches: لا يمكن العثور على تطابقات. لم يتم الحصول على الموافقة من هذه الحالة للكشف عن المعلومات لأغراض التعقب. matched: مطابق fields: @@ -413,25 +443,26 @@ ar-JO: label: اطلع على رغبات الطفل survivor_code: رمز الناجي transfer_accepted: بالنقر فوق "قبول" ، فإنك تقبل المسؤولية عن هذه الحالة ؛ بمجرد النقر فوق "قبول" ، ستصبح مالك السجل في النظام. - transfer_managed_user_accepted: إذا قمت بالنقر فوق "قبول" ،%{transitioned_to}ستصبح مسؤولاً عن هذه الحالة ؛ بمجرد النقر فوق "قبول" ، %{transitioned_to}ستصبح مالك السجل في النظام. - transfer_managed_user_rejected: 'بالنقر فوق "رفض" ، فإنك تشير إلى أنك%{transitioned_to} غير مستعد لقبول المسؤولية عن هذه الحالة في الوقت الحالي. الرجاء إدخال سبب رفضك لهذه الحالة ؛ بمجرد النقر فوق "رفض" %{transitioned_to}لن تتمكن من الوصول إلى سجل هذه الحالة ' - transfer_accepted_rejected: تم رفض نقل الحالة%{record_id} + transfer_managed_user_accepted: إذا قمت بالنقر فوق "قبول" ،%{transitioned_to} ستصبح مسؤولاً عن هذه الحالة ؛ بمجرد النقر فوق "قبول" ، %{transitioned_to} ستصبح مالك السجل في النظام. + transfer_managed_user_rejected: 'بالنقر فوق "رفض" ، فإنك تشير إلى أنك %{transitioned_to} غير مستعد لقبول المسؤولية عن هذه الحالة في الوقت الحالي. الرجاء إدخال سبب رفضك لهذه الحالة ؛ بمجرد النقر فوق "رفض" %{transitioned_to} لن تتمكن من الوصول إلى سجل هذه الحالة ' + transfer_accepted_rejected: تم رفض نقل الحالة %{record_id} transfer_accepted_success: تم قبول نقل الحالة بنجاح. transfer_reject_reason_label: سبب الرفض transfer_rejected: 'بالنقر فوق "رفض" ، فإنك تشير إلى أنك غير مستعد لقبول المسؤولية عن هذه الحالة في الوقت الحالي. الرجاء إدخال سبب رفضك لهذه الحالة ؛ بمجرد النقر فوق "رفض" لن تتمكن من الوصول إلى سجل هذه الحالة ' view_name: عرض الاسم + sort_by: ترتيب حسب change_logs: filters: form: نموذج field: حقل - add_subform: '%{subform_name}%{short_id}تمت إضافة إدخال النموذج الفرعي ' - changes_subform: '%{subform_name}التغييرات على النموذج الفرعي ' + add_subform: 'تمت إضافة إدخال نموذج فرعي "%{subform_name} " رقم # %{short_id}' + changes_subform: 'تعديلات على النموذج الفرعي "%{subform_name}"' create: سجل منشأ - deleted_subform: '%{subform_name}%{short_id}تمت إزالة إدخال النموذج الفرعي' + deleted_subform: 'إزالة إدخال نموذج فرعي "%{subform_name}" رقم #%{short_id}' label: 'سجل التغيير ' see_details: ' اظهار التفاصيل' - change: 'من%{from_value}الى%{to_value}' - updated_subform: 'تم تحديث%{subform_name} إدخال النموذج الفرعي%{short_id}' + change: 'من "%{from_value}" إلى "%{to_value}"' + updated_subform: 'تحديث إدخال نموذج فرعي "%{subform_name}" رقم #%{short_id}' update_subform: 'نموذج فرعي %{subform_name} محدث' from: من to: الى @@ -544,19 +575,114 @@ ar-JO: cases_by_workflow: الحالات حسب سريان العمل cases_this_week: الحالات هذا الأسبوع cases_to_assign: الحالات منتظرة التعيين - closed: أغلقت + closed: مغلقة closed_last_week: مغلقه (الاسبوع الماضي) closed_this_week: مغلقه (الاسبوع الحالي) comprehensive_need_intervention: تدخل شامل + count_new_bia_approvals: + zero: '%{stat} موافقات على %{stat_type} جديدة' + one: '%{stat} موافقة على %{stat_type} جديد' + two: '%{stat} موافقات على %{stat_type} جديدة' + few: '%{stat} موافقات على %{stat_type} جديدة' + many: '%{stat} موافقات على %{stat_type} جديدة' + other: '%{stat} موافقات على %{stat_type} جديدة' + count_new_case_plan_approvals: + zero: '%{stat} موافقات على %{stat_type} جديدة' + one: '%{stat}موافقة %{stat_type}جديدة' + two: '%{stat} موافقات على %{stat_type} جديدة' + few: '%{stat} موافقات على %{stat_type} جديدة' + many: '%{stat} موافقات على %{stat_type} جديدة' + other: '%{stat} موافقات على %{stat_type} جديدة' + count_new_closure_approvals: + zero: '%{stat} موافقة على %{stat_type} جديدة' + one: '%{stat} موافقة على %{stat_type} جديدة' + two: '%{stat} موافقة على %{stat_type} جديدة' + few: '%{stat} موافقات على %{stat_type} جديدة' + many: '%{stat} موافقات على %{stat_type} جديدة' + other: '%{stat} موافقات على %{stat_type} جديدة' + count_pending_approval_total: + zero: لديك %{stat} موافقات %{stat_type} قيد الانتظار + one: لديك %{stat} موافقات %{stat_type} قيد الانتظار + two: لديك %{stat} موافقات %{stat_type} قيد الانتظار + few: لديك %{stat} موافقات %{stat_type} قيد الانتظار + many: لديك %{stat} موافقات %{stat_type} قيد الانتظار + other: لديك %{stat} موافقات %{stat_type} قيد الانتظار + count_pending_transfers: + zero: لديك %{stat} تعيينات معلقة + one: لديك %{stat} تعيينات معلقة + two: لديك %{stat} تعيينات معلقة + few: لديك %{stat} تعيينات معلقة + many: لديك %{stat} تعيينات معلقة + other: لديك %{stat} طلب نقل معلق + count_records_new: + zero: و %{stat} حالات جديدة + one: و %{stat} حالات جديدة + two: و %{stat} حالات جديدة + few: و %{stat} حالات جديدة + many: و %{stat} حالات جديدة + other: و %{stat} حالات جديدة + count_records_total: + zero: 'اجمالي الحالات لديك %{stat} ' + one: 'اجمالي الحالات لديك %{stat} ' + two: 'اجمالي الحالات لديك %{stat} ' + few: 'اجمالي الحالات لديك %{stat} ' + many: 'اجمالي الحالات لديك %{stat} ' + other: 'اجمالي الحالات لديك %{stat} ' + count_referrals_new: + zero: 'و %{stat} إحالات جديدة ' + one: 'و %{stat} إحالات جديدة ' + two: 'و %{stat} إحالات جديدة ' + few: 'و %{stat} إحالات جديدة ' + many: 'و %{stat} إحالات جديدة ' + other: 'و %{stat} إحالات جديدة ' + count_referrals_total: + zero: 'إجمالي الإحالات لديك %{stat} ' + one: 'إجمالي الإحالات لديك %{stat} ' + two: 'إجمالي الإحالات لديك %{stat} ' + few: 'إجمالي الإحالات لديك %{stat} ' + many: 'إجمالي الإحالات لديك %{stat} ' + other: 'إجمالي الإحالات لديك %{stat} ' + count_rejected_approval_total: + zero: و %{stat} موافقات على %{stat_type} مرفوضة + one: و %{stat} موافقات على %{stat_type} مرفوضة + two: و %{stat} موافقات على %{stat_type} مرفوضة + few: و %{stat} موافقات على %{stat_type} مرفوضة + many: و %{stat} موافقات على %{stat_type} مرفوضة + other: و %{stat} موافقات على %{stat_type} مرفوضة + count_rejected_transfers: + zero: و%{stat} نقل حالات مرفوضة + one: و%{stat} نقل حالة مرفوضة + two: و%{stat} نقل حالات مرفوضة + few: و%{stat} نقل حالات مرفوضة + many: و%{stat} نقل حالات مرفوضة + other: و%{stat} نقل حالات مرفوضة + count_risk_level_new: + zero: و %{stat} حالات ذات خطورة %{stat_type} جديدة + one: و %{stat} حالات ذات خطورة %{stat_type} جديدة + two: و %{stat} حالات ذات خطورة %{stat_type} جديدة + few: و %{stat} حالات ذات خطورة %{stat_type} جديدة + many: و %{stat} حالات ذات خطورة %{stat_type} جديدة + other: و %{stat} حالات ذات خطورة %{stat_type} جديدة + count_risk_level_total: + zero: 'لديك %{stat} حالة %{stat_type} ذات خطورة ' + one: 'لديك %{stat} حالة %{stat_type} ذات خطورة ' + two: 'لديك %{stat} حالة %{stat_type} ذات خطورة ' + few: 'لديك %{stat} حالة %{stat_type} ذات خطورة ' + many: 'لديك %{stat} حالة %{stat_type} ذات خطورة ' + other: 'لديك %{stat} حالة %{stat_type} ذات خطورة ' + count_waiting_for_acceptance_transfers: لديك %{stat} نقل حالة بإنتظار موافقتك current_owner: المالك الحالي dash_case_incident_overview: حالاتي dash_group_overview: حالات مجموعاتي - dash_shared_from_my_team: تم مشاركتها مع مجموعتي - dash_shared_with_me: تم مشاركتها معي - dash_shared_with_my_team: تم مشاركتها مع مجموعتي - dash_shared_with_my_team_overview: تم مشاركته مع فريقي (نظرة عامة) - dash_shared_with_others: مشترك مع الآخرين + dash_shared_from_my_team: حالات مشاركة من مجموعتي مع المجموعات الأخرى + dash_shared_with_me: حالات مشاركة معي + dash_shared_with_my_team: حالات مشاركة مع مجموعتي + dash_shared_with_my_team_overview: حالات مشاركة مع مجموعتي (نظرة عامة) + dash_shared_with_others: حالات مشاركة مع مجموعات أخرى dash_national_admin_summary: ملخص المسؤول + dash_violations_category_verification_status: إجمالي عدد الحوادث لكل حالة تحقق + dash_violations_category_region: إجمالي عدد الحوادث التي تم التحقق منها لكل منطقة + dash_perpetrator_armed_force_group_party_names: إجمالي عدد الحوادث لكل مسيء date: التاريخ date_of_incident: تاريخ الحادثة date_of_interview: تاريخ المقابلة @@ -582,6 +708,27 @@ ar-JO: link_see_all: عرض الكل low_level: متدني low_risk: أولوية منخفضة + manager_count_closed_total: + zero: و %{stat} حالة مغلقة + one: و %{stat} حالة مغلقة + two: و %{stat} حالات مغلقة + few: و %{stat} حالات مغلقة + many: و %{stat} حالة مغلقة + other: و %{stat} حالات مغلقة + manager_count_open_total: + zero: 'لديك %{stat} حالة مفتوحة ' + one: 'لديك %{stat} حالة مفتوحة ' + two: 'لديك %{stat} حالات مفتوحة ' + few: 'لديك %{stat} حالات مفتوحة ' + many: 'لديك %{stat} حالة مفتوحة ' + other: 'لديك %{stat} حالات مفتوحة ' + manager_transfers_totals: + zero: 'لديك %{stat} %{stat_type} نقل حالة ' + one: 'لديك %{stat} %{stat_type} نقل حالة ' + two: 'لديك %{stat} %{stat_type} نقل حالة ' + few: 'لديك %{stat} %{stat_type} نقل حالة ' + many: 'لديك %{stat} %{stat_type} نقل حالة ' + other: 'لديك %{stat} %{stat_type} نقل حالة ' match_result: نتائج متشابهة medium_level: متوسط medium_risk: أولوية متوسطة @@ -590,7 +737,7 @@ ar-JO: name_or_survivor_code: اسم الناجي أو رمزه near_deadline: قاربت الانتهاء new: جديد ومُحدَّث - new_child_assigned_to_you: حالات جديدة تم تعيينها لك + new_child_assigned_to_you: الحالات جديدة المعينة لك new_incident: حوادث جديدة new_incident_assigned_to_you: حوادث جديدة تم تعيينها لك new_last_week: جديد (الاسبوع الماضي) @@ -617,7 +764,7 @@ ar-JO: outstanding_transfers: عمليات النقل المعلقة overdue_activities: أنشطة متأخرة overdue_cases_to_assign: الحالات المتأخرة بانتظار التعيين - overdue_cases_to_assign_high: لديك هذه الحالات منذ اكثر من ساعة + overdue_cases_to_assign_high: لديك هذه الحالات منذ اكثر من 1 ساعة overdue_cases_to_assign_low: لديك هذه الحالات منذ اكثر من ثلاث ساعات overview: لمحة عامة pending: قيد الانتظار @@ -636,7 +783,7 @@ ar-JO: registration: التسجيل rejected: مرفوض rejected_transfers: عمليات النقل المرفوضة - response: الاستجابة (قيد المعالجة ) + response: الاستجابة (قيد المعالجة) scheduled_activities: أنشطة مجدولة score_range: نطاق النتائج screening_service: خدمة الفرز @@ -667,6 +814,20 @@ ar-JO: with_incidents: مع الحوادث with_new_incidents: مع حوادث جديدة without_incidents: بدون حوادث + worker_count_referrals_total: + zero: '%{case_worker} لديه %{stat} اجمالي إحالات' + one: '%{case_worker} لديه %{stat} اجمالي إحالات' + two: '%{case_worker} لديه %{stat} اجمالي إحالات' + few: '%{case_worker} لديه %{stat} اجمالي إحالات' + many: '%{case_worker} لديه %{stat} اجمالي إحالات' + other: '%{case_worker} لديه %{stat} اجمالي إحالات' + worker_count_total: + zero: '%{case_worker} لديه %{stat} اجمالي حالات' + one: '%{case_worker} لديه %{stat} اجمالي حالات' + two: '%{case_worker} لديه %{stat} اجمالي حالات' + few: '%{case_worker} لديه %{stat} اجمالي حالات' + many: '%{case_worker} لديه %{stat} اجمالي حالات' + other: '%{case_worker} لديه %{stat} اجمالي حالات' workflow: سير العمل workflow_team: سير العمل - حالات مجموعات you_have: 'لديك' @@ -675,34 +836,34 @@ ar-JO: disabled: تعطيل enabled: مُفعل email_notification: - assign: '%{user} عين ما يلي %{record_type} لك %{record_id}' + assign: 'المستخدم %{user} عين ما يلي %{record_type} لك %{record_id}' assign_subject: '%{record_type} : %{id} - معينة لك' - approval_request: '%{user}المستخدم%{approval_type}يطلب الموافقة على%{case_id}.' - approval_request_subject: '%{id}-طلب مقبول' - approval_response: '%{user}لديها%{status}طلب الموافقة على%{approval_type}الحالة%{case_id}.' - approval_response_subject: '%{id}- طلب مقبول' - referral: '%{user}من %{agency}أشار إلى ما يلي%{record_type}لك%{record_id}ل%{service_type}.' - transfer: '%{user}نقل ما يلي%{record_type}لك:%{record_id}.' + approval_request: 'يطلب المستخدم %{user} الموافقة على %{approval_type} لحالة %{case_id}' + approval_request_subject: 'حالة: %{id} - طلب المصادقة' + approval_response: '%{user} لديها %{status} طلب الموافقة على %{approval_type} الحالة %{case_id}.' + approval_response_subject: 'حالة: %{id} - طلب المصادقة' + referral: '%{user} من %{agency} أشار إلى ما يلي %{record_type} لك %{record_id} ل%{service_type}.' + transfer: '%{user} نقل ما يلي %{record_type} لك: %{record_id}.' transfer_request_subject: طلب نقل لإحدى حالاتك - transfer_subject: '%{record_type}%{id}نقل' - referral_subject: '%{record_type}%{id} احالة' - transfer_request: 'المستخدم %{user}عند%{agency}يطلب منك نقل ملكية هذا%{record_type}سجل%{record_id}حتى يتمكنوا من تقديمها%{record_type}خدمات الإدارة للأفراد في منطقتهم. إذا كان هذا النقل مقبولًا لك ، فيرجى النقر فوق%{record_type}رابط المعرف في هذا البريد الإلكتروني لفتح%{record_type}في النظام وبدء النقل .' + transfer_subject: '%{record_type}: %{id} - نقل' + referral_subject: '%{record_type} : %{id} - احالة' + transfer_request: 'المستخدم %{user} عند %{agency} يطلب منك نقل ملكية هذا %{record_type} سجل %{record_id} حتى يتمكنوا من تقديم %{record_type}خدمات الإدارة للفرد في منطقتهم. إذا كان هذا النقل مقبولًا لك ، فيرجى النقر على %{record_type} رابط المعرف في هذا البريد الإلكتروني لفتح %{record_type} في النظام وبدء النقل.' approval_request_html: 'المستخدم %{user} طلب المصادقة %{approval_type}على الحالة %{case_id}' - approval_response_html: '%{user}لديه%{status}طلب الموافقة على%{approval_type} الحالة%{case_id}.' - referral_html: '%{user}عند%{agency}أشار إلى ما يلي%{record_type}لك:%{record_id}ل%{service_type}.' - transfer_html: '%{user}نقل ما يلي%{record_type}لك:%{record_id}.' - assign_html: '%{user} عين ما يلي %{record_type}لك%{record_id}.' - transfer_request_html: 'المستخدم%{user}عند%{agency}يطلب منك نقل ملكية هذا%{record_type}سجل%{record_id}حتى يتمكنوا من تقديمها%{record_type}خدمات الإدارة للأفراد في منطقتهم. إذا كان هذا النقل مقبولًا لك ، فيرجى النقر فوق%{record_type}رابط المعرف في هذا البريد الإلكتروني لفتح%{record_type}في النظام وبدء النقل .' - transfer_request_notes_html: '%{request_transfer_notes}ملاحظات من مقدم الطلب:' + approval_response_html: '%{user} لديه %{status} طلب الموافقة على %{approval_type} الحالة %{case_id}.' + referral_html: '%{user} عند %{agency} أشار إلى ما يلي %{record_type} لك: %{record_id} ل %{service_type}.' + transfer_html: '%{user} نقل ما يلي %{record_type} لك: %{record_id}.' + assign_html: '%{user} عين ما يلي %{record_type} لك %{record_id}.' + transfer_request_html: 'المستخدم %{user} من %{agency} يطلب منك تحويل مسؤولية %{record_type} بالرقم %{record_id} ليتمكنوا من توفير %{record_type} في منطقتهم. وإذا وافقت على هذا التحويل، رجاء النقر على%{record_type} رابط الهوية في هذه الرسالة الإلكترونية لفتح %{record_type} في النظام وبداية التحويل' + transfer_request_notes_html: '%{request_transfer_notes} ملاحظات من مقدم الطلب:' encrypt: export_type: نوع التصدير file_name: قم بإنشاء اسم الملف الخاص بك (اختياري) password_extra_info: يجب أن تكون كلمة المرور 8 أحرف على الأقل. سيتم ربط كلمة المرور هذه بالملف الذي تم تصديره وسيتعين إدخالها من قبل أي شخص يفتح هذا الملف في المستقبل. password_label: الرجاء إدخال كلمة المرور التي سوف تشفّر ملفك. error_message: - address_fields: تحتاج إلى معالجة%{fields}الحقول%{forms} نماذج - address_form_fields: تحتاج إلى معالجة%{fields}الحقول في هذا النموذج - address_subform_fields: '%{subform} %{fields}يحتوي حقول غير صالحة' + address_fields: تحتاج إلى معالجة %{fields} حقل و %{forms} نموذج + address_form_fields: تحتاج إلى معالجة %{fields} حقل في هذا النموذج + address_subform_fields: '%{subform} %{fields} يحتوي حقول غير صالحة' error_page: not_authorized: server_error: غير مخول بالوصول الى هذة الصفحة @@ -742,7 +903,7 @@ ar-JO: unique_name: توجد وحدة نمطية تحمل هذا الاسم بالفعل، الرجاء إدخال اسم مختلف report: module_presence: يجب ألا تكون الوحدة فارغة - module_syntax: يجب أن تكون كافة وحدات التقرير موجودة بالفعل + module_syntax: يجب أن تكون كافة وحدات التقرير موجودة بالأصل name_presence: لا يجب أن يكون الاسم فارغاً role: permission_presence: الرجاء تحديد إذن واحد على الأقل @@ -754,8 +915,8 @@ ar-JO: code_of_conduct: title_present: يجب ألا يكون العنوان فارغًا content_present: يجب ألا يكون المحتوى فارغًا - created_by_present: حقل الانشاء بواسطةيجب ألا يكون فارغًا - not_found: لم يتم العثور على سجلات + created_by_present: حقل الانشاء بواسطة يجب ألا يكون فارغًا + not_found: لم يتمّ العثور على أي سجل (سجلات) try_again: حاول مرة اخرى exports: case_pdf: @@ -803,10 +964,11 @@ ar-JO: national_id_no: الرقم الوطني progress_id: معرف العملية sex_mapping_m_f_u: الجنس + other_agency_id: رمز المستشفى ورقم المريض male_abbreviation: M unknown_abbreviation: U exported: تم توليد ملف التصدير بنجاح - exported_error: خطأ في توليد ملف التصدير + exported_error: خطأ في إنشاء ملف التصدير forms: button: تصدير النماذج label: 'تصدير ' @@ -821,6 +983,7 @@ ar-JO: on_short_form: في النموذج القصير option_ids: معرفات الخيار options: خيارات + options_lookup: ابحث عن help_text: نص المساعدة guiding_questions: أسئلة موجهه visible: مرئي @@ -833,8 +996,14 @@ ar-JO: agency: مؤسسات user: مستخدمين reportinglocation: مواقع الابلاغ - subforms: 'نموذج فرعي:%{subform_name}' - collapsed_fields: 'حقول منهارة:%{fields}' + subforms: 'نموذج فرعي: %{subform_name}' + collapsed_fields: 'حقول مدمجة: %{fields}' + country: بلاد + summary_header: + form_group: مجموعات نماذج بريميرو + form: نماذج بريميرو + status: الوضع + notes: ملاحظات go_to_exports: انتقل إلى صفحة الصادرات للتحميل incident_recorder_xls: all: مسجل الحادثة @@ -869,18 +1038,18 @@ ar-JO: caseworker_name: اسم منسق الحالة caseworker_agency: مؤسسة منسق الحالة photowall: - all: Photo Wall + all: جدار صور flag_suspect_record: تم وضع علامة عليه كسجل مشتبه به no_photos_available: لا يوجد صور متاحة - one: Photo Wall + one: جدار صور reunited: لم شملهم - selected: تحديد إلى Photo Wall - success_message: انشاء دار الصور%{file_name}لن يتم تضمين الحالات بدون صور. - printed: 'طبع:%{date}' - queueing: إنشاء ملف التصدير%{file_name} + selected: تم الاختيار لجدار الصور + success_message: انشاء جدار الصور %{file_name} لن يتضمين الحالات بدون صور. + printed: 'تمت طباعة: %{date}' + queueing: إنشاء ملف التصدير %{file_name} selected_xls: all: Excel - one: Excel + one: اكسل selected: تحديد إلى Excel selected_fields: الحقول المختارة unhcr_csv: @@ -899,7 +1068,7 @@ ar-JO: governorate_country: المحافظة - البلد id: الرقم التعريفي individual_progress_id: معرف التقدم الفردي - locations_by_level: العنوان (مخيم ،حي،ومستويات عناوين أخرى قابلة للتطبيق ، مثل إحداثيات GPS الخاصة بالمأوى) + locations_by_level: العنوان (مخيم، حي، وعناوين أخرى قابلة للتطبيق، مثل إحداثيات الموقع الجغرافية الخاصة بالمأوى) long_id: معرف طويل moha_id: معرف وزارة الصحة name_of_caregiver: الاسم الكامل لمقدم الرعاية @@ -915,7 +1084,7 @@ ar-JO: vulnerability_details_code: رموز تفاصيل الثغرات الأمنية male_abbreviation: M one: المفوضية السامية للأمم المتحدة لشؤون اللاجئين UNHCR - selected: تحديد إلى المفوضية السامية للأمم المتحدة لشؤون اللاجئين UNHCR + selected: تم الاختيار لمفوضية الأمم المتحدة السامية لشؤون اللاجئين unknown_abbreviation: U xlsx: all: اكسل @@ -927,24 +1096,34 @@ ar-JO: success: تم استيراد المواقع بنجاح no_data: 'لم تتم معالجة الاستيراد: لم يتم تمرير أي بيانات' csv_parse_error: 'لم تتم معالجة الاستيراد: خطأ في تحليل بيانات CSV' - error: 'صف%{row_number}غير معالج:%{message}' - db_error: 'خطأ في الإنشاء%{location_code}:%{message}' - locale_invalid: 'التخطي%{column_name}: اللغة غير صالحة' - insert_all_error: 'لم تتم معالجة الاستيراد. خطأ في قاعدة البيانات:%{message}' + error: 'صف %{row_number} غير معالج: %{message}' + db_error: 'خطأ في إنشاء %{location_code} : %{message}' + locale_invalid: 'تجاوز %{column_name} : الموقع غير صحيح' + insert_all_error: 'لم تتم معالجة الاستيراد. خطأ في قاعدة البيانات: %{message}' + csv_record: + messages: + success: تم استيراد السجلات بنجاح + no_data: 'لم تتم معالجة الاستيراد: لم يتم تمرير أي بيانات' + no_file: 'لم تتم معالجة الاستيراد: الملف غير موجود' + csv_parse_error: 'لم تتم معالجة الاستيراد: خطأ في تحليل بيانات ملف CSV' + error: 'صف %{row_number} غير معالج: %{message}' + db_error: 'خطأ في إنشاء %{location_code} : %{message}' + locale_invalid: 'تجاوز %{column_name} : الموقع غير صحيح' + insert_all_error: 'لم تتم معالجة الاستيراد. خطأ في قاعدة البيانات: %{message}' sync_record: failed: 'آخر مزامنة: فشل' - last: 'آخر مزامنة:%{date_time}' + last: 'آخر مزامنة: %{date_time}' not_found: 'آخر مزامنة: لم يتم العثور على البيانات' retrieving: استرجاع البيانات. see_details: انظر التفاصيل fields: action: إجراء actions: الإجراءات - add: إضافة + add: أضف add_new_field: إنشاء حقل جديد add_existing_field: اضافة حقل موجود add_field: 'إضافة حقل ' - add_field_type: اضافة + add_field_type: اضافة %{file_type} audio: current: التسجيل الحالي audio_upload_box: تحميل ملف صوتي @@ -966,6 +1145,7 @@ ar-JO: date_range: نطاق التاريخ from: من to: إلى + view_by: اظهر حسب date_range_field: نطاق التاريخ date_time: وقت - تاريخ db_name: اسم قاعدة البيانات @@ -991,7 +1171,7 @@ ar-JO: english_text: النص بالإنجليزية field_name: اسم الحقل field_type: نوع الحقل - attachment_too_large: لا يجب ان يكون الملف اكبر من 10 ميجابايت + attachment_too_large: ' يجب ألّا يتعدّى حجم الملفّ 20 ميجابايت' file_upload_box: add_document_label: اضافة وثيقة add_new_document_button_text: إضافة وثيقة آخرى @@ -1006,7 +1186,7 @@ ar-JO: find_lookup: إيجاد البحث form_name: اسم النموذج future_date_not_valid: لا يمكن أن يكون في المستقبل - guidance: إرشاد + guidance: النص التوجيهي guiding_questions: أسئلة موجهه help_text: نص المساعدة hide_on_view_page: عرض الصفحة @@ -1036,7 +1216,7 @@ ar-JO: remove: ازاله remove_attachment_confirmation: هل أنت متأكد أنك تريد إزالة هذا المرفق؟ required: مطلوب - required_field: '%{field}مطلوب' + required_field: '%{field} مطلوب' search_existing: ابحث في الحقول الموجودة select_box: حدد القائمة المنسدلة select_date_validation: اختر طريقة للتأكد من سلامة التاريخ @@ -1046,6 +1226,16 @@ ar-JO: show: عرض show_on: عرض على show_on_minify_form: نموذج قصير + skip_logic: + name: التخطي استنادا على نوع الإجابة + record_section: + title: 'يجب ان يظهر هذا الحقل في حال كان السجل ' + buttons: + add: اضافة شرط السجل + subform_section: + title: يجب ان يظهر هذا الحقل في حال كان النموذج الفرعي + buttons: + add: 'اضافة شرط النموذج الفرعي ' subform: نموذج فرعي subform_group_by: مجمعة حسب subform_remove_message: هل أنت متأكد من حذف هذا النموذج الفرعي؟ @@ -1057,7 +1247,9 @@ ar-JO: subform_prevent_item_removal: منع إزالة إدخال النموذج الفرعي؟ subform_sort_by: مرتبة حسب successfully_added: تم إضافة الحقل بنجاح - tally_field: حقل Tally + tally_field: حقل الفرز + tally_items: عناصر العد + tally_items_maximum: (5 على الأكثر) text_area: منطقة النص text_field: حقل النص textarea: منطقة النص @@ -1075,6 +1267,10 @@ ar-JO: less: أقل more: المزيد save_filters: حفظ + categories: + violations: الانتهاكات + incidents: حوادث + individual_victims: ضحايا فردية flags: add_flag_tab: اضافة علامة جديدة date: 'تاريخ' @@ -1099,7 +1295,7 @@ ar-JO: module: وحدة name: الاسم record_type: نوع السجل - required_field: '%{field} إجباري' + required_field: '%{field} مطلوب' forms: add: اضافة نموذج description: وصف النموذج @@ -1111,7 +1307,7 @@ ar-JO: must_be_english: يجب ان يكون الادخال باللغة الانجليزية related_groups: ضع النموذج في مجموعة ذات صلة للمستخدمين summariaze_purpose: لخص الغرض من النموذج. يجب إدخالها باللغة الإنجليزية - invalid_characters_field: '%{field}يحتوي على أحرف غير صالحة.' + invalid_characters_field: '%{field} يحتوي على أحرف غير صالحة.' label: نماذج manage: ادارة messages: @@ -1140,12 +1336,15 @@ ar-JO: tracing_request: طلب التتبع transfers_assignments: التحويلات / التعيينات violation: انتهاك - required_field: '%{field}هو حقل مطلوب' + registry_details: تفاصيل التسجيل + registry_record: سجل التسجيل + required_field: '%{field} هو حقل مطلوب' select_label: اختار settings: اعدادات show_on: تظهر على - subform_need_to_be_added: هم بحاجة إلى أن يضافوا. - subform_not_found: '%{subform_name}وجدت.' + subform_need_to_be_added: النماذج بحاجة الى إضافة. + subform_need_to_be_added_single: بحاجة الى ان يضاف + subform_not_found: لا يوجد نموذج %{subform_name} title: عنوان النموذج translations: edit: تحرير الترجمات @@ -1159,43 +1358,96 @@ ar-JO: type_label: نوع visibility: مرئي web_app: التطبيق على شبكة الإنترنت + skip_logic: + name: التخطي استنادا على نوع الإجابة + section: + title: يجب ان يظهر هذا النموذج اذا + buttons: + add: اضافة الشرط + conditions: + add: اضافة الشرط + update: تحديث/تعديل الشرط + field_name: اسم الحقل + condition: الشرط + empty: لم يتم اضافة اي شروط + type: نوع + types: + and: + display_text: اضافة الشرط + name: و + or: + display_text: أو هذا الشرط + name: أو home: ar: العربية + ar-IQ: العربية (العراقية) ar-JO: العربية (الأردنية) ar-LB: العربية (اللبنانية) ar-SD: العربية (السودانية) bn: বাংলা current_time_zone: المنطقة الزمنية الحالية - dashboard: لوحة المعلومات + dashboard: لوحة ملخص البيانات (داشبورد) en: الإنجليزية es: الاسبانية + es-GT: الاسبانية + es-ES: اسبانية(اسبانيا) fr: Français - id: Bahasa + hu: المجرية + id: باهاسا km: ភាសាខ្មែរ ku: الكردية + ku-IQ: کوردی (بادینی) + fa-AF: فارسی (افغانستان) + ps-AF: پښتو (افغانستان) + sw-KE: Kiswahili (Kenya) + sw-TZ: Kiswahili (Tanzania) + ne: नेपाली + om: أورومو + am-ET: الأمهرية (إثيوبيا) label: الصفحة الرئيسية language: اللغة manage_system_users: إدارة مستخدمي مزامنة الخادم my: ဗမာစာ + pl: بولندية pt: البرتغالية + pt-BR: Português (Brasil) records_need_attention: السجلات التي تحتاج إلى الإنتباه - ru: Русский + ro: الرومانية + ru: روسية + sk: سلوفينيا so: Af-Soomaali th: ไทย + uk: الأوكرانية users: إدارة المستخدمين view_records: عرض السجلات welcome: مرحبا بكم في بريميرو zh: 中文 incident: + code: رمز الحادثة associated_case: "الحالة المرتبطة:" messages: creation_success: تم إنشاء سجل الحادث بنجاح. creation_success_queue: تم إنشاء سجل الحادث بنجاح في الخلفية disabled: تم تعطيل الحادثة update_success: 'تم تحديث الحادثة %{record_id} بنجاح.' - update_success_queue: 'حادث%{record_id}تم تحديثه بنجاح في الخلفية.' + update_success_queue: 'حادث %{record_id} تم تحديثه بنجاح في الخلفية.' violation: + associated_violations: "الإنتهاكات ذات الصلة:" + update_and_return: 'تحديث والرجوع الى %{association}' + save_and_return: 'اضافة والرجوع الى %{association}' pending: في انتظار التحقق + title: الانتهاكات + types: + killing: قتل الاطفال + maiming: تشويه الاطفال + recruitment: تجنيد و/او استخدام الاطفال + sexual_violence: الاغتصاب و / أو غيره من أشكال العنف الجنسي + abduction: Abduction + attack_on: الهجوم على المدارس و/او المستشفيات + attack_on_hospitals: الهجوم على المستشفى(المستشفيات) + attack_on_schools: الهجوم على المدرسة(المدارس) + military_use: الاستخدام العسكري للمدارس و/او المستشفيات + denial_humanitarian_access: الحرمان من الوصول إلى الخدمات الإنسانية incidents: disable_dialog: سيؤدي النقر فوق "موافق" إلى تغيير حالة هذا الحادث إلى "معطل". disable_dialog_title: تعطيل الحادثة @@ -1204,31 +1456,82 @@ ar-JO: enable_dialog_title: تفعيل الحادثة enable_success: تم تفعيل الحوادث بنجاح. id: المُعرف# + complete: متاح بدون الاتصال بالانترنت date_of_interview: تاريخ المقابلة date_of_incident: تاريخ الحادثة incident_location: مكان الحادث + violations: الانتهاكات export: 'تصدير ' label: حوادث filter_by: + filter_category: فئة التصفية boys: الأولاد by_date: حسب التاريخ children: اطفال girls: الفتيات incident_location: مكان وقوع الحادثة + status: الوضع unaccompanied_separated_status: حالة الحماية unknown: غير معروف + verification_status: حالة التحقق violence_type: نوع العنف + armed_force_group_party_name: القوات المسلحة أو الجماعات أو الأطراف الأخرى + armed_force_group_type: نوع مجموعة القوات المسلحة + violations: الانتهاكات + individual_violations: انتهاكات فردية + individual_age: عمر الفرد + individual_sex: جنس الفرد + victim_deprived_liberty_security_reasons: محرومون من الحرية + reasons_deprivation_liberty: ما هي أسباب الحرمان من الحرية؟ + victim_facilty_victims_held: يرجى تحديد المنشأة التي تم / تم احتجاز الضحية (الضحايا) فيها + torture_punishment_while_deprivated_liberty: هل تعرض / كان الطفل (الأطفال) للتعذيب أو غيره من ضروب المعاملة أو العقوبة القاسية أو اللاإنسانية أو المهينة أثناء حرمانه من الحرية؟ + verified_ghn_reported: حدد GHN الذي تم تضمين هذه الحادثة فيه + weapon_type: 'نوع السلاح / الطريقة المستخدمة' + facility_impact: 'نوع ومدى التأثير المادي' + facility_attack_type: 'نوع الانتهاك المتعلق بالصحة أو التعليم' + child_role: 'ما هو الدور الذي لعبه الطفل (الأطفال) في القوات / الجماعة المسلحة؟' + abduction_purpose_single: 'الغرض من الاختطاف' + military_use_type: 'نوع الاستخدام العسكري' + types_of_aid_disrupted_denial: 'نوع المساعدة / الخدمة المرفوضة / المعطلة.' + late_verified_violations: الانتهاكات التي تم التحقق منها في وقت متأخر + perpetrator_category: نوع المسيء + record_owner: مالك السجل register_new_incident: حادثة جديدة selectable_date_options: date_of_first_report: موعد المقابلة + mrm_date_of_first_report: تاريخ التقرير الأولي لعضوCTFMR + ctfmr_verified_date: تاريخ قرار التحقق من قبل CTFMR incident_date_derived: تاريخ الحادثة - selected_records: '%{select_records}حادث (حوادث) محددة' - selected_all_records: 'حدد جميع%{total_records} الحالات التي تطابق هذا الاستعلام.' + selected_records: '%{select_records} حادث (حوادث) محددة' + selected_all_records: 'حدد جميع %{total_records} الحالات التي تطابق هذا الاستعلام.' + summary_mrm: + label: ملخص الحادثة + fields: + children_multiple_violation: + label: الأطفال المتضررون من انتهاكات متعددة + summary_of_incident: + label: ملخص الحادثة + incident_total_tally: + label: عدد الضحايا + boys: أولاد + girls: بنات + unknown: غير معروف + incident_date: + label: تاريخ الحادثة + incident_location: + label: مكان الحادثة + incident_description: + label: حساب الحادثة + incident_update: + label: تحديث الحادثة survivor_code: رمز الناجي - show_incident: 'رقم الحدث%{short_id}' + show_incident: 'رقم الحادثة %{short_id}' social_worker: عامل اجتماعي + violation_type: نوع الانتهاك violence_type: نوع العنف type_violence: نوع العنف + violation_summary: ملخص + sort_by: ترتيب حسب key_performance_indicators: label: "نبض / KPIs" case_assessment: "تقييم الحالة" @@ -1238,7 +1541,7 @@ ar-JO: case_closure: "اغلاق ملف الحالة" feedback: "تغذية راجعة" other: "آخرى" - date_format: "%b %Y" + date_format: "% b % Y" date_range_select: custom_range: 'مخصص' long_date_format: "dd/MM/yyyy" @@ -1250,11 +1553,11 @@ ar-JO: last_1_year: "العام الماضي" 0-3days: "0 - 3 أيام" 4-5days: "4-5 أيام" - 6-14days: "6-14 يوم" + 6-14days: "6 - 14 أيام" 15-30days: "15 - 30 يوم" 1-3months: "1 - 3 شهور" 4months: "اكبر من 3 شهور" - 1-month: "اقل من1 شهر" + 1-month: "اقل من 1 شهر" 3-6months: "3 - 6 شهور" 7-months: "اكبر من 6 شهور" helptext: @@ -1279,7 +1582,7 @@ ar-JO: total_incidents: "إجمالي الحوادث" helptext: | يحسب هذا المؤشر ويصنف عدد الأيام التي انقضت بين وقت - تعرضت الناجية للعنف المبني على النوع الاجتماعي وعندما أبلغت الناجية بذلك لأول مرة لمقدم الخدمة . أنه تم حسابها بناءً على وقت إبلاغ منظمة المستخدم بالحادثة. البيانات مصنفة على أساس فترات زمنية مختلفة (0-3 أيام ؛ 4-5 أيام ؛ 6-14 يومًا ؛ 15-30 يومًا ؛ اكتر شهر واحد أكثر من 3 أشهر + تعرضت الناجية للعنف المبني على النوع الاجتماعي وعندما أبلغت الناجية بذلك لأول مرة لمقدم الخدمة . أنه تم حسابها بناءً على وقت إبلاغ منظمة المستخدم بالحادثة. البيانات مصنفة على أساس فترات زمنية مختلفة (0-3 أيام ؛ 4-5 أيام ؛ 6-14 يومًا ؛ 15-30 يومًا ؛ اكتر شهر واحد أكثر من 3 أشهر) service_access_delay: title: "تأخير الوصول إلى الخدمة" delay: "تأخير" @@ -1323,8 +1626,11 @@ ar-JO: count: "مرات المقدمة" male: "ذكر" female: "أنثى" - disability: "عجز" - no_disability: "ليس لديهم اعاقة" + 0-11: "0-11" + 12-17: "12-17" + '>18': ">18" + disability: "اعاقة " + no_disability: "لا وجود لاعاقة" helptext: |+ يحسب هذا المؤشر نوع الخدمة (الخدمات) المقدمة للناجين في إدارة الحالة معالجة. من خلال الخدمة المقدمة ، فإننا نعني الخدمة التي تقدمها منظمة المستخدم @@ -1333,11 +1639,7 @@ ar-JO: average_referrals: title: "9. متوسط الإحالات" label: "متوسط الإحالات لكل حالة" - helptext: |+ - يحسب هذا المؤشر متوسط عدد الإحالات لكل حالة مسجلة (لجميع الأنواع - من الخدمات) في جميع الحالات ، سواء كانت الحالة نشطة / مفتوحة أو مغلقة. يتضمن الإحالات - المسجلة في علامة تبويب الحالة ، وليس فقط الإحالات التي تتم من خلال النظام الأساسي - + helptext: "يحسب هذا المؤشر متوسط عدد الإحالات لكل حالة مسجلة (لجميع الأنواع \nمن الخدمات) في جميع الحالات ، سواء كانت الحالة نشطة / مفتوحة أو مغلقة. يتضمن الإحالات \nالمسجلة في علامة تبويب الحالة ، وليس فقط الإحالات التي تتم من خلال النظام الأساسي \n \n" referrals_per_service: title: "الإحالات لكل خدمة" average_followup_meetings_per_case: @@ -1373,8 +1675,8 @@ ar-JO: من خلال استكمال نموذج ملاحظات العميل على GBVIMS + من قبل موظف آخر من أخصائي الحالة الذي قدم الخدمة للناجي. supervisor_to_caseworker_ratio: - title: "14. مشرف على Caseworker Ratio" - label: "عمال الحالات لكل مشرف" + title: "14. عدد منسقي الحالات لكلّ مشرف." + label: "عدد مديري الحالات لكلّ مشرف" helptext: | هذا المؤشر هو عدد الأخصائيين الاجتماعيين الذين يشرف عليهم المشرف: المشرف على الحالة نسبة العاملين. يعتمد هذا الحساب على أدوار النظام المخصصة على النظام الأساسي. @@ -1404,6 +1706,7 @@ ar-JO: camp: مخيم chiefdom: المشيخة city: مدينة + community: مجتمع country: دولة county: دولة district: منطقة @@ -1417,6 +1720,14 @@ ar-JO: sub-district: منطقة فرعية village: قرية zone: منطقة + association: منظمة + division: قسم + central_warehouse: المستودع المركزي + warehouse: مستودع + buyingstation: محطة شراء + township: بلدة + municipality: بلدية + autonomous_region: منطقة الحكم الذاتي label: موقع name: الاسم code: 'الرمز ' @@ -1426,6 +1737,10 @@ ar-JO: import_title: موقع الاستيراد message: الرجاء تحديد ملف CSV للتحميل. يجب أن يستخدم هذا الملف ترميز UTF-8 وأن يتضمن علامات تصنيف HXL في صف الرأس الثاني لكل عمود. no_location: يرجى استيراد المواقع قبل إنشاء أي حسابات مستخدمين. + enable_title: تفعيل الموقع + enable_text: هل أنت متأكد؟ إذا قمت بتفعيل المواقع المحددة ، فستظهر كخيارات في حقول الموقع + disable_title: تعطيل الموقع + disable_text: هل أنت متأكد؟ إذا قمت بتعطيل المواقع المحددة ، فلن تظهر كخيارات في حقول الموقع logger: actions: _approved: تم المصادقة عليها @@ -1437,13 +1752,22 @@ ar-JO: attach: إرفاق bulk_assign: تعيين Bulk  bulk_create: إنشاء Bulk  + bulk_index: فهرس بالجملة case_plan_approved: تمت الموافقة على خطة الحالة case_plan_rejected: تم رفض خطة الحالة case_plan_requested: مطلوب خطة حالة close: اغلاق + create: انشاء + create_bulk: انشاء حزمه delete: حذف + destroy: هدم + detach: فصل + enable_disable_record: فعل تعطيل السجلات export: تصدير + flag: علامة import: استيراد + incident_details_from_case: تفاصيل الحادث من الحالة + index: فهرس list: قائمة login: تسجيل الدخول password_reset: إعادة تعيين كلمة المرور @@ -1455,11 +1779,19 @@ ar-JO: refer_revoke: الغاء الإحالة refer_to: احالة الى reopen: اعادة فتح + services_section_from_case: قسم الخدمات من حالة show: عرض show_alerts: عرض التنبيهات - transfer: نقل + traces: تتبّعات + transfer: نقل حالة transfer_accepted: تم قبول النقل transfer_rejected: تم رفض النقل + transfer_request: طلب النقل + transfer_to: نقل إلى + unflag: 'إزالة العلامة ' + update: تحديث + user_password_reset_request: طلب إعادة تعيين كلمة المرور + webhook: الويب هوك approve_form: action_plan: نموذج خطة العمل bia: نموذج BIA @@ -1468,41 +1800,62 @@ ar-JO: 'false': رفض gbv_closure: استمارة إغلاق العنف القائم على النوع الاجتماعي 'true': مصادقة - assessment_approved: "%{approval_label}وافقت ل" - assessment_requested: "%{approval_label}مصادقة ل" + assessment_approved: "%{approval_label} وافقت ل" + assessment_requested: "%{approval_label} مطلوب ل" bulk_index: قائمة الجميع by_user: من قبل المستخدم - case_plan_approved: "%{approval_label}وافقت ل" - case_plan_requested: "%{approval_label}مطلوب ل" + case_plan_approved: "%{approval_label} وافقت ل" + case_plan_requested: "%{approval_label} مطلوب ل" close: اغلاق - closure_approved: "%{approval_label}وافقت ل" - closure_requested: "%{approval_label}مطلوب ل" + closure_approved: "%{approval_label} وافقت ل" + closure_requested: "%{approval_label} مطلوب ل" consent_count: عدد الموافقة copy: جاري النسخ create: إنشاء - create_subform: تكوين نموذج فرعي - destroy: حذف - edit: التعديل + create_subform: انشاء نموذج فرعي + destroy: جاري الحذف + edit: تعديل enable_disable_record: تفعيل / تعطيل - export: نقل بيانات إلى + export: تحويل البيانات ل .... flag: وضع علامة flag_records: وضع علامة graph_data: عرض بيانات الرسم البياني hide_name: protect: إخفاء الاسم view: إظهار الاسم - index: قائمة السجلات + index: إدراج السجلات list: قائمة login: تسجيل الدخول logout: تسجيل الخروج lookups_for_field: عمليات البحث عن الحقل mark_for_mobile: - 'false': إزالة علامة للمحمول - 'true': وضع علامة للمحمول + 'false': إزالة العلامة للهاتف النقال + 'true': وضع علامة للهاتف النقال match_record: مطابقة الحقل permitted_field_list: قائمة الحقل المسموح بها quick_view: عرض سريع reassign: جاري التعيين + resources: + audit_log: سجل التدقيق + user: مستخدم + agency: مؤسسة + user_group: مجموعة المستخدم + child: طفل + alert: تحذير + form_section: نموذج + lookup: عمليات البحث + system_settings: اعدادات النظام + permission: صلاحية + dashboard: لوحة ملخص البيانات (داشبورد) + report: تقرير + bulk_export: تصدير بالجملة + saved_search: عمليات البحث المحفوظة + role: دور + incident: حادثة + location: موقع + primero_configuration: اعدادات بريميرو + code_of_conduct: مدونة قواعد السلوك + task: مهمة record_state: 'false': تعطيل 'true': تفعيل @@ -1520,13 +1873,13 @@ ar-JO: gbv_closure: طلب الموافقة على استمارة إغلاق العنف ضد المرأة request_transfer: إرسال طلب النقل request_transfer_view: مشاهدة طلب النقل - save_subform: حفظ النموذج الفرعي + save_subform: جاري حفظ النموذج الفرعي search: بحث API show: المعاينة show_alerts: عرض التنبيهات لـ to: الى to_user: للمستخدم - transfer: عملية النقل + transfer: جاري النقل transfer_status: Accepted: نقل مقبول Rejected: نقل مرفوض @@ -1540,7 +1893,7 @@ ar-JO: label: تأكيد كلمة السر password_match: label: كلمة السر يجب ان تتطابق - provider_title: مع%{provider} + provider_title: مع %{provider} title: تسجيل الدخول username: اسم المستخدم password_reset_modal: إعادة تعيين كلمة المرور  @@ -1564,17 +1917,161 @@ ar-JO: no_options: هذا البحث ليس له خيارات حاليا. translation_label: نص الترجمة values: خيارات + locked_alert_message: عمليات البحث مقفلة + managed_reports: + generated_on: انشئت في + label: رؤى + total: مجموع + violations_total: الانتهاكات + filter_by: + date: تاريخ + verification_status: وضع التحقق + violation_type: نوع الانتهاك + date_range: + month: شهر + quarter: ربع + year: سنه + date_range_options: + this_quarter: الربع الحالي + last_quarter: الربع الماضي + this_month: الشهر الحالي + last_month: الشهر الماضي + this_year: العام الحالي + last_year: العام الماضي + custom: مخصص + no_data: لا يوجد بيانات لهذه الرؤى + no_data_table: لا يوجد بيانات لهذه الرؤى + incomplete_data: بيانات غير مكتملة + individual_children: + name: الأطفال الفرديين + reports: + individual_children: الأطفال الفرديين + sub_reports: + individual_age: الأطفال الفرديين حسب العمر + individual_violation_type: الأطفال الفرديين حسب نوع الانتهاك + individual_region: الأطفال الفرديين حسب المنطقة + individual_perpetrator: عدد الاطفال حسب المسيء + ghn_report: + name: المذكرة الافقية الشاملة + reports: + ghn_report: المذكرة الافقية الشاملة + sub_reports: + verified_information: معلومات تم التحقق منها - الضحايا + late_verification: التحقق المتأخر - الضحايا + unverified_information: معلومات لم يتم التحقق منها - الضحايا + verified_information_violations: معلومات تم التحقق منها - الانتهاكات + late_verification_violations: التحقق المتأخر - الانتهاكات + unverified_information_violations: معلومات لم يتم التحقق منها - الانتهاكات + killing: قتل الاطفال + maiming: تشويه الاطفال + recruitment: تجنيد و/او استخدام الاطفال + sexual_violence: الاغتصاب و / أو غيره من أشكال العنف الجنسي + rape: الاغتصاب و / أو غيره من أشكال العنف الجنسي + abduction: خطف + attack_on_hospitals: الهجوم على المستشفى(المستشفيات) + attack_on_schools: الهجوم على المدرسة(المدارس) + military_use: الاستخدام العسكري للمدرسة(المدارس) و/او المستشفى(المستشفيات) + denial_humanitarian_access: الحرمان من الوصول إلى الخدمات الإنسانية + multiple_violations: الأطفال المتضررون من انتهاكات متعددة + detention: احتجاز + boys: أولاد + girls: بنات + total: مجموع + unknown: غير معروف + associated_violations: 'الإنتهاكات ذات الصلة:' + violations: + name: الانتهاكات + filter_options: + incident_date: تاريخ الحادثة + date_of_report: تاريخ التقرير + ctfmr_verified_date: تاريخ التحقق + verified: تم التحقق منه + reports: + killing: قتل الاطفال + maiming: تشويه الاطفال + recruitment: تجنيد و/او استخدام الاطفال + sexual_violence: الاغتصاب و / أو غيره من أشكال العنف الجنسي + rape: الاغتصاب و / أو غيره من أشكال العنف الجنسي + abduction: خطف + attack_on_hospitals: الهجوم على المستشفى(المستشفيات) + attack_on_schools: الهجوم على المدرسة(المدارس) + military_use: الاستخدام العسكري للمدارس و/او المستشفيات + denial_humanitarian_access: الحرمان من الوصول إلى الخدمات الإنسانية + detention: احتجاز + sub_reports: + children: اطفال + combined: الانتهاكات + denial_humanitarian_access: الحرمان وصول الخدمات الانسانية + denial_type: نوع الحرمان + detention_detained: البقاء محتجزا + detention_released: الافراج + perpetrators: عدد الاطفال حسب المسيئين + perpetrators_denial: عدد الانتهاكات حسب المسيئين + perpetrator_detention: عدد الاطفال حسب المسيئين + perpetrators_incidents: عدد الحوادث حسب المسيئين + reporting_location_incidents: عدد الحوادث حسب المنطقة + reporting_location: عدد الاطفال حسب المنطقة + reporting_location_detention: عدد الاطفال حسب المنطقة + reporting_location_denial: عدد الانتهاكات حسب المنطقة + attack_type: عدد الاطفال حسب نوع الاعتداء + boys: أولاد + girls: فتيات + unknown: غير معروف + total: مجموع + violation: الانتهاكات + sexual_violence_type: شكل (أشكال) العنف الجنسي + detention_status: وضع الأطفال المحتجزين + type_of_use: نوع الاستخدام + factors_of_recruitment: اسباب التوظيف + still_being_held: لا يزال محتجزا + released: 'الافراج' + escaped: 'هرب' + abduction_reasons: أسباب الاختطاف + abducted_status: حالة المخطوف + facility_attack_type: نوع الانتهاك + received_response: تلقى الأطفال استجابة + male: ذكر + female: أنثى + military_use_type_of_use: عدد الانتهاكات حسب نوع الاستخدام + gbv_statistics: + name: احصاءات GBV + filter_options: + date_of_first_report: تاريخ المقابلة + incident_date: تاريخ الحادثة + reports: + perpetrators: المسيئين + survivors: الناجين + referrals: الإحالات + sub_reports: + service_safehouse_referral: إحالة البيت الآمن / المأوى الآمن + service_medical_referral: إحالة صحية / طبية + service_psycho_referral: خدمات الاستشارة النفسية / الاجتماعية + service_legal_referral: خدمات المساعدة القانونية + service_police_referral: الشرطة أو أي نوع آخر من خدمات الأمن + service_livelihoods_referral: خدمات الاعاشة + service_protection_referral: خدمات حماية الطفل + survivors_disability_type: مع اعاقات + success_message: تم إنشاء ملف التصدير بنجاح messages: - alert_items: يوجدل لديك%{items} عناصر الملاحظة + alert_items: يوجدل لديك %{items} عناصر الملاحظة alerts_for: approval: الموافقة معلقة لـ%{form_section_name} - field_change: '%{form_section_name}تم تحديثه في%{alert_time}' - transfer_request: تم إجراء طلب نقل جديد في%{date}بواسطة%{user}في%{agency} + field_change: '%{form_section_name} تم تحديثه في %{alert_time}' + transfer_request: تم إجراء طلب نقل جديد في %{date} بواسطة %{user} في %{agency} + duplicate_field: 'هذه الحالة %{field_name} مدخلة مسبقا يرجى العمل على ما يلي: + + + العودة للقائمة الرئيسية والبحث عن الحالة من خلال الرقم الوطني + + إضافة الحادثة الجديدة على الحالة المدخلة مسبقا واستكمال العمل على الحالة + + ابلاغ مدير النظام برقم الحالة الجديدة المكررة المدخلة من قبلكم لغاية تعطيلها' cannot_edit: لا يمكنك تعديل هذا - confirmation_message: انقر فوق موافق لتجاهل أي تغييرات غير محفوظة والعودة إلى عرض القائمة. انقر فوق إلغاء للعودة إلى السجل. - dashboard_offline: أنت غير متصل بالإنترنت. ستعمل لوحة القيادة بكامل طاقتها عندما تعود إلى وضع الاتصال بالإنترنت - field_name_on_form_name: '''%{field_name}"الحقل على"%{form_name}'' شكل.' - logout_confirmation: هل ترغب في الاستمرار في جلسة العمل الخاصة بك؟ + confirmation_message: النقر على موافق سيتجاهل أي تغييرات غير محفوظة والعودة إلى عرض القائمة. انقر فوق إلغاء للعودة إلى السجل. + confirmation_message_subform: النقر على موافق سيتجاهل أي تغييرات غير محفوظة والعودة إلى عرض القائمة. انقر فوق إلغاء للعودة إلى السجل. + dashboard_offline: أنت غير متصل بالإنترنت. ستعمل لوحة ملخص البيانات بكامل طاقتها عندما تعود إلى وضع الاتصال بالإنترنت + field_name_on_form_name: '''%{field_name}" الحقل على "%{form_name}'' شكل.' + logout_confirmation: هل ترغب في متابعة العمل؟ logout_offline_warning: هل أنت متأكد أنك تريد تسجيل الخروج؟ إذا قمت بذلك ، فلن تتمكن من تسجيل الدخول مرة أخرى حتى تتصل بالإنترنت مرة أخرى. ستفقد أي تغييرات أجريتها بدون اتصال بالانترنت. logout_warning: سيتم تسجيل خروجك في 5 دقائق logout_dialog_header: تسجيل الخروج دون اتصال بالانترنت @@ -1596,6 +2093,7 @@ ar-JO: incidents: حوادث logout: تسجيل الخروج reports: تقارير + insights: رؤى search: بحث settings: 'إعدادات ' support: دعم @@ -1604,9 +2102,11 @@ ar-JO: code_of_conduct: القواعد السلوكية terms_of_use: شروط الاستخدام system_information: معلومات النظام + resync: التغييرات التي لم يتم اعتمادها في وضع عدم الاتصال بالانترنت tasks: مهام tracing_request: طلب التتبع activity_log: سجل النشاطات + registry_records: السجل notes: note_success: تم إضافة الملاحظة بنجاح permissions: @@ -1614,29 +2114,29 @@ ar-JO: permission: All: الكل add_note: إضافة ملاحظات - admin_only: لا توجد سجلات - وظائف المشرف فقط + admin_only: لا توجد سجلات - وظائف مسؤول النظام فقط administrator_read: قراءات عن المشرف agency: مؤسسة agency_read: وكالة قراءة all: الوصول لجميع السجلات أو المستخدمين approvals_assessment: '%{approval_label}' - approvals_assessment_pending: '%{approval_label}قيد الانتظار' + approvals_assessment_pending: '%{approval_label} قيد الانتظار' approvals_case_plan: '%{approval_label}' - approvals_case_plan_pending: '%{approval_label}قيد الانتظار' + approvals_case_plan_pending: '%{approval_label} قيد الانتظار' approvals_closure: '%{approval_label}' - approvals_closure_pending: '%{approval_label}قيد الانتظار' - approve_action_plan: مصادقة - approve_assessment: '%{approval_label}شكل' - approve_case_plan: مصادقة%{approval_label} - approve_closure: مصادقة%{approval_label}شكل - approve_gbv_closure: مصادقة%{approval_label}شكل + approvals_closure_pending: '%{approval_label} قيد الانتظار' + approve_action_plan: مصادقة %{approval_label} + approve_assessment: 'مصادقة نموذج %{approval_label} ' + approve_case_plan: مصادقة %{approval_label} + approve_closure: مصادقة نموذج %{approval_label} + approve_gbv_closure: مصادقة نموذج %{approval_label} assign: تعيين/نقل assign_within_agency: تعيين داخل المؤسسة assign_within_user_group: تعيين ضمن مجموعة المستخدم audit_log: سجل التدقيق case: حالة case_approvals: مصادقات الحالة - case_assignments_referrals_transfers: تعينات،إحالات،وتنقلات الحالة + case_assignments_referrals_transfers: تعينات، إحالات، وعمليات نقل الحالة case_exports: صادرات الحالة case_overview: حالاتي case_risk: الحالات حسب مستوى التقييم @@ -1663,15 +2163,15 @@ ar-JO: dash_referrals_by_socal_worker: عرض الإحالات التي قام بها الأخصائي الاجتماعي dash_reporting_location: عرض مواقع الإبلاغ dash_service_provisions: عرض تقديم الخدمات - dash_shared_from_my_team: تم مشاركتها مع مجموعتي - dash_shared_with_me: تم مشاركتها معي - dash_shared_with_my_team: تم مشاركتها مع مجموعتي - dash_shared_with_others: مشترك مع الآخرين - dash_show_none_values: مشاهدة بلا قيم + dash_shared_from_my_team: حالات مشاركة من مجموعتي مع المجموعات الأخرى + dash_shared_with_me: حالات مشاركة معي + dash_shared_with_my_team: حالات مشاركة مع مجموعتي + dash_shared_with_others: حالات مشاركة مع مجموعات أخرى + dash_show_none_values: اطلاع على القيم الصفرية dash_tasks: عرض المهام dash_transfers_by_socal_worker: عرض عمليات النقل التي قام بها الأخصائي الاجتماعي dash_national_admin_summary: ملخص المسؤول - dashboard: لوحة التحكم + dashboard: لوحة ملخص البيانات (داشبورد) delete: حذف display_view_page: عرض صفحة العرض duplicate: بحث مكرر @@ -1684,14 +2184,16 @@ ar-JO: export_list_view_csv: تصدير ملف عرض قائمة csv export_mrm_violation_xls: تصدير ملف انتهاك آلية الرصد والإبلاغ mrm بصيغة xls export_pdf: تصدير ملف pdf - export_photowall: تصدير ملف photowall + export_photowall: تحويل جدار صور export_unhcr_csv: تصدير ملف unhcr csv export_xls: تصدير ملف xls find_tracing_match: ايجاد أثر التطابق من القضية + view_registry_record: عرض سجل التسجيل + add_registry_record: اضافة سجل التسجيل flag: علامة form: نماذج group: 'الوصول لجميع السجلات أو المستخدمين في مجموعتي ' - group_read: قراءات عن المجموعة + group_read: قراءة مجموعة import: استيراد incident: حادثة incident_details_from_case: إضافة تفاصيل حادثة لحالة مستخدم آخر @@ -1699,6 +2201,7 @@ ar-JO: kpi: نبض / KPIs lookup: عمليات البحث manage: إدارة + mark_for_offline: وضع علامة على عدم الاتصال matching_configuration: تكوين المطابقة metadata: النماذج، البحث potential_match: تشابه محتمل @@ -1709,18 +2212,20 @@ ar-JO: receive_transfer: استلام النقل referral: يمكن استخدامها للإحالة referral_from_service: إحالة حالة من نموذج خدمة + registry_record: السجل remove_assigned_users: إزالة المستخدمين المعينين الآخرين (الإحالات) reopen: إعادة فتح report: تقرير + managed_report: رؤى request_approval: طلب للمصادقة - request_approval_action_plan: طلب%{approval_label}مصادقة - request_approval_assessment: طلب%{approval_label}مصادقة - request_approval_case_plan: طلب%{approval_label}مصادقة - request_approval_closure: طلب%{approval_label}مصادقة - request_approval_gbv_closure: طلب%{approval_label}مصادقة + request_approval_action_plan: 'طلب مصادقة على %{approval_label} ' + request_approval_assessment: طلب مصادقة على %{approval_label} + request_approval_case_plan: طلب مصادقة على %{approval_label} + request_approval_closure: طلب مصادقة على %{approval_label} + request_approval_gbv_closure: طلب مصادقة على %{approval_label} request_transfer: طلب نقل role: أدوار المستخدم - save_search: حفظ عمليات البحث + save_search: حفظ البحث saved_search: بحث محفوظ search_owned_by_others: البحث عن سجل الحالة من خلال مستخدم آخر self: الوصول لسجلاتي أو المستخدم فقط @@ -1728,7 +2233,7 @@ ar-JO: services_section_from_case: إضافة تقديم خدمة لحالة مستخدم آخر specific_roles: الوصول لقائمة أدوار المستخدم المحددة sync_external: تزامن مع نظام إدارة المعلومات الخارجية - sync_mobile: مزامنة مع جهاز المحمول + sync_mobile: وضع علامة على عدم الاتصال system: نظام tracing_request: طلب التتبع transfer: يمكن استخدامها للنقل @@ -1737,8 +2242,9 @@ ar-JO: view_approvals: 'عرض المصادقات ' view_assessment: عرض التقييم view_photo: عرض الصورة - view_protection_concerns_filter: عرض مرشح الأمور الخاصة بعملية الحماية + view_protection_concerns_filter: عرض تصفية الأمور الخاصة بعملية الحماية view_response: عرض الاستجابات + webhook: الويب هوك workflow: سير العمل - الحالات الفردية workflow_team: سير العمل - حالات الفرق write: كتابة @@ -1797,7 +2303,7 @@ ar-JO: kpi_time_from_case_open_to_close: explanation: القدرة على معرفة المدة التي تظل فيها الحالة مفتوحة لجميع الحالات التي يمكن للمستخدم الوصول إليها. label: الوقت من فتح القضية إلى إغلاقها - label: KPI + label: مؤشرات الأداء الرئيسية agency: actions: assign: @@ -1815,36 +2321,41 @@ ar-JO: write: explanation: القدرة على تعديل المعلومات حول المؤسسات. يرجى ملاحظة أن هذا ينطبق على جميع المؤسسات في النظام. label: تعديل + explanation: يمثل منظمة بها أعضاء يستخدمون بريميرو. توجد الوكالات بشكل مستقل عن مجموعات المستخدمين. label: مؤسسة audit_log: actions: read: explanation: يسمح للمستخدم بمشاهدة قائمة بجميع الإجراءات التي تم تنفيذها في النظام وتصفيتها ، مقسمة حسب المستخدم ونوع الإجراء ومعرف السجل ووقت الإجراء. هذا هو الأنسب للمسؤولين على المستوى الوطني أو على مستوى الوكالة ، لأن هذا يعرض الإجراءات التي يقوم بها جميع المستخدمين في النظام. يرجى ملاحظة أن سجل التدقيق لا يعرض معلومات التعريف الشخصية حول السجلات المتضمنة في كل إجراء. label: عرض + explanation: قائمة قابلة للتصفية لجميع الإجراءات التي تم تنفيذها في النظام. لا تتضمن أي معلومات تعريفية عن الحالات أو الحوادث أو طلبات البحث عن المفقودين. label: سجل التدقيق case: actions: add_note: explanation: يسمح للمستخدم بإضافة إدخال إلى النموذج الفرعي "ملاحظات" (يُطلق عليه أحيانًا "التعليقات"). يقوم المستخدم بذلك عن طريق النقر فوق الزر "إضافة ملاحظات" في صفحة عرض الحالة. هذا الإجراء مفيد بشكل خاص للمديرين الذين ليس لديهم القدرة على تحرير الحالات ، لكنهم يريدون إضافة تذكيرات إلى حالة لعامل الحالة. بهذه الطريقة ، فإن إضافة ملاحظة تشبه إضافة علم. ميزة إضافة ملاحظة هي أنه عندما يضيف المدير ملاحظة إلى حالة ما ، سيظهر إشعار على الحالة لعامل الحالة عندما يشاهد الحالة على أجهزتهم المحمولة. label: اضافة ملاحظة على الحالة + add_registry_record: + explanation: يسمح للمستخدم بربط سجل بحالة من نموذج تفاصيل السجل. يسمح أيضًا للمستخدم بإلغاء ربط أي سجل مرتبط بالحالة اساسا. + label: إضافة / تحديث سجل التسجيل من الحالة approve_action_plan: - explanation: يسمح للمدير بالموافقة على%{approval_label}لقضايا العاملين في قضيتهم. - label: مصادقة%{approval_label} + explanation: يسمح للمدير بالموافقة على %{approval_label} للمسؤولين عن الحالات. + label: مصادقة %{approval_label} approve_assessment: - explanation: يسمح للمدير بالموافقة على%{approval_label}لقضايا العاملين في قضيتهم. - label: مصادقة%{approval_label}شكل + explanation: يسمح للمدير بالموافقة على %{approval_label} للمسؤولين عن الحالات. + label: مصادقة نموذج %{approval_label} approve_bia: - explanation: يسمح للمدير بالموافقة على%{approval_label}لقضايا العاملين في قضيتهم. - label: مصادقة%{approval_label}نموذج + explanation: يسمح للمدير بالموافقة على %{approval_label} للمسؤولين عن الحالات. + label: مصادقة نموذج %{approval_label} approve_case_plan: - explanation: يسمح للمدير بالموافقة على%{approval_label}لقضايا العاملين في قضيتهم. - label: مصادقة%{approval_label} + explanation: يسمح للمدير بالموافقة على %{approval_label} للمسؤولين عن الحالات. + label: مصادقة %{approval_label} approve_closure: - explanation: يسمح للمدير بالموافقة على%{approval_label}لقضايا العاملين في قضيتهم. - label: مصادقة%{approval_label}نموذج + explanation: يسمح للمدير بالموافقة على %{approval_label} للمسؤولين عن الحالات. + label: مصادقة نموذج %{approval_label} approve_gbv_closure: - explanation: يسمح للمدير بالموافقة على%{approval_label}لقضايا العاملين في قضيتهم. - label: مصادقة%{approval_label}نموذج + explanation: يسمح للمدير بالموافقة على %{approval_label} للمسؤولين عن الحالات. + label: مصادقة نموذج %{approval_label} assign: explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الأصلي إلى أي مستخدم آخر في النظام. لا يلزم موافقة الطفل لهذا الإجراء. على عكس عمليات النقل ، لا يُمنح المستلم الفرصة لقبول المهمة أو رفضها. label: تعيين @@ -1895,7 +2406,7 @@ ar-JO: label: تصدير ملف حالة pdf export_photowall: explanation: يسمح للمستخدم بتصدير ملف من صفحة قائمة الحالة التي تحتوي على صور جميع الحالات المحددة. يستخدم هذا التصدير بشكل أساسي في أنشطة البحث عن الأسرة ولم شملها. نفذت فقط من صفحة قائمة الحالة. - label: تصدير ملف photowall + label: تصدير جدار الصور export_unhcr_csv: label: تصدير مفوضية الأمم المتحدة السامية لشؤون اللاجئين بتنسيق CSV export_xls: @@ -1912,9 +2423,13 @@ ar-JO: label: استيراد incident_details_from_case: explanation: القدرة على إضافة إدخال للنموذج الفرعي "تفاصيل الحادث" في حالة عثرت عليها في نتائج البحث ، ولكن لا يمكنك الوصول إليها. يقوم المستخدم بتنفيذ هذا الإجراء من صفحة نتائج البحث عن طريق تحديد حالة واحدة أو أكثر ، ثم تحديد "إضافة حادث" من قائمة الإجراءات. ثم يرى المستخدم نموذجًا يحتوي على جميع الحقول في النموذج الفرعي "تفاصيل الحادث" ، حيث يمكنه إدخال معلومات حول الخدمة وإرسالها. نظرًا لأنه لا يمكن تنفيذ هذا الإجراء إلا من صفحة نتائج البحث ، فمن المنطقي أن يحصل الدور على هذا الإذن فقط إذا كان لديه أيضًا إذن "البحث عن سجلات الحالة التي يملكها مستخدمون آخرون". - label: أضف تفاصيل الحادث إلى حالة مستخدم آخر من صفحة نتائج البحث + label: أضف تفاصيل الحادثة إلى حالة مستخدم آخر من صفحة نتائج البحث incident_from_case: - explanation: يسمح هذا الإذن للمستخدم بالنقر فوق الزر "إنشاء حادث". يؤدي هذا إلى وقوع حادث قد يحتوي على بعض المعلومات المنسوخة من الحالة. بالنسبة لحالات العنف القائم على النوع الاجتماعي ، يوجد هذا الزر أعلى صفحة حالة العرض ويتوافق مع المعلومات المتعلقة بالحالة ككل. في بعض سياقات تتبع الحوادث ، يوجد هذا الزر في نموذج فرعي "تفاصيل الحادث". في هذه الحالة ، قد يتم نسخ بعض المعلومات من النموذج الفرعي لتفاصيل الحادث حيث تم النقر فوق الزر ، وكذلك من الحالة ككل. بمعنى آخر. قد يحتوي الحادث الجديد الذي تم إنشاؤه على الحقل "نوع العنف" من النموذج الفرعي لتفاصيل الحادث الفردي ، ولكن قد يحتوي أيضًا على عمر وجنس الحالة نفسها. لاحظ أن هذا الإذن يسمح أيضًا للمستخدم بمشاهدة رابط للحادث الذي تم إنشاؤه. + explanation: 'يسمح هذا الإذن للمستخدم بالنقر فوق زر "إنشاء حادثة". يؤدي هذا إلى إنشاء حادثة و قد يحتوي على بعض المعلومات المنسوخة من سجل الحالة. + + بالنسبة لحالات العنف القائم على النوع الاجتماعي، يوجد هذا الزر أعلى صفحة حالة العرض ويتوافق مع المعلومات المتعلقة بالحالة ككل. + + في بعض سياقات تتبع الحوادث، يوجد هذا الزر في نموذج فرعي "تفاصيل الحادثة". في هذه الحالة ، قد يتم نسخ بعض المعلومات من النموذج الفرعي لتفاصيل الحادث حيث تم النقر فوق الزر ، وكذلك من الحالة ككل. بمعنى آخر. قد يحتوي الحادث الجديد الذي تم إنشاؤه على الحقل "نوع العنف" من النموذج الفرعي لتفاصيل الحادث الفردي ، ولكن قد يحتوي أيضًا على عمر وجنس الحالة نفسها. لاحظ أن هذا الإذن يسمح أيضًا للمستخدم بمشاهدة رابط للحادث الذي تم إنشاؤه.' label: إنشاء حادثة من حالة manage: explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة في الحالات. إذن "الإدارة" يعني أساسًا "كل شيء". @@ -1925,8 +2440,11 @@ ar-JO: receive_referral: explanation: يسمح للمستخدم بتلقي الإحالة. سيظهر المستخدمون الذين لديهم هذا الإذن كمستلمين محتملين لإجراء إحالة ، بينما لن يظهر المستخدمون الذين ليس لديهم هذا الإذن كمستلمين محتملين عندما يبحث شخص ما عن مستلم في نموذج الإحالة. label: تلقي الإحالة + receive_referral_different_module: + explanation: يسمح للمستخدم بتلقي إحالة لسجل تم إنشاؤه في وحدة نمطية مختلفة من بريميرو. سيظهر المستخدمون الذين لديهم هذا الإذن كمستلمين محتملين لإجراء إحالة لهذا السجل ، بينما لن يظهر المستخدمون الذين ليس لديهم هذا الإذن كمستلمين محتملين عندما يبحث شخص ما عن مستلم في نموذج الإحالة. + label: تلقي الإحالة من مستخدم في وحدة بريميرو مختلفة receive_transfer: - explanation: يسمح للمستخدم بتلقي تحويل. سيظهر المستخدمون الذين لديهم هذا الإذن كمستلمين محتملين لإجراء النقل ، بينما لن يظهر المستخدمون الذين ليس لديهم هذا الإذن كمستلمين محتملين عندما يبحث شخص ما عن مستلم في طريقة النقل. + explanation: يسمح للمستخدم بتلقي التحويل. سيظهر المستخدمون الذين لديهم هذا الإذن كمستلمين محتملين لإجراء النقل ، بينما لن يظهر المستخدمون الذين ليس لديهم هذا الإذن كمستلمين محتملين عندما يبحث شخص ما عن مستلم في طريقة النقل. label: استلام النقل referral: explanation: يسمح لمستخدم بمنح حق الوصول مؤقتًا إلى حالة لمستخدم آخر. سيتمكن مستلم الإحالة من تنفيذ جميع الإجراءات نفسها في الحالة المُحالة حيث سيكون بمقدوره القيام بذلك في حالاته الخاصة. عندما لا يحتاج المستلم إلى الوصول إلى الحالة ، يمكنه النقر فوق الزر "تم" في النموذج الفرعي الإحالات والتحويلات ، وسيفقد الوصول إلى الحالة. يمكنك فقط إحالة حالة إلى مستخدم له دور له القدرة على تلقي الإحالات. @@ -1941,23 +2459,23 @@ ar-JO: explanation: يسمح للمستخدم بفتح حالة مغلقة حاليًا. label: إعادة فتح request_approval_action_plan: - explanation: يسمح للمستخدم (عادة ما يكون عامل الحالة) بمطالبة مديره بالموافقة على حالتهم%{approval_label}. - label: طلب%{approval_label}مصادقة + explanation: يسمح للمستخدم (عادة ما يكون منسق الحالة) بمطالبة مديره بالموافقة على حالتهم %{approval_label}. + label: طلب مصادقة على %{approval_label} request_approval_assessment: - explanation: يسمح للمستخدم (عادة ما يكون عامل الحالة) بمطالبة مديره بالموافقة على حالتهم%{approval_label}. - label: طلب%{approval_label}مصادقة + explanation: يسمح للمستخدم (عادة ما يكون منسق الحالة) بمطالبة مديره بالموافقة على حالتهم %{approval_label}. + label: طلب مصادقة على %{approval_label} request_approval_bia: - explanation: يسمح للمستخدم (عادة ما يكون عامل الحالة) بمطالبة مديره بالموافقة على حالتهم%{approval_label}. - label: طلب%{approval_label}مصادقة + explanation: يسمح للمستخدم (عادة ما يكون منسق الحالة) بمطالبة مديره بالموافقة على حالتهم %{approval_label}. + label: طلب مصادقة على %{approval_label} request_approval_case_plan: - explanation: يسمح للمستخدم (عادة ما يكون عامل الحالة) بمطالبة مديره بالموافقة على حالتهم%{approval_label}. - label: طلب%{approval_label}مصادقة + explanation: يسمح للمستخدم (عادة ما يكون منسق الحالة) بمطالبة مديره بالموافقة على حالتهم %{approval_label}. + label: طلب مصادقة على %{approval_label} request_approval_closure: - explanation: يسمح للمستخدم (عادة ما يكون عامل الحالة) بمطالبة مديره بالموافقة على حالتهم%{approval_label}. - label: طلب%{approval_label}مصادقة + explanation: يسمح للمستخدم (عادة ما يكون عامل الحالة) بمطالبة مديره بالموافقة على حالتهم %{approval_label}. + label: طلب مصادقة على %{approval_label} request_approval_gbv_closure: - explanation: يسمح للمستخدم (عادة ما يكون عامل الحالة) بمطالبة مديره بالموافقة على حالتهم%{approval_label}. - label: طلب%{approval_label}مصادقة + explanation: يسمح للمستخدم (عادة ما يكون عامل الحالة) بمطالبة مديره بالموافقة على حالتهم %{approval_label}. + label: طلب مصادقة على %{approval_label} request_transfer: explanation: يكشف عن زر "طلب نقل" الموجود على "طريقة العرض". يتيح الزر للمستخدم إرسال رسالة تحتوي على ملاحظة مخصصة عبر البريد الإلكتروني إلى مالك السجل الحالي للقضية ، ويطلب من مالك السجل نقل الحالة إلى المستخدم الذي أرسل الطلب. يعد هذا مفيدًا في السياقات التي يغير فيها الأطفال المواقع كثيرًا ، ويحتاج العاملون في الحالة إلى عامل الحالة السابق للطفل لإرسال معلومات حول الطفل لتجنب إنشاء سجل مكرر. label: طلب نقل @@ -1974,17 +2492,23 @@ ar-JO: explanation: القدرة على مزامنة سجل مع نظام إدارة معلومات خارجي label: تزامن مع نظام إدارة المعلومات الخارجية sync_mobile: - explanation: يسمح هذا الإذن بشكل عام للمستخدم باستخدام تطبيق الهاتف المحمول. أولاً ، يسمح للمستخدم بمشاهدة إجراءات "Mark for Mobile" و "Un-mark for Mobile" ، والتي تظهر في قائمة الحالات وصفحات عرض الحالة. يشير وضع علامة على حالة للجوال إلى أنه يجب مزامنة المعلومات المتعلقة بهذه الحالة بين الجهاز المحمول للمستخدم وتطبيق الويب ، بينما يؤدي إلغاء تحديد حالة للجوال إلى إيقاف حدوث هذه المزامنة. لا يمكن للمستخدمين الذين ليس لديهم هذا الإذن أيضًا مزامنة أجهزتهم المحمولة مع تطبيق الويب بشكل عام ، مما يعني أنهم لا يستطيعون استخدام تطبيق الهاتف لإدارة الحالات. - label: مزامنة مع جهاز المحمول + explanation: يسمح للمستخدم بالتخزين المؤقت للحالات للاستخدام في وضع عدم الاتصال. + label: وضع علامة على عدم الاتصال transfer: explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الحالي إلى أي مستخدم في النظام لديه القدرة على تلقي عمليات النقل. ومع ذلك ، لا يتغير مالك سجل الحالة إلى أن "يقبل" مستلم التحويل. إذا "رفض" المستلم التحويل بدلاً من ذلك ، يفقد المستلم إمكانية الوصول إلى الحالة ، ويحتفظ بمالك السجل الأصلي. - label: نقل + label: نقل حالة view_photo: explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الحالي إلى أي مستخدم في النظام لديه القدرة على تلقي عمليات النقل. ومع ذلك ، لا يتغير مالك سجل الحالة إلى أن "يقبل" مستلم التحويل. إذا "رفض" المستلم التحويل بدلاً من ذلك ، يفقد المستلم إمكانية الوصول إلى الحالة ، ويحتفظ بمالك السجل الأصلي. label: عرض الصورة من عرض قائمة الحالة view_incident_from_case: explanation: '"عند عرض الحالة ، يمكن للمستخدم الاطلاع على قائمة بالأحداث المرتبطة بالحالة ، بالإضافة إلى بعض المعلومات الموجزة حول كل منها.' label: عرض الحوادث من القضية + view_protection_concerns_filter: + explanation: يسمح للمستخدم بمشاهدة عامل التصفية مخاوف الحماية في صفحة قائمة الحالات. + label: اعرض عامل التصفية مخاوف الحماية في صفحة قائمة الحالات + view_registry_record: + explanation: يسمح للمستخدم بعرض معلومات أي سجل مرتبط بحالة. يسمح أيضًا للمستخدم بمشاهدة نموذج تفاصيل السجل على الحالة. + label: عرض سجل التسجيل من الحالة write: explanation: القدرة على النقر فوق الزر "تعديل" وتحديث المعلومات في الحالة والنقر فوق "حفظ" label: تعديل @@ -1994,42 +2518,46 @@ ar-JO: list_case_names: explanation: 'لا يمكن للمديرين عادةً رؤية أسماء الحالات في قائمة الحالات. إذا حصل المدير على هذا الإذن ، فسيكون قادرًا على رؤية الأسماء في القائمة. ' label: إذا كان المدير ، يمكنه رؤية أسماء الحالات في قائمة الحالة. + mark_for_offline: + explanation: يسمح للمستخدم بالتخزين المؤقت للحالة للاستخدام في وضع عدم الاتصال. + label: وضع علامة على عدم الاتصال + explanation: يمثل طفلاً فرديًا أو ناجٍ أو مستفيد آخر. label: حالة dashboard: actions: approvals_action_plan: explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على خطة العمل المعلقة أو الموافق عليها أو المرفوضة. - label: عامل الحالة%{approval_label}الموافقات + label: موافقات منسق الحالات عن %{approval_label} الحالة . approvals_action_plan_pending: explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على خطة العمل المعلقة. - label: مدير%{approval_label}الموافقات + label: موافقات المشرف عن %{approval_label} الحالة . approvals_assessment: explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على التقييم المعلقة أو الموافق عليها أو المرفوضة - label: عامل الحالة%{approval_label}الموافقات + label: موافقات منسق الحالات عن %{approval_label} الحالة . approvals_assessment_pending: explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على التقييم المعلقة. - label: مدير%{approval_label}الموافقات + label: موافقات المشرف عن %{approval_label} الحالة . approvals_case_plan: explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على خطة الحالة المعلقة أو الموافق عليها أو المرفوضة. - label: عامل الحالة%{approval_label}الموافقات + label: موافقات منسق الحالات عن %{approval_label} الحالة . approvals_case_plan_pending: explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على خطة الحالة المعلقة. - label: مدير%{approval_label}الموافقات + label: موافقات المشرف عن %{approval_label} الحالة . approvals_closure: explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة الإغلاق المعلقة أو الموافق عليها أو المرفوضة. - label: عامل الحالة%{approval_label}الموافقات + label: موافقات منسق الحالات عن %{approval_label} الحالة . approvals_closure_pending: explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على الإغلاق المعلقة. - label: مدير%{approval_label}الموافقات + label: موافقات المشرف عن %{approval_label} الحالة . approvals_gbv_closure: explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على إغلاق العنف القائم على النوع الاجتماعي والتي هي في انتظار المراجعة أو الموافقة عليها أو المرفوضة. - label: عامل الحالة%{approval_label}الموافقات + label: موافقات منسق الحالات عن %{approval_label} الحالة . approvals_gbv_closure_pending: explanation: يوضح عدد الحالات في فريق المدير مع طلبات الموافقة المعلقة لإغلاق العنف القائم على النوع الاجتماعي. - label: مدير%{approval_label}الموافقات + label: موافقات المشرف عن %{approval_label} الحالة . case_overview: - explanation: نظرة عامة على بطاقة لوحة المعلومات في الجزء العلوي من الصفحة الرئيسية ، والتي تتضمن أرقامًا مثل الإجمالي والحالات الجديدة - label: نظرة عامة على لوحة القيادة + explanation: نظرة عامة على بطاقة لوحة ملخص البيانات في الجزء العلوي من الصفحة الرئيسية ، والتي تتضمن أرقامًا مثل الإجمالي والحالات الجديدة + label: نظرة عامة على لوحة ملخص البيانات case_risk: explanation: يظهر عدد الحالات في كل مستوى خطر. label: الحالات حسب مستوى الخطورة @@ -2046,13 +2574,12 @@ ar-JO: explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام الخدمة لكل واحد من العاملين في الحالة. label: مهام الخدمة المتأخرة dash_case_incident_overview: - explanation: . label: نظرة عامة - حالاتي / الحوادث dash_cases_by_social_worker: explanation: الجدول الذي يوضح كيفية العدد الإجمالي للحالات المفتوحة وعدد الحالات الجديدة التي يديرها كل مستخدم في مجموعات المستخدمين الحالية. يمثل كل صف مستخدمًا في مجموعات المستخدمين الخاصة بالمستخدم الحالي ، بينما يمثل "الإجمالي" و "الجديد" عمودين. label: عرض الحالات حسب الأخصائي الاجتماعي dash_cases_to_assign: - explanation: 'هام: للمديرين فقط. يعرض عدد الحالات التي يمتلكها المستخدم الحالي مباشرةً (يجب أن يكون مديرًا). تفترض لوحة المعلومات هذه أن المديرين لا يديرون حالاتهم الخاصة ، وأنه إذا كان لدى المدير حالاتهم الخاصة ، فيجب عليهم تعيين هذه الحالات لموظفي الحالة في فريقهم.' + explanation: 'هام: للمديرين فقط. يعرض عدد الحالات التي يمتلكها المستخدم الحالي مباشرةً (يجب أن يكون مديرًا). تفترض لوحة ملخص البيانات هذه أن المديرين لا يديرون حالاتهم الخاصة ، وأنه إذا كان لدى المدير حالاتهم الخاصة ، فيجب عليهم تعيين هذه الحالات لموظفي الحالة في فريقهم.' label: (للمديرين) الحالات التي أحتاج إلى تعيينها لأشخاص في فريقي dash_flags: explanation: يعرض قائمة بالعلامات التي أضافها المستخدمون الآخرون إلى سجلاتي ، بالإضافة إلى العلامات التي أضفتها إلى سجلات المستخدمين الآخرين. @@ -2061,39 +2588,48 @@ ar-JO: explanation: يُظهر للمدير عدد الحالات المفتوحة والمغلقة التي يديرها المستخدمون في فريقهم. label: حالات مجموعاتي dash_matching_results: - explanation: إهمال. لوحة القيادة هذه غير وظيفية وستتم إزالتها في الإصدار 2. + explanation: إهمال. لوحة ملخص البيانات هذه غير وظيفية وستتم إزالتها في الإصدار 2. label: عرض النتائج المطابقة dash_protection_concerns: explanation: الجدول الذي يوضح عدد الحالات التي لها كل مخاوف تتعلق بالحماية. يمثل كل صف في الجدول أحد الشواغل المتعلقة بالحماية ، بينما تشير الأعمدة إلى حالات مختلفة للحالات ("كل الحالات" ، "الحالات المفتوحة" ، "الجديدة (هذا الأسبوع)" ، "مغلقة (هذا الأسبوع)") label: القضايا حسب اهتمامات الحماية dash_protection_concerns_by_location: - explanation: هذا هو نفس لوحة معلومات "عرض مخاوف الحماية" ، باستثناء أنه يمكن للمستخدم تحديد موقع من القائمة المنسدلة لعرض إحصائيات حول انتشار مخاوف الحماية في هذا الموقع فقط. + explanation: هذه هي نفس لوحة ملخص البيانات "عرض مخاوف الحماية" ، باستثناء أنه يمكن للمستخدم تحديد موقع من القائمة المنسدلة لعرض إحصائيات حول انتشار مخاوف الحماية في هذا الموقع فقط. label: عرض مخاوف الحماية حسب الموقع dash_reporting_location: explanation: الجدول الذي يوضح عدد الحالات الموجودة في كل موقع (على مستوى واحد من الخصوصية مثل "مقاطعة" أو "منطقة"). كل صف في الجدول عبارة عن موقع ، وتشير الأعمدة إلى حالات مختلفة للحالات ("OPEN CASES" ، "NEW (LAST WEEK)" ، جدي (هذا الأسبوع)" ، "CLOSED (LAST WEEK) ،" "CLOSED (هذا الاسبوع)"). تستخدم عادة لحسابات المدير أو المسؤول. label: الحالات عن طريق الإبلاغ عن الموقع dash_service_provisions: - explanation: يعرض عدد الحالات التي قام فيها مستخدمون آخرون بإضافة تقديم خدمة لهم. يظهر هذا الرقم في القسم الرئيسي من لوحة المعلومات. + explanation: يعرض عدد الحالات التي قام فيها مستخدمون آخرون بإضافة تقديم خدمة لهم. يظهر هذا الرقم في القسم الرئيسي من لوحة ملخص البيانات (داشبورد) label: الحالات حسب نوع تقديم الخدمة dash_shared_from_my_team: explanation: يُظهر للمدير عدد الحالات التي يديرها كل مستخدم في فريقه ، والتي تتم إحالتها أو نقلها إلى مستخدمين آخرين. - label: تم مشاركتها مع مجموعتي + label: حالات مشاركة من مجموعتي مع المجموعات الأخرى dash_shared_with_me: explanation: يوضح عدد الحالات التي تم إحالتها أو تحويلها إليك. - label: تم مشاركتها معي + label: حالات مشاركة معي dash_shared_with_my_team: explanation: يُظهر للمدير عدد الحالات التي تمت إحالتها أو نقلها إلى كل مستخدم في فريقه. - label: مشترك مع فريقي + label: حالات مشاركة مع مجموعتي dash_shared_with_my_team_overview: - label: تم مشاركته مع فريقي (نظرة عامة) + label: حالات مشاركة مع مجموعتي (نظرة عامة) dash_shared_with_others: explanation: يوضح عدد حالاتي التي تحتوي على إحالات نشطة أو عمليات نقل معلقة أو تحويلات مرفوضة. ليس عادةً للمديرين ، ما لم يديروا القضايا بأنفسهم. - label: مشترك مع الآخرين + label: حالات مشاركة مع مجموعات أخرى + dash_violations_category_verification_status: + explanation: 'يُظهر عدد انتهاكات MRM من كل نوع والتي تم تصنيفها حسب وضع التحقق ' + label: MRM - عدد الانتهاكات لكل حالة تحقق + dash_violations_category_region: + explanation: يوضح عدد انتهاكات MRM التي حدثت في كل منطقة ، مقسمة حسب نوع الانتهاك. + label: MRM - عدد الانتهاكات لكل منطقة + dash_perpetrator_armed_force_group_party_names: + explanation: يُظهر عدد انتهاكات MRM من كل نوع والتي تم تصنيفها حسب المسيء + label: MRM - عدد الانتهاكات حسب المسيء dash_show_none_values: - explanation: يضيف فئة "بلا مستوى مخاطرة" إضافية إلى جميع لوحات المعلومات التي تقسم الحالات حسب مستوى المخاطرة. هذا مخصص بشكل خاص للتكوينات التي تحتوي على خيار "بلا مخاطر" رابع لحقول مستوى المخاطرة. - label: عرض الحالات ذات "مستوى عدم وجود مخاطر" في لوحة معلومات التقييم + explanation: يضيف فئة "بلا مستوى مخاطرة" إضافية إلى جميع لوحات ملخص البيانات التي تقسم الحالات حسب مستوى المخاطرة. هذا مخصص بشكل خاص للتكوينات التي تحتوي على خيار "بلا مخاطر" رابع لحقول مستوى المخاطرة. + label: عرض الحالات ذات "مستوى عدم وجود مخاطر" في لوحة ملخص بيانات (داشبورد) التقييم dash_tasks: - explanation: يسمح للمستخدم برؤية صفحة المهام. يجب استخدام هذا للعاملين في الحالة ومقدمي الخدمات ، حيث ستكون الأرقام مخصصة للحالات التي تديرها بشكل مباشر. يجب على المديرين بدلاً من ذلك الحصول على لوحة التحكم "عرض الحالات حسب المهمة المتأخرة" ، لأن هذا يتيح لهم رؤية المهام المتأخرة لكل شخص في مجموعات المستخدمين الخاصة بهم. + explanation: يسمح للمستخدم برؤية صفحة المهام. يجب استخدام هذا للعاملين في الحالة ومقدمي الخدمات ، حيث ستكون الأرقام مخصصة للحالات التي تديرها بشكل مباشر. يجب على المديرين بدلاً من ذلك الحصول على لوحة ملخص بيانات "عرض الحالات حسب المهمة المتأخرة" ، لأن هذا يتيح لهم رؤية المهام المتأخرة لكل شخص في مجموعات المستخدمين الخاصة بهم. label: صفحة المهام dash_national_admin_summary: explanation: يظهر إجمالي الحالات المفتوحة في النظام ، وعدد الحالات الجديدة التي تم إنشاؤها في كل من الأسبوعين الماضيين ، وعدد الحالات التي تم إغلاقها في كل من الأسبوعين الماضيين. @@ -2107,7 +2643,8 @@ ar-JO: workflow_team: explanation: يسمح للمدير برؤية جدول يوضح عدد حالات الأخصائيين الاجتماعيين في كل مرحلة من مراحل إجراءات إدارة الحالة label: الحالات حسب سير العمل وعامل الحالة - label: لوحة التحكم + explanation: تملي المعلومات الموجزة التي تظهر على الصفحة الرئيسية. + label: لوحة ملخص البيانات (داشبورد) disabled: explanation: إذا قمت بتعطيل هذا الدور ، فلن تتمكن بعد الآن من تعيينه إلى حسابات المستخدمين. label: مُعطله @@ -2116,6 +2653,7 @@ ar-JO: read: explanation: يسمح للمستخدم بإجراء بحث متقدم لجميع الحالات في النظام ، باستخدام عدد من المعايير ، بما في ذلك الاسم واللقب والجنس والعمر والجنسية. label: عرض + explanation: بحث متقدم عن لدور المديرين في النظام. label: بحث مكرر forms: case: @@ -2127,6 +2665,9 @@ ar-JO: tracing_request: explanation: 'تقييد وصول المستخدم إلى النماذج في طلبات التتبع يحد من المعلومات التي يمكن للمستخدم رؤيتها في طلب التتبع. على سبيل المثال ، إذا كان المستخدم لديه حق الوصول إلى نموذج مالك السجل فقط ، فسيكون أيضًا قادرًا فقط على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج. إذا كان المستخدم الحالي لديه وصول محدود إلى النموذج ولديه القدرة على إدارة تكوين النموذج ، فإن تقييد وصوله إلى النموذج يحد أيضًا من النماذج التي يمكنه تكوينها. ملاحظة: إذا لم يتم تحديد أي نماذج ، فهذا يعني أن الدور لديه حق الوصول إلى كافة النماذج الخاصة بطلبات التتبع.' label: نماذج - طلب التتبع + registry_record: + explanation: 'تقييد وصول المستخدم إلى النماذج الخاصة بطلبات التتبع يحد من المعلومات التي يمكن للمستخدم رؤيتها في أي حادث. على سبيل المثال ، إذا كان المستخدم لديه حق الوصول إلى نموذج مالك السجل فقط ، فسيكون أيضًا قادرًا فقط على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج. إذا كان المستخدم الحالي لديه وصول محدود إلى النموذج ولديه القدرة على إدارة تكوين النموذج ، فإن تقييد وصوله إلى النموذج يحد أيضًا من النماذج التي يمكنه تكوينها. ملاحظة: إذا لم يتم تحديد أي نماذج ، فهذا يعني أن الدور لديه حق الوصول إلى جميع نماذج الحوادث.' + label: النماذج - التسجيل group: actions: admin_only: @@ -2152,7 +2693,7 @@ ar-JO: explanation: يمكن للمستخدم رؤية محفوظات لجميع التغييرات التي تم إجراؤها على السجل منذ إنشائه. يتضمن هذا القيم المسجلة لجميع الحقول. label: 'سجل التغيير ' create: - explanation: القدرة على خلق حادثة. + explanation: القدرة على إنشاء حادثة. label: إنشاء enable_disable_record: explanation: القدرة على تعطيل أو تمكين حادث. لا تظهر الحوادث "المعطلة" بشكل افتراضي في قائمة الحوادث. يمكن للمستخدمين رؤية الحوادث المعطلة في قائمة الحوادث من خلال تطبيق مرشح. @@ -2168,6 +2709,9 @@ ar-JO: export_incident_recorder_xls: explanation: يمكن للمستخدم إنشاء ملف تصدير XLS متخصص يسمح بتبادل البيانات باستخدام أداة GBV Incident Recorder. label: تصدير سجل الحادثة بامتداد XLS + export_mrm_violation_xls: + explanation: يمكن للمستخدم إنشاء تصدير Excel (ملف XLS) متخصص لانتهاكات MRM. هذا الإجراء متاح في صفحة عرض الحوادث وقائمة الحوادث. + label: تصدير انتهاكات MRM إلى Excel (ملف XLS) export_json: explanation: يمكن للمستخدم إنشاء ملف تصدير JSON من قائمة الحوادث أو صفحات عرض الحوادث ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ، لحادث واحد أو متعدد أو لجميع الحوادث التي يمكن للمستخدم الوصول إليها. يستخدم هذا التصدير بشكل أساسي لأولئك الذين يرغبون في تصدير الحوادث من نظام Primero الحالي ثم استيرادها إلى نظام Primero مختلف ، أو إلى نظام إدارة معلومات آخر. تنسيق JSON قابل للقراءة آليًا وغير عملي لمعظم المستخدمين. label: تصدير JSON @@ -2198,21 +2742,34 @@ ar-JO: write: explanation: القدرة على النقر فوق الزر "تحرير" وتحديث المعلومات حول الحادث والنقر فوق "حفظ". كما يسمح للمستخدم بتعطيل أو تمكين حادث. label: تعديل + explanation: يمثل الحدث الذي وقع. عادة ما تكون هذه حوادث إساءة أو عنف ، على الرغم من أنها يمكن أن تتوافق أيضًا مع أحداث مثل المواجهات مع سلطات إنفاذ القانون. غالبًا ما ترتبط الحوادث بالحالات. label: حادثة is_manager: - explanation: ينطبق على أي دور مستخدم يشرف عمومًا على مستخدمين آخرين. يسمح هذا للمستخدم بمشاهدة لوحات المعلومات والفلاتر التي تساعد المستخدم في إدارة فريق. - label: هل المدير؟ + explanation: ينطبق على أي دور مستخدم يشرف عمومًا على مستخدمين آخرين. يسمح هذا للمستخدم بمشاهدة لوحات ملخص البيانات (داشبورد) والفلاتر التي تساعد المستخدم في إدارة فريق. + label: هل هو مدير؟ + managed_report: + actions: + violations: + label: الانتهاكات + gbv_statistics: + label: احصاءات GBV + ghn_report: + label: المذكرة الافقية الشاملة + individual_children: + label: الأطفال الفرديين matching_configuration: actions: manage: explanation: القدرة على التحكم في الحقول التي تتم مقارنتها للعثور على التطابقات بين طلب التتبع والحالات. نظرًا لأن هذا يتحكم في كيفية تشغيل المطابقة في النظام بأكمله ، يجب أن يكون هذا الإذن متاحًا بشكل عام فقط لمسؤول النظام. label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: يتحكم في الحقول المستخدمة لمقارنة طلبات التتبع بالحالات أثناء تتبع الأسرة ولم شملها. label: تكوين المطابقة metadata: actions: manage: explanation: القدرة على إنشاء وتحرير وترجمة وحذف النماذج وحقول النماذج وعمليات البحث. يرجى ملاحظة أن المستخدم الذي لديه هذا الإذن سيكون قادرًا فقط على إدارة النماذج التي يمكنه الوصول إليها. على سبيل المثال ، إذا كان المسؤول الوطني لديه القدرة فقط على رؤية نموذج مالك السجل في الحالات ، فلن يتمكن إلا من تحديث التكوين لهذا النموذج. label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: يتحكم في القدرة على تكوين نماذج وحقول Primero ، بالإضافة إلى خيارات البحث المستخدمة داخلها. label: النماذج، البحث module: actions: @@ -2229,6 +2786,15 @@ ar-JO: read: explanation: يمثل الرابط بين طلب التعقب والحالة. يعد الوصول إلى التطابقات المحتملة أمرًا ضروريًا لأعمال تتبع الأسرة ولم شملها (FTR). يسمح للمستخدم بمشاهدة نموذج ملخص التتبع في الحالات. label: عرض + view_audio: + explanation: يتحكم في ما إذا كان المستخدم الذي يبحث عن تطابق تتبع يمكنه رؤية الملفات الصوتية للحالة أو طلب التتبع المرتبط بالمطابقة المحتملة. + label: عرض الملف الصوتي + view_photo: + explanation: يتحكم في ما إذا كان المستخدم الذي يبحث عن تطابق تتبع يمكنه رؤية الصور الخاصة بالحالة أو طلب التتبع المرتبط بالمطابقة المحتملة. + label: عرض الصور + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على المطابقات المحتملة. إذن "الإدارة" يعني أساسًا "كل شيء". + label: ادارة label: تشابه محتمل primero_configuration: actions: @@ -2242,6 +2808,43 @@ ar-JO: explanation: هذا يعني أن الدور سيظهر كخيار لـ "نوع المستلم" عندما يقوم المستخدم بإحالة خارجية. إذا اختار المستخدم هذا الدور كنوع الإحالة ، فإن التصدير الذي ينشئه Primero عندما يرسل المستخدم الإحالة سيحتوي فقط على المعلومات الموجودة في النماذج التي يمكن لهذا الدور الوصول إليها. لذلك ، على سبيل المثال ، إذا اختار المستخدم "مزود الخدمة الطبية" كنوع المستلم ، وكان دور مقدم الخدمة الطبية لديه حق الوصول فقط إلى نماذج الهوية الأساسية ومخاوف الحماية ، فإن ملف التصدير الذي يصدره Primero للإحالة الخارجية سيكون فقط تحتوي على الحقول الموجودة في هذين الشكلين. label: هل يمكن استخدام هذا الدور للإحالات الخارجية؟ label: إحالة + registry_record: + actions: + change_log: + explanation: يمكن للمستخدم رؤية تاريخ التغييرات التي تم إجراؤها على السجل منذ إنشائه. يتضمن هذا القيم المسجلة لجميع الحقول. + label: 'سجل التغيير ' + create: + explanation: القدرة على إنشاء سجل التسجيل. + label: انشاء + enable_disable_record: + explanation: القدرة على تعطيل أو تمكين سجل التسجيل. لا تظهر السجلات "المعطلة" بشكل افتراضي في قائمة التسجيل. يمكن للمستخدمين رؤية سجلات التسجيل المعطلة في قائمة التسجيل باستخدام عامل تصفية. + label: تفعيل / تعطيل + export_csv: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف CSV من قائمة السجل أو صفحات عرض السجل ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ، لسجل واحد أو متعدد أو جميع سجلات السجل التي يمكن للمستخدم الوصول إليها. ملاحظة: لا يعرض تصدير CSV الأحرف غير اللاتينية (مثل العربية والبنغالية)' + label: تصدير ملف إلى CSV + export_json: + explanation: يمكن للمستخدم إنشاء تصدير ملف JSON من قائمة التسجيل أو صفحات عرض السجل ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها. تنسيق JSON قابل للقراءة آليًا وغير عملي لمعظم المستخدمين. + label: تصدير JSON + export_xls: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف XLS من قائمة التسجيل أو صفحات عرض السجل ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها. ملاحظة: يعرض تنسيق XLS الأحرف غير اللاتينية (مثل العربية والبنغالية) بتنسيق قابل للقراءة ، بينما لا يعرض تنسيق CSV.' + label: تصدير ملف Excel (ملف XLS) + flag: + explanation: القدرة على إضافة علامة إلى سجل التسجيل. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي قاموا بإضافتها إلى سجل التسجيل. + label: علامة + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على سجلات التسجيل. إذن "الإدارة" يعني أساسًا "كل شيء". + label: إدارة (كل الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على رؤية سجل التسجيل. + label: عرض + write: + explanation: القدرة على النقر فوق الزر "تعديل" وتحديث المعلومات في الحالة والنقر فوق "حفظ" + label: تعديل + sync_mobile: + explanation: يسمح للمستخدم بالتخزين المؤقت لسجلات التسجيل للاستخدام في وضع عدم الاتصال. + label: وضع علامة على عدم الاتصال بالانترنت + explanation: يمكن أن يمثل هذا فردًا أو مؤسسة تحتاج إلى ربطها بسجلات أخرى مثل الحالات أو الحوادث ، وهي كثيرة جدًا ويتم تحديثها بشكل متكرر بمعلومات جديدة. إنها تشبه عمليات البحث ، ولكن مع مجموعة أكثر تعقيدًا من المعلومات لكل إدخال. + label: سجل التسجيل report: actions: create: @@ -2259,9 +2862,13 @@ ar-JO: write: explanation: القدرة على تحرير جميع التقارير (بما في ذلك تلك التي أنشأها مستخدمون آخرون). label: تعديل + agency_read: + explanation: القدرة على عرض جميع التقارير. ستعكس الأرقام الواردة في كل تقرير فقط تلك السجلات التي يمكن الوصول إليها من قبل المستخدمين في وكالة المستخدم الحالية. غالبًا ما يستخدم هذا الإذن لمسؤولي نظام الوكالة. + label: عرض (البيانات المستندة إلى المنظمة) + explanation: أداة تحليل البيانات المجمعة. يشمل تمثيلات الجدول والرسم البياني للبيانات. label: تقرير reporting_location_level: - explanation: 'سيتحكم هذا في مستوى المواقع التي تظهر لهذا الدور في لوحات المعلومات ، والفلاتر ، وشروط الإحالة ، وشروط النقل. إذا تركت هذا الحقل فارغًا ، فسيرى هذا الدور مستوى موقع الإبلاغ الافتراضي للنظام.' + explanation: 'سيتحكم هذا في مستوى المواقع التي تظهر لهذا الدور في لوحات ملخص البيانات (داشبورد) ، والفلاتر ، وشروط الإحالة ، وشروط النقل. إذا تركت هذا الحقل فارغًا ، فسيرى هذا الدور مستوى موقع الإبلاغ الافتراضي للنظام.' label: ما نوع الموقع الذي يجب استخدامه للإبلاغ عن هذا الدور؟ role: actions: @@ -2289,17 +2896,19 @@ ar-JO: write: explanation: القدرة على النقر فوق الزر "تحرير" في صفحة عرض الدور ، وتحديث أذونات الدور ، ثم حفظ الدور. label: تعديل + explanation: تملي الإجراءات التي يمكن للمستخدم تنفيذها في Primero. label: أدوار المستخدم system: actions: manage: explanation: القدرة على رؤية المعلومات وتحديثها على معلومات الاتصال بالنظام والإشعارات الافتراضية وإعدادات البريد الإلكتروني الترحيبية والخوادم المتزامنة. عادة ما يكون هذا الإذن محجوزًا لمسؤول النظام label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: إعدادات التكوين المتنوعة على مستوى النظام. label: نظام tracing_request: actions: change_log: - explanation: يمكن للمستخدم رؤية محفوظات لجميع التغييرات التي تم إجراؤها على السجل منذ إنشائه. يتضمن هذا القيم المسجلة لجميع الحقول. + explanation: يمكن للمستخدم رؤية التغييرات السابقة التي تم إجراؤها على السجل منذ إنشائه. يتضمن هذا القيم المسجلة لجميع الحقول. label: 'سجل التغيير ' create: explanation: القدرة على إنشاء طلب تتبع @@ -2323,8 +2932,11 @@ ar-JO: explanation: يمكن للمستخدم إنشاء تصدير ملف CSV من صفحة قائمة طلبات التتبع التي تحتوي على نفس الحقول التي تظهر لهذا المستخدم في قائمة طلبات التتبع. يتم إجراؤه فقط من صفحة قائمة طلبات التتبع. label: تصدير ملف عرض قائمة csv export_pdf: - explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة طلبات التتبع أو عرض صفحات طلب التتبع ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ، لسجل واحد أو متعدد أو جميع السجلات التي يمتلك المستخدم حق الوصول إليها. في ملف تصدير PDF ، يتم سرد المعلومات أولاً حسب الحالة ، ثم يتم تنظيمها بشكل أكبر حسب النموذج الذي تظهر عليه المعلومات. + explanation: يمكن للمستخدم إنشاء ملف تصدير PDF من قائمة طلبات التتبع أو عرض صفحات طلب التتبع ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ، لسجل واحد أو متعدد أو جميع السجلات التي يمتلك المستخدم حق الوصول إليها. في ملف تصدير PDF ، يتم سرد المعلومات أولاً حسب الحالة ، ثم يتم تنظيمها بشكل أكبر حسب النموذج الذي تظهر عليه المعلومات. label: تصدير ملف إلى PDF + export_xls: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف XLS من قائمة طلبات التتبع أو صفحات عرض طلب التتبع ، والتي تحتوي على جميع الحقول التي يمتلك المستخدم الحالي حق الوصول إليها ، لطلبات تتبع واحدة أو متعددة أو جميعها التي يمتلك المستخدم حق الوصول إليها. في هذا التصدير ، يتم تمثيل كل نموذج في علامة التبويب الخاصة به داخل ملف XLS. ملاحظة: يعرض تنسيق XLS الأحرف غير اللاتينية (مثل العربية والبنغالية) بتنسيق قابل للقراءة ، بينما لا يعرض تنسيق CSV.' + label: تصدير ملف Excel (ملف XLS) flag: explanation: القدرة على إضافة علم لطلب تتبع. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي قاموا بإضافتها إلى طلب التتبع. label: علامة @@ -2340,13 +2952,14 @@ ar-JO: write: explanation: القدرة على النقر فوق الزر "تحرير" ، وتحديث المعلومات حول طلب التتبع ، والنقر فوق "حفظ". كما يسمح للمستخدم بتعطيل أو تمكين طلب التتبع label: تعديل + explanation: يمثل فردًا يحاول تحديد مكانه وجمع شمله في حالة غير مصحوب أو منفصل. label: طلب التتبع transfer: actions: transfer: - explanation: هذا يعني أن الدور سيظهر كخيار لـ "نوع المستلم" عندما يقوم المستخدم بإحالة خارجية. إذا اختار المستخدم هذا الدور كنوع النقل ، فإن التصدير الذي ينشئه Primero عندما يرسل المستخدم النقل سيحتوي فقط على المعلومات الموجودة في النماذج التي يمكن لهذا الدور الوصول إليها. لذلك ، على سبيل المثال ، إذا اختار المستخدم "مزود الخدمة الطبية" كنوع المستلم ، وكان دور مقدم الخدمة الطبية لديه حق الوصول فقط إلى نماذج الهوية الأساسية ومخاوف الحماية ، فإن ملف التصدير الذي يصدره Primero للتحويل الخارجي سيكون فقط تحتوي على الحقول الموجودة في هذين الشكلين. + explanation: هذا يعني أن الدور سيظهر كخيار لـ "نوع المستلم" عندما يقوم المستخدم بإحالة خارجية. إذا اختار المستخدم هذا الدور كنوع النقل، فإن التصدير الذي ينشئه Primero عندما يرسل المستخدم النقل سيحتوي فقط على المعلومات الموجودة في النماذج التي يمكن لهذا الدور الوصول إليها. لذلك ، على سبيل المثال ، إذا اختار المستخدم "مزود الخدمة الطبية" كنوع المستلم ، وكان دور مقدم الخدمة الطبية لديه حق الوصول فقط إلى نماذج الهوية الأساسية ومخاوف الحماية ، فإن ملف التصدير الذي يصدره Primero للتحويل الخارجي سيكون فقط تحتوي على الحقول الموجودة في هذين الشكلين. label: هل يمكن استخدام هذا الدور للتحويلات الخارجية؟ - label: نقل + label: نقل حالة user: actions: agency_read: @@ -2364,6 +2977,7 @@ ar-JO: write: explanation: القدرة على النقر فوق الزر "تحرير" في صفحة إظهار المستخدم ، وتحديث المعلومات حول المستخدم ، ثم الحفظ. يرجى ملاحظة أن هذا الإذن يمنحك أيضًا القدرة على تعطيل حسابات المستخدمين. label: تعديل + explanation: يمثل حساب مستخدم فردي. label: مستخدمين user_group: actions: @@ -2385,11 +2999,28 @@ ar-JO: write: explanation: القدرة على تعديل مجموعات المستخدمين. label: تعديل + explanation: يمثل فريقًا أو مجموعة متعاونة من المستخدمين الذين يمكنهم مشاركة المعلومات. يمكن للمديرين عادةً رؤية جميع السجلات التي يديرها الأخصائيون الاجتماعيون في مجموعات المستخدمين الخاصة بهم. label: مجموعات المستخدمين + webhook: + actions: + read: + label: عرض + explanation: القدرة على سرد ومراجعة تكوينات webhook عبر واجهة برمجة التطبيقات + write: + label: تعديل + explanation: القدرة على إنشاء وتعديل تهيئة الرد التلقائي على الويب عبر واجهة برمجة التطبيقات + create: + explanation: القدرة على إنشاء تكوين webhook عبر واجهة برمجة التطبيقات. + label: انشاء + delete: + explanation: القدرة على حذف تكوين webhook عبر API. + label: حذف + manage: + label: إدارة (كل الأذونات لهذا النوع من الموارد) activity_log: actions: transfer: - explanation: يمكن للمستخدم النقر فوق قسم سجل النشاطات في لوحة التحكم والاطلاع على سجل بجميع عمليات النقل المقبولة أو المرفوضة للحالات التي يمكنهم الوصول إليها. + explanation: يمكن للمستخدم النقر فوق قسم سجل النشاطات في لوحة ملخص البيانات (داشبورد) والاطلاع على سجل بجميع عمليات النقل المقبولة أو المرفوضة للحالات التي يمكنهم الوصول إليها. label: عمليات النقل manage: label: إدارة (كل الأذونات لهذا النوع من الموارد) @@ -2411,16 +3042,16 @@ ar-JO: likelihood_likely: محتمل likelihood_possible: ممكن potential_matches: - display: عرض التطابقات المحتملة ل%{type}%{id} + display: عرض التطابقات المحتملة ل %{type} %{id} reassign: - multiple_error: حدث خطأ.%{select_records}لم يتم تعيين القضية (الحالات). - multiple_successfully: '%{select_records}تم تعيين الحالة (الحالات) بنجاح' + multiple_error: حدث خطأ. لم يتم تعيين %{select_records} الحالة (الحالات). notes_label: ملاحظات successfully: تمت عملية التعيين بنجاح user_mandatory_label: المستلم مطلوب users_label: مستلم record_information: assigned_user_names: 'المستخدمون المعينون الآخرون ' + created_at: تم إنشاء السجل في created_by: تم إنشاء السجل بواسطة created_organization: تم إنشاؤها من قبل مؤسسة current_owner_separator: المالك الحالي @@ -2432,6 +3063,8 @@ ar-JO: previously_owned_by_agency: المؤسسة السابقة reassigned_tranferred_on: إعادة التعيين / تم النقل في record_history_separator: تاريخ السجل + last_updated_at: تاريخ اخر تحديث + last_updated_by: تاريخ اخر تحديث record_panel: record_information: معلومات السجل referral: @@ -2459,18 +3092,19 @@ ar-JO: date: يوم month: شهر quarter: ربع - quarter_abbr: Q%{quarter} + quarter_abbr: ربع %{quarter} week: اسبوع - year: سنة + year: العام description: الوصف disabled: explanation: إذا عطلت هذا التقرير ، فلن يظهر في التقارير المتاحة. label: مُعطله + exclude_empty_rows: لا تعرض صفوف فارغة disaggregate_by: مجموعات حسب الأعمدة filters: label: الإبلاغ عن عوامل التصفية - label_new: مرشح تقرير جديد - attribute: عامل التصفية + label_new: فلتر تقرير جديد + attribute: عامل التصفية (فلتر) value: مع not_null: ليس فارغا؟ less_than: أقل من @@ -2480,7 +3114,7 @@ ar-JO: is: يكون before: قبل after: بعد - delete_filter_message: هل أنت متأكد أنك تريد حذف هذا المرشح؟ + delete_filter_message: هل أنت متأكد أنك تريد حذف هذا الفلتر؟ group_ages: استخدام نطاقات الأعمار group_dates_by: استخدام نطاقات التواريخ is_graph: هل تريد إنتاج مخطّط بياني؟ @@ -2492,7 +3126,7 @@ ar-JO: name: الاسم name_mandatory: 'مطلوب ادخال الاسم ' no_data: لا يوجد بيانات لهذا التقرير - no_filters_added: لم يتم إضافة أي مرشحات + no_filters_added: لم يتم إضافة أي تصفيات not_selected: لم يتم اختياره record_type: نوع السجل total: الإجمالي @@ -2506,6 +3140,7 @@ ar-JO: edit: تحرير الترجمات manage: إدارة الترجمات select_language: حدد اللغة + error_loading: خطأ في تحميل التقرير request_transfer: notes_label: ملاحظات submit_label: ارسل طلب @@ -2540,15 +3175,15 @@ ar-JO: label: أدوار saved_search: deleted: تم حذف عملية البحث بنجاح. - filters_tab: مرشحات - no_filters: لا توجد مرشحات محددة - save_success: تم حفظ عملية البحث بنجاح. - saved_searches_tab: عمليات البحث المحفوظة + filters_tab: تصفيات (فلاتر) + no_filters: لا توجد تصفيات محددة + save_success: تم حفظ البحث بنجاح. + saved_searches_tab: البحث المحفوظ title_description: هل أنت متأكد أنك تريد حذف عملية البحث المحفوظة؟ title_modal: حذف عمليات البحث المحفوظة saved_searches: no_save_searches: ليس لديك عمليات بحث محفوظة - save_search: حفظ عملية البحث + save_search: احفظ البحث settings: navigation: agencies: مؤسسات @@ -2583,7 +3218,7 @@ ar-JO: types: assessment: تقييم case_plan: خطة الحالة - follow_up: متابعة -%{subtype} + follow_up: متابعة - %{subtype} service: خدمة - %{subtype} tracing_request: label: طلب التتبع @@ -2596,16 +3231,25 @@ ar-JO: match: مطابق matches: مطابقات unmatch: غير متطابق + tracing_request_photos: صور من اجل طلب التتبع هذا + case_photos: صور لهذه الحالة + tracing_request_audios: ملف صوتي من اجل طلب التتبع هذا + case_audios: ملف صوتي لهذه الحالة messages: already_matched: يوجد بالفعل تطابق في النظام مع مستعلم يبحث عن هذا الطفل. disabled: طلب التعقب معطل nothing_found: لم يتم العثور على شيء update_success: 'تم تحديث طلب التتبع %{record_id} بنجاح. ' creation_success: تم إنشاء سجل طلب التتبع بنجاح. - update_success_queue: 'طلب البحث عن المفقودين%{record_id}تم تحديثه بنجاح في الخلفية.' + update_success_queue: 'طلب البحث عن المفقودين %{record_id} تم تحديثه بنجاح في الخلفية.' creation_success_queue: تم إنشاء سجل طلب التتبع بنجاح في الخلفية. - match_action: تم مطابقة التتبع بنجاح%{trace_id}مع حالة%{record_id}. - unmatch_action: تتبع غير متطابق بنجاح%{trace_id}والقضية%{record_id}. + match_action: تم مطابقة التتبع بنجاح %{trace_id} مع حالة %{record_id}. + unmatch_action: تتبع غير متطابق بنجاح %{trace_id} والحالة %{record_id}. + registry_record: + messages: + update_success: 'تم تحديث سجل التسجيل %{record_id} بنجاح.' + creation_success: 'تم إنشاء سجل التسجيل بنجاح.' + disabled: سجل التسجيل معطل tracing_requests: date_of_inquiry: تاريخ الاستعلام disable_dialog_title: تعطيل طلب التعقب @@ -2615,6 +3259,7 @@ ar-JO: enable_dialog_title: تمكين طلب التتبع enable_success: تم تمكين طلب التحويل بنجاح. id: مُعرف + complete: متاح بدون الاتصال بالانترنت filter_by: by_date: حسب التاريخ location_separation: موقع الانفصال @@ -2627,13 +3272,42 @@ ar-JO: register_new_tracing_request: 'طلب تتبع جديد ' selectable_date_options: inquiry_date: تاريخ الإستعلام - selected_records: '%{select_records}تم تحديد طلب (طلبات) التتبع' - selected_all_records: 'اختر الكل%{total_records}طلبات التعقب التي تطابق هذا الاستعلام.' - show_tracing_request: 'معرّف طلب التتبع%{short_id}' + selected_records: '%{select_records} تم تحديد طلب (طلبات) التتبع' + selected_all_records: 'اختر الكل %{total_records} طلبات التعقب التي تطابق هذا الاستعلام.' + show_tracing_request: 'معرّف طلب التتبع %{short_id}' tracing_requests: تتبع الطلبات export: 'تصدير ' + sort_by: ترتيب حسب + registry_records: + id: مُعرف + label: سجل التسجيل + name: الاسم + registry_no: رقم التسجيل + location: موقع + registration_date: تاريخ السجل + selected_records: '%{select_records} تم تحديد سجل (سجلات) التسجيل' + selected_all_records: 'حدد كافة سجلات التسجيل %{total_records} التي تطابق هذا الاستعلام.' + disable_dialog_title: تعطيل سجل التسجيل + disable_dialog: سيؤدي النقر فوق "موافق" إلى تغيير حالة سجل التسجيل هذا إلى معطل. + disable_success: تم تعطيل سجل التسجيل بنجاح + enable_dialog_title: تفعيل سجل التسجيل + enable_dialog: سيؤدي النقر فوق "موافق" إلى تغيير حالة سجل التسجيل هذا إلى مفعل. + enable_success: تم تفعيل سجل التسجيل بنجاح + complete: متاح بدون الاتصال بالانترنت + filter_by: + by_date: حسب التاريخ + status: الوضع + selectable_date_options: + registration_date: تاريخ التسجيل + show_registry_record: 'معرف سجل التسجيل: %{short_id}' + register_new_registry_record: سجل التسجيل جديد + export: تصدير + mark_for_offline: + title: وضع علامة على عدم الاتصال بالانترنت + text: هل أنت متأكد أنك تريد وضع علامة على سجلات التسجيل هذه لاستخدامها عندما تكون غير متصل؟ + success: تم وضع علامة على سجلات التسجيل بنجاح للاستخدام دون اتصال transfer: - label: نقل + label: نقل حالة agency_label: مؤسسة consent_from_individual_label: هل لديك موافقة من الفرد لإجراء هذا التحويل؟ consent_label: لم توفر السجلات الموافقة. @@ -2647,8 +3321,9 @@ ar-JO: success: تم النقل بنجاح transfer_label: نقل على أي حال؟ user_mandatory: المستلم مطلوب + rejected_reason: سبب الرفض transfer_assignment: - title: التحويلات والتخصيصات + title: عمليات النقل والتعيينات transition: agency_label: مؤسسة assigned_by: 'تعيين من قبل ' @@ -2662,7 +3337,7 @@ ar-JO: consent: لم يتم تقديم الموافقة to_user_can_receive: لا يمكن لهذا المستخدم استلام هذا السجل individual_consent: هل حصل عامل الحالة على موافقة الفرد لإجراء هذا النقل؟ - no_consent_share: الموافقة على مشاركة الإعداد الذي تم استبداله؟ + no_consent_share: هل تم تخطي نموذج الموافقة ؟ notes: ملاحظات recipient: مستلم rejected: سبب الرفض @@ -2681,7 +3356,7 @@ ar-JO: reassign: تعيين referral: إحالة external_referral: إحالة خارجية - transfer: نقل + transfer: نقل حالة transferRequest: طلب نقل user: agency_office: مكتب المؤسسة (موقع العنف المبني على النوع الاجتماعي) @@ -2699,8 +3374,8 @@ ar-JO: confirmation: 'هل أنت متأكد أنك تريد حذف هذا المستخدم؟ لا يمكن التراجع عن الحذف. انقر فوق موافق لحذف المستخدم. ' created: تم إنشاء المستخدم بنجاح. failure: حدث خطأ ، يرجى الاتصال بالدعم. - new_confirm_html: أنت على وشك دعوة المستخدم%{username}من عند%{identity}مع الدور%{role}لاستخدام Primero. سيتم إرسال بريد إلكتروني للتأكيد إلى%{email}. هل ترغب في المتابعة؟ - new_confirm_non_identity_html: أنت على وشك دعوة المستخدم%{username}مع الدور%{role}لاستخدام Primero. سيتم إرسال بريد إلكتروني للتأكيد إلى%{email}. هل ترغب في المتابعة؟ + new_confirm_html: أنت على وشك دعوة المستخدم %{username} من عند %{identity} مع الدور %{role} لاستخدام Primero. سيتم إرسال بريد إلكتروني للتأكيد إلى %{email}. هل ترغب في المتابعة؟ + new_confirm_non_identity_html: أنت على وشك دعوة المستخدم%{username} لدور%{role} لاستخدام النظام. سيتم إرسال رسالة تاكيد بالبريد الإلكتروني إلى%{email} هل ترغب في المتابعة؟ not_found: لم يتم العثور على مستخدم بهذا المُعرف password_changed_successfully: تم تغيير كلمة المرور بنجاح passwords_do_not_match: لا تطابق كلمة المرور الحالية @@ -2721,7 +3396,7 @@ ar-JO: password_confirmation: تأكيد كلمة المرور phone: هاتف position: وضع الحالة - provider_username_help: 'مثال: اسم المستخدم@ %{domain}' + provider_username_help: 'مثلا: %{domain}@my.username' role_id: دور send_mail: تلقي إشعارات البريد الإلكتروني؟ user_group_unique_ids: مجموعات المستخدم @@ -2730,26 +3405,27 @@ ar-JO: welcome_email: subject: 'اهلا وسهلاً في %{system}!' greeting: 'اهلا وسهلاً في %{system}!' - body_native: 'لقد تمت إضافتك كـ%{role_name}. الرجاء التواصل%{admin_full_name}(%{admin_email})لمتابعة التعليمات لبدء العمل معها%{host}.' + body_native: 'لقد تمت إضافتك كـ%{role_name}. الرجاء التواصل %{admin_full_name} (%{admin_email}) لمتابعة التعليمات لبدء العمل معها %{host}.' sso: body: 'لقد تمت إضافتك كـ%{role_name}.' - step1: 'اذهب إلى%{host}وانقر%{identity_provider}.' - step2: 'تسجيل الدخول مع الخاص بك%{identity_provider}حساب%{user_name}.' - step3: 'استخدم نفس كلمة المرور التي تستخدمها دائمًا لملف%{identity_provider}حساب.' - footer: 'الرجاء التواصل%{admin_full_name}(%{admin_email})لمزيد من التفاصيل.' + step1: 'اذهب إلى %{host} وانقر %{identity_provider}.' + step2: 'تسجيل الدخول مع الخاص بك %{identity_provider} حساب %{user_name}.' + step3: 'استخدم نفس كلمة المرور التي تستخدمها دائمًا لملف %{identity_provider} حساب.' + footer: 'الرجاء التواصل %{admin_full_name} (%{admin_email}) لمزيد من التفاصيل.' otp: body: 'لقد تمت إضافتك كـ%{role_name}.' - step1: 'الرجاء التواصل%{admin_full_name} (%{admin_email})لتلقي اسم المستخدم الخاص بك.' - step2: 'اذهب إلى%{host}وانقر على "تسجيل الدخول باسم مستخدم Primero.".' - step3: 'تسجيل الدخول باسم المستخدم وكلمة المرور المؤقتة%{otp}.' + step1: 'الرجاء التواصل %{admin_full_name} (%{admin_email}) لتلقي اسم المستخدم الخاص بك.' + step2: 'اذهب إلى %{host} وانقر على "تسجيل الدخول باسم مستخدم بريميرو.".' + step3: 'تسجيل الدخول باسم المستخدم وكلمة المرور المؤقتة %{otp}.' step4: 'عند المطالبة ، أعد تعيين كلمة المرور الخاصة بك.' url_label: بريميرو enabled_label: إرسال بريد إلكتروني ترحيبي؟ text_label: 'نص البريد الإلكتروني الترحيبي ' password_reset: - email_greeting: "عزيزي%{full_name}" + subject: 'تعليمات إعادة تعيين كلمة المرور' + email_greeting: "عزيزي %{full_name}" email_body1: "قدم شخص ما طلبًا لتعيين كلمة المرور الخاصة بك لـ%{host_href}. انقر فوق عنوان url أدناه للبدء:" - email_body2: "ستنتهي صلاحية هذا الرابط في%{hours}ساعات ويمكن استخدامها مرة واحدة فقط. يرجى تجاهل هذا البريد الإلكتروني إذا لم تكن قد طلبت إعادة تعيين كلمة المرور أو لم يتم تسجيل مستخدم Primero جديد نيابة عنك. إذا كان الرابط أعلاه منتهي الصلاحية ، الرجاء الضغط%{reset_request_href}لإعادة تقديم طلب إعادة تعيين كلمة المرور." + email_body2: "ستنتهي صلاحية هذا الرابط في %{hours} ساعات ويمكن استخدامها مرة واحدة فقط. يرجى تجاهل هذا البريد الإلكتروني إذا لم تكن قد طلبت إعادة تعيين كلمة المرور أو لم يتم تسجيل مستخدم Primero جديد نيابة عنك. إذا كان الرابط أعلاه منتهي الصلاحية ، الرجاء الضغط %{reset_request_href} لإعادة تقديم طلب إعادة تعيين كلمة المرور." email_body_link: هنا request_submitted: "تم إرسال طلب إعادة تعيين كلمة المرور" success: "تم تغيير كلمة السر بنجاح" @@ -2757,13 +3433,14 @@ ar-JO: reset_password_token: "رمز إعادة تعيين كلمة المرور غير صالح" password_confirmation: "كلمة السر يجب ان تتطابق" onboard_email: - subject: "على متن الطائرة الى%{system}" - greeting: "عزيزي%{full_name}," + subject: "على متن الطائرة الى %{system}" + greeting: "عزيزي %{full_name}," body1: "مرحبا بكم في بريميرو" - body2: "لقد تم تعيينك كمسؤول تنفيذ لـ%{host_href}.%{reset_notification}" + body2: "لقد تم تعيينك كمسؤول تنفيذ لـ%{host_href}. %{reset_notification}" body2_reset_notification: "ستتلقى رسالة بريد إلكتروني إضافية تطالبك بإعادة تعيين كلمة المرور الخاصة بك." body3: "أنت مسؤول عن ضمان التنفيذ الآمن وفي الوقت المناسب. لكل عملية طرح ، يجب أن تكون قد أكملت خطة التنفيذ مع إستراتيجية إدارة المستخدم والإعداد وبروتوكول مشاركة المعلومات. أنت مسؤول أيضًا عن ضمان وجود شروط استخدام موقعة في الملف لجميع مؤسسات المستخدمين" user_group: + associated_agencies: المؤسسات المرتبطة بمجموعة المستخدمين هذه description: الوصف disabled: explanation: إذا قمت بتعطيل مجموعة المستخدمين هذه ، فلن تتمكن بعد ذلك من إضافة حسابات مستخدمين عليها @@ -2784,6 +3461,11 @@ ar-JO: devise: failure: already_authenticated: "انت مسجل الدخول مسبقاً" - invalid: "غير صالح%{authentication_keys}أو كلمة المرور." + invalid: "غير صالح %{authentication_keys} أو كلمة المرور." locked: "حسابك مغلق" last_attempt: "لديك محاولة أخرى قبل أن يتم قفل حسابك" + admin: + locations: + selected_records: '%{select_records} الموقع (المواقع) المحدد' + selected_all_records: حدد جميع %{total_records} الحالات التي تطابق هذا الاستعلام. + updated: '%{updated_records} تحديث الموقع' diff --git a/config/locales/ar-LB.yml b/config/locales/ar-LB.yml index b3c8ff1d7b..58fbd7e6f6 100644 --- a/config/locales/ar-LB.yml +++ b/config/locales/ar-LB.yml @@ -1,19 +1,54 @@ ar-LB: 'true': 'نعم' 'false': 'لا' + accepted: موافق cancel: إلغاء + connection_lost: غير متصل بالشبكة + connected: متصل بالشبكة + no_connection: غير متصل بالشبكة clear: إلغاء + sandbox_ui: تجربة description: الوصف + form: استمارة + minimum_reportable_fields: "الحد الأدنى من الحقول التي يجب الإبلاغ عنها" + name: الاسم + offline: غير متصل بالشبكة + field_mode_on: "تفعيل" + field_mode_off: "حظر" + unavailable_offline: غير متاح في وضع غير متصل بالشبكة + online: متصل بالشبكة yes_label: 'نعم' + or_label: أو + select_provider: تحديد المزود + select_language: تحديد اللغة + log_in_primero_idp: 'تسجيل الدخول باسم المستخدم%{idp_name} ' + offline_submitted_changes: أنت حاليا غير متصل بالشبكة. سيتم حفظ التغييرات الخاصة بك عند معاودة الاتصال بالشبكة. + updated: محدث + go: اذهب + select_idp_error: الرجاء تحديد المزود + sync: + success: " تمت مزامنة%{records} بنجاح" + error: + create: لم يتم حفظ %{record_type} . يرجى الاتصال بالدعم. + update: لم يتم تحديث%{record_type}%{short_id} . يرجى الاتصال بالدعم. actions: + approvals: الموافقات button: إجراءات + close: إغلاق description: invalid: ملفّ غير صالح valid: ملفّ صالح disable: تعطيل enable: تفعيل/تمكين incident_details_from_case: إضافة حادثة + incident_from_case: اضافة حادثة + next: التالي + notes: إضافة ملاحظات + previous: السابق reopen: إعادة فتح + request_approval: طلب موافقة + revoke: الغاء + save: حفظ services_section_from_case: إضافة تقديم خدمة agencies: label: الوكالة @@ -247,8 +282,6 @@ ar-LB: transfers_by_social_worker: عمليات التحويل/نقل الملفّات من قبل العامل الاجتماعي users: رمز الإعدادات violence_type: نوع العنف - worker_count_referrals_total: - worker_count_total: you_have: 'لديك' disabled: status: @@ -271,10 +304,7 @@ ar-LB: file_name: قم بوضع إسم الملف الخاصّ بك (اختياري) password_label: الرجاء إدخال كلمة المرور التي سوف تشفّر ملفك. error_page: - not_authorized: - code: 403 not_found: - code: 404 contact_admin: في حال التواجد هنا عن طريق الخطأ،الرجاء التواصل مع المشرف التقني. something_went_wrong: نأسف، حدث خطأ ما! errors: @@ -460,7 +490,6 @@ ar-LB: violation: انتهاك home: ar: العربية - ar-IQ: العربية (العراقية) ar-LB: العربية (اللبنانية) bn: বাংলা current_time_zone: المنطقة الزمنية الحالية @@ -470,7 +499,6 @@ ar-LB: fr: الفرنسية id: Bahasa ku: کوردی - ku-IQ: کوردی (بادینی) label: الصفحة الرئيسية language: اللغة manage_system_users: إدارة مزامنة الخادم للمستخدمين @@ -634,7 +662,6 @@ ar-LB: self: النفاذ إلى ملفّاتي أو إلى مستخدم فقط لا غير services_section_from_case: إضافة تقديم خدمة لحالة مستخدم آخر specific_roles: النفاذ إلى قائمة محددة من الأدوار - sync_mobile: مزامنة مع جهاز المحمول system: نظام tracing_request: طلب التتبع user: مستخدمون diff --git a/config/locales/ar-SD.yml b/config/locales/ar-SD.yml index fc83c3a18c..d799535024 100644 --- a/config/locales/ar-SD.yml +++ b/config/locales/ar-SD.yml @@ -5,17 +5,22 @@ ar-SD: cancel: إلغاء connection_lost: حاليا خارج الاتصال connected: متصل + no_connection: غير متصل clear: فارغ sandbox_ui: تجريبي description: وصف form: شكل + minimum_reportable_fields: "الحد الأدنى من الحقول التي يجب الإبلاغ عنها" name: اسم offline: غير متصل بالشبكة + field_mode_on: "تفعيل" + field_mode_off: "غير فعال" unavailable_offline: غير موجود خارج الشبكة online: متصل yes_label: 'نعم' - or_label: أو + or_label: أو، select_provider: قم باختيار مزوّد + select_language: 'أختر اللغة ' log_in_primero_idp: تسجيل دخول باسم مستخدم %{idp_name} offline_submitted_changes: أنت حاليا غير متصل بالشبكة. سيتم تقديم تعديلاتك بعد معاودتك الاتصال sync: @@ -426,11 +431,11 @@ ar-SD: label_new: إعدادات جديدة messages: applied: تم تطبيق الإعدادات بنجاح - created: تم خلق الإعدادات بنجاح + created: تم إنشاء الإعدادات بنجاح deleted: تم حذف الإعدادات بنجاح updated: تم تحديث الإعدادات بنجاح not_allowed: غير مسموح به - unavailable_server: السيرفر غير متوفر مؤقتا + unavailable_server: الخادم غير متاح مؤقتًا. contact: field: email: بريد إلكتروني @@ -929,7 +934,6 @@ ar-SD: english_text: نص إنجليزي field_name: اسم المجال field_type: نوع المجال - attachment_too_large: لا يحب أن يكون لبملف أكبر من 10 mb file_upload_box: add_document_label: أضف الوثيقة add_new_document_button_text: أضف وثيقة أخرى @@ -1881,7 +1885,6 @@ ar-SD: explanation: يسمح للمدير بالاطلاع عاى عدد الحالات بمهام خدمة لم تتم بعد لكل مسؤول عن الحالة label: مهام خدمة لم تتم بعد dash_case_incident_overview: - explanation: . label: نظرة عامة - حالاتي/الأحداث dash_cases_by_social_worker: explanation: جدول يوضح جملة الحالات المفتوحة وعدد الحالات الجديدة المدارة بواسطة كل مستخدم في مجموعة المستخدمين للمستخدم الحالي. ويمثل كل صف مستخدم من مجموعات المستخدمين للمستخدم الحالي، بينما يمثل العمودان :الجملة" و "الجديدة" @@ -2223,7 +2226,6 @@ ar-SD: display: عرض تطابق محتمل ل%{type} %{id} reassign: multiple_error: حدث خطا. %{select_records} حالة (حالات) لم يتم التكليف بها - multiple_successfully: '%{select_records} حالة(حالات) تم التكليف بها بنجاح' notes_label: ملحوظات successfully: إعادة تكليف ناجح user_mandatory_label: المتلقي مطلوب diff --git a/config/locales/ar-SY.yml b/config/locales/ar-SY.yml new file mode 100644 index 0000000000..d2c47e3d01 --- /dev/null +++ b/config/locales/ar-SY.yml @@ -0,0 +1,3872 @@ +ar-SY: + 'true': 'نعم' + 'false': 'لا' + accepted: وافقت + cancel: إلغاء + connection_lost: حاليا في وضع غير متصل بالشبكة + field_mode_offline: حاليا في وضع غير متصل بالشبكة + connected: متصل + no_connection: غير متصل + clear: مسح + sandbox_ui: تجريبي + description: الوصف + form: استمارة + minimum_reportable_fields: "الحد الأدنى من الحقول القابلة للإبلاغ %{record_type}" + name: اسم + offline: غير متصل بالشبكة + field_mode: "الوضع الميداني: %{mode}" + field_mode_on: "فعال" + field_mode_off: "غير فعال" + unavailable_offline: غير متاح غير متصل بالشبكة + online: متصل بالشبكة + yes_label: 'نعم' + or_label: أو، + select_provider: اختر المزود + select_language: اختار اللغة + log_in_primero_idp: 'سجل دخول باسم المستخدم%{idp_name} ' + offline_submitted_changes: أنت حاليا غير متصل بالشبكة. سيتم إرسال التغييرات الخاصة بك عند الاتصال بالإنترنت مرة أخرى. + updated: محدث + go: اذهب/الانتقال + select_idp_error: الرجاء تحديد المزود + sync: + success: "تمت مزامنة سجلات%{records} بنجاح." + error: + create: انشاء %{record_type}قد فشل . يرجى الاتصال بالدعم. + update: التحديث الى %{record_type}%{short_id} قد فشل, يرجى الاتصال بالدعم. + actions: + approvals: الموافقات + button: إجراءات + close: اغلاق + description: + invalid: سجل غير صالح + valid: سجل صالح + disable: تعطيل + enable: تفعيل + incident_details_from_case: إضافة حادثة + incident_from_case: خلق حادثة + next: التالي + notes: ملاحظات + previous: السابق + reopen: إعادة فتح + request_approval: طلب موافقة + revoke: الغاء + save: حفظ + services_from_case_creation_success: تم إنشاء سجل توفير الخدمة بنجاح. + services_section_from_case: إضافة تقديم خدمة + mark_for_offline: وضع علامة على عدم الاتصال بالانترنت + agencies: + label: الهيئة + translations: + manage: إدارة الترجمات + agency: + agency_logos: شعارات الهيئة + code: كود الهيئة + description: الوصف + disabled: 'مُعطلة ' + exclude_agency_from_lookups: استبعاد هذه الهيئة من عمليات البحث وعوامل التصفية + exclude_agency_from_lookups_help: تحقق من هذا إذا لم يكن لدى الهيئة مستخدمون (على سبيل المثال ، تمت إضافة الهيئة حتى يمكن تطبيق الشعار على التصديرات. + label: الهيئة + logo_enabled: عرض شعار هذه الهيئة في Primero؟ + logo_enabled_help: عرض شعار هذه الهيئة في Primero؟ + logo_icon: شعار الايقونة + logo_icon_help: سيظهر هذا على الشاشات صغيرة الحجم والأجهزة اللوحية والهواتف. يجب أن يكون هذا على شكل مربع. + logo_large: شعار كبير + logo_large_help: سيظهر هذا على الشاشات كبيرة الحجم و في صيغة PDF. يجب أن يكون هذا على شكل مستطيل و يجب ان يكون الطول اكبر من الارتفاع + messages: + created: تم انشاء الهيئة بنجاح + updated: تم تحديث الهيئة بنجاح + name: اسم الهيئة + pdf_logo_option: جعل الشعار متاح في صيغة PDF ؟ + pdf_logo_option_help: 'ملاحظة: شعارات الهيئة الخاصة بالمستخدم متاحة لهم بشكل افتراضي ، لذلك يمكنك تحديد هذا فقط إذا كنت تريد أن يكون هذا الشعار متاحًا لجميع المستخدمين.' + services: خدمات الهيئة + terms_of_use: شروط الاستخدام + terms_of_use_help: يسمح فقط بملفات PDF + terms_of_use_download_button: تحميل PDF + terms_of_use_enabled: عرض شروط الاستخدام؟ + approvals: + no_requests: لا توجد طلبات موافقة لهذه الحالة + approved_by: تمت الموافقة عليه من قبل + case_plan_type_label: نوع خطة الحالة + manager_comments_label: تعليقات المدير + rejected_by: تم رفضه من قبل + requested_by: تم طلبه من قبل + requested_for_label: تم طلب الموفقة على + requested_for_title: طلب موافقة + response_for_label: الموافقة على + response_for_title: تم الموافقة عليها + action_plan: خطة العمل + gbv_closure: اغلاق العنف القائم على نوع الجنس + status: + approved: تم الموافقة عليه + pending: قيد الانتظار + rejected: رُفض + requested: تم الطلب + audit_log: + action: إجراء + description: الوصف + record_owner: تسجيل المالك + timestamp: الوقت + user_name: نفّذها + bulk_export: + file_name: ملف + record_type: نوع + retry: هذا النقل غير صحيح. رجاء حاول إعادة عملية النقل الخاصة بك. + started_on: 'بدء ' + status: 'وضع الحالة ' + form_export: + label: تصدير نموذج الإعدادات + include_hidden: تضمين النماذج والحقول المخفية؟ + file_name: قم بإنشاء اسم الملف الخاص بك (اختياري) + success_message: تم إنشاء ملف التصدير بنجاح + buttons: + accept: قبول + add: إضافة + add_another_option: إضافة خيار أخرى + add_note: إضافة ملاحظات + apply: تطبيق + approvals: المصادقات + approve_action_plan: موافقة خطة العمل + approve_bia: الموافقة على المصلحة الفضلى + approve_case_plan: الموافقة على خطة الحالة + approve_closure: الموافقة على الإغلاق + approve_gbv_closure: الموافقة على اغلاق العنف القائم على نوع الجنس + back: السابق + bundle_export: حزمة الإعدادات + bundle_import: حزمة الإعدادات + cancel: إلغاء + change_password: تغيير كلمة المرور + check_status: تحقق من حالة + clear_default: مسح الافتراضي + clear_selection: مسح الاختيار + clear: مسح + close: اغلاق + continue: استمر + create_case: إنشاء حالة + create_incident: 'إنشاء حادثة ' + create_new_record: إنشاء %{model} جديد + delete: حذف + disable: إيقاف + disable_photo_wall: تعطيل عرض الصور + done: تم + download: تحميل + edit: تعديل + edit_subform: تعديل النموذج الفرعي + enable: تشغيل + enable_photo_wall: تفعيل عرض الصور + export: تصدير ملف + filter: تطبيق عامل التصفية + filter_clear: مسح عوامل التصفية + filter_label: 'عامل التصفية:' + filter_restore: الاسترجاع إلى إعدادات النظام + find_tracing_match: إيجاد التطابق لحالة التتبع + flag_model: وضع علامة %{model} + flag_records: وضع علامة + flags: العلامات + guidance: توجيه + guiding_questions: اسئلة توجيهية + import: استيراد + login: تسجيل الدخول + logout: تسجيل خروج + link: رابط + mark_for_mobile: وضع علامة للمحمول + new: 'جديدة ' + ok: موافق + print: مطبعة + reassign: تعيين + referral: 'إحالة ' + referral_again: إحالة مرة اخرى + reject: رفض + remove_referrals: إلغاء الإحالات + reorder: اعادة ترتيب + request_approval: طلب الموافقة + request_transfer: طلب نقل + reunite: إعادة لمّ الشمل + save: حفظ + save_and_add_service_provision: حفظ وإضافة تقديم خدمة + save_and_return: حفظ و رجوع + save_continue: حفظ و استمرار + save_changes: حفظ التغيرات + select: اختيار + send: ارسال + sort_by_case: حالات + sort_by_tr: تتبع الطلبات + sync: مزامنة + submit: تقديم + transfer: نقل + unflag_model: إزالة العلامة %{model} + unflag_model_history: وضع علامة للتاريخ%{model} + unmark_for_mobile: إزالة علامة للمحمول + update: تحديث + view: عرض + view_flags_history: عرض التاريخ + return_to_case: العودة إلى الحالة + enable_webpush: إشعارات الجهاز + dialog_yes: "نعم" + resync_records: + id: رقم الحالة في النظام + record_type: نوع السجل + action: إجراء + date: التاريخ + last_attempt: اخر محاولة + create: إنشاء + update: تحديث + resync: تقديم + case: + label: حالة + create_new_case: انشاء حالة جديدة + create_case: إنشاء حالة + create: إنشاء + add_new: أضف جديد + back_to_family_details: العودة إلى تفاصيل العائلة + back_to_case: العودة إلى الحالة + back_to_results: العودة إلى النتائج + back_to_search: العودة الى البحث + search_by: البحث حسب + search_for: البحث عن %{record_type} + results: النتائج + details: تفاصيل + select: اختيار + deselect: ازالة الاختيار + enter_id_number: قم بإدخال رقم الهوية الشخصية/رقم المنهل + id_search_no_results: لا يوجد متشابه في النظام ل "%{id}"، يُرجى عمل سجل جديد. + messages: + disabled: تم تعطيل الحالة + update_success: 'تم تحديث الحالة %{record_id} بنجاح.' + update_success_queue: 'تم تحديث الحالة %{record_id} بنجاح في الخلفية' + creation_success: 'تم إنشاء سجل الحالة بنجاح.' + creation_success_queue: 'تمّ إنشاء سجل الحالة بنجاح في الخلفية' + already_matched: لقد تمّت مطابقة هذا المستفسر مع حالتك سابقًا. + already_matched_not_current_case: توجد بالفعل حالة في النظام مطابقة لهذا المستفسر. + not_found_case: لم يتم العثور على حالة تطابق "%{search_value}" إنشاء حالة جديدة + introductory_sentence: يرجى تحديد موافقة الفرد على تلقي خدمات إدارة الحالة وتخزين بياناته في Primero. + consent_agreements_required: الرجاء تحديد خيار واحد على الأقل من اتفاقيات الموافقة. + legitimate_basis_required: الرجاء تحديد خيار واحد على الأقل من التصنيفات الأساسية القانونية. + confirm_create_case: هل تريد انشاء حالة لهذا الفرد؟ + case_referral_pending: إحالة الحالة في انتظار المراجعة. + case_transfer_pending: نقل الحالة في انتظار المراجعة. + case_no_approval_request: لا توجد طلبات موافقة لهذه الحالة. + bulk_assign_limit: لا يمكنك تعيين أكثر من 100 حالة في وقت واحد. + bulk_assign_limit_try_again: لا يمكنك تعيين أكثر من 100 حالة في وقت واحد. يرجى تحديد 100 حالة أو أقل ثم حاول مرة أخرى + referral_rejected: تم رفض الإحالة. + transfer_request_made: تم تقديم طلب نقل لهذه الحالة. + save: حفظ الحالة + save_text: قبل المتابعة يرجى حفظ التغييرات التي أجريت على الحالة + skip_and_create: تخطي وإنشاء حالة جديدة + search_existing: بحث في الحالات الموجودة + search_helper_text: لماذا ا؟ لمنع إنشاء حالات مكررة. + consent_agreements: حدد جميع اتفاقيات الموافقة التي تنطبق + legitimate_basis: حدد كل التصنيفات الأساسية القانونية التي تنطبق + family_linked_subform_delete_disabled: يرتبط إدخال النموذج الفرعي هذا بسجل العائلة. يرجى إما إزالة عضو العائلة هذا من سجل العائلة، أو إلغاء ربط حالة فرد العائلة من سجل العائلة. + workflow: + assessment: التقييم + case_plan: خطة الحالة + closed: مغلقة + created_on: تم تسجيل في + in_progress: جاري + new: 'جديدة ' + on_label: 'في' + reopened: تم إعادة فتحها + service_implemented: تم تطبيق الخدمة + services_implemented: تم نطبيق الخدمة + linkedincidents: + label: الحوادث المرتبطة + activity_log: + label: سجل النشاطات(التغييرات) + accepted_transfer: '%{to} قبول نقل %{record_type} %{record_id} من %{from}' + rejected_transfer: '%{to} رفض نقل %{record_type} %{record_id} من %{from}' + cases: + action_plan: خطة العمل + access_denied: "ليس لديك حق الوصول إلى هذه الحالة." + age: العمر + age_estimated: ما هو العمر المقدّر؟ + agency: الهيئة + apply_filter: تطبيق + approval_comments: تعليقات + approval_radio: أودّ أن + approval_radio_accept: أوافق + approval_radio_reject: لا أوافق + approval_select: نموذج لـ + approved_success_action_plan: '%{approval_label} - تمتّ الموافقة عليه' + approved_success_assessment: '%{approval_label} - تمتّ الموافقة عليه' + approved_success_bia: '%{approval_label} - تمتّ الموافقة عليه' + approved_success_case_plan: '%{approval_label} - تمتّ الموافقة عليه' + approved_success_closure: '%{approval_label} - تمتّ الموافقة عليه' + approved_success_gbv_closure: '%{approval_label} - تمتّ الموافقة عليه' + assessment: التقييم + case_opening_date: تاريخ فتح الحالة + case_plan: خطة الحالة + case_worker_code: كود اخصائي الحالة + clear_filter: مسح + close_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحالة مغلقًا + close_dialog_title: اغلاق الحالة + close_success: تمّ إغلاق الحالة بنجاح + closure: اغلاق + complete: متاح بدون الاتصال بالانترنت + date_of_birth: 'تاريخ الميلاد ' + disable_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحالة معطّلًا + disable_dialog_title: تعطيل الحالة + disable_success: تمّ تعطيل الحالة بنجاح + enable_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحالة مفعّلًا + enable_dialog_title: تفعيل الحالة + enable_success: تمّ تفعيل الحالة بنجاح + export: تصدير ملف + mark_for_offline: + title: وضع علامة على عدم الاتصال بالانترنت + text: هل أنت متأكد أنك تريد وضع علامة على هذه الحالات لاستخدامها عندما تكون غير متصل؟ + success: تم وضع علامة على الحالات بنجاح للاستخدام دون اتصال بالانترنت + filter_by: + 3month_inactivity: لمدة أكثر من 3 أشهر + action_plan: خطة العمل + age_0_5: 0 - 5 + age_12_17: 12 - 17 + age_18_more: 18+ + age_6_11: 6 - 11 + age_range: الفئة العمرية + agency: الهيئة + approval_status: وضع الموافقات + approvals: + approved: تم الموافقة عليه + pending: معلّقة + rejected: رُفض + bia: المصلحة الفضلى + by_date: حسب التاريخ + case_open_date: تاريخ فتح الحالة + case_plan: خطة الحالة + closed: مغلقة + closure: اغلاق + current_location: الموقع الحالي + date: تاريخ + displacement_status: وضع النزوح + district: الحي + duplicate: كرّر + enabled_disabled: 'مُفعلة/مُعطلة ' + female: أنثى + flag: 'مميزة بعلامة ' + flag_label: هل كان مُميزًا بعلامة؟ + gbv_closure: اغلاق العنف القائم على النوع الإجتماعي + high: مرتفع + low: منخفض + male: ذكر + medium: متوسط + mobile: حاليا في وضع غير متصل بالشبكة + mobile_label: هل تم وضع علامة للمحمول؟ + my_cases: حالاتي + no_action: لا يوجد إجراء + no_activity: لا توجد أنشطة + open: مفتوح + other: أخرى + photo: صورة + photo_label: هل توجد صورة؟ + protection_concerns: مخاوف تتعلّق بالحماية + protection_status: وضع الحماية + record_state: حالة السجل + referred_cases: الحالات التي تم إحالتها الي + registration_date: تاريخ التسجيل + risk_level: مستوى الخطورة + sex: الجنس + social_worker: حقل/حالة/اخصائي حالة + status: وضع + transferred: تم النقل + type_of_risk: نوع المخاطر + urgent_protection_concern: مخاوف عاجلة بشأن الحماية + user_group: مجموعة المستخدم + workflow: الحالات حسب سريان العمل + include_disabled: اضف الحالات التي تم الغائها + flag_summary: ملخص العلامة + full_name: الاسم الكامل + gbv_closure: اغلاق العنف القائم على النوع الإجتماعي + hide_name: إخفاء الاسم + hide_name_error: حدث خطأ عند حفظ التغييرات. الرجاء المحاولة مرة أخرى. + id: رقم الحالة في النظام + label: الحالات + my_filters: عوامل التصفية + name: الإسم + notes_dialog_title: اضافة ملاحظات + notes_form_notes: ملاحظات + notes_form_subject: الموضوع + ok: تمّ + order_by: + label: ترتيب حسب + most_recently: الأحدث + name: الاسم + owned_by: مالك السجلّ + owned_by_agency: الهيئة مالكة السجلّ + photo: صورة فوتوغرافية + photos: صورة + quick_view: + tracing_message: 'ملاحظة: توجد نتائج مطابقة في النظام لما يبحث عنه المستعلم من أجل هذا الطفل. اتصل باخصائي الحالة المعني بهذا السجل لاتخاذ خطوات إضافية إذا رغب الطفل.' + reassign: + multiple_successfully: Primero يقوم بإعادة تحديث % {select _ records} الحالة (s). قد يستغرق تحديث كل هذه الحالات عدة دقائق. + referral_done: يشير النقر على "اكمل" إلى استكمال الإحالة المرتبطة بهذه الحالة. ما إن تنقر على "اكمل" لن تتمكّن من الاطلاع مجدّدًا على هذا السجل. + referral_done_success: تمّت الإحالة + referral_accepted_header: قبول الإحالة + referral_accepted: هل أنت متأكّد؟ ستكون الآن مسؤولاً عن إكمال العمل المرتبط بهذه الإحالة. + referral_accepted_success: تمّ قبول الإحالة + referral_rejected: يشير النقر على "رفض" إلى عدم استعدادك لتحمّل مسؤولية هذه الإحالة في الوقت الحالي. يرجى إدخال سبب رفضك لهذه الإحالة ؛ بمجرد النقر على "رفض" لن تتمكن من الاطلاع على سجل هذه الحالة. + referral_rejected_success: تمّ رفض الإحالة + register_new_case: حالة جديدة + registration_date: تاريخ التسجيل + rejected_success_action_plan: '%{approval_label}- غير موافق عليها' + rejected_success_assessment: '%{approval_label}- غير موافق عليها' + rejected_success_bia: '%{approval_label}- غير موافق عليها' + rejected_success_case_plan: '%{approval_label}- غير موافق عليها' + rejected_success_closure: '%{approval_label}- غير موافق عليها' + rejected_success_gbv_closure: '%{approval_label}- غير موافق عليها' + reopen_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحالة مفتوحًا + reopen_dialog_title: إعادة فتح الحالة + reopen_success: تمّت إعادة فتح الحالة بنجاح + request_approval_failure: حدث خطأ، يرجى الاتصال بالدعم. + request_approval_select: طلب الموافقة على + request_approval_success_action_plan: طلب الموافقة على نموذج %{approval_label} + request_approval_success_assessment: طلب الموافقة على نموذج %{approval_label} + request_approval_success_case_plan: طلب الموافقة على نموذج %{approval_label} + request_approval_success_closure: طلب الموافقة على نموذج %{approval_label} + request_approval_success_gbv_closure: طلب الموافقة على نموذج %{approval_label} + request_approval_type_of_case_plan: نوع الموافقة على خطة الحالة + request_approve_action_plan: هل توافق على خطة العمل؟ + request_approve_bia: 'هل توافق على التقييم؟ ' + request_approve_case_plan: هل توافق على خطة الحالة؟ + request_approve_closure: هل توافق على الإغلاق؟ + request_approve_gbv_closure: هل توافق على إغلاق العنف القائم على النوع الإجتماعي؟ + revoke_failure: حدث خطأ خلال إلغاء %{transition_type}، يرجى الاتصال بالدعم. + revoke_message: بالنقر على "إلغاء" ستقوم بإزالة إمكانية وصول المستلِم %{transition_type} إلى الحالة. + revoke_success_message: الحالة %{case_id}%{transition_type}%{recipient_username} التي يجب إلغاؤها. + save_filter: حفّظ + selected_all_records: اختيار كلّ %{total_records}الحالات التي تطابق هذا الاستعلام. + selected_records: '%{select_records} حالة (حالات) مختارة' + selected_records_assign: ' %{select_records} حالة (حالات) مختارة' + sex: الجنس + show_case: 'معرّف الحالة: %{short_id}' + social_worker: اخصائي الحالة + status: الوضع + summary: + label: ملخص + find_match: إيجاد تطابق + matched_trace: 'رقم التطابق %{trace_id}' + cannot_find_matches: لم يتمّ العثور على تطابق. لم يتمّ الحصول على موافقة الحالة للكشف عن المعلومات لأغراض التتبع. + matched: تمّت المطابقة. + fields: + consent_for_tracing: + label: تمّ الحصول على الموافقة للكشف عن المعلومات لأغراض التتبع. + help_text: إذا كانت هذه الخانة "لا"، لن يظهر سجل حالة الطفل في التطابقات مع طلبات المستفسِر للتتبّع. + wishes_child_family_tracing: + label: هل يريد الطفل تتبع أفراد الأسرة؟ + wishes_reunification: + label: هل يريد الطفل لَمْ شَمْل الأسرة؟ + options: + yes_as_soon_as_possible: نعم، بأسرع وقت ممكن + yes_but_later: نعم ولكن لاحقًا + not_sure: غير مؤكّد + 'no': 'لا' + data_confidentiality_link: + label: راجع سريّة البيانات + child_wishes_link: + label: راجع رغبات الطفل + survivor_code: كود الناجية + transfer_accepted: بالنقر على "موافقة" فإنك توافق على تحمّل مسؤولية هذه الحالة؛ وبمجرد النقر على "موافقة" ستصبح أنت مالك السجل في النظام. + transfer_managed_user_accepted: إذا قمت بالنقر فوق "قبول" ،%{transitioned_to} ستصبح مسؤولاً عن هذه الحالة ؛ بمجرد النقر فوق "قبول" ، %{transitioned_to} ستصبح مالك السجل في النظام. + transfer_managed_user_rejected: 'بالنقر فوق "رفض" ، فإنك تشير إلى أنك %{transitioned_to} غير مستعد لقبول المسؤولية عن هذه الحالة في الوقت الحالي. الرجاء إدخال سبب رفضك لهذه الحالة ؛ بمجرد النقر فوق "رفض" %{transitioned_to} لن تتمكن من الوصول إلى سجل هذه الحالة ' + transfer_accepted_rejected: تمّ رفض عملية تحويل الحالة %{record_id} + transfer_accepted_success: تمّ قبول تحويل الحالة بنجاح. + transfer_reject_reason_label: سبب الرفض + transfer_rejected: يشير النقر على "رفض" إلى عدم استعدادك لتحمّل مسؤولية هذه الحالة في الوقت الحالي. يرجى إدخال سبب رفضك لهذه الحالة ؛ بمجرد النقر على "رفض" لن تتمكن من الاطلاع على سجل هذه الحالة. + view_name: عرض الاسم + sort_by: ترتيب حسب + change_logs: + filters: + form: استمارة + field: حقل + add_subform: 'تمّت إضافة%{subform_name} رقم مُدخَل النموذج الفرعي %{short_id}' + changes_subform: 'التغييرات على النموذج الفرعي "%{subform_name}"' + create: السجلّ الذي تمّ إنشاؤه + deleted_subform: 'تمّت إزالة %{subform_name} رقم مُدخل النموذج الفرعي "%{short_id}"' + label: تغيير السجل + see_details: راجع التفاصيل + change: 'من "%{from_value}" إلى "%{to_value}"' + updated_subform: 'تمّ تحديث %{subform_name} رقم مُدخل النموذج الفرعي "%{short_id}"' + update_subform: 'تمّ تحديث النموذج الفرعي "%{subform_name}" ' + from: من + to: إلى + children: + selectable_date_options: + assessment_requested_on: تاريخ التقييم + closure_approved_date: 'تاريخ إغلاق ملف الحالة' + created_at: 'تاريخ فتح الحالة ' + date_case_plan_initiated: تاريخ خطة الحالة + date_of_creation: تاريخ الإنشاء + registration_date: تارخ التسجيل + configurations: + apply_label: هل أنت متأكد؟ إذا قمت بتطبيق الإعدادات الموجودة في هذا الإعدادات، ستُطبّق على النظام. ستفقدكلّ إعداداتك الحالية ولن تتمكن من استعادتها ما لم تكن قد حفظتها سابقًا في إعداد آخر. + apply_label_bold: لن يكون بريميرو Primero متاحًا للمستخدمين لبضع دقائق أثناء تحميل التغييرات. + version_mismatch_tooltip: لا يمكنك تطبيق هذا الإعدادات ، لأنه تم إنشاؤه باستخدام إصدار أعلى من Primero من الإصدار الذي يعمل به موقعك. يرجى الانتظار لتطبيق هذا الإعدادات حتى تقوم بتشغيل أحدث إصدار من Primero. + send_header: أرسل إلى الإنتاج + send_text: هل أنت متأكد؟ إذا نقرت على أرسل، سوف ترسل هذا الإعدادات إلى موقع الإنتاج الخاص بك. لن يتم تطبيق هذا الإعدادات على الإنتاج حتى يقوم مسؤول في هذا الموقع بتطبيقه يدويًا. + attributes: + created_by: تمّ الإنشاء من قِبَل + date_created: تاريخ الإنشاء + description: وصف + last_applied_by: تمّ التطبيق الأخير من قِبَل + last_applied_on: تمّ التطبيق الأخير في + name: الإسم + version: إصدار الإعدادات + primero_version: نسخة "Primero" + delete_label: هل انت متأكد من أنك تريد أن تفعل هذا؟ يمثل هذا الأمر جميع الإعدادات منذ إنشاء هذا الإعدادات. لن تتمكن من العودة واستعادة هذه الإعدادات بمجرد حذف هذا الإعدادات. + explanation: 'سيؤدي النقر على "حفظ" إلى إنشاء سجل بجميع إعدادات الإعدادات الحالية (على سبيل المثال: الأدوار والهيئات والنماذج) في هذه المرحلة الزمنية. بعد الحفظ، يمكنك تكرار هذه التغييرات في فقرة أخرى من بريميرو Primero. إذا أجريت، في المستقبل، تغييرات على الإعدادات وتريد التراجع عنها، يمكنك تطبيق سجل الإعدادات هذا لاسترجاع جميع تغييرات الإعدادات التي أجريتها في هذا الوقت.' + label: إعدادات + label_new: إعداد جديد + messages: + applied: تمّ تطبيق الإعدادات بنجاح. + created: تمّ إنشاء الإعدادات بنجاح. + deleted: تمّ حذف الإعدادات بنجاح. + updated: تمّ تحديث الإعدادات بنجاح. + sent: إرسال الإعدادات إلى الإنتاج. يرجى التحقق من موقع الإنتاج لمعرفة ما إذا كان الإعدادات الخاص بك قد وصل. + not_allowed: غير مسموح + unavailable_server: السرفر غير متاح مؤقتًا. + contact: + field: + email: البريد الإلكتروني + location: الموقع + name: الاسم + organization: المنظمة + other_information: معلومات أخرى + phone: الهاتف + position: المسمى الوظيفي + primero_version: نسخة بريميرو Primero + support_forum: رابط المساعدة + system_version: نسخة النظام + info_label: معلومات الاتصال + updated: تم تحديث معلومات الاتصال بنجاح. + code_of_conduct: + field: + title: لقب + content: المحتوى + created_on: تم إنشاؤها على + created_by: انشأ من قبل + info_label: مدونة قواعد السلوك + updated: تم تحديث مدونة قواعد السلوك بنجاح. + dashboard: + activity: النشاط + admin_only: اضغط على %{links} لعمل تغييرات على التطبيق. + all_cases: جميع الحالات + all_services_implemented: تم تقديم جميع الخدمات + and: 'و' + approval_action_plan_approved: تم الموافقة عليه + approval_action_plan_pending: معلّقة + approval_action_plan_pending_group: خطة العمل + approval_action_plan_rejected: رُفض + approval_assessment_approved: تم الموافقة عليه + approval_assessment_pending: معلّقة + approval_assessment_pending_group: التقييم + approval_assessment_rejected: رُفض + approval_case_plan_approved: تم الموافقة عليه + approval_case_plan_pending: معلّق + approval_case_plan_pending_group: خطة الحالة + approval_case_plan_rejected: رُفض + approval_closure_approved: تم الموافقة عليه + approval_closure_pending: معلّقة + approval_closure_pending_group: الإغلاق + approval_closure_rejected: رُفض + approval_gbv_closure_approved: تم الموافقة عليه + approval_gbv_closure_pending: معلّق + approval_gbv_closure_pending_group: اغلاق العنف القائم على النوع الإجتماعي + approval_gbv_closure_rejected: رُفض + approvals: الموافقات + approvals_action_plan: خطة العمل + approvals_assessment: التقييم + approvals_case_plan: خطة الحالة + approvals_closure: الإغلاق + approvals_gbv_closure: اغلاق العنف القائم على النوع الإجتماعي + approved: تم الموافقة عليه + assessment: التقييم + awaiting_acceptance: بانتظار القبول + cases_by_social_worker_total: مجموع + cases_by_social_worker_new_or_updated: جديد ومُحدث + case_id: 'رقم الحالة في النظام' + case_management_service: خدمة إدارة الحالات + case_overview: حالاتي + case_plan: خطة الحالة + case_risk: تصنيف الحالات بحسب مستوى التقييم + case_stat_by_approval_type: الموافقات + case_stat_by_assessment_level: تصنيف الحالات بحسب مستوى التقييم + case_stat_referrals: الإحالات + case_stats: الحالات + case_worker: اخصائي حالة + cases_by_social_worker: الحالات حسب اخصائي الحالة + cases_by_task_overdue: المهام المتأخرة + cases_by_workflow: الحالات حسب سريان العمل + cases_this_week: الحالات هذا الأسبوع + cases_to_assign: الحالات منتظرة التعيين + closed: مغلقة + closed_last_week: أُغلقت (الأسبوع الماضي) + closed_this_week: أُغلقت (هذا الاسبوع) + comprehensive_need_intervention: تدخل شامل + count_new_bia_approvals: + zero: '%{stat}الجدي%{stat_type}الموافقات' + one: '%{stat}الجدي%{stat_type}الموافقات' + two: '%{stat}الجدي%{stat_type}الموافقات' + few: '%{stat}الجدي%{stat_type}الموافقات' + many: '%{stat}الجدي%{stat_type}الموافقات' + other: '%{stat}الجديدة%{stat_type}الموافقات' + count_new_case_plan_approvals: + zero: '%{stat} موافقات %{stat_type} جديدة' + one: '%{stat}موافقة %{stat_type}جديدة' + two: '%{stat}موافقات %{stat_type}جديدة' + few: '%{stat}موافقات %{stat_type}جديدة' + many: '%{stat}موافقات %{stat_type}جديدة' + other: '%{stat}موافقات %{stat_type} جديدة' + count_new_closure_approvals: + zero: '%{stat}موافقة%{stat_type}جديدة' + one: '%{stat}موافقة%{stat_type}جديدة' + two: '%{stat}موافقتان%{stat_type}جديدتان' + few: '%{stat}موافقات%{stat_type}جديدة' + many: '%{stat}موافقات %{stat_type}جديدة' + other: '%{stat}موافقات %{stat_type} جديدة' + count_pending_approval_total: + zero: لديك %{stat} موافقة %{stat_type} قيد الانتظار + one: لديك %{stat} موافقة %{stat_type} قيد الانتظار + two: لديك %{stat} موافقتان %{stat_type} قيد الانتظار + few: لديك %{stat}موافقات %{stat_type} قيد الانتظار + many: لديك %{stat} موافقات %{stat_type} قيد الانتظار + other: لديك %{stat} موافقات %{stat_type} قيد الانتظار + count_pending_transfers: + zero: لديك %{stat} طلب نقل معلق + one: لديك %{stat} طلب نقل معلق + two: لديك %{stat} طلبين نقل معلقين + few: لديك %{stat} طلب نقل معلق + many: لديك %{stat} طلب نقل معلق + other: لديك %{stat} طلب نقل معلق + count_records_new: + zero: 'لديك %{stat} حالات مفتوحة ' + one: 'لديك %{stat} حالات مفتوحة ' + two: 'لديك %{stat} حالات مفتوحة ' + few: 'لديك %{stat} حالات مفتوحة ' + many: 'لديك %{stat} حالات مفتوحة ' + other: 'لديك %{stat} حالات مفتوحة ' + count_records_total: + zero: لديك%{stat} إجمالي الحالات + one: لديك%{stat} إجمالي الحالات + two: لديك%{stat} إجمالي الحالات + few: لديك%{stat} إجمالي الحالات + many: لديك%{stat} إجمالي الحالات + other: لديك%{stat} إجمالي الحالات + count_referrals_new: + zero: 'و %{stat} إحالات جديدة ' + one: 'و %{stat} إحالات جديدة ' + two: 'و %{stat} إحالات جديدة ' + few: 'و %{stat} إحالات جديدة ' + many: 'و %{stat} إحالات جديدة ' + other: 'و %{stat} إحالات جديدة ' + count_referrals_total: + zero: لديك%{stat} إجمالي الإحالات + one: لديك %{stat} إجمالي الإحالات + two: لديك%{stat} إجمالي الإحالات + few: لديك%{stat} إجمالي الإحالات + many: لديك%{stat} إجمالي الإحالات + other: لديك%{stat} إجمالي الإحالات + count_rejected_approval_total: + zero: و %{stat} موافقات على %{stat_type} مرفوضة + one: و %{stat} موافقات على %{stat_type} مرفوضة + two: و %{stat} موافقات على %{stat_type} مرفوضة + few: و %{stat} موافقات على %{stat_type} مرفوضة + many: و %{stat} موافقات على %{stat_type} مرفوضة + other: و %{stat} موافقات على %{stat_type} مرفوضة + count_rejected_transfers: + zero: و%{stat} نقل حالات مرفوضة + one: و%{stat} نقل حالات مرفوضة + two: و%{stat} نقل حالات مرفوضة + few: و%{stat} نقل حالات مرفوضة + many: و%{stat} نقل حالات مرفوضة + other: و%{stat} نقل حالات مرفوضة + count_risk_level_new: + zero: و%{stat} حالات ذات خطورة %{stat_type} جديدة + one: و%{stat} حالات ذات خطورة %{stat_type} جديدة + two: و%{stat} حالات ذات خطورة %{stat_type} جديدة + few: و%{stat} حالات ذات خطورة %{stat_type} جديدة + many: و%{stat} حالات ذات خطورة %{stat_type} جديدة + other: و%{stat} حالات ذات خطورة %{stat_type} جديدة + count_risk_level_total: + zero: 'لديك %{stat} حالة %{stat_type} الخطورة ' + one: 'لديك %{stat} حالة %{stat_type} الخطورة ' + two: 'لديك %{stat} حالة %{stat_type} الخطورة ' + few: 'لديك %{stat} حالة %{stat_type} الخطورة ' + many: 'لديك %{stat} حالة %{stat_type} الخطورة ' + other: 'لديك %{stat} حالة %{stat_type} الخطورة ' + count_waiting_for_acceptance_transfers: لديك %{stat} نقل حالة بإنتظار موافقتك + current_owner: المالك الحالي + dash_case_incident_overview: حالاتي + dash_group_overview: حالات مجموعتي + dash_shared_from_my_team: تمّ تشاركها من فريقي + dash_shared_with_me: 'تم مشاركتها معي ' + dash_shared_with_my_team: تمّ تشاركها مع فريقي + dash_shared_with_my_team_overview: تم مشاركته مع فريقي (نظرة عامة) + dash_shared_with_others: تمّ تشاركها مع آخرين + dash_national_admin_summary: ملخص المدير + dash_violations_category_verification_status: إجمالي عدد الحوادث لكل حالة تحقق + dash_violations_category_region: إجمالي عدد الحوادث التي تم التحقق منها لكل منطقة + dash_perpetrator_armed_force_group_party_names: إجمالي عدد الحوادث لكل مرتكب + date: التاريخ + date_of_incident: تاريخ الحادثة + date_of_interview: تاريخ المقابلة + due: تأخرت + flagged: 'مميزة بعلامة ' + flagged_by: 'تم تمييزه بعلامة بواسطة:' + flagged_by_me: تم تمييزه بعلامة بواسطتي + flagged_by_other: تم تمييزه بواسطة شخص آخر + flagged_cases: الحالات المميّزة بعلامة + follow_up: متابعة + forms: تبويب النماذج + geographic_area: المنطقة الجغرافية + group_overview_closed: مغلقة + group_overview_open: مفتوحة + high_level: مرتفع + high_risk: أولوية عالية + immediate_response: 'استجابة فورية ' + in_progress: قيد التنفيذ + incident_id: 'معرف #الحادثة' + incident_location: موقع الحادثة + incident_status_open: مفتوح + last_updated: آخر تحديث + link_see_all: عرض الكل + low_level: منخفض + low_risk: أولوية منخفضة + manager_count_closed_total: + zero: و %{stat} حالات مغلقة + one: و %{stat} حالات مغلقة + two: و %{stat} حالات مغلقة + few: و %{stat} حالات مغلقة + many: و %{stat} حالات مغلقة + other: و %{stat} حالات مغلقة + manager_count_open_total: + zero: 'لديك %{stat} حالات مفتوحة ' + one: 'لديك %{stat} حالات مفتوحة ' + two: 'لديك %{stat} حالات مفتوحة ' + few: 'لديك %{stat} حالات مفتوحة ' + many: 'لديك %{stat} حالات مفتوحة ' + other: 'لديك %{stat} حالات مفتوحة ' + manager_transfers_totals: + zero: 'لديك %{stat} %{stat_type} نقل حالة ' + one: 'لديك %{stat} %{stat_type} نقل حالة ' + two: 'لديك %{stat} %{stat_type} نقل حالة ' + few: 'لديك %{stat} %{stat_type} نقل حالة ' + many: 'لديك %{stat} %{stat_type} نقل حالة ' + other: 'لديك %{stat} %{stat_type} نقل حالة ' + match_result: نتائج متشابهة + medium_level: متوسط + medium_risk: أولوية متوسطة + missed_cases: الحالات المفقودة + name: الاسم + name_or_survivor_code: اسم الناجي أو كوده + near_deadline: 'قاربت على تاريخ الانتهاء ' + new: جديد ومحدث + new_child_assigned_to_you: حالات جديدة تم تعيينها لك + new_incident: حالات جديدة + new_incident_assigned_to_you: حوادث جديدة تم تعيينها لك + new_last_week: جديد (الاسبوع الماضي) + new_or_updated: جديد أو مُحدث + new_referred: إحالات جديدة + new_service_provision: تقديم خدمة جديدة + new_this_week: جديد(هذا الاسبوع) + no_action_risk: لا يوجد إجراء + no_case_stats: لا يوجد إحصائيات حالة + no_caseworker_data: ' بيانات الباحث الاجتماعي غير موجودة' + no_flagged_child: لا يوجد حالات مميزة بعلامة + no_flagged_incident: لا يوجد حوادث مميزة بعلامة + no_open_incidents: لا يوجد حوادث مفتوحة + no_overdue_activities: لا يوجد أنشطة متأخرة + no_recent_activities: لا يوجد أنشطة حديثة + no_scheduled_activities: لا يوجد أنشطة مجدولة + none_risk: لم تحدد الاولوية + number_of_victims: عدد الضحايا + number_of_violations: عدد الانتهاكات + number_of_violations_verified: التحقق من الانتهاكات + open: مفتوح + open_cases: حالات مفتوحة + open_incidents: حوادث مفتوحة + outstanding_transfers: عمليات التحويل غير المنجزة + overdue_activities: أنشطة متأخرة + overdue_cases_to_assign: الحالات المتأخرة بانتظار التعيين + overdue_cases_to_assign_high: لديك هذه الحالات منذ اكثر من ساعة + overdue_cases_to_assign_low: لديك هذه الحالات منذ اكثر من ثلاث ساعات + overview: لمحة عامّة + pending: قيد الانتظار + pending_approvals: الموافقات المعلّقة + pending_transfers: عمليات النقل المُعلّقة + protection_concern: شواغل الحماية + protection_concerns: مخاوف تتعلق بالحماية + range12+: '+12' + range4: 0-4 + range4_8: 4-8 + range8_12: 8-12 + recent_activities: أنشطة حديثة + recently_flagged_child: حالات تم تمميزها بعلامة مؤخرا + recently_flagged_incident: حوادث مميزة بعلامة مؤخرًا + referrals_by_social_worker: الإحالات بواسطة اخصائي الحالة + registration: التسجيل + rejected: رُفض + rejected_transfers: عمليات النقل المرفوضة + response: الاستجابة (قيد التقدم) + scheduled_activities: أنشطة مجدولة + score_range: نطاق النتائج + screening_service: خدمة الفرز + services: الخدمات + services_implemented: تم تقديم الخدمة + shared_from_my_team_pending_transfers: عمليات النقل المُعلّقة + shared_from_my_team_referrals: الإحالات + shared_from_my_team_rejected_transfers: عمليات النقل المرفوضة + shared_with_me_new_referrals: إحالات جديدة + shared_with_me_total_referrals: مجموع الإحالات + shared_with_me_transfers_awaiting_acceptance: عمليات النقل بانتظار القبول + shared_with_my_team_pending_transfers_overview: عمليات النقل في انتظار القبول + shared_with_my_team_pending_transfers: عمليات النقل المُعلّقة + shared_with_my_team_referrals: الإحالات + shared_with_others_pending_transfers: عمليات النقل المُعلّقة + shared_with_others_referrals: الإحالات + shared_with_others_rejected_transfers: عمليات النقل المرفوضة + status_of_cases: وضع الحالات + system_user: النظام + total: المجموع + total_cases: إجمالي الحالات + total_referred: مجموع الإحالات + tr_stats: تتبع الطلبات + transers_awaiting_acceptance: عمليات النقل بانتظار القبول + transfers_by_social_worker: التحويلات/النقل حسب اخصائي الحالة + users: أيقونة الإعدادات + violence_type: نوع العنف + with_incidents: مع حوادث + with_new_incidents: مع حوادث جديدة + without_incidents: من دون حوادث + worker_count_referrals_total: + zero: '%{case_worker} لديه %{stat} اجمالي إحالات' + one: '%{case_worker} لديه %{stat} اجمالي إحالات' + two: '%{case_worker} لديه %{stat} اجمالي إحالات' + few: '%{case_worker} لديه %{stat} اجمالي إحالات' + many: '%{case_worker} لديه %{stat} اجمالي إحالات' + other: '%{case_worker} لديه %{stat} اجمالي إحالات' + worker_count_total: + zero: '%{case_worker} لديه %{stat} اجمالي حالات' + one: '%{case_worker} لديه %{stat} اجمالي حالات' + two: '%{case_worker} لديه %{stat} اجمالي حالات' + few: '%{case_worker} لديه %{stat} اجمالي حالات' + many: '%{case_worker} لديه %{stat} اجمالي حالات' + other: '%{case_worker} لديه %{stat} اجمالي حالات' + workflow: سير العمل + workflow_team: سير العمل - حالات الفريق/الفرق + you_have: 'لديك' + disabled: + status: + disabled: 'مُعطلة ' + enabled: مُفعلة + email_notification: + assign: 'المستخدم %{user} قد عيّن السجل التالي %{record_type} لك: %{record_id}' + assign_subject: '%{record_type}: %{id} - مُعيّن لك' + approval_request: 'المستخدم %{user} يطلب موافقة من نوع%{approval_type} بخصوص الحالة %{case_id}' + approval_request_subject: 'حالة: %{id} طلب الموافقة' + approval_response: '%{user} لديه %{status} طلب الموافقة من نوع %{approval_type} للحالة %{case_id}.' + approval_response_subject: 'حالة: %{id} الإجابة على طلب الموافقة' + referral: 'المستخدم %{user} من الهيئة %{agency} قد أحال نوع السجل التالي %{record_type} إليك: رقم السجل %{record_id} لنوع الخدمة %{service_type}' + transfer: 'المستخدم %{user} قد حوّل السجل التالي %{record_type}لك: %{record_id}' + transfer_request_subject: طلب تحويل لحالة من حالاتك + transfer_subject: '%{record_type}: %{id} - التحويل' + referral_subject: '%{record_type}: %{id}- الإحالة' + transfer_request: 'مستخدم بريميرو %{user} من الهيئة %{agency} يطلب أن تنقل ملكية هذا السجل من نوع %{record_type} ومعرّف %{record_id} بحيث يتمكنون من تقديم خدمات إدارة للشخص في منطقتهم. إذا كان التحويل مقبولا من طرفك، يرجى النقر على رابط معرف نوع السجل %{record_type} في هذا الايميل لفتح نوع السجل %{record_type} في بريميرو والبدء بعملية التحويل.' + approval_request_html: 'المستخدم %{user} يطلب موافقة من نوع %{approval_type} بخصوص الحالة %{case_id} .' + approval_response_html: 'المستخدم %{user} لديه %{status} طلب الموافقة من نوع %{approval_type} للحالة %{case_id} .' + referral_html: 'المستخدم %{user} من الهيئة %{agency} قد أحال نوع السجل التالي %{record_type} إليك: رقم السجل %{record_id} لنوع الخدمة %{service_type}' + transfer_html: 'المستخدم %{user} قد حوّل السجل التالي %{record_type}لك: %{record_id}.' + assign_html: '%{user} عيّن السجلّ التالي %{record_type} لك: %{record_id}.' + transfer_request_html: 'مستخدم بريميرو %{user} من الهيئة %{agency} يطلب أن تنقل ملكية هذا السجل من نوع %{record_type} ومعرّف %{record_id} بحيث يتمكنون من تقديم خدمات إدارة للشخص في منطقتهم. إذا كان التحويل مقبولا من طرفك، يرجى النقر على رابط معرف نوع السجل %{record_type} في هذا الايميل لفتح نوع السجل %{record_type} في بريميرو والبدء بعملية التحويل.' + transfer_request_notes_html: 'ملاحظات من الشخص مقدم الطلب: %{request_transfer_notes}' + alert: 'تم تحديث% {record _ type}% {id} -% {form _ name}. يرجى تسجيل الدخول إلى Primero لمراجعة التغييرات.' + alert_subject: '% {سجل _ نوع}:% {معرف} -% {شكل _ اسم} محدث' + webpush_notification: + action_label: الذهاب الى الحالة + approval_request: + title: طلب الموافقة + body: ' طلب موافقة معلق لـلحالة% {نوع}.' + approval_response: + title: الرد بالموافقة + body: لقد تلقت إحدى حالاتك ردًا بالموافقة. + assign: + title: تكليف جديد + body: لقد تلقيت تكليف بحالة جديدة + referral: + title: إحالة جديدة + body: لقد تلقيت إحالة لحالة جديدة + transfer: + title: تحويل جديد + body: لقد تلقيت طلب تحويل لحالة جديدة + alert_case: + title: الحالة محدثة + body: "تم تحديث% {نوع} في إحدى حالاتك." + transfer_request: + title: طلب تحويل + body: لقد تلقيت طلب تحويل لحالة جديدة + encrypt: + export_type: نوع التصدير + file_name: قم بإنشاء اسم الملف الخاص بك (اختياري) + password_extra_info: يجب أن تتألّف كلمة المرور من 8 أحرف على الأقل. سيتم ربط كلمة المرور هذه بالملف الذي تم تصديره وسيتعين إدخالها من قبل أي شخص يفتح هذا الملف في المستقبل. + password_label: الرجاء إدخال كلمة المرور التي سوف تشفّر ملفك. + error_message: + address_fields: يجب عليك معالجة الحقول %{fields} في النماذج %{forms} + address_form_fields: يجب عليك معالجة الحقول %{fields} في هذا النموذج + address_subform_fields: 'النموذج الفرعي %{subform} يحتوي على عدد %{fields} من الحقول غير الصالحة' + error_401: لقد قمت بتسجيل الخروج. الرجاء تسجيل الدخول مجددا + error_something_went_wrong: حدث خطأ ما + error_page: + not_authorized: + server_error: أنت غير مخوّل لدخول هذه الصفحة. + title: غير مخوّل + not_found: + contact_admin: إذا كنت تعتقد إنك جئت إلى هنا بالخطأ يرجى الاتصال بالمشرف. + something_went_wrong: نأسف, يوجد خطأ. + errors: + api: + internal_server: خطأ في السيرفر + attachments: + maximum: لقد تخطيت عدد الملفات المسموح به في السجل + error_loading: خطأ في تحميل السجل (السجلات) + models: + agency: + code_present: لا يجب أن يكون فارغا + logo_format: يجب أن يكون الملف بنوع png + terms_of_use_format: يجب أن يكون الملف بتنسيق png + name_present: لا يجب أن يكون فارغا + child: + age: يجب أن يكون العمر ما بين 0 و 130 + date_of_birth: الرجاء إدخال تاريخ ميلاد صالح لسجل الحالة هذه + export_configuration: + opt_out_field_does_not_exist: حقل عدم المشاركة المحدد لا يوجد في السجل + record_type: نوع سجل غير صالح. يجب أن يكون طفل، طلب تتبع أو حادثة. + field: + translated_options_do_not_match: الخيارات المترجمة للحقل يجب أن يكون لها نفس المعرّف + location: + admin_level_present: لا يجب أن يكون فارغا + code_present: لا يجب أن يكون فارغًا + name_present: لا يجب أن يكون فارغًا + unique_location_code: يوجد موقع له نفس الكود بالفعل، يرجى إدخال كود مختلف + lookup: + being_used: هذا البحث مستخدم ولا يمكن حذفه + name_present: لا يجب أن يكون الاسم فارغاً + values_ids_blank: هناك معرّف فارغ لقيمة البحث + primero_module: + associated_record_types: يجب أن يرتبط نوع واحد من السجلات على الأقل بهذه الوحدة النمطية + form_section_ids: يجب أن يرتبط نموذج واحد على الأقل بهذه الوحدة النمطية + name_present: لا يجب أن يكون الاسم فارغاً + unique_name: توجد وحدة نمطية تحمل هذا الاسم بالفعل، الرجاء إدخال اسم مختلف + report: + module_presence: لا يجب أن تكون الوحدة النمطية فارغة + module_syntax: يجب أن تكون جميع وحدات التقرير النمطية موجودة + name_presence: لا يجب أن يكون الاسم فارغاً + role: + permission_presence: الرجاء تحديد إذن واحد على الأقل + user: + email: "يرجى إدخال عنوان بريد إلكتروني صالح (مثلاً: \"name@example.org\")" + password_mismatch: حقول كلمة المرور لا تحمل نفس كلمة المرور + password_length: يجب أن تتألف كلمة المرور من %{min} أحرف على الأقل + email_uniqueness: يوجد بالفعل مستخدم لعنوان البريد الإلكتروني هذا. الرجاء إدخال عنوان مختلف + code_of_conduct: + title_present: يجب ألا يكون العنوان فارغًا + content_present: يجب ألا يكون المحتوى فارغًا + created_by_present: يجب ألا يكون حقل الإنشاء بواسطة فارغًا + webpush_subscription: + notification_url_present: notification_url يجب ألا تكون فارغ + notification_url_format: يجب تنسيق عنوان URL لnotification_url + auth_present: يجب ألا يكون Auth فارغًا + p256dh_present: p256dh يجب ألا تكون فارغة + not_found: لم يتمّ العثور على أي سجل (سجلات) + try_again: حاول مجدّدًا + exports: + case_pdf: + all: PDF + one: PDF + selected: تحديد إلى PDF + csv: + all: CSV + one: CSV + selected: تحديد إلى CSV + custom: + all: مخصّص + custom_exports: + all: مخصّص + choose_fields: هل تريد اختيار حقول فردية من أجل نموذج؟ + empty_fields_forms: الرجاء تحديد بعض النماذج أو الحقول لتصديرها + empty_format: الرجاء تحديد صيغة لتصديرها. + empty_module: الرجاء تحديد وحدة نمطية لتصديرها. + empty_password: الرجاء إدخال كلمة المرور التي سوف تشفر ملفك. + field_label: الحقل + fields: حدد حقول لتصدير الملف + form_label: النموذج + format_label: حدد صيغة + forms: حدد نماذج لتصدير الملف + label: عمليات تصدير الملف المخصصة + module_placeholder: الرجاء تحديد وحدة نمطية. + select_module: حدد وحدة نمطية + submit: موافق + header: رأسيّة + custom_header: رأسيّة مُخصّصة + signatures: تضمين أسطر التوقيع لـ + include_implementation_logos: هل تريد تضمين شعارات التنفيذ؟ + include_implementation_logos_help_text: سيشمل ذلك الشعارات التي تظهر في قائمة التنقل وعلى صفحة تسجيل الدخول. + include_agency_logo: هل تريد تضمين شعار الهيئة؟ + include_other_logos: هل تريد تضمين شعارات أخرى؟ + duplicate_id_csv: + all: معرف مكرر + female_abbreviation: أنثى + headers: + age: العمر + case_id: رقم الحالة في النظام + child_name_last_first: اسم الطفل + family_size: 'حجم العائلة ' + moha_id: معَرف موها مهترئ + national_id_no: رقم الهوية الوطنية + progress_id: معرف التقدم + sex_mapping_m_f_u: 'الجنس ' + other_agency_id: كود المستشفى ورقم المريض + male_abbreviation: ذكر + unknown_abbreviation: U + exported: تمّ إنشاء ملف التصدير بنجاح + exported_error: خطأ في إنشاء ملف التصدير + forms: + button: تصدير نماذج + label: تصدير ملف + header: + form_group: مجموعة النموذج + form_name: اسم النموذج + field_id: معرِّف الحقل + field_type: نوع الحقل + field_name: اسم الحقل + required: مطلوب + on_mobile: على الهاتف المحمول + on_short_form: على نموذج قصير + option_ids: معرِّفات الخيار + options: الخيارات + options_lookup: عمليّات البحث + help_text: نص المساعدة + guiding_questions: اسئلة توجيهية + visible: مرئي + lookup_id: معرِّف البحث + lookup_name: إسم البحث + option_id: معرِّف الخيار + option_name: اسم الخيار + options: + location: المواقع + agency: الهيئات + user: المستخدمون + reportinglocation: مواقع الإبلاغ + subforms: 'النموذج الفرعي: %{subform_name}' + collapsed_fields: 'الحقول الهابطة: %{fields}' + country: بلاد + linkedincidents: ربط الحوادث + summary_header: + form_group: مجموعة نموذج بريميرو + form: نماذج بريميرو + status: الوضع + notes: ملاحظات + go_to_exports: انتقل إلى صفحة التصديرات للتنزيل + incident_recorder_xls: + all: مسجّل الحادثة + one: مسجّل الحادثة + selected: 'تم اختياره لمسجّل الحادثة ' + json: + all: JSON + one: JSON + selected: تحديد إلى JSON + list_view_csv: + all: تصدير ملف عرض القائمة + selected: تحديد إلى CSV + messages: + no_exporter: لم يتم تحديد أي مصدِّر + mrm_violation_xls: + all: انتهاكات آلية المراقبة والإبلاغ MRM + one: انتهاكات آلية المراقبة والإبلاغ MRM + selected: تحدد إلى انتهاكات آلية المراقبة والإبلاغ MRM + no_records: لا يوجد سجلات متاحة! + pdf: + all: PDF (غير مشفَّر) + one: PDF + selected: تحديد إلى PDF + pdf_exports: + label: PDF + recipient: المستلِم + case_worker: اخصائي الحالة + client: العميل + date: التاريخ + recipient_name: اسم المستلِم + recipient_agency: الهيئة المستلِمة + caseworker_name: اسم اخصائي الحالة + caseworker_agency: هيئة اخصائي الحالة + photowall: + all: Photo Wall + flag_suspect_record: مميّز بعلامة كسجلّ المشتبه به + no_photos_available: لا توجد صور متوفّرة + one: Photo Wall + reunited: إعادة لمّ الشمل + selected: تحديد إلى Photo Wall + success_message: إنشاء جدار Photo wall%{file_name} لن يتم تضمين الحالات التي لا تحتوي على صور. + printed: 'تمّت الطباعة %{date}' + queueing: جاري إنشاء ملف التصدير %{file_name} + selected_xls: + all: Excel + one: Excel + selected: تحديد إلى Excel + selected_fields: الحقول المختارة + unhcr_csv: + all: المفوضية السامية للأمم المتحدة لشؤون اللاجئين UNHCR + female_abbreviation: أنثى + headers: + age: العمر + case_status: 'وضع الحالة ' + causes_of_separation: سبب الانفصال + country_of_origin: البلد الأصلي + cpims_code: كود نظام المعلومات الخاص بحماية الطفل + current_care_arrangement: ترتيبات الرعاية الحالية + date_of_birth: 'تاريخ الميلاد ' + date_of_identification: تاريخ التحديد + family_count_no: عدد أفراد الأسرة + governorate_country: المحافظة - الدولة + id: المعرّف + individual_progress_id: معرف التقدم الفردي + locations_by_level: العنوان (مخيم، كتلة سكنية أو أي عنوان صالح كإحداثيات جي بي اس للمأوى) + long_id: هوية شخصية طويلة + moha_id: MOHA ID + name_of_caregiver: اسم مقدم الرعاية الكامل + name_of_child_last_first: اسم الطفل الكامل + primary_protection_concerns: تدابير الحماية الأولية + progres_id: معرف التقدم + reunification_status: حالة جمع شمل الأسرة + secondary_protection_concerns: تدابير الحماية الثانوية + sex: 'الجنس ' + sex_mapping_m_f_u: 'الجنس ' + short_id: هوية شخصية قصيرة + vulnerability_code: 'كود الضعف ' + vulnerability_details_code: 'كود تفاصيل الضعف ' + male_abbreviation: ذكر + one: المفوضية السامية للأمم المتحدة لشؤون اللاجئين UNHCR + selected: تحديد إلى المفوضية السامية للأمم المتحدة لشؤون اللاجئين UNHCR + unknown_abbreviation: U + xlsx: + all: Excel + one: Excel + selected: مختارة لنقلها إلى Excel + imports: + csv_hxl_location: + messages: + success: تمّ استيراد المواقع بنجاح + no_data: 'لم تتمّ معالجة المحتوى المستورد: لم يتم تمرير أي بيانات' + csv_parse_error: 'لم تتم معالجة المحتوى المستورد: خطأ في تحليل بيانات CSV' + error: 'السطر %{row_number} غير معالج: %{message}' + db_error: 'خطأ في إنشاء %{location_code}: %{message}' + locale_invalid: 'التخطي%{column_name}: الموضع غير صالح' + insert_all_error: 'لم تتم معالجة المحتوى المستورد: خطأ في قاعدة البيانات:%{message}' + csv_record: + messages: + success: تم استيراد السجلات بنجاح + no_data: 'لم تتمّ معالجة المحتوى المستورد: لم يتم تمرير أي بيانات' + no_file: 'لم تتم معالجة الاستيراد: الملف غير موجود' + csv_parse_error: 'لم تتم معالجة المحتوى المستورد: خطأ في تحليل بيانات CSV' + error: 'السطر %{row_number} غير معالج: %{message}' + db_error: 'خطأ في إنشاء %{location_code}: %{message}' + locale_invalid: 'تجاوز %{column_name} : الموقع غير صحيح' + insert_all_error: 'لم تتم معالجة المحتوى المستورد: خطأ في قاعدة البيانات:%{message}' + sync_record: + failed: 'آخر مزامنة: فشلت' + last: 'آخر مزامنة:%{date_time}' + not_found: 'آخر مزامنة: لم يتم العثور على البيانات' + retrieving: استرجاع البيانات. + see_details: راجع التفاصيل + fields: + action: إجراء + actions: الإجراءات + add: إضافة + add_new_field: انشاء حقل جديد + add_existing_field: إضافة حقل موجود + add_field: إضافة حقل + add_field_type: إضافة%{file_type} + attachments: + maximum_attached: تخطيت الحد الأقصى للمرفقات لكل سجل (% {maximumtachmentsPerRecord}) . يتضمن ذلك الصور والصوت والمستندات. الرجاء إزالة ملف قبل إضافة آخر. + audio: + current: التسجيل الصوتي الحالي + audio_upload_box: تحميل التسجيل الصوتي + bia_document: مستند المصلحة الفضلى + bid_document: مستند المصلحة الفضلى + check_box: خانات اختيار + clear_group_by: مسح المجموعة حسب + clear_sort_by: مسح الترتيب حسب + copy_from_another_form: تم نسخ هذا الحقل من نموذج آخر + create_field: انشاء حقل + create_unique_values: إنشاء قِيَم فريدة + date_field: حقل التاريخ + date_help: اليوم-الشهر-السنة + date_help_with_time: 'اليوم-الشهر-السنة الساعة: الدقيقة' + date_not_valid: التاريخ غير صحيح + time: الوقت + date_range: + date: التاريخ + date_range: نطاق التاريخ + from: من + to: إلى + view_by: اظهر حسب + date_range_field: نطاق التاريخ + date_time: التاريخ - الوقت + db_name: إسم قاعدة البيانات + default: افتراضي؟ + default_date_validation: التأكد من صحة التاريخ الافتراضي + default_to_current_date: هل تريد جعل التاريخ الحالي إعدادًا افتراضًّيا؟ + default_to_current_datetime: هل تريد جعل التاريخ والوقت الحاليين إعدادًا افتراضًّيا؟ + default_value: القيمة الافتراضية + deleted: تم إلغاء الحقل %{display_name}. + detail: تفاصيل + disabled: 'مُعطلة ' + display_name: عرض الاسم + document: + comments: ملاحظات + current: هل هذا هو الملف الحالي؟ + date: تاريخ المستند + name: اسم المستند + is_current: هل هذا هو الملف الحالي؟ + document_upload_box: تحميل المستند + edit_label: تعديل الحقل + enabled: مُفعلة؟ + enabled_label: مُفعلة + english_text: النص باللغة الإنجليزية + field_name: اسم الحقل + field_type: نوع الحقل + attachment_too_large: ' يجب ألّا يتعدّى حجم الملفّ 20 ميجابايت' + file_upload_box: + add_document_label: إضافة مستند + add_new_document_button_text: إضافة مستند آخر + add_new_photo_button_text: إضافة صورة أخرى + add_photo_label: إضافة صورة + document_description: وصف المستند + document_file_restrictions_message: ' يجب أن لا يتعدى حجم الملف 2mb أوأن لا يكون صيغة الملف exe.' + no_file_selected: لم يتم ارفاق أي ملف. + photo_file_restrictions_message: لا ينبغي أن تكون الصور أكبر من 10 ميجابايت. لا ينبغي أن تكون ملفات الصوت أكبر من 10 ميجابايت. كلما كانت الملفات أصغر كان ذلك أفضل. + recorded_audio_label: اضافة التسجيل صوتي + select_file_button_text: ارفاق ملف + find_lookup: ايجاد البحث + form_name: اسم النموذج + future_date_not_valid: لا يجوز أن يكون في المستقبل + guidance: توجيه + guiding_questions: اسئلة توجيهية + help_text: نص المساعدة + hide_on_view_page: اعرض الصفحة + label: الحقول + mobile_visible: تطبيق على الهاتف الجوال + move_to: الانتقال إلى + multi_select: يمكن تحديد خيارات متعددة + multi_select_box: اختيارات متعدّدة + must_be_english: يجب الإدخال باللغة الإنجليزية + name: الإسم + not_future_date: ليس تاريخ مستقبلي + number_not_valid: أرجو ادخل بيانات رقمية + numeric_field: حقل رقمي + on_collapsed_subform: على النموذج الفرعي الهابط؟ + option_strings_add_option: إضافة خيار + option_strings_source: عمليات البحث + option_strings_text: الخيارات + option_strings_text_display: نص الخيار + option_strings_text_key: مفتاح الخيار + options_indications_lookup_values: يمكنك استخدام عمليات البحث المحددة مسبقًا أو إنشاء قِيَم فريدة. + options_indications_restrictions: لا يمكنك فعل الأمرين. + options_or_lookup_warning: يُرجى إضافة خيارات أواختر بحث. لا تقوم بإدخالهما معا. + other_documents: مستند آخر + photo_upload_box: تحميل صورة + predifined_lookups: استخدام عمليات البحث المحددة مسبقًا + radio_button: زر انتقاء + remove: حذف + remove_attachment_confirmation: هل أنت متأكد أنك تريد إزالة هذا المرفق؟ + required: مطلوب + required_field: '%{field} مطلوب' + search_existing: ابحث في الحقول الموجودة + select_box: حدد القائمة المنسدلة + select_date_validation: اختر طريقة للتأكد من سلامة التاريخ + select_multiple: 'اختَر كلّ ما ينطبق ' + select_single: (اختَر...) + separator: فاصل + show: أظهِر؟ + show_on: اظهِر على + show_on_minify_form: نموذج قصير + skip_logic: + name: التخطي استنادا على نوع الإجابة + record_section: + title: 'يجب ان يظهر هذا الحقل في حال كان السجل ' + buttons: + add: اضافة شرط السجل + subform_section: + title: يجب ان يظهر هذا الحقل في حال كان النموذج الفرعي + buttons: + add: 'اضافة شرط النموذج الفرعي ' + subform: نموذج فرعي + subform_group_by: اجمع حسب + subform_remove_message: هل أنت متأكد من حذف هذا النموذج الفرعي؟ + subform_section: + description: وصف النموذج الفرعي + name: عنوان النموذج الفرعي + starts_with_one_entry: هل تريد البدء بمُدخل نموذج فرعي واحد؟ + subform_append_only: المزامنة الانتقائية على الهاتف المحمول + subform_prevent_item_removal: منع إزالة مُدخل النموذج الفرعي؟ + subform_sort_by: ترتيب حسب + successfully_added: تم إضافة الحقل بنجاح + tally_field: حقل الفرز + tally_items: عناصر العد + tally_items_maximum: (5 على الأكثر) + text_area: منطقة النص + text_field: حقل النص + textarea: منطقة النص + tick_box: خانة الاختيار + tick_box_label: تسمية خانة الاختيار + translation_text: نص الترجمة + total: المجموع + type: النوع + updated: تم تحديث الحقل + visibility: رؤية + web_app: تطبيق على شبكة الإنترنت + filters: + apply_filters: تقديم طلب + clear_filters: مسح + less: أقلّ... + more: أكثر... + save_filters: حفظ + categories: + violations: الانتهاكات + incidents: حوادث + individual_victims: ضحايا فردية + flags: + add_flag_tab: أضِف علامة جديدة + date: 'التاريخ:' + flag_added: تمّت إضافة العلامة بنجاح + flag_date: تاريخ وضع العلامة + flag_reason: سبب وضع العلامة + flag_reason_maximun_label: ' 255 حرفًا كحد أقصى.' + flag_resolved: تمّ حلّ العلامة + flags_tab: العلامات + no_flags: لم يتمّ العثور على علامات + resolve_button: حلّ + resolve_flag: حلّ العلامات + resolve_reason: سبب الإنهاء / الحل + resolved: العلامات التي تمّ حلّها + resolved_date: 'تمّ حلّها:' + resolved_reason: 'سبب الإنهاء / الحل' + title: العلامات + followup_reminders: + system_generated_followup_flag: زيارة متابعة إلزامية + form_section: + form_name: اسم النموذج + module: وحدة + name: الإسم + record_type: نوع السجل + required_field: '%{field} إجباري' + forms: + add: أضِف نموذج + description: وصف النموذج + fields: الحقول + form_description: وصف + form_group: مجموعة النموذج + form_title: عنوان النموذج + help_text: + must_be_english: يجب الإدخال باللغة الإنجليزية + related_groups: ضع النموذج في مجموعة من المستخدمين ذات الصلة + summariaze_purpose: لخّص الغرض من النموذج. يجب الإدخال باللغة الإنجليزية + invalid_characters_field: '%{field}يحتوي على أحرف غير صالحة.' + label: نماذج + manage: إدارة + messages: + created: تمّ إنشاء قسم النموذج بنجاح + fields_with_same_name: لا يمكن أن تحتوي النماذج على حقول بنفس الاسم + save_success: تمّ تحديث أقسام النموذج بنجاح + save_with_errors: حدثت مشكلة ولم يتمّ تحديث بعض أقسام النموذج. + updated: تمّ تحديث قسم النموذج بنجاح + use_existing: نشجعكم على استخدام النماذج القائمة حيث يسهل ذلك مشاركة البيانات ودمجها بين المؤسسات. + mobile_app: تطبيق على الهاتف الجوال + module: وحدة + no_subform_filters_added: لا يحتوي هذا النموذج الفرعي حاليًا على حقول. + record_type: نوع السجل + record_types: + approvals: الموافقات + case: حالة + child: حالة + incident: حادثة + individual_victim: ضحية فردية + potential_match: تشابه محتمل + record_information: معلومات السجلّ + referrals: الإحالات + reportable_follow_up: متابعة + reportable_protection_concern: مخاوف تتعلق بالحماية + reportable_service: خدمة + tracing_request: طلب التتبع + transfers_assignments: عمليات النقل والتعيينات + violation: انتهاك + registry_details: تفاصيل التسجيل + registry_record: سجل التسجيل + family_record: سجل الأسرة + family: سجل الأسرة + required_field: '%{field} هو حقل مطلوب' + select_label: اختيار + settings: إعدادات + show_on: اظهِر على + subform_need_to_be_added: يجب إضافتها. + subform_need_to_be_added_single: بحاجة الى ان يضاف + subform_not_found: لم يتمّ ايجاد النموذج الفرعي %{subform_name}. + title: عنوان النموذج + translations: + edit: تعديل الترجمات + edit_form_group: ' تعديل البحث عن مجموعة النموذج.' + manage: إدارة الترجمات + no_changes_message: لم تقم بأي تغييرات في الترجمة + note: 'ملاحظة:' + note_form_group: لإضافة ترجمات إلى مجموعة النماذج، يجب تعديل ترجمات البحث عن مجموعة النماذج. + select_language: اختَر اللغة + title: الترجمات + type_label: النوع + visibility: رؤية + web_app: تطبيق على شبكة الإنترنت + skip_logic: + name: التخطي استنادا على نوع الإجابة + section: + title: يجب ان يظهر هذا النموذج اذا + buttons: + add: اضافة الشرط + conditions: + add: اضافة الشرط + update: تحديث/تعديل الشرط + field_name: اسم الحقل + condition: الشرط + empty: لم يتم اضافة اي شروط + type: النوع + types: + and: + display_text: بالاضافة الى هذا الشرط + name: 'و ' + or: + display_text: أو هذا الشرط + name: أو + home: + ar: العربية + ar-IQ: العربية (العراقية) + ar-JO: العربية (الأردنية) + ar-LB: العربية (اللبنانية) + ar-SD: العربية (السودانية) + bn: বাংলা + cmn: اللغة الصينية + current_time_zone: المنطقة الزمنية الحالية + dashboard: لوحة المعلومات + en: English + es: Español + es-GT: أسبانية + es-ES: اسبانية(اسبانيا) + fr: Français + hu: المجرية + id: Bahasa + km: ភាសាខ្មែរ + ku: کوردی + ku-IQ: کوردی (بادینی) + fa-AF: فارسی (افغانستان) + ps-AF: پښتو (افغانستان) + sw-KE: الكيسواحيلية (كينيا) + sw-TZ: الكيسواحيلية (تنزانياا) + ne: النيبالية + om: أورومو + am-ET: الأمهرية (إثيوبيا) + tr: تركي + label: الصفحة الرئيسية + language: اللغة + manage_system_users: إدارة مستخدمي مزامنة السيرفر + my: ဗမာစာ + pl: بولندي + pt: Português + pt-BR: برتغالي(البرازيل) + records_need_attention: السجلات التي تحتاج إلى الإنتباه + ro: الروماني + ru: Русский + sk: سلوفينيا + so: Af-Soomaali + th: ไทย + uk: الأوكرانية + users: إدارة المستخدمين + view_records: عرض السجلات + welcome: مرحبا بكم في بريميرو + zh: 中文 + tet: لغة التيتوم + incident: + code: كود الحادثة + associated_case: "الحالة المرتبطة:" + link_incident_to_case: ربط الحادثة بحالة + link_incident_to_case_success: حادثة(حوداث) مرتبطة بحالة + messages: + creation_success: تم إنشاء سجل الحادثة بنجاح. + creation_success_queue: تمّ إنشاء سجل الحادثة بنجاح في الخلفية + disabled: تم تعطيل الحادثة + update_success: 'تم تحديث الحادثة %{record_id} بنجاح.' + update_success_queue: 'تم تحديث الحادثة %{record_id} بنجاح في الخلفية' + bulk_assign_limit_try_again: لا يمكنك تعيين أكثر من 100 حادثة في وقت واحد. يرجى تحديد 100 حادثة أو أقل ثم المحاولة مرة أخرى. + violation: + associated_violations: "المخالفات ذات الصلة:" + update_and_return: 'تحديث والرجوع الى %{association}' + save_and_return: 'اضافة والرجوع الى %{association}' + pending: قيد التحقّق + title: الانتهاكات + types: + killing: قتل الاطفال + maiming: تشويه الاطفال + recruitment: تجنيد و/او استخدام الاطفال + sexual_violence: الاغتصاب و / أو غيره من أشكال العنف الجنسي + abduction: الخطف + attack_on: الهجوم على المدرسة(المدارس) و/او المستشفى(المستشفيات) + attack_on_hospitals: الهجوم على المستشفى(المستشفيات) + attack_on_schools: الهجوم على المدرسة(المدارس) + military_use: الاستخدام العسكري للمدرسة(المدارس) و/او المستشفى(المستشفيات) + denial_humanitarian_access: منع وصول الخدمات الإنسانية للأطفال + incidents: + change_status: تغُير في الوضع + disable_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحادثة معطّلًا. + disable_dialog_title: تعطيل الحادثة + disable_success: تمّ تعطيل الحادثة بنجاح + enable_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحادثة مفعّلًا + enable_dialog_title: تفعيل الحادثة + enable_success: تمّ تفعيل الحوادث بنجاح + id: رقم الحالة في النظام + complete: متاح بدون الاتصال بالانترنت + date_of_interview: تاريخ المقابلة + date_of_incident: تاريخ الحادثة + incident_location: موقع الحادث + violations: الانتهاكات + export: تصدير + label: حوادث + filter_by: + filter_category: فئة المرشح + boys: الأولاد + by_date: حسب التاريخ + children: الأطفال + girls: الفتيات + incident_location: موقع الحادث + status: الوضع + unaccompanied_separated_status: وضع الحماية + unknown: غير معروف + verification_status: وضع التحقق + violence_type: نوع العنف + armed_force_group_party_name: القوات المسلحة أو الجماعات أو الأطراف الأخرى + armed_force_group_type: 'نوع مجموعة القوات المسلحة ' + violations: الانتهاكات + individual_violations: انتهاكات فردية + individual_age: عمر الفرد + individual_sex: جنس الفرد + victim_deprived_liberty_security_reasons: محرومون من الحرية + reasons_deprivation_liberty: ما هي أسباب الحرمان من الحرية؟ + victim_facilty_victims_held: يرجى تحديد المنشأة التي تم / تم احتجاز الضحية (الضحايا) فيها + torture_punishment_while_deprivated_liberty: هل تعرض / كان الطفل (الأطفال) للتعذيب أو غيره من ضروب المعاملة أو العقوبة القاسية أو اللاإنسانية أو المهينة أثناء حرمانه من الحرية؟ + verified_ghn_reported: حدد GHN الذي تم تضمين هذه الحادثة فيه + weapon_type: 'نوع السلاح / الطريقة المستخدمة' + facility_impact: 'نوع ومدى التأثير المادي' + facility_attack_type: 'نوع الانتهاك المتعلق بالصحة أو التعليم' + child_role: 'ما هو الدور الذي لعبه الطفل (الأطفال) في القوات / الجماعة المسلحة؟' + abduction_purpose_single: 'الغرض من الاختطاف' + military_use_type: 'نوع الاستخدام العسكري' + types_of_aid_disrupted_denial: 'نوع المساعدة / الخدمة المرفوضة / المعطلة.' + late_verified_violations: الانتهاكات التي تم التحقق منها في وقت متأخر + perpetrator_category: نوع المسيء + record_owner: مالك السجل + register_new_incident: حادثة جديدة + reassign: + multiple_successfully: Primero يقوم حاليا باعادة تخصيص الحوادث الخاص ب% {select _ records}. قد يستغرق تحديث كل هذه الحوادث عدة دقائق. لاحظ أن الحوادث المربوطة سابقاً لن يتم ربطها مجدداً. + selectable_date_options: + date_of_first_report: تاريخ المقابلة + mrm_date_of_first_report: تاريخ التقرير الأولي لعضوCTFMR + ctfmr_verified_date: تاريخ قرار التحقق من قبل CTFMR + incident_date_derived: تاريخ الحادثة + selected_records: 'سجل %{select_records} الحادثة (الحوادث) المختارة' + selected_records_assign: '% {حدد _ سجلات} حادثة (حوادث) مختارة. لاحظ أن الحوادث التي تم ربطها سابقاً لن يتم تحديدها.' + selected_all_records: 'اختَر جميع الحوادث %{total_records} التي تطابق هذا الاستعلام.' + summary_mrm: + label: ملخص الحادث + fields: + children_multiple_violation: + label: الأطفال المتضررون من انتهاكات متعددة + summary_of_incident: + label: ملخص الحادث + incident_total_tally: + label: عدد الضحايا + boys: الأولاد + girls: الفتيات + unknown: غير معروف + incident_date: + label: تاريخ الحادثة + incident_location: + label: موقع الحادثة + incident_description: + label: حساب الحادثة + incident_update: + label: تحديث الحادثة + survivor_code: كود الناجية + show_incident: 'مُعرِّف الحادثة %{short_id}' + social_worker: اخصائي الحالة + verify_mrm: تحقق من MRM + violation_type: نوع الانتهاك + violence_type: نوع العنف + type_violence: نوع العنف + violation_summary: ملخص + sort_by: ترتيب حسب + key_performance_indicators: + label: "نبض / مؤشرات الأداء الرئيسة" + case_assessment: "تقييم الحالة" + case_action_planning: "تخطيط عمل الحالة" + case_action_plan_implementation: "تنفيذ خطة عمل الحالة" + case_follow_up: "متابعة الحالة" + case_closure: "إغلاق الحالة" + feedback: "تغذية راجعة" + other: "أخرى" + date_format: "%b %Y" + date_range_select: + custom_range: 'نطاق التاريخ المخصص' + long_date_format: "يوم/شهر/سنة" + time_periods: + all_time: 'كلّ الوقت' + current_month: "الشهر الحالي" + last_3_months: "الأشهر الثلاثة 3 الأخيرة" + last_6_months: "الأشهر الستة 6 الأخيرة" + last_1_year: "العام المنصرم" + 0-3days: "0 - 3 أيام" + 4-5days: "4 - 5 أيام" + 6-14days: "6 - 14 أيام" + 15-30days: "15 - 30 أيام" + 1-3months: "1 - 3 أشهر" + 4months: "أكثر من 3 أشهر" + 1-month: "أقلّ من شهر 1" + 3-6months: "3 -6 أشهر" + 7-months: "أكثر من 6 أشهر" + helptext: + helptext: "تعرف على مؤشر الأداء الرئيس هذا." + number_of_cases: + title: "1. عدد الحالات المسجّلة" + reporting_site: "موقع الإبلاغ" + helptext: | + يحتسب هذا المؤشر عدد الحالات الجديدة التي يتم فتحها شهريًا في كلّ موقع إبلاغ. + يُشير موقع الإبلاغ إلى الموقع الذي تقدم فيه منظمة المستخدم الخدمات + و حيث تم الإبلاغ عن الحالة إلى مزود الخدمة. + number_of_incidents: + title: "2. عدد الحوادث المسجّلة" + reporting_site: "موقع الإبلاغ" + helptext: | + يحتسب هذا المؤشر عدد الحوادث الجديدة التي يتم فتحها شهريًا في كلّ موقع إبلاغ. + يُشير موقع الإبلاغ إلى الموقع الذي تقدم فيه منظمة المستخدم الخدمات + و حيث تم الإبلاغ عن الحالة إلى مزود الخدمة. + reporting_delay: + title: "3. الإبلاغ عن التأخير" + delay: "التأخير" + total_incidents: "مجموع الحوادث" + helptext: "يحتسب هذا المؤشر ويصنف عدد الأيام التي انقضت بين وقت\nتعرّض الناجية للعنف القائم على النوع الاجتماعي والوقت الذي أبلغت فيه الناجية مقدم الخدمة بذلك لأول مرة. يتمّ \nاحتسابه بناءً على وقت إبلاغ منظمة المستخدم بالحادثة. يتمّ \nتصنيف البيانات على أساس فترات زمنية مختلفة (0-3 أيام ؛ 4-5 أيام ؛ 6-14 يومًا ؛ 15-30 يومًا ؛\nأكثر من شهر واحد ؛ أكثر من 3 أشهر).\n" + service_access_delay: + title: "تأخير الوصول إلى الخدمة" + delay: "التأخير" + total_incidents: "مجموع الحوادث" + assessment_status: + title: "4. وضع التقييم" + completed: "مكتمل" + completed_supervisor_approved: "مكتمل وتمّت موافقة الحالات" + helptext: | + يحتسب هذا المؤشر نسبة الحالات النشطة التي استكمل نموذج تقييم بشأنها. + يعتبر التقييم مكتملاً عندما يتمّ إكمال مجموعة من الحقول الإلزامية + في "نموذج تقييم الناجين". + completed_case_safety_plans: + title: "5. خطط سلامة الحالة المكتملة" + completed: "خطّة سلامة الحالة المكتملة" + helptext: | + يحسب هذا المؤشر نسبة الحالات النشطة التي أعتُبِر أنّ + خطة السلامة ضرورية لها ومُكتملة (على سبيل المثال، عنف الشريك الحميم، ومخاطر الانتحار / القتل، وحماية الطفل). + تُعتبر خطة السلامة مكتملة عندما يتمّ استكمال مجموعة من الحقول الإلزامية + ضمن نموذج خطة السلامة. + completed_case_action_plans: + title: "6. خطط عمل حالة مكتملة" + completed: "خطّة عمل حالة مكتملة" + label: "6. خطّة عمل حالة مكتملة" + helptext: "يحتسب هذا المؤشر نسبة الحالات النشطة التي استكملت خطة عمل حالة بشأنها. \nتُعتبر خطة عمل حالة مكتملة عندما يتمّ إكمال مجموعة من الحقول الإلزامية\nفي نموذج خطّة العمل.\n" + completed_supervisor_approved_case_action_plans: + title: "7. وافق مشرف الحالات على خطط عمل الحالة" + completed_and_approved: "تمّت الموافقة على خطط عمل الحالة المكتملة من قبل مشرف الحالات" + helptext: "يحتسب هذا المؤشر نسبة الحالات النشطة التي استكملت خطة عمل حالة بشأنها \nوالموافقة عليها من قبل مشرف الحالات. تعتبر خطة عمل حالة مكتملة \nعندما يتمّ إكمال مجموعة من الحقول الإلزامية في نموذج خطّة العمل. تعتبر خطة الحالة\nمعتمدة عندما يطلب اخصائي الحالة الموافقة على خطة الحالة\nووافق مشرف الحالات على خطة الحالة على المنصة.\n" + services_provided: + title: "8. الخدمات المقدَّمة" + service: "الخدمة" + count: "الأوقات المُقدَّمة" + male: "ذكر" + female: "أنثى" + 0-11: "0-11" + 12-17: "12-17" + '>18': ">18" + disability: "اعاقة " + no_disability: "لا وجود لاعاقة" + helptext: |+ + يحسب هذا المؤشر نوع الخدمة (الخدمات) المقدمة للناجين في عملية إدارة الحالة. + من خلال الخدمة المقدمة ، فإننا نعني الخدمة التي تقدمها منظمة المستخدم + داخليًا ، وليست خدمة مقدمة عن طريق الإحالات إلى خدمات أخرى أو إحالات داخلية + + average_referrals: + title: "9. متوسّط الإحالات" + label: "متوسط الإحالات لكلّ حالة" + helptext: |+ + يحسب هذا المؤشر متوسط عدد الإحالات لكل حالة مسجلة (لجميع الأنواع + من الخدمات) في جميع الحالات ، سواء كانت الحالة نشطة / مفتوحة أو مغلقة. يتضمن الإحالات + المسجلة في علامة تبويب الحالة ، وليس فقط الإحالات التي تتم من خلال النظام الأساسي + + referrals_per_service: + title: "الإحالات لكلّ خدمة" + average_followup_meetings_per_case: + title: "10. متوسط اجتماعات المتابعة لكل حالة" + label: "متوسط اجتماعات المتابعة لكل حالة" + helptext: | + يحتسب هذا المؤشر متوسط عدد اجتماعات المتابعة التي أجريت لكلّ حالة نشطة + من قبل كلّ اخصائي الحالة على المنصة. يتمّ اجتماع المتابعة بين اخصائي الحالة والناجية + بعد المقابلة الأوّليّة / الإفصاح الأولي. + time_from_case_open_to_close: + title: "11. الوقت المستغرق من فتح الحالة إلى اغلاقها" + time: "الوقت" + percent: "نسبة الحالات المئوية" + helptext: "يقيس هذا المؤشر المدة التي تظلّ فيها الحالات مفتوحة، والمدة التي تستغرقها عملية إدارة الحالة\nمن الإبلاغ الأوّلي لمنظمة المستخدم حتى إغلاق الحالة. \nيتمّ تقسيم المدة الزمنية حسب الإطار الزمني التالي: أقل من شهر واحد ؛ بين 1 و 3 أشهر ؛ \nبين3-6 أشهر ؛ أكثر من 6 أشهر.\n" + case_closure_rate: + title: "12. عداد إغلاق الحالات" + reporting_site: "موقع الإبلاغ" + helptext: "يقيس هذا المؤشر عدد الحالات التي يتمّ إغلاقها شهريًا في كلّ موقع إبلاغ.\nيُشير موقع الإبلاغ إلى الموقع الذي تقدم فيه منظمة المستخدم الخدمات \nو حيث تم الإبلاغ عن الحالة إلى مزود الخدمة.\n" + client_satisfaction_rate: + title: "13. معدل رضا العميل" + label: "رضا العميل" + invalid: "لا يمكننا حساب هذا في الوقت الحالي." + helptext: | + يقيس هذا المؤشر النسبة المئوية للناجين الذين أكملوا استبيان آراء العملاء + والذين يشعرون بالرضا عن خدمات إدارة الحالة المقدّمة لهم. + يتمّ إحتساب هذا المؤشر من خلال استكمال نموذج استبيان آراء العميل على +GBVIMS من قبل موظف + مختلف عن اخصائي الحالة الذي قدّم الخدمة للناجية. + supervisor_to_caseworker_ratio: + title: "14. عدد اخصائيين الحالة لكل مشرف." + label: "عدد اخصائيين الحالة لكلّ مشرف" + helptext: "يعكس هذا المؤشر عدد اخصائيين الحالة الذين يشرف عليهم مشرف الحالات: ويُعرف بعدد اخصائيين الحالة لكلّ مشرف. \nيعتمد هذا الحساب على الأدوار المخصّصة من النظام على المنصّة.\n" + case_load: + title: "15. عدد الحالات" + case_load: "عدد الحالات" + percent: "النسبة المئوية لاخصائيين الحالة العاملين على حالات" + 10cases: "أقل من 10 حالات" + 20cases: "11 - 20 حالة" + 21-30cases: "21 - 30 حالة" + 30cases: "أكثر من 30 حالة" + helptext: | + يقيس هذا المؤشر متوسط عدد الحالات لكلّ اخصائي الحالة فاعل بناءً على الحالات النشطة. + يتمّ تقسيم نسبة الحالات إلى اخصائيين الحالة وفقًا للتقسيم التالي: + أقلّ من 10 حالات مفتوحة ، بين 10-20 حالة مفتوحة ، بين 21-30 حالة مفتوحة أكثر من 30 حالة مفتوحة. + date_range_dialog: + title: "نطاق تاريخ مُخصّص" + description: "بمجرد تطبيق هذا التغيير، سيتمّ اختيار البيانات من بين التاريخين التاليين." + apply: 'تقديم طلب' + from: 'من' + to: 'إلى' + aria-labels: + from: "سيتم اختيار البيانات بعد هذا التاريخ" + to: "سيتم اختيار البيانات قبل هذا التاريخ" + location: + base_types: + camp: مخيم + chiefdom: مشيخة + city: مدينة + community: مجتمع محلي + country: دولة + county: مقاطعة + district: الحي + governorate: إمارة + locality: ناحية + other: أشياء أخرى + province: إقليم + region: منطقة + site: موقع + state: ولاية + sub-district: حي فرعي + village: قرية + zone: منطقة + association: منظمة + division: قسم + central_warehouse: المستودع المركزي + warehouse: مستودع + buyingstation: محطة شراء + township: بلدة + municipality: بلدية + autonomous_region: منطقة الحكم الذاتي + parish: الرعية + cercle: الدائرة + sub-county: المناطق + departement_fr: 'المقاطعات' + region_fr: 'المنطقة' + wilaya: 'ولاية' + commune: 'البلدة' + division_fr: 'القسم' + prefecture: 'المقاطعات' + moughataa: 'مقطعة' + sub_division: 'القسم الفرعي' + sub-prefecture: 'المقاطعات الفرعية ' + label: الموقع + name: الإسم + code: الكود + admin_level: مستوى المسؤول + type: النوع + hierarchy: التسلسل الهرمي + import_title: موقع الاستيراد + message: يرجى تحديد ملف CSV للتحميل. يجب أن يستخدم هذا الملف ترميز UTF-8 وأن يتضمن علامات تصنيف HXL في الرأسيّة الثانية من كلّ عمود. + no_location: يرجى استيراد المواقع قبل إنشاء أي حسابات مستخدمين. + enable_title: تفعيل الموقع + enable_text: هل أنت متأكد؟ إذا قمت بتفعيل المواقع المحددة ، فستظهر كخيارات في حقول الموقع + disable_title: تعطيل الموقع + disable_text: هل أنت متأكد؟ إذا قمت بتعطيل المواقع المحددة ، فلن تظهر كخيارات في حقول الموقع + logger: + actions: + _approved: تم الموافقة عليه + _rejected: رُفض + _requested: مطلوب + add_note: اضف ملاحظة + assign: تعيين + assign_to: يسند إلى + attach: يربط + bulk_assign: تعيين بالجملة + bulk_create: إنشاء مجمّع + bulk_index: فهرس بالجملة + case_plan_approved: تمت الموافقة على خطة الحالة + case_plan_rejected: تم رفض خطة الحالة + case_plan_requested: مطلوب خطة حالة + close: غلق + create: إنشاء + create_bulk: إنشاء الجزء الأكبر + delete: حذف + destroy: هدم + detach: فصل + enable_disable_record: تمكين تعطيل السجل + export: يصدر + flag: علامة + import: يستورد + incident_details_from_case: تفاصيل الحادث من القضية + index: فهرس + list: قائمة + login: تسجيل الدخول + password_reset: إعادة تعيين كلمة المرور + password_reset_request: طلب إعادة تعيين كلمة المرور + refer: إحالة + refer_accepted: تم قبول الإحالة + refer_done: تمت الإحالة + refer_rejected: إحالة مرفوضة + refer_revoke: إبطال الإحالة + refer_to: إحالة إلى + reopen: أعد فتح + services_section_from_case: قسم الخدمات من القضية + show: عرض + show_alerts: عرض التنبيهات + traces: آثار + transfer: تحويل + transfer_accepted: تم قبول التحويل + transfer_rejected: تم رفض التحويل + transfer_request: طلب تحويل + transfer_to: حول إلى + unflag: إزالة العلامة + update: تحديث + user_password_reset_request: طلب إعادة تعيين كلمة مرور المستخدم + webhook: الويب هوك + approve_form: + action_plan: نموذج خطّة العمل + bia: نموذج المصلحة الفضلى + case_plan: نموذج خطة الحالة + closure: نموذج إغلاق + 'false': رفض + gbv_closure: نموذج إغلاق العنف القائم على النوع الإجتماعي + 'true': موافقة + assessment_approved: "%{approval_label} تمتّ الموافقة عليه لـ" + assessment_requested: "%{approval_label} مطلوب لـ" + bulk_index: قائمة كاملة + by_user: من قبل المستخدم + case_plan_approved: "%{approval_label} تمتّ الموافقة عليه لـ" + case_plan_requested: "%{approval_label} مطلوب لـ" + close: اغلاق + closure_approved: "%{approval_label} تمتّ الموافقة عليه لـ" + closure_requested: "%{approval_label} مطلوب لـ" + consent_count: عدد الموافقات + copy: جاري النسخ + create: إنشاء + create_subform: جاري إنشاء النموذج الفرعي + destroy: جاري الحذف + edit: التعديل + enable_disable_record: تفعيل/تعطيل + export: تصدير بيانات إلى + flag: وضع علامة + flag_records: وضع علامة + graph_data: عرض بيانات الرسم البياني + hide_name: + protect: إخفاء الاسم + view: إظهار الاسم + index: إدراج السجلات + list: قائمة + login: تسجيل الدخول + logout: تسجيل الخروج + lookups_for_field: عمليات البحث عن الحقل + mark_for_mobile: + 'false': إزالة علامة للمحمول + 'true': وضع علامة للمحمول + match_record: سجلات متشابهة + permitted_field_list: قائمة الحقل المسموح بها + quick_view: جاري عرض لمحة سريعة + reassign: جاري التعيين + resources: + audit_log: سجل التدقيق + user: المستعمل + agency: الهيئة + user_group: مجموعة المستخدمين + child: طفل + alert: يحذر + form_section: استمارة + lookup: ابحث عن + system_settings: اعدادات النظام + permission: الإذن + dashboard: لوحة القيادة + report: تقرير + bulk_export: تصدير بالجملة + saved_search: تم الحفظ + role: دور + incident: حادث + location: موقع + primero_configuration: إعدادات Primero + code_of_conduct: مدونة قواعد السلوك + task: مهمة + record_state: + 'false': تعطيل + 'true': تشغيل + refer: قم بالإحالة + refer_to: ابحث عن متلقّي الإحالة + referral: جاري الإحالة + relinquish_referral: تم إرجاع الإحالة + reopen: إعادة فتح + reopen_case: جاري إعادة الفتح + request_approval: + action_plan: طلب الموافقة على نموذج خطة العمل + bia: طلب مصادقة على نموذج المصلحة الفضلى + case_plan: طلب مصادقة على نموذج خطة الحالة + closure: طلب مصادقة على نموذج الإغلاق + gbv_closure: طلب الموافقة على نموذج إغلاق العنف القائم على النوع الإجتماعي + request_transfer: جاري إرسال طلب التحويل + request_transfer_view: جاري عرض طلب التحويل + save_subform: جاري حفظ النموذج الفرعي + search: البحث عن واجهة برمجة التطبيقات + show: جاري العرض + show_alerts: عرض التنبيهات لـ + to: الى + to_user: للمستخدم + transfer: جاري التحويل + transfer_status: + Accepted: التحويل مقبول + Rejected: التحويل مرفوض + unflag: إزالة علامة + update: جاري التحديث + login: + label: تسجيل الدخول + password: + label: كلمة المرور + password_confirmation: + label: تأكيد كلمة المرور + password_match: + label: يجب أن تتطابق كلمة المرور + provider_title: مع %{provider} + title: تسجيل الدخول + username: اسم المستخدم + password_reset_modal: إعادة تعيين كلمة المرور + password_reset_modal_text: سيرسل بريميرو Primero رابط إعادة تعيين كلمة المرور إلى عنوان بريدك الإلكتروني + password_reset_email: البريد الإلكتروني + forgot_password: هل نسيت كلمة المرور؟ + email: + label: البريد الإلكتروني + lookup: + create: بحث جديد + enabled_label: مُفعل + english_label: النص باللغة الإنجليزية + label: بحث + language_label: اللغة + messages: + cannot_create: لا يمكن إنشاء البحث + correct_errors: 'الرجاء تصحيح الأخطاء التالية وإعادة الإرسال:' + created: تم إنشاء البحث بنجاح + updated: تمّ تحديث البحث بنجاح + name: الاسم + no_options: لا يحتوي هذا البحث على خيارات حاليًّا. + translation_label: نص الترجمة + values: خيارات + locked_alert_message: عمليات البحث مقفلة + managed_reports: + generated_on: انشئت في + label: رؤى + total: المجموع + violations_total: الانتهاكات + filter_by: + date: التاريخ + verification_status: وضع التحقق + violation_type: نوع الانتهاك + status: الوضع + status_open: 'مفتوح ' + status_closed: مغلق + user_group: مجموعة مستخدمين + agency: الهيئة + by: بواسطة + workflow: حالة سير العمل + cp_incident_violence_type: نوع العنف + referral_transfer_status: وضع الإحالة / النقل + protection_concerns: مخاوف تتعلق بالحماية + location: مكان الإبلاغ + followup_type: نوع المتابعة + service_type: نوع الخدمة + status_options: + open: فتح + closed: غلق + by_options: + created_by_groups: مجموعات المستخدمين لمنشئ السجل + owned_by_groups: مجموعات المستخدمين لمنشئ السجل + created_organization: هيئة من أنشأ السجل + owned_by_agency_id: هيئة مالك السجل + referral_transfer_status_options: + in_progress: معلق + accepted: تمت الموافقة + rejected: رُفض + done: تم + date_range: + month: شهر + quarter: ربع + year: سنة + week: أسبوع + date_range_options: + this_quarter: الربع الحالي + last_quarter: الربع الماضي + this_month: الشهر الحالي + last_month: الشهر الماضي + this_week: هذا الأسبوع + last_week: الاسبوع الماضي + this_year: العام الحالي + last_year: العام الماضي + custom: مخصّص + no_data: لا يوجد بيانات لهذه الرؤى + no_data_table: لا يوجد جدول بيانات لهذه الرؤى + incomplete_data: بيانات غير مكتملة + individual_children: + name: الأطفال الفرديين + reports: + individual_children: الأطفال الفرديين + sub_reports: + individual_age: الأطفال الفرديين حسب العمر + individual_violation_type: الأطفال الفرديين حسب نوع الانتهاك + individual_region: الأطفال الفرديين حسب المنطقة + individual_perpetrator: عدد الاطفال حسب المسيئين + services: + name: الخدمات + description: الحالات التي تحتوي على أنواع الخدمة المحددة، مقسمة حسب العمر والجنس. + services_report: + reports: + services: خدمات + description: الحالات التي تحتوي على أنواع الخدمة المحددة، مقسمة حسب العمر والجنس. + sub_reports: + services: خدمات + filter_options: + service_implemented_day_time: خدمات اكتملت + followups: + name: المتابعات + description: الحالات مع أنواع المتابعة المحددة، مقسمة حسب العمر والجنس. + followups_report: + filter_options: + followup_date: تاريخ المتابعة + reports: + followups: المتابعات + description: الحالات مع أنواع المتابعة المحددة، مقسمة حسب العمر والجنس. + sub_reports: + followups: المتابعات + protection_concerns: + name: مخاوف تتعلق بالحماية + description: الحالات المتعلقة بمخاوف الحماية المحددة، مقسمة حسب العمر والجنس. + protection_concerns_report: + reports: + protection_concerns: مخاوف تتعلق بالحماية + description: الحالات المتعلقة بمخاوف الحماية المحددة، مقسمة حسب العمر والجنس. + sub_reports: + protection_concerns: مخاوف تتعلق بالحماية + filter_options: + registration_date: تاريخ التسجيل + reporting_locations: + name: مكان الإبلاغ + description: 'الحالات التي تم تحديد موقع الإبلاغ عنها، مقسمة حسب العمر والجنس.' + reporting_locations_report: + reports: + reporting_locations: مكان الإبلاغ + sub_reports: + reporting_location_by_sex_and_age: مكان الإبلاغ + filter_options: + registration_date: تاريخ التسجيل + ghn_report: + name: المذكرة الافقية الشاملة + reports: + ghn_report: المذكرة الافقية الشاملة + sub_reports: + verified_information: معلومات تم التحقق منها - الضحايا + late_verification: التحقق المتأخر - الضحايا + unverified_information: معلومات لم يتم التحقق منها - الضحايا + verified_information_violations: معلومات تم التحقق منها - الانتهاكات + late_verification_violations: التحقق المتأخر - الانتهاكات + unverified_information_violations: معلومات لم يتم التحقق منها - الانتهاكات + killing: قتل الاطفال + maiming: تشويه الاطفال + recruitment: تجنيد و/او استخدام الاطفال + sexual_violence: الاغتصاب و / أو غيره من أشكال العنف الجنسي + rape: الاغتصاب و / أو غيره من أشكال العنف الجنسي + abduction: الخطف + attack_on_hospitals: الهجوم على المستشفى(المستشفيات) + attack_on_schools: الهجوم على المدرسة(المدارس) + military_use: الاستخدام العسكري للمدرسة(المدارس) و/او المستشفى(المستشفيات) + denial_humanitarian_access: منع وصول الخدمات الإنسانية للأطفال + multiple_violations: الأطفال المتضررون من انتهاكات متعددة + detention: احتجاز + boys: الأولاد + girls: الفتيات + total: المجموع + unknown: غير معروف + associated_violations: 'المخالفات ذات الصلة:' + violations: + name: الانتهاكات + filter_options: + incident_date: تاريخ الحادثة + date_of_report: تاريخ التقرير + ctfmr_verified_date: تاريخ التحقق + verified: تم التحقق منه + reports: + killing: قتل الاطفال + maiming: تشويه الاطفال + recruitment: تجنيد و/او استخدام الاطفال + sexual_violence: الاغتصاب و / أو غيره من أشكال العنف الجنسي + rape: الاغتصاب و / أو غيره من أشكال العنف الجنسي + abduction: الخطف + attack_on_hospitals: الهجوم على المستشفى(المستشفيات) + attack_on_schools: الهجوم على المدرسة(المدارس) + military_use: الاستخدام العسكري للمدرسة(المدارس) و/او المستشفى(المستشفيات) + denial_humanitarian_access: منع وصول الخدمات الإنسانية للأطفال + detention: احتجاز + sub_reports: + children: الأطفال + combined: الانتهاكات + denial_humanitarian_access: منع وصول الخدمات الانسانية + denial_type: انواع المنع + detention_detained: البقاء محتجزا + detention_released: الافراج + perpetrators: عدد الاطفال حسب المسيئين + perpetrators_denial: عدد الانتهاكات حسب المسيئين + perpetrator_detention: عدد الاطفال حسب المسيئين + perpetrators_incidents: عدد الحوادث حسب المسيئين + reporting_location_incidents: عدد الحوادث حسب المنطقة + reporting_location: عدد الاطفال حسب المنطقة + reporting_location_detention: عدد الاطفال حسب المنطقة + reporting_location_denial: عدد الاختراقات حسب المنطقة + attack_type: عدد الاطفال حسب نوع الاعتداء + boys: الأولاد + girls: الفتيات + unknown: غير معروف + total: المجموع + violation: الانتهاكات + sexual_violence_type: شكل (أشكال) العنف الجنسي + detention_status: وضع الأطفال المحتجزين + type_of_use: نوع الاستخدام + factors_of_recruitment: اسباب التوظيف + still_being_held: لا يزال محتجزا + released: 'الافراج' + escaped: 'هرب' + abduction_reasons: أسباب الاختطاف + abducted_status: حالة المخطوف + facility_attack_type: نوع الانتهاك + received_response: تلقى الأطفال استجابة + male: ذكر + female: أنثى + military_use_type_of_use: عدد الانتهاكات حسب نوع الاستخدام + gbv_statistics: + name: احصاءات GBV + filter_options: + date_of_first_report: تاريخ المقابلة + incident_date: تاريخ الحادثة + reports: + perpetrators: المسيئين + survivors: الناجين + referrals: الإحالات + sub_reports: + service_safehouse_referral: إحالة البيت الآمن / المأوى الآمن + service_medical_referral: إحالة صحية / طبية + service_psycho_referral: خدمات الاستشارة النفسية / الاجتماعية + service_legal_referral: خدمات المساعدة القانونية + service_police_referral: الشرطة أو أي نوع آخر من خدمات الأمن + service_livelihoods_referral: خدمات الاعاشة + service_protection_referral: خدمات حماية الطفل + survivors_disability_type: مع اعاقات + workflow_report: + name: سير العمل + description: الحالات والحوادث مع أوضاع سير عمل محددة، مقسمة حسب العمر والجنس. + reports: + cases_workflow: سير العمل - الحالات + incidents_workflow: سير العمل - الحوادث + filter_options: + registration_date: تاريخ التسجيل + sub_reports: + case_workflow_by_sex_and_age: إجمالي عدد الحالات حسب الجنس والعمر + incident_workflow_by_sex_and_age: إجمالي عدد الحوادث حسب الجنس والعمر + cases_workflow_report: + name: سير العمل + description: الحالات والحوادث مع أوضاع سير عمل محددة، مقسمة حسب العمر والجنس. + reports: + cases_workflow: سير العمل - الحالات + filter_options: + registration_date: تاريخ التسجيل + sub_reports: + case_workflow_by_sex_and_age: إجمالي عدد الحالات حسب الجنس والعمر + referrals_transfers_report: + name: الإحالات والانتقالات + description: الإحالات والانتقالات التي حدثت خلال فترة زمنية محددة. مقسمة حسب هيئات المرسلة والمستقبلة أو مجموعات المستخدمين. + reports: + total_referrals: الإحالات + total_transfers: الانتقالات + sub_reports: + total_transfers_by_user_groups: إجمالي عمليات النقل + total_referrals_by_user_groups: إجمالي عمليات الإحالة + filter_options: + registration_date: تاريج التسجيل + violence_type_report: + name: نوع العنف + reports: + cases_violence_type: نوع العنف- الحالات + incidents_violence_type: نوع العنف- الحوداث + filter_options: + registration_date: تاريخ التسجيل + sub_reports: + case_violence_type_by_sex_and_age: إجمالي عدد الحالات حسب الجنس والعمر + incident_violence_type_by_sex_and_age: إجمالي عدد الحوادث حسب الجنس والعمر + success_message: تمّ إنشاء ملف التصدير بنجاح + messages: + alert_items: لديك%{items} عناصر ملحوظة. + alerts_for: + approval: الموافقة معلّقة لـ%{form_section_name} + field_change: 'تمّ تحديث %{form_section_name} في %{alert_time}' + transfer_request: تمّ القيام بطلب تحويل في %{date}من قبل %{user} إلى %{agency} + duplicate_field: 'هذه الحالة %{field_name} مدخلة مسبقا يرجى العمل على ما يلي: + + + العودة للقائمة الرئيسية والبحث عن الحالة من خلال الرقم الوطني + + إضافة الحادثة الجديدة على الحالة المدخلة مسبقا واستكمال العمل على الحالة + + ابلاغ مدير النظام برقم الحالة الجديدة المكررة المدخلة من قبلكم لغاية تعطيلها' + cannot_edit: لا يمكن تعديله + confirmation_message: انقر فوق موافق لتجاهل أي تغييرات غير محفوظة والعودة إلى عرض القائمة. انقر فوق إلغاء للعودة إلى السجل. + confirmation_message_subform: النقر على موافق سيتجاهل أي تغييرات غير محفوظة والعودة إلى عرض القائمة. انقر فوق إلغاء للعودة إلى السجل. + dashboard_offline: أنت غير متصل بالشبكة حاليًا. ستعمل لوحة المعلومات بكامل طاقتها عندما تعاود الاتصال بالإنترنت + field_name_on_form_name: 'الحقل %{field_name} على النموذج %{form_name}' + logout_confirmation: هل تريد متابعة جلستك؟ + logout_offline_warning: هل أنت متأكد أنك تريد تسجيل الخروج؟ إذا قمت بذلك، لن تتمكن من تسجيل الدخول مرّة أخرى إلى أن تعاود الإتّصال بالإنترنت. ستفقد أي تغييرات أجريتها عندما لم تكن متّصلاً بالإنترنت. + logout_warning: سيتم تسجيل خروجك خلال 5 دقائق + logout_dialog_header: تسجيل الخروج غير متصل بالشبكة + logout_confirmation_title: تأكيد تسجيل الخروج + logout_confirmation_text: هل أنت متأكد أنك تريد تسجيل الخروج؟ + no_changes: لم تقم بأي تغييرات في الحقل + not_available: غير متوفر + record_list: + column_header_tooltip: ترتيب ل%{column} + of: من + no_match: عذراً، لم يتم العثور على سجلات مطابقة + rows_per_page: عدد الأسطر في الصفحة الواحدة + sort: فرز + navigation: + bulk_exports: تصديرات + cases: حالات + home: الصفحة الرئيسية + key_performance_indicators: نبض / مؤشرات الأداء الرئيسة + incidents: حوادث + logout: تسجيل الخروج + reports: التقارير + insights: رؤى + search: بحث + settings: إعدادات + support: دعم + support_menu: + contact_information: معلومات الاتصال + code_of_conduct: مدونة قواعد السلوك + terms_of_use: شروط الاستخدام + system_information: معلومات النظام + resync: التغييرات التي لم يتم اعتمادها في وضع عدم الاتصال بالانترنت + tasks: المهام + tracing_request: طلبات التتبع + activity_log: سجل التغيير + registry_records: السجل + families: العائلات + notes: + note_success: تمّت إضافة الملاحظة بنجاح + permissions: + label: أذونات + permission: + All: الكل + add_note: إضافة ملاحظات + admin_only: لا توجد سجلات - وظائف المشرف فقط + administrator_read: قراءات عن المشرف + agency: الهيئة + agency_read: قراءة الهيئة + all: الوصول لجميع السجلات أو المستخدمين + approvals_assessment: '%{approval_label}' + approvals_assessment_pending: '%{approval_label} معلّق' + approvals_case_plan: '%{approval_label}' + approvals_case_plan_pending: '%{approval_label} معلّق' + approvals_closure: '%{approval_label}' + approvals_closure_pending: '%{approval_label} معلّق' + approve_action_plan: الموافقة على %{approval_label} + approve_assessment: الموافقة على نموذج %{approval_label} + approve_case_plan: الموافقة على %{approval_label} + approve_closure: الموافقة على نموذج %{approval_label} + approve_gbv_closure: الموافقة على نموذج %{approval_label} + assign: تعيين/نقل + assign_within_agency: تعيين ضمن الهيئة + assign_within_user_group: تعيين ضمن مجموعة المستخدمين + audit_log: سجل التدقيق + case: حالة + case_approvals: موافقات الحالة + case_assignments_referrals_transfers: عمليات تحويل وإحالة وتعيين الحالة + case_exports: تصديرات الحالة + case_overview: حالاتي + case_risk: تصنيف الحالات بحسب مستوى التقييم + cases_by_task_overdue_assessment: عرض الحالات حسب تقييم المهام المتأخرة + cases_by_task_overdue_case_plan: عرض الحالات حسب خطة حالة المهام المتأخرة + cases_by_task_overdue_followups: عرض الحالات حسب خدمات المهام المتأخرة + cases_by_task_overdue_services: عرض الحالات حسب خدمات المهام المتأخرة + cases_managed_other_users: الحالات التي يديرها مستخدمون آخرون + close: اغلاق + consent_override: تجاوز الموافقة + copy: نسخ + copy_of: نسخة من + create: انشاء + dash_case_incident_overview: حالاتي/حوادثي + dash_cases_by_social_worker: عرض الحالات التي تولاها اخصائي الحالة + dash_cases_by_task_overdue: عرض الحالات حسب المهمة المتأخرة + dash_cases_by_workflow: عرض الحالات حسب مخطط سير العمل + dash_cases_to_assign: عرض الحالات التي بانتظار التعيين + dash_group_overview: حالات مجموعتي + dash_manager_transfers: عرض عمليات النقل الخاصة بالمدير + dash_matching_results: عرض النتائج المتشابهة + dash_protection_concerns: عرض المخاوف المتعلقة بالحماية + dash_protection_concerns_by_location: عرض المخاوف المرتبطة بالحماية بحسب الموقع + dash_referrals_by_socal_worker: عرض الإحالات التي قام بها اخصائي الحالة + dash_reporting_location: عرض مواقع الإبلاغ + dash_service_provisions: عرض تقديم الخدمات + dash_shared_from_my_team: تمّ تشاركها من فريقي + dash_shared_with_me: 'تم مشاركتها معي ' + dash_shared_with_my_team: تمّ تشاركها مع فريقي + dash_shared_with_others: تمّ تشاركها مع آخرين + dash_show_none_values: عرض القيم الخالية + dash_tasks: عرض المهام + dash_transfers_by_socal_worker: عرض عمليات النقل التي قام بها اخصائي الحالة + dash_national_admin_summary: ملخص المدير + dashboard: لوحة التحكم + delete: حذف + display_view_page: إظهار صفحة العرض + duplicate: البحث عن المكررات + enable_disable_record: تعطيل + export_case_pdf: تصدير ملف حالة pdf + export_csv: تصدير ملف csv + export_custom: تصدير ملف مخصص + export_duplicate_id_csv: تصدير السجلات المكررة + export_json: تصدير ملف json + export_list_view_csv: تصدير ملف عرض قائمة csv + export_mrm_violation_xls: تصدير ملف انتهاك آلية الرصد والإبلاغ mrm بصيغة xls + export_pdf: تصدير ملف pdf + export_photowall: تصدير ملف photowall + export_unhcr_csv: تصدير ملف unhcr csv + export_xls: تصدير ملف xls + find_tracing_match: ايجاد تطابق التتبع للحالة + view_registry_record: عرض سجل التسجيل + add_registry_record: اضافة سجل التسجيل + family: العائلة + flag: تمييز بعلامة + form: نماذج + group: 'الوصول لجميع السجلات أو المستخدمين في مجموعتي ' + group_read: قراءة المجموعة + import: استيراد + incident: حادثة + incident_details_from_case: إضافة تفاصيل حادثة لحالة مستخدم آخر + incident_from_case: إنشاء حادثة من حالة + kpi: نبض / مؤشرات الأداء الرئيسة + lookup: عمليات البحث + manage: إدارة + mark_for_offline: وضع علامة على عدم الاتصال بالانترنت + matching_configuration: إعدادات مطابقة + metadata: النماذج، البحث + potential_match: تشابه محتمل + primero_configuration: إعدادات + read: قراءة + reassign: إعادة تعيين/نقل + receive_referral: تلقّي الإحالة + receive_transfer: استلام تحويل + referral: يمكن استخدامه للإحالة + referral_from_service: إحالة حالة من نموذج الخدمة + registry_record: السجل + remove_assigned_users: إزالة مستخدمين مخصصين آخرين (إحالات) + reopen: إعادة فتح + report: تقرير + managed_report: رؤى + resolve_any_flag: حل أي علامة + request_approval: طلب للموافقة + request_approval_action_plan: طلب موافقة %{approval_label} + request_approval_assessment: طلب موافقة %{approval_label} + request_approval_case_plan: طلب موافقة %{approval_label} + request_approval_closure: طلب موافقة %{approval_label} + request_approval_gbv_closure: طلب موافقة %{approval_label} + request_transfer: طلب تحويل + role: أدوار المستخدم + save_search: عمليات بحث محفوظة + saved_search: عملية بحث محفوظة + search_owned_by_others: ابحث عن سجلات الحالة المملوكة لمستخدمين آخرين + self: الوصول لسجلاتي أو المستخدم فقط + service_provision_incident_details: عرض زر إضافة تقديم خدمة على جزء عرض تفاصيل الحادثة + services_section_from_case: إضافة تقديم خدمة لحالة مستخدم آخر + specific_roles: الوصول لقائمة أدوار المستخدم المحددة + sync_external: المزامنة مع نظام إدارة معلومات خارجي + sync_mobile: وضع علامة على عدم الاتصال بالانترنت + system: نظام + tracing_request: طلب التتبع + transfer: يمكن استخدامها للتحويل + user: مستخدمون + user_group: مجموعات المستخدمين + verify_mrm: تحقق من MRM + view_approvals: عرض الموافقات + view_assessment: عرض التقييم + view_photo: عرض الصورة + view_protection_concerns_filter: عرض حسب المخاوف المتعلقة بالحماية + view_response: عرض الاستجابات + webhook: الويب هوك + workflow: سير العمل - الحالات الفردية + workflow_team: سير العمل - حالات الفريق/الفرق + write: كتابة + activity_log: سجل التغيير + remove_alert: إزالة تنبيه + resource: + kpi: + actions: + read: + explanation: القدرة على الوصول إلى صفحة النبض/مؤشرات الأداء الرئيسة. + label: الوصول إلى صفحة النبض/مؤشرات الأداء الرئيسة. + kpi_assessment_status: + explanation: القدرة على معرفة نسبة الذين يملكون نموذج تقييم مكتمل بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: وضع التقييم + kpi_average_followup_meetings_per_case: + explanation: القدرة على معرفة متوسط عدد إجتماعات المتابعة التي أجريت خلال فترة زمنية محددة بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: متوسط اجتماعات المتابعة لكل حالة + kpi_average_referrals: + explanation: القدرة على معرفة متوسط عدد الإحالات التي أجريت لكلّ نوع من الخدمات بالنسبة إلى كلّ الحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: متوسّط الإحالات + kpi_case_closure_rate: + explanation: القدرة على معرفة عدد الحالات التي أُغلقت شهريًا في كلّ موقع. + label: عدد إغلاق الحالات + kpi_case_load: + explanation: القدرة على معرفة متوسط عدد الحالات المفتوحة لكلّ اخصائي الحالة. + label: عدد الحالات + kpi_client_satisfaction_rate: + explanation: القدرة على معرفة معدّل الناجين الذين أكملوا استبان آراء العملاء وكانوا راضين بالنسبة إلى كلّ حالة يمكن للمستخدم الوصول إليها. + label: معدّل رضا العميل + kpi_completed_case_action_plans: + explanation: القدرة على معرفة نسبة الذين أكملوا خطة عمل الحالة بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: خطّة عمل حالة مكتملة + kpi_completed_case_safety_plans: + explanation: القدرة على معرفة النسبة المطلوبة وإكمال خطة الأمان، بالنسبة للحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: خطّة أمان الحالة المكتملة + kpi_completed_supervisor_approved_case_action_plans: + explanation: القدرة على معرفة نسبة الذين أكملوا خطة عمل الحالة وتمّ الموافقة عليها من قبل مشرف الحالات بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: تمّت الموافقة على خطط عمل الحالة المكتملة من قبل مشرف الحالات + kpi_goal_progress_per_need: + explanation: القدرة على معرفة النسبة المئوية للأهداف التي تم تحقيقها في كل فئة من فئات الاحتياجات بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: التقدّم المُحرز نحو الأهداف + kpi_number_of_cases: + explanation: القدرة على معرفة عدد الحالات الجديدة المبلَّغ عنها التي يتمّ فتحها شهريًا في كلّ موقع. + label: عدد الحالات + kpi_number_of_incidents: + explanation: القدرة على معرفة عدد الحوادث الجديدة المبلَّغ عنها التي يتمّ فتحها شهريًا في كلّ موقع. + label: عدد الحوادث + kpi_reporting_delay: + explanation: القدرة على معرفة عدد الأيام المنقضية بين وقت تعرّض الناجية للعنف القائم على النوع الاجتماعي ووقت إبلاغ الناجية بذلك لمقدم الخدمة، بالنسبة إلى كلّ الحوادث التي يمكن للمستخدم الوصول إليها. + label: الإبلاغ عن التأخير + kpi_services_provided: + explanation: 'القدرة على معرفة نوع الخدمات التي قدّمتها المنظمة داخليًّا لجميع الحالات التي يمكن للمستخدم الوصول إليها. ' + label: الخدمات المقدَّمة + kpi_supervisor_to_caseworker_ratio: + explanation: القدرة على معرفة متوسط عدد اخصائيين الحالة لكلّ مشرف. + label: عدد اخصائيين الحالة لكلّ مشرف. + kpi_time_from_case_open_to_close: + explanation: القدرة على معرفة مدّة الإبقاء على الحالة مفتوحة بالنسبة إلى كلّ الحالات التي يمكن للمستخدم الوصول إليها. + label: الوقت من فتح القضية إلى إغلاقها + label: مؤشّر الأداء الرئيس + agency: + actions: + assign: + explanation: القدرة على اختيار الهيئة عند إنشاء حساب مستخدم أو تعديله. إذا كان لدى المستخدم الحالي هذا الإذن بالإضافة إلى إذن "قراءة الهيئة" للمستخدمين، فسيكون بإمكانه فقط إضافة مستخدم إلى وكالته الخاصة. + label: تعيين + create: + explanation: القدرة على إنشاء هيئة + label: إنشاء + manage: + explanation: 'يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على الهيئات. إذن "الإدارة" يعني أساسًا "كل شيء". هام: يمنح هذا الإذن أيضًا القدرة على إنشاء الهيئة جديدة.' + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على رؤية الهيئات. + label: عرض + write: + explanation: القدرة على تعديل المعلومات حول الوكالات. يرجى الإنتباه إلى أن هذا الأمر ينطبق على جميع الوكالات في النظام. + label: تعديل + explanation: يمثل منظمة بها أعضاء يستخدمون بريميرو. توجد الهيئات بشكل مستقل عن مجموعات المستخدمين. + label: الهيئة + audit_log: + actions: + read: + explanation: يسمح للمستخدم بمشاهدة قائمة بجميع الإجراءات التي تم تنفيذها في النظام وتصفيتها، وتكون مقسّمة حسب المستخدم ونوع الإجراء ومُعرِّف السجل ووقت الإجراء. تُناسب هذه الخاصيّة المسؤولين على المستوى الوطني أو مستوى الهيئة ، لأنّها تعرض الإجراءات التي يقوم بها جميع المستخدمين في النظام. يرجى الإنتباه إلى أن سجل التدقيق لا يعرض معلومات التعريف الشخصية في السجلات المتضمنة في كل إجراء. + label: عرض + explanation: قائمة قابلة للتصفية لجميع الإجراءات التي تم تنفيذها في النظام. لا تتضمن أي معلومات تعريفية عن الحالات أو الحوادث أو طلبات البحث عن المفقودين. + label: سجل التدقيق + case: + actions: + add_note: + explanation: يسمح للمستخدم بإضافة مُدخَل إلى نموذج "الملاحظات" الفرعي (يُطلق عليه أحيانًا اسم "التعليقات"). يقوم المستخدم بذلك عن طريق النقر فوق زر "إضافة ملاحظات" في صفحة عرض الحالة. هذا الإجراء مفيد بشكل خاص للمديرين الذين ليس لديهم القدرة على تعديل الحالات، ولكنّهم يريدون إضافة تذكيرات عن حالة لاخصائي الحالة. بهذه الطريقة، يُشبِه إضافة ملاحظة إضافة علم. ميزة إضافة ملاحظة هي أنه عندما يضيف المدير ملاحظة إلى حالة ما، سيظهر إشعار على الحالة لاخصائي الحالة عندما يعرض الحالة على هاتفه الجوّال. + label: اضافة ملاحظات إلى حالة + add_registry_record: + explanation: يسمح للمستخدم بربط سجل بحالة من نموذج تفاصيل السجل. يسمح أيضًا للمستخدم بإلغاء ربط أي سجل مرتبط بالحالة اساسا. + label: إضافة / تحديث سجل التسجيل من الحالة + approve_action_plan: + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. + label: الموافقة على %{approval_label} + approve_assessment: + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. + label: الموافقة على نموذج %{approval_label} + approve_bia: + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. + label: الموافقة على نموذج %{approval_label} + approve_case_plan: + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. + label: الموافقة على %{approval_label} + approve_closure: + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. + label: الموافقة على نموذج %{approval_label} + approve_gbv_closure: + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. + label: الموافقة على نموذج %{approval_label} + assign: + explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الأصلي إلى أي مستخدم آخر في النظام. لا حاجة لموافقة الطفل لهذا الإجراء. على عكس عمليات التحويل لا يُمنح المستلِم الفرصة لقبول التعيين أو رفضه. + label: تعيين + assign_within_agency: + explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الأصلي إلى أي مستخدم آخر في هيئة المستخدم الحالية. لا حاجة لموافقة الطفل لهذا الإجراء. على عكس عمليات التحويل، لا يُمنح المستلِم الفرصة لقبول التعيين أو رفضه. + label: تعيين لمستخدم ضمن هيئتي + assign_within_user_group: + explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الأصلي إلى أي مستخدم آخر في مجموعات مستخدمي المستخدم الحالية. لا حاجة لموافقة الطفل لهذا الإجراء. على عكس عمليات التحويل، لا يُمنح المستلِم الفرصة لقبول التعيين أو رفضه + label: تعيين لمستخدم ضمن مجموعة المستخدمين الخاصة بي + change_log: + explanation: يمكن للمستخدم رؤية تاريخ التغييرات التي تم إجراؤها على السجل منذ إنشائه. ويتضمن القيم المسجلة لجميع الحقول. + label: تغيير السجل + close: + explanation: يسمح للمستخدم بتغيير وضع الحالة من مفتوح إلى مغلق. + label: اغلاق + consent_override: + explanation: يسمح للمستخدم بإجراء إحالة أو تحويل لحالة لم تقدّم الموافقة. + label: تجاوز عدم الموافقة عند الإحالة أو التحويل + create: + explanation: القدرة على إنشاء حالة + label: إنشاء + display_view_page: + explanation: إذا أجرى المستخدم بحثًا عن حالة ليس لديه إمكانية الوصول إليها، يسمح له هذا الإذن برؤية قسم صغير يحتوي على المعلومات الأساسية عن الحالة، حتى ولو لم يتمكن المستخدم من النقر فوق الحالة للاطلاع على جميع معلوماتها. الحقول التي تظهر في "عرض الأقسام" هي الحقول التي تمّ تشكيلها إلى "عرض في نموذج قصير". هذا القسم مفيد أيضًا للمستخدمين الذين يقومون بتتبع أفراد الأسرة وإعادة لمّ الشمل نظرًا لأن "عرض الأقسام" متاح للمستخدم لاستعماله عند مراجعة الحالات التي ظهرت على أنها "تطابقات محتملة" لطلب التتبّع. + label: إظهار صفحة العرض + enable_disable_record: + explanation: القدرة على تعطيل أو تفعيل حالة. لا تظهر الحالات "المعطلة" افتراضيًا في قائمة الحالات. يمكن للمستخدمين رؤية الحالات المعطلة في قائمة الحالات باستخدام عامل تصفية. نظرًا لأن بريميرو Primero لا يسمح للمستخدمين بحذف الحالات، قد يرغب المستخدم في تعطيل حالة كبديل. على سبيل المثال، إذا أنشأ المستخدم حالة عن طريق الخطأ، أو كانت الحالة تحتوي على بيانات سيئة، يتوجب على المستخدم تعطيلها. + label: تفعيل/تعطيل + export_case_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة الحالة أو صفحات عرض الحالة، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بحالة واحدة أو حالات متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. في ملف التصدير PDF ، يتم سرد المعلومات أولاً حسب الحالة، ثم يتمّ تنظيمها بعد ذلك حسب النموذج الذي تظهر عليه المعلومات. + label: تصدير ملف حالة pdf + export_csv: + explanation: 'يمكن للمستخدم إنشاء ملف تصدير CSV من قائمة الحالة أو صفحات عرض الحالة، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بحالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. ملاحظة: لا يعرض تصدير CSV الأحرف غير اللاتينية (مثل العربية والبنغالية) في صيغة قابلة للقراءة.' + label: تصدير CSV + export_custom: + explanation: يمكن للمستخدم إنشاء ملف تصدير XLS من قائمة الحالة أو صفحات عرض الحالة، والتي تحتوي على مجموعة مخصّصة من النماذج أو الحقول، بالنسبة إلى حالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. في هذا التصدير، يتمّ تمثيل كلّ نموذج في علامة التبويب الخاصة به داخل ملف XLS. يمكن للمستخدم اختيار النماذج أو الحقول التي يريد تضمينها في التصدير باستخدام قسم التصدير المخصّص. يرجى ملاحظة أنه لا يمكن للمستخدمين تضمين النماذج والحقول في التصدير إلا إذا كان لديهم بالفعل القدرة على رؤية تلك النماذج والحقول عند عرض حالة في التطبيق. + label: تصدير مخصص + export_duplicate_id_csv: + explanation: إنشاء تصدير CSV للحالات التي لها نفس حقل "الهوية الوطنية" (قد يكون لها تسمية مختلفة، اعتمادًا على الإعدادات). يتمّ تنفيذه فقط من صفحة قائمة الحالة. + label: تصدير التكرارات + export_json: + explanation: يمكن للمستخدم إنشاء ملف تصدير JSON من قائمة الحالة أو صفحات عرض الحالة، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ،والمرتبطة بحالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. يستخدم هذا التصدير بشكل أساسي من قبل الذين يرغبون في تصدير الحالات من نظام Primero الحالي ثم استيرادها إلى نظام Primero مختلف، أو إلى نظام إدارة معلومات آخر. تعتبر صيغة JSON قابلة للقراءة آليًا وغير عمليّة لمعظم المستخدمين. + label: تصدير JSON + export_list_view_csv: + explanation: يمكن للمستخدم إنشاء ملف تصدير CSV من صفحة قائمة الحالات التي تحتوي الحقول عينها التي تظهر لهذا المستخدم في قائمة الحالات. يتمّ تنفيذها فقط من صفحة قائمة الحالات. + label: تصدير ملف عرض قائمة csv + export_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة الحالة أو صفحات عرض الحالة ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ، لحالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. في ملف تصدير PDF ، يتم سرد المعلومات أولاً حسب الحالة ، ثم يتم تنظيمها بشكل أكبر حسب النموذج الذي تظهر عليه المعلومات. + label: تصدير ملف PDF + export_photowall: + explanation: تسمح للمستخدم بتصدير ملف من صفحة قائمة الحالة التي تحتوي على صور جميع الحالات المختارة. يستخدم هذا التصدير بشكل أساسي لأنشطة تتبّع أفراد الأسرة ولم شملها. يتمّ تنفيذها فقط من صفحة قائمة الحالة. + label: تصدير ملف photowall + export_unhcr_csv: + label: تصدير مفوضية الأمم المتحدة لشؤون اللاجئين CSV + explanation: لم تعد هذه الميزة قيد الاستخدام. + export_xls: + explanation: 'يمكن للمستخدم إنشاء ملف تصدير XLS من قائمة الحالة أو صفحات عرض الحالة، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بحالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. في هذا التصدير، يُمثّل كلّ نموذج في علامة التبويب الخاصة به داخل ملف XLS. ملاحظة: تعرض صيغة XLS الأحرف غير اللاتينية (مثل العربية والبنغالية) بصيغة قابلة للقراءة، بينما لا تعرض صيغة CSV هذا الأمر.' + label: تصدير EXCEL (ملف XLS) + find_tracing_match: + explanation: يستخدم هذا حصريًا في السياقات التي تتضمن أنشطة تتبّع الأسرة ولم شملها. سيرى المستخدمون الذين لديهم هذا الإذن زر "ايجاد تطابق تتبّع" في صفحة عرض الحالة. عندما ينقرون على هذا الزر، يدخلون إلى قائمة طلبات التتبع في النظام والتي قد تكون مطابقة لحالتهم. + label: ايجاد تطابق التتبع للحالة + flag: + explanation: القدرة على إضافة علم إلى حالة. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي أضافوها إلى إحدى الحالات. + label: تمييز بعلامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: حل إية علامات + import: + explanation: يسمح للمستخدم بإنشاء حالة واحدة جديدة أو أكثر من خلال استيرادها من ملف CSV أو Excel أو JSON. يجب أن يكون الملف المستورد مهيّأ *جدًّا* وخصوصًا حتى يتمّ استيراد المعلومات بشكل صحيح. يجب أن تكون هذه الوظيفة متاحة فقط للمستخدمين الإداريين ذوي المهارات التقنية المتقدّمة والمعرفة العميقة بكيفية تهيئة البيانات في Primero. يتمّ تنفيذها فقط من صفحة قائمة الحالة. + label: استيراد + incident_details_from_case: + explanation: القدرة على إضافة مُدخل في نموذج تفاصيل الحادثة الفرعي في حالة وجدتها في نتائج البحث، ولكن لا يمكنك الوصول إليها. يقوم المستخدم بتنفيذ هذا الإجراء من صفحة نتائج البحث عن طريق اختيار حالة واحدة أو أكثر، ثم تحديد "إضافة حادثة" من قائمة الإجراءات. ثم يعرض المستخدم قسمًا يحتوي على جميع الحقول في نموذج تفاصيل الحادثة الفرعي، حيث يمكنه إدخال معلومات حول الخدمة وإرسالها. نظرًا لأنه لا يمكن تنفيذ هذا الإجراء إلا من صفحة نتائج البحث، فمن المنطقي أن يمتلك الفرد هذا الإذن إذا كان لديه أيضًا إذن "البحث عن سجلات الحالة التي يملكها مستخدمون آخرون". + label: إضافة تفاصيل حادثة لحالة مستخدم آخر من صفحة نتائج البحث + incident_from_case: + explanation: يسمح هذا الإذن للمستخدم بالنقر فوق زر "إنشاء حادثة". يؤدي هذا إلى إنشاء حادثة قد تحتوي على بعض المعلومات المنسوخة من الحالة. بالنسبة إلى حالات العنف القائم على النوع الاجتماعي، يتواجد هذا الزر أعلى صفحة عرض الحالة ويتوافق مع المعلومات المتعلقة بالحالة ككلّ. في بعض سياقات تتبع الحوادث، يكون هذا الزر في نموذج "تفاصيل الحادثة" الفرعي. في هذه الحالة، قد يتم نسخ بعض المعلومات من نموذج تفاصيل الحادثة الفرعي حيث تم النقر فوق الزر ، وكذلك من الحالة ككلّ. بمعنى آخر، قد تحتوي الحادثة الجديدة الذي تمّ إنشاؤها على حقل "نوع العنف" من النموذج الفرعي لتفاصيل الحادثة الفردية، ولكن قد يحتوي أيضًا على عمر وجنس الحالة نفسها. لاحظ أن هذا الإذن يسمح أيضًا للمستخدم بمشاهدة رابط الحادثة الذي تمّ إنشاؤها. + label: إنشاء حادثة من حالة + remove_alert: + explanation: يسمح هذا الإذن للمستخدم بإزالة تنبيه من الحالة. يتم عادةً إنشاء التنبيهات عند تحرير حقل معين، كما هو الحال عند تحديث الملاحظات. تظهر التنبيهات عادة بنقطة صفراء بجوار الحالة. + label: إزالة التنبيه من حالة + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة للحالات. يعني إذْن "الإدارة" بشكل أساسي "كل شيء". + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على عرض حالة + label: عرض + receive_referral: + explanation: يسمح للمستخدم بتلقي الإحالة. سيظهر المستخدمون الذين لديهم هذا الإذن كمستلمين محتملين لإجراء إحالة، بينما لن يظهر المستخدمون الذين ليس لديهم هذا الإذن كمستلمين محتملين عندما يبحث شخص ما عن مستلم في قسم الإحالة. + label: تلقّي الإحالة + receive_referral_different_module: + explanation: يسمح للمستخدم بتلقي إحالة لسجل تم إنشاؤه في وحدة نمطية مختلفة من بريميرو. سيظهر المستخدمون الذين لديهم هذا الإذن كمستلمين محتملين لإجراء إحالة لهذا السجل ، بينما لن يظهر المستخدمون الذين ليس لديهم هذا الإذن كمستلمين محتملين عندما يبحث شخص ما عن مستلم في نموذج الإحالة. + label: تلقي الإحالة من مستخدم في وحدة بريميرو مختلفة + receive_transfer: + explanation: يسمح للمستخدم بتلقي التحويل. سيظهر المستخدمون الذين لديهم هذا الإذن كمستلمين محتملين لإجراء التحويل، بينما لن يظهر المستخدمون الذين ليس لديهم هذا الإذن كمستلمين محتملين عندما يبحث شخص ما عن مستلم في قسم التحويل. + label: استلام التحويل + referral: + explanation: يسمح لمستخدم بمنح مستخدم آخر حق الوصول المؤقت إلى حالة. سيتمكن مستلم الإحالة من تنفيذ الإجراءات نفسها في الحالة المُحالة كما لو أنّه ينفذها على حالاته الخاصة. عندما لا يعود المستلم بحاجة إلى الوصول إلى الحالة ، يمكنه النقر فوق زر "أكتمل" في النموذج الفرعي للإحالات والتحويلات، وسيفقد إمكانية الوصول إلى الحالة. لا يمكنك إحالة حالة إلّا لمستخدم يسمح له دوره بتلقّي الإحالات. + label: إحالة + referral_from_service: + explanation: يسمح للمستخدم برؤية زر "الإحالة" في نموذج الخدمات الفرعي. عندما ينقر المستخدم على هذا الزر، سيظهر قسم الإحالة مع تعطيل حقول نوع الخدمة والهيئة ومقدّم الخدمة والموقع، ولكن يتمّ ملؤها تلقائيًا بالمعلومات الخاصة بهذه الحقول في نموذج الخدمات الفرعي الذي نقر المستخدم على زر الإحالة المرتبط به. + label: إحالة حالة من نموذج الخدمة الفرعي + remove_assigned_users: + explanation: يسمح للمستخدم بإزالة المستخدمين الآخرين من حقل "المستخدمون الآخرون المعيّنون". يتمّ إدراج المستخدم هنا إذا تلقى إحالة أو تحويل للحالة ولكنّه لم يقبلها أو يرفضها بعد. عندما تقوم بإزالة مستخدم من حقل "المستخدمون الآخرون المعيّنون"، فإنك تزيل إمكانية وصولهم إلى الحالة. وبالتالي، يمكن للمستخدمين الذين لديهم هذا الإذن إزالة إمكانية الوصول إلى الحالة من المستخدمين الذين سبق لهم وتلقوا إحالات أو عمليات نحويل معلّقة للحالة. لاحظ أنّ هذا الإذن لا يعمل إلا إذا كان المستخدم الحالي لديه أيضًا القدرة على تعديل الحالة. + label: إزالة المستخدمين المعيّنين الآخرين (استعادة الوصول إلى الحالة من المستخدمين المُحال إليهم) + reopen: + explanation: يسمح للمستخدم بفتح حالة مغلقة حاليًّا + label: إعادة فتح + request_approval_action_plan: + explanation: يسمح للمستخدم (عادة ما يكون إخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. + label: طلب موافقة %{approval_label} + request_approval_assessment: + explanation: يسمح للمستخدم (عادة ما يكون اخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. + label: طلب موافقة %{approval_label} + request_approval_bia: + explanation: يسمح للمستخدم (عادة ما يكون اخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. + label: طلب موافقة %{approval_label} + request_approval_case_plan: + explanation: يسمح للمستخدم (عادة ما يكون اخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. + label: طلب موافقة %{approval_label} + request_approval_closure: + explanation: يسمح للمستخدم (عادة ما يكون اخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. + label: طلب موافقة %{approval_label} + request_approval_gbv_closure: + explanation: يسمح للمستخدم (عادة ما يكون اخصائي حالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. + label: طلب موافقة %{approval_label} + request_transfer: + explanation: يكشف عن زر "طلب التحويل" الموجود على "عرض القسم". يسمح الزر للمستخدم بإرسال رسالة مع ملاحظة شخصية عبر البريد الإلكتروني إلى مالك سجل الحالة الحالي، يطلب من مالك السجل تحويل الحالة إلى المستخدم الذي أرسل الطلب. يُعدّ هذا مفيدًا في السياقات التي يغيّر فيها الأطفال المواقع كثيرًا، ويحتاج اخصائيين الحالة إلى اخصائيين الحالة السابقين الذين عملوا مع الطفل لإرسال معلومات حول الطفل لتجنب إنشاء سجل مكرّر. + label: طلب تحويل + search_owned_by_others: + explanation: يسمح لمستخدم بإجراء بحث عن السجلات التي عادة لا يملك إمكانية الوصول إليها، إما لأنه ليس مالك سجل هذه الحالة، أو (للمديرين) لأن مالك السجل ليس ضمن مجموعات المستخدمين الخاصة بهم. لاحظ أنه في حين سيرى المستخدم الحالة من ضمن عرض نتائج البحث، لن يتمكن من النقر فوق صفحة عرض الحالة لهذه الحالة، ممّا يعني أنّه لن يتمكّن من رؤية أي معلومات تفصيلية حول الحالة. + label: البحث عن سجلات الحالة المملوكة من مستخدم آخر + service_provision_incident_details: + explanation: يسمح للمستخدم برؤية الزر المسمى "حفظ وإضافة تقديم الخدمة" في الجزء السفلي من قسم إضافة الحادثة. يؤدي النقر فوق هذا الزر إلى حفظ المعلومات التي تم إدخالها حاليًا حول الحادثة، ثم ينقل المستخدم مباشرةً إلى قسم إضافة تقديم الخدمة. نظرًا لأن هذا الإجراء مرتبط ارتباطًا مباشرًا بإجراءات إضافة حادثة وإضافة تقديم خدمة، فمن المنطقي فقط منح هذا الإذن إلى فرد يسمح له دوره ولديه الإذن لـ "إضافة تفاصيل الحادثة إلى حالة مستخدم آخر" و "إضافة تقديم الخدمة إلى حالة مستخدم آخر." + label: عرض زر إضافة تقديم خدمة على قسم تفاصيل الحادثة + services_section_from_case: + explanation: القدرة على إضافة مُدخل في نموذج الخدمات الفرعي إلى حالة وجدتها في نتائج البحث، ولكن لا يمكنك الوصول إليها. يقوم المستخدم بتنفيذ هذا الإجراء من صفحة نتائج البحث عن طريق اختيار حالة واحدة أو أكثر، ثم اختيار "إضافة تقديم خدمات" من قائمة الإجراءات. ثم يستعرض المستخدم قسمًا يحتوي على جميع الحقول في نموذج الخدمات الفرعي، حيث يمكنه إدخال معلومات حول خدمة ما وإرسالها. نظرًا لأنه لا يمكن تنفيذ هذا الإجراء إلا من صفحة نتائج البحث، فمن المنطقي أن يمتلك الفرد هذا الإذن إذا كان لديه أيضًا إذن "البحث عن سجلات الحالة التي يملكها مستخدمون آخرون". + label: إضافة تقديم خدمة لحالة مستخدم آخر + sync_external: + explanation: القدرة على مزامنة سجلّ مع نظام إدارة معلومات خارجي + label: المزامنة مع نظام إدارة معلومات خارجي + sync_mobile: + explanation: يسمح للمستخدم بالتخزين المؤقت للحالات للاستخدام في وضع عدم الاتصال. + label: وضع علامة على عدم الاتصال بالانترنت + transfer: + explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الحالي إلى أي مستخدم في النظام مع إمكانية تلقّي عمليات التحويل. لا يتغير مالك سجل الحالة حتى "يقبل" مستلِم التحويل هذا التحويل. ولكن، إذا "رفض" المستلِم التحويل، يفقد بذلك إمكانية الوصول إلى الحالة، وتبقى الحالة بإسم مالك السجل الأصلي. + label: تحويل + view_photo: + explanation: يسمح للمستخدم بمشاهدة صور الحالة من عرض قائمة الحالة. بدون هذا الإذن، لا يرى المستخدم عمود "الصور" في جدول قائمة الحالات، ولا يرى أيضًا رموز الصور التي تظهر هناك. يسمح هذا الإذن أيضًا للمستخدم بمشاهدة صور الطفل في "عرض القسم". + label: مشاهدة الصور من عرض قائمة الحالة + view_incident_from_case: + explanation: '"عند عرض الحالة، يمكن للمستخدم الاطلاع على قائمة بالحوادث المرتبطة بالحالة، بالإضافة إلى بعض المعلومات الموجزة حول كلّ منها.' + label: عرض الحوادث من حالة + view_protection_concerns_filter: + explanation: يسمح للمستخدم برؤية مرشح مشاكل الحمايةفي صفحة قائمة الحالات. + label: عرض مرشح مشاكل الحماية في صفحة قائمة الحالات. + view_registry_record: + explanation: يسمح للمستخدم بعرض معلومات أي سجل مرتبط بحالة. يسمح أيضًا للمستخدم بمشاهدة نموذج تفاصيل السجل على الحالة. + label: عرض سجل التسجيل من الحالة + write: + explanation: القدرة على نقر زر "تعديل" وتحديث المعلومات في الحالة ثم النقر على "حفظ" + label: تعديل + accept_or_reject_transfer: + explanation: السماح للمستخدم بقبول أو رفض النقل نيابة عن مستخدم آخر موجود في فريقك (على سبيل المثال ، يقبل مشرف الحالات نقل تم إرساله إلى اخصائي الحالة). + label: قبول أو رفض النقل لمستخدم آخر في فريقك. + list_case_names: + explanation: 'لا يمكن للمديرين عادةً رؤية أسماء الحالات في قائمة الحالات. إذا حصل المدير على هذا الإذن ، فسيكون قادرًا على رؤية الأسماء في القائمة. ' + label: إذا كان المدير ، يمكنه رؤية أسماء الحالات في قائمة الحالة. + mark_for_offline: + explanation: يسمح للمستخدم بالتخزين المؤقت للحالة للاستخدام في وضع عدم الاتصال. + label: وضع علامة على عدم الاتصال بالانترنت + view_family_record: + explanation: يمكن للمستخدمين عرض نموذج "سجل العائلة" الخاص بالحالة، والذي يتضمن رابطًا لسجل عائلة الحالة. + label: عرض سجل العائلة من الحالة + case_from_family: + explanation: يمكن للمستخدمين إنشاء حالة لأحد أفراد عائلة الحالة في النموذج الفرعي "تفاصيل العائلة". لاحظ أنه سيتم إنشاء سجل العائلة تلقائيًا لربط هاتين الحالتين. + label: إنشاء حالة من تفاصيل العائلة + link_family_record: + explanation: يسمح للمستخدم بالبحث عن سجل العائلة الموجود وربطه بحالته. كما يسمح للمستخدمين بإلغاء ربط سجل العائلة من الحالة. + label: ربط / إلغاء ربط سجل العائلة من الحالة + explanation: يمثل طفلاً فرديًا أو ناجٍ أو مستفيد آخر. + label: حالة + dashboard: + actions: + approvals_action_plan: + explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على خطة العمل المعلّقة أو الموافق عليها أو المرفوضة. + label: موافقات اخصائي الحالة %{approval_label} + approvals_action_plan_pending: + explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على خطة العمل المعلّقة. + label: موافقات المدير %{approval_label} + approvals_assessment: + explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على التقييم المعلّقة أو الموافق عليها أو المرفوضة. + label: موافقات اخصائي الحالة %{approval_label} + approvals_assessment_pending: + explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على التقييم المعلّقة. + label: موافقات المدير %{approval_label} + approvals_case_plan: + explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على خطة الحالة المعلّقة أو الموافق عليها أو المرفوضة. + label: موافقات اخصائي الحالة %{approval_label} + approvals_case_plan_pending: + explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على خطة الحالة المعلّقة. + label: موافقات المدير %{approval_label} + approvals_closure: + explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على الإغلاق المعلّقة أو الموافق عليها أو المرفوضة. + label: موافقات اخصائي الحالة %{approval_label} + approvals_closure_pending: + explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على الإغلاق المعلّقة. + label: موافقات المدير %{approval_label} + approvals_gbv_closure: + explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على إغلاق العنف القائم على النوع الإجتماعي المعلّقة أو الموافق عليها أو المرفوضة. + label: موافقات اخصائي الحالة %{approval_label} + approvals_gbv_closure_pending: + explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على إغلاق العنف القائم على النوع الإجتماعي المعلّقة. + label: موافقات المدير %{approval_label} + case_overview: + explanation: نظرة عامة على بطاقة لوحة المعلومات الموجودة في أعلى الصفحة الرئيسية، والتي تتضمن أرقامًا مثل عدد الحالات الإجمالي والحالات الجديدة + label: نظرة عامّة على لوحة المعلومات + case_risk: + explanation: يظهر عدد الحالات في كلّ مستوى خطر. + label: الحالات حسب مستوى الخطر + cases_by_task_overdue_assessment: + explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام التقييم لكلّ من اخصائيين الحالة. + label: مهام التقييم المتأخرة + cases_by_task_overdue_case_plan: + explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام خطة الحالة لكلّ من اخصائيين الحالة. + label: مهام خطة الحالة المتأخرة + cases_by_task_overdue_followups: + explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام المتابعة لكلّ من اخصائيين الحالة. + label: مهام المتابعة المتأخرة + cases_by_task_overdue_services: + explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام الخدمات لكلّ من اخصائيين الحالة. + label: مهام الخدمات المتأخرة + dash_case_incident_overview: + explanation: يُظهر للمدير عدد الحالات التي يديرها كل مستخدم في فريقه، والتي تتم إحالتها أو نقلها إلى مستخدمين آخرين. + label: لمحة عامّة - حالاتي/حوادثي + dash_cases_by_social_worker: + explanation: الجدول الذي يوضح كيفية إدارة العدد الإجمالي للحالات المفتوحة وعدد الحالات الجديدة التي يديرها كل مستخدم في مجموعات المستخدمين الحالية للمستخدم. يمثّل كل صف مستخدمًا من مجموعات المستخدمين الخاصة بالمستخدم الحالي ، بينما يمثل "الإجمالي" و "الجديد" عمودين. + label: عرض الحالات حسب اخصائي الحالة + dash_cases_to_assign: + explanation: 'هام: للمديرين فقط. يعرض عدد الحالات التي يمتلكها المستخدم الحالي بشكل مباشر (يجب أن يكون مديرًا). تفترض لوحة المعلومات هذه أن المديرين لا يديرون حالاتهم الخاصة، وأنه إذا كان للمدير حالاته الخاصة، يجب عليه تعيين هذه الحالات لاخصائيين الحالة في فريقه.' + label: (للمديرين) الحالات التي أحتاج إلى تعيينها لأشخاص في فريقي + dash_flags: + explanation: يعرض قائمة بالعلامات التي أضافها المستخدمون الآخرون إلى سجلاتي، بالإضافة إلى العلامات التي أضفتها إلى سجلات المستخدمين الآخرين. + label: السجلات المميّزة بعلامة + dash_group_overview: + explanation: يعرض للمدير عدد الحالات المفتوحة والمغلقة التي يديرها المستخدمون في فريقه. + label: حالات مجموعتي + dash_matching_results: + explanation: مهترئ. لوحة المعلومات هذه غير وظيفية وستتم إزالتها في الإصدار 2. + label: عرض النتائج المتطابقة + dash_protection_concerns: + explanation: الجدول الذي يوضح عدد الحالات التي لديها مخاوف تتعلّق بالحماية. يمثل كلّ سطر في الجدول إحدى المخاوف المتعلقة بالحماية، بينما تشير الأعمدة إلى أوضاع مختلفة للحالات ("كلّ الحالات"، "الحالات المفتوحة"، "الجديدة (هذا الأسبوع)"، "المغلقة (هذا الأسبوع)") + label: الحالات حسب مشاكل/قضايا الحماية + dash_protection_concerns_by_location: + explanation: يشبه لوحة معلومات "عرض المخاوف المتعلّقة بالحماية"، باستثناء أنه يمكن للمستخدم اختيار موقع من القائمة المنسدلة لإظهار إحصائيات حول انتشار المخاوف المتعلّقة بالحماية في هذا الموقع فقط. + label: عرض المخاوف المرتبطة بالحماية بحسب الموقع + dash_reporting_location: + explanation: الجدول الذي يوضح عدد الحالات الموجودة في كلّ موقع (على مستوى واحد من المحلّة مثل "مقاطعة" أو "منطقة"). كلّ سطر في الجدول عبارة عن موقع، بينما تشير الأعمدة إلى أوضاع مختلفة للحالات ("الحالات المفتوحة"، "الجديدة (الأسبوع المنصرم)"، "الجديدة (هذا الأسبوع)، "المغلقة (الأسبوع المنصرم)"، "المغلقة (هذا الأسبوع)"). تستخدم عادة لحسابات المدير أو المسؤول. + label: الحالات حسب موقع الإبلاغ + dash_service_provisions: + explanation: يعرض عدد الحالات التي قام فيها مستخدمون آخرون بإضافة تقديم خدمة لها. يظهر هذا الرقم في القسم الرئيس من لوحة المعلومات. + label: الحالات حسب تقديم الخدمة + dash_shared_from_my_team: + explanation: يعرض للمدير عدد الحالات التي يديرها كلّ مستخدم في فريقه والتي تمّ تحويلها أو إحالتها إلى مستخدمين آخرين. + label: تمّ تشاركها من فريقي + dash_shared_with_me: + explanation: يظهر عدد الحالات التي تمّ تحويلها أو إحالتها إليك. + label: 'تم مشاركتها معي ' + dash_shared_with_my_team: + explanation: يعرض للمدير عدد الحالات التي تمّ تحويلها أو إحالتها إلى كلّ مستخدم في فريقه. + label: تمّ تشاركها مع فريقي + dash_shared_with_my_team_overview: + explanation: يُظهر للمدير عدد الحالات المُحالة أو المنقولة إلى كل مستخدم في فريقه. + label: تم مشاركته مع فريقي (نظرة عامة) + dash_shared_with_others: + explanation: يوضح عدد حالاتي التي تحتوي على إحالات نشطة أو عمليات تحويل معلّقة أو مرفوضة. لا تُستخدم عادةً من قبل المديرين، إلّا إذا كانوا يديرون القضايا بأنفسهم. + label: تمّ تشاركها مع آخرين + dash_violations_category_verification_status: + explanation: 'يُظهر عدد انتهاكات MRM من كل نوع والتي تم تصنيفها حسب وضع التحقق ' + label: MRM - عدد الانتهاكات لكل حالة تحقق + dash_violations_category_region: + explanation: يوضح عدد انتهاكات MRM التي حدثت في كل منطقة ، مقسمة حسب نوع الانتهاك. + label: MRM - عدد الانتهاكات لكل منطقة + dash_perpetrator_armed_force_group_party_names: + explanation: يُظهر عدد انتهاكات MRM من كل نوع والتي تم تصنيفها حسب المسيء + label: MRM - عدد الانتهاكات حسب المسيء + dash_show_none_values: + explanation: يضيف فئة "لا مستوى خطورة" إضافية لجميع لوحات المعلومات التي تقسّم الحالات حسب مستوى الخطورة. ينطبق هذا على وجه التحديد على الإعدادات التي لديها خيار رابع "لا مخاطر" لحقول مستوى الخطورة. + label: عرض الحالات مع "لا مستوى خطورة" في لوحة معلومات التقييم + dash_tasks: + explanation: يسمح للمستخدم برؤية صفحة المهام. يجب أن تُستخدم لاخصائيين الحالة ومقدمي الخدمات، حيث ستكون الأرقام مخصّصة للحالات التي تديرها مباشرة. يجب على المديرين بدلاً من ذلك الحصول على لوحة المعلومات المرتبطة بـ "عرض الحالات حسب المهمة المتأخرة" ، لأن هذا يتيح لهم رؤية المهام المتأخرة لكلّ شخص في مجموعات المستخدمين الخاصة بهم. + label: صفحة المهام + dash_national_admin_summary: + explanation: يظهر إجمالي الحالات المفتوحة في النظام ، وعدد الحالات الجديدة التي تم إنشاؤها في كل من الأسبوعين الماضيين ، وعدد الحالات التي تم إغلاقها في كل من الأسبوعين الماضيين. + label: ملخص المسؤول + view_response: + explanation: لكلّ نوع من أنواع الاستجابة، يوضح عدد الحالات في كل مستوى من مستويات الخطورة التي لديها خدمات على وشك الإنتهاء أو متأخّرة. + label: عرض الاستجابات + workflow: + explanation: يسمح لإخصائي الحالة برؤية رسم بياني دائري يوضح عدد الحالات الخاصة به والموجودة في كلّ مرحلة من مراحل سير عمل إدارة الحالة. + label: الحالات مقسّمة حسب سريان العمل + workflow_team: + explanation: 'يسمح للمدير برؤية جدول يوضح عدد حالات اختصاصيين الحالة في كلّ مرحلة من مراحل عملية إدارة الحالة. ' + label: الحالات حسب سير العمل واخصائي الحالة + explanation: تملي المعلومات الموجزة التي تظهر على الصفحة الرئيسية. + label: لوحة المعلومات + disabled: + explanation: إذا قمت بتعطيل هذا الدور، لن تتمكن من تعيينه إلى حسابات المستخدمين. + label: 'مُعطلة ' + referral_authorization: + explanation: ويعني أن الدور سيظهر كخيار للقائمة المنسدلة "نوع الإحالة" عندما يقوم المستخدم بإجراء إحالة داخلية. إذا اختار المستخدم هذا الدور كنوع الإحالة، فلن يتمكن متلقي الإحالة من الوصول إلا إلى النماذج التي يمكن للدور المحدد الوصول إليها. لذا، على سبيل المثال، إذا اختار المستخدم "مقدم الخدمة الطبية" كنوع الإحالة، وكان لدور مقدم الخدمة الطبية حق الوصول فقط إلى نماذج الهوية الأساسية ومخاوف الحماية، فلن يرى المستلم سوى هذه النماذج. + label: هل يمكن استخدام هذا الدور في القائمة المنسدلة "نوع الإحالة"؟ + duplicate: + actions: + read: + explanation: يسمح للمستخدم بإجراء بحث متقدّم لكلّ الحالات في النظام، باستخدام عدد من المعايير، بما في ذلك الاسم واللقب والجنس والعمر والجنسية. + label: عرض + explanation: بحث متقدم لدور المديرين في النظام. + label: بحث مكرر + forms: + case: + explanation: 'يقيّد وصول المستخدم إلى نماذج الحالات ويحدّ من المعلومات التي يمكن للمستخدم رؤيتها في الحادثة. مثلاً، إذا كان للمستخدم حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج فقط. إذا كان المستخدم الحالي لديه وصول محدود إلى النموذج ولديه القدرة على إدارة إعدادات النموذج، فإن تقييد وصوله إلى النموذج يحدّ أيضًا النماذج التي يمكنه تضبيطها. ملاحظة: إذا لم يتمّ تحديد أي نموذج، فهذا يعني أنّ الدور لديه حق الوصول إلى جميع نماذج الحالات.' + label: نماذج - حالة + incident: + explanation: 'تقييد وصول المستخدم إلى النماذج الخاصة بالحوادث يحد من المعلومات التي يمكن للمستخدم رؤيتها في الحادث. على سبيل المثال ، إذا كان المستخدم لديه حق الوصول إلى نموذج مالك السجل فقط ، فسيكون أيضًا قادرًا فقط على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج. إذا كان لدى المستخدم الحالي وصول محدود إلى النموذج ولديه القدرة على إدارة إعدادات النموذج ، فإن تقييد وصوله إلى النموذج يحد أيضًا من النماذج التي يمكنه تكوينها. ملاحظة: إذا لم يتم تحديد أي نماذج ، فهذا يعني أن الدور لديه حق الوصول إلى جميع نماذج الحوادث.' + label: نماذج - حوادث + tracing_request: + explanation: 'يقيّد وصول المستخدم إلى النماذج في طلبات التتبّع ويحدّ من المعلومات التي يمكن للمستخدم رؤيتها في طلب التتبّع. مثلاً، إذا كان للمستخدم حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج فقط. إذا كان المستخدم الحالي لديه وصول محدود إلى النموذج ولديه القدرة على إدارة إعدادات النموذج، فإن تقييد وصوله إلى النموذج يحدّ أيضًا النماذج التي يمكنه إعدادها. ملاحظة: إذا لم يتمّ تحديد أي نموذج، فهذا يعني أنّ الدور لديه حق الوصول إلى جميع النماذج لطلبات التتبّع.' + label: النماذج - طلبات التتبع + registry_record: + explanation: 'تقييد وصول المستخدم إلى النماذج الموجودة في السجلات يحد من المعلومات التي يمكن للمستخدم رؤيتها في السجل. على سبيل المثال ، إذا كان المستخدم لديه حق الوصول إلى نموذج مالك السجل فقط ، فسيكون أيضًا قادرًا فقط على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج. إذا كان لدى المستخدم الحالي وصول محدود إلى النموذج ولديه القدرة على إدارة إعدادات النموذج ، فإن تقييد وصوله إلى النموذج يحد أيضًا من النماذج التي يمكنه إعدادها. ملاحظة: إذا لم يتم تحديد أي نماذج ، فهذا يعني أن الدور له حق الوصول إلى جميع نماذج السجلات.' + label: النماذج - التسجيل + family: + label: النماذج - العائلة + explanation: 'يؤدي تقييد وصول المستخدم إلى نماذج العائلات إلى تحديد المعلومات التي يمكن للمستخدم رؤيتها حول العائلة. على سبيل المثال، إذا كان المستخدم لديه حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الموجودة في الحقول الموجودة في هذا النموذج فقط. إذا كان لدى المستخدم الحالي وصول محدود إلى النموذج ولديه القدرة على إدارة إعداد النموذج، فإن تقييد وصوله إلى النموذج يحد أيضًا من النماذج التي يمكنه تكوينها.' + group: + actions: + admin_only: + explanation: هذا يعني أنّ المستخدمين الذين يؤدّون هذا الدور لن يتمكنوا إلا من رؤية الأمور المتعلّقة بإدارة النظام، مثل التقارير، وإعداد النموذج والبحث، والمستخدمين، والأدوار، ومجموعات المستخدمين. لن يروا أي حالات فردية أو طلبات تتبّع أو حوادث. + label: لا توجد سجلات - وظائف المسؤول فقط + agency: + explanation: يمكن للدور الوصول إلى السجلات التي يديرها جميع المستخدمين في هيئاتهم. إذا كان للمستخدم الحق في الوصول إلى المستخدمين، يمكنه الوصول إلى جميع المستخدمين في هيئته. + label: كلّ السجلات أو المستخدمين في هيئتي + all: + explanation: يمكن للدور الوصول إلى جميع السجلات والمستخدمين ومجموعات المستخدمين في النظام، بغض النظر عن مجموعات المستخدمين التي ينتمون هم إليها. + label: الوصول لجميع السجلات أو المستخدمين + group: + explanation: يمكن للدور الوصول إلى السجلات التي يديرها جميع المستخدمين في مجموعات المستخدمين الخاصّة بهم. لا يمكنهم الوصول إلّا إلى المستخدمين في مجموعات المستخدمين الخاصة بهم. يمكنهم فقط الوصول إلى مجموعات المستخدمين الخاصة بهم. + label: 'الوصول إلى جميع السجلات أو المستخدمين في مجموعتي ' + self: + explanation: يمكن للدور الوصول إلى السجلات الخاصة بهم (الحالات أو طلبات التتبّع أو الحوادث)، ويمكنه تعديل حساب المستخدم الخاص به. + label: الوصول لسجلاتي أو المستخدم الخاص بي فقط + explanation: يتحكّم في السجلات (الحالات أو طلبات التتبّع أو الحوادث) التي يمكن للدور الوصول إليها. إذا كان للدور الحق في الوصول إلى المستخدمين ومجموعات المستخدمين، يستطيع بذلك التحكّم أيضًا بالمستخدمين ومجموعات المستخدمين التي يمكنه الوصول إليهم. يمكن للأدوار التي لها حق الوصول إلى "بلا سجلات" الوصول فقط إلى إعداد النظام مثل النماذج والمستخدمين والتقارير. + label: ما هي السجلات التي يؤثر فيها هذا الدور؟ + incident: + actions: + assign: + explanation: يسمح للمستخدم بإرسال حادثة من مالك السجل الأصلي إلى أي مستخدم آخر في النظام. لا يمكن تعيين الحوادث المرتبطة بالفعل بحالة ما؛ يجب عليك بدلاً من ذلك إعادة تعيين الحالة المرتبطة، مما سيؤدي إلى تحديث ملكية سجل الحادث. + label: تعيين + change_log: + explanation: يمكن للمستخدم رؤية تاريخ التغييرات التي تم إجراؤها على السجل منذ إنشائه. يتضمن هذا القيم المسجلة لجميع الحقول. + label: تغيير السجل + create: + explanation: القدرة على إنشاء حادثة. + label: إنشاء + enable_disable_record: + explanation: القدرة على تعطيل أو تمكين حادثة. لا تظهر الحوادث "المعطّلة" بشكل افتراضي في قائمة الحوادث. يمكن للمستخدمين رؤية الحوادث المعطّلة في قائمة الحوادث من خلال تطبيق عامل تصفية. + label: تفعيل/تعطيل + export_case_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة الحوادث أو صفحات عرض الحوادث، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بسجلّ واحد أو سجلات متعدّدة أو جميع السجلات التي يمكن للمستخدم الوصول إليها. في ملف التصدير PDF، يتمّ سرد المعلومات أولاً حسب الحالة، ثم يتمّ تنظيمها بعد ذلك حسب النموذج الذي تظهر عليه المعلومات. + label: تصدير PDF + export_csv: + explanation: 'يمكن للمستخدم إنشاء ملف تصدير CSV من قائمة الحوادث أو صفحات عرض الحوادث، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بحادثة واحدة أو حوادث متعددة أو جميع الحوادث التي يمكن للمستخدم الوصول إليها. ' + label: تصدير CSV + export_custom: + explanation: يمكن للمستخدم تحديد نماذج أو حقول محددة لتصديرها إلى ملف XLS. + label: تصدير ملف مخصص + export_incident_recorder_xls: + explanation: يمكن للمستخدم إنشاء تصدير ملف XLS متخصّص يسمح بتبادل البيانات باستخدام أداة تسجيل حادثة العنف القائم على النوع الإجتماعي. + label: تصدير مسجّل الحوادث xls + export_mrm_violation_xls: + explanation: يمكن للمستخدم إنشاء تصدير Excel (ملف XLS) متخصص لانتهاكات MRM. هذا الإجراء متاح في صفحة عرض الحوادث وقائمة الحوادث. + label: تصدير انتهاكات MRM إلى Excel (ملف XLS) + export_json: + explanation: يمكن للمستخدم إنشاء ملف تصدير JSON من قائمة الحوادث أو صفحات عرض الحوادث، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ،والمرتبطة بحادثة واحدة أو حوادث متعددة أو جميع الحوادث التي يمكن للمستخدم الوصول إليها. يستخدم هذا التصدير بشكل أساسي من قبل الذين يرغبون في تصدير الحوادث من نظام Primero الحالي ثم استيرادها إلى نظام Primero مختلف، أو إلى نظام إدارة معلومات آخر. تعتبر صيغة JSON قابلة للقراءة آليًا وغير عمليّة لمعظم المستخدمين. + label: تصدير JSON + export_list_view_csv: + explanation: يمكن للمستخدم إنشاء ملف تصدير CSV من صفحة قائمة الحوادث التي تحتوي الحقول عينها التي تظهر لهذا المستخدم في قائمة الحوادث. يتمّ تنفيذها فقط من صفحة قائمة الحوادث. + label: تصدير ملف عرض قائمة csv + export_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة الحوادث أو صفحات عرض الحوادث ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ، لسجل واحد أو متعدد أو جميع السجلات التي يمكن للمستخدم الوصول إليها. في ملف تصدير PDF ، يتم سرد المعلومات أولاً حسب الحالة ، ثم يتم تنظيمها بشكل أكبر حسب النموذج الذي تظهر عليه المعلومات. + label: تصدير ملف PDF + export_xls: + explanation: يمكن للمستخدم إنشاء ملف تصدير XLS من قائمة الحادثة أو صفحات عرض الحوادث، والتي تحتوي على مجموعة مخصّصة من النماذج أو الحقول، بالنسبة إلى حالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. في هذا التصدير، يتمّ تمثيل كلّ نموذج في علامة التبويب الخاصة به داخل ملف XLS. يمكن للمستخدم اختيار النماذج أو الحقول التي يريد تضمينها في التصدير باستخدام قسم التصدير المخصّص. يرجى ملاحظة أنه لا يمكن للمستخدمين تضمين النماذج والحقول في التصدير إلا إذا كان لديهم بالفعل القدرة على رؤية تلك النماذج والحقول عند عرض حالة في التطبيق. + label: تصدير EXCEL (ملف XLS) + flag: + explanation: القدرة على إضافة علم إلى حادثة. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي أضافوها إلى إحدى الحوادث. + label: تمييز بعلامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: إزالة أية علامة + import: + explanation: يسمح للمستخدم بإنشاء حادثة واحدة جديدة أو أكثر من خلال استيرادها من ملف CSV أو Excel أو JSON. يجب أن يكون الملف المستورد مهيّأ *جدًّا* وخصوصًا حتى يتمّ استيراد المعلومات بشكل صحيح. يجب أن تكون هذه الوظيفة متاحة فقط للمستخدمين الإداريين ذوي المهارات التقنية المتقدّمة والمعرفة العميقة بكيفية تهيئة البيانات في Primero. يتمّ تنفيذها فقط من صفحة قائمة الحوادث. + label: استيراد + remove_alert: + explanation: يسمح هذا الإذن للمستخدم بإزالة تنبيه من حادث ما. يتم عادةً إنشاء التنبيهات عند تحرير حقل معين، كما هو الحال عند تحديث الملاحظات. تظهر التنبيهات عادةً بنقطة صفراء بجوار الحادث. + label: إزالة التنبيه من الحادث + link_incident_to_case: + explanation: يسمح للمستخدم بربط الحادث بالحالة المحددة. + label: ربط حادث بحالة + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة للحوادث. يعني إذْن "الإدارة" بشكل أساسي "كل شيء". + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على عرض حادثة. + label: عرض + sync_mobile: + explanation: يسمح هذا الإذن بشكل عام للمستخدم باستخدام تطبيق الهاتف المحمول. أولاً ، يسمح للمستخدم بمشاهدة إجراءات "تحديد للهاتف الجوال" و "ازالة التحديد للهاتف الجوال"، والتي تظهر في قائمة الحوادث وصفحات عرض الحوادث. يشير تحديد الحادثة للجوال إلى أنه يجب مزامنة المعلومات الخاصة بهذه الحادثة بين جهاز المستخدم المحمول والتطبيق على الإنترنت، بينما يؤدي إلغاء تحديد الحادثة للهاتف الجوال إلى إيقاف هذه المزامنة. بالإضافة إلى ذلك، لا يمكن للمستخدمين الذين ليس لديهم هذا الإذن مزامنة هواتفهم المحمولة مع التطبيق على الإنترنت بشكل عام، ممّا يعني أنه لا يمكنهم استخدام تطبيق الهاتف لإدارة الحوادث. + label: مزامنة مع الهاتف المحمول + verify_mrm: + explanation: يمكن لمستخدم MRM تغيير لائحة الانتهاكات. + label: تحقق من MRM + write: + explanation: القدرة على نقر زر "تعديل" وتحديث المعلومات عن الحادثة ثم النقر على "حفظ". تسمح أيضًا للمستخدم بتعطيل حادثة أو تفعيلها. + label: تعديل + explanation: يمثل حدثًا وقع. عادة ما تكون هذه حوادث إساءة أو عنف ، على الرغم من أنها يمكن أن تتوافق أيضًا مع أحداث مثل المواجهات مع سلطات إنفاذ القانون. غالبًا ما ترتبط الحوادث بالحالات. + label: حادثة + is_manager: + explanation: ينطبق على أي دور لمستخدم يشرف بشكل عام على المستخدمين الآخرين. يتيح ذلك للمستخدم رؤية لوحات المعلومات وعوامل التصفية التي تساعد المستخدم في إدارة فريق. + label: هل هو مدير؟ + managed_report: + actions: + reporting_locations_report: + label: موقع الإبلاغ (حالات) + explanation: القدرة على عرض إحصائيات حول عدد الحالات المسجلة خلال نطاق زمني معين، وتصفيتها حسب موقع الإبلاغ، ومقسمة حسب العمر والجنس. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + followups_report: + label: متابعات (حالات) + explanation: القدرة على عرض إحصائيات حول عدد المتابعات التي تم إجراؤها خلال نطاق زمني محدد، والتي تمت تصفيتها حسب نوع المتابعة، ومقسمة حسب العمر والجنس. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + services_report: + label: خدمات (حالات) + explanation: القدرة على عرض إحصائيات حول عدد الخدمات المقدمة خلال نطاق زمني معين، مفلترة حسب نوع الخدمة، ومقسمة حسب العمر والجنس. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + protection_concerns_report: + label: مخاوف تتعلق بالحماية (حالات) + explanation: القدرة على عرض إحصائيات حول اهتمامات الحماية للحالات المسجلة خلال نطاق زمني محدد. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + managed_report_scope: + label: ما السجلات التي يجب أن يتمكن هذا الدور من رؤيتها في Insights؟ + managed_report_scope_all: + label: الكل + managed_report_scope_group: + label: البيانات المستندة إلى المجموعة فقط + managed_report_scope_agency: + label: البيانات المستندة إلى الهيئة فقط + violations: + explanation: القدرة على الوصول إلى MRM Violences Insight. + label: الانتهاكات + gbv_statistics: + explanation: القدرة على الوصول لرؤية إحصاءات العنف القائم على النوع الاجتماعي. + label: احصاءات GBV + ghn_report: + explanation: القدرة على الوصول إلى MRM Global Horizontal Note Insight. + label: المذكرة الافقية الشاملة + individual_children: + explanation: القدرة على الوصول إلى MRM Individual Children Insight. + label: الأطفال الفرديين + workflow_report: + label: سير العمل (حالات و حوادث) + explanation: القدرة على عرض إحصائيات حالة سير العمل لكلا الحالتين والأحداث المرتبطة بهما. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + cases_workflow_report: + label: سير العمل (حالات) + explanation: القدرة على عرض الإحصائيات حول حالات حالة سير العمل. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + violence_type_report: + label: نوع العنف (حالات وحوادث) + explanation: القدرة على عرض إحصائيات عن نوع العنف. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + referrals_transfers_report: + label: الإحالات والانتقالات (حالات) + explanation: يرى المستخدمون عدد الحالات التي تم إحالتها ونقلها من كل مجموعة مستخدمين إلى كل مجموعة مستخدمين أخرى. + matching_configuration: + actions: + manage: + explanation: القدرة على التحكم في الحقول التي تتم مقارنتها للعثور على التطابقات بين طلب التتبع والحالة. نظرًا لأن هذا يتحكم في كيفية تشغيل المطابقة في النظام بأكمله، يجب أن يكون هذا الإذن متاحًا فقط لمسؤول النظام. + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: يتحكم في الحقول المستخدمة لمقارنة طلبات التتبع بالحالات أثناء تتبع الأسرة ولم شملها. + label: إعدادات مطابقة + metadata: + actions: + manage: + explanation: القدرة على إنشاء وتعديل وترجمة وحذف النماذج وحقول النماذج وعمليات البحث. يرجى ملاحظة أن المستخدم الذي لديه هذا الإذن سيكون قادرًا فقط على إدارة النماذج التي يمكنه الوصول إليها. على سبيل المثال، إذا كان للمسؤول الوطني القدرة فقط على رؤية نموذج مالك السجل في الحالات، لن يتمكن إلا من تحديث إعداد هذا النموذج. + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: يتحكم في القدرة على تكوين نماذج وحقول Primero ، بالإضافة إلى خيارات البحث المستخدمة داخلها. + label: النماذج، البحث + module: + actions: + cp: + label: حماية الطفل + gbv: + label: العنف القائم على النوع الإجتماعي + mrm: + label: MRM + explanation: يتحكّم في الوحدات النمطية التي ينطبق عليها هذا الدور + label: الوحدات النمطية + potential_match: + actions: + read: + explanation: يمثل الرابط بين طلب التتبع والحالة. يُعتبر الوصول إلى التطابقات المحتملة أمرًا ضروريًا لتتبع أفراد الأسرة ولم شملهم (FTR). يسمح للمستخدم برؤية نموذج ملخص التتبع في الحالات. + label: عرض + view_audio: + explanation: يتحكم في ما إذا كان المستخدم الذي يبحث عن تطابق تتبع يمكنه رؤية الملفات الصوتية للحالة أو طلب التتبع المرتبط بالمطابقة المحتملة. + label: عرض الملف الصوتي + view_photo: + explanation: يتحكم في ما إذا كان المستخدم الذي يبحث عن تطابق تتبع يمكنه رؤية الصور الخاصة بالحالة أو طلب التتبع المرتبط بالمطابقة المحتملة. + label: عرض الصور + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على المطابقات المحتملة. إذن "الإدارة" يعني أساسًا "كل شيء". + label: إدارة + label: تطابق محتمل + primero_configuration: + actions: + manage: + explanation: القدرة على حفظ الإعدادات وتطبيقها وإرسالها. عادة ما يكون هذا الإذن محجوزًا لمسؤول النظام. + label: إدارة (كافة الأذونات لنوع المورد هذا) + label: إعدادات + referral: + actions: + refer: + explanation: هذا يعني أنّ الدور سيظهر كخيار لـ "نوع المستلِم" عندما يقوم المستخدم بإحالة خارجية. إذا اختار المستخدم هذا الدور كنوع الإحالة، سيحتوي التصدير الذي ينشئه Primero عندما يرسل المستخدم الإحالة فقط على المعلومات الموجودة في النماذج التي يمكن لهذا الدور الوصول إليها. إذًا، على سبيل المثال، إذا اختار المستخدم "مزود الخدمة الطبية" كنوع المستلِم، وكان دور مقدم الخدمة الطبية لديه حق الوصول فقط إلى نماذج الهوية الأساسية والمخاوف المتعلّقة بالحماية، لن يحتوي ملف التصدير الذي يصدره Primero للإحالة الخارجية إلّا على الحقول الموجودة في هذين النموذجين. + label: هل يمكن استخدام هذا الدور للإحالات الخارجية؟ + label: إحالة + registry_record: + actions: + change_log: + explanation: يمكن للمستخدم رؤية محفوظات لجميع التغييرات التي تم إجراؤها على السجل منذ إنشائه. يتضمن هذا القيم المسجلة لجميع الحقول. + label: سجل التغيير + create: + explanation: القدرة على إنشاء سجل التسجيل. + label: إنشاء + enable_disable_record: + explanation: القدرة على تعطيل أو تفعيل سجل التسجيل. لا تظهر السجلات "المعطلة" بشكل افتراضي في قائمة التسجيل. يمكن للمستخدمين رؤية سجلات التسجيل المعطلة في قائمة التسجيل باستخدام مرشح. + label: تفعيل/تعطيل + export_csv: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف CSV من قائمة السجل أو صفحات عرض السجل ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ، لسجل واحد أو متعدد أو جميع سجلات التسجيل التي يمكن للمستخدم الوصول إليها. ملاحظة: لا يعرض تصدير CSV الأحرف غير اللاتينية (مثل العربية والبنغالية)' + label: تصدير CSV + export_json: + explanation: يمكن للمستخدم إنشاء تصدير ملف JSON من قائمة التسجيل أو صفحات عرض السجل ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها. تنسيق JSON قابل للقراءة آليًا وغير عملي لمعظم المستخدمين. + label: تصدير JSON + export_xls: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف XLS من قائمة التسجيل أو صفحات عرض السجل ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها. ملاحظة: يعرض تنسيق XLS الأحرف غير اللاتينية (مثل العربية والبنغالية) بتنسيق قابل للقراءة ، بينما لا يعرض تنسيق CSV.' + label: تصدير EXCEL (ملف XLS) + flag: + explanation: القدرة على إضافة علامة إلى سجل التسجيل. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي قاموا بإضافتها إلى سجل التسجيل. + label: تمييز بعلامة/وضع علامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: حل أي علامة + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على سجلات التسجيل. إذن "الإدارة" يعني أساسًا "كل شيء". + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على رؤية سجل التسجيل. + label: رؤية/تصفح + write: + explanation: القدرة على النقر فوق الزر "تعديل" وتحديث المعلومات في الحالة والنقر فوق "حفظ" + label: تعديل + sync_mobile: + explanation: يسمح للمستخدم بالتخزين المؤقت لسجلات التسجيل للاستخدام في وضع عدم الاتصال. + label: وضع علامة على عدم الاتصال بالانترنت + explanation: يمكن أن يمثل هذا فردًا أو مؤسسة تحتاج إلى ربطها بسجلات أخرى مثل الحالات أو الحوادث ، وهي كثيرة جدًا ويتم تحديثها بشكل متكرر بمعلومات جديدة. إنها تشبه عمليات البحث ، ولكن مع مجموعة أكثر تعقيدًا من المعلومات لكل إدخال. + label: سجل التسجيل + family: + actions: + change_log: + explanation: يمكن للمستخدم رؤية سجل بجميع التغييرات التي تم إجراؤها على السجل منذ إنشائه. يتضمن ذلك القيم المسجلة لجميع الحقول. + label: سجل التغيير + create: + explanation: القدرة على إنشاء سجل العائلة + label: إنشاء + enable_disable_record: + explanation: القدرة على تعطيل أو تفعيل الأسرة. لا تظهر العائلات "المعطلة" بشكل افتراضي في قائمة العائلة. يمكن للمستخدمين رؤية العائلات المعطلة في قائمة العائلة باستخدام عامل التصفية. + label: تفعيل / تعطيل + export_csv: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف CSV من قائمة العائلة أو صفحات عرض العائلة، والتي تحتوي على جميع المجالات التي يمكن للمستخدم الحالي الوصول إليها، لاسرة واحد أو اكثر ا. ملاحظة: لا يعطي تصدير CSV حروف غير لاتينية (مثل العربية)' + label: تصدير من نوع CSV + export_json: + explanation: يمكن للمستخدم إنشاء تصدير ملف JSON من قائمة العائلة أو صفحات عرض العائلة، والتي تحتوي على جميع المجالات التي يمكن للمستخدم الحالي الوصول إليها. تنسيق JSON قابل للقراءة آليًا وليس عمليًا لمعظم المستخدمين. + label: تصدير من نوع JSON + export_xls: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف XLS من قائمة العائلة أو صفحات عرض العائلة، والتي تحتوي على جميع المجالات التي يمكن للمستخدم الحالي الوصول إليها. ملاحظة: يجعل XLS الأحرف غير اللاتينية (مثل العربية) مقروئة، في حين أن تصدير CSV لا يفعل ذلك.' + label: تصدير من نوع XLS + export_list_view_csv: + explanation: يمكن للمستخدم إنشاء تصدير ملف CSV من صفحة قائمة العائلة والتي تحتوي على نفس الحقول التي تظهر لذلك المستخدم في قائمة العائلة. يؤدى فقط من صفحة قائمة العائلة. + label: تصدير للائحة على شكل CSV + export_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة العائلة أو صفحات العرض العائلي، والتي تحتوي على جميع المجالات التي يمكن للمستخدم الحالي الوصول إليها، لسجل واحد أو اكثر والتي يمكن للمستخدم الوصول إليها. في ملف تصدير PDF، يتم سرد المعلومات أولاً حسب الأسرة، ثم يتم تنظيمها من خلال النموذج الذي تظهر عليه المعلومات. + label: تصدير على شكل PDF + export_custom: + label: تصدير لحقول مخصصة من الملف + explanation: يمكن للمستخدم اختيار نماذج أو حقول محددة من قائمة العائلة أو صفحات عرض العائلة للتصدير إلى ملف XLS. + flag: + explanation: القدرة على إضافة اشارة علم إلى العائلة. يمكن للمستخدمين الحاصلين على هذا الإذن أيضًا إزالة اشارات الأعلام التي أضافوها إلى العائلة. + label: علامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: حل أية علامة + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على العائلات. إذن "الإدارة" يعني في الأساس "كل شيء". + label: إدارة (جميع الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على رؤية العائلات + label: عرض + write: + explanation: القدرة على الضغط على زر "تعديل" وتحديث المعلومات الخاصة بالعائلة والنقر على "حفظ". + label: تعديل + sync_mobile: + explanation: يسمح للمستخدم بتخزين سجلات العائلة مؤقتًا للاستخدام دون الاتصال بالإنترنت. + label: وضع علامة على غير متصل + close: + explanation: يسمح للمستخدم بتعيين حالة عائلة مفتوحة إلى مغلقة. + label: غلق + reopen: + explanation: يمكن أن تساعد هذه الحالات على فتح أبوابها. + label: إعادة فتح + case_from_family: + explanation: يسمح للمستخدمين بإنشاء حالة جديدة من نموذج فرعي لأعضاء العائلة داخل سجل العائلة. + label: إنشاء حالة + label: العائلة + report: + actions: + create: + explanation: القدرة على إنشاء تقرير جديد. عندما يُنشئ المستخدم تقريرًا، يصبح مرئيًا لجميع المستخدمين الذين لديهم حق الوصول "للقراءة" أو "قراءة المجموعة" في التقارير. + label: إنشاء + group_read: + explanation: القدرة على عرض جميع التقارير. ستعكس الأرقام في كلّ تقرير فقط السجلات التي يمكن الوصول إليها من قبل المستخدمين في مجموعات المستخدمين المستخدم الحالي. غالبًا ما يستخدم هذا الإذن للمسؤولين المحليين أو الإقليميين أو الهيئات الذين يتطلعون إلى الإطلاع على أداء فرقهم أو منظماتهم. يمنح هذا الإذن المستخدم أيضًا القدرة على تصدير البيانات من تقرير معيّن. + label: عرض (البيانات المستندة إلى المجموعة) + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة للوكالات. يعني إذْن "الإدارة" بشكل أساسي "كل شيء". + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على عرض جميع التقارير. ستعكس الأرقام في كلّ تقرير كلّ السجلات في النظام، بدلاً من السجلات التي يحقّ للمستخدم الحالي فقط الوصول إليها. يمنح هذا الإذن المستخدم أيضًا القدرة على تصدير البيانات من تقرير معيّن. + label: عرض + write: + explanation: القدرة على تعديل كلّ التقارير (بما في ذلك تلك التي أنشأها مستخدمون آخرون). + label: تعديل + agency_read: + explanation: القدرة على عرض جميع التقارير. ستعكس الأرقام الواردة في كل تقرير فقط تلك السجلات التي يمكن الوصول إليها من قبل المستخدمين في الهيئة المستخدمة الحالية. غالبًا ما يستخدم هذا الإذن لمسؤولي نظام الهيئة. + label: عرض (البيانات المستندة إلى الهيئة) + explanation: أداة تحليل البيانات المجمعة. يشمل تمثيلات الجدول والرسم البياني للبيانات. + label: تقرير + reporting_location_level: + explanation: 'سيتحكم هذا في مستوى المواقع التي تظهر لهذا الدور في لوحات المعلومات، وعوامل التصفية، ووحدات الإحالة النمطية، وشروط التحويل. إذا تركت هذا الحقل فارغًا، سيرى هذا الدور مستوى موقع الإبلاغ الافتراضي في النظام.' + label: ما هو نوع الموقع الذي يجب استخدامه للإبلاغ لهذا الدور؟ + role: + actions: + assign: + explanation: القدرة على اختيار دور عند إنشاء أو تعديل حساب مستخدم. هذا الإذن ضروري لأي دور يقوم بإنشاء أو تعديل حسابات المستخدمين. + label: تعيين + copy: + explanation: القدرة على إنشاء نسخة من الدور. هذا مفيد لمسؤولي النظام الذين قد ينشئون عددًا من الأدوار المتشابهة جدًا (مثل مزودي الخدمة). + label: نسخ + create: + explanation: القدرة على إنشاء دور + label: إنشاء + delete: + explanation: القدرة على حذف دور + label: حذف + manage: + explanation: 'يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على الأدوار. إذن "الإدارة" يعني أساسًا "كل شيء". هام: يمنح هذا الإذن أيضًا القدرة على إنشاء أدوار وحذفها.' + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + permitted_roles: + explanation: إذا كان لدور ما القدرة على تنفيذ أي من الإجراءات المذكورة أعلاه على دور، فسيكون قادرًا على تنفيذ تلك الإجراءات على الأدوار المحددة في هذه القائمة. لذلك، على سبيل المثال، إذا كان الدور لديه إذن "قراءة" و "تعيين" للأدوار، ولكن تمّ إدراج "اخصائي الحالة CP" و "المدير CP" فقط على أنّهما "الأدوار المُدارة"، فسيكون قادرًا فقط على رؤية هذين الدورين وسيكون قادرًا فقط على تعيين مستخدمين جدد لهذين الدورين. إذا لم يتمّ تحديد "الأدوار المُدارة" للدور نفسه، فسيكون قادرًا على رؤية جميع الأدوار وسيكون قادرًا على إنشاء حسابات مستخدمين جديدة بأي دور في النظام. + label: الأدوار الأخرى التي يديرها هذا الدور + read: + explanation: القدرة على إنشاء الأدوار + label: عرض + write: + explanation: القدرة على النقر على زر "تعديل" في صفحة عرض الأدوار، وتحديث أذونات الدور، ثم حفظ الدور. + label: تعديل + explanation: تملي الإجراءات التي يمكن للمستخدم تنفيذها في Primero. + label: الأدوار + system: + actions: + manage: + explanation: القدرة على رؤية المعلومات وتحديثها ضمن معلومات الاتصال في النظام والإشعارات الافتراضية وإعدادات البريد الإلكتروني والإعداد الترحيبية والخوادم المتزامنة. عادة ما يكون هذا الإذن مخصّصًا لمسؤول النظام + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: ' الإعدادات المتنوعة على مستوى النظام.' + label: النظام + tracing_request: + actions: + change_log: + explanation: يمكن للمستخدم رؤية تاريخ التغييرات التي تم إجراؤها على السجل منذ إنشائه. يتضمن هذا القيم المسجلة لجميع الحقول. + label: تغيير السجل + create: + explanation: القدرة على إنشاء طلب تتبّع + label: إنشاء + enable_disable_record: + explanation: القدرة على تعطيل أو تمكين طلب تتبّع. لا تظهر طلبات التتبّع "المعطّلة" بشكل افتراضي في قائمة طلبات التتبّع. يمكن للمستخدمين رؤية طلبات التتبّع المعطّلة في قائمة طلبات التتبّع من خلال تطبيق عامل تصفية. + label: تفعيل/تعطيل + export_case_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة طلبات التتبّع أو صفحات عرض طلبات التتبّع، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بسجلّ واحد أو سجلات متعدّدة أو جميع السجلات التي يمكن للمستخدم الوصول إليها. في ملف التصدير PDF، يتمّ سرد المعلومات أولاً حسب الحالة، ثم يتمّ تنظيمها بعد ذلك حسب النموذج الذي تظهر عليه المعلومات. + label: تصدير PDF + export_csv: + explanation: 'يمكن للمستخدم إنشاء ملف تصدير CSV من قائمة طلبات التتبّع أو صفحات عرض طلبات التتبّع، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بطلب تتبّع واحد أو طلبات تتبّع متعددة أو جميع طلبات التتبّع التي يمكن للمستخدم الوصول إليها. ' + label: تصدير CSV + export_custom: + explanation: يمكن للمستخدم إنشاء ملف تصدير XLS من قائمة طلبات التتبّع أو صفحات عرض طلبات التتبّع، والتي تحتوي على مجموعة مخصّصة من النماذج أو الحقول، بالنسبة إلى طلب تتبّع واحدة أو طلبات تتبّع متعددة أو جميع طلبات التتبّع التي يمكن للمستخدم الوصول إليها. في هذا التصدير، يتمّ تمثيل كلّ نموذج في علامة التبويب الخاصة به داخل ملف XLS. يمكن للمستخدم اختيار النماذج أو الحقول التي يريد تضمينها في التصدير باستخدام قسم التصدير المخصّص. يرجى ملاحظة أنه لا يمكن للمستخدمين تضمين النماذج والحقول في التصدير إلا إذا كان لديهم بالفعل القدرة على رؤية تلك النماذج والحقول عند عرض طلب تتبّع في التطبيق. + label: تصدير ملف مخصص + export_json: + explanation: يمكن للمستخدم إنشاء ملف تصدير JSON من قائمة طلبات التتبّع أو صفحات عرض طلبات التتبّع، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ،والمرتبطة بطلب تتبّع واحد أو طلبات تتبّع متعددة أو جميع طلبات التتبّع التي يمكن للمستخدم الوصول إليها. يستخدم هذا التصدير بشكل أساسي من قبل الذين يرغبون في تصدير طلبات التتبّع من نظام Primero الحالي ثم استيرادها إلى نظام Primero مختلف، أو إلى نظام إدارة معلومات آخر. تعتبر صيغة JSON قابلة للقراءة آليًا وغير عمليّة لمعظم المستخدمين. + label: تصدير JSON + export_list_view_csv: + explanation: يمكن للمستخدم إنشاء ملف تصدير CSV من صفحة قائمة طلبات التتبّع التي تحتوي الحقول عينها التي تظهر لهذا المستخدم في قائمة طلبات التتبّع. يتمّ تنفيذها فقط من صفحة قائمة طلبات التتبّع. + label: تصدير ملف عرض قائمة csv + export_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة طلبات التتبع أو عرض صفحات طلب التتبع ، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ، لسجل واحد أو متعدد أو جميع السجلات التي يمتلك المستخدم حق الوصول إليها. في ملف تصدير PDF ، يتم سرد المعلومات أولاً حسب الحالة ، ثم يتم تنظيمها بشكل أكبر حسب النموذج الذي تظهر عليه المعلومات. + label: تصدير ملف PDF + export_xls: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف XLS من قائمة طلبات التتبع أو صفحات عرض طلب التتبع ، والتي تحتوي على جميع الحقول التي يمتلك المستخدم الحالي حق الوصول إليها ، لطلبات تتبع واحدة أو متعددة أو جميعها التي يمتلك المستخدم حق الوصول إليها. في هذا التصدير ، يتم تمثيل كل نموذج في علامة التبويب الخاصة به داخل ملف XLS. ملاحظة: يعرض تنسيق XLS الأحرف غير اللاتينية (مثل العربية والبنغالية) بتنسيق قابل للقراءة ، بينما لا يعرض تنسيق CSV.' + label: تصدير EXCEL (ملف XLS) + flag: + explanation: القدرة على إضافة علم إلى طلب تتبّع. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي أضافوها إلى إحدى طلبات التتبّع. + label: تمييز بعلامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: حل أية علامة + import: + explanation: يسمح للمستخدم بإنشاء حالة واحدة جديدة أو أكثر من خلال استيرادها من ملف CSV أو Excel أو JSON. يجب أن يكون الملف المستورد مهيّأ *جدًّا* وخصوصًا حتى يتمّ استيراد المعلومات بشكل صحيح. يجب أن تكون هذه الوظيفة متاحة فقط للمستخدمين الإداريين ذوي المهارات التقنية المتقدّمة والمعرفة العميقة بكيفية تهيئة البيانات في Primero. يتمّ تنفيذها فقط من صفحة قائمة الحالة. + label: استيراد + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة لطلبات التتبّع. يعني إذْن "الإدارة" بشكل أساسي "كل شيء". + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على عرض طلب التتبع. يجب أن تتمتع الأدوار التي لها القدرة على رؤية طلبات التتبع أيضًا بالقدرة على رؤية نوع سجل التطابق المحتمل. + label: عرض + write: + explanation: القدرة على نقر زر "تعديل" وتحديث المعلومات عن طلب التتبّع ثم النقر على "حفظ". تسمح أيضًا للمستخدم بتعطيل طلب تتبّع أو تفعيله. + label: تعديل + explanation: يمثل فردًا يحاول تحديد مكانه وجمع شمله في حالة غير مصحوب أو منفصل. + label: طلبات التتبع + transfer: + actions: + transfer: + explanation: هذا يعني أنّ الدور سيظهر كخيار لـ "نوع المستلِم" عندما يقوم المستخدم بإحالة خارجية. إذا اختار المستخدم هذا الدور كنوع التحويل، سيحتوي التصدير الذي ينشئه Primero عندما يرسل المستخدم التحويل فقط على المعلومات الموجودة في النماذج التي يمكن لهذا الدور الوصول إليها. إذًا، على سبيل المثال، إذا اختار المستخدم "مزود الخدمة الطبية" كنوع المستلِم، وكان دور مقدم الخدمة الطبية لديه حق الوصول فقط إلى نماذج الهوية الأساسية والمخاوف المتعلّقة بالحماية، لن يحتوي ملف التصدير الذي يصدره Primero للتحويل الخارجي إلّا على الحقول الموجودة في هذين النموذجين. + label: هل يمكن استخدام هذا الدور للتحويلات الخارجية؟ + label: تحويل + user: + actions: + agency_read: + explanation: القدرة على رؤية حسابات المستخدمين في الهيئة المستخدمة الحالية فقط. يؤثر هذا أيضًا على حسابات المستخدمين التي يمكن للمستخدم الحالي تنفيذ إجراءات أخرى عليها. على سبيل المثال ، إذا كان المستخدم الحالي لديه إذن "كتابة" على المستخدمين، ولكن لديه أيضًا إذن قراءة الهيئة، فسيكون قادرًا فقط على تعديل حسابات المستخدمين الموجودة في هيئته الخاصة. وبالمثل، إذا كان المستخدم الحالي لديه إذن "إدارة" للمستخدمين، ولكن لديه إذن "قراءة الهيئة"، فسيكون قادرًا فقط على إنشاء مستخدمين لهيئته الخاصة. + label: عرض (ضمن الهيئة) + create: + explanation: القدرة على إنشاء حساب مستخدم + label: إنشاء + manage: + explanation: 'يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على المستخدمين. إذن "الإدارة" يعني أساسًا "كل شيء". هام: يمنح هذا الإذن أيضًا القدرة على إنشاء حسابات مستخدمين جديدة.' + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على رؤية حسابات المستخدمين. بشكل افتراضي، كلّ مستخدم لديه القدرة على رؤية المعلومات المتعلقة بحسابه الخاص وتعديلها (مثل كلمة المرور والبريد الإلكتروني). + label: عرض + write: + explanation: القدرة على نقر زر "تعديل" في صفحة عرض المستخدم، وتحديث معلومات المستخدم، ثم الحفظ. يرجى ملاحظة أنّ هذا الإذن يمنحك أيضًا القدرة على تعطيل حسابات المستخدمين. + label: تعديل + explanation: يمثل حساب مستخدم فردي. + label: المستخدمون + user_group: + actions: + assign: + explanation: القدرة على اختيار مجموعات المستخدمين عند إنشاء حساب المستخدم أو تعديله. يرجى ملاحظة أنه إذا كان لدى المستخدم الحالي مستوى الوصول فقط إلى "السجلات أو المستخدمين في مجموعتي"، سيكون قادرًا فقط على اختيار مجموعة واحدة أو أكثر من مجموعات المستخدمين * الخاصة بهم * لحساب المستخدم الذي يقومون بإنشائه أو تعديله. هذا يعني أن المدير الذي لديه القدرة على تعيين مجموعات مستخدمين سيكون قادرًا فقط على إضافة مستخدم إلى مجموعات المستخدمين التي ينتمي إليها المدير حاليًا. هذا الإذن ضروري لأي دور يقوم بإنشاء حسابات المستخدمين أو تعديلها. + label: تعيين + create: + explanation: القدرة على إنشاء مجموعة مستخدمين + label: إنشاء + delete: + explanation: القدرة على حذف مجموعة مستخدمين + label: حذف + manage: + explanation: 'يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على مجموعات المستخدمين. إذن "الإدارة" يعني أساسًا "كل شيء". هام: يمنح هذا الإذن أيضًا القدرة على إنشاء مجموعات المستخدمين وحذفها.' + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على رؤية مجموعات المستخدمين + label: عرض + write: + explanation: القدرة على تعديل مجموعات المستخدمين. + label: تعديل + explanation: يمثل فريقًا أو مجموعة متعاونة من المستخدمين الذين يمكنهم مشاركة المعلومات. يمكن للمديرين عادةً رؤية جميع السجلات التي يديرها اخصائيون الحالة في مجموعات المستخدمين الخاصة بهم. + label: مجموعات المستخدمين + webhook: + actions: + read: + label: رؤية/تصفح + explanation: القدرة على سرد ومراجعة إعدادات webhook عبر واجهة برمجة التطبيقات + write: + label: تعديل + explanation: القدرة على إنشاء وتعديل إعدادات webhook عبر واجهة برمجة التطبيقات. + create: + explanation: القدرة على إنشاء إعدادات webhook عبر واجهة برمجة التطبيقات. + label: إنشاء + delete: + explanation: القدرة على حذف إعدادات webhook عبر واجهة برمجة التطبيقات. + label: حذف/إزالة + manage: + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: يُستخدم لأدوار النظام التي تصل إلى Primero Webhooks للأنظمة الأخرى. لا ينصح باستخدامه لغير المطورين. + activity_log: + actions: + transfer: + explanation: يمكن للمستخدم النقر فوق قسم سجل النشاطات في لوحة ملخص البيانات والاطلاع على سجل بجميع عمليات النقل المقبولة أو المرفوضة للحالات التي يمكنهم الوصول إليها. + label: عمليات النقل + manage: + label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: القدرة على الوصول إلى كافة. + label: سجل التغيير + potential_match: + case_id: هوية الحالة + child_age: العمر + child_gender: الجنس + child_id: 'رقم معرف الطفل #' + inquirer_id: معرف المُستفسر# + inquirer_tr_name: تتبع الطلبات + inquiry_date: تاريخ الاستفسار + name: الاسم + score: النتيجة + social_worker: 'اخصائي الحالة ' + social_worker_agency: الهيئة + tracing_request_id: معرّف طلبات التتبّع + trace: تتبّع + likelihood_likely: مرجح + likelihood_possible: ممكن + potential_matches: + display: عرض النتائج المطابقة المحتملة لـ %{type} %{id} + reassign: + multiple_error: حدث خطأ. لم يتم تعيين الحالة (الحالات) %{select_records}. + multiple_successfully: Primero يحدث في هذه الاثنات الحالات % {select _ records} . قد يستغرق تحديث كل هذه الحالات عدة دقائق. + notes_label: ملاحظات + successfully: تمت إعادة التعيين بنجاح + user_mandatory_label: يجب إدخال إسم المستلِم + users_label: المستلِم + incident_from_case_warning: لا يمكنك تعيين هذه الحادثة، لأنها مرتبطة بالفعل بحالة ما. عندما تقوم بتعيين الحالة، يتم تعيين الحادث أيضًا. + record_information: + assigned_user_names: 'المستخدمين الأخرين ' + created_at: تم إنشاء السجل في + created_by: تم إنشاء السجل بواسطة + created_organization: تم الإنشاء بواسطة الهيئة + current_owner_separator: المالك الحالي + module_id: وحدة + owned_by: 'كود اخصائي الحالة ' + owned_by_agency_id: الهيئة + owned_by_text: الحقل/حالة/اخصائي الحالة + previously_owned_by: المستخدم السابق + previously_owned_by_agency: 'الهيئة السابقة ' + reassigned_tranferred_on: إعادة التعيين / التحويل في + record_history_separator: تسجيل التاريخ + last_updated_at: تاريخ اخر تحديث + last_updated_by: 'اخر تحديث تم من قبل ' + record_panel: + record_information: تسجيل المعلومات + referral: + type_of_recipient: نوع المستلِم + type_of_referral_required: مطلوب إدخال نوع الإحالة + referral_authorization_label: هل ترغب في تحديد نوع الإحالة؟ + referral_authorization_help_text: سيؤدي هذا إلى تحديد النماذج التي يمكن للمستلم الوصول إليها. + agency_label: الهيئة + is_remote_label: هل ترغب في احالة الحالة لمؤسسة من خارج النظام؟ + location_label: الموقع + notes_label: ملاحظات + notes_on_referral: الملاحظات عند الإحالة + note_on_referral_from_provider: الملاحظات عند الإحالة من المزوّد + provided_consent_label: لم يتمّ توفير الموافقة في النماذج. + recipient_label: المستلِم + refer_anyway_label: هل تريد الإحالة على أي حال؟ + service_label: خدمة + success: 'تمت إحالة %{record_type} %{id} بنجاح' + user_mandatory_label: المستلم مطلوب + date: التاريخ + rejected_reason: سبب الرفض + report: + aggregate_by: مجموعات حسب الصف + attribute: خاصيّة + constraint: قيود + date_ranges: + date: يوم + month: شهر + quarter: الربع + quarter_abbr: Q%{quarter} + week: اسبوع + year: سنة + description: الوصف + disabled: + explanation: إذا قمت بتعطيل هذا التقرير، لن يظهر ضمن التقارير المتاحة. + label: 'مُعطلة ' + exclude_empty_rows: لا تعرض صفوف فارغة + disaggregate_by: مجموعات حسب الأعمدة + filters: + label: الإبلاغ عن عوامل التصفية + label_new: عامل تصفية جديد للتقرير + attribute: عامل التصفية + value: مع + not_null: ليس فارغًا؟ + less_than: 'أقل من ' + greater_than: أكثر من + equal_to: مساوي لـ + not_blank: ليس فارغًا + is: هو + before: قبل + after: بعد + delete_filter_message: هل أنت متأكد أنك تريد حذف عامل التصفية هذا؟ + group_ages: استخدام نطاقات الأعمار + group_dates_by: استخدام نطاقات التواريخ + is_graph: هل تريد إنتاج مخطّط بياني؟ + messages: + delete_success: تم حذف التقرير بنجاح + success: تم إنشاء التقرير بنجاح. + updated: تم تحديث التقرير بنجاح. + modules: الوحدات النمطية + name: الاسم + name_mandatory: مطلوب ادخال الاسم المستخدم + no_data: لا يوجد بيانات لهذا التقرير + no_filters_added: لم تتمّ إضافة أي عوامل تصفية + not_selected: لم يتم اختياره + record_type: نوع السجل + total: الإجمالي + value: قيمة + incomplete_data: بيانات غير مكتملة + reports: + delete_report: حذف التقرير + delete_report_message: هل أنت متأكد أنك تريد حذف هذا التقرير؟ لا يمكن التراجع عن الحذف. انقر فوق تمّ لحذف التقرير. + label: تقارير + register_new_report: إنشاء تقرير + translations: + edit: تحرير الترجمات + manage: إدارة الترجمات + select_language: اختار اللغة + error_loading: خطأ في تحميل التقرير(التقارير) + request_transfer: + notes_label: ملاحظات -الرجاء ذكر سبب النقل بالإضافة إلى تفاصيل الاجتماعات التي عقدت لمناقشة نقل الحالة + submit_label: أرسل الطلب + success: تم إرسال طلب التحويل + role: + agency_ids_label: وكالات يديرها هذا الدور + copy_failure: خطأ في نسخ الدور. تأكد من أن الاسم لا يتعارض مع دور آخر. + copy_success: نسخ الدور بنجاح. + create: إنشاء دور + delete_header: حذف دور + description: الوصف + edit: تعديل الدور + error_in_updating: خطأ في تحديث تفاصيل الدور. + group_permission_label: ما السجلات التي يؤثر فيها هذا الدور؟ + label: دور + manager: المدير + messages: + confirmation: هل أنت متأكد أنك تريد حذف هذا الدور؟ لا يمكن التراجع عن الحذف. انقر فوق تمّ لحذف الدور. + created: تم إنشاء الدور بنجاح. + deleted: تم حذف الدور بنجاح + updated: تم تحديث الدور بنجاح. + name: الاسم + referral_label: هل يمكن استخدام هذا الدور للإحالات؟ + reporting_location_level_label: ما هو نوع الموقع الذي يجب استخدامه للإبلاغ عن هذا الدور؟ + role_ids_label: الأدوار الأخرى التي يديرها هذا الدور + successfully_updated: تم تحديث تفاصيل الدور بنجاح. + transfer_label: هل يمكن استخدام هذا الدور لعمليات النقل؟ + hide: إخفاء + read: عرض + read_write: عرض وتحرير + roles: + label: دور المستخدم + saved_search: + deleted: تم حذف البحث بنجاح + filters_tab: مرشحات + no_filters: لم يتمّ اختيار أي عوامل تصفية + save_success: تم حفظ البحث بنجاح + saved_searches_tab: عمليات بحث محفوظة + title_description: هل أنت متأكد أنك تريد حذف هذا البحث المحفوظ؟ + title_modal: حذف عمليات البحث المحفوظة + saved_searches: + no_save_searches: لا يوجد لديك عمليات بحث محفوظة + save_search: عملية بحث محفوظة + settings: + navigation: + agencies: الهيئات + audit_logs: سجلات التدقيق + configurations: إعدادات + contact_information: معلومات الاتصال + forms: النماذج + locations: المواقع + lookups: عمليات البحث + user_groups: مجموعات المستخدمين + users: المستخدمون + roles: الأدوار + code_of_conduct: مدونة قواعد السلوك + title: إعدادات + system_settings: + label: إعدادات النظام + task: + due_date: تاريخ الاستحقاق + id: رقم الحالة في النظام + name: الإسم + priorities: + high_level: مرتفع + low_level: منخفض + medium_level: متوسط + no_action_level: لا يوجد إجراء + priority: مستوى الأولوية + status: الوضع + statuses: + overdue: متأخرة + upcoming_soon: أوشك على الاستحقاق + type: نوع الإجراء + types: + assessment: التقييم + case_plan: خطة الحالة + follow_up: متابعة - %{subtype} + service: الخدمة - %{subtype} + tracing_request: + label: طلبات التتبع + has_match: يوجد تطابق + find_match: إيجاد تطابق + back_to_traces: العودة إلى التتبعات + back_to_potential_matches: العودة إلى التطابقات المحتملة + traces: تتبّعات + trace: تتبّع + match: مطابق + matches: تطابقات + unmatch: إزالة التطابق + tracing_request_photos: صور من اجل طلب التتبع هذا + case_photos: صور لهذه الحالة + tracing_request_audios: ملف صوتي من اجل طلب التتبع هذا + case_audios: ملف صوتي لهذه الحالة + messages: + already_matched: يوجد بالفعل تطابقًا في النظام مع مستعلم يبحث عن هذا الطفل. + disabled: تمّ تعطيل طلب التتبع + nothing_found: لم يتم العثور على شيء + update_success: 'تم تحديث طلب التتبع %{record_id} بنجاح. ' + creation_success: 'تم إنشاء سجل طلب التتبع بنجاح. ' + update_success_queue: 'تم تحديث طلب التتبع %{record_id} بنجاح في الخلفية.' + creation_success_queue: تم إنشاء سجل طلب التتبع بنجاح في الخلفية. + match_action: تمت مطابقة التتبع %{trace_id} مع الحالة %{record_id} بنجاح. + unmatch_action: تمت إزالة تطابق التتبع %{trace_id} والحالة %{record_id}بنجاح. + registry_record: + messages: + update_success: 'تم تحديث سجل التسجيل %{record_id} بنجاح.' + creation_success: 'تم إنشاء سجل التسجيل بنجاح.' + disabled: سجل التسجيل معطل + tracing_requests: + date_of_inquiry: تاريخ الاستعلام + disable_dialog_title: تعطيل طلب التتبع + disable_dialog: بالنقر على "تمّ" سيُصبح وضع طلب التتبّع هذا معطّلًا. + disable_success: تمّ تعطيل طلب التتبع بنجاح + enable_dialog: بالنقر على "تمّ" سيُصبح وضع طلب التتبّع هذا مفعّلاً. + enable_dialog_title: تفعيل طلب التتبع + enable_success: تمّ تفعيل طلب التتبع بنجاح + id: الهويّة + complete: متاح بدون الاتصال بالانترنت + filter_by: + by_date: حسب التاريخ + location_separation: موقع الإنفصال + separation_cause: سبب الإنفصال + status: الوضع + label: طلبات التتبع + name_of_inquirer: إسم المُستفسر + inquirer: المُستفسر + name: الإسم + register_new_tracing_request: 'طلب تتبع جديد ' + selectable_date_options: + inquiry_date: تاريخ الاستعلام + selected_records: 'تمّ اختيار طلب التتبّع (طلبات التتبّع) %{select_records}' + selected_all_records: 'اختَر جميع طلبات التتبّع %{total_records} التي تطابق هذا الاستعلام.' + show_tracing_request: 'معرِّف طلب التتبع %{short_id} ' + tracing_requests: طلبات التتبع + export: تصدير + sort_by: ترتيب حسب + registry_records: + id: رقم الحالة في النظام + label: سجل التسجيل + name: الإسم + registry_no: رقم التسجيل + location: موقع + registration_date: تاريخ التسجيل + selected_records: '%{select_records} تم تحديد سجل (سجلات) التسجيل' + selected_all_records: 'حدد كافة سجلات التسجيل %{total_records} التي تطابق هذا الاستعلام.' + disable_dialog_title: تعطيل سجل التسجيل + disable_dialog: سيؤدي النقر فوق "موافق" إلى تغيير حالة سجل التسجيل هذا إلى معطل. + disable_success: تم تعطيل سجل التسجيل بنجاح + enable_dialog_title: تفعيل سجل التسجيل + enable_dialog: سيؤدي النقر فوق "موافق" إلى تغيير حالة سجل التسجيل هذا إلى مفعل. + enable_success: تم تفعيل سجل التسجيل بنجاح + complete: متاح بدون الاتصال بالانترنت + filter_by: + by_date: حسب التاريخ + status: الوضع + selectable_date_options: + registration_date: تاريخ التسجيل + show_registry_record: 'معرف سجل التسجيل: %{short_id}' + register_new_registry_record: سجل التسجيل جديد + export: يصدر + mark_for_offline: + title: وضع علامة على عدم الاتصال بالانترنت + text: هل أنت متأكد أنك تريد وضع علامة على سجلات التسجيل هذه لاستخدامها عندما تكون غير متصل؟ + success: تم وضع علامة على سجلات التسجيل بنجاح للاستخدام دون اتصال بالانترنت + families: + id: بطاقة تعريف + label: العائلة + family_id: معرف العائلة + family_number: رقم العائلة + family_name: اسم العائلة + family_registration_date: تاريخ التسجيل + family_location_current: مكان العائلة + export: استيراد + register_new_family: عائلة جديدة + show_family: 'رقم ملف العائلة %{short_id}' + disable_dialog_title: سجل عائلة معطل + disable_dialog: سيؤدي النقر فوق "موافق" إلى تغيير حالة هذه العائلة إلى "معطل". + selected_records: '%{select_records} سجل (سجلات) عائلية تم اختيارها' + selected_all_records: 'حدد جميع %{total_records} العائلات التي تطابق هذا الاستعلام.' + mark_for_offline: + title: وضع علامة على غير متصل + text: هل أنت متأكد من أنك تريد وضع علامة على سجلات العائلة هذه لاستخدامها عندما تكون غير متصل بالإنترنت؟ + success: تم وضع علامة على سجلات العائلة بنجاح للاستخدام دون اتصال + filter_by: + by_date: ب تاريخ + status: الوضع + current_location: مكان العائلة + family: + family_member: + case_id: معرف الحالة + update_and_return: التحديث والعودة + save_and_return: إضافة والعودة + create_case: إنشاء حالة + back_to_family_members: العودة إلى أعضاء العائلة + create: إنشاء + messages: + update_success: 'تم تحديث ملف العائلة رقم % {record _ id} بنجاح.' + creation_success: 'تم إنشاء سجل العائلة بنجاح.' + disabled: العائلة معطلة + confirm_create_case: هل تريد إنشاء حالة لهذا الشخص؟ + transfer: + label: نقل + agency_label: الهيئة + consent_from_individual_label: هل حصلت على موافقة الشخص لإجراء هذا التحويل؟ + consent_label: لم توفر السجلات الموافقة. + consent_override_label: هل ترغب في تجاوز تعبئة نموذج الموافقة؟ + is_remote_label: هل تقوم بالنقل إلى نظام بعيد؟ + location_label: الموقع + notes_label: ملاحظات -الرجاء ذكر سبب النقل بالإضافة إلى تفاصيل الاجتماعات التي عقدت لمناقشة نقل الحالة + provided_consent_label: لم يتمّ توفير الموافقة في النماذج. + recipient_label: المستلِم + select_label: اختَر... + success: تمّ التحويل بنجاح + transfer_label: هل تريد التحويل على أي حال؟ + user_mandatory: المستلم مطلوب + rejected_reason: سبب الرفض + transfer_assignment: + title: عمليات النقل والتعيينات + transition: + agency_label: الهيئة + assigned_by: تعيين من قِبَل + consent_individual_transfer_value: + true_label: 'نعم' + false_label: 'لا' + consent_overridden_value: + false_label: 'لا' + true_label: 'نعم' + errors: + consent: لم يتمّ توفير الموافقة + to_user_can_receive: لا يستطيع هذا المستخدم استلام هذا السجلّ + individual_consent: هل حصل الإختصاصي الإجتماعي على موافقة الشخص لإجراء هذا التحويل؟ + no_consent_share: تخطّي الموافقة على مشاركة الإعداد؟ + notes: ملاحظات + recipient: المستلِم + rejected: تمّ رفض السبب + requested_by: مطلوب + service_label: الخدمة + responded_at: تمّ الرد في + status: + accepted: تمّت الموافقة + done: استكمال + in_progress: معلّقة + inprogress: معلّقة + rejected: رُفض + revoked: تم الغاء او ملغي + transferred_by: منقول بواسطة + type: + assign: تعيين + reassign: تعيين + referral: إحالة + external_referral: إحالة خارجية + transfer: تحويل + transferRequest: طلب التحويل + user: + agency_office: مكتب الهيئة (موقع العنف المبني على النوع الاجتماعي) + code: 'كود المستخدم ' + disabled: 'مُعطلة ' + email: البريد الإلكتروني + full_name: الاسم الكامل + identity_provider: مزوّد الهويّة + invalid_provider_username: 'صيغة اسم المستخدم غير صالح. مثال: @my.username %{domain}' + label: مستخدم + language: لغة + locale: موضع + location: الموقع + messages: + records_update: يقوم Primero بتحديث سجلات هذا المستخدم لتعكس التغييرات التي أجريتها. قد يستغرق تحديث لوحات المعلومات والتقارير بعض الوقت. + confirmation: 'هل أنت متأكد أنك تريد حذف هذا المستخدم؟ لا يمكن التراجع عن الحذف. انقر فوق موافق لحذف المستخدم. ' + created: تم إنشاء المستخدم بنجاح. + failure: حدث خطأ، يرجى الاتصال بالدعم. + new_confirm_html: أنت على وشك دعوة المستخدم %{username}من %{identity} الذي يتمتّع بدور %{role} لاستخدام Primero. سيتم إرسال بريد إلكتروني للتأكيد إلى %{email}. هل ترغب في المتابعة؟ + new_confirm_non_identity_html: أنت على وشك دعوة المستخدم %{username}الذي يتمتّع بدور %{role} لاستخدام Primero. سيتم إرسال بريد إلكتروني للتأكيد إلى %{email}. هل ترغب في المتابعة؟ + not_found: لم يتم العثور على مستخدم بهذا المُعرف + password_changed_successfully: تغيير كلمة المرور بنجاح + passwords_do_not_match: لا تطابق كلمة المرور الحالية + time_zone_updated: تم تحديث التغيير بنجاح. + updated: تم تحديث المستخدم بنجاح. + created_warning: لقد قمت بإنشاء% {إجمالي _ تمكين} من% {الحد الأقصى _ المستخدمين} المسموح للمستخدمين. + organization: المنظمة + agency: الهيئة + services_help_text: إذا لم تحدّد الخدمات، سيتم منح هذا المستخدم نفس الخدمات التي تتوفر لهيئته. + password_setting: + label: كيف يجب على بريميرو Primero تعيين كلمة مرور المستخدم؟ + self: سوف أقوم بتعيين كلمة المرور + user: سيقوم المستخدم بتعيين كلمة المرور باستخدام البريد الإلكتروني الترحيبي + help_text: يرجى التذكّر أنّه إذا قمت أنت كمسؤول بتعيين كلمة المرور يدويًا، ستحتاج إلى مشاركتها مع المستخدم بطريقة آمنة. + password_reset_header: إرسال بريد إلكتروني لإعادة تعيين كلمة المرور + password_reset_text: إذا قمت بالنقر على "أرسل"، سيتلقى هذا المستخدم بريدًا إلكترونيًا يحتوي على رابط لإعادة تعيين كلمة المرور الخاصة به. + password_reset_request: إرسال بريد إلكتروني لإعادة تعيين كلمة المرور + password: كلمة المرور + password_confirmation: تأكيد كلمة المرور + phone: الهاتف + position: وضع + provider_username_help: 'مثلاً: %{domain}@my.username' + role_id: دور + send_mail: استلام إشعارات عبر الايميل؟ + send_mail_preferences: + label: ما أنواع إشعارات البريد الإلكتروني التي ترغب في تلقيها؟ + help_text: إذا تركت هذا الحقل فارغًا، فستتلقى جميع إشعارات البريد الإلكتروني. + receive_webpush: + label: تلقي الإخطارات؟ + help_text: لاحظ أنك ستظل بحاجة إلى السماح بدفع الإشعارات على متصفح جهازك. + tooltip: يجب عليك أولاً تعديل حسابك وتمكين الإشعارات المباشرة للمستخدم الخاص بك. + receive_webpush_preferences: + label: ما هي أنواع الإشعارات الفورية التي ترغب في تلقيها؟ + help_text: إذا تركت هذا الحقل فارغًا، فستتلقى جميع الإشعارات الفورية. + notification_preferences: + approval_request: 'طلب الموافقة (المديرين)' + approval_response: 'الاستجابة للموافقة (اخصائيون الحالة)' + transition_notification: 'التعيينات والانتقالات والإحالات' + transfer_request: 'طلب نقل' + user_group_unique_ids: مجموعات المستخدمين + user_name: اسم المستخدم + services: الخدمات + welcome_email: + subject: 'مرحبا بكم في %{system}!' + greeting: 'مرحبا بكم في %{system}!' + body_native: 'لقد تمت إضافتك كـ.%{role_name}. يرجى الاتصال بـ%{admin_full_name} (%{admin_email}) للحصول على تعليمات المتابعة لبدء العمل مع%{host}.' + sso: + body: 'قد تمت إضافتك كـ.%{role_name}.' + step1: 'إذهب إلى %{host} وانقر على %{identity_provider}' + step2: 'قم بتسجيل دخول باستخدام حسابك %{identity_provider} %{user_name}' + step3: 'استخدم نفس كلمة المرور التي تستخدمها دائمًا لحسابك %{identity_provider}.' + footer: 'يرجى الاتصال بـ %{admin_full_name} (%{admin_email}) لمزيد من التفاصيل.' + otp: + body: 'قد تمت إضافتك كـ.%{role_name}.' + step1: 'يرجى الاتصال بـ %{admin_full_name} (%{admin_email}) للحصول على اسم المستخدم الخاص بك.' + step2: 'إذهب إلى %{host} وانقر على "تسجيل الدخول باستخدام اسم المستخدم في بريميرو Primero".' + step3: 'تسجيل الدخول باسم المستخدم وكلمة المرور المؤقتة %{otp}.' + step4: 'عند المطالبة، أعد تعيين كلمة المرور الخاصة بك.' + url_label: بريميرو + enabled_label: إرسال رسالة ترحيب عبر البريد الإلكتروني؟ + text_label: نص رسالة الترحيب + password_reset: + subject: 'تعليمات إعادة تعيين كلمة المرور' + email_greeting: "عزيزي%{full_name}" + email_body1: "قدّم أحدٌ ما طلبًا لتعيين كلمة المرور الخاصة بك لـ%{host_href}. انقر فوق الرابط url أدناه للبدء:" + email_body2: "ستنتهي صلاحية هذا الرابط في غضون %{hours} ساعة ويمكن استخدامه مرّة واحدة فقط. يرجى تجاهل هذا البريد الإلكتروني إذا لم تكن قد طلبت إعادة تعيين كلمة المرور أو لم يتمّ تسجيل مستخدم Primero جديد نيابة عنك. في حالة انتهاء صلاحية الرابط أعلاه، يرجى النقر على %{reset_request_href} لإعادة إرسال طلب إعادة تعيين كلمة المرور." + email_body_link: هنا + request_submitted: "تم إرسال طلب إعادة تعيين كلمة المرور" + success: "تمّ تغيير كلمة المرور بنجاح" + errors: + reset_password_token: "كود إعادة تعيين كلمة المرور غير صالح" + password_confirmation: "يجب أن تتطابق كلمات المرور" + onboard_email: + subject: "الإنضمام إلى %{system}" + greeting: "عزيزي%{full_name}،" + body1: "مرحبا بكم في بريميرو!" + body2: "لقد تم تعيينك كمسؤول منفذ لـ%{host_href}، %{reset_notification}" + body2_reset_notification: "ستتلقى رسالة بريد إلكتروني إضافية تطالبك بإعادة تعيين كلمة المرور الخاصة بك." + body3: "أنت مسؤول عن ضمان التنفيذ الآمن وفي الوقت المناسب. لكلّ عملية مطروحة، يجب أن تكون قد أكملت خطة التنفيذ مع إستراتيجية إدارة المستخدم والإنضمام وبروتوكول مشاركة المعلومات. أنت مسؤول أيضًا عن ضمان توقيع شروط الاستخدام من قبل جميع المنظمات المُستخدمة ووضع الشروط الموقعة في ملفّ المنظمات." + user_group: + associated_agencies: الهيئات المرتبطة بمجموعة المستخدمين هذه + description: الوصف + disabled: + explanation: إذا قمت بتعطيل مجموعة المستخدمين هذه، لن تتمكن من تعيينها إلى حسابات المستخدمين. + label: 'مُعطلة ' + messages: + created: تم إنشاء مجموعة المستخدمين بنجاح. + updated: تم تحديث مجموعة المستخدمين بنجاح. + name: الاسم + user_groups: + label: مجموعات المستخدم + users: + label: المستخدمين + headers: + full_name: الاسم الكامل + user_name: اسم المستخدم + position: الوظيفة + agency: الهيئة + alerts: + total_users_created: 'لقد قمت بإنشاء% {إجمالي _ تمكين} من التطبيق % {الحد الأقصى _ المستخدمين} ' + limit_user_reached: لقد وصلت إلى حد% {الحد الأقصى _ المستخدمين} للمستخدمين. يجب عليك تعطيل مستخدم واحد أو أكثر قبل إنشاء المزيد. + limit_user_reached_on_enable: لقد وصلت إلى الحد الأقصى للمستخدمين %{maximum_users} . يجب عليك تعطيل مستخدم واحد أو أكثر قبل إنشاء أو تمكين المزيد. + devise: + failure: + already_authenticated: "انت مُسجّل مسبقا." + invalid: "%{authentication_keys} أو كلمة مرور غير صالحين." + locked: "حسابك مقفل." + last_attempt: "لديك محاولة أخرى قبل أن يتمّ اقفال حسابك." + admin: + locations: + selected_records: '%{select_records} الموقع (المواقع) المحدد/ة' + selected_all_records: اختيار كلّ %{total_records}الحالات التي تطابق هذا الاستعلام. + updated: '%{updated_records} تحديث الموقع(المواقع)' + push_notifications_dialog: + title: إشعارات الجهاز + body_blocked: + message: لقد قمت بحظر إشعارات Primero على هذا الجهاز. لإصلاح هذه المشكلة، ستحتاج إلى تشغيل إشعار الأذونات. + android: "أندرويد: انتقل إلى الإعدادات. انقر على التطبيقات. ابحث عن Primero في قائمة التطبيقات وانقر فوقه. انقر فوق الإخطارات. قم بتبديل مفتاح التبديل للإشعارات إلى وضع التشغيل." + ios: "iOS: انتقل إلى تطبيق الإعدادات. انقر على الإخطارات. قم بالتمرير لأسفل إلى قائمة التطبيقات وابحث عن Primero. قم بتبديل مفتاح التبديل لـ Primero إلى وضع التشغيل." + body: + zero: '0' + one: '1' + two: '2' + few: قليل + many: كثير + other: هل تريد السماح لـ Primero بإرسال إشعارات لك ؟ تذكر أنك ستستمر في تلقي الإشعارات على هذا الجهاز بعد%{count} أيام من تسجيل الخروج. هذا غير موصى به للأجهزة المستخدمة من قبل اكثر من شخص. diff --git a/config/locales/ar.yml b/config/locales/ar.yml index 7370404aa5..ba26448289 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -55,35 +55,36 @@ ar: services_section_from_case: إضافة تقديم خدمة mark_for_offline: وضع علامة على عدم الاتصال بالانترنت agencies: - label: المؤسسة + label: الهيئة translations: manage: إدارة الترجمات agency: - agency_logos: شعارات الوكالة - code: رمز المؤسسة + agency_logos: شعارات الهيئة + code: كود الهيئة description: الوصف disabled: 'مُعطلة ' - exclude_agency_from_lookups: استبعاد هذه الوكالة من عمليات البحث وعوامل التصفية - exclude_agency_from_lookups_help: تحقق من هذا إذا لم يكن لدى الوكالة مستخدمون (على سبيل المثال ، تمت إضافة الوكالة حتى يمكن تطبيق الشعار على الصادرات. - label: وكالة - logo_enabled: عرض شعار هذه الوكالة في Primero؟ - logo_enabled_help: عرض شعار هذه الوكالة في Primero؟ + exclude_agency_from_lookups: استبعاد هذه الهيئة من عمليات البحث وعوامل التصفية + exclude_agency_from_lookups_help: تحقق من هذا إذا لم يكن لدى الهيئة مستخدمون (على سبيل المثال ، تمت إضافة الهيئة حتى يمكن تطبيق الشعار على التصديرات. + label: الهيئة + logo_enabled: عرض شعار هذه الهيئة في Primero؟ + logo_enabled_help: عرض شعار هذه الهيئة في Primero؟ logo_icon: شعار الايقونة logo_icon_help: سيظهر هذا على الشاشات صغيرة الحجم والأجهزة اللوحية والهواتف. يجب أن يكون هذا على شكل مربع. logo_large: شعار كبير logo_large_help: سيظهر هذا على الشاشات كبيرة الحجم و في صيغة PDF. يجب أن يكون هذا على شكل مستطيل و يجب ان يكون الطول اكبر من الارتفاع messages: - created: تم انشاء الوكالة بنجاح - updated: تم تحديث الوكالة بنجاح - name: اسم المؤسسة + created: تم انشاء الهيئة بنجاح + updated: تم تحديث الهيئة بنجاح + name: اسم الهيئة pdf_logo_option: جعل الشعار متاح في صيغة PDF ؟ - pdf_logo_option_help: 'ملاحظة: شعارات الوكالة الخاصة بالمستخدم متاحة لهم بشكل افتراضي ، لذلك يمكنك تحديد هذا فقط إذا كنت تريد أن يكون هذا الشعار متاحًا لجميع المستخدمين.' - services: خدمات المؤسسة + pdf_logo_option_help: 'ملاحظة: شعارات الهيئة الخاصة بالمستخدم متاحة لهم بشكل افتراضي ، لذلك يمكنك تحديد هذا فقط إذا كنت تريد أن يكون هذا الشعار متاحًا لجميع المستخدمين.' + services: خدمات الهيئة terms_of_use: شروط الاستخدام terms_of_use_help: يسمح فقط بملفات PDF terms_of_use_download_button: تحميل PDF terms_of_use_enabled: عرض شروط الاستخدام؟ approvals: + no_requests: لا توجد طلبات موافقة لهذه الحالة approved_by: تمت الموافقة عليه من قبل case_plan_type_label: نوع خطة الحالة manager_comments_label: تعليقات المدير @@ -109,11 +110,11 @@ ar: bulk_export: file_name: ملف record_type: نوع - retry: هذا النقل غير صحيح. أرجو حاول إعادة عمل عملية النقل الخاصة بك. + retry: هذا النقل غير صحيح. رجاء حاول إعادة عملية النقل الخاصة بك. started_on: 'بدء ' status: 'وضع الحالة ' form_export: - label: تصدير نموذج التكوين + label: تصدير نموذج الإعدادات include_hidden: تضمين النماذج والحقول المخفية؟ file_name: قم بإنشاء اسم الملف الخاص بك (اختياري) success_message: تم إنشاء ملف التصدير بنجاح @@ -125,13 +126,13 @@ ar: apply: تطبيق approvals: المصادقات approve_action_plan: موافقة خطة العمل - approve_bia: المصادقة على BIA - approve_case_plan: المصادقة على خطة الحالة + approve_bia: الموافقة على المصلحة الفضلى + approve_case_plan: الموافقة على خطة الحالة approve_closure: الموافقة على الإغلاق approve_gbv_closure: الموافقة على اغلاق العنف القائم على نوع الجنس back: السابق - bundle_export: حزمة التكوين - bundle_import: حزمة التكوين + bundle_export: حزمة الإعدادات + bundle_import: حزمة الإعدادات cancel: إلغاء change_password: تغيير كلمة المرور check_status: تحقق من حالة @@ -141,17 +142,17 @@ ar: close: اغلاق continue: استمر create_case: إنشاء حالة - create_incident: إنشاء حادثة جديدة + create_incident: 'إنشاء حادثة ' create_new_record: إنشاء %{model} جديد delete: حذف disable: إيقاف - disable_photo_wall: تعطيل photo wall + disable_photo_wall: تعطيل عرض الصور done: تم download: تحميل edit: تعديل edit_subform: تعديل النموذج الفرعي enable: تشغيل - enable_photo_wall: تفعيل photo wall + enable_photo_wall: تفعيل عرض الصور export: تصدير ملف filter: تطبيق عامل التصفية filter_clear: مسح عوامل التصفية @@ -166,6 +167,7 @@ ar: import: استيراد login: تسجيل الدخول logout: تسجيل خروج + link: رابط mark_for_mobile: وضع علامة للمحمول new: 'جديدة ' ok: موافق @@ -176,7 +178,7 @@ ar: reject: رفض remove_referrals: إلغاء الإحالات reorder: اعادة ترتيب - request_approval: طلب المصادقة + request_approval: طلب الموافقة request_transfer: طلب نقل reunite: إعادة لمّ الشمل save: حفظ @@ -198,6 +200,8 @@ ar: view: عرض view_flags_history: عرض التاريخ return_to_case: العودة إلى الحالة + enable_webpush: إشعارات الجهاز + dialog_yes: "نعم" resync_records: id: رقم الحالة في النظام record_type: نوع السجل @@ -210,7 +214,10 @@ ar: case: label: حالة create_new_case: انشاء حالة جديدة + create_case: إنشاء حالة + create: إنشاء add_new: أضف جديد + back_to_family_details: العودة إلى تفاصيل العائلة back_to_case: العودة إلى الحالة back_to_results: العودة إلى النتائج back_to_search: العودة الى البحث @@ -220,7 +227,7 @@ ar: details: تفاصيل select: اختيار deselect: ازالة الاختيار - enter_id_number: قم بإدخال رقم الهوية الشخصية/الوثيقة التعريفية لسجل موجود + enter_id_number: قم بإدخال رقم الهوية الشخصية/رقم المنهل id_search_no_results: لا يوجد متشابه في النظام ل "%{id}"، يُرجى عمل سجل جديد. messages: disabled: تم تعطيل الحالة @@ -233,19 +240,28 @@ ar: not_found_case: لم يتم العثور على حالة تطابق "%{search_value}" إنشاء حالة جديدة introductory_sentence: يرجى تحديد موافقة الفرد على تلقي خدمات إدارة الحالة وتخزين بياناته في Primero. consent_agreements_required: الرجاء تحديد خيار واحد على الأقل من اتفاقيات الموافقة. - legitimate_basis_required: الرجاء تحديد خيار واحد على الأقل من تصنيفات الأساس المشروعة. + legitimate_basis_required: الرجاء تحديد خيار واحد على الأقل من التصنيفات الأساسية القانونية. + confirm_create_case: هل تريد انشاء حالة لهذا الفرد؟ + case_referral_pending: إحالة الحالة في انتظار المراجعة. + case_transfer_pending: نقل الحالة في انتظار المراجعة. + case_no_approval_request: لا توجد طلبات موافقة لهذه الحالة. + bulk_assign_limit: لا يمكنك تعيين أكثر من 100 حالة في وقت واحد. + bulk_assign_limit_try_again: لا يمكنك تعيين أكثر من 100 حالة في وقت واحد. يرجى تحديد 100 حالة أو أقل ثم حاول مرة أخرى + referral_rejected: تم رفض الإحالة. + transfer_request_made: تم تقديم طلب نقل لهذه الحالة. save: حفظ الحالة save_text: قبل المتابعة يرجى حفظ التغييرات التي أجريت على الحالة skip_and_create: تخطي وإنشاء حالة جديدة search_existing: بحث في الحالات الموجودة search_helper_text: لماذا ا؟ لمنع إنشاء حالات مكررة. consent_agreements: حدد جميع اتفاقيات الموافقة التي تنطبق - legitimate_basis: حدد كل تصنيفات الأساس الشرعي التي تنطبق + legitimate_basis: حدد كل التصنيفات الأساسية القانونية التي تنطبق + family_linked_subform_delete_disabled: يرتبط إدخال النموذج الفرعي هذا بسجل العائلة. يرجى إما إزالة عضو العائلة هذا من سجل العائلة، أو إلغاء ربط حالة فرد العائلة من سجل العائلة. workflow: assessment: التقييم case_plan: خطة الحالة closed: مغلقة - created_on: تم تسجيل حالة جديدة في + created_on: تم تسجيل في in_progress: جاري new: 'جديدة ' on_label: 'في' @@ -260,9 +276,10 @@ ar: rejected_transfer: '%{to} رفض نقل %{record_type} %{record_id} من %{from}' cases: action_plan: خطة العمل + access_denied: "ليس لديك حق الوصول إلى هذه الحالة." age: العمر age_estimated: ما هو العمر المقدّر؟ - agency: وكالة + agency: الهيئة apply_filter: تطبيق approval_comments: تعليقات approval_radio: أودّ أن @@ -278,7 +295,7 @@ ar: assessment: التقييم case_opening_date: تاريخ فتح الحالة case_plan: خطة الحالة - case_worker_code: رمز الإختصاصي الإجتماعي + case_worker_code: كود اخصائي الحالة clear_filter: مسح close_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحالة مغلقًا close_dialog_title: اغلاق الحالة @@ -305,13 +322,13 @@ ar: age_18_more: 18+ age_6_11: 6 - 11 age_range: الفئة العمرية - agency: وكالة + agency: الهيئة approval_status: وضع الموافقات approvals: approved: تم الموافقة عليه pending: معلّقة rejected: رُفض - bia: BIA + bia: المصلحة الفضلى by_date: حسب التاريخ case_open_date: تاريخ فتح الحالة case_plan: خطة الحالة @@ -320,7 +337,7 @@ ar: current_location: الموقع الحالي date: تاريخ displacement_status: وضع النزوح - district: قضاء + district: الحي duplicate: كرّر enabled_disabled: 'مُفعلة/مُعطلة ' female: أنثى @@ -340,20 +357,21 @@ ar: other: أخرى photo: صورة photo_label: هل توجد صورة؟ - protection_concerns: مخاوف تتعلّق بالحماية (المشاكل/الحماية) + protection_concerns: مخاوف تتعلّق بالحماية protection_status: وضع الحماية record_state: حالة السجل referred_cases: الحالات التي تم إحالتها الي registration_date: تاريخ التسجيل risk_level: مستوى الخطورة sex: الجنس - social_worker: حقل/حالة/اختصاصي إجتماعي + social_worker: حقل/حالة/اخصائي حالة status: وضع transferred: تم النقل type_of_risk: نوع المخاطر urgent_protection_concern: مخاوف عاجلة بشأن الحماية user_group: مجموعة المستخدم workflow: الحالات حسب سريان العمل + include_disabled: اضف الحالات التي تم الغائها flag_summary: ملخص العلامة full_name: الاسم الكامل gbv_closure: اغلاق العنف القائم على النوع الإجتماعي @@ -372,11 +390,13 @@ ar: most_recently: الأحدث name: الاسم owned_by: مالك السجلّ - owned_by_agency: وكالة مالك السجلّ + owned_by_agency: الهيئة مالكة السجلّ photo: صورة فوتوغرافية photos: صورة quick_view: - tracing_message: 'ملاحظة: توجد نتائج مطابقة في النظام لما يبحث عنه المستعلم من أجل هذا الطفل. اتصل بالاخصائي الاجتماعي المعني بهذا السجل لاتخاذ خطوات إضافية إذا رغب الطفل.' + tracing_message: 'ملاحظة: توجد نتائج مطابقة في النظام لما يبحث عنه المستعلم من أجل هذا الطفل. اتصل باخصائي الحالة المعني بهذا السجل لاتخاذ خطوات إضافية إذا رغب الطفل.' + reassign: + multiple_successfully: Primero يقوم بإعادة تحديث % {select _ records} الحالة (s). قد يستغرق تحديث كل هذه الحالات عدة دقائق. referral_done: يشير النقر على "اكمل" إلى استكمال الإحالة المرتبطة بهذه الحالة. ما إن تنقر على "اكمل" لن تتمكّن من الاطلاع مجدّدًا على هذا السجل. referral_done_success: تمّت الإحالة referral_accepted_header: قبول الإحالة @@ -414,9 +434,10 @@ ar: save_filter: حفّظ selected_all_records: اختيار كلّ %{total_records}الحالات التي تطابق هذا الاستعلام. selected_records: '%{select_records} حالة (حالات) مختارة' + selected_records_assign: ' %{select_records} حالة (حالات) مختارة' sex: الجنس show_case: 'معرّف الحالة: %{short_id}' - social_worker: الاخصائي الاجتماعي + social_worker: اخصائي الحالة status: الوضع summary: label: ملخص @@ -441,7 +462,7 @@ ar: label: راجع سريّة البيانات child_wishes_link: label: راجع رغبات الطفل - survivor_code: رمز الناجية + survivor_code: كود الناجية transfer_accepted: بالنقر على "موافقة" فإنك توافق على تحمّل مسؤولية هذه الحالة؛ وبمجرد النقر على "موافقة" ستصبح أنت مالك السجل في النظام. transfer_managed_user_accepted: إذا قمت بالنقر فوق "قبول" ،%{transitioned_to} ستصبح مسؤولاً عن هذه الحالة ؛ بمجرد النقر فوق "قبول" ، %{transitioned_to} ستصبح مالك السجل في النظام. transfer_managed_user_rejected: 'بالنقر فوق "رفض" ، فإنك تشير إلى أنك %{transitioned_to} غير مستعد لقبول المسؤولية عن هذه الحالة في الوقت الحالي. الرجاء إدخال سبب رفضك لهذه الحالة ؛ بمجرد النقر فوق "رفض" %{transitioned_to} لن تتمكن من الوصول إلى سجل هذه الحالة ' @@ -474,12 +495,16 @@ ar: date_case_plan_initiated: تاريخ خطة الحالة date_of_creation: تاريخ الإنشاء registration_date: تارخ التسجيل + followup_date: تاريخ المتابعة + date_reunification: تاريخ لم الشمل + tracing_date: تاريخ التتبع + service_implemented_day_time: تاريخ انتهاء الخدمة configurations: - apply_label: هل أنت متأكد؟ إذا قمت بتطبيق الإعدادات الموجودة في هذا التضبيط، ستُطبّق على النظام. ستفقدكلّ إعداداتك الحالية ولن تتمكن من استعادتها ما لم تكن قد حفظتها سابقًا في تضبيط آخر. + apply_label: هل أنت متأكد؟ إذا قمت بتطبيق الإعدادات الموجودة في هذا الإعدادات، ستُطبّق على النظام. ستفقدكلّ إعداداتك الحالية ولن تتمكن من استعادتها ما لم تكن قد حفظتها سابقًا في إعداد آخر. apply_label_bold: لن يكون بريميرو Primero متاحًا للمستخدمين لبضع دقائق أثناء تحميل التغييرات. - version_mismatch_tooltip: لا يمكنك تطبيق هذا التكوين ، لأنه تم إنشاؤه باستخدام إصدار أعلى من Primero من الإصدار الذي يعمل به موقعك. يرجى الانتظار لتطبيق هذا التكوين حتى تقوم بتشغيل أحدث إصدار من Primero. + version_mismatch_tooltip: لا يمكنك تطبيق هذا الإعدادات ، لأنه تم إنشاؤه باستخدام إصدار أعلى من Primero من الإصدار الذي يعمل به موقعك. يرجى الانتظار لتطبيق هذا الإعدادات حتى تقوم بتشغيل أحدث إصدار من Primero. send_header: أرسل إلى الإنتاج - send_text: هل أنت متأكد؟ إذا نقرت على أرسل، سوف ترسل هذا التضبيط إلى موقع الإنتاج الخاص بك. لن يتم تطبيق هذا التضبيط على الإنتاج حتى يقوم مسؤول في هذا الموقع بتطبيقه يدويًا. + send_text: هل أنت متأكد؟ إذا نقرت على أرسل، سوف ترسل هذا الإعدادات إلى موقع الإنتاج الخاص بك. لن يتم تطبيق هذا الإعدادات على الإنتاج حتى يقوم مسؤول في هذا الموقع بتطبيقه يدويًا. attributes: created_by: تمّ الإنشاء من قِبَل date_created: تاريخ الإنشاء @@ -487,20 +512,20 @@ ar: last_applied_by: تمّ التطبيق الأخير من قِبَل last_applied_on: تمّ التطبيق الأخير في name: الإسم - version: إصدار التكوين + version: إصدار الإعدادات primero_version: نسخة "Primero" - delete_label: هل انت متأكد من أنك تريد أن تفعل هذا؟ يمثل هذا الأمر جميع الإعدادات منذ إنشاء هذا التضبيط. لن تتمكن من العودة واستعادة هذه الإعدادات بمجرد حذف هذا التضبيط. - explanation: 'سيؤدي النقر على "حفظ" إلى إنشاء سجل بجميع إعدادات التضبيط الحالية (على سبيل المثال: الأدوار والوكالات والنماذج) في هذه المرحلة الزمنية. بعد الحفظ، يمكنك تكرار هذه التغييرات في فقرة أخرى من بريميرو Primero. إذا أجريت، في المستقبل، تغييرات على التضبيط وتريد التراجع عنها، يمكنك تطبيق سجل التضبيط هذا لاسترجاع جميع تغييرات التضبيط التي أجريتها في هذا الوقت.' - label: تضبيطات - label_new: تضبيط جديد + delete_label: هل انت متأكد من أنك تريد أن تفعل هذا؟ يمثل هذا الأمر جميع الإعدادات منذ إنشاء هذا الإعدادات. لن تتمكن من العودة واستعادة هذه الإعدادات بمجرد حذف هذا الإعدادات. + explanation: 'سيؤدي النقر على "حفظ" إلى إنشاء سجل بجميع إعدادات الإعدادات الحالية (على سبيل المثال: الأدوار والهيئات والنماذج) في هذه المرحلة الزمنية. بعد الحفظ، يمكنك تكرار هذه التغييرات في فقرة أخرى من بريميرو Primero. إذا أجريت، في المستقبل، تغييرات على الإعدادات وتريد التراجع عنها، يمكنك تطبيق سجل الإعدادات هذا لاسترجاع جميع تغييرات الإعدادات التي أجريتها في هذا الوقت.' + label: إعدادات + label_new: إعداد جديد messages: - applied: تمّ تطبيق التضبيط بنجاح. - created: تمّ إنشاء التضبيط بنجاح. - deleted: تمّ حذف التضبيط بنجاح. - updated: تمّ تحديث التضبيط بنجاح. - sent: إرسال التكوين إلى الإنتاج. يرجى التحقق من موقع الإنتاج لمعرفة ما إذا كان التكوين الخاص بك قد وصل. + applied: تمّ تطبيق الإعدادات بنجاح. + created: تمّ إنشاء الإعدادات بنجاح. + deleted: تمّ حذف الإعدادات بنجاح. + updated: تمّ تحديث الإعدادات بنجاح. + sent: إرسال الإعدادات إلى الإنتاج. يرجى التحقق من موقع الإنتاج لمعرفة ما إذا كان الإعدادات الخاص بك قد وصل. not_allowed: غير مسموح - unavailable_server: الخادم غير متاح مؤقتًا. + unavailable_server: السرفر غير متاح مؤقتًا. contact: field: email: البريد الإلكتروني @@ -569,14 +594,14 @@ ar: case_stat_by_assessment_level: تصنيف الحالات بحسب مستوى التقييم case_stat_referrals: الإحالات case_stats: الحالات - case_worker: 'باحث اجتماعي:' - cases_by_social_worker: الحالات حسب الاخصائي الاجتماعي + case_worker: اخصائي حالة + cases_by_social_worker: الحالات حسب اخصائي الحالة cases_by_task_overdue: المهام المتأخرة cases_by_workflow: الحالات حسب سريان العمل cases_this_week: الحالات هذا الأسبوع cases_to_assign: الحالات منتظرة التعيين closed: مغلقة - closed_last_week: أُغلقت (الأسبوع المنصرم) + closed_last_week: أُغلقت (الأسبوع الماضي) closed_this_week: أُغلقت (هذا الاسبوع) comprehensive_need_intervention: تدخل شامل count_new_bia_approvals: @@ -585,7 +610,7 @@ ar: two: '%{stat}الجدي%{stat_type}الموافقات' few: '%{stat}الجدي%{stat_type}الموافقات' many: '%{stat}الجدي%{stat_type}الموافقات' - other: '%{stat}الجدي%{stat_type}الموافقات' + other: '%{stat}الجديدة%{stat_type}الموافقات' count_new_case_plan_approvals: zero: '%{stat} موافقات %{stat_type} جديدة' one: '%{stat}موافقة %{stat_type}جديدة' @@ -679,7 +704,7 @@ ar: dash_shared_with_my_team: تمّ تشاركها مع فريقي dash_shared_with_my_team_overview: تم مشاركته مع فريقي (نظرة عامة) dash_shared_with_others: تمّ تشاركها مع آخرين - dash_national_admin_summary: ملخص المسؤول + dash_national_admin_summary: ملخص المدير dash_violations_category_verification_status: إجمالي عدد الحوادث لكل حالة تحقق dash_violations_category_region: إجمالي عدد الحوادث التي تم التحقق منها لكل منطقة dash_perpetrator_armed_force_group_party_names: إجمالي عدد الحوادث لكل مرتكب @@ -732,22 +757,22 @@ ar: match_result: نتائج متشابهة medium_level: متوسط medium_risk: أولوية متوسطة - missed_cases: الحالات الفائتة + missed_cases: الحالات المفقودة name: الاسم - name_or_survivor_code: اسم الناجي أو رمزه + name_or_survivor_code: اسم الناجي أو كوده near_deadline: 'قاربت على تاريخ الانتهاء ' new: جديد ومحدث new_child_assigned_to_you: حالات جديدة تم تعيينها لك new_incident: حالات جديدة new_incident_assigned_to_you: حوادث جديدة تم تعيينها لك - new_last_week: جديد (الاسبوع المنصرم) + new_last_week: جديد (الاسبوع الماضي) new_or_updated: جديد أو مُحدث new_referred: إحالات جديدة new_service_provision: تقديم خدمة جديدة new_this_week: جديد(هذا الاسبوع) no_action_risk: لا يوجد إجراء no_case_stats: لا يوجد إحصائيات حالة - no_caseworker_data: ' بيانات الباحث الاجتماعي غير موجودة:' + no_caseworker_data: ' بيانات الباحث الاجتماعي غير موجودة' no_flagged_child: لا يوجد حالات مميزة بعلامة no_flagged_incident: لا يوجد حوادث مميزة بعلامة no_open_incidents: لا يوجد حوادث مفتوحة @@ -770,8 +795,8 @@ ar: pending: قيد الانتظار pending_approvals: الموافقات المعلّقة pending_transfers: عمليات النقل المُعلّقة - protection_concern: شؤون تنتهك الحماية - protection_concerns: شؤون تنتهك الحماية (المشاكل/الحماية) + protection_concern: شواغل الحماية + protection_concerns: مخاوف تتعلق بالحماية range12+: '+12' range4: 0-4 range4_8: 4-8 @@ -779,7 +804,7 @@ ar: recent_activities: أنشطة حديثة recently_flagged_child: حالات تم تمميزها بعلامة مؤخرا recently_flagged_incident: حوادث مميزة بعلامة مؤخرًا - referrals_by_social_worker: الإحالات بواسطة الاخصائي الاجتماعي + referrals_by_social_worker: الإحالات بواسطة اخصائي الحالة registration: التسجيل rejected: رُفض rejected_transfers: عمليات النقل المرفوضة @@ -808,7 +833,7 @@ ar: total_referred: مجموع الإحالات tr_stats: تتبع الطلبات transers_awaiting_acceptance: عمليات النقل بانتظار القبول - transfers_by_social_worker: التحويلات/النقل حسب الاخصائي الاجتماعي + transfers_by_social_worker: التحويلات/النقل حسب اخصائي الحالة users: أيقونة الإعدادات violence_type: نوع العنف with_incidents: مع حوادث @@ -839,22 +864,47 @@ ar: assign: 'المستخدم %{user} قد عيّن السجل التالي %{record_type} لك: %{record_id}' assign_subject: '%{record_type}: %{id} - مُعيّن لك' approval_request: 'المستخدم %{user} يطلب موافقة من نوع%{approval_type} بخصوص الحالة %{case_id}' - approval_request_subject: 'حالة: %{id} طلب المصادقة' + approval_request_subject: 'حالة: %{id} طلب الموافقة' approval_response: '%{user} لديه %{status} طلب الموافقة من نوع %{approval_type} للحالة %{case_id}.' - approval_response_subject: 'حالة: %{id} الإجابة على طلب المصادقة' - referral: 'المستخدم %{user} من مؤسسة %{agency} قد أحال نوع السجل التالي %{record_type} إليك: رقم السجل %{record_id} لنوع الخدمة %{service_type}' + approval_response_subject: 'حالة: %{id} الإجابة على طلب الموافقة' + referral: 'المستخدم %{user} من الهيئة %{agency} قد أحال نوع السجل التالي %{record_type} إليك: رقم السجل %{record_id} لنوع الخدمة %{service_type}' transfer: 'المستخدم %{user} قد حوّل السجل التالي %{record_type}لك: %{record_id}' transfer_request_subject: طلب تحويل لحالة من حالاتك transfer_subject: '%{record_type}: %{id} - التحويل' referral_subject: '%{record_type}: %{id}- الإحالة' - transfer_request: 'مستخدم بريميرو %{user} من مؤسسة %{agency} يطلب أن تنقل ملكية هذا السجل من نوع %{record_type} ومعرّف %{record_id} بحيث يتمكنون من تقديم خدمات إدارة للشخص في منطقتهم. إذا كان التحويل مقبولا من طرفك، يرجى النقر على رابط معرف نوع السجل %{record_type} في هذا الايميل لفتح نوع السجل %{record_type} في بريميرو والبدء بعملية التحويل.' + transfer_request: 'مستخدم بريميرو %{user} من الهيئة %{agency} يطلب أن تنقل ملكية هذا السجل من نوع %{record_type} ومعرّف %{record_id} بحيث يتمكنون من تقديم خدمات إدارة للشخص في منطقتهم. إذا كان التحويل مقبولا من طرفك، يرجى النقر على رابط معرف نوع السجل %{record_type} في هذا الايميل لفتح نوع السجل %{record_type} في بريميرو والبدء بعملية التحويل.' approval_request_html: 'المستخدم %{user} يطلب موافقة من نوع %{approval_type} بخصوص الحالة %{case_id} .' approval_response_html: 'المستخدم %{user} لديه %{status} طلب الموافقة من نوع %{approval_type} للحالة %{case_id} .' - referral_html: 'المستخدم %{user} من مؤسسة %{agency} قد أحال نوع السجل التالي %{record_type} إليك: رقم السجل %{record_id} لنوع الخدمة %{service_type}' + referral_html: 'المستخدم %{user} من الهيئة %{agency} قد أحال نوع السجل التالي %{record_type} إليك: رقم السجل %{record_id} لنوع الخدمة %{service_type}' transfer_html: 'المستخدم %{user} قد حوّل السجل التالي %{record_type}لك: %{record_id}.' assign_html: '%{user} عيّن السجلّ التالي %{record_type} لك: %{record_id}.' - transfer_request_html: 'مستخدم بريميرو %{user} من مؤسسة %{agency} يطلب أن تنقل ملكية هذا السجل من نوع %{record_type} ومعرّف %{record_id} بحيث يتمكنون من تقديم خدمات إدارة للشخص في منطقتهم. إذا كان التحويل مقبولا من طرفك، يرجى النقر على رابط معرف نوع السجل %{record_type} في هذا الايميل لفتح نوع السجل %{record_type} في بريميرو والبدء بعملية التحويل.' + transfer_request_html: 'مستخدم بريميرو %{user} من الهيئة %{agency} يطلب أن تنقل ملكية هذا السجل من نوع %{record_type} ومعرّف %{record_id} بحيث يتمكنون من تقديم خدمات إدارة للشخص في منطقتهم. إذا كان التحويل مقبولا من طرفك، يرجى النقر على رابط معرف نوع السجل %{record_type} في هذا الايميل لفتح نوع السجل %{record_type} في بريميرو والبدء بعملية التحويل.' transfer_request_notes_html: 'ملاحظات من الشخص مقدم الطلب: %{request_transfer_notes}' + alert: 'تم تحديث% {record _ type}% {id} -% {form _ name}. يرجى تسجيل الدخول إلى Primero لمراجعة التغييرات.' + alert_subject: '% {سجل _ نوع}:% {معرف} -% {شكل _ اسم} محدث' + webpush_notification: + action_label: الذهاب الى الحالة + approval_request: + title: طلب الموافقة + body: ' طلب موافقة معلق لـلحالة% {نوع}.' + approval_response: + title: الرد بالموافقة + body: لقد تلقت إحدى حالاتك ردًا بالموافقة. + assign: + title: تكليف جديد + body: لقد تلقيت تكليف بحالة جديدة + referral: + title: إحالة جديدة + body: لقد تلقيت إحالة لحالة جديدة + transfer: + title: تحويل جديد + body: لقد تلقيت طلب تحويل لحالة جديدة + alert_case: + title: الحالة محدثة + body: "تم تحديث% {نوع} في إحدى حالاتك." + transfer_request: + title: طلب تحويل + body: لقد تلقيت طلب تحويل لحالة جديدة encrypt: export_type: نوع التصدير file_name: قم بإنشاء اسم الملف الخاص بك (اختياري) @@ -864,6 +914,8 @@ ar: address_fields: يجب عليك معالجة الحقول %{fields} في النماذج %{forms} address_form_fields: يجب عليك معالجة الحقول %{fields} في هذا النموذج address_subform_fields: 'النموذج الفرعي %{subform} يحتوي على عدد %{fields} من الحقول غير الصالحة' + error_401: لقد قمت بتسجيل الخروج. الرجاء تسجيل الدخول مجددا + error_something_went_wrong: حدث خطأ ما error_page: not_authorized: server_error: أنت غير مخوّل لدخول هذه الصفحة. @@ -872,6 +924,10 @@ ar: contact_admin: إذا كنت تعتقد إنك جئت إلى هنا بالخطأ يرجى الاتصال بالمشرف. something_went_wrong: نأسف, يوجد خطأ. errors: + api: + internal_server: خطأ في السيرفر + attachments: + maximum: لقد تخطيت عدد الملفات المسموح به في السجل error_loading: خطأ في تحميل السجل (السجلات) models: agency: @@ -891,7 +947,7 @@ ar: admin_level_present: لا يجب أن يكون فارغا code_present: لا يجب أن يكون فارغًا name_present: لا يجب أن يكون فارغًا - unique_location_code: يوجد موقع له نفس الرمز بالفعل، يرجى إدخال رمز مختلف + unique_location_code: يوجد موقع له نفس الكود بالفعل، يرجى إدخال كود مختلف lookup: being_used: هذا البحث مستخدم ولا يمكن حذفه name_present: لا يجب أن يكون الاسم فارغاً @@ -916,6 +972,11 @@ ar: title_present: يجب ألا يكون العنوان فارغًا content_present: يجب ألا يكون المحتوى فارغًا created_by_present: يجب ألا يكون حقل الإنشاء بواسطة فارغًا + webpush_subscription: + notification_url_present: notification_url يجب ألا تكون فارغ + notification_url_format: يجب تنسيق عنوان URL لnotification_url + auth_present: يجب ألا يكون Auth فارغًا + p256dh_present: p256dh يجب ألا تكون فارغة not_found: لم يتمّ العثور على أي سجل (سجلات) try_again: حاول مجدّدًا exports: @@ -950,7 +1011,7 @@ ar: signatures: تضمين أسطر التوقيع لـ include_implementation_logos: هل تريد تضمين شعارات التنفيذ؟ include_implementation_logos_help_text: سيشمل ذلك الشعارات التي تظهر في قائمة التنقل وعلى صفحة تسجيل الدخول. - include_agency_logo: هل تريد تضمين شعار الوكالة؟ + include_agency_logo: هل تريد تضمين شعار الهيئة؟ include_other_logos: هل تريد تضمين شعارات أخرى؟ duplicate_id_csv: all: معرف مكرر @@ -964,7 +1025,7 @@ ar: national_id_no: رقم الهوية الوطنية progress_id: معرف التقدم sex_mapping_m_f_u: 'الجنس ' - other_agency_id: رمز المستشفى ورقم المريض + other_agency_id: كود المستشفى ورقم المريض male_abbreviation: ذكر unknown_abbreviation: U exported: تمّ إنشاء ملف التصدير بنجاح @@ -993,12 +1054,13 @@ ar: option_name: اسم الخيار options: location: المواقع - agency: الوكالات + agency: الهيئات user: المستخدمون reportinglocation: مواقع الإبلاغ subforms: 'النموذج الفرعي: %{subform_name}' collapsed_fields: 'الحقول الهابطة: %{fields}' country: بلاد + linkedincidents: ربط الحوادث summary_header: form_group: مجموعة نموذج بريميرو form: نماذج بريميرو @@ -1030,13 +1092,13 @@ ar: pdf_exports: label: PDF recipient: المستلِم - case_worker: الإختصاصي الإجتماعي + case_worker: اخصائي الحالة client: العميل date: التاريخ recipient_name: اسم المستلِم - recipient_agency: وكالة المستلِم - caseworker_name: اسم الإختصاصي الإجتماعي - caseworker_agency: وكالة الإختصاصي الإجتماعي + recipient_agency: الهيئة المستلِمة + caseworker_name: اسم اخصائي الحالة + caseworker_agency: هيئة اخصائي الحالة photowall: all: Photo Wall flag_suspect_record: مميّز بعلامة كسجلّ المشتبه به @@ -1044,7 +1106,7 @@ ar: one: Photo Wall reunited: إعادة لمّ الشمل selected: تحديد إلى Photo Wall - success_message: إنشاء جدار الصور الفوتوغرافية%{file_name} لن يتم تضمين الحالات التي لا تحتوي على صور. + success_message: إنشاء جدار Photo wall%{file_name} لن يتم تضمين الحالات التي لا تحتوي على صور. printed: 'تمّت الطباعة %{date}' queueing: جاري إنشاء ملف التصدير %{file_name} selected_xls: @@ -1060,7 +1122,7 @@ ar: case_status: 'وضع الحالة ' causes_of_separation: سبب الانفصال country_of_origin: البلد الأصلي - cpims_code: رمز نظام المعلومات الخاص بحماية الطفل + cpims_code: كود نظام المعلومات الخاص بحماية الطفل current_care_arrangement: ترتيبات الرعاية الحالية date_of_birth: 'تاريخ الميلاد ' date_of_identification: تاريخ التحديد @@ -1080,8 +1142,8 @@ ar: sex: 'الجنس ' sex_mapping_m_f_u: 'الجنس ' short_id: هوية شخصية قصيرة - vulnerability_code: 'رموز الضعف ' - vulnerability_details_code: 'رموز تفاصيل الضعف ' + vulnerability_code: 'كود الضعف ' + vulnerability_details_code: 'كود تفاصيل الضعف ' male_abbreviation: ذكر one: المفوضية السامية للأمم المتحدة لشؤون اللاجئين UNHCR selected: تحديد إلى المفوضية السامية للأمم المتحدة لشؤون اللاجئين UNHCR @@ -1124,11 +1186,13 @@ ar: add_existing_field: إضافة حقل موجود add_field: إضافة حقل add_field_type: إضافة%{file_type} + attachments: + maximum_attached: تخطيت الحد الأقصى للمرفقات لكل سجل (% {maximumtachmentsPerRecord}) . يتضمن ذلك الصور والصوت والمستندات. الرجاء إزالة ملف قبل إضافة آخر. audio: current: التسجيل الصوتي الحالي audio_upload_box: تحميل التسجيل الصوتي - bia_document: مستند BIA - bid_document: مستند BID + bia_document: مستند المصلحة الفضلى + bid_document: مستند المصلحة الفضلى check_box: خانات اختيار clear_group_by: مسح المجموعة حسب clear_sort_by: مسح الترتيب حسب @@ -1331,13 +1395,15 @@ ar: record_information: معلومات السجلّ referrals: الإحالات reportable_follow_up: متابعة - reportable_protection_concern: امر مقلق خاص بالحماية + reportable_protection_concern: مخاوف تتعلق بالحماية reportable_service: خدمة tracing_request: طلب التتبع transfers_assignments: عمليات النقل والتعيينات violation: انتهاك registry_details: تفاصيل التسجيل registry_record: سجل التسجيل + family_record: سجل الأسرة + family: سجل الأسرة required_field: '%{field} هو حقل مطلوب' select_label: اختيار settings: إعدادات @@ -1374,7 +1440,7 @@ ar: types: and: display_text: بالاضافة الى هذا الشرط - name: و (بالاضافة الى) + name: 'و ' or: display_text: أو هذا الشرط name: أو @@ -1385,6 +1451,7 @@ ar: ar-LB: العربية (اللبنانية) ar-SD: العربية (السودانية) bn: বাংলা + cmn: اللغة الصينية current_time_zone: المنطقة الزمنية الحالية dashboard: لوحة المعلومات en: English @@ -1404,9 +1471,10 @@ ar: ne: النيبالية om: أورومو am-ET: الأمهرية (إثيوبيا) + tr: تركي label: الصفحة الرئيسية language: اللغة - manage_system_users: إدارة مستخدمي مزامنة الخادم + manage_system_users: إدارة مستخدمي مزامنة السيرفر my: ဗမာစာ pl: بولندي pt: Português @@ -1422,15 +1490,19 @@ ar: view_records: عرض السجلات welcome: مرحبا بكم في بريميرو zh: 中文 + tet: لغة التيتوم incident: - code: رمز الحادثة + code: كود الحادثة associated_case: "الحالة المرتبطة:" + link_incident_to_case: ربط الحادثة بحالة + link_incident_to_case_success: حادثة(حوداث) مرتبطة بحالة messages: creation_success: تم إنشاء سجل الحادثة بنجاح. creation_success_queue: تمّ إنشاء سجل الحادثة بنجاح في الخلفية disabled: تم تعطيل الحادثة update_success: 'تم تحديث الحادثة %{record_id} بنجاح.' update_success_queue: 'تم تحديث الحادثة %{record_id} بنجاح في الخلفية' + bulk_assign_limit_try_again: لا يمكنك تعيين أكثر من 100 حادثة في وقت واحد. يرجى تحديد 100 حادثة أو أقل ثم المحاولة مرة أخرى. violation: associated_violations: "المخالفات ذات الصلة:" update_and_return: 'تحديث والرجوع الى %{association}' @@ -1440,7 +1512,7 @@ ar: types: killing: قتل الاطفال maiming: تشويه الاطفال - recruitment: تجنيد(توظيف) و/او استخدام الاطفال + recruitment: تجنيد و/او استخدام الاطفال sexual_violence: الاغتصاب و / أو غيره من أشكال العنف الجنسي abduction: الخطف attack_on: الهجوم على المدرسة(المدارس) و/او المستشفى(المستشفيات) @@ -1449,6 +1521,7 @@ ar: military_use: الاستخدام العسكري للمدرسة(المدارس) و/او المستشفى(المستشفيات) denial_humanitarian_access: منع وصول الخدمات الإنسانية للأطفال incidents: + change_status: تغُير في الوضع disable_dialog: بالنقر على "تمّ" سيُصبح وضع هذه الحادثة معطّلًا. disable_dialog_title: تعطيل الحادثة disable_success: تمّ تعطيل الحادثة بنجاح @@ -1497,12 +1570,15 @@ ar: perpetrator_category: نوع المسيء record_owner: مالك السجل register_new_incident: حادثة جديدة + reassign: + multiple_successfully: Primero يقوم حاليا باعادة تخصيص الحوادث الخاص ب% {select _ records}. قد يستغرق تحديث كل هذه الحوادث عدة دقائق. لاحظ أن الحوادث المربوطة سابقاً لن يتم ربطها مجدداً. selectable_date_options: date_of_first_report: تاريخ المقابلة mrm_date_of_first_report: تاريخ التقرير الأولي لعضوCTFMR ctfmr_verified_date: تاريخ قرار التحقق من قبل CTFMR incident_date_derived: تاريخ الحادثة selected_records: 'سجل %{select_records} الحادثة (الحوادث) المختارة' + selected_records_assign: '% {حدد _ سجلات} حادثة (حوادث) مختارة. لاحظ أن الحوادث التي تم ربطها سابقاً لن يتم تحديدها.' selected_all_records: 'اختَر جميع الحوادث %{total_records} التي تطابق هذا الاستعلام.' summary_mrm: label: ملخص الحادث @@ -1524,9 +1600,10 @@ ar: label: حساب الحادثة incident_update: label: تحديث الحادثة - survivor_code: رمز الناجية + survivor_code: كود الناجية show_incident: 'مُعرِّف الحادثة %{short_id}' - social_worker: الإختصاصي الإجتماعي + social_worker: اخصائي الحالة + verify_mrm: تحقق من MRM violation_type: نوع الانتهاك violence_type: نوع العنف type_violence: نوع العنف @@ -1588,7 +1665,7 @@ ar: assessment_status: title: "4. وضع التقييم" completed: "مكتمل" - completed_supervisor_approved: "مكتمل وتمّت الموافقة على الناجية" + completed_supervisor_approved: "مكتمل وتمّت موافقة الحالات" helptext: | يحتسب هذا المؤشر نسبة الحالات النشطة التي استكمل نموذج تقييم بشأنها. يعتبر التقييم مكتملاً عندما يتمّ إكمال مجموعة من الحقول الإلزامية @@ -1607,9 +1684,9 @@ ar: label: "6. خطّة عمل حالة مكتملة" helptext: "يحتسب هذا المؤشر نسبة الحالات النشطة التي استكملت خطة عمل حالة بشأنها. \nتُعتبر خطة عمل حالة مكتملة عندما يتمّ إكمال مجموعة من الحقول الإلزامية\nفي نموذج خطّة العمل.\n" completed_supervisor_approved_case_action_plans: - title: "7. وافق المشرف على خطط عمل الحالة" - completed_and_approved: "تمّت الموافقة على خطط عمل الحالة المكتملة من قبل المشرف" - helptext: "يحتسب هذا المؤشر نسبة الحالات النشطة التي استكملت خطة عمل حالة بشأنها \nوالموافقة عليها من قبل المشرف. تعتبر خطة عمل حالة مكتملة \nعندما يتمّ إكمال مجموعة من الحقول الإلزامية في نموذج خطّة العمل. تعتبر خطة الحالة\nمعتمدة عندما يطلب الإختصاصي الإجتماعي الموافقة على خطة الحالة\nووافق المشرف على خطة الحالة على المنصة.\n" + title: "7. وافق مشرف الحالات على خطط عمل الحالة" + completed_and_approved: "تمّت الموافقة على خطط عمل الحالة المكتملة من قبل مشرف الحالات" + helptext: "يحتسب هذا المؤشر نسبة الحالات النشطة التي استكملت خطة عمل حالة بشأنها \nوالموافقة عليها من قبل مشرف الحالات. تعتبر خطة عمل حالة مكتملة \nعندما يتمّ إكمال مجموعة من الحقول الإلزامية في نموذج خطّة العمل. تعتبر خطة الحالة\nمعتمدة عندما يطلب اخصائي الحالة الموافقة على خطة الحالة\nووافق مشرف الحالات على خطة الحالة على المنصة.\n" services_provided: title: "8. الخدمات المقدَّمة" service: "الخدمة" @@ -1641,7 +1718,7 @@ ar: label: "متوسط اجتماعات المتابعة لكل حالة" helptext: | يحتسب هذا المؤشر متوسط عدد اجتماعات المتابعة التي أجريت لكلّ حالة نشطة - من قبل كلّ إختصاصي إجتماعي على المنصة. يتمّ اجتماع المتابعة بين الإختصاصي الإجتماعي والناجية + من قبل كلّ اخصائي الحالة على المنصة. يتمّ اجتماع المتابعة بين اخصائي الحالة والناجية بعد المقابلة الأوّليّة / الإفصاح الأولي. time_from_case_open_to_close: title: "11. الوقت المستغرق من فتح الحالة إلى اغلاقها" @@ -1660,22 +1737,22 @@ ar: يقيس هذا المؤشر النسبة المئوية للناجين الذين أكملوا استبيان آراء العملاء والذين يشعرون بالرضا عن خدمات إدارة الحالة المقدّمة لهم. يتمّ إحتساب هذا المؤشر من خلال استكمال نموذج استبيان آراء العميل على +GBVIMS من قبل موظف - مختلف عن الإختصاصي الإجتماعي الذي قدّم الخدمة للناجية. + مختلف عن اخصائي الحالة الذي قدّم الخدمة للناجية. supervisor_to_caseworker_ratio: - title: "14. عدد الإخصائيين الإجتماعيين لكل مشرف." - label: "عدد الإختصاصيين الإجتماعيين لكلّ مشرف" - helptext: "يعكس هذا المؤشر عدد الإختصاصيين الإجتماعيين الذين يشرف عليهم المشرف: ويُعرف بعدد الإختصاصيين الإجتماعيين لكلّ مشرف. \nيعتمد هذا الحساب على الأدوار المخصّصة من النظام على المنصّة.\n" + title: "14. عدد اخصائيين الحالة لكل مشرف." + label: "عدد اخصائيين الحالة لكلّ مشرف" + helptext: "يعكس هذا المؤشر عدد اخصائيين الحالة الذين يشرف عليهم مشرف الحالات: ويُعرف بعدد اخصائيين الحالة لكلّ مشرف. \nيعتمد هذا الحساب على الأدوار المخصّصة من النظام على المنصّة.\n" case_load: title: "15. عدد الحالات" case_load: "عدد الحالات" - percent: "النسبة المئوية للإختصاصيين الإجتماعيين العاملين على حالات" + percent: "النسبة المئوية لاخصائيين الحالة العاملين على حالات" 10cases: "أقل من 10 حالات" 20cases: "11 - 20 حالة" 21-30cases: "21 - 30 حالة" 30cases: "أكثر من 30 حالة" helptext: | - يقيس هذا المؤشر متوسط عدد الحالات لكلّ إختصاصي إجتماعي فاعل بناءً على الحالات النشطة. - يتمّ تقسيم نسبة الحالات إلى الإختصاصيين الإجتماعيين وفقًا للتقسيم التالي: + يقيس هذا المؤشر متوسط عدد الحالات لكلّ اخصائي الحالة فاعل بناءً على الحالات النشطة. + يتمّ تقسيم نسبة الحالات إلى اخصائيين الحالة وفقًا للتقسيم التالي: أقلّ من 10 حالات مفتوحة ، بين 10-20 حالة مفتوحة ، بين 21-30 حالة مفتوحة أكثر من 30 حالة مفتوحة. date_range_dialog: title: "نطاق تاريخ مُخصّص" @@ -1691,18 +1768,18 @@ ar: camp: مخيم chiefdom: مشيخة city: مدينة - community: مجتمع + community: مجتمع محلي country: دولة county: مقاطعة - district: قضاء - governorate: محافظة + district: الحي + governorate: إمارة locality: ناحية other: أشياء أخرى province: إقليم region: منطقة site: موقع state: ولاية - sub-district: قضاء فرعي + sub-district: حي فرعي village: قرية zone: منطقة association: منظمة @@ -1713,12 +1790,24 @@ ar: township: بلدة municipality: بلدية autonomous_region: منطقة الحكم الذاتي + parish: الرعية + cercle: الدائرة + sub-county: المناطق + departement_fr: 'المقاطعات' + region_fr: 'المنطقة' + wilaya: 'ولاية' + commune: 'البلدة' + division_fr: 'القسم' + prefecture: 'المقاطعات' + moughataa: 'مقطعة' + sub_division: 'القسم الفرعي' + sub-prefecture: 'المقاطعات الفرعية ' label: الموقع name: الإسم - code: 'الرمز ' + code: الكود admin_level: مستوى المسؤول type: النوع - hierarchy: التراتبية الهرمية + hierarchy: التسلسل الهرمي import_title: موقع الاستيراد message: يرجى تحديد ملف CSV للتحميل. يجب أن يستخدم هذا الملف ترميز UTF-8 وأن يتضمن علامات تصنيف HXL في الرأسيّة الثانية من كلّ عمود. no_location: يرجى استيراد المواقع قبل إنشاء أي حسابات مستخدمين. @@ -1741,15 +1830,15 @@ ar: case_plan_approved: تمت الموافقة على خطة الحالة case_plan_rejected: تم رفض خطة الحالة case_plan_requested: مطلوب خطة حالة - close: يغلق - create: يخلق + close: غلق + create: إنشاء create_bulk: إنشاء الجزء الأكبر delete: حذف destroy: هدم detach: فصل enable_disable_record: تمكين تعطيل السجل export: يصدر - flag: علم + flag: علامة import: يستورد incident_details_from_case: تفاصيل الحادث من القضية index: فهرس @@ -1757,15 +1846,15 @@ ar: login: تسجيل الدخول password_reset: إعادة تعيين كلمة المرور password_reset_request: طلب إعادة تعيين كلمة المرور - refer: أشير + refer: إحالة refer_accepted: تم قبول الإحالة - refer_done: تمت الإشارة + refer_done: تمت الإحالة refer_rejected: إحالة مرفوضة refer_revoke: إبطال الإحالة - refer_to: تشير إلى + refer_to: إحالة إلى reopen: أعد فتح services_section_from_case: قسم الخدمات من القضية - show: تبين + show: عرض show_alerts: عرض التنبيهات traces: آثار transfer: تحويل @@ -1773,13 +1862,13 @@ ar: transfer_rejected: تم رفض التحويل transfer_request: طلب تحويل transfer_to: حول إلى - unflag: غير متخلف + unflag: إزالة العلامة update: تحديث user_password_reset_request: طلب إعادة تعيين كلمة مرور المستخدم webhook: الويب هوك approve_form: action_plan: نموذج خطّة العمل - bia: نموذج BIA + bia: نموذج المصلحة الفضلى case_plan: نموذج خطة الحالة closure: نموذج إغلاق 'false': رفض @@ -1823,7 +1912,7 @@ ar: resources: audit_log: سجل التدقيق user: المستعمل - agency: وكالة + agency: الهيئة user_group: مجموعة المستخدمين child: طفل alert: يحذر @@ -1832,13 +1921,13 @@ ar: system_settings: اعدادات النظام permission: الإذن dashboard: لوحة القيادة - report: نقل + report: تقرير bulk_export: تصدير بالجملة saved_search: تم الحفظ role: دور incident: حادث location: موقع - primero_configuration: تكوين Primero + primero_configuration: إعدادات Primero code_of_conduct: مدونة قواعد السلوك task: مهمة record_state: @@ -1852,7 +1941,7 @@ ar: reopen_case: جاري إعادة الفتح request_approval: action_plan: طلب الموافقة على نموذج خطة العمل - bia: طلب مصادقة على نموذج BIA + bia: طلب مصادقة على نموذج المصلحة الفضلى case_plan: طلب مصادقة على نموذج خطة الحالة closure: طلب مصادقة على نموذج الإغلاق gbv_closure: طلب الموافقة على نموذج إغلاق العنف القائم على النوع الإجتماعي @@ -1912,15 +2001,44 @@ ar: date: التاريخ verification_status: وضع التحقق violation_type: نوع الانتهاك + status: الوضع + status_open: 'مفتوح ' + status_closed: مغلق + user_group: مجموعة مستخدمين + agency: الهيئة + by: بواسطة + workflow: حالة سير العمل + cp_incident_violence_type: نوع العنف + referral_transfer_status: وضع الإحالة / النقل + protection_concerns: مخاوف تتعلق بالحماية + location: مكان الإبلاغ + followup_type: نوع المتابعة + service_type: نوع الخدمة + status_options: + open: فتح + closed: غلق + by_options: + created_by_groups: مجموعات المستخدمين لمنشئ السجل + owned_by_groups: مجموعات المستخدمين لمنشئ السجل + created_organization: هيئة من أنشأ السجل + owned_by_agency_id: هيئة مالك السجل + referral_transfer_status_options: + in_progress: معلق + accepted: تمت الموافقة + rejected: رُفض + done: تم date_range: month: شهر quarter: ربع year: سنة + week: أسبوع date_range_options: this_quarter: الربع الحالي last_quarter: الربع الماضي this_month: الشهر الحالي last_month: الشهر الماضي + this_week: هذا الأسبوع + last_week: الاسبوع الماضي this_year: العام الحالي last_year: العام الماضي custom: مخصّص @@ -1936,6 +2054,49 @@ ar: individual_violation_type: الأطفال الفرديين حسب نوع الانتهاك individual_region: الأطفال الفرديين حسب المنطقة individual_perpetrator: عدد الاطفال حسب المسيئين + services: + name: الخدمات + description: الحالات التي تحتوي على أنواع الخدمة المحددة، مقسمة حسب العمر والجنس. + services_report: + reports: + services: خدمات + description: الحالات التي تحتوي على أنواع الخدمة المحددة، مقسمة حسب العمر والجنس. + sub_reports: + services: خدمات + filter_options: + service_implemented_day_time: خدمات اكتملت + followups: + name: المتابعات + description: الحالات مع أنواع المتابعة المحددة، مقسمة حسب العمر والجنس. + followups_report: + filter_options: + followup_date: تاريخ المتابعة + reports: + followups: المتابعات + description: الحالات مع أنواع المتابعة المحددة، مقسمة حسب العمر والجنس. + sub_reports: + followups: المتابعات + protection_concerns: + name: مخاوف تتعلق بالحماية + description: الحالات المتعلقة بمخاوف الحماية المحددة، مقسمة حسب العمر والجنس. + protection_concerns_report: + reports: + protection_concerns: مخاوف تتعلق بالحماية + description: الحالات المتعلقة بمخاوف الحماية المحددة، مقسمة حسب العمر والجنس. + sub_reports: + protection_concerns: مخاوف تتعلق بالحماية + filter_options: + registration_date: تاريخ التسجيل + reporting_locations: + name: مكان الإبلاغ + description: 'الحالات التي تم تحديد موقع الإبلاغ عنها، مقسمة حسب العمر والجنس.' + reporting_locations_report: + reports: + reporting_locations: مكان الإبلاغ + sub_reports: + reporting_location_by_sex_and_age: مكان الإبلاغ + filter_options: + registration_date: تاريخ التسجيل ghn_report: name: المذكرة الافقية الشاملة reports: @@ -1949,7 +2110,7 @@ ar: unverified_information_violations: معلومات لم يتم التحقق منها - الانتهاكات killing: قتل الاطفال maiming: تشويه الاطفال - recruitment: تجنيد(توظيف) و/او استخدام الاطفال + recruitment: تجنيد و/او استخدام الاطفال sexual_violence: الاغتصاب و / أو غيره من أشكال العنف الجنسي rape: الاغتصاب و / أو غيره من أشكال العنف الجنسي abduction: الخطف @@ -1974,7 +2135,7 @@ ar: reports: killing: قتل الاطفال maiming: تشويه الاطفال - recruitment: تجنيد(توظيف) و/او استخدام الاطفال + recruitment: تجنيد و/او استخدام الاطفال sexual_violence: الاغتصاب و / أو غيره من أشكال العنف الجنسي rape: الاغتصاب و / أو غيره من أشكال العنف الجنسي abduction: الخطف @@ -1991,9 +2152,9 @@ ar: detention_detained: البقاء محتجزا detention_released: الافراج perpetrators: عدد الاطفال حسب المسيئين - perpetrators_denial: عدد الاختراقات حسب المسيئين + perpetrators_denial: عدد الانتهاكات حسب المسيئين perpetrator_detention: عدد الاطفال حسب المسيئين - perpetrators_incidents: عدد الاطفال حسب المسيئين + perpetrators_incidents: عدد الحوادث حسب المسيئين reporting_location_incidents: عدد الحوادث حسب المنطقة reporting_location: عدد الاطفال حسب المنطقة reporting_location_detention: عدد الاطفال حسب المنطقة @@ -2017,42 +2178,17 @@ ar: received_response: تلقى الأطفال استجابة male: ذكر female: أنثى - military_use_type_of_use: عدد الاختراقات حسب نوع الاستخدام + military_use_type_of_use: عدد الانتهاكات حسب نوع الاستخدام gbv_statistics: name: احصاءات GBV filter_options: date_of_first_report: تاريخ المقابلة incident_date: تاريخ الحادثة reports: - incidents: حوادث perpetrators: المسيئين survivors: الناجين referrals: الإحالات sub_reports: - combined: حوادث - total: عدد حوادث الGBV المبلغة - gbv_sexual_violence: عدد حوادث العنف الجنسي المبلغ عنها - gbv_previous_incidents: عدد الحوادث التي تم التبليغ عنها من قبل الناجيات مع حوادث سابقة للعنف المبني على النوع الإجتماعي - gbv_sexual_violence_type: نوع الحادثة - incident_timeofday: وقت الحادثة من اليوم - elapsed_reporting_time: الوقت بين الحادثة وتاريخ التقرير - elapsed_reporting_time_rape: حوادث الاغتصاب ، الوقت المنقضي بين وقوع الحادثة وتاريخ التبليغ - elapsed_reporting_time_rape_health_referral: حوادث الاغتصاب ، الوقت المنقضي بين وقوع الحادثة وتاريخ التبليغ(خدمة صحية أو إحالة) - incident_location_type: موقع الحادثة - number_of_perpetrators: 'عدد المسيئين ' - perpetrator_relationship: علاقة المسيء الرئيسي بالناجي - perpetrator_age_group: الفئة العمرية للمسيئين الرئيسيين - perpetrator_occupation: طبيعة عمل المسيئين الرئيسيين - age: عدد الناجين حسب العمر - sex: عدد الناجين حسب الجنس - marital_status: الحالة الاجتماعية للناجين - displacement_status: حالة نزوح الناجين - displacement_incident: مرحلة النزوح وقت وقوع الحادث - gbv_case_context: سياق الحالة - incidents_first_point_of_contact: عدد الحوادث التي تكون فيها منظمتك هي نقطة الاتصال الأولى - incidents_from_other_service_provider: الحوادث التي تم احالتها من قبل مقدمي الخدمة الآخرين - number_of_services_provided: عدد الخدمات المقدمة للحوادث - number_of_services_provided_other: إحالات الحوادث الجديدة لمقدمي الخدمات الآخرين service_safehouse_referral: إحالة البيت الآمن / المأوى الآمن service_medical_referral: إحالة صحية / طبية service_psycho_referral: خدمات الاستشارة النفسية / الاجتماعية @@ -2060,8 +2196,48 @@ ar: service_police_referral: الشرطة أو أي نوع آخر من خدمات الأمن service_livelihoods_referral: خدمات الاعاشة service_protection_referral: خدمات حماية الطفل - vulnerable_populations: الفئات السكانية الضعيفة survivors_disability_type: مع اعاقات + workflow_report: + name: سير العمل + description: الحالات والحوادث مع أوضاع سير عمل محددة، مقسمة حسب العمر والجنس. + reports: + cases_workflow: سير العمل - الحالات + incidents_workflow: سير العمل - الحوادث + filter_options: + registration_date: تاريخ التسجيل + sub_reports: + case_workflow_by_sex_and_age: إجمالي عدد الحالات حسب الجنس والعمر + incident_workflow_by_sex_and_age: إجمالي عدد الحوادث حسب الجنس والعمر + cases_workflow_report: + name: سير العمل + description: الحالات والحوادث مع أوضاع سير عمل محددة، مقسمة حسب العمر والجنس. + reports: + cases_workflow: سير العمل - الحالات + filter_options: + registration_date: تاريخ التسجيل + sub_reports: + case_workflow_by_sex_and_age: إجمالي عدد الحالات حسب الجنس والعمر + referrals_transfers_report: + name: الإحالات والانتقالات + description: الإحالات والانتقالات التي حدثت خلال فترة زمنية محددة. مقسمة حسب هيئات المرسلة والمستقبلة أو مجموعات المستخدمين. + reports: + total_referrals: الإحالات + total_transfers: الانتقالات + sub_reports: + total_transfers_by_user_groups: إجمالي عمليات النقل + total_referrals_by_user_groups: إجمالي عمليات الإحالة + filter_options: + registration_date: تاريج التسجيل + violence_type_report: + name: نوع العنف + reports: + cases_violence_type: نوع العنف- الحالات + incidents_violence_type: نوع العنف- الحوداث + filter_options: + registration_date: تاريخ التسجيل + sub_reports: + case_violence_type_by_sex_and_age: إجمالي عدد الحالات حسب الجنس والعمر + incident_violence_type_by_sex_and_age: إجمالي عدد الحوادث حسب الجنس والعمر success_message: تمّ إنشاء ملف التصدير بنجاح messages: alert_items: لديك%{items} عناصر ملحوظة. @@ -2118,6 +2294,7 @@ ar: tracing_request: طلبات التتبع activity_log: سجل التغيير registry_records: السجل + families: العائلات notes: note_success: تمّت إضافة الملاحظة بنجاح permissions: @@ -2127,8 +2304,8 @@ ar: add_note: إضافة ملاحظات admin_only: لا توجد سجلات - وظائف المشرف فقط administrator_read: قراءات عن المشرف - agency: مؤسسة - agency_read: قراءة المؤسسة + agency: الهيئة + agency_read: قراءة الهيئة all: الوصول لجميع السجلات أو المستخدمين approvals_assessment: '%{approval_label}' approvals_assessment_pending: '%{approval_label} معلّق' @@ -2142,7 +2319,7 @@ ar: approve_closure: الموافقة على نموذج %{approval_label} approve_gbv_closure: الموافقة على نموذج %{approval_label} assign: تعيين/نقل - assign_within_agency: تعيين ضمن المؤسسة + assign_within_agency: تعيين ضمن الهيئة assign_within_user_group: تعيين ضمن مجموعة المستخدمين audit_log: سجل التدقيق case: حالة @@ -2162,16 +2339,16 @@ ar: copy_of: نسخة من create: انشاء dash_case_incident_overview: حالاتي/حوادثي - dash_cases_by_social_worker: عرض الحالات التي تولاها الاخصائي الاجتماعي - dash_cases_by_task_overdue: عرض الحالات حسب استحقاق المهمة + dash_cases_by_social_worker: عرض الحالات التي تولاها اخصائي الحالة + dash_cases_by_task_overdue: عرض الحالات حسب المهمة المتأخرة dash_cases_by_workflow: عرض الحالات حسب مخطط سير العمل dash_cases_to_assign: عرض الحالات التي بانتظار التعيين dash_group_overview: حالات مجموعتي - dash_manager_transfers: عرض عمليات التحويل الخاصة بالمدير + dash_manager_transfers: عرض عمليات النقل الخاصة بالمدير dash_matching_results: عرض النتائج المتشابهة - dash_protection_concerns: عرض الأمور الخاصة بالحماية + dash_protection_concerns: عرض المخاوف المتعلقة بالحماية dash_protection_concerns_by_location: عرض المخاوف المرتبطة بالحماية بحسب الموقع - dash_referrals_by_socal_worker: عرض الإحالات التي قام بها الاخصائي الاجتماعي + dash_referrals_by_socal_worker: عرض الإحالات التي قام بها اخصائي الحالة dash_reporting_location: عرض مواقع الإبلاغ dash_service_provisions: عرض تقديم الخدمات dash_shared_from_my_team: تمّ تشاركها من فريقي @@ -2180,8 +2357,8 @@ ar: dash_shared_with_others: تمّ تشاركها مع آخرين dash_show_none_values: عرض القيم الخالية dash_tasks: عرض المهام - dash_transfers_by_socal_worker: عرض عمليات التحويل التي قام بها الباحث الاجتماعي - dash_national_admin_summary: ملخص المسؤول + dash_transfers_by_socal_worker: عرض عمليات النقل التي قام بها اخصائي الحالة + dash_national_admin_summary: ملخص المدير dashboard: لوحة التحكم delete: حذف display_view_page: إظهار صفحة العرض @@ -2201,6 +2378,7 @@ ar: find_tracing_match: ايجاد تطابق التتبع للحالة view_registry_record: عرض سجل التسجيل add_registry_record: اضافة سجل التسجيل + family: العائلة flag: تمييز بعلامة form: نماذج group: 'الوصول لجميع السجلات أو المستخدمين في مجموعتي ' @@ -2213,10 +2391,10 @@ ar: lookup: عمليات البحث manage: إدارة mark_for_offline: وضع علامة على عدم الاتصال بالانترنت - matching_configuration: إعدادات المطابقة + matching_configuration: إعدادات مطابقة metadata: النماذج، البحث potential_match: تشابه محتمل - primero_configuration: ترتيب + primero_configuration: إعدادات read: قراءة reassign: إعادة تعيين/نقل receive_referral: تلقّي الإحالة @@ -2228,7 +2406,8 @@ ar: reopen: إعادة فتح report: تقرير managed_report: رؤى - request_approval: طلب للمصادقة + resolve_any_flag: حل أي علامة + request_approval: طلب للموافقة request_approval_action_plan: طلب موافقة %{approval_label} request_approval_assessment: طلب موافقة %{approval_label} request_approval_case_plan: طلب موافقة %{approval_label} @@ -2238,7 +2417,7 @@ ar: role: أدوار المستخدم save_search: عمليات بحث محفوظة saved_search: عملية بحث محفوظة - search_owned_by_others: البحث عن سجل الحالة من خلال مستخدم آخر + search_owned_by_others: ابحث عن سجلات الحالة المملوكة لمستخدمين آخرين self: الوصول لسجلاتي أو المستخدم فقط service_provision_incident_details: عرض زر إضافة تقديم خدمة على جزء عرض تفاصيل الحادثة services_section_from_case: إضافة تقديم خدمة لحالة مستخدم آخر @@ -2250,16 +2429,18 @@ ar: transfer: يمكن استخدامها للتحويل user: مستخدمون user_group: مجموعات المستخدمين - view_approvals: 'عرض المصادقات ' + verify_mrm: تحقق من MRM + view_approvals: عرض الموافقات view_assessment: عرض التقييم view_photo: عرض الصورة - view_protection_concerns_filter: عرض عامل التصفية الخاص بعملية الحماية + view_protection_concerns_filter: عرض حسب المخاوف المتعلقة بالحماية view_response: عرض الاستجابات webhook: الويب هوك workflow: سير العمل - الحالات الفردية workflow_team: سير العمل - حالات الفريق/الفرق write: كتابة activity_log: سجل التغيير + remove_alert: إزالة تنبيه resource: kpi: actions: @@ -2279,7 +2460,7 @@ ar: explanation: القدرة على معرفة عدد الحالات التي أُغلقت شهريًا في كلّ موقع. label: عدد إغلاق الحالات kpi_case_load: - explanation: القدرة على معرفة متوسط عدد الحالات المفتوحة لكلّ إختصاصي إجتماعي. + explanation: القدرة على معرفة متوسط عدد الحالات المفتوحة لكلّ اخصائي الحالة. label: عدد الحالات kpi_client_satisfaction_rate: explanation: القدرة على معرفة معدّل الناجين الذين أكملوا استبان آراء العملاء وكانوا راضين بالنسبة إلى كلّ حالة يمكن للمستخدم الوصول إليها. @@ -2288,11 +2469,11 @@ ar: explanation: القدرة على معرفة نسبة الذين أكملوا خطة عمل الحالة بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. label: خطّة عمل حالة مكتملة kpi_completed_case_safety_plans: - explanation: القدرة على معرفة نسبة الذين احتاجوا إلى خطّة سلامة وأكملوها بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. - label: خطّة سلامة الحالة المكتملة + explanation: القدرة على معرفة النسبة المطلوبة وإكمال خطة الأمان، بالنسبة للحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: خطّة أمان الحالة المكتملة kpi_completed_supervisor_approved_case_action_plans: - explanation: القدرة على معرفة نسبة الذين أكملوا خطة عمل الحالة وتمّ الموافقة عليها من قبل المشرف بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. - label: تمّت الموافقة على خطط عمل الحالة المكتملة من قبل المشرف + explanation: القدرة على معرفة نسبة الذين أكملوا خطة عمل الحالة وتمّ الموافقة عليها من قبل مشرف الحالات بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. + label: تمّت الموافقة على خطط عمل الحالة المكتملة من قبل مشرف الحالات kpi_goal_progress_per_need: explanation: القدرة على معرفة النسبة المئوية للأهداف التي تم تحقيقها في كل فئة من فئات الاحتياجات بالنسبة إلى الحالات النشطة التي يمكن للمستخدم الوصول إليها. label: التقدّم المُحرز نحو الأهداف @@ -2309,8 +2490,8 @@ ar: explanation: 'القدرة على معرفة نوع الخدمات التي قدّمتها المنظمة داخليًّا لجميع الحالات التي يمكن للمستخدم الوصول إليها. ' label: الخدمات المقدَّمة kpi_supervisor_to_caseworker_ratio: - explanation: القدرة على معرفة متوسط عدد الإختصاصيين الإجتماعيين لكلّ مشرف. - label: عدد الإختصاصيين الإجتماعيين لكلّ مشرف. + explanation: القدرة على معرفة متوسط عدد اخصائيين الحالة لكلّ مشرف. + label: عدد اخصائيين الحالة لكلّ مشرف. kpi_time_from_case_open_to_close: explanation: القدرة على معرفة مدّة الإبقاء على الحالة مفتوحة بالنسبة إلى كلّ الحالات التي يمكن للمستخدم الوصول إليها. label: الوقت من فتح القضية إلى إغلاقها @@ -2318,61 +2499,61 @@ ar: agency: actions: assign: - explanation: القدرة على اختيار وكالة عند إنشاء حساب مستخدم أو تعديله. إذا كان لدى المستخدم الحالي هذا الإذن بالإضافة إلى إذن "قراءة الوكالة" للمستخدمين، فسيكون بإمكانه فقط إضافة مستخدم إلى وكالته الخاصة. + explanation: القدرة على اختيار الهيئة عند إنشاء حساب مستخدم أو تعديله. إذا كان لدى المستخدم الحالي هذا الإذن بالإضافة إلى إذن "قراءة الهيئة" للمستخدمين، فسيكون بإمكانه فقط إضافة مستخدم إلى وكالته الخاصة. label: تعيين create: - explanation: القدرة على إنشاء وكالة + explanation: القدرة على إنشاء هيئة label: إنشاء manage: - explanation: 'يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على الوكالات. إذن "الإدارة" يعني أساسًا "كل شيء". هام: يمنح هذا الإذن أيضًا القدرة على إنشاء وكالة جديدة.' + explanation: 'يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على الهيئات. إذن "الإدارة" يعني أساسًا "كل شيء". هام: يمنح هذا الإذن أيضًا القدرة على إنشاء الهيئة جديدة.' label: إدارة (كافة الأذونات لهذا النوع من الموارد) read: - explanation: القدرة على رؤية الوكالات. + explanation: القدرة على رؤية الهيئات. label: عرض write: explanation: القدرة على تعديل المعلومات حول الوكالات. يرجى الإنتباه إلى أن هذا الأمر ينطبق على جميع الوكالات في النظام. label: تعديل - explanation: يمثل منظمة بها أعضاء يستخدمون بريميرو. توجد الوكالات بشكل مستقل عن مجموعات المستخدمين. - label: وكالة + explanation: يمثل منظمة بها أعضاء يستخدمون بريميرو. توجد الهيئات بشكل مستقل عن مجموعات المستخدمين. + label: الهيئة audit_log: actions: read: - explanation: يسمح للمستخدم بمشاهدة قائمة بجميع الإجراءات التي تم تنفيذها في النظام وتصفيتها، وتكون مقسّمة حسب المستخدم ونوع الإجراء ومُعرِّف السجل ووقت الإجراء. تُناسب هذه الخاصيّة المسؤولين على المستوى الوطني أو مستوى الوكالة ، لأنّها تعرض الإجراءات التي يقوم بها جميع المستخدمين في النظام. يرجى الإنتباه إلى أن سجل التدقيق لا يعرض معلومات التعريف الشخصية في السجلات المتضمنة في كل إجراء. + explanation: يسمح للمستخدم بمشاهدة قائمة بجميع الإجراءات التي تم تنفيذها في النظام وتصفيتها، وتكون مقسّمة حسب المستخدم ونوع الإجراء ومُعرِّف السجل ووقت الإجراء. تُناسب هذه الخاصيّة المسؤولين على المستوى الوطني أو مستوى الهيئة ، لأنّها تعرض الإجراءات التي يقوم بها جميع المستخدمين في النظام. يرجى الإنتباه إلى أن سجل التدقيق لا يعرض معلومات التعريف الشخصية في السجلات المتضمنة في كل إجراء. label: عرض explanation: قائمة قابلة للتصفية لجميع الإجراءات التي تم تنفيذها في النظام. لا تتضمن أي معلومات تعريفية عن الحالات أو الحوادث أو طلبات البحث عن المفقودين. label: سجل التدقيق case: actions: add_note: - explanation: يسمح للمستخدم بإضافة مُدخَل إلى نموذج "الملاحظات" الفرعي (يُطلق عليه أحيانًا اسم "التعليقات"). يقوم المستخدم بذلك عن طريق النقر فوق زر "إضافة ملاحظات" في صفحة عرض الحالة. هذا الإجراء مفيد بشكل خاص للمديرين الذين ليس لديهم القدرة على تعديل الحالات، ولكنّهم يريدون إضافة تذكيرات عن حالة للإختصاصي الإجتماعي. بهذه الطريقة، يُشبِه إضافة ملاحظة إضافة علم. ميزة إضافة ملاحظة هي أنه عندما يضيف المدير ملاحظة إلى حالة ما، سيظهر إشعار على الحالة للإختصاصي الإجتماعي عندما يعرض الحالة على هاتفه الجوّال. + explanation: يسمح للمستخدم بإضافة مُدخَل إلى نموذج "الملاحظات" الفرعي (يُطلق عليه أحيانًا اسم "التعليقات"). يقوم المستخدم بذلك عن طريق النقر فوق زر "إضافة ملاحظات" في صفحة عرض الحالة. هذا الإجراء مفيد بشكل خاص للمديرين الذين ليس لديهم القدرة على تعديل الحالات، ولكنّهم يريدون إضافة تذكيرات عن حالة لاخصائي الحالة. بهذه الطريقة، يُشبِه إضافة ملاحظة إضافة علم. ميزة إضافة ملاحظة هي أنه عندما يضيف المدير ملاحظة إلى حالة ما، سيظهر إشعار على الحالة لاخصائي الحالة عندما يعرض الحالة على هاتفه الجوّال. label: اضافة ملاحظات إلى حالة add_registry_record: explanation: يسمح للمستخدم بربط سجل بحالة من نموذج تفاصيل السجل. يسمح أيضًا للمستخدم بإلغاء ربط أي سجل مرتبط بالحالة اساسا. label: إضافة / تحديث سجل التسجيل من الحالة approve_action_plan: - explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات الإختصاصيين الإجتماعيين لديهم. + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. label: الموافقة على %{approval_label} approve_assessment: - explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات الإختصاصيين الإجتماعيين لديهم. + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. label: الموافقة على نموذج %{approval_label} approve_bia: - explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات الإختصاصيين الإجتماعيين لديهم. + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. label: الموافقة على نموذج %{approval_label} approve_case_plan: - explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات الإختصاصيين الإجتماعيين لديهم. + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. label: الموافقة على %{approval_label} approve_closure: - explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات الإختصاصيين الإجتماعيين لديهم. + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. label: الموافقة على نموذج %{approval_label} approve_gbv_closure: - explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات الإختصاصيين الإجتماعيين لديهم. + explanation: يسمح للمدير بالموافقة على %{approval_label} لحالات اختصاصيين الحالة لديهم. label: الموافقة على نموذج %{approval_label} assign: explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الأصلي إلى أي مستخدم آخر في النظام. لا حاجة لموافقة الطفل لهذا الإجراء. على عكس عمليات التحويل لا يُمنح المستلِم الفرصة لقبول التعيين أو رفضه. label: تعيين assign_within_agency: - explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الأصلي إلى أي مستخدم آخر في وكالة المستخدم الحالية. لا حاجة لموافقة الطفل لهذا الإجراء. على عكس عمليات التحويل، لا يُمنح المستلِم الفرصة لقبول التعيين أو رفضه. - label: تعيين لمستخدم ضمن وكالتي + explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الأصلي إلى أي مستخدم آخر في هيئة المستخدم الحالية. لا حاجة لموافقة الطفل لهذا الإجراء. على عكس عمليات التحويل، لا يُمنح المستلِم الفرصة لقبول التعيين أو رفضه. + label: تعيين لمستخدم ضمن هيئتي assign_within_user_group: explanation: يسمح للمستخدم بإرسال حالة من مالك السجل الأصلي إلى أي مستخدم آخر في مجموعات مستخدمي المستخدم الحالية. لا حاجة لموافقة الطفل لهذا الإجراء. على عكس عمليات التحويل، لا يُمنح المستلِم الفرصة لقبول التعيين أو رفضه label: تعيين لمستخدم ضمن مجموعة المستخدمين الخاصة بي @@ -2404,7 +2585,7 @@ ar: explanation: يمكن للمستخدم إنشاء ملف تصدير XLS من قائمة الحالة أو صفحات عرض الحالة، والتي تحتوي على مجموعة مخصّصة من النماذج أو الحقول، بالنسبة إلى حالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. في هذا التصدير، يتمّ تمثيل كلّ نموذج في علامة التبويب الخاصة به داخل ملف XLS. يمكن للمستخدم اختيار النماذج أو الحقول التي يريد تضمينها في التصدير باستخدام قسم التصدير المخصّص. يرجى ملاحظة أنه لا يمكن للمستخدمين تضمين النماذج والحقول في التصدير إلا إذا كان لديهم بالفعل القدرة على رؤية تلك النماذج والحقول عند عرض حالة في التطبيق. label: تصدير مخصص export_duplicate_id_csv: - explanation: إنشاء تصدير CSV للحالات التي لها نفس حقل "الهوية الوطنية" (قد يكون لها تسمية مختلفة، اعتمادًا على التشكيل). يتمّ تنفيذه فقط من صفحة قائمة الحالة. + explanation: إنشاء تصدير CSV للحالات التي لها نفس حقل "الهوية الوطنية" (قد يكون لها تسمية مختلفة، اعتمادًا على الإعدادات). يتمّ تنفيذه فقط من صفحة قائمة الحالة. label: تصدير التكرارات export_json: explanation: يمكن للمستخدم إنشاء ملف تصدير JSON من قائمة الحالة أو صفحات عرض الحالة، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها ،والمرتبطة بحالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. يستخدم هذا التصدير بشكل أساسي من قبل الذين يرغبون في تصدير الحالات من نظام Primero الحالي ثم استيرادها إلى نظام Primero مختلف، أو إلى نظام إدارة معلومات آخر. تعتبر صيغة JSON قابلة للقراءة آليًا وغير عمليّة لمعظم المستخدمين. @@ -2420,6 +2601,7 @@ ar: label: تصدير ملف photowall export_unhcr_csv: label: تصدير مفوضية الأمم المتحدة لشؤون اللاجئين CSV + explanation: لم تعد هذه الميزة قيد الاستخدام. export_xls: explanation: 'يمكن للمستخدم إنشاء ملف تصدير XLS من قائمة الحالة أو صفحات عرض الحالة، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بحالة واحدة أو متعددة أو جميع الحالات التي يمكن للمستخدم الوصول إليها. في هذا التصدير، يُمثّل كلّ نموذج في علامة التبويب الخاصة به داخل ملف XLS. ملاحظة: تعرض صيغة XLS الأحرف غير اللاتينية (مثل العربية والبنغالية) بصيغة قابلة للقراءة، بينما لا تعرض صيغة CSV هذا الأمر.' label: تصدير EXCEL (ملف XLS) @@ -2429,6 +2611,9 @@ ar: flag: explanation: القدرة على إضافة علم إلى حالة. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي أضافوها إلى إحدى الحالات. label: تمييز بعلامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: حل إية علامات import: explanation: يسمح للمستخدم بإنشاء حالة واحدة جديدة أو أكثر من خلال استيرادها من ملف CSV أو Excel أو JSON. يجب أن يكون الملف المستورد مهيّأ *جدًّا* وخصوصًا حتى يتمّ استيراد المعلومات بشكل صحيح. يجب أن تكون هذه الوظيفة متاحة فقط للمستخدمين الإداريين ذوي المهارات التقنية المتقدّمة والمعرفة العميقة بكيفية تهيئة البيانات في Primero. يتمّ تنفيذها فقط من صفحة قائمة الحالة. label: استيراد @@ -2438,6 +2623,9 @@ ar: incident_from_case: explanation: يسمح هذا الإذن للمستخدم بالنقر فوق زر "إنشاء حادثة". يؤدي هذا إلى إنشاء حادثة قد تحتوي على بعض المعلومات المنسوخة من الحالة. بالنسبة إلى حالات العنف القائم على النوع الاجتماعي، يتواجد هذا الزر أعلى صفحة عرض الحالة ويتوافق مع المعلومات المتعلقة بالحالة ككلّ. في بعض سياقات تتبع الحوادث، يكون هذا الزر في نموذج "تفاصيل الحادثة" الفرعي. في هذه الحالة، قد يتم نسخ بعض المعلومات من نموذج تفاصيل الحادثة الفرعي حيث تم النقر فوق الزر ، وكذلك من الحالة ككلّ. بمعنى آخر، قد تحتوي الحادثة الجديدة الذي تمّ إنشاؤها على حقل "نوع العنف" من النموذج الفرعي لتفاصيل الحادثة الفردية، ولكن قد يحتوي أيضًا على عمر وجنس الحالة نفسها. لاحظ أن هذا الإذن يسمح أيضًا للمستخدم بمشاهدة رابط الحادثة الذي تمّ إنشاؤها. label: إنشاء حادثة من حالة + remove_alert: + explanation: يسمح هذا الإذن للمستخدم بإزالة تنبيه من الحالة. يتم عادةً إنشاء التنبيهات عند تحرير حقل معين، كما هو الحال عند تحديث الملاحظات. تظهر التنبيهات عادة بنقطة صفراء بجوار الحالة. + label: إزالة التنبيه من حالة manage: explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة للحالات. يعني إذْن "الإدارة" بشكل أساسي "كل شيء". label: إدارة (كافة الأذونات لهذا النوع من الموارد) @@ -2457,7 +2645,7 @@ ar: explanation: يسمح لمستخدم بمنح مستخدم آخر حق الوصول المؤقت إلى حالة. سيتمكن مستلم الإحالة من تنفيذ الإجراءات نفسها في الحالة المُحالة كما لو أنّه ينفذها على حالاته الخاصة. عندما لا يعود المستلم بحاجة إلى الوصول إلى الحالة ، يمكنه النقر فوق زر "أكتمل" في النموذج الفرعي للإحالات والتحويلات، وسيفقد إمكانية الوصول إلى الحالة. لا يمكنك إحالة حالة إلّا لمستخدم يسمح له دوره بتلقّي الإحالات. label: إحالة referral_from_service: - explanation: يسمح للمستخدم برؤية زر "الإحالة" في نموذج الخدمات الفرعي. عندما ينقر المستخدم على هذا الزر، سيظهر قسم الإحالة مع تعطيل حقول نوع الخدمة والوكالة ومقدّم الخدمة والموقع، ولكن يتمّ ملؤها تلقائيًا بالمعلومات الخاصة بهذه الحقول في نموذج الخدمات الفرعي الذي نقر المستخدم على زر الإحالة المرتبط به. + explanation: يسمح للمستخدم برؤية زر "الإحالة" في نموذج الخدمات الفرعي. عندما ينقر المستخدم على هذا الزر، سيظهر قسم الإحالة مع تعطيل حقول نوع الخدمة والهيئة ومقدّم الخدمة والموقع، ولكن يتمّ ملؤها تلقائيًا بالمعلومات الخاصة بهذه الحقول في نموذج الخدمات الفرعي الذي نقر المستخدم على زر الإحالة المرتبط به. label: إحالة حالة من نموذج الخدمة الفرعي remove_assigned_users: explanation: يسمح للمستخدم بإزالة المستخدمين الآخرين من حقل "المستخدمون الآخرون المعيّنون". يتمّ إدراج المستخدم هنا إذا تلقى إحالة أو تحويل للحالة ولكنّه لم يقبلها أو يرفضها بعد. عندما تقوم بإزالة مستخدم من حقل "المستخدمون الآخرون المعيّنون"، فإنك تزيل إمكانية وصولهم إلى الحالة. وبالتالي، يمكن للمستخدمين الذين لديهم هذا الإذن إزالة إمكانية الوصول إلى الحالة من المستخدمين الذين سبق لهم وتلقوا إحالات أو عمليات نحويل معلّقة للحالة. لاحظ أنّ هذا الإذن لا يعمل إلا إذا كان المستخدم الحالي لديه أيضًا القدرة على تعديل الحالة. @@ -2466,25 +2654,25 @@ ar: explanation: يسمح للمستخدم بفتح حالة مغلقة حاليًّا label: إعادة فتح request_approval_action_plan: - explanation: يسمح للمستخدم (عادة ما يكون إختصاصي إجتماعي) الطلب من مديره الموافقة على حالتهم %{approval_label}. + explanation: يسمح للمستخدم (عادة ما يكون إخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. label: طلب موافقة %{approval_label} request_approval_assessment: - explanation: يسمح للمستخدم (عادة ما يكون إختصاصي إجتماعي) الطلب من مديره الموافقة على حالتهم %{approval_label}. + explanation: يسمح للمستخدم (عادة ما يكون اخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. label: طلب موافقة %{approval_label} request_approval_bia: - explanation: يسمح للمستخدم (عادة ما يكون إختصاصي إجتماعي) الطلب من مديره الموافقة على حالتهم %{approval_label}. + explanation: يسمح للمستخدم (عادة ما يكون اخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. label: طلب موافقة %{approval_label} request_approval_case_plan: - explanation: يسمح للمستخدم (عادة ما يكون إختصاصي إجتماعي) الطلب من مديره الموافقة على حالتهم %{approval_label}. + explanation: يسمح للمستخدم (عادة ما يكون اخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. label: طلب موافقة %{approval_label} request_approval_closure: - explanation: يسمح للمستخدم (عادة ما يكون إختصاصي إجتماعي) الطلب من مديره الموافقة على حالتهم %{approval_label}. + explanation: يسمح للمستخدم (عادة ما يكون اخصائي الحالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. label: طلب موافقة %{approval_label} request_approval_gbv_closure: - explanation: يسمح للمستخدم (عادة ما يكون إختصاصي إجتماعي) الطلب من مديره الموافقة على حالتهم %{approval_label}. + explanation: يسمح للمستخدم (عادة ما يكون اخصائي حالة) الطلب من مديره الموافقة على حالتهم %{approval_label}. label: طلب موافقة %{approval_label} request_transfer: - explanation: يكشف عن زر "طلب التحويل" الموجود على "عرض القسم". يسمح الزر للمستخدم بإرسال رسالة مع ملاحظة شخصية عبر البريد الإلكتروني إلى مالك سجل الحالة الحالي، يطلب من مالك السجل تحويل الحالة إلى المستخدم الذي أرسل الطلب. يُعدّ هذا مفيدًا في السياقات التي يغيّر فيها الأطفال المواقع كثيرًا، ويحتاج الإختصاصيّون الإجتماعيّون إلى الإختصاصيّين الإجتماعيّين السابقين الذين عملوا مع الطفل لإرسال معلومات حول الطفل لتجنب إنشاء سجل مكرّر. + explanation: يكشف عن زر "طلب التحويل" الموجود على "عرض القسم". يسمح الزر للمستخدم بإرسال رسالة مع ملاحظة شخصية عبر البريد الإلكتروني إلى مالك سجل الحالة الحالي، يطلب من مالك السجل تحويل الحالة إلى المستخدم الذي أرسل الطلب. يُعدّ هذا مفيدًا في السياقات التي يغيّر فيها الأطفال المواقع كثيرًا، ويحتاج اخصائيين الحالة إلى اخصائيين الحالة السابقين الذين عملوا مع الطفل لإرسال معلومات حول الطفل لتجنب إنشاء سجل مكرّر. label: طلب تحويل search_owned_by_others: explanation: يسمح لمستخدم بإجراء بحث عن السجلات التي عادة لا يملك إمكانية الوصول إليها، إما لأنه ليس مالك سجل هذه الحالة، أو (للمديرين) لأن مالك السجل ليس ضمن مجموعات المستخدمين الخاصة بهم. لاحظ أنه في حين سيرى المستخدم الحالة من ضمن عرض نتائج البحث، لن يتمكن من النقر فوق صفحة عرض الحالة لهذه الحالة، ممّا يعني أنّه لن يتمكّن من رؤية أي معلومات تفصيلية حول الحالة. @@ -2520,7 +2708,7 @@ ar: explanation: القدرة على نقر زر "تعديل" وتحديث المعلومات في الحالة ثم النقر على "حفظ" label: تعديل accept_or_reject_transfer: - explanation: السماح للمستخدم بقبول أو رفض النقل نيابة عن مستخدم آخر موجود في فريقك (على سبيل المثال ، يقبل المشرف نقل تم إرساله إلى الاخصائي الاجتماعي). + explanation: السماح للمستخدم بقبول أو رفض النقل نيابة عن مستخدم آخر موجود في فريقك (على سبيل المثال ، يقبل مشرف الحالات نقل تم إرساله إلى اخصائي الحالة). label: قبول أو رفض النقل لمستخدم آخر في فريقك. list_case_names: explanation: 'لا يمكن للمديرين عادةً رؤية أسماء الحالات في قائمة الحالات. إذا حصل المدير على هذا الإذن ، فسيكون قادرًا على رؤية الأسماء في القائمة. ' @@ -2528,37 +2716,46 @@ ar: mark_for_offline: explanation: يسمح للمستخدم بالتخزين المؤقت للحالة للاستخدام في وضع عدم الاتصال. label: وضع علامة على عدم الاتصال بالانترنت + view_family_record: + explanation: يمكن للمستخدمين عرض نموذج "سجل العائلة" الخاص بالحالة، والذي يتضمن رابطًا لسجل عائلة الحالة. + label: عرض سجل العائلة من الحالة + case_from_family: + explanation: يمكن للمستخدمين إنشاء حالة لأحد أفراد عائلة الحالة في النموذج الفرعي "تفاصيل العائلة". لاحظ أنه سيتم إنشاء سجل العائلة تلقائيًا لربط هاتين الحالتين. + label: إنشاء حالة من تفاصيل العائلة + link_family_record: + explanation: يسمح للمستخدم بالبحث عن سجل العائلة الموجود وربطه بحالته. كما يسمح للمستخدمين بإلغاء ربط سجل العائلة من الحالة. + label: ربط / إلغاء ربط سجل العائلة من الحالة explanation: يمثل طفلاً فرديًا أو ناجٍ أو مستفيد آخر. label: حالة dashboard: actions: approvals_action_plan: explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على خطة العمل المعلّقة أو الموافق عليها أو المرفوضة. - label: موافقات الإختصاصي الإجتماعي %{approval_label} + label: موافقات اخصائي الحالة %{approval_label} approvals_action_plan_pending: explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على خطة العمل المعلّقة. label: موافقات المدير %{approval_label} approvals_assessment: explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على التقييم المعلّقة أو الموافق عليها أو المرفوضة. - label: موافقات الإختصاصي الإجتماعي %{approval_label} + label: موافقات اخصائي الحالة %{approval_label} approvals_assessment_pending: explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على التقييم المعلّقة. label: موافقات المدير %{approval_label} approvals_case_plan: explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على خطة الحالة المعلّقة أو الموافق عليها أو المرفوضة. - label: موافقات الإختصاصي الإجتماعي %{approval_label} + label: موافقات اخصائي الحالة %{approval_label} approvals_case_plan_pending: explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على خطة الحالة المعلّقة. label: موافقات المدير %{approval_label} approvals_closure: explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على الإغلاق المعلّقة أو الموافق عليها أو المرفوضة. - label: موافقات الإختصاصي الإجتماعي %{approval_label} + label: موافقات اخصائي الحالة %{approval_label} approvals_closure_pending: explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على الإغلاق المعلّقة. label: موافقات المدير %{approval_label} approvals_gbv_closure: explanation: يعرض عدد حالات المستخدم الحالي مع طلبات الموافقة على إغلاق العنف القائم على النوع الإجتماعي المعلّقة أو الموافق عليها أو المرفوضة. - label: موافقات الإختصاصي الإجتماعي %{approval_label} + label: موافقات اخصائي الحالة %{approval_label} approvals_gbv_closure_pending: explanation: يعرض عدد الحالات في فريق المدير مع طلبات الموافقة على إغلاق العنف القائم على النوع الإجتماعي المعلّقة. label: موافقات المدير %{approval_label} @@ -2569,25 +2766,25 @@ ar: explanation: يظهر عدد الحالات في كلّ مستوى خطر. label: الحالات حسب مستوى الخطر cases_by_task_overdue_assessment: - explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام التقييم لكلّ من الإختصاصيين الإجتماعيين. + explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام التقييم لكلّ من اخصائيين الحالة. label: مهام التقييم المتأخرة cases_by_task_overdue_case_plan: - explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام خطة الحالة لكلّ من الإختصاصيين الإجتماعيين. + explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام خطة الحالة لكلّ من اخصائيين الحالة. label: مهام خطة الحالة المتأخرة cases_by_task_overdue_followups: - explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام المتابعة لكلّ من الإختصاصيين الإجتماعيين. + explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام المتابعة لكلّ من اخصائيين الحالة. label: مهام المتابعة المتأخرة cases_by_task_overdue_services: - explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام الخدمات لكلّ من الإختصاصيين الإجتماعيين. + explanation: يسمح للمدير بمعرفة عدد الحالات التي تأخرت فيها مهام الخدمات لكلّ من اخصائيين الحالة. label: مهام الخدمات المتأخرة dash_case_incident_overview: - explanation: . + explanation: يُظهر للمدير عدد الحالات التي يديرها كل مستخدم في فريقه، والتي تتم إحالتها أو نقلها إلى مستخدمين آخرين. label: لمحة عامّة - حالاتي/حوادثي dash_cases_by_social_worker: explanation: الجدول الذي يوضح كيفية إدارة العدد الإجمالي للحالات المفتوحة وعدد الحالات الجديدة التي يديرها كل مستخدم في مجموعات المستخدمين الحالية للمستخدم. يمثّل كل صف مستخدمًا من مجموعات المستخدمين الخاصة بالمستخدم الحالي ، بينما يمثل "الإجمالي" و "الجديد" عمودين. - label: عرض الحالات حسب الإختصاصي الإجتماعي + label: عرض الحالات حسب اخصائي الحالة dash_cases_to_assign: - explanation: 'هام: للمديرين فقط. يعرض عدد الحالات التي يمتلكها المستخدم الحالي بشكل مباشر (يجب أن يكون مديرًا). تفترض لوحة المعلومات هذه أن المديرين لا يديرون حالاتهم الخاصة، وأنه إذا كان للمدير حالاته الخاصة، يجب عليه تعيين هذه الحالات لإختصاصيين إجتماعيين في فريقه.' + explanation: 'هام: للمديرين فقط. يعرض عدد الحالات التي يمتلكها المستخدم الحالي بشكل مباشر (يجب أن يكون مديرًا). تفترض لوحة المعلومات هذه أن المديرين لا يديرون حالاتهم الخاصة، وأنه إذا كان للمدير حالاته الخاصة، يجب عليه تعيين هذه الحالات لاخصائيين الحالة في فريقه.' label: (للمديرين) الحالات التي أحتاج إلى تعيينها لأشخاص في فريقي dash_flags: explanation: يعرض قائمة بالعلامات التي أضافها المستخدمون الآخرون إلى سجلاتي، بالإضافة إلى العلامات التي أضفتها إلى سجلات المستخدمين الآخرين. @@ -2620,6 +2817,7 @@ ar: explanation: يعرض للمدير عدد الحالات التي تمّ تحويلها أو إحالتها إلى كلّ مستخدم في فريقه. label: تمّ تشاركها مع فريقي dash_shared_with_my_team_overview: + explanation: يُظهر للمدير عدد الحالات المُحالة أو المنقولة إلى كل مستخدم في فريقه. label: تم مشاركته مع فريقي (نظرة عامة) dash_shared_with_others: explanation: يوضح عدد حالاتي التي تحتوي على إحالات نشطة أو عمليات تحويل معلّقة أو مرفوضة. لا تُستخدم عادةً من قبل المديرين، إلّا إذا كانوا يديرون القضايا بأنفسهم. @@ -2634,10 +2832,10 @@ ar: explanation: يُظهر عدد انتهاكات MRM من كل نوع والتي تم تصنيفها حسب المسيء label: MRM - عدد الانتهاكات حسب المسيء dash_show_none_values: - explanation: يضيف فئة "لا مستوى خطورة" إضافية لجميع لوحات المعلومات التي تقسّم الحالات حسب مستوى الخطورة. ينطبق هذا على وجه التحديد على التضبيطات التي لديها خيار رابع "لا مخاطر" لحقول مستوى الخطورة. + explanation: يضيف فئة "لا مستوى خطورة" إضافية لجميع لوحات المعلومات التي تقسّم الحالات حسب مستوى الخطورة. ينطبق هذا على وجه التحديد على الإعدادات التي لديها خيار رابع "لا مخاطر" لحقول مستوى الخطورة. label: عرض الحالات مع "لا مستوى خطورة" في لوحة معلومات التقييم dash_tasks: - explanation: يسمح للمستخدم برؤية صفحة المهام. يجب أن تُستخدم للإختصاصيين الإجتماعيين ومقدمي الخدمات، حيث ستكون الأرقام مخصّصة للحالات التي تديرها مباشرة. يجب على المديرين بدلاً من ذلك الحصول على لوحة المعلومات المرتبطة بـ "عرض الحالات حسب المهمة المتأخرة" ، لأن هذا يتيح لهم رؤية المهام المتأخرة لكلّ شخص في مجموعات المستخدمين الخاصة بهم. + explanation: يسمح للمستخدم برؤية صفحة المهام. يجب أن تُستخدم لاخصائيين الحالة ومقدمي الخدمات، حيث ستكون الأرقام مخصّصة للحالات التي تديرها مباشرة. يجب على المديرين بدلاً من ذلك الحصول على لوحة المعلومات المرتبطة بـ "عرض الحالات حسب المهمة المتأخرة" ، لأن هذا يتيح لهم رؤية المهام المتأخرة لكلّ شخص في مجموعات المستخدمين الخاصة بهم. label: صفحة المهام dash_national_admin_summary: explanation: يظهر إجمالي الحالات المفتوحة في النظام ، وعدد الحالات الجديدة التي تم إنشاؤها في كل من الأسبوعين الماضيين ، وعدد الحالات التي تم إغلاقها في كل من الأسبوعين الماضيين. @@ -2646,16 +2844,19 @@ ar: explanation: لكلّ نوع من أنواع الاستجابة، يوضح عدد الحالات في كل مستوى من مستويات الخطورة التي لديها خدمات على وشك الإنتهاء أو متأخّرة. label: عرض الاستجابات workflow: - explanation: يسمح لإختصاصي إجتماعي برؤية رسم بياني دائري يوضح عدد الحالات الخاصة به والموجودة في كلّ مرحلة من مراحل سير عمل إدارة الحالة. + explanation: يسمح لإخصائي الحالة برؤية رسم بياني دائري يوضح عدد الحالات الخاصة به والموجودة في كلّ مرحلة من مراحل سير عمل إدارة الحالة. label: الحالات مقسّمة حسب سريان العمل workflow_team: - explanation: 'يسمح للمدير برؤية جدول يوضح عدد حالات الإختصاصيين الاجتماعيين في كلّ مرحلة من مراحل عملية إدارة الحالة. ' - label: الحالات حسب سير العمل والإختصاصي الإجتماعي + explanation: 'يسمح للمدير برؤية جدول يوضح عدد حالات اختصاصيين الحالة في كلّ مرحلة من مراحل عملية إدارة الحالة. ' + label: الحالات حسب سير العمل واخصائي الحالة explanation: تملي المعلومات الموجزة التي تظهر على الصفحة الرئيسية. label: لوحة المعلومات disabled: explanation: إذا قمت بتعطيل هذا الدور، لن تتمكن من تعيينه إلى حسابات المستخدمين. label: 'مُعطلة ' + referral_authorization: + explanation: ويعني أن الدور سيظهر كخيار للقائمة المنسدلة "نوع الإحالة" عندما يقوم المستخدم بإجراء إحالة داخلية. إذا اختار المستخدم هذا الدور كنوع الإحالة، فلن يتمكن متلقي الإحالة من الوصول إلا إلى النماذج التي يمكن للدور المحدد الوصول إليها. لذا، على سبيل المثال، إذا اختار المستخدم "مقدم الخدمة الطبية" كنوع الإحالة، وكان لدور مقدم الخدمة الطبية حق الوصول فقط إلى نماذج الهوية الأساسية ومخاوف الحماية، فلن يرى المستلم سوى هذه النماذج. + label: هل يمكن استخدام هذا الدور في القائمة المنسدلة "نوع الإحالة"؟ duplicate: actions: read: @@ -2665,25 +2866,28 @@ ar: label: بحث مكرر forms: case: - explanation: 'يقيّد وصول المستخدم إلى نماذج الحالات ويحدّ من المعلومات التي يمكن للمستخدم رؤيتها في الحادثة. مثلاً، إذا كان للمستخدم حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج فقط. إذا كان المستخدم الحالي لديه وصول محدود إلى النموذج ولديه القدرة على إدارة تضبيطات النموذج، فإن تقييد وصوله إلى النموذج يحدّ أيضًا النماذج التي يمكنه تضبيطها. ملاحظة: إذا لم يتمّ تحديد أي نموذج، فهذا يعني أنّ الدور لديه حق الوصول إلى جميع نماذج الحالات.' + explanation: 'يقيّد وصول المستخدم إلى نماذج الحالات ويحدّ من المعلومات التي يمكن للمستخدم رؤيتها في الحادثة. مثلاً، إذا كان للمستخدم حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج فقط. إذا كان المستخدم الحالي لديه وصول محدود إلى النموذج ولديه القدرة على إدارة إعدادات النموذج، فإن تقييد وصوله إلى النموذج يحدّ أيضًا النماذج التي يمكنه تضبيطها. ملاحظة: إذا لم يتمّ تحديد أي نموذج، فهذا يعني أنّ الدور لديه حق الوصول إلى جميع نماذج الحالات.' label: نماذج - حالة incident: - explanation: 'تقييد وصول المستخدم إلى النماذج الخاصة بالحوادث يحد من المعلومات التي يمكن للمستخدم رؤيتها في الحادث. على سبيل المثال ، إذا كان المستخدم لديه حق الوصول إلى نموذج مالك السجل فقط ، فسيكون أيضًا قادرًا فقط على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج. إذا كان لدى المستخدم الحالي وصول محدود إلى النموذج ولديه القدرة على إدارة تكوين النموذج ، فإن تقييد وصوله إلى النموذج يحد أيضًا من النماذج التي يمكنه تكوينها. ملاحظة: إذا لم يتم تحديد أي نماذج ، فهذا يعني أن الدور لديه حق الوصول إلى جميع نماذج الحوادث.' + explanation: 'تقييد وصول المستخدم إلى النماذج الخاصة بالحوادث يحد من المعلومات التي يمكن للمستخدم رؤيتها في الحادث. على سبيل المثال ، إذا كان المستخدم لديه حق الوصول إلى نموذج مالك السجل فقط ، فسيكون أيضًا قادرًا فقط على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج. إذا كان لدى المستخدم الحالي وصول محدود إلى النموذج ولديه القدرة على إدارة إعدادات النموذج ، فإن تقييد وصوله إلى النموذج يحد أيضًا من النماذج التي يمكنه تكوينها. ملاحظة: إذا لم يتم تحديد أي نماذج ، فهذا يعني أن الدور لديه حق الوصول إلى جميع نماذج الحوادث.' label: نماذج - حوادث tracing_request: - explanation: 'يقيّد وصول المستخدم إلى النماذج في طلبات التتبّع ويحدّ من المعلومات التي يمكن للمستخدم رؤيتها في طلب التتبّع. مثلاً، إذا كان للمستخدم حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج فقط. إذا كان المستخدم الحالي لديه وصول محدود إلى النموذج ولديه القدرة على إدارة تضبيطات النموذج، فإن تقييد وصوله إلى النموذج يحدّ أيضًا النماذج التي يمكنه تضبيطها. ملاحظة: إذا لم يتمّ تحديد أي نموذج، فهذا يعني أنّ الدور لديه حق الوصول إلى جميع النماذج لطلبات التتبّع.' + explanation: 'يقيّد وصول المستخدم إلى النماذج في طلبات التتبّع ويحدّ من المعلومات التي يمكن للمستخدم رؤيتها في طلب التتبّع. مثلاً، إذا كان للمستخدم حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج فقط. إذا كان المستخدم الحالي لديه وصول محدود إلى النموذج ولديه القدرة على إدارة إعدادات النموذج، فإن تقييد وصوله إلى النموذج يحدّ أيضًا النماذج التي يمكنه إعدادها. ملاحظة: إذا لم يتمّ تحديد أي نموذج، فهذا يعني أنّ الدور لديه حق الوصول إلى جميع النماذج لطلبات التتبّع.' label: النماذج - طلبات التتبع registry_record: - explanation: 'تقييد وصول المستخدم إلى النماذج الموجودة في السجلات يحد من المعلومات التي يمكن للمستخدم رؤيتها في السجل. على سبيل المثال ، إذا كان المستخدم لديه حق الوصول إلى نموذج مالك السجل فقط ، فسيكون أيضًا قادرًا فقط على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج. إذا كان لدى المستخدم الحالي وصول محدود إلى النموذج ولديه القدرة على إدارة تكوين النموذج ، فإن تقييد وصوله إلى النموذج يحد أيضًا من النماذج التي يمكنه تكوينها. ملاحظة: إذا لم يتم تحديد أي نماذج ، فهذا يعني أن الدور له حق الوصول إلى جميع نماذج السجلات.' + explanation: 'تقييد وصول المستخدم إلى النماذج الموجودة في السجلات يحد من المعلومات التي يمكن للمستخدم رؤيتها في السجل. على سبيل المثال ، إذا كان المستخدم لديه حق الوصول إلى نموذج مالك السجل فقط ، فسيكون أيضًا قادرًا فقط على رؤية المعلومات الواردة في الحقول الموجودة في هذا النموذج. إذا كان لدى المستخدم الحالي وصول محدود إلى النموذج ولديه القدرة على إدارة إعدادات النموذج ، فإن تقييد وصوله إلى النموذج يحد أيضًا من النماذج التي يمكنه إعدادها. ملاحظة: إذا لم يتم تحديد أي نماذج ، فهذا يعني أن الدور له حق الوصول إلى جميع نماذج السجلات.' label: النماذج - التسجيل + family: + label: النماذج - العائلة + explanation: 'يؤدي تقييد وصول المستخدم إلى نماذج العائلات إلى تحديد المعلومات التي يمكن للمستخدم رؤيتها حول العائلة. على سبيل المثال، إذا كان المستخدم لديه حق الوصول إلى نموذج مالك السجل فقط، فسيكون قادرًا أيضًا على رؤية المعلومات الموجودة في الحقول الموجودة في هذا النموذج فقط. إذا كان لدى المستخدم الحالي وصول محدود إلى النموذج ولديه القدرة على إدارة إعداد النموذج، فإن تقييد وصوله إلى النموذج يحد أيضًا من النماذج التي يمكنه تكوينها.' group: actions: admin_only: - explanation: هذا يعني أنّ المستخدمين الذين يؤدّون هذا الدور لن يتمكنوا إلا من رؤية الأمور المتعلّقة بإدارة النظام، مثل التقارير، وتضبيط النموذج والبحث، والمستخدمين، والأدوار، ومجموعات المستخدمين. لن يروا أي حالات فردية أو طلبات تتبّع أو حوادث. + explanation: هذا يعني أنّ المستخدمين الذين يؤدّون هذا الدور لن يتمكنوا إلا من رؤية الأمور المتعلّقة بإدارة النظام، مثل التقارير، وإعداد النموذج والبحث، والمستخدمين، والأدوار، ومجموعات المستخدمين. لن يروا أي حالات فردية أو طلبات تتبّع أو حوادث. label: لا توجد سجلات - وظائف المسؤول فقط agency: - explanation: يمكن للدور الوصول إلى السجلات التي يديرها جميع المستخدمين في وكالتهم. إذا كان للمستخدم الحق في الوصول إلى المستخدمين، يمكنه الوصول إلى جميع المستخدمين في وكالته. - label: 'كلّ السجلات أو المستخدمين في وكالتي ' + explanation: يمكن للدور الوصول إلى السجلات التي يديرها جميع المستخدمين في هيئاتهم. إذا كان للمستخدم الحق في الوصول إلى المستخدمين، يمكنه الوصول إلى جميع المستخدمين في هيئته. + label: كلّ السجلات أو المستخدمين في هيئتي all: explanation: يمكن للدور الوصول إلى جميع السجلات والمستخدمين ومجموعات المستخدمين في النظام، بغض النظر عن مجموعات المستخدمين التي ينتمون هم إليها. label: الوصول لجميع السجلات أو المستخدمين @@ -2693,10 +2897,13 @@ ar: self: explanation: يمكن للدور الوصول إلى السجلات الخاصة بهم (الحالات أو طلبات التتبّع أو الحوادث)، ويمكنه تعديل حساب المستخدم الخاص به. label: الوصول لسجلاتي أو المستخدم الخاص بي فقط - explanation: يتحكّم في السجلات (الحالات أو طلبات التتبّع أو الحوادث) التي يمكن للدور الوصول إليها. إذا كان للدور الحق في الوصول إلى المستخدمين ومجموعات المستخدمين، يستطيع بذلك التحكّم أيضًا بالمستخدمين ومجموعات المستخدمين التي يمكنه الوصول إليهم. يمكن للأدوار التي لها حق الوصول إلى "بلا سجلات" الوصول فقط إلى تضبيط النظام مثل النماذج والمستخدمين والتقارير. + explanation: يتحكّم في السجلات (الحالات أو طلبات التتبّع أو الحوادث) التي يمكن للدور الوصول إليها. إذا كان للدور الحق في الوصول إلى المستخدمين ومجموعات المستخدمين، يستطيع بذلك التحكّم أيضًا بالمستخدمين ومجموعات المستخدمين التي يمكنه الوصول إليهم. يمكن للأدوار التي لها حق الوصول إلى "بلا سجلات" الوصول فقط إلى إعداد النظام مثل النماذج والمستخدمين والتقارير. label: ما هي السجلات التي يؤثر فيها هذا الدور؟ incident: actions: + assign: + explanation: يسمح للمستخدم بإرسال حادثة من مالك السجل الأصلي إلى أي مستخدم آخر في النظام. لا يمكن تعيين الحوادث المرتبطة بالفعل بحالة ما؛ يجب عليك بدلاً من ذلك إعادة تعيين الحالة المرتبطة، مما سيؤدي إلى تحديث ملكية سجل الحادث. + label: تعيين change_log: explanation: يمكن للمستخدم رؤية تاريخ التغييرات التي تم إجراؤها على السجل منذ إنشائه. يتضمن هذا القيم المسجلة لجميع الحقول. label: تغيير السجل @@ -2713,6 +2920,7 @@ ar: explanation: 'يمكن للمستخدم إنشاء ملف تصدير CSV من قائمة الحوادث أو صفحات عرض الحوادث، والتي تحتوي على جميع الحقول التي يمكن للمستخدم الحالي الوصول إليها، والمرتبطة بحادثة واحدة أو حوادث متعددة أو جميع الحوادث التي يمكن للمستخدم الوصول إليها. ' label: تصدير CSV export_custom: + explanation: يمكن للمستخدم تحديد نماذج أو حقول محددة لتصديرها إلى ملف XLS. label: تصدير ملف مخصص export_incident_recorder_xls: explanation: يمكن للمستخدم إنشاء تصدير ملف XLS متخصّص يسمح بتبادل البيانات باستخدام أداة تسجيل حادثة العنف القائم على النوع الإجتماعي. @@ -2735,9 +2943,18 @@ ar: flag: explanation: القدرة على إضافة علم إلى حادثة. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي أضافوها إلى إحدى الحوادث. label: تمييز بعلامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: إزالة أية علامة import: explanation: يسمح للمستخدم بإنشاء حادثة واحدة جديدة أو أكثر من خلال استيرادها من ملف CSV أو Excel أو JSON. يجب أن يكون الملف المستورد مهيّأ *جدًّا* وخصوصًا حتى يتمّ استيراد المعلومات بشكل صحيح. يجب أن تكون هذه الوظيفة متاحة فقط للمستخدمين الإداريين ذوي المهارات التقنية المتقدّمة والمعرفة العميقة بكيفية تهيئة البيانات في Primero. يتمّ تنفيذها فقط من صفحة قائمة الحوادث. label: استيراد + remove_alert: + explanation: يسمح هذا الإذن للمستخدم بإزالة تنبيه من حادث ما. يتم عادةً إنشاء التنبيهات عند تحرير حقل معين، كما هو الحال عند تحديث الملاحظات. تظهر التنبيهات عادةً بنقطة صفراء بجوار الحادث. + label: إزالة التنبيه من الحادث + link_incident_to_case: + explanation: يسمح للمستخدم بربط الحادث بالحالة المحددة. + label: ربط حادث بحالة manage: explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة للحوادث. يعني إذْن "الإدارة" بشكل أساسي "كل شيء". label: إدارة (كافة الأذونات لهذا النوع من الموارد) @@ -2747,6 +2964,9 @@ ar: sync_mobile: explanation: يسمح هذا الإذن بشكل عام للمستخدم باستخدام تطبيق الهاتف المحمول. أولاً ، يسمح للمستخدم بمشاهدة إجراءات "تحديد للهاتف الجوال" و "ازالة التحديد للهاتف الجوال"، والتي تظهر في قائمة الحوادث وصفحات عرض الحوادث. يشير تحديد الحادثة للجوال إلى أنه يجب مزامنة المعلومات الخاصة بهذه الحادثة بين جهاز المستخدم المحمول والتطبيق على الإنترنت، بينما يؤدي إلغاء تحديد الحادثة للهاتف الجوال إلى إيقاف هذه المزامنة. بالإضافة إلى ذلك، لا يمكن للمستخدمين الذين ليس لديهم هذا الإذن مزامنة هواتفهم المحمولة مع التطبيق على الإنترنت بشكل عام، ممّا يعني أنه لا يمكنهم استخدام تطبيق الهاتف لإدارة الحوادث. label: مزامنة مع الهاتف المحمول + verify_mrm: + explanation: يمكن لمستخدم MRM تغيير لائحة الانتهاكات. + label: تحقق من MRM write: explanation: القدرة على نقر زر "تعديل" وتحديث المعلومات عن الحادثة ثم النقر على "حفظ". تسمح أيضًا للمستخدم بتعطيل حادثة أو تفعيلها. label: تعديل @@ -2757,34 +2977,70 @@ ar: label: هل هو مدير؟ managed_report: actions: + reporting_locations_report: + label: موقع الإبلاغ (حالات) + explanation: القدرة على عرض إحصائيات حول عدد الحالات المسجلة خلال نطاق زمني معين، وتصفيتها حسب موقع الإبلاغ، ومقسمة حسب العمر والجنس. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + followups_report: + label: متابعات (حالات) + explanation: القدرة على عرض إحصائيات حول عدد المتابعات التي تم إجراؤها خلال نطاق زمني محدد، والتي تمت تصفيتها حسب نوع المتابعة، ومقسمة حسب العمر والجنس. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + services_report: + label: خدمات (حالات) + explanation: القدرة على عرض إحصائيات حول عدد الخدمات المقدمة خلال نطاق زمني معين، مفلترة حسب نوع الخدمة، ومقسمة حسب العمر والجنس. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + protection_concerns_report: + label: مخاوف تتعلق بالحماية (حالات) + explanation: القدرة على عرض إحصائيات حول اهتمامات الحماية للحالات المسجلة خلال نطاق زمني محدد. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + managed_report_scope: + label: ما السجلات التي يجب أن يتمكن هذا الدور من رؤيتها في Insights؟ + managed_report_scope_all: + label: الكل + managed_report_scope_group: + label: البيانات المستندة إلى المجموعة فقط + managed_report_scope_agency: + label: البيانات المستندة إلى الهيئة فقط violations: + explanation: القدرة على الوصول إلى MRM Violences Insight. label: الانتهاكات gbv_statistics: + explanation: القدرة على الوصول لرؤية إحصاءات العنف القائم على النوع الاجتماعي. label: احصاءات GBV ghn_report: + explanation: القدرة على الوصول إلى MRM Global Horizontal Note Insight. label: المذكرة الافقية الشاملة individual_children: + explanation: القدرة على الوصول إلى MRM Individual Children Insight. label: الأطفال الفرديين + workflow_report: + label: سير العمل (حالات و حوادث) + explanation: القدرة على عرض إحصائيات حالة سير العمل لكلا الحالتين والأحداث المرتبطة بهما. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + cases_workflow_report: + label: سير العمل (حالات) + explanation: القدرة على عرض الإحصائيات حول حالات حالة سير العمل. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + violence_type_report: + label: نوع العنف (حالات وحوادث) + explanation: القدرة على عرض إحصائيات عن نوع العنف. يسمح هذا الإذن أيضًا للمستخدم بتصدير البيانات من Insight. + referrals_transfers_report: + label: الإحالات والانتقالات (حالات) + explanation: يرى المستخدمون عدد الحالات التي تم إحالتها ونقلها من كل مجموعة مستخدمين إلى كل مجموعة مستخدمين أخرى. matching_configuration: actions: manage: explanation: القدرة على التحكم في الحقول التي تتم مقارنتها للعثور على التطابقات بين طلب التتبع والحالة. نظرًا لأن هذا يتحكم في كيفية تشغيل المطابقة في النظام بأكمله، يجب أن يكون هذا الإذن متاحًا فقط لمسؤول النظام. label: إدارة (كافة الأذونات لهذا النوع من الموارد) explanation: يتحكم في الحقول المستخدمة لمقارنة طلبات التتبع بالحالات أثناء تتبع الأسرة ولم شملها. - label: تضبيطات المطابقة + label: إعدادات مطابقة metadata: actions: manage: - explanation: القدرة على إنشاء وتعديل وترجمة وحذف النماذج وحقول النماذج وعمليات البحث. يرجى ملاحظة أن المستخدم الذي لديه هذا الإذن سيكون قادرًا فقط على إدارة النماذج التي يمكنه الوصول إليها. على سبيل المثال، إذا كان للمسؤول الوطني القدرة فقط على رؤية نموذج مالك السجل في الحالات، لن يتمكن إلا من تحديث تضبيط هذا النموذج. + explanation: القدرة على إنشاء وتعديل وترجمة وحذف النماذج وحقول النماذج وعمليات البحث. يرجى ملاحظة أن المستخدم الذي لديه هذا الإذن سيكون قادرًا فقط على إدارة النماذج التي يمكنه الوصول إليها. على سبيل المثال، إذا كان للمسؤول الوطني القدرة فقط على رؤية نموذج مالك السجل في الحالات، لن يتمكن إلا من تحديث إعداد هذا النموذج. label: إدارة (كافة الأذونات لهذا النوع من الموارد) explanation: يتحكم في القدرة على تكوين نماذج وحقول Primero ، بالإضافة إلى خيارات البحث المستخدمة داخلها. label: النماذج، البحث module: actions: cp: - label: CP + label: حماية الطفل gbv: - label: العنق القائم على النوع الإجتماعي + label: العنف القائم على النوع الإجتماعي mrm: label: MRM explanation: يتحكّم في الوحدات النمطية التي ينطبق عليها هذا الدور @@ -2807,9 +3063,9 @@ ar: primero_configuration: actions: manage: - explanation: القدرة على حفظ التكوينات وتطبيقها وإرسالها. عادة ما يكون هذا الإذن محجوزًا لمسؤول النظام. + explanation: القدرة على حفظ الإعدادات وتطبيقها وإرسالها. عادة ما يكون هذا الإذن محجوزًا لمسؤول النظام. label: إدارة (كافة الأذونات لنوع المورد هذا) - label: ترتيب + label: إعدادات referral: actions: refer: @@ -2839,6 +3095,9 @@ ar: flag: explanation: القدرة على إضافة علامة إلى سجل التسجيل. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي قاموا بإضافتها إلى سجل التسجيل. label: تمييز بعلامة/وضع علامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: حل أي علامة manage: explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على سجلات التسجيل. إذن "الإدارة" يعني أساسًا "كل شيء". label: إدارة (كافة الأذونات لهذا النوع من الموارد) @@ -2853,13 +3112,70 @@ ar: label: وضع علامة على عدم الاتصال بالانترنت explanation: يمكن أن يمثل هذا فردًا أو مؤسسة تحتاج إلى ربطها بسجلات أخرى مثل الحالات أو الحوادث ، وهي كثيرة جدًا ويتم تحديثها بشكل متكرر بمعلومات جديدة. إنها تشبه عمليات البحث ، ولكن مع مجموعة أكثر تعقيدًا من المعلومات لكل إدخال. label: سجل التسجيل + family: + actions: + change_log: + explanation: يمكن للمستخدم رؤية سجل بجميع التغييرات التي تم إجراؤها على السجل منذ إنشائه. يتضمن ذلك القيم المسجلة لجميع الحقول. + label: سجل التغيير + create: + explanation: القدرة على إنشاء سجل العائلة + label: إنشاء + enable_disable_record: + explanation: القدرة على تعطيل أو تفعيل الأسرة. لا تظهر العائلات "المعطلة" بشكل افتراضي في قائمة العائلة. يمكن للمستخدمين رؤية العائلات المعطلة في قائمة العائلة باستخدام عامل التصفية. + label: تفعيل / تعطيل + export_csv: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف CSV من قائمة العائلة أو صفحات عرض العائلة، والتي تحتوي على جميع المجالات التي يمكن للمستخدم الحالي الوصول إليها، لاسرة واحد أو اكثر ا. ملاحظة: لا يعطي تصدير CSV حروف غير لاتينية (مثل العربية)' + label: تصدير من نوع CSV + export_json: + explanation: يمكن للمستخدم إنشاء تصدير ملف JSON من قائمة العائلة أو صفحات عرض العائلة، والتي تحتوي على جميع المجالات التي يمكن للمستخدم الحالي الوصول إليها. تنسيق JSON قابل للقراءة آليًا وليس عمليًا لمعظم المستخدمين. + label: تصدير من نوع JSON + export_xls: + explanation: 'يمكن للمستخدم إنشاء تصدير ملف XLS من قائمة العائلة أو صفحات عرض العائلة، والتي تحتوي على جميع المجالات التي يمكن للمستخدم الحالي الوصول إليها. ملاحظة: يجعل XLS الأحرف غير اللاتينية (مثل العربية) مقروئة، في حين أن تصدير CSV لا يفعل ذلك.' + label: تصدير من نوع XLS + export_list_view_csv: + explanation: يمكن للمستخدم إنشاء تصدير ملف CSV من صفحة قائمة العائلة والتي تحتوي على نفس الحقول التي تظهر لذلك المستخدم في قائمة العائلة. يؤدى فقط من صفحة قائمة العائلة. + label: تصدير للائحة على شكل CSV + export_pdf: + explanation: يمكن للمستخدم إنشاء تصدير ملف PDF من قائمة العائلة أو صفحات العرض العائلي، والتي تحتوي على جميع المجالات التي يمكن للمستخدم الحالي الوصول إليها، لسجل واحد أو اكثر والتي يمكن للمستخدم الوصول إليها. في ملف تصدير PDF، يتم سرد المعلومات أولاً حسب الأسرة، ثم يتم تنظيمها من خلال النموذج الذي تظهر عليه المعلومات. + label: تصدير على شكل PDF + export_custom: + label: تصدير لحقول مخصصة من الملف + explanation: يمكن للمستخدم اختيار نماذج أو حقول محددة من قائمة العائلة أو صفحات عرض العائلة للتصدير إلى ملف XLS. + flag: + explanation: القدرة على إضافة اشارة علم إلى العائلة. يمكن للمستخدمين الحاصلين على هذا الإذن أيضًا إزالة اشارات الأعلام التي أضافوها إلى العائلة. + label: علامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: حل أية علامة + manage: + explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على العائلات. إذن "الإدارة" يعني في الأساس "كل شيء". + label: إدارة (جميع الأذونات لهذا النوع من الموارد) + read: + explanation: القدرة على رؤية العائلات + label: عرض + write: + explanation: القدرة على الضغط على زر "تعديل" وتحديث المعلومات الخاصة بالعائلة والنقر على "حفظ". + label: تعديل + sync_mobile: + explanation: يسمح للمستخدم بتخزين سجلات العائلة مؤقتًا للاستخدام دون الاتصال بالإنترنت. + label: وضع علامة على غير متصل + close: + explanation: يسمح للمستخدم بتعيين حالة عائلة مفتوحة إلى مغلقة. + label: غلق + reopen: + explanation: يمكن أن تساعد هذه الحالات على فتح أبوابها. + label: إعادة فتح + case_from_family: + explanation: يسمح للمستخدمين بإنشاء حالة جديدة من نموذج فرعي لأعضاء العائلة داخل سجل العائلة. + label: إنشاء حالة + label: العائلة report: actions: create: explanation: القدرة على إنشاء تقرير جديد. عندما يُنشئ المستخدم تقريرًا، يصبح مرئيًا لجميع المستخدمين الذين لديهم حق الوصول "للقراءة" أو "قراءة المجموعة" في التقارير. label: إنشاء group_read: - explanation: القدرة على عرض جميع التقارير. ستعكس الأرقام في كلّ تقرير فقط السجلات التي يمكن الوصول إليها من قبل المستخدمين في مجموعات المستخدمين المستخدم الحالي. غالبًا ما يستخدم هذا الإذن للمسؤولين المحليين أو الإقليميين أو الوكالات الذين يتطلعون إلى الإطلاع على أداء فرقهم أو منظماتهم. يمنح هذا الإذن المستخدم أيضًا القدرة على تصدير البيانات من تقرير معيّن. + explanation: القدرة على عرض جميع التقارير. ستعكس الأرقام في كلّ تقرير فقط السجلات التي يمكن الوصول إليها من قبل المستخدمين في مجموعات المستخدمين المستخدم الحالي. غالبًا ما يستخدم هذا الإذن للمسؤولين المحليين أو الإقليميين أو الهيئات الذين يتطلعون إلى الإطلاع على أداء فرقهم أو منظماتهم. يمنح هذا الإذن المستخدم أيضًا القدرة على تصدير البيانات من تقرير معيّن. label: عرض (البيانات المستندة إلى المجموعة) manage: explanation: يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة للوكالات. يعني إذْن "الإدارة" بشكل أساسي "كل شيء". @@ -2871,8 +3187,8 @@ ar: explanation: القدرة على تعديل كلّ التقارير (بما في ذلك تلك التي أنشأها مستخدمون آخرون). label: تعديل agency_read: - explanation: القدرة على عرض جميع التقارير. ستعكس الأرقام الواردة في كل تقرير فقط تلك السجلات التي يمكن الوصول إليها من قبل المستخدمين في وكالة المستخدم الحالية. غالبًا ما يستخدم هذا الإذن لمسؤولي نظام الوكالة. - label: عرض (البيانات المستندة إلى المنظمة) + explanation: القدرة على عرض جميع التقارير. ستعكس الأرقام الواردة في كل تقرير فقط تلك السجلات التي يمكن الوصول إليها من قبل المستخدمين في الهيئة المستخدمة الحالية. غالبًا ما يستخدم هذا الإذن لمسؤولي نظام الهيئة. + label: عرض (البيانات المستندة إلى الهيئة) explanation: أداة تحليل البيانات المجمعة. يشمل تمثيلات الجدول والرسم البياني للبيانات. label: تقرير reporting_location_level: @@ -2896,7 +3212,7 @@ ar: explanation: 'يسمح للمستخدم بتنفيذ جميع الإجراءات المتاحة على الأدوار. إذن "الإدارة" يعني أساسًا "كل شيء". هام: يمنح هذا الإذن أيضًا القدرة على إنشاء أدوار وحذفها.' label: إدارة (كافة الأذونات لهذا النوع من الموارد) permitted_roles: - explanation: إذا كان لدور ما القدرة على تنفيذ أي من الإجراءات المذكورة أعلاه على دور، فسيكون قادرًا على تنفيذ تلك الإجراءات على الأدوار المحددة في هذه القائمة. لذلك، على سبيل المثال، إذا كان الدور لديه إذن "قراءة" و "تعيين" للأدوار، ولكن تمّ إدراج "الإختصاصي الإجتماعي CP" و "المدير CP" فقط على أنّهما "الأدوار المُدارة"، فسيكون قادرًا فقط على رؤية هذين الدورين وسيكون قادرًا فقط على تعيين مستخدمين جدد لهذين الدورين. إذا لم يتمّ تحديد "الأدوار المُدارة" للدور نفسه، فسيكون قادرًا على رؤية جميع الأدوار وسيكون قادرًا على إنشاء حسابات مستخدمين جديدة بأي دور في النظام. + explanation: إذا كان لدور ما القدرة على تنفيذ أي من الإجراءات المذكورة أعلاه على دور، فسيكون قادرًا على تنفيذ تلك الإجراءات على الأدوار المحددة في هذه القائمة. لذلك، على سبيل المثال، إذا كان الدور لديه إذن "قراءة" و "تعيين" للأدوار، ولكن تمّ إدراج "اخصائي الحالة CP" و "المدير CP" فقط على أنّهما "الأدوار المُدارة"، فسيكون قادرًا فقط على رؤية هذين الدورين وسيكون قادرًا فقط على تعيين مستخدمين جدد لهذين الدورين. إذا لم يتمّ تحديد "الأدوار المُدارة" للدور نفسه، فسيكون قادرًا على رؤية جميع الأدوار وسيكون قادرًا على إنشاء حسابات مستخدمين جديدة بأي دور في النظام. label: الأدوار الأخرى التي يديرها هذا الدور read: explanation: القدرة على إنشاء الأدوار @@ -2911,7 +3227,7 @@ ar: manage: explanation: القدرة على رؤية المعلومات وتحديثها ضمن معلومات الاتصال في النظام والإشعارات الافتراضية وإعدادات البريد الإلكتروني والإعداد الترحيبية والخوادم المتزامنة. عادة ما يكون هذا الإذن مخصّصًا لمسؤول النظام label: إدارة (كافة الأذونات لهذا النوع من الموارد) - explanation: إعدادات التكوين المتنوعة على مستوى النظام. + explanation: ' الإعدادات المتنوعة على مستوى النظام.' label: النظام tracing_request: actions: @@ -2948,6 +3264,9 @@ ar: flag: explanation: القدرة على إضافة علم إلى طلب تتبّع. يمكن للمستخدمين الذين لديهم هذا الإذن أيضًا إزالة العلامات التي أضافوها إلى إحدى طلبات التتبّع. label: تمييز بعلامة + resolve_any_flag: + explanation: يسمح للمستخدم بحل أي علامة في السجل، بغض النظر عمن قام بإنشاء العلامة. + label: حل أية علامة import: explanation: يسمح للمستخدم بإنشاء حالة واحدة جديدة أو أكثر من خلال استيرادها من ملف CSV أو Excel أو JSON. يجب أن يكون الملف المستورد مهيّأ *جدًّا* وخصوصًا حتى يتمّ استيراد المعلومات بشكل صحيح. يجب أن تكون هذه الوظيفة متاحة فقط للمستخدمين الإداريين ذوي المهارات التقنية المتقدّمة والمعرفة العميقة بكيفية تهيئة البيانات في Primero. يتمّ تنفيذها فقط من صفحة قائمة الحالة. label: استيراد @@ -2971,8 +3290,8 @@ ar: user: actions: agency_read: - explanation: القدرة على رؤية حسابات المستخدمين في وكالة المستخدم الحالية فقط. يؤثر هذا أيضًا على حسابات المستخدمين التي يمكن للمستخدم الحالي تنفيذ إجراءات أخرى عليها. على سبيل المثال ، إذا كان المستخدم الحالي لديه إذن "كتابة" على المستخدمين، ولكن لديه أيضًا إذن قراءة الوكالة، فسيكون قادرًا فقط على تعديل حسابات المستخدمين الموجودة في وكالته الخاصة. وبالمثل، إذا كان المستخدم الحالي لديه إذن "إدارة" للمستخدمين، ولكن لديه إذن "قراءة الوكالة"، فسيكون قادرًا فقط على إنشاء مستخدمين لوكالته الخاصة. - label: عرض (ضمن الوكالة) + explanation: القدرة على رؤية حسابات المستخدمين في الهيئة المستخدمة الحالية فقط. يؤثر هذا أيضًا على حسابات المستخدمين التي يمكن للمستخدم الحالي تنفيذ إجراءات أخرى عليها. على سبيل المثال ، إذا كان المستخدم الحالي لديه إذن "كتابة" على المستخدمين، ولكن لديه أيضًا إذن قراءة الهيئة، فسيكون قادرًا فقط على تعديل حسابات المستخدمين الموجودة في هيئته الخاصة. وبالمثل، إذا كان المستخدم الحالي لديه إذن "إدارة" للمستخدمين، ولكن لديه إذن "قراءة الهيئة"، فسيكون قادرًا فقط على إنشاء مستخدمين لهيئته الخاصة. + label: عرض (ضمن الهيئة) create: explanation: القدرة على إنشاء حساب مستخدم label: إنشاء @@ -3007,31 +3326,33 @@ ar: write: explanation: القدرة على تعديل مجموعات المستخدمين. label: تعديل - explanation: يمثل فريقًا أو مجموعة متعاونة من المستخدمين الذين يمكنهم مشاركة المعلومات. يمكن للمديرين عادةً رؤية جميع السجلات التي يديرها الأخصائيون الاجتماعيون في مجموعات المستخدمين الخاصة بهم. + explanation: يمثل فريقًا أو مجموعة متعاونة من المستخدمين الذين يمكنهم مشاركة المعلومات. يمكن للمديرين عادةً رؤية جميع السجلات التي يديرها اخصائيون الحالة في مجموعات المستخدمين الخاصة بهم. label: مجموعات المستخدمين webhook: actions: read: label: رؤية/تصفح - explanation: القدرة على سرد ومراجعة تكوينات webhook عبر واجهة برمجة التطبيقات + explanation: القدرة على سرد ومراجعة إعدادات webhook عبر واجهة برمجة التطبيقات write: label: تعديل - explanation: القدرة على إنشاء وتعديل تكوين webhook عبر واجهة برمجة التطبيقات. + explanation: القدرة على إنشاء وتعديل إعدادات webhook عبر واجهة برمجة التطبيقات. create: - explanation: القدرة على إنشاء تكوين webhook عبر واجهة برمجة التطبيقات. + explanation: القدرة على إنشاء إعدادات webhook عبر واجهة برمجة التطبيقات. label: إنشاء delete: - explanation: القدرة على حذف تكوين webhook عبر واجهة برمجة التطبيقات. + explanation: القدرة على حذف إعدادات webhook عبر واجهة برمجة التطبيقات. label: حذف/إزالة manage: label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: يُستخدم لأدوار النظام التي تصل إلى Primero Webhooks للأنظمة الأخرى. لا ينصح باستخدامه لغير المطورين. activity_log: actions: transfer: - explanation: يمكن للمستخدم النقر فوق قسم سجل التغيير/النشاطات في لوحة ملخص البيانات (داشبورد) والاطلاع على سجل بجميع عمليات النقل المقبولة أو المرفوضة للحالات التي يمكنهم الوصول إليها. + explanation: يمكن للمستخدم النقر فوق قسم سجل النشاطات في لوحة ملخص البيانات والاطلاع على سجل بجميع عمليات النقل المقبولة أو المرفوضة للحالات التي يمكنهم الوصول إليها. label: عمليات النقل manage: label: إدارة (كافة الأذونات لهذا النوع من الموارد) + explanation: القدرة على الوصول إلى كافة. label: سجل التغيير potential_match: case_id: هوية الحالة @@ -3043,8 +3364,8 @@ ar: inquiry_date: تاريخ الاستفسار name: الاسم score: النتيجة - social_worker: 'الاخصائي الاجتماعي\ الاخصائية الاجتماعية ' - social_worker_agency: مؤسسة + social_worker: 'اخصائي الحالة ' + social_worker_agency: الهيئة tracing_request_id: معرّف طلبات التتبّع trace: تتبّع likelihood_likely: مرجح @@ -3053,23 +3374,24 @@ ar: display: عرض النتائج المطابقة المحتملة لـ %{type} %{id} reassign: multiple_error: حدث خطأ. لم يتم تعيين الحالة (الحالات) %{select_records}. - multiple_successfully: 'تم تعيين الحالة (الحالات) %{select_records} بنجاح' + multiple_successfully: Primero يحدث في هذه الاثنات الحالات % {select _ records} . قد يستغرق تحديث كل هذه الحالات عدة دقائق. notes_label: ملاحظات successfully: تمت إعادة التعيين بنجاح user_mandatory_label: يجب إدخال إسم المستلِم users_label: المستلِم + incident_from_case_warning: لا يمكنك تعيين هذه الحادثة، لأنها مرتبطة بالفعل بحالة ما. عندما تقوم بتعيين الحالة، يتم تعيين الحادث أيضًا. record_information: assigned_user_names: 'المستخدمين الأخرين ' created_at: تم إنشاء السجل في created_by: تم إنشاء السجل بواسطة - created_organization: 'تم الإنشاء بواسطة مؤسسة/ منظمة ' + created_organization: تم الإنشاء بواسطة الهيئة current_owner_separator: المالك الحالي module_id: وحدة - owned_by: 'رمز الاخصائي الاجتماعي ' - owned_by_agency_id: وكالة - owned_by_text: الحقل/حالة/اختصاصي إجتماعي + owned_by: 'كود اخصائي الحالة ' + owned_by_agency_id: الهيئة + owned_by_text: الحقل/حالة/اخصائي الحالة previously_owned_by: المستخدم السابق - previously_owned_by_agency: 'المنظمة السابقة ' + previously_owned_by_agency: 'الهيئة السابقة ' reassigned_tranferred_on: إعادة التعيين / التحويل في record_history_separator: تسجيل التاريخ last_updated_at: تاريخ اخر تحديث @@ -3079,7 +3401,9 @@ ar: referral: type_of_recipient: نوع المستلِم type_of_referral_required: مطلوب إدخال نوع الإحالة - agency_label: مؤسسة + referral_authorization_label: هل ترغب في تحديد نوع الإحالة؟ + referral_authorization_help_text: سيؤدي هذا إلى تحديد النماذج التي يمكن للمستلم الوصول إليها. + agency_label: الهيئة is_remote_label: هل ترغب في احالة الحالة لمؤسسة من خارج النظام؟ location_label: الموقع notes_label: ملاحظات @@ -3140,6 +3464,7 @@ ar: record_type: نوع السجل total: الإجمالي value: قيمة + incomplete_data: بيانات غير مكتملة reports: delete_report: حذف التقرير delete_report_message: هل أنت متأكد أنك تريد حذف هذا التقرير؟ لا يمكن التراجع عن الحذف. انقر فوق تمّ لحذف التقرير. @@ -3178,7 +3503,7 @@ ar: successfully_updated: تم تحديث تفاصيل الدور بنجاح. transfer_label: هل يمكن استخدام هذا الدور لعمليات النقل؟ hide: إخفاء - read: تبين + read: عرض read_write: عرض وتحرير roles: label: دور المستخدم @@ -3195,9 +3520,9 @@ ar: save_search: عملية بحث محفوظة settings: navigation: - agencies: الوكالات + agencies: الهيئات audit_logs: سجلات التدقيق - configurations: تضبيطات + configurations: إعدادات contact_information: معلومات الاتصال forms: النماذج locations: المواقع @@ -3221,7 +3546,7 @@ ar: priority: مستوى الأولوية status: الوضع statuses: - overdue: متأخة + overdue: متأخرة upcoming_soon: أوشك على الاستحقاق type: نوع الإجراء types: @@ -3315,9 +3640,45 @@ ar: title: وضع علامة على عدم الاتصال بالانترنت text: هل أنت متأكد أنك تريد وضع علامة على سجلات التسجيل هذه لاستخدامها عندما تكون غير متصل؟ success: تم وضع علامة على سجلات التسجيل بنجاح للاستخدام دون اتصال بالانترنت + families: + id: بطاقة تعريف + label: العائلة + family_id: معرف العائلة + family_number: رقم العائلة + family_name: اسم العائلة + family_registration_date: تاريخ التسجيل + family_location_current: مكان العائلة + export: استيراد + register_new_family: عائلة جديدة + show_family: 'رقم ملف العائلة %{short_id}' + disable_dialog_title: سجل عائلة معطل + disable_dialog: سيؤدي النقر فوق "موافق" إلى تغيير حالة هذه العائلة إلى "معطل". + selected_records: '%{select_records} سجل (سجلات) عائلية تم اختيارها' + selected_all_records: 'حدد جميع %{total_records} العائلات التي تطابق هذا الاستعلام.' + mark_for_offline: + title: وضع علامة على غير متصل + text: هل أنت متأكد من أنك تريد وضع علامة على سجلات العائلة هذه لاستخدامها عندما تكون غير متصل بالإنترنت؟ + success: تم وضع علامة على سجلات العائلة بنجاح للاستخدام دون اتصال + filter_by: + by_date: ب تاريخ + status: الوضع + current_location: مكان العائلة + family: + family_member: + case_id: معرف الحالة + update_and_return: التحديث والعودة + save_and_return: إضافة والعودة + create_case: إنشاء حالة + back_to_family_members: العودة إلى أعضاء العائلة + create: إنشاء + messages: + update_success: 'تم تحديث ملف العائلة رقم % {record _ id} بنجاح.' + creation_success: 'تم إنشاء سجل العائلة بنجاح.' + disabled: العائلة معطلة + confirm_create_case: هل تريد إنشاء حالة لهذا الشخص؟ transfer: label: نقل - agency_label: مؤسسة + agency_label: الهيئة consent_from_individual_label: هل حصلت على موافقة الشخص لإجراء هذا التحويل؟ consent_label: لم توفر السجلات الموافقة. consent_override_label: هل ترغب في تجاوز تعبئة نموذج الموافقة؟ @@ -3334,7 +3695,7 @@ ar: transfer_assignment: title: عمليات النقل والتعيينات transition: - agency_label: وكالة + agency_label: الهيئة assigned_by: تعيين من قِبَل consent_individual_transfer_value: true_label: 'نعم' @@ -3360,6 +3721,7 @@ ar: inprogress: معلّقة rejected: رُفض revoked: تم الغاء او ملغي + transferred_by: منقول بواسطة type: assign: تعيين reassign: تعيين @@ -3368,8 +3730,8 @@ ar: transfer: تحويل transferRequest: طلب التحويل user: - agency_office: مكتب المؤسسة (موقع العنف المبني على النوع الاجتماعي) - code: 'رمز المستخدم ' + agency_office: مكتب الهيئة (موقع العنف المبني على النوع الاجتماعي) + code: 'كود المستخدم ' disabled: 'مُعطلة ' email: البريد الإلكتروني full_name: الاسم الكامل @@ -3380,6 +3742,7 @@ ar: locale: موضع location: الموقع messages: + records_update: يقوم Primero بتحديث سجلات هذا المستخدم لتعكس التغييرات التي أجريتها. قد يستغرق تحديث لوحات المعلومات والتقارير بعض الوقت. confirmation: 'هل أنت متأكد أنك تريد حذف هذا المستخدم؟ لا يمكن التراجع عن الحذف. انقر فوق موافق لحذف المستخدم. ' created: تم إنشاء المستخدم بنجاح. failure: حدث خطأ، يرجى الاتصال بالدعم. @@ -3390,9 +3753,10 @@ ar: passwords_do_not_match: لا تطابق كلمة المرور الحالية time_zone_updated: تم تحديث التغيير بنجاح. updated: تم تحديث المستخدم بنجاح. + created_warning: لقد قمت بإنشاء% {إجمالي _ تمكين} من% {الحد الأقصى _ المستخدمين} المسموح للمستخدمين. organization: المنظمة - agency: وكالة - services_help_text: إذا لم تحدّد الخدمات، سيتم منح هذا المستخدم نفس الخدمات التي تتوفر لوكالته. + agency: الهيئة + services_help_text: إذا لم تحدّد الخدمات، سيتم منح هذا المستخدم نفس الخدمات التي تتوفر لهيئته. password_setting: label: كيف يجب على بريميرو Primero تعيين كلمة مرور المستخدم؟ self: سوف أقوم بتعيين كلمة المرور @@ -3408,6 +3772,21 @@ ar: provider_username_help: 'مثلاً: %{domain}@my.username' role_id: دور send_mail: استلام إشعارات عبر الايميل؟ + send_mail_preferences: + label: ما أنواع إشعارات البريد الإلكتروني التي ترغب في تلقيها؟ + help_text: إذا تركت هذا الحقل فارغًا، فستتلقى جميع إشعارات البريد الإلكتروني. + receive_webpush: + label: تلقي الإخطارات؟ + help_text: لاحظ أنك ستظل بحاجة إلى السماح بدفع الإشعارات على متصفح جهازك. + tooltip: يجب عليك أولاً تعديل حسابك وتمكين الإشعارات المباشرة للمستخدم الخاص بك. + receive_webpush_preferences: + label: ما هي أنواع الإشعارات الفورية التي ترغب في تلقيها؟ + help_text: إذا تركت هذا الحقل فارغًا، فستتلقى جميع الإشعارات الفورية. + notification_preferences: + approval_request: 'طلب الموافقة (المديرين)' + approval_response: 'الاستجابة للموافقة (اخصائيون الحالة)' + transition_notification: 'التعيينات والانتقالات والإحالات' + transfer_request: 'طلب نقل' user_group_unique_ids: مجموعات المستخدمين user_name: اسم المستخدم services: الخدمات @@ -3439,7 +3818,7 @@ ar: request_submitted: "تم إرسال طلب إعادة تعيين كلمة المرور" success: "تمّ تغيير كلمة المرور بنجاح" errors: - reset_password_token: "رمز إعادة تعيين كلمة المرور غير صالح" + reset_password_token: "كود إعادة تعيين كلمة المرور غير صالح" password_confirmation: "يجب أن تتطابق كلمات المرور" onboard_email: subject: "الإنضمام إلى %{system}" @@ -3449,7 +3828,7 @@ ar: body2_reset_notification: "ستتلقى رسالة بريد إلكتروني إضافية تطالبك بإعادة تعيين كلمة المرور الخاصة بك." body3: "أنت مسؤول عن ضمان التنفيذ الآمن وفي الوقت المناسب. لكلّ عملية مطروحة، يجب أن تكون قد أكملت خطة التنفيذ مع إستراتيجية إدارة المستخدم والإنضمام وبروتوكول مشاركة المعلومات. أنت مسؤول أيضًا عن ضمان توقيع شروط الاستخدام من قبل جميع المنظمات المُستخدمة ووضع الشروط الموقعة في ملفّ المنظمات." user_group: - associated_agencies: المؤسسات المرتبطة بمجموعة المستخدمين هذه + associated_agencies: الهيئات المرتبطة بمجموعة المستخدمين هذه description: الوصف disabled: explanation: إذا قمت بتعطيل مجموعة المستخدمين هذه، لن تتمكن من تعيينها إلى حسابات المستخدمين. @@ -3466,7 +3845,11 @@ ar: full_name: الاسم الكامل user_name: اسم المستخدم position: الوظيفة - agency: وكالة + agency: الهيئة + alerts: + total_users_created: 'لقد قمت بإنشاء% {إجمالي _ تمكين} من التطبيق % {الحد الأقصى _ المستخدمين} ' + limit_user_reached: لقد وصلت إلى حد% {الحد الأقصى _ المستخدمين} للمستخدمين. يجب عليك تعطيل مستخدم واحد أو أكثر قبل إنشاء المزيد. + limit_user_reached_on_enable: لقد وصلت إلى الحد الأقصى للمستخدمين %{maximum_users} . يجب عليك تعطيل مستخدم واحد أو أكثر قبل إنشاء أو تمكين المزيد. devise: failure: already_authenticated: "انت مُسجّل مسبقا." @@ -3478,3 +3861,16 @@ ar: selected_records: '%{select_records} الموقع (المواقع) المحدد/ة' selected_all_records: اختيار كلّ %{total_records}الحالات التي تطابق هذا الاستعلام. updated: '%{updated_records} تحديث الموقع(المواقع)' + push_notifications_dialog: + title: إشعارات الجهاز + body_blocked: + message: لقد قمت بحظر إشعارات Primero على هذا الجهاز. لإصلاح هذه المشكلة، ستحتاج إلى تشغيل إشعار الأذونات. + android: "أندرويد: انتقل إلى الإعدادات. انقر على التطبيقات. ابحث عن Primero في قائمة التطبيقات وانقر فوقه. انقر فوق الإخطارات. قم بتبديل مفتاح التبديل للإشعارات إلى وضع التشغيل." + ios: "iOS: انتقل إلى تطبيق الإعدادات. انقر على الإخطارات. قم بالتمرير لأسفل إلى قائمة التطبيقات وابحث عن Primero. قم بتبديل مفتاح التبديل لـ Primero إلى وضع التشغيل." + body: + zero: '0' + one: '1' + two: '2' + few: قليل + many: كثير + other: هل تريد السماح لـ Primero بإرسال إشعارات لك ؟ تذكر أنك ستستمر في تلقي الإشعارات على هذا الجهاز بعد%{count} أيام من تسجيل الخروج. هذا غير موصى به للأجهزة المستخدمة من قبل اكثر من شخص. diff --git a/config/locales/bn.yml b/config/locales/bn.yml index b1a9362000..3249047e93 100644 --- a/config/locales/bn.yml +++ b/config/locales/bn.yml @@ -1724,20 +1724,7 @@ bn: date_of_first_report: সাক্ষাৎকারের তারিখ incident_date: ঘটনার তারিখ reports: - incidents: ঘটনাসমূহ perpetrators: অপরাধীরা - sub_reports: - combined: ঘটনাসমূহ - total: রিপোর্ট করা GBV ঘটনার সংখ্যা - gbv_sexual_violence: যৌন সহিংসতার ঘটনার সংখ্যা রিপোর্ট করা হয়েছে - gbv_previous_incidents: পূর্ববর্তী GBV ঘটনার সাথে বেঁচে থাকা ব্যক্তিদের দ্বারা রিপোর্ট করা ঘটনাগুলির সংখ্যা - gbv_sexual_violence_type: ঘটনার ধরন - incident_timeofday: দিনের ঘটনার সময় - elapsed_reporting_time: ঘটনা এবং প্রতিবেদনের তারিখের মধ্যবর্তী সময় - elapsed_reporting_time_rape: ধর্ষণের ঘটনা, ঘটনা এবং প্রতিবেদনের তারিখের মধ্যে সময় অতিবাহিত হয়েছে - incident_location_type: ঘটনার অবস্থান - perpetrator_age_group: অভিযুক্ত প্রাথমিক অপরাধীদের বয়স গ্রুপ - perpetrator_occupation: অভিযুক্ত প্রধান অপরাধী পেশা messages: alert_items: আপনার আছে %{items}জিনিসপত্রের চিহ্ন। alerts_for: @@ -2359,7 +2346,6 @@ bn: display: ১% [টাইপ] এবং ২% [আইডি] এর জন্য সম্ভাব্য মিলগুলো প্রদর্শন করুন। reassign: multiple_error: একটি ত্রুটি ঘটেছে। %{select_records}কেস(গুলি) বরাদ্দ করা হয়নি। - multiple_successfully: '%{select_records}কেস(গুলি) সফলভাবে বরাদ্দ করা হয়েছে৷' notes_label: নোটসমুহ successfully: সফলভাবে পুনরায় বরাদ্দ করা হয়েছে৷ user_mandatory_label: প্রাপক আবশ্যক diff --git a/config/locales/cmn.yml b/config/locales/cmn.yml index 06d9546cee..a6666339ec 100644 --- a/config/locales/cmn.yml +++ b/config/locales/cmn.yml @@ -84,6 +84,7 @@ cmn: terms_of_use_download_button: 下载PDF terms_of_use_enabled: 显示使用条款? approvals: + no_requests: 该个案没有审批请求 approved_by: 批准人 case_plan_type_label: 个案计划类型 manager_comments_label: 督导意见 @@ -98,8 +99,8 @@ cmn: status: approved: 已批准 pending: 待定 - rejected: 拒绝 - requested: 请求 + rejected: 已拒绝 + requested: 已请求 audit_log: action: 行动 description: 说明 @@ -122,7 +123,7 @@ cmn: add: 添加 add_another_option: 添加另一个选项 add_note: 添加备注 - apply: 申请 + apply: 应用 approvals: 批准 approve_action_plan: 批准行动计划 approve_bia: 批准最佳利益评估 @@ -166,6 +167,7 @@ cmn: import: 导入 login: 登录 logout: 登出 + link: 连接 mark_for_mobile: 移动设备标记 new: 新 ok: 好的 @@ -201,7 +203,7 @@ cmn: enable_webpush: 设备通知 dialog_yes: "是" resync_records: - id: 身份证号 + id: 个案编号 record_type: 记录类别 action: 行动 date: 日期 @@ -214,7 +216,7 @@ cmn: create_new_case: 创建新个案 create_case: 创建个案 create: 创建 - add_new: 创建新 + add_new: 添加 back_to_family_details: 返回家庭详情 back_to_case: 返回个案 back_to_results: 返回结果 @@ -225,7 +227,7 @@ cmn: details: 详细信息 select: 选择 deselect: 取消选择 - enter_id_number: 输入 ID 编号以搜索现有记录 + enter_id_number: 输入个案编号以搜索现有记录 id_search_no_results: 系统中没有匹配的"%{search_query}"。请创建新记录。 messages: disabled: 个案不可用 @@ -240,13 +242,13 @@ cmn: consent_agreements_required: 请从同意协议中选择至少一项。 legitimate_basis_required: 请从合法的基础分类中至少选择一项。 confirm_create_case: 您要为此人创建一个个案吗? - case_referral_pending: 案件转介待定。 - case_transfer_pending: 案件移交待定。 + case_referral_pending: 个案转介待定。 + case_transfer_pending: 个案移交待定。 case_no_approval_request: 本个案无审批申请。 bulk_assign_limit: 您不能同时分配超过 100 个个案。 bulk_assign_limit_try_again: 您不能同时分配超过 100 个个案。请选择 100 个或更少的个案,然后重试。 referral_rejected: 转介已被拒绝。 - transfer_request_made: 已为此案提出移交申请。 + transfer_request_made: 已为该个案提出移交申请。 save: 保存个案 save_text: 在继续之前,请保存您对个案所做的更改。 skip_and_create: 跳过并创建新个案 @@ -264,8 +266,8 @@ cmn: new: 新 on_label: '上' reopened: 已重新开案 - service_implemented: 已实施的服务 - services_implemented: 已实施的服务 + service_implemented: 服务已实施 + services_implemented: 服务已实施 linkedincidents: label: 已关联事件 activity_log: @@ -278,7 +280,7 @@ cmn: age: 年龄 age_estimated: 估计的年龄? agency: 机构 - apply_filter: 申请 + apply_filter: 应用 approval_comments: 评论 approval_radio: 我希望 approval_radio_accept: 批准 @@ -297,8 +299,8 @@ cmn: clear_filter: 清除 close_dialog: 单击 "确定 "将把此个案的状态更改为 "已结案"。 close_dialog_title: 结案 - close_success: 结案成功 - closure: 关闭 + close_success: 成功关闭个案 + closure: 结案 complete: 离线可用 date_of_birth: 出生日期 disable_dialog: 单击 "确定 "将把此个案的状态更改为"禁用"。 @@ -330,8 +332,8 @@ cmn: by_date: 按日期 case_open_date: 个案开案日期 case_plan: 个案计划 - closed: 已关闭 - closure: 关闭 + closed: 已结案 + closure: 结案 current_location: 当前位置 date: 日期 displacement_status: 流离失所情况 @@ -359,7 +361,7 @@ cmn: protection_status: 保护状态 record_state: 记录状态 referred_cases: 转介给我的个案 - registration_date: 注册日期 + registration_date: 登记日期 risk_level: 风险等级 sex: 性别 social_worker: 现场/个案/社工 @@ -369,12 +371,13 @@ cmn: urgent_protection_concern: 保护方面的紧急关切 user_group: 用户组 workflow: 按工作流程分类的个案 + include_disabled: 包括已禁用 flag_summary: 标记摘要 full_name: 全名 gbv_closure: GBV结案 hide_name: 隐藏姓名 hide_name_error: 保存更改时出现错误。请重试。 - id: 身份证号# + id: 个案编号 label: 个案 my_filters: 我的筛选器 name: 名称 @@ -392,6 +395,8 @@ cmn: photos: 照片 quick_view: tracing_message: '注意:系统中有一位查询者正在寻找这名儿童。如果该儿童愿意,请联系此记录的社工以采取进一步行动。' + reassign: + multiple_successfully: Primero 正在重新分配 %{select_records} 个案。这些个案可能需要几分钟才能完成更新。 referral_done: 单击 "完成 "表示您已完成与此个案相关的转介工作。点击 "完成 "后,您将无法再访问此记录。 referral_done_success: 转介已完成。 referral_accepted_header: 接受转介 @@ -400,7 +405,7 @@ cmn: referral_rejected: 单击 "拒绝 "表示您目前尚未准备好接受此转介的责任。请输入您拒绝此转介的理由;一旦点击 "拒绝",您将无法再访问此个案记录。 referral_rejected_success: 转介已拒绝。 register_new_case: 新个案 - registration_date: 注册日期 + registration_date: 登记日期 rejected_success_action_plan: '%{approval_label} - 未批准' rejected_success_assessment: '%{approval_label} - 未批准' rejected_success_bia: '%{approval_label} - 未批准' @@ -429,6 +434,7 @@ cmn: save_filter: 保存 selected_all_records: 选择与此查询匹配的所有%{total_records}案例。 selected_records: '已选定%{select_records}个个案' + selected_records_assign: '已选择%{select_records}个个案' sex: 性别 show_case: '个案编号:%{short_id}' social_worker: 社工 @@ -460,7 +466,7 @@ cmn: transfer_accepted: 点击 "接受 "后,您将接受对该案件的责任;点击 "接受 "后,您将成为系统中记录的所有者。 transfer_managed_user_accepted: 如果您点击 "接受",%{transitioned_to}将成为此案件的负责人;一旦您点击 "接受",%{transitioned_to}·将成为系统中记录的所有者。 transfer_managed_user_rejected: 单击 "拒绝 "表示%{transitioned_to}目前还不准备承担此个案的责任。请输入拒绝接受此个案的理由;一旦点击 "拒绝",%{transitioned_to}将无法再访问此个案记录。 - transfer_accepted_rejected: 案件%{record_id}移交被拒绝。 + transfer_accepted_rejected: 个案%{record_id}移交被拒绝。 transfer_accepted_success: 成功接受个案移交。 transfer_reject_reason_label: 拒绝原因 transfer_rejected: 单击 "拒绝 "表示您目前尚未准备好接受此个案的责任。请输入您拒绝此个案的理由;一旦点击 "拒绝",您将无法再访问此个案记录。 @@ -486,9 +492,9 @@ cmn: assessment_requested_on: 评估日期 closure_approved_date: '结案日期 ' created_at: 个案开始日期 - date_case_plan_initiated: 个按计划日期 + date_case_plan_initiated: 个案计划日期 date_of_creation: 创建日期 - registration_date: 注册日期 + registration_date: 登记日期 configurations: apply_label: 您确定吗?如果应用,此配置中的设置将应用于系统。您将丢失当前的所有设置,并且无法恢复,除非您已将其保存在另一个配置中。 apply_label_bold: 在更改加载期间,用户将有几分钟无法使用 Primero。 @@ -500,7 +506,7 @@ cmn: date_created: 创建日期 description: 描述 last_applied_by: 最近应用者 - last_applied_on: 最后应用日期 + last_applied_on: 最近应用日期 name: 名称 version: 配置版本 primero_version: Primero版本 @@ -547,7 +553,7 @@ cmn: approval_action_plan_approved: 已批准 approval_action_plan_pending: 待定 approval_action_plan_pending_group: 行动计划 - approval_action_plan_rejected: 否决 + approval_action_plan_rejected: 已拒绝 approval_assessment_approved: 已批准 approval_assessment_pending: 待定 approval_assessment_pending_group: 评估 @@ -641,8 +647,8 @@ cmn: flagged_by: '标记者' flagged_by_me: 由我标记 flagged_by_other: 由他人标记 - flagged_cases: 标记个案 - follow_up: 后续行动 + flagged_cases: 已标记个案 + follow_up: 跟进 forms: 表格选项卡 geographic_area: 地理区域 group_overview_closed: 已结案 @@ -685,7 +691,7 @@ cmn: no_caseworker_data: 无个案社工数据 no_flagged_child: 无标记个案 no_flagged_incident: 无标记事件 - no_open_incidents: 无未决事件 + no_open_incidents: 无在开案事件 no_overdue_activities: 无逾期活动 no_recent_activities: 近期无活动 no_scheduled_activities: 无预定活动 @@ -694,8 +700,8 @@ cmn: number_of_violations: 违规次数 number_of_violations_verified: 已核实的违规行为 open: 开案 - open_cases: 开案个案 - open_incidents: 未决事件 + open_cases: 在开案个案 + open_incidents: 在开案事件 outstanding_transfers: 重要的移交 overdue_activities: 逾期活动 overdue_cases_to_assign: 逾期待分配个案 @@ -715,7 +721,7 @@ cmn: recently_flagged_child: 最近标记的案例 recently_flagged_incident: 最近标记的事件 referrals_by_social_worker: 按社工分列的转介 - registration: 注册 + registration: 登记 rejected: 已拒绝 rejected_transfers: 拒绝移交 response: 响应(进行中) @@ -723,7 +729,7 @@ cmn: score_range: 分值范围 screening_service: 筛查服务 services: 服务 - services_implemented: 已实施的服务 + services_implemented: 服务已实施 shared_from_my_team_pending_transfers: 待处理的移交 shared_from_my_team_referrals: 转介 shared_from_my_team_rejected_transfers: 已退回的移交 @@ -826,6 +832,8 @@ cmn: errors: api: internal_server: 服务器出错 + attachments: + maximum: 您已经达到个案最大附件数量。 error_loading: 加载记录时出错 models: agency: @@ -912,7 +920,7 @@ cmn: include_agency_logo: 是否包含机构标识? include_other_logos: 包括其他标识? duplicate_id_csv: - all: 重复 ID + all: 重复个案编号 female_abbreviation: 女 headers: age: 年龄 @@ -958,6 +966,7 @@ cmn: subforms: '子表格:%{subform_name}' collapsed_fields: '收缩的字段:%{fields}' country: 国家 + linkedincidents: 已链接的事件 summary_header: form_group: Primero表格组 form: Primero 表格 @@ -983,7 +992,7 @@ cmn: selected: 选择至违反监测和报告机制 no_records: 无相关记录! pdf: - all: 无加密PDF + all: PDF(未加密) one: PDF selected: 选定为 PDF 格式 pdf_exports: @@ -1025,7 +1034,7 @@ cmn: date_of_identification: 识别日期 family_count_no: 家庭数量 governorate_country: 省份 - 国家 - id: 身份证号 + id: 个案编号 individual_progress_id: 个人进度标识 locations_by_level: 地址(营地、街区和其他适用的地址级别,如避难所 GPS 坐标) long_id: 长 ID @@ -1083,14 +1092,16 @@ cmn: add_existing_field: 添加现有字段 add_field: 添加字段 add_field_type: 添加%{file_type} + attachments: + maximum_attached: 已达到单个记录附件数量最大值(%{maximumttachmentsPerRecord}),包括照片、音频和文件。请在添加新附件之前删除现有附件。 audio: current: 当前音频 audio_upload_box: 音频上传 bia_document: 最佳利益评估文件 bid_document: 最佳利益决定文件 check_box: 复选框 - clear_group_by: 清除小组方式 - clear_sort_by: 清除排序方式 + clear_group_by: 清除用于组合的字段 + clear_sort_by: 清除用于排序的字段 copy_from_another_form: 该字段从另一个表格复制而来 create_field: 创建字段 create_unique_values: 创建唯一值 @@ -1102,8 +1113,8 @@ cmn: date_range: date: 日期 date_range: 日期范围 - from: 来自 - to: 给 + from: 从 + to: 到 view_by: 查看方式 date_range_field: 日期范围 date_time: 日期-时间 @@ -1186,7 +1197,7 @@ cmn: show_on: 显示 show_on_minify_form: 简表 skip_logic: - name: 略过逻辑? + name: 跳转逻辑? record_section: title: 若记录,本字段应可见 buttons: @@ -1221,7 +1232,7 @@ cmn: visibility: 可见度 web_app: 网页应用 filters: - apply_filters: 申请 + apply_filters: 应用 clear_filters: 清除 less: 更少 more: 更多 @@ -1241,14 +1252,14 @@ cmn: flags_tab: 标记 no_flags: 未找到标记 resolve_button: 待解决 - resolve_flag: 待解决标记 - resolve_reason: 待解决原因 - resolved: 已解决标记 + resolve_flag: 解除标记 + resolve_reason: 解除原因 + resolved: 已解除标记 resolved_date: '已解决:' - resolved_reason: '待解决原因:' + resolved_reason: '解除原因:' title: 标记 followup_reminders: - system_generated_followup_flag: 强制性后续随访 + system_generated_followup_flag: 强制跟进 form_section: form_name: 表格名 module: 模块 @@ -1320,7 +1331,7 @@ cmn: visibility: 可见度 web_app: 网页应用 skip_logic: - name: 略过逻辑? + name: 跳转逻辑? section: title: 如果出现以下情况,该表格应可见 buttons: @@ -1334,18 +1345,19 @@ cmn: type: 类型 types: and: - display_text: 而这一条件 + display_text: 以及这一条件 name: 和 or: - display_text: 或这种条件 + display_text: 或这一条件 name: 或 home: ar: 阿拉伯语 - ar-IQ: 英语(伊拉克语) - ar-JO: 英语(约旦语) - ar-LB: 英语(黎巴嫩语) + ar-IQ: 阿拉伯语(伊拉克语) + ar-JO: 阿拉伯语(约旦语) + ar-LB: 阿拉伯语(黎巴嫩语) ar-SD: 阿拉伯语(苏丹语) bn: 孟加拉语 + cmn: 中文 current_time_zone: 当前时区 dashboard: 仪表板 en: 英语 @@ -1384,15 +1396,19 @@ cmn: view_records: 查看记录 welcome: 欢迎来到 Primero zh: 中文 + tet: 德顿语 incident: code: 事件代码 associated_case: "相关个案:" + link_incident_to_case: 将事件关联至个案 + link_incident_to_case_success: 将多个事件关联至个案 messages: creation_success: 成功创建事件记录 creation_success_queue: 在后台成功创建事件记录 disabled: 事件已禁用 update_success: '事件%{record_id}已成功更新。' update_success_queue: '事件%{record_id}已在后台更新成功' + bulk_assign_limit_try_again: 您不能同时分配100个事件。请选取100个或少于100个事件后再尝试。 violation: associated_violations: "相关违规:" update_and_return: '更新并返回至%{association}' @@ -1411,13 +1427,14 @@ cmn: military_use: 学校和/或医院用于军事目的 denial_humanitarian_access: 拒绝让儿童获得人道主义援助 incidents: + change_status: 修改状态 disable_dialog: 单击 "确定 "将把此事件的状态更改为 "已禁用"。 disable_dialog_title: 禁用事件 disable_success: 成功禁用事件 enable_dialog: 单击 "确定 "将把此事件的状态更改为 "已启用"。 enable_dialog_title: 启用事件 enable_success: 成功启用事件 - id: 身份证号# + id: 个案编号 complete: 离线可用 date_of_interview: 面谈日期 date_of_incident: 事件日期 @@ -1459,12 +1476,15 @@ cmn: perpetrator_category: 犯罪者类型 record_owner: 记录所有人 register_new_incident: 新事件 + reassign: + multiple_successfully: Primero正在重新分配%{select_records}个事件。将要花一点时间更新事件。请注意,不会分配已经跟个案关联的事件。 selectable_date_options: date_of_first_report: 面谈日期 mrm_date_of_first_report: 向监测和报告国家工作队成员提交初次报告的日期 ctfmr_verified_date: 监测和报告国家工作队作出核查决定的日期 incident_date_derived: 事件日期 selected_records: '已选定%{select_records}个事件' + selected_records_assign: '已选定%{select_records}个事件。请注意,不会分配已经跟个案关联的事件。' selected_all_records: '选择与此查询匹配的所有%{total_records}事件。' summary_mrm: label: 事件概述 @@ -1489,6 +1509,7 @@ cmn: survivor_code: 幸存者代码 show_incident: '事件编号%{short_id}' social_worker: 社工 + verify_mrm: 验证MRM violation_type: 违规类型 violence_type: 暴力类型 type_violence: 暴力类型 @@ -1499,7 +1520,7 @@ cmn: case_assessment: "个案评估" case_action_planning: "个案行动计划" case_action_plan_implementation: "个案行动计划的实施" - case_follow_up: "个案跟踪" + case_follow_up: "个案跟进" case_closure: "个案结案" feedback: "反馈" other: "其他" @@ -1553,7 +1574,7 @@ cmn: delay: "延迟" total_incidents: "事件总数" assessment_status: - title: "4. 评估状况" + title: "4. 评估状态" completed: "已完成" completed_supervisor_approved: "已完成并获得督导批准" helptext: | @@ -1580,7 +1601,7 @@ cmn: 该指标计算的是已完成个案行动计划并经督导批准的在办个案比例。 当完成行动计划表格中的一组必填字段时,个案行动计划即被视为已完成。当个案社工请求批准个案计划并且督导在平台上批准了该计划时,个案计划被视为已批准。 services_provided: - title: "8. 提供的服务" + title: "8. 已提供的服务" service: "服务" count: "提供的时间" male: "男性" @@ -1617,7 +1638,7 @@ cmn: helptext: | 该指标用于衡量每个报告站点每月结案的数量。报告站点是指用户组织提供服务的地点以及向服务提供方报告事件的地点。 client_satisfaction_rate: - title: "13. Client Satisfaction Rate" + title: "13. 客户满意度" label: "客户满意度" invalid: "目前我们还无法计算。" helptext: | @@ -1640,9 +1661,9 @@ cmn: date_range_dialog: title: "自定义日期范围" description: "一旦应用了这一更改,将从以下两个日期之间选择数据。" - apply: '申请' - from: '开始时间' - to: '结束时间' + apply: '应用' + from: '从' + to: '至' aria-labels: from: "将选出在此日期后的数据" to: "将选出在此日期前的数据" @@ -1676,6 +1697,15 @@ cmn: parish: 教区 cercle: 城市圈 sub-county: 子县 + departement_fr: 'Département' + region_fr: 'Région' + wilaya: 'Wilaya' + commune: '公社' + division_fr: 'Division' + prefecture: '州' + moughataa: 'Moughataa' + sub_division: 'Sub-division' + sub-prefecture: 'Sub-Prefecture' label: 位置 name: 姓名 code: 代码 @@ -1702,11 +1732,11 @@ cmn: bulk_create: 批量创建 bulk_index: 批量索引 case_plan_approved: 个案计划已获批准 - case_plan_rejected: 个案计划已被否决 + case_plan_rejected: 个案计划已被退回 case_plan_requested: 要求制定个案计划 close: 关闭 create: 创建 - create_bulk: 创建大容量 + create_bulk: 批量创建 delete: 删除 destroy: 销毁 detach: 脱离 @@ -1722,8 +1752,8 @@ cmn: password_reset_request: 密码重置请求 refer: 转介 refer_accepted: 转介已接受 - refer_done: 转介已完成。 - refer_rejected: 转介已拒绝。 + refer_done: 转介已完成 + refer_rejected: 转介已拒绝 refer_revoke: 撤回转介 refer_to: 转介给 reopen: 重新开案 @@ -1750,7 +1780,7 @@ cmn: 'true': 批准中 assessment_approved: "%{approval_label} - 批准用于" assessment_requested: "%{approval_label}请求" - bulk_index: List all + bulk_index: 全部列出 by_user: 按用户 case_plan_approved: "%{approval_label} - 批准用于" case_plan_requested: "%{approval_label}请求" @@ -1767,15 +1797,15 @@ cmn: export: 导出数据 flag: 标记 flag_records: 标记 - graph_data: 查看图形数据 + graph_data: 查看图表数据 hide_name: protect: 隐藏名称 view: 查看名称 index: 列出记录 list: 列表 login: 登录 - logout: 注销 - lookups_for_field: 字段查找 + logout: 登出 + lookups_for_field: 字段查询 mark_for_mobile: 'false': 去除移动设备标记 'true': 移动设备标记 @@ -1788,10 +1818,10 @@ cmn: user: 用户 agency: 机构 user_group: 用户组 - child: 孩子 + child: 儿童 alert: 警报 form_section: 表格 - lookup: 查找 + lookup: 查询 system_settings: 系统设置 permission: 许可 dashboard: 仪表板 @@ -1816,7 +1846,7 @@ cmn: request_approval: action_plan: 请求批准行动计划表格 bia: 请求批准 BIA 表单 - case_plan: 请求批准“案例计划”表单 + case_plan: 请求批准个案计划表单 closure: 请求批准结案表单 gbv_closure: 请求批准 GBV 结案表格 request_transfer: 发送移交请求 @@ -1851,10 +1881,10 @@ cmn: email: label: 邮箱 lookup: - create: 新的查找 + create: 新查询 enabled_label: 已启用? english_label: 英语文本 - label: 查找 + label: 查询 language_label: 语言 messages: cannot_create: 无法创建查找 @@ -1862,10 +1892,10 @@ cmn: created: 查找已成功创建。 updated: 查找已成功更新。 name: 姓名 - no_options: 此查找当前没有选项。 + no_options: 此查询当前没有选项。 translation_label: 翻译文本 values: 选项 - locked_alert_message: 此查找已锁定。 + locked_alert_message: 此查询已锁定。 managed_reports: generated_on: 生成于 label: 见解 @@ -1881,9 +1911,13 @@ cmn: user_group: 用户组 agency: 机构 by: 通过 - workflow: Workflow Status + workflow: 工作流程状态 cp_incident_violence_type: 暴力类型 referral_transfer_status: 转介/移交状态 + protection_concerns: 儿童保护担忧 + location: 报告位置 + followup_type: 跟进类型 + service_type: 服务类型 status_options: open: 开案 closed: 已结案 @@ -1916,14 +1950,57 @@ cmn: no_data_table: 此见解不存在任何表数据 incomplete_data: 数据不完整 individual_children: - name: 个别儿童 + name: 儿童个人 + reports: + individual_children: 儿童个人 + sub_reports: + individual_age: 按年龄划分的儿童 + individual_violation_type: 按违规类型划分的儿童 + individual_region: 按地区划分的儿童 + individual_perpetrator: 肇事者分列的儿童 + services: + name: 服务 + description: 有所选服务类型的个案,按年龄和性别分列 + services_report: + reports: + services: 服务 + description: 有所选服务类型的个案,按年龄和性别分列 + sub_reports: + services: 服务 + filter_options: + service_implemented_day_time: 服务已实施 + followups: + name: 跟进 + description: 有所选跟进类型的个案,按年龄和性别分列 + followups_report: + filter_options: + followup_date: 跟进日期 + reports: + followups: 跟进 + description: 有所选跟进类型的个案,按年龄和性别分列 + sub_reports: + followups: 跟进 + protection_concerns: + name: 儿童保护担忧 + description: 有所选保护担忧的个案,按年龄和性别分列 + protection_concerns_report: reports: - individual_children: 个别儿童 + protection_concerns: 儿童保护担忧 + description: 有所选保护担忧的个案,按年龄和性别分列 sub_reports: - individual_age: 按年龄划分的个别儿童 - individual_violation_type: 按违规类型划分的个别儿童 - individual_region: 按地区划分的个别儿童 - individual_perpetrator: 肇事者分列的个别儿童 + protection_concerns: 儿童保护担忧 + filter_options: + registration_date: 登记日期 + reporting_locations: + name: 报告位置 + description: '有所选报告位置的个案,按年龄和性别分列' + reporting_locations_report: + reports: + reporting_locations: 报告位置 + sub_reports: + reporting_location_by_sex_and_age: 报告位置 + filter_options: + registration_date: 登记日期 ghn_report: name: 全球横向说明 reports: @@ -2012,35 +2089,10 @@ cmn: date_of_first_report: 面谈日期 incident_date: 事件日期 reports: - incidents: 事件 perpetrators: 肇事者 survivors: 幸存者 referrals: 转介 sub_reports: - combined: 事件 - total: 报告的 GBV 事件数量 - gbv_sexual_violence: 报告的性暴力事件数量 - gbv_previous_incidents: 既往发生过 GBV 事件的幸存者报告的事件数量 - gbv_sexual_violence_type: 事件类型 - incident_timeofday: 事件时间 - elapsed_reporting_time: 事件和报告日期之间的时间 - elapsed_reporting_time_rape: 强奸事件,事件与报告日期之间经过的时间 - elapsed_reporting_time_rape_health_referral: 强奸事件,事件与报告日期之间经过的时间(卫生服务或转诊) - incident_location_type: 事件地点 - number_of_perpetrators: 肇事者人数 - perpetrator_relationship: 被指控的主要肇事者与幸存者的关系 - perpetrator_age_group: 被指控的主要肇事者年龄组 - perpetrator_occupation: 被指控的主要肇事者职业 - age: 按年龄划分的幸存者人数 - sex: 按性别分列的幸存者人数 - marital_status: 幸存者的婚姻状况 - displacement_status: 幸存者的流离失所状况 - displacement_incident: 事故发生时的流离失所阶段 - gbv_case_context: 个案背景 - incidents_first_point_of_contact: 您的组织作为第一联系人的事件数 - incidents_from_other_service_provider: 从其他服务提供方转介的事件 - number_of_services_provided: 为事件提供的服务数量 - number_of_services_provided_other: 将新事件转介给其他服务提供商 service_safehouse_referral: 安全屋/安全庇护所转介 service_medical_referral: 健康/医疗转介 service_psycho_referral: 社会心理/咨询服务 @@ -2048,20 +2100,30 @@ cmn: service_police_referral: 警察或其他类型的安全服务 service_livelihoods_referral: 生计服务 service_protection_referral: 儿童保护服务 - vulnerable_populations: 弱势群体 survivors_disability_type: 残障人士 workflow_report: name: 工作流程 + description: 有所选工作流程的个案和事件,按年龄和性别分列 reports: - cases_workflow: 工作流 - 个案 - incidents_workflow: 工作流 - 事件 + cases_workflow: 工作流程 - 个案 + incidents_workflow: 工作流程 - 事件 filter_options: registration_date: 注册日期 sub_reports: case_workflow_by_sex_and_age: 按性别和年龄分列的个案总数 incident_workflow_by_sex_and_age: 按性别和年龄分列的事件总数 + cases_workflow_report: + name: 工作流程 + description: 有所选工作流程的个案,按年龄和性别分列 + reports: + cases_workflow: 工作流程 - 个案 + filter_options: + registration_date: 登记日期 + sub_reports: + case_workflow_by_sex_and_age: 按性别和年龄分列的个案总数 referrals_transfers_report: name: 转介和移交 + description: 在一定期间内发生的转介和移交。按照发起和接收的机构或小组分列。 reports: total_referrals: 转介 total_transfers: 移交 @@ -2069,20 +2131,20 @@ cmn: total_transfers_by_user_groups: 移交总数 total_referrals_by_user_groups: 转介总数 filter_options: - registration_date: 注册日期 + registration_date: 登记日期 violence_type_report: name: 暴力类型 reports: cases_violence_type: 暴力类型 - 案件 incidents_violence_type: 暴力类型 - 事件 filter_options: - registration_date: 注册日期 + registration_date: 登记日期 sub_reports: case_violence_type_by_sex_and_age: 按性别和年龄分列的个案总数 incident_violence_type_by_sex_and_age: 按性别和年龄分列的事件总数 success_message: 成功生成导出文件 messages: - alert_items: 你有%{items} 个笔记项目 + alert_items: 你有%{items} 个备注 alerts_for: approval: ' %{form_section_name}等待审批' field_change: '%{form_section_name} 已于%{alert_time}更新 ' @@ -2096,9 +2158,9 @@ cmn: logout_confirmation: 您想继续吗? logout_offline_warning: 确定您想注销吗?如果这样做,直到您再次在线之前,您将无法重新登录。您在离线时进行的任何更改都将丢失。 logout_warning: 您将在5分钟内登录 - logout_dialog_header: 离线注销 - logout_confirmation_title: 注销确认 - logout_confirmation_text: 确定要注销吗? + logout_dialog_header: 离线登出 + logout_confirmation_title: 登出确认 + logout_confirmation_text: 确定要登出吗? no_changes: 您没有进行字段更改 not_available: 无法使用 record_list: @@ -2133,10 +2195,10 @@ cmn: notes: note_success: 成功添加了注释 permissions: - label: 许可 + label: 权限 permission: All: 全部 - add_note: 添加笔记 + add_note: 添加备注 admin_only: 没有记录 - 仅管理功能 administrator_read: 管理员阅读 agency: 机构 @@ -2169,7 +2231,7 @@ cmn: cases_by_task_overdue_services: 按逾期服务查看个案 cases_managed_other_users: 其他用户管理的个案 close: 关闭 - consent_override: 同意替代 + consent_override: 同意覆盖 copy: 复制 copy_of: 备份 create: 创建 @@ -2181,10 +2243,10 @@ cmn: dash_group_overview: 我小组的案件 dash_manager_transfers: 查看督导移交 dash_matching_results: 查看匹配结果 - dash_protection_concerns: 查看匹配结果 - dash_protection_concerns_by_location: 按位置查看保护问题 + dash_protection_concerns: 查看保护担忧 + dash_protection_concerns_by_location: 按位置查看保护担忧 dash_referrals_by_socal_worker: 按社会工作者查看转介 - dash_reporting_location: 查看报告地点 + dash_reporting_location: 查看报告位置 dash_service_provisions: 查看服务提供 dash_shared_from_my_team: 我的团队分享 dash_shared_with_me: 与我分享 @@ -2210,7 +2272,7 @@ cmn: export_photowall: 导出照片墙 export_unhcr_csv: 导出难民署CSV export_xls: 导出XLS - find_tracing_match: 在个案者查找追踪匹配 + find_tracing_match: 在个案中查找追踪匹配 view_registry_record: 查看登记记录 add_registry_record: 添加登记记录 family: 家庭 @@ -2223,11 +2285,11 @@ cmn: incident_details_from_case: 将事件详细信息添加到另一个用户的个案 incident_from_case: 从个案中创建事件 kpi: 进展/KPIs - lookup: 查找 + lookup: 查询 manage: 管理 mark_for_offline: 标记离线 matching_configuration: 匹配配置 - metadata: 表格,查找 + metadata: 表格,查询 potential_match: 潜在匹配 primero_configuration: 配置 read: 阅读 @@ -2241,6 +2303,7 @@ cmn: reopen: 重新开案 report: 报告 managed_report: 见解 + resolve_any_flag: 解除标记 request_approval: 请求批准 request_approval_action_plan: 要求 %{approval_label}批准 request_approval_assessment: 要求 %{approval_label}批准 @@ -2263,6 +2326,7 @@ cmn: transfer: 可用于移交 user: 用户 user_group: 用户组 + verify_mrm: 验证MRM view_approvals: 查看批准 view_assessment: 查看评估 view_photo: 查看照片 @@ -2434,6 +2498,7 @@ cmn: label: 导出照片墙 export_unhcr_csv: label: 导出联合国难民署CSV文件 + explanation: DEPRECATED - This feature is no longer in use. export_xls: explanation: '用户可以从“跟踪请求”列表或“跟踪请求”显示页面生成 XLS 文件导出,其中包含当前用户有权访问的一个、多个或所有该用户能访问的个案。在此导出中,每个表单都表示在 XLS 文件中自己的选项卡中。注意:XLS 格式以可读格式呈现非拉丁字符(例如阿拉伯语、孟加拉语),而 CSV 导出则不然。' label: Excel(XLS文件)导出 @@ -2443,6 +2508,9 @@ cmn: flag: explanation: 能够向个案添加标记。获得此权限的用户还可以删除添加到个案中的标记。 label: 标记 + resolve_any_flag: + explanation: 允许用户解除记录中的标记,无论是谁做的标记。 + label: 解除标记 import: explanation: 允许用户通过从CSV,Excel或JSON文件中导入一个或多个新个案。导入的文件格必须非常式化 ,以使信息正确导入。此功能仅适用于具有高级技术技能的管理用户,并深入了解Primero中数据的格式。仅在个案列表页面上执行。 label: 导入 @@ -2607,7 +2675,7 @@ cmn: explanation: 允许经理查看每个个案社工有多少逾期服务任务。 label: 逾期服务任务 dash_case_incident_overview: - explanation: . + explanation: 给督导显示其团队中成员转介或移交给其他用户的个案数量。 label: 概述 - 我的个案 /事件 dash_cases_by_social_worker: explanation: 该表显示了当前用户的用户组中每个用户负责的已开案个案总数和新个案的总数。每行都是当前用户的用户组中的用户,“总数”和“新个案”是两列。 @@ -2626,10 +2694,10 @@ cmn: label: 查看匹配结果 dash_protection_concerns: explanation: 该表显示了有多少个个案。表的每一行都是一个保护问题,而列则表示个案的不同状态(“所有个案”,“开案个案”,“新增(本周)”,“已结案(本周)”) - label: 按保护问题分列个案 + label: 按保护担忧分列个案 dash_protection_concerns_by_location: explanation: 这与“查看保护问题”仪表板相同,只是用户可以从下拉列表中选择一个位置,以显示有关该位置的保护问题流行率的统计信息。 - label: 按位置查看保护问题 + label: 按位置查看保护担忧 dash_reporting_location: explanation: 该表显示每个位置有多少个个案(具体到“省”或“地区”)。表的每一行都是一个位置,每一列表示个案的不同状态(“开案”,“新增(上周)”,“新增(本周)”,“已结案(上周)”,“已结案(本星期)”)。通常用于经理或管理员帐户。 label: 按报告位置显示个案 @@ -2646,6 +2714,7 @@ cmn: explanation: 向经理展示给其团队中每个用户转介或移交的个案数量。 label: 与我的团队分享 dash_shared_with_my_team_overview: + explanation: 向督导展示给其团队中每个用户转介或移交的个案数量。 label: 与我的团队共享(概述) dash_shared_with_others: explanation: 显示我有多少个案有活跃的转介,待定移交或已拒绝移交。除非管理人员本身管理个案,否则通常不适合管理人员。 @@ -2682,6 +2751,9 @@ cmn: disabled: explanation: 如果您禁用此角色,您将不再能够将其分配给用户帐户。 label: 已禁用 + referral_authorization: + explanation: 表示该角色会作为“转介类别”的一个选项显示在用户转介的页面。如果用户选择了该角色作为转介类型,接收转介的人仅能访问该角色权限内的表格。因此,如果用户选择了“医疗服务”这一转介类别,而该类角色只能查看基本信息表和儿童保护担忧表,则接收转介的人只能访问这两个表。 + label: 该角色可以用作“转介类别”下拉菜单选项? duplicate: actions: read: @@ -2704,6 +2776,7 @@ cmn: label: 表格 - 登记表 family: label: 表格 - 家庭 + explanation: '限制用户访问家庭表单会限制用户可以查看的家庭信息。例如,如果用户只能访问记录所有者表单,他们也只能看到该表单中的字段信息。如果当前用户的表单访问权限受限且能够管理表单配置,那么限制他们的表单访问权限也会限制他们可以配置的表单。' group: actions: admin_only: @@ -2725,6 +2798,9 @@ cmn: label: 此角色会影响哪些记录? incident: actions: + assign: + explanation: 允许用户把事件记录从原记录所有人发送至系统内的其他任意用户。已经跟个案关联的事件将不能分配,需要重新分配已关联的个案,更新事件记录所有人。 + label: 分配 change_log: explanation: 用户可以查看自创建记录以来对记录所做的所有更改的历史记录。这包括为所有字段记录的值。 label: 更改日志 @@ -2741,6 +2817,7 @@ cmn: explanation: 用户可以从事件列表或事件显示页面生成 CSV 文件导出,其中包含当前用户有权访问的一个、多个或所有事件的 CSV 文件。 label: 导出 CSV export_custom: + explanation: 用户可以选择具体的表格或者字段导出为XLS文件。 label: 导出自定义 export_incident_recorder_xls: explanation: 用户可以生成专门的 XLS 文件导出,允许与 GBV 事件记录器工具进行数据交换。 @@ -2763,12 +2840,18 @@ cmn: flag: explanation: 能够向事件添加标记。具有此权限的用户还可以删除已添加到事件的标记。 label: 标记 + resolve_any_flag: + explanation: 允许用户解除记录中的标记,无论是谁做的标记。 + label: 解除标记 import: explanation: 允许用户通过从CSV,Excel或JSON文件中导入一个或多个新事件。导入的文件格必须非常式化 ,以使信息正确导入。此功能仅适用于具有高级技术技能的管理用户,并深入了解Primero中数据的格式。仅在事件列表页面上执行。 label: 导入 remove_alert: explanation: 此许可使用户可以从事件中删除提醒。编辑特定字段时,通常会生成提醒,例如注释更新时。提醒通常在事件旁边显示黄点。 label: 从事件中删除提醒 + link_incident_to_case: + explanation: 允许用户将事件关联至选取的个案。 + label: 将事件关联至个案 manage: explanation: 允许用户对事件执行所有可用操作。“管理”权限本质上意味着“一切”。 label: 管理(此资源类型的所有权限) @@ -2778,6 +2861,9 @@ cmn: sync_mobile: explanation: 此权限通常允许用户使用移动应用程序。首先,它允许用户查看“标记为移动设备”和“取消标记为移动设备”操作,这些操作显示在事件列表和事件显示页面上。为移动设备标记事件表示有关该事件的信息应在用户的移动设备和 Web 应用程序之间同步,而取消标记移动设备事件会阻止此同步的发生。没有此权限的用户通常也无法将其移动设备与 Web 应用程序同步,这意味着他们无法使用移动应用程序来管理事件。 label: 与移动设备同步 + verify_mrm: + explanation: MRM用户可以更改违规状态。 + label: 验证MRM write: explanation: 能够单击“编辑”按钮,更新有关事件的信息,然后单击“保存”。还允许用户禁用或启用事件。 label: 编辑 @@ -2788,6 +2874,18 @@ cmn: label: 是经理吗? managed_report: actions: + reporting_locations_report: + label: 报告位置(个案) + explanation: 能查看给定期间内个案登记数量的统计数据,可用报告位置筛选,按年龄和性别分列。该权限也允许用户从见解中导出数据。 + followups_report: + label: 跟进(个案) + explanation: 查看给定期间内实施跟进的统计数据,可用跟进类型筛选,按年龄和性别分列。该权限也允许用户从见解中导出数据。 + services_report: + label: 服务(个案) + explanation: 能查看给定期间内已实施服务的统计数据,可用服务类型筛选,按年龄和性别分列。该权限也允许用户从见解中导出数据。 + protection_concerns_report: + label: 儿童保护担忧(个案) + explanation: 能查看给定期间内登记个案中儿童保护担忧的统计数据。该权限也允许用户从见解中导出数据。 managed_report_scope: label: 此角色应能够在 Insights 中看到哪些记录? managed_report_scope_all: @@ -2797,21 +2895,28 @@ cmn: managed_report_scope_agency: label: 仅限基于机构的数据 violations: + explanation: 能访问MRM违规Insight。 label: 违规 gbv_statistics: + explanation: 能访问GVB统计Insight。 label: GBV统计数据 ghn_report: + explanation: 能访问MRM Global Horizontal Note Insight。 label: 全球横向说明 individual_children: - label: 个别儿童 + explanation: 能访问MRM儿童个人Insight。 + label: 儿童个人 workflow_report: - label: 工作流程 - explanation: 能够查看有关工作流状态的统计信息。此权限还允许用户从 Insight 导出数据。 + label: 工作流程(个案和事件) + explanation: 能查看相关联个案和事件的工作流程统计数据。该权限也允许用户从见解中导出数据。 + cases_workflow_report: + label: 工作流程(个案) + explanation: 能够查看个案工作流状态的统计信息。此权限还允许用户从 Insight 导出数据。 violence_type_report: - label: 暴力类型 + label: 暴力类型(事件) explanation: 能够查看有关暴力类型的统计数据。此权限还允许用户从 Insight 导出数据。 referrals_transfers_report: - label: 转介和移交 + label: 转介和移交(个案) explanation: 用户可以看到从每个用户组转介和移交到每个用户组的个案数。 matching_configuration: actions: @@ -2887,6 +2992,9 @@ cmn: flag: explanation: 能够向登记表记录添加标记。具有此权限的用户还可以删除已添加到登记表记录的标记。 label: 标记 + resolve_any_flag: + explanation: 允许用户解除记录中的标记,无论是谁做的标记。 + label: 解除标记 manage: explanation: 允许用户对登记表记录执行所有可用操作。“管理”权限本质上意味着“一切”。 label: 管理(此资源类型的所有权限) @@ -2929,9 +3037,13 @@ cmn: label: 导出PDF export_custom: label: 导出自定义 + explanation: 用户可以从家庭列表或家庭中选择具体的表格或者字段导出为XLS文件。 flag: explanation: 能够向家庭添加标记。具有此权限的用户还可以删除已添加到家庭的标记。 label: 标记 + resolve_any_flag: + explanation: 允许用户解除记录中的标记,无论是谁做的标记。 + label: 解除标记 manage: explanation: 允许用户对家庭执行所有可用操作。“管理”权限本质上意味着“一切”。 label: 管理(此资源类型的所有权限) @@ -3049,6 +3161,9 @@ cmn: flag: explanation: 能够向追踪请求添加标记。具有此权限的用户还可以删除已添加到追踪请求的标记。 label: 标记 + resolve_any_flag: + explanation: 允许用户解除记录中的标记,无论是谁做的标记。 + label: 解除标记 import: explanation: 允许用户通过从CSV,Excel或JSON文件中导入一个或多个新个案。导入的文件格必须非常式化 ,以使信息正确导入。此功能仅适用于具有高级技术技能的管理用户,并深入了解Primero中数据的格式。仅在个案列表页面上执行。 label: 导入 @@ -3126,6 +3241,7 @@ cmn: label: 删除 manage: label: 管理(此资源类型的所有权限) + explanation: 用于访问Primero Webhooks到其他系统的系统角色。不建议非开发人员使用。 activity_log: actions: transfer: @@ -3133,6 +3249,7 @@ cmn: label: 移交 manage: label: 管理(此资源类型的所有权限) + explanation: 能访问全部 label: 活动日志 potential_match: case_id: 个案编号 @@ -3159,6 +3276,7 @@ cmn: successfully: 已成功重新分配 user_mandatory_label: 接收人为必填项 users_label: 接收人 + incident_from_case_warning: 您无法分配此事件,因其已与个案关联。当分配相应个案时,该事件也随之被分配。 record_information: assigned_user_names: 其他分配的用户 created_at: 记录创建于 @@ -3180,6 +3298,8 @@ cmn: referral: type_of_recipient: 接收人类型 type_of_referral_required: 转介类型为必填项 + referral_authorization_label: 需要明确具体的转介类型么? + referral_authorization_help_text: 将限制接收方能访问的表格。 agency_label: 机构 is_remote_label: 你指的是远程系统吗? location_label: 位置 @@ -3313,7 +3433,7 @@ cmn: label: 系统设置 task: due_date: 完成日期 - id: 身份证号# + id: 任务编号# name: 名字 priorities: high_level: 高 @@ -3498,6 +3618,7 @@ cmn: inprogress: 待定 rejected: 已拒绝 revoked: 已撤销 + transferred_by: 由...转介 type: assign: 分配 reassign: 分配 @@ -3529,6 +3650,7 @@ cmn: passwords_do_not_match: 与当前密码不匹配 time_zone_updated: 更改已成功更新。 updated: 用户已成功更新。 + created_warning: 您已经创建了最大用户数%{maximum_users}中的%{total_enabled}个用户。 organization: 组织 agency: 机构 services_help_text: 如果您不指定服务,则该用户将获得其代理机构拥有的相同服务。 @@ -3547,10 +3669,21 @@ cmn: provider_username_help: '示例:my.username@%{domain}' role_id: 角色 send_mail: 接收电子邮件通知? + send_mail_preferences: + label: 您希望收到什么类别的邮件通知? + help_text: 如果您留空此字段,您将收到所有电子邮件通知。 receive_webpush: label: 接收推送通知? help_text: 请注意,您仍然需要在设备的浏览器上允许推送通知。 tooltip: 您必须先编辑您的帐户并为您的用户启用推送通知。 + receive_webpush_preferences: + label: 您希望接收哪种类型的推送通知? + help_text: 如果您留空此字段,您将收到所有推送通知。 + notification_preferences: + approval_request: '申请批准(督导)' + approval_response: '批准回应(个案社工)' + transition_notification: '分配、移交和转介。' + transfer_request: '移交请求' user_group_unique_ids: 用户组 user_name: 用户名 services: 服务 @@ -3610,6 +3743,10 @@ cmn: user_name: 用户名 position: 职位 agency: 机构 + alerts: + total_users_created: 您已创建了%{total_enabled}个启用用户,达到您的实施允许的%{maximum_users}个用户上限。 + limit_user_reached: 您已达到 %{maximum_users}个启用用户的上限。在创建更多用户之前,您必须禁用一个或多个用户。 + limit_user_reached_on_enable: 您已达到 %{maximum_users}个启用用户的上限。在创建或启用更多用户之前,您必须禁用一个或多个用户。 devise: failure: already_authenticated: "您已登录。" diff --git a/config/locales/dates/aeb.yml b/config/locales/dates/aeb.yml new file mode 100644 index 0000000000..0a6f5ef0af --- /dev/null +++ b/config/locales/dates/aeb.yml @@ -0,0 +1,69 @@ +aeb: + date: + today: 'اليوم' + clear: 'مسح' + abbr_day_names_short: + - الأحد + - الإثنين + - الثلاثاء + - الأربعاء + - الخميس + - الجمعة + - السبت + abbr_day_names: + - الأحد + - الإثنين + - الثلاثاء + - الأربعاء + - الخميس + - الجمعة + - السبت + abbr_month_names: + - ~ + - يناير + - فبراير + - مارس + - أبريل + - مايو + - يونيو + - يوليو + - اغسطس + - سبتمبر + - أكتوبر + - نوفمبر + - ديسمبر + day_names: + - الأحد + - الإثنين + - الثّلاثاء + - الأربعاء + - الخميس + - الجمعة + - السّبت + month_names: + - ~ + - يناير + - فبراير + - مارس + - أبريل + - مايو + - يونيو + - يوليو + - اغسطس + - سبتمبر + - أكتوبر + - نوفمبر + - ديسمبر + formats: + default: "%d-%b-%Y" + with_time: "%d-%b-%Y %H:%M" + rtl: "%Y-%b-%d" + rtl_with_time: "%M:%H %Y-%b-%d" + time: + formats: + default: "%d-%b-%Y" + with_time: "%d-%b-%Y %H:%M" + rtl: "%Y-%b-%d" + rtl_with_time: "%M:%H %Y-%b-%d" + 'true': "نعم" + 'false': "لا" diff --git a/config/locales/dates/ar-JO.yml b/config/locales/dates/ar-JO.yml index fa39609b04..6915288b82 100644 --- a/config/locales/dates/ar-JO.yml +++ b/config/locales/dates/ar-JO.yml @@ -1,8 +1,7 @@ ar-JO: date: today: 'اليوم' - clear: 'واضح' - first_day: 0 + clear: 'مسح' abbr_day_names_short: - الاحد - الاثنين @@ -11,6 +10,14 @@ ar-JO: - الخميس - الجمعة - السبت + abbr_day_names: + - الأحد + - الإثنين + - الثلاثاء + - الأربعاء + - الخميس + - الجمعة + - السبت abbr_month_names: - ~ - كانون الثاني diff --git a/config/locales/dates/ar-SY.yml b/config/locales/dates/ar-SY.yml new file mode 100644 index 0000000000..4abc6802e5 --- /dev/null +++ b/config/locales/dates/ar-SY.yml @@ -0,0 +1,69 @@ +ar-SY: + date: + today: 'اليوم' + clear: 'مسح' + abbr_day_names_short: + - الأحد + - الإثنين + - الثلاثاء + - الأربعاء + - الخميس + - الجمعة + - السبت + abbr_day_names: + - الأحد + - الإثنين + - الثلاثاء + - الأربعاء + - الخميس + - الجمعة + - السبت + abbr_month_names: + - ~ + - يناير + - فبراير + - مارس + - أبريل + - مايو + - يونيو + - يوليو + - اغسطس + - سبتمبر + - أكتوبر + - نوفمبر + - ديسمبر + day_names: + - الأحد + - الإثنين + - الثّلاثاء + - الأربعاء + - الخميس + - الجمعة + - السّبت + month_names: + - ~ + - يناير + - فبراير + - مارس + - أبريل + - مايو + - يونيو + - يوليو + - اغسطس + - سبتمبر + - أكتوبر + - نوفمبر + - ديسمبر + formats: + default: "%d-%b-%Y" + with_time: "%d-%b-%Y %H:%M" + rtl: "%Y-%b-%d" + rtl_with_time: "%M:%H %Y-%b-%d" + time: + formats: + default: "%d-%b-%Y" + with_time: "%d-%b-%Y %H:%M" + rtl: "%Y-%b-%d" + rtl_with_time: "%M:%H %Y-%b-%d" + 'true': "نعم" + 'false': "لا" diff --git a/config/locales/dates/ar.yml b/config/locales/dates/ar.yml index 7fcf20d814..891209c566 100644 --- a/config/locales/dates/ar.yml +++ b/config/locales/dates/ar.yml @@ -20,18 +20,18 @@ ar: - السبت abbr_month_names: - ~ - - كانون الثاني/يناير - - شباط/فبراير - - آذار/مارس - - نيسان/أبريل - - أيار/مايو - - حزيران/يونيو - - تموز/يوليو - - آب/اغسطس - - أيلول/سبتمبر - - تشرين الأول/أكتوبر - - تشرين الثاني/نوفمبر - - كانون الأول/ديسمبر + - يناير + - فبراير + - مارس + - أبريل + - مايو + - يونيو + - يوليو + - اغسطس + - سبتمبر + - أكتوبر + - نوفمبر + - ديسمبر day_names: - الأحد - الإثنين @@ -42,18 +42,18 @@ ar: - السّبت month_names: - ~ - - كانون الثاني/يناير - - شباط/فبراير - - آذار/مارس - - نيسان/أبريل - - أيار/مايو - - حزيران/يونيو - - تموز/يوليو - - آب/اغسطس - - أيلول/سبتمبر - - تشرين الأول/أكتوبر - - تشرين الثاني/نوفمبر - - كانون الأول/ديسمبر + - يناير + - فبراير + - مارس + - أبريل + - مايو + - يونيو + - يوليو + - اغسطس + - سبتمبر + - أكتوبر + - نوفمبر + - ديسمبر formats: default: "%d-%b-%Y" with_time: "%d-%b-%Y %H:%M" diff --git a/config/locales/dates/cmn.yml b/config/locales/dates/cmn.yml index 803681f49c..a8db858db3 100644 --- a/config/locales/dates/cmn.yml +++ b/config/locales/dates/cmn.yml @@ -19,6 +19,7 @@ cmn: - 星期五 - 星期六 abbr_month_names: + - ~ - 一月 - 二月 - 三月 @@ -40,6 +41,7 @@ cmn: - 星期五 - 星期六 month_names: + - ~ - 一月 - 二月 - 三月 diff --git a/config/locales/dates/hu.yml b/config/locales/dates/hu.yml index a6454131c3..9ae5956da5 100644 --- a/config/locales/dates/hu.yml +++ b/config/locales/dates/hu.yml @@ -54,5 +54,16 @@ hu: - Október - November - December + formats: + default: "%d-%b-%Y" + with_time: "%d-%b-%Y %H:%M" + rtl: "%Y-%b-%d" + rtl_with_time: "%M:%H %Y-%b-%d" + time: + formats: + default: "%d-%b-%Y" + with_time: "%d-%b-%Y %H:%M" + rtl: "%Y-%b-%d" + rtl_with_time: "%M:%H %Y-%b-%d" 'true': "Igen" 'false': "Nem" diff --git a/config/locales/dates/so.yml b/config/locales/dates/so.yml index 6e1fa13a38..dbdf295322 100644 --- a/config/locales/dates/so.yml +++ b/config/locales/dates/so.yml @@ -1,57 +1,60 @@ so: date: - today: 'maanta' + today: 'maanta ' clear: 'Cadee' + first_day: 0 abbr_day_names_short: - - Axad - - Isniin - - Salaasa - - Arbaco - - Khamiis - - Jimce - - Sabti + - Axad + - Isniin + - Salaasa + - Arbaco + - Khamiis + - Jimce + - Sabti abbr_day_names: - - Axad - - Isniin - - Salaasa - - Arbaca - - Khamiis - - Jimce - - sabti + - Axad + - Isniin + - Salaasa + - Arbaca + - Khamiis + - Jimce + - sabti abbr_month_names: - - Janaayo - - Febraayo - - Marso - - Abril - - Meey - - Juun - - Luulyo - - Agoosta - - Sebtembar - - Oktoobar - - Nofembar - - Dhisenbar + - ~ + - Janaayo + - Febraayo + - Marso + - Abril + - Meey + - Juun + - Luulyo + - Agoosta + - Sebtembar + - Oktoobar + - Nofembar + - Dhisenbar day_names: - - Axad - - Isniin - - Salaasa - - Arbaca - - Khamiis - - Jimco - - Sabti + - Axad + - Isniin + - Salaasa + - Arbaca + - Khamiis + - Jimco + - Sabti month_names: - - Jnaayo - - Febraayo - - Maarso - - Abril - - Meey - - Juun - - Luulyo - - Agoosto - - Sebtembar - - Octoobar - - Nofembar - - Dhiseenbar + - ~ + - Jnaayo + - Febraayo + - Maarso + - Abril + - Meey + - Juun + - Luulyo + - Agoosto + - Sebtembar + - Octoobar + - Nofembar + - Dhiseenbar formats: default: "%d-b-%Y" with_time: "%d-5b-%Y%H:%M" diff --git a/config/locales/dates/sw-TZ.yml b/config/locales/dates/sw-TZ.yml index af94333064..e5e006baed 100644 --- a/config/locales/dates/sw-TZ.yml +++ b/config/locales/dates/sw-TZ.yml @@ -10,3 +10,6 @@ sw-TZ: - Alhamisi - Ijumaa - Jumamosi + abbr_day_names: + - Jumapili + - Jumatatu diff --git a/config/locales/dates/uk.yml b/config/locales/dates/uk.yml index 66529a14d5..4d154326ed 100644 --- a/config/locales/dates/uk.yml +++ b/config/locales/dates/uk.yml @@ -55,15 +55,15 @@ uk: - Листопад - Грудень formats: - default: "%d-%b-%Y" - with_time: "%d-%b-%Y %H:%M" - rtl: "%Y-%b-%d" - rtl_with_time: "%M:%H %Y-%b-%d" + default: "%d-%b-%Р" + with_time: "%d-%b-%Р %Г:%Х" + rtl: "%Р-%b-%d" + rtl_with_time: "%Х:%Г %Р-%b-%d" time: formats: - default: "%d-%b-%Y" - with_time: "%d-%b-%Y %H:%M" - rtl: "%Y-%b-%d" - rtl_with_time: "%M:%H %Y-%b-%d" + default: "%d-%b-%Р" + with_time: "%d-%b-%Р %Г:%Х" + rtl: "%Р-%b-%d" + rtl_with_time: "%Х:%Г %Р-%b-%d" 'true': "Так" 'false': "Ні" diff --git a/config/locales/en.yml b/config/locales/en.yml index fe89ebc5fa..5bb9c17b31 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -184,6 +184,7 @@ en: import: Import login: Log in logout: Log out + link: Link mark_for_mobile: Mark for mobile new: New ok: OK @@ -534,6 +535,10 @@ en: date_case_plan_initiated: Date of Case Plan date_of_creation: Date of Creation registration_date: Date of Registration + followup_date: Date of Follow Up + date_reunification: Date of Reunification + tracing_date: Date of Tracing + service_implemented_day_time: Date Service Completed configurations: apply_label: Are you sure? If you apply, the settings in this configuration will be applied to the system. You will lose all your current settings and will not be able to get them back unless you have already saved @@ -598,6 +603,13 @@ en: all_cases: All Cases all_services_implemented: All Services Implemented and: 'and ' + action_needed: + awaiting_acceptance: Awaiting Acceptance + header: Action Needed + new: New + new_this_week: New this Week + referrals: Referrals + transfers: Transfers approval_action_plan_approved: Approved approval_action_plan_pending: Pending approval_action_plan_pending_group: Action Plan @@ -903,6 +915,8 @@ en: errors: api: internal_server: Server Error + attachments: + maximum: You have reached your maximum attachments per record. error_loading: Error Loading Record(s) models: agency: @@ -1039,6 +1053,7 @@ en: subforms: 'Subform: %{subform_name}' collapsed_fields: 'Collapsed Fields: %{fields}' country: Countries + linkedincidents: Linked Incidents summary_header: form_group: Primero Form Group form: Primero Forms @@ -1167,6 +1182,8 @@ en: add_existing_field: Add Existing Field add_field: Add Field add_field_type: Add %{file_type} + attachments: + maximum_attached: Maximum attachments limit per record (%{maximumttachmentsPerRecord}) reached. This includes photos, audio, and documents. Please remove a file before adding another. audio: current: Current Audio audio_upload_box: Audio Upload @@ -1435,6 +1452,8 @@ en: ar-JO: العربية (الأردنية) ar-LB: العربية (اللبنانية) ar-SD: العربية (السودانية) + aeb: العربية (التونسية) + ar-SY: العربية (السورية) bn: বাংলা cmn: 中文 current_time_zone: Current time zone @@ -1479,6 +1498,8 @@ en: incident: code: Incident Code associated_case: "Associated Case:" + link_incident_to_case: Link Incident to Case + link_incident_to_case_success: Linked incident(s) to case messages: creation_success: Incident record successfully created. creation_success_queue: Incident record successfully created in background @@ -1504,6 +1525,7 @@ en: military_use: Military use of school(s) and/or hospital(s) denial_humanitarian_access: Denial of humanitarian access for children incidents: + change_status: Change Status disable_dialog: Clicking OK will change the status of this incident to Disabled. disable_dialog_title: Disable Incident disable_success: Successfully disabled incident @@ -1585,6 +1607,7 @@ en: survivor_code: Survivor Code show_incident: 'Incident ID %{short_id}' social_worker: Social Worker + verify_mrm: Verify MRM violation_type: Violation Type violence_type: Violence Type type_violence: Type of Violence @@ -1795,6 +1818,15 @@ en: parish: Parish cercle: Cercle sub-county: Sub-county + departement_fr: 'Département' + region_fr: 'Région' + wilaya: 'Wilaya' + commune: 'Commune' + division_fr: 'Division' + prefecture: 'Prefecture' + moughataa: 'Moughataa' + sub_division: 'Sub-division' + sub-prefecture: 'Sub-Prefecture' label: Location name: Name code: Code @@ -2003,6 +2035,10 @@ en: workflow: Workflow Status cp_incident_violence_type: Type of Violence referral_transfer_status: Referral / Transfer Status + protection_concerns: Protection Concerns + location: Reporting Location + followup_type: Type of Follow Up + service_type: Type of Service status_options: open: Open closed: Closed @@ -2044,6 +2080,50 @@ en: individual_violation_type: Individual Children by Violation Type individual_region: Individual Children by Region individual_perpetrator: Individual Children by Perpetrator + services: + name: Services + description: Cases with the selected Service types, broken down by age and sex. + services_report: + reports: + services: Services + description: Cases with the selected Service types, broken down by age and sex. + sub_reports: + services: Services + filter_options: + service_implemented_day_time: Service completed + followups: + name: Follow Ups + description: Cases with the selected Follow Up types, broken down by age and sex. + followups_report: + filter_options: + followup_date: Date of follow-up + reports: + followups: Follow Ups + description: Cases with the selected Follow Up types, broken down by age and sex. + sub_reports: + followups: Follow Ups + protection_concerns: + name: Protection Concerns + description: Cases with the selected Protection Concerns, broken down by age and sex. + protection_concerns_report: + reports: + protection_concerns: Protection Concerns + description: Cases with the selected Protection Concerns, broken down by age and sex. + sub_reports: + protection_concerns: Protection Concerns + filter_options: + registration_date: Date of Registration + reporting_locations: + name: Reporting Location + description: 'Cases with the selected Reporting Location, broken down by age and sex.' + reporting_locations_report: + reports: + reporting_locations: Reporting Location + description: '' + sub_reports: + reporting_location_by_sex_and_age: Reporting Location + filter_options: + registration_date: Date of Registration ghn_report: name: Global Horizontal Note description: '' @@ -2135,35 +2215,36 @@ en: date_of_first_report: Date of Interview incident_date: Date of Incident reports: - incidents: Incidents + incidents: GBV Statistics perpetrators: Perpetrators survivors: Survivors referrals: Referrals sub_reports: - combined: Incidents - total: Number of GBV Incidents Reported - gbv_sexual_violence: Number of Incidents of Sexual Violence Reported - gbv_previous_incidents: Number of Incidents Reported by Survivors with Prior GBV Incidents - gbv_sexual_violence_type: Incident Type - incident_timeofday: Incident Time of Day - elapsed_reporting_time: Time Between Incident and Report Date - elapsed_reporting_time_rape: Incidents of Rape, Time Elapsed between Incident and Report Date - elapsed_reporting_time_rape_health_referral: Incidents of Rape, Time Elapsed between Incident and Report Date (Health Service or Referral) - incident_location_type: Incident Location - number_of_perpetrators: Number of Perpetrators - perpetrator_relationship: Alleged Primary Perpetrator's Relationship to Survivor - perpetrator_age_group: Alleged Primary Perpetrators Age Group - perpetrator_occupation: Alleged Primary Perpetrator Occupation - age: Number of Survivors by Age - sex: Number of Survivors by Sex - marital_status: Marital Status of Survivors - displacement_status: Displacement Status of Survivors - displacement_incident: Stage of Displacement at time of Incident - gbv_case_context: Case Context - incidents_first_point_of_contact: Number of Incidents where your organization is the first point of contact - incidents_from_other_service_provider: Incidents Referred from Other Service Providers - number_of_services_provided: Number of Services Provided for Incidents - number_of_services_provided_other: New Incident Referrals to Other Service Providers + incidents: Incidents + combined: General Statistics + total: 1. New GBV Incidents Reported + gbv_sexual_violence: Survivor Statistics - 9. Number of Incidents of Sexual Violence Reported + gbv_previous_incidents: 2. New Incidents of Sexual Violence Reported + gbv_sexual_violence_type: Incident Statistics - 10. Type of GBV + incident_timeofday: Incident Statistics - 11. Incident Time of Day + elapsed_reporting_time: Incident Statistics - 13. Time Between Incident and Report Date + elapsed_reporting_time_rape: Incident Statistics - 14. Incidents of Rape, Time Elapsed between Incident and Report Date + elapsed_reporting_time_rape_health_referral: Incident Statistics - 15. Incidents of Rape, Time Elapsed (Health Service or Referral) + incident_location_type: Incident Statistics - 16. Incident Location + number_of_perpetrators: Perpetrator Statistics - 17. Number of Primary Perpetrators + perpetrator_relationship: Perpetrator Statistics - 18. Alleged Perpetrator - Survivor Relationship + perpetrator_age_group: Perpetrator Statistics - 19. Alleged Primary Perpetrators Age Group + perpetrator_occupation: Perpetrator Statistics - 20. Alleged Primary Perpetrator Occupation + age: Survivor Statistics - 4. Age of survivors + sex: Survivor Statistics - 3. Sex of survivors + marital_status: Survivor Statistics - 5. Marital Status of Survivors + displacement_status: Survivor Statistics - 6. Displacement Status at Time of Report + displacement_incident: Survivor Statistics - 7. Stage of Displacement at Time of Incident + gbv_case_context: Incident Statistics - 12. Case Context + incidents_first_point_of_contact: Referral Statistics - 21. Number of incidents for which your organisation is the first point of contact + incidents_from_other_service_provider: Referral Statistics - 22. Incidents Referred From Other Service Providers + number_of_services_provided: Referral Statistics - 23. Number of Services Provided for Incidents + number_of_services_provided_other: Referral Statistics - 24. New Incident Referrals to Other Service Providers service_safehouse_referral: Safe House/Safe Shelter Referral service_medical_referral: Health/Medical Referral service_psycho_referral: Psychosocial/Counseling Services @@ -2171,11 +2252,11 @@ en: service_police_referral: Police or Other Type of Security Services service_livelihoods_referral: Livelihoods Services service_protection_referral: Child Protection Services - vulnerable_populations: Vulnerable Populations + vulnerable_populations: Survivor Statistics - 8. Vulnerable Populations survivors_disability_type: With Disabilities workflow_report: name: Workflow - description: '' + description: Cases and Incidents with the selected Workflow Status, broken down by age and sex. reports: cases_workflow: Workflow - Cases incidents_workflow: Workflow - Incidents @@ -2184,9 +2265,18 @@ en: sub_reports: case_workflow_by_sex_and_age: Total Number of Cases by Sex and Age incident_workflow_by_sex_and_age: Total Number of Incidents by Sex and Age + cases_workflow_report: + name: Workflow + description: Cases with the selected Workflow Status, broken down by age and sex. + reports: + cases_workflow: Workflow - Cases + filter_options: + registration_date: Registration Date + sub_reports: + case_workflow_by_sex_and_age: Total Number of Cases by Sex and Age referrals_transfers_report: name: Referrals and Transfers - description: '' + description: Referrals and Transfers which have occurred within a given time span. Broken down by sending and receiving Agencies or User Groups. reports: total_referrals: Referrals total_transfers: Transfers @@ -2235,6 +2325,7 @@ en: no_match: Sorry, no matching records found rows_per_page: Rows per page sort: Sort + sort_disabled_name_fields: Sort disabled when searching by name fields navigation: bulk_exports: Exports cases: Cases @@ -2245,6 +2336,12 @@ en: reports: Reports insights: Insights search: Search + phonetic_search: + title: Enter a name to search for an existing record. + label: Use Name Fields + help_text: Phonetic search is available for Name fields + id_search: + title: Enter the ID number to search for an existing record. settings: Settings support: Support support_menu: @@ -2393,6 +2490,7 @@ en: transfer: Can be used for transfer user: Users user_group: User Groups + verify_mrm: Verify MRM view_approvals: View Approvals view_assessment: View Assessment view_photo: View Photo @@ -2912,6 +3010,20 @@ en: label: Case dashboard: actions: + action_needed_new_updated: + explanation: Displays the 'New and Updated' indicator in the 'Action Needed' dashboard. + This includes Cases which are newly assigned to the current user, or which another + user has updated since the last time the current user updated it. + label: 'Action Needed: New or Updated' + action_needed_new_referrals: + explanation: Displays the 'New Referrals' indicator in the 'Action Needed' dashboard. + This includes any Cases with a new Referral sent to the current user, + where the current user is not the last person to update the Case. + label: 'Action Needed: New Referrals' + action_needed_transfer_awaiting_acceptance: + explanation: Displays the 'Transfers Awaiting Acceptance' indicator in the 'Action Needed' dashboard. + This includes any Cases with a Transfer to the current user, which the current user has not accepted. + label: 'Action Needed: Transfers Awaiting Acceptance' approvals_action_plan: explanation: Shows the number of the current user's cases with Action Plan approval requests which are Pending, Approved, or Rejected. @@ -3290,6 +3402,9 @@ en: edited, such as when notes are updated. Alerts are usually shown with a yellow dot next to the incident. label: Remove alert from an incident + link_incident_to_case: + explanation: Allows the user to link the incident with selected case. + label: Link incident to Case manage: explanation: Allows a user to perform all available actions on incidents. The "Manage" permission essentially means "everything". @@ -3308,6 +3423,9 @@ en: also cannot sync their mobile devices with the web application in general, meaning that they cannot use the mobile app to manage incidents. label: Sync with mobile device + verify_mrm: + explanation: MRM user can change the status of violations. + label: Verify MRM write: explanation: Ability to click the "Edit" button, update information about the incident, and click "Save". Also allows the user to disable or enable @@ -3325,6 +3443,18 @@ en: label: Is Manager? managed_report: actions: + reporting_locations_report: + label: Reporting Location (Cases) + explanation: Ability to view statistics on the number of Cases registered within a given date range, filtered by Reporting Location, and broken down by age and sex. This permission also allows the user to export data from an Insight. + followups_report: + label: Followups (Cases) + explanation: Ability to view statistics on the number of Follow Ups performed within a given date range, filtered by Type of Follow Up, and broken down by age and sex. This permission also allows the user to export data from an Insight. + services_report: + label: Services (Cases) + explanation: Ability to view statistics on the number of Services performed within a given date range, filtered by service type, and broken down by age and sex. This permission also allows the user to export data from an Insight. + protection_concerns_report: + label: Protection Concerns (Cases) + explanation: Ability to view statistics on the Protection Concerns of Cases registered within a given date range. This permission also allows the user to export data from an Insight. managed_report_scope: label: What records should this role be able to see in Insights? managed_report_scope_all: @@ -3346,15 +3476,17 @@ en: explanation: Ability to access the MRM Individual Children Insight. label: Individual Children workflow_report: - label: Workflow - explanation: Ability to view statistics on Workflow Status. This permission also allows the user to export - data from an Insight. + label: Workflow (Cases and Incidents) + explanation: Ability to view statistics on Workflow Status for both Cases and the Incidents linked to them. This permission also allows the user to export data from an Insight. + cases_workflow_report: + label: Workflow (Cases) + explanation: Ability to view statistics on Workflow Status Cases. This permission also allows the user to export data from an Insight. violence_type_report: - label: Type of Violence + label: Type of Violence (Cases and Incidents) explanation: Ability to view statistics on Type of Violence. This permission also allows the user to export data from an Insight. referrals_transfers_report: - label: Referrals and Transfers + label: Referrals and Transfers (Cases) explanation: Users see the number of cases referred and transferred from each User Group to each other User Group. matching_configuration: @@ -4305,10 +4437,21 @@ en: provider_username_help: 'Example: my.username@%{domain}' role_id: Role send_mail: Receive email notifications? + send_mail_preferences: + label: Which types of email notifications would you like to receive? + help_text: If you leave this field blank, you will receive all email notifications. receive_webpush: label: Receive push notifications? help_text: Note that you will still need to allow push notifications on your device’s browser. tooltip: You must first edit your account and enable push notifications for your user. + receive_webpush_preferences: + label: Which types of push notifications would you like to receive? + help_text: If you leave this field blank, you will receive all push notifications. + notification_preferences: + approval_request: 'Approval Request (Managers)' + approval_response: 'Approval Response (Case Workers)' + transition_notification: 'Assignments, Transfers, and Referrals' + transfer_request: 'Transfer Requests' user_group_unique_ids: User Groups user_name: Username services: Services diff --git a/config/locales/es-ES.yml b/config/locales/es-ES.yml index d9b14b8a23..25c0b74a1e 100644 --- a/config/locales/es-ES.yml +++ b/config/locales/es-ES.yml @@ -1,4 +1,4 @@ -es_ES: +es-ES: 'true': 'Sí' 'false': 'No' accepted: Aceptado @@ -14,7 +14,6 @@ es_ES: unavailable_offline: No está disponible fuera de línea online: En línea yes_label: 'Sí' - or_label: o select_provider: Seleccionar prestadora de servicios select_language: Seleccionar idioma log_in_primero_idp: iniciar sesión con%{idp_name} nombre de usuario @@ -1046,7 +1045,6 @@ es_ES: english_text: Texto en Inglés field_name: Nombre del campo field_type: Tipo de Campo - attachment_too_large: El archivo no puede ser mayor a 10mb file_upload_box: add_document_label: Agregar Documento add_new_document_button_text: Agregar otro documento @@ -2092,7 +2090,6 @@ es_ES: explanation: Permite a un(a) gerente ver cuántos casos tienen tareas de Servicios vencidas para cada una de sus trabajadoras de casos. label: tareas de Servicios Vencidas dash_case_incident_overview: - explanation: . label: Información General - Mis Casos /Incidentes dash_cases_by_social_worker: explanation: Tabla que muestra el número total de casos abiertos y el número de nuevos casos gestionados por cada usuario(a) en los grupos de usuario(a)s de el/la usuario(a) actual. Cada línea es un(a) usuario(a) dentro de los grupos de usuario(a)s de el/la usuario(a) actual, mientras que columnas son dos "Total" y "Nuevo". @@ -2449,7 +2446,6 @@ es_ES: display: Mostrando posibles concordancias para %{type}%{id} reassign: multiple_error: Ha ocurrido un error. %{select_records} caso(a) no asignados. - multiple_successfully: '%{select_records} caso(s) asignados correctamente' notes_label: Notas successfully: Reasignado correctamente user_mandatory_label: Se requiere destinatario(a) diff --git a/config/locales/es-GT.yml b/config/locales/es-GT.yml index f05b784028..908af6a333 100644 --- a/config/locales/es-GT.yml +++ b/config/locales/es-GT.yml @@ -84,6 +84,7 @@ es-GT: terms_of_use_download_button: Descargar PDF terms_of_use_enabled: ¿Mostrar Términos de su Uso? approvals: + no_requests: No hay solicitudes de aprobación para este Caso. approved_by: Aprobado Por case_plan_type_label: Tipo de Plan de Caso manager_comments_label: Comentarios de Gerente @@ -166,6 +167,7 @@ es-GT: import: Importar login: Iniciar sesión logout: Terminar sesión + link: Enlace mark_for_mobile: Marcar para móvil new: Nuevo ok: OK @@ -198,6 +200,8 @@ es-GT: view: Ver view_flags_history: Ver Historial return_to_case: Regresar al Caso + enable_webpush: Notificaciones de dispositivo + dialog_yes: "Sí" resync_records: id: Documento de Identificación (ID) record_type: Tipo de registro @@ -210,7 +214,10 @@ es-GT: case: label: Caso create_new_case: Crear Nuevo Caso + create_case: Crear Caso + create: Crear add_new: Agregar Nuevo + back_to_family_details: Regresar a Detalles de la Familia back_to_case: Regresar al Caso back_to_results: Regresar a Resultados back_to_search: Regresar a Buscar @@ -234,6 +241,14 @@ es-GT: introductory_sentence: Por favor especificque el consentimiento de la persona para recibir los servicios de gestión de casos y para que sus datos se almacenen en Primero. consent_agreements_required: Por favor seleccione al menos una opción de los acuerdos de consentimiento. legitimate_basis_required: Por favor seleccione al menos una opción de las clasificaciones base permitidas + confirm_create_case: ¿Desea crear un Caso para este individuo? + case_referral_pending: Hay una referencia de Caso pendiente. + case_transfer_pending: Hay una transferencia de Caso pendiente. + case_no_approval_request: No hay solicitudes de aprobación para este Caso. + bulk_assign_limit: No puede asignar mas de 100 Casos al mismo tiempo. + bulk_assign_limit_try_again: No puede asignar mas de 100 Casos al mismo tiempo. Por favor, seleccione 100 Casos o menos e inténtelo nuevamente. + referral_rejected: La Referencia ha sido rechazada. + transfer_request_made: Se ha creado una solicitud de Transferencia para este Caso. save: Guardar Caso save_text: Antes de continuar, por favor guarde los cambios hechos al Caso skip_and_create: Crear Nuevo Caso @@ -241,6 +256,7 @@ es-GT: search_helper_text: ¿Para qué? Para evitar la creación de casos duplicados. consent_agreements: Selecciones todos los acuerdos de consentimiento que apliquen legitimate_basis: Seleccione todas las clasificaciones base permitidas que apliquen + family_linked_subform_delete_disabled: Este sub formulario está enlazado a un Registro Familiar. Por favor, remueva a este miembro de la familia del Registro Familiar, o desvincule el Caso del miembro familiar del Registro Familiar. workflow: assessment: Evaluación case_plan: Plan del Caso @@ -260,6 +276,7 @@ es-GT: rejected_transfer: '%{to} transferencia rechazada de %{record_type}%{record_id} de %{from}' cases: action_plan: Plan de Acción + access_denied: "Usted no tiene acceso a este Caso." age: Edad age_estimated: ¿Edad Estimada? agency: Agencia @@ -354,6 +371,7 @@ es-GT: urgent_protection_concern: Inquietud sobre Protección Urgente user_group: Grupo de Usuario(a)s workflow: Casos por Flujo de Trabajo + include_disabled: Incluir deshabilitados flag_summary: Resumen de registros marcados full_name: Nombre Completo gbv_closure: Cierre de Violencia Basada en Género (GBV) @@ -377,6 +395,8 @@ es-GT: photos: Fotografía quick_view: tracing_message: 'Nota: Hay una concordancia en el sistema en la que un(a) Investigador(a) busca a este niño, niña, o adolescente. Contacte a la trabajadora social de este registro para acciones futuras si el niño, niña, o adolescente así lo desea.' + reassign: + multiple_successfully: Primero está reevaluando %{select_records} Caso(s). La actualización de todos los Casos puede tomar varios minutos. referral_done: Hacer clic en "Realizado" significa que usted ha completado el trabajo de referencia relacionado a este caso. Una vez usted hace clic en "Realizado" ya no tendrá acceso a este registro. referral_done_success: Referencia Realizada. referral_accepted_header: Aceptar Referencia @@ -414,6 +434,7 @@ es-GT: save_filter: Guardar selected_all_records: Seleccione todos los casos %{total_records} que concuerden con esta consulta. selected_records: '%{select_records} caso(s) seleccionado(s)' + selected_records_assign: '%{select_records}caso(s) seleccionados' sex: Sexo show_case: 'ID del Caso: %{short_id}' social_worker: Trabajadora Social @@ -474,6 +495,10 @@ es-GT: date_case_plan_initiated: Fecha del Plan del Caso date_of_creation: Fecha de Creación registration_date: Fecha de Registro + followup_date: Fecha del Seguimiento + date_reunification: Fecha de Reunificación + tracing_date: Fecha de Rastreo + service_implemented_day_time: Fecha de finalización del Servicio configurations: apply_label: ¿Está seguro(a)? Si usted aplica, los ajustes en esta configuración se aplicarán al sistema. Usted perderá todos sus ajustes actuales y no podrá recuperarlos a menos que ya los haya guardado en otra Configuración. apply_label_bold: Primero no estará disponible para sus usuario(a)s por unos minutos mientras se cargan los cambios. @@ -529,6 +554,13 @@ es-GT: all_cases: Todos los Casos all_services_implemented: Todos los Servicios Implementados and: 'y' + action_needed: + awaiting_acceptance: Esperando Aceptación + header: Acción requerida + new: Nuevo + new_this_week: Nuevo esta Semana + referrals: Referencias + transfers: Transferencias approval_action_plan_approved: Aprobado approval_action_plan_pending: Pendiente approval_action_plan_pending_group: Plan de Acción @@ -635,9 +667,9 @@ es-GT: current_owner: Propietario Actual dash_case_incident_overview: Mis Casos dash_group_overview: Casos de Mi Grupo - dash_shared_from_my_team: Coompartido Desde Mi Equipo + dash_shared_from_my_team: Compartido Desde Mi Equipo dash_shared_with_me: Compartido Conmigo - dash_shared_with_my_team: Coompartido Con Mi Equipo + dash_shared_with_my_team: Compartido Con Mi Equipo dash_shared_with_my_team_overview: Compartido con Mi Equipo (Resumen) dash_shared_with_others: Compartido Con Otro(a)s dash_national_admin_summary: Resumen de Administrador(a) @@ -801,6 +833,31 @@ es-GT: assign_html: '%{user} le ha asignado el siguiente %{record_type}: %{record_id}.' transfer_request_html: 'El/la usuario(a) de Primero %{user} de %{agency} está solicitando que le transfiera la propiedad de este %{record_type} registro %{record_id} para que pueda prestarle servicios de gestión de %{record_type} a la persona en su área. Si esta transferencia le parece aceptable, por favor haga clic en el vínculo de ID %{record_type} en este correo para abrir el %{record_type} en Primero e iniciar la transferencia.' transfer_request_notes_html: 'Notas de la persona que hace la solicitud: %{request_transfer_notes}' + alert: '%{record_type}%{id}-%{form_name} ha sido actualizado. Por favor, ingrese a Primero para revisar los cambios.' + alert_subject: '%{record_type}:%{id} - %{form_name} Actualizado' + webpush_notification: + action_label: Ir al Caso + approval_request: + title: Solicitud de Aprobación + body: Un caso de su equipo tiene una solicitud de aprobación pendiente por %{type}. + approval_response: + title: Respuesta de aprobación + body: Uno de sus casos ha recibido una respuesta de aprobación. + assign: + title: Nueva Asignación + body: Ha recibido una nueva Asignación de Caso. + referral: + title: Nueva Referencia + body: Ha recibido una nueva Referencia de Caso. + transfer: + title: Nueva Transferencia + body: Ha recibido una nueva Transferencia de Caso. + alert_case: + title: Caso Actualizado + body: "%{type}ha sido actualizado en uno de tus casos." + transfer_request: + title: Solicitud de Transferencia + body: Ha recibido una nueva solicitud de Transferencia de Caso. encrypt: export_type: Tipo de exportación file_name: Cree su propio nombre de archivo (Optativo) @@ -810,6 +867,8 @@ es-GT: address_fields: Necesita abordar %{fields} campos en %{forms} formularios address_form_fields: Necesita abordar %{fields} campos en este formulario address_subform_fields: '%{subform} tiene %{fields} campos inválidos' + error_401: Se ha cerrado su sesión. Por favor inicie sesión nuevamente. + error_something_went_wrong: Ha ocurrido un error. error_page: not_authorized: server_error: Usted no está autorizado(a) para acceder a esta página @@ -818,6 +877,10 @@ es-GT: contact_admin: Si cree que está aquí por error, por favor contacte a su admin. something_went_wrong: Lo sentimos ¡Algo salió mal! errors: + api: + internal_server: Error de Servidor + attachments: + maximum: Ha llegado a la cantidad máxima de adjuntos por Registro. error_loading: Error al Descargar Registro(s) models: agency: @@ -862,6 +925,11 @@ es-GT: title_present: El título no puede estar vacío content_present: El contenido no puede estar vacío created_by_present: Creado Por no debe estar vacío + webpush_subscription: + notification_url_present: notification_url no debe estar en blanco + notification_url_format: notification_url debe tener un formato de URL + auth_present: Auth no debe estar en blanco + p256dh_present: p256dh no debe estar en blanco not_found: No se Encon(tró)(traron) Registro(s) try_again: Trate de nuevo exports: @@ -1070,6 +1138,8 @@ es-GT: add_existing_field: Agregar Campo Existente add_field: Agregar Campo add_field_type: Agregar %{file_type} + attachments: + maximum_attached: Se ha alcanzado el límite máximo de adjuntos por Registro (%{maximumttachmentsPerRecord}). Esto incluye fotos, audio y documentos. Por favor elimine un adjunto antes de añadir otro. audio: current: Audio Actual audio_upload_box: Carga de Audio @@ -1284,10 +1354,13 @@ es-GT: violation: Violación registry_details: Detalles de Registro registry_record: Ficha de Registro + family_record: Registro de Familia + family: Registro de Familia required_field: '%{field} es un campo requerido' select_label: Seleccionar settings: Configuraciones show_on: Mostrar en + subform_need_to_be_added: Necesitan ser añadidos. subform_need_to_be_added_single: Debe agregarse. subform_not_found: No se encontró %{subform_name}. title: Título del Formulario @@ -1339,12 +1412,15 @@ es-GT: incident: code: Código de Incidente associated_case: "Caso Asociado:" + link_incident_to_case: Vincular Incidente al Caso + link_incident_to_case_success: Incidente(s) relacionado(s) al caso messages: creation_success: El registro del incidente se generó correctamente. creation_success_queue: El Registro del Incidente se generó correctamente (en background) disabled: El incidente está deshabilitado update_success: 'El incidente %{record_id} se actualizó correctamente.' update_success_queue: 'El Incidente %{record_id} se actualizó correctamente (en background).' + bulk_assign_limit_try_again: No puede asignar más de 100 incidentes al mismo tiempo. Por favor seleccione 100 incidentes o menos e inténtelo nuevamente. violation: associated_violations: "Violaciones asociadas:" update_and_return: 'Actualizar y Regresar a %{association}' @@ -1363,6 +1439,7 @@ es-GT: military_use: Uso militar de escuela(s) y/u hospital(es) denial_humanitarian_access: Negación de acceso a la ayuda humanitaria para los niños/niñas incidents: + change_status: Cambiar Estado disable_dialog: Al hacer clic en OK cambiará el estado de este incidente a Deshabilitado. disable_dialog_title: Deshabilitar Incidente disable_success: Incidente deshabilitado correctamente. @@ -1411,12 +1488,15 @@ es-GT: perpetrator_category: Tipo de perpetrador record_owner: Propietario del registro register_new_incident: Nuevo incidente + reassign: + multiple_successfully: 'Primero está reasignando %{select_records}incidente(s). Esta actualización puede demorar. Note que los incidentes ya enlazados a Casos no serán reasignados. ' selectable_date_options: date_of_first_report: Fecha de la Entrevista mrm_date_of_first_report: Fecha del reporte inicial al miebro de CTFMR ctfmr_verified_date: Fecha de la decisión de verificación de CTFMR incident_date_derived: Fecha del incidente selected_records: '%{select_records} incidente(s) seleccionados' + selected_records_assign: '%{select_records} incidente(s) seleccionado(s). Tome en cuenta que los incidentes ya enlazados a Casos no serán asignados.' selected_all_records: 'Seleccione todos los incidentes %{total_records} que concuerdan con esta consulta.' summary_mrm: label: Resumen del incidente @@ -1441,6 +1521,7 @@ es-GT: survivor_code: Código de sobreviviente show_incident: 'ID del Incidente %{short_id}' social_worker: Trabajadora Social + verify_mrm: Verificar MRM violation_type: Tipo de violación violence_type: Tipo de Violencia type_violence: Tipo de Violencia @@ -1633,6 +1714,8 @@ es-GT: township: Municipio municipality: Municipalidad autonomous_region: Región autónoma + parish: Parroquia + sub-county: Sub condado label: Ubicación name: Nombre code: Código @@ -1832,15 +1915,44 @@ es-GT: date: Fecha verification_status: Estado de verificación violation_type: Tipo de violación + status: Estado + status_open: Abierto + status_closed: Cerrado + user_group: Grupo de Usuario + agency: Agencia + by: por + workflow: Estado del flujo de trabajo + cp_incident_violence_type: Tipo de Violencia + referral_transfer_status: Estado de la Referencia/Transferencia + protection_concerns: Preocupaciones de Protección + location: Ubicación del Reporte + followup_type: Tipo de Seguimiento + service_type: Tipo de Servicio + status_options: + open: Abierto + closed: Cerrado + by_options: + created_by_groups: Grupo de Usuario del creador del Registro + owned_by_groups: Grupo de Usuario del dueño del Registro + created_organization: Agencia del Creador del Registro + owned_by_agency_id: Agencia del dueño del Registro + referral_transfer_status_options: + in_progress: Pendiente + accepted: Aceptado + rejected: Rechazado + done: Realizado date_range: month: Mes quarter: Trimestre year: Año + week: Semana date_range_options: this_quarter: Este trimestre last_quarter: El trimestre pasado this_month: Este mes last_month: Mes pasado + this_week: Esta Semana + last_week: Semana Anterior this_year: Este año last_year: Año pasado custom: Personalizado @@ -1856,6 +1968,49 @@ es-GT: individual_violation_type: Niños individuales por tipo de violación individual_region: Niños individuales por región individual_perpetrator: Niños individuales por perpetrador + services: + name: Servicios + description: Casos con la selección de tipos de Servicio, desglosados por edad y sexo. + services_report: + reports: + services: Servicios + description: Casos con el tipo de Servicio seleccionado, desglosado por edad y sexo. + sub_reports: + services: Servicios + filter_options: + service_implemented_day_time: Servicio completado + followups: + name: Seguimientos + description: Casos con el tipo de Seguimiento seleccionado, desglosado por edad y sexo. + followups_report: + filter_options: + followup_date: Fecha del Seguimiento + reports: + followups: Seguimientos + description: Casos con los tipos de Seguimientos seleccionados, desglosados por edad y sexo. + sub_reports: + followups: Seguimientos + protection_concerns: + name: Preocupaciones de Protección + description: Casos con las Preocupaciones de Protección seleccionadas, desglosados por edad y sexo. + protection_concerns_report: + reports: + protection_concerns: Preocupaciones de Protección + description: Casos con las Preocupaciones de Protección seleccionadas, desglosados por edad y sexo. + sub_reports: + protection_concerns: Preocupaciones de Protección + filter_options: + registration_date: Fecha del Registro + reporting_locations: + name: Ubicación del Reporte + description: 'Casos con la Ubicación de Reporte seleccionada, desglosados por edad y sexo.' + reporting_locations_report: + reports: + reporting_locations: Ubicación de Reporte + sub_reports: + reporting_location_by_sex_and_age: Ubicación de Reporte + filter_options: + registration_date: Fecha de Registro ghn_report: name: Nota Horizontal Global reports: @@ -1944,35 +2099,10 @@ es-GT: date_of_first_report: Fecha de la Entrevista incident_date: Fecha del Incidente reports: - incidents: Incidentes perpetrators: Perpetradores survivors: Sobrevivientes referrals: Referencias sub_reports: - combined: Incidentes - total: Número de Incidentes de VBG Reportados - gbv_sexual_violence: Número de Incidentes de Violencia Sexual Reportados - gbv_previous_incidents: Número de Incidentes Reportados por Sobrevivientes con Incidentes de VBG previos - gbv_sexual_violence_type: Tipo de Incidente - incident_timeofday: Hora del día del Incidente - elapsed_reporting_time: Tiempo transcurrido entre el Incidente y la Fecha de Reporte - elapsed_reporting_time_rape: Incidentes de violación, tiempo transcurrido entre el Incidente y Fecha de Reporte - elapsed_reporting_time_rape_health_referral: Incidentes de violación, tiempo transcurrido entre el Incidente y Fecha de Reporte - incident_location_type: Ubicación del Incidente - number_of_perpetrators: Número de Perpetradores - perpetrator_relationship: Relación del Presunto Perpetrador Principal con la/el Sobreviviente - perpetrator_age_group: Grupo de edad de Presunto(s) Perpetrador(es) Principal(es) - perpetrator_occupation: Ocupación del Presunto Perpetrador Principal - age: Número de sobrevivientes por edad - sex: Número de sobrevivientes por sexo - marital_status: Estado civil de sobrevivientes - displacement_status: Estado civil de sobrevivientes - displacement_incident: Etapa de desplazamiento al momento del incidente - gbv_case_context: Contexto del Caso - incidents_first_point_of_contact: Número de incidentes donde tu organizacion es el primer punto de contacto - incidents_from_other_service_provider: Incidentes derivados de otros proveedores de servicios - number_of_services_provided: Número de servicios prestados por incidentes - number_of_services_provided_other: Referencia de nuevos incidente a otros proveedores de otros servicios service_safehouse_referral: Referencia a casa segura/refugio seguro service_medical_referral: Referencia médica/salud service_psycho_referral: Servicios psicosociales/consejería @@ -1980,8 +2110,48 @@ es-GT: service_police_referral: Servicios de policía u otros servicios de seguridad service_livelihoods_referral: Servicios de Subsistencia service_protection_referral: Servicios de Protección a la Niñez - vulnerable_populations: Poblaciones vulnerables survivors_disability_type: Con discapacidad + workflow_report: + name: Flujo de Trabajo + description: Casos e Incidentes con el Estado de Flujo de Trabajo seleccionado, desglosado por edad y sexo. + reports: + cases_workflow: Flujo de Trabajo - Casos + incidents_workflow: Flujo de Trabajo - Incidentes + filter_options: + registration_date: Fecha de Registro + sub_reports: + case_workflow_by_sex_and_age: Número total de Casos por Sexo y Edad + incident_workflow_by_sex_and_age: Número total de Incidentes por Sexo y Edad + cases_workflow_report: + name: Flujo de Trabajo + description: Casos con el Estado del Flujo de Trabajo seleccionado, desglosado por edad y sexo. + reports: + cases_workflow: Flujo de Trabajo - Casos + filter_options: + registration_date: Fecha de Registro + sub_reports: + case_workflow_by_sex_and_age: Número total de Casos por Sexo y Edad + referrals_transfers_report: + name: Referencias y Transferencias + description: 'Referencias y Transferencias que han ocurrido dentro de un período de tiempo. Desglosado por Agencias o Grupos de Usuario que han enviado o recibido. ' + reports: + total_referrals: Referencias + total_transfers: Transferencias + sub_reports: + total_transfers_by_user_groups: Total de Transferencias + total_referrals_by_user_groups: Total de Referencias + filter_options: + registration_date: Fecha de Registro + violence_type_report: + name: Tipo de Violencia + reports: + cases_violence_type: Tipo de Violencia - Casos + incidents_violence_type: Tipo de Violencia - Incidentes + filter_options: + registration_date: Fecha de Registro + sub_reports: + case_violence_type_by_sex_and_age: Número total de Casos por Sexo y Edad + incident_violence_type_by_sex_and_age: Número total de Incidentes por Sexo y Edad success_message: Ha generado correctamente el archivo de exportación messages: alert_items: Usted tiene %{items} items de nota. @@ -2019,6 +2189,12 @@ es-GT: reports: Reportes insights: Perspectivas search: Buscar + phonetic_search: + title: Ingrese un nombre para buscar un registro existente. + label: Campos de Nombre de Usuario + help_text: La búsqueda fonética está disponible para campos de Nombre + id_search: + title: Ingrese el número de ID para buscar un registro existente. settings: Configuraciones support: Apoyo support_menu: @@ -2031,6 +2207,7 @@ es-GT: tracing_request: Solicitudes de Localización activity_log: Bitácora de actividades registry_records: Registro + families: Familias notes: note_success: Nota agregada correctamente permissions: @@ -2114,6 +2291,7 @@ es-GT: find_tracing_match: Encontrar concordancia en localización desde el caso view_registry_record: Ver Ficha de Registro add_registry_record: Agregar Ficha de Registro + family: Familia flag: Marcar form: Formularios group: Acceso a todos los registros o usuarios en mi grupo @@ -2141,6 +2319,7 @@ es-GT: reopen: Reabrir report: Reporte managed_report: Perspectivas + resolve_any_flag: Resolver cualquier Bandera request_approval: Solicitud para Aprobación request_approval_action_plan: 'Sólicitar aprobación %{approval_label} ' request_approval_assessment: 'Sólicitar aprobación %{approval_label} ' @@ -2163,6 +2342,7 @@ es-GT: transfer: Puede utilizarse para transferir user: Usuarios user_group: Grupos de usuario(a)s + verify_mrm: Verificar MRM view_approvals: Ver Aprobaciones view_assessment: Ver Evaluación view_photo: Ver Fotografía @@ -2173,6 +2353,7 @@ es-GT: workflow_team: Flujo de Trabajo - Casos de Equipos write: Escribir activity_log: Bitácora de actividades + remove_alert: Remover Alerta resource: kpi: actions: @@ -2333,6 +2514,7 @@ es-GT: label: Exportar galería de fotos export_unhcr_csv: label: Exportar CSV de OACNUDH + explanation: OBSOLETO - Esta función ya no está en uso. export_xls: explanation: 'Desde las páginas de listado de casos, o de presentación de casos, el/la usuario(a) puede generar la exportación de un archivo XLS, que contenga todos los campos a los que el/la usuario(a) actual tiene acceso para uno, varios, o todos los casos a los que el/la usuario(a) tiene acceso. En esta exportación, cada formulario está representado en su propia pestaña dentro del archivo XLS. NOTA: El formato XLS procesa caracteres no latinos (ej. Árabe, Bengalí) en un formato legible, mientras que el CSV exportado no.' label: Exportación de Excel (archivo XLS) @@ -2342,6 +2524,9 @@ es-GT: flag: explanation: 'Habilitado(a) para agregar una marca a un caso. Lo(a)s usuario(a)s con este permiso también pueden eliminar las marcas que hayan agregado a un caso. ' label: Marca + resolve_any_flag: + explanation: Permitir al usuario resolver cualquier Bandera en el registro, independientemente de quién haya creado la Bandera. + label: Resolver cualquier Bandera import: explanation: 'Permite a el/la usuario(a) crear uno o más casos nuevos importándolos desde un archivo CSV, Excel, o JSON. El archivo importado debe estar formateado "muy" específicamente para que la información se importe correctamente. Esta función sólo debe estar disponible para usuario(a)s administrativo(a)s con habilidades técnicas avanzadas y un conocimiento a fondo sobre cómo se formatean los datos en Primero. Sólo puede hacerse desde la página de listado de casos. ' label: Importar @@ -2351,6 +2536,9 @@ es-GT: incident_from_case: explanation: Este permiso le permite a el/la usuario(a) hacer un clic en el botón "Crear Incidente". Esto genera un incidente que puede contener alguna información copiada desde el caso. Para casos de Violencia Basada en Género (GVB), este botón está en el margen superior de la página de presentación de caso, y corresponde a información sobre el caso como un todo. En algunos contextos de localización de incidentes, este botón está en un subformulario de "Detalles del Incidente". En esta situación, alguna información puede ser copiada desde el subformulario de detalles del incidente en donde se hizo clic al botón, así como desde el caso como un todo. Es decir, el nuevo incidente creado puede contener el campo "Tipo de Violencia" desde el subformulario de incidente individual, pero también puede contender la edad y sexo del caso mismo. Nótese que este permiso también deja que el/ usuario(a) vea un vínculo hacia el incidente que fue creado. label: Crear un incidente desde un caso + remove_alert: + explanation: 'Este permiso permite al usuario quitar una alerta de un caso. Las alertas son usualmente generadas cuando un campo particular ha sido editado, como cuando las notas son actualizadas. Las alertas se muestran usualmente como un punto amarillo a lado del caso. ' + label: Remover alerta de un caso manage: explanation: Permite a un(a) usuario(a) llevar a cabo todas las acciones disponibles en los casos. El permiso "Administrar" significa en esencia "todo". label: Administrar (todos los permisos para este tipo de recurso) @@ -2441,10 +2629,28 @@ es-GT: mark_for_offline: explanation: Permite a el/la usuario(a) almacenar en caché los casos para utilizarlos sin conexión. label: Marca para fuera de línea + view_family_record: + explanation: Usuarios pueden ver el formulario de "Registro de Familia" en el caso, el cual incluye un enlace al registro de familia del caso. + label: Ver registro familiar del caso + case_from_family: + explanation: Usuarios pueden crear un Caso para uno de los miembros familiares del Caso en el subformulario de Detalles de la Familia. Tome en cuenta que un Registro de Familia será automáticamente creado para vincular estos dos casos. + label: Crear Caso a partir de los Detalles de la Familia + link_family_record: + explanation: Permite a un usuario buscar y vincular un Registro Familiar a su Caso. Además permite a los usuarios a desvincular un Registro Familiar de un Caso. + label: Vincular/Desvincular Registro Familiar del Caso explanation: Representa a un(a) niño/niña individual, a un(a) sobreviviente o a otro(a) beneficiario(a). label: Caso dashboard: actions: + action_needed_new_updated: + explanation: Muestra el indicador de "Nuevo y Actualizado" en el tablero de "Acción Requerida". Esto incluye Casos que han sido recientemente asignados al usuario actual, o aquellos que otro usuario ha actualizado desde la última vez que el usuario actual los haya actualizado. + label: 'Accion Requerida: Nuevo o Actualizado' + action_needed_new_referrals: + explanation: Muestra el indicador de "Nuevas Referencias" en el tablero de "Acción Requerida". Esto incluye cualquier Caso con una Referencia nueva enviada al usuario actual, donde el usuario actual no es la última persona en actualizar dicho Caso. + label: 'Acción Requerida: Nuevas Referencias' + action_needed_transfer_awaiting_acceptance: + explanation: 'Muestra el indicador de "Transferencias Esperando Aceptación" en el tablero de "Acción Requerida". Esto incluye cualquier Caso con una Transferencia al usuario actual, el cual el usuario actual no ha aceptado. ' + label: 'Acción Requerida: Transferencias Esperando Aceptación' approvals_action_plan: explanation: Muestra el número de casos de el/la usuario(a) actual que cuentan con solicitud de aprobación de Plan de Acción la cual está Pendiente, Aprobada, o Rechazada. label: Aprobaciones %{approval_label} de la trabajadora del caso @@ -2494,7 +2700,7 @@ es-GT: explanation: Permite a un(a) gerente ver cuántos casos tienen tareas de Servicios vencidas para cada una de sus trabajadoras de casos. label: tareas de Servicios Vencidas dash_case_incident_overview: - explanation: . + explanation: Muestra a un Gerente el número de casos manejados por cada usuario en su equipo, los cuales están siendo referidos o transferidos a otros usuarios. label: Información General - Mis Casos /Incidentes dash_cases_by_social_worker: explanation: Tabla que muestra el número total de casos abiertos y el número de nuevos casos gestionados por cada usuario(a) en los grupos de usuario(a)s de el/la usuario(a) actual. Cada línea es un(a) usuario(a) dentro de los grupos de usuario(a)s de el/la usuario(a) actual, mientras que columnas son dos "Total" y "Nuevo". @@ -2525,7 +2731,7 @@ es-GT: label: Casos por tipo de Prestación de Servicios dash_shared_from_my_team: explanation: Muestra a un(a) gerente el número de casos gestionados por cada usuario(a) en su equipo que han sido referidos o transferidos a otro(a)s usuario(a)s. - label: Coompartido Desde Mi Equipo + label: Compartido Desde Mi Equipo dash_shared_with_me: explanation: Muestra cuántos casos le han sido referidos o transferidos a usted. label: Compartido Conmigo @@ -2533,6 +2739,7 @@ es-GT: explanation: Muestra a un(a) gerente el número de casos referidos o transferidos a cada uno(a) de lo(a)s usuario(a)s en su equipo. label: Compartido Con Mi Equipo dash_shared_with_my_team_overview: + explanation: Muestra a un gerente el número de casos referidos o transferidos a cada uno de los usuarios en su equipo. label: Compartido con Mi Equipo (Resumen) dash_shared_with_others: explanation: Muestra cuántos de mis casos tienen referencias activas, transferencias pendientes, o transferencias rechazadas. Típicamente no es para gerentes, a menos que también gestionen casos. @@ -2569,6 +2776,9 @@ es-GT: disabled: explanation: Si usted deshabilita este Rol, ya no podrá asignarlo a las cuentas de Usuario(a). label: Deshabilitado + referral_authorization: + explanation: Esto significa que el rol va a aparecer como una opción para el listado "Tipo de Referencia" cuando el usuario realice una referencia interna. Si el usuario elige este rol como el tipo de referencia, el receptor de dicha referencia solo podrá acceder a los formularios que el rol seleccionado tiene permitido. Por ejemplo, si el usuario elige "Proveedor de Servicios Médicos" como Tipo de Referencia, y el rol de Proveedor de Servicios Médicos solo tiene acceso a los formularios de Identidad Básica y Preocupaciones de Protección, el recipiente solo podrá ver estos formularios. + label: ¿Puede utilizarse este rol en una lista desplegable de "Tipo de Referencia"? duplicate: actions: read: @@ -2589,6 +2799,9 @@ es-GT: registry_record: explanation: 'Limitar el acceso de un(a) usuario(a) a los formularios de registro limita la información que puede ver el/la usuario(a) sobre un registro. Por ejemplo, si el/la usuario(a) sólo tiene acceso al formulario de Propietario(a) del Registro, sólo podrá ver la información contenida en los campos de ese formulario. Si el/la usuario(a) actual tiene acceso limitado al formulario y está habilitado(a) para administrar la configuración del formulario, limitar su acceso al formulario también limita los formularios a los que puede configurar. NOTA: Si no se especifican los formularios, significa que el rol tiene acceso a todos los formularios de registro.' label: Formularios - Registro + family: + label: Formularios - Familia + explanation: 'Limitar el acceso de un usuario a los formularios para Familias limita cuál información el usuario puede ver sobre una Familia. Por ejemplo, si el usuario solo tiene acceso al formulario de Dueño del Caso, solo podrán ver la información contenida en los campos de ese formulario. Si el usuario actual tiene acceso limitado a los formularios y puede manejar la configuración de los formularios, limitar su acceso a los formularios también limita los formularios que pueda configurar.' group: actions: admin_only: @@ -2610,6 +2823,9 @@ es-GT: label: ¿Qué registros afecta este rol? incident: actions: + assign: + explanation: Permite a un usuario enviar un Incidente desde su dueño original del registro a cualquier otro usuario en el sistema. Los Incidentes que ya han sido vinculados a un Caso no pueden ser asignados; en su lugar debe reasignar el Caso vinculado, el cual actualizará la titularidad del registro. + label: Asignar change_log: explanation: El/la usuario(a) puede ver el historial de todos los cambios hechos al registro desde que fue creado. Esto incluye los valores registrados para todos los campos. label: Bitácora de Cambios @@ -2626,6 +2842,7 @@ es-GT: explanation: Desde las páginas de listado de incidentes, o de presentación de incidentes, el/la usuario(a) puede generar la exportación de un archivo CSV que contenga todos los campos a los que el/la usuario(a) actual tiene acceso para uno, varios, o todos los incidentes a los que el/la usuario(a) tiene acceso. label: Exportar CSV export_custom: + explanation: Usuario puede selecionar formularios o campos específicos para exportar a un archivo XLS. label: Exportar personalizado export_incident_recorder_xls: explanation: El/la usuario(a) puede generar la exportación de un archivo XLS especializado que permita el intercambio de datos con la herramienta Registradora de Incidentes de Violencia Basada en Género (GBV). @@ -2648,9 +2865,18 @@ es-GT: flag: explanation: 'Habilitado(a) para agregar una marca a un incidente. Lo(a)s usuario(a)s con este permiso también pueden eliminar las marcas que hayan agregado a un incidente. ' label: Marca + resolve_any_flag: + explanation: Permite al usuario resolver cualquier Bandera en el registro, independientemente de quién creó la Bandera. + label: Resolver cualquier Bandera import: explanation: 'Permite a el/la usuario(a) crear uno o más incidentes importándolos desde un archivo CSV, Excel, o JSON. El archivo importado debe estar formateado "muy" específicamente para que la información se importe correctamente. Esta función sólo debe estar disponible para usuario(a)s administrativo(a)s con habilidades técnicas avanzadas y un conocimiento a fondo sobre cómo se formatean los datos en Primero. Sólo puede hacerse desde la página de listado de incidentes. ' label: Importar + remove_alert: + explanation: 'Este permiso permite al usuario remover una alerta de un Incidente. Las alertas son generadas usualmente cuando un campo particular es editado, como cuando se actualiza una nota. Las alertas usualmente se muestran como un punto amarillo a lado de lncidente. ' + label: Remover una alerta de un Incidente + link_incident_to_case: + explanation: Permite al usuario vincular el incidente al caso seleccionado. + label: Vincular incidente al Caso manage: explanation: Permite a un(a) usuario(a) llevar a cabo todas las acciones disponibles en los Incidentes. El permiso "Administrar" significa en esencia "todo". label: Administrar (todos los permisos para este tipo de recurso) @@ -2660,6 +2886,9 @@ es-GT: sync_mobile: explanation: Este permiso generalmente le permite a el/la usuario(a) usar la aplicación móvil. En primer lugar, le permite ver las acciones "Marcar para Móvil" y "Desmarcar para Móvil", que aparecen en las páginas de listado de incidentes y presentación de incidentes. Marcar un incidente para móvil indica que la información de ese incidente debe estar sincronizada entre el dispositivo móvil de el/la usuario(a) y la aplicación web, mientras que desmarcar un caso del móvil, detiene esta sincronización. Lo(a)s usuario(a) sin este permiso tampoco pueden sincronizar sus dispositivos móviles con la aplicación web en general, lo que significa que no pueden usar la aplicación móvil para la gestión de incidentes. label: Sincronizar con dispositivo móvil + verify_mrm: + explanation: Usuario MRM puede cambiar el estado de las violaciones. + label: Verificar MRM write: explanation: Habilitado(a) para hacer clic en el botón "Editar", actualizar la información sobre el incidente, y hacer clic en "Guardar". También permite a el/la usuario(a) deshabilitar o habilitar un incidente. label: Editar @@ -2670,14 +2899,48 @@ es-GT: label: ¿Es Gerente? managed_report: actions: + reporting_locations_report: + label: Ubicación del Reporte (Casos) + explanation: La habilidad para ver estadísticas en el número de Casos registrados dentro de un período determinado, filtrado por Ubicación del Reporte, y desglosado por edad y sexo. Este permiso también permite al usuario exportar datos de un Insight. + followups_report: + label: Seguimientos (Casos) + explanation: La habilidad para ver estadísticas del número de Seguimientos realizados dentro de un período determinado, filtrado por Tipo de Seguimiento, y desglosado por edad y sexo. Este permiso además permite al usuario exportar datos de un Insight. + services_report: + label: Servicios (Casos) + explanation: La habilidad para ver estadísticas del número de Servicios realizados dentro de un período determinado, filtrado por tipo de servicio, y desglosado por edad y sexo. Este permiso además permite al usuario exportar data de un Insight. + protection_concerns_report: + label: Preocupaciones de Protección (Casos) + explanation: La habilidad de ver estadísticas de las Preocupaciones de Protección de Casos registrados dentro de un período determinado. Este permiso además permite al usuario exportar datos de un Insight. + managed_report_scope: + label: ¿Qué registros debe poder ver este rol en Insights? + managed_report_scope_all: + label: Todo + managed_report_scope_group: + label: Datos basados en Grupos solamente + managed_report_scope_agency: + label: Datos basados en Agencia solamente violations: + explanation: Habilidad para acceder a las Violaciones MRM de Insight. label: Violaciones gbv_statistics: + explanation: Habilidad para acceder y ver las Estadísticas de GBV en Insight. label: Estadísticas de VBG ghn_report: label: Nota Horizontal Global individual_children: label: Niños individuales + workflow_report: + label: Flujo de Trabajo (Casos e Incidentes) + explanation: Habilidad para ver estadísticas sobre el Estado del Flujo de Trabajo para los Casos e Incidentes vinculados a ellos. Este permiso además permite al usuario exportar data de un Insight. + cases_workflow_report: + label: Flujo de Trabajo (Casos) + explanation: Habilidad para ver las estadísticas de los Estados de Flujo de Trabajo de los Casos. Este permiso además permite al usuario a exportar data de un Insight. + violence_type_report: + label: Tipo de Violencia (Casos e Incidentes) + explanation: Habilidad para ver estadísticas de Tipo de Violencia. Este permiso además permite al usuario exportar datos de un Insight. + referrals_transfers_report: + label: Referencias y Transferencias (Casos) + explanation: 'Los usuarios ven el número de casos referidos y transferidos por cada Grupo de Usuarios a los demás Grupos de Usuarios. ' matching_configuration: actions: manage: @@ -2752,6 +3015,9 @@ es-GT: flag: explanation: Habilitado(a) para agregar una marca a una Ficha de Registro. Lo(a)s usuario(a)s con este permiso también pueden elimibar las marcas que hayan agregafo a una Ficha de Registro. label: Marcar Registros + resolve_any_flag: + explanation: Permite al usuario resolver cualquier Bandera del registro, independientemente de quién haya creado la Bandera. + label: Resolver cualquier Bandera manage: explanation: Permite a un(a) usuario(a) llevar a cabo todas las acciones disponibles en Fichas de Registro. El permiso "Administrar" significa en esencia "todo". label: Administrar (todos los permisos para este tipo de recurso) @@ -2766,6 +3032,63 @@ es-GT: label: Marca para fuera de línea explanation: Esto puede representar a un individuo o una institución que deben vincularse a otros registros como casos o incidentes, son muy numerosos y se actualizan repetidamente con nueva información. Son similares a las búsquedas, pero con un conjunto de información más complejo para cada entrada. label: Ficha de Registro + family: + actions: + change_log: + explanation: 'Los usuarios pueden ver el historial de todos los cambios realizadosal registro desde que fue creado. Esto incluye los valores registrados para todos los campos. ' + label: 'Bitácora de Cambios ' + create: + explanation: Habilidad para crear un registro de Familia + label: Crear + enable_disable_record: + explanation: Capacidad para deshabilitar o habilitar una Familia. Familias "Deshabilitadas" no aparecen en la lista de Familia por defecto. Los usuarios pueden ver Familias deshabilitadas en la lista de Familia utilizando un filtro. + label: Habilitar/Deshabilitar + export_csv: + explanation: 'El usuario puede generar un archivo CSV desde la página de lista de Familia y en la página de visión general de Familia, la cual contiene todos los campos a los cuales el usuario actual tiene acceso para una, múltiples, o varias Familias. Nota: el archivo CSV exportado no renderiza caracteres no Latinos (p.e. Arábico, Bangla)' + label: Exportar CSB + export_json: + explanation: El usuario puede generar un archivo exportado JSON de una lista de Familia o página de Familia, la cual contiene todos los campos para los cuales el usuario actual tiene acceso. El formato JSON es legible para una computadora y no práctico para muchos usuarios. + label: Exportar JSON + export_xls: + explanation: 'El usuario puede generar un archivo exportado XLS de la lista de Familia o página de Familia, la cual contiene todos los campos a los cuales el usuario actual tiene acceso. Nota: el formato XLS renderiza caracteres no Latinos (p.e. Arábico, Bangla) en un formato de lectura, mientras que las exportaciones en CSV no. ' + label: Excel (archivo XLS) exportado + export_list_view_csv: + explanation: El usuario puede generar un archivo CSV de exportación de la página de la lista de Familia, la cual contiene los mismos campos que aparecen para el usuario en la lista de Familia. Solo se realiza desde la página de lista de Familia. + label: Exportar CSV de vista de lista + export_pdf: + explanation: Los usuarios pueden generar un archivo PDF de exportación de la página de lista de Familia y en la página de visión general de Familia, las cuales contienen todos los campos para los cuales el usuario tiene acceso, para uno, múltiples o todos los registros. En el archivo PDF de exportación, la información está listada primero por familia, y luego se organiza por el formulario en donde aparece la información. + label: Exportar PDF + export_custom: + label: 'Exportar personalizado ' + explanation: El usuario puede seleccionar formularios o campos específicos de la página de lista de Familia o la página de visión general de Familia para exportar a un archivo XLS. + flag: + explanation: Habilidad para añadir una Bandera a una Familia. Los usuarios con este permiso además pueden remover las Banderas que hayan añadido a una Familia. + label: Bandera + resolve_any_flag: + explanation: Permite al usuario resolver cualquier Bandera en el registro, independientemente de quien creó la Bandera. + label: Resolver cualquier Bandera + manage: + explanation: Permite a un usuario realizar todas las acciones en Familias. El permiso de "Administrar" esencialmente significa "todo". + label: Administrar (todos los permisos para este tipo de recurso) + read: + explanation: Habilidad para ver Familias + label: Ver + write: + explanation: Habilidad para dar click en el botón de "Editar", actualizar información sobre la Familia y dar click en "Guardar". + label: Editar + sync_mobile: + explanation: Permite al usuario almacenar en caché los registros familiares para su uso fuera de línea. + label: Marcar para Fuera de Línea + close: + explanation: Permite a los usuarios pasar el estado de "Abierto" de una Familia a "Cerrado" + label: Cerrar + reopen: + explanation: Permite al usuario abrir una familia que está cerrada actualmente. + label: Reabrir + case_from_family: + explanation: Permite al usuario crear un caso nuevo de un subformulario de Miembro de Familia dentro del Registro de Familia. + label: Crear Caso + label: Familia report: actions: create: @@ -2861,6 +3184,9 @@ es-GT: flag: explanation: Habilitado(a) para agregar una marca a una solicitud de localización. Lo(a)s usuario(a)s con este permiso también pueden eliminar las marcas que han agregado a una solicitud de localización. label: Marcar + resolve_any_flag: + explanation: Permite al usuario resolver cualquier Bandera, independientemente de quién creó la Bandera. + label: Resolver cualquier Bandera import: explanation: 'Permite a el/la usuario(a) crear uno o más casos nuevos importándolos desde un archivo CSV, Excel, o JSON. El archivo importado debe estar formateado "muy" específicamente para que la información se importe correctamente. Esta función sólo debe estar disponible para usuario(a)s administrativo(a)s con habilidades técnicas avanzadas y un conocimiento a fondo sobre cómo se formatean los datos en Primero. Sólo puede hacerse desde la página de listado de casos. ' label: Importar @@ -2938,6 +3264,7 @@ es-GT: label: Eliminar manage: label: Administrar (todos los permisos para este tipo de recurso) + explanation: Utilizado para roles de sistema que le dan acceso a los Webhooks de Primero a otros sistemas. No es recomendado para usuarios que no son desarrolladores. activity_log: actions: transfer: @@ -2945,6 +3272,7 @@ es-GT: label: Transferencias manage: label: Administrar (todos los permisos para este tipo de recurso) + explanation: Habilidad para acceder a todo. label: Registro de Actividades potential_match: case_id: Identificación de Caso @@ -2966,11 +3294,12 @@ es-GT: display: Mostrando posibles concordancias para %{type}%{id} reassign: multiple_error: Ha ocurrido un error. %{select_records} caso(a) no asignados. - multiple_successfully: '%{select_records} caso(s) asignados correctamente' + multiple_successfully: Primero está reevaluando %{select_records}Caso(s). La actualización de todos los Casos puede tomar varios minutos. notes_label: Notas successfully: Reasignado correctamente user_mandatory_label: Se requiere destinatario(a) users_label: Destinatario(a) + incident_from_case_warning: No puede asignar este Incidente, porque ya está vinculado a un Caso. Cuando asigne el Caso, el Incidente se asignará también. record_information: assigned_user_names: Otro(a)s Usuario(a)s Asignado(a)s created_at: Fecha de creación de registro @@ -2992,6 +3321,8 @@ es-GT: referral: type_of_recipient: Tipo de Destinatario(a) type_of_referral_required: Se requiere Tipo de Referencia + referral_authorization_label: Quisiera especificar un Tipo de Referencia? + referral_authorization_help_text: Esto limitará a qué formularios puede acceder el receptor. agency_label: Agencia is_remote_label: ¿Está refiriendo a un sistema remoto? location_label: Ubicación @@ -3053,6 +3384,7 @@ es-GT: record_type: Tipo de registro total: Total value: Valor + incomplete_data: Data Incompleta reports: delete_report: Eliminar Reporte delete_report_message: ¿Está seguro(a) de que desea eliminar este reporte? La eliminación no se puede deshacer. Haga clic en OK para eliminar el informe @@ -3228,6 +3560,42 @@ es-GT: title: Marca para fuera de línea text: ¿Está seguro(a) de que quiere marcar estas fichas de registro para usarlos cuando esté desconectado(a)? success: Fichas de Registro marcados correctamente para uso fuera de línea + families: + id: ID + label: Familias + family_id: ID de Familia + family_number: Número de Familia + family_name: Nombre de la Familia + family_registration_date: Fecha de Registro + family_location_current: Ubicación de la Familia + export: Exportar + register_new_family: Nueva Familia + show_family: 'ID de Familia %{short_id}' + disable_dialog_title: Deshabilitar Familia + disable_dialog: Al dar click en Ok se cambiará el estado de esta Familia a Deshabilitada. + selected_records: '%{select_records}registro(s) de familia seleccionado(s)' + selected_all_records: 'Seleccionar las %{total_records}familias que coinciden con esta consulta.' + mark_for_offline: + title: Marcar para Fuera de Línea + text: ¿Está seguro que quiere marcar estos Registros de Familia para utilizar cuando esté fuera de línea? + success: Registros de Familia marcados exitosamente para uso Fuera de Línea + filter_by: + by_date: Por Fecha + status: Estado + current_location: Ubicación de la Familia + family: + family_member: + case_id: ID del Caso + update_and_return: Actualizar y Regresar + save_and_return: Añadir y Regresar + create_case: Crear Caso + back_to_family_members: 'Regresar a Miembros de la Familia ' + create: Crear + messages: + update_success: 'Familia %{record_id} fue actualizada exitosamente.' + creation_success: 'La Familia fue creada exitosamente.' + disabled: Familia está deshabilitada + confirm_create_case: ¿Quiere crear un Caso para este individuo? transfer: label: 'Transferir ' agency_label: Agencia @@ -3273,6 +3641,7 @@ es-GT: inprogress: Pendiente rejected: Rechazado revoked: Anulado + transferred_by: Transferido por type: assign: Asignar reassign: Asignar @@ -3293,6 +3662,7 @@ es-GT: locale: Ubicación location: Ubicación messages: + records_update: 'Primero está actualizando los registros de este usuario para reflejar los cambios que ha realizado. Puede que los reportes y tableros tomen unos minutos para actualizarse. ' confirmation: ¿Está seguro(a) de que desea eliminar este usuario? La eliminación no puede deshacerse. Haga clic en OK para eliminar el usuario. created: El usuario se generó correctamente. failure: Ocurrió un error, por favor contacte a apoyo. @@ -3303,6 +3673,7 @@ es-GT: passwords_do_not_match: no concuerda con la contraseña actual time_zone_updated: El cambio se actualizó correctamente. updated: El usuario se actualizó correctamente. + created_warning: Usted ha creado %{total_enabled} de sus %{maximum_users}usuarios habilitados permitidos. organization: Organización agency: Agencia services_help_text: Si no especifica servicios, a este Usuario se le darán los mismos servicios que tiene su Agencia. @@ -3321,6 +3692,21 @@ es-GT: provider_username_help: 'Ejemplo: mi.nombreseusuario@%{domain}' role_id: Rol send_mail: ¿Recibir correos electrónicos de confirmación? + send_mail_preferences: + label: ¿Qué tipos de correos de notificaciones quisiera recibir? + help_text: Si usted deja este campo en blanco, recibirá todos los emails de notificaciones. + receive_webpush: + label: ¿Recibir notificaciones automáticas? + help_text: Tome en cuenta que aún tendrá que permitir las notificaciones automáticas en el navegador de su dispositivo. + tooltip: Usted debe primero editar su cuenta y habilitar notificaciones automáticas para sus usuarios. + receive_webpush_preferences: + label: ¿Qué tipos de notificaciones automáticas quisiera recibir? + help_text: Si deja este campo en blanco, recibirá todas las notificaciones automáticas. + notification_preferences: + approval_request: 'Solicitud de Aprobación (Gerentes)' + approval_response: 'Respuesta de Aprobación (Trabajador de Caso)' + transition_notification: 'Asignaciones, Transferencias, y Referencias' + transfer_request: 'Solicitudes de Transferencia' user_group_unique_ids: Grupos de usuario(a)s. user_name: Nombre de usuario services: Servicios @@ -3380,6 +3766,10 @@ es-GT: user_name: Nombre de usuario position: Puesto agency: Agencia + alerts: + total_users_created: Usted ha creado %{total_enabled}de los %{maximum_users}usuarios habilitados permitidos como máximo. + limit_user_reached: 'Usted ha llegado a su límite de %{maximum_users}Usuarios habilitados. Debe deshabilitar uno o más Usuarios antes de crear más. ' + limit_user_reached_on_enable: Usted ha llegado a su límite de %{maximum_users}Usuarios habilitados. Usted debe deshabilitar uno o más Usuarios antes de crear o habilitar más. devise: failure: already_authenticated: "Usted ya ha iniciado sesión." @@ -3391,3 +3781,13 @@ es-GT: selected_records: '%{select_records} localidad(es) seleccionada(s)' selected_all_records: Seleccione todos los casos %{total_records} que concuerden con esta consulta. updated: '%{updated_records}localidad(es) actualizada(s)' + push_notifications_dialog: + title: 'Notificación en Dispositvos ' + body_blocked: + message: 'Usted ha bloqueado notificaciones de Primero en este dispositivo. Para cambiar esto, necesitará activar los permisos de notificaciones. ' + android: "Android: Vaya a Configuración. De click en Apps. Encuentre Primero en la lista de aplicaciones y de click en esto. De click a Notificaciones. Cambie el botón de notificaciones al estado \"encendido\"." + ios: "iOS: Vaya al app de Configuración. De click en Notificaciones. Desplace la lista hacia abajo a la lista de Apps y encuentre Primero. Active la opción de notificaciones de Primero." + body: + one: ¿Quiere permitir que Primero le envíe notificaciones? Recuerde que seguirá recibiendo notificaciones en este dispositivo %{count}día luego de haber cerrado sesión. Esto no es recomendado para dispositivos compartidos. + many: ¿Quiere permitir que Primero le envíe notificaciones? Recuerde que seguirá recibiendo notificaciones en este dispositivo %{count}días luego de haber cerrado sesión. Esto no es recomendado para dispositivos compartidos. + other: ¿Quiere permitir que Primero le envíe notificaciones? Recuerde que va a continuar recibiendo notificaciones en este dispositivo %{count}días luego de haber cerrado sesión. Esto no es recomendado para dispositivos compartidos. diff --git a/config/locales/es.yml b/config/locales/es.yml index 946807a287..1ff1d986d4 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -84,6 +84,7 @@ es: terms_of_use_download_button: Descargar PDF terms_of_use_enabled: ¿Mostrar Términos de su Uso? approvals: + no_requests: Caso approved_by: Aprobado Por case_plan_type_label: Tipo de Plan de Caso manager_comments_label: Comentarios de Gerente @@ -166,6 +167,7 @@ es: import: Importar login: Iniciar sesión logout: Terminar sesión + link: Enlace mark_for_mobile: Marcar para móvil new: Nuevo ok: OK @@ -198,6 +200,8 @@ es: view: Ver view_flags_history: Ver Historial return_to_case: Regresar al Caso + enable_webpush: notificaciones del dispositivo + dialog_yes: "Si" resync_records: id: Documento de Identificación (ID) record_type: Tipo de registro @@ -210,7 +214,10 @@ es: case: label: Caso create_new_case: Crear Nuevo Caso + create_case: Crear caso + create: Crear add_new: Agregar Nuevo + back_to_family_details: Regresar a Datos de la Familia back_to_case: Regresar al Caso back_to_results: Regresar a Resultados back_to_search: Regresar a Buscar @@ -234,6 +241,14 @@ es: introductory_sentence: Por favor especificque el consentimiento de la persona para recibir los servicios de gestión de casos y para que sus datos se almacenen en Primero. consent_agreements_required: Por favor seleccione al menos una opción de los acuerdos de consentimiento. legitimate_basis_required: Por favor seleccione al menos una opción de las clasificaciones base permitidas + confirm_create_case: ¿Desea crear un Caso para esta persona? + case_referral_pending: Hay una referencia de Caso pendiente. + case_transfer_pending: Hay una transferencia de Caso pendiente. + case_no_approval_request: No hay solicitudes de aprobación para este Caso. + bulk_assign_limit: No puede asignar mas de 100 Casos al mismo tiempo. + bulk_assign_limit_try_again: No puede asignar mas de 100 Casos al mismo tiempo. Por favor, seleccione 100 Casos o menos e inténtelo nuevamente. + referral_rejected: La Referencia ha sido rechazada. + transfer_request_made: Una solicitud de transferencia ha sido realizada para este caso. save: Guardar Caso save_text: Antes de continuar, por favor guarde los cambios hechos al Caso skip_and_create: Omitir y Crear Nuevo Caso @@ -241,6 +256,7 @@ es: search_helper_text: ¿Para qué? Para evitar la creación de casos duplicados. consent_agreements: Selecciones todos los acuerdos de consentimiento que apliquen legitimate_basis: Seleccione todas las clasificaciones base permitidas que apliquen + family_linked_subform_delete_disabled: Este sub formulario está enlazado a un Registro Familiar. Por favor, remueva a este miembro de la familia del Registro Familiar, o desvincule el Caso del familiar del Registro Familiar. workflow: assessment: Evaluación case_plan: Plan del Caso @@ -260,6 +276,7 @@ es: rejected_transfer: '%{to} transferencia rechazada de %{record_type}%{record_id} de %{from}' cases: action_plan: Plan de Acción + access_denied: "Usted no tiene acceso a este Caso." age: Edad age_estimated: ¿Edad Estimada? agency: Agencia @@ -354,6 +371,7 @@ es: urgent_protection_concern: Inquietud sobre Protección Urgente user_group: Grupo de Usuario(a)s workflow: Casos por Flujo de Trabajo + include_disabled: Incluya personas con discapacidad flag_summary: Resumen de registros marcados full_name: Nombre Completo gbv_closure: Cierre de Violencia Basada en Género (GBV) @@ -377,6 +395,8 @@ es: photos: Fotografía quick_view: tracing_message: 'Nota: Hay una concordancia en el sistema en la que un(a) Investigador(a) busca a este niño, niña, o adolescente. Contacte a la trabajadora social de este registro para acciones futuras si el niño, niña, o adolescente así lo desea.' + reassign: + multiple_successfully: Primero está reasignando %{select_records}Caso(s). La actualización de todos los Casos puede tomar varios minutos. referral_done: Hacer clic en "Realizado" significa que usted ha completado el trabajo de referencia relacionado a este caso. Una vez usted hace clic en "Realizado" ya no tendrá acceso a este registro. referral_done_success: Referencia Realizada. referral_accepted_header: Aceptar Referencia @@ -414,6 +434,7 @@ es: save_filter: Guardar selected_all_records: Seleccione todos los casos %{total_records} que concuerden con esta consulta. selected_records: '%{select_records} caso(s) seleccionado(s)' + selected_records_assign: '%{select_records} caso(s) seleccionado(s)' sex: Sexo show_case: 'ID del Caso: %{short_id}' social_worker: Trabajadora Social @@ -474,6 +495,10 @@ es: date_case_plan_initiated: Fecha del Plan del Caso date_of_creation: Fecha de Creación registration_date: Fecha de Registro + followup_date: Fecha del Seguimiento + date_reunification: Fecha de Reunificación + tracing_date: Fecha de seguimiento + service_implemented_day_time: Fecha de finalización del Servicio configurations: apply_label: ¿Está seguro(a)? Si usted aplica, los ajustes en esta configuración se aplicarán al sistema. Usted perderá todos sus ajustes actuales y no podrá recuperarlos a menos que ya los haya guardado en otra Configuración. apply_label_bold: Primero no estará disponible para sus usuario(a)s por unos minutos mientras se cargan los cambios. @@ -529,6 +554,13 @@ es: all_cases: Todos los Casos all_services_implemented: Todos los Servicios Implementados and: 'y' + action_needed: + awaiting_acceptance: Esperando Aceptación + header: Acción requerida + new: Nuevo + new_this_week: Nuevo esta Semana + referrals: Referencias + transfers: Transferencias approval_action_plan_approved: Aprobado approval_action_plan_pending: Pendiente approval_action_plan_pending_group: Plan de Acción @@ -801,6 +833,31 @@ es: assign_html: '%{user} le ha asignado el siguiente %{record_type}: %{record_id}.' transfer_request_html: 'El/la usuario(a) de Primero %{user} de %{agency} está solicitando que le transfiera la propiedad de este %{record_type} registro %{record_id} para que pueda prestarle servicios de gestión de %{record_type} a la persona en su área. Si esta transferencia le parece aceptable, por favor haga clic en el vínculo de ID %{record_type} en este correo para abrir el %{record_type} en Primero e iniciar la transferencia.' transfer_request_notes_html: 'Notas de la persona que hace la solicitud: %{request_transfer_notes}' + alert: '%{record_type}%{id}-%{form_name}ha sido actualizado. Por favor, ingrese a Primero para revisar los cambios.' + alert_subject: '%{record_type}:%{id} - %{form_name}Actualizado' + webpush_notification: + action_label: Ir al Caso + approval_request: + title: Solicitud de Aprobación + body: Un caso de su equipo tiene una solicitud de aprobación pendiente por %{type}. + approval_response: + title: Respuesta de aprobación + body: Uno de sus casos ha recibido una respuesta de aprobación. + assign: + title: Nueva tarea + body: Usted ha recibido una nueva Asignación de Caso. + referral: + title: Nueva Referencia + body: Usted ha recibido una nueva Referencia de Caso. + transfer: + title: Nueva Transferencia + body: Usted ha recibido una nueva Transferencia de Caso. + alert_case: + title: Caso Actualizado + body: "%{type}ha sido actualizado en uno de tus casos." + transfer_request: + title: Solicitud de Transferencia + body: Usted ha recibido una nueva solicitud de Transferencia de Caso. encrypt: export_type: Tipo de exportación file_name: Cree su propio nombre de archivo (Optativo) @@ -810,6 +867,8 @@ es: address_fields: Necesita abordar %{fields} campos en %{forms} formularios address_form_fields: Necesita abordar %{fields} campos en este formulario address_subform_fields: '%{subform} tiene %{fields} campos inválidos' + error_401: Se ha cerrado su sesión. Por favor inicie sesión nuevamente. + error_something_went_wrong: Ha ocurrido un error. error_page: not_authorized: server_error: Usted no está autorizado(a) para acceder a esta página @@ -818,6 +877,10 @@ es: contact_admin: Si cree que está aquí por error, por favor contacte a su admin. something_went_wrong: Lo sentimos ¡Algo salió mal! errors: + api: + internal_server: Error de Servidor + attachments: + maximum: Ha alcanzado la cantidad máxima de archivos adjuntos por Registro. error_loading: Error al Descargar Registro(s) models: agency: @@ -862,6 +925,11 @@ es: title_present: El título no puede estar vacío content_present: El contenido no puede estar vacío created_by_present: Creado Por no debe estar vacío + webpush_subscription: + notification_url_present: notification_url no debe estar vacío + notification_url_format: notification_url debe tener un formato URL + auth_present: Auth no debe estar vacío + p256dh_present: p256dh no debe estar vacío not_found: No se Encon(tró)(traron) Registro(s) try_again: Trate de nuevo exports: @@ -1070,6 +1138,8 @@ es: add_existing_field: Agregar Campo Existente add_field: Agregar Campo add_field_type: Agregar %{file_type} + attachments: + maximum_attached: Se ha alcanzado el límite máximo de archivos adjuntos por Registro (%{maximumttachmentsPerRecord}). Esto incluye fotos, audio y documentos. Por favor elimine un archivo adjunto antes de añadir otro. audio: current: Audio Actual audio_upload_box: Carga de Audio @@ -1284,6 +1354,8 @@ es: violation: Violación registry_details: Detalles de Registro registry_record: Ficha de Registro + family_record: Registro de Familia + family: Registro de Familia required_field: '%{field} es un campo requerido' select_label: Seleccionar settings: Configuraciones @@ -1331,6 +1403,7 @@ es: ar-LB: العربية (اللبنانية) ar-SD: العربية (السودانية) bn: বাংলা + cmn: Chino current_time_zone: Zona horaria actual dashboard: Tablero en: Inglés @@ -1350,6 +1423,7 @@ es: ne: नेपाली om: Oromo am-ET: Amharic (Ethiopia) + tr: Turco label: Pagina de inicio language: Idioma manage_system_users: Administrar la Sincronización de Usuario(a)s en el Servidor @@ -1371,12 +1445,15 @@ es: incident: code: Código de Incidente associated_case: "Caso Asociado:" + link_incident_to_case: Vincular Incidente al Caso + link_incident_to_case_success: Incidente(s) vinculado(s) al caso messages: creation_success: El registro del incidente se generó correctamente. creation_success_queue: El Registro del Incidente se generó correctamente (en background) disabled: El incidente está deshabilitado update_success: 'El incidente %{record_id} se actualizó correctamente.' update_success_queue: 'El Incidente %{record_id} se actualizó correctamente (en background).' + bulk_assign_limit_try_again: No puede asignar más de 100 incidentes al mismo tiempo. Por favor seleccione 100 incidentes o menos e inténtelo nuevamente. violation: associated_violations: "Violaciones asociadas:" update_and_return: 'Actualizar y Regresar a %{association}' @@ -1395,6 +1472,7 @@ es: military_use: Uso militar de escuela(s) y/u hospital(es) denial_humanitarian_access: Negación de acceso a la ayuda humanitaria para los niños/niñas incidents: + change_status: Cambiar Estado disable_dialog: Al hacer clic en OK cambiará el estado de este incidente a Deshabilitado. disable_dialog_title: Deshabilitar Incidente disable_success: Incidente deshabilitado correctamente. @@ -1443,12 +1521,15 @@ es: perpetrator_category: Tipo de perpetrador record_owner: Propietario(a) del Registro register_new_incident: Nuevo incidente + reassign: + multiple_successfully: 'Primero está reasignando %{select_records}incidente(s). Esta actualización puede demorar. Note que los incidentes ya vinculados a Casos no serán reasignados. ' selectable_date_options: date_of_first_report: Fecha de la Entrevista mrm_date_of_first_report: Fecha del reporte inicial al miebro de CTFMR ctfmr_verified_date: Fecha de la decisión de verificación de CTFMR incident_date_derived: Fecha del incidente selected_records: '%{select_records} incidente(s) seleccionados' + selected_records_assign: '%{select_records} incidente(s) seleccionado(s). Tome en cuenta que los incidentes ya vinculados a Casos no serán asignados.' selected_all_records: 'Seleccione todos los incidentes %{total_records} que concuerdan con esta consulta.' summary_mrm: label: Resumen del incidente @@ -1473,6 +1554,7 @@ es: survivor_code: Código de sobreviviente show_incident: 'ID del Incidente %{short_id}' social_worker: Trabajadora Social + verify_mrm: Verifique MRM violation_type: Tipo de violación violence_type: Tipo de Violencia type_violence: Tipo de Violencia @@ -1665,6 +1747,8 @@ es: township: Municipio municipality: Municipalidad autonomous_region: Región autónoma + parish: Parroquia + sub-county: Sub condado label: Ubicación name: Nombre code: Código @@ -1864,15 +1948,44 @@ es: date: Fecha verification_status: Estado de verificación violation_type: Tipo de violación + status: Estado + status_open: Abierto + status_closed: Cerrado + user_group: Grupo de Usuario(a)s + agency: Agencia + by: por + workflow: Estado del flujo de trabajo + cp_incident_violence_type: Tipo de Violencia + referral_transfer_status: Estado de la Referencia/Transferencia + protection_concerns: Preocupaciones de Protección + location: Ubicación de Reporte + followup_type: Tipo de Seguimiento + service_type: Tipo de Servicio + status_options: + open: Abierto + closed: Cerrado + by_options: + created_by_groups: Grupo de Usuario del(la) creador(a) del Registro + owned_by_groups: Grupo de Usuario del(la) dueño(a) del Registro + created_organization: Agencia del(la) Creador(a) del Registro + owned_by_agency_id: Agencia del(la) dueño(a) del Registro + referral_transfer_status_options: + in_progress: Pendiente + accepted: Aceptado + rejected: Rechazado + done: Realizado date_range: month: Mes quarter: Trimestre year: Año + week: Semana date_range_options: this_quarter: Este trimestre last_quarter: El trimestre pasado this_month: Este mes last_month: El mes pasado + this_week: Esta Semana + last_week: Semana Anterior this_year: Este año last_year: El año pasado custom: Personalizado @@ -1888,6 +2001,49 @@ es: individual_violation_type: Niños individuales por tipo de violación individual_region: Niños individuales por región individual_perpetrator: Niños individuales por perpetrador + services: + name: Servicios + description: Casos con el tipo de Servicio seleccionado, desagregado por edad y sexo. + services_report: + reports: + services: Servicios + description: Casos con el tipo de Servicio seleccionado, desagregado por edad y sexo. + sub_reports: + services: Servicios + filter_options: + service_implemented_day_time: Servicio completado + followups: + name: Seguimientos + description: Casos con el tipo de Seguimiento seleccionado, desagregado por edad y sexo. + followups_report: + filter_options: + followup_date: Fecha del Seguimiento + reports: + followups: Seguimientos + description: Casos con el tipo de Seguimiento seleccionado, desagregado por edad y sexo. + sub_reports: + followups: Seguimientos + protection_concerns: + name: Preocupaciones de Protección + description: Casos con las Preocupaciones de Protección seleccionadas, desagregados por edad y sexo. + protection_concerns_report: + reports: + protection_concerns: Preocupaciones de Protección + description: Casos con las Preocupaciones de Protección seleccionadas, desagregados por edad y sexo. + sub_reports: + protection_concerns: Preocupaciones de Protección + filter_options: + registration_date: Fecha de Registro + reporting_locations: + name: Ubicación del Reporte + description: 'Casos con la Ubicación de Reporte seleccionada, desagregados por edad y sexo.' + reporting_locations_report: + reports: + reporting_locations: Ubicación del Reporte + sub_reports: + reporting_location_by_sex_and_age: Ubicación del Reporte + filter_options: + registration_date: Fecha de Registro ghn_report: name: Nota Horizontal Global reports: @@ -1976,35 +2132,10 @@ es: date_of_first_report: Fecha de la Entrevista incident_date: Fecha del Incidente reports: - incidents: Incidentes perpetrators: Perpetradores survivors: Sobrevivientes referrals: Referencias sub_reports: - combined: Incidentes - total: Número de Incidentes de VBG Reportados - gbv_sexual_violence: Número de Incidentes de Violencia Sexual Reportados - gbv_previous_incidents: Número de Incidentes Reportados por Sobrevivientes con Incidentes de VBG previos - gbv_sexual_violence_type: Tipo de Incidente - incident_timeofday: Hora del día del Incidente - elapsed_reporting_time: Tiempo transcurrido entre el Incidente y la Fecha de Reporte - elapsed_reporting_time_rape: Incidentes de violación, tiempo transcurrido entre el Incidente y Fecha de Reporte - elapsed_reporting_time_rape_health_referral: Incidentes de violación, tiempo transcurrido entre el Incidente y Fecha de Reporte - incident_location_type: Ubicación del Incidente - number_of_perpetrators: Número de Perpetradores - perpetrator_relationship: Relación del Presunto Perpetrador Principal con la/el Sobreviviente - perpetrator_age_group: Grupo de edad de Presunto(s) Perpetrador(es) Principal(es) - perpetrator_occupation: Ocupación del Presunto Perpetrador Principal - age: Número de sobrevivientes por edad - sex: Número de sobrevivientes por sexo - marital_status: Estado civil de sobrevivientes - displacement_status: Estado civil de sobrevivientes - displacement_incident: Etapa de desplazamiento al momento del incidente - gbv_case_context: Contexto del Caso - incidents_first_point_of_contact: Número de incidentes donde tu organizacion es el primer punto de contacto - incidents_from_other_service_provider: Incidentes derivados de otros proveedores de servicios - number_of_services_provided: Número de servicios prestados por incidentes - number_of_services_provided_other: Referencia de nuevos incidente a otros proveedores de otros servicios service_safehouse_referral: Referencia a casa segura/refugio seguro service_medical_referral: Referencia médica/salud service_psycho_referral: Servicios psicosociales/consejería @@ -2012,8 +2143,48 @@ es: service_police_referral: Servicios de policía u otros servicios de seguridad service_livelihoods_referral: Servicios de Subsistencia service_protection_referral: Servicios de Protección a la Niñez - vulnerable_populations: Poblaciones vulnerables survivors_disability_type: Con discapacidad + workflow_report: + name: Flujo de Trabajo + description: Casos e Incidentes con el Estado de Flujo de Trabajo seleccionado, desagregado por edad y sexo. + reports: + cases_workflow: Flujo de Trabajo - Casos + incidents_workflow: Flujo de Trabajo - Incidentes + filter_options: + registration_date: Fecha de Registro + sub_reports: + case_workflow_by_sex_and_age: Número total de Casos por Sexo y Edad + incident_workflow_by_sex_and_age: Número total de Incidentes por Sexo y Edad + cases_workflow_report: + name: Flujo de Trabajo + description: Casos con el Estado del Flujo de Trabajo seleccionado, desagregado por edad y sexo. + reports: + cases_workflow: Flujo de Trabajo - Casos + filter_options: + registration_date: Fecha de Registro + sub_reports: + case_workflow_by_sex_and_age: Número total de Casos por Sexo y Edad + referrals_transfers_report: + name: Referencias y Transferencias + description: 'Referencias y Transferencias que han ocurrido dentro de un período de tiempo. Desagregado por Agencias o Grupos de Usuario que han enviado y recibido. ' + reports: + total_referrals: Referencias + total_transfers: Transferencias + sub_reports: + total_transfers_by_user_groups: Total de Transferencias + total_referrals_by_user_groups: Referencias Totales + filter_options: + registration_date: Fecha de Registro + violence_type_report: + name: Tipo de Violencia + reports: + cases_violence_type: Tipo de Violencia - Casos + incidents_violence_type: Tipo de Violencia - Incidentes + filter_options: + registration_date: Fecha de Registro + sub_reports: + case_violence_type_by_sex_and_age: Número total de Casos por Sexo y Edad + incident_violence_type_by_sex_and_age: Número total de Incidentes por Sexo y Edad success_message: Ha generado correctamente el archivo de exportación messages: alert_items: Usted tiene %{items} items de nota. @@ -2063,6 +2234,7 @@ es: tracing_request: Solicitudes de Localización activity_log: Registro de Actividades registry_records: Registro + families: Familias notes: note_success: Nota agregada correctamente permissions: @@ -2146,6 +2318,7 @@ es: find_tracing_match: Encontrar concordancia en localización desde el caso view_registry_record: Ver Ficha de Registro add_registry_record: Agregar Ficha de Registro + family: Familia flag: Marcar form: Formularios group: Acceso a todos los registros o usuarios en mi grupo @@ -2173,6 +2346,7 @@ es: reopen: Reabrir report: Reporte managed_report: Perspectiva + resolve_any_flag: Resolver cualquier Bandera request_approval: Solicitud para Aprobación request_approval_action_plan: 'Sólicitar aprobación %{approval_label} ' request_approval_assessment: 'Sólicitar aprobación %{approval_label} ' @@ -2195,6 +2369,7 @@ es: transfer: Puede utilizarse para transferir user: Usuarios user_group: Grupos de usuario(a)s + verify_mrm: Verifique MRM view_approvals: Ver Aprobaciones view_assessment: Ver Evaluación view_photo: Ver Fotografía @@ -2205,6 +2380,7 @@ es: workflow_team: Flujo de Trabajo - Casos de Equipos write: Escribir activity_log: Registro de Actividades + remove_alert: Eliminar alerta resource: kpi: actions: @@ -2365,6 +2541,7 @@ es: label: Exportar galería de fotos export_unhcr_csv: label: Exportar CSV de OACNUDH + explanation: OBSOLETO - Esta función ya no está en uso. export_xls: explanation: 'Desde las páginas de listado de casos, o de presentación de casos, el/la usuario(a) puede generar la exportación de un archivo XLS, que contenga todos los campos a los que el/la usuario(a) actual tiene acceso para uno, varios, o todos los casos a los que el/la usuario(a) tiene acceso. En esta exportación, cada formulario está representado en su propia pestaña dentro del archivo XLS. NOTA: El formato XLS procesa caracteres no latinos (ej. Árabe, Bengalí) en un formato legible, mientras que el CSV exportado no.' label: Exportación de Excel (archivo XLS) @@ -2374,6 +2551,8 @@ es: flag: explanation: 'Habilitado(a) para agregar una marca a un caso. Lo(a)s usuario(a)s con este permiso también pueden eliminar las marcas que hayan agregado a un caso. ' label: Marca + resolve_any_flag: + explanation: Permite al usuario resolver cualquier Alerta en el registro, independientemente de quién creó la Alerta. import: explanation: 'Permite a el/la usuario(a) crear uno o más casos nuevos importándolos desde un archivo CSV, Excel, o JSON. El archivo importado debe estar formateado "muy" específicamente para que la información se importe correctamente. Esta función sólo debe estar disponible para usuario(a)s administrativo(a)s con habilidades técnicas avanzadas y un conocimiento a fondo sobre cómo se formatean los datos en Primero. Sólo puede hacerse desde la página de listado de casos. ' label: Importar @@ -2477,6 +2656,15 @@ es: label: Caso dashboard: actions: + action_needed_new_updated: + explanation: Muestra el indicador de "Nuevo y Actualizado" en el tablero de "Acción Requerida". Esto incluye Casos que han sido recientemente asignados al usuario actual, o aquellos que otro usuario ha actualizado desde la última vez que el usuario actual los haya actualizado. + label: 'Accion Requerida: Nuevo o Actualizado' + action_needed_new_referrals: + explanation: Muestra el indicador de "Nuevas Referencias" en el tablero de "Acción Requerida". Esto incluye cualquier Caso con una Referencia nueva enviada al usuario actual, donde el usuario actual no es la última persona en actualizar dicho Caso. + label: 'Acción Requerida: Nuevas Referencias' + action_needed_transfer_awaiting_acceptance: + explanation: 'Muestra el indicador de "Transferencias Esperando Aceptación" en el tablero de "Acción Requerida". Esto incluye cualquier Caso con una Transferencia al usuario actual, el cual el usuario actual no ha aceptado. ' + label: 'Acción Requerida: Transferencias Esperando Aceptación' approvals_action_plan: explanation: Muestra el número de casos de el/la usuario(a) actual que cuentan con solicitud de aprobación de Plan de Acción la cual está Pendiente, Aprobada, o Rechazada. label: Aprobaciones %{approval_label} de la trabajadora del caso @@ -2526,7 +2714,6 @@ es: explanation: Permite a un(a) gerente ver cuántos casos tienen tareas de Servicios vencidas para cada una de sus trabajadoras de casos. label: tareas de Servicios Vencidas dash_case_incident_overview: - explanation: . label: Información General - Mis Casos /Incidentes dash_cases_by_social_worker: explanation: Tabla que muestra el número total de casos abiertos y el número de nuevos casos gestionados por cada usuario(a) en los grupos de usuario(a)s de el/la usuario(a) actual. Cada línea es un(a) usuario(a) dentro de los grupos de usuario(a)s de el/la usuario(a) actual, mientras que columnas son dos "Total" y "Nuevo". @@ -2998,7 +3185,6 @@ es: display: Mostrando posibles concordancias para %{type}%{id} reassign: multiple_error: Ha ocurrido un error. %{select_records} caso(a) no asignados. - multiple_successfully: '%{select_records} caso(s) asignados correctamente' notes_label: Notas successfully: Reasignado correctamente user_mandatory_label: Se requiere destinatario(a) diff --git a/config/locales/fa-AF.yml b/config/locales/fa-AF.yml index 9fb01da726..f2278c7144 100644 --- a/config/locales/fa-AF.yml +++ b/config/locales/fa-AF.yml @@ -1799,7 +1799,6 @@ fa-AF: display: نشان دادن تطابقات باالقوه برای %{type} %{id} reassign: multiple_error: خطایی رخ داد. %{select_records} قضیه/قضایای اختصاص داده نشده. - multiple_successfully: '%{select_records} قضیه موفقانه اختصاص داده شد' notes_label: یاداشت successfully: موفقانه دوباره اختصاص داده شده user_mandatory_label: گیرنده لازم است diff --git a/config/locales/fr.yml b/config/locales/fr.yml index f475317b0c..9cf6536877 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -47,7 +47,7 @@ fr: next: Suivant notes: Ajouter des notes previous: Précédent - reopen: Rouvrir + reopen: Réouvrir request_approval: Demander une approbation revoke: Révoquer save: Enregistrer @@ -84,6 +84,7 @@ fr: terms_of_use_download_button: Téléchargé PDF terms_of_use_enabled: 'Afficher les conditions d''utilisation ? ' approvals: + no_requests: Il n'y a pas de demande d'approbation pour ce cas approved_by: Approuvé par case_plan_type_label: 'Type de plan d''action ' manager_comments_label: Commentaires du superviseur / manager @@ -166,6 +167,7 @@ fr: import: Importer login: Se connecter logout: 'Se déconnecter ' + link: Lien mark_for_mobile: Marquer pour mobile new: Nouveau ok: OK @@ -198,6 +200,8 @@ fr: view: Voir view_flags_history: 'Voir l''historique ' return_to_case: 'Retourner au cas ' + enable_webpush: Notifications sur les appareils + dialog_yes: "Oui" resync_records: id: ID record_type: 'Type d''enregistrement ' @@ -210,7 +214,10 @@ fr: case: label: Cas create_new_case: Créer un nouveau cas + create_case: Créer un cas + create: Créer add_new: Ajouter nouveau + back_to_family_details: Retour aux détails sur la famille back_to_case: Retour au cas back_to_results: Retour aux résultats back_to_search: Retour à la recherche @@ -234,6 +241,14 @@ fr: introductory_sentence: Veuillez spécifier le consentement de la personne à recevoir des services de gestion de cas et à ce que ses données soient stockées dans Primero. consent_agreements_required: Veuillez sélectionner au moins une option parmi les accords de consentement. legitimate_basis_required: Veuillez sélectionner au moins une option parmi les accords de consentement. + confirm_create_case: Souhaitez vous ouvrir un dossier pour cette personne ? + case_referral_pending: Une référence de cas est en attente + case_transfer_pending: 'Un transfert de cas est en attente ' + case_no_approval_request: Il n'y a pas de demande d'approbation pour ce cas + bulk_assign_limit: Vous ne pouvez pas assigner plus de 100 cas à la fois. + bulk_assign_limit_try_again: Vous ne pouvez pas assigner plus de 100 cas à la fois. Veuillez sélectionner 100 cas ou moins et réessayer. + referral_rejected: La référence a été rejetée. + transfer_request_made: Une demande de transfert a été faite pour ce cas. save: Enregistrer le cas save_text: Avant de continuer, veuillez enregistrer les modifications apportées au cas. skip_and_create: Ignorer et créer un nouveau cas @@ -241,6 +256,7 @@ fr: search_helper_text: Pourquoi? Pour éviter la création de cas en double. consent_agreements: Sélectionnez tous les accords de consentement qui s'appliquent legitimate_basis: Sélectionnez toutes les classifications de base légitimes qui s'appliquent + family_linked_subform_delete_disabled: Ce sous formulaire est lié à un dossier familial. Veuillez soit supprimer ce membre de la famille du dossier familial, soit dissocier le dossier de ce membre de la famille du dossier familial. workflow: assessment: Evaluation case_plan: Plan d'action @@ -249,7 +265,7 @@ fr: in_progress: en cours new: Nouveau on_label: 'sur' - reopened: Rouvert + reopened: Réouvrir service_implemented: Service mis en œuvre services_implemented: Service mis en œuvre linkedincidents: @@ -260,6 +276,7 @@ fr: rejected_transfer: '%{to} rejeté transfert %{record_type} %{record_id} de %{from}' cases: action_plan: 'Plan d''action ' + access_denied: "Vous n'avez pas accès à ce cas." age: 'Age ' age_estimated: 'Age estimé? ' agency: 'Organisation ' @@ -354,6 +371,7 @@ fr: urgent_protection_concern: 'Problème de protection urgent ' user_group: Groupe d'utilisateur workflow: Cas Selon le Flux de Travail + include_disabled: Inclure les personnes handicapées flag_summary: Résumé des alertes full_name: 'Nom complet ' gbv_closure: Clôture de cas VBG @@ -377,6 +395,8 @@ fr: photos: Photo quick_view: tracing_message: 'Remarque: Il y a une correspondance dans le système avec un demandeur à la recherche de cet enfant. Contactez le travailleur social de ce dossier pour d''autres actions si l''enfant le souhaite.' + reassign: + multiple_successfully: Primero est en train de réattribuer %{select_records} dossier(s). La mise à jour de tous ces dossiers peut prendre plusieurs minutes. referral_done: En cliquant sur "Terminé", vous indiquez que vous avez terminé les tâches liées à la référence sur le cas. Une fois que vous aurez cliqué sur "Terminé", vous n'aurez plus accès au cas. referral_done_success: Référence faite referral_accepted_header: 'Accepter la référence ' @@ -414,6 +434,7 @@ fr: save_filter: Enregistrer selected_all_records: Sélectionnez tous les cas %{total_records} qui correspondent à cette requête. selected_records: '%{select_records} cas sélectionné(s) ' + selected_records_assign: '%{select_records} dossier(s) sélectionnés' sex: Sexe show_case: 'Id du cas: %{short_id}' social_worker: Travailleur social @@ -801,6 +822,31 @@ fr: assign_html: 'L''utilisateur %{user} vous a assigné le cas suivant %{record_type} %{record_id}.' transfer_request_html: 'L''utilisateur Primero %{user} de %{agency} vous demande de transférer la gestion du cas %{record_type}, %{record_id} afin qu''il puisse fournir des services de %{record_type} dans sa région. Si ce transfert vous convient, veuillez cliquer sur le lien %{record_type} dans cet e-mail pour ouvrir le fichier %{record_type}dans Primero et effectuer le transfert.' transfer_request_notes_html: 'Notes de la personne qui fait la demande: %{request_transfer_notes}' + alert: '%{record_type} %{id} - %{form_name} a été mis à jour. Veuillez vous connecter à Primero pour consulter les modifications.' + alert_subject: '%{record_type} : %{id} - %{form_name} mis à jour ' + webpush_notification: + action_label: Aller au cas + approval_request: + title: Demande d'approbation + body: Un cas de votre équipe a une demande d'approbation en attente pour %{type}. + approval_response: + title: Réponse à la demande d'approbation + body: L'un de vos cas a reçu une réponse a votre demande d'approbation. + assign: + title: Nouvelle assignation + body: Vous avez reçu une nouvelle assignation. + referral: + title: 'Nouvelle référence ' + body: Vous avez reçu une nouvelle référence de cas. + transfer: + title: 'Nouveau transfert ' + body: Vous avez reçu un nouveau transfert de cas + alert_case: + title: 'Cas mis à jour ' + body: "%{type} a été mis à jour sur l'un de vos cas." + transfer_request: + title: Demande de transfert + body: Vous avez reçu une nouvelle demande de transfert de cas encrypt: export_type: 'Type d''exportation ' file_name: Créer votre propre nom de fichier (facultatif) @@ -810,6 +856,8 @@ fr: address_fields: Vous devez renseigner les champs%{fields} dans le formulaire %{forms} address_form_fields: Vous devez renseigner le champ %{fields} sur ce formulaire address_subform_fields: '%{subform} a %{fields} champs invalides ' + error_401: Vous avez été déconnecté. Veuillez vous reconnecter. + error_something_went_wrong: Quelque chose n'a pas fonctionné. error_page: not_authorized: server_error: Vous n'êtes pas autorisé à accéder à cette page @@ -818,6 +866,10 @@ fr: contact_admin: Si vous pensez que vous êtes ici par erreur, veuillez contacter votre administrateur. something_went_wrong: Désolé, quelque chose s'est mal passé! errors: + api: + internal_server: Erreur du serveur + attachments: + maximum: Vous avez atteint le nombre maximum de pièces jointes par cas. error_loading: Erreur lors du chargement du(es) cas models: agency: @@ -862,6 +914,11 @@ fr: title_present: Le titre ne doit pas être vide content_present: Le contenu ne doit pas être vide created_by_present: Créé par ne doit pas être vide + webpush_subscription: + notification_url_present: notification_url ne doit pas être vide + notification_url_format: notification_url doit être au format URL + auth_present: Auth ne doit pas être vide + p256dh_present: p256dh ne doit pas être vide not_found: Pas d'enregistrement trouvé(s) try_again: Essayer encore exports: @@ -941,10 +998,11 @@ fr: location: 'Localisation ' agency: 'Organisation ' user: 'Utilisateurs ' - reportinglocation: 'Lieu de rapportage ' + reportinglocation: 'Lieu de déclaration ' subforms: 'Sous formulaire %{subform_name}' collapsed_fields: 'Champs imbriqués : %{fields}' country: Pays + linkedincidents: Incidents liés summary_header: form_group: Groupe de formulaire Primero form: 'Formulaire Primero ' @@ -1070,6 +1128,8 @@ fr: add_existing_field: 'Ajouter un champ existant ' add_field: Ajouter un champ add_field_type: Ajouter %{file_type} + attachments: + maximum_attached: La limite maximale de pièces jointes par cas (%{maximumttachmentsPerRecord}) est atteinte. Cela inclut les photos, les fichiers audio et les documents. Veuillez supprimer un fichier avant d'en ajouter un autre. audio: current: Audio reçent audio_upload_box: Télécharger un audio @@ -1167,7 +1227,7 @@ fr: select_box: Sélectionner le menu déroulant select_date_validation: Sélectionnez méthode de validation de la date select_multiple: Sélectionnez tout ce qui s'applique - select_single: (Sectionner...) + select_single: (Sélectionner...) separator: Séparateur show: Afficher ? show_on: 'Afficher sur ' @@ -1284,6 +1344,8 @@ fr: violation: Violation registry_details: Détails du registre registry_record: Dossier du registre + family_record: Dossier familial + family: Dossier familial required_field: '%{field} est un champ obligatoire ' select_label: 'Sélectionner ' settings: 'Paramètres ' @@ -1331,6 +1393,7 @@ fr: ar-LB: Arabe (Libanais) ar-SD: arabe (soudanais) bn: বাংলা + cmn: 中文 current_time_zone: 'Fuseau horaire actuel ' dashboard: Tableau de bord en: English @@ -1350,6 +1413,7 @@ fr: ne: नेपाली om: Oromo am-ET: Amharique (Éthiopie) + tr: Turque label: Accueil language: Langue manage_system_users: 'Gérer la synchronisation des serveurs des utilisateurs ' @@ -1368,15 +1432,19 @@ fr: view_records: Voir les dossiers welcome: Bienvenue sur Primero zh: 中文 + tet: Tetum incident: code: Code de l'incident associated_case: "Cas associé " + link_incident_to_case: Lier l'incident au cas + link_incident_to_case_success: Incident(s) lié(s) au cas messages: creation_success: 'Incident crée avec succès ' creation_success_queue: Création réussie d'un incident en arrière-plan disabled: L'incident est désactivé update_success: 'L''incident %{record_id} a bien été mis à jour.' update_success_queue: 'L''incident %{record_id} a été mis à jour avec succès en arrière plan ' + bulk_assign_limit_try_again: Vous ne pouvez pas assigner plus de 100 incidents à la fois. Veuillez sélectionner 100 incidents ou moins et réessayer. violation: associated_violations: "Violations associées :" update_and_return: 'Mettre à jour et retourner à %{association}' @@ -1395,6 +1463,7 @@ fr: military_use: Utilisation militaire d'école(s) et/ou d'hôpital(s) denial_humanitarian_access: Refus de l'accès humanitaire aux enfants incidents: + change_status: Modifier le statut disable_dialog: En cliquant sur OK, le statut de cet incident passera à Désactivé. disable_dialog_title: 'Incident désactivé ' disable_success: 'Incident désactivé avec succès ' @@ -1443,12 +1512,15 @@ fr: perpetrator_category: Type d'auteur record_owner: Gestionnaire du cas register_new_incident: Nouvel incident + reassign: + multiple_successfully: Primero est en train d'assigner %{select_records} incident(s). La mise à jour de tous ces incidents peut prendre plusieurs minutes. Notez que les incidents déjà liés à des cas ne seront pas attribués. selectable_date_options: date_of_first_report: 'Date de l''entretien ' mrm_date_of_first_report: Date du rapport initial au membre de la CTFMR ctfmr_verified_date: Date de la décision de vérification par le CTFMR incident_date_derived: Date de l'incident selected_records: '%{select_records} incident(s) sélectionné' + selected_records_assign: ' %{select_records} incident(s) sélectionnés. Notez que les incidents déjà liés à des cas ne seront pas assignés.' selected_all_records: 'Sélectionner tous les incident %{total_records} qui correspondent à cette requête' summary_mrm: label: Résumé de l'incident @@ -1473,6 +1545,7 @@ fr: survivor_code: Code survivant-e show_incident: 'ID de l''incident %{short_id}' social_worker: 'Travailleur social ' + verify_mrm: Vérifier le MRM violation_type: 'Type de violation ' violence_type: 'Type de violence ' type_violence: 'Type de violence ' @@ -1510,20 +1583,20 @@ fr: helptext: "En savoir plus sur les KPI." number_of_cases: title: "1. Nombre de cas enregistrés" - reporting_site: "Site de rapport" + reporting_site: "Site de déclaration " helptext: | - Cet indicateur compte le nombre de nouveaux cas ouverts chaque mois par site de rapportage. + Cet indicateur compte le nombre de nouveaux cas ouverts chaque mois par site de déclaration . Un site de rapportage est le site où l'organisation utilisatrice fournit des services et où le cas a été signalé au prestataire de services. number_of_incidents: title: "2. Nombre d'incidents enregistrés" - reporting_site: "Site de rapportage " + reporting_site: "Site de déclaration " helptext: | Cet indicateur compte le nombre de nouveaux incidents ouverts chaque mois par site de rapportage. Un site de rapportage est considéré comme le site où l'organisation utilisatrice fournit des services et où l'incident a été signalé au prestataire de services. reporting_delay: - title: "3. Retard de rapportage" + title: "3. Retard de déclaration " delay: "Retard " total_incidents: "Total des incidents " helptext: "Cet indicateur compte et catégorise le nombre de jours qui se sont écoulés entre le moment où \nla personne a été victime de violence basé sur le genre et lorsque la victime l'a signalé pour la première fois à un prestataire de services. Il s'agit de\ncalculé en fonction de la date à laquelle l'incident a été signalé pour la première fois à l'organisation utilisatrice. Les données sont\nclassés en fonction de différentes durées (0-3 jours ; 4-5 jours ; 6-14 jours ; 15-30 jours ; Plus de\n1 mois ; Plus de 3 mois).\n" @@ -1596,11 +1669,8 @@ fr: helptext: "Cet indicateur mesure combien de temps le cas est resté ouvert, la durée à l'ouverture des cas, jusqu'à la clôture du cas\nLe processus va du contact initial à l'organisation utilisatrice jusqu'à la clôture du dossier. La durée est \nventilée selon les délais suivants : moins d'un mois ; entre 1 et 3 mois ; entre\n3-6 mois ; plus de 6 mois.\n" case_closure_rate: title: "12. Décompte des clôtures de dossiers" - reporting_site: "Site de rapportage " - helptext: | - Cet indicateur mesure le nombre de cas clôturés par mois et par site. Un site de rapportage - est entendu comme le site où l'organisation fournit des services et où - l'incident a été signalé au prestataire de services. + reporting_site: "Site de déclaration " + helptext: "Cet indicateur mesure le nombre de cas clôturés par mois et par site. Un site de déclaration \nest entendu comme le site où l'organisation fournit des services et où\nl'incident a été signalé au prestataire de services.\n" client_satisfaction_rate: title: "13. Taux de satisfaction des clients" label: "Satisfaction du client " @@ -1660,6 +1730,18 @@ fr: township: Canton municipality: 'Municipalité ' autonomous_region: 'Région autonome ' + parish: Parish + cercle: Cercle + sub-county: Sous-comté + departement_fr: 'Département' + region_fr: 'Région' + wilaya: 'Wilaya' + commune: 'Commune' + division_fr: 'Département' + prefecture: 'Préfecture' + moughataa: 'Moughataa' + sub_division: 'Commune' + sub-prefecture: 'Sous-préfecture' label: 'Localisation ' name: Nom code: Code @@ -1861,15 +1943,44 @@ fr: date: Date verification_status: Statut de la vérification violation_type: 'Type de violation ' + status: Statut + status_open: Ouvert + status_closed: Clôturé + user_group: Groupe d'utilisateur + agency: Organisation + by: Par + workflow: Statut du workflow + cp_incident_violence_type: Type de violence + referral_transfer_status: Statut des Références / Transferts + protection_concerns: Problèmes de protection + location: 'Lieu de déclaration ' + followup_type: 'Type de suivi ' + service_type: Type de service + status_options: + open: Ouvert + closed: Clôturé + by_options: + created_by_groups: Groupes d'utilisateurs du gestionnaire qui a créé le cas + owned_by_groups: Groupes d'utilisateurs du gestionnaire actuel du cas + created_organization: Organisation du gestionnaire qui a créé le cas + owned_by_agency_id: Organisation du gestionnaire actuel du cas + referral_transfer_status_options: + in_progress: 'En attente ' + accepted: 'Accepté ' + rejected: Rejeté + done: Terminé date_range: month: Mois quarter: Trimestre year: Année + week: Semaine date_range_options: this_quarter: Ce trimestre last_quarter: Le trimestre passé this_month: Ce mois last_month: Le mois passé + this_week: Cette semaine + last_week: 'Semaine dernière ' this_year: Cette année last_year: L'année passée custom: Personnaliser @@ -1885,6 +1996,49 @@ fr: individual_violation_type: Enfant par type de violation individual_region: Enfant par région individual_perpetrator: Enfants par auteur + services: + name: Services + description: Cas avec les types de services sélectionnés, ventilés par âge et par sexe. + services_report: + reports: + services: Services + description: Cas avec les types de services sélectionnés, ventilés par âge et par sexe. + sub_reports: + services: Services + filter_options: + service_implemented_day_time: Service mis en œuvre + followups: + name: Suivi + description: Cas avec les types de suivi sélectionnés, ventilés par âge et par sexe. + followups_report: + filter_options: + followup_date: Date du suivi + reports: + followups: Suivi + description: Cas avec les types de suivi sélectionnés, ventilés par âge et par sexe. + sub_reports: + followups: Suivi + protection_concerns: + name: Problèmes de protection + description: Cas avec les problèmes de protection sélectionnés, ventilés par âge et par sexe. + protection_concerns_report: + reports: + protection_concerns: Problèmes de protection + description: Cas avec les problèmes de protection sélectionnés, ventilés par âge et par sexe. + sub_reports: + protection_concerns: Problèmes de protection + filter_options: + registration_date: Date d'enregistrement + reporting_locations: + name: 'Lieu de déclaration ' + description: 'Cas avec le lieu de déclaration sélectionné, ventilés par âge et par sexe.' + reporting_locations_report: + reports: + reporting_locations: 'Lieu de déclaration ' + sub_reports: + reporting_location_by_sex_and_age: 'Lieu de déclaration ' + filter_options: + registration_date: Date d'enregistrement ghn_report: name: 'Note Global Horizontale ' reports: @@ -1973,35 +2127,10 @@ fr: date_of_first_report: Date de l'Interview incident_date: 'Date de l''incident ' reports: - incidents: Incidents perpetrators: Auteur survivors: Survivants referrals: Références sub_reports: - combined: Incidents - total: Nombre de cas VBG rapporté - gbv_sexual_violence: Nombre d'incident ou violence sexuel rapporté - gbv_previous_incidents: Nombre d'incidents signalés par survivants ayant déjà été victimes de violence basée sur le genre. - gbv_sexual_violence_type: 'Type d''incident ' - incident_timeofday: Heure de l'incident - elapsed_reporting_time: Délai entre l'incident et le signalement - elapsed_reporting_time_rape: Incidents de viol, temps écoulé entre l'incident et la date du signalement - elapsed_reporting_time_rape_health_referral: Incidents de viols, temps écoulé entre l'incident et la date du signalement (service de santé ou référence) - incident_location_type: 'Lieu de l''incident ' - number_of_perpetrators: 'Nombre d''auteurs ' - perpetrator_relationship: Relation entre le présumé auteur principal et la survivante - perpetrator_age_group: 'Groupe d''âge des principaux auteurs présumés ' - perpetrator_occupation: 'Profession du présumé auteur principal ' - age: 'Nombre de survivants par âge ' - sex: Nombre de survivants par sexe - marital_status: Statut matrimonial des survivants - displacement_status: Statut de déplacement des survivants - displacement_incident: Étape du déplacement au moment de l'incident - gbv_case_context: Contexte du cas - incidents_first_point_of_contact: Nombre d'incidents pour lesquels votre organisation est le premier point de contact - incidents_from_other_service_provider: Incidents référés par d'autres prestataires de services - number_of_services_provided: Nombre de services fournis pour les incidents - number_of_services_provided_other: Nouveaux incidents référés vers d'autres prestataires de services service_safehouse_referral: Référence à une maison ou un abri sûr service_medical_referral: Référence sanitaire/médicale service_psycho_referral: Services psychosociaux/counseling @@ -2009,8 +2138,48 @@ fr: service_police_referral: Police ou autre type de services de sécurité service_livelihoods_referral: Services relatifs aux moyens de subsistance service_protection_referral: Services de protection de l'enfant - vulnerable_populations: 'Populations vulnérables ' survivors_disability_type: Avec des handicaps + workflow_report: + name: Étapes de prise en charge + description: Cas et incidents avec le workflow sélectionné, ventilés par âge et par sexe. + reports: + cases_workflow: Étapes de prise en charge des cas + incidents_workflow: Étapes de prise en charge des incidents + filter_options: + registration_date: Date d'enregistrement + sub_reports: + case_workflow_by_sex_and_age: Nombre total de cas par âge et par sexe + incident_workflow_by_sex_and_age: 'Nombre total des incidents par sexe et par âge ' + cases_workflow_report: + name: Workflow + description: Cas avec les types de suivi sélectionnés, ventilés par âge et par sexe. + reports: + cases_workflow: Workflow - Cas + filter_options: + registration_date: Date d'enregistrement + sub_reports: + case_workflow_by_sex_and_age: Nombre total de cas par sexe et âge  + referrals_transfers_report: + name: Références et transferts + description: Références et transferts qui ont eu lieu dans une période donnée. Ces données sont ventilées par organisation d'envoi et de réception ou par groupe d'utilisateurs. + reports: + total_referrals: Références + total_transfers: Tranferts + sub_reports: + total_transfers_by_user_groups: Total des transferts + total_referrals_by_user_groups: 'Total des références ' + filter_options: + registration_date: Date d'enregistrement + violence_type_report: + name: Type de violence + reports: + cases_violence_type: Type de violence - cas + incidents_violence_type: Type de violence - incidents + filter_options: + registration_date: Date d'enregistrement + sub_reports: + case_violence_type_by_sex_and_age: Nombre total de cas par sexe et âge  + incident_violence_type_by_sex_and_age: 'Nombre total des incidents par sexe et âge ' success_message: Le fichier d'exportation généré avec succès messages: alert_items: Vous avez %{items}éléments à noter. @@ -2060,6 +2229,7 @@ fr: tracing_request: 'Demandes de recherche ' activity_log: Log activités registry_records: Registre + families: 'Familles ' notes: note_success: Notes ajouté avec succès permissions: @@ -2114,7 +2284,7 @@ fr: dash_protection_concerns: Afficher les problèmes de protection dash_protection_concerns_by_location: Voir les problèmes de protection par localité dash_referrals_by_socal_worker: Afficher les référencements par travailleur social - dash_reporting_location: Afficher les zones de rapportages + dash_reporting_location: 'Afficher les zones de déclaration ' dash_service_provisions: Afficher les services fournis dash_shared_from_my_team: Partagé par mon équipe dash_shared_with_me: Partagé avec moi @@ -2143,6 +2313,7 @@ fr: find_tracing_match: Trouver une correspondance à partir d'un cas view_registry_record: Voir le cas add_registry_record: Ajouter un cas au registre + family: 'Famille ' flag: Mettre une alerte form: Formulaires group: Accéder à tous les dossiers ou utilisateurs de mon groupe @@ -2170,6 +2341,7 @@ fr: reopen: 'Réouvert ' report: Rapport managed_report: Insights + resolve_any_flag: Résoudre toutes les alertes request_approval: Demande d'Approbation request_approval_action_plan: Demande d'approbation %{approval_label} request_approval_assessment: Demande d'approbation %{approval_label} @@ -2192,6 +2364,7 @@ fr: transfer: Peut être utilisé pour un transfert user: Utilisateurs user_group: Groupes d'utilisateurs + verify_mrm: Vérifier le MRM view_approvals: Voir Approbations view_assessment: Voir Evaluation view_photo: Afficher les photos @@ -2202,6 +2375,7 @@ fr: workflow_team: Flux d'information - Cas des équipes write: Écrire activity_log: Log activités + remove_alert: Supprimer l'alerte resource: kpi: actions: @@ -2246,7 +2420,7 @@ fr: label: Nombre d'incidents kpi_reporting_delay: explanation: Possibilité de voir, pour tous les incidents auxquels l'utilisateur a accès, le nombre de jours écoulés entre le moment où la victime a subi une violence basée sur le genre et celui où elle l'a signalée à un prestataire de services. - label: Retard de rapportage + label: Délai de déclaration kpi_services_provided: explanation: Possibilité de voir, dans tous les cas auxquels l'utilisateur a accès, quels types de services ont été fournis par l'organisation directement. label: Services fournis @@ -2362,6 +2536,7 @@ fr: label: Exporter en mur de photos export_unhcr_csv: label: Exporter au format UNHCR CVS + explanation: SUPPRIMÉ - Cette fonction n'est plus utilisée. export_xls: explanation: 'L''utilisateur peut générer une exportation de fichier XLS à partir de la liste des cas ou des pages de présentation des cas, qui contient tous les champs auxquels l''utilisateur actuel a accès, pour un, plusieurs ou tous les cas auxquels l''utilisateur a accès. Dans cette exportation, chaque formulaire est représenté dans son propre onglet au sein du fichier XLS. NOTE : Le format XLS rend les caractères non latins (par exemple, l''arabe, le bengali) dans un format lisible, alors que l''exportation CSV ne le fait pas.' label: Exporter au format EXCEL (XLS) @@ -2371,6 +2546,9 @@ fr: flag: explanation: Possibilité d'ajouter un marquage en drapeaux à un cas. Les utilisateurs ayant cette permission peuvent également supprimer les marquages qu'ils ont ajoutés à un cas. label: 'Mettre une alerte ' + resolve_any_flag: + explanation: Permet à l'utilisateur de résoudre n'importe quel alerte sur le cas, quel que soit le responsable. + label: Résoudre toutes les alertes import: explanation: Permet à l'utilisateur de créer un ou plusieurs nouveaux cas en les important à partir d'un fichier CSV, Excel ou JSON. Le fichier importé doit être formaté *très* spécifiquement pour que les informations soient importées correctement. Cette fonction ne doit être disponible que pour les utilisateurs administratifs ayant des compétences techniques avancées et une connaissance approfondie de la façon dont les données sont formatées dans Primero. Cette fonction ne peut être exécutée qu'à partir de la page de la liste des cas. label: Importer @@ -2380,6 +2558,9 @@ fr: incident_from_case: explanation: Cette autorisation permet à l'utilisateur de cliquer sur le bouton "Créer un incident". Cela génère un incident qui peut contenir des informations copiées à partir d'un cas. Pour les cas de VBG, ce bouton se trouve en haut de la page de présentation des cas, et correspond aux informations sur l'ensemble du cas. Dans certains contextes de suivi des incidents, ce bouton se trouve sur un sous-formulaire "Détails de l'incident". Dans ce cas, certaines informations peuvent être copiées à partir du sous-formulaire "Détails de l'incident" où le bouton a été cliqué, ainsi que du cas dans son ensemble. Par exemple, le nouvel incident créé peut contenir le champ "Type de violence" du sous-formulaire "Détails de l'incident", mais peut également contenir l'âge et le sexe du cas lui-même. Notez que cette autorisation permet également à l'utilisateur de voir un lien vers l'incident qui a été créé. label: 'Créer un incident à partir d''un cas ' + remove_alert: + explanation: Cette autorisation permet à l'utilisateur de supprimer les mises à jour d'un cas. Les alertes sont généralement générées lorsqu'un champ particulier est modifié, par exemple lorsque des notes sont mises à jour. Les alertes sont généralement représentées par un point jaune à côté du cas. + label: Supprimer les mises à jour d'un cas manage: explanation: Permet à un utilisateur d'effectuer toutes les actions disponibles sur les cas. La permission "Gérer" signifie essentiellement "tout". label: Gérer (toutes les autorisations pour ce type de ressources) @@ -2406,7 +2587,7 @@ fr: label: Supprimer les autres utilisateurs assignés (reprendre l'accès aux dossiers des utilisateurs ayant reçu une référence) reopen: explanation: Permet à un utilisateur d'ouvrir un cas qui est actuellement clos. - label: Ré-ouvrir + label: Réouvrir request_approval_action_plan: explanation: Permet à un utilisateur (généralement un gestionnaire de cas) d'effectuer une demande d'approbation de %{approval_label} à son superviseur. label: Demande d'approbation %{approval_label} @@ -2470,6 +2651,15 @@ fr: mark_for_offline: explanation: Permet à l'utilisateur de mettre en cache les cas pour une utilisation hors ligne. label: Marquer pour hors ligne + view_family_record: + explanation: Les utilisateurs peuvent consulter le formulaire « Informations familiales » du cas, qui comprend un lien vers les informations familiales. + label: Consulter le dossier familial à partir du cas + case_from_family: + explanation: Les utilisateurs peuvent créer un cas pour l'un des membres de la famille du cas dans le sous-formulaire Détails de la famille. Notez qu'un dossier familial sera automatiquement créé pour lier ces deux cas. + label: Créer un cas à partir des détails de la famille + link_family_record: + explanation: Permet à un utilisateur de rechercher et de lier un dossier familial existant à son cas. Il permet également aux utilisateurs de dissocier un dossier familial d'un cas. + label: Lier / Dissocier l'enregistrement familial au cas explanation: Représente un enfant, un survivant ou un autre bénéficiaire. label: Cas dashboard: @@ -2523,7 +2713,7 @@ fr: explanation: Permet à un superviseur de voir combien de cas ont des services à mettre en œuvre en retard pour chacun des gestionnaires de cas. label: Services en retard dash_case_incident_overview: - explanation: . + explanation: Indique au superviseur le nombre de cas gérés par chaque gestionnaire de cas de son équipe, ceux qui sont référés ou transférés à d'autres utilisateurs. label: Vue d'ensemble - Mes cas / Incidents dash_cases_by_social_worker: explanation: Tableau qui affiche le nombre total de cas ouverts et le nombre de nouveaux cas géré par chaque gestionnaire de cas dans les groupes d'utilisateurs du gestionnaire actuel. Chaque ligne correspond à un utilisateur dans les groupes d'utilisateurs du gestionnaire de cas actuel, tandis que "Total" et "Nouveau" sont les deux colonnes. @@ -2548,7 +2738,7 @@ fr: label: Voir les problèmes de protection par localité dash_reporting_location: explanation: Tableau qui indique le nombre de cas à chaque lieu (à un seul niveau ou spécification tel que "Province" ou "District"). Chaque ligne du tableau est un lieu, et les colonnes indiquent différents statuts pour les cas ("CAS OUVERTS", "NOUVEAU (DERNIÈRE SEMAINE)", "NOUVEAU (CETTE SEMAINE)", "FERMÉ (DERNIÈRE SEMAINE)", "FERMÉ (CETTE SEMAINE)"). Généralement utilisé pour les comptes des superviseurs ou des administrateurs. - label: Cas par zone de rapportage + label: Cas par zone de déclaration dash_service_provisions: explanation: Affiche le nombre de cas dans lesquels d'autres utilisateurs ont ajouté une prestation de service. Ce nombre apparaît dans la section principale du tableau de bord. label: 'Cas par types de services fournis ' @@ -2562,6 +2752,7 @@ fr: explanation: Afficher au superviseur, le nombre de cas référé ou transféré par chaque gestionnaire de cas de son équipe label: Partagé avec mon équipe dash_shared_with_my_team_overview: + explanation: Indique au superviseur le nombre de cas référés ou transférés à chacun des gestionnaires de cas de son équipe. label: Partagé avec mon équipe (Aperçu) dash_shared_with_others: explanation: Indique le nombre de mes cas dont la référence est active, les transferts en attente ou les transferts rejetées. Ne concerne généralement pas les superviseurs, sauf s'ils gèrent eux-mêmes les cas. @@ -2611,6 +2802,9 @@ fr: disabled: explanation: Si vous désactivez ce rôle, vous ne pourrez plus l'attribuer aux comptes d'utilisateur. label: 'Désactivé ' + referral_authorization: + explanation: Cela signifie que la fonction apparaîtra comme une option dans la liste déroulante « Type de référence » lorsque l'utilisateur effectuera une référence interne. Si l'utilisateur choisit cette fonction comme type de référence, le destinataire de la référence ne pourra accéder qu'aux formulaires auxquels la fonction sélectionné peut accéder. Ainsi, par exemple, si l'utilisateur choisit « Prestataire de services médicaux » comme type de référence et que la fonction de prestataire de services médicaux n'a accès qu'aux formulaires Identité de base et Préoccupations en matière de protection, le destinataire ne verra que ces formulaires. + label: Cete fonction peut-elle être utilisée pour la liste déroulante « Type de référence » ? duplicate: actions: read: @@ -2631,6 +2825,9 @@ fr: registry_record: explanation: 'Limiter l''accès d''un utilisateur aux formulaires des registres limite les informations que l''utilisateur peut voir. Par exemple, si l''utilisateur a uniquement accès au formulaire des informations sur le gestionnaire de cas, il ne pourra également voir que les informations contenues dans les champs de ce formulaire. Si l''utilisateur en question a un accès limité aux formulaires et a la possibilité de gérer la configuration des formulaires, le fait de limiter son accès aux formulaires limite également les formulaires qu''il peut configurer. NOTE : Si aucun formulaire n''est spécifié, cela signifie que le rôle a accès à tous les formulaires ' label: Formulaires - Registre + family: + label: 'Formulaires - Famille ' + explanation: 'En limitant l''accès d''un utilisateur aux formulaires pour les familles, on limite les informations que l''utilisateur peut voir sur une famille. Par exemple, si l''utilisateur n''a accès qu''au formulaire Enregistrement du cas, il ne pourra voir que les informations contenues dans les champs de ce formulaire. Si l''utilisateur actuel a un accès limité aux formulaires et qu''il a la possibilité de gérer la configuration des formulaires, le fait de limiter son accès aux formulaires limite également les formulaires qu''il peut configurer.' group: actions: admin_only: @@ -2652,6 +2849,9 @@ fr: label: Quels sont les cas concernés par cette fonction ? incident: actions: + assign: + explanation: Permet à un utilisateur d'envoyer un incident du gestionnaire de cas d'origine à n'importe quel autre utilisateur du système. Les incidents déjà liés à un cas ne peuvent pas être assignés ; vous devez réassigner le cas lié, ce qui mettra à jour le gestionnaire de cas. + label: Assigner change_log: explanation: L'utilisateur peut voir l'historique de toutes les modifications apportées à un cas depuis sa création. Cela inclut les valeurs enregistrées pour tous les champs. label: 'Journal ' @@ -2668,6 +2868,7 @@ fr: explanation: L'utilisateur peut générer une exportation de fichier CSV à partir de la liste des incidents ou des pages d'affichage des incidents, qui contient tous les champs auxquels l'utilisateur a accès, pour un, plusieurs ou tous les incidents auxquels l'utilisateur a accès. label: Exporter en CSV export_custom: + explanation: L'utilisateur peut sélectionner des formulaires ou des champs spécifiques à exporter vers un fichier XLS. label: 'Exportation personnalisé ' export_incident_recorder_xls: explanation: L'utilisateur peut générer et exporter un fichier XLS spécialisé qui permet l'échange de données avec l'outil VBG d'enregistrement des incidents. @@ -2690,9 +2891,18 @@ fr: flag: explanation: Possibilité d'ajouter un marquage à un incident. Les utilisateurs ayant cette permission peuvent également supprimer les marquages qu'ils ont ajoutés à un incident. label: 'Mettre une alerte ' + resolve_any_flag: + explanation: Permet à l'utilisateur de résoudre n'importe quel alerte sur le cas, quel que soit l'auteur de l'alerte. + label: Résoudre toutes les alertes import: explanation: Permet à l'utilisateur de créer un ou plusieurs nouveaux incidents en les important à partir d'un fichier CSV, Excel ou JSON. Le fichier importé doit être formaté *très* spécifiquement pour que les informations soient importées correctement. Cette fonction ne doit être disponible que pour les utilisateurs administratifs ayant des compétences techniques avancées et une connaissance approfondie de la façon dont les données sont formatées dans Primero. Cette fonction ne peut être exécutée qu'à partir de la page de la liste des incidents. label: Importer + remove_alert: + explanation: Cette autorisation permet à l'utilisateur de supprimer les mises à jour d'un incident. Les alertes sont généralement générées lorsqu'un champ particulier est modifié, par exemple lorsque des notes sont mises à jour. Les alertes sont généralement représentées par un point jaune à côté de l'incident. + label: Supprimer les mises à jour d'un incident + link_incident_to_case: + explanation: Permet à l'utilisateur de lier l'incident au cas sélectionné. + label: Lier l'incident au cas manage: explanation: Permet à un utilisateur d'effectuer toutes les actions disponibles sur les incidents. La permission "Gérer" signifie essentiellement "tout". label: Gérer (toutes les autorisations pour ce type de ressources) @@ -2702,6 +2912,9 @@ fr: sync_mobile: explanation: Cette autorisation permet généralement à l'utilisateur d'utiliser l'application mobile. Tout d'abord, elle permet à l'utilisateur de voir les actions "Marquer pour mobile" et "Supprimer le marquage pour mobile", qui apparaissent sur la liste des incidents et les pages d'affichage des incidents. Marquer un incident pour mobile indique que les informations sur cet incident doivent être synchronisées entre l'appareil mobile de l'utilisateur et l'application web, tandis que le fait de supprimer le marquage pour mobile d'un incident empêche cette synchronisation de se produire. Les utilisateurs sans cette autorisation ne peuvent pas non plus synchroniser leur appareil mobile avec l'application web, ce qui signifie qu'ils ne peuvent pas utiliser l'application mobile pour superviser les incidents. label: Synchroniser avec appareil mobile + verify_mrm: + explanation: L'utilisateur MRM peut modifier le statut des violations. + label: Vérifier le MRM write: explanation: Possibilité de cliquer sur le bouton "Modifier", de mettre à jour les informations relatives à l'incident et de cliquer sur "Enregistrer". Permet également à l'utilisateur de désactiver ou d'activer un incident. label: 'Editer ' @@ -2712,14 +2925,50 @@ fr: label: est ce un superviseur ? managed_report: actions: + reporting_locations_report: + label: Lieu de déclaration (Cas) + explanation: Possibilité de consulter des statistiques sur le nombre de cas enregistrés au cours d'une période donnée, filtrées par lieu de déclaration et ventilées par âge et par sexe. Cette autorisation permet également à l'utilisateur d'exporter les données d'un Insight. + followups_report: + label: Suivis (Cas) + explanation: Possibilité de consulter des statistiques sur le nombre de suivis effectués dans une période donnée, filtrées par type de suivi et ventilées par âge et par sexe. Cette autorisation permet également à l'utilisateur d'exporter les données d'un Insight. + services_report: + label: Services (Cas) + explanation: Possibilité de consulter des statistiques sur le nombre de services fournis au cours d'une période donnée, filtrées par type de service et ventilées par âge et par sexe. Cette autorisation permet également à l'utilisateur d'exporter les données d'un Insight. + protection_concerns_report: + label: Problèmes de protection (Cas) + explanation: Possibilité de consulter des statistiques sur les problèmes de protection des cas enregistrés dans une période donnée. Cette autorisation permet également à l'utilisateur d'exporter les données d'un Insight. + managed_report_scope: + label: Quels cas cette fonction doit-elle pouvoir consultées dans Insights ? + managed_report_scope_all: + label: Tous + managed_report_scope_group: + label: Données des groupes uniquement + managed_report_scope_agency: + label: Données des organisations uniquement violations: + explanation: Possibilité d'accéder aux insights violations du MRM. label: Violations gbv_statistics: + explanation: Possibilité d'accéder aux insights sur les VBG. label: Statistiques VBG ghn_report: + explanation: Possibilité d'accéder aux Insights sur les notes horizontales globales de MRM. label: 'Note Global Horizontale ' individual_children: + explanation: Possibilité d'accéder aux insights individuel des enfants du MRM. label: Enfant individuellement + workflow_report: + label: Workflow (Cas et Incidents) + explanation: Possibilité de consulter des statistiques sur l'état du flux de travail pour les cas et les incidents qui leur sont liés. Cette autorisation permet également à l'utilisateur d'exporter les données d'un Insight. + cases_workflow_report: + label: Workflow (Cas) + explanation: Possibilité de consulter les statistiques sur le workflow des cas. Cette autorisation permet également à l'utilisateur d'exporter les données d'un Insight. + violence_type_report: + label: Type de violence (Cas et incidents) + explanation: Possibilité de consulter les statistiques sur le type de violence. Cette autorisation permet également à l'utilisateur d'exporter les données d'un Insight. + referrals_transfers_report: + label: Références et transferts (Cas) + explanation: Les utilisateurs voient le nombre de cas référés et transférés d'un groupe d'utilisateurs à un autre groupe d'utilisateurs. matching_configuration: actions: manage: @@ -2794,6 +3043,9 @@ fr: flag: explanation: 'Possibilité d''ajouter un drapeau à un cas. Les utilisateurs disposant de cette autorisation peuvent également supprimer les drapeaux qu''ils ont ajoutés à un cas. ' label: 'Mettre une alerte ' + resolve_any_flag: + explanation: Permet à l'utilisateur de résoudre n'importe quel alerte sur le cas, quel que soit l'auteur de l'alerte. + label: Résoudre toutes les alertes manage: explanation: Permet à un utilisateur d'effectuer toutes les actions disponibles sur un cas. L'autorisation "Gérer" signifie essentiellement "tout". label: Gérer (toutes les autorisations pour ce type de ressource) @@ -2808,6 +3060,63 @@ fr: label: Marquer pour hors ligne explanation: Il peut s'agir d'une personne ou d'une institution qui doit être liée à d'autres cas ou des incidents, qui sont très nombreux et qui sont mis à jour de façon répétée avec de nouvelles informations. Ils sont similaires aux références, mais avec un ensemble plus complexe d'informations. label: Dossier du registre + family: + actions: + change_log: + explanation: L'utilisateur peut voir un historique de toutes les modifications apportées au cas depuis sa création. Cela inclut les valeurs enregistrées pour tous les champs. + label: 'Journal des modifications ' + create: + explanation: Capacité de créer une famille. + label: Créer + enable_disable_record: + explanation: Possibilité de désactiver ou d'activer une famille. Les familles « désactivées » n'apparaissent pas par défaut dans la liste des familles. Les utilisateurs peuvent voir les familles désactivées dans la liste des familles en utilisant un filtre. + label: Activer/ Désactiver + export_csv: + explanation: 'L''utilisateur peut générer un fichier CSV à partir de la liste des familles ou des pages de présentation des familles, qui contient tous les champs auxquels l''utilisateur a accès. REMARQUE : L''exportation CSV ne rend pas les caractères non latins (par ex. arabe, bangladais).' + label: Exporter en CVS + export_json: + explanation: L'utilisateur peut générer un fichier JSON à partir de la liste des familles ou des pages de présentation des familles, qui contient tous les champs auxquels l'utilisateur actuel a accès. Le format JSON est lisible par une machine et n'est pas pratique pour la plupart des utilisateurs. + label: Exporter en JSON + export_xls: + explanation: 'L''utilisateur peut générer un fichier XLS à partir de la liste des familles ou des pages de présentation des familles, qui contient tous les champs auxquels a accès l''utilisateur actuel. NOTE : Le format XLS rend les caractères non latins (par ex. arabe, bangladais) dans un format lisible, alors que l''exportation CSV ne le fait pas.' + label: Exporter en Excel (fichier XLS) + export_list_view_csv: + explanation: L'utilisateur peut générer un fichier CSV exporté à partir de la page Liste des familles, qui contient les mêmes champs que ceux qui apparaissent pour cet utilisateur dans la liste des familles. Cette opération n'est possible qu'à partir de la page Liste des familles. + label: Exporter la liste en CSV + export_pdf: + explanation: L'utilisateur peut générer un fichier d'exportation PDF à partir de la liste des familles ou des pages d'affichage des familles, qui contient tous les champs auxquels l'utilisateur a accès, pour un, plusieurs ou tous les enregistrements auxquels l'utilisateur a accès. Dans le fichier d'exportation PDF, les informations sont d'abord répertoriées par famille, puis organisées en fonction du formulaire sur lequel elles apparaissent. + label: Exporter en PDF + export_custom: + label: 'Exportation personnalisée ' + explanation: L'utilisateur peut sélectionner des formulaires ou des champs spécifiques de la liste des familles ou des pages de présentation des familles pour les exporter vers un fichier XLS. + flag: + explanation: Possibilité d'ajouter une alerte à une famille. Les utilisateurs disposant de cette autorisation peuvent également supprimer les alertes qu'ils ont ajoutés à une famille. + label: 'Mettre une alerte ' + resolve_any_flag: + explanation: Permet à l'utilisateur de résoudre n'importe quel alerte sur le cas, quel que soit l'auteur de l'alerte. + label: Résoudre toutes les alertes + manage: + explanation: Permet à un utilisateur d'effectuer toutes les actions disponibles sur les familles. L'autorisation « Gérer » signifie essentiellement « tout ». + label: Gérer (toutes les autorisations de cette ressource) + read: + explanation: Capacité à voir les familles + label: Voir + write: + explanation: Possibilité de cliquer sur le bouton « Modifier », de mettre à jour les informations concernant la famille et de cliquer sur « Enregistrer ». + label: 'Editer ' + sync_mobile: + explanation: Permet à l'utilisateur de mettre en cache les fiches familiales pour une utilisation hors ligne. + label: Marquer pour hors ligne + close: + explanation: Permet à un utilisateur de définir le statut d'une famille ouverte comme étant clôturée. + label: 'Clôturer ' + reopen: + explanation: Permet à un utilisateur de réouvrir une famille qui est actuellement clôturée. + label: Réouvrir + case_from_family: + explanation: Permet aux utilisateurs de créer un nouveau cas à partir d'un sous-formulaire « Membres de la famille » dans le dossier familial. + label: Créer un cas + label: 'Famille ' report: actions: create: @@ -2903,6 +3212,9 @@ fr: flag: explanation: Possibilité d'ajouter un marquage ou drapeau à une demande de recherche. Les utilisateurs ayant cette autorisation peuvent également supprimer les marquages ou drapeaux qu'ils ont ajoutés à une demande de recherche. label: 'Mettre une alerte ' + resolve_any_flag: + explanation: Permet à l'utilisateur de résoudre n'importe quel alerte sur le cas, quel que soit l'auteur de l'alerte. + label: Résoudre toutes les alertes import: explanation: Permet à l'utilisateur de créer un ou plusieurs nouveaux cas en les important à partir d'un fichier CSV, Excel ou JSON. Le fichier importé doit être formaté *très* spécifiquement pour que les informations soient importées correctement. Cette fonction ne doit être disponible que pour les utilisateurs administratifs ayant des compétences techniques avancées et une connaissance approfondie de la façon dont les données sont formatées dans Primero. Cette fonction ne peut être exécutée qu'à partir de la page de la liste des cas. label: 'Importer ' @@ -2980,6 +3292,7 @@ fr: label: Supprimer manage: label: Gérer (toutes les autorisations pour ce type de ressource) + explanation: Utilisé pour les rôles système qui accèdent aux Webhooks de Primero vers d'autres systèmes. Il n'est pas recommandé aux non-développeurs de l'utiliser. activity_log: actions: transfer: @@ -2987,6 +3300,7 @@ fr: label: Transferts manage: label: Gérer (toutes les autorisations pour ce type de ressource) + explanation: Possibilité d'accéder à tous. label: Log activités potential_match: case_id: ID du cas @@ -3008,11 +3322,12 @@ fr: display: Afficher les potentielles correspondances pour %{type} %{id} reassign: multiple_error: Une erreur est survenue. Cas %{select_records} non assigné(s) - multiple_successfully: 'Cas %{select_records} assigné(s) avec succès' + multiple_successfully: Primero est en train de réassigner %{select_records} un (des) cas. La mise à jour de tous ces cas peut prendre plusieurs minutes. notes_label: Notes successfully: 'Réassigné avec succès ' user_mandatory_label: Destinataire est requis users_label: 'Destinataire ' + incident_from_case_warning: Vous ne pouvez pas assigner cet incident, car il est déjà lié à un cas. Lorsque vous assignez le cas, l'incident est également assigné. record_information: assigned_user_names: Autres utilisateurs assignés created_at: Cas créé le @@ -3034,6 +3349,8 @@ fr: referral: type_of_recipient: 'Type de destinataire ' type_of_referral_required: Type de référence requis + referral_authorization_label: Souhaitez-vous spécifier un type de référence ? + referral_authorization_help_text: Cela limitera les formulaires auxquels le destinataire peut accéder. agency_label: Organisation is_remote_label: Souhaitez vous référer à l'extérieur de Primero? location_label: Lieu @@ -3095,6 +3412,7 @@ fr: record_type: Type de dossier total: Total value: Valeur + incomplete_data: 'Données incomplètes ' reports: delete_report: Supprimer le rapport delete_report_message: Êtes-vous sûr de vouloir supprimer ce rapport ? La suppression ne peut pas être annulée. Cliquez sur OK pour supprimer le rapport @@ -3270,6 +3588,42 @@ fr: title: Marquer pour hors ligne text: Êtes-vous sûr de vouloir marquer ces pour les utiliser lorsque vous êtes hors ligne ? success: Les cas ont été marqués avec succès pour une utilisation hors ligne + families: + id: ID + label: 'Familles ' + family_id: Identifiant de la famille + family_number: Numéro de la famille + family_name: Nom de famille + family_registration_date: Date d'enregistrement + family_location_current: Localisation de la famille + export: Exporter + register_new_family: Nouvelle famille + show_family: 'Court identifiant de la famille' + disable_dialog_title: Désactiver la famille + disable_dialog: En cliquant sur OK, le statut de cette famille passera à Désactivé. + selected_records: '%{select_records} dossiers sélectionné(s)' + selected_all_records: 'Sélectionner toutes les %{total_records} familles qui correspondent à cette requête.' + mark_for_offline: + title: Marquer pour hors ligne + text: Êtes-vous sûr de vouloir marquer ces dossiers familiaux pour les utiliser lorsque vous êtes hors ligne ? + success: Les dossiers de la famille ont été enregistrés avec succès pour une utilisation hors ligne + filter_by: + by_date: Par date + status: Statut + current_location: Localisation de la famille + family: + family_member: + case_id: ID du cas + update_and_return: Mettre à jour et quitter + save_and_return: Ajouter et quitter + create_case: Créer un cas + back_to_family_members: Revenir aux membres de la famille + create: Créer + messages: + update_success: 'Le dossier de la famille %{record_id} a été mis à jour avec succès.' + creation_success: 'La famille a été créer avec succès' + disabled: 'La famille a été désactivée ' + confirm_create_case: Souhaitez-vous créer un cas pour cette personne ? transfer: label: Transfert agency_label: Organisation @@ -3315,6 +3669,7 @@ fr: inprogress: 'En attente ' rejected: 'Rejeté ' revoked: Révoqué + transferred_by: Transféré par type: assign: 'Assigner ' reassign: 'Assigner ' @@ -3335,6 +3690,7 @@ fr: locale: Locale location: Lieu messages: + records_update: Primero est en train de mettre à jour les données de cet utilisateur pour refléter les changements que vous avez effectués. La mise à jour des tableaux de bord et des rapports peut prendre un certain temps. confirmation: Êtes-vous sûre de vouloir supprimer cet utilisateur ? La suppression est irréversible. Cliquez sur OK pour supprimer l'utilisateur. created: L'utilisateur a bien été créé. failure: Une erreur s'est produite, veuillez contacter le support s'il vous plaît. @@ -3345,6 +3701,7 @@ fr: passwords_do_not_match: ne correspond pas au mot de passe actuel time_zone_updated: La modification a bien été mise à jour. updated: L'utilisateur a bien été mis à jour. + created_warning: Vous avez créé %{total_enabled} sur vos %{maximum_users} utilisateurs actifs autorisés. organization: Organisation agency: Organisation services_help_text: Si vous ne spécifiez pas de services, cet utilisateur bénéficiera des mêmes services que son organisation. @@ -3363,6 +3720,21 @@ fr: provider_username_help: 'Exemple: mon.nom@%{domain}' role_id: Fonction send_mail: Recevoir des notifications par email? + send_mail_preferences: + label: Quels types de notifications par courrier électronique souhaitez-vous recevoir ? + help_text: Si vous laissez ce champ vide, vous recevrez toutes les notifications par courrier électronique. + receive_webpush: + label: Recevoir des notifications push ? + help_text: Notez que vous devrez toujours autoriser les notifications push dans le navigateur de votre appareil. + tooltip: Vous devez d'abord modifier votre compte et activer les notifications push pour votre utilisateur. + receive_webpush_preferences: + label: Quels types de notifications push souhaitez-vous recevoir ? + help_text: Si vous laissez ce champ vide, vous recevrez toutes les notifications push. + notification_preferences: + approval_request: 'Demande d''approbation (Superviseur)' + approval_response: 'Réponse à la demande d''approbation (travailleurs sociaux)' + transition_notification: 'Assignations, transferts et références' + transfer_request: 'Demande de transfert' user_group_unique_ids: Groupe d'utilisateur user_name: Nom d'utilisateur services: Services @@ -3422,6 +3794,10 @@ fr: user_name: Nom d'utilisateur position: Poste agency: 'Organisation ' + alerts: + total_users_created: 'Vous avez créé %{total_enabled} utilisateurs en dehors de la limite de votre système qui autorise %{maximum_users} utilisateurs autorisés. ' + limit_user_reached: Vous avez atteint votre limite de %{maximum_users} utilisateurs actifs. Vous devez désactiver un ou plusieurs utilisateurs avant d'en créer d'autres. + limit_user_reached_on_enable: Vous avez atteint votre limite de %{maximum_users} utilisateurs actifs. Vous devez désactiver un ou plusieurs utilisateurs avant d'en créer d'autres. devise: failure: already_authenticated: "Vous êtes déjà enregistré." @@ -3433,3 +3809,9 @@ fr: selected_records: '%{select_records} lieu(x) sélectionnés' selected_all_records: Sélectionnez tous les cas %{total_records} qui correspondent à cette requête. updated: '%{updated_records} localité(s) mis à jour ' + push_notifications_dialog: + title: Notifications sur les appareils + body_blocked: + message: Vous avez bloqué les notifications pour Primero sur cet appareil. Pour remédier à ce problème, vous devez autoriser les notifications. + android: "Android : Allez dans Paramètres. Cliquez sur Applications. Trouvez Primero dans la liste des applications et cliquez dessus. Cliquez sur Notifications. Activez le bouton de notification." + ios: "iOS : Allez dans les réglages. Cliquez sur Notifications. Faites défiler vers le bas jusqu'à la liste des applications et trouvez Primero. Activez le bouton de Primero." diff --git a/config/locales/hu.yml b/config/locales/hu.yml index e2b862d666..d56161214b 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -12,6 +12,8 @@ hu: minimum_reportable_fields: "Minimális mezők %{record_type}" name: Név offline: Offline + field_mode_on: "Bekapcsolva" + field_mode_off: "Kikapcsolva" unavailable_offline: Nem elérhető online: Online yes_label: 'Igen' @@ -21,6 +23,8 @@ hu: log_in_primero_idp: Lépj be%{idp_name} offline_submitted_changes: Jelenleg offline módban van. A módosítások mentve lesznek ha újra online módban lesz. updated: Frissítve + go: Mehet + select_idp_error: Válassz szolgáltatót sync: success: "%{records} rekordok sikeresen szinkronizálva." error: @@ -28,7 +32,7 @@ hu: update: A %{record_type} %{short_id} frissítése sikertelen. Kérjük, forduljon az ügyfélszolgálathoz. actions: approvals: ' Jóváhagyások' - button: Cselekvények + button: Cselekmények close: Bezárni description: invalid: Érvénytelen adat @@ -94,7 +98,7 @@ hu: rejected: Elutasítva requested: Kérvényezve audit_log: - action: Cselekvény + action: Cselekmény description: Leírás record_owner: Adattulajdonos timestamp: Idő @@ -113,7 +117,7 @@ hu: buttons: accept: Elfogadom add: Hozzáaddni - add_another_option: Hozzáadni egy másikat + add_another_option: Egy másik opció hozzáadása add_note: Jegyzetek hozzáadása apply: Alkalmazni approvals: Jóváhagyások @@ -141,7 +145,7 @@ hu: disable_photo_wall: Fotófalat letiltani done: Kész download: Letöltés - edit: Módosítás + edit: Szerkesztés edit_subform: Alűrlap módosítása enable: Engedélyezni enable_photo_wall: Fotófalat engedélyezni @@ -155,16 +159,17 @@ hu: flag_records: Megjelölni flags: Megjelölések guidance: Tanácsadó - guiding_questions: Tanácsadó kérdések + guiding_questions: Útmutató kérdések import: Import - login: Belépés + login: Bejelentkezés logout: Kilépés + link: Hivatkozás mark_for_mobile: Jelölje meg mobilra new: Új ok: OK print: Nyomtatás reassign: Kiosztani - referral: Utal + referral: Hivatkozás referral_again: Újra utal reject: Elutasít remove_referrals: Referenciák eltávolítása @@ -191,11 +196,24 @@ hu: view: Megtekintés view_flags_history: Előzmények megtekintése return_to_case: Vissza az Esetre + enable_webpush: Értesítések + dialog_yes: "Igen" + resync_records: + id: Azonosító + action: Tevékenység + date: Dátum + last_attempt: Utolsó próbálkozás + create: Létrehozás + update: Frissítés + resync: Beküldés case: label: Eset - create_new_case: Új Eset Létrehozása - add_new: Újat Hozzáadni - back_to_case: Vissza az Esetre + create_new_case: Új ügyfél regisztrációja + create_case: Új ügyfél regisztrációja + create: Létrehozás + add_new: Új hozzáadása + back_to_family_details: Vissza a családi részletekhez + back_to_case: Vissza az Ügyfélhez back_to_results: Vissza az Eredményekhez back_to_search: Vissza a Kereséshez search_by: Keresni @@ -262,7 +280,7 @@ hu: assessment: Értékelés case_opening_date: Az Eset megnyitásának dátuma case_plan: Esetterv - case_worker_code: Esetkód + case_worker_code: Ügyintéző kódja clear_filter: Törölni close_dialog: Az OK gombra kattintva az ügy állapota Lezártra változik close_dialog_title: Eset Lezárása @@ -295,7 +313,7 @@ hu: pending: Függőben levő rejected: Elutasítva bia: BIA - by_date: Dátum szerint + by_date: Dátummal case_open_date: Az Eset megnyitásának dátuma case_plan: Esetterv closed: Lezárva @@ -306,7 +324,7 @@ hu: district: Kerület duplicate: Kettőzött enabled_disabled: Engedélyezve / Tiltva - female: Női + female: Nő flag: Megjelölve flag_label: Meg van jelölve? gbv_closure: GBV Lezárni @@ -339,7 +357,7 @@ hu: workflow: Esetek munkafolyamat szerint flag_summary: Ellenőrizze az összefoglalót full_name: Teljes név - gbv_closure: GBV Lezárni + gbv_closure: GBV Lezárás hide_name: Név elrejtése hide_name_error: Hiba történt a módosítások mentésekor. Kérjük, próbálja meg újra. id: ID# @@ -394,7 +412,7 @@ hu: revoke_failure: Hiba történt a %{transition_type} visszavonása közben. Kérjük, forduljon az ügyfélszolgálathoz. revoke_message: A „Visszavonás” gombra kattintva eltávolítja a %{transition_type} címzett hozzáférését az esethez. revoke_success_message: A %{case_id}%{transition_type}%{recipient_username}eset visszavonva. - save_filter: Menteni + save_filter: Mentés selected_all_records: Válassza ki az összes %{total_records} esetet, amely megfelel ennek a lekérdezésnek. selected_records: '%{select_records}kiválasztott eset(ek)' sex: Nem @@ -403,7 +421,7 @@ hu: status: Állapot summary: label: Összefoglaló - find_match: Egyezést keresni + find_match: Találj egyezést matched_trace: 'Egyezik # %{trace_id}' cannot_find_matches: Nem található egyezés. Ebben az ügyben nem kaptunk hozzájárulást az információk nyomon követési célú közzétételéhez. matched: Egyezett @@ -442,7 +460,7 @@ hu: create: Adat létrehozva deleted_subform: 'Eltávolítva "%{subform_name}" alűrlap bejegyzés száma %{short_id}' label: Változási napló - see_details: Megtekinteni a részleteket + see_details: Lásd a részleteket. change: '"%{from_value}"-tól "%{to_value}"-ig' updated_subform: 'Frissítve " %{subform_name}" alűrlap bejegyzés száma %{short_id}' update_subform: 'Frissítve "%{subform_name}" alűrlap' @@ -486,7 +504,7 @@ hu: contact: field: email: E-mail - location: Hely + location: Helyszín name: Név organization: Szervezet other_information: Egyéb információk @@ -540,7 +558,7 @@ hu: approved: Jóváhagyva assessment: Értékelés awaiting_acceptance: Elfogadásra vár - cases_by_social_worker_total: Teljes + cases_by_social_worker_total: Összesen cases_by_social_worker_new_or_updated: Új és frissített case_id: 'Esetszám' case_management_service: Ügykezelési szolgáltatás @@ -551,7 +569,7 @@ hu: case_stat_by_assessment_level: Az esetek értékelési szint szerint case_stat_referrals: Referenciák case_stats: Esetek - case_worker: A munkás esetei + case_worker: Ügyintéző cases_by_social_worker: A szociális munkás esetei cases_by_task_overdue: Lejárt feladatok cases_by_workflow: Esetek munkafolyamat szerint @@ -570,14 +588,45 @@ hu: count_new_closure_approvals: one: '%{stat} új %{stat_type} jóváhagyás' other: '%{stat} új %{stat_type} jóváhagyások' + count_pending_approval_total: + one: Önnek %{stat}függőben lévő %{stat_type}jóváhagyása van + other: Önnek %{stat}függőben lévő%{stat_type}jóváhagyása van + count_pending_transfers: + one: Önnek %{stat}függőben lévő átutalása van + other: Önnek %{stat}függőben lévő átutalása van + count_records_new: + one: és %{stat}új esete van + other: és %{stat}új esete van + count_records_total: + one: Önnek összesen %{stat}esete van + other: Önnek összesen %{stat}esete van + count_referrals_new: + one: és %{stat}új ajánlása van + other: és %{stat}új ajánlása van + count_referrals_total: + one: Önnek összesen %{stat}ajánlása van + other: Önnek összesen %{stat}ajánlása van + count_rejected_approval_total: + one: és %{stat} elutasított %{stat_type} jóváhagyás + other: és %{stat} elutasított %{stat_type} jóváhagyás + count_rejected_transfers: + one: és %{stat} elutasított átutalás + other: és %{stat} elutasított átutalás + count_risk_level_new: + one: és %{stat} új %{stat_type} kockázati eset + other: és %{stat} új %{stat_type} kockázati eset + count_risk_level_total: + one: 'Önnek van %{stat} %{stat_type} kockázati esete ' + other: 'Önnek van %{stat} %{stat_type} kockázati esete ' + count_waiting_for_acceptance_transfers: '%{stat}átutalás vár az Ön elfogadására' current_owner: Jelenlegi tulajdonos dash_case_incident_overview: Saját Esetek - dash_group_overview: Csapat esetei + dash_group_overview: A csoportom esetei dash_shared_from_my_team: Megosztva a csapatomtól - dash_shared_with_me: Megosztotta velem + dash_shared_with_me: Megosztva velem dash_shared_with_my_team: Megosztva a csapatommal dash_shared_with_my_team_overview: Megosztva a csapatommal (áttekintés) - dash_shared_with_others: Megosztva másokkal + dash_shared_with_others: Másokkal megosztva dash_national_admin_summary: Rendszergazdai összefoglaló date: Dátum date_of_incident: Az incidens dátuma @@ -604,6 +653,15 @@ hu: link_see_all: Megtekinteni az összeset low_level: Alacsony low_risk: Alacsony prioritás + manager_count_closed_total: + one: és %{stat} lezárt eset + other: és %{stat} lezárt eset + manager_count_open_total: + one: Önnek %{stat} nyitott ügye van + other: Önnek %{stat} nyitott ügye van + manager_transfers_totals: + one: 'Önnek %{stat} %{stat_type} átutalása van ' + other: 'Önnek %{stat} %{stat_type} átutalása van ' match_result: Egyező eredmények medium_level: Közepes medium_risk: Közepes prioritás @@ -620,18 +678,27 @@ hu: new_referred: Új Referenciák new_service_provision: 'Új szolgáltatásnyújtás ' new_this_week: Új (ezen a héten) - no_action_risk: Cselekvény Mentes + no_action_risk: Cselekmény Mentes no_case_stats: Statisztika mentes no_caseworker_data: Nincsenek ügykezelői adatok no_flagged_child: Nincsenek megjelölt esetek no_flagged_incident: Nincsenek megjelölt incidensek no_open_incidents: Nincsenek nyitott incidensek no_overdue_activities: Nincsenek lejárt tevékenységek + no_recent_activities: Nincs friss tevékenység + no_scheduled_activities: Nincsenek ütemezett tevékenység + none_risk: Nincs elsőbbség + number_of_victims: Áldozatok száma + number_of_violations: Szabálysértések száma + number_of_violations_verified: Igazolt szabálysértések + open: Nyitott open_cases: Nyitott ügyek open_incidents: Nyitott incidensek outstanding_transfers: Kiemelkedő átvitelek overdue_activities: Lejárt tevékenységek overdue_cases_to_assign: Lejárt esetek kiosztása + overdue_cases_to_assign_high: Ezek az esetek már több mint 1 órája fennállnak + overdue_cases_to_assign_low: Ezek az esetek már több mint három órája fennállnak overview: Áttekintés pending: Függőben pending_approvals: Függőben lévő jóváhagyások @@ -643,12 +710,16 @@ hu: range4_8: 4-8 range8_12: 8-12 recent_activities: Legutóbbi tevékenységek + recently_flagged_child: Nemrégiben megjelölt esetek + recently_flagged_incident: Nemrégiben megjelölt incidensek referrals_by_social_worker: Szociális munkás referenciái registration: Registráció rejected: Elutasítva rejected_transfers: Elutasított átvitelek response: Válasz (Folyamatban) scheduled_activities: Tervezett tevékenységek + score_range: Pontszámtartomány + screening_service: Szűrőszolgáltatás services: Szolgáltatások services_implemented: Megvalósult szolgáltatások shared_from_my_team_pending_transfers: Függőben levő átvitelek @@ -663,225 +734,1909 @@ hu: shared_with_others_pending_transfers: Függőben levő átvitelek shared_with_others_referrals: Referenciák shared_with_others_rejected_transfers: Elutasított átvitelek + status_of_cases: Az ügyek helyzete system_user: Rendszer total: Összesen + total_cases: Összes eset total_referred: Összes Referenciák + tr_stats: Nyomkövetési kérelmek transers_awaiting_acceptance: Elfogadásra váró átvitelek transfers_by_social_worker: A szociális munkás átvitelei + users: BEÁLLÍTÁSOK ikon + violence_type: Erőszak típusa + with_incidents: Incidensekkel + with_new_incidents: Új incedensekkel + without_incidents: Incidensek nélkúl + worker_count_referrals_total: + one: '%{case_worker} ősszesen %{stat}ajánlással rendelkezik' + other: '%{case_worker} ősszesen %{stat}ajánlással rendelkezik' + worker_count_total: + one: '%{case_worker} ősszesen %{stat}esettel rendelkezik' + other: '%{case_worker} ősszesen %{stat}esettel rendelkezik' + workflow: Munkafolyamat + workflow_team: Munkafolyamat - Csapatok esetei + you_have: 'Önnek van' + disabled: + status: + disabled: Korlátozva + enabled: Engedélyezve email_notification: assign: '%{user}A következő %{record_type}kiosztva önhöz: %{record_id}' assign_subject: '%{record_type}:%{id}- Önhöz kiosztott' + approval_request: 'A felhasználó %{user} %{approval_type} jóváhagyást kér %{case_id}ügyhöz.' + approval_request_subject: 'Ügy: %{id} - jóváhagyási kérelem' + approval_response: '%{user} %{status} jóváhagyási kérelmet nyújtott be %{approval_type} a/az %{case_id} esethez.' + approval_response_subject: 'Eset: %{id} - jóváhagyási válasz' + referral: '%{user} a/az %{agency} a következő %{record_type}adatot küldte Önnek: %{record_id} a %{service_type}számára.' transfer: '%{user}a következőket adta át %{record_type}önnek: %{record_id}. ' transfer_request_subject: Átvitelési kérvényezés az egyik esetéhez transfer_subject: '%{record_type}:%{id}- Átadta' + referral_subject: '%{record_type}: %{id} - Ajánlás' transfer_request: 'A Primero felhasználója %{user}az %{agency}től, kérvényezi, hogy adja át ennek a rekordnak %{record_type}%{record_id}a tulajdonjogát hogy biztosítani tudják az %{record_type}kezelését a környéken élő személynek. Ha ez az átvitel delfogadható az Ön számára, kérjük, kattintson az ebben az e-mailben található %{record_type} azonosító linkre az %{record_type} megnyitásához Primero-ban és az átvitel elindításához.' + approval_request_html: 'A felhasználó %{user} %{approval_type} jóváhagyást kér %{case_id}ügyhöz.' + approval_response_html: '%{user}rendelkezik %{status}a jóváhagyási kérelemmel %{approval_type}az %{case_id} ügyben.' transfer_html: '%{user}átkerült az%{record_type}Önhöz:%{record_id}' assign_html: '%{user}Aakövetkező %{record_type}kiosztva önhöz: %{record_id}.' transfer_request_html: 'A Primero felhasználója %{user}%{agency}től, kérvényezi, hogy adja át ennek a rekordnak %{record_type}%{record_id} a tulajdonjogát hogy biztosítani tudják az %{record_type} kezelését a környéken élő személynek. Ha ez az átvitel delfogadható az Ön számára, kérjük, kattintson az ebben az e-mailben található %{record_type} azonosító linkre az %{record_type} megnyitásához Primero-ban és az átvitel elindításához.' transfer_request_notes_html: 'A kérvény benyújtó személy megjegyzései:%{request_transfer_notes}' + encrypt: + export_type: Az export típusa + file_name: Saját fájlnév létrehozása (választató) + password_extra_info: A jelszónak legalább 8 karakterből kell állnia. Ez a jelszó az exportált fájlhoz lesz rendelve, és a jövőben bárkinek, aki megnyitja a fájlt, be kell írnia. + password_label: Kérjük, adjon meg egy jelszót, amely titkosítja a fájlt. + error_message: + address_fields: '%{fields} mezőt kell kitöltenie %{forms} nyomtatványon' + address_form_fields: Az űrlapon %{fields} mezőt kell kitöltenie + address_subform_fields: '%{subform} %{fields} érvénytelen mezőket tartalmaz' + error_page: + not_authorized: + server_error: Nincs jogosultsága az oldal eléréséhez. + title: Nem engedélyezett + not_found: + contact_admin: Ha úgy gondolja, hogy tévedésből került ide, kérjük, lépjen kapcsolatba az adminisztrátorral. + something_went_wrong: Elnézést, valami elromlott. errors: + error_loading: Hiba az adat(ok) betöltése során models: agency: code_present: nem lehet üresen + logo_format: A fájlnak png formátumban kell lennie + terms_of_use_format: A fájlnak png formátumban kell lennie name_present: nem lehet üresen + child: + age: Az életkornak 0 és 130 között kell lennie + date_of_birth: Kérjük, adjon meg egy érvényes születési dátumot ehhez az esethez. + export_configuration: + opt_out_field_does_not_exist: A megadott opt_out mező nem létezik a feljegyzésben. + record_type: Érvénytelen bejegyzés. "Gyermek", "Nyomon követési kérelem", vagy "Incidens" kell legyen. + field: + translated_options_do_not_match: A mező lefordított opcióinak azonos azonosítókkal kell rendelkezniük location: admin_level_present: nem lehet üresen code_present: nem lehet üresen name_present: nem lehet üresen + unique_location_code: Ezzel a helykóddal már létezik egy "Helyszín", kérjük, adjon meg egy másik helykódot. lookup: + being_used: Ez a keresés használatban van, és nem törölhető. name_present: A név nem maradhat üresen + values_ids_blank: A lookup_value azonosító üres primero_module: + associated_record_types: Legalább egy rekordtípust kell társítani ehhez a modulhoz. + form_section_ids: Legalább egy űrlapot kell társítani ehhez a modulhoz. name_present: A név nem maradhat üresen + unique_name: Egy ilyen nevű modul már létezik, kérjük, adjon meg egy másik nevet. report: + module_presence: A modul nem maradhat üresen + module_syntax: Minden jelentésmodulnak már léteznie kell name_presence: A név nem maradhat üresen + role: + permission_presence: Kérjük, válasszon ki legalább egy engedélyt user: email: "Kérjük, adjon meg egy érvényes e-mail címet (pl.: name@example.org)" + password_mismatch: A jelszó mezők nem ugyanazzal a jelszóval rendelkeznek + password_length: A jelszónak legalább %{min}karakterből kell állnia email_uniqueness: Már van egy felhasználó ezzel az e-mail címmel. Kérjük, adjon meg egy másikat + code_of_conduct: + title_present: A "Cím" nem lehet üres + content_present: A "Tartalom" nem lehet üres + created_by_present: A "Létrehozta" nem lehet üres + not_found: Nem talált feljegyzés(ek) try_again: Próbálja újra exports: case_pdf: all: PDF one: PDF + selected: Kiválasztva PDF-be + csv: + all: CSV + one: CSV + selected: Kiválasztva CSV-be + custom: + all: Egyéni custom_exports: + all: Egyéni + choose_fields: Szeretné kiválasztani az űrlap egyes mezőit? + empty_fields_forms: Kérjük, válasszon ki néhány űrlapot vagy mezőt az exportáláshoz. + empty_format: Kérjük, válassza ki az exportálandó formátumot. + empty_module: Kérjük, válassza ki az exportálandó modult. + empty_password: Kérjük, adjon meg egy jelszót, amely titkosítja a fájlt. + field_label: Mező + fields: Válassza ki az exportálandó mezőket + form_label: Formanyomtatvány + format_label: Formátum kiválasztása + forms: Válassza a "Forms" menüpontot az exportáláshoz + label: Egyéni export + module_placeholder: Kérjük, válasszon egy modult. + select_module: Válasszon modult submit: OK + header: Fejléc + custom_header: Egyéni fejléc + include_implementation_logos: Tartalmazza a végrehajtási logókat? + include_agency_logo: Tartalmazza az ügynökség logóját? duplicate_id_csv: + all: Duplikált azonosító female_abbreviation: F headers: age: Életkor + case_id: Ügy azonosítója child_name_last_first: Gyermek neve + family_size: Család mérete + national_id_no: Nemzeti azonosítószám + progress_id: Haladás azonosító + sex_mapping_m_f_u: Nem + other_agency_id: Kórházi kód és a beteg száma male_abbreviation: M unknown_abbreviation: U + exported: Az export fájl sikeresen generálva + exported_error: Hiba az exportfájl generálásában forms: + button: Formanyomtatványok exportálása label: Export + header: + form_name: Formanyomtatvány neve + field_id: Mező azonosítója + field_type: Mező típusa + field_name: Mezőnév + required: Kötelező + on_mobile: Mobilon + on_short_form: Rövidített formában + option_ids: Opciók azonosítói + options: Opciók + options_lookup: Keresés + help_text: Súgó szöveg + guiding_questions: Útmutató kérdések + visible: Látható + lookup_id: Keresési azonosító + lookup_name: Név keresés + option_id: Opció azonosítója + option_name: Opció neve + options: + location: Helyszínek + agency: Ügynökségek + user: Felhasználók + reportinglocation: Helyszínek bejelentése + subforms: 'Alnyomtatvány: %{subform_name}' + collapsed_fields: 'Összeomlott mezők:%{fields}' + country: Országok + summary_header: + status: Állapot + notes: Jegyzetek + json: + all: JSON + one: JSON + selected: Kiválasztva JSON-ba + list_view_csv: + all: Listanézet exportálása + selected: Kiválasztva CSV-be + messages: + no_exporter: Nincs megnevezett exportőr + mrm_violation_xls: + all: MRM szabálysértések + one: MRM szabálysértések + selected: MRM jogsértésekhez kiválasztva + no_records: Nincsenek rendelkezésre álló feljegyzések! pdf: + all: PDF (nem titkosított) one: PDF + selected: Kiválasztva PDF-be pdf_exports: label: PDF recipient: Címzett + case_worker: Ügyintéző + client: Ügyfél date: Dátum recipient_name: Címzett neve recipient_agency: A ügynökség címzettje + caseworker_name: Ügyintéző neve + caseworker_agency: Ügyintéző iroda + photowall: + all: Fotófal + no_photos_available: Nincsenek rendelkezésre álló fényképek + one: Fotófal + reunited: Újraegyesített + selected: Kiválasztva a Fénykép falra + queueing: Az exportfájl %{file_name}létrehozása + selected_xls: + all: Excel + one: Excel + selected: Kiválasztva Excelbe + selected_fields: Kiválasztott mezők unhcr_csv: + all: ENSZ MENEKÜLTÜGYI FŐBIZTOSSÁG female_abbreviation: F headers: age: Életkor + causes_of_separation: Az elkülönülés okai + country_of_origin: Származási ország + cpims_code: CPIMS-kód + current_care_arrangement: Jelenlegi gondozási rendszer date_of_birth: Születési dátum + date_of_identification: Azonosítás dátuma + family_count_no: A család számlálószáma + governorate_country: Kormányzóság - Ország + id: Azonosító + individual_progress_id: Egyéni fejlődési azonosító + locations_by_level: Cím (tábor, tömb, és egyéb alkalmazható címszintek, például a menedékhely GPS-koordinátái) + long_id: Hosszú azonosító + moha_id: MOHA azonosító + name_of_caregiver: A gondozó teljes neve + name_of_child_last_first: Gyermek teljes neve + primary_protection_concerns: Elsődleges védelmi aggályok + progres_id: Haladás azonosító + reunification_status: Újraegyesítési állapot + secondary_protection_concerns: Másodlagos védelmi aggályok + sex: Nem + sex_mapping_m_f_u: Nem + short_id: Rövid azonosító + vulnerability_code: Sérülékenységi kódok male_abbreviation: M + one: ENSZ MENEKÜLTÜGYI FŐBIZTOSSÁG + selected: Az UNHCR számára kiválasztott + unknown_abbreviation: U + xlsx: + all: Excel + one: Excel + selected: Kiválasztva Excelbe + imports: + csv_hxl_location: + messages: + success: '''Helyszínek'' importálása sikeres' + no_data: 'Nem feldolgozott import: Nincs adatátvitel' + csv_parse_error: 'Nem feldolgozott import: CSV-adatok elemzési hibája' + db_error: 'Hiba létrehozása %{location_code}:%{message}' + locale_invalid: 'Kihagyás %{column_name}: Érvénytelen helyszín' + insert_all_error: 'Nem feldolgozott import. Adatbázis hiba:%{message}' + csv_record: + messages: + success: '''Bejegyzések'' importálása sikeres' + no_data: 'Nem feldolgozott import: Nincs adatátvitel' + no_file: 'Nem feldolgozott import: A fájl nem létezik' + csv_parse_error: 'Nem feldolgozott import: CSV-adatok elemzési hibája' + error: 'Nem feldolgozott: %{message}sor %{row_number}' + db_error: 'Hiba létrehozása %{location_code}:%{message}' + locale_invalid: 'Kihagyás %{column_name}: Érvénytelen helyszín' + insert_all_error: 'Nem feldolgozott import. Adatbázis hiba:%{message}' + sync_record: + failed: 'Utolsó szinkronizálás: Sikertelen' + last: 'Utolsó szinkronizáció: %{date_time}' + not_found: 'Utolsó szinkronizálás: Adat nem található' + retrieving: Adatok lekérése. + see_details: Lásd a részleteket. + fields: + action: Cselekmény + actions: Cselekmények + add: Hozzáaddni + add_new_field: Új mező létrehozása + add_field: Mező hozzáadása + add_field_type: Hozzáadás %{file_type} + audio: + current: Jelenlegi Audio + audio_upload_box: Audio feltöltés + bia_document: BIA dokumentum + bid_document: BID dokumentum + check_box: Ellenőrizze a 'Dobozok' jelölőnégyzeteket + copy_from_another_form: Ez a mező egy másik űrlapról lett átmásolva + create_field: Mező létrehozása + create_unique_values: Egyedi értékek létrehozása + date_field: Dátum mező + date_help: dd-mmm-yyyy + date_help_with_time: dd-mmm-yyyy hh:mm + date_not_valid: Ez a dátum nem érvényes. + time: Idő + date_range: + date: Dátum + date_range: Dátumtartomány + from: tól + date_range_field: Dátumtartomány + date_time: Dátum- Idő + db_name: Adatbázis neve + default: Alapértelmezett? + default_date_validation: Alapértelmezett dátum érvényesítése + default_value: Alapérték + deleted: A %{display_name}mező törlésre került. + detail: Részlet + disabled: Letiltva + display_name: Megjelenítendő név + document: + comments: Megjegyzések + current: Ez az aktuális dokumentum? + date: Dokumentum dátuma + name: Dokumentum neve + is_current: Ez az aktuális dokumentum? + document_upload_box: Dokumentum feltöltése + edit_label: Mező szerkesztése + enabled: Engedélyezve? + enabled_label: Engedélyezve + english_text: Angol szöveg + field_name: Mezőnév + field_type: Mező típusa + file_upload_box: + add_document_label: Dokumentum hozzáadása + add_new_document_button_text: Újabb dokumentum hozzáadása + add_new_photo_button_text: Újabb fénykép hozzáadása + add_photo_label: Fénykép hozzáadása + document_description: Dokumentum leírása + document_file_restrictions_message: A fájlok mérete nem lehet nagyobb 2 MB-nál (futtatható (.exe) fájlok nem tölthetők fel). + no_file_selected: Nincs kiválasztott fájl. + photo_file_restrictions_message: A fényképek mérete nem lehet nagyobb 10 MB-nál. A hangfájlok nem lehetnek nagyobbak 10 MB-nál. Minél kisebb, annál jobb. + recorded_audio_label: Felvett hangfelvétel + select_file_button_text: Fájl kiválasztása + form_name: Formanyomtatvány neve + future_date_not_valid: A jövőben nem lehetséges. + guidance: Tanácsadó + guiding_questions: Útmutató kérdések + help_text: Súgó szöveg + hide_on_view_page: Oldal megjelenítése + label: Mezők + mobile_visible: Mobil alkalmazás + move_to: Tovább a + multi_select: Több opciót is kiválaszthat + multi_select_box: Több választási lehetőség + must_be_english: Angol nyelven kell beadni + name: Név + not_future_date: Nem jövőbeli dátum + number_not_valid: Kérjük, adjon meg numerikus adatokat + numeric_field: Numerikus mező + option_strings_add_option: Opció hozzáadása + option_strings_source: Keresések + option_strings_text: Opciók + option_strings_text_display: Szöveg opció + option_strings_text_key: Kulcs opció + options_indications_lookup_values: Használhat előre megadott kereséseket vagy egyedi értékeket is létrehozhat. + options_indications_restrictions: Mindkettő nem lehetséges. + options_or_lookup_warning: Kérjük, adjon hozzá opciókat vagy válasszon egy keresést. Ne adja meg mindkettőt. + other_documents: Egyéb dokumentum + photo_upload_box: Fénykép feltöltése + predifined_lookups: Előre meghatározott keresés használata + radio_button: Rádió gomb + remove: Távolítsa el + remove_attachment_confirmation: Biztos, hogy el akarja távolítani ezt a mellékletet? + required: Kötelező + required_field: '%{field}szükséges' + search_existing: Meglévő mezők keresése + select_box: Drop Down kiválasztása + select_date_validation: Válassza ki a dátum érvényesítési módszert + select_multiple: Válassza ki az összes megfelelőt + select_single: (Válasszon...) + separator: Elválasztó + show: Mutatni? + show_on: Mutassa tovább + show_on_minify_form: Rövidített forma + subform: Alűrlap + subform_group_by: Csoportosítva + subform_remove_message: Biztos, hogy el akarja távolítani ezt az alnyomtatványt? + subform_section: + description: Alforma leírása + name: Alűrlap címe + starts_with_one_entry: Kezdd egy alnyomtatvány bejegyzéssel? + subform_append_only: Szelektív szinkronizálás mobilon + subform_prevent_item_removal: Alforma bejegyzés eltávolításának megakadályozása? + subform_sort_by: Rendezés + successfully_added: Mező sikeresen hozzáadva + tally_items_maximum: (Maximum 5) + text_area: Szövegterület + text_field: Szövegmező + textarea: Szövegterület + tick_box: Jelölőnégyzet + tick_box_label: A jelölőnégyzet címkéje + total: Összesen + type: Típus + updated: Mező frissítve + visibility: Láthatóság + web_app: Webalkalmazás + filters: + apply_filters: Alkalmazni + clear_filters: Törölni + less: Kevesebb... + more: Több... + save_filters: Mentés + flags: + date: 'Dátum:' + flag_reason_maximun_label: Maximum 255 karakter. + resolved_date: 'Megoldva:' + followup_reminders: + system_generated_followup_flag: kötelező ellenőrző vizsgálat + form_section: + form_name: Formanyomtatvány neve + module: Modul + name: Név + record_type: Felvétel típusa + required_field: '%{field}szükséges' forms: + add: Formanyomtatvány hozzáadása + fields: Mezők + form_description: Leírás + help_text: + summariaze_purpose: Összefoglalja az űrlap célját. Angol nyelven kell beírni + invalid_characters_field: '%{field} érvénytelen karaktereket tartalmaz.' + label: Nyomtatványok + manage: Kezelje + messages: + created: Sikeresen létrehozott űrlaprész + save_with_errors: Probléma merült fel, és néhány űrlaprészlet nem frissült. + updated: Az űrlaprész sikeresen frissült + use_existing: A meglévő űrlapok használatát javasoljuk, mivel ez megkönnyíti az intézmények közötti adatmegosztást és adategyesítést. + mobile_app: Mobil alkalmazás + module: Modul + no_subform_filters_added: Ez az alűrlap jelenleg nem rendelkezik mezőkkel. + record_type: Felvétel típusa record_types: + approvals: ' Jóváhagyások' + case: Eset + child: Eset + incident: Incidens + individual_victim: Egyéni áldozat + potential_match: Potenciális egyezés + record_information: Információk felvétele referrals: Referenciák + reportable_follow_up: Folytatás + reportable_protection_concern: Védelmi aggály + reportable_service: Szolgáltatás + tracing_request: Nyomkövetési kérelem transfers_assignments: Átvitelek / Kiosztások + violation: Szabálysértés + registry_details: Nyilvántartás részletei + registry_record: Nyilvántartási bejegyzés + select_label: Válassza ki + settings: Beállítások + show_on: Mutassa tovább + subform_need_to_be_added: Ezt hozzá kell adni. + subform_need_to_be_added_single: Ezt hozzá kell adni. + subform_not_found: Nem találtunk %{subform_name}. + title: Formanyomtatvány címe + translations: + edit: Fordítások szerkesztése + no_changes_message: Nem hajtott végre fordítási változtatásokat + note: 'Megjegyzés:' + select_language: Válasszon nyelvet + title: Fordítások + type_label: Típus + visibility: Láthatóság + web_app: Webalkalmazás + home: + ar: العربية + ar-IQ: العربية (العراقية) + ar-JO: العربية (الأردنية) + ar-LB: العربية (اللبنانية) + ar-SD: العربية (السودانية) + bn: বাংলা + current_time_zone: Aktuális időzóna + dashboard: Irányítópult + en: Angol + es: Español + fr: Français + id: Bahasa + km: ភាសាខ្មែរ + ku: کوردی + ku-IQ: کوردی (بادینی) + fa-AF: فارسی (افغانستان) + ps-AF: پښتو (افغانستان) + sw-KE: Kiswahili (Kenya) + sw-TZ: Kiswahili (Tanzania) + ne: नेपाली + label: Főoldal + language: Nyelv + manage_system_users: A "Kiszolgálói szinkronizálás felhasználói" kezelése + my: ဗမာစာ + pt: Português + pt-BR: Português (Brasil) + records_need_attention: Feljegyzések figyelemre szorulnak + ru: Русский + so: Af-Soomaali + th: ไทย + users: Felhasználók kezelése + view_records: Bejegyzések megtekintése + welcome: Üdvözöljük a Primero-ban + zh: 中文 + incident: + associated_case: "Kapcsolódó ügy:" + messages: + creation_success: Sikeresen létrehozott eseménynyilvántartás. + creation_success_queue: Sikeresen létrehozott incidens nyilvántartás a háttérben + disabled: Incidens letiltva + update_success: 'Az incidens %{record_id} sikeresen frissült.' + update_success_queue: 'Az incidens %{record_id}sikeresen frissült a háttérben.' + violation: + update_and_return: 'Frissítés és visszatérés a%{association}' + save_and_return: 'Hozzáadás és visszatérés a%{association}' + pending: Ellenőrzés folyamatban + title: Szabálysértések + types: + killing: Gyermekek meggyilkolása + maiming: Gyermekek megcsonkítása + recruitment: Gyermekek toborzása és/vagy kihasználása + abduction: Emberrablás + attack_on: Iskola(k) és/vagy kórház(ak) elleni támadások + military_use: Iskola(k) és/vagy kórház(ak) katonai célú használata + denial_humanitarian_access: A gyermekek humanitárius segítségnyújtásának megtagadása + incidents: + disable_dialog_title: Incidens letiltása + disable_success: Sikeresen letiltott incidens + enable_dialog_title: Incidens engedélyezése + id: Azonosítószám + date_of_interview: Az interjú dátuma + date_of_incident: Az incidens dátuma + incident_location: Incidens helye + violations: Szabálysértések + export: Exportálás + label: Incidensek + filter_by: + boys: Fiúk + by_date: Dátummal + children: Gyermekek + girls: Lányok + incident_location: Incidens helye + unaccompanied_separated_status: Védelmi állapot + unknown: Ismeretlen + verification_status: Ellenőrzési állapot + violence_type: Erőszak típusa + register_new_incident: Új incidens + selectable_date_options: + date_of_first_report: Interjú időpontja + incident_date_derived: Incidens dátuma + selected_records: '%{select_records}kiválasztott incidens(ek)' + selected_all_records: 'Válassza ki az összes %{total_records} eseményt, amely megfelel a lekérdezésnek.' + survivor_code: Túlélő Kód + show_incident: 'Incidens azonosítója %{short_id}' + social_worker: Szociális munkás + type_violence: Az erőszak típusa key_performance_indicators: + case_closure: "Ügy lezárása" + feedback: "Visszajelzés" + other: "Egyéb" + date_format: "%b %Y" + date_range_select: + custom_range: 'Egyéni' + long_date_format: "dd/MM/yyyy" + time_periods: + all_time: 'Minden időben' + current_month: "Aktuális hónap" + last_3_months: "Az elmúlt 3 hónap" + last_6_months: "Az elmúlt 6 hónap" + 0-3days: "0 - 3 nap" + 4-5days: "4 - 5 nap" + 6-14days: "6 - 14 nap" + 15-30days: "15 - 30 nap" + 1-3months: "1 - 3 hónapig" + 4months: "> 3 hónap" + 1-month: "< 1 hónap" + 3-6months: "3 - 6 hónapig" + 7-months: "> 6 hónap" + number_of_cases: + title: "1. A rögzített esetek száma" + reporting_delay: + delay: "Késleltetés" + total_incidents: "Összes incidens" + service_access_delay: + delay: "Késleltetés" + total_incidents: "Összes incidens" + assessment_status: + title: "4. Értékelési státusz" + completed: "Befejezett" + services_provided: + title: "8. Szolgáltatások" + service: "Szolgáltatás" + count: "A megadott időpontok" + male: "Férfi" + female: "Nő" + 0-11: "0-11" + 12-17: "12-17" + '>18': ">18" + disability: "Fogyatékosság" + no_disability: "Nincs fogyatékosság" average_referrals: title: "9. Átlagos Referenciák" label: "Átlagos referenciák esetenként" referrals_per_service: title: "Átlagos referenciák szolgáltatásonként" + average_followup_meetings_per_case: + title: "10. Átlagos nyomon követési találkozók esetenként" + time_from_case_open_to_close: + title: "11. Az ügy megnyitásától az ügy lezárásáig eltelt idő" + percent: "Az esetek százalékos aránya" + case_closure_rate: + title: "12. Az ügy lezárásának száma" + client_satisfaction_rate: + title: "13. Ügyfél-elégedettségi arány" + label: "Ügyfél-elégedettség" + invalid: "Ezt jelenleg nem tudjuk kiszámítani." + supervisor_to_caseworker_ratio: + title: "14. Felügyelő és ügyintéző közötti arány" + case_load: + title: "15. Ügyszám" + case_load: "Ügyszám" + percent: "az ügyintézők százalékos aránya" + 10cases: "< 10 eset" + 20cases: "11 - 20 eset" + 21-30cases: "21 - 30 eset" + 30cases: "> 30 eset" + date_range_dialog: + title: "Egyéni dátumtartomány" + description: "Ha ezt a módosítást alkalmazza, az adatok az alábbi két dátum között lesznek kiválasztva." + apply: 'Alkalmazni' + aria-labels: + from: "Az adatok kiválasztására ezen időpont után kerül sor" + to: "Az adatok kiválasztására ezen időpont előtt kerül sor" + location: + base_types: + camp: Tábor + chiefdom: Törzshely + city: Város + community: Közösség + country: Ország + county: Megye + district: Kerület + governorate: Kormányzóhivatal + locality: Helyszín + other: Egyéb + province: Tartomány + region: Régió + site: Oldal + state: Állapot + sub-district: Alkörzet + village: Falu + zone: Zóna + association: Szövetség + label: Helyszín + name: Név + code: Kód + admin_level: Admin-szint + type: Típus + hierarchy: Hierarchia + import_title: '''Helyszín'' importálása' + no_location: Kérjük, a Felhasználói fiókok létrehozása előtt importálja a Helyszíneket. + enable_title: Helyszín engedélyezése + enable_text: Biztos benne? Ha engedélyezi a kiválasztott Helyeket, akkor a Helyek mezőkben opcióként jelennek meg. + disable_title: Helyszín letiltása logger: actions: + _approved: Jóváhagyva + _rejected: Elutasítva + _requested: Kérvényezve + add_note: Jegyzet hozzáadása assign: Kiosztani + attach: Csatlakoztassa + bulk_assign: Tömeges hozzárendelés + bulk_create: Tömeges létrehozás + bulk_index: Tömegindex + case_plan_approved: Jóváhagyott esetterv + case_plan_rejected: Elutasított esetterv + case_plan_requested: Igényelt esetterv + close: Bezárni + create: Hozzon létre + create_bulk: Tömeges létrehozás + delete: Törölni + destroy: Megsemmisíteni + detach: Leválasztani + enable_disable_record: Rekord letiltásának engedélyezése + export: Exportálás + flag: Megjelölni + import: Import + incident_details_from_case: Az eset részletei az ügyből + index: Index + list: Lista + login: Bejelentkezés + password_reset: Jelszó visszaállítása + password_reset_request: Jelszó visszaállítási kérelem + refer: Hivatkozás refer_accepted: A referencia elfogadva. + refer_done: Hivatkozás megtörtént + refer_rejected: Hivatkozás elutasítva + refer_revoke: Hivatkozás visszavonása + refer_to: Hivatkozzon a + reopen: Újranyitni + services_section_from_case: Szolgáltatások szekció az esetből + show: Mutassa + show_alerts: Figyelmeztetések megjelenítése + traces: Nyomok transfer: Adatátvitel transfer_accepted: Átvitel elfogadva. transfer_rejected: Átvitel elutasítva. transfer_request: Átvitelési kérvény transfer_to: Átvitelni + update: Frissítés + user_password_reset_request: Felhasználói jelszó visszaállításának kérelmezése + approve_form: + bia: BIA nyomtatvány + case_plan: Esetterv űrlap + closure: Lezárási formanyomtatvány + 'false': Elutasítás + gbv_closure: GBV Zárónyomtatvány + 'true': Jóváhagyás + assessment_approved: "%{approval_label}jóváhagyva" + bulk_index: Sorolja fel az összes + by_user: felhasználó által + case_plan_approved: "%{approval_label}jóváhagyva" + close: Bezárni + closure_approved: "%{approval_label}jóváhagyva" consent_count: Hozzájárulás száma + copy: Másolás + create: A létrehozása + create_subform: Al-formanyomtatvány létrehozása + destroy: A törlése + edit: Szerkesztés + enable_disable_record: Engedélyezés / Tiltás + export: Adatok exportálása a + flag: Jelölés + flag_records: Jelölés + graph_data: Grafikus adatok megtekintése + hide_name: + protect: Név elrejtése + view: Név Megtekintése + index: Bejegyzések listázása + list: Lista + login: Bejelentkezés + logout: Kijelentkezés + lookups_for_field: Mező keresése + mark_for_mobile: + 'false': Törölje a mobil kijelölését + 'true': Jelölés mobilra + match_record: Egyezik a Bejegyzéssel + permitted_field_list: Engedélyezett mezők listája + quick_view: Gyorsnézet megtekintése + reassign: kijelölése resources: + audit_log: Ellenőrzési napló + user: Felhasználó + agency: Ügynökség user_group: Felhasználói csoport + child: Gyermek + alert: Figyelmeztetés + form_section: Formanyomtatvány + lookup: Keresés + system_settings: Rendszerbeállítások + permission: Engedély + dashboard: Irányítópult + report: Jelentés + bulk_export: Tömeges export + saved_search: Elmentett keresés role: Szerepkör + incident: Incidens + location: Helyszín + primero_configuration: Primero konfiguráció + code_of_conduct: Magatartási kódex + task: Feladat + record_state: + 'true': Engedélyezés + refer: Hivatkozás refer_to: Keresni a referencia címzettjét + referral: Hivatkozó + relinquish_referral: A "Kész" hivatkozásról való lemondás + reopen: Újranyitni + reopen_case: Újbóli megnyitás + request_approval: + bia: Kérelem jóváhagyás a BIA űrlaphoz + case_plan: Az " Esetterv " formanyomtatvány jóváhagyása iránti kérelem + closure: A "Lezárás jóváhagyása" nyomtatvány igénylése request_transfer: Átviteli kérvényezés küldése request_transfer_view: Átviteli kérvényezés megtekintése + save_subform: Alforma elmentése + search: API-keresés + show: Megtekintés + show_alerts: Figyelmeztetések megtekintése + to: ig + to_user: a felhasználónak transfer: Átadás transfer_status: Accepted: Átvitel elfogadva Rejected: Átvitel elutasítva + unflag: Feloldás + update: Frissítés login: + label: Bejelentkezés + password: + label: Jelszó + password_confirmation: + label: Jelszó megerősítés + password_match: + label: A jelszónak egyeznie kell + title: Bejelentkezés + username: Felhasználó neve + password_reset_modal: Jelszó visszaállítása password_reset_modal_text: Primero elküld egy jelszó-visszaállítási linket az Ön e-mail címére password_reset_email: E-mail + forgot_password: Elfelejtette jelszavát? email: label: E-mail + lookup: + create: Új keresés + enabled_label: Engedélyezve? + english_label: Angol szöveg + label: Keresés + language_label: Nyelv + messages: + cannot_create: A keresést nem sikerült létrehozni + correct_errors: 'Kérjük, javítsa ki az alábbi hibákat, és küldje be újra:' + created: A keresés sikeresen létrejött. + updated: A keresés sikeresen frissült. + name: Név + no_options: Ez a keresés jelenleg nem rendelkezik beállításokkal. + values: Opciók + managed_reports: + date_range: + month: Hónap + quarter: Negyedév + year: Év + date_range_options: + this_quarter: Ebben a negyedévben + last_quarter: Utolsó negyedév + this_month: Ebben a hónapban + last_month: Múlt hónapban + this_year: Idén + last_year: Tavaly + custom: Egyéni + no_data: Erre a felismerésre vonatkozóan nincsenek adatok + no_data_table: Ehhez a betekintéshez nem léteznek táblázatadatok + violations: + name: Szabálysértések + filter_options: + incident_date: Az incidens dátuma + date_of_report: Jelentés időpontja + ctfmr_verified_date: Az ellenőrzés dátuma + reports: + killing: Gyermekek meggyilkolása + maiming: Gyermekek megcsonkítása + recruitment: Gyermekek toborzása és/vagy kihasználása + denial_humanitarian_access: A gyermekek humanitárius segítségnyújtásának megtagadása + sub_reports: + detention_detained: Maradjon őrizetben + perpetrators: A gyermekek száma az elkövetők szerint + reporting_location: Gyermekek száma régiónként + attack_type: Gyermekek száma támadás típusa szerint + boys: Fiúk + girls: Lányok + unknown: Ismeretlen + total: Összesen + gbv_statistics: + filter_options: + date_of_first_report: Az interjú dátuma + incident_date: Az incidens dátuma messages: alerts_for: + field_change: '%{form_section_name}frissítésre került%{alert_time}' transfer_request: Új átviteli kérvény érkezett %{date}, %{user} által ehez az %{agency}hez + cannot_edit: Ezt nem szerkesztheti + confirmation_message: Az OK gombra kattintva a nem mentett módosításokat elveti, és visszatér a lista nézethez . Kattintson a törlés gombra a rekordhoz való visszatéréshez. + dashboard_offline: Offline vagy. A műszerfal teljesen működőképes lesz, amikor újra online lesz. + logout_confirmation: Folytatni szeretné a munkamenetet? + logout_offline_warning: Biztos, hogy ki szeretne jelentkezni? Ha igen, akkor nem fog tudni újra bejelentkezni, amíg újra nem lesz online. Az offline állapotban végzett módosítások elvesznek. + logout_warning: 5 perc múlva kijelentkezik a rendszerből + logout_dialog_header: Offline kijelentkezés + logout_confirmation_title: Kijelentkezés megerősítése + logout_confirmation_text: Biztos, hogy ki akar jelentkezni? + no_changes: Nem hajtott végre mezőváltoztatásokat + not_available: Nem elérhető + record_list: + column_header_tooltip: Válogassa szét %{column} + no_match: Sajnálom, nem találtunk megfelelő bejegyzéseket + navigation: + bulk_exports: Exportálások + cases: Esetek + home: Főoldal + incidents: Incidensek + logout: Kilépés + reports: Jelentések + insights: Betekintések + search: Keresés + settings: Beállítások + support: Támogatás + support_menu: + code_of_conduct: Magatartási kódex + terms_of_use: Felhasználási feltételek + system_information: Rendszerinformáció + tasks: Feladatok + tracing_request: Nyomkövetési kérelem + registry_records: Nyilvántartás + notes: + note_success: Sikeresen hozzáadott megjegyzés permissions: + label: Engedélyek permission: + All: Összes + add_note: Jegyzetek hozzáadása + admin_only: Nincsenek bejegyzések - Csak admin funkciók + administrator_read: Rendszergazda Olvassa + agency: Ügynökség + agency_read: Ügynökség Olvassa + all: Hozzáférés az összes bejegyzéshez vagy felhasználóhoz + approvals_assessment: '%{approval_label}' + approvals_assessment_pending: '%{approval_label} függőben' + approvals_case_plan: '%{approval_label}' + approvals_case_plan_pending: '%{approval_label} függőben' + approvals_closure: '%{approval_label}' + approvals_closure_pending: '%{approval_label} függőben' + approve_action_plan: Jóváhagyás%{approval_label} + approve_assessment: '%{approval_label}Nyomtatvány jóváhagyása' + approve_case_plan: Jóváhagyás%{approval_label} + approve_closure: '%{approval_label}Nyomtatvány jóváhagyása' + approve_gbv_closure: '%{approval_label}Nyomtatvány jóváhagyása' + assign: Illetékes személy + assign_within_agency: Ügynökségen belüli kijelölés + assign_within_user_group: Felhasználói csoporton belüli kijelölés + audit_log: Ellenőrzési napló + case: Eset + case_approvals: Eseti jóváhagyások case_assignments_referrals_transfers: Esetkiosztások, referenciák és átvitelek + case_overview: Saját Esetek + close: Bezárni consent_override: Hozzájárulás felülbírálása + copy: Másolás + copy_of: Másolata + create: Hozzon létre + dash_case_incident_overview: Eseteim / incidenseim + dash_cases_by_social_worker: Szociális munkás által végzett 'Esetek' megtekintése + dash_cases_by_task_overdue: Ügyek megtekintése 'Túl késedelmes feladat' szerint + dash_cases_by_workflow: Esetek megtekintése munkafolyamatok szerint + dash_cases_to_assign: Hozzárendelendő esetek megtekintése dash_manager_transfers: Kezelői átvitelek megtekintése + dash_matching_results: Találatok megtekintése + dash_protection_concerns: Védelmi aggályok megtekintése + dash_protection_concerns_by_location: Védelmi aggályok megtekintése "Helyszín" szerint + dash_referrals_by_socal_worker: Szociális munkás által végzett Ajánlások megtekintése + dash_reporting_location: Jelentési helyszínek megtekintése + dash_service_provisions: Szolgáltatási rendelkezések megtekintése + dash_shared_with_me: Megosztva velem + dash_shared_with_my_team: Megosztva a csapatommal + dash_shared_with_others: Másokkal megosztva + dash_show_none_values: '''Nincsenek értékek'' megtekintése' + dash_tasks: Feladatok megtekintése dash_transfers_by_socal_worker: A szociális munkás által végzett átvitelek megtekintése + dash_national_admin_summary: Rendszergazdai összefoglaló + dashboard: Irányítópult + display_view_page: '''Oldal megtekintése'' kijelző' + duplicate: Duplikált 'Keresés' + enable_disable_record: Letiltás + export_csv: CSV exportálása + export_custom: Egyéni exportálás + export_duplicate_id_csv: Másolatok exportálása + export_json: Json exportálása + export_list_view_csv: Listanézet csv exportálása + export_mrm_violation_xls: '''mrm jogsértés'' xls exportálása' + export_pdf: PDF exportálása + export_photowall: Fotófal exportálása + export_unhcr_csv: Unhcr csv exportálása + export_xls: xls exportálása + find_tracing_match: Nyomkövetési egyezés keresése az esetből + view_registry_record: Nyilvántartási bejegyzés megtekintése + add_registry_record: Nyilvántartási bejegyzés hozzáadása + flag: Megjelölni + form: Nyomtatványok + group: Hozzáférés a csoportom összes bejegyzéséhez vagy felhasználójához + group_read: Csoport 'Olvasás' + import: Import + incident: Incidens + incident_details_from_case: Incidens részletek hozzáadása egy másik felhasználó ügyéhez + incident_from_case: Incidens létrehozása egy esetből + lookup: Keresések + manage: Kezelje + mark_for_offline: '"Offline" jelölés' + matching_configuration: Egyező konfiguráció + metadata: Nyomtatványok, keresések + potential_match: Potenciális egyezés + primero_configuration: Konfiguráció + read: Olvassa el + reassign: Újra kijelölni + receive_referral: Referencia fogadása receive_transfer: Átvitel fogadása + referral: Ajánlásra használható + registry_record: Nyilvántartás + remove_assigned_users: Más hozzárendelt felhasználók eltávolítása (ajánlások) + reopen: Újranyitni + report: Jelentés + managed_report: Betekintések + request_approval: Jóváhagyás iránti kérelem + request_approval_action_plan: Jóváhagyás iránti %{approval_label}kérelem + request_approval_assessment: Jóváhagyás iránti %{approval_label}kérelem + request_approval_case_plan: Jóváhagyás iránti %{approval_label}kérelem + request_approval_closure: Jóváhagyás iránti %{approval_label}kérelem + request_approval_gbv_closure: Jóváhagyás iránti %{approval_label}kérelem request_transfer: Átvitel kérvényezése role: Szerepkörök + save_search: Keresések mentése + saved_search: Elmentett keresés + search_owned_by_others: Más felhasználók által birtokolt ügyiratok keresése + self: Csak a saját bejegyzéseimhez vagy felhasználóimhoz való hozzáférés + service_provision_incident_details: Lásd a Szolgáltatásnyújtás hozzáadása gombot az Incidens részletek modulon. + services_section_from_case: Szolgáltatásnyújtás hozzáadása egy másik felhasználó esetéhez specific_roles: Hozzáférés a szerepkörök meghatározott listájához + sync_external: Szinkronizálás külső információkezelő rendszerrel + sync_mobile: '"Offline" jelölés' + system: Rendszer + tracing_request: Nyomkövetési kérelem transfer: Átvitelre használható + user: Felhasználók user_group: Felhasználói csoportok + view_approvals: Engedélyek megtekintése + view_assessment: Értékelés megtekintése + view_photo: Fénykép megtekintése + view_protection_concerns_filter: Védelmi aggályok szűrőjének megtekintése + view_response: Válaszok megtekintése + workflow: Munkafolyamat - Egyéni esetek + workflow_team: Munkafolyamat - Csapatok esetei + write: Írjon + activity_log: Tevékenység Napló resource: + kpi: + actions: + kpi_assessment_status: + explanation: Lehetőség annak megtekintésére, hogy a felhasználó által hozzáférhető aktív ügyek milyen arányban rendelkeznek kitöltött értékelő űrlappal. + kpi_case_load: + label: Ügyszám + kpi_completed_case_action_plans: + label: Befejezett Eseti cselekvési tervek + kpi_completed_supervisor_approved_case_action_plans: + label: A felügyelő által jóváhagyott, befejezett cselekvési terv + kpi_number_of_cases: + label: Esetek száma + kpi_number_of_incidents: + label: Incidensek száma + label: KPI + agency: + actions: + create: + explanation: Ügynökség létrehozásának lehetősége. + label: Hozzon létre + manage: + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) + read: + explanation: Lehetőség az ügynökségek megtekintésére. + label: Megtekintés + write: + explanation: Lehetőség az ügynökségekre vonatkozó információk szerkesztésére. Felhívjuk figyelmét, hogy ez a rendszerben lévő összes ügynökségre vonatkozik. + label: Szerkesztés + explanation: Olyan szervezetet képvisel, amelynek tagjai a Primero-t használják. Az ügynökségek a felhasználói csoportoktól függetlenül léteznek. + label: Ügynökség + audit_log: + actions: + read: + label: Megtekintés + explanation: A rendszerben végrehajtott összes művelet szűrhető listája. Nem tartalmaz semmilyen azonosítható információt az Ügyekről, Eseményekről vagy Nyomonkövetési kérelmekről. + label: Ellenőrzési napló case: actions: + add_registry_record: + explanation: Lehetővé teszi a felhasználó számára, hogy a nyilvántartás adatait tartalmazó űrlapon keresztül összekapcsoljon egy nyilvántartást egy esettel. Lehetővé teszi továbbá, hogy a felhasználó visszavonja az Ügyhöz már hozzákapcsolt nyilvántartás összekapcsolását. + label: Nyilvántartási rekord hozzáadása/frissítése az Ügyiratból + approve_action_plan: + explanation: Lehetővé teszi a menedzser számára, hogy jóváhagyja a %{approval_label}az ügyintézők eseteit. + label: Jóváhagyás%{approval_label} + approve_assessment: + explanation: Lehetővé teszi a menedzser számára, hogy jóváhagyja a %{approval_label}az ügyintézők eseteit. + label: '%{approval_label}Nyomtatvány jóváhagyása' + approve_bia: + explanation: Lehetővé teszi a menedzser számára, hogy jóváhagyja a %{approval_label}az ügyintézők eseteit. + label: '%{approval_label}Nyomtatvány jóváhagyása' + approve_case_plan: + explanation: Lehetővé teszi a menedzser számára, hogy jóváhagyja a %{approval_label}az ügyintézők eseteit. + label: Jóváhagyás%{approval_label} + approve_closure: + label: '%{approval_label}Nyomtatvány jóváhagyása' + approve_gbv_closure: + explanation: Lehetővé teszi a menedzser számára, hogy jóváhagyja a %{approval_label}az ügyintézők eseteit. + label: '%{approval_label}Nyomtatvány jóváhagyása' assign: explanation: Megengedi a felhasználót, hogy elküldje az esetet az eredeti rekordtulajdonostól a rendszer bármely más felhasználójának. Ehhez nem szükséges a gyermek hozzájárulása. Az átvitelekkel ellentétben, a címzettnek nincs lehetősége elfogadni vagy elutasítani a megbízást. assign_within_agency: explanation: Megengedi a felhasználót, hogy elküldje az esetet az eredeti rekordtulajdonostól a ügynökség bármely más felhasználójának. Ehhez nem szükséges a gyermek hozzájárulása. Az átvitelekkel ellentétben, a címzettnek nincs lehetősége elfogadni vagy elutasítani a megbízást. assign_within_user_group: explanation: Megengedi a felhasználót, hogy elküldje az esetet az eredeti rekordtulajdonostól az aktuális felhasználói csoportok bármely más felhasználójának. Ehhez nem szükséges a gyermek hozzájárulása. Az átvitelekkel ellentétben, a címzettnek nincs lehetősége elfogadni vagy elutasítani a megbízást. + label: Hozzárendelés a saját felhasználói csoportomban lévő felhasználóhoz + change_log: + explanation: A felhasználó láthatja a bejegyzés létrehozásától kezdve a rajta végrehajtott összes változtatás előzményeit. consent_override: explanation: Megengedi a felhasználót, hogy beutalást vagy átvitelt hajtson végre olyan ügyben, amelyhez nem adtak hozzájárulást. label: A hozzájárulás hiányának felülbírálása utaláskor vagy átvitelkor + create: + explanation: Eset létrehozásának lehetősége + label: Hozzon létre + enable_disable_record: + label: Engedélyezés / Tiltás + export_csv: + label: CSV exportálása + export_custom: + label: Egyéni exportálás + export_duplicate_id_csv: + label: Másolatok exportálása + export_json: + label: JSON exportálása + export_list_view_csv: + label: Listanézet csv exportálása + export_photowall: + label: Fotófal exportálása + export_unhcr_csv: + label: UNHCR CSV exportálása + export_xls: + label: Excel (XLS fájl) exportálása + find_tracing_match: + label: Nyomkövetési egyezés keresése az esetből + import: + label: Import + incident_details_from_case: + label: Esemény részleteinek hozzáadása egy másik felhasználó esetéhez a keresési eredmények oldaláról + incident_from_case: + explanation: Ez az engedély lehetővé teszi a felhasználó számára, hogy az "Incidens létrehozása" gombra kattintson. Ez egy incidenst generál, amely tartalmazhat néhány, az ügyből átmásolt információt. A GBV-ügyek esetében ez a gomb az ügyet megjelenítő oldal tetején található, és az ügy egészére vonatkozó információknak felel meg. Egyes incidenskövető kontextusokban ez a gomb az "Incidens részletei" alűrlapon található. Ebben a helyzetben bizonyos információk átmásolhatók az incidens részleteit tartalmazó alűrlapról, ahol a gombra kattintottak, valamint az eset egészéből. Vagyis a létrehozott új incidens tartalmazhatja az "Erőszak típusa" mezőt az egyedi incidens részleteit tartalmazó alűrlapról, de tartalmazhatja magának az esetnek a korát és nemét is. Megjegyzendő, hogy ez a jogosultság lehetővé teszi a felhasználó számára a létrehozott incidensre mutató link megtekintését is. + label: Incidens létrehozása egy esetből + manage: + explanation: Lehetővé teszi a felhasználó számára, hogy az összes rendelkezésre álló műveletet elvégezze az ügyeken. A "Kezelés" engedély lényegében "mindent" jelent. + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) + read: + explanation: Az ügy megtekintésének képessége + label: Megtekintés + receive_referral: + label: Referencia fogadása receive_transfer: explanation: Megengedi a felhasználót hogy elfogadja az átvitelet. Az ezzel az engedéllyel rendelkező felhasználók az átviteli művelet lehetséges címzettjeként jelennek meg, míg az ezzel az engedéllyel nem rendelkező felhasználók nem jelennek meg potenciális címzettként, amikor valaki az átviteli módban címzettet keres. label: Átvitel fogadása + referral: + explanation: Lehetővé teszi a felhasználó számára, hogy ideiglenesen hozzáférést adjon egy ügyhöz egy másik felhasználónak. Az átirányítás címzettje ugyanazokat a műveleteket végezheti el az átirányított ügyön, mint a saját ügyein. Amikor a címzettnek már nincs szüksége az ügyhöz való hozzáférésre, az "Átirányítások és átadások" alűrlapon a "Kész" gombra kattintva elveszíti az ügyhöz való hozzáférést. Ügyet csak olyan felhasználónak lehet átirányítani, akinek a szerepkörében lehetőség van átirányítások fogadására. + label: Ajánlás + reopen: + explanation: Lehetővé teszi a felhasználó számára, hogy megnyisson egy jelenleg lezárt ügyet. + request_approval_action_plan: + label: Jóváhagyás iránti %{approval_label}kérelem + request_approval_assessment: + label: Jóváhagyás iránti %{approval_label}kérelem + request_approval_bia: + label: Jóváhagyás iránti %{approval_label}kérelem + request_approval_case_plan: + explanation: Lehetővé teszi a felhasználó (általában az ügyintéző) számára, hogy kérje, hogy a vezetője hagyja jóvá az ügyet%{approval_label} + label: Jóváhagyás iránti %{approval_label}kérelem + request_approval_closure: + explanation: Lehetővé teszi a felhasználó (általában az ügyintéző) számára, hogy kérje, hogy a vezetője hagyja jóvá az ügyet%{approval_label} + label: Jóváhagyás iránti %{approval_label}kérelem + request_approval_gbv_closure: + label: Jóváhagyás iránti %{approval_label}kérelem request_transfer: explanation: Megjeleníti az „Átvitel kérése” gombot a „Modális megtekintés” menüben. A gomb segítségével a felhasználó személyre szabott megjegyzéssel üzenetet küldhet e-mailben az ügy aktuális irattulajdonosának, arra kérve, hogy az irattulajdonos adja át az ügyet a kérelmet küldő felhasználónak. Ez olyan helyzetekben hasznos, amikor a gyerekek gyakran változtatják a helyszínt, és a szociális munkásoknak szükségük van a gyermek korábbi ügyvezetőjére, hogy információkat küldjenek a gyermekről, hogy elkerüljék az ismétlődő rekordok létrehozását. label: Átvitel kérvényezése + search_owned_by_others: + label: Más felhasználók által birtokolt ügyiratok keresése + service_provision_incident_details: + explanation: Lehetővé teszi a felhasználó számára, hogy az Esemény hozzáadása modal alján megjelenjen a "Mentés és szolgáltatásnyújtás hozzáadása" feliratú gomb. Erre a gombra kattintva a felhasználó elmenti az incidenssel kapcsolatban jelenleg megadott információkat, és közvetlenül a Szolgáltatás hozzáadása modalra lép. Mivel ez a művelet közvetlenül kapcsolódik az Esemény hozzáadása és a Szolgáltatásnyújtás hozzáadása műveletekhez, csak akkor van értelme ezt a jogosultságot megadni egy szerepkörnek, ha az adott szerepkör rendelkezik az "Eseményadatok hozzáadása egy másik felhasználó ügyéhez" és a "Szolgáltatásnyújtás hozzáadása egy másik felhasználó ügyéhez" jogosultságokkal is. + label: Lásd a Szolgáltatásnyújtás hozzáadása gombot az Incidens részletek modulon. + sync_mobile: + label: '"Offline" jelölés' transfer: label: Adatátvitel + view_photo: + label: Fénykép megtekintése az esetlista nézetéből + view_incident_from_case: + label: '''Események'' megtekintése az ''Ügy'' menüpontból' + view_registry_record: + explanation: Lehetővé teszi a felhasználó számára, hogy megtekintse az Ügyhöz kapcsolódó bármely nyilvántartás adatait. Lehetővé teszi továbbá a felhasználó számára, hogy megnézze az Ügy nyilvántartási adatlapját. + label: A nyilvántartási rekord megtekintése az Ügyiratból + mark_for_offline: + explanation: Lehetővé teszi a felhasználó számára az "Ügy" gyorsítótárba helyezését offline használatra. + label: '"Offline" jelölés' + explanation: Egyéni gyermeket, túlélő hozzátartozót vagy más kedvezményezettet képvisel. + label: Eset + dashboard: + actions: + approvals_action_plan: + label: Az ügyintéző %{approval_label} jóváhagyásai + approvals_action_plan_pending: + label: '%{approval_label}Menedzseri jóváhagyások' + approvals_assessment: + label: Az ügyintéző %{approval_label} jóváhagyásai + approvals_assessment_pending: + label: '%{approval_label}Menedzseri jóváhagyások' + approvals_case_plan: + explanation: Megmutatja az aktuális felhasználó "Esetterv" jóváhagyási kérelmekkel rendelkező ügyeinek számát, amelyek Függőben, Jóváhagyva vagy Elutasítva vannak. + approvals_case_plan_pending: + label: '%{approval_label}Menedzseri jóváhagyások' + approvals_closure: + explanation: Megmutatja az aktuális felhasználó "Lezárási jóváhagyási kérelemmel" rendelkező ügyeinek számát, amelyek Függőben, Jóváhagyva vagy Elutasítva vannak. + label: Az ügyintéző %{approval_label} jóváhagyásai + approvals_closure_pending: + label: '%{approval_label}Menedzseri jóváhagyások' + approvals_gbv_closure: + explanation: Megmutatja az aktuális felhasználó azon ügyeinek számát, amelyekben a GBV lezárási jóváhagyási kérelmek függőben, jóváhagyva vagy elutasítva vannak. + label: Az ügyintéző %{approval_label} jóváhagyásai + approvals_gbv_closure_pending: + label: '%{approval_label}Menedzseri jóváhagyások' + case_overview: + explanation: A kezdőlap tetején található áttekintő műszerfal-kártya, amely olyan számadatokat tartalmaz, mint az "Összes" és az "Új esetek". + case_risk: + explanation: Megmutatja, mennyi eset tartozik az egyes kockázati szintekhez. + label: Esetek kockázati szintek szerint + cases_by_task_overdue_services: + explanation: Lehetővé teszi a menedzser számára, hogy lássa, hány esetben van lejárt Szolgáltatási feladat az egyes esetkezelői számára. + dash_case_incident_overview: + label: Áttekintés - Eseteim / incidenseim + dash_cases_to_assign: + label: (Menedzsereknek) Esetek, amelyeket a csapatomban dolgozóknak kell kiosztanom + dash_flags: + explanation: Megjeleníti azoknak a zászlóknak a listáját, amelyeket más felhasználók adtak hozzá a bejegyzéseimhez, valamint azoknak a zászlóknak a listáját, amelyeket én adtam hozzá más felhasználók bejegyzéseihez. + label: Megjelölt bejegyzések + dash_group_overview: + label: A csoportom esetei + dash_matching_results: + explanation: MEGSZÜNTETVE. Ez a műszerfal nem funkcionális, és a v2-ben eltávolításra kerül. + label: Találatok megtekintése + dash_protection_concerns: + label: Védelmi aggályok szerinti esetek + dash_shared_from_my_team: + explanation: Megmutatja a menedzsereknek, hogy csapatuk egyes felhasználói hány olyan ügyet kezelnek, amelyeket más felhasználóknak továbbítanak vagy átadnak. + dash_shared_with_me: + label: Megosztva velem + dash_shared_with_my_team: + label: Megosztva a csapatommal + dash_shared_with_others: + label: Másokkal megosztva + dash_tasks: + label: Feladatok oldala + dash_national_admin_summary: + label: Rendszergazdai összefoglaló + view_response: + label: Válaszok megtekintése + workflow: + explanation: Lehetővé teszi az ügyintéző számára, hogy egy kördiagramon lássa, hány ügye van az ügykezelési munkafolyamat egyes szakaszaiban. + explanation: Meghatározza, milyen összefoglaló információk jelenjenek meg a kezdőlapon. + label: Irányítópult + disabled: + explanation: Ha letiltja ezt a szerepet, többé nem tudja hozzáadni a felhasználói fiókokhoz. + label: Letiltva + duplicate: + actions: + read: + explanation: Lehetővé teszi a felhasználó számára, hogy a rendszerben lévő összes esetre kiterjedő keresést végezzen, számos kritérium, többek között a név, becenév, nem, életkor és állampolgárság alapján. + label: Megtekintés + explanation: Részletes ügykeresés az adminisztrátorok számára. + label: Duplikált 'Keresés' + forms: + case: + label: Nyomtatványok - Eset + incident: + label: Nyomtatványok - incidensek + registry_record: + explanation: 'A felhasználó hozzáférésének korlátozása a bejegyzések űrlapjaihoz behatárolja, hogy a felhasználó milyen információkat láthat a bejegyzésekben. Ha például a felhasználónak csak a Nyilvántartás-tulajdonos űrlaphoz van hozzáférése, akkor csak az ezen az űrlapon található mezőkben szereplő információkat láthatja. Ha az aktuális felhasználó korlátozott űrlap-hozzáféréssel rendelkezik, és képes kezelni az űrlapok konfigurációját, az űrlap-hozzáférés korlátozása azt is limitálja, hogy mely űrlapokat konfigurálhatja. MEGJEGYZÉS: Ha nincsenek űrlapok megadva, az azt jelenti, hogy a szerepkörnek hozzáférése van a nyilvántartások összes űrlapjához.' + label: Nyomtatványok - Nyilvántartás + group: + actions: + admin_only: + label: Nincsenek bejegyzések - Csak admin funkciók + agency: + label: Az ügynökségem összes bejegyzése vagy felhasználója + all: + label: Hozzáférés az összes bejegyzéshez vagy felhasználóhoz + group: + explanation: A szerepkör hozzáférhet a Felhasználói csoportok összes Felhasználója által kezelt bejegyzésekhez. Csak a saját felhasználói csoportjukban lévő felhasználókhoz férhetnek hozzá. Csak a saját felhasználói csoportjaikhoz férhetnek hozzá. + label: Hozzáférés a csoportom összes bejegyzéséhez vagy felhasználójához + self: + label: Csak a saját bejegyzéseimhez vagy felhasználóimhoz való hozzáférés + label: Milyen bejegyzéseket érint ez a szerepkör? + incident: + actions: + create: + explanation: Esemény létrehozásának képessége. + label: Hozzon létre + export_case_pdf: + label: PDF exportálása + export_custom: + label: Egyéni exportálás + export_json: + label: JSON exportálása + export_list_view_csv: + explanation: A felhasználó az incidenslista oldalról CSV fájl exportálást generálhat, amely ugyanazokat a mezőket tartalmazza, amelyek az adott felhasználó esetében az incidenslistán megjelennek. Csak az incidenslista oldalról végezhető el. + label: Listanézet csv exportálása + export_xls: + label: Excel (XLS fájl) exportálása + import: + label: Import + manage: + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) + read: + explanation: Lehetőség az incidens megtekintésére + label: Megtekintés + sync_mobile: + label: Szinkronizálás mobileszközzel + write: + label: Szerkesztés + explanation: Egy bekövetkezett eseményt képvisel. Ezek általában bántalmazási vagy erőszakos esetek, bár megfelelhetnek olyan eseményeknek is, mint például a bűnüldöző szervekkel való összetűzések. Az incidensek gyakran kapcsolódnak az Ügyekhez. + label: Incidens + is_manager: + explanation: Minden olyan felhasználói szerepkörre vonatkozik, amely általában más felhasználókat felügyel. Ez lehetővé teszi a felhasználó számára, hogy olyan műszerfalakat és szűrőket lásson, amelyek segítenek a felhasználónak a csapat irányításában. + label: Menedzser? + managed_report: + actions: + violations: + label: Szabálysértések + gbv_statistics: + label: GBV statisztikák + matching_configuration: + actions: + manage: + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) + explanation: Szabályozza, hogy a családok felkutatása és újraegyesítése során mely mezőket használják a Nyomkövetési kérelmek és az Ügyek összehasonlítására. + label: Egyező konfiguráció + metadata: + actions: + manage: + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) + explanation: A Primero űrlapok és mezők, valamint a bennük használt keresési opciók konfigurálásának lehetőségét vezérli. + label: Nyomtatványok, keresések + module: + actions: + cp: + label: CP + gbv: + label: GBV + mrm: + label: MRM + explanation: Szabályozza, mely modulokra vonatkozik ez a szerepkör + potential_match: + actions: + read: + label: Megtekintés + label: Potenciális egyezés + primero_configuration: + actions: + manage: + explanation: Konfigurációk mentésének, alkalmazásának és küldésének lehetősége. Ez a jogosultság általában a rendszergazdának van fenntartva. + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) + label: Konfiguráció + referral: + actions: + refer: + label: Használható-e ez a szerep külső Ajánlásokhoz? + label: Ajánlás + registry_record: + actions: + change_log: + explanation: A felhasználó láthatja a bejegyzés létrehozásától kezdve a rajta végrehajtott összes változtatás előzményeit. + label: Változási napló + create: + explanation: Képes nyilvántartási bejegyzés létrehozására. + label: Hozzon létre + enable_disable_record: + explanation: Lehetőség a nyilvántartási bejegyzések letiltására vagy engedélyezésére. A "letiltott" bejegyzések alapértelmezés szerint nem jelennek meg a nyilvántartási listában. A felhasználók egy szűrő használatával láthatják a letiltott " Nyilvántartási bejegyzéseket" a "Nyilvántartási listában". + label: Engedélyezés / Tiltás + export_csv: + explanation: 'A felhasználó a Nyilvántartási lista vagy a Nyilvántartás megjelenítése oldalakról CSV fájl exportálást hozhat létre, amely tartalmazza az összes olyan mezőt, amelyhez az aktuális felhasználónak hozzáférése van, egy, több vagy az összes olyan nyilvántartási bejegyzéshez, amelyhez a felhasználónak hozzáférése van. MEGJEGYZÉS: A CSV export nem jeleníti meg a nem latin betűket (pl. arab, bangla).' + label: CSV exportálása + export_json: + explanation: A felhasználó létrehozhat egy JSON fájl exportot a Nyilvántartási lista vagy a Nyilvántartás megjelenítése oldalakról, amely tartalmazza az összes olyan mezőt, amelyhez az aktuális felhasználónak hozzáférése van. A JSON formátum gépileg olvasható, és a legtöbb felhasználó számára nem praktikus. + label: JSON exportálása + export_xls: + explanation: 'A felhasználó a Nyilvántartási lista vagy a Nyilvántartás megjelenítése oldalakról XLS fájl exportálást készíthet, amely tartalmazza az összes olyan mezőt, amelyhez az aktuális felhasználónak hozzáférése van. MEGJEGYZÉS: Az XLS formátum a nem latin betűket (pl. arab, bangla) olvasható formában adja vissza, míg a CSV export nem.' + label: Excel (XLS fájl) exportálása + flag: + explanation: Lehetőség a nyilvántartási bejegyzések megjelölésének hozzáadására. Az ezzel a jogosultsággal rendelkező felhasználók eltávolíthatják az általuk a nyilvántartási bejegyzésekhez hozzáadott jelöléseket is. + label: Megjelölni + manage: + explanation: Lehetővé teszi a felhasználó számára, hogy a nyilvántartási bejegyzéseken az összes rendelkezésre álló műveletet elvégezze. A "Kezelés" engedély lényegében "mindent" jelent. + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) + read: + explanation: A "Nyilvántartási bejegyzések" megtekintése + label: Megtekintés + write: + explanation: Lehetővé teszi a "Szerkesztés" gombra való kattintást, a nyilvántartási bejegyzésre vonatkozó információk frissítését és a "Mentés" gombra való kattintást. + label: Szerkesztés + sync_mobile: + explanation: Lehetővé teszi a felhasználó számára, hogy a nyilvántartási bejegyzéseket offline használatra gyorsítótárba helyezze. + label: '"Offline" jelölés' + explanation: Ez egy személyt vagy intézményt képviselhet, amelyet más nyilvántartásokkal, például esetekkel vagy eseményekkel kell összekapcsolni, amelyek igen nagy számban léteznek, és amelyeket folyamatosan új információkkal frissítenek. Hasonlóak a keresésekhez, de minden egyes bejegyzéshez összetettebb információkészletet tartalmaznak. + label: Nyilvántartási bejegyzés + report: + actions: + create: + label: Hozzon létre + group_read: + explanation: Lehetőség az összes jelentés megtekintésére. Az egyes jelentésekben szereplő számok csak azokat a rekordokat tükrözik, amelyek az aktuális felhasználó felhasználói csoportjába tartozó felhasználók számára elérhetőek. Ezt a jogosultságot gyakran használják helyi, regionális vagy ügynökségi adminisztrátorok, akik betekintést szeretnének nyerni saját csapatuk vagy szervezetük teljesítményébe. Ez a jogosultság lehetőséget ad a felhasználónak arra is, hogy a jelentésből adatokat exportáljon. + label: Nézet (csoportalapú adatok) + manage: + explanation: Lehetővé teszi a felhasználó számára, hogy az "Ügynökségek" összes rendelkezésre álló műveletét elvégezze. A "Kezelés" engedély lényegében "mindent" jelent. + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) + read: + label: Megtekintés + write: + explanation: Lehetőség az összes jelentés szerkesztésére (beleértve a más felhasználók által létrehozott jelentéseket is). + explanation: 'Összesített adatelemző eszköz. Tartalmazza az adatok táblázatos és grafikus megjelenítését. ' + label: Jelentés + reporting_location_level: + label: Milyen helyszíntípust kell használni a jelentéskészítéshez ebben a szerepkörben? role: + actions: + copy: + label: Másolás + create: + explanation: Szerepkör létrehozásának lehetősége + label: Hozzon létre + delete: + explanation: Szerepkörök törlésének lehetősége. + label: Törölni + manage: + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) + permitted_roles: + label: A szerepkör által kezelt egyéb feladatok + read: + explanation: Lehetőség a szerepek megtekintésére + label: Megtekintés + write: + explanation: Lehetőség a "Szerkesztés" gombra kattintani a szerepek megjelenítése oldalon, frissíteni a szerep jogosultságait, majd elmenteni a szerepet. + label: Szerkesztés + explanation: Meghatározza, hogy a Felhasználó milyen műveleteket hajthat végre a Primero rendszerben. label: Szerepkörök system: actions: manage: explanation: Megtekintheti és frissítheti a rendszer kapcsolati adatait, az alapértelmezett értesítési és üdvözlő e-mail beállításokat, valamint a szinkronizált szervereket.. Ez az engedély általában a rendszergazdának van fenntartva + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) + explanation: Különféle rendszerszintű konfigurációs beállítások. + label: Rendszer + tracing_request: + actions: + change_log: + explanation: A felhasználó láthatja a bejegyzés létrehozásától kezdve a rajta végrehajtott összes változtatás előzményeit. + label: Változási napló + create: + explanation: Nyomkövetési kérelem létrehozásának képessége + label: Hozzon létre + enable_disable_record: + label: Engedélyezés / Tiltás + export_case_pdf: + label: PDF exportálása + export_csv: + label: CSV exportálása + export_custom: + label: Egyéni exportálás + export_json: + label: JSON exportálása + export_list_view_csv: + label: Listanézet csv exportálása + export_pdf: + label: PDF exportálása + export_xls: + label: Excel (XLS fájl) exportálása + import: + label: Import + manage: + explanation: Lehetővé teszi a felhasználó számára, hogy a nyomonkövetési kérelmekkel kapcsolatos összes rendelkezésre álló műveletet elvégezze. A "Kezelés" engedély lényegében "mindent" jelent. + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) + read: + label: Megtekintés + write: + label: Szerkesztés + explanation: Olyan személyt képvisel, aki megpróbálja felkutatni és újraegyesíteni kísérő nélküli vagy különélő "ügyét". + label: Nyomkövetési kérelem transfer: + actions: + transfer: + explanation: Ez azt jelenti, hogy a szerepkör a "Címzett típusa" opcióként jelenik meg, amikor a felhasználó külső átirányítást végez. Ha a felhasználó ezt a szerepet választja az átutalás típusaként, akkor a Primero által az átutalás benyújtásakor generált export csak azokat az információkat fogja tartalmazni, amelyek az adott szerepkör által használt űrlapokon találhatók. Így például, ha a felhasználó az "Orvosi szolgáltató" opciót választja a címzett típusaként, és az Orvosi szolgáltató szerepkör csak az Alapvető személyazonosság és a Védelmi aggályok űrlapokhoz rendelkezik hozzáféréssel, a Primero által a külső átutaláshoz exportált exportfájl csak azokat a mezőket fogja tartalmazni, amelyek ebben a két űrlapban szerepelnek. + label: Használható-e ez a szerep külső átutalásokra? label: Adatátvitel user: actions: + agency_read: + label: Nézet (ügynökségen belül) + create: + explanation: Felhasználói fiók létrehozásának lehetősége. + label: Hozzon létre + manage: + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) read: explanation: Lehetőség a felhasználói fiókok megtekintésére. Alapértelmezés szerint minden felhasználó megtekintheti és szerkesztheti a saját felhasználói fiókjával kapcsolatos információkat (pl. jelszó, e-mail). + label: Megtekintés + write: + explanation: Lehetőség a "felhasználó megjelenítése" oldalon a "Szerkesztés" gombra kattintani, frissíteni a felhasználóra vonatkozó információkat, majd elmenteni őket. Felhívjuk figyelmét, hogy ez a jogosultság a felhasználói fiókok letiltására is lehetőséget ad. + label: Szerkesztés + explanation: Egyedi felhasználói fiókot képvisel. + label: Felhasználók user_group: + actions: + assign: + label: Illetékes személy + create: + explanation: Felhasználói csoport létrehozásának lehetősége. + label: Hozzon létre + delete: + explanation: Felhasználói csoport törlésének lehetősége. + label: Törölni + manage: + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) + read: + explanation: A felhasználói csoportok megtekintésének lehetősége. + label: Megtekintés + write: + explanation: Felhasználói csoportok szerkesztésének lehetősége. + label: Szerkesztés + explanation: Egy csapatot vagy olyan felhasználók együttműködő csoportját jelképezi, akik információt oszthatnak meg egymással. A menedzserek általában a "felhasználói csoportjukban" lévő szociális munkások által kezelt összes bejegyzést láthatják. label: Felhasználói csoportok + webhook: + actions: + read: + label: Megtekintés + write: + label: Szerkesztés + create: + label: Hozzon létre + delete: + label: Törölni + manage: + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) activity_log: actions: transfer: label: Adatátvitelek + manage: + label: Kezelés (az adott erőforrástípus teljes körű engedélyezése) + potential_match: + case_id: Ügy azonosítója + child_age: Életkor + child_gender: Nem + child_id: gyermek azonosítószáma + inquirer_id: kérdező azonosítószáma + inquirer_tr_name: Nyomkövetési kérelem + inquiry_date: A vizsgálat időpontja + name: Név + score: Pontszám + social_worker: Szociális munkás + social_worker_agency: Ügynökség + trace: Nyomkövetés + likelihood_likely: Valószínűleg + likelihood_possible: Lehetséges + potential_matches: + display: Potenciális találatok megjelenítése a%{type}%{id} reassign: + multiple_error: Hibát észleltünk. %{select_records}nem rendelt eset(ek). + notes_label: Jegyzetek + successfully: Sikeresen átcsoportosítva user_mandatory_label: A címzett megadása kötelező users_label: Címzett + record_information: + created_at: A bejegyzés létrejötte + created_by: A bejegyzést létrehozta + created_organization: Ügynökség által létrehozott + current_owner_separator: Jelenlegi tulajdonos + module_id: Modul + owned_by: Ügyintéző kódja + owned_by_agency_id: Ügynökség + owned_by_text: Terep/Eset/Szociális Munkás + previously_owned_by: Előző tulajdonos + previously_owned_by_agency: Előző ügynökség + reassigned_tranferred_on: Áthelyezés / átcsoportosítás + record_history_separator: Rekordtörténet + last_updated_at: Utoljára frissítve + last_updated_by: 'Utolsó frissítés:' + record_panel: + record_information: Információk felvétele referral: type_of_recipient: Címzett típusa + type_of_referral_required: '"Beutalás típusa" szükséges' + agency_label: Ügynökség + is_remote_label: Távoli rendszerre utal? + location_label: Helyszín + notes_label: Jegyzetek provided_consent_label: ' A hozzájárulás nincs megadva az űrlapokon.' recipient_label: Címzett + refer_anyway_label: Egyébként is ajánlja? + service_label: Szolgáltatás + success: '%{record_type}%{id}sikeresen átirányított' user_mandatory_label: A címzett megadása kötelező + date: Dátum + rejected_reason: Elutasítás oka + report: + aggregate_by: Csoportosítás soronként + constraint: Korlátozás + date_ranges: + date: Nap + month: Hónap + quarter: Negyedév + quarter_abbr: Q%{quarter} + week: Hét + year: Év + description: Leírás + disabled: + explanation: Ha letiltja ezt a jelentést, az nem jelenik meg a rendelkezésre álló jelentések között. + label: Letiltva + exclude_empty_rows: Ne jelenítsen meg üres sorokat + disaggregate_by: Group by column + filters: + label: Jelentés szűrők + label_new: Új jelentésszűrő + attribute: Szűrő + value: -val + not_null: Nem üres? + less_than: Kevesebb, mint + greater_than: Nagyobb, mint + equal_to: Egyenlő a + not_blank: Nem üres + before: Mielőtt + after: Miután + delete_filter_message: Biztos, hogy törölni szeretné ezt a szűrőt? + group_ages: Használjon korhatárokat + group_dates_by: Használjon különböző dátumtartományokat + is_graph: Grafikon generálása? + messages: + delete_success: A jelentést sikeresen töröltük. + updated: A jelentés sikeresen frissült. + modules: Modulok + name: Név + name_mandatory: A név kötelező + no_data: Ehhez a jelentéshez nem állnak rendelkezésre adatok + no_filters_added: Nincsenek hozzáadott szűrők + not_selected: Nincs kiválasztva + record_type: Felvétel típusa + total: Összesen + value: Érték + reports: + delete_report_message: Biztos, hogy törölni szeretné ezt a jelentést? A törlés nem vonható vissza. Kattintson az OK gombra a jelentés törléséhez + label: Jelentések + register_new_report: Jelentés létrehozása + translations: + edit: Fordítások szerkesztése + manage: Fordítások kezelése + select_language: Válasszon nyelvet + error_loading: Hiba a jelentés(ek) betöltése során request_transfer: + notes_label: Jegyzetek + submit_label: Kérelem küldése success: Átvitel kérvényezés küldése role: + agency_ids_label: A szerepkör által irányított ügynökségek + copy_failure: Hiba a Szerep másolásában. Győződjön meg róla, hogy a név nem ütközik egy másik Szerepkörrel. + copy_success: A szerepkör sikeresen másolva. + create: Szerepkör létrehozása + delete_header: Szerepkör törlése + description: Leírás + edit: '''Szerep'' szerkesztése' + error_in_updating: Hiba a 'Szerepkör adatainak' frissítésében. + group_permission_label: Milyen bejegyzéseket érint ez a szerepkör? label: Szerepkör + manager: Menedzser + messages: + confirmation: Biztos, hogy törölni szeretné ezt a szerepet? A törlés nem vonható vissza. Kattintson az OK gombra a szerepkör törléséhez. + created: A szerepkör sikeresen létrejött. + updated: A szerepkör sikeresen frissült. + name: Név + referral_label: Használható ez a szerepkör Ajánlásokhoz? + reporting_location_level_label: Milyen helyszíntípust kell használni a jelentéskészítéshez ebben a szerepkörben? + role_ids_label: A szerepkör által kezelt egyéb feladatok + successfully_updated: A szerepkör adatai sikeresen frissültek. transfer_label: Használható ez a szerep átigazolásokhoz? + hide: Rejtse el + read: Mutassa + read_write: Megjelenítés és szerkesztés roles: label: Szerepkörök + saved_search: + deleted: A keresés sikeresen törölve. + filters_tab: Szűrők + no_filters: Nincsenek kiválasztott szűrők + save_success: Keresés sikeresen elmentve. + saved_searches_tab: Elmentett keresések + title_description: Biztos, hogy törölni szeretné ezt a mentett keresést? + title_modal: Elmentett keresések törlése + saved_searches: + no_save_searches: Nincsenek elmentett keresései. + save_search: Keresés mentése settings: navigation: + agencies: Ügynökségek + configurations: Konfigurációk + contact_information: Kapcsolatfelvételi adatok + forms: Nyomtatványok + locations: Helyszínek + lookups: Keresések user_groups: Felhasználói csoportok + users: Felhasználók roles: Szerepkörök + title: Beállítások + system_settings: + label: Rendszerbeállítások task: + due_date: Esedékesség dátuma + id: Azonosítószám + name: Név + priorities: + low_level: Alacsony + medium_level: Közepes + no_action_level: Cselekmény Mentes + priority: Prioritás szint + status: Állapot statuses: overdue: Lejárt + upcoming_soon: Majdnem esedékes + type: Művelet típusa + types: + assessment: Értékelés + case_plan: Esetterv + follow_up: Folytatás - %{subtype} + service: Szolgáltatás - %{subtype} + tracing_request: + label: Nyomkövetési kérelem + find_match: Találj egyezést + traces: Nyomok + match: Találat + matches: Találatok + unmatch: Nem egyező + messages: + disabled: A Nyomkövetési kérelem le van tiltva + nothing_found: Semmit sem találtunk + update_success: 'A Nyomkövetési kérelem %{record_id}sikeresen frissült.' + creation_success: Nyomonkövetési kérelem bejegyzés sikeresen létrehozva. + update_success_queue: 'A nyomkövetési kérelem %{record_id}sikeresen frissült a háttérben.' + registry_record: + messages: + update_success: 'A nyilvántartási bejegyzés %{record_id}sikeresen frissült.' + creation_success: 'Regisztrációs bejegyzés sikeresen létrehozva.' + disabled: A nyilvántartási bejegyzés le van tiltva + tracing_requests: + disable_dialog: Az OK gombra kattintva a nyomkövetési kérelem állapota Letiltottra változik. + disable_success: Sikeresen letiltotta a nyomkövetési kérelmet + enable_dialog: Az OK gombra kattintva a nyomkövetési kérelem állapota Engedélyezve állapotra változik. + enable_success: Sikeresen engedélyezte a nyomkövetési kérelmet. + id: Azonosító + filter_by: + by_date: Dátummal + location_separation: Elkülönítés helye + separation_cause: Elválasztás oka + status: Állapot + label: Nyomkövetési kérelmek + name_of_inquirer: A kérelmező neve + register_new_tracing_request: Új nyomonkövetési kérelem + selectable_date_options: + inquiry_date: A vizsgálat időpontja + selected_records: '%{select_records}kiválasztott nyomkövetési kérelem(ek)' + selected_all_records: 'Válassza ki az összes %{total_records} nyomkövetési kérelmet, amely megfelel ennek a lekérdezésnek.' + show_tracing_request: 'Nyomkövetési kérelem azonosítója %{short_id}' + tracing_requests: Nyomkövetési kérelmek + export: Exportálás + registry_records: + id: Azonosító + label: Nyilvántartási bejegyzések + name: Név + registry_no: Nyilvántartási szám + location: Helyszín + registration_date: Regisztráció dátuma + selected_records: '%{select_records}kiválasztott nyilvántartási bejegyzés(ek)' + selected_all_records: 'Válassza ki az összes %{total_records} nyilvántartási bejegyzést, amely megfelel a lekérdezésnek.' + disable_dialog_title: Nyilvántartási bejegyzés letiltása + disable_dialog: Az OK gombra kattintva a nyilvántartási bejegyzés állapota "Letiltott"-ra változik. + disable_success: Sikeresen letiltotta a nyilvántartási bejegyzést + enable_dialog_title: Nyilvántartási bejegyzés engedélyezése + enable_dialog: Az OK gombra kattintva a nyilvántartási bejegyzés állapota "Engedélyezve" állapotra változik. + enable_success: Sikeresen engedélyezte a nyilvántartási bejegyzést. + filter_by: + by_date: Dátummal + status: Állapot + selectable_date_options: + registration_date: A regisztráció dátuma + show_registry_record: 'Nyilvántartási bejegyzés azonosítója: %{short_id}' + register_new_registry_record: Új nyilvántartási bejegyzés + export: Exportálás + mark_for_offline: + title: '"Offline" jelölés' + text: Biztos, hogy ezeket a nyilvántartási bejegyzéseket offline állapotban is használni kívánja? + success: Offline használatra sikeresen megjelölt nyilvántartási bejegyzések transfer: label: Adatátvitel + agency_label: Ügynökség consent_from_individual_label: Rendelkezik a személy hozzájárulásával az átvitelhez? consent_label: a nyilvántartások nem tükrözték a hozzájárulást. + consent_override_label: Szeretné felülbírálni ezt a beállítást? is_remote_label: Átvitel egy távoli rendszerre? + location_label: Helyszín + notes_label: Jegyzetek provided_consent_label: ' A hozzájárulás nincs megadva az űrlapokon.' recipient_label: Címzett + select_label: Válassza ki success: Az átvitel sikeres volt - transfer_label: Átvitelni mégis? + transfer_label: Egyébként is átutalja? user_mandatory: A címzett megadása kötelező + rejected_reason: Elutasított "Indok" transfer_assignment: title: Átvitelek és Kiosztások transition: + agency_label: Ügynökség + consent_individual_transfer_value: + true_label: 'Igen' + false_label: 'Nem' + consent_overridden_value: + false_label: 'Nem' + true_label: 'Igen' errors: consent: Hozzájárulás nincs megadva individual_consent: Az ügyet intéző dolgozó rendelkezik a személy hozzájárulásával az átvitelhez? no_consent_share: Hozzájárul a megosztási beállítás felülírásához? + notes: Jegyzetek recipient: Címzett + rejected: Elutasítás oka + requested_by: Kérte + service_label: Szolgáltatás + status: + accepted: Elfogadva + in_progress: Függőben + inprogress: Függőben + rejected: Elutasítva + revoked: Visszavont type: + assign: Hozzárendelés + reassign: Hozzárendelés + referral: Ajánlás + external_referral: Külső hivatkozás transfer: Adatátvitel transferRequest: Átvitelési kérvény user: + agency_office: Ügynökségi iroda (GBV terület) + code: Felhasználói kód + disabled: Letiltva email: E-mail + full_name: Teljes név + label: Felhasználó + language: Nyelv + locale: Helyszín + location: Helyszín messages: + confirmation: Biztos, hogy törölni szeretné ezt a felhasználót? A törlés nem vonható vissza. Kattintson az OK gombra a felhasználó törléséhez. + created: A felhasználó sikeresen létre lett hozva. + failure: Hiba történt, kérjük, forduljon az ügyfélszolgálathoz. new_confirm_html: Arra készül, hogy meghívja %{username} felhasználót, %{identity}tól (től), a következő szerepkörrel %{role}, a Primero használatára. A megerősítő e-mailt a %{email} címre lesz elküldve. Szeretné folytatni? new_confirm_non_identity_html: Arra készül, hogy meghívja %{username} felhasználót, a következő szerepkörrel %{role}, a Primero használatára. A megerősítő e-mailt a %{email} címre lesz elküldve. Szeretné folytatni? + not_found: A megadott azonosítóval rendelkező felhasználó nem található + password_changed_successfully: A jelszó sikeresen megváltozott + passwords_do_not_match: nem egyezik a jelenlegi jelszóval + time_zone_updated: A módosítás sikeresen frissült. + updated: '''Felhasználó'' sikeresen frissült.' + organization: Szervezet + agency: Ügynökség + services_help_text: Ha nem ad meg szolgáltatásokat, akkor ez a Felhasználó ugyanazokat a szolgáltatásokat kapja, mint az Ügynökség. password_setting: + label: Hogyan állítsa be a Primero a felhasználó jelszavát? + self: Megadom a jelszót user: A felhasználó az üdvözlő e-mailben állítja be a jelszót + help_text: Ne feledje, ha Ön, a rendszergazda kézzel állítja be a jelszót, akkor azt biztonságos módon kell megosztania a felhasználóval. password_reset_header: Jelszó-visszaállítási e-mail küldése password_reset_text: Ha a „Küldés” gombra kattint, ez a felhasználó egy e-mailt fog kapni a jelszava visszaállításához szükséges linkkel. password_reset_request: Jelszó-visszaállítási e-mail küldése + password: Jelszó + password_confirmation: Jelszó megerősítés + phone: Telefon + position: Pozíció + provider_username_help: 'Például: my.username@%{domain}' role_id: Szerepkör send_mail: Szeretne e-mail értesítéseket kapni? user_group_unique_ids: Felhasználói csoportok user_name: Felhasználónév + services: Szolgáltatások welcome_email: + subject: 'Üdvözöljük a %{system}!' + greeting: 'Üdvözöljük a %{system}!' body_native: 'Ön hozzá lett adva a %{role_name}. Kérjük, lépjen kapcsolatba a %{admin_full_name} (%{admin_email}) a további utasításokért a %{host}val való munka megkezdéséhez.' sso: footer: 'Kérjük, lépjen kapcsolatba a %{admin_full_name} (%{admin_email}) további részletekért.' otp: + body: 'Önt hozzáadták, mint%{role_name}' step1: 'Kérjük, lépjen kapcsolatba a %{admin_full_name} (%{admin_email}) hogy megkapja felhasználói nevét.' + step2: 'Menjen a %{host} és kattintson a "bejelentkezés a Primero felhasználónévvel." gombra.' + step4: 'Ha a rendszer kéri, állítsa vissza a jelszavát.' url_label: Primero enabled_label: Szeretne üdvözlő e-mailt küldeni? text_label: Üdvözlő e-mail szöveg password_reset: + subject: 'Jelszó-visszaállítási utasítások' + email_greeting: "Tisztelt %{full_name} " + email_body1: "Valaki kérte, hogy állítsa be a jelszavát a %{host_href}. Kattintson az alábbi url-re az indításhoz:" email_body2: "Ez a link lejár %{hours} belül, és csak egyszer használható. Kérjük, hagyja figyelmen kívül ezt az e-mailt, ha nem kért jelszó-visszaállítást, vagy ha nem regisztráltak új Primero-felhasználót az Ön nevében. Ha a fenti link lejárt, kattintson az %{reset_request_href}, a jelszó-visszaállítási kérelem újra küldéséhez." email_body_link: itt request_submitted: "Jelszó visszaállítási kérelem elküldve" @@ -890,12 +2645,17 @@ hu: reset_password_token: "Érvénytelen jelszó - visszaállítási token" password_confirmation: "A jelszavaknak egyezniük kell" onboard_email: + greeting: "Tisztelt %{full_name} ," body1: "Üdvözöljük a Primero-ban" body2_reset_notification: "További e-mailt fog kapni, amely felszólítja jelszava visszaállítására." user_group: + associated_agencies: A felhasználói csoporthoz kapcsolódó ügynökségek description: Leírás disabled: label: Letiltva + messages: + created: A felhasználói csoport sikeresen létrejött. + updated: A felhasználói csoportot sikeresen frissítettük. name: Név user_groups: label: Felhasználói csoportok @@ -909,4 +2669,10 @@ hu: devise: failure: already_authenticated: "Már bejelentkezett." + invalid: "Érvénytelen %{authentication_keys} vagy jelszó." locked: "Fiókja zárolva van." + last_attempt: "Még egy próbálkozása van, mielőtt a fiókját zárolják." + admin: + locations: + selected_records: '%{select_records}kiválasztott helyszín(ek)' + updated: '%{updated_records}frissített helyszín(ek)' diff --git a/config/locales/id.yml b/config/locales/id.yml index eb85bb5cb7..aa2196a3cc 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -4,7 +4,9 @@ id: accepted: Diterima cancel: Batal connection_lost: Saat ini menggunakan moda luring + field_mode_offline: Umur Perorangan connected: Terhubung + no_connection: Tak ada Koneksi clear: Hapus sandbox_ui: Demo description: Deskripsi @@ -12,17 +14,22 @@ id: minimum_reportable_fields: "Minimum kolom yang dapat dilaporkan %{record_type}" name: Nama offline: Luring + field_mode: "Field Mode: %{mode}" + field_mode_on: "On" + field_mode_off: "Off" unavailable_offline: Tidak tersedia luring online: Daring yes_label: 'Ya' - or_label: atau + or_label: atau, select_provider: Pilih penyedia select_language: Pilih bahasa - log_in_primero_idp: Masuk menggunakan nama pengguna %{idp_name} - offline_submitted_changes: Saat ini Anda di luar jaringan. Perubahan Anda akan terkirim setelah Anda dalam jaringan lagi. + log_in_primero_idp: Login dengan menggunakan nama pengguna %{idp_name} + offline_submitted_changes: Saat ini Anda sedang offline. Perubahan Anda akan terkirim setelah Anda online lagi. updated: Diperbaharui + go: Jalankan + select_idp_error: Pilih penyedia layanan sync: - success: "%{records}rekaman berhasil disesuaikan." + success: "%{records}rekaman berhasil diselaraskan." error: create: Gagal membuat %{record_type}. Silakan menghubungi kontak bantuan. update: Pembaharuan untuk %{record_type}%{short_id}gagal. Silakan menghubungi kontak bantuan. @@ -90,7 +97,7 @@ id: gbv_closure: Penghentian GBV status: approved: Disetujui - pending: Tertunda + pending: Ditunda rejected: Ditolak requested: Sudah diminta audit_log: @@ -150,7 +157,7 @@ id: filter_clear: Hapus Filter filter_label: 'Filter:' filter_restore: Kembalikan ke Pengaturan Sistem - find_tracing_match: Temukan Kecocokan Pelacakan + find_tracing_match: Temukan Kecocokan Data Penelusuran flag_model: Tandai %{model} flag_records: Penanda flags: Penanda @@ -180,7 +187,7 @@ id: select: Pilih send: Kirim sort_by_case: Kasus - sort_by_tr: Permintaan Pelacakan + sort_by_tr: Permintaan Penelusuran Keluarga sync: Penyelarasan submit: Kirim transfer: Pindahkan @@ -191,6 +198,15 @@ id: view: Lihat view_flags_history: Lihat Riwayat return_to_case: Kembali ke Kasus + resync_records: + id: ID + record_type: Jenis rekaman/catatan + action: Tindakan + date: Tanggal + last_attempt: Upaya Terakhir + create: Buat + update: Perbarui + resync: Kirim case: label: Kasus create_new_case: Buat Kasus Baru @@ -212,8 +228,8 @@ id: update_success_queue: 'Kasus %{record_id} berhasil diperbarui pada latar belakang.' creation_success: 'Data kasus berhasil dibuat.' creation_success_queue: 'Data kasus berhasil dibuat pada latar belakang.' - already_matched: Penyelidik ini sudah dicocokkan dengan kasus Anda. - already_matched_not_current_case: Sudah ada kasus di sistem yang cocok dengan penyelidik ini. + already_matched: Pemohon pencarian ini sudah dicocokkan dengan kasus Anda. + already_matched_not_current_case: Sudah ada kasus di sistem yang cocok dengan permohonan pencarian ini. not_found_case: Tidak ada Kasus yang cocok dengan "%{search_value}". Buat Kasus baru. introductory_sentence: Mohon jelaskan persetujuan individu untuk menerima layanan manajemen kasus dan persetujuan untuk penyimpanan data mereka di Primero. consent_agreements_required: Silakan memilih salah satu pilihan dari kesepakatan persetujuan. @@ -268,6 +284,7 @@ id: close_dialog_title: Kasus Ditutup close_success: Kasus berhasil ditutup closure: Dihentikan + complete: Tersedia luring date_of_birth: Tanggal lahir disable_dialog: Mengklik OK akan mengubah status kasus ini menjadi Dinonaktifkan disable_dialog_title: Kasus dinonaktifkan @@ -405,12 +422,12 @@ id: label: Ringkasan find_match: Temukan Kecocokan matched_trace: 'Cocok #%{trace_id}' - cannot_find_matches: Tidak menemukan kecocokan. Kasus ini tidak mendapatkan persetujuan untuk mengungkap informasi yang diperlukan untuk tujuan pelacakan. + cannot_find_matches: Tidak ditemukan kecocokan data. Informasi kasus ini tidak disetujui untuk dibuka untuk tujuan penelusuran. matched: Cocok. fields: consent_for_tracing: - label: Mendapatkan persetujuan untuk mengungkap informasi yang diperlukan untuk tujuan pelacakan. - help_text: Jika kolom ini diisi 'Tidak', data kasus anak tidak akan muncul pada 'Kecocokan' dengan Permintaan Pelacakan oleh Penyelidik. + label: Persetujuan telah diperoleh untuk mengungkap informasi yang diperlukan untuk tujuan penelusuran. + help_text: Jika kolom ini diisi 'Tidak', data kasus anak tidak akan muncul pada 'Pencocokan' dengan Permintaan Penelusuran oleh Pemohon. wishes_child_family_tracing: label: Apakah anak ingin melacak anggota keluarga? wishes_reunification: @@ -433,6 +450,7 @@ id: transfer_reject_reason_label: Alasan Penolakan transfer_rejected: Dengan menekan tombol 'Tolak' menunjukkan bahwa Anda belum siap untuk menerima tanggung jawab atas kasus ini saat ini. Mohon jelaskan alasan mengapa Anda menolak kasus ini; Setelah Anda menekan tombol 'Tolak' Anda tidak lagi memiliki akses ke data kasus ini. view_name: Tampilkan Nama + sort_by: Urutkan Berdasar change_logs: filters: form: Formulir @@ -597,6 +615,9 @@ id: dash_shared_with_my_team_overview: Bagikan dengan Team saya (Overview) dash_shared_with_others: Bagikan Dengan Yang Lain dash_national_admin_summary: Ringkasan Administrator + dash_violations_category_verification_status: Jumlah kejadian per status verifikasi + dash_violations_category_region: Total Jumlah kejadian terverifikasi per wilayah + dash_perpetrator_armed_force_group_party_names: Total Jumlah kejadian per pelaku date: Tanggal date_of_incident: Tanggal dari Insiden date_of_interview: Tanggal Wawancara @@ -705,7 +726,7 @@ id: total: Total total_cases: Total Jumlah Kasus total_referred: Total Rujukan - tr_stats: Permintaan Pelacakan + tr_stats: Permintaan Penelusuran transers_awaiting_acceptance: Pengalihan sedang Menunggu Persetujuan transfers_by_social_worker: Dialihkan oleh Pekerja Sosial users: tanda PENGATURAN @@ -773,7 +794,7 @@ id: date_of_birth: Silahkan masukkan tanggal lahir yang benar untuk data kasus ini export_configuration: opt_out_field_does_not_exist: Bidang opt_out yang ditentukan tidak ada pada catatan. - record_type: Jenis catatan tidak valid. Harus Kasus Anak, Permintaan Pelacakan, atau Insiden. + record_type: Jenis catatan tidak valid. Harus Kasus Anak, Permintaan Penelusuran, atau Insiden. field: translated_options_do_not_match: Pilihan-pilihan bidang harus memiliki ID yang sama location: @@ -1060,7 +1081,7 @@ id: english_text: Teks Bahasa Inggris field_name: Nama Kolom field_type: Tipe Kolom - attachment_too_large: Kolom tidak boleh lebih besar dari pada 10mb + attachment_too_large: File tidak boleh lebih dari 20mb file_upload_box: add_document_label: Tambah Dokumen add_new_document_button_text: Tambah dokumen lain @@ -1078,7 +1099,7 @@ id: guidance: Panduan guiding_questions: Pertanyaan Panduan help_text: Teks bantuan - hide_on_view_page: Tampilkan laman + hide_on_view_page: Halaman Tampilkan label: Kolom mobile_visible: Aplikasi Seluler move_to: Pindah ke @@ -1115,6 +1136,16 @@ id: show: Tunjukkan? show_on: Tunjukkan pada show_on_minify_form: Formulir Ringkas + skip_logic: + name: Skip Logic? + record_section: + title: Bidang ini harus terlihat jika catatan/rekaman + buttons: + add: Tambahkan kondisi syarat catatan/rekaman + subform_section: + title: Bidang ini harus terlihat jika sub-formulir + buttons: + add: Tambahkan kondisi syarat sub-formulir subform: Subform subform_group_by: Grup berdasarkan subform_remove_message: Yakin ingin menghapus subform ini? @@ -1146,6 +1177,10 @@ id: less: Kurangi more: Lebihkan... save_filters: Simpan + categories: + violations: Pelanggaran + incidents: Kejadian + individual_victims: Korban Individual flags: add_flag_tab: Tambahkan Tanda Bendera Baru date: 'Tanggal:' @@ -1208,7 +1243,7 @@ id: reportable_follow_up: Menindaklanjuti reportable_protection_concern: Masalah Perlindungan reportable_service: Pelayanan - tracing_request: Permintaan Pelacakan + tracing_request: Permintaan Penelusuran transfers_assignments: Transfer / Tugas violation: Pelanggaran registry_details: Detil Pendaftaran @@ -1233,6 +1268,26 @@ id: type_label: Tipe visibility: Penglihatan web_app: Aplikasi Web + skip_logic: + name: Skip Logic? + section: + title: Form ini harus terlihat jika + buttons: + add: Tambah kondisi syarat + conditions: + add: Tambah kondisi syarat + update: Perbarui kondisi syarat + field_name: Nama Bidang + condition: Kondisi syarat + empty: Tak ada kondisi syarat yang ditambahkan + type: Jenis + types: + and: + display_text: Dan kondisi syarat ini + name: DAN + or: + display_text: Atau kondisi syarat ini + name: ATAU home: ar: العربية ar-IQ: Arab (Irak) @@ -1244,8 +1299,10 @@ id: dashboard: Dashboard en: English es: Español - es-GT: Español (Guatemala) + es-GT: Spanyol + es-ES: Spanyol fr: Français + hu: Magyar id: Bahasa km: ភាសាខ្មែរ ku: کوردی @@ -1255,21 +1312,28 @@ id: sw-KE: Kiswahili (Kenya) sw-TZ: Kiswahili (Tanzania) ne: Nepali + om: Oromo + am-ET: Amharic (Ethiopia) label: Beranda language: Bahasa manage_system_users: Mengelola Pengguna Sinkronisasi Server my: ဗမာစာ + pl: Polandia pt: Português pt-BR: Português (Brasil) records_need_attention: Data yang perlu perhatian + ro: Română ru: Русский + sk: Slowakia so: Af-Soomaali th: ไทย + uk: Ukrainia users: Kelola Para Pengguna view_records: Lihat Data welcome: Selamat Datang di Primero zh: 中文 incident: + code: Kode Kejadian associated_case: "Kasus yang Berkaitan:" messages: creation_success: Data insiden berhasil dibuat. @@ -1278,6 +1342,7 @@ id: update_success: 'Data Insiden %{record_id} berhasil diubah.' update_success_queue: 'Insiden %{record_id} berhasil diperbarui pada latar belakang.' violation: + associated_violations: "Pelanggaran yang Terkait:" update_and_return: 'Perbarui dan Kembali ke %{association}' save_and_return: 'Tambahkan dan Kembali ke %{association}' pending: Verifikasi Tertunda @@ -1286,9 +1351,11 @@ id: killing: Pembunuhan Anak-anak maiming: Mencederai Anak-anak recruitment: Merekrut dan/atau Memanfaatkan Anak-anak - sexual_violence: Perkosaan dan/atau Bentuk Lain Kekerasan Seksual + sexual_violence: Perkosaan dan Bentuk Kekerasan Seksual lainnya abduction: Penculikan attack_on: Serangan di Sekolah dan/atau Rumah sakit + attack_on_hospitals: Serangan terhadap Rumasakit + attack_on_schools: Serangan terhadap Sekolah military_use: Penggunaan Sekolah dan/atau Rumahsakit oleh Militer denial_humanitarian_access: Penolakan akses bantuan kemanusiaan untuk anak incidents: @@ -1299,6 +1366,7 @@ id: enable_dialog_title: Insiden yang Diaktifkan enable_success: Insiden berhasil diaktifkan. id: ID# + complete: Tersedia Luring date_of_interview: Tanggal Wawancara date_of_incident: Tanggal dari Insiden incident_location: Lokasi insiden @@ -1306,28 +1374,74 @@ id: export: Ekspor label: Insiden filter_by: + filter_category: Kategori Filter boys: Anak laki-laki by_date: Berdasarkan Tanggal children: Anak-anak girls: Anak perempuan incident_location: Lokasi Insiden + status: Status unaccompanied_separated_status: Status Perlindungan unknown: Tidak diketahui verification_status: Status Verifikasi violence_type: Jenis Kekerasan - armed_force_group_name: Nama Kelompok Bersenjata + armed_force_group_party_name: Angkatan bersenjata, kelompok bersenjata, dan pihak lainnya armed_force_group_type: Jenis Kelompok Bersenjata + violations: Pelanggaran + individual_violations: Pelanggaran Individual + individual_age: Usia Individual + individual_sex: Jenis Kelamin Perorangan + victim_deprived_liberty_security_reasons: Dirampas Kebebasannya + reasons_deprivation_liberty: Apa alasan atas perampasan kebebasannya? + victim_facilty_victims_held: Pilih fasilitas/tempat di mana korban ditahan + torture_punishment_while_deprivated_liberty: Apakah anak/korban mengalami penyiksaan atau hukuman yang kejam atau merendahkan martabat selama ditahan? + verified_ghn_reported: Tentukan GHN yang menyertakan insiden/kejadian ini + weapon_type: 'Jenis senjata/metode yang digunakan' + facility_impact: 'Jenis dan seberapa besar dampak fisik' + facility_attack_type: 'Jenis pelanggaran terkait kesehatan atau pendidikan' + child_role: 'Apa peran anak di dalam kelompok bersenjata?' + abduction_purpose_single: 'Tujuan penculikan' + military_use_type: 'Jenis penggunaan militer' + types_of_aid_disrupted_denial: 'Jenis bantuan/layanan yang ditolak/terganggu.' + late_verified_violations: Pelanggaran yang diverifikasi belakangan + perpetrator_category: Kategori Pelaku + record_owner: Pemilik Catatan register_new_incident: Insiden Baru selectable_date_options: date_of_first_report: Tanggal Wawancara + mrm_date_of_first_report: Tanggal pelaporan awal ke CTFMR + ctfmr_verified_date: Tanggal verifikasi oleh CTFMR incident_date_derived: Tanggal Kejadian selected_records: 'Insiden %{select_records} dipilih' selected_all_records: 'Pilih semua insiden %{total_records} yang cocok dengan permintaan ini.' + summary_mrm: + label: Ringkasan Kejadian + fields: + children_multiple_violation: + label: Anak-anak terdampak beberapa pelanggaran + summary_of_incident: + label: Ringkasan Kejadian + incident_total_tally: + label: Jumlah korban + boys: Anak Laki-laki + girls: Anak Perempuan + unknown: Tidak Diketahui + incident_date: + label: Tanggal Insiden + incident_location: + label: Lokasi Kejadian + incident_description: + label: Gambaran Kejadian + incident_update: + label: Update tentang Kejadian survivor_code: Kode Penyintas show_incident: 'ID Insiden: %{short_id}' social_worker: Pekerja Sosial + violation_type: Jenis Pelanggaran violence_type: Jenis Kekerasan type_violence: Jenis dari Kekerasan + violation_summary: Ringkasan + sort_by: Urutkan Berdasar key_performance_indicators: label: "Pulse/KPIs" case_assessment: "Penilaian Kasus" @@ -1526,6 +1640,9 @@ id: central_warehouse: Gudang Pusat warehouse: Gudang buyingstation: Stasiun Pembelian + township: Kecamatan + municipality: Kota/Kabupaten + autonomous_region: Daerah Otonomi label: Lokasi name: Nama code: Kode @@ -1715,12 +1832,16 @@ id: no_options: Pencarian pilihan ini tidak memiliki pilihan translation_label: Teks Terjemahan values: Pilihan + locked_alert_message: Referensi ini dikunci managed_reports: + generated_on: Dihasilkan pada label: Insights total: Total + violations_total: Pelanggaran filter_by: date: Tanggal verification_status: Status Verifikasi + violation_type: Jenis Pelanggaran date_range: month: Bulan quarter: Triwulan @@ -1735,54 +1856,117 @@ id: custom: Sesuaikan no_data: Tidak ada data untuk insight ini no_data_table: Tidak ada data tabel untuk insight ini + incomplete_data: Data tidak lengkap + individual_children: + name: Jumlah Anak + reports: + individual_children: Jumlah Anak + sub_reports: + individual_age: Jumlah Anak berdasar Usia + individual_violation_type: Jumlah Anak berdasar Jenis Pelanggaran + individual_region: Jumlah Anak berdasar Wilayah + individual_perpetrator: Jumlah Anak berdasar Pelaku Penyerangan + ghn_report: + name: Global Horizontal Note + reports: + ghn_report: Global Horizontal Note + sub_reports: + verified_information: Informasi Terverifikasi - Korban + late_verification: Verifikasi Belakangan - Korban + unverified_information: Informasi yang Belum Terverifikasi - Korban + verified_information_violations: Informasi Terverifikasi - Pelanggaran + late_verification_violations: Terverifikasi Belakangan - Pelanggaran + unverified_information_violations: Informasi yang Belum Terverifikasi - Pelanggaran + killing: Pembunuhan Anak-anak + maiming: Melukai Anak-anak + recruitment: Perekrutan dan/atau Penggunaan Anak-anak + sexual_violence: Perkosaan dan Bentuk Kekerasan Sexual Lainnya + rape: Perkosaan dan Bentuk Kekerasan Sexual Lainnya + abduction: Penculikan + attack_on_hospitals: Serangan terhadap Rumasakit + attack_on_schools: Serangan terhadap Sekolah + military_use: Penggunaan Sekolah dan/atau Rumasakit untuk Keperluan Militer + denial_humanitarian_access: Penolakan bantuan kemanusiaan untuk anak + multiple_violations: Anak-anak terdampak beragam kekerasan + detention: Penahanan + boys: Anak Laki-laki + girls: Anak Perempuan + total: Total + unknown: Tidak Diketahui + associated_violations: 'Pelanggaran yang Terkait:' violations: name: Pelanggaran filter_options: incident_date: Tanggal Insiden date_of_report: Tanggal Laporan ctfmr_verified_date: Tanggal Verifikasi + verified: Terverifikasi reports: killing: Pembunuhan Anak-anak maiming: Mencederai Anak-anak recruitment: Rekrutmen dan/atau Pemanfaatan Anak-anak - sexual_violence: Perkosaan dan/atau Bentuk Kekerasan Seksual lainnya + sexual_violence: Perkosaan dan Bentuk Kekerasan Sexual Lainnya + rape: Perkosaan dan Bentuk Kekerasan Sexual Lainnya abduction: Penculikan - attack_on: Penyerangan di Sekolah dan/atau Rumahsakit + attack_on_hospitals: Serangan terhadap Rumasakit + attack_on_schools: Serangan terhadap Sekolah military_use: Penggunaan Sekolah dan/atau Rumahsakit oleh Militer denial_humanitarian_access: Penolakan akses bantuan kemanusdiaan untuk anak-anak + detention: Tahanan sub_reports: + children: Anak-anak combined: Pelanggaran + denial_humanitarian_access: Penolakan bantuan kemanusiaan + denial_type: Bentuk penolakan detention_detained: Tetap Ditahan detention_released: Dibebaskan perpetrators: Jumlah Anak berdasar Pelaku Kekerasan + perpetrators_denial: Jumlah Pelanggaran berdasar Pelaku + perpetrator_detention: Jumlah Anak berdasar Pelaku Kekerasan + perpetrators_incidents: Jumlah kejadian berdasar pelaku + reporting_location_incidents: Jumlah kejadian berdasar daerah reporting_location: Jumlah Anak berdasar Agama + reporting_location_detention: Jumlah anak berdasar daerah + reporting_location_denial: Jumlah pelanggaran berdasar daerah attack_type: Jumlah Anak berdasar Jenis Serangan boys: Anak Laki-laki girls: Anak Perempuan unknown: Tidak Diketahui total: Total + violation: Pelanggaran + sexual_violence_type: Bentuk-(bentuk) kekerasan seksual + detention_status: Status anak yang ditahan + type_of_use: Jenis penggunaan + factors_of_recruitment: Alasan perekrutan + still_being_held: Masih ditahan + released: 'Dibebaskan' + escaped: 'Melarikan diri' + abduction_reasons: Alasan penculikan + abducted_status: Status anak yang diculik + facility_attack_type: Jenis pelanggaran + received_response: Anak-anak yang mendapatkan respon + male: Laki-Laki + female: Perempuan + military_use_type_of_use: Jumlah pelanggaran berdasar jenis penggunaan gbv_statistics: name: Statistik KBG filter_options: date_of_first_report: Tanggal Wawancara incident_date: Tanggal Insiden reports: - incidents: Insiden perpetrators: Pelaku Kekerasan + survivors: Penyintas + referrals: Rujukan sub_reports: - combined: Insiden - total: Jumlah Insiden KBG yang Dilaporkan - gbv_sexual_violence: Jumlah Insiden Kekerasan Seksual yang Dilaporkan - gbv_previous_incidents: Jumlah Insiden yang Dilaporkan oleh Penyintas dengan Insiden GBV Sebelumnya - gbv_sexual_violence_type: Jenis Insiden - incident_timeofday: Waktu terjadinya Insiden - elapsed_reporting_time: Jeda antara Tanggal Insiden dan Pelaporan - elapsed_reporting_time_rape: Insiden Perkosaan, Jeda Waktu antara Tanggal Insiden dan Pelaporan - incident_location_type: Lokasi Insiden - number_of_perpetrators: Jumlah Pelaku (Kekerasan) Utama - perpetrator_relationship: Hubungan antara Terduga Pelaku Utama dengan Penyintas - perpetrator_age_group: Kelompok Usias Terduga Pelaku Utama - perpetrator_occupation: Pekerjaan Terduga Pelaku Utama + service_safehouse_referral: Rujukan Rumah Aman / Shelter + service_medical_referral: Rujukan Layanan Kesehatan/Medis + service_psycho_referral: Layanan Psikososial/Konseling + service_legal_referral: Layanan Bantuan Hukum + service_police_referral: Polisi atau layanan pengamanan lainnya + service_livelihoods_referral: Layanan mata pencarian + service_protection_referral: Layanan perlindungan anak + survivors_disability_type: Dengan disabilitas + success_message: Export File berhasil dilakukan messages: alert_items: Anda memiliki %{items} item yang dicatat. alerts_for: @@ -1826,8 +2010,9 @@ id: code_of_conduct: Kode Etik terms_of_use: Syarat Penggunaan system_information: Informasi Sistem + resync: Perubahan offline belum dikirimkan tasks: Tugas-tugas - tracing_request: Permintaan Pelacakan + tracing_request: Permintaan Penelusuran activity_log: Log Aktivitas registry_records: Pendaftaran notes: @@ -1910,7 +2095,7 @@ id: export_photowall: Ekspor Foto Dinding export_unhcr_csv: Ekspor unhcr csv export_xls: Ekspor XLS - find_tracing_match: Temukan kecocokan pelacakan dari kasus + find_tracing_match: Temukan kecocokan penelusuran dari kasus view_registry_record: Lihat catatan pendaftaran add_registry_record: Tambahkan catatan pendaftaran flag: Tandai dengan Bendera @@ -1958,7 +2143,7 @@ id: sync_external: Sinkronkan dengan sistem manajemen informasi eksternal sync_mobile: Tandai untuk Offline system: Sistem - tracing_request: Permintaan Pelacakan + tracing_request: Permintaan Penelusuran transfer: Dapat digunakan untuk pemindahan user: Pengguna user_group: Grup Pengguna @@ -2051,12 +2236,12 @@ id: read: explanation: Memungkinkan pengguna untuk melihat dan memfilter daftar semua tindakan yang dilakukan dalam sistem, dikelompokkan berdasarkan pengguna, jenis tindakan, ID rekaman, dan waktu tindakan. Ini paling cocok untuk administrator tingkat nasional atau lembaga, karena ini menunjukkan tindakan yang dilakukan oleh semua pengguna dalam sistem. Harap dicatat bahwa log audit tidak menampilkan informasi identitas pribadi tentang rekaman yang terlibat dalam setiap tindakan. label: Lihat - explanation: Daftar semua tindakan yang dilakukan dalam sistem yang dapat difilter. Tidak termasuk informasi yang dapat diidentifikasi pada Kasus, Insiden, atau Permintaan Pelacakan. + explanation: Daftar semua tindakan yang dilakukan dalam sistem yang dapat difilter. Tidak termasuk informasi yang dapat diidentifikasi pada Kasus, Insiden, atau Permintaan Penelusuran. label: Audit Log case: actions: add_note: - explanation: Memungkinkan pengguna untuk menambahkan entri ke dalam subformulir "Catatan" (kadang juga disebut "Komentar"). Pengguna melakukan ini dengan mengklik tombol "Tambah Catatan" pada laman pertunjukan kasus. Tindakan ini sangat berguna bagi manajer yang tidak memiliki kemampuan untuk mengubah kasus, tetapi ingin menambahkan pengingat ke kasus untuk pekerja kasus. Dengan cara ini, menambahkan catatan mirip dengan menambahkan bendera. Keuntungan menambahkan catatan adalah, ketika manajer menambahkan catatan ke kasus, pemberitahuan akan muncul di kasus untuk pekerja kasus ketika mereka melihat kasus di perangkat seluler mereka. + explanation: Memungkinkan pengguna untuk menambahkan entri ke dalam subformulir "Catatan" (kadang juga disebut "Komentar"). Pengguna melakukan ini dengan mengklik tombol "Tambah Catatan" pada halaman tampilan kasus. Tindakan ini sangat berguna bagi manajer yang tidak memiliki akses untuk mengubah kasus, tetapi ingin menambahkan pengingat ke kasus untuk pekerja kasus. Dengan cara ini, menambahkan catatan mirip dengan menambahkan bendera. Keuntungan menambahkan catatan adalah, ketika manajer menambahkan catatan ke kasus, pemberitahuan akan muncul di kasus untuk pekerja kasus ketika mereka melihat kasus di perangkat seluler mereka. label: Tambahkan Catatan pada kasus add_registry_record: explanation: Izinkan pengguna menautkan Nomor Pendaftaran ke Kasus dari formulir detail pendaftaran. Juga izinkan pengguna untuk melakukan pembatalan. @@ -2101,7 +2286,7 @@ id: explanation: Kemampuan untuk membuat kasus label: Buat display_view_page: - explanation: Jika pengguna melakukan pencarian untuk kasus yang mereka tidak memiliki akses, izin ini memungkinkan mereka untuk melihat modal kecil dengan informasi dasar tentang kasus tersebut, bahkan jika pengguna tidak dapat mengklik ke dalam kasus untuk melihat semua informasinya. Kolom yang muncul di "Lihat Modal" ini adalah kolom yang telah dikonfigurasi ke "Tampilkan pada Formulir Ringkas". Modal ini juga berguna bagi pengguna yang melakukan tindakan Pelacakan Keluarga dan Penyatuan Kembali, karena "Lihat Modal" tersedia untuk diakses pengguna saat mereka meninjau kasus yang muncul sebagai "Kemungkinan Cocok" untuk Permintaan Pelacakan. + explanation: Jika pengguna melakukan pencarian untuk kasus yang mereka tidak memiliki akses, izin ini memungkinkan mereka untuk melihat modal kecil dengan informasi dasar tentang kasus tersebut, bahkan jika pengguna tidak dapat mengklik ke dalam kasus untuk melihat semua informasinya. Kolom yang muncul di "Lihat Modal" ini adalah kolom yang telah dikonfigurasi ke "Tampilkan pada Formulir Ringkas". Modal ini juga berguna bagi pengguna yang melakukan tindakan Penelusuran dan Reunifikasi Keluarga, karena "Lihat Modal" tersedia untuk diakses pengguna saat mereka meninjau kasus yang muncul sebagai "Kemungkinan Cocok" untuk Permintaan Pelacakan. label: Tampilkan Tinjauan Halaman enable_disable_record: explanation: Kemampuan untuk menonaktifkan atau mengaktifkan kasus. Kasus yang "dinonaktifkan" tidak muncul secara default dalam daftar kasus. Pengguna dapat melihat kasus yang dinonaktifkan dalam daftar kasus dengan menggunakan filter. Karena Primero tidak mengizinkan pengguna untuk menghapus kasus, pengguna mungkin ingin menonaktifkan kasus sebagai pengganti. Misalnya, jika pengguna membuat kasus secara tidak sengaja, atau kasus memiliki data yang buruk, pengguna harus menonaktifkannya. @@ -2128,7 +2313,7 @@ id: explanation: Pengguna dapat menghasilkan ekspor file PDF dari daftar kasus atau halaman pertunjukan kasus, yang berisi semua bidang yang dapat diakses oleh pengguna saat ini, untuk satu, beberapa, atau semua kasus yang dapat diakses oleh pengguna. Dalam file ekspor PDF, informasi didaftar pertama berdasarkan kasus, dan kemudian diatur lebih lanjut oleh formulir di mana informasi muncul. label: Ekspor PDF kasus export_photowall: - explanation: Memungkinkan pengguna untuk mengekspor file dari halaman daftar kasus yang berisi foto dari semua kasus yang dipilih. Ekspor ini terutama digunakan untuk kegiatan Family Tracing dan Reunification. Hanya dilakukan dari halaman daftar kasus. + explanation: Memungkinkan pengguna untuk mengekspor file dari halaman daftar kasus yang berisi foto dari semua kasus yang dipilih. Ekspor ini terutama digunakan untuk kegiatan Penelusuran dan Reunifikasi Keluarga. Hanya dilakukan dari halaman daftar kasus. label: Ekspor Foto Dinding export_unhcr_csv: label: Ekspor UNCHR CSV @@ -2136,8 +2321,8 @@ id: explanation: 'Pengguna dapat membuat ekspor file XLS dari daftar kasus atau halaman pertunjukan kasus, yang berisi semua bidang yang dapat diakses oleh pengguna saat ini, untuk satu, beberapa, atau semua kasus yang dapat diakses oleh pengguna. Dalam ekspor ini, setiap formulir diwakili di tabnya sendiri di dalam file XLS. CATATAN: Format XLS merender karakter non-Latin (misalnya Arab, Bangla) dalam format yang dapat dibaca, sedangkan ekspor CSV tidak.' label: Ekspor Excel (file XLS) find_tracing_match: - explanation: Ini digunakan secara eksklusif untuk konteks dengan aktivitas Pelacakan Keluarga dan Penyatuan Kembali. Pengguna dengan izin ini akan melihat tombol "Temukan Pelacakan yang Cocok" di halaman pertunjukan kasus. Ketika mereka mengkliknya, mereka akan sampai pada daftar permintaan pelacakan dalam sistem yang merupakan kemungkinan cocok untuk kasus mereka. - label: Temukan kecocokan pelacakan dari kasus + explanation: Ini digunakan khusus hanya untuk konteks terkait dengan aktivitas Penelusuran dan Reunifikasi Keluarga. Pengguna dengan izin ini akan melihat tombol "Temukan Penelusuran yang Cocok" di halaman tampilan kasus. Ketika mereka mengkliknya, mereka akan melihat daftar permintaan penelusuran dalam sistem yang mungkin cocok untuk kasus mereka. + label: Temukan kecocokan penelusuran dari kasus flag: explanation: Kemampuan untuk menambahkan tanda bendera ke kasus. Pengguna dengan izin ini juga dapat menghapus tanda bendera yang telah mereka tambahkan ke kasus. label: Tandai Bendera @@ -2293,7 +2478,6 @@ id: explanation: Memungkinkan manajer untuk melihat berapa banyak kasus yang memiliki tugas Layanan yang terlambat untuk masing-masing pekerja kasus mereka. label: Tugas Layanan Terlambat dash_case_incident_overview: - explanation: . label: Ikhtisar - Kasus / Insiden Saya dash_cases_by_social_worker: explanation: Tabel yang menunjukkan bagaimana jumlah total kasus terbuka dan jumlah kasus baru yang dikelola oleh setiap pengguna di grup pengguna milik pengguna saat ini. Setiap baris adalah pengguna di grup pengguna pengguna saat ini, sedangkan "Total" dan "Baru" adalah dua kolom. @@ -2336,6 +2520,15 @@ id: dash_shared_with_others: explanation: Menunjukkan berapa banyak kasus saya yang memiliki rujukan aktif, pemindahan tertunda, atau transfer ditolak. Biasanya tidak untuk manajer, kecuali jika mereka mengelola kasus sendiri. label: Bagikan Dengan Yang Lain + dash_violations_category_verification_status: + explanation: Tunjukkan jumlah pelanggaran MRM untuk setiap jenis, dipilah berdasar status verifikasi + label: MRM - Jumlah pelanggaran per status verifikasi + dash_violations_category_region: + explanation: Tunjukkan jumlah pelanggaran MRM untuk setiap wilayah, dipilah berdasar jenis pelanggaran + label: MRM - Jumlah pelanggaran per wilayah + dash_perpetrator_armed_force_group_party_names: + explanation: Tunjukkan jumlah pelanggaran MRM untuk setiap jenis, dipilah berdasar pelaku + label: MRM - Jumlah pelanggaran per status pelaku dash_show_none_values: explanation: Menambahkan kategori "Tanpa Tingkat Risiko" tambahan ke semua dashboard yang mengelompokkan kasus berdasarkan tingkat risiko. Ini khusus untuk konfigurasi yang memiliki opsi "Tanpa Risiko" keempat untuk bidang tingkat risiko. label: Lihat kasus dengan 'Tanpa Tingkat Risiko' di Dasbor Penilaian @@ -2374,15 +2567,15 @@ id: explanation: 'Pembatasan akses pengguna ke formulir insiden membatasi informasi mana yang dapat dilihat pengguna pada suatu insiden. Misalnya, jika pengguna hanya memiliki akses ke formulir Pemilik Catatan, mereka juga hanya dapat melihat informasi yang terdapat dalam kolom pada formulir tersebut. Jika pengguna saat ini memiliki akses formulir terbatas dan memiliki kemampuan untuk mengelola konfigurasi formulir, membatasi akses formulir mereka juga membatasi formulir mana yang dapat mereka konfigurasi. CATATAN: Jika tidak ada formulir yang ditentukan, artinya peran tersebut memiliki akses ke semua formulir untuk insiden.' label: Formulir - Insiden tracing_request: - explanation: 'Membatasi akses pengguna ke formulir pada permintaan pelacakan membatasi informasi mana yang dapat dilihat pengguna pada permintaan pelacakan. Misalnya, jika pengguna hanya memiliki akses ke formulir Pemilik Rekaman, mereka juga hanya dapat melihat informasi yang terdapat dalam kolom pada formulir tersebut. Jika pengguna saat ini memiliki akses formulir terbatas dan memiliki kemampuan untuk mengelola konfigurasi formulir, membatasi akses formulir mereka juga membatasi formulir mana yang dapat mereka konfigurasi. CATATAN: Jika tidak ada formulir yang ditentukan, artinya peran tersebut memiliki akses ke semua formulir untuk Permintaan Pelacakan.' - label: Formulir - Permintaan Pelacakan + explanation: 'Membatasi akses pengguna ke formulir pada permintaan penelusuran akan membatasi informasi mana yang dapat dilihat pengguna pada permintaan penelusuran. Misalnya, jika pengguna hanya memiliki akses ke formulir Pemilik Catatan, mereka juga hanya dapat melihat informasi yang terdapat dalam kolom pada formulir tersebut. Jika pengguna saat ini memiliki akses formulir terbatas dan memiliki kemampuan untuk mengelola konfigurasi formulir, membatasi akses mereka ke formulir juga akan membatasi formulir mana yang dapat mereka konfigurasi. CATATAN: Jika tidak ada formulir yang ditentukan, artinya peran tersebut memiliki akses ke semua formulir untuk Permintaan Penelusuran.' + label: Formulir - Permintaan Penelusuran registry_record: explanation: 'Pembatasan akses pengguna ke formulir Pendaftaran membatasi informasi mana yang dapat dilihat pengguna pada suatu Pendaftaran. Misalnya, jika pengguna hanya memiliki akses ke formulir Pemilik Catatan, mereka juga hanya dapat melihat informasi yang terdapat dalam kolom pada formulir tersebut. Jika pengguna saat ini memiliki akses formulir terbatas dan memiliki kemampuan untuk mengelola konfigurasi formulir, membatasi akses formulir mereka juga membatasi formulir mana yang dapat mereka konfigurasi. CATATAN: Jika tidak ada formulir yang ditentukan, artinya peran tersebut memiliki akses ke semua formulir untuk Pendaftaran.' label: Formulir - Pendaftaran group: actions: admin_only: - explanation: Artinya, pengguna dengan peran ini hanya akan dapat melihat hal-hal yang berkaitan dengan administrasi sistem, seperti laporan, konfigurasi formulir dan pencarian, pengguna, peran, dan grup pengguna. Mereka tidak akan melihat kasus individual, permintaan pelacakan, atau insiden apa pun. + explanation: Artinya, pengguna dengan peran ini hanya akan dapat melihat hal-hal yang berkaitan dengan administrasi sistem, seperti laporan, konfigurasi formulir dan referensi (lookup), pengguna, peran, dan grup pengguna. Mereka tidak akan melihat kasus individual, permintaan penelusuran, atau insiden apa pun. label: Tidak ada data - Hanya untuk Admin agency: explanation: Peran tersebut dapat mengakses rekaman yang dikelola oleh semua pengguna di lembaga mereka. Jika pengguna memiliki akses ke pengguna, mereka dapat mengakses semua pengguna di lembaga mereka. @@ -2394,9 +2587,9 @@ id: explanation: Peran tersebut dapat mengakses rekaman yang dikelola oleh semua Pengguna di Grup Pengguna mereka. Mereka hanya dapat mengakses Pengguna di Grup Pengguna mereka. Mereka hanya dapat mengakses Grup Pengguna mereka sendiri. label: Akses semua data atau pengguna di grup saya self: - explanation: Peran dapat mengakses data mereka sendiri (kasus, permintaan pelacakan, atau insiden), dan dapat mengubah akun pengguna mereka sendiri. + explanation: Peran dapat mengakses data mereka sendiri (kasus, permintaan penelusuran, atau insiden), dan dapat mengubah akun pengguna mereka sendiri. label: Akses hanya data saya atau pengguna - explanation: Mengontrol rekaman mana (Kasus, Permintaan Pelacakan, atau Insiden), yang dapat diakses oleh peran. Jika peran memiliki akses ke Pengguna dan Grup Pengguna, ini juga mengontrol Pengguna dan Grup Pengguna mana yang dapat mereka akses. Peran dengan akses ke "Tidak Ada Data" hanya dapat mengakses konfigurasi sistem seperti Formulir, Pengguna, dan Laporan. + explanation: Mengontrol catatan yang mana (Kasus, Permintaan Penelusuran, atau Insiden), yang dapat diakses oleh peran ini. Jika peran memiliki akses ke Pengguna dan Grup Pengguna, berarti juga mengontrol Pengguna dan Grup Pengguna mana yang dapat mereka akses. Peran dengan akses ke "Tidak Ada Catatan" hanya dapat mengakses konfigurasi sistem seperti Formulir, Pengguna, dan Laporan. label: Data apa yang mempengaruhi peran ini? incident: actions: @@ -2420,6 +2613,9 @@ id: export_incident_recorder_xls: explanation: Pengguna dapat membuat ekspor file XLS khusus yang memungkinkan pertukaran data dengan alat Perekam Insiden GBV. label: Perekam insiden ekspor xls + export_mrm_violation_xls: + explanation: Pengguna dapat membuat ekspor Excel (file XLS) khusus untuk Pelanggaran MRM. Tindakan ini tersedia di tampilan halaman Insiden dan daftar Insiden. + label: Eksport Pelanggaran MRM ke Excel (XLS file) export_json: explanation: Pengguna dapat membuat ekspor file JSON dari daftar insiden atau halaman acara insiden, yang berisi semua bidang yang dapat diakses oleh pengguna saat ini, untuk satu, beberapa, atau semua insiden yang dapat diakses pengguna. Ekspor ini terutama digunakan untuk mereka yang ingin mengekspor insiden dari sistem Primero saat ini dan kemudian mengimpornya ke sistem Primero yang berbeda, atau ke sistem manajemen informasi lainnya. Format JSON dapat dibaca mesin dan tidak praktis untuk sebagian besar pengguna. label: Ekspor JSON @@ -2461,12 +2657,16 @@ id: label: Pelanggaran gbv_statistics: label: Statistik KBG + ghn_report: + label: Global Horizontal Note + individual_children: + label: Jumlah Anak matching_configuration: actions: manage: - explanation: Kemampuan untuk mengontrol kolom mana yang dibandingkan untuk menemukan kecocokan antara permintaan pelacakan dan kasus. Karena ini mengontrol bagaimana pencocokan dijalankan di seluruh sistem, izin ini biasanya hanya tersedia untuk administrator sistem. + explanation: Kemampuan untuk mengontrol kolom-kolom mana yang akan dibandingkan untuk menemukan kecocokan antara permintaan penelusuran dan data kasus. Karena ini mengontrol bagaimana pencocokan dijalankan di seluruh sistem, izin ini biasanya hanya tersedia untuk administrator sistem. label: Kelola (semua izin untuk jenis sumber daya ini) - explanation: Mengatur bidang mana yang digunakan untuk membandingkan Permintaan Pelacakan dengan Kasus selama tahap Pelacakan dan Reunifikasi Keluarga. + explanation: Mengatur bidang mana yang digunakan untuk membandingkan Permintaan Penelusuran dengan Kasus dalam proses Penelusuran dan Reunifikasi Keluarga. label: Pengaturan Pencocokan metadata: actions: @@ -2488,8 +2688,17 @@ id: potential_match: actions: read: - explanation: Mewakili hubungan antara Permintaan Pelacakan dan Kasus. Akses ke Kecocokan Potensial diperlukan untuk pekerjaan Family Tracing and Reunification (FTR). Memungkinkan pengguna untuk melihat formulir Ringkasan Pelacakan pada Kasus. + explanation: Mewakili hubungan antara sebuah Permintaan Penelusuran dan suatu Kasus. Akses ke Kecocokan Potensial diperlukan untuk pekerjaan Penelusuran dan Reunifikasi Keluarga (FTR). Memungkinkan pengguna untuk melihat formulir Ringkasan Penelusuran sebuah Kasus. label: Lihat + view_audio: + explanation: Tentukan apakah pengguna yang mencari kecocokan penelusuran dapat melihat file audio untuk Kasus atau Permintaan Penelusuran yang terkait dengan Kecocokan Potensial. + label: Lihat Audio + view_photo: + explanation: Tentukan apakah pengguna yang mencari kecocokan penelusuran dapat melihat file Foto untuk Kasus atau Permintaan Penelusuran yang terkait dengan Kecocokan Potensial. + label: Lihat Foto + manage: + explanation: Memungkinkan pengguna untuk melakukan semua tindakan yang tersedia di Kecocokan Potensial. Izin "Kelola" pada dasarnya berarti "semuanya". + label: Kelola label: Potensi Kecocokan primero_configuration: actions: @@ -2557,6 +2766,9 @@ id: write: explanation: Kemampuan untuk mengubah semua laporan (termasuk yang dibuat oleh pengguna lain). label: Ubah + agency_read: + explanation: Kemampuan untuk melihat semua laporan. Angka di setiap laporan hanya akan mencerminkan catatan yang dapat diakses oleh pengguna di Agensi pengguna saat ini. Izin ini sering digunakan untuk administrator agensi. + label: Lihat (data berbasis agensi) explanation: Alat analisis data agregat. Termasuk tabel dan grafik representasi data. label: Laporan reporting_location_level: @@ -2603,49 +2815,49 @@ id: explanation: Pengguna dapat melihat riwayat semua perubahan yang dibuat pada catatan sejak dibuat. Ini termasuk nilai yang direkam untuk semua bidang. label: Ubah Log create: - explanation: Kemampuan untuk membuat permintaan pelacakan + explanation: Kemampuan untuk membuat permintaan penelusuran label: Buat enable_disable_record: - explanation: Kemampuan untuk menonaktifkan atau mengaktifkan Permintaan Pelacakan. Permintaan Pelacakan "Dinonaktifkan" tidak muncul secara default di daftar Permintaan Pelacakan. Pengguna dapat melihat Permintaan Pelacakan yang dinonaktifkan di daftar Permintaan Pelacakan dengan menerapkan filter. + explanation: Kemampuan untuk menonaktifkan atau mengaktifkan Permintaan Penelusuran. Permintaan Penelusuran yang "Dinonaktifkan" secara default tidak dimunculkan di daftar Permintaan Penelusuran. Pengguna dapat melihat Permintaan Penelusuran yang dinonaktifkan di daftar dengan cara menerapkan filter. label: Aktifkan / Nonaktifkan export_case_pdf: - explanation: Pengguna dapat menghasilkan ekspor file PDF dari daftar permintaan pelacakan atau halaman acara permintaan penelusuran, yang berisi semua bidang yang dapat diakses oleh pengguna saat ini, untuk satu, beberapa, atau semua catatan yang dapat diakses pengguna. Dalam file ekspor PDF, informasi didaftar pertama berdasarkan kasus, dan kemudian diatur lebih lanjut oleh formulir di mana informasi muncul. + explanation: Pengguna dapat melakukan ekspor file PDF dari daftar permintaan penelusuran atau halaman tampilan permintaan penelusuran, yang berisi semua data yang dapat diakses oleh pengguna saat ini, untuk satu, beberapa, atau semua catatan yang dapat diakses pengguna. Dalam file ekspor PDF, informasi di urutkan berdasarkan kasus, dan kemudian diatur berdasar formulir tempat informasi berada. label: PDF Ekspor export_csv: - explanation: Pengguna dapat membuat ekspor file CSV dari daftar permintaan penelusuran atau halaman acara permintaan penelusuran, yang berisi semua kolom yang dapat diakses oleh pengguna saat ini, untuk satu, beberapa, atau semua permintaan pelacakan yang dapat diakses pengguna. + explanation: Pengguna dapat membuat ekspor file CSV dari daftar permintaan penelusuran atau halaman tampilan permintaan penelusuran, yang berisi semua data yang dapat diakses oleh pengguna saat ini, untuk satu, beberapa, atau semua permintaan penelusuran yang dapat diakses pengguna. label: Ekspor CSV export_custom: - explanation: Pengguna dapat membuat ekspor file XLS dari daftar permintaan pelacakan atau halaman acara permintaan pelacakan, yang berisi kumpulan formulir atau bidang khusus, untuk satu, beberapa, atau semua permintaan pelacakan yang dapat diakses pengguna. Dalam ekspor ini, setiap formulir diwakili di tabnya sendiri di dalam file XLS. Pengguna dapat memilih formulir atau bidang mana yang ingin mereka sertakan dalam ekspor menggunakan modal Ekspor Kustom. Harap diperhatikan bahwa pengguna hanya dapat menyertakan formulir dan bidang dalam ekspor jika mereka telah memiliki kemampuan untuk melihat formulir dan bidang tersebut saat melihat permintaan pelacakan dalam aplikasi. + explanation: Pengguna dapat melakukan ekspor file XLS dari daftar permintaan penelusuran atau halaman tampilan permintaan penelusuran, yang berisi sejumlah formulir atau kolom data, untuk satu, beberapa, atau semua permintaan penelusuraran yang dapat diakses pengguna. Dalam ekspor ini, masing-masing formulir diwakili di tabnya sendiri di dalam file XLS. Pengguna dapat memilih formulir atau bidang mana yang ingin mereka sertakan dalam ekspor menggunakan pilihan di Ekspor Kustom. Harap diperhatikan bahwa pengguna hanya dapat menyertakan formulir dan bidang dalam ekspor jika mereka telah memiliki kemampuan untuk melihat formulir dan bidang tersebut saat melihat permintaan penelusuran dalam aplikasi. label: Ekspor kustomisasi export_json: - explanation: Pengguna dapat membuat ekspor file JSON dari daftar permintaan penelusuran atau halaman acara permintaan penelusuran, yang berisi semua bidang yang dapat diakses oleh pengguna saat ini, untuk satu, beberapa, atau semua permintaan pelacakan yang dapat diakses pengguna. Ekspor ini terutama digunakan bagi mereka yang ingin mengekspor permintaan pelacakan dari sistem Primero saat ini dan kemudian mengimpornya ke sistem Primero yang berbeda, atau ke sistem manajemen informasi lainnya. Format JSON dapat dibaca mesin dan tidak praktis untuk sebagian besar pengguna. + explanation: Pengguna dapat membuat ekspor file JSON dari daftar permintaan penelusuran atau halaman tampilan permintaan penelusuran, yang berisi semua bidang yang dapat diakses oleh pengguna saat ini, untuk satu, beberapa, atau semua permintaan penelusuran yang boleh diakses pengguna. Ekspor ini terutama digunakan bagi mereka yang ingin mengekspor permintaan penelusuran dari SimfoniPPA saat ini dan kemudian mengimpornya ke sistem manajemen informasi lainnya. JSON adalah format yang dapat dibaca mesin, namun tidak praktis untuk sebagian besar pengguna. label: Ekspor JSON export_list_view_csv: - explanation: Pengguna dapat membuat ekspor file CSV dari halaman daftar permintaan pelacakan yang berisi bidang yang sama yang muncul untuk pengguna tersebut pada daftar permintaan pelacakan. Hanya dilakukan dari halaman daftar permintaan penelusuran. + explanation: Pengguna dapat membuat ekspor file CSV dari halaman daftar permintaan pelnelusuran yang berisi bidang yang sama dengan yang muncul untuk pengguna tersebut pada daftar permintaan penelusuran. Hanya dilakukan dari halaman daftar permintaan penelusuran. label: Tampilan daftar ekspor CSV export_pdf: - explanation: Pengguna dapat menghasilkan ekspor file PDF dari daftar permintaan pelacakan atau halaman acara permintaan penelusuran, yang berisi semua bidang yang dapat diakses oleh pengguna saat ini, untuk satu, beberapa, atau semua catatan yang dapat diakses pengguna. Dalam file ekspor PDF, informasi didaftar pertama berdasarkan kasus, dan kemudian diatur lebih lanjut oleh formulir di mana informasi muncul. + explanation: Pengguna dapat menghasilkan ekspor file PDF dari daftar permintaan penelusuran atau halaman acara permintaan penelusuran, yang berisi semua bidang yang dapat diakses oleh pengguna saat ini, untuk satu, beberapa, atau semua catatan yang dapat diakses pengguna. Dalam file ekspor PDF, informasi didaftar pertama berdasarkan kasus, dan kemudian diatur lebih lanjut oleh formulir di mana informasi muncul. label: PDF Ekspor export_xls: - explanation: 'Pengguna dapat membuat ekspor file XLS dari daftar Permintaan Pelacakan atau halaman tampilan Permintaan Pelacakan, yang berisi semua bidang yang dapat diakses oleh pengguna saat ini, untuk satu, beberapa, atau semua Permintaan Pelacakan yang dapat diakses oleh pengguna. Dalam ekspor ini, setiap formulir diwakili di tabnya sendiri di dalam file XLS. CATATAN: Format XLS merender karakter non-Latin (misalnya Arab, Bangla) dalam format yang dapat dibaca, sedangkan ekspor CSV tidak.' + explanation: 'Pengguna dapat membuat ekspor file XLS dari daftar Permintaan Penelusuran atau halaman tampilan Permintaan Penelusuran, yang berisi semua bidang yang dapat diakses oleh pengguna saat ini, untuk satu, beberapa, atau semua Permintaan Penelusuran yang dapat diakses oleh pengguna. Dalam ekspor ini, setiap formulir diwakili di tabnya sendiri di dalam file XLS. CATATAN: Format XLS merender karakter non-Latin (misalnya Arab, Bangla) dalam format yang dapat dibaca, sedangkan ekspor CSV tidak.' label: Ekspor Excel (file XLS) flag: - explanation: Kemampuan untuk menambahkan tanda bendera ke permintaan pelacakan. Pengguna dengan izin ini juga dapat menghapus tanda bendera yang telah mereka tambahkan ke permintaan pelacakan. + explanation: Kemampuan untuk menambahkan tanda bendera ke permintaan penelusuran. Pengguna dengan izin ini juga dapat menghapus tanda bendera yang telah mereka tambahkan ke permintaan penelusuran. label: Tandai Bendera import: explanation: Memungkinkan pengguna membuat satu atau beberapa kasus baru dengan mengimpornya dari file CSV, Excel, atau JSON. File yang diimpor harus diformat *sangat* khusus agar informasi dapat diimpor dengan benar. Fungsi ini seharusnya hanya tersedia untuk pengguna administratif dengan keterampilan teknis tingkat lanjut dan pengetahuan mendalam tentang bagaimana data diformat di Primero. Hanya dilakukan dari halaman daftar kasus. label: Impor manage: - explanation: Memungkinkan pengguna untuk melakukan semua tindakan yang tersedia pada permintaan pelacakan. Izin "Kelola" pada dasarnya berarti "semuanya". + explanation: Memungkinkan pengguna untuk melakukan semua tindakan yang tersedia pada permintaan penelusuran. Izin "Kelola" pada dasarnya berarti izin untuk "semuanya". label: Kelola (semua izin untuk jenis sumber daya ini) read: - explanation: Kemampuan untuk melihat permintaan pelacakan. Peran dengan kemampuan untuk melihat permintaan pelacakan juga harus memiliki kemampuan untuk melihat jenis rekaman Kemungkinan Cocok. + explanation: Kemampuan untuk melihat permintaan penelusuran. Peran dengan kemampuan untuk melihat permintaan penelusuran juga harus memiliki kemampuan untuk melihat jenis catatan Kecocokan Potensial. label: Lihat write: - explanation: Kemampuan untuk mengklik tombol "Ubah", memperbarui informasi tentang permintaan pelacakan, dan mengklik "Simpan". Juga memungkinkan pengguna untuk menonaktifkan atau mengaktifkan permintaan pelacakan + explanation: Kemampuan untuk mengklik tombol "Ubah", untuk memperbarui informasi tentang permintaan penelusuran, dan mengklik "Simpan". Juga memungkinkan pengguna untuk menonaktifkan atau mengaktifkan permintaan penelusuran label: Ubah explanation: Mewakili individu yang mencoba menemukan dan menyatukan kembali dengan Kasus yang anak tanpa pendamping atau terpisah. - label: Permintaan Pelacakan + label: Permintaan Penelusuran transfer: actions: transfer: @@ -2722,14 +2934,14 @@ id: child_age: Umur child_gender: Gender child_id: '#id anak' - inquirer_id: ID# Penyelidik + inquirer_id: ID# Pemohon Pencarian inquirer_tr_name: Permintaan Penelusuran - inquiry_date: Tanggal Penyelidikan + inquiry_date: tanggal Permohonan Pencarian name: Nama score: Nilai social_worker: Pekerja Sosial social_worker_agency: Agensi - tracing_request_id: 'ID Permintaan Pelacakan ' + tracing_request_id: 'ID Permintaan Penelusuran ' trace: Lacak likelihood_likely: Kemungkinan Besar likelihood_possible: Ada kemungkinan @@ -2737,7 +2949,6 @@ id: display: Menampilkan kecocokan yang mungkin ada untuk %{type} %{id} reassign: multiple_error: Terjadi kesalahan. %{select_records} kasus tidak ditugaskan. - multiple_successfully: '%{select_records} kasus berhasil ditugaskan' notes_label: Catatan successfully: Berhasil ditugaskan kembali user_mandatory_label: Penerima diwajibkan @@ -2914,7 +3125,7 @@ id: follow_up: Tindak Lanjut - %{subtype} service: Layanan - %{subtype} tracing_request: - label: Permintaan Pelacakan + label: Permintaan Penelusuran has_match: Cocok find_match: Temukan Kecocokan back_to_traces: Kembali ke Melacak @@ -2924,14 +3135,18 @@ id: match: Cocok matches: Cocok unmatch: Tidak cocok + tracing_request_photos: Foto-foto untuk Permintaan Penelusuran ini. + case_photos: Foto-foto untuk Kasus ini + tracing_request_audios: Audio untuk Permintaan Penelusuran ini. + case_audios: Audio untuk Kasus ini messages: - already_matched: Sudah terdapat kecocokan dalam sistem dengan Penyelidik yang mencari anak ini. - disabled: Permintaan Pelacakan Dinonaktifkan + already_matched: Sudah terdapat kecocokan dalam sistem dengan Pemohon pencarian anak ini. + disabled: Permintaan Penelusuran Dinonaktifkan nothing_found: Tidak ditemukan update_success: 'Permintaan Penelusuran %{record_id} telah berhasil diperbarui.' - creation_success: Rekaman Permintaan Pelacakan berhasil dibuat. - update_success_queue: 'Permintaan Pelacakan %{record_id} berhasil diperbarui di latar belakang.' - creation_success_queue: Rekaman Permintaan Pelacakan berhasil dibuat di latar belakang. + creation_success: Rekaman Permintaan Penelusuran berhasil dibuat. + update_success_queue: 'Permintaan Penelusuran %{record_id} berhasil diperbarui di latar belakang.' + creation_success_queue: Rekaman Permintaan Penelusuran berhasil dibuat di latar belakang. match_action: Berhasil cocok Pelacakan %{trace_id} dengan Kasus%{record_id}. unmatch_action: Berhasil membatalkan kecocokan Pelacakan %{trace_id} dan Kasus %{record_id}. registry_record: @@ -2940,31 +3155,33 @@ id: creation_success: 'Catatan Pendaftaran berhasil dibuat.' disabled: Pencatatan Pendaftaran dinonaktifkan tracing_requests: - date_of_inquiry: Tanggal Penyelidikan - disable_dialog_title: Permintaan Pelacakan yang Dinonaktifkan - disable_dialog: Mengklik OK akan mengubah status pelacakan ini menjadi Dinonaktifkan - disable_success: Permintaan pelacakan berhasil dinonaktifkan - enable_dialog: Mengklik OK akan mengubah status permintaan pelacakan ini menjadi Diaktifkan. - enable_dialog_title: Aktifkan Permintaan Pelacakan + date_of_inquiry: Tanggal Permohonan Pencarian + disable_dialog_title: Permintaan Penelusuran yang Dinonaktifkan + disable_dialog: Mengklik OK akan mengubah status penelusuran ini menjadi Dinonaktifkan + disable_success: Permintaan penelusuran berhasil dinonaktifkan + enable_dialog: Mengklik OK akan mengubah status permintaan penelusuran ini menjadi Diaktifkan. + enable_dialog_title: Aktifkan Permintaan Penelusuran enable_success: Permintaan pelacakan berhasil diaktifkan. id: ID + complete: Tersedia Offline filter_by: by_date: Berdasarkan Tanggal location_separation: Lokasi Keterpisahan separation_cause: Penyebab Keterpisahan status: Status - label: Permintaan Pelacakan - name_of_inquirer: Nama dari Penyelidik - inquirer: Penyelidik + label: Permintaan Penelusuran + name_of_inquirer: Nama Pemohon Pencarian + inquirer: Pemohon Pencarian name: Nama register_new_tracing_request: Permintaan Penelusuran Baru selectable_date_options: - inquiry_date: Tanggal Penyelidikan - selected_records: '%{select_records} permintaan pelacakan telah dipilih' - selected_all_records: 'Pilih semua permintaan pelacakan %{total_records} yang cocok dengan permintaan ini.' - show_tracing_request: 'ID Permintaan Pelacakan %{short_id}' - tracing_requests: Permintaan Pelacakan + inquiry_date: Tanggal Permohonan Pencarian + selected_records: '%{select_records} permintaan penelusuran telah dipilih' + selected_all_records: 'Pilih semua permintaan penelusuran %{total_records} yang cocok dengan pencarian ini.' + show_tracing_request: 'ID Permintaan Penelusuran %{short_id}' + tracing_requests: Permintaan Penelusuran export: Ekspor + sort_by: Urutkan berdasar registry_records: id: ID label: Catatan Pendaftaran @@ -2980,6 +3197,7 @@ id: enable_dialog_title: Aktifkan Catatan Pendaftaran enable_dialog: Mengklik OK akan mengubah status catatan pendaftaran ini menjadi Diaktifkan enable_success: Catatan Pendaftaran berhasil diaktifkan + complete: Tersedia Offline filter_by: by_date: Berdasarkan Tanggal status: Status diff --git a/config/locales/incident_recorder/aeb.yml b/config/locales/incident_recorder/aeb.yml new file mode 100644 index 0000000000..4f77c096a5 --- /dev/null +++ b/config/locales/incident_recorder/aeb.yml @@ -0,0 +1,76 @@ +aeb: + permissions: + permission: + export_incident_recorder_xls: "تصدير سجل الحوادث xls" + exports: + incident_recorder_xls: + all: سجل الحوادث + one: سجل الحوادث + selected: 'تم اختياره لسجل الحوادث ' + 'yes': "نعم" + 'no': "لا" + gender: + male: "ذكر" + female: "أنثى" + both: "ذكر وأنثى" + age_group: + age: "السن" + 61_older: "61 عاما فأكثر" + unknown: "غير معروف" + header: "الفئة العمرية للجاني المزعوم" + age_type: + adult: "بالغ" + minor: "قاصر" + both: "شخص بالغ وشخص قاصر " + unknown: "غير معروف" + header: "نوع عمر الجاني المزعوم" + service_referral: + undecided: "غير مقرّر" + headers: + incident_id: "كود الحادثة" + survivor_code: "كود الناجية" + case_manager_code: "كود مدير الحالة" + case_worker_code: "كود اخصائي الحالة" + date_of_interview: "تاريخ المقابلة" + date_of_incident: "تاريخ الحادثة" + date_of_birth: "تاريخ الميلاد" + sex: "الجنس" + ethnicity: "الإثنية" + country_of_origin: "البلد الأصلي" + marital_status: "الحالة المدنية / الزوجية " + displacement_status: "وضع النزوح عند الإبلاغ عن الحادثة" + disability_type: "شخص من ذوي الإعاقة؟" + unaccompanied_separated_status: "طفل غير مصحوب أو منفصل عن ذويه؟" + stage_of_displacement: "مرحلة النزوح عند وقوع الحادثة" + time_of_day: "الوقت من اليوم الذي وقعت فيه الحادثة" + location: "موقع الحادثة" + county: "المقاطعة" + district: "الحي" + camp_town: "المخيم / البلدة" + camp: "المخيم" + gbv_type: "نوع العنف القائم على اساس النوع الاجتماعي" + harmful_traditional_practice: "عادات وتقاليد ضارّة" + goods_money_exchanged: "هل تم تبادل أموال أو بضائع أو مزايا و / أو خدمات فيما يتعلق بالحادثة؟" + abduction_type: "نوع الاختطاف/الإجبار " + previously_reported: "هل تم الإبلاغ عن هذه الحادثة سابقاً؟" + gbv_previous_incidents: "حوادث عنف قائم على اساس النوع الاجتماعي سابقة؟" + number_primary_perpetrators: "رقم الجاني (الجناة) الرئيسيين المزعومين" + perpetrator: + sex: "جنس الجاني المزعوم" + former: "حوادث سابقة ارتكبها هذا الجاني" + relationship: "علاقة الجاني المزعوم مع الناجية" + occupation: "مهنة الجاني المزعوم" + age_group: "الفئة العمرية للجاني المزعوم" + age_type: "نوع عمر الجاني المزعوم" + service: + referred_from: "نموذج الإحالة إليك؟" + safehouse_referral: "بيت آمن / مأوى" + medical_referral: "خدمات صحية / طبية" + psycho_referral: "خدمات نفسية اجتماعية" + wants_legal_action: "يطلب اتخاذ إجراء قانوني؟" + legal_referral: "خدمات المساعدة القانونية" + police_referral: "الشرطة / جهة أمنية أخرى" + livelihoods_referral: "برنامج سبل المعيشة" + protection_referral: "خدمات حماية الطفل / خدمات تعليمية" + consent: "تم إعطاء موافقة" + agency_code: "كود الهيئة المبلغة" diff --git a/config/locales/incident_recorder/ar-SY.yml b/config/locales/incident_recorder/ar-SY.yml new file mode 100644 index 0000000000..053e621653 --- /dev/null +++ b/config/locales/incident_recorder/ar-SY.yml @@ -0,0 +1,76 @@ +ar-SY: + permissions: + permission: + export_incident_recorder_xls: "تصدير سجل الحوادث xls" + exports: + incident_recorder_xls: + all: سجل الحوادث + one: سجل الحوادث + selected: 'تم اختياره لسجل الحوادث ' + 'yes': "نعم" + 'no': "لا" + gender: + male: "ذكر" + female: "أنثى" + both: "ذكر وأنثى" + age_group: + age: "السن" + 61_older: "61 عاما فأكثر" + unknown: "غير معروف" + header: "الفئة العمرية للجاني المزعوم" + age_type: + adult: "بالغ" + minor: "قاصر" + both: "شخص بالغ وشخص قاصر " + unknown: "غير معروف" + header: "نوع عمر الجاني المزعوم" + service_referral: + undecided: "غير مقرّر" + headers: + incident_id: "كود الحادثة" + survivor_code: "كود الناجية" + case_manager_code: "كود مدير الحالة" + case_worker_code: "كود اخصائي الحالة" + date_of_interview: "تاريخ المقابلة" + date_of_incident: "تاريخ الحادثة" + date_of_birth: "تاريخ الميلاد" + sex: "الجنس" + ethnicity: "الإثنية" + country_of_origin: "البلد الأصلي" + marital_status: "الحالة المدنية / الزوجية " + displacement_status: "وضع النزوح عند الإبلاغ عن الحادثة" + disability_type: "شخص من ذوي الإعاقة؟" + unaccompanied_separated_status: "طفل غير مصحوب أو منفصل عن ذويه؟" + stage_of_displacement: "مرحلة النزوح عند وقوع الحادثة" + time_of_day: "الوقت من اليوم الذي وقعت فيه الحادثة" + location: "موقع الحادثة" + county: "المقاطعة" + district: "الحي" + camp_town: "المخيم / البلدة" + camp: "المخيم" + gbv_type: "نوع العنف القائم على اساس النوع الاجتماعي" + harmful_traditional_practice: "عادات وتقاليد ضارّة" + goods_money_exchanged: "هل تم تبادل أموال أو بضائع أو مزايا و / أو خدمات فيما يتعلق بالحادثة؟" + abduction_type: "نوع الاختطاف/الإجبار " + previously_reported: "هل تم الإبلاغ عن هذه الحادثة سابقاً؟" + gbv_previous_incidents: "حوادث عنف قائم على اساس النوع الاجتماعي سابقة؟" + number_primary_perpetrators: "رقم الجاني (الجناة) الرئيسيين المزعومين" + perpetrator: + sex: "جنس الجاني المزعوم" + former: "حوادث سابقة ارتكبها هذا الجاني" + relationship: "علاقة الجاني المزعوم مع الناجية" + occupation: "مهنة الجاني المزعوم" + age_group: "الفئة العمرية للجاني المزعوم" + age_type: "نوع عمر الجاني المزعوم" + service: + referred_from: "نموذج الإحالة إليك؟" + safehouse_referral: "بيت آمن / مأوى" + medical_referral: "خدمات صحية / طبية" + psycho_referral: "خدمات نفسية اجتماعية" + wants_legal_action: "يطلب اتخاذ إجراء قانوني؟" + legal_referral: "خدمات المساعدة القانونية" + police_referral: "الشرطة / جهة أمنية أخرى" + livelihoods_referral: "برنامج سبل المعيشة" + protection_referral: "خدمات حماية الطفل / خدمات تعليمية" + consent: "تم إعطاء موافقة" + agency_code: "كود الهيئة المبلغة" diff --git a/config/locales/incident_recorder/ar.yml b/config/locales/incident_recorder/ar.yml index 2e050b4bde..6c7b5c1159 100644 --- a/config/locales/incident_recorder/ar.yml +++ b/config/locales/incident_recorder/ar.yml @@ -1,7 +1,7 @@ ar: permissions: permission: - export_incident_recorder_xls: "تحميل سجل الحوادث لجداول xls" + export_incident_recorder_xls: "تصدير سجل الحوادث xls" exports: incident_recorder_xls: all: سجل الحوادث @@ -27,10 +27,10 @@ ar: service_referral: undecided: "غير مقرّر" headers: - incident_id: "رمز الحادثة" - survivor_code: "رمز الناجية" - case_manager_code: "رمز مدير الحالة" - case_worker_code: "رمز الموظف المختص بالحالة" + incident_id: "كود الحادثة" + survivor_code: "كود الناجية" + case_manager_code: "كود مدير الحالة" + case_worker_code: "كود اخصائي الحالة" date_of_interview: "تاريخ المقابلة" date_of_incident: "تاريخ الحادثة" date_of_birth: "تاريخ الميلاد" @@ -39,13 +39,13 @@ ar: country_of_origin: "البلد الأصلي" marital_status: "الحالة المدنية / الزوجية " displacement_status: "وضع النزوح عند الإبلاغ عن الحادثة" - disability_type: "شخص يعاني من إعاقة؟" + disability_type: "شخص من ذوي الإعاقة؟" unaccompanied_separated_status: "طفل غير مصحوب أو منفصل عن ذويه؟" stage_of_displacement: "مرحلة النزوح عند وقوع الحادثة" time_of_day: "الوقت من اليوم الذي وقعت فيه الحادثة" location: "موقع الحادثة" county: "المقاطعة" - district: "القضاء" + district: "الحي" camp_town: "المخيم / البلدة" camp: "المخيم" gbv_type: "نوع العنف القائم على اساس النوع الاجتماعي" @@ -54,7 +54,7 @@ ar: abduction_type: "نوع الاختطاف/الإجبار " previously_reported: "هل تم الإبلاغ عن هذه الحادثة سابقاً؟" gbv_previous_incidents: "حوادث عنف قائم على اساس النوع الاجتماعي سابقة؟" - number_primary_perpetrators: "عدد الجناة المزعومين" + number_primary_perpetrators: "رقم الجاني (الجناة) الرئيسيين المزعومين" perpetrator: sex: "جنس الجاني المزعوم" former: "حوادث سابقة ارتكبها هذا الجاني" @@ -73,4 +73,4 @@ ar: livelihoods_referral: "برنامج سبل المعيشة" protection_referral: "خدمات حماية الطفل / خدمات تعليمية" consent: "تم إعطاء موافقة" - agency_code: "رمز المؤسسة المبلغة" + agency_code: "كود الهيئة المبلغة" diff --git a/config/locales/incident_recorder/en.yml b/config/locales/incident_recorder/en.yml index afae1356e0..2a19334d34 100644 --- a/config/locales/incident_recorder/en.yml +++ b/config/locales/incident_recorder/en.yml @@ -76,3 +76,6 @@ en: protection_referral: "CHILD PROTECTION SERVICES / EDUCATION SERVICES" consent: "CONSENT GIVEN" agency_code: "REPORTING AGENCY CODE" + number_primary_perpetrators: + more_than_three: "More than 3" + \ No newline at end of file diff --git a/config/locales/incident_recorder/hu.yml b/config/locales/incident_recorder/hu.yml index 5f24672468..255a126cfb 100644 --- a/config/locales/incident_recorder/hu.yml +++ b/config/locales/incident_recorder/hu.yml @@ -1 +1,73 @@ -hu: {} +hu: + permissions: + permission: + export_incident_recorder_xls: "'Incidensfelvevő' xls exportálása" + exports: + incident_recorder_xls: + all: Incidens rögzítő + 'yes': "Igen" + 'no': "Nem" + gender: + male: "M" + female: "F" + both: "M és F" + age_group: + age: "Életkor" + 61_older: "61 éves és idősebb" + unknown: "Ismeretlen" + header: "FELTÉTELEZETT ELKÖVETŐ KORCSOPORTJA" + age_type: + adult: "Felnőtt" + minor: "Jelentéktelen" + both: "Felnőtt & kiskorú" + unknown: "Ismeretlen" + header: "FELTÉTELEZETT ELKÖVETŐ ÉLETKOR TÍPUSA" + service_referral: + undecided: "Döntésképtelen" + headers: + incident_id: "ESEMÉNY AZONOSÍTÓJA" + survivor_code: "TÚLÉLŐ KÓD" + case_manager_code: "ÜGYKEZELŐI KÓD" + case_worker_code: "ÜGYINTÉZŐ KÓDJA" + date_of_interview: "AZ INTERJÚ IDŐPONTJA" + date_of_incident: "AZ ESEMÉNY IDŐPONTJA" + date_of_birth: "SZÜLETÉSI DÁTUM" + sex: "NEME" + ethnicity: "ETNIKUM" + country_of_origin: "SZÁRMAZÁSI ORSZÁG" + marital_status: "POLGÁRI / CSALÁDI ÁLLAPOT" + displacement_status: "AZ ELMOZDULÁS HELYZETE A JELENTÉSKOR" + disability_type: "FOGYATÉKKAL ÉLŐ SZEMÉLY?" + unaccompanied_separated_status: "KÍSÉRŐ NÉLKÜLI VAGY ELKÜLÖNÍTETT GYERMEK?" + stage_of_displacement: "AZ ELMOZDULÁS FÁZISA AZ ESEMÉNYKOR" + location: "INCIDENS HELYSZÍNE" + county: "ESEMÉNY MEGYÉJE" + district: "INCIDENSKÖRZET" + camp_town: "INCIDENS TÁBOR / VÁROS" + camp: "INCIDENS TÁBOR" + gbv_type: "GBV TÍPUS" + harmful_traditional_practice: "ÁRTALMAS HAGYOMÁNYOS GYAKORLAT" + goods_money_exchanged: "PÉNZ, ÁRU, JUTTATÁS ÉS/VAGY SZOLGÁLTATÁS CSERÉJE?" + abduction_type: "AZ EMBERRABLÁS TÍPUSA" + previously_reported: "KORÁBBAN JELENTETTE EZT AZ ESETET?" + gbv_previous_incidents: "KORÁBBI GBV INCIDENSEK?" + number_primary_perpetrators: "Nem. FELTÉTELEZETT ELSŐDLEGES ELKÖVETŐ(K)" + perpetrator: + sex: "FELTÉTELEZETT ELKÖVETŐ NEME" + former: "KORÁBBI INCIDENS AZ ELKÖVETŐVEL" + relationship: "FELTÉTELEZETT ELKÖVETŐ-TÚLÉLŐ KAPCSOLAT" + occupation: "FELTÉTELEZETT ELKÖVETŐ FOGLALKOZÁSA" + age_group: "FELTÉTELEZETT ELKÖVETŐ KORCSOPORTJA" + age_type: "FELTÉTELEZETT ELKÖVETŐ ÉLETKOR TÍPUSA" + service: + referred_from: "AJÁNLOTTÁK ÖNNEK?" + safehouse_referral: "MENEDÉKHÁZ / MENEDÉKHELY" + medical_referral: "EGÉSZSÉGÜGYI / ORVOSI SZOLGÁLTATÁSOK" + psycho_referral: "PSZICHOSZOCIÁLIS SZOLGÁLTATÁSOK" + wants_legal_action: "JOGI LÉPÉSEKET AKAR TENNI?" + legal_referral: "JOGSEGÉLYSZOLGÁLATOK" + police_referral: "RENDŐRSÉG / MÁS BIZTONSÁGI SZEREPLŐ" + livelihoods_referral: "MEGÉLHETÉST SEGÍTŐ PROGRAM" + protection_referral: "GYERMEKVÉDELMI / OKTATÁSI SZOLGÁLTATÁSOK" + consent: "BELEEGYEZÉS MEGADVA" + agency_code: "ADATSZOLGÁLTATÓ ÜGYNÖKSÉG KÓDJA" diff --git a/config/locales/incident_recorder/so.yml b/config/locales/incident_recorder/so.yml index 1da25c4387..dd73821d4b 100644 --- a/config/locales/incident_recorder/so.yml +++ b/config/locales/incident_recorder/so.yml @@ -1,21 +1,21 @@ so: permissions: permission: - export_incident_recorder_xls: "Diiwaangalinta dhacdooyinka waa lagudbin" + export_incident_recorder_xls: "U badal Diiwaangaliyaha dhacdooyinka file excel ah xls" exports: incident_recorder_xls: - all: Dhacddoyinka waa ladiiwaangali - one: Dhacddoyinka waa ladiiwaangali - selected: dhacddoyinka ladoortay waa ladiiwaangali - 'yes': "Haa" - 'no': "Maya" + all: "Diwaangaliyaha Dhacdada " + one: Diwaangaliyaha Dhacdada + selected: u doortay diiwaangaliyaha dhacdada + "yes": "Haa" + "no": "Maya" gender: - male: "M" - female: "F" - both: "M iyo F" + male: "Lab" + female: "Dhedig" + both: "Lab iyo Dhedig " age_group: - age: "Da'a" - 61_older: "61 iyo wixi kaweyn" + age: "Da'da " + 61_older: "61 jir & wixi kaweyn" unknown: "Aan lagaraneynin" header: "Kooxda da'da dembiilayaasha ee lagu eedeeyay" age_type: @@ -23,9 +23,9 @@ so: minor: "Yar" both: "Qaangadh iyo Yar" unknown: "Aan lagaraneynin" - header: "Kooxda da'da dembiilayaasha ee nooca lagu eedeeyay " + header: "da'da eedaysanaha dambiga " service_referral: - undecided: "Aan la goaamin" + undecided: "Aan la go'aamin" headers: incident_id: "Summadda Dhacdada" survivor_code: "Summadda Badbaadaha" @@ -44,7 +44,7 @@ so: stage_of_displacement: "Heerka Barakaca ee Dhacdada" time_of_day: "Wakhtiga iyo Maalinta Dhacdada" location: "Goobta Dhacdada" - county: "waddanka Dhacdadan ka dhacday " + county: "Dagmada ay Dhacdadani ka dhacday " district: "Degmada Dhacdada " camp_town: "Goobta/Magaalada Dhacdada" camp: "Goobta Dhacdada" diff --git a/config/locales/km.yml b/config/locales/km.yml index 08b2e40096..ef60d8d7ed 100644 --- a/config/locales/km.yml +++ b/config/locales/km.yml @@ -15,26 +15,24 @@ km: unavailable_offline: មិនអាចប្រើ គ្មានសេវាអ៊ីនធឺណិត online: មានសេវាអ៊ីនធឺណិត yes_label: 'បាទ/ចាស' - or_label: ឬ select_provider: ជ្រើសរើសអ្នកផ្តល់សេវា select_language: ជ្រើសរើស​ភាសា - log_in_primero_idp: "ចូលជាមួយនឹង%{idp_name}ឈ្មោះអ្នកប្រើប្រាស់" + log_in_primero_idp: ចូលជាមួយនឹង%{idp_name}ឈ្មោះអ្នកប្រើប្រាស់ offline_submitted_changes: អ្នកកំពុងគ្មានសេវាអ៊ីនធឺណិត។ ការកែសម្រួលរបស់អ្នកនឹងធ្វើបច្ចុប្បន្នភាព នៅពេលដែលមានសេវាអ៊ីនធឺណិត។ updated: ធ្វើបច្ចុប្បន្នភាព sync: success: "%{records}​កំណត់ត្រា​ធ្វើសមកាលកម្មដោយ​ជោគជ័យ។" error: - create: "មិនអាចបង្កើត%{record_type}។ សូមរកជំនួយ" - update: "ធ្វើបច្ចុប្បន្នភាព%{record_type}%{short_id}បរាជ័យ។​ សូមរកជំនួយ។ " - + create: មិនអាចបង្កើត%{record_type}។ សូមរកជំនួយ + update: 'ធ្វើបច្ចុប្បន្នភាព%{record_type}%{short_id}បរាជ័យ។​ សូមរកជំនួយ។ ' actions: approvals: ការអនុម័ត button: សកម្មភាព - close: បិទ + close: បិទករណី description: invalid: កំណត់ត្រា​មិន​ត្រឹមត្រូវ valid: កំណត់ត្រា​ត្រឹមត្រូវ - disable: បិទ + disable: បិទដំណើរការ (disable) enable: បើក incident_details_from_case: បញ្ចូល​ហេតុការណ៍ incident_from_case: បង្កើតហេតុការណ៍ @@ -56,12 +54,12 @@ km: agency_logos: និមិត្តសញ្ញា​ស្ថាប័ន code: លេខកូដ​ស្ថាប័ន description: ការពណ៌នា - disabled: បិទដំណើរការ + disabled: បិទដំណើរការ (disable) exclude_agency_from_lookups: មិនរាប់បញ្ចូលស្ថាប័នរនេះពីការស្វែងរក និងតម្រង exclude_agency_from_lookups_help: ពិនិត្យមើលប្រសិនបើស្ថាប័នមិនមានអ្នកប្រើប្រាស់ (ឧ. ភ្នាក់ងារត្រូវបានបន្ថែម ដូច្នេះនិមិត្តសញ្ញាអាចត្រូវបានអនុវត្តចំពោះការនាំចេញ។) label: ស្ថាប័ន - logo_enabled: "បង្ហាញនិមិត្តសញ្ញារបស់ភ្នាក់ងារនេះនៅក្នុង Primero?" - logo_enabled_help: "បង្ហាញនិមិត្តសញ្ញារបស់ស្ថាប័ននេះនៅក្នុង Primero?" + logo_enabled: បង្ហាញនិមិត្តសញ្ញារបស់ភ្នាក់ងារនេះនៅក្នុង Primero? + logo_enabled_help: បង្ហាញនិមិត្តសញ្ញារបស់ស្ថាប័ននេះនៅក្នុង Primero? logo_icon: រូបតំណាងនិមិត្តសញ្ញា logo_icon_help: វានឹងបង្ហាញនៅលើទំហំអេក្រង់តូច ថេប្លេត និងទូរសព្ទ។ នេះគួរតែជាការ៉េ។ logo_large: និមិត្តសញ្ញាធំ @@ -70,12 +68,12 @@ km: created: បាន​បង្កើតស្ថាប័ន​​ដោយ​ជោគជ័យ។ updated: បាន​ធ្វើ​បច្ចុប្បន្នភាពស្ថាប័ន​ដោយ​ជោគជ័យ។ name: ឈ្មោះ​ស្ថាប័ន - pdf_logo_option: "ធ្វើឱ្យមាននិមិត្តសញ្ញាសម្រាប់ការនាំចេញ PDF?" + pdf_logo_option: ធ្វើឱ្យមាននិមិត្តសញ្ញាសម្រាប់ការនាំចេញ PDF? pdf_logo_option_help: 'ចំណាំ៖ និមិត្តសញ្ញាស្ថាប័នររបស់អ្នកប្រើមានសម្រាប់ពួកគេតាមលំនាំដើម ដូច្នេះអ្នកគ្រាន់តែពិនិត្យមើលវាប្រសិនបើអ្នកចង់ឱ្យនិមិត្តសញ្ញានេះមានសម្រាប់អ្នកប្រើប្រាស់ទាំងអស់។' services: សេវាកម្ម​ស្ថាប័ន terms_of_use: ល័ក្ខខ័ណ្ឌនៃការប្រើប្រាស់ terms_of_use_help: អនុញ្ញាតតែឯកសារ PDF ប៉ុណ្ណោះ។ - terms_of_use_download_button: "ទាញយកឯកសារ PDF " + terms_of_use_download_button: 'ទាញយកឯកសារ PDF ' terms_of_use_enabled: បង្ហាញល័ក្ខខ័ណ្ឌនៃការប្រើប្រាស់ approvals: approved_by: ​អនុម័តដោយ @@ -98,7 +96,7 @@ km: action: សកម្មភាព description: ការពណ៌នា record_owner: ម្ចាស់​កំណត់​ត្រា - timestamp: "ពេលវេលា " + timestamp: 'ពេលវេលា ' user_name: បានអនុវត្តដោយ bulk_export: file_name: ឯកសារ @@ -108,7 +106,7 @@ km: status: ស្ថានភាព form_export: label: ​ការ​កំណត់ទម្រង់នាំចេញ - include_hidden: "បន្ថែមទាំងទម្រង់ និងសំណួរលាក់?" + include_hidden: បន្ថែមទាំងទម្រង់ និងសំណួរលាក់? file_name: បង្កើតឈ្មោះឯកសារផ្ទាល់ខ្លួនរបស់អ្នក (មានជម្រើស) success_message: បានបង្កើតឯកសារនាំចេញដោយជោគជ័យ buttons: @@ -132,13 +130,13 @@ km: clear_default: លុបលំនាំដើម clear_selection: លុបការជ្រើសរើស clear: លុប - close: បិទ + close: បិទករណី continue: បន្ត create_case: បង្កើតករណី create_incident: បង្កើតហេតុការណ៍ - create_new_record: "បង្កើតថ្មី %{model}" + create_new_record: បង្កើតថ្មី %{model} delete: លុប - disable: បិទដំណើរការ + disable: បិទដំណើរការ (disable) disable_photo_wall: បិទ​ផ្ទាំង​រូបថត done: រួចរាល់ download: ទាញយក @@ -152,7 +150,7 @@ km: filter_label: 'ចម្រាញ់ទិន្នន័យ៖' filter_restore: ស្ដារ​ទៅ​ការ​កំណត់​ប្រព័ន្ធ​ឡើងវិញ find_tracing_match: ស្វែងរកការផ្គូផ្គង​ - flag_model: "សម្គាល់ %{model}" + flag_model: សម្គាល់ %{model} flag_records: សម្គាល់ flags: សម្គាល់ guidance: កំណត់សម្គាល់ @@ -165,7 +163,7 @@ km: ok: យល់ព្រម print: បោះពុម្ព reassign: ចាត់តាំង - referral: "បញ្ជូន " + referral: 'បញ្ជូន ' referral_again: បញ្ជូនម្តងទៀត reject: បដិសេដ remove_referrals: ដក​ការ​បញ្ជូន​ចេញ @@ -184,9 +182,9 @@ km: sort_by_tr: សំណើ​ស្វែងរក sync: សមកាលកម្ម submit: បញ្ជូន - transfer: "ផ្ទេរ " - unflag_model: "ដកសម្គាល់ %{model}" - unflag_model_history: "ប្រវត្តិ​សម្គាល់ %{model}" + transfer: 'ផ្ទេរ ' + unflag_model: ដកសម្គាល់ %{model} + unflag_model_history: ប្រវត្តិ​សម្គាល់ %{model} unmark_for_mobile: មិន​ប្រើ​សម្រាប់​ទូរស័ព្ទ update: ធ្វើបច្ចុប្បន្នភាព view: មើល @@ -200,13 +198,13 @@ km: back_to_results: ត្រឡប់ទៅលទ្ធផល back_to_search: ត្រឡប់ទៅស្វែងរក search_by: ស្វែងរកតាម - search_for: "ស្វែងរក %{record_type}" + search_for: ស្វែងរក %{record_type} results: លទ្ធផល details: លម្អិត select: ជ្រើសរើស deselect: ដោះការជ្រើសរើសចេញ enter_id_number: បញ្ចូលលេខកូដ ដើម្បីស្វែងរកកំណត់ត្រាដែលមានស្រាប់ - id_search_no_results: "មិនមានការផ្គូផ្គងនៅក្នុងប្រព័ន្ធសម្រាប់%{search_query} ទេ។ សូមបង្កើតកំណត់ត្រាថ្មី។" + id_search_no_results: មិនមានការផ្គូផ្គងនៅក្នុងប្រព័ន្ធសម្រាប់%{search_query} ទេ។ សូមបង្កើតកំណត់ត្រាថ្មី។ messages: disabled: ករណីនេះត្រូវបានបិទដំណើរហើយ update_success: 'បាន​ធ្វើ​បច្ចុប្បន្ន​ភាព​ករណី %{record_id} ដោយជោគជ័យ។' @@ -215,7 +213,7 @@ km: creation_success_queue: 'បាន​បង្កើត​កំណត់​ត្រា​ដោយ​ជោគជ័យ។' already_matched: អ្នក​ស្វែងរកត្រូវបានផ្គូផ្គងនឹងករណីរបស់អ្នករួចហើយ។ already_matched_not_current_case: មានករណីមួយនេះរួចហើយនៅក្នុងប្រព័ន្ធ។ - not_found_case: "%{search_value}មិនមានករណីបានរកឃើញ ។ បង្កើតករណីថ្មី។" + not_found_case: '%{search_value}មិនមានករណីបានរកឃើញ ។ បង្កើតករណីថ្មី។' introductory_sentence: សូមបញ្ជាក់ការយល់ព្រមពីអតិថិជនក្នុងការទទួលសេវាគ្រប់គ្រងករណី និងសម្រាប់រក្សាទុកទិន្នន័យរបស់ពួកគេនៅក្នុង Primero ។ consent_agreements_required: សូមជ្រើសរើសយ៉ាងហោចណាស់ជម្រើសមួយពីការយល់ព្រមទាំងនេះ legitimate_basis_required: សូមជ្រើសរើសយ៉ាងហោចណាស់ជម្រើសមួយពីការចាត់ថ្នាក់មូលដ្ឋានស្របច្បាប់។ @@ -223,13 +221,13 @@ km: save_text: មុននឹងបន្ត សូមរក្សាទុករាល់ការផ្លាស់ប្តូរសម្រាប់ករណី។ skip_and_create: រំលង រួចបង្កើតករណីថ្មី search_existing: ស្វែងរកករណីដែលមានស្រាប់ - search_helper_text: "មូលហេតុ? ដើម្បីការពារការបញ្ចូលករណីជាន់គ្នា។" + search_helper_text: មូលហេតុ? ដើម្បីការពារការបញ្ចូលករណីជាន់គ្នា។ consent_agreements: ជ្រើសរើសកិច្ចព្រមព្រៀងទាំងអស់ដែលសមស្រប legitimate_basis: ជ្រើសរើសការចាត់ថ្នាក់មូលដ្ឋានស្របច្បាប់ទាំងអស់ដែលអនុវត្ត workflow: assessment: ការ​ប៉ាន់ប្រមាណ case_plan: ផែនការករណី - closed: បានបិទ + closed: បានបិទករណី created_on: បានបង្កើត​នៅ in_progress: កំពុងដំណើរការ new: ថ្មី @@ -246,7 +244,7 @@ km: cases: action_plan: ផែនការសកម្មភាព age: អាយុ - age_estimated: "អាយុប៉ាន់ស្មាន?" + age_estimated: អាយុប៉ាន់ស្មាន? agency: ស្ថាប័ន apply_filter: អនុវត្ត approval_comments: មតិយោបល់ @@ -271,7 +269,7 @@ km: closure: ការ​បិទ date_of_birth: ថ្ងៃខែឆ្នាំកំណើត disable_dialog: ចុច​យល់ព្រម(OK) នឹងធ្វើឱ្យករណីនេះបិទដំណើរការក្នុងប្រព័ន្ធ (disabled)។ - disable_dialog_title: បិទករណី (disable case) + disable_dialog_title: បិទដំណើរការ (disable) disable_success: បិទដំណើរការករណីដោយជោគជ័យ enable_dialog: ចុច​យល់ព្រម(OK) នឹង​ធ្វើឱ្យករណីនេះ​បើកដំណើរការក្នុងប្រព័ន្ (enabled)។ enable_dialog_title: បើកករណី (enable case) @@ -279,7 +277,7 @@ km: export: នាំចេញ mark_for_offline: title: ប្រើសម្រាប់ពេលគ្មានសេវាអីនធឺណេត - text: "តើអ្នកពិតជាចង់កំណត់ករណីនេះសម្រាប់ប្រើពេលដែលគ្មានសេវាអីនធឺណេតមែនទេ?" + text: តើអ្នកពិតជាចង់កំណត់ករណីនេះសម្រាប់ប្រើពេលដែលគ្មានសេវាអីនធឺណេតមែនទេ? success: ករណីត្រូវបានកំណត់សម្រាប់ប្រើពេលគ្មានសេវាអីនធឺណេត ដោយជោគជ័យ filter_by: 3month_inactivity: សម្រាប់លើស​ពី 3 ខែ @@ -288,7 +286,7 @@ km: age_12_17: 12 - 17 age_18_more: 18+ age_6_11: 6 - 11 - age_range: "ចន្លោះអាយុ " + age_range: 'ចន្លោះអាយុ ' agency: អង្គភាព approval_status: ស្ថានភាពអនុម័ត approvals: @@ -299,7 +297,7 @@ km: by_date: នៅកាលបរិច្ឆេទ case_open_date: កាលបរិច្ឆេទ​បើក​ករណី case_plan: ផែនការករណី - closed: បានបិទ + closed: បានបិទករណី closure: បិទករណី current_location: ទីតាំងបច្ចុប្បន្ន date: កាលបរិច្ឆេទ @@ -309,21 +307,21 @@ km: enabled_disabled: បើក/បិទដំណើរការករណី female: ស្រី flag: បានសម្គាល់ - flag_label: "បាន​សម្គាល់​ឬ?" + flag_label: បាន​សម្គាល់​ឬ? gbv_closure: ​បិទករណី high: ខ្ពស់ low: ទាប male: ប្រុស medium: មធ្យម mobile: ទូរស័ព្ទ - mobile_label: "ប្រើ​សម្រាប់​ទូរស័ព្ទ​ឬ?" + mobile_label: ប្រើ​សម្រាប់​ទូរស័ព្ទ​ឬ? my_cases: ករណីរបស់ខ្ញុំ no_action: មិនត្រូវការអន្តរាគមន៍ no_activity: មិនត្រូវការអន្តរាគមន៍ open: បើក other: ផ្សេងៗ photo: រូបថត - photo_label: "មានរូបថតដែរឬទេ?" + photo_label: មានរូបថតដែរឬទេ? protection_concerns: បញ្ហាដែលជាកង្វល់​ protection_status: ស្ថានភាពការពារ record_state: ស្ថានភាព​ករណី @@ -364,7 +362,7 @@ km: referral_done: ការ​ចុច​ រួចរាល់ ​មាន​ន័យ​ថា​អ្នក​បានបញ្ចប់​ការបញ្ជូន​ករណី​នេះហើយ ហើយអ្នកមិនអាចចូលមើលកំណត់ត្រានេះទៀតទេ។ referral_done_success: បញ្ចប់ការ​បញ្ជូន​ referral_accepted_header: ទទួល​ការ​បញ្ជូន - referral_accepted: "តើអ្នកប្រាកដទេ? អ្នកនឹងទទួលខុសត្រូវក្នុងការបំំពេញព័ត៌មានផ្សេងៗដែលទាក់ទងនឹងករណីបញ្ជូនមួយនេះ" + referral_accepted: តើអ្នកប្រាកដទេ? អ្នកនឹងទទួលខុសត្រូវក្នុងការបំំពេញព័ត៌មានផ្សេងៗដែលទាក់ទងនឹងករណីបញ្ជូនមួយនេះ referral_accepted_success: យល់ព្រមទទួលយកការ​បញ្ជូន​ referral_rejected: ការ​ចុច​ 'បដិសេធ' ​មាន​ន័យ​ថា​អ្នកមិន​ទាន់រួចរាល់​ដើម្បី​ទទួលយក​ការ​ទទួល​ខុស​ត្រូវ​​សម្រាប់​បញ្ជូនករណីនេះ​នៅ​ពេល​នេះ​ទេ។ សូម​បញ្ចូល​មូលហេតុ​ដែល​អ្នក​បដិសេធ​ករណី​បញ្ជូននេះ នៅ​ពេល​អ្នក​ចុច'បដិសេធ' ​ អ្នក​នឹង​លែង​អាច​ចូលប្រើប្រាស់​កំណត់ត្រា​នេះ​បាន​ហើយ។ referral_rejected_success: ករណីបញ្ជូនបានបដិសេធ @@ -381,22 +379,22 @@ km: reopen_success: បើកករណីឡើងវិញដោយជោគជ័យ request_approval_failure: មានបញ្ហា សូមទាក់ទងផ្នែកជំនួយ។ request_approval_select: ស្នើសុំការ​អនុម័ត​សម្រាប់ - request_approval_success_action_plan: "ការអនុម័តត្រូវបានស្នើសំុសម្រាប់%{approval_label}​ទម្រង់" - request_approval_success_assessment: "ការអនុម័តត្រូវបានស្នើសំុសម្រាប់%{approval_label}​ទម្រង់" - request_approval_success_case_plan: "ការអនុម័តត្រូវបានស្នើសំុសម្រាប់%{approval_label}​ទម្រង់" - request_approval_success_closure: "ការអនុម័តត្រូវបានស្នើសំុសម្រាប់%{approval_label}​ទម្រង់" - request_approval_success_gbv_closure: "ការអនុម័តត្រូវបានស្នើសំុសម្រាប់%{approval_label}​ទម្រង់" + request_approval_success_action_plan: ការអនុម័តត្រូវបានស្នើសំុសម្រាប់%{approval_label}​ទម្រង់ + request_approval_success_assessment: ការអនុម័តត្រូវបានស្នើសំុសម្រាប់%{approval_label}​ទម្រង់ + request_approval_success_case_plan: ការអនុម័តត្រូវបានស្នើសំុសម្រាប់%{approval_label}​ទម្រង់ + request_approval_success_closure: ការអនុម័តត្រូវបានស្នើសំុសម្រាប់%{approval_label}​ទម្រង់ + request_approval_success_gbv_closure: ការអនុម័តត្រូវបានស្នើសំុសម្រាប់%{approval_label}​ទម្រង់ request_approval_type_of_case_plan: ​ការ​អនុម័ត​ប្រភេទផែនការករណី - request_approve_action_plan: "អនុម័ត​ផែនការ​សកម្មភាព?" - request_approve_bia: "អនុម័តការប៉ាន់ប្រមាណ?" - request_approve_case_plan: "អនុម័ត​ផែនការ​ករណី?" - request_approve_closure: "អនុម័ត​ការបិទករណី?" + request_approve_action_plan: អនុម័ត​ផែនការ​សកម្មភាព? + request_approve_bia: អនុម័តការប៉ាន់ប្រមាណ? + request_approve_case_plan: អនុម័ត​ផែនការ​ករណី? + request_approve_closure: អនុម័ត​ការបិទករណី? request_approve_gbv_closure: អនុម័ត​ការបិទករណី - revoke_failure: "មានបញ្ហាខណៈពេលលុបចោល%{transition_type} សូមទាក់ទងផ្នែកជំនួយ។" - revoke_message: "ដោយចុច 'ដកហូត' អ្នកនឹងដកសិទ្ធិ%{transition_type}ចូលដំណើរការរបស់អ្នកទទួលទៅករណីនេះ។" - revoke_success_message: "ករណី%{case_id}%{transition_type}ទៅ%{recipient_username}ត្រូវបានបោះបង់។" + revoke_failure: មានបញ្ហាខណៈពេលលុបចោល%{transition_type} សូមទាក់ទងផ្នែកជំនួយ។ + revoke_message: ដោយចុច 'ដកហូត' អ្នកនឹងដកសិទ្ធិ%{transition_type}ចូលដំណើរការរបស់អ្នកទទួលទៅករណីនេះ។ + revoke_success_message: ករណី%{case_id}%{transition_type}ទៅ%{recipient_username}ត្រូវបានបោះបង់។ save_filter: រក្សាទុក - selected_all_records: "ជ្រើសរើសករណីទាំងអស់%{total_records}ដែលត្រូវនឹងសំណួរនេះ។" + selected_all_records: ជ្រើសរើសករណីទាំងអស់%{total_records}ដែលត្រូវនឹងសំណួរនេះ។ selected_records: 'ជ្រើសរើស%{select_records}ករណី' sex: ភេទ show_case: 'លេខកូដ​ករណី​ (ខ្លី) %{short_id}' @@ -413,9 +411,9 @@ km: label: យល់ព្រមចែករំលែកព័ត៌មានសម្រាប់ការស្វែងរក help_text: ប្រសិនបើសំណួរនេះគឺ 'ទេ' នោះកំណត់ត្រាករណីរបស់កុមារនឹងមិនបង្ហាញនៅក្នុងការផ្គូផ្គងជាមួយសំណើស្វែងរកអ្នកសួរទេ។ wishes_child_family_tracing: - label: "តើ​កុមារ​ចង់​ស្វែងរក​សមាជិក​គ្រួសារ​ដែ​រឬទេ?" + label: តើ​កុមារ​ចង់​ស្វែងរក​សមាជិក​គ្រួសារ​ដែ​រឬទេ? wishes_reunification: - label: "តើ​កុមារ​ចង់​ឱ្យមាន​ការ​បង្រួមបង្រួម​គ្រួសារ​ដែ​រឬទេ?" + label: តើ​កុមារ​ចង់​ឱ្យមាន​ការ​បង្រួមបង្រួម​គ្រួសារ​ដែ​រឬទេ? options: yes_as_soon_as_possible: ប្រាកដណាស់ ឆាប់ៗតាមដែលអាចធ្វើបាន yes_but_later: យល់ តែចាំលើកក្រោយ @@ -427,9 +425,9 @@ km: label: មើលឃើញបំណងប្រាថ្នារបស់កុមារ survivor_code: លេខកូដ​ជនរងគ្រោះ transfer_accepted: ដោយ​ចុច​ 'ព្រម​ទទួល' អ្នកព្រម​ទទួល​​ចំពោះ​ការ​ទទួល​ខុសត្រូវ​សម្រាប់​ករណី​នេះ នៅ​ពេល​អ្នក​ចុច​ 'យល់ព្រម' អ្នក​នឹង​ក្លាយ​ជា​ម្ចាស់​កំណត់ត្រា​នៅ​​ក្នុង​ប្រព័ន្ធ។ - transfer_managed_user_accepted: ដោយ​ចុច​ 'ព្រម​ទទួល' អ្នកព្រម​ទទួល​​ចំពោះ​ការ​ទទួល​ខុសត្រូវ​សម្រាប់​ករណី​នេះ នៅ​ពេល​អ្នក​ចុច​ 'យល់ព្រម' អ្នក​នឹង​ក្លាយ​ជា​ម្ចាស់​កំណត់ត្រា​នៅ​​ក្នុង​ប្រព័ន្ធ។ - transfer_managed_user_rejected: "ការ​ចុច​ 'បដិសេធ' ​មាន​ន័យ​ថា​អ្នកមិន​ទាន់រួចរាល់​ដើម្បី​ទទួលយក​ការ​ទទួល​ខុស​ត្រូវ​​សម្រាប់​ករណី%{transitioned_to}​នៅ​ពេល​នេះ​បាន​ទេ។ សូម​បញ្ចូល​មូលហេតុ​ដែល​អ្នក​បដិសេធ​ករណី%{transitioned_to}​នេះ នៅ​ពេល​អ្នក​ចុចអ្នក​ចុច​'បដិសេធ' ​ អ្នក​នឹង​លែង​អាច​ចូលប្រើប្រាស់​កំណត់ត្រា​នេះ​បាន​ហើយ។" - transfer_accepted_rejected: "ករណី%{record_id}ផ្ទេរត្រូវបានបដិសេធ" + transfer_managed_user_accepted: ដោយ​ចុច​ 'ព្រម​ទទួល' %{transitioned_to}​នឹងទទួល​ខុសត្រូវ​សម្រាប់​ករណី​នេះ នៅ​ពេល​អ្នក​ចុច​ 'យល់ព្រម' អ្ន%{transitioned_to}នឹង​ក្លាយ​ជា​ម្ចាស់​កំណត់ត្រា​នៅ​​ក្នុង​ប្រព័ន្ធ។ + transfer_managed_user_rejected: ការ​ចុច​ 'បដិសេធ' ​មាន​ន័យ​ថា​អ្នកមិន​ទាន់រួចរាល់​ដើម្បី​ទទួលយក​ការ​ទទួល​ខុស​ត្រូវ​​សម្រាប់​ករណី%{transitioned_to}​នៅ​ពេល​នេះ​បាន​ទេ។ សូម​បញ្ចូល​មូលហេតុ​ដែល​អ្នក​បដិសេធ​ករណី%{transitioned_to}​នេះ នៅ​ពេល​អ្នក​ចុចអ្នក​ចុច​'បដិសេធ' ​ អ្នក​នឹង​លែង​អាច​ចូលប្រើប្រាស់​កំណត់ត្រា​នេះ​បាន​ហើយ។ + transfer_accepted_rejected: ករណី%{record_id}ផ្ទេរត្រូវបានបដិសេធ transfer_accepted_success: បានទទួលយកការផ្ទេរ​​ដោយ​ជោគជ័យ។ transfer_reject_reason_label: មូលហេតុ​បដិសេធ transfer_rejected: ការ​ចុច​ 'បដិសេធ' ​មាន​ន័យ​ថា​អ្នកមិន​ទាន់រួចរាល់​ដើម្បី​ទទួលយក​ការ​ទទួល​ខុស​ត្រូវ​​សម្រាប់​ករណីនេះ​នៅ​ពេល​នេះ​បាន​ទេ។ សូម​បញ្ចូល​មូលហេតុ​ដែល​អ្នក​បដិសេធ​ករណី​នេះ នៅ​ពេលអ្នក​ចុច​'បដិសេធ' ​ អ្នក​នឹង​លែង​អាច​ចូលប្រើប្រាស់​កំណត់ត្រា​នេះ​បាន​ហើយ។ @@ -458,11 +456,11 @@ km: date_of_creation: កាលបរិច្ឆេទបង្កើត registration_date: កាលបរិច្ឆេទ​ចុះឈ្មោះ configurations: - apply_label: "តើ​អ្នក​ប្រាកដ​ឬ​អត់? ប្រសិនបើអ្នកអនុវត្ត ការកំណត់(setting)នៅក្នុងការកំណត់(confi)នេះនឹងត្រូវបានអនុវត្តចំពោះប្រព័ន្ធ។ អ្នកនឹងបាត់បង់ការកំណត់បច្ចុប្បន្នរបស់អ្នកទាំងអស់ ហើយនឹងមិនអាចយកពួកវាមកវិញបានទេ លុះត្រាតែអ្នកបានរក្សាទុកពួកវានៅក្នុងការកំណត់មួយផ្សេងទៀតរួចហើយ។" + apply_label: តើ​អ្នក​ប្រាកដ​ឬ​អត់? ប្រសិនបើអ្នកអនុវត្ត ការកំណត់(setting)នៅក្នុងការកំណត់(configuration)នេះនឹងត្រូវបានអនុវត្តចំពោះប្រព័ន្ធ។ អ្នកនឹងបាត់បង់ការកំណត់បច្ចុប្បន្នរបស់អ្នកទាំងអស់ ហើយនឹងមិនអាចយកពួកវាមកវិញបានទេ លុះត្រាតែអ្នកបានរក្សាទុកពួកវានៅក្នុងការកំណត់មួយផ្សេងទៀតរួចហើយ។ apply_label_bold: Primero នឹងមិនអាចប្រើបានក្នុងរយៈពេលពីរបីនាទី ខណៈពេលដែលការផ្លាស់ប្តូរកំពុងដំណើរការ។ version_mismatch_tooltip: អ្នក​មិន​អាច​អនុវត្ត​ការ​កំណត់​រចនាសម្ព័ន្ធ​នេះ​បាន​ទេ ព្រោះ​វា​ត្រូវ​បាន​បង្កើត​ឡើង​ដោយ​ប្រើជំនាន់ Primero ដែលខ្ពស់​ជាងប្រព័ន្ធដែល​អ្នក​កំពុង​ដំណើរការ។ សូមរង់ចាំរហូតដល់ចាប់ផ្តើមប្រើប្រាស់ជំនាន់ចុងក្រោយបំផុតរបស់កម្មវិធី Primero។ send_header: ផ្ញើទៅគេហទំព័រផលិតកម្ម - send_text: "តើ​អ្នក​ប្រាកដ​ឬ​ទេ? ប្រសិនបើអ្នកចុចផ្ញើ អ្នកនឹងផ្ញើការកំណត់រចនាសម្ព័ន្(configuration)ធនេះទៅកាន់គេហទំព័រផលិតកម្ម(production site)របស់អ្នក។ ការកំណត់រចនាសម្ព័ន្ធនេះនឹងមិនត្រូវបានអនុវត្តលើគេហទំព័រផលិតកម្មទេ ទាល់តែអ្នកគ្រប់គ្រងនៅលើគេហទំព័រនោះអនុវត្តវាដោយដៃ។" + send_text: តើ​អ្នក​ប្រាកដ​ឬ​ទេ? ប្រសិនបើអ្នកចុចផ្ញើ អ្នកនឹងផ្ញើការកំណត់រចនាសម្ព័ន្(configuration)នេះទៅកាន់គេហទំព័រផលិតកម្ម(production site)របស់អ្នក។ ការកំណត់រចនាសម្ព័ន្ធនេះនឹងមិនត្រូវបានអនុវត្តលើគេហទំព័រផលិតកម្មទេ ទាល់តែអ្នកគ្រប់គ្រងនៅលើគេហទំព័រនោះអនុវត្តវាដោយដៃ។ attributes: created_by: បង្កើត​ដោយ date_created: កាលបរិច្ឆេទបង្កើត @@ -472,7 +470,7 @@ km: name: ឈ្មោះ version: កំណែការកំណត់ primero_version: ជំនាន់ Primero - delete_label: "តើអ្នកប្រាកដថាចង់ធ្វើបែបនេះទេ? នេះតំណាងឱ្យការកំណត់ទាំងអស់ពីពេលដែលការកំណត់រចនាសម្ព័ន្ធនេះត្រូវបានបង្កើត។ អ្នក​នឹង​មិន​អាច​ត្រឡប់​ទៅ​វិញ​និង​ស្ដារ​ការ​កំណត់​ទាំង​នេះ​នៅ​ពេល​ដែល​អ្នក​លុប​ការ​កំណត់​រចនាសម្ព័ន្ធ​នេះទេ​។" + delete_label: តើអ្នកប្រាកដថាចង់ធ្វើបែបនេះទេ? នេះតំណាងឱ្យការកំណត់ទាំងអស់ពីពេលដែលការកំណត់រចនាសម្ព័ន្ធនេះត្រូវបានបង្កើត។ អ្នក​នឹង​មិន​អាច​ត្រឡប់​ទៅ​វិញ​និង​ស្ដារ​ការ​កំណត់​ទាំង​នេះ​នៅ​ពេល​ដែល​អ្នក​លុប​ការ​កំណត់​រចនាសម្ព័ន្ធ​នេះទេ​។ explanation: 'ការចុចរក្សាទុកនឹងបង្កើតកំណត់ត្រានៃការកំណត់បច្ចុប្បន្នទាំងអស់ (ឧទាហរណ៍៖ តួនាទី ភ្នាក់ងារ ទម្រង់) នៅចំណុចនេះក្នុងពេលនេះ។ បន្ទាប់ពីអ្នករក្សាទុក អ្នកអាចរុញការផ្លាស់ប្តូរទាំងនេះទៅ Primero ។ ប្រសិនពេលអនាគត អ្នកធ្វើការផ្លាស់ប្តូរការកំណត់ដែលអ្នកមិនចង់ធ្វើវិញ អ្នកអាចអនុវត្តកំណត់ត្រាការកំណត់នេះ ដើម្បីស្ដាររាល់ការផ្លាស់ប្តូរការកំណត់រចនាដែលអ្នកមាននៅពេលនេះ។' label: ការកំណត់ label_new: ការកំណត់ថ្មី @@ -508,7 +506,7 @@ km: updated: ក្រមសីលធម៌បានរក្សាទុកដោយជោគជ័យ។ dashboard: activity: សកម្មភាព - admin_only: "ចុច​លើ %{links} ដើម្បី​ធ្វើការ​ផ្លាស់ប្ដូរ​ចំពោះ​កម្មវិធី។" + admin_only: ចុច​លើ %{links} ដើម្បី​ធ្វើការ​ផ្លាស់ប្ដូរ​ចំពោះ​កម្មវិធី។ all_cases: គ្រប់ករណី​ទាំង​អស់ all_services_implemented: បានអនុវត្តសេវា and: 'និង' @@ -558,9 +556,9 @@ km: cases_by_workflow: ករណី​តាម​លំហូរ​ការងារ cases_this_week: ករណី​ក្នុង​សប្ដាហ៍​នេះ cases_to_assign: ករណី​ត្រូវ​ចាត់ចែង - closed: បានបិទ - closed_last_week: បាន​បិទ (សប្ដាហ៍​មុន) - closed_this_week: បាន​បិទ (សប្ដាហ៍​នេះ) + closed: បានបិទករណី + closed_last_week: បាន​បិទករណី (សប្ដាហ៍​មុន) + closed_this_week: បាន​បិទករណី (សប្ដាហ៍​នេះ) comprehensive_need_intervention: ការឆ្លើយតប​ពេញលេញ count_new_bia_approvals: other: '%{stat} ការ​អនុម័តថ្មី %{stat_type}' @@ -569,17 +567,17 @@ km: count_new_closure_approvals: other: '%{stat}ថ្មី %{stat_type} អនុម័ត' count_pending_approval_total: - other: 'អ្នក​មាន​%{stat}កំពុង​រង់ចាំ%{stat_type}អនុម័ត' + other: អ្នក​មាន​%{stat}កំពុង​រង់ចាំ%{stat_type}អនុម័ត count_pending_transfers: - other: 'អ្នកមាន​ការ​ផ្ទេរ %{stat}កំពុង​រង់ចាំ' + other: អ្នកមាន​ការ​ផ្ទេរ %{stat}កំពុង​រង់ចាំ count_records_new: other: និង%{stat}ករណីថ្មី count_records_total: - other: 'អ្នក​មាន​ %{stat} ករណីសរុប' + other: អ្នក​មាន​ %{stat} ករណីសរុប count_referrals_new: other: និង%{stat}ការបញ្ជូនថ្មី count_referrals_total: - other: 'អ្នកមាន%{stat}ការបញ្ជូនសរុប' + other: អ្នកមាន%{stat}ការបញ្ជូនសរុប count_rejected_approval_total: other: 'និង%{stat}បាន​បដិសេធ %{stat_type}អនុម័ត ' count_rejected_transfers: @@ -587,16 +585,16 @@ km: count_risk_level_new: other: និង %{stat}ករណី​ហានីភ័យថ្មី%{stat_type} count_risk_level_total: - other: 'អ្នកមាន%{stat}%{stat_type}ករណីហានិភ័យ' - count_waiting_for_acceptance_transfers: "អ្នក​មាន​ការ​ផ្ទេរ%{stat}កំពុង​រង់ចាំ​​" + other: អ្នកមាន%{stat}%{stat_type}ករណីហានិភ័យ + count_waiting_for_acceptance_transfers: អ្នក​មាន​ការ​ផ្ទេរ%{stat}កំពុង​រង់ចាំ​​ current_owner: ម្ចាស់​បច្ចុប្បន្ន dash_case_incident_overview: ករណីរបស់ខ្ញុំ dash_group_overview: ករណីក្នុងក្រុមរបស់ខ្ញុំ dash_shared_from_my_team: ករណីបញ្ជូន/ផ្ទេរពីក្រុមខ្ញុំ - dash_shared_with_me: ករណីបញ្ជូន/ផ្ទេរមកខ្ញុំ + dash_shared_with_me: ករណីបញ្ជូន ឬផ្ទេរមកខ្ញុំ dash_shared_with_my_team: ករណីបញ្ជូន/ផ្ទេរមកក្រុមខ្ញុំ dash_shared_with_my_team_overview: ករណីបញ្ជូន/ផ្ទេរមកក្រុមខ្ញុំ - dash_shared_with_others: ករណីបញ្ជូន/ផ្ទេរពីខ្ញុំ + dash_shared_with_others: 'ករណីបញ្ជូន ឬផ្ទេរពីខ្ញុំ ' dash_national_admin_summary: សេចក្តីសង្ខេបរបស់ Admin date: កាលបរិច្ឆេទ date_of_incident: កាលបរិច្ឆេទហេតុការណ៍ @@ -624,9 +622,9 @@ km: low_level: ទាប low_risk: អាទិភាព​ទាប manager_count_closed_total: - other: 'និង​%{stat}ករណីបាន​បិទ' + other: និង​%{stat}ករណីបាន​បិទ manager_count_open_total: - other: 'អ្នកមាន​ %{stat}ករណីបើក' + other: អ្នកមាន​ %{stat}ករណីបើក manager_transfers_totals: other: 'អ្នកមាន​%{stat}%{stat_type}ការ​ផ្ទេរ ' match_result: លទ្ធផល​ផ្គូផ្គង @@ -719,11 +717,11 @@ km: worker_count_total: other: '%{case_worker}អ្នក​មាន​%{stat}ករណីសរុប' workflow: លំហូរការងារ - workflow_team: លំហូរការងារ - ករណីក្រុម + workflow_team: លំហូរការងារ - ករណីរបស់ក្រុម you_have: 'អ្នក​មាន' disabled: status: - disabled: បាន​បិទ + disabled: បិទដំណើរការ (disable) enabled: បាន​បើក email_notification: assign: '%{user}បានចាត់តាំងដល់អ្នកដូចខាងក្រោម%{record_type}៖%{record_id}' @@ -751,16 +749,14 @@ km: password_extra_info: ពាក្យសម្ងាត់ត្រូវតែមានយ៉ាងហោចណាស់ 8 តួអក្សរ។​ ពាក្យសម្ងាត់​នេះ​នឹង​ត្រូវ​បាន​ភ្ជាប់​ជា​មួយ​ឯកសារ​ដែល​បាននាំចេញ ហើយ​នឹង​ត្រូវ​បានបញ្ចូល​ដោយ​អ្នក​ណា​ម្នាក់​ដែល​បើក​ឯកសារ​នេះ​នៅ​ពេល​អនាគត។ password_label: សូម​បញ្ចូល​ពាក្យសម្ងាត់​ដែល​នឹង​អ៊ីនគ្រិប​ឯកសារ​របស់​អ្នក។ error_message: - address_fields: "អ្នកត្រូវដោះស្រាយ%{fields}សំណួរនៅលើទម្រង់%{forms}" - address_form_fields: "អ្នកត្រូវដោះស្រាយ%{fields}សំណួរនៅលើទម្រង់នេះ" + address_fields: អ្នកត្រូវដោះស្រាយ%{fields}សំណួរនៅលើទម្រង់%{forms} + address_form_fields: អ្នកត្រូវដោះស្រាយ%{fields}សំណួរនៅលើទម្រង់នេះ address_subform_fields: '%{subform}មាន%{fields}សំណួរមិនត្រឹមត្រូវ' error_page: not_authorized: - code: 403 server_error: អ្នកមិនត្រូវបានអនុញ្ញាតឱ្យចូលប្រើទំព័រនេះទេ។ title: មិនត្រូវបានអនុញ្ញាត not_found: - code: 404 contact_admin: ប្រសិន​បើ​អ្នក​នៅ​ទីនេះ​ដោយ​សារ​មាន​កំហុស សូម​ទាក់ទង​អ្នក​គ្រប់គ្រង​របស់​អ្នក។ something_went_wrong: សូម​ទោស មាន​អ្វី​មួយ​មិន​ប្រក្រតី! errors: @@ -802,7 +798,7 @@ km: user: email: "សូមបញ្ចូលអ៊ីមែលដែលមានសុពលភាព (ឧទាហរណ៍៖ 'name@example.org')" password_mismatch: កន្លែង​បញ្ចូល​ពាក្យសម្ងាត់​មិនមាន​​ពាក្យ​សម្ងាត់​ដូច​គ្នា - password_length: "ពាក្យសម្ងាត់ត្រូវតែមានយ៉ាងហោចណាស់%{min}តួអក្សរ" + password_length: ពាក្យសម្ងាត់ត្រូវតែមានយ៉ាងហោចណាស់%{min}តួអក្សរ email_uniqueness: អ្នកប្រើប្រាស់ដែលមានអាសយដ្ឋានអ៊ីមែលនេះមានរួចហើយ។ សូមបញ្ចូលមួយផ្សេង code_of_conduct: title_present: ចំណងជើងមិន​ត្រូវ​ទទេ @@ -823,7 +819,7 @@ km: all: កំណត់តាមបំណង (custom) custom_exports: all: កំណត់តាមបំណង (custom) - choose_fields: "តើ​អ្នកច​ង់​ជ្រើសរើស​កន្លែង​បញ្ចូលនីមួយៗ​សម្រាប់​ទម្រង់​ដែរ​ឬទេ?" + choose_fields: តើ​អ្នកច​ង់​ជ្រើសរើស​កន្លែង​បញ្ចូលនីមួយៗ​សម្រាប់​ទម្រង់​ដែរ​ឬទេ? empty_fields_forms: សូម​ជ្រើសរើស​ទម្រង់ ឬ​កន្លែង​បញ្ចូល​​ខ្លះ​ដើម្បី​នាំចេញ។ empty_format: សូម​ជ្រើសរើស​ទម្រង់​ដើម្បី​នាំចេញ។ empty_module: សូម​ជ្រើសរើស​ម៉ុឌុល​ដើម្បីនាំចេញ។ @@ -840,10 +836,10 @@ km: header: ក្បាលទំព័រ custom_header: ក្បាលទំព័រដែលកំណត់តាមបំណង signatures: បញ្ចូលហត្ថលេខាសម្រាប់ - include_implementation_logos: "បញ្ចូលLogo?" + include_implementation_logos: បញ្ចូលLogo? include_implementation_logos_help_text: រួមទាំងLogoដែលបង្ហាញនៅក្នុងម៉ឺនុយរុករក និងនៅលើទំព័រចូល។ - include_agency_logo: "បញ្ចូលLogoស្ថាប័ន?" - include_other_logos: "បង្ហាញLogoដ៏ទៃទៀត?" + include_agency_logo: បញ្ចូលLogoស្ថាប័ន? + include_other_logos: បង្ហាញLogoដ៏ទៃទៀត? duplicate_id_csv: all: លេខកូដ​ស្ទួន female_abbreviation: ស @@ -896,7 +892,6 @@ km: form: Primero Forms status: ស្ថានភាព notes: សម្គាល់ - go_to_exports: ចូលទៅកាន់ទំព័រនាំចេញ ដើម្បីទាញយក incident_recorder_xls: all: អ្នក​កត់ត្រា​ហេតុការណ៍ @@ -907,7 +902,7 @@ km: one: JSON selected: បាន​ជ្រើសរើស​ទៅ JSON list_view_csv: - all: ទិដ្ឋភាព​បញ្ជីនាំចេញ + all: នាំចេញ​បញ្ជីករណី selected: បាន​ជ្រើសរើស​ទៅ​ជា CSV messages: no_exporter: មិនមានបញ្ជាក់ព័ត៌មាននាំចេញ @@ -937,9 +932,9 @@ km: one: ផ្ទាំង​រូបថត reunited: ​បង្រួបបង្រួម selected: បាន​ជ្រើសរើស​ទៅ​ផ្ទាំង​រូបថត - success_message: "ការបង្កើត Photowall %{file_name}ករណីដែលគ្មានរូបថតនឹងមិនត្រូវបានបញ្ចូលទេ។" + success_message: ការបង្កើត Photowall %{file_name}ករណីដែលគ្មានរូបថតនឹងមិនត្រូវបានបញ្ចូលទេ។ printed: 'បោះពុម្ព៖%{date}' - queueing: "ការបង្កើតឯកសារនាំចេញ%{file_name}" + queueing: ការបង្កើតឯកសារនាំចេញ%{file_name} selected_xls: all: Excel one: Excel @@ -961,7 +956,7 @@ km: governorate_country: តំបន់ - ប្រទេស id: លេខ​កូដ individual_progress_id: លេខសម្គាល់​វឌ្ឍនភាព​នីមួយៗ - locations_by_level: "អាសយដ្ឋាន (ជំរុំ, ប្លុក និង​កម្រិត​អាសយដ្ឋាន​ដែល​មាន​ផ្សេងៗ​ទៀត ដូច​ជា​និយាមការ​ជីភីអេស​ទី​ជម្រក)" + locations_by_level: អាសយដ្ឋាន (ជំរុំ, ប្លុក និង​កម្រិត​អាសយដ្ឋាន​ដែល​មាន​ផ្សេងៗ​ទៀត ដូច​ជា​និយាមការ​ជីភីអេស​ទី​ជម្រក) long_id: លេខកូដ​វែង moha_id: លេខសម្គាល់ MOHA name_of_caregiver: ឈ្មោះ​ពេញ​របស់​អ្នក​ថែទាំ @@ -1016,7 +1011,7 @@ km: add_new_field: បង្កើត​សំណួរថ្មី add_existing_field: បញ្ចូលសំណួរដែលមានស្រាប់ add_field: បន្ថែមសំណួរ - add_field_type: "បញ្ចូល%{file_type}" + add_field_type: បញ្ចូល%{file_type} audio: current: សំឡេង​បច្ចុប្បន្ន audio_upload_box: ផ្ទុកសារសំឡេង @@ -1024,13 +1019,13 @@ km: bid_document: ឯកសារ BID check_box: ប្រអប់​គូស​ធីក clear_group_by: លុបក្រុមតាម - clear_sort_by: "លុបការតម្រៀបទិន្នន័យ " + clear_sort_by: 'លុបការតម្រៀបទិន្នន័យ ' copy_from_another_form: សំណួរនេះត្រូវបានចម្លងពីទម្រង់ផ្សេងទៀត។ create_field: បង្កើត​សំណួរ create_unique_values: បង្កើតតម្លៃតែមួយគត់ date_field: កន្លែង​បញ្ចូលកាលបរិច្ឆេទ date_help: dd-mmm-yyyy - date_help_with_time: "dd-mmm-yyyy hh:mm" + date_help_with_time: dd-mmm-yyyy hh:mm date_not_valid: កាលបរិច្ឆេទ​នេះ​មិន​ត្រឹមត្រូវ​ទេ។ time: ពេលវេលា date_range: @@ -1042,29 +1037,28 @@ km: date_range_field: ចន្លោះ​កាលបរិច្ឆេទ date_time: កាលបរិច្ឆេទ-ពេលវេលា db_name: ឈ្មោះ​ប្រព័ន្ធ​ទិន្នន័យ - default: "លំនាំដើម?" + default: លំនាំដើម? default_date_validation: ការ​ផ្ទៀងផ្ទាត់​កាលបរិច្ឆេទ​លំនាំដើម - default_to_current_date: "លំនាំដើមដល់កាលបរិច្ឆេទបច្ចុប្បន្ន?" - default_to_current_datetime: "លំនាំដើមដល់កាលបរិច្ឆេទនិងពេលវេលាបច្ចុប្បន្ន?" + default_to_current_date: លំនាំដើមដល់កាលបរិច្ឆេទបច្ចុប្បន្ន? + default_to_current_datetime: លំនាំដើមដល់កាលបរិច្ឆេទនិងពេលវេលាបច្ចុប្បន្ន? default_value: តម្លៃ​លំនាំដើម - deleted: "បាន​លុប​កន្លែង​បញ្ចូល %{display_name} ។" + deleted: បាន​លុប​កន្លែង​បញ្ចូល %{display_name} ។ detail: ព័ត៌មានលម្អិត​ - disabled: បិទករណី (disable case) + disabled: បិទដំណើរការ (disable) display_name: ឈ្មោះ​បង្ហាញ document: comments: មតិយោបល់ - current: "តើ​នេះ​ជា​ឯកសារ​បច្ចុប្បន្ន​ឬ?" + current: តើ​នេះ​ជា​ឯកសារ​បច្ចុប្បន្ន​ឬ? date: កាលបរិច្ឆេទ​ឯកសារ name: ឈ្មោះ​ឯកសារ - is_current: "តើ​នេះ​ជា​ឯកសារ​បច្ចុប្បន្ន​ឬ?" + is_current: តើ​នេះ​ជា​ឯកសារ​បច្ចុប្បន្ន​ឬ? document_upload_box: ផ្ទុកឯកសារ edit_label: កែសម្រួលសំណួរ - enabled: "បើក?" + enabled: បើក? enabled_label: បើក​ (enabled) english_text: អក្សរភាសាអង់គ្លេស field_name: ឈ្មោះសំណួរ field_type: ប្រភេទសំណួរ - attachment_too_large: ឯកសារមិនគួរធំជាង 10mb file_upload_box: add_document_label: បញ្ចូល​ឯកសារ add_new_document_button_text: បញ្ចូល​ឯកសារ​ផ្សេង​ទៀត @@ -1093,7 +1087,7 @@ km: not_future_date: មិនមែន​ជា​កាលបរិច្ឆេទ​នៅ​ពេល​អនាគត number_not_valid: សូម​បញ្ចូល​ទិន្នន័យ​ជា​លេខ numeric_field: កន្លែង​បញ្ចូល​ជា​លេខ - on_collapsed_subform: "នៅលើទម្រង់រងដែលបានបង្រួម?" + on_collapsed_subform: នៅលើទម្រង់រងដែលបានបង្រួម? option_strings_add_option: បញ្ចូល​ជម្រើស option_strings_source: រក​មើល option_strings_text: ជម្រើស @@ -1107,7 +1101,7 @@ km: predifined_lookups: ប្រើការរកមើលដែលបានកំណត់ជាមុន radio_button: ប៊ូតុង​មូល remove: ដក​ចេញ - remove_attachment_confirmation: "តើ​អ្នក​ប្រាកដជា​ចង់​លុបឯកសារ​ភ្ជាប់នេះ​​មែនទេ?" + remove_attachment_confirmation: តើ​អ្នក​ប្រាកដជា​ចង់​លុបឯកសារ​ភ្ជាប់នេះ​​មែនទេ? required: ត្រូវបំពេញ required_field: 'ត្រូវបញ្ចូលព័ត៌មាន%{field}' search_existing: ស្វែងរកសំណួរដែលមានស្រាប់ @@ -1116,18 +1110,18 @@ km: select_multiple: ជ្រើសរើស​ទាំងអស់​ដែល​អនុវត្ត select_single: (ជ្រើសរើស...) separator: សញ្ញា​បំបែក - show: "បង្ហាញ?" + show: បង្ហាញ? show_on: បង្ហាញ show_on_minify_form: ទម្រង់​ខ្លី subform: ទម្រង់​រង subform_group_by: ដាក់ជា​ក្រុម​តាម​ - subform_remove_message: "តើ​អ្នក​ប្រាកដជា​ចង់​ដក​ទម្រង់​រង​នេះ​ចេញ​មែនទេ?" + subform_remove_message: តើ​អ្នក​ប្រាកដជា​ចង់​ដក​ទម្រង់​រង​នេះ​ចេញ​មែនទេ? subform_section: description: ការពិពណ៌នាទម្រង់រង name: ឈ្មោះ​ទម្រង់រង - starts_with_one_entry: "ចាប់ផ្តើមជាមួយនឹងការបញ្ចូលទម្រង់រងមួយ?" + starts_with_one_entry: ចាប់ផ្តើមជាមួយនឹងការបញ្ចូលទម្រង់រងមួយ? subform_append_only: ការ​ធ្វើសមកាលកម្ម​ដោយ​ជ្រើសរើស (ឧបករណ៍​ចល័ត) - subform_prevent_item_removal: "ទប់ស្កាត់ការដកចេញទម្រង់រង?" + subform_prevent_item_removal: ទប់ស្កាត់ការដកចេញទម្រង់រង? subform_sort_by: តំរៀបដោយ successfully_added: បាន​បញ្ចូលកន្លែង​បញ្ចូល​ដោយ​ជោគជ័យ tally_field: កន្លែង​បញ្ចូលចំនួន​សរុប @@ -1223,7 +1217,7 @@ km: show_on: បង្ហាញលើ subform_need_to_be_added: សូមចុច​ប៊ូតុង​​បញ្ចូល។ subform_need_to_be_added_single: សូមចុច​ប៊ូតុង​​បញ្ចូល។ - subform_not_found: "មិនមានព័ត៌មាន%{subform_name}" + subform_not_found: មិនមានព័ត៌មាន%{subform_name} title: ឈ្មោះ​ទម្រង់ translations: edit: កែសម្រួលការបកប្រែ @@ -1248,7 +1242,6 @@ km: dashboard: ផ្ទាំងព័ត៌មាន en: អង់គ្លេស es: Español - es-GT: អេស្ប៉ាណុល (ហ្គាតេម៉ាឡា) fr: បារាំង id: Bahasa km: ភាសាខ្មែរ @@ -1290,7 +1283,6 @@ km: killing: ធ្វើឃាតុកុមារ maiming: ការចិញ្ចឹមកុមារ recruitment: ការជ្រើសរើស និងឬប្រើប្រាស់កុមារ - sexual_violence: ការរំលោភ និងឬទម្រង់ផ្សេងទៀតនៃអំពើហិង្សាផ្លូវភេទ abduction: ការចាប់ពង្រត់ attack_on: ការវាយប្រហារលើសាលារៀន និងឬមន្ទីពេទ្រ military_use: ការប្រើប្រាស់សាលារៀន និងឬមន្ទីរពេទ្យសម្រាប់យោធា @@ -1319,7 +1311,6 @@ km: unknown: មិនស្គាល់ verification_status: ស្ថានភាពការ​ផ្ទៀងផ្ទាត់ violence_type: ប្រភេទហិង្សា - armed_force_group_name: ឈ្មោះក្រុមកងកម្លាំងប្រដាប់អាវុធ armed_force_group_type: ប្រភេទក្រុមប្រដាប់​អាវុធ៖ register_new_incident: ហេតុការណ៍​​ថ្មី selectable_date_options: @@ -1420,19 +1411,14 @@ km: female: "ស្រី" 0-11: "0-11" 12-17: "12-17" - ">18": ">18" + '>18': ">18" disability: "ពិការ" no_disability: "គ្មានពិការភាព" - helptext: | - សូចនាករនេះរាប់ប្រភេទសេវាដែលផ្តល់ដល់ជនរងគ្រោះក្នុងដំណើរការគ្រប់គ្រងករណី។ - ការផ្តល់សេវាមានន័យថា សេវាដែលត្រូវបានផ្តល់ដោយស្ថាប័នអ្នកប្រើប្រាស់ (in house) - មិនមែនសេវាដែលផ្តល់ដោយការបញ្ជូនទៅកាន់អ្នកផ្តល់សេវាផ្សេងទៀត ឬការបញ្ជូនខាងក្នុងទេ។ + helptext: "សូចនាករនេះរាប់ប្រភេទសេវាដែលផ្តល់ដល់ជនរងគ្រោះក្នុងដំណើរការគ្រប់គ្រងករណី។ \nការផ្តល់សេវាមានន័យថា សេវាដែលត្រូវបានផ្តល់ដោយស្ថាប័នអ្នកប្រើប្រាស់ (in house)\n មិនមែនសេវាដែលផ្តល់ដោយការបញ្ជូនទៅកាន់អ្នកផ្តល់សេវាផ្សេងទៀត ឬការបញ្ជូនខាងក្នុងទេ។\n" average_referrals: title: "9. មធ្យមភាគនៃការបញ្ជូន" label: "មធ្យមភាគនៃការបញ្ជូនក្នុងមួយករណី" - helptext: | - សូចនាករនេះរាប់ចំនួនមធ្យមនៃការបញ្ជូនសម្រាប់ករណីនីមួយៗ (សម្រាប់គ្រប់ប្រភេទសេវា) - នៅគ្រប់ករណីទាំងអស់ គិតទាំងករណីសកម្ម/បើក ឬបិទ។ វារួមទាំងការបញ្ជូនដែលកត់ត្រាក្នុងទម្រង់ករណី មិនមែនត្រឹមតែការបញ្ជូនធ្វើឡើងតាមរយៈប្រព័ន្ធប៉ុណ្ណោះទេ។ + helptext: "សូចនាករនេះរាប់ចំនួនមធ្យមនៃការបញ្ជូនសម្រាប់ករណីនីមួយៗ (សម្រាប់គ្រប់ប្រភេទសេវា) \nនៅគ្រប់ករណីទាំងអស់ គិតទាំងករណីសកម្ម/បើក ឬបិទ។ វារួមទាំងការបញ្ជូនដែលកត់ត្រាក្នុងទម្រង់ករណី មិនមែនត្រឹមតែការបញ្ជូនធ្វើឡើងតាមរយៈប្រព័ន្ធប៉ុណ្ណោះទេ។\n" referrals_per_service: title: "ចំនួននៃការបញ្ជូនក្នុងសេវាមួយប្រភេទ" average_followup_meetings_per_case: @@ -1490,7 +1476,6 @@ km: aria-labels: from: "ទិន្នន័យនឹងត្រូវបានជ្រើសរើសបន្ទាប់ពីកាលបរិច្ឆេទនេះ" to: "ទិន្នន័យនឹងត្រូវបានជ្រើសរើសមុនកាលបរិច្ឆេទដែលអ្នកបានកំណត់" - location: base_types: camp: ជំរុំ @@ -1525,9 +1510,9 @@ km: message: សូមជ្រើសរើសឯកសារ CSV ដើម្បីបង្ហោះ។ ឯកសារនេះគួរតែប្រើការអ៊ិនកូដ UTF-8 និងរួមបញ្ចូល HXL hashtags នៅក្នុងជួរក្បាលទំព័រទីពីរនៃជួរនីមួយៗ no_location: មុនពេលបង្កើតអ្នកប្រើប្រាស់ថ្មី សូមនាំចូលឈ្មោះទីតាំងជាមុនសិន enable_title: បង្ហាញទីតាំង - enable_text: "តើអ្នកប្រាកដទេ? ប្រសិនបើអ្នកជ្រើសរើសទីតាំងទាំងនេះ វានឹងបង្ហាញក្នុងតារាងជ្រើសរើសទីតាំង" + enable_text: តើអ្នកប្រាកដទេ? ប្រសិនបើអ្នកជ្រើសរើសទីតាំងទាំងនេះ វានឹងបង្ហាញក្នុងតារាងជ្រើសរើសទីតាំង disable_title: លាក់ទីតាំង - disable_text: "តើអ្នកប្រាកដទេ? ប្រសិនបើអ្នកជ្រើសរើសទីតាំងទាំងនេះ វានឹងបង្ហាញក្នុងតារាងជ្រើសរើសទីតាំង" + disable_text: តើអ្នកប្រាកដទេ? ប្រសិនបើអ្នកជ្រើសរើសទីតាំងទាំងនេះ វានឹងបង្ហាញក្នុងតារាងជ្រើសរើសទីតាំង logger: actions: _approved: បានអនុម័ត @@ -1543,7 +1528,7 @@ km: case_plan_approved: ផែនការ​ករណីបានអនុម័ត case_plan_rejected: ផែនការ​ករណីបានបដិសេធ case_plan_requested: ផែនការ​ករណីបានដាក់ស្នើរ - close: បិទ + close: បិទករណី create: បង្កើត create_bulk: បង្កើត​ច្រើន delete: លុប @@ -1570,7 +1555,7 @@ km: show: បង្ហាញ show_alerts: បង្ហាញការជូនដំណឹង traces: ស្វែងរក - transfer: "ផ្ទេរ " + transfer: 'ផ្ទេរ ' transfer_accepted: ករណីផ្ទេរបានទទួល transfer_rejected: បដិសេធការផ្ទេរ transfer_request: សំណើ​ផ្ទេរ @@ -1593,7 +1578,7 @@ km: by_user: ដោយ​អ្នកប្រើប្រាស់ case_plan_approved: "%{approval_label}អនុម័តសម្រាប់" case_plan_requested: "%{approval_label}ស្នើសុំសម្រាប់" - close: បិទ + close: បិទករណី closure_approved: "%{approval_label}អនុម័តសម្រាប់" closure_requested: "%{approval_label}ស្នើសុំសម្រាប់" consent_count: ចំនួន​ការ​យល់ព្រម @@ -1644,7 +1629,7 @@ km: code_of_conduct: ក្រមសីលធម៌ task: កិច្ចការ record_state: - 'false': បិទករណី (disable case) + 'false': បិទកំណត់ត្រាករណី (disable case) 'true': បើក refer: បញ្ជូន refer_to: ស្វែងរកអ្នកទទួលការបញ្ជូន @@ -1680,18 +1665,18 @@ km: label: បញ្ជាក់លេខកូដសម្ងាត់ password_match: label: ពាក្យសម្ងាត់ត្រូវតែដូចគ្នា - provider_title: "ជាមួយ%{provider}" + provider_title: ជាមួយ%{provider} title: ចូល username: អ្នកប្រើប្រាស់ password_reset_modal: កំណត់ពាក្យសម្ងាត់ឡើងវិញ password_reset_modal_text: Primero នឹងផ្ញើតំណកំណត់ពាក្យសម្ងាត់ឡើងវិញទៅកាន់អ៊ីមែលរបស់អ្នក។ password_reset_email: អ៊ីមែល - forgot_password: "ភ្លេចពាក្យសម្ងាត់?" + forgot_password: ភ្លេចពាក្យសម្ងាត់? email: label: អ៊ីមែល lookup: create: កា​ររក​មើល​ថ្មី - enabled_label: "បើក?" + enabled_label: បើក? english_label: អត្ថបទភាសាអង់គ្លេស label: ការ​រក​មើល language_label: ភាសា @@ -1726,7 +1711,6 @@ km: no_data_table: មិនមាន​ទិន្នន័យ​​ទេ violations: name: ការបំពាន - description: '' filter_options: incident_date: កាលបរិច្ឆេទហេតុការណ៍ date_of_report: កាលបរិច្ឆេទ​របាយការណ៍ @@ -1735,9 +1719,7 @@ km: killing: ធ្វើឃាតុកុមារ maiming: ការចិញ្ចឹមកុមារ recruitment: ការជ្រើសរើស និងឬប្រើប្រាស់កុមារ - sexual_violence: ការរំលោភ និងឬទម្រង់ផ្សេងទៀតនៃអំពើហិង្សាផ្លូវភេទ abduction: ការចាប់ជំរិត - attack_on: ការវាយប្រហារលើសាលារៀន និងឬមន្ទីពេទ្រ military_use: ការប្រើប្រាស់សាលារៀន និងឬមន្ទីរពេទ្យសម្រាប់យោធា denial_humanitarian_access: បដិសេធសកម្មភាពមនុស្សធម៌ដល់កុមារ sub_reports: @@ -1753,49 +1735,33 @@ km: total: សរុប gbv_statistics: name: ស្ថិតិ GBV - description: '' filter_options: date_of_first_report: កាលបរិច្ឆេទ​សម្ភាសន៍ incident_date: កាលបរិច្ឆេទហេតុការណ៍ reports: - incidents: ហេតុការណ៍ perpetrators: ជនល្មើស - sub_reports: - combined: ហេតុការណ៍ - total: ចំនួនឩប្បត្តិហេតុ GBV ដែលបានរាយការណ៍ - gbv_sexual_violence: ចំនួនឩប្បត្តិហេតុអំពើហិង្សាផ្លូវភេទដែលបានរាយការណ៍ - gbv_previous_incidents: "ចំនួនឩប្បត្តិហេតុដែលបានរាយការណ៍មុនពេលឩប្បត្តិហេតុ GBV " - gbv_sexual_violence_type: ប្រភេទឩប្បត្តិហេតុ - incident_timeofday: ពេលវេលាដែលឩប្បត្តិហេតុកើតឡើង - elapsed_reporting_time: ពេលវេលាចន្លោះរវាង ឩប្បត្តិហេតុ និងថ្ងៃរាយការណ៍ - elapsed_reporting_time_rape: ឩប្បត្តិហេតុនៃការរំលាភ ចន្លោះពេលវេលារវាងឩប្បត្តិហេតុ និងថ្ងៃរាយការណ៍ - incident_location_type: កន្លែងកើតឩប្បត្តិហេតុ - number_of_perpetrators: ចំនួនជនល្មើសបឋម - perpetrator_relationship: ទំនាក់ទំនងរបស់ជនល្មើសដែលជាប់ចោទ និងជនរងគ្រោះ - perpetrator_age_group: ក្រុមអាយុ ជនល្មើសដែលជាប់ចោទ - perpetrator_occupation: មុនរបរ​ ជនល្មើសដែលជាប់ចោទ messages: - alert_items: "អ្នកមាន%{items}កំណត់គសម្គាល់។" + alert_items: អ្នកមាន%{items}កំណត់គសម្គាល់។ alerts_for: - approval: "ការអនុម័តកំពុងរងចាំសម្រាប់%{form_section_name}" + approval: ការអនុម័តកំពុងរងចាំសម្រាប់%{form_section_name} field_change: 'ធ្វើបច្ចុប្បន្នភាព%{form_section_name}នៅ%{alert_time}' - transfer_request: "សំណើ​ផ្ទេរ​ថ្មី​ត្រូវ​បាន​បង្កើត​នៅ %{date} ដោយ%{user} នៅ %{agency}" - duplicate_field: ដូចគ្នាទៅនឹងករណីមួយទៀតនៅក្នុងប្រព័ន្ធ + transfer_request: សំណើ​ផ្ទេរ​ថ្មី​ត្រូវ​បាន​បង្កើត​នៅ %{date} ដោយ%{user} នៅ %{agency} + duplicate_field: 'ករណីផ្សេងមួយទៀតនៅក្នុងប្រព័ន្ធមាន%{field_name}ដូចគ្នា ' cannot_edit: អ្នកមិនអាចកែសម្រួលទេ confirmation_message: ការ​ចុច​យល់ព្រម នឹង​បោះបង់​ការ​ផ្លាស់ប្ដូរ​ដែល​មិនបាន​រក្សាទុក និងត្រឡប់​ទៅ​ទិដ្ឋភាព​បញ្ជី។ ចុច​បោះបង់ ដើម្បី​ត្រឡប់​ទៅ​កំណត់​ត្រា​វិញ។ confirmation_message_subform: ការ​ចុច​យល់ព្រម នឹង​បោះបង់​ការ​ផ្លាស់ប្ដូរ​ដែល​មិនបាន​រក្សាទុក។ ចុច​បោះបង់ ដើម្បីបន្តកែសម្រួល។ dashboard_offline: អ្នកគ្មានសេវាអ៊ីនធឺណិតទេ។ ផ្ទាំងទិន្នន័យនឹងដំណើរការពេលដែលអ្នកមានសេរាអ៊ីនធឺណិតវិញ។ field_name_on_form_name: '%{field_name}សំណួរលើ%{form_name}ទម្រង់' - logout_confirmation: "តើអ្នកចង់បន្តសកម្មភាពរបស់អ្នកដែរឬទេ?" - logout_offline_warning: "តើអ្នកចង់ចេញពីប្រព័ន្ធមែនទេ? ប្រសិនបើបាទ/ចាស អ្នកនឹងមិនអាចចូលក្នុងប្រព័ន្ធបានទេ ទាល់តែអ្នកមានសេវាអ៊ីនធឺណិត។​ រាល់ការកែសម្រួលដែលអ្នកបានធ្វើពេលគ្មានសេវាអ៊ីនធឺណិតនឹងបាត់បង់។" + logout_confirmation: តើអ្នកចង់បន្តសកម្មភាពរបស់អ្នកដែរឬទេ? + logout_offline_warning: តើអ្នកចង់ចេញពីប្រព័ន្ធមែនទេ? ប្រសិនបើបាទ/ចាស អ្នកនឹងមិនអាចចូលក្នុងប្រព័ន្ធបានទេ ទាល់តែអ្នកមានសេវាអ៊ីនធឺណិត។​ រាល់ការកែសម្រួលដែលអ្នកបានធ្វើពេលគ្មានសេវាអ៊ីនធឺណិតនឹងបាត់បង់។ logout_warning: អ្នកនឹងចេញពីប្រព័ន្ធដោយស្វ័យប្រវត្តិក្នុង​រយៈពេល5នាទីទៀត logout_dialog_header: ចេញពីប្រព័ន្ធ ដោយមិនមានសេវាអ៊ីនធឺណិត logout_confirmation_title: បញ្ជាក់ការចាកចេញពីប្រព័ន្ធ - logout_confirmation_text: "តើអ្នកពិតជាចង់ចាកចេញមែន​ទេ?" + logout_confirmation_text: តើអ្នកពិតជាចង់ចាកចេញមែន​ទេ? no_changes: អ្នកមិនបានផ្លាស់ប្តូរសំណួរទេ។ not_available: មិនមាន record_list: - column_header_tooltip: "តំរៀបតាម%{column}" + column_header_tooltip: តំរៀបតាម%{column} of: / no_match: សុំទោស រកមិនឃើញព័ត៌មាននេះទេ rows_per_page: ចំនួនជួរដេកក្នុងមួយទំព័រ @@ -1804,7 +1770,7 @@ km: bulk_exports: ការនាំចេញ​ cases: ករណី home: ទំព័រដើម - key_performance_indicators: " សូចនាករវាស់វែងការអនុវត្តការងារសំខាន់ៗ (Pulse/KPIs)" + key_performance_indicators: ' សូចនាករវាស់វែងការអនុវត្តការងារសំខាន់ៗ (Pulse/KPIs)' incidents: ហេតុការណ៍ logout: ចេញពីប្រព័ន្ធ reports: របាយការណ៍ @@ -1839,11 +1805,11 @@ km: approvals_case_plan_pending: '%{approval_label}កំពុងរងចាំ' approvals_closure: '%{approval_label}' approvals_closure_pending: '%{approval_label}កំពុងរងចាំ' - approve_action_plan: "អនុម័ត​%{approval_label}" - approve_assessment: "អនុម័ត%{approval_label}​ទម្រង់" - approve_case_plan: "អនុម័ត​%{approval_label}" - approve_closure: "អនុម័ត%{approval_label}​ទម្រង់" - approve_gbv_closure: "អនុម័ត%{approval_label}​ទម្រង់" + approve_action_plan: អនុម័ត​%{approval_label} + approve_assessment: អនុម័ត%{approval_label}​ទម្រង់ + approve_case_plan: អនុម័ត​%{approval_label} + approve_closure: អនុម័ត%{approval_label}​ទម្រង់ + approve_gbv_closure: អនុម័ត%{approval_label}​ទម្រង់ assign: ចាត់ចែង assign_within_agency: ចាត់ចែង​នៅ​ក្នុង​ស្ថាប័ន assign_within_user_group: ចាត់ចែង​នៅ​ក្នុង​ក្រុម​របស់​អ្នក​ប្រើប្រាស់ @@ -1859,8 +1825,8 @@ km: cases_by_task_overdue_followups: មើលករណី​ដែលហួស​ពេលកំណត់​ផ្តល់សេវា cases_by_task_overdue_services: មើលករណី​ដែលហួស​ពេលកំណត់​ផ្តល់សេវា cases_managed_other_users: ករណីដែលគ្រប់គ្រងដោយអ្នកប្រើប្រាស់ផ្សេងទៀត - close: បិទ - consent_override: "ការ​យល់ព្រម មិនត្រូវបានពិចារណា " + close: បិទករណី + consent_override: 'ការ​យល់ព្រម មិនត្រូវបានពិចារណា ' copy: ចម្លង copy_of: ច្បាប់ចម្លងនៃ create: បង្កើត @@ -1878,9 +1844,9 @@ km: dash_reporting_location: មើល​ទីតាំង​រាយការណ៍ dash_service_provisions: មើល​ការ​ផ្ដល់​សេវាកម្ម dash_shared_from_my_team: ករណីបញ្ជូន/ផ្ទេរពីក្រុមខ្ញុំ - dash_shared_with_me: ករណីបញ្ជូន/ផ្ទេរមកខ្ញុំ + dash_shared_with_me: ករណីបញ្ជូន ឬផ្ទេរមកខ្ញុំ dash_shared_with_my_team: ករណីបញ្ជូន/ផ្ទេរមកក្រុមខ្ញុំ - dash_shared_with_others: ករណីបញ្ជូន/ផ្ទេរពីខ្ញុំ + dash_shared_with_others: 'ករណីបញ្ជូន ឬផ្ទេរពីខ្ញុំ ' dash_show_none_values: មើល​តម្លៃគ្មាន dash_tasks: មើលកិច្ចការ dash_transfers_by_socal_worker: មើល​កា​រផ្ទេរ​ដោយ​បុគ្គលិកសង្គម @@ -1889,13 +1855,13 @@ km: delete: លុប display_view_page: បង្ហាញ​ទំព័រ​ទិដ្ឋភាព duplicate: ស្ទួន​ការ​ស្វែងរក - enable_disable_record: បិទករណី (disable case) + enable_disable_record: បិទដំណើរការ (disable) export_case_pdf: នាំចេញ​ករណីជា pdf export_csv: នាំចេញជា csv export_custom: នាំចេញ​ផ្ទាល់ខ្លួន export_duplicate_id_csv: នាំចេញ​ភាព​ស្ទួន export_json: នាំចេញ​ជា json - export_list_view_csv: នាំចេញ​ទិដ្ឋភាព​បញ្ជី cvs + export_list_view_csv: នាំចេញ​បញ្ជីករណីជាឯកសារ cvs export_mrm_violation_xls: នាំចេញ​ការ​បំពាន mrm ជា xls export_pdf: នាំចេញជា pdf export_photowall: នាំចេញ​ផ្ទាំង​រូបថត @@ -1912,12 +1878,12 @@ km: incident: ហេតុការណ៍ incident_details_from_case: បញ្ចូល​ព័ត៌មាន​លម្អិត​អំពី​ហេតុការណ៍​ទៅ​ក្នុង​ករណី​របស់​អ្នក​ប្រើប្រាស់​ផ្សេង incident_from_case: បង្កើត​ហេតុការណ៍​​ពី​ករណី - kpi: " សូចនាករវាស់វែងការអនុវត្តការងារសំខាន់ៗ (Pulse/KPIs)" + kpi: ' សូចនាករវាស់វែងការអនុវត្តការងារសំខាន់ៗ (Pulse/KPIs)' lookup: រក​មើល manage: គ្រប់គ្រង mark_for_offline: ប្រើសម្រាប់ពេលគ្មានសេវាអីនធឺណេត matching_configuration: ផ្គូផ្គង​ការ​កំណត់​រចនាសម្ព័ន្ធ - metadata: "ទម្រង់, ការ​រក​មើល" + metadata: ទម្រង់, ការ​រក​មើល potential_match: ការ​ផ្គូផ្គង​ខ្លាំង primero_configuration: ការកំណត់ read: អាន @@ -1932,11 +1898,11 @@ km: report: របាយការណ៍ managed_report: ព័ត៌មាន request_approval: ស្នើសុំ​ការ​អនុម័ត - request_approval_action_plan: "ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត" - request_approval_assessment: "ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត" - request_approval_case_plan: "ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត" - request_approval_closure: "ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត" - request_approval_gbv_closure: "ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត" + request_approval_action_plan: ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត + request_approval_assessment: ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត + request_approval_case_plan: ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត + request_approval_closure: ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត + request_approval_gbv_closure: ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត request_transfer: ស្នើសុំការផ្ទេរ role: តួនាទី save_search: រក្សាទុក​ការ​ស្វែងរក @@ -1960,7 +1926,7 @@ km: view_response: មើលការ​ឆ្លើយតប webhook: Webhook workflow: លំហូរការងារ - ករណីនីមួយៗ - workflow_team: លំហូរការងារ - ករណីក្រុម + workflow_team: លំហូរការងារ - ករណីរបស់ក្រុម write: សរសេរ activity_log: កំណត់ហេតុសកម្មភាព resource: @@ -2053,23 +2019,23 @@ km: explanation: អនុញ្ញាតឱ្យអ្នកប្រើភ្ជាប់ការចុះឈ្មោះទៅករណីមួយពីទម្រង់បែបបទព័ត៌មានលម្អិតនៃការចុះបញ្ជី។ ក៏អនុញ្ញាតឱ្យអ្នកប្រើលុបការភ្ជាប់ការចុះបញ្ជីណាមួយដែលបានភ្ជាប់ទៅករណី។ label: បន្ថែម / ធ្វើបច្ចុប្បន្នភាពកំណត់ត្រាចុះបញ្ជីពីករណី approve_action_plan: - explanation: "អនុញ្ញាតឱ្យអ្នកគ្រប់គ្រងអនុម័ត%{approval_label}លើករណីរបស់អ្នកកាន់ករណីក្នុងក្រុម។" - label: "អនុម័ត​%{approval_label}" + explanation: អនុញ្ញាតឱ្យអ្នកគ្រប់គ្រងអនុម័ត%{approval_label}លើករណីរបស់អ្នកកាន់ករណីក្នុងក្រុម។ + label: អនុម័ត​%{approval_label} approve_assessment: - explanation: "អនុញ្ញាតឱ្យអ្នកគ្រប់គ្រងអនុម័ត%{approval_label}លើករណីរបស់អ្នកកាន់ករណី" - label: "អនុម័ត%{approval_label}​ទម្រង់" + explanation: អនុញ្ញាតឱ្យអ្នកគ្រប់គ្រងអនុម័ត%{approval_label}លើករណីរបស់អ្នកកាន់ករណី + label: អនុម័ត%{approval_label}​ទម្រង់ approve_bia: - explanation: "អនុញ្ញាតឱ្យអ្នកគ្រប់គ្រងអនុម័ត%{approval_label}លើករណីរបស់អ្នកកាន់ករណីក្នុងក្រុម។" - label: "អនុម័ត%{approval_label}​ទម្រង់" + explanation: អនុញ្ញាតឱ្យអ្នកគ្រប់គ្រងអនុម័ត%{approval_label}លើករណីរបស់អ្នកកាន់ករណីក្នុងក្រុម។ + label: អនុម័ត%{approval_label}​ទម្រង់ approve_case_plan: - explanation: "អនុញ្ញាតឱ្យអ្នកគ្រប់គ្រងអនុម័ត%{approval_label}លើករណីរបស់អ្នកកាន់ករណីក្នុងក្រុម។" - label: "អនុម័ត​%{approval_label}" + explanation: អនុញ្ញាតឱ្យអ្នកគ្រប់គ្រងអនុម័ត%{approval_label}លើករណីរបស់អ្នកកាន់ករណីក្នុងក្រុម។ + label: អនុម័ត​%{approval_label} approve_closure: - explanation: "អនុញ្ញាតឱ្យអ្នកគ្រប់គ្រងអនុម័ត%{approval_label}លើករណីរបស់អ្នកកាន់ករណីក្នុងក្រុម។" - label: "អនុម័ត%{approval_label}​ទម្រង់" + explanation: អនុញ្ញាតឱ្យអ្នកគ្រប់គ្រងអនុម័ត%{approval_label}លើករណីរបស់អ្នកកាន់ករណីក្នុងក្រុម។ + label: អនុម័ត%{approval_label}​ទម្រង់ approve_gbv_closure: - explanation: "អនុញ្ញាតឱ្យអ្នកគ្រប់គ្រងអនុម័ត%{approval_label}លើករណីរបស់អ្នកកាន់ករណី" - label: "អនុម័ត%{approval_label}​ទម្រង់" + explanation: អនុញ្ញាតឱ្យអ្នកគ្រប់គ្រងអនុម័ត%{approval_label}លើករណីរបស់អ្នកកាន់ករណី + label: អនុម័ត%{approval_label}​ទម្រង់ assign: explanation: អនុញ្ញាតឱ្យអ្នកប្រើផ្ញើករណីពីម្ចាស់កំណត់ត្រាដើមទៅអ្នកប្រើប្រាស់ផ្សេងទៀតក្នុងប្រព័ន្ធ។ មិនចាំបាច់មានការយល់ព្រមពីកុមារសម្រាប់សកម្មភាពនេះទេ។ មិនដូចការផ្ទេរទេ អ្នកទទួលមិនត្រូវបានផ្តល់ឱកាសឱ្យទទួលយក ឬបដិសេធកិច្ចការនោះទេ។ label: ចាត់តាំង @@ -2084,7 +2050,7 @@ km: label: កំណត់ត្រានៃសកម្មភាពកែសម្រួល close: explanation: អនុញ្ញាតឱ្យអ្នកប្រើកំណត់ស្ថានភាពនៃករណីបើកទៅករណីបិទ។ - label: បិទ + label: បិទករណី consent_override: explanation: អនុញ្ញាត​ឱ្យ​អ្នក​ប្រើ​ធ្វើ​ការ​បញ្ជូន​ឬ​ផ្ទេរ​សម្រាប់​ករណី​ដែល​មិន​បាន​ផ្តល់​ការ​យល់ព្រម​។ label: ធ្វើការបញ្ជូន ឬផ្ទេរ ដែលមិនមានការយល់ព្រម @@ -2096,7 +2062,7 @@ km: label: បង្ហាញ​ទំព័រ​ទិដ្ឋភាព enable_disable_record: explanation: អាចបិទដំណើរការឬបើកករណី។ ករណី "បិទដំណើរការ" មិនបង្ហាញតាមលំនាំដើមក្នុងបញ្ជីករណីទេ។ អ្នកប្រើប្រាស់អាចមើលឃើញករណីដែលបិទដំណើរការនៅក្នុងបញ្ជីករណីដោយប្រើតម្រង។ ដោយសារ Primero មិនអនុញ្ញាតឱ្យអ្នកប្រើលុបករណី អ្នកប្រើប្រាស់អាចចង់បិទដំណើរការករណីជំនួសវិញ។ ឧទាហរណ៍ ប្រសិនបើអ្នកប្រើបង្កើតករណីដោយច្រឡំ ឬករណីមានទិន្នន័យមិនល្អ អ្នកប្រើប្រាស់គួរតែបិទដំណើរការវា។ - label: បើក/បិទដំណើរការករណី + label: បើក/បិទដំណើរការ export_case_pdf: explanation: អ្នកប្រើប្រាស់អាចបង្កើតការនាំចេញឯកសារ PDF ពីបញ្ជីករណី ឬទំព័របង្ហាញករណី ដែលមានសំណួរទាំងអស់ដែលអ្នកប្រើប្រាស់បច្ចុប្បន្នមានសិទ្ធិចូលប្រើ សម្រាប់ករណីមួយ ច្រើន ឬគ្រប់ករណីដែលអ្នកប្រើប្រាស់មានសិទ្ធិចូលប្រើប្រាស់។ នៅក្នុងឯកសារនាំចេញ PDF ព័ត៌មានត្រូវបានរាយបញ្ជីដំបូងតាមករណី ហើយបន្ទាប់មករៀបចំតាមទម្រង់ដែលព័ត៌មានជាបន្តបន្ទាប់។ label: នាំចេញ​ករណីជា pdf @@ -2114,7 +2080,7 @@ km: label: នាំចេញជាឯកសារJSON export_list_view_csv: explanation: អ្នកប្រើប្រាស់អាចបង្កើតការនាំចេញឯកសារ CSV ពីទំព័របញ្ជីករណីដែលមានសំណួរដូចគ្នាដែលលេចឡើងសម្រាប់អ្នកប្រើប្រាស់នោះក្នុងបញ្ជីករណី។ អនុវត្តតែពីទំព័របញ្ជីករណីប៉ុណ្ណោះ។ - label: Export list view CSV + label: នាំចេញ​បញ្ជីករណីជាឯកសារ cvs export_pdf: explanation: អ្នកប្រើប្រាស់អាចបង្កើតការនាំចេញឯកសារ PDF ពីបញ្ជីឧប្បត្តិហេតុ ឬទំព័របង្ហាញឧប្បត្តិហេតុ ដែលមានសំណួរទាំងអស់ដែលអ្នកប្រើប្រាស់បច្ចុប្បន្នមានសិទ្ធិចូលប្រើ សម្រាប់កំណត់ត្រាមួយ ច្រើន ឬទាំងអស់ដែលអ្នកប្រើប្រាស់មានសិទ្ធិចូលប្រើ។ នៅក្នុងឯកសារនាំចេញ PDF ព័ត៌មានត្រូវបានរាយបញ្ជីដំបូងតាមករណី ហើយបន្ទាប់មករៀបចំបន្ថែមទៀតដោយទម្រង់ដែលព័ត៌មានលេចឡើង។ label: នាំចេញ​ករណីជា pdf @@ -2125,7 +2091,7 @@ km: label: Export UNHCR CSV export_xls: explanation: 'អ្នកប្រើប្រាស់អាចបង្កើតការនាំចេញឯកសារ XLS ពីបញ្ជីករណី ឬទំព័របង្ហាញករណី ដែលមានសំណួរទាំងអស់ សម្រាប់ករណីមួយ ច្រើន ឬគ្រប់ករណីទាំងអស់ដែលអ្នកប្រើប្រាស់មានសិទ្ធិចូលប្រើប្រាស់។ នៅក្នុងការនាំចេញនេះ ទម្រង់នីមួយៗត្រូវបានតំណាងនៅក្នុងផ្ទាំងរបស់វានៅក្នុងឯកសារ XLS។ ចំណាំ៖ ទ្រង់ទ្រាយ XLS បង្ហាញតួអក្សរដែលមិនមែនជាឡាតាំង (ឧ. អារ៉ាប់, Bangla) ក្នុងទម្រង់ដែលអាចអានបាន ខណៈពេលដែលការនាំចេញ CSV មិនដំណើរការ។' - label: "នាំចេញឯកសារ​​​ Excel (XLS file) " + label: 'នាំចេញឯកសារ​​​ Excel (XLS file) ' find_tracing_match: explanation: វា​ត្រូវ​បាន​ប្រើ​សម្រាប់​បរិបទ​ដែល​មាន​សកម្មភាពស្វែងរកគ្រួសារ និង​ការ​បង្រួបបង្រួម។ អ្នកប្រើប្រាស់ដែលមានការអនុញ្ញាតនេះនឹងឃើញប៊ូតុង "ស្វែងរកការផ្គូផ្គងការស្វែងរក" នៅលើទំព័របង្ហាញករណី។ នៅពេលពួកគេចុចវា ពួកគេនឹងទៅដល់បញ្ជីនៃសំណើស្វែងរកនៅក្នុងប្រព័ន្ធ ដែលជាការផ្គូផ្គងសក្តានុពលសម្រាប់ករណីរបស់ពួកគេ។ label: ស្វែងរកការផ្គូផ្គងករណី @@ -2133,7 +2099,9 @@ km: explanation: អាចបន្ថែមសម្គាល់ទៅលើករណីមួយ។ អ្នក​ប្រើ​ដែល​មាន​ការ​អនុញ្ញាត​នេះ​ក៏​អាច​លុបសម្គាល់​​ដែល​ពួក​គេ​បាន​បន្ថែម​ទៅលើករណីមួយ​​ផង​ដែរ។ label: សម្គាល់ import: - explanation: "អនុញ្ញាតឱ្យអ្នកប្រើបង្កើតករណីថ្មីមួយ ឬច្រើនដោយនាំចូលពួកវាពីឯកសារ CSV, Excel ឬ JSON ។ ឯកសារដែលបាននាំចូលត្រូវតែធ្វើទ្រង់ទ្រាយ *ខ្លាំងណាស់* ជាពិសេសសម្រាប់ព័ត៌មានដែលត្រូវនាំចូលត្រឹមត្រូវ។ មុខងារនេះគួរតែមានសម្រាប់តែអ្នកប្រើប្រាស់រដ្ឋបាលដែលមានជំនាញបច្ចេកទេសកម្រិតខ្ពស់ និងចំណេះដឹងស៊ីជម្រៅអំពីរបៀបធ្វើទ្រង់ទ្រាយទិន្នន័យនៅក្នុង Primero ប៉ុណ្ណោះ។ អនុវត្តតែពីទំព័របញ្ជីករណីប៉ុណ្ណោះ។\n " + explanation: 'អនុញ្ញាតឱ្យអ្នកប្រើបង្កើតករណីថ្មីមួយ ឬច្រើនដោយនាំចូលពួកវាពីឯកសារ CSV, Excel ឬ JSON ។ ឯកសារដែលបាននាំចូលត្រូវតែធ្វើទ្រង់ទ្រាយ *ខ្លាំងណាស់* ជាពិសេសសម្រាប់ព័ត៌មានដែលត្រូវនាំចូលត្រឹមត្រូវ។ មុខងារនេះគួរតែមានសម្រាប់តែអ្នកប្រើប្រាស់រដ្ឋបាលដែលមានជំនាញបច្ចេកទេសកម្រិតខ្ពស់ និងចំណេះដឹងស៊ីជម្រៅអំពីរបៀបធ្វើទ្រង់ទ្រាយទិន្នន័យនៅក្នុង Primero ប៉ុណ្ណោះ។ អនុវត្តតែពីទំព័របញ្ជីករណីប៉ុណ្ណោះ។ + +  ' label: នាំចូល incident_details_from_case: explanation: អាចបន្ថែមព័ត៌មានសម្រាប់ទម្រង់រងព័ត៌មានលម្អិតឧប្បត្តិហេតុលើករណីដែលអ្នកបានរកឃើញនៅក្នុងលទ្ធផលស្វែងរក ប៉ុន្តែអ្នកមិនមានសិទ្ធិចូលប្រើ។ អ្នកប្រើប្រាស់អនុវត្តសកម្មភាពនេះពីទំព័រលទ្ធផលស្វែងរកដោយជ្រើសរើសករណីមួយ ឬច្រើន បន្ទាប់មកជ្រើសរើស "បន្ថែមឧប្បត្តិហេតុ" ពីម៉ឺនុយសកម្មភាព។ បន្ទាប់មកអ្នកប្រើប្រាស់នឹងឃើញម៉ូឌុលដែលមានសំណួរទាំងអស់នៅលើទម្រង់រងនៃព័ត៌មានលម្អិតឧប្បត្តិហេតុ ដែលពួកគេអាចបញ្ចូល និងបញ្ជូនព័ត៌មានអំពីសេវាកម្មមួយ។ ដោយសារតែសកម្មភាពនេះអាចអនុវត្តបានតែពីទំព័រលទ្ធផលស្វែងរកប៉ុណ្ណោះ វាសមហេតុផលសម្រាប់តួនាទីដែលមានការអនុញ្ញាតនេះ ប្រសិនបើពួកគេក៏មានការអនុញ្ញាត "ស្វែងរកករណីដែលគ្រប់គ្រងដោយអ្នកប្រើប្រាស់ផ្សេងទៀត" ផងដែរ។ @@ -2169,23 +2137,23 @@ km: explanation: អនុញ្ញាតឱ្យអ្នកប្រើប្រាស់បើកករណីដែលបានបិទហើយ label: បើក​ឡើងវិញ request_approval_action_plan: - explanation: "អនុញ្ញាតឲ្យអ្នកប្រើប្រាស់ (ជាធម្មតាជាអ្នកកាន់ករណី) ស្នើសុំឱ្យអ្នកគ្រប់គ្រងរបស់ពួកគេអនុម័តលើករណីរបស់ពួកគេ%{approval_label}។" - label: "ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត" + explanation: អនុញ្ញាតឲ្យអ្នកប្រើប្រាស់ (ជាធម្មតាជាអ្នកកាន់ករណី) ស្នើសុំឱ្យអ្នកគ្រប់គ្រងរបស់ពួកគេអនុម័តលើករណីរបស់ពួកគេ%{approval_label}។ + label: ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត request_approval_assessment: - explanation: "អនុញ្ញាតឲ្យអ្នកប្រើប្រាស់ (ជាធម្មតាជាអ្នកកាន់ករណី) ស្នើសុំឱ្យអ្នកគ្រប់គ្រងរបស់ពួកគេអនុម័តលើករណីរបស់ពួកគេ%{approval_label}។" - label: "ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត" + explanation: អនុញ្ញាតឲ្យអ្នកប្រើប្រាស់ (ជាធម្មតាជាអ្នកកាន់ករណី) ស្នើសុំឱ្យអ្នកគ្រប់គ្រងរបស់ពួកគេអនុម័តលើករណីរបស់ពួកគេ%{approval_label}។ + label: ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត request_approval_bia: - explanation: "អនុញ្ញាតឲ្យអ្នកប្រើប្រាស់ (ជាធម្មតាជាអ្នកកាន់ករណី) ស្នើសុំឱ្យអ្នកគ្រប់គ្រងរបស់ពួកគេអនុម័តលើករណីរបស់ពួកគេ%{approval_label}។" - label: "ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត" + explanation: អនុញ្ញាតឲ្យអ្នកប្រើប្រាស់ (ជាធម្មតាជាអ្នកកាន់ករណី) ស្នើសុំឱ្យអ្នកគ្រប់គ្រងរបស់ពួកគេអនុម័តលើករណីរបស់ពួកគេ%{approval_label}។ + label: ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត request_approval_case_plan: - explanation: "អនុញ្ញាតឲ្យអ្នកប្រើប្រាស់ (ជាធម្មតាជាអ្នកកាន់ករណី) ស្នើសុំឱ្យអ្នកគ្រប់គ្រងរបស់ពួកគេអនុម័តករណីរបស់ពួកគេ%{approval_label}។" - label: "ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត" + explanation: អនុញ្ញាតឲ្យអ្នកប្រើប្រាស់ (ជាធម្មតាជាអ្នកកាន់ករណី) ស្នើសុំឱ្យអ្នកគ្រប់គ្រងរបស់ពួកគេអនុម័តករណីរបស់ពួកគេ%{approval_label}។ + label: ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត request_approval_closure: - explanation: "អនុញ្ញាតឲ្យអ្នកប្រើប្រាស់ (ជាធម្មតាជាអ្នកកាន់ករណី) ស្នើសុំឱ្យអ្នកគ្រប់គ្រងរបស់ពួកគេអនុម័តលើករណីរបស់ពួកគេ%{approval_label}។" - label: "ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត" + explanation: អនុញ្ញាតឲ្យអ្នកប្រើប្រាស់ (ជាធម្មតាជាអ្នកកាន់ករណី) ស្នើសុំឱ្យអ្នកគ្រប់គ្រងរបស់ពួកគេអនុម័តលើករណីរបស់ពួកគេ%{approval_label}។ + label: ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត request_approval_gbv_closure: - explanation: "អនុញ្ញាតឲ្យអ្នកប្រើប្រាស់ (ជាធម្មតាជាអ្នកកាន់ករណី) ស្នើសុំឱ្យអ្នកគ្រប់គ្រងរបស់ពួកគេអនុម័តលើករណីរបស់ពួកគេ%{approval_label}។" - label: "ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត" + explanation: អនុញ្ញាតឲ្យអ្នកប្រើប្រាស់ (ជាធម្មតាជាអ្នកកាន់ករណី) ស្នើសុំឱ្យអ្នកគ្រប់គ្រងរបស់ពួកគេអនុម័តលើករណីរបស់ពួកគេ%{approval_label}។ + label: ស្នើ​សុំ​%{approval_label}ការ​អនុម័ត request_transfer: explanation: បង្ហាញប៊ូតុង "ស្នើសុំផ្ទេរ" នៅលើ "មើលម៉ូឌុល" ។ ប៊ូតុងអនុញ្ញាតឱ្យអ្នកប្រើប្រាស់ផ្ញើសារជាមួយនឹងកំណត់ចំណាំផ្ទាល់ខ្លួនតាមរយៈអ៊ីមែលទៅកាន់ម្ចាស់កំណត់ត្រាបច្ចុប្បន្ននៃករណី ដោយស្នើសុំឱ្យម្ចាស់កំណត់ត្រាផ្ទេរករណីទៅអ្នកប្រើប្រាស់ដែលបានផ្ញើសំណើ។ វាមានប្រយោជន៍ក្នុងបរិបទដែលកុមារផ្លាស់ប្តូរទីតាំងជាញឹកញាប់ ហើយអ្នកធ្វើការករណីត្រូវការបុគ្គលិកករណីមុនរបស់កុមារដើម្បីបញ្ជូនព័ត៌មានអំពីកុមារ ដើម្បីជៀសវាងការបង្កើតករណីស្ទួន។ label: ស្នើ​សុំ​ការ​ផ្ទេរ @@ -2206,7 +2174,7 @@ km: label: ប្រើសម្រាប់ពេលគ្មានសេវាអីនធឺណេត transfer: explanation: អនុញ្ញាតឱ្យអ្នកប្រើផ្ញើករណីពីម្ចាស់កំណត់ត្រាបច្ចុប្បន្នរបស់វាទៅអ្នកប្រើប្រាស់ណាមួយនៅក្នុងប្រព័ន្ធដែលមានលទ្ធភាពទទួលការផ្ទេរ។ ទោះជាយ៉ាងណាក៏ដោយ ម្ចាស់កំណត់ត្រានៃសំណុំរឿងមិនផ្លាស់ប្តូរទេ រហូតដល់អ្នកទទួលការផ្ទេរនេះ "ទទួលយក" វា។ ប្រសិនបើអ្នកទទួល "បដិសេធ" ការផ្ទេរ អ្នកទទួលបាត់បង់សិទ្ធិចូលប្រើករណីនេះ ហើយវារក្សាម្ចាស់កំណត់ត្រាដើមរបស់វា។ - label: "ផ្ទេរ " + label: 'ផ្ទេរ ' view_photo: explanation: អនុញ្ញាតឱ្យអ្នកប្រើមើលឃើញរូបថតករណីពីបញ្ជីករណី។ បើគ្មានការអនុញ្ញាតនេះទេ អ្នកប្រើប្រាស់មិនឃើញជួរឈរ "រូបថត" នៃតារាងបញ្ជីករណី ឬរូបតំណាងរូបថតដែលបង្ហាញនៅទីនោះទេ។ ការអនុញ្ញាតនេះក៏អនុញ្ញាតឱ្យអ្នកប្រើប្រាស់មើលឃើញរូបថតរបស់កុមារនៅក្នុង "View Modal" ផងដែរ។ label: មើលរូបថតពីបញ្ជីករណី @@ -2237,34 +2205,34 @@ km: actions: approvals_action_plan: explanation: បង្ហាញចំនួនករណីរបស់អ្នកប្រើប្រាស់បច្ចុប្បន្នជាមួយនឹងសំណើការអនុម័តផែនការ ដែលកំពុងរងចាំ អនុម័ត ឬបដិសេធ។ - label: "អ្នកកាន់ករណី%{approval_label}អនុម័ត" + label: អ្នកកាន់ករណី%{approval_label}អនុម័ត approvals_action_plan_pending: explanation: បង្ហាញចំនួនករណីនៅក្នុងក្រុមរបស់អ្នកគ្រប់គ្រងនូវសំណើអនុម័តផែនការដែលកំពុងរងចាំ - label: "អ្នកគ្រប់គ្រង%{approval_label}អនុម័ត" + label: អ្នកគ្រប់គ្រង%{approval_label}អនុម័ត approvals_assessment: explanation: បង្ហាញចំនួនករណីរបស់អ្នកប្រើប្រាស់បច្ចុប្បន្នជាមួយនឹងសំណើការអនុម័តប៉ាន់ប្រមាណដែលកំពុងរងចាំ អនុម័ត ឬបដិសេធ។ - label: "អ្នកកាន់ករណី%{approval_label}អនុម័ត" + label: អ្នកកាន់ករណី%{approval_label}អនុម័ត approvals_assessment_pending: explanation: បង្ហាញចំនួនករណីនៅក្នុងក្រុមរបស់អ្នកគ្រប់គ្រងនូវសំណើអនុម័តការប៉ាន់ប្រមាណដែលកំពុងរងចាំ - label: "អ្នកគ្រប់គ្រង%{approval_label}អនុម័ត" + label: អ្នកគ្រប់គ្រង%{approval_label}អនុម័ត approvals_case_plan: explanation: បង្ហាញចំនួនករណីរបស់អ្នកប្រើប្រាស់បច្ចុប្បន្នជាមួយនឹងសំណើការអនុម័តផែនការ ដែលកំពុងរងចាំ អនុម័ត ឬបដិសេធ។ - label: "អ្នកកាន់ករណី%{approval_label}អនុម័ត" + label: អ្នកកាន់ករណី%{approval_label}អនុម័ត approvals_case_plan_pending: explanation: បង្ហាញចំនួនករណីនៅក្នុងក្រុមរបស់អ្នកគ្រប់គ្រងនូវសំណើអនុម័តផែនការដែលកំពុងរងចាំ - label: "អ្នកគ្រប់គ្រង%{approval_label}អនុម័ត" + label: អ្នកគ្រប់គ្រង%{approval_label}អនុម័ត approvals_closure: explanation: បង្ហាញចំនួនករណីរបស់អ្នកប្រើប្រាស់បច្ចុប្បន្នជាមួយនឹងសំណើការអនុម័តបិទ ដែលរង់ចាំ អនុម័ត ឬបដិសេធ។ - label: "អ្នកកាន់ករណី%{approval_label}អនុម័ត" + label: អ្នកកាន់ករណី%{approval_label}អនុម័ត approvals_closure_pending: explanation: បង្ហាញចំនួនករណីនៅក្នុងក្រុមរបស់អ្នកគ្រប់គ្រងដែលមានសំណើអនុម័តការបិទកំពុងរងចាំ - label: "អ្នកគ្រប់គ្រង%{approval_label}អនុម័ត" + label: អ្នកគ្រប់គ្រង%{approval_label}អនុម័ត approvals_gbv_closure: explanation: បង្ហាញចំនួនករណីរបស់អ្នកប្រើប្រាស់បច្ចុប្បន្នជាមួយនឹងសំណើការអនុម័តបិទ ដែលរង់ចាំ អនុម័ត ឬបដិសេធ។ - label: "អ្នកកាន់ករណី%{approval_label}អនុម័ត" + label: អ្នកកាន់ករណី%{approval_label}អនុម័ត approvals_gbv_closure_pending: explanation: បង្ហាញចំនួនករណីនៅក្នុងក្រុមរបស់អ្នកគ្រប់គ្រងដែលមានសំណើអនុម័តការបិទកំពុងរងចាំ - label: "អ្នកគ្រប់គ្រង%{approval_label}អនុម័ត" + label: អ្នកគ្រប់គ្រង%{approval_label}អនុម័ត case_overview: explanation: ផ្ទាំងគ្រប់គ្រងទិន្នន័យទូទៅនៅផ្នែកខាងលើនៃទំព័រដើម ដែលរួមបញ្ចូលតួលេខដូចជាករណីសរុប និងករណីថ្មី។ label: ផ្ទាំងគ្រប់គ្រងទិន្នន័យ @@ -2284,7 +2252,6 @@ km: explanation: អនុញ្ញាតឱ្យអ្នកគ្រប់គ្រងមើលថាតើករណីប៉ុន្មានដែលហួសកាលកំណត់ផ្តល់សេវាសម្រាប់អ្នកកាន់ករណីនីមួយៗ។ label: ការងារផ្តល់សេវាបានហួសកាលកំណត់ dash_case_incident_overview: - explanation: . label: ទិដ្ឋភាពទូទៅ - ករណីរបស់ខ្ញុំ / ឧប្បត្តិហេតុ dash_cases_by_social_worker: explanation: តារាងដែលបង្ហាញពីរបៀបដែលចំនួនសរុបនៃករណីបើក និងចំនួនករណីថ្មីដែលគ្រប់គ្រងដោយអ្នកប្រើប្រាស់នីមួយៗនៅក្នុងក្រុមអ្នកប្រើប្រាស់បច្ចុប្បន្ន។ ជួរនីមួយៗគឺជាអ្នកប្រើប្រាស់នៅក្នុងក្រុមអ្នកប្រើប្រាស់បច្ចុប្បន្ន ខណៈពេលដែល "សរុប" និង "ថ្មី" គឺជាជួរទាំងពីរ។ @@ -2318,7 +2285,7 @@ km: label: ករណីបញ្ជូន/ផ្ទេរពីក្រុមខ្ញុំ dash_shared_with_me: explanation: បង្ហាញចំនួនករណីដែលត្រូវបានបញ្ជូន ឬផ្ទេរទៅឱ្យអ្នក។ - label: ករណីបញ្ជូន/ផ្ទេរមកខ្ញុំ + label: ករណីបញ្ជូន ឬផ្ទេរមកខ្ញុំ dash_shared_with_my_team: explanation: បង្ហាញអ្នកគ្រប់គ្រងនូវចំនួនករណីបញ្ជូន និងផ្ទេររបស់អ្នកប្រើប្រាស់និមួយៗនៅក្នុងក្រុម។ label: ករណីបញ្ជូន/ផ្ទេរមកក្រុមខ្ញុំ @@ -2326,7 +2293,7 @@ km: label: ករណីបញ្ជូន/ផ្ទេរមកក្រុមខ្ញុំ dash_shared_with_others: explanation: បង្ហាញចំនួនករណីរបស់ខ្ញុំដែលមានការបញ្ជូនសកម្ម ការផ្ទេរកំពុងរងចាំ ឬការផ្ទេរដែលត្រូវបានបដិសេធ។ ជាធម្មតាមិនមែនសម្រាប់អ្នកគ្រប់គ្រងទេ លុះត្រាតែពួកគេគ្រប់គ្រងករណីដោយខ្លួនឯង។ - label: ករណីបញ្ជូន/ផ្ទេរពីខ្ញុំ + label: 'ករណីបញ្ជូន ឬផ្ទេរពីខ្ញុំ ' dash_show_none_values: explanation: បន្ថែមប្រភេទ "គ្មានកម្រិតហានិភ័យ" បន្ថែមទៅលើផ្ទាំងគ្រប់គ្រងទាំងអស់ ដែលបំបែកករណីតាមកម្រិតហានិភ័យ។ នេះជាពិសេសសម្រាប់ការកំណត់ដែលមានជម្រើសទីបួន "គ្មានហានិភ័យ" សម្រាប់កម្រិតហានិភ័យ។ label: មើល​ករណី​ដែល '​គ្មាន​ហានិភ័យ' នៅ​ក្នុង​ផ្ទាំង​ព័ត៌មាន​ការ​ប៉ាន់ប្រមាណ @@ -2349,7 +2316,7 @@ km: label: ផ្ទាំងព័ត៌មាន disabled: explanation: ប្រសិនបើអ្នកបិទតួនាទីនេះ អ្នកនឹងមិនអាចចាត់តាំងវាទៅគណនីអ្នកប្រើប្រាស់បានទេ។ - label: បិទករណី (disable case) + label: បិទដំណើរការ (disable) duplicate: actions: read: @@ -2388,7 +2355,7 @@ km: explanation: តួនាទីអាចចូលប្រើកំណត់ត្រាផ្ទាល់ខ្លួនរបស់ពួកគេ (ករណី សំណើស្វែងរក ឬឧប្បត្តិហេតុ) និងអាចកែសម្រួលគណនីអ្នកប្រើប្រាស់ផ្ទាល់ខ្លួនរបស់ពួកគេ។ label: ចូលប្រើប្រាស់​តែ​កំណត់ត្រា ឬ​អ្នក​ប្រើប្រាស់​របស់ខ្ញុំ​ប៉ុណ្ណោះ explanation: គ្រប់គ្រងការកត់ត្រាណាមួយ (ករណី សំណើស្វែងរក ឬឧប្បត្តិហេតុ) តួនាទីអាចចូលប្រើបាន។ ប្រសិនបើតួនាទីមានសិទ្ធិចូលប្រើ Users និង User Groups នេះក៏គ្រប់គ្រង Users និង User Group ដែលពួកគេអាចចូលប្រើបាន។ តួនាទីដែលមានសិទ្ធិចូលប្រើ "គ្មានកំណត់ត្រា" អាចចូលប្រើបានតែការកំណត់រចនាសម្ព័ន្ធប្រព័ន្ធដូចជា ទម្រង់ អ្នកប្រើប្រាស់ និងរបាយការណ៍។ - label: "តើ​តួនាទី​នេះ​ប៉ះពាល់​ដល់​កំណត់ត្រា​អ្វីដែរ?​" + label: តើ​តួនាទី​នេះ​ប៉ះពាល់​ដល់​កំណត់ត្រា​អ្វីដែរ?​ incident: actions: change_log: @@ -2399,7 +2366,7 @@ km: label: បង្កើត enable_disable_record: explanation: អាចបិទឬបើកហេតុការណ៍។ ពេល"បិទ" ហេតុការណ៍នឹងមិនបង្ហាញនៅលើបញ្ជីហេតុការណ៍ទេ។ អ្នក​ប្រើ​អាច​មើល​ឃើញ​ហេតុការណ៍​ដែល​បាន​បិទ​ក្នុង​បញ្ជី​ហេតុការណ៍​ដោយ​អនុវត្ត​តម្រង។ - label: បើក/បិទដំណើរការករណី + label: បើក/បិទដំណើរការ export_case_pdf: explanation: អ្នកប្រើប្រាស់អាចបង្កើតការនាំចេញឯកសារ PDF ពីបញ្ជីឧប្បត្តិហេតុ ឬទំព័របង្ហាញឧប្បត្តិហេតុ ដែលមានសំណួរទាំងអស់ដែលអ្នកប្រើប្រាស់បច្ចុប្បន្នមានសិទ្ធិចូលប្រើ សម្រាប់កំណត់ត្រាមួយ ច្រើន ឬទាំងអស់ដែលអ្នកប្រើប្រាស់មានសិទ្ធិចូលប្រើ។ នៅក្នុងឯកសារនាំចេញ PDF ព័ត៌មានត្រូវបានរាយបញ្ជីដំបូងតាមករណី ហើយបន្ទាប់មករៀបចំបន្ថែមទៀតដោយទម្រង់ដែលព័ត៌មានលេចឡើង។ label: នាំចេញជាឯកសារ PDF @@ -2416,18 +2383,18 @@ km: label: នាំចេញជាឯកសារJSON export_list_view_csv: explanation: អ្នកប្រើប្រាស់អាចបង្កើតការនាំចេញឯកសារ CSV ពីទំព័របញ្ជីឧប្បត្តិហេតុដែលមានសំណួរដូចគ្នាដែលលេចឡើងសម្រាប់អ្នកប្រើប្រាស់នោះក្នុងបញ្ជីឧប្បត្តិហេតុ។ អនុវត្តតែពីទំព័របញ្ជីឧប្បត្តិហេតុប៉ុណ្ណោះ។ - label: Export list view CSV + label: នាំចេញ​បញ្ជីករណីជាឯកសារ cvs export_pdf: explanation: អ្នកប្រើប្រាស់អាចបង្កើតការនាំចេញឯកសារ PDF ពីបញ្ជីឧប្បត្តិហេតុ ឬទំព័របង្ហាញឧប្បត្តិហេតុ ដែលមានសំណួរទាំងអស់ដែលអ្នកប្រើប្រាស់បច្ចុប្បន្នមានសិទ្ធិចូលប្រើ សម្រាប់កំណត់ត្រាមួយ ច្រើន ឬទាំងអស់ដែលអ្នកប្រើប្រាស់មានសិទ្ធិចូលប្រើ។ នៅក្នុងឯកសារនាំចេញ PDF ព័ត៌មានត្រូវបានរាយបញ្ជីដំបូងតាមករណី ហើយបន្ទាប់មករៀបចំបន្ថែមទៀតដោយទម្រង់ដែលព័ត៌មានលេចឡើង។ label: នាំចេញជាឯកសារ PDF export_xls: explanation: អ្នកប្រើប្រាស់អាចបង្កើតការនាំចេញឯកសារ XLS ពីបញ្ជីឧប្បត្តិហេតុ ឬទំព័របង្ហាញឧប្បត្តិហេតុ ដែលមានសំណុំទម្រង់ ឬសំពួរផ្ទាល់ខ្លួន សម្រាប់ករណីមួយ ច្រើន ឬគ្រប់ករណីដែលអ្នកប្រើប្រាស់មានសិទ្ធិចូលប្រើប្រាស់។ នៅក្នុងការនាំចេញនេះ ទម្រង់នីមួយៗត្រូវបានតំណាងនៅក្នុងផ្ទាំងរបស់វាផ្ទាល់នៅក្នុងឯកសារ XLS។ អ្នក​ប្រើ​អាច​ជ្រើស​ទម្រង់​ឬ​វាល​មួយ​ណា​ដែល​ពួកគេ​ចង់​បាន​រួម​បញ្ចូល​ក្នុង​ការ​នាំ​ចេញ​ដោយ​ប្រើ​ម៉ូឌុល​នាំចេញ​ផ្ទាល់ខ្លួន។ សូមចំណាំថា អ្នកប្រើប្រាស់អាចបញ្ចូលទម្រង់ និងសំណួរនៅក្នុងការនាំចេញតែប៉ុណ្ណោះ ប្រសិនបើពួកគេមានលទ្ធភាពមើលទម្រង់ និងសំណួរទាំងនោះរួចហើយ នៅពេលមើលករណីនៅក្នុងកម្មវិធី។ - label: "នាំចេញឯកសារ​​​ Excel (XLS file) " + label: 'នាំចេញឯកសារ​​​ Excel (XLS file) ' flag: explanation: អាចបន្ថែមសម្គាល់ទៅលើឧប្បត្តិហេតុ។ អ្នក​ប្រើ​ដែល​មាន​ការ​អនុញ្ញាត​នេះ​ក៏​អាច​លុបសម្គាល់​​ដែល​ពួក​គេ​បាន​បន្ថែម​ទៅលើឧប្បត្តិហេតុ​​ផង​ដែរ។ label: សម្គាល់ import: - explanation: "អនុញ្ញាតឱ្យអ្នកប្រើបង្កើតករណីថ្មីមួយ ឬច្រើនដោយនាំចូលពួកវាពីឯកសារ CSV, Excel ឬ JSON ។ ឯកសារដែលបាននាំចូលត្រូវតែformat *ខ្លាំងណាស់* ជាពិសេសសម្រាប់ព័ត៌មានដែលត្រូវនាំចូលត្រឹមត្រូវ។ មុខងារនេះគួរតែមានសម្រាប់តែអ្នកប្រើប្រាស់រដ្ឋបាលដែលមានជំនាញបច្ចេកទេសកម្រិតខ្ពស់ និងចំណេះដឹងស៊ីជម្រៅអំពីរបៀបធ្វើformat ទិន្នន័យនៅក្នុង Primero ប៉ុណ្ណោះ។ អនុវត្តតែពីទំព័របញ្ជីករណីប៉ុណ្ណោះ។" + explanation: អនុញ្ញាតឱ្យអ្នកប្រើបង្កើតករណីថ្មីមួយ ឬច្រើនដោយនាំចូលពួកវាពីឯកសារ CSV, Excel ឬ JSON ។ ឯកសារដែលបាននាំចូលត្រូវតែformat *ខ្លាំងណាស់* ជាពិសេសសម្រាប់ព័ត៌មានដែលត្រូវនាំចូលត្រឹមត្រូវ។ មុខងារនេះគួរតែមានសម្រាប់តែអ្នកប្រើប្រាស់រដ្ឋបាលដែលមានជំនាញបច្ចេកទេសកម្រិតខ្ពស់ និងចំណេះដឹងស៊ីជម្រៅអំពីរបៀបធ្វើformat ទិន្នន័យនៅក្នុង Primero ប៉ុណ្ណោះ។ អនុវត្តតែពីទំព័របញ្ជីករណីប៉ុណ្ណោះ។ label: នាំចូល manage: explanation: អនុញ្ញាតឱ្យអ្នកប្រើប្រាស់មួយអាចអនុវត្តសកម្មភាពដែលមានទាំងអស់សម្រាប់ឧប្បត្តិហេតុ។ ការអនុញ្ញាត "គ្រប់គ្រង" មានន័យថា "អ្វីគ្រប់យ៉ាង" ។ @@ -2445,7 +2412,7 @@ km: label: ហេតុការណ៍ is_manager: explanation: អនុវត្តចំពោះតួនាទីអ្នកប្រើប្រាស់ណាដែលជាទូទៅគ្រប់គ្រងអ្នកប្រើប្រាស់ផ្សេងទៀត។ វាអនុញ្ញាតឱ្យអ្នកប្រើមើលឃើញផ្ទាំងគ្រប់គ្រង និងតម្រងដែលជួយអ្នកប្រើប្រាស់គ្រប់គ្រងក្រុម។ - label: "អ្នក​គ្រប់គ្រង?" + label: អ្នក​គ្រប់គ្រង? managed_report: actions: violations: @@ -2465,7 +2432,7 @@ km: explanation: អាចបង្កើត កែសម្រួល បកប្រែ និងលុបទម្រង់ សំណួរក្នុងទម្រង់ និងការស្វែងរក។ សូមចំណាំថាអ្នកប្រើប្រាស់ដែលមានការអនុញ្ញាតនេះនឹងអាចគ្រប់គ្រងទម្រង់ដែលពួកគេមានសិទ្ធិចូលប្រើប្រាស់ប៉ុណ្ណោះ។ ជាឧទាហរណ៍ ប្រសិនបើអ្នកគ្រប់គ្រងជាតិ (national admin)មានលទ្ធភាពមើលទម្រង់បែបបទម្ចាស់កំណត់ត្រាលើករណីប៉ុណ្ណោះ នោះពួកគេនឹងអាចធ្វើបច្ចុប្បន្នភាពការកំណត់សម្រាប់ទម្រង់បែបបទនេះ។ label: គ្រប់គ្រង (ការអនុញ្ញាតទាំងអស់សម្រាប់ប្រភេទធនធាននេះ) explanation: គ្រប់គ្រងសមត្ថភាពក្នុងការកំណត់រចនាសម្ព័ន្ធ Primero Forms និង Fields ក៏ដូចជាជម្រើសរកមើលដែលប្រើនៅក្នុងពួកវា។ - label: "ទម្រង់, ការ​រក​មើល" + label: ទម្រង់, ការ​រក​មើល module: actions: cp: @@ -2492,7 +2459,7 @@ km: actions: refer: explanation: នេះមានន័យថាតួនាទីនឹងបង្ហាញជាជម្រើសសម្រាប់ "ប្រភេទអ្នកទទួល" នៅពេលអ្នកប្រើប្រាស់ធ្វើការបញ្ជូនបន្តពីខាងក្រៅ។ ប្រសិនបើអ្នកប្រើជ្រើសរើសតួនាទីនេះជាប្រភេទនៃការបញ្ជូន នោះការនាំចេញដែល Primero បង្កើតនៅពេលអ្នកប្រើប្រាស់ដាក់បញ្ជូនការបញ្ជូននឹងមានព័ត៌មានដែលត្រូវបានរកឃើញនៅក្នុងទម្រង់ដែលតួនាទីនេះមានសិទ្ធិចូលប្រើ។ ដូច្នេះ ជាឧទាហរណ៍ ប្រសិនបើអ្នកប្រើប្រាស់ជ្រើសរើស "អ្នកផ្តល់សេវាវេជ្ជសាស្រ្ត" ជាប្រភេទអ្នកទទួល ហើយតួនាទីអ្នកផ្តល់សេវាវេជ្ជសាស្រ្តមានសិទ្ធិចូលប្រើទម្រង់ព័ត៌មានបឋម និងទម្រង់បញ្ហាជាកង្វល់តែប៉ុណ្ណោះ ។​ឯកសារដែលPrimero នាំចេញសម្រាប់ការបញ្ជូនខាងក្រៅនឹងមានតែព័ត៌មាននៅក្នុងទម្រង់ទាំងពីរនេះ។ - label: "តើ​អ្នក​ប្រើប្រាស់​នេះ​អាច​បញ្ជូនករណី​ទៅក្រៅប្រព័ន្ធបាន​ដែរ​ឬទេ?" + label: តើ​អ្នក​ប្រើប្រាស់​នេះ​អាច​បញ្ជូនករណី​ទៅក្រៅប្រព័ន្ធបាន​ដែរ​ឬទេ? label: ការបញ្ចូន registry_record: actions: @@ -2504,7 +2471,7 @@ km: label: បង្កើត enable_disable_record: explanation: អាចបិទឬបើកកំណត់ត្រាចុះបញ្ជី។ កំណត់ត្រា "បិទ" មិនបង្ហាញតាមលំនាំដើមក្នុងបញ្ជីឈ្មោះទេ។ អ្នក​ប្រើ​អាច​មើល​ឃើញ​ការ​ចុះ​បញ្ជី​ដែល​បាន​បិទ​ក្នុង​បញ្ជី​ឈ្មោះ​ដោយ​ប្រើ filter.ត្រា​លេខ។ - label: បើក / បិទ + label: 'បើក / បិទដំណើរការ ' export_csv: explanation: 'អ្នកប្រើប្រាស់អាចបង្កើតការនាំចេញឯកសារ CSV ពីបញ្ជីបញ្ជីឈ្មោះ ឬទំព័របង្ហាញបញ្ជីឈ្មោះ ដែលមានវាលទាំងអស់ដែលអ្នកប្រើប្រាស់បច្ចុប្បន្នមានសិទ្ធិចូលប្រើ សម្រាប់កំណត់ត្រាចុះបញ្ជីមួយ ច្រើន ឬទាំងអស់ដែលអ្នកប្រើប្រាស់មានសិទ្ធិចូលប្រើប្រាស់។ ចំណាំ៖ ការនាំចេញ CSV មិនបង្ហាញតួអក្សរដែលមិនមែនជាឡាតាំងទេ (ឧ. អារ៉ាប់, Bangla)' label: នាំចេញ CSV @@ -2513,7 +2480,7 @@ km: label: នាំចេញជាឯកសារJSON export_xls: explanation: 'អ្នកប្រើប្រាស់អាចបង្កើតការនាំចេញឯកសារ XLS ពីបញ្ជីបញ្ជីឈ្មោះ ឬទំព័របង្ហាញបញ្ជីឈ្មោះ ដែលមានវាលទាំងអស់ដែលអ្នកប្រើប្រាស់បច្ចុប្បន្នមានសិទ្ធិចូលប្រើ។ ចំណាំ៖ ទ្រង់ទ្រាយ XLS បង្ហាញតួអក្សរដែលមិនមែនជាឡាតាំង (ឧ. អារ៉ាប់, Bangla) ក្នុងទម្រង់ដែលអាចអានបាន ខណៈពេលដែលការនាំចេញ CSV មិនមាន។' - label: "នាំចេញឯកសារ​​​ Excel (XLS file) " + label: 'នាំចេញឯកសារ​​​ Excel (XLS file) ' flag: explanation: អាចបន្ថែមសម្គាល់ (flag) ទៅកំណត់ត្រាចុះបញ្ជី។ អ្នក​ប្រើ​ដែល​មាន​ការ​អនុញ្ញាត​នេះ​ក៏​អាច​ដក​ទង់ជាតិ​ដែល​ពួក​គេ​បាន​បន្ថែម​ទៅ​ក្នុង​បញ្ជី​ឈ្មោះ​ផង​ដែរ​។ label: សម្គាល់ @@ -2552,7 +2519,7 @@ km: label: របាយការណ៍ reporting_location_level: explanation: 'វានឹងគ្រប់គ្រងកម្រិតនៃទីតាំងដែលបង្ហាញសម្រាប់តួនាទីនេះនៅក្នុងផ្ទាំងគ្រប់គ្រង តម្រង គំរូបញ្ជូនបន្ត និងម៉ូឌុលផ្ទេរ។ ប្រសិនបើអ្នកទុកវាលនេះឱ្យនៅទទេ តួនាទីនេះនឹងឃើញកម្រិតទីតាំងរាយការណ៍លំនាំដើមរបស់ប្រព័ន្ធ។' - label: "តើ​​ប្រភេទ​ទីតាំង​អ្វី​ដែល​គួរ​ត្រូវ​បានប្រើប្រាស់​សម្រាប់​រាយការណ៍​អំពី​តួនាទី​នេះ?" + label: តើ​​ប្រភេទ​ទីតាំង​អ្វី​ដែល​គួរ​ត្រូវ​បានប្រើប្រាស់​សម្រាប់​រាយការណ៍​អំពី​តួនាទី​នេះ? role: actions: assign: @@ -2613,18 +2580,18 @@ km: label: នាំចេញជាឯកសារJSON export_list_view_csv: explanation: អ្នកប្រើប្រាស់អាចបង្កើតការនាំចេញឯកសារ CSV ពីទំព័របញ្ជីសំណើស្វែងរកដែលមានសំណួរដូចគ្នាដែលលេចឡើងសម្រាប់អ្នកប្រើប្រាស់នោះនៅលើបញ្ជីសំណើរស្វែងរក។ អនុវត្តតែពីទំព័របញ្ជីសំណើស្វែងរកប៉ុណ្ណោះ។ - label: ទិដ្ឋភាព​បញ្ជីនាំចេញឯកសារCSV + label: នាំចេញ​បញ្ជីករណីជាឯកសារ cvs export_pdf: explanation: អ្នកប្រើប្រាស់អាចបង្កើតការនាំចេញឯកសារ PDF ពីបញ្ជីឧប្បត្តិហេតុ ឬទំព័របង្ហាញឧប្បត្តិហេតុ ដែលមានសំណួរទាំងអស់ដែលអ្នកប្រើប្រាស់បច្ចុប្បន្នមានសិទ្ធិចូលប្រើ សម្រាប់កំណត់ត្រាមួយ ច្រើន ឬទាំងអស់ដែលអ្នកប្រើប្រាស់មានសិទ្ធិចូលប្រើ។ នៅក្នុងឯកសារនាំចេញ PDF ព័ត៌មានត្រូវបានរាយបញ្ជីដំបូងតាមករណី ហើយបន្ទាប់មករៀបចំបន្ថែមទៀតដោយទម្រង់ដែលព័ត៌មានលេចឡើង។ label: នាំចេញជាឯកសារ PDF export_xls: explanation: 'អ្នកប្រើប្រាស់អាចបង្កើតការនាំចេញឯកសារ XLS ពីបញ្ជីស្វែងរកករណី ឬទំព័របង្ហាញករណីស្វែងរក ដែលមានសំណួរទាំងអស់ សម្រាប់ករណីមួយ ច្រើន ឬគ្រប់ករណីទាំងអស់ដែលអ្នកប្រើប្រាស់មានសិទ្ធិចូលប្រើប្រាស់។ នៅក្នុងការនាំចេញនេះ ទម្រង់នីមួយៗត្រូវបានតំណាងនៅក្នុងផ្ទាំងរបស់វានៅក្នុងឯកសារ XLS។ ចំណាំ៖ ទ្រង់ទ្រាយ XLS បង្ហាញតួអក្សរដែលមិនមែនជាឡាតាំង (ឧ. អារ៉ាប់, Bangla) ក្នុងទម្រង់ដែលអាចអានបាន ខណៈពេលដែលការនាំចេញ CSV មិនដំណើរការ។' - label: "នាំចេញឯកសារ​​​ Excel (XLS file) " + label: 'នាំចេញឯកសារ​​​ Excel (XLS file) ' flag: explanation: អាចបន្ថែមសម្គាល់ទៅការសំណើស្វែងរក។ អ្នក​ប្រើ​ដែល​មាន​ការ​អនុញ្ញាត​នេះ​ក៏​អាច​លុបសម្គាល់​​ដែល​ពួក​គេ​បាន​បន្ថែម​ទៅ​ក្នុង​សំណើស្វែងរក​​ផង​ដែរ។ label: សម្គាល់ import: - explanation: "អនុញ្ញាតឱ្យអ្នកប្រើបង្កើតករណីថ្មីមួយ ឬច្រើនដោយនាំចូលពួកវាពីឯកសារ CSV, Excel ឬ JSON ។ ឯកសារដែលបាននាំចូលត្រូវតែformat *ខ្លាំងណាស់* ជាពិសេសសម្រាប់ព័ត៌មានដែលត្រូវនាំចូលត្រឹមត្រូវ។ មុខងារនេះគួរតែមានសម្រាប់តែអ្នកប្រើប្រាស់រដ្ឋបាលដែលមានជំនាញបច្ចេកទេសកម្រិតខ្ពស់ និងចំណេះដឹងស៊ីជម្រៅអំពីរបៀបធ្វើformat ទិន្នន័យនៅក្នុង Primero ប៉ុណ្ណោះ។ អនុវត្តតែពីទំព័របញ្ជីករណីប៉ុណ្ណោះ។" + explanation: អនុញ្ញាតឱ្យអ្នកប្រើបង្កើតករណីថ្មីមួយ ឬច្រើនដោយនាំចូលពួកវាពីឯកសារ CSV, Excel ឬ JSON ។ ឯកសារដែលបាននាំចូលត្រូវតែformat *ខ្លាំងណាស់* ជាពិសេសសម្រាប់ព័ត៌មានដែលត្រូវនាំចូលត្រឹមត្រូវ។ មុខងារនេះគួរតែមានសម្រាប់តែអ្នកប្រើប្រាស់រដ្ឋបាលដែលមានជំនាញបច្ចេកទេសកម្រិតខ្ពស់ និងចំណេះដឹងស៊ីជម្រៅអំពីរបៀបធ្វើformat ទិន្នន័យនៅក្នុង Primero ប៉ុណ្ណោះ។ អនុវត្តតែពីទំព័របញ្ជីករណីប៉ុណ្ណោះ។ label: នាំចូល manage: explanation: អនុញ្ញាតឱ្យអ្នកប្រើប្រាស់មួយអាចអនុវត្តសកម្មភាពដែលមានទាំងអស់សម្រាប់សំណើស្វែងរក។ ការផ្តល់សិទ្ធ "គ្រប់គ្រង" មានន័យថា "អ្វីគ្រប់យ៉ាង" ។ @@ -2641,8 +2608,8 @@ km: actions: transfer: explanation: នេះមានន័យថាតួនាទីនឹងបង្ហាញជាជម្រើសមួយសម្រាប់ "ប្រភេទអ្នកទទួល" នៅពេលអ្នកប្រើប្រាស់ធ្វើការបញ្ជូនបន្តពីខាងក្រៅ។ ប្រសិនបើអ្នកប្រើជ្រើសរើសតួនាទីនេះជាប្រភេទនៃការផ្ទេរ ការនាំចេញដែល Primero បង្កើតនៅពេលអ្នកប្រើប្រាស់ដាក់បញ្ជូនការផ្ទេរនឹងមានតែព័ត៌មានដែលត្រូវបានរកឃើញនៅក្នុងទម្រង់ដែលតួនាទីនេះមានសិទ្ធិចូលប្រើ។ ឧទាហរណ៍ ប្រសិនបើអ្នកប្រើប្រាស់ជ្រើសរើស "អ្នកផ្តល់សេវាវេជ្ជសាស្រ្ត" ជាប្រភេទអ្នកទទួល ហើយតួនាទីអ្នកផ្តល់សេវាវេជ្ជសាស្រ្តមានសិទ្ធិចូលប្រើទម្រង់ព័ត៌មានបឋម និងទម្រង់បញ្ហាជាកង្វល់ប៉ុណ្ណោះ ឯកសារដែល Primero នាំចេញសម្រាប់ការផ្ទេរខាងក្រៅនឹងមានតែព័ត៌នៅក្នុងទម្រង់ទាំងពីរនោះតែប៉ុណ្ណោះ។ - label: "តើ​អ្នក​ប្រើប្រាស់​នេះ​អាច​បញ្ជូនករណី​ទៅក្រៅប្រព័ន្ធបាន​ដែរ​ឬទេ?" - label: "ផ្ទេរ " + label: តើ​អ្នក​ប្រើប្រាស់​នេះ​អាច​បញ្ជូនករណី​ទៅក្រៅប្រព័ន្ធបាន​ដែរ​ឬទេ? + label: 'ផ្ទេរ ' user: actions: agency_read: @@ -2700,15 +2667,13 @@ km: label: លុប manage: label: គ្រប់គ្រង (ការអនុញ្ញាតទាំងអស់សម្រាប់ប្រភេទធនធាននេះ) - explanation: activity_log: actions: transfer: explanation: អ្នកប្រើប្រាស់អាចចូលទៅក្នុងផ្នែកកំណត់ត្រាសកម្មភាពនៅក្នុងទំព័រគ្រប់គ្រង និងមើលកំណត់ត្រាទាំងអស់ដែលបានទទួល ឬបដិសេធសម្រាប់ករណីដែលពួកគេមានសិទ្ធិធ្វើប្រិតបត្តិការណ៍ - label: "ផ្ទេរ " + label: 'ផ្ទេរ ' manage: label: គ្រប់គ្រង (ការអនុញ្ញាតទាំងអស់សម្រាប់ប្រភេទធនធាននេះ) - explanation: label: កំណត់ហេតុសកម្មភាព potential_match: case_id: លេខកូដករណី @@ -2722,15 +2687,14 @@ km: score: ពិន្ទុ social_worker: បុគ្គលិកសង្គម social_worker_agency: ស្ថាប័ន៖ - tracing_request_id: "លេខកូដសំណើ​ស្វែងរក " + tracing_request_id: 'លេខកូដសំណើ​ស្វែងរក ' trace: ស្វែងរក likelihood_likely: ទំនងជា likelihood_possible: អាច​ធ្វើ​បាន potential_matches: - display: "បង្ហាញ​កា​រផ្គូផ្គង​ខ្លាំង​សម្រាប់ %{type} %{id}" + display: បង្ហាញ​កា​រផ្គូផ្គង​ខ្លាំង​សម្រាប់ %{type} %{id} reassign: - multiple_error: "មានបញ្ហា ហើយករណី%{select_records}មិនត្រូវបានចាត់តាំង។" - multiple_successfully: '%{select_records}ករណីត្រូវបានចាត់តាំងដោយជោគជ័យ' + multiple_error: មានបញ្ហា ហើយករណី%{select_records}មិនត្រូវបានចាត់តាំង។ notes_label: កំណត់សម្គាល់ successfully: ចាត់តាំងដោយជោគជ័យ user_mandatory_label: ត្រូវបញ្ចូល​អ្នកទទួល @@ -2757,14 +2721,14 @@ km: type_of_recipient: ប្រភេទ​អ្នកទទួល type_of_referral_required: ត្រូវការប្រភេទការបញ្ជូន agency_label: ស្ថាប័ន៖ - is_remote_label: "បញ្ជូនទៅរកសេវាពីអង្គភាពដែលមិនប្រើប្រាស់ Primero និង​OSCaR?​" + is_remote_label: បញ្ជូនទៅរកសេវាពីអង្គភាពដែលមិនប្រើប្រាស់ Primero និង​OSCaR?​ location_label: ទីតាំង notes_label: កំណត់សម្គាល់ notes_on_referral: កំណត់សម្គាល់នៃការ​បញ្ជូន note_on_referral_from_provider: កំណត់សម្គាល់លើការបញ្ជូនពីអ្នកផ្តល់សេវា provided_consent_label: មិនមានការយល់ព្រមនៅក្នុងទម្រង់នេះទេ។ recipient_label: អ្នកទទួល - refer_anyway_label: "បញ្ជូន?" + refer_anyway_label: បញ្ជូន? service_label: សេវាកម្ម success: 'បាន​បញ្ជូន​ %{record_type} %{id} ដោយ​ជោគជ័យ' user_mandatory_label: ត្រូវបញ្ចូល​អ្នកទទួល @@ -2778,13 +2742,13 @@ km: date: ថ្ងៃ month: ខែ quarter: ត្រីមាស - quarter_abbr: "Q%{quarter}" + quarter_abbr: Q%{quarter} week: សប្ដាហ៍ year: ឆ្នាំ description: ការពណ៌នា disabled: explanation: ប្រសិនបើអ្នកបិទរបាយការណ៍នេះ វានឹងមិនបង្ហាញនៅក្នុងរបាយការណ៍ដែលមានទេ។ - label: បិទករណី (disable case) + label: បិទដំណើរការ (disable) exclude_empty_rows: កុំ​បង្ហាញ​ជួរដេក​ទទេ disaggregate_by: ដាក់ជា​ក្រុម​តាម​ជួរឈរ filters: @@ -2798,12 +2762,12 @@ km: equal_to: ស្មើនឹង not_blank: មិនទទេ is: គឺ - before: "មុន " - after: "បន្ទាប់​ពី " - delete_filter_message: "តើ​អ្នក​ប្រាកដ​ជា​ចង់​លុប​សំណួរនេះ​ឬ?" + before: 'មុន ' + after: 'បន្ទាប់​ពី ' + delete_filter_message: តើ​អ្នក​ប្រាកដ​ជា​ចង់​លុប​សំណួរនេះ​ឬ? group_ages: ប្រើប្រាស់​ចន្លោះ​អាយុ group_dates_by: ប្រើប្រាស់​ចន្លោះ​កាលបរិច្ឆេទ - is_graph: "បង្កើត​ក្រាហ្វមែនទេ?" + is_graph: បង្កើត​ក្រាហ្វមែនទេ? messages: delete_success: បានលុប​របាយការណ៍​ដោយជោគជ័យ។ success: បង្កើតរបាយការណ៍​ដោយជោគជ័យ។ @@ -2819,7 +2783,7 @@ km: value: តម្លៃ reports: delete_report: លុបរបាយការណ៍ - delete_report_message: "តើ​អ្នក​ប្រាកដ​ជា​ចង់​លុប​របាយការណ៍​នេះ​មែនទេ? ការ​លុប​មិន​អាច​ត្រឡប់​វិញ​បាន​ទេ។ ចុច​យល់ព្រម ដើម្បី​លុប​របាយការណ៍។" + delete_report_message: តើ​អ្នក​ប្រាកដ​ជា​ចង់​លុប​របាយការណ៍​នេះ​មែនទេ? ការ​លុប​មិន​អាច​ត្រឡប់​វិញ​បាន​ទេ។ ចុច​យល់ព្រម ដើម្បី​លុប​របាយការណ៍។ label: របាយការណ៍ register_new_report: បង្កើត​របាយការណ៍ translations: @@ -2840,20 +2804,20 @@ km: description: ការពណ៌នា edit: កែសម្រួល​តួនាទី error_in_updating: មាន​បញ្ហា​ក្នុងការ​ធ្វើ​បច្ចុប្បន្នភាព​ព័ត៌មាន​លម្អិត​​អំពី​តួនាទី។ - group_permission_label: "តើ​តួនាទី​នេះ​ប៉ះពាល់​ដល់​កំណត់ត្រា​អ្វីដែរ?​" + group_permission_label: តើ​តួនាទី​នេះ​ប៉ះពាល់​ដល់​កំណត់ត្រា​អ្វីដែរ?​ label: តួនាទី manager: អ្នក​គ្រប់គ្រង messages: - confirmation: "តើ​អ្នក​ប្រាកដ​ជា​ចង់លុបតួនាទីនេះ​ឬ? ពេលលុបហើយ​មិនអាចត្រឡប់​វិញ​បាន​ទេ។ ចុច​យល់ព្រម ដើម្បី​លុប​តួនាទី។" + confirmation: តើ​អ្នក​ប្រាកដ​ជា​ចង់លុបតួនាទីនេះ​ឬ? ពេលលុបហើយ​មិនអាចត្រឡប់​វិញ​បាន​ទេ។ ចុច​យល់ព្រម ដើម្បី​លុប​តួនាទី។ created: តួនាទីត្រូវបានបង្កើតដោយជោគជ័យ។ deleted: លុបតួនាទីដោយជោគជ័យ updated: ធ្វើបច្ចុប្បន្នភាព​តួនាទី​ដោយជោគជ័យ។ name: ឈ្មោះ - referral_label: "តើ​អ្នក​ប្រើប្រាស់​នេះ​អាច​បញ្ជូនករណី​បាន​ដែរ​ឬទេ?" - reporting_location_level_label: "តើ​​ប្រភេទ​ទីតាំង​អ្វី​ដែល​គួរ​ត្រូវ​បានប្រើប្រាស់​សម្រាប់​រាយការណ៍​អំពី​តួនាទី​នេះ?" + referral_label: តើ​អ្នក​ប្រើប្រាស់​នេះ​អាច​បញ្ជូនករណី​បាន​ដែរ​ឬទេ? + reporting_location_level_label: តើ​​ប្រភេទ​ទីតាំង​អ្វី​ដែល​គួរ​ត្រូវ​បានប្រើប្រាស់​សម្រាប់​រាយការណ៍​អំពី​តួនាទី​នេះ? role_ids_label: តួនាទី​ផ្សេង​បានគ្រប់គ្រង​ដោយ​តួនាទី​នេះ successfully_updated: បាន​ធ្វើបច្ចុប្បន្នភាព​ព័ត៌មានលម្អិត​អំពី​តួនាទី​ដោយ​ជោគជ័យ។ - transfer_label: "តើ​អាច​ប្រើប្រាស់​តួនាទី​នេះ​សម្រាប់ការ​ផ្ទេរ​បាន​ដែ​ររទេ?" + transfer_label: តើ​អាច​ប្រើប្រាស់​តួនាទី​នេះ​សម្រាប់ការ​ផ្ទេរ​បាន​ដែ​ររទេ? hide: លាក់ read: បង្ហាញ read_write: បង្ហាញ និងកែសម្រួល @@ -2865,7 +2829,7 @@ km: no_filters: មិនមានសំណួរដែលបានជ្រើសរើសទេ save_success: បាន​រក្សាទុក​ការ​ស្វែងរក​ដោយ​ជោគជ័យ។ saved_searches_tab: ការ​ស្វែងរក​ដែល​បាន​រក្សាទុក - title_description: "តើ​អ្នក​ពិតជា​ចង់​លុប​ការ​ស្វែងរកដែលបានរក្សាទុក​មែន​ឬ?" + title_description: តើ​អ្នក​ពិតជា​ចង់​លុប​ការ​ស្វែងរកដែលបានរក្សាទុក​មែន​ឬ? title_modal: លុបការស្វែងរកដែលបានរក្សាទុក saved_searches: no_save_searches: អ្នក​​មិនមានការ​ស្វែងរក​ដែល​បាន​រក្សាទុក​ទេ។ @@ -2904,8 +2868,8 @@ km: types: assessment: ការ​ប៉ាន់ប្រមាណ case_plan: ផែនការករណី - follow_up: "ការតាមដាន - %{subtype}" - service: "សេវាកម្ម - %{subtype}" + follow_up: ការតាមដាន - %{subtype} + service: សេវាកម្ម - %{subtype} tracing_request: label: សំណើ​ស្វែងរក has_match: ការ​ផ្គូផ្គង​រកឃើញ @@ -2925,8 +2889,8 @@ km: creation_success: សំណើ​ស្វែងរកបានបង្កើតដោយ​ជោគជ័យ។ update_success_queue: 'បាន​ធ្វើបច្ចុប្បន្នភាព​សំណើ​ស្វែងរក %{record_id} ដោយ​ជោគជ័យ។' creation_success_queue: បង្កើត​សំណើ​ស្វែងរកដោយ​ជោគជ័យ។ - match_action: "ផ្គូផ្គងការស្វែងរក%{trace_id}ជាមួយនឹងករណី%{record_id}ដោយជោគជ័យ។" - unmatch_action: "ដោះការផ្គូផ្គងការស្វែងរក%{trace_id}ជាមួយនឹងករណី%{record_id}ដោយជោគជ័យ។" + match_action: ផ្គូផ្គងការស្វែងរក%{trace_id}ជាមួយនឹងករណី%{record_id}ដោយជោគជ័យ។ + unmatch_action: ដោះការផ្គូផ្គងការស្វែងរក%{trace_id}ជាមួយនឹងករណី%{record_id}ដោយជោគជ័យ។ registry_record: messages: update_success: 'បញ្ជីកំណត់ត្រា​ %{record_id} បាន​ធ្វើ​បច្ចុប្បន្ន​ភាពដោយជោគជ័យ។' @@ -2983,22 +2947,22 @@ km: export: នាំចេញ mark_for_offline: title: ប្រើសម្រាប់ពេលគ្មានសេវាអីនធឺណេត - text: "តើអ្នកពិតជាចង់កំណត់បញ្ជីកំណត់ត្រានេះសម្រាប់ប្រើពេលដែលគ្មានសេវាអីនធឺណេតមែនទេ?" + text: តើអ្នកពិតជាចង់កំណត់បញ្ជីកំណត់ត្រានេះសម្រាប់ប្រើពេលដែលគ្មានសេវាអីនធឺណេតមែនទេ? success: បញ្ជីកំណត់ត្រាត្រូវបានកំណត់សម្រាប់ប្រើពេលគ្មានសេវាអីនធឺណេត ដោយជោគជ័យ transfer: - label: "ផ្ទេរ " + label: 'ផ្ទេរ ' agency_label: ស្ថាប័ន៖ - consent_from_individual_label: "តើ​អ្នកមាន​ការ​យល់ព្រមដើម្បី​ធ្វើ​ការ​ផ្ទេរ​នេះ​ដែ​រឬទេ?" + consent_from_individual_label: តើ​អ្នកមាន​ការ​យល់ព្រមដើម្បី​ធ្វើ​ការ​ផ្ទេរ​នេះ​ដែ​រឬទេ? consent_label: កំណត់ត្រា​មិន​បានផ្ដល់​ការ​យល់ព្រម​ទេ។ - consent_override_label: "តើ​អ្នក​ចង់​សរសេរ​ជាន់លើ​ការ​កំណត់​នេះ​ដែ​រឬទេ?" - is_remote_label: "បញ្ជូនទៅរកសេវាពីអង្គភាពដែលមិនប្រើប្រាស់ Primero និង​OSCaR?​" + consent_override_label: តើ​អ្នក​ចង់​សរសេរ​ជាន់លើ​ការ​កំណត់​នេះ​ដែ​រឬទេ? + is_remote_label: បញ្ជូនទៅរកសេវាពីអង្គភាពដែលមិនប្រើប្រាស់ Primero និង​OSCaR?​ location_label: ទីតាំង notes_label: កំណត់សម្គាល់ provided_consent_label: ការយល់ព្រមមិនត្រូវបានផ្តល់ជូនក្នុងទម្រង់ទេ។ recipient_label: អ្នកទទួល select_label: ជ្រើសរើស... success: ផ្ទេរដោយជោគជ័យ - transfer_label: "នៅបន្តផ្ទេរ?" + transfer_label: នៅបន្តផ្ទេរ? user_mandatory: ត្រូវបញ្ចូល​អ្នកទទួល rejected_reason: មូលហេតុ​បដិសេធ transfer_assignment: @@ -3015,8 +2979,8 @@ km: errors: consent: មិនទាន់មានការយល់ព្រមទេ to_user_can_receive: អ្នកប្រើប្រាស់នេះមិនអាចទទួលបានកំណត់ត្រានេះទេ - individual_consent: "តើ​អ្នកមាន​ការ​យល់ព្រម​​ដើម្បី​ធ្វើ​ការ​ផ្ទេរ​នេះ​ដែ​រឬទេ?" - no_consent_share: "ការ​យល់ព្រម មិនត្រូវបានពិចារណា " + individual_consent: តើ​អ្នកមាន​ការ​យល់ព្រម​​ដើម្បី​ធ្វើ​ការ​ផ្ទេរ​នេះ​ដែ​រឬទេ? + no_consent_share: 'ការ​យល់ព្រម មិនត្រូវបានពិចារណា ' notes: កំណត់សម្គាល់ recipient: អ្នកទទួល rejected: បដិសេធហេតុផល @@ -3035,12 +2999,12 @@ km: reassign: ចាត់តាំង referral: ការបញ្ចូន external_referral: ការ​បញ្ជូន​ក្រៅប្រព័ន្ធ - transfer: "ផ្ទេរ " + transfer: 'ផ្ទេរ ' transferRequest: សំណើ​ផ្ទេរ user: agency_office: Agency Office (GBV field) code: លេខ​កូដ​អ្នក​ប្រើប្រាស់ - disabled: បាន​បិទ + disabled: បិទដំណើរការ (disable) email: អ៊ីមែល full_name: ឈ្មោះ​ពេញ identity_provider: អ្នកផ្តល់អត្តសញ្ញាណ @@ -3050,11 +3014,11 @@ km: locale: មូលដ្ឋាន location: ទីតាំង messages: - confirmation: "តើ​អ្នក​ប្រាកដ​ជា​ចង់លុប​​អ្នក​ប្រើប្រាស់​ម្នាក់​នេះ​ឬ? ការ​លុប​មិន​ត្រឡប់​វិញ​បាន​ទេ។ ចុច​យល់ព្រម ដើម្បី​លុប​អ្នក​ប្រើប្រាស់។" + confirmation: តើ​អ្នក​ប្រាកដ​ជា​ចង់លុប​​អ្នក​ប្រើប្រាស់​ម្នាក់​នេះ​ឬ? ការ​លុប​មិន​ត្រឡប់​វិញ​បាន​ទេ។ ចុច​យល់ព្រម ដើម្បី​លុប​អ្នក​ប្រើប្រាស់។ created: បាន​បង្កើតអ្នក​ប្រើប្រាស់​​ដោយ​ជោគជ័យ។ failure: មានបញ្ហា សូមទាក់ទងផ្នែកជំនួយ។ - new_confirm_html: "អ្នកហៀបនឹងអញ្ជើញអ្នកប្រើប្រាស់%{username}ពី%{identity}ដែលមានតួនាទី%{role}ឱ្យប្រើ Primero ។ អ៊ីមែលបញ្ជាក់នឹងត្រូវបានផ្ញើទៅ%{email}។ តើអ្នកចង់បន្តទេ?" - new_confirm_non_identity_html: "អ្នកហៀបនឹងអញ្ជើញអ្នកប្រើប្រាស់%{username}ដែលមានតួនាទី%{role}ឱ្យប្រើ Primero ។ អ៊ីមែលបញ្ជាក់នឹងត្រូវបានផ្ញើទៅ%{email}។ តើអ្នកចង់បន្តទេ?" + new_confirm_html: អ្នកហៀបនឹងអញ្ជើញអ្នកប្រើប្រាស់%{username}ពី%{identity}ដែលមានតួនាទី%{role}ឱ្យប្រើ Primero ។ អ៊ីមែលបញ្ជាក់នឹងត្រូវបានផ្ញើទៅ%{email}។ តើអ្នកចង់បន្តទេ? + new_confirm_non_identity_html: អ្នកហៀបនឹងអញ្ជើញអ្នកប្រើប្រាស់%{username}ដែលមានតួនាទី%{role}ឱ្យប្រើ Primero ។ អ៊ីមែលបញ្ជាក់នឹងត្រូវបានផ្ញើទៅ%{email}។ តើអ្នកចង់បន្តទេ? not_found: រក​មិន​ឃើញ​អ្នក​ប្រើប្រាស់​ដែល​មាន​លេខសម្គាល់​ដែល​បាន​ផ្ដល់​ឲ្យ​ទេ password_changed_successfully: បាន​ផ្លាស់ប្ដូរ​ពាក្យ​សម្ងាត់​ដោយ​ជោគជ័យ passwords_do_not_match: មិន​ដូច​នឹង​ពាក្យសម្ងាត់​បច្ចុប្ប​ន្ន​ទេ @@ -3064,7 +3028,7 @@ km: agency: ស្ថាប័ន services_help_text: ប្រសិនបើអ្នកមិនបញ្ជាក់សេវាជាក់លាក់ទេ អ្នកប្រើប្រាស់នេះនឹងត្រូវបានផ្តល់សេវាមដូចគ្នាដែលស្ថាប័នរបស់វាមាន។ password_setting: - label: "តើ Primero គួរកំណត់ពាក្យសម្ងាត់របស់អ្នកប្រើយ៉ាងដូចម្តេច?" + label: តើ Primero គួរកំណត់ពាក្យសម្ងាត់របស់អ្នកប្រើយ៉ាងដូចម្តេច? self: ញុំនឹងកំណត់ពាក្យសម្ងាត់ user: អ្នកប្រើប្រាស់នឹងកំណត់ពាក្យសម្ងាត់ដោយប្រើអ៊ីមែលស្វាគមន៍ help_text: សូមចងចាំថា ប្រសិនបើអ្នក ជាអ្នកគ្រប់គ្រងកំណត់ពាក្យសម្ងាត់ដោយដៃ អ្នកនឹងត្រូវចែករំលែកវាជាមួយអ្នកប្រើប្រាស់ក្នុងលក្ខណៈសុវត្ថិភាព។ @@ -3077,7 +3041,7 @@ km: position: មុខតំណែង provider_username_help: 'ឧទាហរណ៍៖ my.username@%{domain}' role_id: តួនាទី - send_mail: "តើ​ទទួល​បាន​ការ​ជូន​ដំណឹង​តាម​អ៊ីមែល​ដែ​រឬទេ?" + send_mail: តើ​ទទួល​បាន​ការ​ជូន​ដំណឹង​តាម​អ៊ីមែល​ដែ​រឬទេ? user_group_unique_ids: ក្រុម​អ្នកប្រើប្រាស់ user_name: អ្នកប្រើប្រាស់ services: សេវា @@ -3098,7 +3062,7 @@ km: step3: 'ចូលក្នុងប្រព័ន្ធដោយប្រើឈ្មោះអ្នកប្រើប្រាស់ និងលេខកូដបណ្តោះអាសន្ន%{otp}' step4: 'នៅពេលទម្រង់លេចឡើង កែប្រែលេខសម្ងាត់របស់អ្នក។' url_label: Primero - enabled_label: "តើ​ផ្ញើ​អ៊ីមែល​ស្វាគមន៍​ឬ?" + enabled_label: តើ​ផ្ញើ​អ៊ីមែល​ស្វាគមន៍​ឬ? text_label: អត្ថបទ​អ៊ីមែល​ស្វាគមន៍ password_reset: subject: 'ការណែនាំពីរបៀបផ្លាស់ប្តូរលេខកូខសម្ងាត់' @@ -3123,7 +3087,7 @@ km: description: ការពណ៌នា disabled: explanation: ប្រសិនបើអ្នកបិទក្រុមអ្នកប្រើប្រាស់នេះ អ្នកនឹងមិនអាចកំណត់វាទៅគណនីអ្នកប្រើប្រាស់បានទេ។ - label: បិទករណី (disable case) + label: បិទដំណើរការ (disable) messages: created: បង្កើតក្រុម​អ្នក​ប្រើប្រាស់​ដោយ​ជោគជ័យ។ updated: បាន​ធ្វើបច្ចុប្បន្នភាពក្រុម​អ្នក​ប្រើប្រាស់​ដោយ​ជោគជ័យ។ @@ -3146,5 +3110,5 @@ km: admin: locations: selected_records: '%{select_records}​ ទីតាំងបានជ្រើសរើស' - selected_all_records: "ជ្រើសរើសករណីទាំងអស់%{total_records}ដែលត្រូវនឹងសំណួរនេះ។" + selected_all_records: ជ្រើសរើសករណីទាំងអស់%{total_records}ដែលត្រូវនឹងសំណួរនេះ។ updated: '%{updated_records} ទីតាំងបានកែសម្រួល' diff --git a/config/locales/ku-IQ.yml b/config/locales/ku-IQ.yml index c3d766cf11..845af18d0a 100644 --- a/config/locales/ku-IQ.yml +++ b/config/locales/ku-IQ.yml @@ -1942,35 +1942,10 @@ ku-IQ: date_of_first_report: رێکه فتا چافپێکەفتنێ incident_date: رێکه فتا رویدانێ reports: - incidents: رويدان perpetrators: تاوانبار survivors:  رزگاربووی referrals: رەوانەکرن sub_reports: - combined: رويدان - total: هژمارا وان روویدانێن توندوتیژی یێن جێندەری کو هاتینە ڕاپۆرت کرن - gbv_sexual_violence: هژمارا وان روویدانێن توندوتیژی یێن جنسی کو هاتینە راپورت کرن - gbv_previous_incidents: هژمارا وان روویدانێن کو هاتینە راگەهاندن ژ لایێ وان کەسان ئەوێن رزگار بوویی ل روویدانێن توندوتیژی یێن جێندەری - gbv_sexual_violence_type: جۆرێ رویدانێ - incident_timeofday: دەما رویدانێ د رۆژێدا - elapsed_reporting_time: دەما دناڤبەرا رویدانێ ورێکه فتا راپورت کرنێ - elapsed_reporting_time_rape: روویدانێن دەستدرێژیکرنێ، دەما د ناڤبەرا روویدانێ و راپۆرت کرنێ - elapsed_reporting_time_rape_health_referral: ' روویدانێن دەستدرێژیکرنا سێكسێ ل دەمێ دناڤبەرا روویدانێ و راپورتكرنێ (خزمەتگوزاریێت تەندروستێ یان رەوانەكرنێ) ' - incident_location_type: جهێ رویدانێ - number_of_perpetrators: ژمارا تاوانباران - perpetrator_relationship: پەیوەندی دناڤبەرا رزگار بوویی و تاوانبارێ سەرەکی دا - perpetrator_age_group: 'گروپێ تەمەنێ تاوانبارێن سەرەکی ' - perpetrator_occupation: کار و پیشەیا تاوانبارێن سەرەکی - age: هژمارا رزگاربویان ل دویڤ ژیێ وان - sex: هژمارا رزگاربویان ل دویڤ رەگەزێ وان - marital_status: بارێ خێزانی یێ رزگاربویان - displacement_status: بارودوخێ ئاوارەبوونێ یێ رزگاربویان - displacement_incident: قوناغا ئاوارەبوونێ ل دەمێ بوویەرێ - gbv_case_context: ناڤەروكا كەیسی - incidents_first_point_of_contact: 'هژمارا رویدانا یت كو رێكخراواتە ئێكەمین خالا پەیوەندێكرنێیە ' - incidents_from_other_service_provider: ' روویدانێت هاتینە ریپورتكرن ژلایێ پێشكێشكەرێن خزمەتگوزاریان ڤە' - number_of_services_provided: هژمارا خزمەتگوزاریا هاتینە پێشكێشكرن بو روویدانا - number_of_services_provided_other: 'رویدانا نوی هاتیە ریپورتكرن بو پێشكێشكەرێن خزمەتگوزاریا ' service_safehouse_referral: خانیێ ئارام یان پەناگەها ئارام بو هاتیە رەوانەكرن service_medical_referral: رەوانەكرنێت ساخلەمی یان پزیشکی service_psycho_referral: خزمەتگوزارییت دەرونی/ راوێشكاری @@ -1978,7 +1953,6 @@ ku-IQ: service_police_referral: 'خزمەتگوزاریێت پولیسی یان هەر جورەكێ خزمەتگوزاریێت دی یت ئێمناهیێ ' service_livelihoods_referral: خزمەتگوزاریێن ژیارێ service_protection_referral: 'خزمەتگوزاریێت پاراستنا زاورکا ' - vulnerable_populations: هژمارا دانیشتوانێت لاواز survivors_disability_type: كێم ئەندام success_message: فایلێ دەرخستنێ ب سەرکەفتیانە هاتە دروستکرن messages: @@ -2496,7 +2470,6 @@ ku-IQ: explanation: رێکێ دەتە رێڤەبەری بۆ دیتنا کا چەند کەیسا کارێ خزمەتگوزاریا گیرو هەیە بۆ هەر ئێک ژ وان کارکەرێن کەیسی label: 'کارێن خزمەتگوزاریا گیرو هەی ' dash_case_incident_overview: - explanation: . label: کورتی - کەیسێن من یان رویدان dash_cases_by_social_worker: explanation: خشتێ وێ چەندێ نیشانددەت کا چەوا سەرجەمێ ژمارا کەیسێن ڤەکری و ژمارا کەیسێن نی دهێنە برێڤەبرن ژ لایێ هەر ئێک بکارهێنەری د گروپێ نوکەیێ بکارهێنەرادا. هەر رێزەک بکارهێنەرەکە د گروپێ نوکەیێ بکارهێنەرادا، ل دەما کو سەرجەم و نی دوو لانە @@ -2970,7 +2943,6 @@ ku-IQ: display: پێشاندانا وەکهەڤیێن دیار بو %{type}%{id} reassign: multiple_error: خەلەتیەک چێبوو. %{select_records} کەسی نەهاتنە دەستنیشانکرن - multiple_successfully: 'کەیس سەرکەفتیانە هاتنە دەستنیشانکرن %{select_records}' notes_label: تێبینی successfully: ب سەرکەفتیانە دوبارە هاتە دەستنیشانکرن user_mandatory_label: ' وه رگر یێ پێدڤیە' diff --git a/config/locales/ku.yml b/config/locales/ku.yml index 43f6dba971..a9d54cd25f 100644 --- a/config/locales/ku.yml +++ b/config/locales/ku.yml @@ -2042,41 +2042,10 @@ ku: date_of_first_report: بەرواری چاوپێکەوتنەکە incident_date: بەرواری روداوەکە reports: - incidents: 'رووداوەكان - -  ' perpetrators: ' تاوانباران' survivors: ڕزگاربووان referrals: ئیحالەکان- ڕەوانەكردنەكان sub_reports: - combined: 'رووداوەكان  - -  ' - total: ' ژمارەی ئەو رووداوانەی توندوتیژی جێندەری كە هەواڵیان لەبارەوە دراوە' - gbv_sexual_violence: ' ژمارەی ئەو رووداوانەی توندوتیژی جنسی كە هەواڵی لەبارەوە دراوە' - gbv_previous_incidents: ژمارەی ئەو ڕووداوانەی کە لەلایەن ئەو ڕزگاربووانەوە ڕاپۆرتکراون کە پێشتر ڕووداوی GBV یان هەبووە - gbv_sexual_violence_type: جۆری رووداوەكە - incident_timeofday: ' كاتی رووداوەكە لە رۆژدا' - elapsed_reporting_time: کاتی نێوان ڕووداو و بەرواری ڕاپۆرت - elapsed_reporting_time_rape: ڕووداوەکانی دەستدرێژی سێکسی، کاتی بەسەرچوو لە نێوان ڕووداو و بەرواری ڕاپۆرت - elapsed_reporting_time_rape_health_referral: ڕووداوەکانی دەستدرێژی سێکسی، ماوەی تێپەڕبوو لە نێوان ڕووداو و بەرواری ڕاپۆرت (خزمەتگوزاری تەندروستی یان ڕەوانەکردن) - incident_location_type: 'شوێنی رووداوەكە - -  ' - number_of_perpetrators: ژمارەی تاوانباران - perpetrator_relationship: پەیوەندی تاوانباری سەرەتایی گومانلێکراو لەگەڵ ڕزگاربوو - perpetrator_age_group: گروپی تەمەنی تاوانبارانی سەرەکی - perpetrator_occupation: پیشەی تاوانباری گومانلێکراوی سەرەکی - age: ژمارەی رزگاربوان بەپێی تەمەن - sex: ژمارەی رزگاربوان بەپێی ڕەگەز - marital_status: دۆخی خێزانی ڕزگاربوان - displacement_status: دۆخی ئاوارەبوونی ڕزگاربووان - displacement_incident: قۆناغی ئاوارەبوون لە کاتی ڕووداوەکەدا - gbv_case_context: سیاقی کەیسەکە - incidents_first_point_of_contact: ژمارەی ئەو ڕووداوانەی کە ڕێکخراوەکەت یەکەم خاڵی پەیوەندییە - incidents_from_other_service_provider: ئەو ڕووداوانەی کە لە پێشکەشکارانی خزمەتگوزارییەکانی ترەوە ڕەوانە دەکرێن - number_of_services_provided: ژمارەی ئەو خزمەتگوزارییانەی کە بۆ ڕووداوەکان پێشکەش دەکرێن - number_of_services_provided_other: ڕەوانەکردنی ڕووداوی نوێ بۆ پێشکەشکارانی خزمەتگوزاری تر service_safehouse_referral: ڕەوانەکردنی خانووی سەلامەت/پەناگەی سەلامەت service_medical_referral: ڕەوانەکردنی تەندروستی/پزیشکی service_psycho_referral: خزمەتگوزاری دەروونی کۆمەڵایەتی/ڕاوێژکاری @@ -2084,7 +2053,6 @@ ku: service_police_referral: پۆلیس یان جۆرەکانی تری خزمەتگوزاری ئەمنی service_livelihoods_referral: خزمەتگوزاری بژێوی ژیان service_protection_referral: خزمەتگوزاری پاراستنی منداڵان - vulnerable_populations: دانیشتوانی لاواز survivors_disability_type: لەگەڵ خاوەن پێداویستییە تایبەتەکان success_message: بە سەرکەوتوویی فایلە هەناردەکراوەکانی دروست کرا messages: @@ -2700,7 +2668,6 @@ ku:  ' label: ئەركە درەنگوەختەكانی خزمەتگوزاری dash_case_incident_overview: - explanation: ' ' label: پوختە-كەیسەكانم/ رووداوەكانم dash_cases_by_social_worker: explanation: ' خشتەیەك ئەوە پیشان دەدات كە چۆن تێكڕای ژمارەی كەیسە كراوەكان و ژمارەی كەیسە نوێیە بەڕێوەبردرێن لەلایەن هەر بەكارهێنەرێكەوە لە گروپە بەكارهێنەرەكانی بەكارهێنەری ئێستا. هەر ریزێك بەكارهێنەرە لە گروپە بەكارهێنەرەكانی بەكارهێنەری ئێستا، كە "تێكڕا" و "نوێ" دوو ستوونی نوێن. ' @@ -3340,7 +3307,6 @@ ku: display: هاوبەشە شاراوەکان پیشانبدە بو %{type} %{id} reassign: multiple_error: هەڵەیەك روویدا%{select_records}كەیسەكە(كەیسەكان) دەستنیشان نەكراون - multiple_successfully: '%{select_records}كەیس(ەكان) بە سەركەوتویی دەستنیشانكران' notes_label: تێبینیەکان successfully: سەرکەوتوانە دەستنیشانكرانەوە user_mandatory_label: وەرگر پێویستە diff --git a/config/locales/my.yml b/config/locales/my.yml index 424ae04f70..f0820121be 100644 --- a/config/locales/my.yml +++ b/config/locales/my.yml @@ -15,18 +15,16 @@ my: unavailable_offline: အော့ဖ်လိုင်း မရနိုင်ပါ။ online: ဤ application သည် အင်တာနက်နှင့်ချိတ်ဆက်ထားသည်။ yes_label: 'ဟုတ်သည်' - or_label: သို့မဟုတ် select_provider: ဝန်ဆောင်မှုပေးသူ ကိုရွေးချယ်ပါ select_language: ဘာသာစကားကိုရွေးချယ်ပါ - log_in_primero_idp: "အသုံးပြုသူအမည် %{idp_name} ဖြင့်ဝင်ရောက်ပါ။" + log_in_primero_idp: အသုံးပြုသူအမည် %{idp_name} ဖြင့်ဝင်ရောက်ပါ။ offline_submitted_changes: သင်သည် လောလောဆယ် အင်တာနက်နှင့်ချိတ်ထားဆက်ခြင်းမရှိပါ။ အင်တာနက် ချိတ်ဆက်၍ရသောအခါတွင် သင်၏ပြောင်းလဲမှုများကို တင်သွင်းပါမည်။ updated: နောက်ဆုံးအခြေအနေနှင့်အညီ ပြုပြင်မွမ်းမံထားသည် sync: success: "%{records}ဖြစ်ရပ်မှတ်တမ်းများကိုအောင်မြင်စွာ ထပ်တူပြုထားသည်။" error: - create: "ပြုလုပ်၍မရပါ%{record_type}။ ကျေးဇူးပြု၍ အကူအညီပေးကဏ္ဍ ကိုဆက်သွယ်ပါ။" - update: "%{record_type} %{short_id} သို့ အပ်ဒိတ်ပြုလုပ်မှု မအောင်မြင်ပါ။ ကျေးဇူးပြု၍ အကူအညီပေးကဏ္ဍ ကိုဆက်သွယ်ပါ။ " - + create: ပြုလုပ်၍မရပါ%{record_type}။ ကျေးဇူးပြု၍ အကူအညီပေးကဏ္ဍ ကိုဆက်သွယ်ပါ။ + update: '%{record_type} %{short_id} သို့ အပ်ဒိတ်ပြုလုပ်မှု မအောင်မြင်ပါ။ ကျေးဇူးပြု၍ အကူအညီပေးကဏ္ဍ ကိုဆက်သွယ်ပါ။ ' actions: approvals: အတည်ပြုချက်များ button: ဆောင်ရွက်ချက်များ @@ -98,7 +96,7 @@ my: action: အရေးယူဆောင်ရွက်မှု description: ရှင်းလင်းဖော်ပြချက် record_owner: မှတ်တမ်း၏ ပိုင်ရှင် - timestamp: "ညှိနှိုင်းထားသော ကမ္ဘာလုံးဆိုင်ရာအချိန် " + timestamp: 'ညှိနှိုင်းထားသော ကမ္ဘာလုံးဆိုင်ရာအချိန် ' user_name: အသုံးပြုသူ၏ အမည် bulk_export: file_name: ဖိုင် @@ -136,7 +134,7 @@ my: continue: ရှေ့ဆက်သွားပါ။ create_case: ဖြစ်ရပ် စတင်စာရင်းသွင်းရန် create_incident: ဖြစ်စဉ်ကို စတင်စာရင်းသွင်းရန် - create_new_record: "အသစ်ပြုလုပ်သည် %{model}" + create_new_record: အသစ်ပြုလုပ်သည် %{model} delete: ဖျက်သည် disable: လုပ်ဆောင်၍မရနိုင်ပါ disable_photo_wall: ဓာတ်ပုံအများအပြားထည့်သွင်း မလုပ်ဆောင်နိုင်ရန်ပြုလုပ်သည် @@ -148,11 +146,11 @@ my: enable_photo_wall: ဓာတ်ပုံများထည့်သွင်းနိုင်ရန်ပြုလုပ်သည် export: အချက်အလက်များထုတ်ယူခြင်း filter: ရွေးချယ်စစ်ထုတ်သည့်အရာကို အသုံးပြုပါ - filter_clear: "ရွေးချယ်စစ်ထုတ်သည့်အရာကို ရှင်းလင်းပါ " + filter_clear: 'ရွေးချယ်စစ်ထုတ်သည့်အရာကို ရှင်းလင်းပါ ' filter_label: 'ရွေးချယ်စစ်ထုတ်သည့်အရာ' filter_restore: စနစ်ချိန်ညှိချက်များအားမူလအတိုင်း ပြန်ထားပါ find_tracing_match: ခြေရာခံရန်တူညီမှုများကို ရှာဖွေပါ - flag_model: "အမှတ်အသားပြုခြင်း %{model}" + flag_model: အမှတ်အသားပြုခြင်း %{model} flag_records: အမှတ်အသားပြုခြင်း flags: အမှတ်အသားပြုခြင်း guidance: လမ်းညွှန်ချက် @@ -165,8 +163,8 @@ my: ok: သဘောတူသည် print: Print - ပရင့်ထုတ်ခြင်း - ပုံနှိပ်မိတ္တူထုတ် ခြင်း reassign: တာဝန်ပေးသည့် - referral: "ညွှန်းပို့လွှဲပြောင်း " - referral_again: "ထပ်မံ လွှဲပြောင်းညွှန်းပို့ခြင်း " + referral: 'ညွှန်းပို့လွှဲပြောင်း ' + referral_again: 'ထပ်မံ လွှဲပြောင်းညွှန်းပို့ခြင်း ' reject: ငြင်းဆိုသည်/ပယ်ဖျက်ခြင်း remove_referrals: လွှဲပြောင်းညွှန်ပို့မှုကို ဖယ်ရှားသည် reorder: မှတ်တမ်းတင်ခြင်း/ မှတ်တမ်းယူသူ @@ -185,8 +183,8 @@ my: sync: ထပ်တူကျသည်။ submit: တင်သွင်းခြင်း transfer: လွှဲပြောင်း - unflag_model: "အမှတ်အသားဖျက်သိမ်းခြင်း %{model}" - unflag_model_history: "အမှတ်အသားပြုလုပ်ခဲ့မှု %{model}" + unflag_model: အမှတ်အသားဖျက်သိမ်းခြင်း %{model} + unflag_model_history: အမှတ်အသားပြုလုပ်ခဲ့မှု %{model} unmark_for_mobile: မိုဘိုင်းဖုန်း အတွက်မှတ်သားမှုကို ပယ်ဖျက်ပါ update: နောက်ဆုံးအခြေအနေနှင့်အညီ ပြုပြင်မွမ်းမံသည် view: ကြည့်ရန် @@ -200,13 +198,13 @@ my: back_to_results: ရလဒ်များသို့ ပြန်သွားရန် back_to_search: ရှာဖွေခြင်းသို့ ပြန်သွားရန် search_by: ရှာဖွေရန် - search_for: "အတွက် ရှာဖွေပါ %{record_type}" + search_for: အတွက် ရှာဖွေပါ %{record_type} results: ရလဒ်များ details: အသေးစိတ် select: ရွေးချယ်ပါ deselect: မရွေးချယ်ပါ enter_id_number: ရှိပြီးမှတ်တမ်းတစ်ခုကိုရှာရန် ID နံပါတ်ကိုရိုက်ထည့်ပါ - id_search_no_results: "စနစ်အတွင်း %{id}နှင့်ကိုက်ညီသူမရှိပါ၊ ကျေးဇူးပြု၍ မှတ်တမ်းအသစ်တစ်ခုပြုလုပ်ပါ။" + id_search_no_results: စနစ်အတွင်း %{id}နှင့်ကိုက်ညီသူမရှိပါ၊ ကျေးဇူးပြု၍ မှတ်တမ်းအသစ်တစ်ခုပြုလုပ်ပါ။ messages: disabled: ဖြစ်ရပ်ကို ပိတ်ထားသည် update_success: '%{record_id} ဖြစ်ရပ်ကို နောက်ဆုံးအခြေအနေနှင့်အညီ အောင်မြင်စွာပြင်ဆင်ခဲ့သည်။' @@ -215,8 +213,8 @@ my: creation_success_queue: 'ဖြစ်ရပ်မှတ်တမ်းကို နောက်ခံတွင် အောင်မြင်စွာ စတင်ပြုလုပ်ခဲ့သည်။' already_matched: ဤ စုံစမ်းမေးမြန်းမှုသည် သင့်ဖြစ်ရပ်နှင့် ကိုက်ညီပြီးဖြစ်သည်။ already_matched_not_current_case: ဤစုံစမ်းမှုမေးမြန်းမှုနှင့် ကိုက်ညီသော ဖြစ်ရပ်တစ်ခု စနစ်တွင် ရှိနှင့်ပြီးဖြစ်သည်။ - not_found_case: "တူညီသော ဖြစ်ရပ်မတွေ့ပါ \"%{search_value}\". ဖြစ်ရပ် အသစ်တစ်ခု စတင်ပြုလုပ်ပါ။" - introductory_sentence: "ဖြစ်ရပ်စီမံခန့်ခွဲမှုဝန်ဆောင်မှုများလက်ခံရယူရန်နှင့် ၎င်းတို့၏ဒေတာများကို Primero တွင်သိမ်းဆည်းရန်အတွက် တစ်ဦးချင်းစီ၏သဘောတူညီချက်ကို ကျေးဇူးပြုပြီး သတ်မှတ်ပေးပါ။ " + not_found_case: တူညီသော ဖြစ်ရပ်မတွေ့ပါ "%{search_value}". ဖြစ်ရပ် အသစ်တစ်ခု စတင်ပြုလုပ်ပါ။ + introductory_sentence: 'ဖြစ်ရပ်စီမံခန့်ခွဲမှုဝန်ဆောင်မှုများလက်ခံရယူရန်နှင့် ၎င်းတို့၏ဒေတာများကို Primero တွင်သိမ်းဆည်းရန်အတွက် တစ်ဦးချင်းစီ၏သဘောတူညီချက်ကို ကျေးဇူးပြုပြီး သတ်မှတ်ပေးပါ။ ' consent_agreements_required: ကျေးဇူးပြု၍ သဘောတူညီ ခွင့်ပြုချက်များမှ အနည်းဆုံးရွေးချယ်ခွင့်တစ်ခုကို ရွေးပါ။ legitimate_basis_required: ကျေးဇူးပြု၍ တရားဝင် အခြေခံအမျိုးအစားခွဲခြားမှုများမှးမှ အနည်းဆုံးရွေးချယ်ခွင့်တစ်ခုကို ရွေးပါ။ save: ဖြစ်ရပ်ကို သိမ်းဆည်းပါ @@ -225,12 +223,12 @@ my: search_existing: ရှိပြီသား ဖြစ်ရပ်များကိုရှာပါ search_helper_text: အဘယ်ကြောင့်နည်း ။ ထပ်တူညီသော ဖြစ်ရပ်များ အသစ်ပြုလုပ်ခြင်းမှ တားဆီးရန်။ consent_agreements: သက်ဆိုင်ရာ သဘောတူညီချက်များအားလုံးကို ရွေးချယ်ပါ။ - legitimate_basis: "သက်ဆိုင်သည့်ဆက်စက်မှုရှိသည့် အမျိုးအစားအားလုံးကို ရွေးပါ။ " + legitimate_basis: 'သက်ဆိုင်သည့်ဆက်စက်မှုရှိသည့် အမျိုးအစားအားလုံးကို ရွေးပါ။ ' workflow: assessment: အကဲဖြတ်ဆန်းစစ်သုံးသပ်ခြင်း case_plan: ဖြစ်ရပ်အတွက်အစီအစဉ် closed: ပိတ်သိမ်းခဲ့ပြီးဖြစ်သည် - created_on: " တွင်စတင်ပြုလုပ်ခဲ့သည်" + created_on: ' တွင်စတင်ပြုလုပ်ခဲ့သည်' in_progress: ဆောင်ရွက်ဆဲ new: အသစ် on_label: 'တွင် /ဖွင့်' @@ -253,7 +251,7 @@ my: approval_radio: ကျွန်ုပ် .... ချင်ပါသည် approval_radio_accept: အတည်ပြုသည် approval_radio_reject: အတည်မပြုပါ။ - approval_select: "..... အတွက် ဖောင်ပုံစံ" + approval_select: '..... အတွက် ဖောင်ပုံစံ' approved_success_action_plan: '%{approval_label} - အတည်ပြုပြီး' approved_success_assessment: '%{approval_label} - အတည်ပြုပြီး' approved_success_bia: '%{approval_label} - အတည်ပြုပြီး' @@ -288,7 +286,7 @@ my: age_12_17: 12 - 17 age_18_more: 18+ age_6_11: 6 - 11 - age_range: "အသက်အပိုင်းအခြား:" + age_range: 'အသက်အပိုင်းအခြား:' agency: အဖွဲ့အစည်း approval_status: အတည်ပြုချက်များ အခြေအနေ approvals: @@ -306,7 +304,7 @@ my: displacement_status: နေအိမ်စွန့်ခွာထွက်ပြေးရသည့် အခြေအနေ district: ခရိုင် - duplicate: ထပ်နေသည် - enabled_disabled: "အသုံးပြုနိုင်အောင်ဖွင့်ပါ / အသုံးမပြုနိုင်အောင်ပိတ်ပါ " + enabled_disabled: 'အသုံးပြုနိုင်အောင်ဖွင့်ပါ / အသုံးမပြုနိုင်အောင်ပိတ်ပါ ' female:  မ flag: အမှတ်အသားပြုခဲ့သည် flag_label: အမှတ်အသားပြုခဲ့သလား။ @@ -323,15 +321,15 @@ my: open: ဖွင့်သည် other: အခြား photo: ဓါတ်ပုံ- - photo_label: "ဓါတ်ပုံရှိပါသလား?" + photo_label: ဓါတ်ပုံရှိပါသလား? protection_concerns: ကာကွယ်စောင့်ရှောက်ရေးအတွက်စိုးရိမ်ပူပန်မှုများ- - protection_status: "ကာကွယ်စောင့်ရှောက်မှုအခြေအနေ:" + protection_status: 'ကာကွယ်စောင့်ရှောက်မှုအခြေအနေ:' record_state: မှတ်တမ်း၏ အခြေအနေ referred_cases: ကျွန်ုပ်ထံ လွှဲပြောင်းထားသော ဖြစ်ရပ်များ registration_date: မှတ်ပုံတင်သည့် ရက်စွဲ- risk_level: အန္တရာယ်အဆင့် sex: လိင်- - social_worker: "ကွင်းဆင်း / ဖြစ်ရပ် / လူမှုရေးလုပ်သား:" + social_worker: 'ကွင်းဆင်း / ဖြစ်ရပ် / လူမှုရေးလုပ်သား:' status: ဖြစ်ရပ်အခြေအနေ transferred: လွှဲပြောင်းပေးခဲ့သည် type_of_risk: အန္တရာယ်အမျိုးအစား- @@ -356,17 +354,17 @@ my: most_recently: မကြာသေးမီက name: အမည် owned_by: မှတ်တမ်း ပိုင်ရှင် - owned_by_agency: "မှတ်တမ်း ပိုင်ရှင်အဖွဲ့အစည်း " + owned_by_agency: 'မှတ်တမ်း ပိုင်ရှင်အဖွဲ့အစည်း ' photo: ဓါတ်ပုံ photos: ဓါတ်ပုံ quick_view: tracing_message: 'မှတ်ချက် -၎င်းကလေးကိုရှာဖွေနေသောသူနှင့် တူညီသူကို စနစ်အတွင်းတွေ့ရှိပါသည်။ အကယ်၍ ကလေးကဆန္ဒရှိပါက နောက်ထပ်အရေးယူမှုဆောင်ရွက်မှုများအတွက် ဤမှတ်တမ်းမှ လူမှုရေးဝန်ထမ်းအားဆက်သွယ်ပါ။' - referral_done: "'ပြီးပါပြီ' ကို နှိပ်လျှင် ဤဖြစ်ရပ်နှင့် ဆက်စပ်နေသော ညွှန်းပို့လွှဲပြောင်းခြင်းလုပ်ငန်း ပြီးဖြစ်ပါသည်။ 'ပြီးပါပြီ' ကို နှိပ်လိုက်သည်နှင့် သင်သည် ဤမှတ်တမ်းသို့ ဝင်ရောက်ခွင့် မရှိတော့ပါ။ " + referral_done: '''ပြီးပါပြီ'' ကို နှိပ်လျှင် ဤဖြစ်ရပ်နှင့် ဆက်စပ်နေသော ညွှန်းပို့လွှဲပြောင်းခြင်းလုပ်ငန်း ပြီးဖြစ်ပါသည်။ ''ပြီးပါပြီ'' ကို နှိပ်လိုက်သည်နှင့် သင်သည် ဤမှတ်တမ်းသို့ ဝင်ရောက်ခွင့် မရှိတော့ပါ။ ' referral_done_success: ညွှန်းပို့ခြင်းကို လုပ်ဆောင်ပြီးပါပြီ referral_accepted_header: ညွှန်းပို့ခြင်းကို လက်ခံပါသည်။ referral_accepted: သင်သေချာပါသလား။ ဤညွှန်းပို့လွှဲအပ်မှုချက်နှင့် ဆက်စပ်သော အလုပ်များကို ပြီးမြောက်ရန် သင်သည် ယခု တာဝန်ယူရမည်ဖြစ်ပါသည်။ referral_accepted_success: ညွှန်းပို့ခြင်းကို လုပ်ဆောင်ပြီးပါပြီ - referral_rejected: "'ငြင်းပယ်ရန်' ကိုနှိပ်ခြင်းဖြင့် သင်သည် ဤညွှန်းပို့လွှဲအပ်မှုအား ယခုအချိန်တွင် လက်ခံရန် အဆင်သင့်မဖြစ်သေးကြောင်း ညွှန်ပြနေပါသည်။ ဤညွှန်းပို့လွှဲအပ်မှုကို သင် ငြင်းပယ်သည့် အကြောင်းရင်းကို ထည့်သွင်းပါ။ 'ငြင်းပယ်' ကိုနှိပ်လိုက်သည်နှင့် သင်သည် ဤဖြစ်ရပ်မှတ်တမ်းသို့ ဝင်ရောက်ခွင့်မရှိတော့ပါ။" + referral_rejected: '''ငြင်းပယ်ရန်'' ကိုနှိပ်ခြင်းဖြင့် သင်သည် ဤညွှန်းပို့လွှဲအပ်မှုအား ယခုအချိန်တွင် လက်ခံရန် အဆင်သင့်မဖြစ်သေးကြောင်း ညွှန်ပြနေပါသည်။ ဤညွှန်းပို့လွှဲအပ်မှုကို သင် ငြင်းပယ်သည့် အကြောင်းရင်းကို ထည့်သွင်းပါ။ ''ငြင်းပယ်'' ကိုနှိပ်လိုက်သည်နှင့် သင်သည် ဤဖြစ်ရပ်မှတ်တမ်းသို့ ဝင်ရောက်ခွင့်မရှိတော့ပါ။' referral_rejected_success: ညွှန်းပို့ခြင်းကို ငြင်းဆိုထားသည် register_new_case: ဖြစ်ရပ်အသစ် registration_date: စာရင်းသွင်းသည့် နေ့စွဲ @@ -381,22 +379,22 @@ my: reopen_success: ဖြစ်ရပ်ကို အောင်မြင်စွာ ပြန်လည်ဖွင့်ပြီးပါပြီ request_approval_failure: အမှားတစ်ခု ဖြစ်ပွားခဲ့သည်၊ ကျေးဇူးပြု၍ အကူအညီကဏ္ဍကို ဆက်သွယ်ပါ။ request_approval_select: အတွက် ခွင့်ပြုချက်တောင်းခံခြင်း။ - request_approval_success_action_plan: "%{approval_label} ဖောင်ပုံစံအတွက် အတည်ပြုချက်တောင်းခံခြင်း။" - request_approval_success_assessment: "%{approval_label} ဖောင်ပုံစံအတွက် အတည်ပြုချက်တောင်းခံခြင်း။" - request_approval_success_case_plan: "%{approval_label} ဖောင်ပုံစံအတွက် အတည်ပြုချက်တောင်းခံခြင်း။" - request_approval_success_closure: "%{approval_label} ဖောင်ပုံစံအတွက် အတည်ပြုချက်တောင်းခံခြင်း။" - request_approval_success_gbv_closure: "%{approval_label} ဖောင်ပုံစံအတွက် အတည်ပြုချက်တောင်းခံခြင်း။" + request_approval_success_action_plan: '%{approval_label} ဖောင်ပုံစံအတွက် အတည်ပြုချက်တောင်းခံခြင်း။' + request_approval_success_assessment: '%{approval_label} ဖောင်ပုံစံအတွက် အတည်ပြုချက်တောင်းခံခြင်း။' + request_approval_success_case_plan: '%{approval_label} ဖောင်ပုံစံအတွက် အတည်ပြုချက်တောင်းခံခြင်း။' + request_approval_success_closure: '%{approval_label} ဖောင်ပုံစံအတွက် အတည်ပြုချက်တောင်းခံခြင်း။' + request_approval_success_gbv_closure: '%{approval_label} ဖောင်ပုံစံအတွက် အတည်ပြုချက်တောင်းခံခြင်း။' request_approval_type_of_case_plan: ဖြစ်ရပ်အစီအစဉ် အတည်ပြုချက် အမျိုးအစား request_approve_action_plan: ဖြစ်ရပ်အစီအစဉ်ကို အတည်ပြုမည်လား request_approve_bia: အကဲဖြတ်ဆန်းစစ်သုံးသပ်ခြင်းကို အတည်ပြုမည်လား။ request_approve_case_plan: ဖြစ်ရပ်အစီအစဉ်ကို အတည်ပြုမည်လား request_approve_closure: ပိတ်သိမ်းမှုကို အတည်ပြုမည်လား - request_approve_gbv_closure: "ကျား/မအခြေပြုမတော်မတရားပြုမူမှု ဖြစ်ရပ်ပိတ်သိမ်းရန် ခွင့်ပြုပါသလား?" - revoke_failure: "%{transition_type}ဖျက်သိမ်းနေစဉ် အမှားတစ်ခု ဖြစ်ပွားခဲ့သည်၊ ကျေးဇူးပြု၍ အကူအညီကဏ္ဍ ကို ဆက်သွယ်ပါ။" - revoke_message: "'ရုပ်သိမ်းရန်' ကိုနှိပ်ခြင်းဖြင့် %{transition_type} လက်ခံသူ၏ဝင်ရောက်ခွင့်ကို ဖယ်ရှားပါမည်။" - revoke_success_message: "%{case_id} %{transition_type}ဖြစ်ရပ်အား {recipient_username} ရုပ်သိမ်းလိုက်သည်။" + request_approve_gbv_closure: ကျား/မအခြေပြုမတော်မတရားပြုမူမှု ဖြစ်ရပ်ပိတ်သိမ်းရန် ခွင့်ပြုပါသလား? + revoke_failure: '%{transition_type}ဖျက်သိမ်းနေစဉ် အမှားတစ်ခု ဖြစ်ပွားခဲ့သည်၊ ကျေးဇူးပြု၍ အကူအညီကဏ္ဍ ကို ဆက်သွယ်ပါ။' + revoke_message: '''ရုပ်သိမ်းရန်'' ကိုနှိပ်ခြင်းဖြင့် %{transition_type} လက်ခံသူ၏ဝင်ရောက်ခွင့်ကို ဖယ်ရှားပါမည်။' + revoke_success_message: '%{case_id} %{transition_type}ဖြစ်ရပ်အား {recipient_username} ရုပ်သိမ်းလိုက်သည်။' save_filter: သိမ်းဆည်းသည်၊ - selected_all_records: "ဤမေးခွန်းနှင့် ကိုက်ညီသော %{total_records} ဖြစ်ရပ်များအားလုံးကို ရွေးပါ။" + selected_all_records: ဤမေးခွန်းနှင့် ကိုက်ညီသော %{total_records} ဖြစ်ရပ်များအားလုံးကို ရွေးပါ။ selected_records: '%{select_records} ရွေးချယ်ထားသော ဖြစ်ရပ်(များ)' sex: လိင် show_case: 'ဖြစ်ရပ် ID %{short_id}' @@ -426,13 +424,13 @@ my: child_wishes_link: label: ကလေး၏ဆန္ဒများကိုကြည့်ပါ။ survivor_code: ရှင်သန်ကျန်ရစ်သူ ကုဒ်နံပါတ် - transfer_accepted: "'လက်ခံသည်' ကိုနှိပ်ခြင်းဖြင့် သင်သည် ဤဖြစ်ရပ်အတွက်ဖြေရှင်းဆောင်ရွက်ရန် တာဝန်ကို လက်ခံပါသည်။ 'လက်ခံသည်' ကိုနှိပ်လိုက်သည်နှင့် သင်သည် စနစ်အတွင်းရှိ မှတ်တမ်းပိုင်ရှင် ဖြစ်လာမည်ဖြစ်သည်။ " - transfer_managed_user_accepted: "'လက်ခံသည်' ကိုနှိပ်ပါက ဤဖြစ်ရပ်အတွက် %{transitioned_to}တာဝန်ရှိပါမည်။ 'လက်ခံသည်' ကို နှိပ်လိုက်သည်နှင့် %{transitioned_to} စနစ်အတွင်းရှိ မှတ်တမ်းပိုင်ရှင် ဖြစ်လာမည်ဖြစ်သည်။" - transfer_managed_user_rejected: "'ငြင်းပယ်ရန်' ကိုနှိပ်ခြင်းဖြင့် သင်သည် ဤဖြစ်ရပ်အတွက် %{transitioned_to}တာဝန်ယူရန် အဆင်သင့်မဖြစ်သေးကြောင်း ဖော်ပြနေပါသည်။ ဤဖြစ်ရပ်ကိုကိုင်တွယ်ဖြေရှင်းရန် သင်ငြင်းဆိုရသည့် အကြောင်းပြချက်ကို ထည့်သွင်းဖော်ပြပါ။ 'ငြင်းပယ်' ကို နှိပ်လိုက်သည်နှင့် %{transitioned_to} ဤဖြစ်ရပ်မှတ်တမ်းသို့ ဝင်ရောက်ခွင့်မရှိတော့ပါ။" - transfer_accepted_rejected: "%{record_id}ဖြစ်ရပ်လွှဲပြောင်းမှုကို ငြင်းပယ်ခဲ့သည်။" + transfer_accepted: '''လက်ခံသည်'' ကိုနှိပ်ခြင်းဖြင့် သင်သည် ဤဖြစ်ရပ်အတွက်ဖြေရှင်းဆောင်ရွက်ရန် တာဝန်ကို လက်ခံပါသည်။ ''လက်ခံသည်'' ကိုနှိပ်လိုက်သည်နှင့် သင်သည် စနစ်အတွင်းရှိ မှတ်တမ်းပိုင်ရှင် ဖြစ်လာမည်ဖြစ်သည်။ ' + transfer_managed_user_accepted: '''လက်ခံသည်'' ကိုနှိပ်ပါက ဤဖြစ်ရပ်အတွက် %{transitioned_to}တာဝန်ရှိပါမည်။ ''လက်ခံသည်'' ကို နှိပ်လိုက်သည်နှင့် %{transitioned_to} စနစ်အတွင်းရှိ မှတ်တမ်းပိုင်ရှင် ဖြစ်လာမည်ဖြစ်သည်။' + transfer_managed_user_rejected: '''ငြင်းပယ်ရန်'' ကိုနှိပ်ခြင်းဖြင့် သင်သည် ဤဖြစ်ရပ်အတွက် %{transitioned_to}တာဝန်ယူရန် အဆင်သင့်မဖြစ်သေးကြောင်း ဖော်ပြနေပါသည်။ ဤဖြစ်ရပ်ကိုကိုင်တွယ်ဖြေရှင်းရန် သင်ငြင်းဆိုရသည့် အကြောင်းပြချက်ကို ထည့်သွင်းဖော်ပြပါ။ ''ငြင်းပယ်'' ကို နှိပ်လိုက်သည်နှင့် %{transitioned_to} ဤဖြစ်ရပ်မှတ်တမ်းသို့ ဝင်ရောက်ခွင့်မရှိတော့ပါ။' + transfer_accepted_rejected: '%{record_id}ဖြစ်ရပ်လွှဲပြောင်းမှုကို ငြင်းပယ်ခဲ့သည်။' transfer_accepted_success: ဖြစ်ရပ်လွှဲပြောင်းမှုကို အောင်မြင်စွာ လက်ခံခဲ့သည်။ transfer_reject_reason_label: ငြင်းပယ်ရသည့် အကြောင်းအရင်း - transfer_rejected: "'ငြင်းပယ်ရန်' ကိုနှိပ်ခြင်းဖြင့် သင်သည် ဤဖြစ်ရပ်အတွက် တာဝန်ယူရန် အဆင်သင့်မဖြစ်သေးကြောင်း ဖော်ပြနေပါသည်။ ဤဖြစ်ရပ်ကိုကိုင်တွယ်ဖြေရှင်းရန် သင်ငြင်းဆိုရသည့် အကြောင်းပြချက်ကို ထည့်သွင်းဖော်ပြပါ။ 'ငြင်းပယ်' ကို နှိပ်လိုက်သည်နှင့် သင်သည် ဤဖြစ်ရပ်မှတ်တမ်းသို့ ဝင်ရောက်ခွင့်မရှိတော့ပါ။" + transfer_rejected: '''ငြင်းပယ်ရန်'' ကိုနှိပ်ခြင်းဖြင့် သင်သည် ဤဖြစ်ရပ်အတွက် တာဝန်ယူရန် အဆင်သင့်မဖြစ်သေးကြောင်း ဖော်ပြနေပါသည်။ ဤဖြစ်ရပ်ကိုကိုင်တွယ်ဖြေရှင်းရန် သင်ငြင်းဆိုရသည့် အကြောင်းပြချက်ကို ထည့်သွင်းဖော်ပြပါ။ ''ငြင်းပယ်'' ကို နှိပ်လိုက်သည်နှင့် သင်သည် ဤဖြစ်ရပ်မှတ်တမ်းသို့ ဝင်ရောက်ခွင့်မရှိတော့ပါ။' view_name: အမည်ကို ကြည့်ရန် change_logs: filters: @@ -461,7 +459,7 @@ my: apply_label: သင်သေချာပါသလား။ အကယ်၍ သင်အသုံးပြုပါက၊ ဤ configuration ပါရှိ ဆက်တင်များကို စနစ်သို့ သက်ရောက်မည်ဖြစ်သည်။ သင့်လက်ရှိဆက်တင်များအားလုံးကို သင်ဆုံးရှုံးသွားမည်ဖြစ်ပြီး ၎င်းတို့ကို အခြား configuration တွင် မသိမ်းဆည်းထားပါက ၎င်းတို့ကို ပြန်လည်ရရှိနိုင်မည်မဟုတ်ပေ။ apply_label_bold: အပြောင်းအလဲများကို ဖွင့်နေချိန်တွင် Primero ကို အသုံးပြုသူများ အနေဖြင့် မိနစ်အနည်းငယ်ကြာအောင် မရနိုင်ပါ။ version_mismatch_tooltip: သင့်လက်ရှိသုံးနေသော ဗားရှင်းထက် ပိုမိုမြင့်မားသော Primero ဗားရှင်းကို အသုံးပြု၍ ဖန်တီးထားသောကြောင့် ဤ configurationကို သင်အသုံးပြု၍မရပါ။ Primero ၏နောက်ဆုံးထွက်ဗားရှင်းကို သင်အသုံးမပြုမချင်း ဤ configurationကို အသုံးပြုရန် ကျေးဇူးပြုပြီးစောင့်ဆိုင်းပါ။ - send_header: "ထုတ်လုပ်ရေးသို့ ပို့ပါ။ " + send_header: 'ထုတ်လုပ်ရေးသို့ ပို့ပါ။ ' send_text: သင်သေချာလားပါသလား။ 'ပေးပို့ပါ' ကို နှိပ်ပါက၊ သင်သည် ဤ ဖွဲ့စည်းမှုပုံစံ configurationကို သင်၏ ထုတ်လုပ်မှုဆိုက်သို့ ပေးပို့မည်ဖြစ်သည်။ ထိုဆိုဒ်ရှိ စီမံခန့်ခွဲသူတစ်ဦးမှ ၎င်းကို မသုံးပေးမချင်း ဤဖွဲ့စည်းပုံ configuration သည် ထုတ်လုပ်မှုတွင် သက်ရောက်မှုရှိမည်မဟုတ်ပါ။ attributes: created_by: စတင်ပြုလုပ်သူ @@ -481,7 +479,7 @@ my: created: စီစဉ်ဖွဲ့စည်းမှုကို အောင်မြင်စွာ စတင်ပြုလုပ်ခဲ့သည် deleted: စီစဉ်ဖွဲ့စည်းမှုကို အောင်မြင်စွာ ဖျက်သိမ်းခဲ့သည် updated: စီစဉ်ဖွဲ့စည်းမှုကို နောက်ဆုံးအခြေအနေနှင့်အညီ အောင်မြင်စွာပြင်ဆင်ခဲ့သည်။ - sent: "ထုတ်လုပ်မှုသို့ ဖွဲ့စည်းမှုပုံစံကို ပေးပို့ခြင်း။ ကျေးဇူးပြု၍ သင်၏ ပုံဖွဲ့စည်းပုံရောက်ရှိခြင်းရှိ၊ မရှိစစ်ဆေးပါ။ " + sent: 'ထုတ်လုပ်မှုသို့ ဖွဲ့စည်းမှုပုံစံကို ပေးပို့ခြင်း။ ကျေးဇူးပြု၍ သင်၏ ပုံဖွဲ့စည်းပုံရောက်ရှိခြင်းရှိ၊ မရှိစစ်ဆေးပါ။ ' not_allowed: ခွင့်မပြုပါ။ unavailable_server: Server ကို ယာယီအသုံးပြု၍မရနိုင်ပါ။ contact: @@ -508,7 +506,7 @@ my: updated: ကျင့်ဝတ်စည်းမျဥ်းကို နောက်ဆုံးအခြေအနေနှင့်အညီ အောင်မြင်စွာပြင်ဆင်ပြီးပါပြီ။ dashboard: activity: ဆောင်ရွက်မှု - admin_only: "လျှောက်လွှာအားပြောင်းလဲမှုများပြုလုပ်ရန် %{links}ကိုနှိပ်ပါ။" + admin_only: လျှောက်လွှာအားပြောင်းလဲမှုများပြုလုပ်ရန် %{links}ကိုနှိပ်ပါ။ all_cases: ဖြစ်ရပ်များအားလုံး all_services_implemented: ဝန်ဆောင်မှုအားလုံး အကောင်အထည်ဖော်ပြီးဖြစ်သည် and: 'နှင့်' @@ -569,26 +567,26 @@ my: count_new_closure_approvals: other: '%{stat}အသစ် %{stat_type}အတည်ပြုမှုများ' count_pending_approval_total: - other: 'သင့်ထံတွင် %{stat}ဆိုင်းငံ့ထားသည့် %{stat_type} အတည်ပြုမှုများ' + other: သင့်ထံတွင် %{stat}ဆိုင်းငံ့ထားသည့် %{stat_type} အတည်ပြုမှုများ count_pending_transfers: - other: 'သင့်ထံတွင် %{stat}ဆိုင်းငံ့ထားသည့် လွှဲပြောင်းပေးမှုများ' + other: သင့်ထံတွင် %{stat}ဆိုင်းငံ့ထားသည့် လွှဲပြောင်းပေးမှုများ count_records_new: other: နှင့် %{stat} ဖြစ်ရပ်များ အသစ် count_records_total: - other: 'သင့်တွင် %{stat}ဖြစ်ရပ်များ စုစုပေါင်းရှိသည်' + other: သင့်တွင် %{stat}ဖြစ်ရပ်များ စုစုပေါင်းရှိသည် count_referrals_new: other: နှင့် %{stat} လွှဲပြောင်းညွှန်းပို့မှုများ အသစ် count_referrals_total: - other: 'သင့်တွင် %{stat}ညွှန်းပို့လွှဲအပ်မှု စုစုပေါင်းရှိသည်' + other: သင့်တွင် %{stat}ညွှန်းပို့လွှဲအပ်မှု စုစုပေါင်းရှိသည် count_rejected_approval_total: - other: 'နှင့် %{stat}ငြင်းဆိုခဲ့သည့် %{stat_type}အတည်ပြုမှုများ' + other: နှင့် %{stat}ငြင်းဆိုခဲ့သည့် %{stat_type}အတည်ပြုမှုများ count_rejected_transfers: - other: 'နှင့် %{stat}ငြင်းဆိုခဲ့သည့် လွှဲပြောင်းပေးမှုများ' + other: နှင့် %{stat}ငြင်းဆိုခဲ့သည့် လွှဲပြောင်းပေးမှုများ count_risk_level_new: other: နှင့် %{stat}အသစ်%{stat_type} အန္တရာယ် ဖြစ်ရပ် count_risk_level_total: - other: 'သင့်ထံတွင် %{stat} %{stat_type}အန္တရာယ်ရှိသည့် ဖြစ်ရပ်ခု ရှိသည်' - count_waiting_for_acceptance_transfers: "သင့်ထံတွင် %{stat}လွှဲပြောင်းပေးမှုများ စောင့်ဆိုင်းနေသည့် သင့်၏လက်ခံမှုကို" + other: သင့်ထံတွင် %{stat} %{stat_type}အန္တရာယ်ရှိသည့် ဖြစ်ရပ်ခု ရှိသည် + count_waiting_for_acceptance_transfers: သင့်ထံတွင် %{stat}လွှဲပြောင်းပေးမှုများ စောင့်ဆိုင်းနေသည့် သင့်၏လက်ခံမှုကို current_owner: လက်ရှိပိုင်ရှင် dash_case_incident_overview: ကျွန်ုပ်စီမံခန့်ခွဲနေသော ဖြစ်ရပ်များ dash_group_overview: ကျွန်ုပ်အဖွဲ့မှစီမံခန့်ခွဲနေသော ဖြစ်ရပ်များ @@ -597,7 +595,7 @@ my: dash_shared_with_my_team: ကျွန်ုပ်၏အဖွဲ့နှင့်အတူ မျှဝေထားသည်။ dash_shared_with_my_team_overview: ကျွန်ုပ်၏အဖွဲ့နှင့် မျှဝေထားသည် (ခြုံငုံသုံးသပ်ချက်) dash_shared_with_others: အခြားသူများနှင့်အတူ မျှဝေထားသည်။ - dash_national_admin_summary: "Administrator အနှစ်ချုပ် " + dash_national_admin_summary: 'Administrator အနှစ်ချုပ် ' date: ရက်စွဲ date_of_incident: ဖြစ်စဉ်ဖြစ်ပွားခဲ့သည့် ရက်စွဲ date_of_interview: တွေ့ဆုံမေးမြန်းမှု ပြုလုပ်သည့် ရက်စွဲ @@ -624,11 +622,11 @@ my: low_level: နိမ့် low_risk: အနိမ့်ဆုံး ဦးစားပေးမှု manager_count_closed_total: - other: 'နှင့် %{stat}ဖြစ်ရပ် ပိတ်သိမ်းပြီး' + other: နှင့် %{stat}ဖြစ်ရပ် ပိတ်သိမ်းပြီး manager_count_open_total: - other: 'သင့်ထံတွင် %{stat}ဖြစ်ရပ်များ ဖွင့်လှစ်' + other: သင့်ထံတွင် %{stat}ဖြစ်ရပ်များ ဖွင့်လှစ် manager_transfers_totals: - other: 'သင့်ထံတွင် %{stat}လွဲပြောင်းပေးမှု‌‌ပေါင်း %{stat_type}' + other: သင့်ထံတွင် %{stat}လွဲပြောင်းပေးမှု‌‌ပေါင်း %{stat_type} match_result: ကိုက်ညီသောရလဒ်များ medium_level: အလယ်အလတ် medium_risk: အလယ်အလတ် ဦးစားပေးမှု @@ -685,7 +683,7 @@ my: rejected_transfers: လွှဲပြောင်းခြင်းကို ငြင်းပယ်ခဲ့သည် response: တုန့်ပြန်မှု (In Progress) scheduled_activities: စီစဉ်ထားသောဆောင်ရွက်မှုများ - score_range: "ရမှတ်အဆင့်အပိုင်းအခြား:" + score_range: 'ရမှတ်အဆင့်အပိုင်းအခြား:' screening_service: ဆန်းစစ်ခြင်း ဝန်ဆောင်မှု services: ဝန်ဆောင်မှုများ services_implemented: ဝန်ဆောင်မှုများအကောင်အထည်ဖေါ်ပြီးဖြစ်သည် @@ -717,7 +715,7 @@ my: worker_count_referrals_total: other: '%{case_worker}တွင် %{stat}ညွှန်းပို့လွှဲအပ်မှု စုစုပေါင်း' worker_count_total: - other: '%{case_worker}ရှိသည် %{stat}ဖြစ်ရပ် စုစုပေါင်း' + other: %{case_worker}ရှိသည် %{stat}ဖြစ်ရပ် စုစုပေါင်း workflow: လုပ်ငန်းဆောင်ရွက်မှုလမ်းကြောင်း workflow_team: လုပ်ငန်းဆောင်ရွက်မှုလမ်းကြောင်း - အဖွဲ့ဖြစ်ရပ်များ you_have: 'သင့်တွင်ရှိသည်' @@ -755,16 +753,14 @@ my: password_extra_info: စကားဝှက်သည် အနည်းဆုံး စာလုံး 8 လုံးရှိရမည်။ ဤစကားဝှက်သည် export သတင်းအချက်အလက်ထုတ်ယူထားသောဖိုင်နှင့်ဆက်စပ်နေပြီး နောင်တွင်ဤဖိုင်ကိုဖွင့်သူမည်သူမဆို ရိုက်ထည့်ရန်လိုအပ်ပါမည်။ password_label: ကျေးဇူးပြု၍ သင်၏ဖိုင်ကိုစာဝှက်ရန် စကားဝှက်ကိုရေးပါ။ error_message: - address_fields: "သင်သည် %{forms} ဖောင်ပေါ်တွင် %{fields} fields များကို လိပ်စာတပ်ပေးရန်လိုအပ်သည်။" - address_form_fields: "သင်သည် ဤဖောင်ပေါ်တွင် %{fields} fields များကို လိပ်စာတပ်ပေးရန်လိုအပ်သည်။" + address_fields: သင်သည် %{forms} ဖောင်ပေါ်တွင် %{fields} fields များကို လိပ်စာတပ်ပေးရန်လိုအပ်သည်။ + address_form_fields: သင်သည် ဤဖောင်ပေါ်တွင် %{fields} fields များကို လိပ်စာတပ်ပေးရန်လိုအပ်သည်။ address_subform_fields: '%{subform}မှာ %{fields}မမှန်ကန်သော fields များရှိသည်။' error_page: not_authorized: - code: 403 server_error: ဤစာမျက်နှာကို ဝင်ရောက်ကြည့်ရှုရန် သင့်အား ခွင့်မပြုပါ။ title: လုပ်ပိုင်ခွင့်မရှိပါ။ not_found: - code: 404 contact_admin: သင်သည် ဤနေရာသို့ မှား၍ရောက်ရှိလာသည်ဟု ယုံကြည်ပါက သင်၏ admin ကိုဆက်သွယ်ပါ။ something_went_wrong: တောင်းပန်ပါသည်။ တစ်ခုခုမှားသွားပါတယ် errors: @@ -780,7 +776,7 @@ my: date_of_birth: ဒီဖြစ်ရပ်အတွက် မှန်ကန်သော မွေးနေ့သက္ကရာဇ်ကို ရေးသွင်းပါ။ export_configuration: opt_out_field_does_not_exist: သတ်မှတ်ထားသော opt_out field သည်မှတ်တမ်းထဲတွင်မရှိပါ။ - record_type: "မမှန်ကန်သော မှတ်တမ်းအမျိုးအစား။ ကလေး၊ ခြေရာခံရန်တောင်းဆိုမှု သို့မဟုတ် ဖြစ်စဉ် ဖြစ်ရမည်၊ " + record_type: 'မမှန်ကန်သော မှတ်တမ်းအမျိုးအစား။ ကလေး၊ ခြေရာခံရန်တောင်းဆိုမှု သို့မဟုတ် ဖြစ်စဉ် ဖြစ်ရမည်၊ ' field: translated_options_do_not_match: Field ဘာသာပြန်ခြင်းရွေးချယ်မှုများသည် တူညီသောအိုင်ဒီများရှိရမည် location: @@ -806,7 +802,7 @@ my: user: email: "ကျေးဇူးပြု၍ မှန်ကန်သော အီးမေးလ်လိပ်စာကို ရေးသွင်းပါ။ (ဥပမာ- 'name@example.org')" password_mismatch: စကားဝှက် field များတွင် တူညီသောစကားဝှက်မတွေ့ပါ - password_length: "စကားဝှက်သည် အနည်းဆုံး %{min} စာလုံးများဖြစ်ရမည်။" + password_length: စကားဝှက်သည် အနည်းဆုံး %{min} စာလုံးများဖြစ်ရမည်။ email_uniqueness: ဤအီးမေးလ်လိပ်စာဖြင့် အသုံးပြုသူတစ်ဦးရှိနှင့်ပြီးဖြစ်သည်။ ကျေးဇူးပြု၍ အခြားတစ်ခုထည့်ပါ။ code_of_conduct: title_present: ခေါင်းစဉ် ကွက်လပ် မဖြစ်ရပါ။ @@ -839,7 +835,7 @@ my: forms: ရွေးချယ်ထားသည့် ပုံစံများကို export လုပ်ပါ label: Custom Exports module_placeholder: ကျေးဇူးပြု၍ module တစ်ခုကိုရွေးပါ။ - select_module: " Module ကိုရွေးချယ်ပါ" + select_module: ' Module ကိုရွေးချယ်ပါ' submit: သဘောတူသည် header: ခေါင်းစီး custom_header: စိတ်ကြိုက်ပြင်ဆင်ထားသော ခေါင်းစီး @@ -850,7 +846,7 @@ my: include_other_logos: အခြားအမှတ်တံဆိပ်များကို ထည့်သွင်းမလား။ duplicate_id_csv: all: မိတ္တူ အိုင်ဒီ - female_abbreviation: "မ " + female_abbreviation: 'မ ' headers: age: အသက် case_id: ဖြစ်ရပ် အိုင်ဒီ @@ -861,7 +857,7 @@ my: progress_id: တိုးတက်မှု ID sex_mapping_m_f_u: လိင်- other_agency_id: ဆေးရုံကုဒ်နံပါတ် နှင့် လူနာအမှတ် - male_abbreviation: "ကျား " + male_abbreviation: 'ကျား ' unknown_abbreviation: U - under - အသက်အောက် exported: Export သတင်းအချက်အလက်ထုတ်ယူမှုဖိုင်ကို အောင်မြင်စွာ ထုတ်ပြီးပါပြီ။ exported_error: Export သတင်းအချက်အလက်ထုတ်ယူမှုဖိုင်ကို ထုတ်ရာတွင် အမှားရှိသည်။ @@ -871,7 +867,7 @@ my: header: form_group: ဖောင်ပုံစံ အုပ်စု form_name: ဖောင်ပုံစံအမည် - field_id: "Field အိုင်ဒီ " + field_id: 'Field အိုင်ဒီ ' field_type: Field အမျိုးအစား field_name: Field အမည် required: မဖြစ်မနေ လိုအပ်သည်။ @@ -900,14 +896,13 @@ my: form: Primero ဖောင်ပုံစံများ status: ဖြစ်ရပ်အခြေအနေ notes: မှတ်ချက်များ - go_to_exports: ဒေါင်းလုဒ်လုပ်ရန် Exports သတင်းအချက်အလက်ထုတ်ယူမှုစာမျက်နှာသို့ သွားပါ။ incident_recorder_xls: all: ဖြစ်စဉ်ကို မှတ်တမ်းတင်ခြင်း one: ဖြစ်စဉ်ကို မှတ်တမ်းတင်ခြင်း selected: ဖြစ်စဉ်မှတ်တမ်းကို ရွေးချယ်ထားသည် json: - all: "JSON - JavaScript Object Notation " + all: 'JSON - JavaScript Object Notation ' one: JSON - JavaScript Object Notation selected: JSON - JavaScript Object Notation သို့ ရွေးချယ်ခဲ့သည် list_view_csv: @@ -941,9 +936,9 @@ my: one: ဓါတ်ပုံများတင်ထားသည့်နေရာ/နံရံ reunited: ပြန်လည်ပေါင်းစည်းခဲ့သည် selected: ဓါတ်ပုံများတင်ထားသည့်နေရာ/နံရံသို့ ရွေးချယ်ခဲ့သည် - success_message: "ဓာတ်ပုံထည့်သွင်းခြင်းမပြုပဲ Photowall %{file_name}ဖြစ်ရပ်ဖန်တီးနိုင်မည်မဟုတ်ပါ။" + success_message: ဓာတ်ပုံထည့်သွင်းခြင်းမပြုပဲ Photowall %{file_name}ဖြစ်ရပ်ဖန်တီးနိုင်မည်မဟုတ်ပါ။ printed: 'ပုံနှိပ်သည် -%{date}' - queueing: "%{file_name} export သတင်းအချက်အလက်ထုတ်ယူမှု ဖိုင်ကို ထုတ်လုပ်နေသည်" + queueing: '%{file_name} export သတင်းအချက်အလက်ထုတ်ယူမှု ဖိုင်ကို ထုတ်လုပ်နေသည်' selected_xls: all: Excel one: Excel @@ -951,7 +946,7 @@ my: selected_fields: ရွေးချယ်ထားသော Fields များ unhcr_csv: all: UNHCR - female_abbreviation: "မ " + female_abbreviation: 'မ ' headers: age: အသက် case_status: ဖြစ်ရပ်အခြေအနေ @@ -979,7 +974,7 @@ my: short_id: ID အတို vulnerability_code: ထိခိုက်လွယ်ခြင်း ကုဒ်နံပါတ် vulnerability_details_code: ထိခိုက်လွယ်မှု အသေးစိတ်ပြ ကုဒ်နံပါတ် - male_abbreviation: "ကျား " + male_abbreviation: 'ကျား ' one: UNHCR selected: UNHCR သို့ ရွေးချယ်ခဲ့သည် unknown_abbreviation: U - under - အသက်အောက် @@ -1020,7 +1015,7 @@ my: add_new_field: Field အသစ် စတင်ပြုလုပ်ရန် add_existing_field: ရှိပြီသား Field ကိုထည့်ပါ add_field: Field ကိုထည့်ပါ - add_field_type: "ထည့်ပါ %{file_type}" + add_field_type: ထည့်ပါ %{file_type} audio: current: လက်ရှိအသံ audio_upload_box: အသံဖိုင်တင်ခြင်း။ @@ -1039,11 +1034,11 @@ my: time: အချိန် date_range: date: ရက်စွဲ - date_range: "ရက်စွဲအပိုင်းအခြား:" + date_range: 'ရက်စွဲအပိုင်းအခြား:' from: မှ to: သို့ view_by: ကြည့်ရန် - date_range_field: "ရက်စွဲအပိုင်းအခြား:" + date_range_field: 'ရက်စွဲအပိုင်းအခြား:' date_time: ရက်စွဲ-အချိန် db_name: DB အမည် default: ပုံသေသတ်မှတ်မည်လား @@ -1051,16 +1046,16 @@ my: default_to_current_date: လက်ရှိရက်စွဲမှာ ပုံသေသတ်မှတ်ချက်များ ရှိပါသလား။ default_to_current_datetime: လက်ရှိ ရက်စွဲ နှင့် အချိန်မှာ ပုံသေသတ်မှတ်ချက်များ ရှိပါသလား။ default_value: မူလတန်ဖိုး - deleted: "Field %{display_name}ကို နောက်ဆုံးအခြေအနေနှင့်အညီ ပြုပြင်ပြီးဖြစ်ပါသည်" + deleted: Field %{display_name}ကို နောက်ဆုံးအခြေအနေနှင့်အညီ ပြုပြင်ပြီးဖြစ်ပါသည် detail: အသေးစိတ် disabled: ပိတ်ထားသည် display_name: အမည် ဖေါ်ပြထားသည် document: comments: အကြံပြုချက်များ - current: "ဒါကလက်ရှိစာရွက်စာတမ်းဖြစ်ပါသလား?" + current: ဒါကလက်ရှိစာရွက်စာတမ်းဖြစ်ပါသလား? date: စာရွက်စာတမ်း၏ ရက်စွဲ name: စာရွက်စာတမ်းအမည် - is_current: "ဒါကလက်ရှိစာရွက်စာတမ်းဖြစ်ပါသလား?" + is_current: ဒါကလက်ရှိစာရွက်စာတမ်းဖြစ်ပါသလား? document_upload_box: စာရွက်စာတမ်းအား အပ်လုဒ် လုပ်ပါ edit_label: Field ကိုပြင်ဆင်ရန် enabled: စတင်လုပ်ဆောင်စေမည်လား။ @@ -1068,7 +1063,6 @@ my: english_text: အင်္ဂလိပ်စာသား field_name: Field အမည် field_type: Field အမျိုးအစား - attachment_too_large: ဖိုင်ဆိုဒ်သည် 10mb ထက်မကြီးသင့်ပါ။ file_upload_box: add_document_label: စာရွက်စာတမ်းကို ထည့်ပါ add_new_document_button_text: အခြားစာရွက်စာတမ်းကို ထည့်ပါ @@ -1097,13 +1091,13 @@ my: not_future_date: မရောက်ရှိသေးသည့်နေ့ရက်မဟုတ်ပါ number_not_valid: ကျေးဇူးပြု၍ ကိန်းဂဏန်းအချက်အလက်များဖြည့်ပါ numeric_field: ကိန်းဂဏန်းများထည့်သွင်းရန် နေရာ - on_collapsed_subform: "ဖောင်ပုံစံခွဲတွင် ဖြည့်သွင်းထားပါသလား?" + on_collapsed_subform: ဖောင်ပုံစံခွဲတွင် ဖြည့်သွင်းထားပါသလား? option_strings_add_option: ရွေးချယ်စရာ ထည့်ပါ option_strings_source: ရှာဖွေခြင်းများ option_strings_text: ရွေးချယ်စရာများ option_strings_text_display: ရွေးချယ်စရာအတွက် စာသားများ option_strings_text_key: ရွေးချယ်စရာ ခလုပ် - options_indications_lookup_values: " ကြိုတင်ရှာဖွေထားမှုများကို သုံးနိုင်သည် သို့မဟုတ် ထူးခြားသောတန်ဖိုးများကို ဖန်တီးနိုင်သည်။" + options_indications_lookup_values: ' ကြိုတင်ရှာဖွေထားမှုများကို သုံးနိုင်သည် သို့မဟုတ် ထူးခြားသောတန်ဖိုးများကို ဖန်တီးနိုင်သည်။' options_indications_restrictions: သင် နှစ်ခုလုံးလုပ်လို့မရနိုင်ပါ။ options_or_lookup_warning: ကျေးဇူးပြု၍ ရွေးချယ်စရာကိုထည့်သွင်းပါ သို့မဟုတ် ရှာဖွေရန်ကိုရွေးပါ။ နှစ်ခုလုံးကိုမထည့်ပါနှင့် other_documents: အခြားစာရွက်စာတမ်း @@ -1122,7 +1116,7 @@ my: separator: ပိုင်းခြားပေးသည့်အရာ show: ပြမည်လား။ show_on: ပြပါ။ - show_on_minify_form: "အတိုချုပ်ပုံစံ " + show_on_minify_form: 'အတိုချုပ်ပုံစံ ' subform: ဖောင်ပုံစံခွဲ subform_group_by: အုပ်စု အလိုက် subform_remove_message: ဤဖောင်ပုံစံခွကိုသင်ဖယ်ရှားလိုသည်မှာ သေချာပါသလား။ @@ -1227,7 +1221,7 @@ my: show_on: ပြပါ။ subform_need_to_be_added: သူတို့ထပ်ထည့်ဖို့ လိုတယ်။ subform_need_to_be_added_single: ၎င်းကို ထပ်ဖြည့်ဖို့ လိုပါတယ်။ - subform_not_found: "%{subform_name}ကိုမတွေ့ပါ။" + subform_not_found: '%{subform_name}ကိုမတွေ့ပါ။' title: ဖောင်ပုံစံ ခေါင်းစဥ် translations: edit: ဘာသာပြန်ဆိုမှုများကို တည်းဖြတ်ပါ။ @@ -1252,7 +1246,6 @@ my: dashboard: ဒိုင်ခွက်ဘောင် en: အင်္ဂလိပ် es: စပိန်စာ - es-GT: စပိန် (ဂွါတီမာလာ) fr: ပြင်သစ်စာ id: မလေးစာ km: ခမာစာ @@ -1294,7 +1287,6 @@ my: killing: ကလေးသူငယ်များကို သတ်ဖြတ်ခြင်း maiming: ကလေးသူငယ်များကို ကိုယ်လက်အင်္ဂါချို့တဲ့စေခြင်း recruitment: တပ်သားစုဆောင်းခြင်းနှင့်/သို့မဟုတ် ကလေးသူငယ်များအားအသုံးပြုခြင်း။ - sexual_violence: မုဒိမ်းမှု နှင့်/သို့မဟုတ် အခြားသော လိင်ပိုင်းဆိုင်ရာ အကြမ်းဖက်မှု abduction: အဓမ္မသွေးဆောင်ဖြားယောင်းခြင်း attack_on: စာသင်ကျောင်း(များ) နှင့်/သို့မဟုတ် ဆေးရုံ(များ)ကို တိုက်ခိုက်ခြင်း၊ military_use: စာသင်ကျောင်း(များ) နှင့်/သို့မဟုတ် ဆေးရုံ(များ)ကို စစ်ရေးအရ အသုံးပြုခြင်း၊ @@ -1319,11 +1311,10 @@ my: children: ကလေးများ girls: မိန်းကလေးငယ်များ incident_location: ဖြစ်စဉ်ဖြစ်ပွားခဲ့သည့် နေရာ - unaccompanied_separated_status: "ကာကွယ်စောင့်ရှောက်မှုအခြေအနေ:" + unaccompanied_separated_status: 'ကာကွယ်စောင့်ရှောက်မှုအခြေအနေ:' unknown: မသိ verification_status: အတည်ပြုမှုအခြေအနေ violence_type: အကြမ်းဖက်မှုအမျိုးအစား - armed_force_group_name: လက်နက်ကိုင်အဖွဲ့အမည် armed_force_group_type: လက်နက်ကိုင်တပ်ဖွဲ့ အမျိုးအစား register_new_incident: ဖြစ်စဉ်အသစ် selectable_date_options: @@ -1392,15 +1383,11 @@ my: title: "4. အကဲဖြတ်ဆန်းစစ်သုံးသပ်ခြင်း အခြေအနေ" completed: "ဆောင်ရွက်ပြီးစီးပါပြီ။" completed_supervisor_approved: "ဆောင်ရွက်ပြီးစီးပြီး ကြီးကြပ်ရေးမှူးက အတည်ပြုပြီးပါပြီ။" - helptext: | - ဤအညွှန်းကိန်းသည် အကဲဖြတ်မှုပုံစံကို ပြီးမြောက်စေသည့် လက်ရှိဖြစ်ရပ်များ၏ အချိုးအစားကို တွက်ချက်သည်။ - ရှင်သန်ကျန်ရစ်သူ အကဲဖြတ်ဆန်းစစ်သုံးသပ်ခြင်း ပုံစံ အတွင်း မဖြစ်မနေ ဖြည့်ရမည့် fields များပြီးမြောက်ပါက အကဲဖြတ်ခြင်းကို ပြီးမြောက်သည်ဟု ယူဆပါသည်။ + helptext: "ဤအညွှန်းကိန်းသည် အကဲဖြတ်မှုပုံစံကို ပြီးမြောက်စေသည့် လက်ရှိဖြစ်ရပ်များ၏ အချိုးအစားကို တွက်ချက်သည်။ \nရှင်သန်ကျန်ရစ်သူ အကဲဖြတ်ဆန်းစစ်သုံးသပ်ခြင်း ပုံစံ အတွင်း မဖြစ်မနေ ဖြည့်ရမည့် fields များပြီးမြောက်ပါက အကဲဖြတ်ခြင်းကို ပြီးမြောက်သည်ဟု ယူဆပါသည်။\n" completed_case_safety_plans: title: "5.ဆောင်ရွက်ပြီးစီးသည့် ဖြစ်ရပ်လုံခြုံရေးအစီအစဉ်များ " completed: "ဆောင်ရွက်ပြီးစီးသည့် ဖြစ်ရပ်လုံခြုံရေးအစီအစဉ်များ " - helptext: | - ဤအညွှန်းကိန်းသည် ဘေးကင်းရေးအစီအစဥ်ကို လိုအပ်သည်ဟု မှတ်ယူထားကာပြီးမြောက်ခဲ့သည့် လက်ရှိဖြစ်ရပ်များ၏အချိုးအစား (ဥပမာ- ရင်းနှီးဖော်ရွေသော အကြမ်းဖက်မှု၊ သတ်သေခြင်း/လူသတ်မှုအန္တရာယ်၊ ကလေးသူငယ်ကာကွယ်မှု)။ - Safety Plan ဘေးကင်းရေးအစီအစဥ်ဖောင်တွင် မဖြစ်မနေပါရှိရမည့် fields အားလုံး ပြီးပြည့်စုံသောအခါတွင် ဘေးကင်းရေး အစီအစဉ်ကို ပြီးမြောက်သည်ဟု ယူဆပါသည်။ + helptext: "ဤအညွှန်းကိန်းသည် ဘေးကင်းရေးအစီအစဥ်ကို လိုအပ်သည်ဟု မှတ်ယူထားကာပြီးမြောက်ခဲ့သည့် လက်ရှိဖြစ်ရပ်များ၏အချိုးအစား (ဥပမာ- ရင်းနှီးဖော်ရွေသော အကြမ်းဖက်မှု၊ သတ်သေခြင်း/လူသတ်မှုအန္တရာယ်၊ ကလေးသူငယ်ကာကွယ်မှု)။ \nSafety Plan ဘေးကင်းရေးအစီအစဥ်ဖောင်တွင် မဖြစ်မနေပါရှိရမည့် fields အားလုံး ပြီးပြည့်စုံသောအခါတွင် ဘေးကင်းရေး အစီအစဉ်ကို ပြီးမြောက်သည်ဟု ယူဆပါသည်။\n" completed_case_action_plans: title: "6. ဆောင်ရွက်ပြီးစီးသည့် ဖြစ်ရပ်လုပ်ငန်းအစီအစဉ်များ " completed: "ဆောင်ရွက်ပြီးစီးသည့် ဖြစ်ရပ်လုပ်ငန်းအစီအစဉ်" @@ -1420,7 +1407,7 @@ my: female: "အမျိုးသမီး" 0-11: "0-11" 12-17: "12-17" - ">18": ">18 " + '>18': ">18 " disability: "မသန်စွမ်းမှု" no_disability: "မသန်စွမ်းမှု မရှိပါ။" helptext: | @@ -1479,7 +1466,6 @@ my: aria-labels: from: "ဤရက်စွဲပြီးနောက် Data ကို ရွေးချယ်ပါမည်။" to: "ဤရက်စွဲမတိုင်ခင် Data ကို ရွေးချယ်ပါမည်။" - location: base_types: camp: စခန်း @@ -1511,7 +1497,7 @@ my: type: အမျိုးအစား hierarchy: အဆင့် import_title: နေရာဒေသကို ထည့်သွင်းခြင်း - message: "ကျေးဇူးပြု၍ ထည့်သွင်းရန် CSV ဖိုင်ကို ရွေးပါ။ ဤဖိုင်သည် UTF-8 ကုဒ်နံပါတ်ကို အသုံးပြုသင့်ပြီး ကော်လံတစ်ခုစီ၏ ဒုတိယခေါင်းစီးအတန်းတွင် HXL hashtags များ ထည့်သွင်းသင့်သည်။ " + message: 'ကျေးဇူးပြု၍ ထည့်သွင်းရန် CSV ဖိုင်ကို ရွေးပါ။ ဤဖိုင်သည် UTF-8 ကုဒ်နံပါတ်ကို အသုံးပြုသင့်ပြီး ကော်လံတစ်ခုစီ၏ ဒုတိယခေါင်းစီးအတန်းတွင် HXL hashtags များ ထည့်သွင်းသင့်သည်။ ' no_location: အသုံးပြုသူအကောင့်များ မဖန်တီးမီ တည်နေရာများကို ထည့်သွင်းပါ။ enable_title: တည်နေရာကို ဖွင့်ပါ enable_text: သင်သေချာပါသလား။ သင်ရွေးချယ်ထားသော တည်နေရာများကို အသုံးပြုခွင့်ဖွင့်ထားပါက ၎င်းတို့သည် တည်နေရာအကွက်များတွင် ရွေးချယ်စရာများအဖြစ် ပေါ်လာမည်ဖြစ်သည်။ @@ -1527,7 +1513,7 @@ my: assign_to: တာဝန်ပေးသည် attach: ပူးတွဲပါ bulk_assign: အစုလိုက်သတ်မှတ်ပေးသည်။ - bulk_create: "အစုလိုက်ဖန်တီးပါ။ " + bulk_create: 'အစုလိုက်ဖန်တီးပါ။ ' bulk_index: အစုလိုက်အညွှန်း case_plan_approved: ဖြစ်ရပ်အစီအစဥ် အတည်ပြုထားသည် case_plan_rejected: ဖြစ်ရပ်အစီအစဥ် ငြင်းပယ်ထားသည် @@ -1591,7 +1577,7 @@ my: create_subform: ဖောင်ပုံစံခွဲကို စတင်ပြုလုပ်နေသည် destroy: ဖျက်နေသည် edit: ပြင်ဆင်နေသည် - enable_disable_record: "အသုံးပြုနိုင်အောင်ဖွင့်ပါ / အသုံးမပြုနိုင်အောင်ပိတ်ပါ " + enable_disable_record: 'အသုံးပြုနိုင်အောင်ဖွင့်ပါ / အသုံးမပြုနိုင်အောင်ပိတ်ပါ ' export: အချက်အလက်များကို တင်ပို့နေသည် flag: အမှတ်အသားပြုလုပ်ခြင်း flag_records: အမှတ်အသားပြုလုပ်နေသည် @@ -1669,7 +1655,7 @@ my: label: စကားဝှက်အတည်ပြုခြင်း။ password_match: label: စကားဝှက် ကိုက်ညီရပါမည်။ - provider_title: "နှင့်အတူ%{provider}" + provider_title: နှင့်အတူ%{provider} title: စနစ်အတွင်းဝင်ရောက်ခြင်း username: အသုံးပြုသူ၏ အမည် password_reset_modal: စကားဝှက်အား ပြန်လည်သတ်မှတ်ပါ။ @@ -1715,7 +1701,6 @@ my: no_data_table: ဤထိုးထွင်းသိမြင်မှုအတွက် ဇယားအချက်အလက်မရှိပါ။ violations: name: ချိုးဖောက်မှုများ - description: '' filter_options: incident_date: ဖြစ်စဉ် နေ့စွဲ date_of_report: အစီရင်ခံစာ ရက်စွဲ @@ -1724,9 +1709,7 @@ my: killing: ကလေးသူငယ်များကို သတ်ဖြတ်ခြင်း maiming: ကလေးသူငယ်များကို ကိုယ်လက်အင်္ဂါချို့တဲ့စေခြင်း recruitment: တပ်သားစုဆောင်းခြင်းနှင့်/သို့မဟုတ် ကလေးသူငယ်များအားအသုံးပြုခြင်း။ - sexual_violence: မုဒိမ်းမှု နှင့်/သို့မဟုတ် အခြားသော လိင်ပိုင်းဆိုင်ရာ အကြမ်းဖက်မှု abduction: အဓမ္မသွေးဆောင်ဖြားယောင်းခြင်း - attack_on: စာသင်ကျောင်း(များ) နှင့်/သို့မဟုတ် ဆေးရုံ(များ)ကို တိုက်ခိုက်ခြင်း၊ military_use: စာသင်ကျောင်း(များ) နှင့်/သို့မဟုတ် ဆေးရုံ(များ)ကို စစ်ရေးအရ အသုံးပြုခြင်း၊ denial_humanitarian_access: ကလေးသူငယ်များအတွက် လူသားချင်းစာနာထောက်ထားမှု လက်လှမ်းမှီရေးကို ငြင်းပယ်ဟန့်တားခြင်း။ sub_reports: @@ -1742,34 +1725,18 @@ my: total: စုစုပေါင်း gbv_statistics: name: GBV စာရင်းအင်းများ - description: '' filter_options: date_of_first_report: တွေ့ဆုံမေးမြန်းမှု ပြုလုပ်သည့် ရက်စွဲ incident_date: ဖြစ်စဉ် နေ့စွဲ reports: - incidents: ဖြစ်စဉ်များ perpetrators: ကျူးလွန်သူများ - sub_reports: - combined: ဖြစ်စဉ်များ - total: GBV ဖြစ်စဉ်များ အစီရင်ခံထားသော အရေအတွက် - gbv_sexual_violence: အစီရင်ခံထားသော လိင်ပိုင်းဆိုင်ရာ အကြမ်းဖက် ဖြစ်ပွားမှုအရေအတွက် - gbv_previous_incidents: ယခင် GBV ဖြစ်စဉ်များ နှင့်အတူ အသက်ရှင်ကျန်ရစ်သူများမှ အစီရင်ခံထားသော ဖြစ်စဉ်များ အရေအတွက် - gbv_sexual_violence_type: ဖြစ်စဉ် အမျိုးအစား - incident_timeofday: အခင်းဖြစ်ပွားချိန် - elapsed_reporting_time: ဖြစ်စဉ် နှင့် အစီရင်ခံစာ ရက်စွဲကြား အချိန် - elapsed_reporting_time_rape: မုဒိမ်းမှု ဖြစ်စဉ်များ၊ ဖြစ်စဉ် နှင့် အစီရင်ခံစာ ရက်စွဲကြား ကုန်ဆုံးသွားသော အချိန် - incident_location_type: ဖြစ်စဉ်ဖြစ်ပွားခဲ့သည့် နေရာ - number_of_perpetrators: မူလပြစ်မှုကျူးလွန်သူအရေအတွက် - perpetrator_relationship: စွပ်စွဲထားသော မူလပြစ်မှုကျူးလွန်သူ နှင့် အသက်ရှင်ကျန်ရစ်သူတို့၏ ပတ်သက်မှု - perpetrator_age_group: စွပ်စွဲထားသော မူလပြစ်မှုကျူးလွန်သူ၏ အသက်အုပ်စု - perpetrator_occupation: စွပ်စွဲထားသောမူလပြစ်မှုကျူးလွန်သူ၏ အလုပ်အကိုင် messages: - alert_items: "သင့်တွင် %{items}မှတ်သားစရာအချက်များရှိသည်။" + alert_items: သင့်တွင် %{items}မှတ်သားစရာအချက်များရှိသည်။ alerts_for: - approval: "%{form_section_name}အတွက် အတည်ပြုချက်ကို ဆိုင်းငံ့ထားသည်။" + approval: '%{form_section_name}အတွက် အတည်ပြုချက်ကို ဆိုင်းငံ့ထားသည်။' field_change: '%{form_section_name}တွင် အပ်ဒိပ်လုပ်ခဲ့သည်။%{alert_time}' - transfer_request: "လွှဲပြောင်းပေးရန် တောင်းဆိုချက်အသစ်ကို %{date} မှ%{user}တွင်%{agency} ပြုလုပ်ခဲ့သည်။" - duplicate_field: "စနစ်တွင်ရှိသော အခြား ဖြစ်ရပ်တစ်ခု မှာ ဤအရာနှင့် တူညီသော%{field_name} ရှိသည်" + transfer_request: လွှဲပြောင်းပေးရန် တောင်းဆိုချက်အသစ်ကို %{date} မှ%{user}တွင်%{agency} ပြုလုပ်ခဲ့သည်။ + duplicate_field: စနစ်တွင်ရှိသော အခြား ဖြစ်ရပ်တစ်ခု မှာ ဤအရာနှင့် တူညီသော%{field_name} ရှိသည် cannot_edit: ဤအရာကို သင်ပြင်ဆင်လို့ မရနိုင်ပါ။ confirmation_message: OK ကိုနှိပ်ပါက သိမ်းဆည်းထားခြင်းမရှိသော မည်သည့်ပြောင်းလဲမှုကိုမဆို ဖယ်ရှားပြီး စာရင်းမြင်ကွင်းသို့ပြန်သွားပါမည်။ မှတ်တမ်းသို့ပြန်သွားရန် Cancel ကိုနှိပ်ပါ။ confirmation_message_subform: OK ကိုနှိပ်ခြင်းဖြင့် ဤအရာအတွက် မသိမ်းဆည်းရသေးသော ပြောင်းလဲမှုများကို ဖယ်ပစ်ပါမည်။ ပြောင်းလဲမှုများ ဆက်လက်ပြုလုပ်ရန် ပယ်ဖျက်ရန် နှိပ်ပါ။ @@ -1784,7 +1751,7 @@ my: no_changes: သင်သည် field ပြောင်းလဲမှုများ မပြုလုပ်ခဲ့ပါ။ not_available: မရရှိနိုင်ပါ။ record_list: - column_header_tooltip: "%{column}အတွက်စီသည်" + column_header_tooltip: '%{column}အတွက်စီသည်' of: ၏ no_match: ဝမ်းနည်းပါသည်၊ တူညီသောမှတ်တမ်းများမတွေ့ပါ။ rows_per_page: စာမျက်နှာတစ်မျက်နှာရှိ အတန်းများ @@ -1828,11 +1795,11 @@ my: approvals_case_plan_pending: '%{approval_label}ဆိုင်းငံ့ထားသည်။' approvals_closure: '%{approval_label}' approvals_closure_pending: '%{approval_label}ဆိုင်းငံ့ထားသည်။' - approve_action_plan: "%{approval_label}ကိုအတည်ပြုသည်" - approve_assessment: "%{approval_label}ပုံစံကို အတည်ပြုသည်" - approve_case_plan: "%{approval_label}ကို အတည်ပြုသည်" - approve_closure: "%{approval_label}ပုံစံကို အတည်ပြုသည်" - approve_gbv_closure: "%{approval_label}ပုံစံကို အတည်ပြုသည်" + approve_action_plan: '%{approval_label}ကိုအတည်ပြုသည်' + approve_assessment: '%{approval_label}ပုံစံကို အတည်ပြုသည်' + approve_case_plan: '%{approval_label}ကို အတည်ပြုသည်' + approve_closure: '%{approval_label}ပုံစံကို အတည်ပြုသည်' + approve_gbv_closure: '%{approval_label}ပုံစံကို အတည်ပြုသည်' assign: တာဝန်ပေးသည် assign_within_agency: အဖွဲ့အစည်းအတွင်း သတ်မှတ်ခြင်း assign_within_user_group: အသုံးပြုသူအုပ်စုများအတွင်း သတ်မှတ်ခြင်း @@ -1870,7 +1837,7 @@ my: dash_shared_with_me: ကျွန်ုပ်နှင့်အတူ မျှဝေထားသည်။ dash_shared_with_my_team: ကျွန်ုပ်၏အဖွဲ့နှင့်အတူ မျှဝေထားသည်။ dash_shared_with_others: အခြားသူများနှင့်အတူ မျှဝေထားသည်။ - dash_show_none_values: "အကဲဖြတ်လေ့လာခြင်း Dashboard တွင် 'အန္တရာယ်မရှိသည့်အဆင့်' ရှိဖြစ်ရပ်များကိုကြည့်ပါ " + dash_show_none_values: 'အကဲဖြတ်လေ့လာခြင်း Dashboard တွင် ''အန္တရာယ်မရှိသည့်အဆင့်'' ရှိဖြစ်ရပ်များကိုကြည့်ပါ ' dash_tasks: လုပ်ငန်းတာဝန်များကိုကြည့်ပါ dash_transfers_by_socal_worker: လူမှုရေးလုပ်သားက လွှဲပြောင်းမှုကိုကြည့်ပါ dash_national_admin_summary: အမျိုးသားအဆင့် Admin အနှစ်ချုပ်ကို ကြည့်ပါ @@ -1921,11 +1888,11 @@ my: report: အစီရင်ခံစာ managed_report: ထိုးထွင်းသိမြင်ခြင်း request_approval: ခွင့်ပြုချက်တောင်းခံမှု - request_approval_action_plan: "%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း" - request_approval_assessment: "%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း" - request_approval_case_plan: "%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း" - request_approval_closure: "%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း" - request_approval_gbv_closure: "%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း" + request_approval_action_plan: '%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း' + request_approval_assessment: '%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း' + request_approval_case_plan: '%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း' + request_approval_closure: '%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း' + request_approval_gbv_closure: '%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း' request_transfer: လွှဲပြောင်းရန် တောင်းဆိုခြင်း role: အခန်းကဏ္ဍ save_search: ရှာဖွေကြည့်ရှုမှုများကို မှတ်သားထားသည်။ @@ -1974,16 +1941,16 @@ my: explanation: ဖြစ်ရပ်လုပ်သားတစ်ဦးစီတွင် ပျမ်းမျှဖွင့်ထားသော ဖြစ်ရပ်အရေအတွက်ကို ကြည့်ရှုနိုင်မှု။ label: ဖြစ်ရပ်အရေအတွက် kpi_client_satisfaction_rate: - explanation: "အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် ကိစ္စတိုင်းအတွက်၊ စိတ်ကျေနပ်မှု တုံ့ပြန်ချက်စစ်တမ်းကို ရှင်သန်ကျန်ရစ်သူများ အချိုးအစားမည်မျှ ကျေနပ်မှုရှိသည်ကို သိရှိနိုင်မည်ဖြစ်ပါသည်။ " + explanation: 'အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် ကိစ္စတိုင်းအတွက်၊ စိတ်ကျေနပ်မှု တုံ့ပြန်ချက်စစ်တမ်းကို ရှင်သန်ကျန်ရစ်သူများ အချိုးအစားမည်မျှ ကျေနပ်မှုရှိသည်ကို သိရှိနိုင်မည်ဖြစ်ပါသည်။ ' label: လူမှုရေးရာ ဝန်ဆောင်မှုရယူသူ၏ စိတ်ကျေနပ်မှုနှုန်း kpi_completed_case_action_plans: explanation: အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် ပံ့ပိုးမှုပေးဆဲ ဖြစ်ရပ်များအတွက်၊ ပြီးမြောက်သော ဖြစ်ရပ်လုပ်ငန်းအစီအစဉ် အချိုးအစားရှိသည်ကို မြင်နိုင်စေပါသည်။ - label: "ဆောင်ရွက်ပြီးစီးသည့် ဖြစ်ရပ်လုပ်ငန်းအစီအစဉ်များ " + label: 'ဆောင်ရွက်ပြီးစီးသည့် ဖြစ်ရပ်လုပ်ငန်းအစီအစဉ်များ ' kpi_completed_case_safety_plans: explanation: အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် ပံ့ပိုးမှုပေးဆဲ ဖြစ်ရပ်များနှင့် ဘေးကင်းလုံခြုံမှု အစီအစဉ် ပြီးမြောက်ရန် လိုအပ်သည့် ဖြစ်ရပ်အချိုးအစားကို ကြည့်ရှုနိုင်ပါသည်။ label: ဘေးကင်းလုံခြုံရေး ဖြစ်ရပ်အစီအစဉ်ရေးဆွဲမှု ပြီးမြောက်ပါပြီ kpi_completed_supervisor_approved_case_action_plans: - explanation: "အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် ဆောင်ရွက်နေသောကိစ္စရပ်များအတွက် ဖြစ်ရပ်ကြီးကြပ်သူမှ အတည်ပြုထားသည့် ဖြစ်ရပ်လုပ်ငန်းအကောင်အထည်ဖော်မှု အစီအစဉ် မည်မျှပြီးမြောက်နေသည်ကို ကြည့်ရှုနိုင်မည်ဖြစ်သည်။ " + explanation: 'အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် ဆောင်ရွက်နေသောကိစ္စရပ်များအတွက် ဖြစ်ရပ်ကြီးကြပ်သူမှ အတည်ပြုထားသည့် ဖြစ်ရပ်လုပ်ငန်းအကောင်အထည်ဖော်မှု အစီအစဉ် မည်မျှပြီးမြောက်နေသည်ကို ကြည့်ရှုနိုင်မည်ဖြစ်သည်။ ' label: ကြီးကြပ်သူမှ အတည်ပြုထားသော ဆောင်ရွက်ပြီးစီးသည့် ဖြစ်ရပ်လုပ်ငန်းအစီအစဉ်များ kpi_goal_progress_per_need: explanation: အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့်ကိစ္စများအတွက် လိုအပ်ချက်အမျိုးအစားတစ်ခုစီရှိ ရည်မှန်းချက် ပန်းတိုင်များ၏ ရာခိုင်နှုန်းမည်မျှပြည့်မှီသည်ကို မြင်တွေ့နိုင်မည်ဖြစ်သည်။ @@ -2010,7 +1977,7 @@ my: agency: actions: assign: - explanation: "အသုံးပြုသူအကောင့်တစ်ခုဖန်တီးရာတွင် သို့မဟုတ် တည်းဖြတ်သည့်အခါ အေဂျင်စီတစ်ခုအား ရွေးချယ်နိုင်သည်။ လက်ရှိအသုံးပြုသူတွင် ဤခွင့်ပြုချက်အပြင် သုံးစွဲသူများအတွက် \"Agency Read\" ခွင့်ပြုချက်ပါရှိပါက၊ ၎င်းတို့၏အေဂျင်စီအတွက်အသုံးပြုသူတစ်ဦးကိုသာ ထည့်သွင်းနိုင်မည်ဖြစ်သည်။ " + explanation: 'အသုံးပြုသူအကောင့်တစ်ခုဖန်တီးရာတွင် သို့မဟုတ် တည်းဖြတ်သည့်အခါ အေဂျင်စီတစ်ခုအား ရွေးချယ်နိုင်သည်။ လက်ရှိအသုံးပြုသူတွင် ဤခွင့်ပြုချက်အပြင် သုံးစွဲသူများအတွက် "Agency Read" ခွင့်ပြုချက်ပါရှိပါက၊ ၎င်းတို့၏အေဂျင်စီအတွက်အသုံးပြုသူတစ်ဦးကိုသာ ထည့်သွင်းနိုင်မည်ဖြစ်သည်။ ' label: တာဝန်ပေးသည် create: explanation: အေဂျင်စီတစ်ခုဖန်တီးနိုင်မှု @@ -2042,41 +2009,41 @@ my: explanation: အသုံးပြုသူတစ်ဦးအား မှတ်ပုံတင်ခြင်းအသေးစိတ်ပုံစံမှ ဖြစ်ရပ်တစ်ခုသို့ မှတ်ပုံတင်ရန် လင့်ခ်လုပ်ခွင့်ပြုသည်။ အသုံးပြုသူတစ်ဦးအား ဖြစ်ရပ် နှင့်ချိတ်ဆက်ထားပြီးဖြစ်သော မှတ်ပုံတင်ခြင်းကို လင့်ခ်ဖြုတ်ရန်လည်း ခွင့်ပြုပါသည်။ label: ဖြစ်ရပ်မှ မှတ်ပုံတင်မှတ်တမ်းကို ထည့်/မွမ်းမံပါ။ approve_action_plan: - explanation: "မန်နေဂျာတစ်ဦးအား ၎င်း၏ ဖြစ်ရပ်လုပ်သားများ၏ ဖြစ်ရပ်များအတွက် အတည်ပြုရန် %{approval_label}ခွင့်ပြုသည်။" - label: "%{approval_label}အတည်ပြုသည်" + explanation: မန်နေဂျာတစ်ဦးအား ၎င်း၏ ဖြစ်ရပ်လုပ်သားများ၏ ဖြစ်ရပ်များအတွက် အတည်ပြုရန် %{approval_label}ခွင့်ပြုသည်။ + label: '%{approval_label}အတည်ပြုသည်' approve_assessment: - explanation: "မန်နေဂျာတစ်ဦးအား ၎င်း၏ ဖြစ်ရပ်လုပ်သားများ၏ ဖြစ်ရပ်များအတွက် အတည်ပြုရန် %{approval_label}ခွင့်ပြုသည်။" - label: "ဖောင်ပုံစံကို %{approval_label}အတည်ပြုသည်" + explanation: မန်နေဂျာတစ်ဦးအား ၎င်း၏ ဖြစ်ရပ်လုပ်သားများ၏ ဖြစ်ရပ်များအတွက် အတည်ပြုရန် %{approval_label}ခွင့်ပြုသည်။ + label: ဖောင်ပုံစံကို %{approval_label}အတည်ပြုသည် approve_bia: - explanation: "မန်နေဂျာတစ်ဦးအား ၎င်း၏ ဖြစ်ရပ်လုပ်သားများ၏ ဖြစ်ရပ်များအတွက် အတည်ပြုရန် %{approval_label}ခွင့်ပြုသည်။" - label: "ပုံစံကို %{approval_label}အတည်ပြုသည်" + explanation: မန်နေဂျာတစ်ဦးအား ၎င်း၏ ဖြစ်ရပ်လုပ်သားများ၏ ဖြစ်ရပ်များအတွက် အတည်ပြုရန် %{approval_label}ခွင့်ပြုသည်။ + label: ပုံစံကို %{approval_label}အတည်ပြုသည် approve_case_plan: - explanation: "မန်နေဂျာတစ်ဦးအား ၎င်း၏ ဖြစ်ရပ်လုပ်သားများ၏ ဖြစ်ရပ်များအတွက် အတည်ပြုရန် %{approval_label}ခွင့်ပြုသည်။" - label: "အတည်ပြုသည်%{approval_label}" + explanation: မန်နေဂျာတစ်ဦးအား ၎င်း၏ ဖြစ်ရပ်လုပ်သားများ၏ ဖြစ်ရပ်များအတွက် အတည်ပြုရန် %{approval_label}ခွင့်ပြုသည်။ + label: အတည်ပြုသည်%{approval_label} approve_closure: - explanation: "မန်နေဂျာတစ်ဦးအား ၎င်း၏ ဖြစ်ရပ်လုပ်သားများ၏ ဖြစ်ရပ်များအတွက် အတည်ပြုရန် %{approval_label}ခွင့်ပြုသည်။" - label: "ဖောင်%{approval_label}ပုံစံကို အတည်ပြုသည်" + explanation: မန်နေဂျာတစ်ဦးအား ၎င်း၏ ဖြစ်ရပ်လုပ်သားများ၏ ဖြစ်ရပ်များအတွက် အတည်ပြုရန် %{approval_label}ခွင့်ပြုသည်။ + label: ဖောင်%{approval_label}ပုံစံကို အတည်ပြုသည် approve_gbv_closure: - explanation: "မန်နေဂျာတစ်ဦးအား ၎င်း၏ ဖြစ်ရပ်လုပ်သားများ၏ ဖြစ်ရပ်များအတွက် အတည်ပြုရန် %{approval_label}ခွင့်ပြုသည်။" - label: "ဖောင်ပုံစံကို%{approval_label} အတည်ပြုသည်" + explanation: မန်နေဂျာတစ်ဦးအား ၎င်း၏ ဖြစ်ရပ်လုပ်သားများ၏ ဖြစ်ရပ်များအတွက် အတည်ပြုရန် %{approval_label}ခွင့်ပြုသည်။ + label: ဖောင်ပုံစံကို%{approval_label} အတည်ပြုသည် assign: - explanation: "အသုံးပြုသူတစ်ဦးအား ဖြစ်ရပ်မူရင်းမှတ်တမ်းပိုင်ရှင်မှ စနစ်ရှိ အခြားအသုံးပြုသူထံသို့ ဖြစ်ရပ်တစ်ခုပေးပို့ခွင့်ပြုသည်။ ဤလုပ်ဆောင်ချက်အတွက် ကလေး၏ ခွင့်ပြုချက် မလိုအပ်ပါ။ လွှဲပြောင်းမှုများနှင့်မတူဘဲ၊ လက်ခံသူသည် အဆိုပါတာဝန်ကို လက်ခံရန် သို့မဟုတ် ငြင်းပယ်ရန် အခွင့်အရေး မရှိပါ။ " + explanation: 'အသုံးပြုသူတစ်ဦးအား ဖြစ်ရပ်မူရင်းမှတ်တမ်းပိုင်ရှင်မှ စနစ်ရှိ အခြားအသုံးပြုသူထံသို့ ဖြစ်ရပ်တစ်ခုပေးပို့ခွင့်ပြုသည်။ ဤလုပ်ဆောင်ချက်အတွက် ကလေး၏ ခွင့်ပြုချက် မလိုအပ်ပါ။ လွှဲပြောင်းမှုများနှင့်မတူဘဲ၊ လက်ခံသူသည် အဆိုပါတာဝန်ကို လက်ခံရန် သို့မဟုတ် ငြင်းပယ်ရန် အခွင့်အရေး မရှိပါ။ ' label: တာဝန်ပေးသည် assign_within_agency: - explanation: "အသုံးပြုသူတစ်ဦးအား ဖြစ်ရပ်မူရင်းမှတ်တမ်းပိုင်ရှင်မှ လက်ရှိအသုံးပြုသူအဖွဲ့အစည်းများရှိ အခြားအသုံးပြုသူထံသို့ ဖြစ်ရပ်တစ်ခုပေးပို့ခွင့်ပြုသည်။ ဤလုပ်ဆောင်ချက်အတွက် ကလေး၏ ခွင့်ပြုချက် မလိုအပ်ပါ။ လွှဲပြောင်းမှုများနှင့်မတူဘဲ၊ လက်ခံသူသည် အဆိုပါတာဝန်ကို လက်ခံရန် သို့မဟုတ် ငြင်းပယ်ရန် အခွင့်အရေး မရှိပါ။ " + explanation: 'အသုံးပြုသူတစ်ဦးအား ဖြစ်ရပ်မူရင်းမှတ်တမ်းပိုင်ရှင်မှ လက်ရှိအသုံးပြုသူအဖွဲ့အစည်းများရှိ အခြားအသုံးပြုသူထံသို့ ဖြစ်ရပ်တစ်ခုပေးပို့ခွင့်ပြုသည်။ ဤလုပ်ဆောင်ချက်အတွက် ကလေး၏ ခွင့်ပြုချက် မလိုအပ်ပါ။ လွှဲပြောင်းမှုများနှင့်မတူဘဲ၊ လက်ခံသူသည် အဆိုပါတာဝန်ကို လက်ခံရန် သို့မဟုတ် ငြင်းပယ်ရန် အခွင့်အရေး မရှိပါ။ ' label: အသုံးပြုသူကို အဖွဲ့အစည်းအတွင်း သတ်မှတ်တာဝန်ပေးသည်။ assign_within_user_group: - explanation: "အသုံးပြုသူတစ်ဦးအား ဖြစ်ရပ်မူရင်းမှတ်တမ်းပိုင်ရှင်မှ လက်ရှိအသုံးပြုသူအုပ်စုများရှိ အခြားအသုံးပြုသူထံသို့ ဖြစ်ရပ်တစ်ခုပေးပို့ခွင့်ပြုသည်။ ဤလုပ်ဆောင်ချက်အတွက် ကလေး၏ ခွင့်ပြုချက် မလိုအပ်ပါ။ လွှဲပြောင်းမှုများနှင့်မတူဘဲ၊ လက်ခံသူသည် အဆိုပါတာဝန်ကို လက်ခံရန် သို့မဟုတ် ငြင်းပယ်ရန် အခွင့်အရေး မရှိပါ။ " + explanation: 'အသုံးပြုသူတစ်ဦးအား ဖြစ်ရပ်မူရင်းမှတ်တမ်းပိုင်ရှင်မှ လက်ရှိအသုံးပြုသူအုပ်စုများရှိ အခြားအသုံးပြုသူထံသို့ ဖြစ်ရပ်တစ်ခုပေးပို့ခွင့်ပြုသည်။ ဤလုပ်ဆောင်ချက်အတွက် ကလေး၏ ခွင့်ပြုချက် မလိုအပ်ပါ။ လွှဲပြောင်းမှုများနှင့်မတူဘဲ၊ လက်ခံသူသည် အဆိုပါတာဝန်ကို လက်ခံရန် သို့မဟုတ် ငြင်းပယ်ရန် အခွင့်အရေး မရှိပါ။ ' label: အသုံးပြုသူကို အဖွဲ့အစည်းအတွင်း သတ်မှတ်တာဝန်ပေးသည်။ change_log: - explanation: "အသုံးပြုသူသည် ၎င်းကို စတင်ဖန်တီးစဉ်ကတည်းက မှတ်တမ်းတွင် ပြုလုပ်ထားသည့် ပြောင်းလဲမှုအားလုံး၏ ကြည့်ရှုနိုင်သည်။ အကွက်အားလုံးအတွက် မှတ်တမ်းတင်ထားသော အချက်များပါဝင်သည်။ " + explanation: 'အသုံးပြုသူသည် ၎င်းကို စတင်ဖန်တီးစဉ်ကတည်းက မှတ်တမ်းတွင် ပြုလုပ်ထားသည့် ပြောင်းလဲမှုအားလုံး၏ ကြည့်ရှုနိုင်သည်။ အကွက်အားလုံးအတွက် မှတ်တမ်းတင်ထားသော အချက်များပါဝင်သည်။ ' label: အမှတ်တံဆိပ် လိုဂိုအား ပြောင်းလဲမည်။ close: explanation: အသုံးပြုသူတစ်ဦးအား ဖွင့်ထားသောဖြစ်ရပ်အား ပိတ်သိမ်းခြင်းအခြေအနေသို့ ပြောင်းလဲ သတ်မှတ်ခွင့်ပြုသည်။ label: စာရင်းပိတ် consent_override: explanation: သဘောတူညီချက်မရရှိသည့်ဖြစ်ရပ်အတွက် ညွှန်းပို့လွှဲအပ်မှု သို့မဟုတ် လွှဲပြောင်းမှုပြုလုပ်ရန် အသုံးပြုသူကို ခွင့်ပြုသည်။ - label: "ညွှန်းပိုခြင်း သို့မဟုတ် လွှဲပြောင်းသည့်အခါ သဘောတူညီချက်မရှိခြင်းကို အစားထိုးပါ။ " + label: 'ညွှန်းပိုခြင်း သို့မဟုတ် လွှဲပြောင်းသည့်အခါ သဘောတူညီချက်မရှိခြင်းကို အစားထိုးပါ။ ' create: explanation: ဖြစ်ရပ်တစ်ခု စတင်ပြုလုပ်နိုင်မှု label: စတင်ပြုလုပ်သည် @@ -2085,7 +2052,7 @@ my: label: စာမျက်နှာကို ကြည့်ရှုပါ။ enable_disable_record: explanation: ဖြစ်ရပ်တစ်ခုကို ပိတ်ရန် သို့မဟုတ် ဖွင့်ရန် စွမ်းရည်။ "ပိတ်ထားသည်" ဖြစ်ရပ်များသည် ဖြစ်ရပ်စာရင်းတွင် မူရင်းအတိုင်း မပေါ်ပါ။ အသုံးပြုသူများသည် စစ်ထုတ်မှုတစ်ခုအသုံးပြုခြင်းဖြင့် ဖြစ်ရပ်စာရင်းတွင် အသုံးပြု၍မရအောင်ပိတ်ထားသောဖြစ်ရပ်များကို ကြည့်ရှုနိုင်သည်။ Primero သည် အသုံးပြုသူများအား ဖြစ်ရပ်များကို ဖျက်ရန် ခွင့်မပြုသောကြောင့်၊ အသုံးပြုသူတစ်ဦးသည် ဖြစ်ရပ်ကို အစားထိုးအဖြစ် ပိတ်ရန် ဆန္ဒရှိနိုင်သည်။ ဥပမာအားဖြင့်၊ အသုံးပြုသူတစ်ဦးသည် ဖြစ်ရပ်တစ်ခုကို မှားယွင်းစွာဖန်တီးခဲ့လျှင် သို့မဟုတ် ဖြစ်ရပ်တွင် အချက်အလက် အရည်အသွေးညံ့နေပါက၊ အသုံးပြုသူသည် ၎င်းကို အသုံးပြု၍မရအောင်ပိတ်သင့်သည်။ - label: "အသုံးပြုနိုင်အောင်ဖွင့်ပါ / အသုံးမပြုနိုင်အောင်ပိတ်ပါ " + label: 'အသုံးပြုနိုင်အောင်ဖွင့်ပါ / အသုံးမပြုနိုင်အောင်ပိတ်ပါ ' export_case_pdf: explanation: အသုံးပြုသူသည် စာရင်း သို့မဟုတ် ဖြစ်ရပ်စာရင်း သို့မဟုတ် ဖြစ်ရပ်ဖော်ပြစာမျက်နှာများမှ PDF ဖိုင်ကို ထုတ်လွှတ်နိုင်သည်၊ ၎င်းသည် လက်ရှိအသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် fields အားလုံး၊ တစ်ခု၊ အများအပြား သို့မဟုတ် အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် ဖြစ်ရပ်အားလုံးတွင် ပါဝင်ပါသည်။ PDF ထုတ်ယူခြင်းဖိုင်တွင် အချက်အလက်များကို ဖြစ်ရပ်တစ်ခုချင်းစီကို ဦးစွာဖော်ပြထားပြီး အချက်အလက်များပေါ်လာသည့်ပုံစံဖြင့် ထပ်မံဖွဲ့စည်းထားသည်။ label: pdf ကိုexport သတင်းအချက်အလက်ထုတ်ယူခြင်းလုပ်ပါ @@ -2093,7 +2060,7 @@ my: explanation: 'အသုံးပြုသူသည် ဖြစ်ရပ်စာရင်း သို့မဟုတ် ဖြစ်ရပ်ဖော်ပြစာမျက်နှာများမှ CSV ဖိုင်ကို ထုတ်လွှတ်နိုင်သည်၊ ၎င်းသည် လက်ရှိအသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် fields အားလုံး၊ တစ်ခု၊ အများအပြား သို့မဟုတ် အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် ဖြစ်ရပ်အားလုံးတွင် ပါဝင်ပါသည်။ မှတ်ချက်- CSV ထုတ်ယူမှုသည် လက်တင်မဟုတ်သော အက္ခရာများ (ဥပမာ အာရဗီ၊ ဘင်္ဂလာ) ကို ဖတ်နိုင်သော format ဖြင့် မဖော်ပြပါ။ ' label: CSV ကို ထုတ်ယူပါ။ export_custom: - explanation: "အသုံးပြုသူသည် ဖြစ်ရပ်စာရင်း သို့မဟုတ် ဖြစ်ရပ် ဖြစ်ပွားမှုပြသသည့် စာမျက်နှာများမှ XLS ဖိုင်ကို ထုတ်လွှတ်နိုင်သည်၊ ၎င်းတွင် အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် စိတ်ကြိုက်ဖောင်ပုံစံများ သို့မဟုတ် field များ၊တစ်ခု၊ မျိုးစုံ သို့မဟုတ် ဖြစ်ရပ်အားလုံး ပါရှိပါသည်။၊ ဤထုတ်ယူမှုတွင်၊ ဖောင်တစ်ခုစီကို XLS ဖိုင်အတွင်း ၎င်း၏ကိုယ်ပိုင်တက်ဘ်တွင် ကိုယ်စားပြုထားသည်။ Custom Export modal ကို အသုံးပြု၍ ထုတ်ယူမှုတွင် ထည့်သွင်းလိုသော ဖောင် သို့မဟုတ် အကွက်များကို အသုံးပြုသူက ရွေးချယ်နိုင်သည်။ အသုံးပြုသူများသည် အပလီကေးရှင်းရှိ ဖြစ်ရပ်ကိုကြည့်ရှုသည့်အခါ အဆိုပါပုံစံများနှင့် အကွက်များကို မြင်နိုင်စွမ်းရှိပြီးသားဖြစ်မှသာ ထုတ်ယူမှုတွင် ဖောင်နှင့်အကွက်များ ထည့်သွင်းနိုင်သည်ကို သတိပြုပါ။ " + explanation: 'အသုံးပြုသူသည် ဖြစ်ရပ်စာရင်း သို့မဟုတ် ဖြစ်ရပ် ဖြစ်ပွားမှုပြသသည့် စာမျက်နှာများမှ XLS ဖိုင်ကို ထုတ်လွှတ်နိုင်သည်၊ ၎င်းတွင် အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် စိတ်ကြိုက်ဖောင်ပုံစံများ သို့မဟုတ် field များ၊တစ်ခု၊ မျိုးစုံ သို့မဟုတ် ဖြစ်ရပ်အားလုံး ပါရှိပါသည်။၊ ဤထုတ်ယူမှုတွင်၊ ဖောင်တစ်ခုစီကို XLS ဖိုင်အတွင်း ၎င်း၏ကိုယ်ပိုင်တက်ဘ်တွင် ကိုယ်စားပြုထားသည်။ Custom Export modal ကို အသုံးပြု၍ ထုတ်ယူမှုတွင် ထည့်သွင်းလိုသော ဖောင် သို့မဟုတ် အကွက်များကို အသုံးပြုသူက ရွေးချယ်နိုင်သည်။ အသုံးပြုသူများသည် အပလီကေးရှင်းရှိ ဖြစ်ရပ်ကိုကြည့်ရှုသည့်အခါ အဆိုပါပုံစံများနှင့် အကွက်များကို မြင်နိုင်စွမ်းရှိပြီးသားဖြစ်မှသာ ထုတ်ယူမှုတွင် ဖောင်နှင့်အကွက်များ ထည့်သွင်းနိုင်သည်ကို သတိပြုပါ။ ' label: custom export စိတ်ကြိုက်ရွေးချယ်ထားသောသတင်းအချက်အလက်ထုတ်ယူခြင်းလုပ်ပါ export_duplicate_id_csv: explanation: တူညီသောနိုင်ငံသားစီစစ်ရေးfield ပါရှိသော ဖြစ်ရပ်များ၏ CSV export ကို ဖန်တီးပါ (configuration အပေါ်မူတည်၍ မတူညီသော အညွှန်းတစ်ခုရှိနိုင်သည်)။ ဖြစ်ရပ်စာရင်းစာမျက်နှာမှသာလျှင် လုပ်ဆောင်ခဲ့သည်။ @@ -2119,16 +2086,16 @@ my: explanation: Family Tracing နှင့် ပြန်လည်ပေါင်းစည်းရေး လုပ်ဆောင်ချက်တို့ပါရှိသည့် အကြောင်းအရာများအတွက် သီးသန့်အသုံးပြုသည်။ ဤခွင့်ပြုချက်ဖြင့် အသုံးပြုသူများသည် ဖြစ်ရပ်ဖော်ပြ စာမျက်နှာရှိ "ခြေရာခံကိုက်ညီမှုကို ရှာဖွေရန်" ခလုတ်ကို တွေ့ရပါမည်။ ၎င်းကို နှိပ်လိုက်သောအခါ၊ ၎င်းတို့သည် ၎င်းတို့၏ ဖြစ်ရပ်အတွက် ဖြစ်နိုင်ချေရှိသော ကိုက်ညီမှုရှိသော စနစ်ရှိ ခြေရာခံတောင်းဆိုမှုစာရင်းကို ရောက်ရှိမည်ဖြစ်သည်။ label: ဖြစ်ရပ်မှ ကိုက်ညီသည့် ခြေရာခံမှု ရှာဖွေပါ flag: - explanation: " ဖြစ်ရပ်တစ်ခုအတွက်တွင် သတိပေးမှုထည့်သွင်းနိုင်သည်။ ဤခွင့်ပြုချက်ရှိသော အသုံးပြုသူများသည် ကိစ္စတစ်ခုတွင် ၎င်းတို့ထည့်သွင်းထားသော သတိပေးချက်များကို ဖယ်ရှားနိုင်သည်။ " + explanation: ' ဖြစ်ရပ်တစ်ခုအတွက်တွင် သတိပေးမှုထည့်သွင်းနိုင်သည်။ ဤခွင့်ပြုချက်ရှိသော အသုံးပြုသူများသည် ကိစ္စတစ်ခုတွင် ၎င်းတို့ထည့်သွင်းထားသော သတိပေးချက်များကို ဖယ်ရှားနိုင်သည်။ ' label: အမှတ်အသားပြုခြင်း import: explanation: အသုံးပြုသူကို CSV၊ Excel သို့မဟုတ် JSON ဖိုင်မှ import သွင်းခြင်းဖြင့် တစ်ခု သို့မဟုတ် တစ်ခုထက်ပိုသော ဖြစ်ရပ်အသစ်များကို ဖန်တီးခွင့်ပြုသည်။ အချက်အလက်များကို မှန်ကန်စွာ တင်သွင်းနိုင်ရန် အတွက် တင်သွင်းထားသော ဖိုင်ကို *very* အထူးပြုလုပ်ထားသည့် format ဖြင့်လုပ်ရပါမည်။ အဆင့်မြင့်နည်းပညာဆိုင်ရာ ကျွမ်းကျင်မှုများနှင့် Primero တွင် ဒေတာကို ဖော်မတ်ချထားပုံနှင့်ပတ်သက်သော နက်နက်နဲနဲ သိရှိသော စီမံခန့်ခွဲရေးအသုံးပြုသူများအတွက်သာ ဤလုပ်ဆောင်ချက်ကို ရရှိသင့်ပါသည်။ ဖြစ်ရပ်စာရင်းစာမျက်နှာမှသာလျှင် လုပ်ဆောင်ခဲ့သည်။ label: တင်သွင်းခြင်း incident_details_from_case: - explanation: "ရှာဖွေမှုရလဒ်များတွင် သင်တွေ့ရှိထားသော ဖြစ်ရပ်တစ်ခုရှိ Incident Details ပုံစံခွဲအတွက် ထည့်သွင်းနိုင်သော်လည်း သင်ဝင်ရောက်ခွင့်မရှိပါ။ အသုံးပြုသူသည် ဖြစ်ရပ်တစ်ခု သို့မဟုတ် တစ်ခုထက်ပိုသော ဖြစ်ရပ်များကို ရွေးချယ်ခြင်းဖြင့် ရှာဖွေမှုရလဒ်စာမျက်နှာမှ လုပ်ဆောင်ချက်ကို လုပ်ဆောင်ပြီး ၎င်း၏မီနူးမှ \"ဖြစ်ရပ်ကို ထည့်ပါ\" ကို ရွေးချယ်ရပါမည်။ ထို့နောက် အသုံးပြုသူသည် ဝန်ဆောင်မှုတစ်ခုနှင့်ပတ်သက်သော အချက်အလက်များကို ထည့်သွင်းနိုင်ပြီး တင်သွင်းနိုင်သည့် Incident Details အမျိုးအစားခွဲတွင် ကွက်လပ်အားလုံးပါရှိသော ပုံစံတစ်ခုကို တွေ့ပါမည်။ ဤပြုလုပ်မှုသည် ရှာဖွေမှုရလဒ်စာမျက်နှာတွင်သာ လုပ်ဆောင်နိုင်သောကြောင့် \"အခြားအသုံးပြုသူများပိုင်ဆိုင်သည့် ဖြစ်ရပ်မှတ်တမ်းများကို ရှာဖွေရန်\" ခွင့်ပြုချက်ရရှိပြီးဖြစ်သင့်သည်။ " + explanation: 'ရှာဖွေမှုရလဒ်များတွင် သင်တွေ့ရှိထားသော ဖြစ်ရပ်တစ်ခုရှိ Incident Details ပုံစံခွဲအတွက် ထည့်သွင်းနိုင်သော်လည်း သင်ဝင်ရောက်ခွင့်မရှိပါ။ အသုံးပြုသူသည် ဖြစ်ရပ်တစ်ခု သို့မဟုတ် တစ်ခုထက်ပိုသော ဖြစ်ရပ်များကို ရွေးချယ်ခြင်းဖြင့် ရှာဖွေမှုရလဒ်စာမျက်နှာမှ လုပ်ဆောင်ချက်ကို လုပ်ဆောင်ပြီး ၎င်း၏မီနူးမှ "ဖြစ်ရပ်ကို ထည့်ပါ" ကို ရွေးချယ်ရပါမည်။ ထို့နောက် အသုံးပြုသူသည် ဝန်ဆောင်မှုတစ်ခုနှင့်ပတ်သက်သော အချက်အလက်များကို ထည့်သွင်းနိုင်ပြီး တင်သွင်းနိုင်သည့် Incident Details အမျိုးအစားခွဲတွင် ကွက်လပ်အားလုံးပါရှိသော ပုံစံတစ်ခုကို တွေ့ပါမည်။ ဤပြုလုပ်မှုသည် ရှာဖွေမှုရလဒ်စာမျက်နှာတွင်သာ လုပ်ဆောင်နိုင်သောကြောင့် "အခြားအသုံးပြုသူများပိုင်ဆိုင်သည့် ဖြစ်ရပ်မှတ်တမ်းများကို ရှာဖွေရန်" ခွင့်ပြုချက်ရရှိပြီးဖြစ်သင့်သည်။ ' label: ရှာဖွေမှုရလဒ်များစာမျက်နှာမှ အခြားအသုံးပြုသူ၏ဖြစ်ရပ်တွင် ဖြစ်စဉ်အသေးစိတ်အချက်အလက်များကို ထည့်ပါ။ incident_from_case: - explanation: "ဤခွင့်ပြုချက်သည် သုံးစွဲသူအား \"ဖြစ်ရပ်ဖန်တီးရန်\" ခလုတ်ကို နှိပ်ရန် ခွင့်ပြုသည်။ ၎င်းတွင် ဖြစ်ရပ်မှကူးယူထားသော အချက်အလက်အချို့ပါ၀င်သည့် အဖြစ်အပျက်တစ်ခု ပါဝင်သည်။ GBV ကျား/မရေးရာ အခြေပြု မတော်မတရားပြုမူမှု ဖြစ်ရပ်များအတွက် ခလုတ်သည် ပြခန်းစာမျက်နှာ၏ထိပ်တွင်ရှိပြီး ဖြစ်ရပ်တစ်ခုလုံးနှင့်ပတ်သက်သည့် အချက်အလက်များနှင့် သက်ဆိုင်ပါသည်။ အချို့သော အဖြစ်အပျက်ကို ခြေရာခံသည့် အခြေအနေများတွင်၊ ဤခလုတ်သည် \"ဖြစ်ရပ်အသေးစိတ်များ\" ပုံစံခွဲပေါ်တွင် ရှိနေသည်။ ဤအခြေအနေတွင်၊ ခလုတ်ကိုနှိပ်လိုက်သည့် အဖြစ်အပျက်အသေးစိတ်ပုံစံခွဲမှ အချက်အလက်အချို့ကို ဖြစ်ရပ်တစ်ခုလုံးမှ ကူးယူနိုင်ပါသည်။ ဉပမာ။ ။ အဖြစ်အပျက်အသစ်တွင် တစ်ဦးချင်းဖြစ်ရပ်အသေးစိတ်ပုံစံခွဲမှ \"အကြမ်းဖက်မှုအမျိုးအစား\" အကွက်ပါဝင်ပြီး ဖြစ်ရပ်၏အသက်နှင့် လိင်အမျိုးအစားလည်း ပါဝင်ပါသည်။ မှတ်ချက်။ ။ အသုံးပြုသူအား ဖန်တီးခဲ့သည့်လင့်ခ်တွင် အဖြစ်အပျက် ကြည့်ရှုနိုင်စေပါသည်။ " + explanation: 'ဤခွင့်ပြုချက်သည် သုံးစွဲသူအား "ဖြစ်ရပ်ဖန်တီးရန်" ခလုတ်ကို နှိပ်ရန် ခွင့်ပြုသည်။ ၎င်းတွင် ဖြစ်ရပ်မှကူးယူထားသော အချက်အလက်အချို့ပါ၀င်သည့် အဖြစ်အပျက်တစ်ခု ပါဝင်သည်။ GBV ကျား/မရေးရာ အခြေပြု မတော်မတရားပြုမူမှု ဖြစ်ရပ်များအတွက် ခလုတ်သည် ပြခန်းစာမျက်နှာ၏ထိပ်တွင်ရှိပြီး ဖြစ်ရပ်တစ်ခုလုံးနှင့်ပတ်သက်သည့် အချက်အလက်များနှင့် သက်ဆိုင်ပါသည်။ အချို့သော အဖြစ်အပျက်ကို ခြေရာခံသည့် အခြေအနေများတွင်၊ ဤခလုတ်သည် "ဖြစ်ရပ်အသေးစိတ်များ" ပုံစံခွဲပေါ်တွင် ရှိနေသည်။ ဤအခြေအနေတွင်၊ ခလုတ်ကိုနှိပ်လိုက်သည့် အဖြစ်အပျက်အသေးစိတ်ပုံစံခွဲမှ အချက်အလက်အချို့ကို ဖြစ်ရပ်တစ်ခုလုံးမှ ကူးယူနိုင်ပါသည်။ ဉပမာ။ ။ အဖြစ်အပျက်အသစ်တွင် တစ်ဦးချင်းဖြစ်ရပ်အသေးစိတ်ပုံစံခွဲမှ "အကြမ်းဖက်မှုအမျိုးအစား" အကွက်ပါဝင်ပြီး ဖြစ်ရပ်၏အသက်နှင့် လိင်အမျိုးအစားလည်း ပါဝင်ပါသည်။ မှတ်ချက်။ ။ အသုံးပြုသူအား ဖန်တီးခဲ့သည့်လင့်ခ်တွင် အဖြစ်အပျက် ကြည့်ရှုနိုင်စေပါသည်။ ' label: ဖြစ်ရပ်တစ်ခုမှ ဖြစ်စဉ်တစ်ခုကို စတင်ပြုလုပ်ပါ manage: explanation: အသုံးပြုသူတစ်ဦးအား ဖြစ်ရပ်များတွင် ရရှိနိုင်သော လုပ်ဆောင်ချက်များအားလုံးကို လုပ်ဆောင်ရန် ခွင့်ပြုသည်။ "စီမံခန့်ခွဲခြင်း" ခွင့်ပြုချက်သည် အခြေခံအားဖြင့် "ရရှိနိုင်သော လုပ်ဆောင်ချက်များအားလုံ" ကို ဆိုလိုသည်။ @@ -2152,31 +2119,31 @@ my: explanation: ဝန်ဆောင်မှုဖောင်ပုံစံခွဲတွင် အသုံးပြုသူကို "လွှဲအပ်" ခလုတ်ကို ကြည့်ရှုခွင့်ပြုသည်။ အသုံးပြုသူသည် ဤခလုတ်ကို နှိပ်သောအခါ၊ ဝန်ဆောင်မှုအမျိုးအစား၊ အေဂျင်စီ၊ ဝန်ဆောင်မှုပေးသူနှင့် တည်နေရာအကွက်များကို ပိတ်ထားခြင်းဖြင့် လွှဲပြောင်းမှုပုံစံပေါ်လာမည်ဖြစ်ပြီး၊ သို့သော် သုံးစွဲသူက လွှဲအပ်သည့်ခလုတ်ကိုနှိပ်ပြီးသည့်အခါ ဝန်ဆောင်မှုပုံစံခွဲအတွင်းရှိ အဆိုပါကွက်လပ်များအတွက် အချက်အလက်များကို အလိုအလျောက်ဖြည့်ပေးမည်ဖြစ်သည်။ label: ဝန်ဆောင်မှုဖောင်ပုံစံခွဲမှ လွှဲပြောင်းညွန်းပို့သည့်ဖြစ်ရပ် remove_assigned_users: - explanation: "အသုံးပြုသူကို \"အခြားသတ်မှတ်ထားသော အသုံးပြုသူများ\" အကွက်မှ အခြားအသုံးပြုသူများကို ဖယ်ရှားရန် ခွင့်ပြုသည်။ အသုံးပြုသူတစ်ဦးသည် ဖြစ်ရပ်အတွက် လွှဲပြောင်းမှုကို လက်ခံရရှိပါက သို့မဟုတ် ဖြစ်ရပ်အတွက် လွှဲပြောင်းမှုတစ်ခု လက်ခံရရှိသော်လည်း လက်ခံခြင်း သို့မဟုတ် ငြင်းပယ်ခြင်းမရှိသေးပါက ဤနေရာတွင် စာရင်းသွင်းထားပါသည်။ \"အခြားသတ်မှတ်ပေးထားသည့်အသုံးပြုသူများ\" အကွက်မှ သုံးစွဲသူတစ်ဦးကို ဖယ်ရှားသည့်အခါ၊ ၎င်းတို့၏အသုံးပြုခွင့်ကို ဖယ်ရှားမည်ဖြစ်သည်။ ထို့ကြောင့် ခွင့်ပြုချက်ရှိသော အသုံးပြုသူများသည် ယခင်က လွှဲပြောင်းပေးမှုများကို လက်ခံရရှိထားသူများ သို့မဟုတ် ဖြစ်ရပ်အတွက် ဆိုင်းငံ့ထားဆဲ လွှဲပြောင်းမှုများကို လက်ခံရရှိထားသည့် အသုံးပြုသူများထံမှ ဖြစ်ရပ်ကို ဖယ်ရှားနိုင်သည်။ လက်ရှိအသုံးပြုသူသည် ဖြစ်ရပ်ကို တည်းဖြတ်နိုင်စွမ်းရှိမှသာ ဤခွင့်ပြုချက်သည် အလုပ်လုပ်ကြောင်း သတိပြုပါ။ " + explanation: 'အသုံးပြုသူကို "အခြားသတ်မှတ်ထားသော အသုံးပြုသူများ" အကွက်မှ အခြားအသုံးပြုသူများကို ဖယ်ရှားရန် ခွင့်ပြုသည်။ အသုံးပြုသူတစ်ဦးသည် ဖြစ်ရပ်အတွက် လွှဲပြောင်းမှုကို လက်ခံရရှိပါက သို့မဟုတ် ဖြစ်ရပ်အတွက် လွှဲပြောင်းမှုတစ်ခု လက်ခံရရှိသော်လည်း လက်ခံခြင်း သို့မဟုတ် ငြင်းပယ်ခြင်းမရှိသေးပါက ဤနေရာတွင် စာရင်းသွင်းထားပါသည်။ "အခြားသတ်မှတ်ပေးထားသည့်အသုံးပြုသူများ" အကွက်မှ သုံးစွဲသူတစ်ဦးကို ဖယ်ရှားသည့်အခါ၊ ၎င်းတို့၏အသုံးပြုခွင့်ကို ဖယ်ရှားမည်ဖြစ်သည်။ ထို့ကြောင့် ခွင့်ပြုချက်ရှိသော အသုံးပြုသူများသည် ယခင်က လွှဲပြောင်းပေးမှုများကို လက်ခံရရှိထားသူများ သို့မဟုတ် ဖြစ်ရပ်အတွက် ဆိုင်းငံ့ထားဆဲ လွှဲပြောင်းမှုများကို လက်ခံရရှိထားသည့် အသုံးပြုသူများထံမှ ဖြစ်ရပ်ကို ဖယ်ရှားနိုင်သည်။ လက်ရှိအသုံးပြုသူသည် ဖြစ်ရပ်ကို တည်းဖြတ်နိုင်စွမ်းရှိမှသာ ဤခွင့်ပြုချက်သည် အလုပ်လုပ်ကြောင်း သတိပြုပါ။ ' label: အခြားသတ်မှတ်ပေးထားသည့်အသုံးပြုသူများကို ဖယ်ရှားပါ (ရည်ညွှန်းထားသော အသုံးပြုသူများထံမှ ဖြစ်ရပ်အသုံးပြုခွင့်ကို ပြန်လည်ရယူခြင်း) reopen: explanation: အသုံးပြုသူတစ်ဦးအား လက်ရှိပိတ်ထားသည့် ဖြစ်ရပ်ကို ဖွင့်လှစ် ခွင့်ပြုသည်။ label: ပြန်လည်ဖွင့်လှစ်သည် request_approval_action_plan: - explanation: "အသုံးပြုသူတစ်ဦး (များသောအားဖြင့် ဖြစ်ရပ်လုပ်သားတစ်ဦး) အား ၎င်းတို့၏မန်နေဂျာမှ ၎င်းတို့၏ ဖြစ်ရပ်များ%{approval_label}ကို အတည်ပြုရန် တောင်းဆိုခွင့်ပြုသည်။" - label: "%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း" + explanation: အသုံးပြုသူတစ်ဦး (များသောအားဖြင့် ဖြစ်ရပ်လုပ်သားတစ်ဦး) အား ၎င်းတို့၏မန်နေဂျာမှ ၎င်းတို့၏ ဖြစ်ရပ်များ%{approval_label}ကို အတည်ပြုရန် တောင်းဆိုခွင့်ပြုသည်။ + label: '%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း' request_approval_assessment: - explanation: "အသုံးပြုသူတစ်ဦး (များသောအားဖြင့် ဖြစ်ရပ်လုပ်သားတစ်ဦး) အား ၎င်းတို့၏မန်နေဂျာမှ ၎င်းတို့၏ ဖြစ်ရပ်များ%{approval_label}ကို အတည်ပြုရန် တောင်းဆိုခွင့်ပြုသည်။" - label: "%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း" + explanation: အသုံးပြုသူတစ်ဦး (များသောအားဖြင့် ဖြစ်ရပ်လုပ်သားတစ်ဦး) အား ၎င်းတို့၏မန်နေဂျာမှ ၎င်းတို့၏ ဖြစ်ရပ်များ%{approval_label}ကို အတည်ပြုရန် တောင်းဆိုခွင့်ပြုသည်။ + label: '%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း' request_approval_bia: - explanation: "အသုံးပြုသူတစ်ဦး (များသောအားဖြင့် ဖြစ်ရပ်လုပ်သားတစ်ဦး) အား ၎င်းတို့၏မန်နေဂျာမှ ၎င်းတို့၏ ဖြစ်ရပ်များ%{approval_label}ကို အတည်ပြုရန် တောင်းဆိုခွင့်ပြုသည်။" - label: "%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း" + explanation: အသုံးပြုသူတစ်ဦး (များသောအားဖြင့် ဖြစ်ရပ်လုပ်သားတစ်ဦး) အား ၎င်းတို့၏မန်နေဂျာမှ ၎င်းတို့၏ ဖြစ်ရပ်များ%{approval_label}ကို အတည်ပြုရန် တောင်းဆိုခွင့်ပြုသည်။ + label: '%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း' request_approval_case_plan: - explanation: "အသုံးပြုသူတစ်ဦး (များသောအားဖြင့် ဖြစ်ရပ်လုပ်သားတစ်ဦး) အား ၎င်းတို့၏မန်နေဂျာမှ ၎င်းတို့၏ ဖြစ်ရပ်များ%{approval_label}ကို အတည်ပြုရန် တောင်းဆိုခွင့်ပြုသည်။" - label: "%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း" + explanation: အသုံးပြုသူတစ်ဦး (များသောအားဖြင့် ဖြစ်ရပ်လုပ်သားတစ်ဦး) အား ၎င်းတို့၏မန်နေဂျာမှ ၎င်းတို့၏ ဖြစ်ရပ်များ%{approval_label}ကို အတည်ပြုရန် တောင်းဆိုခွင့်ပြုသည်။ + label: '%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း' request_approval_closure: - explanation: "အသုံးပြုသူတစ်ဦး (များသောအားဖြင့် ဖြစ်ရပ်လုပ်သားတစ်ဦး) အား ၎င်းတို့၏မန်နေဂျာမှ ၎င်းတို့၏ ဖြစ်ရပ်များ%{approval_label}ကို အတည်ပြုရန် တောင်းဆိုခွင့်ပြုသည်။" - label: "%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း" + explanation: အသုံးပြုသူတစ်ဦး (များသောအားဖြင့် ဖြစ်ရပ်လုပ်သားတစ်ဦး) အား ၎င်းတို့၏မန်နေဂျာမှ ၎င်းတို့၏ ဖြစ်ရပ်များ%{approval_label}ကို အတည်ပြုရန် တောင်းဆိုခွင့်ပြုသည်။ + label: '%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း' request_approval_gbv_closure: - explanation: "အသုံးပြုသူတစ်ဦး (များသောအားဖြင့် ဖြစ်ရပ်လုပ်သားတစ်ဦး) အား ၎င်းတို့၏မန်နေဂျာမှ ၎င်းတို့၏ ဖြစ်ရပ်များ%{approval_label}ကို အတည်ပြုရန် တောင်းဆိုခွင့်ပြုသည်။" - label: "%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း" + explanation: အသုံးပြုသူတစ်ဦး (များသောအားဖြင့် ဖြစ်ရပ်လုပ်သားတစ်ဦး) အား ၎င်းတို့၏မန်နေဂျာမှ ၎င်းတို့၏ ဖြစ်ရပ်များ%{approval_label}ကို အတည်ပြုရန် တောင်းဆိုခွင့်ပြုသည်။ + label: '%{approval_label}အတည်ပြုချက်ကိုတောင်းခံခြင်း' request_transfer: - explanation: "\"View Modal\" တွင် \"Request Transfer\" ခလုတ်ကိုရှာဖွေပါ ။ ခလုတ်သည် သုံးစွဲသူအား ဖြစ်ရပ်၏ လက်ရှိမှတ်တမ်းပိုင်ရှင်ထံ အီးမေးလ်မှတစ်ဆင့် ပုဂ္ဂိုလ်ရေးသီးသန့်မှတ်စုဖြင့် မက်ဆေ့ချ်ပေးပို့ပါမည်၊ မှတ်တမ်းပိုင်ရှင်မှ တောင်းဆိုချက်ကို ပေးပို့သည့်အသုံးပြုသူထံ လွှဲပြောင်းပေးရန် တောင်းဆိုခွင့်ပြုသည်။ ဤအရာသည် ကလေးများ မကြာခဏ အရပ်ဒေသပြောင်းသည့် အခြေအနေမျိုးတွင် အသုံးဝင်ပြီး မိတ္တူပွားမှုမှတ်တမ်းကို ရှောင်ရှားရန်အတွက် ကလေးနှင့်ပတ်သက်သော အချက်အလက်များကို ပေးပို့ရန် ဖြစ်ရပ်လုပ်ငန်းဆောင်ရွက်သူ တစ်ဦးမှ အခြားတစ်ဉီးသို့ ပေးပို့ရာတွင် ထပ်နေမှုကို ရှောင်ရှားနိုင် ပါသည်။ " + explanation: '"View Modal" တွင် "Request Transfer" ခလုတ်ကိုရှာဖွေပါ ။ ခလုတ်သည် သုံးစွဲသူအား ဖြစ်ရပ်၏ လက်ရှိမှတ်တမ်းပိုင်ရှင်ထံ အီးမေးလ်မှတစ်ဆင့် ပုဂ္ဂိုလ်ရေးသီးသန့်မှတ်စုဖြင့် မက်ဆေ့ချ်ပေးပို့ပါမည်၊ မှတ်တမ်းပိုင်ရှင်မှ တောင်းဆိုချက်ကို ပေးပို့သည့်အသုံးပြုသူထံ လွှဲပြောင်းပေးရန် တောင်းဆိုခွင့်ပြုသည်။ ဤအရာသည် ကလေးများ မကြာခဏ အရပ်ဒေသပြောင်းသည့် အခြေအနေမျိုးတွင် အသုံးဝင်ပြီး မိတ္တူပွားမှုမှတ်တမ်းကို ရှောင်ရှားရန်အတွက် ကလေးနှင့်ပတ်သက်သော အချက်အလက်များကို ပေးပို့ရန် ဖြစ်ရပ်လုပ်ငန်းဆောင်ရွက်သူ တစ်ဦးမှ အခြားတစ်ဉီးသို့ ပေးပို့ရာတွင် ထပ်နေမှုကို ရှောင်ရှားနိုင် ပါသည်။ ' label: လွှဲပြောင်းရန် တောင်းဆိုခြင်း search_owned_by_others: explanation: အသုံးပြုသူတစ်ဦးအား အများအားဖြင့် ဝင်ရောက်ကြည့်ရှုခွင့်မရှိသည့် မှတ်တမ်းများကို ရှာဖွေခွင့်ပြုသည်၊ ၎င်းတို့သည် ထိုဖြစ်ရပ်၏ မှတ်တမ်းပိုင်ရှင်မဟုတ်သောကြောင့် သို့မဟုတ် (မန်နေဂျာများအတွက်) ၊မှတ်တမ်းပိုင်ရှင်သည် ၎င်းတို့၏အသုံးပြုသူအုပ်စုများတွင် မရှိသောကြောင့် သော်လည်းကောင်းဖြစ်သည်။ အသုံးပြုသူသည် ရှာဖွေမှုရလဒ်များတွင် ဖြစ်ရပ်ကိုမြင်ရသော်လည်း ထိုဖြစ်ရပ်အတွက် case show page သို့ ကလစ်နှိပ်၍မရပါ၊ ဆိုလိုသည်မှာ ဖြစ်ရပ်နှင့်ပတ်သက်သည့်အသေးစိတ်အချက်အလက်များကို ၎င်းတို့မြင်နိုင်မည်မဟုတ်ကြောင်း သတိပြုပါ။ @@ -2194,7 +2161,7 @@ my: explanation: အသုံးပြုသူကို အော့ဖ်လိုင်းအသုံးပြုမှုအတွက် ဖြစ်ရပ်များကို ၀ှက်ထားရန် ခွင့်ပြုသည်။ label: အော့ဖ်လိုင်းအတွက် အမှတ်အသားပြုလုပ်ပါ။ transfer: - explanation: "အသုံးပြုသူတစ်ဦးအား လက်ရှိဖြစ်ရပ်မှတ်တမ်းပိုင်ရှင်မှ ညွှန်းပို့မှုများကို လက်ခံနိုင်သည့်စနစ်ဖြင့် ဖြစ်ရပ်ကို ပေးပို့ခွင့်ပြုသည်။ သို့ရာတွင် ညွှန်းပို့လက်ခံသူမှ \"လက်ခံသည်\" တိုင်အောင် ဖြစ်ရပ်၏မှတ်တမ်းပိုင်ရှင်သည် မပြောင်းလဲပါ။ လက်ခံသူက ညွှန်းပို့မှုကို \"ပယ်ချ\" ပါက ဖြစ်ရပ်သို့ ဝင်ရောက်ခွင့်ဆုံးရှုံးသွားမည်ဖြစ်ပြီး မူရင်းမှတ်တမ်းပိုင်ရှင်သာ ဝင်ရောက်ခွင့်ရှိမည်ဖြစ်ပါသည်။ " + explanation: 'အသုံးပြုသူတစ်ဦးအား လက်ရှိဖြစ်ရပ်မှတ်တမ်းပိုင်ရှင်မှ ညွှန်းပို့မှုများကို လက်ခံနိုင်သည့်စနစ်ဖြင့် ဖြစ်ရပ်ကို ပေးပို့ခွင့်ပြုသည်။ သို့ရာတွင် ညွှန်းပို့လက်ခံသူမှ "လက်ခံသည်" တိုင်အောင် ဖြစ်ရပ်၏မှတ်တမ်းပိုင်ရှင်သည် မပြောင်းလဲပါ။ လက်ခံသူက ညွှန်းပို့မှုကို "ပယ်ချ" ပါက ဖြစ်ရပ်သို့ ဝင်ရောက်ခွင့်ဆုံးရှုံးသွားမည်ဖြစ်ပြီး မူရင်းမှတ်တမ်းပိုင်ရှင်သာ ဝင်ရောက်ခွင့်ရှိမည်ဖြစ်ပါသည်။ ' label: လွှဲပြောင်း view_photo: explanation: အသုံးပြုသူတစ်ဦးအား case list view မှ case ၏ ဓာတ်ပုံများကို ကြည့်ရှုခွင့်ပြုသည်။ ဤခွင့်ပြုချက်မရှိဘဲ၊ အသုံးပြုသူသည် ဖြစ်ရပ်စာရင်းဇယား၏ "ဓာတ်ပုံ" ကော်လံ သို့မဟုတ် ထိုနေရာတွင် ပေါ်လာသည့် ဓာတ်ပုံအိုင်ကွန်များကို မမြင်ရပါ။ ဤခွင့်ပြုချက်သည် သုံးစွဲသူအား "View Modal" တွင် ကလေး၏ဓာတ်ပုံများကို မြင်နိုင်စေပါသည်။ @@ -2209,7 +2176,7 @@ my: explanation: အသုံးပြုသူတစ်ဦးအား ဖြစ်ရပ်တစ်ခုနှင့် ချိတ်ဆက်ထားသော မှတ်ပုံတင်ခြင်း၏ အချက်အလက်များကို ကြည့်ရှုခွင့်ပြုသည်။ ဖြစ်ရပ် ရှိ မှတ်ပုံတင်ခြင်းအသေးစိတ်ပုံစံကို အသုံးပြုသူအား ကြည့်ရှုနိုင်စေပါသည်။ label: ဖြစ်ရပ်မှ မှတ်ပုံတင်မှတ်တမ်းကို ကြည့်ပါ။ write: - explanation: " ဖြစ်ရပ်အတွက် အချက်အလက်ကို အပ်ဒိတ်လုပ်ရန်နှင့် \"သိမ်းဆည်းရန်\" အတွက်\"တည်းဖြတ်ရန်\" ခလုတ်ကို နှိပ်ပါ။" + explanation: ' ဖြစ်ရပ်အတွက် အချက်အလက်ကို အပ်ဒိတ်လုပ်ရန်နှင့် "သိမ်းဆည်းရန်" အတွက်"တည်းဖြတ်ရန်" ခလုတ်ကို နှိပ်ပါ။' label: ပြင်ဆင်သည် accept_or_reject_transfer: explanation: သင့်အဖွဲ့တွင်ရှိသော အခြားအသုံးပြုသူတစ်ဦးကိုယ်စား လွှဲပြောင်းမှုကို လက်ခံရန် သို့မဟုတ် ငြင်းပယ်ရန် သုံးစွဲသူအား ခွင့်ပြုပါ (ဥပမာ၊ ကြီးကြပ်သူတစ်ဦးသည် ၎င်းတို့၏ လူမှုရေလုပ်သားထံ ပေးပို့ထားသည့် လွှဲပြောင်းမှုကို လက်ခံခြင်း)။ @@ -2226,34 +2193,34 @@ my: actions: approvals_action_plan: explanation: ဆိုင်းငံ့ထားသော၊ အတည်ပြုထားသော သို့မဟုတ် ငြင်းပယ်ခံရသည့် လုပ်ဆောင်ချက်အစီအစဉ် အတည်ပြုချက်တောင်းဆိုမှုများဖြင့် လက်ရှိအသုံးပြုသူ၏ ဖြစ်ရပ်အရေအတွက်ကို ပြသည်။ - label: "ဖြစ်ရပ်လုပ်သား %{approval_label}အတည်ပြုချက်များ" + label: ဖြစ်ရပ်လုပ်သား %{approval_label}အတည်ပြုချက်များ approvals_action_plan_pending: explanation: ဆိုင်းငံ့ထားသော လုပ်ငန်းစီအစဥ်အတည်ပြုချက်တောင်းဆိုချက်များပါရှိသော မန်နေဂျာ၏အဖွဲ့ရှိ ဖြစ်ရပ်အရေအတွက်ကို ပြသည်။ - label: "မန်နေဂျာ %{approval_label}အတည်ပြုချက်များ" + label: မန်နေဂျာ %{approval_label}အတည်ပြုချက်များ approvals_assessment: explanation: လက်ရှိအသုံးပြုသူ၏ ဆိုင်းငံ့ထားသော၊ အတည်ပြုထားသော သို့မဟုတ် ငြင်းပယ်ခံရသည့် အကဲဖြတ်ဆန်းစစ်မှုဆိုင်ရာ အတည်ပြုချက်တောင်းခံခြင်းများ၏ ဖြစ်ရပ်အရေအတွက်ကို ပြသည်။ - label: "ဖြစ်ရပ်လုပ်သား %{approval_label}အတည်ပြုချက်များ" + label: ဖြစ်ရပ်လုပ်သား %{approval_label}အတည်ပြုချက်များ approvals_assessment_pending: explanation: မန်နေဂျာအဖွဲ့ရှိ ဆိုင်းငံ့ထားသော အကဲဖြတ်ဆန်းစစ်မှုဆိုင်ရာ အတည်ပြုချက်တောင်းခံခြင်းများ၏ ဖြစ်ရပ်အရေအတွက်ကို ပြသည်။ - label: "မန်နေဂျာ %{approval_label}အတည်ပြုချက်များ" + label: မန်နေဂျာ %{approval_label}အတည်ပြုချက်များ approvals_case_plan: explanation: လက်ရှိအသုံးပြုသူ၏ ဆိုင်းငံ့ထားသော၊ အတည်ပြုထားသော သို့မဟုတ် ငြင်းပယ်ခံရသည့် ဖြစ်ရပ်အစီအစဥ်ဆိုင်ရာ အတည်ပြုချက်တောင်းခံခြင်းများ၏ ဖြစ်ရပ်အရေအတွက်ကို ပြသည်။ - label: "ဖြစ်ရပ်လုပ်သား %{approval_label}အတည်ပြုချက်များ" + label: ဖြစ်ရပ်လုပ်သား %{approval_label}အတည်ပြုချက်များ approvals_case_plan_pending: explanation: မန်နေဂျာအဖွဲ့ရှိ ဆိုင်းငံ့ထားသော ဖြစ်ရပ်အစီအစဥ်ဆိုင်ရာ အတည်ပြုချက်တောင်းခံခြင်းများ၏ ဖြစ်ရပ်အရေအတွက်ကို ပြသည်။ - label: "မန်နေဂျာ %{approval_label}အတည်ပြုချက်များ" + label: မန်နေဂျာ %{approval_label}အတည်ပြုချက်များ approvals_closure: explanation: လက်ရှိအသုံးပြုသူ၏ ဆိုင်းငံ့ထားသော၊ အတည်ပြုထားသော သို့မဟုတ် ငြင်းပယ်ခံရသည့် ဖြစ်ရပ်ပိတ်သိမ်းခြင်းဆိုင်ရာ အတည်ပြုချက်တောင်းခံခြင်းများ၏ ဖြစ်ရပ်အရေအတွက်ကို ပြသည်။ - label: "ဖြစ်ရပ်လုပ်သား %{approval_label}အတည်ပြုချက်များ" + label: ဖြစ်ရပ်လုပ်သား %{approval_label}အတည်ပြုချက်များ approvals_closure_pending: explanation: မန်နေဂျာအဖွဲ့ရှိ ဆိုင်းငံ့ထားသော ဖြစ်ရပ်ပိတ်သိမ်းခြင်းဆိုင်ရာ အတည်ပြုချက်တောင်းခံခြင်းများ၏ ဖြစ်ရပ်အရေအတွက်ကို ပြသည်။ - label: "မန်နေဂျာ %{approval_label}အတည်ပြုချက်များ" + label: မန်နေဂျာ %{approval_label}အတည်ပြုချက်များ approvals_gbv_closure: explanation: ဆိုင်းငံ့ထားသော၊ အတည်ပြုထားသော သို့မဟုတ် ငြင်းပယ်ခံရသည့် GBV ပိတ်သိမ်းခြင်းဆိုင်ရာ အတည်ပြုချက်တောင်းဆိုမှုများဖြင့် လက်ရှိအသုံးပြုသူ၏ ဖြစ်ရပ်အရေအတွက်ကို ပြသည်။ - label: "ဖြစ်ရပ်လုပ်သား %{approval_label}အတည်ပြုချက်များ" + label: ဖြစ်ရပ်လုပ်သား %{approval_label}အတည်ပြုချက်များ approvals_gbv_closure_pending: explanation: ဆိုင်းငံ့ထားသော GBV ပိတ်သိမ်းခြင်း အတည်ပြုချက် တောင်းဆိုချက်များပါရှိသော မန်နေဂျာ၏အဖွဲ့ရှိ ဖြစ်ရပ်အရေအတွက်ကို ပြသည်။ - label: "မန်နေဂျာ %{approval_label}အတည်ပြုချက်များ" + label: မန်နေဂျာ %{approval_label}အတည်ပြုချက်များ case_overview: explanation: စုစုပေါင်းနှင့် ဖြစ်ရပ်အသစ်များကဲ့သို့ ကိန်းဂဏန်းများ ပါဝင်သည့် ပင်မစာမျက်နှာထိပ်ရှိ Dashboard ခြုံငုံသုံးသပ်ချက်ကဒ် label: Dashboard ခြုံငုံသုံးသပ်ချက် @@ -2262,18 +2229,17 @@ my: label: အန္တရာယ်အဆင့်အလိုက် ဖြစ်ရပ်များ cases_by_task_overdue_assessment: explanation: ၎င်းတို့၏ ဖြစ်ရပ်လုပ်သားတစ်ဦးစီအတွက် ရက်လွန်အကဲဖြတ်လေ့လာဆန်းစစ်ခြင်းလုပ်ငန်း မည်မျှရှိသည်ကို မန်နေဂျာတစ်ဦးအား ကြည့်ရှုခွင့်ပြုပါ။ - label: "ဆန်းစစ်သုံးသပ်ခြင်းပြုလုပ်ရန် ရက်ကျော်လွန်နေပြီ ဖြစ်သည်။ " + label: 'ဆန်းစစ်သုံးသပ်ခြင်းပြုလုပ်ရန် ရက်ကျော်လွန်နေပြီ ဖြစ်သည်။ ' cases_by_task_overdue_case_plan: explanation: ၎င်းတို့၏ ဖြစ်ရပ်လုပ်သားတစ်ဦးစီအတွက် ရက်လွန် ဖြစ်ရပ် အစီအစဥ် မည်မျှရှိသည်ကို မန်နေဂျာတစ်ဦးအား ကြည့်ရှုခွင့်ပြုပါ။ - label: "ဖြစ်ရပ်အစီအစဉ်ရေးဆွဲရန် ရက်ကျော်လွန်နေပြီ ဖြစ်သည်။ " + label: 'ဖြစ်ရပ်အစီအစဉ်ရေးဆွဲရန် ရက်ကျော်လွန်နေပြီ ဖြစ်သည်။ ' cases_by_task_overdue_followups: explanation: ၎င်းတို့၏ ဖြစ်ရပ်လုပ်သားတစ်ဦးစီအတွက် ရက်လွန် နောက်ဆက်တွဲလုပ်ငန်းမည်မျှရှိသည်ကို မန်နေဂျာတစ်ဦးအား ကြည့်ရှုခွင့်ပြုပါ။ - label: "နောက်ဆက်တွဲလေ့လာခြင်းပြုလုပ်ရန် ရက်ကျော်လွန်နေပြီ ဖြစ်သည်။ " + label: 'နောက်ဆက်တွဲလေ့လာခြင်းပြုလုပ်ရန် ရက်ကျော်လွန်နေပြီ ဖြစ်သည်။ ' cases_by_task_overdue_services: explanation: ၎င်းတို့၏ ဖြစ်ရပ်လုပ်သားတစ်ဦးစီအတွက် ရက်လွန် ဝန်ဆောင်မှုပေးခြင်း လုပ်ငန်းမည်မျှရှိသည်ကို မန်နေဂျာတစ်ဦးအား ကြည့်ရှုခွင့်ပြုပါ။ - label: "ပံ့ပိုးကူညီမှုပေးရန်ရက်ကျော်လွန်နေပြီ ဖြစ်သည်။ " + label: 'ပံ့ပိုးကူညီမှုပေးရန်ရက်ကျော်လွန်နေပြီ ဖြစ်သည်။ ' dash_case_incident_overview: - explanation: . label: ခြုံငုံသုံးသပ်ချက် - ကျွနုပ်၏ ဖြစ်ရပ်များ / ဖြစ်စဥ်များ dash_cases_by_social_worker: explanation: လက်ရှိအသုံးပြုသူ၏အသုံးပြုသူအုပ်စုများရှိ သုံးစွဲသူတစ်ဦးစီမှ စီမံခန့်ခွဲသည့် ဖွင့်လှစ်ထားသော စုစုပေါင်း ဖြစ်ရပ်အရေအတွက်နှင့် ဖြစ်ရပ်အသစ်အရေအတွက်ကို ပြသသည့်ဇယား။ အတန်းတစ်ခုစီသည် လက်ရှိအသုံးပြုသူ၏အသုံးပြုသူအုပ်စုများရှိ သုံးစွဲသူဖြစ်ပြီး "Total" နှင့် "New" သည် ကော်လံနှစ်ခုဖြစ်သည်။ @@ -2288,7 +2254,7 @@ my: explanation: ၎င်းတို့၏အဖွဲ့ရှိ သုံးစွဲသူများက စီမံခန့်ခွဲသည့် ဖွင့်လှစ်ဆဲနှင့် ပိတ်သိမ်းပြီးဖြစ်ရပ်အရေအတွက်ကို မန်နေဂျာတစ်ဦးကို ပြသည်။ label: ကျွန်ုပ်အုပ်စု၏ ဖြစ်ရပ်များ dash_matching_results: - explanation: "ကန့်ကွက်ထားသည်။ ။ဤဒက်ရှ်ဘုတ်သည် အလုပ်မလုပ်တော့သည့်အတွက် v2 တွင် ဖယ်ရှားပါမည်။ " + explanation: 'ကန့်ကွက်ထားသည်။ ။ဤဒက်ရှ်ဘုတ်သည် အလုပ်မလုပ်တော့သည့်အတွက် v2 တွင် ဖယ်ရှားပါမည်။ ' label: ကိုက်ညီသောရလဒ်များကိုကြည့်ပါ dash_protection_concerns: explanation: ဇယားတွင် ကာကွယ်စောင့်ရှောက်ရေးဆိုင်ရာစိုးရိမ်ပူပန်မှုတစ်ခုစီတွင် ဖြစ်ရပ် မည်မျှရှိသည်ကိုပြသသည်။ ဇယား၏အတန်းတစ်ခုစီသည် ကာကွယ်စောင့်ရှောက်ရေးဆိုင်ရာစိုးရိမ်ပူပန်မှုတစ်ခုဖြစ်ပြီး၊ ကော်လံများသည်ဖြစ်ရပ်များအတွက် မတူညီသောအခြေအနေများကိုဖော်ပြနေသည် ("ဖြစ်ရပ်အားလုံး" "အဖွင့်ဖြစ်ရပ်များ" "အသစ် (ယခုအပတ်)" "ပိတ်သိမ်းပြီး (ယခုအပတ်)") @@ -2324,7 +2290,7 @@ my: label: လုပ်ငန်းတာဝန်စာမျက်နှာ dash_national_admin_summary: explanation: စနစ်ရှိ စုစုပေါင်းဖွင့်ထားသော ဖြစ်ရပ်များ၊ ပြီးခဲ့သောနှစ်ပတ်စီတွင် အသစ်ဖွင့်ထားသော ဖြစ်ရပ်အရေအတွက်နှင့် ပြီးခဲ့သောနှစ်ပတ်စီတွင် ပိတ်ထားသော ဖြစ်ရပ်အရေအတွက်တို့ကို ပြသသည်။ - label: "Administrator အနှစ်ချုပ် " + label: 'Administrator အနှစ်ချုပ် ' view_response: explanation: တုံ့ပြန်မှုအမျိုးအစားတစ်ခုစီအတွက်၊ ဝန်ဆောင်မှု ပြီးမြောက်ရန်သတ်မှတ်ရက်နီးနီး သို့မဟုတ် ရက်လွန်နေသည့် အန္တရာယ်အဆင့်တစ်ခုစီရှိ ဝန်ဆောင်မှုများ မည်မျှရှိသည်ကို ပြသသည်။ label: တုန့်ပြန်မှုများကို ကြည့်ရန် @@ -2355,7 +2321,7 @@ my: label: ဖောင်ပုံစံများ - ဖြစ်စဉ် tracing_request: explanation: 'ဖြစ်ရပ်၏ သတင်းအချက်အလက် ဖြည့်သွင်းထားသည့်ဖောင်များကို အသုံးပြုသူမှ ကြည့်ရှုလိုသည့် အချက်အလက်များကိုသာ လက်လှမ်းမှီနိုင်စေရန်ကန့်သပ်ထားသည်။ ထိုအစား အသုံးပြုသူသည် Record Owner ဖောင်ကိုသာ ဝင်ခွင့်ရပါက၊ ထိုဖောင်ပေါ်ရှိ အကွက်များတွင်ပါရှိသော အချက်အလက်များကိုသာ တွေ့မြင်နိုင်မည်ဖြစ်သည်။ လက်ရှိအသုံးပြုသူ၏ ဖောင်ပုံစံဖွဲ့စည်းပုံ စီမံခန့်ခွဲနိုင်စွမ်းကို ကန့်သတ်ထားရှိပါသည်။ ဖောင်အသုံးပြုခွင့်ကို ကန့်သတ်ခြင်းဖြင့် ၎င်းတို့၏ configure လုပ်နိုင်သော ဖောင်များကို ကန့်သတ်ထားသည်။ မှတ်ချက်- ဖောင်များကို မသတ်မှတ်ထားပါက ခြေရာခံခြင်းတောင်းဆိုမှုများအတွက် ဖောင်များအားလုံးသို့ ဝင်ရောက်ခွင့်ရှိသည်ဟု ဆိုလိုသည်။' - label: "ဖောင်ပုံစံများ - ခြေရာခံတောင်းဆိုမှု " + label: 'ဖောင်ပုံစံများ - ခြေရာခံတောင်းဆိုမှု ' registry_record: explanation: 'အသုံးပြုသူတစ်ဦး၏ မှတ်ပုံတင်ထားသော ဖောင်များတွင် ဝင်ရောက်ခွင့်ကို ကန့်သတ်ခြင်းအားဖြင့် မှတ်ပုံတင်တစ်ခုအတွက် သိမြင်နိုင်သည့်အချက်အလက်များကို ကန့်သတ်ထားသည်။ ဥပမာအားဖြင့်၊ အသုံးပြုသူသည် Record Owner ဖောင်ကို ဝင်ခွင့်ရပါက၊ ထိုဖောင်ပေါ်ရှိ အကွက်များတွင်ပါရှိသော အချက်အလက်များကိုသာ တွေ့မြင်နိုင်မည်ဖြစ်သည်။ လက်ရှိအသုံးပြုသူ၏ ဖောင်ပုံစံဖွဲ့စည်းပုံ စီမံခန့်ခွဲနိုင်စွမ်းကို ကန့်သတ်ထားရှိပါသည်။ ဖောင်အသုံးပြုခွင့်ကို ကန့်သတ်ခြင်းဖြင့် ၎င်းတို့၏ configure လုပ်နိုင်သော ဖောင်များကို ကန့်သတ်ထားသည်။ မှတ်ချက်။ ။ ဖောင်များကို ကန့်သပ်ထားခြင်းမရှိပါက၊ မှတ်ပုံတင်ခြင်းများအတွက် ဖောင်အားလုံးသို့ ဝင်ရောက်ခွင့်ရှိသည်ဟု ဆိုလိုသည်။' label: ဖောင်ပုံစံများ - မှတ်ပုံတင် @@ -2371,10 +2337,10 @@ my: explanation: အခန်းကဏ္ဍသည် သူတို့ကိုယ်တိုင် ပိုင်သည့် မည်သည့်အသုံးပြုသူအုပ်စုကိုမဆို စနစ်အတွင်းရှိ မှတ်တမ်းများ၊ အသုံးပြုသူများနှင့် အသုံးပြုသူအုပ်စုများအားလုံးကို ဝင်ရောက်ကြည့်ရှုနိုင်ပါသည်။ label: မှတ်တမ်းအားလုံး သို့မဟုတ် အသုံးပြုသူအားလုံးကိုဝင်ရောက်ခွင့်ပြုခြင်း group: - explanation: " အသုံးပြုသူများသည် ၎င်းတို့၏ အသုံးပြုသူများ အုပ်စုတွင် စီမံခန့်ခွဲထားသည့် မှတ်တမ်းများကို ဝင်ရောက်ကြည့်ရှုနိုင်သည်။၎င်းတို့၏ အသုံးပြုသူများ အုပ်စုအတွင်းရှိ မှတ်တမ်းများကို သာဝင်ရောက်ကြည့်ရှုနိုင်မည်ဖြစ်သည်။ " + explanation: ' အသုံးပြုသူများသည် ၎င်းတို့၏ အသုံးပြုသူများ အုပ်စုတွင် စီမံခန့်ခွဲထားသည့် မှတ်တမ်းများကို ဝင်ရောက်ကြည့်ရှုနိုင်သည်။၎င်းတို့၏ အသုံးပြုသူများ အုပ်စုအတွင်းရှိ မှတ်တမ်းများကို သာဝင်ရောက်ကြည့်ရှုနိုင်မည်ဖြစ်သည်။ ' label: မှတ်တမ်းများအားလုံး သို့မဟုတ် ကျွုန်ပ်အဖွဲ့ရှိ အသုံးပြုသူများအားလုံးကို ဝင်ရောက်ခွင့်ပြုခြင်း self: - explanation: "ဒီအခန်းကဏ္ဍသည် ၎င်းတို့၏ကိုယ်ပိုင်မှတ်တမ်းများ (ဖြစ်ရပ်များ၊ ခြေရာခံတောင်းဆိုမှုများ သို့မဟုတ် ဖြစ်စဉ်များ) ကို ဝင်ရောက်ကြည့်ရှုနိုင်ပြီး ၎င်းတို့၏ကိုယ်ပိုင် အသုံးပြုသူအကောင့်ကို ပြင်ဆင်နိုင်သည်။ " + explanation: 'ဒီအခန်းကဏ္ဍသည် ၎င်းတို့၏ကိုယ်ပိုင်မှတ်တမ်းများ (ဖြစ်ရပ်များ၊ ခြေရာခံတောင်းဆိုမှုများ သို့မဟုတ် ဖြစ်စဉ်များ) ကို ဝင်ရောက်ကြည့်ရှုနိုင်ပြီး ၎င်းတို့၏ကိုယ်ပိုင် အသုံးပြုသူအကောင့်ကို ပြင်ဆင်နိုင်သည်။ ' label: ကျွန်ုပ်၏မှတ်တမ်းများ သို့မဟုတ် အသုံးပြုသူကိုသာ ဝင်ရောက်ခွင့်ပြုခြင်း explanation: အခန်းကဏ္ဍသည် ဝင်ရောက်နိုင်သည့် မှတ်တမ်းများ(ဖြစ်ရပ်များ၊ ခြေရာခံတောင်းဆိုမှုများ၊ သို့မဟုတ် ဖြစ်စဉ်များ) ကို ထိန်းချုပ်သည်။ အကယ်၍ ဒီအခန်းကဏ္ဍသည် အသုံးပြုသူများနှင့် အသုံးပြုသူအုပ်စုများသို့ ဝင်ရောက်ခွင့်ရှိပါက၊ ၎င်းသည် ၎င်းတို့ဝင်ရောက်နိုင်သည့် အသုံးပြုသူများနှင့် အသုံးပြုသူအုပ်စုများကိုလည်း ထိန်းချုပ်ပါသည်။ "No Records" သို့ဝင်ရောက်ခွင့်ရှိသည့် အခန်းကဏ္ဍများသည် ဖောင်များ၊ အသုံးပြုသူများနှင့် အစီရင်ခံစာများကဲ့သို့ စနစ်ဖွဲ့စည်းပုံများကိုသာ ဝင်ရောက်ကြည့်ရှုနိုင်ပါသည်။ label: ဤအခန်းကဏ္ဍက မည်သည့်မှတ်တမ်းများအပေါ် သက်ရောက်မှုရှိပါသလဲ။ @@ -2388,7 +2354,7 @@ my: label: စတင်ပြုလုပ်သည် enable_disable_record: explanation: ဖြစ်စဉ်တစ်ခုကို ပိတ်နိုင်ရန် သို့မဟုတ်ဖွင့်နိုင်ရန် ။ "ပိတ်ထားသည်" ဖြစ်စဉ်များသည် ဖြစ်စဉ်စာရင်းတွင် ပုံသေအားဖြင့် မပေါ်ပါ။ အသုံးပြုသူများသည် စစ်ထုတ်မှုတစ်ခုကို အသုံးပြုခြင်းဖြင့် ဖြစ်စဉ်စာရင်းတွင် ပိတ်ထားရသော ဖြစ်စဉ်များကို ကြည့်ရှုနိုင်သည်။ - label: "အသုံးပြုနိုင်အောင်ဖွင့်ပါ / အသုံးမပြုနိုင်အောင်ပိတ်ပါ " + label: 'အသုံးပြုနိုင်အောင်ဖွင့်ပါ / အသုံးမပြုနိုင်အောင်ပိတ်ပါ ' export_case_pdf: explanation: အသုံးပြုသူသည် ဖြစ်စဉ်များစာရင်း သို့မဟုတ် ဖြစ်စဉ်ပြသသည့်စာမျက်နှာများမှ PDF ဖိုင်ကို export သတင်းအချက်အလက်ထုတ်ယူခြင်း လုပ်နိုင်ပြီး၊ ၎င်းသည် လက်ရှိအသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် field အားလုံးပါဝင်သည့်၊ ဖြစ်စဉ်တစ်ခု၊ အများအပြား သို့မဟုတ် အားလုံးအတွက် ပါဝင်ပါသည်။PDF export သတင်းအချက်အလက်ထုတ်ယူခြင်း ဖိုင်တွင် အချက်အလက်များကို ဖြစ်ရပ်တစ်ခုချင်းအလိုက် ဦးစွာဖော်ပြထားပြီး အချက်အလက်များပေါ်လာသည့်ပုံစံဖြင့် ထပ်မံဖွဲ့စည်းထားသည်။ label: pdf အနေဖြင့် export သတင်းအချက်အလက်ထုတ်ယူခြင်း လုပ်ပါ @@ -2410,7 +2376,7 @@ my: explanation: အသုံးပြုသူသည် ဖြစ်စဉ်များစာရင်း သို့မဟုတ် ဖြစ်စဉ်ပြသသည့်စာမျက်နှာများမှ PDF ဖိုင်ကို export သတင်းအချက်အလက်ထုတ်ယူခြင်းလုပ်နိုင်ပြီး၊ ၎င်းသည် လက်ရှိအသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် field များအားလုံးပါဝင်သည့်၊ ဖြစ်စဉ်တစ်ခု၊ အများအပြား သို့မဟုတ် အားလုံးအတွက် ပါဝင်ပါသည်။PDF export ဖိုင်တွင် အချက်အလက်များကို ဖြစ်ရပ်တစ်ခုချင်းအလိုက် ဦးစွာဖော်ပြထားပြီး အချက်အလက်များပေါ်လာသည့်ပုံစံဖြင့် ထပ်မံဖွဲ့စည်းထားသည်။ label: pdf ဖိုင်အဖြစ် export သတင်းအချက်အလက်ထုတ်ယူပါလုပ်ပါ export_xls: - explanation: "အသုံးပြုသူသည် အဖြစ်အပျက်များစာရင်း သို့မဟုတ် အဖြစ်အပျက် ဖြစ်ပွားမှုပြသသည့် စာမျက်နှာများမှ XLS ဖိုင်ကို ထုတ်ယူနိုင်သည်၊ အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် စိတ်ကြိုက်ပုံစံများ သို့မဟုတ် အကွက်များပါရှိပါသည်။၊ ဤထုတ်ယူမှုတွင်၊ ဖောင်တစ်ခုစီကို XLS ဖိုင်အတွင်း ၎င်း၏ကိုယ်ပိုင်တက်ဘ်တွင် ကိုယ်စားပြုထားသည်။ Custom Export modal ကို အသုံးပြု၍ ထုတ်ယူမှုတွင် ထည့်သွင်းလိုသော ဖောင် သို့မဟုတ် အကွက်များကို အသုံးပြုသူက ရွေးချယ်နိုင်သည်။ အသုံးပြုသူများသည် အပလီကေးရှင်းရှိ ဖြစ်ရပ်ကိုကြည့်ရှုသည့်အခါ အဆိုပါပုံစံများနှင့် အကွက်များကို မြင်နိုင်စွမ်းရှိပြီးသားဖြစ်မှသာ ထုတ်ယူမှုတွင် ဖောင်နှင့်အကွက်များ ထည့်သွင်းနိုင်သည်ကို သတိပြုပါ။ " + explanation: 'အသုံးပြုသူသည် အဖြစ်အပျက်များစာရင်း သို့မဟုတ် အဖြစ်အပျက် ဖြစ်ပွားမှုပြသသည့် စာမျက်နှာများမှ XLS ဖိုင်ကို ထုတ်ယူနိုင်သည်၊ အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် စိတ်ကြိုက်ပုံစံများ သို့မဟုတ် အကွက်များပါရှိပါသည်။၊ ဤထုတ်ယူမှုတွင်၊ ဖောင်တစ်ခုစီကို XLS ဖိုင်အတွင်း ၎င်း၏ကိုယ်ပိုင်တက်ဘ်တွင် ကိုယ်စားပြုထားသည်။ Custom Export modal ကို အသုံးပြု၍ ထုတ်ယူမှုတွင် ထည့်သွင်းလိုသော ဖောင် သို့မဟုတ် အကွက်များကို အသုံးပြုသူက ရွေးချယ်နိုင်သည်။ အသုံးပြုသူများသည် အပလီကေးရှင်းရှိ ဖြစ်ရပ်ကိုကြည့်ရှုသည့်အခါ အဆိုပါပုံစံများနှင့် အကွက်များကို မြင်နိုင်စွမ်းရှိပြီးသားဖြစ်မှသာ ထုတ်ယူမှုတွင် ဖောင်နှင့်အကွက်များ ထည့်သွင်းနိုင်သည်ကို သတိပြုပါ။ ' label: Excel ( xls ဖိုင် ) ကို export လုပ်ပါ flag: explanation: ဖြစ်ရပ်တစ်ခုတွင် အမှတ်အသားတစ်ခုထည့်နိုင်သည်။ ခွင့်ပြုချက်ရှိသော အသုံးပြုသူများသည် ဖြစ်ရပ်တစ်ခုတွင် ၎င်းတို့ထည့်သွင်းထားသော အမှတ်အသားများကို ဖယ်ရှားနိုင်သည်။ @@ -2425,10 +2391,10 @@ my: explanation: ဖြစ်စဉ်တစ်ခုကို ကြည့်ရှုနိုင်မှု label: ကြည့်ရန် sync_mobile: - explanation: "ယခုခွင့်ပြုချက်သည် ယေဘူယျအားဖြင့် သုံးစွဲသူအား မိုဘိုင်းအက်ပလီကေးရှင်းကို အသုံးပြုခွင့်ပေးခြင်းဖြစ်သည်။ ပထမဦးစွာ၊ ၎င်းသည် အသုံးပြုသူအား အဖြစ်အပျက်စာရင်းနှင့် ဖြစ်ပွားမှုပြသသည့်စာမျက်နှာများတွင် ပေါ်နေသည့် \" မိုဘိုင်း ကို ခြစ်ရန်\" နှင့် \" မိုဘိုင်း ကိုမခြစ်ရန်\" လုပ်ဆောင်ချက်များကို ကြည့်ရှုနိုင်စေပါသည်။ မိုဘိုင်းအတွက် အဖြစ်အပျက်တစ်ခုကို အမှတ်အသားပြုခြင်းသည် အသုံးပြုသူ၏ မိုဘိုင်းစက်ပစ္စည်းနှင့် ဝဘ်အက်ပလီကေးရှင်းကြားတွင် အဖြစ်အပျက်တစ်ခုအား ထပ်တူဖြစ်သင့်သည်၊ မိုဘိုင်းအတွက် အဖြစ်အပျက်တစ်ခုကို အမှတ်အသားပြုခြင်းဖြင့် ထပ်တူပြုခြင်းကို ရပ်တန့်သွားစေသည်။ ဤခွင့်ပြုချက်မရှိဘဲ အသုံးပြုသူများသည် ၎င်းတို့၏မိုဘိုင်းစက်ပစ္စည်းများကို ဝဘ်အက်ပလီကေးရှင်းနှင့် ယေဘုယျအားဖြင့် ထပ်တူပြုလုပ်၍မရပါ၊ ဆိုလိုသည်မှာ အဖြစ်အပျက်များကို စီမံခန့်ခွဲရန် မိုဘိုင်းအက်ပ်ကို အသုံးမပြုနိုင်ပါ။ " + explanation: 'ယခုခွင့်ပြုချက်သည် ယေဘူယျအားဖြင့် သုံးစွဲသူအား မိုဘိုင်းအက်ပလီကေးရှင်းကို အသုံးပြုခွင့်ပေးခြင်းဖြစ်သည်။ ပထမဦးစွာ၊ ၎င်းသည် အသုံးပြုသူအား အဖြစ်အပျက်စာရင်းနှင့် ဖြစ်ပွားမှုပြသသည့်စာမျက်နှာများတွင် ပေါ်နေသည့် " မိုဘိုင်း ကို ခြစ်ရန်" နှင့် " မိုဘိုင်း ကိုမခြစ်ရန်" လုပ်ဆောင်ချက်များကို ကြည့်ရှုနိုင်စေပါသည်။ မိုဘိုင်းအတွက် အဖြစ်အပျက်တစ်ခုကို အမှတ်အသားပြုခြင်းသည် အသုံးပြုသူ၏ မိုဘိုင်းစက်ပစ္စည်းနှင့် ဝဘ်အက်ပလီကေးရှင်းကြားတွင် အဖြစ်အပျက်တစ်ခုအား ထပ်တူဖြစ်သင့်သည်၊ မိုဘိုင်းအတွက် အဖြစ်အပျက်တစ်ခုကို အမှတ်အသားပြုခြင်းဖြင့် ထပ်တူပြုခြင်းကို ရပ်တန့်သွားစေသည်။ ဤခွင့်ပြုချက်မရှိဘဲ အသုံးပြုသူများသည် ၎င်းတို့၏မိုဘိုင်းစက်ပစ္စည်းများကို ဝဘ်အက်ပလီကေးရှင်းနှင့် ယေဘုယျအားဖြင့် ထပ်တူပြုလုပ်၍မရပါ၊ ဆိုလိုသည်မှာ အဖြစ်အပျက်များကို စီမံခန့်ခွဲရန် မိုဘိုင်းအက်ပ်ကို အသုံးမပြုနိုင်ပါ။ ' label: လက်ကိုင်ဖုန်းနှင့် Sync ပြုလုပ်ခြင်း write: - explanation: "\"တည်းဖြတ်ရန်\" ခလုတ်ကို နှိပ်ခြင်း၊ ဖြစ်စဉ်ဆိုင်ရာ အချက်အလက်ကို နောက်ဆုံးအခြေအနေနှင့်အညီ ပြုပြင်မွမ်းမံခြင်းနှင့် \"သိမ်းဆည်းရန်\" ကို နှိပ်နိုင်သည်။ အသုံးပြုသူအား ဖြစ်စဉ်တစ်ခုကို ပိတ်ရန် သို့မဟုတ် ဖွင့်ရန်လည်း ခွင့်ပြုသည်။" + explanation: '"တည်းဖြတ်ရန်" ခလုတ်ကို နှိပ်ခြင်း၊ ဖြစ်စဉ်ဆိုင်ရာ အချက်အလက်ကို နောက်ဆုံးအခြေအနေနှင့်အညီ ပြုပြင်မွမ်းမံခြင်းနှင့် "သိမ်းဆည်းရန်" ကို နှိပ်နိုင်သည်။ အသုံးပြုသူအား ဖြစ်စဉ်တစ်ခုကို ပိတ်ရန် သို့မဟုတ် ဖွင့်ရန်လည်း ခွင့်ပြုသည်။' label: ပြင်ဆင်သည် explanation: ဖြစ်ပျက်ခဲ့သည့် အဖြစ်အပျက်ကို ကိုယ်စားပြုသည်။ ၎င်းတို့သည် အများအားဖြင့် အလွဲသုံးစားလုပ်ခြင်း သို့မဟုတ် အကြမ်းဖက်မှု ဖြစ်စဉ်များဖြစ်ပြီး ၎င်းတို့သည် တရားဥပဒေစိုးမိုးရေးနှင့် ကြုံတွေ့ရမှုများကဲ့သို့ ဖြစ်ရပ်များနှင့်လည်း ဆက်စပ်နိုင်သည်။ ဖြစ်စဉ်များသည် ဖြစ်ရပ်များနှင့် ဆက်စပ်နေတတ်သည်။ label: ဖြစ်စဉ် @@ -2451,7 +2417,7 @@ my: metadata: actions: manage: - explanation: "ဖောင်များကို ဖန်တီးခြင်း၊ တည်းဖြတ်ခြင်း၊ ဘာသာပြန်ခြင်း နှင့် ပယ်ဖျက်ခြင်းများ၊ ဖောင်အကွက်များနှင့် ရှာဖွေမှုများ ပြုလုပ်နိုင်ပါသည်။ ခွင့်ပြုချက်ရှိသော အသုံးပြုသူတစ်ဦးသည် ၎င်းတို့ဝင်ရောက်ခွင့်ရှိသည့် ဖောင်များကိုသာ စီမံခန့်ခွဲနိုင်မည်ဖြစ်ကြောင်း ကျေးဇူးပြု၍ သတိပြုပါ။ အသုံးပြုသူကိုယ်စား စနစ်စီမံခန့်ခွဲပံပိုးသူမှ ဖြစ်ရပ်မှတ်တမ်းဖောင်ကို ကြည့်ရှုနိုင်ပါသည်။ ၎င်းတို့သည် ဤဖောင်ပုံစံဖွဲ့စည်းပုံကို ဘယ်သောအခါမှ မွမ်းမံပြင်ဆင်နိုင်မည်မဟုတ်ပါ။ " + explanation: 'ဖောင်များကို ဖန်တီးခြင်း၊ တည်းဖြတ်ခြင်း၊ ဘာသာပြန်ခြင်း နှင့် ပယ်ဖျက်ခြင်းများ၊ ဖောင်အကွက်များနှင့် ရှာဖွေမှုများ ပြုလုပ်နိုင်ပါသည်။ ခွင့်ပြုချက်ရှိသော အသုံးပြုသူတစ်ဦးသည် ၎င်းတို့ဝင်ရောက်ခွင့်ရှိသည့် ဖောင်များကိုသာ စီမံခန့်ခွဲနိုင်မည်ဖြစ်ကြောင်း ကျေးဇူးပြု၍ သတိပြုပါ။ အသုံးပြုသူကိုယ်စား စနစ်စီမံခန့်ခွဲပံပိုးသူမှ ဖြစ်ရပ်မှတ်တမ်းဖောင်ကို ကြည့်ရှုနိုင်ပါသည်။ ၎င်းတို့သည် ဤဖောင်ပုံစံဖွဲ့စည်းပုံကို ဘယ်သောအခါမှ မွမ်းမံပြင်ဆင်နိုင်မည်မဟုတ်ပါ။ ' label: စီမံခန့်ခွဲပါ (ဤအရင်းအမြစ်အမျိုးအစားအတွက် ခွင့်ပြုချက်အားလုံးကို) explanation: Primero ဖောင်ပုံစံများ နှင့် Fields များကို configure လုပ်နိုင်စွမ်းအပြင် ၎င်းတို့အတွင်းအသုံးပြုထားသော Lookup options များကိုလည်း ထိန်းချုပ်ပါသည်။ label: ပုံစံများ၊ ရှာဖွေခြင်း @@ -2480,8 +2446,8 @@ my: referral: actions: refer: - explanation: "သုံးစွဲသူသည် ပြင်ပသို့ ညွှန်းပို့မှု လုပ်ဆောင်သည့်အခါ \"လက်ခံသူ အမျိုးအစား\" အတွက် ရွေးချယ်စရာတစ်ခုအဖြစ် အခန်းကဏ္ဍပေါ်လာမည်ဖြစ်သည်။ အသုံးပြုသူသည် ဤအခန်းကဏ္ဍကို ညွှန်းပို့မှုအမျိုးအစားအဖြစ် ရွေးချယ်ပါက လွှဲပြောင်းပေးပို့မှုကို ထည့်သွင်းသည့်အခါ ဤအခန်းကဏ္ဍမှ ဝင်ရောက်အသုံးပြုနိုင်သည့် ဖောင်များတွင်သာ တွေ့ရသည့် အချက်အလက်ပါရှိပါသည်။ ဥပမာအားဖြင့်၊ အသုံးပြုသူသည် လက်ခံသူအမျိုးအစားအဖြစ် \"ကျန်းမာရေးဆိုင်ရာ ဝန်ဆောင်မှုပေးသူ\" ကို ရွေးချယ်ပါက၊ ကျန်းမာရေးဆိုင်ရာ ဝန်ဆောင်မှုပေးသူ၏ အခန်းကဏ္ဍသည် အခြေခံ အထောက်အထားနှင့် အကာအကွယ်ပေးရေးဆိုင်ရာ စိုးရိမ်မှုပုံစံများကိုသာ ဝင်ရောက်ခွင့်ရှိပါမည်။ Primero မှ ပြင်ပသို့ ညွှန်းပို့မှုအတွက် ထုတ်ယူသည့် ဖိုင်ကိုသာ ရရှိမည်ဖြစ်သည်။ " - label: "ဤအခန်းကဏ္ဍကို ပြင်ပသို့လွှဲပြောင်းညွှန်းပို့ရာတွင် အသုံးပြုနိုင်ပါသလား?" + explanation: 'သုံးစွဲသူသည် ပြင်ပသို့ ညွှန်းပို့မှု လုပ်ဆောင်သည့်အခါ "လက်ခံသူ အမျိုးအစား" အတွက် ရွေးချယ်စရာတစ်ခုအဖြစ် အခန်းကဏ္ဍပေါ်လာမည်ဖြစ်သည်။ အသုံးပြုသူသည် ဤအခန်းကဏ္ဍကို ညွှန်းပို့မှုအမျိုးအစားအဖြစ် ရွေးချယ်ပါက လွှဲပြောင်းပေးပို့မှုကို ထည့်သွင်းသည့်အခါ ဤအခန်းကဏ္ဍမှ ဝင်ရောက်အသုံးပြုနိုင်သည့် ဖောင်များတွင်သာ တွေ့ရသည့် အချက်အလက်ပါရှိပါသည်။ ဥပမာအားဖြင့်၊ အသုံးပြုသူသည် လက်ခံသူအမျိုးအစားအဖြစ် "ကျန်းမာရေးဆိုင်ရာ ဝန်ဆောင်မှုပေးသူ" ကို ရွေးချယ်ပါက၊ ကျန်းမာရေးဆိုင်ရာ ဝန်ဆောင်မှုပေးသူ၏ အခန်းကဏ္ဍသည် အခြေခံ အထောက်အထားနှင့် အကာအကွယ်ပေးရေးဆိုင်ရာ စိုးရိမ်မှုပုံစံများကိုသာ ဝင်ရောက်ခွင့်ရှိပါမည်။ Primero မှ ပြင်ပသို့ ညွှန်းပို့မှုအတွက် ထုတ်ယူသည့် ဖိုင်ကိုသာ ရရှိမည်ဖြစ်သည်။ ' + label: ဤအခန်းကဏ္ဍကို ပြင်ပသို့လွှဲပြောင်းညွှန်းပို့ရာတွင် အသုံးပြုနိုင်ပါသလား? label: ညွှန်းပို့မှု registry_record: actions: @@ -2493,7 +2459,7 @@ my: label: စတင်ပြုလုပ်သည် enable_disable_record: explanation: မှတ်ပုံတင်မှတ်တမ်းကို disable သို့မဟုတ် enable လုပ်နိုင်စွမ်း။ "Disabled " လုပ်ထားသည့် မှတ်တမ်းများသည် မှတ်ပုံတင်စာရင်းတွင် ပုံသေအားဖြင့် မပေါ်ပါ။ အသုံးပြုသူများသည် စစ်ထုတ်မှုတစ်ခုကို အသုံးပြုခြင်းဖြင့် မှတ်ပုံတင်စာရင်းတွင် ပိတ်ထားသော မှတ်ပုံတင် မှတ်တမ်းများကို ကြည့်ရှုနိုင်သည်။ - label: "အသုံးပြုနိုင်အောင်ဖွင့်ပါ / အသုံးမပြုနိုင်အောင်ပိတ်ပါ " + label: 'အသုံးပြုနိုင်အောင်ဖွင့်ပါ / အသုံးမပြုနိုင်အောင်ပိတ်ပါ ' export_csv: explanation: 'အသုံးပြုသူသည် ဖြစ်ရပ်စာရင်း သို့မဟုတ် ဖြစ်ရပ်ဖော်ပြစာမျက်နှာများမှ CSV ဖိုင်ကို ထုတ်လွှတ်နိုင်သည်၊ ၎င်းသည် လက်ရှိအသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် fields အားလုံး၊ တစ်ခု၊ အများအပြား သို့မဟုတ် အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် မှတ်ပုံတင်မှတ်တမ်းအားလုံးတွင် ပါဝင်ပါသည်။ မှတ်ချက်- CSV ထုတ်ယူမှုသည် လက်တင်မဟုတ်သော အက္ခရာများ (ဥပမာ အာရဗီ၊ ဘင်္ဂလာ) ကို ဖတ်နိုင်သော format ဖြင့် မဖော်ပြပါ။ ' label: CSV ဖိုင်အဖြစ် export လုပ်ပါ @@ -2534,7 +2500,7 @@ my: explanation: အသုံးပြုသူတစ်ဦးအား အဖွဲ့အစည်းများတွင် ရရှိနိုင်သော လုပ်ဆောင်ချက်များအားလုံးကို လုပ်ဆောင်ရန် ခွင့်ပြုသည်။ "စီမံခန့်ခွဲခြင်း" ခွင့်ပြုချက်သည် အခြေခံအားဖြင့် "အရာအားလုံး" ကို ဆိုလိုသည်။ label: စီမံခန့်ခွဲပါ (ဤအရင်းအမြစ်အမျိုးအစားအတွက် ခွင့်ပြုချက်အားလုံးကို) read: - explanation: "အစီရင်ခံစာအားလုံးကိုကြည့်ရှုနိုင်မှု။ အစီရင်ခံစာတစ်ခုစီရှိ နံပါတ်များသည် လက်ရှိအသုံးပြုသူ ဝင်ရောက်ကြည့်ရှုနိုင်သည့် မှတ်တမ်းများထက် စနစ်အတွင်းရှိ မှတ်တမ်းများအားလုံးကို ထင်ဟပ်စေမည်ဖြစ်သည်။ ဤခွင့်ပြုချက်သည် သုံးစွဲသူအား အစီရင်ခံစာတစ်ခုမှ အချက်အလက်များကို ထုတ်ယူနိုင်စေပါသည်။ " + explanation: 'အစီရင်ခံစာအားလုံးကိုကြည့်ရှုနိုင်မှု။ အစီရင်ခံစာတစ်ခုစီရှိ နံပါတ်များသည် လက်ရှိအသုံးပြုသူ ဝင်ရောက်ကြည့်ရှုနိုင်သည့် မှတ်တမ်းများထက် စနစ်အတွင်းရှိ မှတ်တမ်းများအားလုံးကို ထင်ဟပ်စေမည်ဖြစ်သည်။ ဤခွင့်ပြုချက်သည် သုံးစွဲသူအား အစီရင်ခံစာတစ်ခုမှ အချက်အလက်များကို ထုတ်ယူနိုင်စေပါသည်။ ' label: ကြည့်ရန် write: explanation: အစီရင်ခံစာများအားလုံးကို တည်းဖြတ်နိုင်မှု (အခြားအသုံးပြုသူများမှ ဖန်တီးထားသည့်အရာများအပါအဝင်)။ @@ -2543,11 +2509,11 @@ my: label: အစီရင်ခံစာ reporting_location_level: explanation: 'ဒက်ရှ်ဘုတ်များ၊ စစ်ထုတ်မှုများ၊ လွှဲပြောင်းမှုပုံစံများနှင့် လွှဲပြောင်းမှုပုံစံများရှိ အခန်းကဏ္ဍအတွက် တည်နေရာအဆင့်ကို ထိန်းချုပ်မည်ဖြစ်သည်။ အကယ်၍ သင်သည် ဤအကွက်ကို ကွက်လပ်ထားခဲ့ပါက၊ ဤအခန်းကဏ္ဍအတွက် စနစ်တွင် ပုံသေအစီရင်ခံခြင်းတည်နေရာအဆင့်ကို မြင်တွေ့ရမည်ဖြစ်သည်။ ' - label: "ဒီအခန်းကဏ္ဍအတွက် အစီရင်ခံရန် မည်သည့်တည်နေရာကို အသုံးပြုသင့်ပါသလဲ?" + label: ဒီအခန်းကဏ္ဍအတွက် အစီရင်ခံရန် မည်သည့်တည်နေရာကို အသုံးပြုသင့်ပါသလဲ? role: actions: assign: - explanation: "အသုံးပြုသူအကောင့်တစ်ခုဖန်တီးရန် သို့မဟုတ် တည်းဖြတ်ရန် အတွက်အခန်းကဏ္ဍတစ်ခုကို ရွေးချယ်နိုင်ပါသည်။ အသုံးပြုသူအကောင့်များကို ဖန်တီးခြင်း သို့မဟုတ် တည်းဖြတ်မည့် မည်သည့်အခန်းကဏ္ဍအတွက်မဆို ခွင့်ပြုချက်လိုအပ်ပါသည်။ " + explanation: 'အသုံးပြုသူအကောင့်တစ်ခုဖန်တီးရန် သို့မဟုတ် တည်းဖြတ်ရန် အတွက်အခန်းကဏ္ဍတစ်ခုကို ရွေးချယ်နိုင်ပါသည်။ အသုံးပြုသူအကောင့်များကို ဖန်တီးခြင်း သို့မဟုတ် တည်းဖြတ်မည့် မည်သည့်အခန်းကဏ္ဍအတွက်မဆို ခွင့်ပြုချက်လိုအပ်ပါသည်။ ' label: တာဝန်ပေးသည် copy: explanation: အခန်းကဏ္ဍတစ်ခု၏မိတ္တူကိုဖန်တီးနိုင်မှု။ တစ်ခုနှင့်တစ်ခု အလွန်တူညီသည့် အခန်းကဏ္ဍများစွာကို ဖန်တီးနေသည့် စနစ်စီမံခန့်ခွဲသူများအတွက် အသုံးဝင်သည် (ဥပမာ ဝန်ဆောင်မှုပေးသူများ)။ @@ -2562,7 +2528,7 @@ my: explanation: 'အသုံးပြုသူတစ်ဦးအား အခန်းကဏ္ဍများတွင် ရရှိနိုင်သော လုပ်ဆောင်ချက်များအားလုံးကို လုပ်ဆောင်ရန် ခွင့်ပြုသည်။ "စီမံခန့်ခွဲခြင်း" ခွင့်ပြုချက်သည် အခြေခံအားဖြင့် "အရာအားလုံး" ကို ဆိုလိုသည်။ အရေးကြီးသည်- ၎င်းသည် အခန်းကဏ္ဍများကို အသစ်ဖန်တီးခြင်းနှင့် ဖျက်သိမ်းခြင်းတို့ကိုလည်း လုပ်ဆောင်နိုင်စေပါသည်။' label: စီမံခန့်ခွဲပါ (ဤအရင်းအမြစ်အမျိုးအစားအတွက် ခွင့်ပြုချက်အားလုံးကို) permitted_roles: - explanation: "အကယ်၍ ခန်းကဏ္ဍတစ်ခုတွင် အထက်ဖော်ပြပါ လုပ်ဆောင်ချက်များကို လုပ်ဆောင်နိုင်စွမ်းရှိပါက ဤစာရင်းတွင် သတ်မှတ်ထားသည့် အခန်းကဏ္ဍများတွင် ယင်းလုပ်ဆောင်ချက်များကို လုပ်ဆောင်နိုင်မည်ဖြစ်သည်။ ဥပမာအားဖြင့်၊ အကယ်၍ အခန်းကဏ္ဍတစ်ခုတွင် \"Read\" နှင့် \"Assign\" ခွင့်ပြုချက်ရှိသော်လည်း ကလေးသူငယ်ကာကွယ်စောင့်ရှောက်ရေး ဖြစ်ရပ်လုပ်ငန်းဆောင်ရွက်သူနှင့် ကလေးသူငယ်ကာကွယ်စောင့်ရှောက်ရေး မန်နေဂျာတို့ကို \"Managed Roles\" အဖြစ် စာရင်းသွင်းထားမှသာ ၎င်းတို့ကို မြင်နိုင်မည်ဖြစ်သည်။ အခန်းကဏ္ဍနှစ်ခုနှင့် သုံးစွဲသူအသစ်များကို ထိုအခန်းကဏ္ဍနှစ်ခုတွင်သာ သတ်မှတ်နိုင်မည်ဖြစ်သည်။ တူညီသောအခန်းကဏ္ဍတွင် \"စီမံအုပ်ချုပ်မှုအခန်းကဏ္ဍ\" သတ်မှတ်ထားပါက အခန်းကဏ္ဍအားလုံးကိုမြင်နိုင်မည်ဖြစ်ပြီး စနစ်အတွင်းရှိမည်သည့်အခန်းကဏ္ဍမှမဆို role အသစ်များကို ဖန်တီးနိုင်မည်ဖြစ်သည်။ " + explanation: 'အကယ်၍ ခန်းကဏ္ဍတစ်ခုတွင် အထက်ဖော်ပြပါ လုပ်ဆောင်ချက်များကို လုပ်ဆောင်နိုင်စွမ်းရှိပါက ဤစာရင်းတွင် သတ်မှတ်ထားသည့် အခန်းကဏ္ဍများတွင် ယင်းလုပ်ဆောင်ချက်များကို လုပ်ဆောင်နိုင်မည်ဖြစ်သည်။ ဥပမာအားဖြင့်၊ အကယ်၍ အခန်းကဏ္ဍတစ်ခုတွင် "Read" နှင့် "Assign" ခွင့်ပြုချက်ရှိသော်လည်း ကလေးသူငယ်ကာကွယ်စောင့်ရှောက်ရေး ဖြစ်ရပ်လုပ်ငန်းဆောင်ရွက်သူနှင့် ကလေးသူငယ်ကာကွယ်စောင့်ရှောက်ရေး မန်နေဂျာတို့ကို "Managed Roles" အဖြစ် စာရင်းသွင်းထားမှသာ ၎င်းတို့ကို မြင်နိုင်မည်ဖြစ်သည်။ အခန်းကဏ္ဍနှစ်ခုနှင့် သုံးစွဲသူအသစ်များကို ထိုအခန်းကဏ္ဍနှစ်ခုတွင်သာ သတ်မှတ်နိုင်မည်ဖြစ်သည်။ တူညီသောအခန်းကဏ္ဍတွင် "စီမံအုပ်ချုပ်မှုအခန်းကဏ္ဍ" သတ်မှတ်ထားပါက အခန်းကဏ္ဍအားလုံးကိုမြင်နိုင်မည်ဖြစ်ပြီး စနစ်အတွင်းရှိမည်သည့်အခန်းကဏ္ဍမှမဆို role အသစ်များကို ဖန်တီးနိုင်မည်ဖြစ်သည်။ ' label: ဤအခန်းကဏ္ဍက စီမံခန့်ခွဲသည့် အခြားအခန်းကဏ္ဍ read: explanation: အခန်းကဏ္ဍများကို မြင်နိုင်သည်။ @@ -2575,21 +2541,21 @@ my: system: actions: manage: - explanation: "စနစ်အဆက်အသွယ်အချက်အလက်၊ သတိပေးချက်နှင့် အီးမေးလ်ဆက်တင်များ၊ နှင့် ထပ်တူပြုထားသည့် ဆာဗာများဆိုင်ရာ အချက်အလက်များကို ကြည့်ရှုခြင်းနှင့် အပ်ဒိတ်လုပ်နိုင်ပါသည်။ ဤခွင့်ပြုချက်ကို စနစ်စီမံခန့်ခွဲသူအတွက် သီးသန့်ထားရှိသည်။ " + explanation: 'စနစ်အဆက်အသွယ်အချက်အလက်၊ သတိပေးချက်နှင့် အီးမေးလ်ဆက်တင်များ၊ နှင့် ထပ်တူပြုထားသည့် ဆာဗာများဆိုင်ရာ အချက်အလက်များကို ကြည့်ရှုခြင်းနှင့် အပ်ဒိတ်လုပ်နိုင်ပါသည်။ ဤခွင့်ပြုချက်ကို စနစ်စီမံခန့်ခွဲသူအတွက် သီးသန့်ထားရှိသည်။ ' label: စီမံခန့်ခွဲပါ (ဤအရင်းအမြစ်အမျိုးအစားအတွက် ခွင့်ပြုချက်အားလုံးကို) explanation: အမျိုးမျိုးသော စနစ် - ကျယ်ပြန့်သော ဖွဲ့စည်းမှုဆက်တင်များ။ label: စနစ် tracing_request: actions: change_log: - explanation: "အသုံးပြုသူသည် ၎င်းကို ဖန်တီးခဲ့ပြီးကတည်းက မှတ်တမ်းတင် ပြုလုပ်ထားသည့် ပြောင်းလဲမှုအားလုံး ၏ မှတ်တမ်းကို ကြည့်ရှုနိုင်သည်။ အကွက်အားလုံးအတွက် မှတ်တမ်းတင်ထားသော အချက်များပါဝင်ပါသည်။ " + explanation: 'အသုံးပြုသူသည် ၎င်းကို ဖန်တီးခဲ့ပြီးကတည်းက မှတ်တမ်းတင် ပြုလုပ်ထားသည့် ပြောင်းလဲမှုအားလုံး ၏ မှတ်တမ်းကို ကြည့်ရှုနိုင်သည်။ အကွက်အားလုံးအတွက် မှတ်တမ်းတင်ထားသော အချက်များပါဝင်ပါသည်။ ' label: မှတ်တမ်းကို ပြောင်းပါ။ create: explanation: ရှာဖွေမှုပြုရန်အတွက် တောင်းဆိုမှုကို စတင်ဖန်တီးနိုင်မှု။ label: စတင်ပြုလုပ်သည် enable_disable_record: explanation: ခြေရာခံတောင်းဆိုမှုတစ်ခုကို ပိတ်ရန် သို့မဟုတ် ဖွင့်ရန် စွမ်းရည်။ "ပိတ်ထားသည်" ခြေရာခံတောင်းဆိုမှုများသည် ခြေရာခံတောင်းဆိုမှုစာရင်းတွင် ပုံသေအားဖြင့် မပေါ်ပါ။ အသုံးပြုသူများသည် စစ်ထုတ်မှုတစ်ခုကို အသုံးပြုခြင်းဖြင့် ခြေရာခံတောင်းဆိုမှုစာရင်းတွင် ပိတ်ထားရသော ခြေရာခံတောင်းဆိုမှုများကို ကြည့်ရှုနိုင်သည်။ - label: "အသုံးပြုနိုင်အောင်ဖွင့်ပါ / အသုံးမပြုနိုင်အောင်ပိတ်ပါ " + label: 'အသုံးပြုနိုင်အောင်ဖွင့်ပါ / အသုံးမပြုနိုင်အောင်ပိတ်ပါ ' export_case_pdf: explanation: အသုံးပြုသူသည် ခြေရာခံတောင်းဆိုမှုများစာရင်း သို့မဟုတ် ခြေရာခံတောင်းဆိုမှုပြသသည့်စာမျက်နှာများမှ PDF ဖိုင်ကို export လုပ်နိုင်ပြီး၊ ၎င်းသည် လက်ရှိအသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် field များအားလုံးပါဝင်သည့်၊ ဖြစ်စဉ်တစ်ခု၊ အများအပြား သို့မဟုတ် အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် မှတ်တမ်းအားလုံးပါဝင်ပါသည် ။ PDF export ဖိုင်တွင် အချက်အလက်များကို ဖြစ်ရပ်တစ်ခုချင်းအလိုက် ဦးစွာဖော်ပြထားပြီး အချက်အလက်များပေါ်လာသည့်ပုံစံဖြင့် ထပ်မံဖွဲ့စည်းထားသည်။ label: pdf ဖိုင်အဖြစ် export လုပ်ပါ @@ -2597,7 +2563,7 @@ my: explanation: အသုံးပြုသူသည် ခြေရာခံတောင်းဆိုမှုစာရင်း သို့မဟုတ် ခြေရာခံတောင်းဆိုချက်စာမျက်နှာများကို CSV ဖိုင်အဖြစ်ထုတ်ယူနိုင်ပြီး၊ လက်ရှိအသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် အကွက်အားလုံးပါဝင်သည့် ခြေရာခံတောင်းဆိုမှုအားလုံးရရှိနိုင်ပါသည်။ label: CSV ဖိုင်အဖြစ် export လုပ်ပါ export_custom: - explanation: "အသုံးပြုသူသည် ခြေရာခံတောင်းဆိုမှုစာရင်း သို့မဟုတ် ခြေရာခံတောင်းဆိုမှုပြသသည့် စာမျက်နှာများမှ XLS ဖိုင်ကို ထုတ်ယူနိုင်သည်၊ ၎င်းတွင် အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် စိတ်ကြိုက်ဖောင်ပုံစံများ သို့မဟုတ် field များ၊တစ်ခု၊ မျိုးစုံ သို့မဟုတ် ခြေရာခံတောင်းဆိုမှု အားလုံး ပါရှိပါသည်။၊ ဤထုတ်ယူမှုတွင်၊ ဖောင်တစ်ခုစီကို XLS ဖိုင်အတွင်း ၎င်း၏ကိုယ်ပိုင်တက်ဘ်တွင် ကိုယ်စားပြုထားသည်။ Custom Export modal ကို အသုံးပြု၍ ထုတ်ယူမှုတွင် ထည့်သွင်းလိုသော ဖောင် သို့မဟုတ် fields များကို အသုံးပြုသူက ရွေးချယ်နိုင်သည်။ အသုံးပြုသူများသည် အပလီကေးရှင်းရှိ ခြေရာခံတောင်းဆိုမှုကိုကြည့်ရှုသည့်အခါ အဆိုပါဖောင်ပုံစံများနှင့် fields များကို မြင်နိုင်စွမ်းရှိပြီးသားဖြစ်မှသာ ထုတ်ယူမှုတွင် ဖောင်နှင့်fieldsများ ထည့်သွင်းနိုင်သည်ကို သတိပြုပါ။ " + explanation: 'အသုံးပြုသူသည် ခြေရာခံတောင်းဆိုမှုစာရင်း သို့မဟုတ် ခြေရာခံတောင်းဆိုမှုပြသသည့် စာမျက်နှာများမှ XLS ဖိုင်ကို ထုတ်ယူနိုင်သည်၊ ၎င်းတွင် အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် စိတ်ကြိုက်ဖောင်ပုံစံများ သို့မဟုတ် field များ၊တစ်ခု၊ မျိုးစုံ သို့မဟုတ် ခြေရာခံတောင်းဆိုမှု အားလုံး ပါရှိပါသည်။၊ ဤထုတ်ယူမှုတွင်၊ ဖောင်တစ်ခုစီကို XLS ဖိုင်အတွင်း ၎င်း၏ကိုယ်ပိုင်တက်ဘ်တွင် ကိုယ်စားပြုထားသည်။ Custom Export modal ကို အသုံးပြု၍ ထုတ်ယူမှုတွင် ထည့်သွင်းလိုသော ဖောင် သို့မဟုတ် fields များကို အသုံးပြုသူက ရွေးချယ်နိုင်သည်။ အသုံးပြုသူများသည် အပလီကေးရှင်းရှိ ခြေရာခံတောင်းဆိုမှုကိုကြည့်ရှုသည့်အခါ အဆိုပါဖောင်ပုံစံများနှင့် fields များကို မြင်နိုင်စွမ်းရှိပြီးသားဖြစ်မှသာ ထုတ်ယူမှုတွင် ဖောင်နှင့်fieldsများ ထည့်သွင်းနိုင်သည်ကို သတိပြုပါ။ ' label: custom စိတ်ကြိုက်ဖိုင်ပုံစံ ဖြင့် export လုပ်ပါ export_json: explanation: အသုံးပြုသူသည် ခြေရာခံတောင်းဆိုမှုစာရင်း သို့မဟုတ် ခြေရာခံတောင်းဆိုမှုဖော်ပြစာမျက်နှာများမှ JSON ဖိုင်ကို export လုပ်နိုင်သည်၊ ၎င်းသည် လက်ရှိအသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် fields အားလုံး၊ တစ်ခု၊ အများအပြား သို့မဟုတ် အသုံးပြုသူဝင်ရောက်ခွင့်ရှိသည့် ခြေရာခံတောင်းဆိုမှုအားလုံးတွင် ပါဝင်ပါသည်။ ဤ export ကို လက်ရှိ Primero စနစ်မှ ဖြစ်ရပ်များကို export လုပ်လိုပြီး ၎င်းတို့ကို မတူညီသော Primero စနစ်သို့ import လုပ်လိုသူများအတွက် သို့မဟုတ် အခြားသော သတင်းအချက်အလက် စီမံခန့်ခွဲမှုစနစ်သို့ import လုပ်လိုသူများအတွက် အဓိကအားဖြင့် အသုံးပြုပါသည်။ JSON format သည် စက်ဖြင့်ဖတ်နိုင်သော်လည်း အသုံးပြုသူအများစုအတွက် လက်တွေ့မကျပါ။ @@ -2624,15 +2590,15 @@ my: explanation: ခြေရာခံတောင်းဆိုချက်ကို ကြည့်ရှုနိုင်မှု။ ခြေရာခံတောင်းဆိုမှုများကို ကြည့်ရှုနိုင်စွမ်းရှိသော အခန်းကဏ္ဍများသည် ဖြစ်နိုင်ချေရှိသော ကိုက်ညီမှုမှတ်တမ်းအမျိုးအစားကို ကြည့်ရှုနိုင်စေသင့်ပါသည်။ label: ကြည့်ရန် write: - explanation: "\"တည်းဖြတ်ရန်\" ခလုတ်ကို နှိပ်ခြင်း၊ ခြေရာခံခြင်းတောင်းဆိုမှုဆိုင်ရာ အချက်အလက်ကို နောက်ဆုံးအခြေအနေနှင့်အညီ ပြုပြင်မွမ်းမံခြင်းနှင့် \"သိမ်းဆည်းရန်\" ကို နှိပ်နိုင်သည်။ အသုံးပြုသူကို ခြေရာခံခြင်းတောင်းဆိုမှုကို ပိတ်ရန် သို့မဟုတ် ဖွင့်ရန်လည်း ခွင့်ပြုသည်။" + explanation: '"တည်းဖြတ်ရန်" ခလုတ်ကို နှိပ်ခြင်း၊ ခြေရာခံခြင်းတောင်းဆိုမှုဆိုင်ရာ အချက်အလက်ကို နောက်ဆုံးအခြေအနေနှင့်အညီ ပြုပြင်မွမ်းမံခြင်းနှင့် "သိမ်းဆည်းရန်" ကို နှိပ်နိုင်သည်။ အသုံးပြုသူကို ခြေရာခံခြင်းတောင်းဆိုမှုကို ပိတ်ရန် သို့မဟုတ် ဖွင့်ရန်လည်း ခွင့်ပြုသည်။' label: ပြင်ဆင်သည် explanation: အုပ်ထိန်းသူမဲ့ခြင်း သို့မဟုတ် မိသားစုနှင့် ကွဲကွာနေသော ဖြစ်ရပ်တစ်ခုအား ရှာဖွေပြီး ပြန်လည်ပေါင်းစည်းရန် ကြိုးစားနေသည့် တစ်ဦးချင်းစီကို ကိုယ်စားပြုသည်။ - label: "ခြေရာခံတောင်းဆိုမှု " + label: 'ခြေရာခံတောင်းဆိုမှု ' transfer: actions: transfer: explanation: သုံးစွဲသူသည် ပြင်ပသို့ ညွှန်းပို့မှု လုပ်ဆောင်သည့်အခါ "လက်ခံသူ အမျိုးအစား" အတွက် ရွေးချယ်စရာတစ်ခုအဖြစ် အခန်းကဏ္ဍပေါ်လာမည်ဖြစ်သည်။ အသုံးပြုသူသည် ဤအခန်းကဏ္ဍကို လွှဲပြောင်းမှုအမျိုးအစားအဖြစ် ရွေးချယ်ပါက လွှဲပြောင်းပေးပို့မှုကို ထည့်သွင်းသည့်အခါ ဤအခန်းကဏ္ဍမှ ဝင်ရောက်အသုံးပြုနိုင်သည့် ဖောင်များတွင်သာ တွေ့ရသည့် အချက်အလက်ပါရှိပါသည်။ ဥပမာအားဖြင့်၊ အသုံးပြုသူသည် လက်ခံသူအမျိုးအစားအဖြစ် "ကျန်းမာရေးဆိုင်ရာ ဝန်ဆောင်မှုပေးသူ" ကို ရွေးချယ်ပါက၊ ကျန်းမာရေးဆိုင်ရာ ဝန်ဆောင်မှုပေးသူ၏ အခန်းကဏ္ဍသည် အခြေခံ အထောက်အထားနှင့် ကာကွယ်စောင့်ရှောက်မှုဆိုင်ရာ စိုးရိမ်မှုပုံစံများကိုသာ ဝင်ရောက်ခွင့်ရှိပါမည်။ Primero မှ ပြင်ပသို့ လွှဲပြောင်းမှုအတွက် တင်ပို့သည့် ဖိုင်ကိုသာ ရရှိမည်ဖြစ်သည်။ - label: "ဤအခန်းကဏ္ဍကို ပြင်ပသို့လွှဲပြောင်းရာတွင် အသုံးပြုနိုင်ပါသလား?" + label: ဤအခန်းကဏ္ဍကို ပြင်ပသို့လွှဲပြောင်းရာတွင် အသုံးပြုနိုင်ပါသလား? label: လွှဲပြောင်းသည် user: actions: @@ -2656,7 +2622,7 @@ my: user_group: actions: assign: - explanation: "အသုံးပြုသူအကောင့်တစ်ခုကို ဖန်တီးခြင်း သို့မဟုတ် တည်းဖြတ်သည့်အခါ အသုံးပြုသူအုပ်စုများကို ရွေးချယ်နိုင်မှု။ အကယ်၍ လက်ရှိအသုံးပြုသူတွင် \"တစ်ခုတည်းသောမှတ်တမ်းများ သို့မဟုတ် အဖွဲ့ရှိအသုံးပြုသူများ\" အဆင့် ဝင်ရောက်ခွင့်ရှိပါက ၎င်းတို့ဖန်တီးနေသောအသုံးပြုသူအကောင့်အတွက် သို့မဟုတ် တည်းဖြတ်သည့်အသုံးပြုသူအကောင့်အတွက် *၎င်းတို့၏ကိုယ်ပိုင်* အသုံးပြုသူအုပ်စုများထဲမှ တစ်ခု သို့မဟုတ် တစ်ခုထက်ပို၍ ရွေးချယ်နိုင်ပါမည်။ ဆိုလိုသည်မှာ အသုံးပြုသူအုပ်စုများကို သတ်မှတ်ပေးနိုင်စွမ်းရှိသော မန်နေဂျာသည် လက်ရှိမန်နေဂျာပိုင်ဆိုင်သည့် အသုံးပြုသူအုပ်စုများအတွင်းသို့သာ အသုံးပြုသူတစ်ဦးကို ထည့်သွင်းနိုင်မည်ဖြစ်သည်။ အသုံးပြုသူအကောင့်များ ဖန်တီးခြင်း သို့မဟုတ် တည်းဖြတ်မည့် မည်သည့်အခန်းကဏ္ဍအတွက်မဆို ဤခွင့်ပြုချက်လိုအပ်ပါသည်။ " + explanation: 'အသုံးပြုသူအကောင့်တစ်ခုကို ဖန်တီးခြင်း သို့မဟုတ် တည်းဖြတ်သည့်အခါ အသုံးပြုသူအုပ်စုများကို ရွေးချယ်နိုင်မှု။ အကယ်၍ လက်ရှိအသုံးပြုသူတွင် "တစ်ခုတည်းသောမှတ်တမ်းများ သို့မဟုတ် အဖွဲ့ရှိအသုံးပြုသူများ" အဆင့် ဝင်ရောက်ခွင့်ရှိပါက ၎င်းတို့ဖန်တီးနေသောအသုံးပြုသူအကောင့်အတွက် သို့မဟုတ် တည်းဖြတ်သည့်အသုံးပြုသူအကောင့်အတွက် *၎င်းတို့၏ကိုယ်ပိုင်* အသုံးပြုသူအုပ်စုများထဲမှ တစ်ခု သို့မဟုတ် တစ်ခုထက်ပို၍ ရွေးချယ်နိုင်ပါမည်။ ဆိုလိုသည်မှာ အသုံးပြုသူအုပ်စုများကို သတ်မှတ်ပေးနိုင်စွမ်းရှိသော မန်နေဂျာသည် လက်ရှိမန်နေဂျာပိုင်ဆိုင်သည့် အသုံးပြုသူအုပ်စုများအတွင်းသို့သာ အသုံးပြုသူတစ်ဦးကို ထည့်သွင်းနိုင်မည်ဖြစ်သည်။ အသုံးပြုသူအကောင့်များ ဖန်တီးခြင်း သို့မဟုတ် တည်းဖြတ်မည့် မည်သည့်အခန်းကဏ္ဍအတွက်မဆို ဤခွင့်ပြုချက်လိုအပ်ပါသည်။ ' label: တာဝန်ပေးသည် create: explanation: အသုံးပြုသူအုပ်စုကို စတင်ဖန်တီးနိုင်မှု။ @@ -2691,7 +2657,6 @@ my: label: ဖျက်သည် manage: label: စီမံခန့်ခွဲပါ (ဤအရင်းအမြစ်အမျိုးအစားအတွက် ခွင့်ပြုချက်အားလုံးကို) - explanation: activity_log: actions: transfer: @@ -2699,7 +2664,6 @@ my: label: လွှဲပြောင်းမှုများ manage: label: စီမံခန့်ခွဲပါ (ဤအရင်းအမြစ်အမျိုးအစားအတွက် ခွင့်ပြုချက်အားလုံးကို) - explanation: label: ဆောင်ရွက်မှုမှတ်တမ်း potential_match: case_id: ဖြစ်ရပ်အမှတ်စဉ် @@ -2718,10 +2682,9 @@ my: likelihood_likely: ဖြစ်နိုင်ချေရှိသော likelihood_possible: ဖြစ်နိုင်ချေရှိသော potential_matches: - display: "%{type}%{id}တို့အတွက် အလားအလာရှိသည့် ကိုက်ညီသူများကို ပြသခြင်း" + display: '%{type}%{id}တို့အတွက် အလားအလာရှိသည့် ကိုက်ညီသူများကို ပြသခြင်း' reassign: - multiple_error: "အမှားတစ်ခု ဖြစ်ပွားခဲ့သည်။ %{select_records}ဖြစ်ရပ်(များ)ကို တာဝန်သတ်မှတ်မပေးပါ။" - multiple_successfully: '%{select_records}ဖြစ်ရပ်(များ)ကို အောင်မြင်စွာ သတ်မှတ် တာဝန်ခွဲပေးခဲ့ပါသည်။' + multiple_error: အမှားတစ်ခု ဖြစ်ပွားခဲ့သည်။ %{select_records}ဖြစ်ရပ်(များ)ကို တာဝန်သတ်မှတ်မပေးပါ။ notes_label: မှတ်စုများ successfully: အောင်မြင်စွာ ပြန်လည်သတ်မှတ်ခဲ့ပြီးဖြစ်ပါသည်။ user_mandatory_label: လက်ခံသူ လိုအပ်ပါသည်။ @@ -2730,13 +2693,13 @@ my: assigned_user_names: အခြား တာဝန်သတ်မှတ်ပေးထားသော အသုံးပြုသူများ created_at: မှတ်တမ်း ဖန်တီးထားသည့်အချိန် created_by: ဖန်တီးထားသော မှတ်တမ်း - created_organization: " အဖွဲ့အစည်းမှ စတင်ပြုလုပ်ထားသည်။" + created_organization: ' အဖွဲ့အစည်းမှ စတင်ပြုလုပ်ထားသည်။' current_owner_separator: လက်ရှိပိုင်ရှင် - module_id: "မော်ဂျူး " + module_id: 'မော်ဂျူး ' owned_by: ဖြစ်ရပ်စီမံခန့်ခွဲသူ ကုဒ်နံပါတ် owned_by_agency_id: အဖွဲ့အစည်း owned_by_text: ကွင်းဆင်း / ဖြစ်ရပ် / လူမှုရေးလုပ်သား - previously_owned_by: "ယခင်ပိုင်ရှင် " + previously_owned_by: 'ယခင်ပိုင်ရှင် ' previously_owned_by_agency: ယခင်အဖွဲ့အစည်း reassigned_tranferred_on: ပြန်လည်တာဝန်သတ်မှတ်ပြီး/ လွှဲပြောင်းပြီး record_history_separator: မှတ်တမ်းသမိုင်း @@ -2794,7 +2757,7 @@ my: delete_filter_message: ဤစစ်ထုတ်သည့်အရာကို ဖျက်လိုသည်မှာ သေချာပါသလား။ group_ages: အသက်အပိုင်းအခြားကို အသုံးပြုပါ group_dates_by: ရက်စွဲအပိုင်းအခြားကို အသုံးပြုပါ - is_graph: "ဂရပ်တစ်ခုထုတ်လုပ်ရန်?" + is_graph: ဂရပ်တစ်ခုထုတ်လုပ်ရန်? messages: delete_success: အစီရင်ခံစာကိုအောင်မြင်စွာဖျက်ပြီးပါပြီ success: အစီရင်ခံစာကို အောင်မြင်စွာ စတင်ပြုလုပ်ပြီးပြီ။ @@ -2823,7 +2786,7 @@ my: submit_label: တောင်းဆိုမှုကို ပေးပို့ခဲ့သည် success: လွှဲပြောင်းရန် တောင်းဆိုမှုကိုပေးပို့ခဲ့သည် role: - agency_ids_label: " အေဂျင်စီများများမှ ယခုအခန်းကဏ္ဍကို စီမံခန့်ခွဲပါသည်" + agency_ids_label: ' အေဂျင်စီများများမှ ယခုအခန်းကဏ္ဍကို စီမံခန့်ခွဲပါသည်' copy_failure: အခန်းကဏ္ဍကို ကူးယူရာတွင်အမှားဖြစ်ခဲ့သည်။ အမည်နှင့် အခြားအခန်း ကဏ္ဍတို့ ပဋိပက္ခဖြစ်မှုမရှိကြောင်း သေချာပါစေ။ copy_success: အခန်းကဏ္ဍကို အောင်မြင်စွာကူးယူခဲ့သည်။ create: အခန်းကဏ္ဍအသစ် စတင်ပြုလုပ်ရန် @@ -2840,11 +2803,11 @@ my: deleted: အခန်းကဏ္ဍကို အောင်မြင်စွာဖျက်ပြီးပါပြီ updated: အခန်းကဏ္ဍကို အောင်မြင်စွာ အပ်ဒိတ် လုပ်ပြီးပါပြီ name: အမည် - referral_label: "ဤအခန်းကဏ္ဍကို လွှဲပြောင်းညွှန်းပို့ရာတွင် အသုံးပြုနိုင်ပါသလား?" - reporting_location_level_label: "ဒီအခန်းကဏ္ဍအတွက် အစီရင်ခံရန် မည်သည့်တည်နေရာကို အသုံးပြုသင့်ပါသလဲ?" - role_ids_label: "ဤအခန်းကဏ္ဍက စီမံခန့်ခွဲသည့် အခြားအခန်းကဏ္ဍများ " + referral_label: ဤအခန်းကဏ္ဍကို လွှဲပြောင်းညွှန်းပို့ရာတွင် အသုံးပြုနိုင်ပါသလား? + reporting_location_level_label: ဒီအခန်းကဏ္ဍအတွက် အစီရင်ခံရန် မည်သည့်တည်နေရာကို အသုံးပြုသင့်ပါသလဲ? + role_ids_label: 'ဤအခန်းကဏ္ဍက စီမံခန့်ခွဲသည့် အခြားအခန်းကဏ္ဍများ ' successfully_updated: အခန်းကဏ္ဍအသေးစိတ်အချက်အလက်များကို နောက်ဆုံးအခြေအနေနှင့်အညီ အောင်မြင်စွာပြင်ဆင်ခဲ့သည်။ - transfer_label: "ဤအခန်းကဏ္ဍကို လွှဲပြောင်းရာတွင် အသုံးပြုနိုင်ပါသလား?" + transfer_label: ဤအခန်းကဏ္ဍကို လွှဲပြောင်းရာတွင် အသုံးပြုနိုင်ပါသလား? hide: ကွယ်ဝှက်သည် read: ပြသည် read_write: ပြသပြီး ပြင်ဆင်တည်းဖြတ်ပါ။ @@ -2874,7 +2837,7 @@ my: users: အသုံးပြုသူများ roles: အခန်းကဏ္ဍ code_of_conduct: ကျင့်ဝတ်စည်းမျဥ်း - title: "ဆက်တင် " + title: 'ဆက်တင် ' system_settings: label: စနစ်ချိန်ညှိချက်များ task: @@ -2890,13 +2853,13 @@ my: status: ဖြစ်ရပ်အခြေအနေ statuses: overdue: ရက်ကျော်နေပြီဖြစ် - upcoming_soon: "ပြီးခါနီးပြီ။ " + upcoming_soon: 'ပြီးခါနီးပြီ။ ' type: အရေးယူဆောင်ရွက်မှုအမျိုးအစား types: assessment: အကဲဖြတ်ဆန်းစစ်သုံးသပ်ခြင်း case_plan: ဖြစ်ရပ်အတွက် အစီအစဉ် - follow_up: "နောက်ဆက်တွဲ - %{subtype}" - service: "ဝန်ဆောင်မှု - %{subtype}" + follow_up: နောက်ဆက်တွဲ - %{subtype} + service: ဝန်ဆောင်မှု - %{subtype} tracing_request: label: စုံစမ်းမေးမြန်းသူ၏ ID has_match: တူညီချက်များ ရှိပါသည် @@ -2909,15 +2872,15 @@ my: matches: ကိုက်ညီမှုများ unmatch: မကိုက်ညီပါ messages: - already_matched: "စနစ်တွင် ဤကလေးနှင့် ကိုက်ညီသော အချက်အလက်များရှိ နှစ်ပြီးဖြစ်ပါသည်။ " + already_matched: 'စနစ်တွင် ဤကလေးနှင့် ကိုက်ညီသော အချက်အလက်များရှိ နှစ်ပြီးဖြစ်ပါသည်။ ' disabled: ခြေရာခံတောင်းဆိုမှုကို ပိတ်ထားသည်။ nothing_found: မည်သည့်အရာမျှမှမတွေ့ပါ။ update_success: 'ခြေရာခံမှုတောင်းဆိုမှု %{record_id}ကို နောက်ဆုံးအခြေအနေနှင့်အညီ အောင်မြင်စွာပြင်ဆင်ခဲ့သည်။' creation_success: ခြေရာခံမှုတောင်းဆိုမှုမှတ်တမ်း ကို အောင်မြင်စွာ စတင်ပြုလုပ်ခဲ့သည် update_success_queue: '%{record_id}ခြေရာခံတောင်းဆိုမှုကို နောက်ခံတွင် အောင်မြင်စွာ ပြုပြင်မွမ်းမံပြီးဖြစ်သည်။' creation_success_queue: ခြေရာခံတောင်းဆိုမှုကို နောက်ခံတွင် အောင်မြင်စွာ စတင်ပြုလုပ်ခဲ့သည်။ - match_action: "%{record_id}ဖြစ်ရပ် နှင့် ရှာဖွေမှု%{trace_id} ကိုက်ညီပါသည်။" - unmatch_action: "%{record_id}ဖြစ်ရပ် နှင့် ရှာဖွေမှု %{trace_id}မကိုက်ညီပါသည်။" + match_action: '%{record_id}ဖြစ်ရပ် နှင့် ရှာဖွေမှု%{trace_id} ကိုက်ညီပါသည်။' + unmatch_action: '%{record_id}ဖြစ်ရပ် နှင့် ရှာဖွေမှု %{trace_id}မကိုက်ညီပါသည်။' registry_record: messages: update_success: '%{record_id}မှတ်ပုံတင်မှတ်တမ်းကို အောင်မြင်စွာမွမ်းမံ ပြီးပါပြီ။' @@ -2948,7 +2911,7 @@ my: selected_all_records: 'ဤမေးခွန်းနှင့် ကိုက်ညီသော ခြေရာခံတောင်းဆိုမှုအားလုံးကို ရွေးပါ။%{total_records}' show_tracing_request: 'ခြေရာခံတောင်းဆိုမှု ID%{short_id}' tracing_requests: ခြေရာခံတောင်းဆိုမှုများ - export: "အချက်အလက်ထုတ်ယူခြင်းများ " + export: 'အချက်အလက်ထုတ်ယူခြင်းများ ' registry_records: id: အိုင်ဒီနံပါတ် label: မှတ်ပုံတင်မှတ်တမ်းများ @@ -3034,7 +2997,7 @@ my: disabled: ပိတ်ထားသည် email: အီးမေးလ် full_name: နာမည်အပြည့်အစုံ - identity_provider: "အထောက်အထားပေးသူ " + identity_provider: 'အထောက်အထားပေးသူ ' invalid_provider_username: 'အသုံးပြုသူအမည် Format မမှန်ပါ။ ဥပမာ: my.username@ %{domain}' label: အသုံးပြုသူ language: ဘာသာစကား @@ -3044,8 +3007,8 @@ my: confirmation: သင်ဤအသုံးပြုသူကို ဖျက်ချင်သည်မှာ သေချာပါသလား။ ဖျက်ပြီးသည်များ ပြန်မရနိုင်ပါ။ အသုံးပြုသူကိုဖျက်ရန် OK ကိုနှိပ်ပါ။ created: အသုံးပြုသူကိုအောင်မြင်စွာ စတင်ပြုလုပ်ခဲ့သည် failure: အမှားတစ်ခု ဖြစ်ပွားခဲ့သည်၊ ကျေးဇူးပြု၍ အကူအညီကို ဆက်သွယ်ပါ။ - new_confirm_html: "Primero ကိုအသုံးပြုရန် အသုံးပြုသူကို%{username} %{identity}မှ%{role}အခန်းကဏ္ဍဖြင့် ဖိတ်ကြားတော့မည်ဖြစ်သည်။ အတည်ပြုအီးမေးလ်ကို 4 %{email} သို့ပေးပို့ပါမည်။ ရှေ့ဆက်လိုပါသလား။" - new_confirm_non_identity_html: "Primero ကိုအသုံးပြုရန် အသုံးပြုသူကို%{username} %{role}အခန်းကဏ္ဍဖြင့် ဖိတ်ကြားတော့မည်ဖြစ်သည်။ အတည်ပြုအီးမေးလ်ကို %{email} သို့ပေးပို့ပါမည်။ ရှေ့ဆက်လိုပါသလား။" + new_confirm_html: Primero ကိုအသုံးပြုရန် အသုံးပြုသူကို%{username} %{identity}မှ%{role}အခန်းကဏ္ဍဖြင့် ဖိတ်ကြားတော့မည်ဖြစ်သည်။ အတည်ပြုအီးမေးလ်ကို 4 %{email} သို့ပေးပို့ပါမည်။ ရှေ့ဆက်လိုပါသလား။ + new_confirm_non_identity_html: Primero ကိုအသုံးပြုရန် အသုံးပြုသူကို%{username} %{role}အခန်းကဏ္ဍဖြင့် ဖိတ်ကြားတော့မည်ဖြစ်သည်။ အတည်ပြုအီးမေးလ်ကို %{email} သို့ပေးပို့ပါမည်။ ရှေ့ဆက်လိုပါသလား။ not_found: ပေးထားသောအိုင်ဒီနှင့်တူသည့်အသုံးပြုသူကိုရှာမတွေ့ပါ password_changed_successfully: စကားဝှက်ကိုအောင်မြင်စွာပြောင်းလဲပြီးပါပြီ passwords_do_not_match: လက်ရှိစကားဝှက်နှင့် မကိုက်ညီပါ @@ -3065,10 +3028,10 @@ my: password: စကားဝှက် password_confirmation: စကားဝှက်အတည်ပြုခြင်း။ phone: ဖုန်း - position: " ရာထူး" + position: ' ရာထူး' provider_username_help: 'နမူနာ : my.username@%{domain}' role_id: အခန်းကဏ္ဍ - send_mail: "အီးမေးလ် အသိပေးချက်များကို လက်ခံရရှိပါသလား?" + send_mail: အီးမေးလ် အသိပေးချက်များကို လက်ခံရရှိပါသလား? user_group_unique_ids: အသုံးပြုသူအုပ်စုများ user_name: အသုံးပြုသူအမည် services: ဝန်ဆောင်မှုများ @@ -3137,5 +3100,5 @@ my: admin: locations: selected_records: '%{select_records}... တည်နေရာ(များ)ကို ရွေးထားသည်။' - selected_all_records: "ဤမေးခွန်းနှင့် ကိုက်ညီသော %{total_records} ဖြစ်ရပ်များအားလုံးကို ရွေးပါ။" + selected_all_records: ဤမေးခွန်းနှင့် ကိုက်ညီသော %{total_records} ဖြစ်ရပ်များအားလုံးကို ရွေးပါ။ updated: '%{updated_records}တည်နေရာ(များ)ကို အပ်ဒိတ်လုပ်ပါ' diff --git a/config/locales/ne.yml b/config/locales/ne.yml index a93d7d23f1..e311a66c3b 100644 --- a/config/locales/ne.yml +++ b/config/locales/ne.yml @@ -1,21 +1,8 @@ -# encoding: utf-8 -# -# This is the English localization file for Primero. It is based on the sample -# English localization file found in the repository linked below[1]. -# -# Anyone editing this file is strongly encouraged to use yamllint[2] to ensure -# that this document remains valid YAML. -# -# [1] https://github.com/svenfuchs/rails-i18n/ -# [2] https://yamllint.readthedocs.io/en/stable/ - - ---- ne: 'true': 'हो' 'false': 'होइन ' accepted: स्वीकार गरिएको - cancel: "रद्द " + cancel: 'रद्द ' connection_lost: हाल अफलाईन मोडमा field_mode_offline: हाल फिल्ड मोडमा रहेको connected: जोडिएको @@ -23,20 +10,20 @@ ne: clear: खाली sandbox_ui: डेमो description: विवरण - form: "फारम " + form: 'फारम ' minimum_reportable_fields: "न्यूनतम प्रतिवेदन योग्य क्षेत्रहरु %{record_type}" - name: "नाम " + name: 'नाम ' offline: अफलाईन field_mode: "फिल्ड मोड: %{mode}" field_mode_on: "अन" field_mode_off: "अफ" unavailable_offline: अफलाईन उपलब्ध नभएको - online: "अनलाईन " + online: 'अनलाईन ' yes_label: 'हो' - or_label: "वा," + or_label: वा, select_provider: प्रदायक छनौट गर्नुहोस् select_language: भाषा छनौट गर्नुहोस् - log_in_primero_idp: "%{idp_name} प्रयोगकर्ताको रूपमा लगईन गर्नुहोस्" + log_in_primero_idp: '%{idp_name} प्रयोगकर्ताको रूपमा लगईन गर्नुहोस्' offline_submitted_changes: हाल तपाई अफलाईन हुनुहुन्छ। तपाईले गर्नु भएका परिवर्तनहरू अनलाईन भएपछि पेस हुने छन् । updated: अद्यावधिक भएको go: जानुहोस् @@ -44,9 +31,8 @@ ne: sync: success: "%{records} रेकर्डहरू सफलतापूर्वक सिंक्रोनाइज्ड भयो ।" error: - create: "%{record_type}सिर्जना गर्न असफल भयो । सहयोगका लागि सम्पर्क गर्नुहोस् ।  " - update: "%{record_type}%{short_id}अद्यावधिक असफल भयो । सहयोगका लागि सम्पर्क गर्नुहोस् ।  " - + create: '%{record_type}सिर्जना गर्न असफल भयो । सहयोगका लागि सम्पर्क गर्नुहोस् ।  ' + update: '%{record_type}%{short_id}अद्यावधिक असफल भयो । सहयोगका लागि सम्पर्क गर्नुहोस् ।  ' actions: approvals: स्वीकृति button: कार्यहरू @@ -55,7 +41,7 @@ ne: invalid: अवैध अभिलेख valid: प्रमाणीत अभिलेख disable: निष्क्रिय पार्नुहोस् - enable: "सक्रिय पार्नुहोस् " + enable: 'सक्रिय पार्नुहोस् ' incident_details_from_case: घटना थप्‍नुहोस् incident_from_case: घटना सिर्जना गर्नुहोस् next: अर्को @@ -78,25 +64,25 @@ ne: description: विवरण disabled: निष्क्रिय पारिएको exclude_agency_from_lookups: खोजी तथा छनोटबाट यो निकायलाई हटाउनुहोस् - exclude_agency_from_lookups_help: "यस निकायका प्रयोगकर्ताहरू छैनन् भन्ने कुराको जाँच गर्नुहोस् । (उदाहरणको लागि, लोगो निर्यात गर्न सकियोस भन्नका लागि निकायलाई जोडिएको थियो कि)" + exclude_agency_from_lookups_help: यस निकायका प्रयोगकर्ताहरू छैनन् भन्ने कुराको जाँच गर्नुहोस् । (उदाहरणको लागि, लोगो निर्यात गर्न सकियोस भन्नका लागि निकायलाई जोडिएको थियो कि) label: निकाय - logo_enabled: "प्रिमेरोमा यो निकायको लोगो देखाउन चाहानुहुन्छ ?" - logo_enabled_help: "प्रिमेरोमा यो निकायको लोगो देखाउन चाहानुहुन्छ ?" + logo_enabled: प्रिमेरोमा यो निकायको लोगो देखाउन चाहानुहुन्छ ? + logo_enabled_help: प्रिमेरोमा यो निकायको लोगो देखाउन चाहानुहुन्छ ? logo_icon: लोगो - logo_icon_help: "यो सानो आकारको स्क्रिन, ट्याब्लेट र फोनमा देखा पर्नेछ। यो वर्गाकार हुनुपर्दछ ।" + logo_icon_help: यो सानो आकारको स्क्रिन, ट्याब्लेट र फोनमा देखा पर्नेछ। यो वर्गाकार हुनुपर्दछ । logo_large: ठुलो लोगो logo_large_help: यो ठुलो आकारको स्क्रिन र PDF डाउनलोडमा देखा पर्नेछ । यो उचाइभन्दा लामो लम्बाइ भएको आयतकार हुनुपर्दछ । messages: created: निकाय सफलतापूर्वक सिर्जना भयो updated: निकाय सफलतापूर्वक अद्यावधिक भयो name: निकायको नाम - pdf_logo_option: "PDF डाउनलोडमा लोगो उपलब्ध गराउन चाहानुहुन्छ ?" + pdf_logo_option: PDF डाउनलोडमा लोगो उपलब्ध गराउन चाहानुहुन्छ ? pdf_logo_option_help: 'नोट : प्रयोगकर्ताका लागि निकायको लोगो पूर्वनिर्धारित नै उपलब्ध छन् । त्यसैले तपाईँले यो लोगो सबै प्रयोगकर्ताहरूका लागि उपलब्ध गराउन चाहानु हुन्छ भने मात्र यो जाँच गर्नुहोस् ।' services: निकायको सेवाहरु terms_of_use: प्रयोगको नियम terms_of_use_help: PDF फाईलहरु मात्र समावेश गर्नसकिने terms_of_use_download_button: PDF डाउनलोड गर्नुहोस् - terms_of_use_enabled: "प्रयोगको सर्तहरू प्रदर्शन गर्नुहुन्छ ?" + terms_of_use_enabled: प्रयोगको सर्तहरू प्रदर्शन गर्नुहुन्छ ? approvals: approved_by: स्वीकृत गर्ने case_plan_type_label: घटनाको योजना प्रकार @@ -105,7 +91,7 @@ ne: requested_by: अनुरोध गरिएको requested_for_label: स्वीकृतिको लागि ‌ अनुरोध requested_for_title: स्वीकृति अनुरोध - response_for_label: "स्वीकृतिको लागि " + response_for_label: 'स्वीकृतिको लागि ' response_for_title: स्वीकृति action_plan: कार्ययोजना gbv_closure: GBV समापन @@ -123,12 +109,12 @@ ne: bulk_export: file_name: फाईल record_type: प्रकार - retry: "यो export अवैध छ । कृपया तपाईको export पुन: सिर्जना गर्ने प्रयास गर्नुहोस् ।" + retry: 'यो export अवैध छ । कृपया तपाईको export पुन: सिर्जना गर्ने प्रयास गर्नुहोस् ।' started_on: सुरुवात status: स्थिति form_export: label: Export फारम कन्फिगरेसन - include_hidden: "लुकेका फारमहरू र फिल्डहरुलाई समावेश गर्नुहुन्छ?" + include_hidden: लुकेका फारमहरू र फिल्डहरुलाई समावेश गर्नुहुन्छ? file_name: तपाईको आफ्नै फाईल नाम सिर्जना गर्नुहोस् (वैकल्पिक) success_message: Export फाईल सफलतापूर्वक सिर्जना गरियो buttons: @@ -156,7 +142,7 @@ ne: continue: जारी राख्नुहोस् create_case: घटना सिर्जना गर्नुहोस् create_incident: घटना सिर्जना गर्नुहोस् - create_new_record: "नयाँ %{model}सिर्जना गर्नुहोस्" + create_new_record: नयाँ %{model}सिर्जना गर्नुहोस् delete: मेटाउनुस् disable: असक्षम गर्नुहोस् disable_photo_wall: फोटो वाल निस्कृय पार्नुहोस् @@ -172,7 +158,7 @@ ne: filter_label: 'फिल्टर' filter_restore: प्रणाली सेटिङ पूर्वावस्थामा ल्याउनुहोस् find_tracing_match: ट्रेसिङ जोडा फेला पार्नुहोस् - flag_model: "फ्ल्याग %{model}" + flag_model: फ्ल्याग %{model} flag_records: फ्ल्याग flags: फ्ल्यागहरू guidance: मार्गदर्शन @@ -186,13 +172,13 @@ ne: print: छाप्नुहोस् reassign: तोक्नुहोस् referral: रिफर - referral_again: "पुन : रिफर गर्ने" + referral_again: 'पुन : रिफर गर्ने' reject: अस्वीकार गर्नुहोस् remove_referrals: रिफरलहरु हटाउनुहोस् - reorder: "पुन: क्रमबद्ध गर्नुहोस्" + reorder: 'पुन: क्रमबद्ध गर्नुहोस्' request_approval: स्वीकृतिका लागि अनुरोध request_transfer: स्थानान्तरण अनुरोध गर्नुहोस् - reunite: "पुन: एक गर्नुहोस्" + reunite: 'पुन: एक गर्नुहोस्' save: सुरक्षित गर्नुहोस् save_and_add_service_provision: सुरक्षित गरी सेवा प्रावधान थप्नुहोस् save_and_return: सुरक्षित गरी फिर्ता हुनुहोस् @@ -205,8 +191,8 @@ ne: sync: Sync submit: पेस गर्नुहोस् transfer: स्थान्तरण गर्नुहोस् - unflag_model: "फ्ल्याग हटाउनुहोस् %{model}" - unflag_model_history: "इतिहास फ्ल्याग गर्नुहोस् %{model}" + unflag_model: फ्ल्याग हटाउनुहोस् %{model} + unflag_model_history: इतिहास फ्ल्याग गर्नुहोस् %{model} unmark_for_mobile: मोबाइलका लागि चिह्न हटाउनुहोस् update: अद्यावधिक गर्नुहोस् view: हेर्नुहोस् @@ -229,13 +215,13 @@ ne: back_to_results: नतिजामा फर्किनुहोस् back_to_search: खोजमा फर्किनुहोस् search_by: द्वारा खोजी गर्नुहोस् - search_for: "%{record_type} को लागि खोजी गर्नुहोस्" + search_for: '%{record_type} को लागि खोजी गर्नुहोस्' results: नतिजाहरु details: विवरणहरु select: छनौट गर्नुहोस् deselect: छनौट हटाउनुहोस् enter_id_number: अभिलेख खोजी गर्न आईडी नम्बर प्रविष्ट गर्नुहोस् - id_search_no_results: "\"%{search_query}\" यो प्रणालीमा छैन । कृपया नयाँ अभिलेख सिर्जना गर्नुहोस् ।" + id_search_no_results: '"%{search_query}" यो प्रणालीमा छैन । कृपया नयाँ अभिलेख सिर्जना गर्नुहोस् ।' messages: disabled: घटना निस्क्रिय छ update_success: 'केस %{record_id} सफलतापूर्वक अद्यावधिक गरियो ।  ' @@ -244,15 +230,15 @@ ne: creation_success_queue: 'घटनाको अभिलेख पृष्ठभूमिमा सफलतापूर्वक सिर्जना भयो ।' already_matched: यो जाँचकर्ता पहिले नै तपाईँको घटनासँग मेल खाएको छ । already_matched_not_current_case: यो जाँचकर्तासँग मेल खाने घटना पहिला नै प्रणालीमा छ । - not_found_case: "%{search_value}सँग मिल्दो कुनै पनि घटना फेला परेन। नयाँ घटना सिर्जना गर्नुहोस् ।" + not_found_case: '%{search_value}सँग मिल्दो कुनै पनि घटना फेला परेन। नयाँ घटना सिर्जना गर्नुहोस् ।' introductory_sentence: कृपया घटना व्यवस्थापन सेवाहरू प्राप्त गर्न र तिनीहरूको तथ्याङ्क प्रीमेरोमा भण्डारण गर्न व्यक्तिको सहमति प्राप्त गर्नुहोस् । consent_agreements_required: कृपया सहमति सम्झौताबाट कम्तीमा एउटा विकल्प छान्नुहोस् । legitimate_basis_required: कृपया वैध आधार वर्गीकरणबाट कम्तीमा एउटा विकल्प छान्नुहोस्। save: घटना सुरक्षित गर्नुहोस् - save_text: "अघिबढ्नु पूर्व, कृपया घटनामा तपाइँको परिवर्तनहरू सुरक्षित गर्नुहोस् ।" + save_text: अघिबढ्नु पूर्व, कृपया घटनामा तपाइँको परिवर्तनहरू सुरक्षित गर्नुहोस् । skip_and_create: छोड्नुहोस् र नयाँ घटना सिर्जना गर्नुहोस् search_existing: हाल रहेका घटनाहरू खोजी गर्नुहोस् - search_helper_text: "किन ? डुप्लिकेट घटनाहरू सिर्जना गर्न रोक्न।" + search_helper_text: किन ? डुप्लिकेट घटनाहरू सिर्जना गर्न रोक्न। consent_agreements: लागु हुने सबै सहमती प्राप्त सम्झौताहरू छान्नुहोस् legitimate_basis: लागु हुने सबै वैध आधार वर्गिकरण छनौट गर्नुहोस् workflow: @@ -263,7 +249,7 @@ ne: in_progress: प्रगति ‍भईरहेको new: नयाँ on_label: 'on' - reopened: "पुन: खोलिएको" + reopened: 'पुन: खोलिएको' service_implemented: सेवा लागु गरिएको services_implemented: सेवा लागु गरिएको linkedincidents: @@ -275,7 +261,7 @@ ne: cases: action_plan: कार्ययोजना age: उमेर - age_estimated: "अनुमानित उमेर ?" + age_estimated: अनुमानित उमेर ? agency: निकाय apply_filter: लागु गर्नुहोस् approval_comments: टिप्पणी गर्नुहोस् @@ -294,22 +280,22 @@ ne: case_plan: घटना योजना case_worker_code: केस कार्यकर्ताको कोड clear_filter: खाली गर्नुहोस् - close_dialog: "'ठिक छ' क्लिक गर्दा यो घटनाको स्थिति बन्द हुनेछ ।" + close_dialog: '''ठिक छ'' क्लिक गर्दा यो घटनाको स्थिति बन्द हुनेछ ।' close_dialog_title: घटना बन्द गर्नुहोस् close_success: घटना सफलतापूर्वक बन्द भयो closure: समापन गर्नुहोस् complete: अफलाईन उपलब्ध रहेको date_of_birth: जन्ममिति - disable_dialog: "'ठिक छ' क्लिक गर्दा यो घटनाको स्थिति निस्क्रियमा परिवर्तन हुनेछ ।" + disable_dialog: '''ठिक छ'' क्लिक गर्दा यो घटनाको स्थिति निस्क्रियमा परिवर्तन हुनेछ ।' disable_dialog_title: घटना निस्क्रिय पार्नुहोस् disable_success: सफलतापूर्वक निस्क्रिय पारिएको घटना - enable_dialog: "'ठिक छ' क्लिक गर्दा घटनाको स्थिति सक्रिय हुनेछ ।" + enable_dialog: '''ठिक छ'' क्लिक गर्दा घटनाको स्थिति सक्रिय हुनेछ ।' enable_dialog_title: घटना सक्रिय पार्नुहोस् enable_success: सफलतापूर्वक सक्रिय पारिएको घटना export: Export गर्नुहोस् mark_for_offline: title: अफलाईनको लागि चिन्ह लगाउनुहोस् - text: "तपाई अफलाईन हुँदा प्रयोग गर्नको लागि यी घटनाहरूलाई चिन्ह लगाउन निश्चित हुनुहुन्छ?" + text: तपाई अफलाईन हुँदा प्रयोग गर्नको लागि यी घटनाहरूलाई चिन्ह लगाउन निश्चित हुनुहुन्छ? success: अफलाईन प्रयोगको लागि घटनाहरुमा सफलतापूर्वक चिन्ह लगाईएको filter_by: 3month_inactivity: ३+ महिनाका लागि @@ -329,31 +315,31 @@ ne: by_date: मिति अनुसार case_open_date: घटना शुरु मिति case_plan: घटना योजना - closed: "बन्द " + closed: 'बन्द ' closure: समापन current_location: हालको स्थान - date: "मिति " + date: 'मिति ' displacement_status: विस्थापन स्थिति district: जिल्ला duplicate: दोहोर्‍याउनुहोस् enabled_disabled: सक्रिय पार्नुहोस् / निष्क्रिय पार्नुहोस् female: महिला flag: फ्ल्याग गरिएको - flag_label: "फ्ल्याग गरिएको ?" + flag_label: फ्ल्याग गरिएको ? gbv_closure: GBV समापन गरिएको high: उच्च - low: "न्यून " + low: 'न्यून ' male: पुरुष medium: मध्यम mobile: मोबाइल - mobile_label: "मोबाइलका लागि चिह्न लगाइयो ?" + mobile_label: मोबाइलका लागि चिह्न लगाइयो ? my_cases: मेरो केसहरू no_action: कुनै कारबाही नभएको no_activity: कुनै गतिविधि नभएको open: खोल्नुहोस् other: अन्य photo: तस्बिर - photo_label: "तस्बिर छ ?" + photo_label: तस्बिर छ ? protection_concerns: संरक्षण सवालहरु protection_status: संरक्षण स्थिति record_state: अभिलेख स्थिति @@ -372,11 +358,11 @@ ne: full_name: ‌पूरा नाम gbv_closure: GBV समापन hide_name: नाम लुकाउनुहोस् - hide_name_error: "तपाईँको परिवर्तनहरू सुरक्षित गर्दा एउटा त्रुटि देखा पर्‍यो । कृपया पुन: प्रयास गर्नुहोस् ।" + hide_name_error: 'तपाईँको परिवर्तनहरू सुरक्षित गर्दा एउटा त्रुटि देखा पर्‍यो । कृपया पुन: प्रयास गर्नुहोस् ।' id: आईडी# label: घटनाहरू my_filters: मेरो फिल्टर - name: " नाम " + name: ' नाम ' notes_dialog_title: नोटहरू थप्‍नुहोस् notes_form_notes: नोटहरू notes_form_subject: विषय @@ -384,19 +370,19 @@ ne: order_by: label: क्रम अनुसार most_recently: हालैसालैको - name: " नाम " + name: ' नाम ' owned_by: अभिलेखकर्ता owned_by_agency: अभिलेखवाला निकाय photo: तस्बिर photos: तस्बिर quick_view: tracing_message: 'नोट: प्रणालीमा यस बच्चाको बारे पहिलैनै खोजी भएको छ । यदि बच्चाले चाहान्छ भने थप कारबाहीका लागि यो अभिलेखको सामाजिक कार्यकर्तालाई सम्पर्क गर्नुहोस् ।' - referral_done: "\"सम्पन्न\" क्लिक गर्दा तपाईले यस घटनासँग सम्बन्धित रिफरल कार्य पूरा गर्नुभएको सङ्केत गर्दछ । \"सम्पन्न\" क्लिक गरेपछि अब तपाइले यो अभिलेखमा पहुँच पाउनु हुने छैन।" + referral_done: '"सम्पन्न" क्लिक गर्दा तपाईले यस घटनासँग सम्बन्धित रिफरल कार्य पूरा गर्नुभएको सङ्केत गर्दछ । "सम्पन्न" क्लिक गरेपछि अब तपाइले यो अभिलेखमा पहुँच पाउनु हुने छैन।' referral_done_success: रिफरल गरियो referral_accepted_header: रिफरल स्वीकार गर्नुहोस् - referral_accepted: "यस रेफरलसँग सम्बन्धित कार्य पूरा गर्नका लागि अब तपाई जिम्मेवार हुनुहुनेछ । के तपाई यो कार्यको लागि निश्चित हुनुहुन्छ ?" + referral_accepted: यस रेफरलसँग सम्बन्धित कार्य पूरा गर्नका लागि अब तपाई जिम्मेवार हुनुहुनेछ । के तपाई यो कार्यको लागि निश्चित हुनुहुन्छ ? referral_accepted_success: रिफरल स्वीकृत भयो - referral_rejected: "'अस्वीकार' मा क्लिक गरेर तपाईले यो रिफरलको जिम्मेवारी, यो समयमा स्वीकार गर्न तयार हुनुहुन्न भन्ने कुरा सङ्केत गरिरहनुभएको छ । कृपया तपाईले यो रिफर अस्वीकार गर्दै हुनुहुन्छ भन्ने कारण प्रविष्ट गर्नुहोस् । 'अस्वीकार गर्नुहोस्' क्लिक गरेपछि तपाईले अब यो घटना अभिलेखमा पहुँच प्राप्त गर्न सक्नुहुने छैन ।" + referral_rejected: '''अस्वीकार'' मा क्लिक गरेर तपाईले यो रिफरलको जिम्मेवारी, यो समयमा स्वीकार गर्न तयार हुनुहुन्न भन्ने कुरा सङ्केत गरिरहनुभएको छ । कृपया तपाईले यो रिफर अस्वीकार गर्दै हुनुहुन्छ भन्ने कारण प्रविष्ट गर्नुहोस् । ''अस्वीकार गर्नुहोस्'' क्लिक गरेपछि तपाईले अब यो घटना अभिलेखमा पहुँच प्राप्त गर्न सक्नुहुने छैन ।' referral_rejected_success: रिफरल अस्वीकृत भयो register_new_case: नयाँ घटना registration_date: दर्ता मिति @@ -406,27 +392,27 @@ ne: rejected_success_case_plan: '%{approval_label} - स्वीकृत नभएको' rejected_success_closure: '%{approval_label} - स्वीकृत नभएको' rejected_success_gbv_closure: '%{approval_label} - स्वीकृत नभएको' - reopen_dialog: "'ठिक छ' क्लिक गर्दा यो केसको स्थिति खुल्ला हुनेछ ।" - reopen_dialog_title: "घटना पुन: सुरुगर्नुहोस्" - reopen_success: "घटना सफलतापूर्वक पुन: सुरुगरियो" - request_approval_failure: "एउटा त्रुटि देखा पर्‍यो, कृपया सहयोगका लागि सम्पर्क गर्नुहोस्" + reopen_dialog: '''ठिक छ'' क्लिक गर्दा यो केसको स्थिति खुल्ला हुनेछ ।' + reopen_dialog_title: 'घटना पुन: सुरुगर्नुहोस्' + reopen_success: 'घटना सफलतापूर्वक पुन: सुरुगरियो' + request_approval_failure: एउटा त्रुटि देखा पर्‍यो, कृपया सहयोगका लागि सम्पर्क गर्नुहोस् request_approval_select: स्वीकृतिका लागि सहयोग अनुरोध गर्नुहोस् - request_approval_success_action_plan: "%{approval_label}फारम स्वीकृतिको लागि अनुरोध गरिएको छ" - request_approval_success_assessment: "%{approval_label}फारम स्वीकृतिको लागि अनुरोध गरिएको छ" - request_approval_success_case_plan: "%{approval_label} फारम स्वीकृतिको लागि अनुरोध गरिएको छ" - request_approval_success_closure: "%{approval_label} फारम स्वीकृतिको लागि अनुरोध गरिएको छ" - request_approval_success_gbv_closure: "%{approval_label} फारम स्वीकृतिको लागि अनुरोध गरिएको छ" + request_approval_success_action_plan: '%{approval_label}फारम स्वीकृतिको लागि अनुरोध गरिएको छ' + request_approval_success_assessment: '%{approval_label}फारम स्वीकृतिको लागि अनुरोध गरिएको छ' + request_approval_success_case_plan: '%{approval_label} फारम स्वीकृतिको लागि अनुरोध गरिएको छ' + request_approval_success_closure: '%{approval_label} फारम स्वीकृतिको लागि अनुरोध गरिएको छ' + request_approval_success_gbv_closure: '%{approval_label} फारम स्वीकृतिको लागि अनुरोध गरिएको छ' request_approval_type_of_case_plan: घटना योजना स्वीकृतिका प्रकारहरू - request_approve_action_plan: "कार्य योजना ‌स्वीकृत गर्नुहुन्छ ?" - request_approve_bia: "मूल्याङ्कन स्वीकृत गर्नुहुन्छ ?" - request_approve_case_plan: "घटना योजना स्वीकृत गर्नुहुोस ?" - request_approve_closure: "समापन गर्न अनुमति दिन्छ?" - request_approve_gbv_closure: "GBV समापन गर्न अनुमति दिनुहुन्छ ?" - revoke_failure: "%{transition_type} रद्द गर्दा एउटा त्रुटि देखापर्यो, कृपया सहयोगको लागि सम्पर्क गर्नुहोस्।" - revoke_message: "\" रद्द गर्नुहोस्\" क्लिक गरेर, तपाईँले घटनामा %{transition_type} प्रापकको पहुँच हटाउनु हुनेछ ।" - revoke_success_message: "%{case_id}%{transition_type}घटना लाई %{recipient_username}रद्द गर्नुपर्ने " + request_approve_action_plan: कार्य योजना ‌स्वीकृत गर्नुहुन्छ ? + request_approve_bia: मूल्याङ्कन स्वीकृत गर्नुहुन्छ ? + request_approve_case_plan: घटना योजना स्वीकृत गर्नुहुोस ? + request_approve_closure: समापन गर्न अनुमति दिन्छ? + request_approve_gbv_closure: GBV समापन गर्न अनुमति दिनुहुन्छ ? + revoke_failure: '%{transition_type} रद्द गर्दा एउटा त्रुटि देखापर्यो, कृपया सहयोगको लागि सम्पर्क गर्नुहोस्।' + revoke_message: '" रद्द गर्नुहोस्" क्लिक गरेर, तपाईँले घटनामा %{transition_type} प्रापकको पहुँच हटाउनु हुनेछ ।' + revoke_success_message: '%{case_id}%{transition_type}घटना लाई %{recipient_username}रद्द गर्नुपर्ने ' save_filter: सुरक्षित गर्नुहोस् - selected_all_records: "यो प्रश्नसँग मिल्ने सबै %{total_records} घटनाहरू छनौट गर्नुहोस्" + selected_all_records: यो प्रश्नसँग मिल्ने सबै %{total_records} घटनाहरू छनौट गर्नुहोस् selected_records: '%{select_records} घटना(हरु) छनौट गरिएको ' sex: लिङ्ग show_case: 'घटना आईडी : %{short_id}' @@ -443,12 +429,12 @@ ne: label: ट्रेसिंगका लागि सूचनाहरू प्रदान गर्न अनुमति प्राप्त भएको छ । help_text: यदि यो क्षेत्र "होइन" भएमा बालबालिकाको घटना अभिलेख ट्रेसिङ अनुरोधको खोजमा देखिनेछैन । wishes_child_family_tracing: - label: "के बच्चाले परिवारका सदस्यहरूलाई पत्ता लगाउन चाहन्छ ?" + label: के बच्चाले परिवारका सदस्यहरूलाई पत्ता लगाउन चाहन्छ ? wishes_reunification: - label: "के बच्चा परिवार पुनर्मिलन चाहन्छ ?" + label: के बच्चा परिवार पुनर्मिलन चाहन्छ ? options: - yes_as_soon_as_possible: "हो, जति सक्दो चाँडो" - yes_but_later: "हो, तर पछि" + yes_as_soon_as_possible: हो, जति सक्दो चाँडो + yes_but_later: हो, तर पछि not_sure: निश्चित छैन 'no': 'होइन' data_confidentiality_link: @@ -456,13 +442,13 @@ ne: child_wishes_link: label: बच्चाको इच्छाहरू हेर्नुहोस् survivor_code: Survivor कोड - transfer_accepted: "\"स्वीकार गर्नुहोस्\" क्लिक गरेर तपाई यस घटनाको लागि जिम्मेवारी स्वीकार गर्नुहुन्छ । एक पटक तपाई \"स्वीकार गर्नुहोस्\" क्लिक गरेपछि तपाई प्रणालीमा रहेको अभिलेखको स्वामित्व ग्रहण गर्नुहुनेछ । " - transfer_managed_user_accepted: "यदि तपाईले 'स्वीकार गर्नुहोस्' क्लिक गर्नुभयो भने, %{transitioned_to} यस घटनाको लागि जिम्मेवार हुनेछ; तपाईले 'स्वीकार गर्नुहोस्' क्लिक गरेपछि, %{transitioned_to}प्रणालीमा रेकर्ड मालिक बन्नुहुनेछ।" - transfer_managed_user_rejected: "'अस्वीकार गर्नुहोस्' मा क्लिक गरेर तपाईले %{transitioned_to} ले यो घटनाको जिम्मेवारी स्वीकार गर्न तयार नभएको संकेत गरिरहनुभएको छ। तपाईले यो घटना अस्वीकार गरिरहनुभएको कारण प्रविष्टि गर्नुहोस्; एकचोटि तपाईले 'अस्वीकार गर्नुहोस्' क्लिक गरेपछि %{transitioned_to} सँग यो घटनाको पहुँच हुनेछैन।" - transfer_accepted_rejected: "%{record_id} घटनाको स्थानान्तरण अस्वीकार गरियो" + transfer_accepted: '"स्वीकार गर्नुहोस्" क्लिक गरेर तपाई यस घटनाको लागि जिम्मेवारी स्वीकार गर्नुहुन्छ । एक पटक तपाई "स्वीकार गर्नुहोस्" क्लिक गरेपछि तपाई प्रणालीमा रहेको अभिलेखको स्वामित्व ग्रहण गर्नुहुनेछ । ' + transfer_managed_user_accepted: यदि तपाईले 'स्वीकार गर्नुहोस्' क्लिक गर्नुभयो भने, %{transitioned_to} यस घटनाको लागि जिम्मेवार हुनेछ; तपाईले 'स्वीकार गर्नुहोस्' क्लिक गरेपछि, %{transitioned_to}प्रणालीमा रेकर्ड मालिक बन्नुहुनेछ। + transfer_managed_user_rejected: '''अस्वीकार गर्नुहोस्'' मा क्लिक गरेर तपाईले %{transitioned_to} ले यो घटनाको जिम्मेवारी स्वीकार गर्न तयार नभएको संकेत गरिरहनुभएको छ। तपाईले यो घटना अस्वीकार गरिरहनुभएको कारण प्रविष्टि गर्नुहोस्; एकचोटि तपाईले ''अस्वीकार गर्नुहोस्'' क्लिक गरेपछि %{transitioned_to} सँग यो घटनाको पहुँच हुनेछैन।' + transfer_accepted_rejected: '%{record_id} घटनाको स्थानान्तरण अस्वीकार गरियो' transfer_accepted_success: केस स्थानान्तरण सफलतापूर्वक स्वीकार गरियो transfer_reject_reason_label: अस्वीकारको कारण - transfer_rejected: "\"अस्वीकार गर्नुहोस्\" क्लिक गरेर तपाईले यो समयमा यो घटनाको जिम्मेवारी स्वीकार गर्न तयार हुनुहुन्न भन्ने सङ्केत गर्दै हुनुहुन्छ । कृपया तपाईले यो घटना अस्वीकार गर्दै हुनुहुन्छ भन्ने एउटा कारण प्रविष्ट गर्नुहोस् । \"अस्वीकार गर्नुहोस्\" क्लिक गरेपछि तपाईले अब यो घटना अभिलेखमा पहुँच प्राप्त गर्न सक्नुहुने छैन ।" + transfer_rejected: '"अस्वीकार गर्नुहोस्" क्लिक गरेर तपाईले यो समयमा यो घटनाको जिम्मेवारी स्वीकार गर्न तयार हुनुहुन्न भन्ने सङ्केत गर्दै हुनुहुन्छ । कृपया तपाईले यो घटना अस्वीकार गर्दै हुनुहुन्छ भन्ने एउटा कारण प्रविष्ट गर्नुहोस् । "अस्वीकार गर्नुहोस्" क्लिक गरेपछि तपाईले अब यो घटना अभिलेखमा पहुँच प्राप्त गर्न सक्नुहुने छैन ।' view_name: नाम हेर्नुहोस् sort_by: क्रमबद्ध गर्नुहोस् change_logs: @@ -489,21 +475,21 @@ ne: date_of_creation: सिर्जना गरेको मिति registration_date: दर्ता भएको मिति configurations: - apply_label: "के तपाई निश्चित हुनुहुन्छ ? यदि तपाईले लागु गर्नुभयो भने, यो कन्फिगरेसनको सेटिङ प्रणालीमा लागु गरिने छ । तपाईको हालका सबै सेटिङ हराउनु हुने छ र तपाईले तिनीहरूलाई अर्को कन्फिगरेसनमा पहिल्यै सुरक्षित नगरेसम्म तिनीहरूलाई फिर्ता प्राप्त गर्न सक्षम हुनुहुने छैन ।" - apply_label_bold: "परिवर्तन लोड हुँदा प्रीमेरो, प्रयोगकर्ताका लागि केही मिनेटका लागि उपलब्ध हुने छैन ।" - version_mismatch_tooltip: "तपाईले यो कन्फिगरेसन लागु गर्न सक्नुहुन्न किनकि तपाईको हाल चलिरहेकोभन्दा उच्च संस्करणको प्रीमेरो प्रयोग गरेर सिर्जना गरिएको थियो । तपाईले प्रीमेरोको नयाँ संस्करण नचलाएसम्म कृपया यो कन्फिगरेसन लागु गर्न प्रतीक्षा गर्नुहोस् । " + apply_label: के तपाई निश्चित हुनुहुन्छ ? यदि तपाईले लागु गर्नुभयो भने, यो कन्फिगरेसनको सेटिङ प्रणालीमा लागु गरिने छ । तपाईको हालका सबै सेटिङ हराउनु हुने छ र तपाईले तिनीहरूलाई अर्को कन्फिगरेसनमा पहिल्यै सुरक्षित नगरेसम्म तिनीहरूलाई फिर्ता प्राप्त गर्न सक्षम हुनुहुने छैन । + apply_label_bold: परिवर्तन लोड हुँदा प्रीमेरो, प्रयोगकर्ताका लागि केही मिनेटका लागि उपलब्ध हुने छैन । + version_mismatch_tooltip: 'तपाईले यो कन्फिगरेसन लागु गर्न सक्नुहुन्न किनकि तपाईको हाल चलिरहेकोभन्दा उच्च संस्करणको प्रीमेरो प्रयोग गरेर सिर्जना गरिएको थियो । तपाईले प्रीमेरोको नयाँ संस्करण नचलाएसम्म कृपया यो कन्फिगरेसन लागु गर्न प्रतीक्षा गर्नुहोस् । ' send_header: प्रोडक्सनमा पठाउनुहोस् - send_text: "के तपाई निश्चित हुनुहुन्छ ? यदि तपाईले 'पठाउनुहोस्' क्लिक गर्नुभयो भने तपाईले यो कन्फिगरेसन प्रोडक्सन साइटमा पठाउनु हुनेछ । त्यो साइटको प्रशासकले यसलाई म्यानुअल रूपमा लागु नगरेसम्म यो कन्फिगरेसन उत्पादनमा लागु गरिने छैन ।" + send_text: के तपाई निश्चित हुनुहुन्छ ? यदि तपाईले 'पठाउनुहोस्' क्लिक गर्नुभयो भने तपाईले यो कन्फिगरेसन प्रोडक्सन साइटमा पठाउनु हुनेछ । त्यो साइटको प्रशासकले यसलाई म्यानुअल रूपमा लागु नगरेसम्म यो कन्फिगरेसन उत्पादनमा लागु गरिने छैन । attributes: - created_by: "सिर्जना गर्ने :" + created_by: 'सिर्जना गर्ने :' date_created: सिर्जना गरिएको मिति description: विवरण - last_applied_by: "अन्तिम पटक लागु गर्ने :" + last_applied_by: 'अन्तिम पटक लागु गर्ने :' last_applied_on: मा अन्तिम पटक लागु गरिएको - name: " नाम " + name: ' नाम ' version: कन्फिगरेसन संस्करण primero_version: प्राइमरो संस्करण - delete_label: "तपाई यो कार्य गर्न निश्चित हुनुहुन्छ ? यसले कन्फिगरेसन सिर्जना भएको समयदेखि सबै सेटिङको प्रतिनिधित्व गर्दछ । तपाईले यो कन्फिगरेसन मेटनु भयो भने यी सेटिङहरू पुन: प्राप्त गर्न सक्नुहुने छैन ।" + delete_label: 'तपाई यो कार्य गर्न निश्चित हुनुहुन्छ ? यसले कन्फिगरेसन सिर्जना भएको समयदेखि सबै सेटिङको प्रतिनिधित्व गर्दछ । तपाईले यो कन्फिगरेसन मेटनु भयो भने यी सेटिङहरू पुन: प्राप्त गर्न सक्नुहुने छैन ।' explanation: '"सुरक्षित" क्लिक गर्दा यो समयमा हालको सबै कन्फिगरेसन सेटिङ (उदाहरणका लागि : ‌भूमिका, एजेन्सी, फारम) को अभिलेख सिर्जना हुने छ । सुरक्षित गरेपछि, तपाईले यी परिवर्तनहरूलाई प्रीमेरोको अर्को संस्करणमा पठाउन सक्नुहुन्छ । यदि, भविष्यमा, तपाईले पूर्वस्थितिमा फर्काउन चाहेर कन्फिगरेसन परिवर्तन गरेमा, तपाईले यो बेलामा भएको सबै कन्फिगरेसन परिवर्तनहरू पूर्वावस्थामा ल्याउन यो कन्फिगरेसन अभिलेखबाट गर्न सक्नुहुन्छ ।' label: कन्फिगरेसन label_new: नयाँ कन्फिगरेसन @@ -539,28 +525,28 @@ ne: updated: आचार संहिता सफलतापूर्वक अद्यावधिक गरियो । dashboard: activity: क्रियाकलाप - admin_only: "आवेदनमा परिवर्तन गर्न %{links}मा क्लिक गर्नुहोस्" + admin_only: आवेदनमा परिवर्तन गर्न %{links}मा क्लिक गर्नुहोस् all_cases: सबै घटनाहरू all_services_implemented: सबै सेवाहरू कार्यान्वयन गरियो and: 'र' approval_action_plan_approved: स्वीकृत - approval_action_plan_pending: "विचाराधीन " + approval_action_plan_pending: 'विचाराधीन ' approval_action_plan_pending_group: कार्य योजना approval_action_plan_rejected: अस्वीकृत approval_assessment_approved: स्वीकृत - approval_assessment_pending: "विचाराधीन " + approval_assessment_pending: 'विचाराधीन ' approval_assessment_pending_group: मूल्याङ्कन गर्नुहोस् approval_assessment_rejected: अस्वीकृत approval_case_plan_approved: स्वीकृत - approval_case_plan_pending: "विचाराधीन " + approval_case_plan_pending: 'विचाराधीन ' approval_case_plan_pending_group: घटना योजना approval_case_plan_rejected: अस्वीकृत approval_closure_approved: स्वीकृत - approval_closure_pending: "विचाराधीन " + approval_closure_pending: 'विचाराधीन ' approval_closure_pending_group: समापन approval_closure_rejected: अस्वीकृत approval_gbv_closure_approved: स्वीकृत - approval_gbv_closure_pending: "विचाराधीन " + approval_gbv_closure_pending: 'विचाराधीन ' approval_gbv_closure_pending_group: GBV समापन approval_gbv_closure_rejected: अस्वीकृत approvals: अनुमतिहरू @@ -572,7 +558,7 @@ ne: approved: स्वीकृत assessment: मूल्याङ्कन गर्नुहोस् awaiting_acceptance: स्वीकृति पर्खिरहेको छ - cases_by_social_worker_total: "जम्मा " + cases_by_social_worker_total: 'जम्मा ' cases_by_social_worker_new_or_updated: नयाँ र अद्यावधिक case_id: 'घटना आइ डी#' case_management_service: घटना व्यवस्थापन सेवा @@ -583,10 +569,10 @@ ne: case_stat_by_assessment_level: मूल्याङ्कनस्तर अनुसार घटनाहरु case_stat_referrals: रिफरलहरु case_stats: घटनाहरू - case_worker: "घटना कामदार " + case_worker: 'घटना कामदार ' cases_by_social_worker: सामाजिक कार्यकर्ता अनुसार घटनाहरु cases_by_task_overdue: म्याद नाघेको कार्य - cases_by_workflow: "कार्य प्रवाह अनुसार घटनाहरू " + cases_by_workflow: 'कार्य प्रवाह अनुसार घटनाहरू ' cases_this_week: यो हप्ताका घटनाहरू cases_to_assign: जिम्मेवारी तोक्नुपर्ने घटना closed: बन्द गरिएको @@ -603,17 +589,17 @@ ne: one: '%{stat}नयाँ %{stat_type} स्वीकृतिहरू' other: '%{stat}नयाँ %{stat_type} स्वीकृतिहरू' count_pending_approval_total: - one: 'तपाईंँसित %{stat}विचाराधीन स्वीकृतिहरू %{stat_type}छन् ।' - other: 'तपाईसँग %{stat} विचाराधीन %{stat_type}स्वीकृतिहरू छन् ।' + one: तपाईंँसित %{stat}विचाराधीन स्वीकृतिहरू %{stat_type}छन् । + other: तपाईसँग %{stat} विचाराधीन %{stat_type}स्वीकृतिहरू छन् । count_pending_transfers: - one: 'तपाईंँसित %{stat}विचाराधीन स्थानान्तरणहरू छन्। ' - other: 'तपाईसँग %{stat}विचाराधीन स्थानान्तरणहरू छन् ।' + one: तपाईंँसित %{stat}विचाराधीन स्थानान्तरणहरू छन्।  + other: तपाईसँग %{stat}विचाराधीन स्थानान्तरणहरू छन् । count_records_new: one: र %{stat}नयाँ केस  other: र %{stat}नयाँ केसहरु count_records_total: one: 'तपाईंँसित जम्मा %{stat}केसहरू छन्। ' - other: 'तपाईसँग %{stat}जम्मा केसहरू छन्' + other: तपाईसँग %{stat}जम्मा केसहरू छन् count_referrals_new: one: र %{stat} नयाँ रेफेरलहरू other: 'र %{stat}नयाँ रेफेरलहरू ' @@ -621,18 +607,18 @@ ne: one: 'तपाईंँसित %{stat}जम्मा रेफेरलहरू छन्। ' other: 'तपाईसँग जम्मा %{stat}रेफेरलहरू छन्। ' count_rejected_approval_total: - one: 'र %{stat}अस्वीकृत %{stat_type}स्वीकृति' + one: र %{stat}अस्वीकृत %{stat_type}स्वीकृति other: '%{stat}र अस्वीकृत %{stat_type}स्वीकृतिहरू' count_rejected_transfers: - one: 'तपाईंँसित %{stat}अस्वीकृत रेफेरलहरू छन्।' - other: 'र %{stat}अस्वीकृत स्थानान्तरणहरू' + one: तपाईंँसित %{stat}अस्वीकृत रेफेरलहरू छन्। + other: र %{stat}अस्वीकृत स्थानान्तरणहरू count_risk_level_new: one: 'र %{stat}नयाँ%{stat_type}जोखिम केसहरू ' other: 'र %{stat}नयाँ %{stat_type}जोखिम केसहरू ' count_risk_level_total: - one: 'तपाईंँसित %{stat} %{stat_type}जोखिम केसहरू छन्। ' - other: 'तपाईसँग %{stat} %{stat_type}जोखिम केसहरू छन्।' - count_waiting_for_acceptance_transfers: "%{stat}स्थानान्तरणको लागि तपाईँले स्वीकृतिको प्रतीक्षा रहेको छ" + one: तपाईंँसित %{stat} %{stat_type}जोखिम केसहरू छन्।  + other: तपाईसँग %{stat} %{stat_type}जोखिम केसहरू छन्। + count_waiting_for_acceptance_transfers: '%{stat}स्थानान्तरणको लागि तपाईँले स्वीकृतिको प्रतीक्षा रहेको छ' current_owner: हालको मालिक dash_case_incident_overview: मेरो केसहरू dash_group_overview: मेरो समूहको केसहरू @@ -671,15 +657,15 @@ ne: low_level: न्यून low_risk: न्यून प्राथमिकता manager_count_closed_total: - one: 'र %{stat}बन्द केसहरू' - other: 'र %{stat}बन्द केसहरू' + one: र %{stat}बन्द केसहरू + other: र %{stat}बन्द केसहरू manager_count_open_total: - one: 'तपाईंँसित %{stat}खुल्ला केसहरू छन्। ' + one: तपाईंँसित %{stat}खुल्ला केसहरू छन्।  other: 'तपाईसँग %{stat} खुल्ला केसहरू छन्।  ' manager_transfers_totals: - one: 'तपाईंँसित %{stat}%{stat_type} स्थानान्तरणहरू छन्। ' - other: 'तपाईसँग %{stat}%{stat_type} स्थानान्तरणहरू छन्।' - match_result: "मिलदो नतिजा " + one: तपाईंँसित %{stat}%{stat_type} स्थानान्तरणहरू छन्।  + other: तपाईसँग %{stat}%{stat_type} स्थानान्तरणहरू छन्। + match_result: 'मिलदो नतिजा ' medium_level: मध्यम medium_risk: मध्यम प्राथमिकता missed_cases: छुटेका घटनाहरू @@ -710,22 +696,22 @@ ne: number_of_violations_verified: उल्लङ्घन प्रमाणित भएको open: खोल्नुहोस् open_cases: घटनाहरू खोल्नुहोस् - open_incidents: "खुला घटना " + open_incidents: 'खुला घटना ' outstanding_transfers: Outstanding ट्रान्सफर overdue_activities: म्याद नाघेका क्रियाकलापहरू overdue_cases_to_assign: तोकिनुपर्ने म्याद नाघेका घटनाहरू overdue_cases_to_assign_high: तपाई सँग यी घटनाहरू १ घण्टा भन्दा बढी देखी रहेको छ । overdue_cases_to_assign_low: तपाई सँग यी घटनाहरू ३ घण्टा भन्दा बढी देखी रहेको छ । overview: अवलोकन - pending: "विचाराधीन " + pending: 'विचाराधीन ' pending_approvals: विचाराधीन स्वीकृति pending_transfers: विचाराधीन स्थानान्तरण protection_concern: संरक्षण सवालहरु protection_concerns: संरक्षण सवालहरु range12+: १२+ - range4: "०-४ " + range4: '०-४ ' range4_8: ४-८ - range8_12: "८-१२ " + range8_12: '८-१२ ' recent_activities: हालका गतिविधिहरू recently_flagged_child: हालसालै फ्ल्याग गरिएका घटनाहरू recently_flagged_incident: हालसालै फ्ल्याग गरिएका घटनाहरू @@ -744,7 +730,7 @@ ne: shared_from_my_team_rejected_transfers: अस्वीकृत स्थानान्तरणहरू shared_with_me_new_referrals: नयाँ रेफेरलहरू shared_with_me_total_referrals: जम्मा रेफेरलहरू - shared_with_me_transfers_awaiting_acceptance: "स्वीकृतिको प्रतीक्षामा स्थानान्तरणहरू " + shared_with_me_transfers_awaiting_acceptance: 'स्वीकृतिको प्रतीक्षामा स्थानान्तरणहरू ' shared_with_my_team_pending_transfers_overview: स्थानान्तरण स्वीकृतिको लागि पर्खिरहेको छ shared_with_my_team_pending_transfers: विचाराधीन स्थानान्तरणहरू shared_with_my_team_referrals: रेफेरलहरू @@ -803,18 +789,16 @@ ne: password_extra_info: पासवर्ड कम्‍तीमा ८अक्षरको हुनुपर्छ । यो पासवर्ड export गरिएको फाइलसँग सम्बन्धित हुने छ र भविष्यमा यो फाइल खोल्ने जोसुकैद्वारा प्रविष्ट गर्नुपर्ने छ । password_label: कृपया तपाईको फाइल encrypt गर्ने पासवर्ड प्रविष्ट गर्नुहोस् । error_message: - address_fields: "तपाईले %{forms} फारमका %{fields} फिल्डहरूलाई सम्बोधन गर्न आवश्यक छ" - address_form_fields: "तपाईले फारमका %{fields} क्षेत्रहरूलाई सम्बोधन गर्न आवश्यक छ" + address_fields: तपाईले %{forms} फारमका %{fields} फिल्डहरूलाई सम्बोधन गर्न आवश्यक छ + address_form_fields: तपाईले फारमका %{fields} क्षेत्रहरूलाई सम्बोधन गर्न आवश्यक छ address_subform_fields: '%{subform} मा %{fields} अवैध फिल्डहरु छन्' error_page: not_authorized: - code: 403 server_error: तपाईलाई यो पृष्ठमा पहुँच राख्न अधिकार प्राप्त छैन । title: अधिकार प्राप्त छैन not_found: - code: 404 - contact_admin: "यदि तपाई त्रुटिको कारण यहाँ छु भन्ने लाग्छ छ भने, कृपया तपाईको एडमिनसँग सम्पर्क गर्नुहोस् ।" - something_went_wrong: "माफ गर्नुहोस्, केही त्रुटि भयो" + contact_admin: यदि तपाई त्रुटिको कारण यहाँ छु भन्ने लाग्छ छ भने, कृपया तपाईको एडमिनसँग सम्पर्क गर्नुहोस् । + something_went_wrong: माफ गर्नुहोस्, केही त्रुटि भयो errors: error_loading: रेकर्ड(हरु) लोड गर्दा त्रुटि models: @@ -828,23 +812,23 @@ ne: date_of_birth: कृपया यो घटना अभिलेखका लागि वैध जन्ममिति प्रविष्ट गर्नुहोस् । export_configuration: opt_out_field_does_not_exist: निर्दिष्ट opt_out क्षेत्र अभिलेखमा छैन । - record_type: "अवैध अभिलेख प्रकार। बालबालिका, ट्रेसिङ अनुरोध वा घटना हुनैपर्छ। " + record_type: 'अवैध अभिलेख प्रकार। बालबालिका, ट्रेसिङ अनुरोध वा घटना हुनैपर्छ। ' field: - translated_options_do_not_match: "फिल्ड अनुवाद गरिएको विकल्पमा उस्तै आईडी हुनुपर्दछ । " + translated_options_do_not_match: 'फिल्ड अनुवाद गरिएको विकल्पमा उस्तै आईडी हुनुपर्दछ । ' location: admin_level_present: खाली हुनु हुँदैन code_present: खाली हुनु हुँदैन name_present: खाली हुनु हुँदैन - unique_location_code: "त्यो लोकेसन कोड भएको स्थान पहिलै ने अवस्थित छ, कृपया फरक लोकेसन कोड प्रविष्ट गर्नुहोस् ।" + unique_location_code: त्यो लोकेसन कोड भएको स्थान पहिलै ने अवस्थित छ, कृपया फरक लोकेसन कोड प्रविष्ट गर्नुहोस् । lookup: being_used: यो खोजी भइरहेको छ र मेट्न सकिँदैन । name_present: नाम खाली हुनु हुँदैन - values_ids_blank: " एउटा lookup_value आईडी खाली छ" + values_ids_blank: ' एउटा lookup_value आईडी खाली छ' primero_module: associated_record_types: कम्‍तीमा एउटा अभिलेख प्रकार यो मोड्युलसँग सम्बन्धित हुनुपर्दछ form_section_ids: ‌कम्तीमा एउटा फारम यो मोड्युलसँग सम्बन्धित हुनुपर्दछ name_present: नाम खाली हुनु हुँदैन - unique_name: "त्यो नामको मोड्युल पहिल्यै रहेको छ, कृपया फरक नाम प्रविष्ट गर्नुहोस् ।" + unique_name: त्यो नामको मोड्युल पहिल्यै रहेको छ, कृपया फरक नाम प्रविष्ट गर्नुहोस् । report: module_presence: मोड्युल खाली हुनु ‌हुँदैन module_syntax: सबै प्रतिवेदन मोड्युल पहिल्यै रहेको हुनुपर्दछ @@ -854,7 +838,7 @@ ne: user: email: "कृपया वैध इमेल प्रविष्ट गर्नुहोस् (उदाहरण: 'name@example.org')" password_mismatch: पासवर्ड क्षेत्रमा प्रविष्टि गरिएको पासवर्ड समान छैन - password_length: "पासवर्ड कम्तीमा %{min} अक्षरको हुनुपर्दछ" + password_length: पासवर्ड कम्तीमा %{min} अक्षरको हुनुपर्दछ email_uniqueness: यो इमेल भएको प्रयोगकर्ता पहिले नै हुनुहुन्छ । कृपया भिन्न इमेल प्रविष्ट गर्नुहोस् । code_of_conduct: title_present: शीर्षक खाली हुनु हुँदैन @@ -875,7 +859,7 @@ ne: all: कस्टम custom_exports: all: कस्टम - choose_fields: "के तपाई फारमका लागि एउटा-एउटा गरी फिल्डहरु रोज्न चाहनु हुन्छ ?" + choose_fields: के तपाई फारमका लागि एउटा-एउटा गरी फिल्डहरु रोज्न चाहनु हुन्छ ? empty_fields_forms: निर्यात गर्नका लागि कृपया केही फारामहरू वा फिल्डहरू छनौट गर्नुहोस् । empty_format: कृपया export गर्न का लागि एउटा ढाँचा छनौट गर्नुहोस् । empty_module: कृपया export गर्न का लागि एउटा मोड्युल छनौट गर्नुहोस् । @@ -886,16 +870,16 @@ ne: format_label: ढाँचा छनौट गर्नुहोस् forms: export गर्न फारम छनौट गर्नुहोस् label: कस्टम export - module_placeholder: "मोड्युल छनौट गर्नुहोस् " - select_module: "मोड्युल छनौट गर्नुहोस् " + module_placeholder: 'मोड्युल छनौट गर्नुहोस् ' + select_module: 'मोड्युल छनौट गर्नुहोस् ' submit: ‌ठिक छ header: हेडर custom_header: कस्टम हेडर signatures: यसका लागि हस्ताक्षर लाइनहरू समावेश गर्नुहोस् - include_implementation_logos: "कार्यान्वयन लोगो समावेश गर्नुहुन्छ ?" + include_implementation_logos: कार्यान्वयन लोगो समावेश गर्नुहुन्छ ? include_implementation_logos_help_text: यसले नेभिगेसन मेनु र लगइन पृष्ठमा देखिने लोगो समावेश गर्ने छ । - include_agency_logo: "निकायको लोगो समावेश गर्नुहुन्छ ?" - include_other_logos: "अन्य लोगो समावेश गर्नुहुन्छ ?" + include_agency_logo: निकायको लोगो समावेश गर्नुहुन्छ ? + include_other_logos: अन्य लोगो समावेश गर्नुहुन्छ ? duplicate_id_csv: all: दोहोरिएको आईडी female_abbreviation: महिला @@ -908,7 +892,7 @@ ne: national_id_no: राष्ट्रिय परिचयपत्र नं progress_id: प्रगति आईडी sex_mapping_m_f_u: लिङ्ग - other_agency_id: " अस्पतालको कोड र बिरामी नम्बर" + other_agency_id: ' अस्पतालको कोड र बिरामी नम्बर' male_abbreviation: पुरुष unknown_abbreviation: U exported: Export फाइल सफलतापूर्वक सिर्जना गरियो @@ -927,7 +911,7 @@ ne: on_short_form: छोटकरीमा option_ids: विकल्पहरुको आईडी options: विकल्पहरु - options_lookup: "खोजी " + options_lookup: 'खोजी ' help_text: सहयोगी पाठ guiding_questions: मार्गदर्शक प्रश्नहरू visible: दृश्यात्मक @@ -948,15 +932,14 @@ ne: form: प्रीमेरो फारमहरु status: स्थिति notes: नोटहरू - go_to_exports: डाउनलोड गर्न Export पेजमा जानुहोस् incident_recorder_xls: all: घटना अभिलेखकर्ता one: घटना अभिलेखकर्ता selected: घटना अभिलेखकर्तामा छनौट गरिएको json: - all: "JSON " - one: "JSON " + all: 'JSON ' + one: 'JSON ' selected: JSON मा छनौट गरिएको list_view_csv: all: list view export गर्नुहोस् @@ -987,11 +970,11 @@ ne: flag_suspect_record: शंकास्पद अभिलेखको रूपमा फ्ल्याग्ड गरिएको no_photos_available: कुनै तस्बिर उपलब्ध छैन one: भित्ता चित्र - reunited: "पुन: एक भएको" + reunited: 'पुन: एक भएको' selected: भित्ता चित्रमा छनौट गरिएको - success_message: "%{file_name} फोटोवाल सिर्जना गर्दै। तस्बिर बिनाका घटनाहरू समावेश हुनै छैन ।" + success_message: '%{file_name} फोटोवाल सिर्जना गर्दै। तस्बिर बिनाका घटनाहरू समावेश हुनै छैन ।' printed: 'छापिएको: %{date}' - queueing: "export फाईल %{file_name}सिर्जना भईरहेको" + queueing: export फाईल %{file_name}सिर्जना भईरहेको selected_xls: all: एक्सेल one: एक्सेल @@ -1013,7 +996,7 @@ ne: governorate_country: राज्यपाल - देश id: आईडी# individual_progress_id: व्यक्तिगत प्रगति आईडी - locations_by_level: "ठेगाना (शिविर, ब्लक र अन्य लागु हुने ठेगानाका स्तरहरू जस्तै आश्रयस्थलको जीपीएस तथ्याङ्क)" + locations_by_level: ठेगाना (शिविर, ब्लक र अन्य लागु हुने ठेगानाका स्तरहरू जस्तै आश्रयस्थलको जीपीएस तथ्याङ्क) long_id: लामो आईडी moha_id: MOHA आईडी name_of_caregiver: हेरचाहकर्ताको पूरा नाम @@ -1059,7 +1042,7 @@ ne: failed: 'Last sync: असफल' last: 'Last Sync:%{date_time}' not_found: 'Last Sync: तथ्याङ्क भेटिएन' - retrieving: "तथ्याङ्क पुन: प्राप्ति" + retrieving: 'तथ्याङ्क पुन: प्राप्ति' see_details: विवरण हेर्नुहोस् fields: action: कार्य @@ -1068,7 +1051,7 @@ ne: add_new_field: नयाँ फिल्ड सिर्जना गर्नुहोस् add_existing_field: अवस्थित फिल्ड थप्नुहोस् add_field: फिल्ड थप्नुहोस् - add_field_type: "%{file_type}थप्नुहोस्" + add_field_type: '%{file_type}थप्नुहोस्' audio: current: वर्तमान अडियो audio_upload_box: अडियो अपलोड गर्नुहोस् @@ -1082,7 +1065,7 @@ ne: create_unique_values: युनिक value हरु सिर्जना गर्नुहोस् date_field: मिति क्षेत्र date_help: मिति-महिना-वर्ष - date_help_with_time: "मिति-महिना-वर्ष घण्टा:मिनेट" + date_help_with_time: मिति-महिना-वर्ष घण्टा:मिनेट date_not_valid: यो मिति मान्य छैन time: समय date_range: @@ -1094,21 +1077,21 @@ ne: date_range_field: मिति दायरा date_time: मिति समय db_name: डाटाबेस नाम - default: "पूर्वनिर्धारित ?" + default: पूर्वनिर्धारित ? default_date_validation: पूर्वनिर्धारित मिति प्रमाणीकरण default_to_current_date: वर्तमान मितिमा पूर्वनिर्धारित - default_to_current_datetime: "वर्तमान मिति र समयमा पूर्वनिर्धारित ?" + default_to_current_datetime: वर्तमान मिति र समयमा पूर्वनिर्धारित ? default_value: पूर्वनिर्धारित मान - deleted: "%{display_name}फिल्ड मेटिएको छ" + deleted: '%{display_name}फिल्ड मेटिएको छ' detail: विस्तार disabled: निष्क्रिय पारिएको display_name: देखाउने नाम document: comments: टिप्पणीहरू - current: "के यो वर्तमान दस्तावेज हो ?" + current: के यो वर्तमान दस्तावेज हो ? date: दस्तावेज मिति name: दस्तावेजको नाम - is_current: "के यो वर्तमान दस्तावेज हो ?" + is_current: के यो वर्तमान दस्तावेज हो ? document_upload_box: दस्तावेज अपलोड गर्नुहोस् । edit_label: फिल्ड सम्पादन गर्नुहोस् enabled: सक्रिय पारिएको @@ -1121,7 +1104,7 @@ ne: add_document_label: दस्तावेज थप्नुहोस् add_new_document_button_text: अर्को दस्तावेज थप्नुहोस् add_new_photo_button_text: अर्को फोटो थप्नुहोस् - add_photo_label: " फोटो थप्नुहोस्" + add_photo_label: ' फोटो थप्नुहोस्' document_description: दस्तावेज विवरण document_file_restrictions_message: फाईलहरू २ MB भन्दा ठुलो हुनु हुँदैन (executable (.exe) फाईलहरु अपलोड गर्न सकिँदैन)। no_file_selected: कुनै फाइल चयन गरिएको छैन @@ -1145,7 +1128,7 @@ ne: not_future_date: भविष्यको मिति होइन number_not_valid: कृपया संख्यात्मक तथ्याङ्क प्रविष्ट गर्नुहोस् numeric_field: नम्बर फिल्ड - on_collapsed_subform: "कोल्यापस भएका सहायक फारममा ?" + on_collapsed_subform: कोल्यापस भएका सहायक फारममा ? option_strings_add_option: विकल्प थप्नुहोस् option_strings_source: खोजी option_strings_text: विकल्प @@ -1159,7 +1142,7 @@ ne: predifined_lookups: पूर्व परिभाषित लुकअपको प्रयोग गर्नुहोस् radio_button: रेडियो बटन remove: हटाउनुहोस् - remove_attachment_confirmation: "के तपाई यहाँ संलग्न सामाग्री पक्का हटाउन चाहानुहुन्छ ?" + remove_attachment_confirmation: के तपाई यहाँ संलग्न सामाग्री पक्का हटाउन चाहानुहुन्छ ? required: आवश्यक छ required_field: '%{field}आवश्यक छ' search_existing: पहिल्यै रहेको फिल्डहरु खोज्नुहोस् @@ -1168,11 +1151,11 @@ ne: select_multiple: लागु हुने सबै छनौट गर्नुहोस् select_single: (छनौट गर्नुहोस् ...) separator: विभाजक - show: "देखाउनु ?" + show: देखाउनु ? show_on: देखाउनुहोस् show_on_minify_form: छोटो रूप skip_logic: - name: "स्किप लजिक?" + name: स्किप लजिक? record_section: title: रेकर्ड भएमा यो फिल्ड देखिने हुनुपर्छ buttons: @@ -1181,15 +1164,15 @@ ne: title: यदि सहायक फारम छ भने यो फिल्ड देखिने हुनुपर्छ buttons: add: सहायक फारमको शर्त थप्नुहोस् - subform: "साहयक फारम " - subform_group_by: "समूहगत बनाउनुहोस् । " - subform_remove_message: "के तपाइँ यो सहायक फारम पक्का हटाउन चाहानु हुन्छ?" + subform: 'साहयक फारम ' + subform_group_by: 'समूहगत बनाउनुहोस् । ' + subform_remove_message: के तपाइँ यो सहायक फारम पक्का हटाउन चाहानु हुन्छ? subform_section: description: सहायक फारमको विवरण name: सहायक फारमको शीर्षक - starts_with_one_entry: "एउटा सहायक फारमको प्रविष्टिबाट सुरु गर्ने ? " + starts_with_one_entry: 'एउटा सहायक फारमको प्रविष्टिबाट सुरु गर्ने ? ' subform_append_only: मोबाइलमा Selective syncing - subform_prevent_item_removal: "सहायक फारम प्रविष्टि हटाउन रोक्नुहोस् ?" + subform_prevent_item_removal: सहायक फारम प्रविष्टि हटाउन रोक्नुहोस् ? subform_sort_by: Sort by successfully_added: क्षेत्र सफलतापूर्वक थपियो tally_field: तुलना गर्नुहोस् @@ -1204,7 +1187,7 @@ ne: total: जम्मा type: प्रकार updated: फिल्ड अपडेट गरियो - visibility: "दृश्यता " + visibility: 'दृश्यता ' web_app: वेब एप filters: apply_filters: पेश गर्नु @@ -1270,11 +1253,11 @@ ne: approvals: अनुमतिहरू case: घटना child: घटना - incident: "घटना " + incident: 'घटना ' individual_victim: व्यक्तिगत पीडित व्यक्ति potential_match: मेल खाने सम्भावना भएको record_information: रेकर्ड विवरण - referrals: "रेफेरलहरू " + referrals: 'रेफेरलहरू ' reportable_follow_up: फलोअप reportable_protection_concern: संरक्षण सवालहरु reportable_service: सेवाहरू @@ -1289,7 +1272,7 @@ ne: show_on: मा देखाइएको छ subform_need_to_be_added: उनीहरूलाई थप्नु आवश्यक छ subform_need_to_be_added_single: यो थप्न आवश्यक छ। - subform_not_found: "%{subform_name} भेटिएन" + subform_not_found: '%{subform_name} भेटिएन' title: फारम शीर्षक translations: edit: अनुवाद सम्पादन गर्नुहोस् @@ -1301,10 +1284,10 @@ ne: select_language: भाषा छनोट गर्नुस् title: अनुवाद type_label: प्रकार - visibility: "दृश्यता " + visibility: 'दृश्यता ' web_app: वेब एप skip_logic: - name: "स्किप लजिक?" + name: स्किप लजिक? section: title: यो फारम देखिनु पर्दछ यदि buttons: @@ -1324,7 +1307,7 @@ ne: display_text: वा यो अवस्था name: वा home: - ar: " अरबी" + ar: ' अरबी' ar-IQ: अरबी (इराकी) ar-JO: अरबी (जोर्डन) ar-LB: अरबी (लेबनानी) @@ -1371,9 +1354,9 @@ ne: code: घटना कोड associated_case: "सम्बन्धित केस :" messages: - creation_success: "घटना अभिलेख सफलतापूर्वक सिर्जना गरिएको " - creation_success_queue: "घटना अभिलेख सफलतापूर्वक पृष्ठभूमिमा सिर्जना गरिएको " - disabled: "घटना निष्क्रिय पारिएको " + creation_success: 'घटना अभिलेख सफलतापूर्वक सिर्जना गरिएको ' + creation_success_queue: 'घटना अभिलेख सफलतापूर्वक पृष्ठभूमिमा सिर्जना गरिएको ' + disabled: 'घटना निष्क्रिय पारिएको ' update_success: '%{record_id}घटना सफलतापूर्वक अद्यावधिक गरिएको छ' update_success_queue: '%{record_id}घटना सफलतापूर्वक पृष्ठभूमिमा अद्यावधिक गरिएको छ' violation: @@ -1394,10 +1377,10 @@ ne: military_use: विद्यालय(हरू) र/वा अस्पताल(हरू) सैन्य कार्यको लागि प्रयोग denial_humanitarian_access: बालबालिकाको लागि मानवीय सेावको पहुँच अस्वीकार incidents: - disable_dialog: "'ठीक छ' क्लिक गर्दा यो घटनाको स्थिति निष्क्रियमा परिवर्तन हुनेछ ।" + disable_dialog: '''ठीक छ'' क्लिक गर्दा यो घटनाको स्थिति निष्क्रियमा परिवर्तन हुनेछ ।' disable_dialog_title: घटनालाई निष्क्रिय पार्नुहोस् disable_success: सफलतापूर्वक निष्कृय भएको घटना - enable_dialog: "'ठीक छ' क्लिक गर्दा यो घटनाको स्थिति सक्रियमा परिवर्तन हुनेछ ।" + enable_dialog: '''ठीक छ'' क्लिक गर्दा यो घटनाको स्थिति सक्रियमा परिवर्तन हुनेछ ।' enable_dialog_title: घटनालाई सकृय पार्नुहोस् enable_success: घटना सफलतापूर्वक सकृय भयो id: आईडी# @@ -1407,7 +1390,7 @@ ne: incident_location: घटना स्थान violations: उल्लङ्घनहरू export: Export - label: "घटना " + label: 'घटना ' filter_by: filter_category: फिल्टर समूह boys: बालकहरू @@ -1420,16 +1403,16 @@ ne: unknown: अज्ञात verification_status: प्रमाणीकरण स्थिति violence_type: हिंसाको प्रकार - armed_force_group_party_name: "सशस्त्र बल, समूह, वा अन्य टोली" + armed_force_group_party_name: सशस्त्र बल, समूह, वा अन्य टोली armed_force_group_type: सशस्त्र बल समूहको प्रकार violations: उल्लङ्घनहरू individual_violations: व्यक्तिगत उल्लङ्घनहरू individual_age: व्यक्तिगत उमेर individual_sex: व्यक्तिगत लिङ्ग victim_deprived_liberty_security_reasons: स्वतन्त्रताबाट वञ्चित - reasons_deprivation_liberty: "स्वतन्त्रताबाट वञ्चित हुनुको कारण के हो ?" + reasons_deprivation_liberty: स्वतन्त्रताबाट वञ्चित हुनुको कारण के हो ? victim_facilty_victims_held: कृपया पीडित(हरू) लाई राखिएको स्थान चयन गर्नुहोस् - torture_punishment_while_deprivated_liberty: "के बालबालिका(हरु) स्वतन्त्रताबाट वञ्चित हुँदा यातना वा अन्य क्रूर, अमानवीय वा अपमानजनक व्यवहार वा सजायको अधिनमा थिए?" + torture_punishment_while_deprivated_liberty: के बालबालिका(हरु) स्वतन्त्रताबाट वञ्चित हुँदा यातना वा अन्य क्रूर, अमानवीय वा अपमानजनक व्यवहार वा सजायको अधिनमा थिए? verified_ghn_reported: यो घटना समावेश भएको GHN निर्दिष्ट गर्नुहोस् weapon_type: 'प्रयोग गरिएको हतियार/विधिको प्रकार' facility_impact: 'भौतिक प्रभावको प्रकार र सीमा' @@ -1510,26 +1493,16 @@ ne: number_of_cases: title: "१. अभिलेख गरिएका केसहरूको संख्या" reporting_site: "रिपोर्टिङ साईट" - helptext: | - यो सूचकले प्रति महिना प्रति रिपोर्टिङ साइट कति वटा नयाँ केस खोलिन्छ भनेर गणना गर्दछ । - रिपोर्टिङ साइट भन्नाले प्रयोगकर्ता संस्थाले सेवाहरू प्रदान गरिरहेको साइट र - सेवा प्रदायकलाई कहाँ केस रिपोर्ट गरियो भन्ने बुझिन्छ । + helptext: "यो सूचकले प्रति महिना प्रति रिपोर्टिङ साइट कति वटा नयाँ केस खोलिन्छ भनेर गणना गर्दछ । \nरिपोर्टिङ साइट भन्नाले प्रयोगकर्ता संस्थाले सेवाहरू प्रदान गरिरहेको साइट र\n सेवा प्रदायकलाई कहाँ केस रिपोर्ट गरियो भन्ने बुझिन्छ ।\n" number_of_incidents: title: "२ अभिलेख गरिएका घटनाहरूको संख्या" reporting_site: "रिपोर्टिङ साईट" - helptext: | - यो सूचकले प्रति महिना प्रति रिपोर्टिङ साइट कति वटा नयाँ घटना खोलियो भनेर गणना गर्दछ । - रिपोर्टिङ साइट भन्नाले प्रयोगकर्ता संस्थाले सेवाहरू प्रदान गरिरहेको साइट र सेवा प्रदायकलाई घटना रिपोर्ट गरिएको ठाउँ भन्ने बुझिन्छ । + helptext: "यो सूचकले प्रति महिना प्रति रिपोर्टिङ साइट कति वटा नयाँ घटना खोलियो भनेर गणना गर्दछ ।\nरिपोर्टिङ साइट भन्नाले प्रयोगकर्ता संस्थाले सेवाहरू प्रदान गरिरहेको साइट र सेवा प्रदायकलाई घटना रिपोर्ट गरिएको ठाउँ भन्ने बुझिन्छ । \n" reporting_delay: title: "३. रिपोर्टिङमा ढिलाइ" delay: "ढिला" total_incidents: "कुल घटनाहरू" - helptext: | - यो सूचकले सर्भाइभरले - लैङ्गिक हिंसा अनुभव गरेको र सेवा प्रदायकलाई पहिलो पटक रिपोर्ट गरेको बिचको दिनहरूको संख्यालाई गणना र वर्गीकृत गर्छ । प्रयोगकर्ता संस्थालाई पहिलो पटक घटना कहिले रिपोर्ट गरिएको थियो भन्ने आधारमा - गणना गरिन्छ । विभिन्न समयावधीलाई - (०-३ दिन, ४-५ दिन, ६-१४ दिन, १५-३० दिन, १ महिनाभन्दा बढी; ३ महिनाभन्दा बढी) आधारमानी - तथ्याङ्क वर्गीकृत गरिन्छ। + helptext: "यो सूचकले सर्भाइभरले \nलैङ्गिक हिंसा अनुभव गरेको र सेवा प्रदायकलाई पहिलो पटक रिपोर्ट गरेको बिचको दिनहरूको संख्यालाई गणना र वर्गीकृत गर्छ । प्रयोगकर्ता संस्थालाई पहिलो पटक घटना कहिले रिपोर्ट गरिएको थियो भन्ने आधारमा \nगणना गरिन्छ । विभिन्न समयावधीलाई\n (०-३ दिन, ४-५ दिन, ६-१४ दिन, १५-३० दिन, १ महिनाभन्दा बढी; ३ महिनाभन्दा बढी) आधारमानी \nतथ्याङ्क वर्गीकृत गरिन्छ।\n" service_access_delay: title: "सेवाको पहुँचमा ढिलाइ" delay: "ढिला" @@ -1538,33 +1511,20 @@ ne: title: "४. मूल्याङ्कन स्थिति" completed: "पूरा गरिएको " completed_supervisor_approved: "पूरा भई पर्यवेक्षकद्वारा स्वीकृत भएको ।" - helptext: | - यो सूचकले मूल्याङ्कन फारम - पूरा भएको सक्रिय केसहरूको अनुपात गणना गर्दछ । सर्भाइभरले - मूल्याङ्कन फारम भित्रका अनिवार्य फिल्डहरू पूरा गरेमा मात्र मूल्याङ्कन पूरा भएको मानिन्छ । + helptext: "यो सूचकले मूल्याङ्कन फारम \nपूरा भएको सक्रिय केसहरूको अनुपात गणना गर्दछ । सर्भाइभरले \nमूल्याङ्कन फारम भित्रका अनिवार्य फिल्डहरू पूरा गरेमा मात्र मूल्याङ्कन पूरा भएको मानिन्छ ।\n" completed_case_safety_plans: title: "५. केसको सुरक्षा योजना पूरा भएको" completed: "केसको सुरक्षा योजना पूरा भएको" - helptext: | - यो सूचकले सुरक्षा योजना आवश्यक र पूरा भइसकेको सक्रिय केसहरूको अनुपात गणना गर्दछ (जस्तै: अन्तरङ्ग साथी द्वारा हिंसा, आत्महत्या/हत्याको जोखिम, बाल संरक्षण ) । - सुरक्षा योजना फारम भित्र भएको अनिवार्य फिल्डहरू पूरा भएपछि मात्र सुरक्षा योजना पूरा भएको मानिन्छ । + helptext: "यो सूचकले सुरक्षा योजना आवश्यक र पूरा भइसकेको सक्रिय केसहरूको अनुपात गणना गर्दछ (जस्तै: अन्तरङ्ग साथी द्वारा हिंसा, आत्महत्या/हत्याको जोखिम, बाल संरक्षण ) ।\nसुरक्षा योजना फारम भित्र भएको अनिवार्य फिल्डहरू पूरा भएपछि मात्र सुरक्षा योजना पूरा भएको मानिन्छ । \n" completed_case_action_plans: title: "६. केसको कार्य योजना पूरा भएको" completed: "केसको कार्य योजना पूरा भएको" label: "केसको कार्य योजना पूरा भएको" - helptext: | - यो सूचकले केस कार्य योजना पूरा भएको सक्रिय केसहरूको अनुपात गणना गर्दछ । - केस योजना फारमका - अनिवार्य फिल्डहरु पूरा भएपछि मात्र केस कार्य योजना सम्पन्न भएको मानिन्छ । + helptext: "यो सूचकले केस कार्य योजना पूरा भएको सक्रिय केसहरूको अनुपात गणना गर्दछ । \nकेस योजना फारमका \nअनिवार्य फिल्डहरु पूरा भएपछि मात्र केस कार्य योजना सम्पन्न भएको मानिन्छ ।\n" completed_supervisor_approved_case_action_plans: title: "७. पर्यवेक्षकबाट स्वीकृत भएको केसको कार्य योजना" completed_and_approved: "पर्यवेक्षकबाट स्वीकृत सम्पन्न भएको केसको कार्य योजना" - helptext: | - यो सूचकले केस कार्य योजना पूरा भएको - र पर्यवेक्षणद्वारा स्विकृत भएको सक्रिय केसहरूको अनुपात गणना गर्दछ । केस योजना फारमका - अनिवार्य फिल्डहरु पूरा भएपछि मात्र केस कार्य योजना सम्पन्न भएको मानिन्छ ।केसवर्करले कार्य योजनाको लागि स्विकृति अनुरोध गरेर पर्यवेक्षणद्वारा प्लेटफर्ममा - स्विकृत भएपछि केस कार्य योजना - स्वीकृत भएको मानिन्छ । + helptext: "यो सूचकले केस कार्य योजना पूरा भएको \nर पर्यवेक्षणद्वारा स्विकृत भएको सक्रिय केसहरूको अनुपात गणना गर्दछ । केस योजना फारमका \nअनिवार्य फिल्डहरु पूरा भएपछि मात्र केस कार्य योजना सम्पन्न भएको मानिन्छ ।केसवर्करले कार्य योजनाको लागि स्विकृति अनुरोध गरेर पर्यवेक्षणद्वारा प्लेटफर्ममा \nस्विकृत भएपछि केस कार्य योजना \nस्वीकृत भएको मानिन्छ ।\n" services_provided: title: "८. प्रदान गरिएको सेवाहरु" service: "सेवा" @@ -1573,13 +1533,10 @@ ne: female: "महिला" 0-11: "०-११" 12-17: "१२-१७ " - ">18": ">१८ " + '>18': ">१८ " disability: "अशक्त" no_disability: "अशक्त नभएको" - helptext: | - यो सूचकले घटना व्यवस्थापन - प्रक्रियामा सर्भाइभरहरूलाई प्रदान गरिएको सेवा(हरू) को प्रकारको गणना गर्दछ। सेवा प्रदान गरिएको भन्नाले संस्था भित्रबाटै प्रदान गरिएको सेवा बुझिन्छ - र यसले अन्य सेवाहरू गरिएको रिफरल वा आन्तरिक रिफरललाई बुझिदैन । + helptext: "यो सूचकले घटना व्यवस्थापन \nप्रक्रियामा सर्भाइभरहरूलाई प्रदान गरिएको सेवा(हरू) को प्रकारको गणना गर्दछ। सेवा प्रदान गरिएको भन्नाले संस्था भित्रबाटै प्रदान गरिएको सेवा बुझिन्छ \nर यसले अन्य सेवाहरू गरिएको रिफरल वा आन्तरिक रिफरललाई बुझिदैन । \n" average_referrals: title: "९. औसत रिफरल" label: "प्रति केस औसत रिफरल" @@ -1590,41 +1547,25 @@ ne: average_followup_meetings_per_case: title: "१०. प्रति केस औसत फलोअप बैठकहरू" label: "प्रति केस औसत फलोअप बैठकहरू" - helptext: | - यो सूचकले प्लेटफर्ममा रहेको केसमा - काम गर्ने व्यक्तिको प्रत्येक सक्रिय केसको लागि आयोजित अनुगमन बैठकहरूको औसत संख्या गणना गर्दछ । फलोअप बैठक भनेको केसमा काम गर्ने व्यक्ति र - सर्भाइभर बीच भएको प्रारम्भिक अन्तरवार्ता /साक्षात्कारपछि हुने बैठक हो । + helptext: "यो सूचकले प्लेटफर्ममा रहेको केसमा \nकाम गर्ने व्यक्तिको प्रत्येक सक्रिय केसको लागि आयोजित अनुगमन बैठकहरूको औसत संख्या गणना गर्दछ । फलोअप बैठक भनेको केसमा काम गर्ने व्यक्ति र \nसर्भाइभर बीच भएको प्रारम्भिक अन्तरवार्ता /साक्षात्कारपछि हुने बैठक हो ।\n" time_from_case_open_to_close: title: "११. केसहरू खुल्लाबाट बन्द हुन लाग्ने समय" time: "समय" percent: "केसहरूको प्रतिशत" - helptext: | - यो सूचकले कति समयसम्म केस खुल्ला राखिन्छ, पहिलो पटक गरिएको रिपोर्टलाई केस - व्यवस्थापनले केस खुलालाई कति समय लगाएर केस बन्द गर्दछ भन्ने कुराको मापन गर्दछ । समयको अवधि निम्न समय सीमाद्वारा - विभाजित गरिएको हुन्छ : १ महिनाभन्दा कम; १ र ३ महिनाको बीच; - ३ र ६ महिनाको बीच; ६ महिना भन्दा बढी । + helptext: "यो सूचकले कति समयसम्म केस खुल्ला राखिन्छ, पहिलो पटक गरिएको रिपोर्टलाई केस \nव्यवस्थापनले केस खुलालाई कति समय लगाएर केस बन्द गर्दछ भन्ने कुराको मापन गर्दछ । समयको अवधि निम्न समय सीमाद्वारा \nविभाजित गरिएको हुन्छ : १ महिनाभन्दा कम; १ र ३ महिनाको बीच;\n३ र ६ महिनाको बीच; ६ महिना भन्दा बढी ।\n" case_closure_rate: title: "१२. बन्द भएका केसका संख्या" reporting_site: "प्रतिवेदन स्थान" - helptext: | - यो सूचकले प्रति रिपोर्टिङ साइट प्रति महिना बन्द गरिएका केसहरूको गणना मापन गर्दछ । रिपोर्टिङ साइट भन्नाले - त्यो स्थानलाई बुझाउँछ जहाँ प्रयोगकर्ता संस्था सेवाहरूले सेवा प्रदान गरिरहेको छ र जुन स्थानमा - सेवा प्रदायकलाई घटना रिपोर्ट गरिएको थियो । + helptext: "यो सूचकले प्रति रिपोर्टिङ साइट प्रति महिना बन्द गरिएका केसहरूको गणना मापन गर्दछ । रिपोर्टिङ साइट भन्नाले \nत्यो स्थानलाई बुझाउँछ जहाँ प्रयोगकर्ता संस्था सेवाहरूले सेवा प्रदान गरिरहेको छ र जुन स्थानमा \nसेवा प्रदायकलाई घटना रिपोर्ट गरिएको थियो । \n" client_satisfaction_rate: title: "१३. ग्राहक सन्तुष्टि दर " label: "ग्राहक सन्तुष्टि" invalid: "अहिले यो गणना गर्न सक्दैनौं।" - helptext: | - यो सूचकले घटना व्यवस्थापन सेवाहरूसँग सन्तुष्ट भएर ग्राहक प्रतिक्रिया सर्वेक्षण पुरा गरेका - सर्भाइभरहरूको प्रतिशत मापन गर्दछ । यो सूचक - सर्भाइभरलाई सेवा प्रदान गर्ने र केसमा काम गर्ने कर्मचारी सदस्य नभएर - अन्य कर्मचारी सदस्य द्वारा GBVIMS+ मा भएको ग्राहक प्रतिक्रिया फारम भरेको आधारमा सूचित गरिन्छ। + helptext: "यो सूचकले घटना व्यवस्थापन सेवाहरूसँग सन्तुष्ट भएर ग्राहक प्रतिक्रिया सर्वेक्षण पुरा गरेका \nसर्भाइभरहरूको प्रतिशत मापन गर्दछ । यो सूचक\n सर्भाइभरलाई सेवा प्रदान गर्ने र केसमा काम गर्ने कर्मचारी सदस्य नभएर \nअन्य कर्मचारी सदस्य द्वारा GBVIMS+ मा भएको ग्राहक प्रतिक्रिया फारम भरेको आधारमा सूचित गरिन्छ। \n" supervisor_to_caseworker_ratio: title: "१४. पर्यवेक्षक र केस कामदारको अनुपात" label: "प्रति पर्यवेक्षक केस कार्यकर्ताहरु " - helptext: | - यो सूचक एउटा पर्यवेक्षकले पर्यवेषण गर्ने केस कामदारको संख्या हो : पर्यवेक्षक र - केस कामदारको अनुपात । यो गणना प्लेटफर्ममा तोकिएको प्रणाली भूमिकाहरूमा आधारित छ। + helptext: "यो सूचक एउटा पर्यवेक्षकले पर्यवेषण गर्ने केस कामदारको संख्या हो : पर्यवेक्षक र \nकेस कामदारको अनुपात । यो गणना प्लेटफर्ममा तोकिएको प्रणाली भूमिकाहरूमा आधारित छ।\n" case_load: title: "केस भार" case_load: " केस भार" @@ -1633,10 +1574,7 @@ ne: 20cases: "११-२० केसहरु" 21-30cases: "२१-३० केसहरु" 30cases: "> ३० केसहरु" - helptext: | - यो सूचकले सक्रिय केसहरूमा प्रति केस कामदार औसत केसको भार मापन गर्दछ । - केसमा कामदार र केसको अनुपात निम्नानुसार विभाजिन गरीएको छ: १० भन्दा कम - खुला केसहरू, १०-२० बीचका खुला केसहरू, २१-३० बीचको खुला केसहरू, ३० भन्दा बढी खुल्ला केसहरू। + helptext: "यो सूचकले सक्रिय केसहरूमा प्रति केस कामदार औसत केसको भार मापन गर्दछ । \nकेसमा कामदार र केसको अनुपात निम्नानुसार विभाजिन गरीएको छ: १० भन्दा कम\n खुला केसहरू, १०-२० बीचका खुला केसहरू, २१-३० बीचको खुला केसहरू, ३० भन्दा बढी खुल्ला केसहरू। \n" date_range_dialog: title: "मिति दायरा अनुकूल पार्ने" description: "एक पटक यो परिवर्तन लागू भएपछि, तल दिइएका दुई मितिहरूबीचबाट तथ्याङ्क छनौट गरिनेछ ।" @@ -1646,7 +1584,6 @@ ne: aria-labels: from: "यो मितिपछिको तथ्याङ्क छनौट गरिनेछ ।" to: "यो मितिभन्दा अघिको तथ्याङ्क छनौट गरिनेछ ।" - location: base_types: camp: शिविर @@ -1661,7 +1598,7 @@ ne: other: अन्य province: प्रदेश region: क्षेत्र - site: "स्थान " + site: 'स्थान ' state: प्रदेश sub-district: उप-जिल्ला village: गाउँ @@ -1683,10 +1620,10 @@ ne: import_title: स्थान आयात गर्नुहोस् । message: कृपया अपलोड गर्नका लागि एउटा csv फाइल छनौट गर्नुहोस् । यो फाइलमा प्रत्येक स्तम्भको दोस्रो पङ्कति मा UTF-8 encoding र HXL hashtags प्रयोग गर्नुपर्छ । no_location: कुनै पनि प्रयोगकर्ता खाताहरू सिर्जना गर्नुअघि स्थानहरू Import गर्नुहोस् । - enable_title: "स्थान सकृय पार्नुहोस् । " - enable_text: "के तपाई साच्चै अगाडि बढ्न चाहानुहुन्छ? ? यदि तपाईले छनौट गर्नु भएको स्थानहरूलाई सक्रिय गर्नु भयो भने ती स्थान क्षेत्रहरूमा विकल्पको रूपमा देखा पर्नेछन् । " + enable_title: 'स्थान सकृय पार्नुहोस् । ' + enable_text: 'के तपाई साच्चै अगाडि बढ्न चाहानुहुन्छ? ? यदि तपाईले छनौट गर्नु भएको स्थानहरूलाई सक्रिय गर्नु भयो भने ती स्थान क्षेत्रहरूमा विकल्पको रूपमा देखा पर्नेछन् । ' disable_title: स्थान निस्कृय पार्नुहोस् । - disable_text: "के तपाई साच्चै अगाडि बढ्न चाहानुहुन्छ? ? यदि तपाईले छनौट गर्नु भएको स्थानहरूलाई निष्क्रिय गर्नु भयो भने ती स्थान क्षेत्रहरूमा विकल्पको रूपमा देखा पर्ने छैनन् । " + disable_text: 'के तपाई साच्चै अगाडि बढ्न चाहानुहुन्छ? ? यदि तपाईले छनौट गर्नु भएको स्थानहरूलाई निष्क्रिय गर्नु भयो भने ती स्थान क्षेत्रहरूमा विकल्पको रूपमा देखा पर्ने छैनन् । ' logger: actions: _approved: स्वीकृत @@ -1712,7 +1649,7 @@ ne: export: एक्सपोर्ट flag: फ्ल्याग import: ईमपोर्ट - incident_details_from_case: "केसबाट घटना विवरण " + incident_details_from_case: 'केसबाट घटना विवरण ' index: ईन्डेक्स list: सूची login: लग-इन @@ -1732,7 +1669,7 @@ ne: transfer: स्थानान्तरण गर्नुहोस् । transfer_accepted: स्थानान्तरण स्वीकार गरियो । transfer_rejected: स्थानान्तरण अस्वीकृत गरियो । - transfer_request: "स्थानान्तरणको लागि अनुरोध " + transfer_request: 'स्थानान्तरणको लागि अनुरोध ' transfer_to: मा स्थानान्तरण गर्नुहोस् । unflag: अनफ्ल्याग गर्नुहोस् । update: अद्यावधिक गर्नुहोस् । @@ -1763,21 +1700,21 @@ ne: edit: सम्पादन enable_disable_record: सक्रिय / निष्क्रिय पार्नुहोस् export: को लागि तथ्याङ्क export गर्दै - flag: "फ्ल्यागिङ गर्दै " - flag_records: "फ्ल्यागिङ गर्दै " + flag: 'फ्ल्यागिङ गर्दै ' + flag_records: 'फ्ल्यागिङ गर्दै ' graph_data: ग्राफ तथ्याङ्क हेर्नुहोस् । hide_name: protect: नाम लुकाउनुहोस् । view: नाम हेर्नुहोस् । - index: "अभिलेखहरूलाई सूचिकृत गर्दै " + index: 'अभिलेखहरूलाई सूचिकृत गर्दै ' list: सूची login: लगईन - logout: "लग-आउट " + logout: 'लग-आउट ' lookups_for_field: फिल्डका लागि खोजीहरू mark_for_mobile: 'false': मोबाइलका लागि चिन्ह हटाउनुहोस् । 'true': मोबाइलका लागि चिन्ह लगाउनुहोस्  । - match_record: "अभिलेख मिलाउने " + match_record: 'अभिलेख मिलाउने ' permitted_field_list: अनुमति दिइएको फिल्ड सूची quick_view: quick view हेर्दै reassign: तोकिदै @@ -1785,8 +1722,8 @@ ne: audit_log: अडिट लग user: प्रयोगकर्ता agency: निकाय - user_group: "प्रयोगकर्ताको समुह " - child: "बालबालिका " + user_group: 'प्रयोगकर्ताको समुह ' + child: 'बालबालिका ' alert: सतर्कता form_section: फारम lookup: खोजी @@ -1797,7 +1734,7 @@ ne: bulk_export: बल्कमा export गर्नुहोस् । saved_search: सुरक्षित गरिएको खोजहरु role: भूमिका - incident: "घटना " + incident: 'घटना ' location: स्थान primero_configuration: प्रीमेरो कन्फिगरेसन code_of_conduct: आचार संहिता @@ -1823,7 +1760,7 @@ ne: search: API सर्च show: हेर्दै show_alerts: को लागि अलर्ट हेर्नुहोस् । - to: "को लागि " + to: 'को लागि ' to_user: प्रयोगकर्ताको लागि transfer: स्थानान्तरण गरिदै । transfer_status: @@ -1834,23 +1771,23 @@ ne: login: label: लग–इन password: - label: "पासवर्ड " + label: 'पासवर्ड ' password_confirmation: label: पासवर्ड पुष्टि password_match: label: पासवर्ड मिल्नु पर्छ । - provider_title: "%{provider} संग" + provider_title: '%{provider} संग' title: लग-इन गर्नुहोस् username: प्रयोगकर्ता नाम password_reset_modal: पासवर्ड रिसेट गर्नुहोस् password_reset_modal_text: प्राइमेरोले तपाईंको ईमेल ठेगानामा पासवर्ड रिसेट गर्ने लिङ्क पठाउनेछ । password_reset_email: इमेल - forgot_password: "तपाइँको पासवर्ड बिर्सनुभयो?" + forgot_password: तपाइँको पासवर्ड बिर्सनुभयो? email: label: इमेल lookup: - create: "नयाँ खोजी " - enabled_label: "सक्रिय पारिएको?" + create: 'नयाँ खोजी ' + enabled_label: सक्रिय पारिएको? english_label: अङ्ग्रेजी पाठ label: खोजी language_label: भाषा @@ -1890,7 +1827,6 @@ ne: incomplete_data: अपूर्ण तथ्याङ्क individual_children: name: बालबालिका - description: '' reports: individual_children: बालबालिका sub_reports: @@ -1900,7 +1836,6 @@ ne: individual_perpetrator: पीडक अनुसार बालबालिका ghn_report: name: ग्लोबल होरिजन्टल नोट - description: '' reports: ghn_report: ग्लोबल होरिजन्टल नोट sub_reports: @@ -1929,7 +1864,6 @@ ne: associated_violations: सम्बन्धित उल्लङ्घनहरू violations: name: उल्लङ्घनहरू - description: '' filter_options: incident_date: घटना मिति date_of_report: प्रतिवेदन मिति @@ -1984,40 +1918,14 @@ ne: military_use_type_of_use: प्रयोगको प्रकार अनुसार उल्लङ्घन संख्या gbv_statistics: name: लैङ्गिक हिंसाको तथ्याङ्क - description: '' filter_options: date_of_first_report: अन्तर्वार्ताको मिति incident_date: घटना मिति reports: - incidents: घटनाहरु perpetrators: पीडकहरु survivors: पीडितहरु referrals: रिफरलहरु sub_reports: - combined: घटनाहरु - total: प्रतिवेदन गरिएको लैङ्गिक हिंसाका घटनाहरूको संख्या - gbv_sexual_violence: प्रतिवेदन गरिएको यौन हिंसाका घटनाहरूको संख्या - gbv_previous_incidents: अघिल्लो GBV घटनाहरू भएका बाँचेकाहरूद्वारा रिपोर्ट गरिएका घटनाहरूको सङ्ख्या - gbv_sexual_violence_type: घटनाको प्रकार - incident_timeofday: घटना समय - elapsed_reporting_time: घटना मिति र प्रतिवेदन मिति बीचको समय - elapsed_reporting_time_rape: "बलात्कारका घटनाहरू, घटना र रिपोर्ट मिति बीचको समय" - elapsed_reporting_time_rape_health_referral: "बलात्कारका घटनाहरू, घटना र प्रतिवेदन मिति (स्वास्थ्य सेवामा वा रेफरल) बीच बितेको समय" - incident_location_type: घटना स्थान - number_of_perpetrators: पीडकहरूको संख्या - perpetrator_relationship: पीडित सँग आरोपित मुख्य पीडकको सम्बन्ध - perpetrator_age_group: आरोपित प्राथमिक पीडकको उमेर समूह - perpetrator_occupation: आरोपित प्राथमिक पीडकको पेशा - age: उमेर अनुसार पीडित संख्या - sex: लिङ्ग अनुसार पीडित संख्या - marital_status: पीडितहरूको वैवाहिक स्थिति - displacement_status: पीडितहरूको विस्थापन स्थिति - displacement_incident: घटनाको समयमा विस्थापनको चरण - gbv_case_context: घटनाको सन्दर्भ - incidents_first_point_of_contact: तपाईको संस्था सम्पर्कको पहिलो बिन्दु भएको घटना संख्या - incidents_from_other_service_provider: अन्य सेवा प्रदायकहरूबाट रिफर गरिएका घटनाहरू - number_of_services_provided: घटनाहरूको लागि प्रदान गरिएका सेवाहरूको संख्या - number_of_services_provided_other: अन्य सेवा प्रदायकहरूलाई नयाँ घटना रिफरल service_safehouse_referral: सुरक्षित घर/सुरक्षित आश्रयस्थललाई रिफरल service_medical_referral: स्वास्थ्य/चिकित्सा सेवाको रिफरल service_psycho_referral: मनोसामाजिक/परामर्श सेवाहरू @@ -2025,33 +1933,32 @@ ne: service_police_referral: प्रहरी वा अन्य प्रकारका सुरक्षा सेवाहरू service_livelihoods_referral: जीविकोपार्जन सेवाहरु service_protection_referral: बाल संरक्षण सेवाहरु - vulnerable_populations: जोखिमपूर्ण जनसंख्या survivors_disability_type: अपाङ्गता भएकाहरु success_message: एक्सपोर्ट फाईल सफलतापूर्वक उत्पन्न भयो messages: - alert_items: "तपाईंसँग नोट गर्नु पर्ने %{items} आइटमहरू छन् ।" + alert_items: तपाईंसँग नोट गर्नु पर्ने %{items} आइटमहरू छन् । alerts_for: - approval: "%{form_section_name}को लागि स्वीकृति बाँकी छ ।" + approval: '%{form_section_name}को लागि स्वीकृति बाँकी छ ।' field_change: '%{form_section_name}%{alert_time}मा अद्यावधिक गरिएको थियो ।' - transfer_request: "%{date}मा%{user}द्वारा%{agency}मा एउटा नयाँ स्थानान्तरण अनुरोध गरिएको थियो ।" - duplicate_field: "प्रणालीमा रहेको अर्को केसमा %{field_name} जस्तै रहेको छ।" + transfer_request: '%{date}मा%{user}द्वारा%{agency}मा एउटा नयाँ स्थानान्तरण अनुरोध गरिएको थियो ।' + duplicate_field: प्रणालीमा रहेको अर्को केसमा %{field_name} जस्तै रहेको छ। cannot_edit: तपाईले यो सम्पादन गर्न सक्नुहुन्न । - confirmation_message: "'ठीक छ' क्लिक गर्दा असुरक्षित परिवर्तनहरू हराएर जानेछन् र लिष्ट भ्यूमा फर्किनेछ। अभिलेखमा फर्कन 'रद्द' मा क्लिक गर्नुहोस् ।" + confirmation_message: '''ठीक छ'' क्लिक गर्दा असुरक्षित परिवर्तनहरू हराएर जानेछन् र लिष्ट भ्यूमा फर्किनेछ। अभिलेखमा फर्कन ''रद्द'' मा क्लिक गर्नुहोस् ।' confirmation_message_subform: ठीक छ क्लिक गर्नाले सुरक्षित नगरिएका परिवर्तनहरू खारेज हुनेछ। परिवर्तन जारी राख्न रद्द क्लिक गर्नुहोस् dashboard_offline: तपाई अफलाईन हुनुहुन्छ । तपाई अनलाइनमा आएपछि ड्यासबोर्ड पुरा तरिकाले काम गर्नेछ । field_name_on_form_name: '''%{form_name}'' फारममा भएको ''%{field_name}'' फिल्डहरु' - logout_confirmation: "के तपाई यो सत्र जारी राख्न चाहनुहुन्छ ? " - logout_offline_warning: "के तपाई निश्चित रूपमा लग आउट गर्न चाहनुहुन्छ ? गर्न चाहनुहुन्छ भने तपाई फेरि अनलाइन नहुँदासम्म लग इन हुन सक्नुहुन्न । अफलाईन हुँदा तपाईले गर्नुभएका सबै परिवर्तनहरू हराउनेछन् ।" + logout_confirmation: 'के तपाई यो सत्र जारी राख्न चाहनुहुन्छ ? ' + logout_offline_warning: के तपाई निश्चित रूपमा लग आउट गर्न चाहनुहुन्छ ? गर्न चाहनुहुन्छ भने तपाई फेरि अनलाइन नहुँदासम्म लग इन हुन सक्नुहुन्न । अफलाईन हुँदा तपाईले गर्नुभएका सबै परिवर्तनहरू हराउनेछन् । logout_warning: तपाई ५ मिनेटमा लग आउट हुनुहुनेछ । logout_dialog_header: अफलाइन लग आउट logout_confirmation_title: लग आउट पुष्टि - logout_confirmation_text: "के तपाईं पक्का लग आउट गर्न चाहनुहुन्छ ?" + logout_confirmation_text: के तपाईं पक्का लग आउट गर्न चाहनुहुन्छ ? no_changes: तपाईंले कुनै फिल्ड परिवर्तन गर्नुभएको छैन । not_available: उपलब्ध छैन record_list: - column_header_tooltip: "%{column}को लागि sort गर्नुहोस्" + column_header_tooltip: '%{column}को लागि sort गर्नुहोस्' of: को - no_match: "माफ गर्नुहोस्, कुनै मिल्दो अभिलेख भेटिएन ।" + no_match: माफ गर्नुहोस्, कुनै मिल्दो अभिलेख भेटिएन । rows_per_page: प्रति पृष्ठ पंक्तिहरु sort: क्रमबद्ध navigation: @@ -2059,13 +1966,13 @@ ne: cases: घटनाहरू home: गृहपृष्ठ key_performance_indicators: Pulse/KPIs - incidents: "घटना " + incidents: 'घटना ' logout: लगआउट गर्नुहोस् reports: रिपोर्ट insights: अन्तर्दृष्टिहरू search: खोज settings: सेटिङ् - support: "सहयोग " + support: 'सहयोग ' support_menu: contact_information: सम्पर्क जानकारी code_of_conduct: आचारसंहिता @@ -2094,18 +2001,18 @@ ne: approvals_case_plan_pending: '%{approval_label} विचाराधीन' approvals_closure: '%{approval_label}' approvals_closure_pending: '%{approval_label} विचाराधीन' - approve_action_plan: "स्वीकृत%{approval_label}" - approve_assessment: "स्वीकृत%{approval_label} फारम" - approve_case_plan: "स्वीकृत%{approval_label}" - approve_closure: "स्वीकृत%{approval_label} फारम" - approve_gbv_closure: "स्वीकृत%{approval_label}फारम" + approve_action_plan: स्वीकृत%{approval_label} + approve_assessment: स्वीकृत%{approval_label} फारम + approve_case_plan: स्वीकृत%{approval_label} + approve_closure: स्वीकृत%{approval_label} फारम + approve_gbv_closure: स्वीकृत%{approval_label}फारम assign: तोक्नुहोस् । assign_within_agency: निकाय भित्र तोक्नुहोस् । assign_within_user_group: प्रयोगकर्ता समूह भित्र तोक्नुहोस् । audit_log: अडिट लग case: घटना case_approvals: घटना अनुमतिहरू - case_assignments_referrals_transfers: "केस कार्यभार, रिफर र स्थानान्तरण" + case_assignments_referrals_transfers: केस कार्यभार, रिफर र स्थानान्तरण case_exports: केस Export case_overview: मेरो केसहरू case_risk: मूल्याङ्कनस्तर अनुसार घटनाहरु @@ -2132,7 +2039,7 @@ ne: dash_referrals_by_socal_worker: सामाजिक कार्यकर्ता अनुसार रिफरल हेर्नुहोस् । dash_reporting_location: रिपोर्टिङ स्थानहरू हेर्नुहोस् । dash_service_provisions: सेवा प्रावधान हेर्नुहोस् । - dash_shared_from_my_team: "मेरो समूहबाट शेयर गरिएको " + dash_shared_from_my_team: 'मेरो समूहबाट शेयर गरिएको ' dash_shared_with_me: मलाई शेयर भएको dash_shared_with_my_team: मेरो समूहसँग शेयर गरिएको dash_shared_with_others: अरुलाई शेयर भएको @@ -2142,12 +2049,12 @@ ne: dash_national_admin_summary: प्रशासकीय सारांश dashboard: ड्यासबोर्ड delete: मेटाउनहोस् - display_view_page: " भ्यू पृष्ठ प्रदर्शन गर्नुहोस् ।" + display_view_page: ' भ्यू पृष्ठ प्रदर्शन गर्नुहोस् ।' duplicate: डुप्लिकेट खोज enable_disable_record: असक्षम गर्नुहोस् - export_case_pdf: "केस pdf export गर्नुहोस्। " + export_case_pdf: 'केस pdf export गर्नुहोस्। ' export_csv: Export csv - export_custom: "कस्टम export गर्नुहोस्। " + export_custom: 'कस्टम export गर्नुहोस्। ' export_duplicate_id_csv: दोहोरिएकाहरू export गर्नुहोस्। export_json: Export json export_list_view_csv: लिष्ट भ्यू CSV मा export गर्नुहोस् । @@ -2155,16 +2062,16 @@ ne: export_pdf: Export pdf export_photowall: भित्ते चित्र export गर्नुहोस् । export_unhcr_csv: UNHCR csv मा export गर्नुहोस्। - export_xls: "xls export गर्नुहोस्। " + export_xls: 'xls export गर्नुहोस्। ' find_tracing_match: केसबाट ट्रेसिङ्ग मिलान पत्ता लगाउनुहोस् । view_registry_record: रजिस्ट्री रेकर्ड हेर्नुहोस् add_registry_record: रजिस्ट्री रेकर्ड थप्नुहोस् flag: फ्ल्याग form: फारमहरू group: मेरो समूहमा भएका सबै अभिलेखहरू वा प्रयोगकर्ताहरूलाई पहुँच गर्नुहोस् । - group_read: "समूहगत अध्ययन " + group_read: 'समूहगत अध्ययन ' import: आयात गर्नुहोस् - incident: "घटना " + incident: 'घटना ' incident_details_from_case: अर्को प्रयोगकर्ताको केसमा घटना विवरण थप्नुहोस् । incident_from_case: एउटा केसबाट घटना सिर्जना गर्नुहोस् । kpi: Pulse/KPIs @@ -2172,8 +2079,8 @@ ne: manage: प्रबन्ध गर्नुहोस् mark_for_offline: अफलाईनको लागि चिन्ह लगाउनुहोस् matching_configuration: कन्फिगरेसन मिलाईदैछ - metadata: "फारमहरू, लुकअप " - potential_match: "सम्भावित मिलान " + metadata: 'फारमहरू, लुकअप ' + potential_match: 'सम्भावित मिलान ' primero_configuration: कन्फिगरेसन read: पढ्नुहोस् । reassign: पुनः तोक्नुहोस् । @@ -2187,11 +2094,11 @@ ne: report: रिपोर्ट managed_report: अन्तर्दृष्टिहरू request_approval: स्वीकृतिका लागि अनुरोध गर्नुहोस् - request_approval_action_plan: "%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्" - request_approval_assessment: "%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्" - request_approval_case_plan: "%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्" - request_approval_closure: "%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्" - request_approval_gbv_closure: "%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्" + request_approval_action_plan: '%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्' + request_approval_assessment: '%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्' + request_approval_case_plan: '%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्' + request_approval_closure: '%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्' + request_approval_gbv_closure: '%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्' request_transfer: स्थानान्तरण अनुरोध गर्नुहोस् role: भूमिकाहरू save_search: खोजहरू सुरक्षित गर्नुहोस् । @@ -2228,20 +2135,20 @@ ne: explanation: प्रयोगकर्ताको पहुँच भएको सक्रिय केसहरूमध्ये कतिको अनुपातले मूल्याङ्कन फारम भरेका छन् हेर्न सक्ने क्षमता label: मूल्याङ्कन स्थिति kpi_average_followup_meetings_per_case: - explanation: "प्रयोगकर्ताको पहुँच भएको सक्रिय केसहरूमध्ये, निश्चित समयावधीमा फलोअप बैठक आयोजना गरिएको औसत संख्या" + explanation: प्रयोगकर्ताको पहुँच भएको सक्रिय केसहरूमध्ये, निश्चित समयावधीमा फलोअप बैठक आयोजना गरिएको औसत संख्या label: प्रति केस औसत फलो-अप बैठकहरू kpi_average_referrals: - explanation: "प्रयोगकर्ताको पहुँच भएको सबै सक्रिय केसहरूको संंख्या, प्रत्येक प्रकारको सेवाहरूका लागि गरिएको रेफरलको औसत संख्या हेर्न सक्ने क्षमता" - label: " औसत रिफरल" + explanation: प्रयोगकर्ताको पहुँच भएको सबै सक्रिय केसहरूको संंख्या, प्रत्येक प्रकारको सेवाहरूका लागि गरिएको रेफरलको औसत संख्या हेर्न सक्ने क्षमता + label: ' औसत रिफरल' kpi_case_closure_rate: explanation: प्रत्येक साइटमा प्रति महिना कति केसहरू बन्द गरिएको थियो भनेर हेर्ने क्षमता label: बन्द भएका केसका संख्या kpi_case_load: explanation: प्रत्येक केस कामदारसित भएको केसहरूको औसत संख्या हेर्ने क्षमता - label: " केस भार" + label: ' केस भार' kpi_client_satisfaction_rate: - explanation: "प्रयोगकर्ताको पहुँच भएको केसहरूमा, कति अनुपातमा पृष्ठपोषण फारम भरेका सर्भाइभरहरु सन्तुष्ट थिए भनेर हेर्न सक्ने क्षमता" - label: "ग्राहक सन्तुष्टि दर " + explanation: प्रयोगकर्ताको पहुँच भएको केसहरूमा, कति अनुपातमा पृष्ठपोषण फारम भरेका सर्भाइभरहरु सन्तुष्ट थिए भनेर हेर्न सक्ने क्षमता + label: 'ग्राहक सन्तुष्टि दर ' kpi_completed_case_action_plans: explanation: प्रयोगकर्ताको पहुँच भएको सक्रिय केसहरूमध्ये कतिको अनुपातमा केस कार्य योजना पूरा भएको छ भनेर हेर्न सक्ने क्षमता label: सम्पन्न भएका केस कार्य योजनाहरू @@ -2252,7 +2159,7 @@ ne: explanation: प्रयोगकर्ताको पहुँच भएको सक्रिय केसहरूमध्ये कुन अनुपातमा पर्यवेक्षकद्वारा स्वीकृत केस सुरक्षा योजनाहरू पूरा भए भनेर हेर्न सक्ने क्षमता label: पर्यवेक्षकद्वारा स्वीकृत सम्पन्न भएका केस सुरक्षा योजनाहरू kpi_goal_progress_per_need: - explanation: "प्रयोगकर्ताको पहुँच भएको केसहरूको प्रत्येक वर्गमा कति प्रतिशत लक्ष्य प्राप्त भयो भनेर हेर्न सक्ने क्षमता " + explanation: 'प्रयोगकर्ताको पहुँच भएको केसहरूको प्रत्येक वर्गमा कति प्रतिशत लक्ष्य प्राप्त भयो भनेर हेर्न सक्ने क्षमता ' label: लक्ष्य प्राप्तिका लागि गरिएको प्रगति kpi_number_of_cases: explanation: प्रति साइट प्रति महिना कति रिपोर्ट गरिएका नयाँ केसहरू खोलिन्छ भनेर हेर्न सक्ने क्षमता @@ -2295,44 +2202,44 @@ ne: audit_log: actions: read: - explanation: "प्रयोगकर्तालाई यो प्रणालीको सूचीमा भएका र गरिएका सबै कार्यहरू, प्रयोगकर्ताद्वारा नष्ट पारिएका कार्य, कार्यको प्रकार, अभिलेख आईडी र कार्यको समय हेर्न र फिल्टर गर्न अनुमति दिन्छ । यो राष्ट्रिय स्तर वा निकाय स्तरका प्रशासकहरूको लागि सबैभन्दा उपयुक्त छ किनभने यो प्रणालीमा सबै प्रयोगकर्ताहरूद्वारा गरिएका कार्यहरू देखिन्छन् । कृपया ध्यान दिनुहोस् कि अडिट लगले प्रत्येक कार्यमा संलग्न अभिलेखको बारेमा व्यक्तिगत पहिचानयोग्य जानकारी देखाउँदैन । " + explanation: 'प्रयोगकर्तालाई यो प्रणालीको सूचीमा भएका र गरिएका सबै कार्यहरू, प्रयोगकर्ताद्वारा नष्ट पारिएका कार्य, कार्यको प्रकार, अभिलेख आईडी र कार्यको समय हेर्न र फिल्टर गर्न अनुमति दिन्छ । यो राष्ट्रिय स्तर वा निकाय स्तरका प्रशासकहरूको लागि सबैभन्दा उपयुक्त छ किनभने यो प्रणालीमा सबै प्रयोगकर्ताहरूद्वारा गरिएका कार्यहरू देखिन्छन् । कृपया ध्यान दिनुहोस् कि अडिट लगले प्रत्येक कार्यमा संलग्न अभिलेखको बारेमा व्यक्तिगत पहिचानयोग्य जानकारी देखाउँदैन । ' label: हेर्नुहोस - explanation: "प्रणालीमा गरिएका सबै कार्यहरूको फिल्टर गर्न मिल्ने सूची। केसहरू, घटनाहरू, वा ट्रेसिङ अनुरोधहरूमा कुनै पनि पहिचान योग्य जानकारी समावेश हुदैन।" + explanation: प्रणालीमा गरिएका सबै कार्यहरूको फिल्टर गर्न मिल्ने सूची। केसहरू, घटनाहरू, वा ट्रेसिङ अनुरोधहरूमा कुनै पनि पहिचान योग्य जानकारी समावेश हुदैन। label: अडिट लग case: actions: add_note: - explanation: "प्रयोगकर्तालाई \"नोट्स\" (कहिलेकाहिँ \"टिप्पणी\" भनिने) सहायक फारममा प्रविष्टि थप्नको लागि अनुमति दिन्छ । यसको लागि प्रयोगकर्ताले 'केस देखाउनुहोस्' पृष्ठमा भएको \"नोट्स थप्नुहोस्\" बटनमा क्लिक गर्नुपर्छ । यो विशेष गरी त्यस्ता प्रबन्धकहरूको लागि उपयोगी छ जसमा केसहरू सम्पादन गर्न क्षमता हुँदैन र केस कार्यकर्ताको लागि रिमाईन्डर राख्न चाहन्छन् । यसरी, एउटा नोट थप्नु भनेको फ्ल्याग गर्नु जस्तै हो । एउटा नोट थप्नुको फाइदा यो हो कि जब प्रबन्धकले केसमा एउटा नोट थप्छ तब केस कामदारले आफ्नो मोबाइल उपकरणमा केस हेर्दा एउटा सूचना देखापर्छ ।" + explanation: प्रयोगकर्तालाई "नोट्स" (कहिलेकाहिँ "टिप्पणी" भनिने) सहायक फारममा प्रविष्टि थप्नको लागि अनुमति दिन्छ । यसको लागि प्रयोगकर्ताले 'केस देखाउनुहोस्' पृष्ठमा भएको "नोट्स थप्नुहोस्" बटनमा क्लिक गर्नुपर्छ । यो विशेष गरी त्यस्ता प्रबन्धकहरूको लागि उपयोगी छ जसमा केसहरू सम्पादन गर्न क्षमता हुँदैन र केस कार्यकर्ताको लागि रिमाईन्डर राख्न चाहन्छन् । यसरी, एउटा नोट थप्नु भनेको फ्ल्याग गर्नु जस्तै हो । एउटा नोट थप्नुको फाइदा यो हो कि जब प्रबन्धकले केसमा एउटा नोट थप्छ तब केस कामदारले आफ्नो मोबाइल उपकरणमा केस हेर्दा एउटा सूचना देखापर्छ । label: केसमा नोट थप्नुहोस् । add_registry_record: explanation: प्रयोगकर्तालाई रजिस्ट्री विवरण फारमबाट केसमा रजिस्ट्री लिङ्क गर्न अनुमति दिन्छ। प्रयोगकर्तालाई केससँग पहिले नै लिङ्क गरिएको कुनै पनि रजिस्ट्री अनलिंक गर्न अनुमति दिन्छ। label: केसबाट रजिस्ट्री रेकर्ड थप्नुहोस्/अद्यावधिक गर्नुहोस् approve_action_plan: - explanation: "प्रबन्धकलाई उनीहरूको केस कामदारहरूको %{approval_label}स्वीकृत गर्न अनुमति दिन्छ।" - label: "%{approval_label}स्वीकृत गर्नुहोस् ।" + explanation: प्रबन्धकलाई उनीहरूको केस कामदारहरूको %{approval_label}स्वीकृत गर्न अनुमति दिन्छ। + label: '%{approval_label}स्वीकृत गर्नुहोस् ।' approve_assessment: - explanation: "प्रबन्धकलाई उनीहरूको केस कामदारहरूको %{approval_label} स्वीकृत गर्न अनुमति दिन्छ।" - label: " %{approval_label}फारम स्वीकृत गर्नुहोस्" + explanation: प्रबन्धकलाई उनीहरूको केस कामदारहरूको %{approval_label} स्वीकृत गर्न अनुमति दिन्छ। + label: ' %{approval_label}फारम स्वीकृत गर्नुहोस्' approve_bia: - explanation: "प्रबन्धकलाई उनीहरूको केस कामदारहरूको %{approval_label} स्वीकृत गर्न अनुमति दिन्छ।" - label: "%{approval_label} फारम स्वीकृत गर्नुहोस् " + explanation: प्रबन्धकलाई उनीहरूको केस कामदारहरूको %{approval_label} स्वीकृत गर्न अनुमति दिन्छ। + label: '%{approval_label} फारम स्वीकृत गर्नुहोस् ' approve_case_plan: - explanation: "प्रबन्धकलाई उनीहरूको केस कामदारहरूको %{approval_label} स्वीकृत गर्न अनुमति दिन्छ।" - label: "%{approval_label} स्वीकृत गर्नुहोस् ।" + explanation: प्रबन्धकलाई उनीहरूको केस कामदारहरूको %{approval_label} स्वीकृत गर्न अनुमति दिन्छ। + label: '%{approval_label} स्वीकृत गर्नुहोस् ।' approve_closure: - explanation: "प्रबन्धकलाई उनीहरूको केस कामदारहरूको %{approval_label} स्वीकृत गर्न अनुमति दिन्छ।" - label: "%{approval_label} फारम स्वीकृत गर्नुहोस्" + explanation: प्रबन्धकलाई उनीहरूको केस कामदारहरूको %{approval_label} स्वीकृत गर्न अनुमति दिन्छ। + label: '%{approval_label} फारम स्वीकृत गर्नुहोस्' approve_gbv_closure: - explanation: "प्रबन्धकलाई उनीहरूको केस कामदारहरूको %{approval_label} स्वीकृत गर्न अनुमति दिन्छ।" - label: "%{approval_label} फारम स्वीकृत गर्नुहोस् " + explanation: प्रबन्धकलाई उनीहरूको केस कामदारहरूको %{approval_label} स्वीकृत गर्न अनुमति दिन्छ। + label: '%{approval_label} फारम स्वीकृत गर्नुहोस् ' assign: - explanation: "प्रयोगकर्तालाई मूल अभिलेख मालिकसँग भएको केसलाई प्रणालीमा भएको अन्य कुनै प्रयोगकर्तालाई केस पठाउन अनुमति दिन्छ। यो कार्यको लागि बालबालिकाको सहमति आवश्यक छैन । स्थानान्तरणमा जस्तै, प्राप्तकर्तालाई असाइनमेन्ट स्वीकार गर्ने वा अस्वीकार गर्ने मौका दिइएको छैन ।" - label: "तोक्नुहोस् " + explanation: प्रयोगकर्तालाई मूल अभिलेख मालिकसँग भएको केसलाई प्रणालीमा भएको अन्य कुनै प्रयोगकर्तालाई केस पठाउन अनुमति दिन्छ। यो कार्यको लागि बालबालिकाको सहमति आवश्यक छैन । स्थानान्तरणमा जस्तै, प्राप्तकर्तालाई असाइनमेन्ट स्वीकार गर्ने वा अस्वीकार गर्ने मौका दिइएको छैन । + label: 'तोक्नुहोस् ' assign_within_agency: - explanation: "प्रयोगकर्तालाई मूल अभिलेख मालिकसँग भएको केसलाई हालको प्रयोगकर्ता निकायभित्र भएको अन्य कुनै प्रयोगकर्तालाई केस पठाउन अनुमति दिन्छ। यो कार्यको लागि बालबालिकाको सहमति आवश्यक छैन। स्थानान्तरणमा जस्तै, प्राप्तकर्तालाई असाइनमेन्ट स्वीकार गर्ने वा अस्वीकार गर्ने मौका दिइएको छैन ।" + explanation: प्रयोगकर्तालाई मूल अभिलेख मालिकसँग भएको केसलाई हालको प्रयोगकर्ता निकायभित्र भएको अन्य कुनै प्रयोगकर्तालाई केस पठाउन अनुमति दिन्छ। यो कार्यको लागि बालबालिकाको सहमति आवश्यक छैन। स्थानान्तरणमा जस्तै, प्राप्तकर्तालाई असाइनमेन्ट स्वीकार गर्ने वा अस्वीकार गर्ने मौका दिइएको छैन । label: मेरो निकायभित्रको प्रयोगकर्तालाई तोक्नुहोस् । assign_within_user_group: - explanation: "प्रयोगकर्तालाई मूल अभिलेख मालिकसँग भएको केसलाई हालको प्रयोगकर्ता रहेको प्रयोगकर्ता समूहको अन्य कुनै प्रयोगकर्तालाई केस पठाउन अनुमति दिन्छ। यो कार्यको लागि बालबालिकाको सहमति आवश्यक छैन । स्थानान्तरणमा जस्तै, प्राप्तकर्तालाई असाइनमेन्ट स्वीकार गर्ने वा अस्वीकार गर्ने मौका दिइएको छैन ।" + explanation: प्रयोगकर्तालाई मूल अभिलेख मालिकसँग भएको केसलाई हालको प्रयोगकर्ता रहेको प्रयोगकर्ता समूहको अन्य कुनै प्रयोगकर्तालाई केस पठाउन अनुमति दिन्छ। यो कार्यको लागि बालबालिकाको सहमति आवश्यक छैन । स्थानान्तरणमा जस्तै, प्राप्तकर्तालाई असाइनमेन्ट स्वीकार गर्ने वा अस्वीकार गर्ने मौका दिइएको छैन । label: मेरो प्रयोगकर्ता समूहभित्रको प्रयोगकर्तालाई तोक्नुहोस् । change_log: explanation: प्रयोगकर्ताले अभिलेख सिर्जना भएदेखि त्यसमा गरिएका सबै परिवर्तनहरूको इतिहास देख्न सक्छ । यसअन्तर्गत सबै फिल्डहरूको लागि अभिलेख गरिएका मानहरू पनि सामेल छन् । @@ -2341,7 +2248,7 @@ ne: explanation: प्रयोगकर्तालाई खुला केसको स्थिति बन्द गर्नको लागि अनुमति दिन्छ । label: बन्द गर्नुहोस् consent_override: - explanation: "प्रयोगकर्तालाई अनुमति नभएको केस रिफर गर्न वा स्थानान्तरण गर्न अनुमति दिन्छ । " + explanation: 'प्रयोगकर्तालाई अनुमति नभएको केस रिफर गर्न वा स्थानान्तरण गर्न अनुमति दिन्छ । ' label: रिफर वा स्थानान्तरण गर्दा सहमतिको कमीलाई ओभरराइड गर्नुहोस् । create: explanation: केस सिर्जना गर्ने क्षमता @@ -2350,37 +2257,37 @@ ne: explanation: यदि प्रयोगकर्ताले उनीहरूलाई पहुँच नभएको केसबारे खोजी गर्दछन भने यो अनुमतिले उनीहरूलाई केसमा क्लिक गरेर त्यसबारे सबै जानकारी हेर्ने अनुमति नदिएता पनि आधारभूत जानकारीसँगै एउटा सानो मोडाल हेर्ने अनुमति दिन्छ । यस "भ्यू मोडल" मा देखा पर्ने फिल्डरू "छोटो फारममा देखाउनुहोस् ।" को लागि कन्फिगर गरिएका छन् । ट्रेसिंङ अनुरोधको लागि प्रयोगकर्ताले "सम्भावित मिलान" अन्तर्गत केसहरूको समीक्षा गरिरहँदा "भ्यू मोडल" मा उनीहरूको पहुँच हुने हुँदा यो मोडल परिवारबारे पत्ता लगाउने र पुनर्मिलन कार्यहरू गर्नको लागि पनि उपयोगी छ । label: भ्यू पृष्ठ प्रदर्शन गर्नुहोस् । enable_disable_record: - explanation: "केसलाई सकृय वा निस्कृय बनाउने सक्ने क्षमता । \"निष्कृय\" केसहरू केस सूचीमा पूर्वनिर्धारित रूपमा देखा पर्दैनन् । प्रयोगकर्ताहरूले छनोटको उपयोग गरेर केस सूचीमा भएका निष्कृय केसहरू देख्न सक्छन् । प्रीमेरोले प्रयोगकर्ताहरूलाई केसहरू मेटाउने अनुमति नदिने हुनाले, प्रयोगकर्ताले विकल्पको रूपमा केसलाई निष्कृय बनाउन सक्दछन् । उदाहरणको लागि, यदि प्रयोगकर्ताले गल्तीले केस सिर्जना गरेको छ वा केसको तथ्याङ्क बिग्रेको छ भने प्रयोगकर्ताले केसलाई निष्कृय गर्नुपर्छ । " + explanation: 'केसलाई सकृय वा निस्कृय बनाउने सक्ने क्षमता । "निष्कृय" केसहरू केस सूचीमा पूर्वनिर्धारित रूपमा देखा पर्दैनन् । प्रयोगकर्ताहरूले छनोटको उपयोग गरेर केस सूचीमा भएका निष्कृय केसहरू देख्न सक्छन् । प्रीमेरोले प्रयोगकर्ताहरूलाई केसहरू मेटाउने अनुमति नदिने हुनाले, प्रयोगकर्ताले विकल्पको रूपमा केसलाई निष्कृय बनाउन सक्दछन् । उदाहरणको लागि, यदि प्रयोगकर्ताले गल्तीले केस सिर्जना गरेको छ वा केसको तथ्याङ्क बिग्रेको छ भने प्रयोगकर्ताले केसलाई निष्कृय गर्नुपर्छ । ' label: सक्रिय/निष्क्रिय पार्नुहोस् । export_case_pdf: - explanation: "प्रयोगकर्ताले केस सूची वा केस देखाउनुहोस् पृष्ठहरू बाट PDF फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसका सबै फिल्डहरु हुन्छ । PDF export फाइलमा, सूचनालाई पहिला केस सूची अनुसार र त्यसपछि जानकारी देखा पर्ने फारम अनुसार थप व्यवस्थित गरिएको छ ।" - label: "PDF मा केस export गर्नुहोस्। " + explanation: प्रयोगकर्ताले केस सूची वा केस देखाउनुहोस् पृष्ठहरू बाट PDF फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसका सबै फिल्डहरु हुन्छ । PDF export फाइलमा, सूचनालाई पहिला केस सूची अनुसार र त्यसपछि जानकारी देखा पर्ने फारम अनुसार थप व्यवस्थित गरिएको छ । + label: 'PDF मा केस export गर्नुहोस्। ' export_csv: explanation: 'प्रयोगकर्ताले केस सूची वा केस देखाउनुहोस् पृष्ठहरू बाट CSV फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसका सबै फिल्डहरु हुन्छ । नोट: CSV export ले अरबी र बंगाली जस्ता गैर ल्याटिन वर्णहरूलाई पठनीय ढाँचामा प्रस्तुत गर्दैन।' label: Export csv export_custom: - explanation: "प्रयोगकर्ताले केस सूची वा केस देखाउनुहोस् पृष्ठहरू बाट CSV फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसका कस्टम फारम र फिल्डहरु हुन्छ । यो export मा, प्रत्येक फारमलाई XLS फाइल भित्रको आफ्नै ट्याबमा प्रतिनिधित्व गरीन्छ। कस्टम export मोडलको प्रयोग गरेर प्रयोगकर्ताले export मा आफुले समावेश गर्न चाहे जस्तो फारम वा क्षेत्रहरु छनौट गर्न सक्नुहुन्छ । कृपया ध्यान दिनुहोस् कि प्रयोगकर्ताहरुले application मा केस हेर्दा फारमहरु र क्षेत्रहरु हेर्ने क्षमता छ भने मात्र export मा फारमहरु र क्षेत्रहरु समावेश गर्न सक्छन् ।" + explanation: प्रयोगकर्ताले केस सूची वा केस देखाउनुहोस् पृष्ठहरू बाट CSV फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसका कस्टम फारम र फिल्डहरु हुन्छ । यो export मा, प्रत्येक फारमलाई XLS फाइल भित्रको आफ्नै ट्याबमा प्रतिनिधित्व गरीन्छ। कस्टम export मोडलको प्रयोग गरेर प्रयोगकर्ताले export मा आफुले समावेश गर्न चाहे जस्तो फारम वा क्षेत्रहरु छनौट गर्न सक्नुहुन्छ । कृपया ध्यान दिनुहोस् कि प्रयोगकर्ताहरुले application मा केस हेर्दा फारमहरु र क्षेत्रहरु हेर्ने क्षमता छ भने मात्र export मा फारमहरु र क्षेत्रहरु समावेश गर्न सक्छन् । label: कस्टम export गर्नुहोस्। export_duplicate_id_csv: explanation: एउटै राष्ट्रिय आईडी फिल्ड (कन्फिगरेसनको आधारमा भिन्न लेबल हुनसक्दछ) भएका केसहरूको CSV export सिर्जना गर्दछ। केस सुची पृष्‍ठ बाट मात्रै सिर्जना गरिएको । label: दोहोरिएकाहरू export गर्नुहोस्। export_json: - explanation: "प्रयोगकर्ताले केस सूची वा केस देखाउने पृष्ठहरूबाट JSON फाइल export गर्न सक्छ जसमा समा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसका सबै फिल्डहरु हुन्छ । यो export मुख्य रूपमा ती सबैको लागि प्रयोग गरिन्छ जस्ले हालको प्रीमेरो प्रणाली बाट केस export गरेर भिन्न प्रीमेरो प्रणालीमा वा अन्य सूचना व्यवस्थापन प्रणालीमा import गर्न चाहन्छन् । JSON ढाँचा मेशिनद्वारा पठनीय छ र धेरै प्रयोगकर्ताहरूको लागी व्यावहारिक छैन।" + explanation: प्रयोगकर्ताले केस सूची वा केस देखाउने पृष्ठहरूबाट JSON फाइल export गर्न सक्छ जसमा समा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसका सबै फिल्डहरु हुन्छ । यो export मुख्य रूपमा ती सबैको लागि प्रयोग गरिन्छ जस्ले हालको प्रीमेरो प्रणाली बाट केस export गरेर भिन्न प्रीमेरो प्रणालीमा वा अन्य सूचना व्यवस्थापन प्रणालीमा import गर्न चाहन्छन् । JSON ढाँचा मेशिनद्वारा पठनीय छ र धेरै प्रयोगकर्ताहरूको लागी व्यावहारिक छैन। label: Export JSON export_list_view_csv: explanation: केस सूची पृष्ठबाट प्रयोगकर्ताले CSV फाईल export गर्न सक्दछन् र सो पृष्ठमा देखा पर्ने फिल्डहरु अर्को प्रयोगकर्ताको केस लिष्टमा देखिनेछ । केस सुची पृष्‍ठ बाट मात्रै कार्य गर्ने सकिनेछ । label: लिस्ट भ्यू CSV मा export गर्नुहोस् । export_pdf: - explanation: "प्रयोगकर्ताले केस सूची वा केस देखाउने पृष्ठहरूबाट PDF फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसहरुको फिल्ड रहेको हुन्छ । PDF export फाइलमा, सूचनालाई पहिला केस सूची अनुसार र त्यसपछि सूचना देखा पर्ने फारम अनुसार थप व्यवस्थित गरीएको छ ।" - label: "PDF मा केस export गर्नुहोस्। " + explanation: प्रयोगकर्ताले केस सूची वा केस देखाउने पृष्ठहरूबाट PDF फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसहरुको फिल्ड रहेको हुन्छ । PDF export फाइलमा, सूचनालाई पहिला केस सूची अनुसार र त्यसपछि सूचना देखा पर्ने फारम अनुसार थप व्यवस्थित गरीएको छ । + label: 'PDF मा केस export गर्नुहोस्। ' export_photowall: explanation: प्रयोगकर्तालाई छनौट गरिएका सबै केसहरूको फोटोहरू भएको केस सूची पृष्ठ बाट एउटा फाइल export गर्ने अनुमति दिन्छ । यो export मुख्य रूपमा परिवार पत्ता लगाउने र पुनर्मिलन गरिएका गतिविधिहरूको लागी प्रयोग गरीन्छ। केस सुची पृष्‍ठ बाट मात्रै कार्यगर्ने सकिने । label: फोटोवाल export गर्नुहोस् । export_unhcr_csv: - label: "UNHCR CSV export गर्नुहोस्। " + label: 'UNHCR CSV export गर्नुहोस्। ' export_xls: explanation: 'प्रयोगकर्ताले केस सूची वा केस देखाउने पृष्ठहरू बाट XLS फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसहरुको फिल्ड रहेको हुन्छ । यो export मा, प्रत्येक फारमलाई XLS फाइल भित्रको आफ्नै ट्याबमा प्रतिनिधित्व गरीन्छ। नोट: XLS फरम्याटले गैर ल्याटिन वर्णहरूलाई (उदाहरणः अरबी र बंगाली) पठनीय ढाँचामा प्रस्तुत गर्दैछ तर CSV ले गर्दैन।' - label: "Excel (XLS file) export गर्नुहोस्। " + label: 'Excel (XLS file) export गर्नुहोस्। ' find_tracing_match: explanation: यो विशेष गरी परिवार पत्ता लगाउने र पुनर्मिलन गतिविधिको सन्दर्भहरूमा प्रयोग गरीन्छ। यो अनुमति पाएका प्रयोगकर्ताहरूले केस देखाउने पृष्ठमा "Tracing match खोज्नुहोस् " बटन देख्नेछन्। उनीहरूले बटनलाई क्लिक गर्दा प्रणालीमा उनीहरूको केस संग मिल्ने सम्भावना भएका ट्रेसिङ्ग अनुरोधहरूको सूचीमा देखिनेछन । label: केस बाट ट्रेसिंग मिलान पत्ता लगाउनुहोस् । @@ -2388,16 +2295,16 @@ ne: explanation: प्रयोगकर्तालाई केसमा फ्ल्याग थप्ने क्षमता छ। यो अनुमति पाएका प्रयोगकर्ताले क्षमता केसमा थपेका फ्ल्यागहरू हटाउन पनि सक्छन्। label: फ्ल्याग import: - explanation: "CSV, एक्सेल, वा JSON फाइल बाट import गरेर प्रयोगकर्तालाई एक वा एक भन्दा बढी नयाँ केसहरू सिर्जना गर्न अनुमति दिन्छ। सही तरिकाले जानकारी import गर्न आयातित फाइलको ढाँचा \"अत्ती नै\" विशेष हुनुपर्छ । यो सुविधा प्रीमेरोमा तथ्याड़कलाई कसरी फरम्याट गरिन्छ भन्ने उच्च प्राविधिक सीप र गहन ज्ञान भएको प्रशासनिक प्रयोगकर्ताहरूलाई उपलब्ध हुनु पर्छ। केस सूची पृष्ठबाट मात्र प्रयोग गर्न मिल्ने छ । " + explanation: 'CSV, एक्सेल, वा JSON फाइल बाट import गरेर प्रयोगकर्तालाई एक वा एक भन्दा बढी नयाँ केसहरू सिर्जना गर्न अनुमति दिन्छ। सही तरिकाले जानकारी import गर्न आयातित फाइलको ढाँचा "अत्ती नै" विशेष हुनुपर्छ । यो सुविधा प्रीमेरोमा तथ्याड़कलाई कसरी फरम्याट गरिन्छ भन्ने उच्च प्राविधिक सीप र गहन ज्ञान भएको प्रशासनिक प्रयोगकर्ताहरूलाई उपलब्ध हुनु पर्छ। केस सूची पृष्ठबाट मात्र प्रयोग गर्न मिल्ने छ । ' label: Import गर्नुहोस् incident_details_from_case: - explanation: "तपाइँले खोजी गर्दा भेटेको तर तपाइँको पहुँचको नभएको केसमा घटना विवरण सहायक फारममा प्रविष्टि गर्न सक्ने क्षमता । प्रयोगकर्ताले खोज नतिजा पृष्ठबाट एक वा धेरै केसहरू छनौट गरेपछि कार्य मेनुको \"घटना थप्नुहोस्\" छनौट गरेर यो कार्य गर्दछन् । प्रयोगकर्ताले त्यस्पछि घटना विवरण सहायक फारममा सबै फिल्डहरु भएका मोडल देख्छन् जहाँ उनीहरूले सेवा बारे जानकारी प्रविष्ट र सबमिट गर्न सक्छन् । यो कार्य खोज परिणाम पृष्ठ बाट मात्र गर्न सकिने हुनाले र यदि भूमिकालाई \"अन्य प्रयोगकर्ताहरूको स्वामित्वमा रहेको केस अभिलेख खोज गर्ने\" अनुमति छ भने उनीहरूले यो अनुमति पाउन जायज छ । " + explanation: 'तपाइँले खोजी गर्दा भेटेको तर तपाइँको पहुँचको नभएको केसमा घटना विवरण सहायक फारममा प्रविष्टि गर्न सक्ने क्षमता । प्रयोगकर्ताले खोज नतिजा पृष्ठबाट एक वा धेरै केसहरू छनौट गरेपछि कार्य मेनुको "घटना थप्नुहोस्" छनौट गरेर यो कार्य गर्दछन् । प्रयोगकर्ताले त्यस्पछि घटना विवरण सहायक फारममा सबै फिल्डहरु भएका मोडल देख्छन् जहाँ उनीहरूले सेवा बारे जानकारी प्रविष्ट र सबमिट गर्न सक्छन् । यो कार्य खोज परिणाम पृष्ठ बाट मात्र गर्न सकिने हुनाले र यदि भूमिकालाई "अन्य प्रयोगकर्ताहरूको स्वामित्वमा रहेको केस अभिलेख खोज गर्ने" अनुमति छ भने उनीहरूले यो अनुमति पाउन जायज छ । ' label: अर्को प्रयोगकर्ताको केसमा खोज परिणाम पृष्ठ बाट घटना विवरण थप्नुहोस् । incident_from_case: - explanation: "प्रयोगकर्तालाई \"घटना सिर्जना गर्नुहोस्\" बटन क्लिक गर्न अनुमति दिन्छ। यसले एउटा घटना उत्पन्न गर्दछ जसमा केहि जानकारी केस बाट साभार गरिएको हुन सक्छ। GBV केसहरूको लागी यो बटन केस देखाउने पृष्ठको शीर्षमा छ र समग्रमा केसको जानकारी संग मेल खान्छ। केही घटना ट्रयाकिंग गर्ने सन्दर्भमा, यो बटन \"घटना विवरण\" सहायक फारममा छ। यस स्थितिमा, केहि जानकारी बटन क्लिक गरिएको घटना विवरण सहायक फारम बाट साभार भएको हुन सक्छ । साथै, समग्रमा केस बाट नै साभार भएको पनि हुन सक्छ। भन्नाले, सिर्जना गरिएको नयाँ घटनामा व्यक्तिगत घटना विवरण सहायक फारममा भएको \"हिंसाको प्रकार\" भन्ने फिल्ड हुन सक्छ र उमेर अनि केसको लिंग पनि समावेश भएको हुन सक्छ। ध्यान दिनुहोस् कि यो अनुमतिले प्रयोगकर्तालाई घटना सँग सम्बन्धित एउटा लिंक हेर्ने अनुमति पनि दिन्छ।" + explanation: प्रयोगकर्तालाई "घटना सिर्जना गर्नुहोस्" बटन क्लिक गर्न अनुमति दिन्छ। यसले एउटा घटना उत्पन्न गर्दछ जसमा केहि जानकारी केस बाट साभार गरिएको हुन सक्छ। GBV केसहरूको लागी यो बटन केस देखाउने पृष्ठको शीर्षमा छ र समग्रमा केसको जानकारी संग मेल खान्छ। केही घटना ट्रयाकिंग गर्ने सन्दर्भमा, यो बटन "घटना विवरण" सहायक फारममा छ। यस स्थितिमा, केहि जानकारी बटन क्लिक गरिएको घटना विवरण सहायक फारम बाट साभार भएको हुन सक्छ । साथै, समग्रमा केस बाट नै साभार भएको पनि हुन सक्छ। भन्नाले, सिर्जना गरिएको नयाँ घटनामा व्यक्तिगत घटना विवरण सहायक फारममा भएको "हिंसाको प्रकार" भन्ने फिल्ड हुन सक्छ र उमेर अनि केसको लिंग पनि समावेश भएको हुन सक्छ। ध्यान दिनुहोस् कि यो अनुमतिले प्रयोगकर्तालाई घटना सँग सम्बन्धित एउटा लिंक हेर्ने अनुमति पनि दिन्छ। label: एउटा केसबाट घटना सिर्जना गर्नुहोस् । manage: - explanation: "प्रयोगकर्तालाई केसहरूमा सबै उपलब्ध कार्यहरू गर्ने अनुमति दिन्छ । \"प्रबन्ध\" अनुमतिले मुख्यत \"सबै कुरा\" भन्ने अर्थ दिन्छ । " + explanation: 'प्रयोगकर्तालाई केसहरूमा सबै उपलब्ध कार्यहरू गर्ने अनुमति दिन्छ । "प्रबन्ध" अनुमतिले मुख्यत "सबै कुरा" भन्ने अर्थ दिन्छ । ' label: प्रबन्ध गर्नुहोस् (यो स्रोत प्रकारको लागि सबै अनुमतिहरू) read: explanation: केस हेर्न गर्ने क्षमता @@ -2406,52 +2313,52 @@ ne: explanation: प्रयोगकर्तालाई रेफरल प्राप्त गर्न अनुमति दिन्छ। यो अनुमति पाएका प्रयोगकर्ताहरू रेफरल कार्यको सम्भावित प्राप्तकर्ताको रूपमा देखा पर्नेछन् भने कसैले रेफरल मोडलमा प्राप्तकर्ता खोजी गर्दा यो अनुमति नपाएका प्रयोगकर्ताहरू सम्भावित प्राप्तकर्ताको रूपमा देखा पर्ने छैनन् । label: रिफरल प्राप्त गर्नुहोस् । receive_referral_different_module: - explanation: " प्रयोगकर्तालाई फरक प्रीमेरो मोड्युलमा बनाईएको अभिलेखको रेफरल प्राप्त गर्न अनुमति दिन्छ। यो अनुमति पाएका प्रयोगकर्ताहरू रेफरल कार्यको सम्भावित प्राप्तकर्ताको रूपमा देखा पर्नेछन् भने कसैले रेफरल मोडलमा प्राप्तकर्ता खोजी गर्दा प्रयोगकर्ताहरू सम्भावित प्राप्तकर्ताको रूपमा देखा पर्ने छैनन् । " + explanation: ' प्रयोगकर्तालाई फरक प्रीमेरो मोड्युलमा बनाईएको अभिलेखको रेफरल प्राप्त गर्न अनुमति दिन्छ। यो अनुमति पाएका प्रयोगकर्ताहरू रेफरल कार्यको सम्भावित प्राप्तकर्ताको रूपमा देखा पर्नेछन् भने कसैले रेफरल मोडलमा प्राप्तकर्ता खोजी गर्दा प्रयोगकर्ताहरू सम्भावित प्राप्तकर्ताको रूपमा देखा पर्ने छैनन् । ' label: प्रयोगकर्ता बाट फरक मोड्युलमा रेफरल प्राप्त गर्नुहोस् । receive_transfer: explanation: प्रयोगकर्तालाई स्थानान्तरण प्राप्त गर्न अनुमति दिन्छ। यो अनुमति पाएका प्रयोगकर्ताहरू स्थानान्तरण कार्यको सम्भावित प्राप्तकर्ताको रूपमा देखा पर्नेछन् भने कसैले स्थानान्तरण मोडलमा प्राप्तकर्ता खोजी गर्दा यो अनुमति नपाएका प्रयोगकर्ताहरू सम्भावित प्राप्तकर्ताको रूपमा देखा पर्ने छैनन् । label: स्थानान्तरण प्राप्त गर्नुहोस् । referral: explanation: प्रयोगकर्ताले अस्थायी रूपमा अर्को प्रयोगकर्तालाई केसमा पहुँच दिन अनुमति दिन्छ। रेफरलको प्राप्तकर्ताले रेफर गरिएको केसहरुमा आफ्नै केसमा जस्तै कार्यहरू गर्न सक्षम हुनेछन । जब प्राप्तकर्तालाई केसमा पहुँचको आवश्यकता छैन तब उनीहरूले रेफरलहरू र स्थानान्तरण सहायक फारममा भएको "सम्पन्न" बटन क्लिक गर्न सक्छन् । त्यसपछि उनीहरूले केसमा पहुँच गुमाउनेछन्। तपाइँले त्यस्ता प्रयोगकर्तालाई मात्र केस रेफर गर्न सक्नुहुनेछ जसको भूमिकामा रेफरल प्राप्त गर्ने क्षमता छ । - label: "रेफेरल " + label: 'रेफेरल ' referral_from_service: - explanation: "प्रयोगकर्तालाई सेवाहरू सहायक फारममा भएको \"रेफेर \" बटन हेर्न अनुमति दिन्छ। प्रयोगकर्ताले यो बटन क्लिक गर्दा सेवा प्रकार, निकाय, सेवा प्रदायक र स्थान फिल्डहरु सहितको रेफरल मोडल देखा पर्नेछ र प्रयोगकर्ताले रिफर बटन क्लिक गर्दा सेवा सहायक फारमको फिल्डमा सूचनाहरु स्वचालित रुपमा भरिएको हुन्छ ।" + explanation: प्रयोगकर्तालाई सेवाहरू सहायक फारममा भएको "रेफेर " बटन हेर्न अनुमति दिन्छ। प्रयोगकर्ताले यो बटन क्लिक गर्दा सेवा प्रकार, निकाय, सेवा प्रदायक र स्थान फिल्डहरु सहितको रेफरल मोडल देखा पर्नेछ र प्रयोगकर्ताले रिफर बटन क्लिक गर्दा सेवा सहायक फारमको फिल्डमा सूचनाहरु स्वचालित रुपमा भरिएको हुन्छ । label: सेवा सहायक फारामबाट केस रेफेर गर्नुहोस् । remove_assigned_users: - explanation: "प्रयोगकर्तालाई \"अन्य तोकिएका प्रयोगकर्ताहरू\" फिल्डबाट अन्य प्रयोगकर्ताहरूलाई हटाउन अनुमति दिन्छ। केसको लागी रेफरल वा स्थानान्तरण प्राप्त भएको तर उनीहरूले अझै स्वीकार वा अस्वीकार नगरेको प्रयोगकर्ता यहाँ सूचीबद्ध हुन्छ । तपाइँले \"अन्य तोकिएका प्रयोगकर्ताहरू\" फिल्डबाट प्रयोगकर्तालाई हटाउँदा उनीहरूको पहुँच पनि हटाउनुहुनेछ । त्यसैले, अनुमति पाएका प्रयोगकर्ताहरूले पहिले रेफरल पाएका वा केसको स्थानान्तरण बाँकी रहेको प्रयोगकर्ताहरूको केसबाट पहुँच हटाउन सक्छन्। ध्यान राख्नुहोस् कि यो अनुमतिले तब मात्र काम गर्दछ जब यदि वर्तमान प्रयोगकर्ता सँग केस सम्पादन गर्ने क्षमता छ।" + explanation: प्रयोगकर्तालाई "अन्य तोकिएका प्रयोगकर्ताहरू" फिल्डबाट अन्य प्रयोगकर्ताहरूलाई हटाउन अनुमति दिन्छ। केसको लागी रेफरल वा स्थानान्तरण प्राप्त भएको तर उनीहरूले अझै स्वीकार वा अस्वीकार नगरेको प्रयोगकर्ता यहाँ सूचीबद्ध हुन्छ । तपाइँले "अन्य तोकिएका प्रयोगकर्ताहरू" फिल्डबाट प्रयोगकर्तालाई हटाउँदा उनीहरूको पहुँच पनि हटाउनुहुनेछ । त्यसैले, अनुमति पाएका प्रयोगकर्ताहरूले पहिले रेफरल पाएका वा केसको स्थानान्तरण बाँकी रहेको प्रयोगकर्ताहरूको केसबाट पहुँच हटाउन सक्छन्। ध्यान राख्नुहोस् कि यो अनुमतिले तब मात्र काम गर्दछ जब यदि वर्तमान प्रयोगकर्ता सँग केस सम्पादन गर्ने क्षमता छ। label: तोकिएका अन्य प्रयोगकर्तालाई हटाउनुहोस् (रिफर गरिएको प्रयोगकर्ताबाट केसको पहुँचलाई फिर्ता लाने) reopen: - explanation: " प्रयोगकर्तालाई हाल बन्द भएको केस खोल्न अनुमति दिन्छ।" + explanation: ' प्रयोगकर्तालाई हाल बन्द भएको केस खोल्न अनुमति दिन्छ।' label: पुनः खोल्नुहोस् । request_approval_action_plan: - explanation: " प्रयोगकर्ता (प्राय: केस कामदार) ले प्रबन्धकलाई उनीहरुको %{approval_label}केस स्वीकृतिको अनुरोध गर्ने अनुमति दिन्छ।" - label: "%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्" + explanation: ' प्रयोगकर्ता (प्राय: केस कामदार) ले प्रबन्धकलाई उनीहरुको %{approval_label}केस स्वीकृतिको अनुरोध गर्ने अनुमति दिन्छ।' + label: '%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्' request_approval_assessment: - explanation: "प्रयोगकर्ता (प्राय: केस कामदार) ले प्रबन्धकलाई उनीहरुको %{approval_label} केस स्वीकृतिको अनुरोध गर्ने अनुमति दिन्छ।" - label: "%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्" + explanation: 'प्रयोगकर्ता (प्राय: केस कामदार) ले प्रबन्धकलाई उनीहरुको %{approval_label} केस स्वीकृतिको अनुरोध गर्ने अनुमति दिन्छ।' + label: '%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्' request_approval_bia: - explanation: "प्रयोगकर्ता (प्राय: केस कामदार) ले प्रबन्धकलाई उनिहरुको%{approval_label}केस स्वीकृतिको अनुरोध गर्ने अनुमति दिन्छ।" - label: "%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्" + explanation: 'प्रयोगकर्ता (प्राय: केस कामदार) ले प्रबन्धकलाई उनिहरुको%{approval_label}केस स्वीकृतिको अनुरोध गर्ने अनुमति दिन्छ।' + label: '%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्' request_approval_case_plan: - explanation: "प्रयोगकर्ता (प्राय: केस कामदार) ले प्रबन्धकलाई उनीहरुको %{approval_label}केस स्वीकृतिको अनुरोध गर्ने अनुमति दिन्छ।" - label: "%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्" + explanation: 'प्रयोगकर्ता (प्राय: केस कामदार) ले प्रबन्धकलाई उनीहरुको %{approval_label}केस स्वीकृतिको अनुरोध गर्ने अनुमति दिन्छ।' + label: '%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्' request_approval_closure: - explanation: "प्रयोगकर्ता (प्राय: केस कामदार) ले प्रबन्धकलाई उनीहरुको %{approval_label} केस स्वीकृतिको अनुरोध गर्ने अनुमति दिन्छ।" - label: "%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्" + explanation: 'प्रयोगकर्ता (प्राय: केस कामदार) ले प्रबन्धकलाई उनीहरुको %{approval_label} केस स्वीकृतिको अनुरोध गर्ने अनुमति दिन्छ।' + label: '%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्' request_approval_gbv_closure: - explanation: "प्रयोगकर्ता (प्राय: केस कामदार) ले प्रबन्धकलाई उनीहरुको %{approval_label} केस स्वीकृतिको अनुरोध गर्ने अनुमति दिन्छ।" - label: "%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्" + explanation: 'प्रयोगकर्ता (प्राय: केस कामदार) ले प्रबन्धकलाई उनीहरुको %{approval_label} केस स्वीकृतिको अनुरोध गर्ने अनुमति दिन्छ।' + label: '%{approval_label}स्वीकृतिका लागि अनुरोध गर्नुहोस्' request_transfer: - explanation: "\"मोडल हेर्नुहोस्\" मा भएको \"स्थानान्तरण अनुरोध\" बटन देखाउँछ । बटनले प्रयोगकर्तालाई ईमेलको माध्यम बाट वर्तमान अभिलेख मालिकलाई केस स्थानान्तरणको अनुरोधको लागि व्यक्तिगत सन्देश पठाउन अनुमति दिन्छ । बालबालिकाहरुले प्राय: स्थान परिवर्तन गर्ने हुँदा अभिलेख दोहोरिनबाट बच्न केस कामदारहरूलाई जानकारी पठाउन उपयोगी हुन्छ ।" + explanation: '"मोडल हेर्नुहोस्" मा भएको "स्थानान्तरण अनुरोध" बटन देखाउँछ । बटनले प्रयोगकर्तालाई ईमेलको माध्यम बाट वर्तमान अभिलेख मालिकलाई केस स्थानान्तरणको अनुरोधको लागि व्यक्तिगत सन्देश पठाउन अनुमति दिन्छ । बालबालिकाहरुले प्राय: स्थान परिवर्तन गर्ने हुँदा अभिलेख दोहोरिनबाट बच्न केस कामदारहरूलाई जानकारी पठाउन उपयोगी हुन्छ ।' label: स्थानान्तरण अनुरोध गर्नुहोस् search_owned_by_others: - explanation: "प्रयोगकर्तालाई त्यस्ता अभिलेखहरू खोज गर्न अनुमति दिईन्छ जुनमा या त उनीहरूलाई सामान्यतया पहुँच छैन या उनीहरू त्यो केसका अभिलेख मालिक होइनन् , वा (प्रबन्धकहरूको अवस्थामा) किनभने अभिलेख मालिक आफ्नो प्रयोगकर्ता समूहहरूमा छैनन्। ध्यान दिनुहोस् कि, जब प्रयोगकर्ताले सर्च रिजल्ट भ्यूमा केस देख्नेछन्, उनीहरू त्यो केसको लागी केस देखाउनुहोस् पृष्ठमा क्लिक गर्न सक्षम हुनेछैनन् । यसको मतलब उनीहरू केस बारे कुनै विस्तृत जानकारी हेर्न सक्षम हुनेछैनन्।" + explanation: प्रयोगकर्तालाई त्यस्ता अभिलेखहरू खोज गर्न अनुमति दिईन्छ जुनमा या त उनीहरूलाई सामान्यतया पहुँच छैन या उनीहरू त्यो केसका अभिलेख मालिक होइनन् , वा (प्रबन्धकहरूको अवस्थामा) किनभने अभिलेख मालिक आफ्नो प्रयोगकर्ता समूहहरूमा छैनन्। ध्यान दिनुहोस् कि, जब प्रयोगकर्ताले सर्च रिजल्ट भ्यूमा केस देख्नेछन्, उनीहरू त्यो केसको लागी केस देखाउनुहोस् पृष्ठमा क्लिक गर्न सक्षम हुनेछैनन् । यसको मतलब उनीहरू केस बारे कुनै विस्तृत जानकारी हेर्न सक्षम हुनेछैनन्। label: अन्य प्रयोगकर्ताहरूको स्वामित्वमा रहेका केस अभिलेखहरूको खोज गर्नुहोस् । service_provision_incident_details: explanation: प्रयोगकर्तालाई घटना मोडल थप्नुहोस् को तल भएको "सुरक्षित गर्नुहोस् र सेवा प्रावधान थप्नुहोस्" भन्ने लेबल भएको बटन हेर्न अनुमति दिन्छ। यो बटन क्लिक गर्नाले घटनाको हाल प्रविष्ट गरेको जानकारी सुरक्षित गर्दछ र प्रयोगकर्तालाई सीधा सेवा प्रावधान थप्नुहोस् मोडलमा लैजान्छ । यो कार्य सीधै घटना थप्नुहोस् र सेवा प्रावधान कार्यहरू थप्नुहोस् संग जोडिएको हुनाले "अर्को प्रयोगकर्ताको केसमा घटनाको विवरण थप्नुहोस्" र "अर्को प्रयोगकर्ताको केसमा सेवा प्रावधान थप्नुहोस्" को अनुमति पाएको भूमिकालाई यो अनुमति दिन जायज हुन्छ । label: घटना विवरण मोडलमा सेवा प्रावधान थप्ने बटन हेर्नुहोस् । services_section_from_case: - explanation: "तपाइँले खोजी परीणामहरुमा केस भेटेको तर जसमा तपाइँको पहुँचको नभएको सेवाहरू सहायक फारममा एउटा प्रविष्टि थप्न सक्ने क्षमता । प्रयोगकर्ताले एक वा धेरै केसहरू छनौट गरेपछि कार्य मेनु बाट \"सेवा प्रावधान थप्नुहोस्\" बटन छनौट गरी खोज परिणाम पृष्ठ बाट यो कार्य गर्दछन् । प्रयोगकर्ताले त्यसपछि सहायक फारममा सबै क्षेत्रहरू भएका मोडल देख्छन् जहाँ उनीहरूले सेवा बारे जानकारी प्रविष्ट र पेश गर्न सक्छन् । यो कार्य खोज परिणाम पृष्ठबाट मात्र गर्न सकिने हुनाले र यदि भूमिकालाई \"अन्य प्रयोगकर्ताहरूको स्वामित्वमा रहेको केस अभिलेख खोज गर्ने\" अनुमति छ भने उनीहरूले यो अनुमति पाउन जायज छ । " + explanation: 'तपाइँले खोजी परीणामहरुमा केस भेटेको तर जसमा तपाइँको पहुँचको नभएको सेवाहरू सहायक फारममा एउटा प्रविष्टि थप्न सक्ने क्षमता । प्रयोगकर्ताले एक वा धेरै केसहरू छनौट गरेपछि कार्य मेनु बाट "सेवा प्रावधान थप्नुहोस्" बटन छनौट गरी खोज परिणाम पृष्ठ बाट यो कार्य गर्दछन् । प्रयोगकर्ताले त्यसपछि सहायक फारममा सबै क्षेत्रहरू भएका मोडल देख्छन् जहाँ उनीहरूले सेवा बारे जानकारी प्रविष्ट र पेश गर्न सक्छन् । यो कार्य खोज परिणाम पृष्ठबाट मात्र गर्न सकिने हुनाले र यदि भूमिकालाई "अन्य प्रयोगकर्ताहरूको स्वामित्वमा रहेको केस अभिलेख खोज गर्ने" अनुमति छ भने उनीहरूले यो अनुमति पाउन जायज छ । ' label: अर्को प्रयोगकर्ताको केसमा सेवा प्रावधान थप्नुहोस् । sync_external: explanation: बाह्य सूचना व्यवस्थापन प्रणालीसँग अभिलेखलाई sync गर्ने क्षमता । @@ -2463,65 +2370,65 @@ ne: explanation: प्रयोगकर्तालाई स्थानान्तरण प्राप्त गर्ने क्षमता सँगै आफ्नो वर्तमान अभिलेख मालिक बाट प्रणालीमा भएको कुनै पनी प्रयोगकर्तालाई केस पठाउन अनुमति दिन्छ। स्थानान्तरणको प्राप्तकर्ताले "स्वीकार" नगरे सम्म केसको अभिलेख मालिक परिवर्तन हुँदैन । यदि प्राप्तकर्ताले स्थानान्तरण "अस्वीकार" गरेमा केसको पहुँच गुमाउँछ र यसको मूल अभिलेख मालिक पहिले कै रहन्छ । label: स्थानान्तरण गर्नुहोस् । view_photo: - explanation: "प्रयोगकर्तालाई केस सूची बाट केसको फोटो हेर्न अनुमति दिन्छ। यो अनुमति बिना, प्रयोगकर्ताले केस सूची तालिका को \"फोटो\" स्तम्भ, वा फोटो आइकनहरू देख्न सक्दैनन् । यो अनुमतिले प्रयोगकर्तालाई \"मोडल हेर्नुहोस्\" मा बालबालिकाको फोटो हेर्ने अनुमति पनि दिन्छ।" + explanation: प्रयोगकर्तालाई केस सूची बाट केसको फोटो हेर्न अनुमति दिन्छ। यो अनुमति बिना, प्रयोगकर्ताले केस सूची तालिका को "फोटो" स्तम्भ, वा फोटो आइकनहरू देख्न सक्दैनन् । यो अनुमतिले प्रयोगकर्तालाई "मोडल हेर्नुहोस्" मा बालबालिकाको फोटो हेर्ने अनुमति पनि दिन्छ। label: केस लिस्ट भ्यू बाट फोटो हेर्नुहोस् view_incident_from_case: - explanation: "\"प्रयोगकर्ताले केस हेर्दै गर्दा केस संग जोडिएको घटनाहरूको सूची देख्न सक्छ र साथै प्रत्येक केसको बारे सारांशमा केही जानकारी पनि देख्न सक्छ ।" + explanation: '"प्रयोगकर्ताले केस हेर्दै गर्दा केस संग जोडिएको घटनाहरूको सूची देख्न सक्छ र साथै प्रत्येक केसको बारे सारांशमा केही जानकारी पनि देख्न सक्छ ।' label: केस बाट घटनाहरू हेर्नुहोस्। view_protection_concerns_filter: explanation: प्रयोगकर्तालाई केस सूची पृष्ठमा संरक्षण चासो सम्बन्धी फिल्टर हेर्ने अनुमति दिन्छ। - label: " केस सूची पृष्ठमा संरक्षण चासो सम्बन्धी फिल्टरहरू हेर्नुहोस्" + label: ' केस सूची पृष्ठमा संरक्षण चासो सम्बन्धी फिल्टरहरू हेर्नुहोस्' view_registry_record: explanation: प्रयोगकर्तालाई केससँग लिङ्क गरिएको कुनै पनि रजिस्ट्रीको जानकारी हेर्न अनुमति दिन्छ। साथै प्रयोगकर्तालाई घटनाको रजिस्ट्री विवरण हेर्न अनुमति दिन्छ। label: केसबाट रजिस्ट्री रेकर्ड हेर्नुहोस् write: - explanation: "\"सम्पादन\" बटन क्लिक गर्ने, केसमा जानकारी अद्यावधिक गर्ने र 'सुरक्षित गर्नुहोस्' बटनमा क्लिक गर्ने क्षमता" + explanation: '"सम्पादन" बटन क्लिक गर्ने, केसमा जानकारी अद्यावधिक गर्ने र ''सुरक्षित गर्नुहोस्'' बटनमा क्लिक गर्ने क्षमता' label: सम्पादन गर्नुहोस् accept_or_reject_transfer: - explanation: "प्रयोगकर्तालाई तपाईको टोलीमा रहेको अर्को प्रयोगकर्ताको तर्फबाट स्थानान्तरण स्वीकार वा अस्वीकार गर्न अनुमति दिन्छ (उदाहरणका लागि, सामाजिक कार्यकर्तालाई स्थानान्तरण स्वीकार गर्न पठाइएको घटना पर्यवेक्षकले स्वीकार गर्नु)।" + explanation: प्रयोगकर्तालाई तपाईको टोलीमा रहेको अर्को प्रयोगकर्ताको तर्फबाट स्थानान्तरण स्वीकार वा अस्वीकार गर्न अनुमति दिन्छ (उदाहरणका लागि, सामाजिक कार्यकर्तालाई स्थानान्तरण स्वीकार गर्न पठाइएको घटना पर्यवेक्षकले स्वीकार गर्नु)। label: तपाईको टोलीमा अर्को प्रयोगकर्ताको लागि स्थानान्तरण स्वीकार वा अस्वीकार गर्नुहोस्। list_case_names: - explanation: "प्रबन्धकहरूले सामान्यतया केस सूचीमा केसहरूको नाम देख्न सक्दैनन्। यदि प्रबन्धकसँग यो अनुमति छ भने, उनीहरूले सूचीमा नामहरू हेर्न सक्षम हुनेछन्।" - label: "यदि प्रबन्धकले चाहेको खण्डमा, केस सूचीमा रहेको केस नामहरू हेर्न सक्दछन् ।" + explanation: प्रबन्धकहरूले सामान्यतया केस सूचीमा केसहरूको नाम देख्न सक्दैनन्। यदि प्रबन्धकसँग यो अनुमति छ भने, उनीहरूले सूचीमा नामहरू हेर्न सक्षम हुनेछन्। + label: यदि प्रबन्धकले चाहेको खण्डमा, केस सूचीमा रहेको केस नामहरू हेर्न सक्दछन् । mark_for_offline: explanation: प्रयोगकर्तालाई अफलाईन प्रयोगको लागि केस cache गर्न अनुमति दिन्छ। label: अफलाईनको लागि चिन्ह लगाउनुहोस् - explanation: "बालबालिका, हिंसाबाट बचेका, वा अन्य लाभग्राहीको प्रतिनिधित्व गर्दछ।" + explanation: बालबालिका, हिंसाबाट बचेका, वा अन्य लाभग्राहीको प्रतिनिधित्व गर्दछ। label: केस dashboard: actions: approvals_action_plan: - explanation: "विचाराधीन, स्वीकृत वा अस्वीकृत कार्य योजना स्वीकृति अनुरोधहरूको संख्या चालु प्रयोगकर्तालाई देखाउँछ। " - label: "केस कामदारद्वारा स्वीकृत %{approval_label}" + explanation: 'विचाराधीन, स्वीकृत वा अस्वीकृत कार्य योजना स्वीकृति अनुरोधहरूको संख्या चालु प्रयोगकर्तालाई देखाउँछ। ' + label: केस कामदारद्वारा स्वीकृत %{approval_label} approvals_action_plan_pending: explanation: प्रबन्धकको टोलीमा भएको विचाराधीन कार्य योजना स्वीकृति अनुरोधहरूको संख्या देखाउँछ। - label: "प्रबन्धकद्वारा स्वीकृत %{approval_label}" + label: प्रबन्धकद्वारा स्वीकृत %{approval_label} approvals_assessment: - explanation: "विचाराधीन, स्वीकृत वा अस्वीकृत मूल्यांकन स्वीकृतिको अनुरोध संख्या चालु प्रयोगकर्तालाई देखाउँछ। " - label: "केस कामदारद्वारा स्वीकृत%{approval_label}" + explanation: 'विचाराधीन, स्वीकृत वा अस्वीकृत मूल्यांकन स्वीकृतिको अनुरोध संख्या चालु प्रयोगकर्तालाई देखाउँछ। ' + label: केस कामदारद्वारा स्वीकृत%{approval_label} approvals_assessment_pending: explanation: प्रबन्धकको टोलीमा भएको विचाराधीन मूल्यांकन स्वीकृतिको अनुरोध संख्या देखाउँछ। - label: "प्रबन्धकद्वारा स्वीकृत %{approval_label}" + label: प्रबन्धकद्वारा स्वीकृत %{approval_label} approvals_case_plan: - explanation: "विचाराधीन, स्वीकृत वा अस्वीकृत केस योजना स्वीकृतिको अनुरोध संख्या चालु प्रयोगकर्ताहरुलाई देखाउँछ। " - label: "केस कामदारद्वारा स्वीकृत %{approval_label}" + explanation: 'विचाराधीन, स्वीकृत वा अस्वीकृत केस योजना स्वीकृतिको अनुरोध संख्या चालु प्रयोगकर्ताहरुलाई देखाउँछ। ' + label: केस कामदारद्वारा स्वीकृत %{approval_label} approvals_case_plan_pending: explanation: प्रबन्धकको टोलीमा भएको विचाराधीन केस योजना स्वीकृतिहरुको अनुरोध संख्या देखाउँछ। - label: "प्रबन्धकद्वारा स्वीकृत %{approval_label}" + label: प्रबन्धकद्वारा स्वीकृत %{approval_label} approvals_closure: - explanation: "विचाराधीन, स्वीकृत वा अस्वीकृत समापन स्वीकृतिको लागि गरिएको अनुरोधहरूको संख्या प्रयोगकर्तालाई देखाउँछ। " - label: "केस कामदारद्वारा स्वीकृत %{approval_label}" + explanation: 'विचाराधीन, स्वीकृत वा अस्वीकृत समापन स्वीकृतिको लागि गरिएको अनुरोधहरूको संख्या प्रयोगकर्तालाई देखाउँछ। ' + label: केस कामदारद्वारा स्वीकृत %{approval_label} approvals_closure_pending: explanation: प्रबन्धकको टोलीमा भएको विचाराधीन समापन स्वीकृति अनुरोधहरूको संख्या देखाउँछ। - label: "प्रबन्धकद्वारा स्वीकृत %{approval_label}" + label: प्रबन्धकद्वारा स्वीकृत %{approval_label} approvals_gbv_closure: - explanation: "विचाराधीन, स्वीकृत वा अस्वीकृत GBV समापन स्वीकृतिका अनुरोधहरू केस संख्या चालु प्रयोगकर्तालाई देखाउँछ। " - label: "केस कामदारद्वारा स्वीकृत %{approval_label}" + explanation: 'विचाराधीन, स्वीकृत वा अस्वीकृत GBV समापन स्वीकृतिका अनुरोधहरू केस संख्या चालु प्रयोगकर्तालाई देखाउँछ। ' + label: केस कामदारद्वारा स्वीकृत %{approval_label} approvals_gbv_closure_pending: explanation: प्रबन्धकको टोलीमा भएको विचाराधीन GBV बन्द गर्न स्वीकृतिका लागि अनुरोध संख्या देखाउँछ। - label: "प्रबन्धकद्वारा स्वीकृत %{approval_label}" + label: प्रबन्धकद्वारा स्वीकृत %{approval_label} case_overview: - explanation: "कुल र नयाँ केसहरू समावेश तथ्याङ्क ड्यासबोर्डको गृह पृष्ठको माथिल्लो भागमा समावेश गरिनेछ । " + explanation: 'कुल र नयाँ केसहरू समावेश तथ्याङ्क ड्यासबोर्डको गृह पृष्ठको माथिल्लो भागमा समावेश गरिनेछ । ' label: ड्यासबोर्ड अवलोकन गर्नुहोस् case_risk: explanation: प्रत्येक जोखिम स्तरमा कति वटा केसहरू छन् भन्ने देखाउँछ। @@ -2530,19 +2437,18 @@ ne: explanation: प्रबन्धकलाई प्रत्येक केस कामदारहरूको म्याद नाघेको मूल्या्कन कार्यहरूको केस संख्या हेर्ने अनुमति दिन्छ । label: म्याद नाघेको मूल्याङकन कार्यहरू cases_by_task_overdue_case_plan: - explanation: "प्रबन्धकलाई प्रत्येक केस कामदारहरूको म्याद नाघेको केस योजना कार्यहरूको केस संख्या हेर्ने अनुमति दिन्छ । " + explanation: 'प्रबन्धकलाई प्रत्येक केस कामदारहरूको म्याद नाघेको केस योजना कार्यहरूको केस संख्या हेर्ने अनुमति दिन्छ । ' label: म्याद नाघेको केस योजना कार्यहरू cases_by_task_overdue_followups: - explanation: "प्रबन्धकलाई प्रत्येक केस कामदारहरूको म्याद नाघेको फलोअप कार्यहरूको केस संख्या हेर्नेअनुमति दिन्छ । " + explanation: 'प्रबन्धकलाई प्रत्येक केस कामदारहरूको म्याद नाघेको फलोअप कार्यहरूको केस संख्या हेर्नेअनुमति दिन्छ । ' label: म्याद नाघेको फलोअप कार्यहरू cases_by_task_overdue_services: - explanation: "प्रबन्धकलाई प्रत्येक केस कामदारहरूको म्याद नाघेको सेवा कार्यहरूको केस संख्या हेर्ने अनुमति दिन्छ । " + explanation: 'प्रबन्धकलाई प्रत्येक केस कामदारहरूको म्याद नाघेको सेवा कार्यहरूको केस संख्या हेर्ने अनुमति दिन्छ । ' label: म्याद नाघेको सेवा कार्यहरू dash_case_incident_overview: - explanation: . label: संक्षेपमा मेरो केस/घटनाहरू dash_cases_by_social_worker: - explanation: "वर्तमान प्रयोगकर्ता समूहका प्रत्यक प्रयोगकर्ताले खुल्ला केस र नयाँ केसहरूको व्यवस्थापन कसरी गरिरहेका छन् भनेर देखाउने तालिका । तालिकाको प्रत्येक पंक्ति वर्तमान प्रयोगकर्ता समूहमा भएको प्रयोगकर्ता हो भने \"कुल\" र \"नयाँ\" दुई स्तम्भहरू हुन् । " + explanation: 'वर्तमान प्रयोगकर्ता समूहका प्रत्यक प्रयोगकर्ताले खुल्ला केस र नयाँ केसहरूको व्यवस्थापन कसरी गरिरहेका छन् भनेर देखाउने तालिका । तालिकाको प्रत्येक पंक्ति वर्तमान प्रयोगकर्ता समूहमा भएको प्रयोगकर्ता हो भने "कुल" र "नयाँ" दुई स्तम्भहरू हुन् । ' label: सामाजिक कार्यकर्ताहरू अनुसार केसहरू हेर्नुहोस् । dash_cases_to_assign: explanation: 'महत्वपूर्ण: प्रबन्धकहरूको लागी मात्र। वर्तमान प्रयोगकर्ता (प्रबन्धक हुनु पर्छ) को स्वामित्वमा रहेका केसहरूको संख्या देखाउँछ। यो ड्यासबोर्डको मान्यता अनुसार प्रबन्धकहरूले आफ्नो केसहरू ब्यबस्थापन गर्दैनन् र यदि प्रबन्धकको आफ्नै केसहरू छन्, भने उनीहरूले ती केसहरूलाई आफ्नो टोलिमा भएका केस कामदारहरूलाई तोक्नु पर्छ।' @@ -2557,17 +2463,17 @@ ne: explanation: DEPRECATED । यो ड्यासबोर्ड हाल संचालनमा छैन र यसलाई दोस्रो संस्करण v2 मा हटाइनेछ। label: मिलन भएका नतिजाहरू हेर्नुहोस् dash_protection_concerns: - explanation: "कति केसहरूमा संरक्षण चासो छन् भनेर देखाउने तालिका । तालिकाको प्रत्येक पंक्ति संरक्षण चासो हो, र स्तम्भहरूले केसहरूको बिभिन्न स्थितिको संकेत गर्दछ (जस्तै : \"सबै केसहरू\", \"खुला केस,\" \"नयाँ(यो हप्ता),\" \"बन्द (यो हप्ता)\")।" - label: "संरक्षणको चासो अनुसार केसहरू " + explanation: 'कति केसहरूमा संरक्षण चासो छन् भनेर देखाउने तालिका । तालिकाको प्रत्येक पंक्ति संरक्षण चासो हो, र स्तम्भहरूले केसहरूको बिभिन्न स्थितिको संकेत गर्दछ (जस्तै : "सबै केसहरू", "खुला केस," "नयाँ(यो हप्ता)," "बन्द (यो हप्ता)")।' + label: 'संरक्षणको चासो अनुसार केसहरू ' dash_protection_concerns_by_location: explanation: यो "संरक्षण चासो देखाउनुहोस् " ड्यासबोर्ड जस्तै हो । फरक यति मात्र हो कि प्रयोगकर्ताले एउटा ड्रपडाउन बाट स्थान छनौट गरेर त्यस स्थानमा मात्र रहेको संरक्षण चासोको तथ्याङ्क देखाउन सक्छन् । - label: "स्थान अनुसार संरक्षणको चासोहरू हेर्नुहोस् । " + label: 'स्थान अनुसार संरक्षणको चासोहरू हेर्नुहोस् । ' dash_reporting_location: - explanation: "प्रत्येक स्थानमा कति केसहरू छन् भनेर देखाउने तालिका (\"प्रदेश\" वा \"जिल्ला\" को स्तरमा )। तालिका को प्रत्येक पंक्ति एउटा स्थान हो, र स्तम्भहरूले केसहरूको बिभिन्न स्थितिको संकेत गर्दछ (जस्तै : \"खुला केस,\" \"नयाँ (गत हप्ता),\" \"नयाँ (यो हप्ता),\" \"बन्द (गत हप्ता),\" \"बन्द (यो हप्ता)\")। सामान्यतया प्रबन्धक वा प्रशासक खाता को लागी प्रयोग गरीन्छ। " + explanation: 'प्रत्येक स्थानमा कति केसहरू छन् भनेर देखाउने तालिका ("प्रदेश" वा "जिल्ला" को स्तरमा )। तालिका को प्रत्येक पंक्ति एउटा स्थान हो, र स्तम्भहरूले केसहरूको बिभिन्न स्थितिको संकेत गर्दछ (जस्तै : "खुला केस," "नयाँ (गत हप्ता)," "नयाँ (यो हप्ता)," "बन्द (गत हप्ता)," "बन्द (यो हप्ता)")। सामान्यतया प्रबन्धक वा प्रशासक खाता को लागी प्रयोग गरीन्छ। ' label: रिपोर्टि स्थानहरू अनुसार केसहरू dash_service_provisions: explanation: अन्य प्रयोगकर्ताहरूले सेवा प्रावधान थपेका केसहरूको संख्या देखाउँछ। यो नम्बर ड्यासबोर्डको मुख्य खण्डमा देखिन्छ। - label: " सेवा प्रावधानको प्रकार अनुसार केसहरू" + label: ' सेवा प्रावधानको प्रकार अनुसार केसहरू' dash_shared_from_my_team: explanation: प्रबन्धकलाई उनीहरूको टोलीको प्रत्येक प्रयोगकर्ता द्वारा अन्य प्रयोगकर्ताहरूलाई रेफर वा हस्तान्तरण गरिएको केसहरूको संख्या देखाउँछ। label: मेरो समूहबाट शेयर गरिएको @@ -2580,7 +2486,7 @@ ne: dash_shared_with_my_team_overview: label: मेरो समूहमा आदानप्रदान गरिएको (संक्षेपमा) dash_shared_with_others: - explanation: "मेरा केसहरू मध्ये कति सक्रिय रेफरलहरु, विचाराधीन स्थानान्तरण, वा अस्वीकृत स्थानान्तरण छन् भन्ने देखाउँछ। यो सामान्यतया प्रबन्धकहरूको लागी होईन, यदि उनीहरु आफैं केसहरूको ब्यबस्थापन गर्दैनन् भने ।" + explanation: मेरा केसहरू मध्ये कति सक्रिय रेफरलहरु, विचाराधीन स्थानान्तरण, वा अस्वीकृत स्थानान्तरण छन् भन्ने देखाउँछ। यो सामान्यतया प्रबन्धकहरूको लागी होईन, यदि उनीहरु आफैं केसहरूको ब्यबस्थापन गर्दैनन् भने । label: अरुलाई शेयर भएको dash_violations_category_verification_status: explanation: प्रमाणीकरण स्थिति अनुसार प्रत्येक प्रकार को कति MRM उल्लङ्घनहरू भएको छ भन्ने देखाउँछ । @@ -2592,35 +2498,35 @@ ne: explanation: पीडक अनुसार कति MRM उल्लङ्घनहरू भएका छन् भन्ने देखाउँछ label: MRM - पीडक अनुसार उल्लङ्घनको संख्या dash_show_none_values: - explanation: " \"कुनै जोखिम स्तर छैन\" भन्ने वर्ग सबै ड्यासबोर्डहरूमा थपिन्छ जसले जोखिम स्तरको आधारमा केसहरूलाई छुट्टयाउँछ । यो विशेष गरी जोखिम स्तर क्षेत्रहरूको लागी \"कुनै जोखिम छैन\" भन्ने चौथो विकल्प भएको कन्फिगरेसनको लागी हो।" + explanation: ' "कुनै जोखिम स्तर छैन" भन्ने वर्ग सबै ड्यासबोर्डहरूमा थपिन्छ जसले जोखिम स्तरको आधारमा केसहरूलाई छुट्टयाउँछ । यो विशेष गरी जोखिम स्तर क्षेत्रहरूको लागी "कुनै जोखिम छैन" भन्ने चौथो विकल्प भएको कन्फिगरेसनको लागी हो।' label: मूल्याङकन ड्यासबोर्डमा 'कुनै जोखिम स्तर छैन' अनुसार केसहरू हेर्नुहोस् । dash_tasks: explanation: प्रयोगकर्तालाई कार्य पृष्ठ हेर्ने अनुमति दिन्छ। संख्याहरू विशेष गरी तपाइँले प्रत्यक्ष व्यवस्थापन गर्ने केसको लागी हुनाले यो केस कामदारहरू र सेवा प्रदायकहरूको लागी प्रयोग गरिनु पर्दछ। प्रबन्धकहरूलाई "म्याद नाघेका कार्यहरू द्वारा केसहरू हेर्नुहोस्" ड्यासबोर्डमा पाउनेछन जसले गर्दा उनीहरूलाई प्रयोगकर्ता समूहहरूमा भएका सबै म्याद नाघेका कार्यहरू हेर्न दिन्छ। label: कार्य पृष्ठ dash_national_admin_summary: - explanation: "प्रणालीमा भएका कुल खुल्ला केसहरू, गत दुई हप्तामा सिर्जना गरिएका नयाँ केसहरूको संख्या र प्रत्येक गत दुई हप्तामा बन्द गरिएका केसहरूको संख्या देखाउँछ।" + explanation: प्रणालीमा भएका कुल खुल्ला केसहरू, गत दुई हप्तामा सिर्जना गरिएका नयाँ केसहरूको संख्या र प्रत्येक गत दुई हप्तामा बन्द गरिएका केसहरूको संख्या देखाउँछ। label: प्रशासकीय सारांश view_response: - explanation: "प्रत्येक प्रतिक्रिया प्रकारको लागी, म्याद नजिक पुगेका वा म्याद नाघेका सेवाहरू प्रत्येक जोखिम स्तरमा कति केसहरू छन् भन्ने देखाउँछ ।" + explanation: प्रत्येक प्रतिक्रिया प्रकारको लागी, म्याद नजिक पुगेका वा म्याद नाघेका सेवाहरू प्रत्येक जोखिम स्तरमा कति केसहरू छन् भन्ने देखाउँछ । label: प्रतिक्रियाहरू हेर्नुहोस् । workflow: - explanation: "केस कामदारलाई एउटा पाई ग्राफमा केस व्यवस्थापन कार्यप्रवाहको प्रत्येक चरणमा उनीहरूको केसहरूको संख्या हेर्ने अनुमति दिन्छ । " + explanation: 'केस कामदारलाई एउटा पाई ग्राफमा केस व्यवस्थापन कार्यप्रवाहको प्रत्येक चरणमा उनीहरूको केसहरूको संख्या हेर्ने अनुमति दिन्छ । ' label: कार्यप्रवाहको आधारमा विभाजन गरिएका केसहरू workflow_team: - explanation: "प्रबन्धकलाई एउटा तालिकामा केस व्यवस्थापन प्रकृयाको प्रत्येक चरणमा भएका सामाजिक कार्यकर्ताका केसहरूको संख्या हेर्ने अनुमति दिन्छ । " + explanation: 'प्रबन्धकलाई एउटा तालिकामा केस व्यवस्थापन प्रकृयाको प्रत्येक चरणमा भएका सामाजिक कार्यकर्ताका केसहरूको संख्या हेर्ने अनुमति दिन्छ । ' label: कार्यप्रवाह र केस कामदारहरूको आधारमा केसहरू explanation: गृह पृष्ठमा कुन सारांश जानकारी देखा पर्दछ भनेर निर्धारण गर्दछ। label: ड्यासबोर्ड disabled: - explanation: "यदि तपाईंले यो भूमिकालाई निष्कृय गर्नु भयो भने, अब उप्रान्त प्रयोगकर्ता खाताहरूलाई तोक्न सक्षम हुनुहुने छैन ।" + explanation: यदि तपाईंले यो भूमिकालाई निष्कृय गर्नु भयो भने, अब उप्रान्त प्रयोगकर्ता खाताहरूलाई तोक्न सक्षम हुनुहुने छैन । label: निष्क्रिय पारिएको duplicate: actions: read: - explanation: "नाम, उपनाम, लिंग, उमेर, र राष्ट्रियता सहितको मापदण्ड प्रयोग गरेर प्रणालीमा भएका सबै केसहरूको उच्च स्तरको खोज गर्न प्रयोगकर्तालाई अनुमति दिन्छ।" + explanation: नाम, उपनाम, लिंग, उमेर, र राष्ट्रियता सहितको मापदण्ड प्रयोग गरेर प्रणालीमा भएका सबै केसहरूको उच्च स्तरको खोज गर्न प्रयोगकर्तालाई अनुमति दिन्छ। label: हेर्नुहोस । explanation: प्रशासकहरूको लागि एड्भान्स केस सर्च - label: "डुप्लिकेटको खोजी " + label: 'डुप्लिकेटको खोजी ' forms: case: explanation: 'केस फारममा प्रयोगकर्ताको पहुँच सीमित गर्नाले प्रयोगकर्ताले एउटा घटनामा हेर्न सक्ने जानकारी पनि सीमित गर्दछ । उदाहरणको लागी, यदि प्रयोगकर्तालाई अभिलेख मालिक फारममा मात्र पहुँच छ भने उनीहरूले त्यो फारमको फिल्डहरूमा रहेको जानकारी मात्र हेर्न सक्षम हुनेछन्। यदि वर्तमान प्रयोगकर्ताको फारममा सीमित पहुँच छ र फारम कन्फिगरेसन व्यवस्थापन गर्ने क्षमता छ भने उनीहरुलाई फारमको पहुँचमा सीमित हुनुका साथै फारम कन्फिगरेसन गर्नमा पनि पहुँच सीमित गर्छ। नोट: यदि कुनै फारम निर्दिष्ट गरीएको छैन भने त्यसको मतलब केसको सबै फारमको पहुँचको भूमिका रहन्छ । ' @@ -2637,82 +2543,82 @@ ne: group: actions: admin_only: - explanation: "यसको मतलब यो भूमिकाका भएको प्रयोगकर्ताहरूले प्रणालीको प्रशासनसंग सम्बन्धित रिपोर्ट, फारम र लुकअप कन्फिगरेसन, प्रयोगकर्ताहरू, भूमिकाहरू, र प्रयोगकर्ता समूहहरू जस्ता कुराहरू मात्र हेर्न सक्षम हुनेछन् । उनीहरूले कुनै पनी व्यक्तिगत केसहरू, ट्रेसिङ्ग अनुरोधहरू वा घटनाहरू देख्ने छैनन्।" + explanation: यसको मतलब यो भूमिकाका भएको प्रयोगकर्ताहरूले प्रणालीको प्रशासनसंग सम्बन्धित रिपोर्ट, फारम र लुकअप कन्फिगरेसन, प्रयोगकर्ताहरू, भूमिकाहरू, र प्रयोगकर्ता समूहहरू जस्ता कुराहरू मात्र हेर्न सक्षम हुनेछन् । उनीहरूले कुनै पनी व्यक्तिगत केसहरू, ट्रेसिङ्ग अनुरोधहरू वा घटनाहरू देख्ने छैनन्। label: कुनै अभिलेख छैन - व्यवस्थापक कार्यक्षमताको लागि मात्र agency: explanation: भूमिकाले आफ्नो निकायमा भएका सबै प्रयोगकर्ताहरू द्वारा व्यवस्थित अभिलेखहरू पहुँच गर्न सक्छन् । यदि प्रयोगकर्तालाई प्रयोगकर्ताको पहुँच छ भने उनीहरूले आफ्नो निकायका सबै प्रयोगकर्ताहरूलाई पहुँच गर्न सक्छन्। label: मेरो निकायमा भएका सबै अभिलेखहरू वा प्रयोगकर्ताहरू। all: - explanation: "यस भूमिकाले आफु जुन सुकै प्रयोगकर्ता समूह सँग सम्बन्धित भएता पनि प्रणालीमा भएका सबै अभिलेखहरू, प्रयोगकर्ताहरू र प्रयोगकर्ता समूहहरू पहुँच गर्न सक्छन् ।" + explanation: यस भूमिकाले आफु जुन सुकै प्रयोगकर्ता समूह सँग सम्बन्धित भएता पनि प्रणालीमा भएका सबै अभिलेखहरू, प्रयोगकर्ताहरू र प्रयोगकर्ता समूहहरू पहुँच गर्न सक्छन् । label: सबै अभिलेख वा प्रयोगकर्ताहरू पहुँच गर्नुहोस् । group: - explanation: "यो भूमिकाले प्रयोगकर्ता समूहमा भएका सबै प्रयोगकर्ताहरूद्वारा व्यवस्थित अभिलेखहरू पहुँच गर्न सक्छन् । उनीहरूले आफ्नो प्रयोगकर्ता समूहमा भएका प्रयोगकर्ताहरूमा मात्र पहुँच गर्न सक्छन्। उनीहरूले आफ्नो प्रयोगकर्ता समूह मात्र पहुँच गर्न सक्छन्। " + explanation: 'यो भूमिकाले प्रयोगकर्ता समूहमा भएका सबै प्रयोगकर्ताहरूद्वारा व्यवस्थित अभिलेखहरू पहुँच गर्न सक्छन् । उनीहरूले आफ्नो प्रयोगकर्ता समूहमा भएका प्रयोगकर्ताहरूमा मात्र पहुँच गर्न सक्छन्। उनीहरूले आफ्नो प्रयोगकर्ता समूह मात्र पहुँच गर्न सक्छन्। ' label: मेरो समूहमा भएका सबै अभिलेखहरू वा प्रयोगकर्ताहरूलाई पहुँच गर्नुहोस् । self: - explanation: "भूमिकाले आफ्नो अभिलेख (केस हरू, ट्रेसिङ्ग अनुरोधहरू वा घटनाहरू) पहुँच गर्न र आफ्नो प्रयोगकर्ता खाता सम्पादन गर्न सक्नुहुन्छ।" + explanation: भूमिकाले आफ्नो अभिलेख (केस हरू, ट्रेसिङ्ग अनुरोधहरू वा घटनाहरू) पहुँच गर्न र आफ्नो प्रयोगकर्ता खाता सम्पादन गर्न सक्नुहुन्छ। label: मेरो वा प्रयोगकर्ताको अभिलेखहरू मात्र पहुँच गर्नुहोस् । - explanation: "यो भूमिकाले पहुँच गर्न सक्ने अभिलेखहरू (केसहरु, ट्रेसिङ्ग अनुरोधहरू वा घटनाहरू) नियन्त्रण गर्दछ । यदि भूमिकालाई प्रयोगकर्ताहरू र प्रयोगकर्ता समूहहरूको पहुँच छ भने उनीहरूले पहुँच गर्न सक्ने प्रयोगकर्ताहरू र प्रयोगकर्ता समूहहरू पनि नियन्त्रण गर्दछ । \"कुनै अभिलेखहरू छैन \" को पहुँच भएका भूमिकाहरूबाट फारमहरू, प्रयोगकर्ताहरू र अभिलेखहरू जस्तो प्रणाली कन्फिगरेसन मात्र पहुँच गर्न सक्छन् । " - label: "यो रेकर्डले कुन भूमिकालाई असर गर्छ ?" + explanation: 'यो भूमिकाले पहुँच गर्न सक्ने अभिलेखहरू (केसहरु, ट्रेसिङ्ग अनुरोधहरू वा घटनाहरू) नियन्त्रण गर्दछ । यदि भूमिकालाई प्रयोगकर्ताहरू र प्रयोगकर्ता समूहहरूको पहुँच छ भने उनीहरूले पहुँच गर्न सक्ने प्रयोगकर्ताहरू र प्रयोगकर्ता समूहहरू पनि नियन्त्रण गर्दछ । "कुनै अभिलेखहरू छैन " को पहुँच भएका भूमिकाहरूबाट फारमहरू, प्रयोगकर्ताहरू र अभिलेखहरू जस्तो प्रणाली कन्फिगरेसन मात्र पहुँच गर्न सक्छन् । ' + label: यो रेकर्डले कुन भूमिकालाई असर गर्छ ? incident: actions: change_log: explanation: प्रयोगकर्ताले अभिलेख सिर्जना भएदेखि त्यसमा गरिएका सबै परिवर्तनहरूको इतिहास देख्न सक्छ । यसअन्तर्गत सबै फिल्डहरुको लागि अभिलेख गरिएका मानहरू पनि सामेल छन् । - label: " परिवर्तन लग" + label: ' परिवर्तन लग' create: explanation: घटना सिर्जना गर्न सक्ने क्षमता - label: "सिर्जना गर्नुहोस् " + label: 'सिर्जना गर्नुहोस् ' enable_disable_record: explanation: घटनालाई सक्रिय वा निष्क्रिय गर्ने क्षमता। "निष्क्रिय" घटनाहरू घटना सूचीमा पूर्वनिर्धारित रूपमा देखा पर्दैन। प्रयोगकर्ताहरूले फिल्टर प्रयोग गरेर घटना सूचीमा निष्क्रिय घटनाहरू देख्न सक्छन् । label: सक्रिय/निष्क्रिय पार्नुहोस् export_case_pdf: - explanation: "प्रयोगकर्ताले घटना सूची वा घटना देखाउने पृष्ठहरू बाट PDF फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसहरुको फिल्ड रहेको हुन्छ । PDF export फाइलमा, सूचनालाई पहिला केस सूची अनुसार र त्यसपछि सूचना देखा पर्ने फारम अनुसार थप व्यवस्थित गरीएको छ ।" + explanation: प्रयोगकर्ताले घटना सूची वा घटना देखाउने पृष्ठहरू बाट PDF फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसहरुको फिल्ड रहेको हुन्छ । PDF export फाइलमा, सूचनालाई पहिला केस सूची अनुसार र त्यसपछि सूचना देखा पर्ने फारम अनुसार थप व्यवस्थित गरीएको छ । label: PDF Export गर्नुहोस् export_csv: - explanation: "प्रयोगकर्ताले घटना सूची वा घटना देखाउने पृष्ठहरू बाट CSV फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसहरुको फिल्ड रहेको हुन्छ ।" - label: "CSV Export गर्नुहोस्। " + explanation: प्रयोगकर्ताले घटना सूची वा घटना देखाउने पृष्ठहरू बाट CSV फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसहरुको फिल्ड रहेको हुन्छ । + label: 'CSV Export गर्नुहोस्। ' export_custom: - label: "कस्टम export गर्नुहोस्। " + label: 'कस्टम export गर्नुहोस्। ' export_incident_recorder_xls: - explanation: "प्रयोगकर्ताले विशेष XLS फाइल export गर्न सक्दछन् र यो export बाट GBV घटना रेकर्डर प्रणाली सँग तथ्याड़क साटासाट गर्ने सुविधा प्रदान गर्दछ । " - label: "घटना अभिलेख XLS मा export गर्नुहोस् " + explanation: 'प्रयोगकर्ताले विशेष XLS फाइल export गर्न सक्दछन् र यो export बाट GBV घटना रेकर्डर प्रणाली सँग तथ्याड़क साटासाट गर्ने सुविधा प्रदान गर्दछ । ' + label: 'घटना अभिलेख XLS मा export गर्नुहोस् ' export_mrm_violation_xls: explanation: प्रयोगकर्ताले MRM उल्लङ्घनहरूको लागि विशेष एक्सेल (XLS फाइल) डाउनलोड गर्न सक्दछन्। यो कार्य घटना पृष्ठ र घटना सूचीमा उपलब्ध छ। - label: "MRM उल्लङ्घनहरू एक्सेल (XLS फाइल) मा डाउनलोड गर्नुहोस् " + label: 'MRM उल्लङ्घनहरू एक्सेल (XLS फाइल) मा डाउनलोड गर्नुहोस् ' export_json: - explanation: "प्रयोगकर्ताले घटना सूची वा घटना देखाउने पृष्ठहरूबाट JSON फाइल export गर्न सक्दछन जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण घटनाहरुको फिल्ड रहेको हुन्छ । यो export मुख्य रूपमा ती सबैको लागि प्रयोग गरिन्छ जसले हालको प्रीमेरो प्रणालीबाट घटना export गरेर फरक प्रीमेरो प्रणालीमा वा अन्य सूचना व्यवस्थापन प्रणालीमा import गर्न चाहन्छन् । JSON ढाँचा मेशिन द्वारा पठनीय छ र धेरै प्रयोगकर्ताहरूको लागी व्यावहारिक छैन।" + explanation: प्रयोगकर्ताले घटना सूची वा घटना देखाउने पृष्ठहरूबाट JSON फाइल export गर्न सक्दछन जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण घटनाहरुको फिल्ड रहेको हुन्छ । यो export मुख्य रूपमा ती सबैको लागि प्रयोग गरिन्छ जसले हालको प्रीमेरो प्रणालीबाट घटना export गरेर फरक प्रीमेरो प्रणालीमा वा अन्य सूचना व्यवस्थापन प्रणालीमा import गर्न चाहन्छन् । JSON ढाँचा मेशिन द्वारा पठनीय छ र धेरै प्रयोगकर्ताहरूको लागी व्यावहारिक छैन। label: JSON export गर्नुहोस्। export_list_view_csv: explanation: घटना सूचीमा प्रयोगकर्ताको लागी देखा पर्ने फिल्डहरुबाट प्रयोगकर्ताले एउटा CSV फाइल export गर्न सक्छ । घटना सूची पृष्‍ठ बाट मात्रै कार्य गर्न सकिने। label: लिस्ट भ्यू CSV मा Export गर्नुहोस् export_pdf: - explanation: "प्रयोगकर्ताले घटना सूची वा घटना देखाउने पृष्ठहरूबाट PDF फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसहरुको फिल्ड रहेको हुन्छ । PDF export फाइलमा, सूचनालाई पहिला केस सूची अनुसार र त्यसपछि सूचना देखा पर्ने फारम अनुसार थप व्यवस्थित गरीएको छ ।" - label: "PDF export गर्नुहोस्। " + explanation: प्रयोगकर्ताले घटना सूची वा घटना देखाउने पृष्ठहरूबाट PDF फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसहरुको फिल्ड रहेको हुन्छ । PDF export फाइलमा, सूचनालाई पहिला केस सूची अनुसार र त्यसपछि सूचना देखा पर्ने फारम अनुसार थप व्यवस्थित गरीएको छ । + label: 'PDF export गर्नुहोस्। ' export_xls: - explanation: "प्रयोगकर्ताले घटना सूची वा घटना देखाउने पृष्ठहरूबाट XLS फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसहरुको कस्टम फाईल वा फिल्ड रहेको हुन्छ । यो export मा, प्रत्येक फारमलाई XLS फाइल भित्रको आफ्नै ट्याबमा प्रतिनिधित्व गरीन्छ। कस्टम export मोडलको प्रयोग गरेर प्रयोगकर्ताले export मा आफुले समावेश गर्न चाहे जस्तो फारम वा फिल्डहरु छनौट गर्न सक्नुहुन्छ । कृपया ध्यान दिनुहोस् कि प्रयोगकर्ताहरुले प्रणालीमा केस हेर्दा फारमहरु र फिल्डहरु हेर्ने क्षमता छ भने मात्र export मा फारमहरु र क्षेत्रहरु समावेश गर्न सक्छन् । " - label: "Excel (XLS file) export गर्नुहोस्। " + explanation: 'प्रयोगकर्ताले घटना सूची वा घटना देखाउने पृष्ठहरूबाट XLS फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण केसहरुको कस्टम फाईल वा फिल्ड रहेको हुन्छ । यो export मा, प्रत्येक फारमलाई XLS फाइल भित्रको आफ्नै ट्याबमा प्रतिनिधित्व गरीन्छ। कस्टम export मोडलको प्रयोग गरेर प्रयोगकर्ताले export मा आफुले समावेश गर्न चाहे जस्तो फारम वा फिल्डहरु छनौट गर्न सक्नुहुन्छ । कृपया ध्यान दिनुहोस् कि प्रयोगकर्ताहरुले प्रणालीमा केस हेर्दा फारमहरु र फिल्डहरु हेर्ने क्षमता छ भने मात्र export मा फारमहरु र क्षेत्रहरु समावेश गर्न सक्छन् । ' + label: 'Excel (XLS file) export गर्नुहोस्। ' flag: explanation: प्रयोगकर्तालाई घटनामा फ्ल्याग थप्ने अनुमति दिन्छ। यो अनुमति पाएका प्रयोगकर्ताले घटनामा थपेका फ्ल्यागहरू हटाउन पनि सक्छन्। label: फ्ल्याग import: - explanation: "CSV, एक्सेल, वा JSON फाइल बाट Import गरेर प्रयोगकर्तालाई एक वा एक भन्दा बढी नयाँ घटनाहरू सिर्जना गर्न अनुमति दिन्छ। सही तरिकाले जानकारी import गर्न आयातित फाइलको ढाँचा \"अत्ती नै\" विशेष हुनुपर्छ । यो सुविधा प्रीमेरोमा तथ्याड़कलाई कसरी फरम्याट गरिन्छ भन्ने उच्च प्राविधिक सीप र गहन ज्ञान भएको प्रशासनिक प्रयोगकर्ताहरूलाई उपलब्ध हुनु पर्छ। घटना सूची पृष्ठ बाट मात्र कार्य गर्न मिल्छ । " + explanation: 'CSV, एक्सेल, वा JSON फाइल बाट Import गरेर प्रयोगकर्तालाई एक वा एक भन्दा बढी नयाँ घटनाहरू सिर्जना गर्न अनुमति दिन्छ। सही तरिकाले जानकारी import गर्न आयातित फाइलको ढाँचा "अत्ती नै" विशेष हुनुपर्छ । यो सुविधा प्रीमेरोमा तथ्याड़कलाई कसरी फरम्याट गरिन्छ भन्ने उच्च प्राविधिक सीप र गहन ज्ञान भएको प्रशासनिक प्रयोगकर्ताहरूलाई उपलब्ध हुनु पर्छ। घटना सूची पृष्ठ बाट मात्र कार्य गर्न मिल्छ । ' label: Import गर्नुहोस् manage: - explanation: "प्रयोगकर्तालाई घटनाहरूमा सबै उपलब्ध कार्यहरू गर्ने अनुमति दिन्छ । \"प्रबन्ध\" अनुमतिले मुख्यत \"सबै कुरा\" भन्ने अर्थ दिन्छ । " + explanation: 'प्रयोगकर्तालाई घटनाहरूमा सबै उपलब्ध कार्यहरू गर्ने अनुमति दिन्छ । "प्रबन्ध" अनुमतिले मुख्यत "सबै कुरा" भन्ने अर्थ दिन्छ । ' label: प्रबन्ध गर्नुहोस् (यो स्रोत प्रकारको लागि सबै अनुमतिहरू) read: explanation: घटना हेर्न सक्ने क्षमता label: हेर्नुहोस । sync_mobile: - explanation: "यो अनुमतिले प्राय: प्रयोगकर्तालाई मोबाइल एपलिकेसनको प्रयोग गर्ने अनुमति दिन्छ। सबै भन्दा पहिला, प्रयोगकर्तालाई घटना सूची र घटना देखाउनुहोस् पृष्ठहरुमा देखिने \"मोबाइल को लागी चिन्ह लगाउने \" र \"मोबाइल को लागी चिन्ह नलगाउने\" कार्यहरू हेर्ने अनुमति दिन्छ। मोबाइलमा घटना चिन्ह लगाउनाले प्रयोगकर्ताको मोबाइल उपकरण र वेब एपलिकेसन बीच घटनाको बारे जानकारी sync हुन पर्छ भन्ने संकेत गर्दछ भने मोबाइल बाट घटना चिन्ह हटाउनाले sync हुन बाट रोक्छ। यो अनुमति बिना प्रयोगकर्ताहरूले सामान्य रूपमा वेब एपलिकेसनसंग आफ्नो मोबाइल उपकरणहरू sync गर्न सक्दैनन् र यसको अर्थ घटनाहरूको व्यवस्थापन गर्न उनीहरूले मोबाइल एपको प्रयोग गर्न सक्दैनन्।" + explanation: 'यो अनुमतिले प्राय: प्रयोगकर्तालाई मोबाइल एपलिकेसनको प्रयोग गर्ने अनुमति दिन्छ। सबै भन्दा पहिला, प्रयोगकर्तालाई घटना सूची र घटना देखाउनुहोस् पृष्ठहरुमा देखिने "मोबाइल को लागी चिन्ह लगाउने " र "मोबाइल को लागी चिन्ह नलगाउने" कार्यहरू हेर्ने अनुमति दिन्छ। मोबाइलमा घटना चिन्ह लगाउनाले प्रयोगकर्ताको मोबाइल उपकरण र वेब एपलिकेसन बीच घटनाको बारे जानकारी sync हुन पर्छ भन्ने संकेत गर्दछ भने मोबाइल बाट घटना चिन्ह हटाउनाले sync हुन बाट रोक्छ। यो अनुमति बिना प्रयोगकर्ताहरूले सामान्य रूपमा वेब एपलिकेसनसंग आफ्नो मोबाइल उपकरणहरू sync गर्न सक्दैनन् र यसको अर्थ घटनाहरूको व्यवस्थापन गर्न उनीहरूले मोबाइल एपको प्रयोग गर्न सक्दैनन्।' label: मोबाइल उपकरणसँग sync गर्नुहोस् । write: - explanation: "\"सम्पादन\" बटन क्लिक गर्ने , घटना बारे जानकारी अपडेट गर्ने र \"सुरक्षित\" मा क्लिक गर्ने क्षमता भएको । साथै, प्रयोगकर्तालाई घटना निस्कृय वा सकृय गर्ने अनुमति पनि दिन्छ । " + explanation: '"सम्पादन" बटन क्लिक गर्ने , घटना बारे जानकारी अपडेट गर्ने र "सुरक्षित" मा क्लिक गर्ने क्षमता भएको । साथै, प्रयोगकर्तालाई घटना निस्कृय वा सकृय गर्ने अनुमति पनि दिन्छ । ' label: सम्पादन गर्नुहोस् । - explanation: "घटेको घटनाको प्रतिनिधित्व गर्दछ। यी सामान्यतया दुर्व्यवहार वा हिंसाका घटनाहरू हुन्, यद्यपि तिनीहरू कानून प्रवर्तन सँग मुठभेड जस्ता घटनाहरूसँग पनि मेल खान सक्छन्। घटनाहरू प्रायः केसहरूसँग जोडिएका हुन्छन्।" - label: "घटना " + explanation: घटेको घटनाको प्रतिनिधित्व गर्दछ। यी सामान्यतया दुर्व्यवहार वा हिंसाका घटनाहरू हुन्, यद्यपि तिनीहरू कानून प्रवर्तन सँग मुठभेड जस्ता घटनाहरूसँग पनि मेल खान सक्छन्। घटनाहरू प्रायः केसहरूसँग जोडिएका हुन्छन्। + label: 'घटना ' is_manager: explanation: सामान्यतया अन्य प्रयोगकर्ताहरूलाई सुपरिवेक्षण गर्ने कुनै पनि प्रयोगकर्ताको भूमिकाको लागी लागू हुन्छ। यसले प्रयोगकर्तालाई टोलिको व्यवस्थापन गर्नमा मद्दत पुर्‍याउन ड्यासबोर्ड र फिल्टर हेर्न अनुमति दिन्छ। - label: "प्रबन्धक हो ?" + label: प्रबन्धक हो ? managed_report: actions: violations: @@ -2726,17 +2632,17 @@ ne: matching_configuration: actions: manage: - explanation: "केसहरू र ट्रेसिङ्ग अनुरोध बीच मेल खोज्नको लागि कुन फिल्डहरूलाई तुलना गरिन्छ भनेर नियन्त्रण गर्ने क्षमता। यसले सम्पूर्ण प्रणालीमा कसरी मेल गराइन्छ भनेर नियन्त्रण गर्ने हुनाले यो अनुमति सामान्यतया प्रणाली प्रशासकलाई मात्र उपलब्ध हुनु पर्छ। " + explanation: 'केसहरू र ट्रेसिङ्ग अनुरोध बीच मेल खोज्नको लागि कुन फिल्डहरूलाई तुलना गरिन्छ भनेर नियन्त्रण गर्ने क्षमता। यसले सम्पूर्ण प्रणालीमा कसरी मेल गराइन्छ भनेर नियन्त्रण गर्ने हुनाले यो अनुमति सामान्यतया प्रणाली प्रशासकलाई मात्र उपलब्ध हुनु पर्छ। ' label: प्रबन्ध गर्नुहोस् (यो स्रोत प्रकारको लागि सबै अनुमतिहरू दिइएको ) । explanation: परिवार ट्रेसिङ र पुनर्मिलन को समयमा केसहरु सँग ट्रेसिङ अनुरोध तुलना गर्न को लागी कुन फिल्डहरु प्रयोग गरिन्छ भन्ने नियन्त्रण गर्दछ। label: कन्फिगरेसन मिलाउदै metadata: actions: manage: - explanation: "सिर्जना, सम्पादन, अनुवाद गर्न सक्ने र फारम, फारम क्षेत्रहरू र खोजीहरू मेटाउने क्षमता। कृपया ध्यान दिनुहोस् कि यो अनुमति भएको प्रयोगकर्ता सँग उनीहरूको पहुँच भएको फारमहरू मात्र व्यवस्थापन गर्न सक्षम हुनेछ। उदाहरणको लागि, यदि एउटा राष्ट्रिय प्रशासकलाई केसहरूमा अभिलेख मालिक मात्र हेर्ने क्षमता छ भने त्यो फारमको लागि मात्र कन्फिगरेसन अद्यावधिक गर्न सक्षम हुनेछन्।" + explanation: सिर्जना, सम्पादन, अनुवाद गर्न सक्ने र फारम, फारम क्षेत्रहरू र खोजीहरू मेटाउने क्षमता। कृपया ध्यान दिनुहोस् कि यो अनुमति भएको प्रयोगकर्ता सँग उनीहरूको पहुँच भएको फारमहरू मात्र व्यवस्थापन गर्न सक्षम हुनेछ। उदाहरणको लागि, यदि एउटा राष्ट्रिय प्रशासकलाई केसहरूमा अभिलेख मालिक मात्र हेर्ने क्षमता छ भने त्यो फारमको लागि मात्र कन्फिगरेसन अद्यावधिक गर्न सक्षम हुनेछन्। label: प्रबन्ध गर्नुहोस् (यो स्रोत प्रकारको लागि सबै अनुमतिहरू ) । - explanation: "प्रीमेरो फारम र फिल्डहरू, साथै त्यहाँ भित्र प्रयोग गरिएका लुकअपको विकल्पहरू कन्फिगर गर्ने क्षमता नियन्त्रण गर्दछ।" - label: "फारमहरू, खोजी" + explanation: प्रीमेरो फारम र फिल्डहरू, साथै त्यहाँ भित्र प्रयोग गरिएका लुकअपको विकल्पहरू कन्फिगर गर्ने क्षमता नियन्त्रण गर्दछ। + label: फारमहरू, खोजी module: actions: cp: @@ -2761,19 +2667,19 @@ ne: manage: explanation: प्रयोगकर्तालाई सम्भावित मिलानहरूमा सबै उपलब्ध कार्यहरू गर्न अनुमति दिन्छ। "व्यवस्थापन" अनुमति भन्नाले अनिवार्य रूपमा "सबै कुरा" हो। label: प्रबन्ध गर्नुहोस् - label: "सम्भावित मिलान " + label: 'सम्भावित मिलान ' primero_configuration: actions: manage: - explanation: "सुरक्षित गर्ने , लागू गर्ने र कन्फिगरेसनहरू पठाउने क्षमता। यो अनुमति सामान्यतया प्रणाली प्रशासकको लागी सुरक्षित छ।" + explanation: सुरक्षित गर्ने , लागू गर्ने र कन्फिगरेसनहरू पठाउने क्षमता। यो अनुमति सामान्यतया प्रणाली प्रशासकको लागी सुरक्षित छ। label: प्रबन्ध गर्नुहोस् (यो स्रोत प्रकारको लागि सबै अनुमतिहरू) label: कन्फिगरेसन referral: actions: refer: - explanation: "यसको मतलब प्रयोगकर्ताले बाह्य रेफरल प्रयोग गर्दा भूमिका \"प्रापक को प्रकार\" को विकल्पको रूपमा देखिनेछ। यदि प्रयोगकर्ताले रेफेरलको प्रकारको रूपमा यो भूमिका छनौट गरेमा प्रयोगकर्ताले स्थानान्तरण पेश गर्दा प्रीमेरोले उत्पन्न गर्ने export मा यो भूमिकाको पहुँच भएको फारममा हुने जानकारी मात्र हुन्छ । उदाहरणको लागी, यदि प्रयोगकर्ताले प्राप्तकर्ताको प्रकारको रूपमा \"चिकित्सा सेवा प्रदायक\" छनौट गरेमा र चिकित्सा सेवा प्रदायक भूमिकालाई आधारभूत पहिचान र संरक्षण चासोको फारामहरू मात्र पहुँच छ भने Primero ले बाह्य स्थानान्तरणको लागि export गर्ने फाईलमा यी दुई फारमहरूमा भएका फिल्डहरु मात्र समावेश हुनेछन् । " - label: "के यो भूमिका बाह्य रेफेरलहरूको लागी प्रयोग गर्न सकिन्छ?" - label: "रेफेरल " + explanation: 'यसको मतलब प्रयोगकर्ताले बाह्य रेफरल प्रयोग गर्दा भूमिका "प्रापक को प्रकार" को विकल्पको रूपमा देखिनेछ। यदि प्रयोगकर्ताले रेफेरलको प्रकारको रूपमा यो भूमिका छनौट गरेमा प्रयोगकर्ताले स्थानान्तरण पेश गर्दा प्रीमेरोले उत्पन्न गर्ने export मा यो भूमिकाको पहुँच भएको फारममा हुने जानकारी मात्र हुन्छ । उदाहरणको लागी, यदि प्रयोगकर्ताले प्राप्तकर्ताको प्रकारको रूपमा "चिकित्सा सेवा प्रदायक" छनौट गरेमा र चिकित्सा सेवा प्रदायक भूमिकालाई आधारभूत पहिचान र संरक्षण चासोको फारामहरू मात्र पहुँच छ भने Primero ले बाह्य स्थानान्तरणको लागि export गर्ने फाईलमा यी दुई फारमहरूमा भएका फिल्डहरु मात्र समावेश हुनेछन् । ' + label: के यो भूमिका बाह्य रेफेरलहरूको लागी प्रयोग गर्न सकिन्छ? + label: 'रेफेरल ' registry_record: actions: change_log: @@ -2789,7 +2695,7 @@ ne: explanation: 'प्रयोगकर्ताले रजिस्ट्री सूची वा रजिस्ट्री पृष्ठहरूबाट CSV फाइल export गर्न सक्दछन्, जसमा हालको प्रयोगकर्ताको पहुँचमा रहेको एउटा, धेरै वा सबै रजिस्ट्री रेकर्डका सबै क्षेत्रहरू समावेश छन्। नोट: CSV export ले गैर-ल्याटिन वर्णहरू (जस्तै अरबी, बांग्ला) रेन्डर गर्दैन।' label: Export CSV export_json: - explanation: "प्रयोगकर्ताले रजिस्ट्री सूची वा रजिस्ट्री पृष्ठहरूबाट JSON फाइल export गर्न सक्दछन्, जसमा हालको प्रयोगकर्ताले पहुँच गरेको सबै क्षेत्रहरू समावेश रहेको हुन्छ। JSON ढाँचा मेसिन रिडेबल छ र धेरै प्रयोगकर्ताहरूको लागि व्यावहारिक छैन।" + explanation: प्रयोगकर्ताले रजिस्ट्री सूची वा रजिस्ट्री पृष्ठहरूबाट JSON फाइल export गर्न सक्दछन्, जसमा हालको प्रयोगकर्ताले पहुँच गरेको सबै क्षेत्रहरू समावेश रहेको हुन्छ। JSON ढाँचा मेसिन रिडेबल छ र धेरै प्रयोगकर्ताहरूको लागि व्यावहारिक छैन। label: JSON Export गर्नुहोस् export_xls: explanation: 'प्रयोगकर्ताले रजिस्ट्री सूची वा रजिस्ट्री पृष्ठहरूबाट XLS फाईल export गर्न सक्छ, जसमा हालको प्रयोगकर्ताको पहुँच भएको सबै क्षेत्रहरू समावेश छन्। नोट: XLS ढाँचाले गैर-ल्याटिन वर्णहरू (जस्तै अरबी, बांग्ला) पढ्न योग्य ढाँचामा रेन्डर गर्दछ, जबकि CSV ले गर्दैन।' @@ -2804,29 +2710,29 @@ ne: explanation: रजिस्ट्री रेकर्ड हेर्न सक्ने क्षमता label: हेर्नुहोस् write: - explanation: "\"सम्पादन गर्नुहोस्\" बटन क्लिक गर्ने क्षमता, रजिस्ट्री रेकर्डको सूचना अध्यावधिक गर्नुहोस्, र \"बचत गर्नुहोस्\"।" + explanation: '"सम्पादन गर्नुहोस्" बटन क्लिक गर्ने क्षमता, रजिस्ट्री रेकर्डको सूचना अध्यावधिक गर्नुहोस्, र "बचत गर्नुहोस्"।' label: सम्पादन sync_mobile: explanation: प्रयोगकर्तालाई अफलाईन प्रयोगको लागि रजिस्ट्री रेकर्डहरू cache गर्न अनुमति दिन्छ label: अफलाईनको लागि चिन्ह लगाउनुहोस् - explanation: "यसले व्यक्ति वा संस्थालाई प्रतिनिधित्व गर्न सक्छ जसलाई अन्य अभिलेखहरू जस्तै केस वा घटनाहरूसँग जोड्न आवश्यक छ, धेरै संख्यामा छन्, र बारम्बार नयाँ जानकारीको साथ अध्यावधिक हुन्छन्। तिनीहरू लुकअपहरू जस्तै छन्, तर प्रत्येक प्रविष्टिको लागि जानकारीहरु थप जटिल हुन्छन।" + explanation: यसले व्यक्ति वा संस्थालाई प्रतिनिधित्व गर्न सक्छ जसलाई अन्य अभिलेखहरू जस्तै केस वा घटनाहरूसँग जोड्न आवश्यक छ, धेरै संख्यामा छन्, र बारम्बार नयाँ जानकारीको साथ अध्यावधिक हुन्छन्। तिनीहरू लुकअपहरू जस्तै छन्, तर प्रत्येक प्रविष्टिको लागि जानकारीहरु थप जटिल हुन्छन। label: रजिष्ट्री रेकर्ड report: actions: create: - explanation: "नयाँ रिपोर्ट बनाउन सक्ने क्षमता। प्रयोगकर्ताले रिपोर्ट बनाउँदा सो रिपोर्ट सबै प्रयोगकर्ताले देख्नन् सक्नेछन र रिपोर्टमा \"पढ्नुहोस्\" वा \"समूहमा पढ्नुहोस्\" पहुँच प्राप्त गर्नेछन् । " + explanation: 'नयाँ रिपोर्ट बनाउन सक्ने क्षमता। प्रयोगकर्ताले रिपोर्ट बनाउँदा सो रिपोर्ट सबै प्रयोगकर्ताले देख्नन् सक्नेछन र रिपोर्टमा "पढ्नुहोस्" वा "समूहमा पढ्नुहोस्" पहुँच प्राप्त गर्नेछन् । ' label: सिर्जना गर्नुहोस् । group_read: - explanation: "सबै रिपोर्ट हेर्न सक्ने क्षमता। प्रत्येक रिपोर्टमा भएको संख्याले वर्तमान प्रयोगकर्ताले आफ्नो प्रयोगकर्ता समूहहरूका लागि पहुँच योग्य अभिलेखहरू मात्र प्रतिबिम्बित गर्नेछ । यो अनुमति प्राय: स्थानीय, क्षेत्रीय, वा निकाय प्रशासकहरूको लागी आफ्नै टोलीहरू वा संस्थाहरूले गर्ने काम बारे बुझनको लागी प्रयोग गरिन्छ। यो अनुमतिले प्रयोगकर्तालाई रिपोर्ट बाट तथ्याङ्क export गर्ने क्षमता पनि दिन्छ। " - label: " हेर्नुहोस (समूह-आधारित तथ्याड़क)" + explanation: 'सबै रिपोर्ट हेर्न सक्ने क्षमता। प्रत्येक रिपोर्टमा भएको संख्याले वर्तमान प्रयोगकर्ताले आफ्नो प्रयोगकर्ता समूहहरूका लागि पहुँच योग्य अभिलेखहरू मात्र प्रतिबिम्बित गर्नेछ । यो अनुमति प्राय: स्थानीय, क्षेत्रीय, वा निकाय प्रशासकहरूको लागी आफ्नै टोलीहरू वा संस्थाहरूले गर्ने काम बारे बुझनको लागी प्रयोग गरिन्छ। यो अनुमतिले प्रयोगकर्तालाई रिपोर्ट बाट तथ्याङ्क export गर्ने क्षमता पनि दिन्छ। ' + label: ' हेर्नुहोस (समूह-आधारित तथ्याड़क)' manage: - explanation: "प्रयोगकर्तालाई निकायहरूमा सबै उपलब्ध कार्यहरू गर्ने अनुमति दिन्छ । \"प्रबन्ध\" अनुमतिले मुख्यत \"सबै कुरा\" भन्ने अर्थ दिन्छ । " + explanation: 'प्रयोगकर्तालाई निकायहरूमा सबै उपलब्ध कार्यहरू गर्ने अनुमति दिन्छ । "प्रबन्ध" अनुमतिले मुख्यत "सबै कुरा" भन्ने अर्थ दिन्छ । ' label: प्रबन्ध गर्नुहोस् (यो स्रोत प्रकारको लागि सबै अनुमतिहरू) read: explanation: सबै रिपोर्ट हेर्ने क्षमता। प्रत्येक रिपोर्टमा भएको संख्याले वर्तमान प्रयोगकर्ताको पहुँच भएको अभिलेखहरू मात्र नभएर प्रणालीमा भएको सबै अभिलेखहरूको संख्या प्रतिबिम्बित गर्दछ । यो अनुमतिले प्रयोगकर्तालाई रिपोर्ट बाट तथ्याड़क export गर्ने क्षमता पनि दिन्छ। label: हेर्नुहोस । write: - explanation: "अन्य प्रयोगकर्ताहरूद्वारा बनाईएको सहित, सबै रिपोर्टहरू सम्पादन गर्ने क्षमता।" + explanation: अन्य प्रयोगकर्ताहरूद्वारा बनाईएको सहित, सबै रिपोर्टहरू सम्पादन गर्ने क्षमता। label: सम्पादन गर्नुहोस् । agency_read: explanation: सबै रिपोर्टहरू हेर्न क्षमता। प्रत्येक प्रतिवेदनमा भएका संख्याहरूले हालको प्रयोगकर्ताको एजेन्सीमा प्रयोगकर्ताहरूका लागि पहुँचयोग्य रेकर्डहरू मात्र प्रतिबिम्बित गर्नेछ। यो अनुमति प्रायः एजेन्सी प्रशासकहरूको लागि प्रयोग गरिन्छ। @@ -2835,7 +2741,7 @@ ne: label: प्रतिवेदन reporting_location_level: explanation: 'यस भूमिकामा ड्यासबोर्ड, फिल्टर, रेफरल मोडल, र स्थानान्तरण मोडलमा कुन स्तरको स्थानहरू देखा पर्दछ भन्ने कुरा यसले नियन्त्रण गर्दछ। यदि तपाइले यो क्षेत्र खाली छोड्नु भयो भने यो भूमिकाले प्रणालीको पूर्वनिर्धारित रिपोर्टिंग स्थानको स्तर देखिनेछ। ' - label: "यो भूमिकाको रिपोर्टिङ्को लागि कुन प्रकारको स्थान उपयोग गर्नुपर्छ ?" + label: यो भूमिकाको रिपोर्टिङ्को लागि कुन प्रकारको स्थान उपयोग गर्नुपर्छ ? role: actions: assign: @@ -2849,25 +2755,25 @@ ne: label: सिर्जना गर्नुहोस् । delete: explanation: भूमिका मेटाउने क्षमता - label: "मेटाउनुहोस्। " + label: 'मेटाउनुहोस्। ' manage: explanation: 'प्रयोगकर्तालाई भूमिकाहरूमा सबै उपलब्ध कार्यहरू गर्ने अनुमति दिन्छ । "प्रबन्ध" अनुमतिले मुख्यत "सबै कुरा" भन्ने अर्थ दिन्छ । महत्त्वपूर्ण : यसले भूमिकाहरू सिर्जना गर्ने र मेटाउने क्षमता पनि दिन्छ ।' label: प्रबन्ध गर्नुहोस् (यो स्रोत प्रकारको लागि सबै अनुमतिहरू) permitted_roles: - explanation: "यदि भूमिकालाई भूमिका माथि भनिएका कुनै पनि कार्यहरू गर्ने क्षमता छ भने उनीहरूलाई यो सूचीमा निर्दिष्ट गरिएका भूमिकामा ती कार्यहरू गर्न सक्षम हुनेछन्। त्यसैले, उदाहरणको लागी, यदि भूमिकालाई \"पढ्नुहोस्\" र \"असाइन\" अनुमति छ तर \"व्यवस्थित भूमिका\" को रूपमा \"बाल संरक्षण केस कामदार\" र \"बाल संरक्षण प्रबन्धक\" मात्र सूचीबद्ध छ भने यी दुई भूमिका मात्र देखा पर्दछ र ती भूमिका मात्र तोक्न सक्षम हुनेछ। यदि उक्त भूमिकालाई कुनै \"व्यवस्थित भूमिका\" निर्दिष्ट छैन भने उसले सबै भूमिकाहरू देख्न सक्षम हुनेछ र प्रणालीमा कुनै पनि भूमिकाको रूपमा नयाँ प्रयोगकर्ता खाताहरू बनाउन सक्षम हुनेछ। " + explanation: 'यदि भूमिकालाई भूमिका माथि भनिएका कुनै पनि कार्यहरू गर्ने क्षमता छ भने उनीहरूलाई यो सूचीमा निर्दिष्ट गरिएका भूमिकामा ती कार्यहरू गर्न सक्षम हुनेछन्। त्यसैले, उदाहरणको लागी, यदि भूमिकालाई "पढ्नुहोस्" र "असाइन" अनुमति छ तर "व्यवस्थित भूमिका" को रूपमा "बाल संरक्षण केस कामदार" र "बाल संरक्षण प्रबन्धक" मात्र सूचीबद्ध छ भने यी दुई भूमिका मात्र देखा पर्दछ र ती भूमिका मात्र तोक्न सक्षम हुनेछ। यदि उक्त भूमिकालाई कुनै "व्यवस्थित भूमिका" निर्दिष्ट छैन भने उसले सबै भूमिकाहरू देख्न सक्षम हुनेछ र प्रणालीमा कुनै पनि भूमिकाको रूपमा नयाँ प्रयोगकर्ता खाताहरू बनाउन सक्षम हुनेछ। ' label: यो भूमिकाद्वारा व्यवस्थित अन्य भूमिकाहरू read: - explanation: "भूमिकाहरू हेर्ने क्षमता भएको " + explanation: 'भूमिकाहरू हेर्ने क्षमता भएको ' label: हेर्नुहोस । write: - explanation: "भूमिका देखाउने पृष्ठमा \"सम्पादन\" बटन क्लिक गर्ने, भूमिकाको अनुमतिहरूलाई अद्यावधिक गर्ने र त्यसपछि भूमिकालाई सुरक्षित गर्ने क्षमता ।" + explanation: भूमिका देखाउने पृष्ठमा "सम्पादन" बटन क्लिक गर्ने, भूमिकाको अनुमतिहरूलाई अद्यावधिक गर्ने र त्यसपछि भूमिकालाई सुरक्षित गर्ने क्षमता । label: सम्पादन गर्नुहोस् । explanation: प्रयोगकर्ताले प्रीमेरोमा कुन-कुन कार्यहरू गर्न सक्छन् भनेर निर्धारण गर्दछ। label: भूमिकाहरू system: actions: manage: - explanation: "प्रणालीको सम्पर्क सूचना, पूर्वनिर्धारित नोटिफिकेसन, स्वागत ईमेल सेटिङ्ग र synchronized सर्भरहरू हेर्न र अपडेट गर्ने क्षमता। यो अनुमति सामान्यतया प्रणाली प्रशासकको लागी सुरक्षित छ ।" + explanation: प्रणालीको सम्पर्क सूचना, पूर्वनिर्धारित नोटिफिकेसन, स्वागत ईमेल सेटिङ्ग र synchronized सर्भरहरू हेर्न र अपडेट गर्ने क्षमता। यो अनुमति सामान्यतया प्रणाली प्रशासकको लागी सुरक्षित छ । label: प्रबन्ध गर्नुहोस् (यो स्रोत प्रकारको लागि सबै अनुमतिहरू दिइएको ) । explanation: विविध प्रणाली-व्यापी कन्फिगरेसन सेटिङहरू। label: प्रणाली @@ -2877,29 +2783,29 @@ ne: explanation: प्रयोगकर्ताले अभिलेख सिर्जना भएदेखि त्यसमा गरिएका सबै परिवर्तनहरूको इतिहास देख्न सक्छ । यसअन्तर्गत सबै फिल्डहरूको लागि अभिलेख गरिएका मानहरू पनि सामेल छन् । label: परिवर्तन लग create: - explanation: "ट्रेसिङ्ग अनुरोध सिर्जना गर्ने क्षमता भएको " + explanation: 'ट्रेसिङ्ग अनुरोध सिर्जना गर्ने क्षमता भएको ' label: सिर्जना गर्नुहोस् । enable_disable_record: - explanation: "ट्रेसिङ्ग अनुरोध सक्रिय वा निष्क्रिय गर्ने क्षमता। ट्रेसिङ्ग अनुरोध सूचीमा \"निस्कृय\" भएको पूर्वनिर्धारित रूपमा देखा पर्दैन। निस्कृय भएको ट्रेसिङ्ग अनुरोध हेर्न प्रयोगकर्ताहरूले फिल्टर गर्नुपर्छ। " + explanation: 'ट्रेसिङ्ग अनुरोध सक्रिय वा निष्क्रिय गर्ने क्षमता। ट्रेसिङ्ग अनुरोध सूचीमा "निस्कृय" भएको पूर्वनिर्धारित रूपमा देखा पर्दैन। निस्कृय भएको ट्रेसिङ्ग अनुरोध हेर्न प्रयोगकर्ताहरूले फिल्टर गर्नुपर्छ। ' label: सक्रिय पार्नुहोस् ।/ निष्क्रिय पार्नुहोस् । export_case_pdf: - explanation: "प्रयोगकर्ताले ट्रेसिङ्ग अनुरोध सूची वा ट्रेसिङ्ग अनुरोध देखिने पृष्ठहरू बाट PDF फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको पहुँचमा रहेको सबै फिल्डहरु रहेको हुन्छ र सोमा एक, धेरै वा सबै अभिलेखहरु हुन्छ । PDF export फाईलमा, सूचनालाई पहिला केस सूची अनुसार र त्यसपछि सूचना देखा पर्ने फारम अनुसार थप व्यवस्थित गरीएको छ ।" - label: " Pdf export गर्नुहोस्।" + explanation: प्रयोगकर्ताले ट्रेसिङ्ग अनुरोध सूची वा ट्रेसिङ्ग अनुरोध देखिने पृष्ठहरू बाट PDF फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको पहुँचमा रहेको सबै फिल्डहरु रहेको हुन्छ र सोमा एक, धेरै वा सबै अभिलेखहरु हुन्छ । PDF export फाईलमा, सूचनालाई पहिला केस सूची अनुसार र त्यसपछि सूचना देखा पर्ने फारम अनुसार थप व्यवस्थित गरीएको छ । + label: ' Pdf export गर्नुहोस्।' export_csv: - explanation: "प्रयोगकर्ताले ट्रेसिङ्ग अनुरोध सूची वा ट्रेसिङ्ग अनुरोध देखाउने पृष्ठहरूबाट CSV फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको पहुँचमा रहेको सबै फिल्डहरु रहेको हुन्छ र सोमा एक, धेरै वा सबै ट्रेसिङ्ग अनुरोधहरु हुन्छ ।" - label: "CSV export गर्नुहोस्। " + explanation: प्रयोगकर्ताले ट्रेसिङ्ग अनुरोध सूची वा ट्रेसिङ्ग अनुरोध देखाउने पृष्ठहरूबाट CSV फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको पहुँचमा रहेको सबै फिल्डहरु रहेको हुन्छ र सोमा एक, धेरै वा सबै ट्रेसिङ्ग अनुरोधहरु हुन्छ । + label: 'CSV export गर्नुहोस्। ' export_custom: - explanation: "प्रयोगकर्ताले ट्रेसिङ्ग अनुरोध सूची वा ट्रेसिङ्ग अनुरोध देखाउने पृष्ठहरूबाट XLS फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण ट्रेसिङ्ग अनुरोधहरुको कस्टम फिल्ड वा फारम रहेको हुन्छ । यो export मा, प्रत्येक फारमलाई XLS फाइल भित्रको आफ्नै ट्याबमा प्रतिनिधित्व गरीन्छ। कस्टम export मोडलको प्रयोग गरेर प्रयोगकर्ताले export मा आफुले समावेश गर्न चाहे जस्तो फारम वा फिल्डहरु छनौट गर्न सक्नुहुन्छ । कृपया ध्यान दिनुहोस् कि प्रयोगकर्ताहरुले प्रणालीमा ट्रेसिङ्ग अनुरोधहरू हेर्दा फारमहरु र फिल्डहरु हेर्ने क्षमता छ भने मात्र export मा फारमहरु र फिल्डहरु समावेश गर्न सक्छन् ।" - label: "कस्टम export गर्नुहोस्। " + explanation: प्रयोगकर्ताले ट्रेसिङ्ग अनुरोध सूची वा ट्रेसिङ्ग अनुरोध देखाउने पृष्ठहरूबाट XLS फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण ट्रेसिङ्ग अनुरोधहरुको कस्टम फिल्ड वा फारम रहेको हुन्छ । यो export मा, प्रत्येक फारमलाई XLS फाइल भित्रको आफ्नै ट्याबमा प्रतिनिधित्व गरीन्छ। कस्टम export मोडलको प्रयोग गरेर प्रयोगकर्ताले export मा आफुले समावेश गर्न चाहे जस्तो फारम वा फिल्डहरु छनौट गर्न सक्नुहुन्छ । कृपया ध्यान दिनुहोस् कि प्रयोगकर्ताहरुले प्रणालीमा ट्रेसिङ्ग अनुरोधहरू हेर्दा फारमहरु र फिल्डहरु हेर्ने क्षमता छ भने मात्र export मा फारमहरु र फिल्डहरु समावेश गर्न सक्छन् । + label: 'कस्टम export गर्नुहोस्। ' export_json: - explanation: "प्रयोगकर्ताले ट्रेसिङ्ग अनुरोध सूची वा ट्रेसिङ्ग अनुरोध देखाउने पृष्ठहरू बाट JSON फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण ट्रेसिङ्ग अनुरोधहरुको फिल्ड रहेको हुन्छ । यो export मुख्य रूपमा ती सबैको लागि प्रयोग गरिन्छ जसले हालको प्रीमेरो प्रणालीबाट ट्रेसिङ्ग अनुरोध export गरेर फरक प्रीमेरो प्रणालीमा वा अन्य सूचना व्यवस्थापन प्रणालीमा import गर्न चाहन्छन् । JSON ढाँचा मेशिन द्वारा पठनीय छ र धेरै प्रयोगकर्ताहरूको लागी व्यावहारिक छैन।" + explanation: प्रयोगकर्ताले ट्रेसिङ्ग अनुरोध सूची वा ट्रेसिङ्ग अनुरोध देखाउने पृष्ठहरू बाट JSON फाइल export गर्न सक्छ जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण ट्रेसिङ्ग अनुरोधहरुको फिल्ड रहेको हुन्छ । यो export मुख्य रूपमा ती सबैको लागि प्रयोग गरिन्छ जसले हालको प्रीमेरो प्रणालीबाट ट्रेसिङ्ग अनुरोध export गरेर फरक प्रीमेरो प्रणालीमा वा अन्य सूचना व्यवस्थापन प्रणालीमा import गर्न चाहन्छन् । JSON ढाँचा मेशिन द्वारा पठनीय छ र धेरै प्रयोगकर्ताहरूको लागी व्यावहारिक छैन। label: JSON export गर्नुहोस्। export_list_view_csv: explanation: केस सूचीमा प्रयोगकर्ताको लागी देखा पर्ने फिल्डहरु जस्ता ट्रेसिङ्ग अनुरोध सूची पृष्ठ बाट प्रयोगकर्ताले एउटा CSV फाइल export गर्न सक्दछन् । ट्रेसिङ्ग अनुरोध सुची पृष्‍ठ बाट मात्रै सिर्जना गरिएको । label: लिस्ट भ्यू CSV मा export गर्नुहोस् । export_pdf: - explanation: "ट्रेसिङ्ग अनुरोध सूची वा ट्रेसिङ्ग अनुरोध देखाउने पेजबाट (जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण रेकर्डहरु भएका फिल्डहरु हुनेछन) प्रयोगकर्ताले PDF फाइल export उत्पन्न गर्न सक्दछन् । PDF export फाइलमा, सूचनालाई केसको आधारमा सूचीबद्ध गरिएको छ र त्यसपछि सूचना देखा पर्ने फारम अनुसार थप व्यवस्थित गरिएको छ ।" - label: "Pdf export गर्नुहोस्। " + explanation: ट्रेसिङ्ग अनुरोध सूची वा ट्रेसिङ्ग अनुरोध देखाउने पेजबाट (जसमा प्रयोगकर्ताको हाल पहुँचमा रहेको एउटा, धेरै वा सम्पूर्ण रेकर्डहरु भएका फिल्डहरु हुनेछन) प्रयोगकर्ताले PDF फाइल export उत्पन्न गर्न सक्दछन् । PDF export फाइलमा, सूचनालाई केसको आधारमा सूचीबद्ध गरिएको छ र त्यसपछि सूचना देखा पर्ने फारम अनुसार थप व्यवस्थित गरिएको छ । + label: 'Pdf export गर्नुहोस्। ' export_xls: explanation: 'प्रयोगकर्ताले ट्रेसिङ अनुरोध सूची वा ट्रेसिङ अनुरोध पृष्ठहरूबाट XLS फाइल export गर्न सक्छ, जसमा हालको प्रयोगकर्ताले पहुँचमा रहेको एउटा, धेरै वा सबै ट्रेसिङ अनुरोधका सबै फिल्डहरू समावेश हुन्छन। यस export मा, प्रत्येक फारम XLS फाइल भित्र आफ्नै ट्याबमा प्रतिनिधित्व गरिन्छ। नोट: XLS ढाँचाले गैर-ल्याटिन वर्णहरू (जस्तै अरबी, बांग्ला) पढ्न योग्य ढाँचामा रेन्डर गर्दछ, जबकि CSV ले गर्दैन।' label: एक्सेल (XLS फाइल) export @@ -2907,29 +2813,29 @@ ne: explanation: प्रयोगकर्तालाई ट्रेसिङ्ग अनुरोधमा फ्ल्याग थप्ने अनुमति दिन्छ। यो अनुमति पाएका प्रयोगकर्ताले ट्रेसिङ्ग अनुरोधमा थपेका फ्ल्यागहरू हटाउन पनि सक्छन्। label: फ्ल्याग import: - explanation: "CSV, Excel, वा JSON फाइल बाट import गरेर प्रयोगकर्तालाई एक वा एक भन्दा बढी नयाँ केसहरू सिर्जना गर्न अनुमति दिन्छ। सही तरिकाले जानकारी import गर्न imported फाइलको ढाँचा \"अत्ती नै\" विशेष हुनुपर्छ । यो कार्य प्रीमेरोमा तथ्याड़कलाई कसरी फर्मयाट गरिन्छ भन्ने उच्च प्राविधिक सीप र गहन ज्ञान भएको प्रशासनिक प्रयोगकर्ताहरूलाई उपलब्ध हुनु पर्छ। केस लिस्ट पेजबाट मात्र गर्न मिल्ने ।" + explanation: CSV, Excel, वा JSON फाइल बाट import गरेर प्रयोगकर्तालाई एक वा एक भन्दा बढी नयाँ केसहरू सिर्जना गर्न अनुमति दिन्छ। सही तरिकाले जानकारी import गर्न imported फाइलको ढाँचा "अत्ती नै" विशेष हुनुपर्छ । यो कार्य प्रीमेरोमा तथ्याड़कलाई कसरी फर्मयाट गरिन्छ भन्ने उच्च प्राविधिक सीप र गहन ज्ञान भएको प्रशासनिक प्रयोगकर्ताहरूलाई उपलब्ध हुनु पर्छ। केस लिस्ट पेजबाट मात्र गर्न मिल्ने । label: Import गर्नुहोस् manage: - explanation: "प्रयोगकर्तालाई ट्रेसिङ्ग अनुरोधहरूमा सबै उपलब्ध कार्यहरू गर्ने अनुमति दिन्छ । \"प्रबन्ध\" अनुमतिले मुख्यत \"सबै कुरा\" भन्ने अर्थ दिन्छ । " + explanation: 'प्रयोगकर्तालाई ट्रेसिङ्ग अनुरोधहरूमा सबै उपलब्ध कार्यहरू गर्ने अनुमति दिन्छ । "प्रबन्ध" अनुमतिले मुख्यत "सबै कुरा" भन्ने अर्थ दिन्छ । ' label: प्रबन्ध गर्नुहोस् (यो स्रोत प्रकारको लागि सबै अनुमतिहरू) read: explanation: ट्रेसिङ्ग अनुरोध हेर्ने क्षमता। ट्रेसिङ्ग अनुरोध हेर्ने क्षमता भएका भूमिकामा हुने संग सम्भावित अभिलेखको मिलानको हेर्ने क्षमता पनि हुनु पर्छ। label: हेर्नुहोस । write: - explanation: "\"सम्पादन\" बटन क्लिक गर्ने , 'ट्रेसिङ्ग अनुरोधहरू' बारे जानकारी अद्यावधिक गर्ने र \"सुरक्षित\" मा क्लिक गर्ने क्षमता भएको । साथै, प्रयोगकर्तालाई ट्रेसिङ्ग अनुरोध निस्कृय वा सकृय गर्ने अनुमति पनि दिन्छ ।" + explanation: '"सम्पादन" बटन क्लिक गर्ने , ''ट्रेसिङ्ग अनुरोधहरू'' बारे जानकारी अद्यावधिक गर्ने र "सुरक्षित" मा क्लिक गर्ने क्षमता भएको । साथै, प्रयोगकर्तालाई ट्रेसिङ्ग अनुरोध निस्कृय वा सकृय गर्ने अनुमति पनि दिन्छ ।' label: सम्पादन गर्नुहोस् । - explanation: "बेसाहारा तथा छुट्टिएका केसहरुलाई खोज्ने र पुन: एकीकरण गर्न प्रयास गर्ने व्यक्तिलाई प्रतिनिधित्व गर्दछ।" + explanation: 'बेसाहारा तथा छुट्टिएका केसहरुलाई खोज्ने र पुन: एकीकरण गर्न प्रयास गर्ने व्यक्तिलाई प्रतिनिधित्व गर्दछ।' label: पत्ता लगाउन अनुरोध transfer: actions: transfer: - explanation: " यसको मतलब प्रयोगकर्ताले बाह्य रेफरल प्रयोग गर्दा भूमिका \"प्रापक को प्रकार\" विकल्पको रूपमा देखिनेछ । यदि प्रयोगकर्ताले स्थानान्तरणको प्रकारको रूपमा यो भूमिका छनौट गरेमा प्रयोगकर्ताले स्थानान्तरण पेश गर्दा प्रीमेरोले निकाल्ने export मा यो भूमिकाको पहुँच भएको फारममा हुने जानकारी मात्र हुन्छ । उदाहरणको लागी, यदि प्रयोगकर्ताले प्राप्तकर्ताको प्रकारको रूपमा \"चिकित्सा सेवा प्रदायक\" छनौट गरेमा र चिकित्सा सेवा प्रदायक भूमिकालाई आधारभूत पहिचान र संरक्षण चासोका फारामहरू मात्र पहुँच छ भने प्रीमेरोले बाह्य स्थानान्तरणको लागि export गर्ने फाईलमा यी दुई फारमहरूमा भएका फिल्डहरु मात्र समावेश हुनेछन् । " - label: "के यो भूमिका बाह्य स्थानान्तरणको लागी प्रयोग गर्न सकिन्छ?" + explanation: ' यसको मतलब प्रयोगकर्ताले बाह्य रेफरल प्रयोग गर्दा भूमिका "प्रापक को प्रकार" विकल्पको रूपमा देखिनेछ । यदि प्रयोगकर्ताले स्थानान्तरणको प्रकारको रूपमा यो भूमिका छनौट गरेमा प्रयोगकर्ताले स्थानान्तरण पेश गर्दा प्रीमेरोले निकाल्ने export मा यो भूमिकाको पहुँच भएको फारममा हुने जानकारी मात्र हुन्छ । उदाहरणको लागी, यदि प्रयोगकर्ताले प्राप्तकर्ताको प्रकारको रूपमा "चिकित्सा सेवा प्रदायक" छनौट गरेमा र चिकित्सा सेवा प्रदायक भूमिकालाई आधारभूत पहिचान र संरक्षण चासोका फारामहरू मात्र पहुँच छ भने प्रीमेरोले बाह्य स्थानान्तरणको लागि export गर्ने फाईलमा यी दुई फारमहरूमा भएका फिल्डहरु मात्र समावेश हुनेछन् । ' + label: के यो भूमिका बाह्य स्थानान्तरणको लागी प्रयोग गर्न सकिन्छ? label: स्थानान्तरण गर्नुहोस् । user: actions: agency_read: - explanation: "वर्तमान प्रयोगकर्ताको निकायमा भएको प्रयोगकर्ता खाताहरू मात्र हेर्ने क्षमता। यसले वर्तमान प्रयोगकर्ताले कुन प्रयोगकर्ता खाताहरूमा अन्य कार्यहरू गर्न सक्छ भन्ने कुराले पनि प्रभावित गर्दछ । उदाहरणको लागी, यदि वर्तमान प्रयोगकर्तालाई प्रयोगकर्ताहरूमा \"लेख्ने\" अनुमति छ र साथै \"निकाय द्वारा पढिएको\" अनुमति छ भने उनीहरू आफ्नो निकायमा भएका प्रयोगकर्ता खाताहरू मात्र सम्पादन गर्न सक्षम हुनेछन्। त्यस्तै गरी, यदि वर्तमान प्रयोगकर्तालाई प्रयोगकर्ताहरूमा \"व्यवस्थापन\" को अनुमति छ तर \"निकाय द्वारा पढिएको\" अनुमति छ भने उनीहरु आफ्नो निकायमा मात्र प्रयोगकर्ताहरू बनाउन सक्षम हुनेछन् ।" + explanation: वर्तमान प्रयोगकर्ताको निकायमा भएको प्रयोगकर्ता खाताहरू मात्र हेर्ने क्षमता। यसले वर्तमान प्रयोगकर्ताले कुन प्रयोगकर्ता खाताहरूमा अन्य कार्यहरू गर्न सक्छ भन्ने कुराले पनि प्रभावित गर्दछ । उदाहरणको लागी, यदि वर्तमान प्रयोगकर्तालाई प्रयोगकर्ताहरूमा "लेख्ने" अनुमति छ र साथै "निकाय द्वारा पढिएको" अनुमति छ भने उनीहरू आफ्नो निकायमा भएका प्रयोगकर्ता खाताहरू मात्र सम्पादन गर्न सक्षम हुनेछन्। त्यस्तै गरी, यदि वर्तमान प्रयोगकर्तालाई प्रयोगकर्ताहरूमा "व्यवस्थापन" को अनुमति छ तर "निकाय द्वारा पढिएको" अनुमति छ भने उनीहरु आफ्नो निकायमा मात्र प्रयोगकर्ताहरू बनाउन सक्षम हुनेछन् । label: हेर्नुहोस् (निकाय भित्र) create: explanation: प्रयोगकर्ता खाता सिर्जना गर्ने क्षमता भएको @@ -2938,32 +2844,32 @@ ne: explanation: 'प्रयोगकर्तालाई प्रयोगकर्ताहरूमा सबै उपलब्ध कार्यहरू गर्ने अनुमति दिन्छ । "प्रबन्ध" अनुमतिले मुख्यत "सबै कुरा" भन्ने अर्थ दिन्छ । महत्त्वपूर्ण : यसले नयाँ प्रयोगकर्ता खाता सिर्जना गर्ने क्षमता पनि दिन्छ ।' label: प्रबन्ध गर्नुहोस् (यो स्रोत प्रकारको लागि सबै अनुमतिहरू) read: - explanation: "प्रयोगकर्ता खाता हेर्ने क्षमता भएको। प्रत्येक प्रयोगकर्ताले आफ्नो प्रयोगकर्ता खातामा भएको पासवर्ड र ईमेल जस्ता जानकारी हेर्ने र सम्पादन हेर्ने पूर्वनिर्धारित क्षमता छ। (उदाहरणः पासवर्ड, इमेल) " + explanation: 'प्रयोगकर्ता खाता हेर्ने क्षमता भएको। प्रत्येक प्रयोगकर्ताले आफ्नो प्रयोगकर्ता खातामा भएको पासवर्ड र ईमेल जस्ता जानकारी हेर्ने र सम्पादन हेर्ने पूर्वनिर्धारित क्षमता छ। (उदाहरणः पासवर्ड, इमेल) ' label: हेर्नुहोस । write: - explanation: "सो युजेर पेजमा \"सम्पादन\" बटन क्लिक गर्ने, प्रयोगकर्ताको बारेमा जानकारी अपडेट गर्ने र 'सुरक्षित गर्नुहोस्' गर्न सक्ने क्षमता । कृपया ध्यान दिनुहोस् कि यो अनुमतिले प्रयोगकर्ता खाताहरू निस्कृय पार्ने क्षमता पनि दिन्छ। " + explanation: 'सो युजेर पेजमा "सम्पादन" बटन क्लिक गर्ने, प्रयोगकर्ताको बारेमा जानकारी अपडेट गर्ने र ''सुरक्षित गर्नुहोस्'' गर्न सक्ने क्षमता । कृपया ध्यान दिनुहोस् कि यो अनुमतिले प्रयोगकर्ता खाताहरू निस्कृय पार्ने क्षमता पनि दिन्छ। ' label: सम्पादन गर्नुहोस् । explanation: व्यक्तिगत प्रयोगकर्ता खाता प्रतिनिधित्व गर्दछ। label: प्रयोगकर्ताहरू user_group: actions: assign: - explanation: "प्रयोगकर्ता खाता सिर्जना वा सम्पादन गर्दा प्रयोगकर्ता समूहहरू छनौट गर्ने क्षमता। कृपया ध्यान दिनुहोस् कि यदि हालको प्रयोगकर्तासँग \"मेरो समूहको रेकर्डहरू वा प्रयोगकर्ताहरू\" स्तरको पहुँच छ भने, उनीहरूले सिर्जना वा सम्पादन गरिरहेको प्रयोगकर्ता खाताको लागि आफ्नो प्रयोगकर्ता समूहहरू मध्ये छनौट गर्न सक्नेछन् । यसको मतलब यो हो कि प्रयोगकर्ता समूहहरू तोक्ने क्षमता भएको प्रबन्धकले प्रयोगकर्तालाई हालको प्रबन्धक समूहहरूमा मात्र थप्न सक्षम हुनेछ। प्रयोगकर्ता खाताहरू सिर्जना वा सम्पादन गर्ने भूमिकामा रहेको जो कसैलाई पनि यो अनुमति आवश्यक छ ।" + explanation: प्रयोगकर्ता खाता सिर्जना वा सम्पादन गर्दा प्रयोगकर्ता समूहहरू छनौट गर्ने क्षमता। कृपया ध्यान दिनुहोस् कि यदि हालको प्रयोगकर्तासँग "मेरो समूहको रेकर्डहरू वा प्रयोगकर्ताहरू" स्तरको पहुँच छ भने, उनीहरूले सिर्जना वा सम्पादन गरिरहेको प्रयोगकर्ता खाताको लागि आफ्नो प्रयोगकर्ता समूहहरू मध्ये छनौट गर्न सक्नेछन् । यसको मतलब यो हो कि प्रयोगकर्ता समूहहरू तोक्ने क्षमता भएको प्रबन्धकले प्रयोगकर्तालाई हालको प्रबन्धक समूहहरूमा मात्र थप्न सक्षम हुनेछ। प्रयोगकर्ता खाताहरू सिर्जना वा सम्पादन गर्ने भूमिकामा रहेको जो कसैलाई पनि यो अनुमति आवश्यक छ । label: तोक्नुहोस् । create: - explanation: "प्रयोगकर्ता समूह सिर्जना गर्ने क्षमता भएको " + explanation: 'प्रयोगकर्ता समूह सिर्जना गर्ने क्षमता भएको ' label: सिर्जना गर्नुहोस् । delete: - explanation: " प्रयोगकर्ता समूह मेटाउने क्षमता भएको" - label: "मेटाउनुहोस्। " + explanation: ' प्रयोगकर्ता समूह मेटाउने क्षमता भएको' + label: 'मेटाउनुहोस्। ' manage: explanation: 'प्रयोगकर्तालाई प्रयोगकर्ता समूहहरूमा सबै उपलब्ध कार्यहरू गर्ने अनुमति दिन्छ । "प्रबन्ध" अनुमतिले मुख्यत "सबै कुरा" भन्ने अर्थ दिन्छ । महत्त्वपूर्ण : यसले प्रयोगकर्ता समूहहरू सिर्जना गर्ने र मेटाउने क्षमता पनि दिन्छ ।' label: प्रबन्ध गर्नुहोस् (यो स्रोत प्रकारको लागि सबै अनुमतिहरू) read: - explanation: " प्रयोगकर्ता समूहहरू हेर्ने क्षमता भएको" + explanation: ' प्रयोगकर्ता समूहहरू हेर्ने क्षमता भएको' label: हेर्नुहोस् write: - explanation: " प्रयोगकर्ता समूहहरू सम्पादन गर्ने क्षमता भएको" + explanation: ' प्रयोगकर्ता समूहहरू सम्पादन गर्ने क्षमता भएको' label: सम्पादन गर्नुहोस् explanation: जानकारी आदानप्रदान गर्न सक्ने प्रयोगकर्ताहरूको टोली वा सहयोगी समूहको प्रतिनिधित्व गर्दछ। प्रबन्धकहरूले सामान्यतया उनीहरूको प्रयोगकर्ता समूहहरूमा सामाजिक कार्यकर्ताहरूद्वारा व्यवस्थित गरिएका सबै रेकर्डहरू हेर्न सक्छन्। label: प्रयोगकर्ता समूह @@ -2980,10 +2886,9 @@ ne: label: सिर्जना गर्नुहोस delete: explanation: API बाट webhook कन्फिगरेसन मेटाउने क्षमता भएको - label: "मेटाउनुहोस्। " + label: 'मेटाउनुहोस्। ' manage: label: प्रबन्ध गर्नुहोस् (यो स्रोत प्रकारको लागि सबै अनुमतिहरू) - explanation: activity_log: actions: transfer: @@ -2991,7 +2896,6 @@ ne: label: स्थानान्तरणहरु manage: label: प्रबन्ध गर्नुहोस् (यस स्रोत प्रकारका लागि सबै अनुमतिहरू) - explanation: label: गतिविधि लग potential_match: case_id: घटना आइडी @@ -3006,14 +2910,13 @@ ne: social_worker: सामाजिक कार्यकर्ता social_worker_agency: निकाय tracing_request_id: ट्रेसिङ्ग अनुरोध आईडी - trace: "पत्ता लगाउने " + trace: 'पत्ता लगाउने ' likelihood_likely: हुन सक्ने likelihood_possible: सम्भावित potential_matches: - display: "%{type}%{id} को लागी सम्भावित मिलान देखाइएको" + display: '%{type}%{id} को लागी सम्भावित मिलान देखाइएको' reassign: - multiple_error: "एउटा त्रुटि देखापर्यो । %{select_records}केस (हरू) तोकिएका छैनन् ।" - multiple_successfully: '%{select_records}केस (हरू) सफलतापूर्वक तोकियो' + multiple_error: एउटा त्रुटि देखापर्यो । %{select_records}केस (हरू) तोकिएका छैनन् । notes_label: नोटहरू successfully: सफलतापूर्वक पुनः तोकिएको । user_mandatory_label: प्रापक आवश्यक छ । @@ -3040,19 +2943,19 @@ ne: type_of_recipient: प्रापकको प्रकार type_of_referral_required: रेफेरलको प्रकार आवश्यक छ agency_label: निकाय - is_remote_label: "के तपाईं रिमोट प्रणालीका बारे उल्लेख गर्दै हुनुहुन्छ ?" + is_remote_label: के तपाईं रिमोट प्रणालीका बारे उल्लेख गर्दै हुनुहुन्छ ? location_label: स्थान notes_label: नोटहरु notes_on_referral: रेफेरलमा नोट note_on_referral_from_provider: प्रदायकबाट रेफेरलमा नोटहरु provided_consent_label: फारमहरूमा सहमति प्रदान गरिएको छैन । recipient_label: प्रापक - refer_anyway_label: "जे भए पनि रिफर गर्ने ? " + refer_anyway_label: 'जे भए पनि रिफर गर्ने ? ' service_label: सेवा success: ' %{record_type}%{id} सफलतापूर्वक रिफर गरियो' user_mandatory_label: प्रापक आवश्यक छ । date: मिति - rejected_reason: "अस्वीकार गर्नुको कारण " + rejected_reason: 'अस्वीकार गर्नुको कारण ' report: aggregate_by: पक्तिको आधारमा समूह बनाउनुहोस् । attribute: विशेषता @@ -3061,32 +2964,32 @@ ne: date: दिन month: महिना quarter: त्रैमासिक - quarter_abbr: "Q%{quarter}" + quarter_abbr: Q%{quarter} week: हप्ता year: वर्ष description: विवरण disabled: - explanation: "यदि तपाईंले यो प्रतिवेदनलाई निष्कृय पार्नुभयो भने, उपलब्ध प्रतिवेदनहरूमा यो देखिने छैन ।" + explanation: यदि तपाईंले यो प्रतिवेदनलाई निष्कृय पार्नुभयो भने, उपलब्ध प्रतिवेदनहरूमा यो देखिने छैन । label: निष्क्रिय पारिएको - exclude_empty_rows: "खाली पक्तिहरु नदेखाउनुहोस्। " + exclude_empty_rows: 'खाली पक्तिहरु नदेखाउनुहोस्। ' disaggregate_by: कोलुमको समूह बनाउनुहोस filters: - label: " प्रतिवेदन फिल्टरहरू" + label: ' प्रतिवेदन फिल्टरहरू' label_new: नयाँ प्रतिवेदन फिल्टर attribute: फिल्टर value: संग - not_null: "खाली छैन ?" + not_null: खाली छैन ? less_than: भन्दा कम greater_than: भन्दा ठुलो equal_to: बराबर - not_blank: "खाली छैन " + not_blank: 'खाली छैन ' is: हो छ - before: "अघि " + before: 'अघि ' after: पछि - delete_filter_message: "के तपाईं यो फिल्टर पक्का हटाउन चाहनुहुन्छ ?" + delete_filter_message: के तपाईं यो फिल्टर पक्का हटाउन चाहनुहुन्छ ? group_ages: उमेर दायराहरूको प्रयोग गर्नुहोस् । group_dates_by: मिति दायराहरूको प्रयोग गर्नुहोस् । - is_graph: "ग्राफ सिर्जना गर्न चाहनुहुन्छ ?" + is_graph: ग्राफ सिर्जना गर्न चाहनुहुन्छ ? messages: delete_success: रिपोर्ट सफलतापूर्वक मेटाइएको । success: रिपोर्ट सफलतापूर्वक सिर्जना गरिएको । @@ -3102,17 +3005,17 @@ ne: value: Value reports: delete_report: प्रतिवेदन मेटाउनुहोस् - delete_report_message: "के तपाईं पक्का यो प्रतिवेदन मेटाउन चाहनुहुन्छ ? मेटाएपछि पुन: प्रतिवेदन पाउन सकिँदैन । प्रतिवेदन मेटाउन \"ठीक छ\" क्लिक गर्नुहोस् ।" + delete_report_message: 'के तपाईं पक्का यो प्रतिवेदन मेटाउन चाहनुहुन्छ ? मेटाएपछि पुन: प्रतिवेदन पाउन सकिँदैन । प्रतिवेदन मेटाउन "ठीक छ" क्लिक गर्नुहोस् ।' label: प्रतिवेदनहरू register_new_report: प्रतिवेदन सिर्जना गर्नुहोस translations: edit: अनुवाद सम्पादन गर्नुहोस् । manage: अनुवादहरूको प्रबन्ध मिलाउनुहोस् । - select_language: "भाषा छनौट गर्नुहोस् " + select_language: 'भाषा छनौट गर्नुहोस् ' error_loading: प्रतिवेदन(हरु) लोड गर्दा त्रुटि request_transfer: notes_label: नोटहरु - submit_label: "अनुरोध पठाउनुहोस । " + submit_label: 'अनुरोध पठाउनुहोस । ' success: स्थानान्तरण अनुरोध पठाइयो । role: agency_ids_label: यस भूमिकाद्वारा व्यवस्थित निकायहरू @@ -3123,20 +3026,20 @@ ne: description: विवरण edit: भूमिका सम्पादन गर्नुहोस्। error_in_updating: भूमिका विवरण अद्यावधिक गर्दा त्रुटि देखियो - group_permission_label: "यो भूमिकाले कुन रेकर्डलाई असर गर्छ ?" + group_permission_label: यो भूमिकाले कुन रेकर्डलाई असर गर्छ ? label: भूमिका manager: प्रबन्धक messages: - confirmation: "के तपाईं यो भूमिका पक्का मेटाउन चाहनुहुन्छ ? मेटाएपछि पुन: भूमिका पाउन सकिँदैन । भूमिका मेटाउन \"ठीक छ\" क्लिक गर्नुहोस् ।" + confirmation: 'के तपाईं यो भूमिका पक्का मेटाउन चाहनुहुन्छ ? मेटाएपछि पुन: भूमिका पाउन सकिँदैन । भूमिका मेटाउन "ठीक छ" क्लिक गर्नुहोस् ।' created: भूमिका सफलतापूर्वक सिर्जना गरिएको । deleted: भूमिका सफलतापूर्वक मेटाइएको । updated: भूमिका सफलतापूर्वक अद्यावधिक गरिएको । name: नाम - referral_label: "के यो भूमिका रेफरलको लागि प्रयोग गर्न सकिन्छ ?" - reporting_location_level_label: "यो भूमिकाको प्रतिवेदनको लागि कुन प्रकारको स्थान उपयोग गर्नुपर्छ ?" + referral_label: के यो भूमिका रेफरलको लागि प्रयोग गर्न सकिन्छ ? + reporting_location_level_label: यो भूमिकाको प्रतिवेदनको लागि कुन प्रकारको स्थान उपयोग गर्नुपर्छ ? role_ids_label: यो भूमिकाद्वारा व्यवस्थित अन्य भूमिकाहरू - successfully_updated: "भूमिका विवरण सफलतापूर्वक अद्यावधिक गरिएको छ । " - transfer_label: "के यो भूमिका स्थानान्तरणको लागि प्रयोग गर्न सकिन्छ ?" + successfully_updated: 'भूमिका विवरण सफलतापूर्वक अद्यावधिक गरिएको छ । ' + transfer_label: के यो भूमिका स्थानान्तरणको लागि प्रयोग गर्न सकिन्छ ? hide: लुकाउनुहोस् read: देखाउनु read_write: देखाउनुहोस् र सम्पादन गर्नुहोस्। @@ -3145,13 +3048,13 @@ ne: saved_search: deleted: खोज सफलतापूर्वक मेटाइएको । filters_tab: फिल्टर - no_filters: " कुनै फिल्टर छनौट गरिएको छैन।" - save_success: "खोज सफलतापूर्वक सुरक्षित गरिएको । " + no_filters: ' कुनै फिल्टर छनौट गरिएको छैन।' + save_success: 'खोज सफलतापूर्वक सुरक्षित गरिएको । ' saved_searches_tab: सुरक्षित गरिएको खोजहरु - title_description: "के तपाईं यो सुरक्षित गरिएको खोज पक्का मेटाउन चाहनुहुन्छ ?" + title_description: के तपाईं यो सुरक्षित गरिएको खोज पक्का मेटाउन चाहनुहुन्छ ? title_modal: सुरक्षित गरिएको खोजहरु मेटाउनुहोस् saved_searches: - no_save_searches: "तपाइँसँग कुनै खोज सुरक्षित गरिएको छैन । " + no_save_searches: 'तपाइँसँग कुनै खोज सुरक्षित गरिएको छैन । ' save_search: खोज सुरक्षित गर्नुहोस् । settings: navigation: @@ -3182,22 +3085,22 @@ ne: status: स्थिति statuses: overdue: म्याद नाघेको - upcoming_soon: "लगभग म्याद सकिएको " + upcoming_soon: 'लगभग म्याद सकिएको ' type: कार्यको प्रकार types: assessment: मूल्याङ्कन गर्नुहोस् case_plan: घटना योजना - follow_up: "फलोअप - %{subtype}" - service: "सेवा - %{subtype}" + follow_up: फलोअप - %{subtype} + service: सेवा - %{subtype} tracing_request: label: ट्रेसिङ्ग अनुरोध has_match: मिल्दो फेला परेको छ। find_match: मिल्दो फेला पार्नुहोस् - back_to_traces: "ट्रेसहरु पुन:फर्कनुहोस" + back_to_traces: ट्रेसहरु पुन:फर्कनुहोस back_to_potential_matches: सम्भावित मेलमा फर्कनुहोस् । traces: ट्रेसहरु trace: ट्रेस - match: "मेल खायो " + match: 'मेल खायो ' matches: मेलहरु unmatch: मेल खाएन tracing_request_photos: यस ट्रेसिङ अनुरोधको लागि फोटोहरू @@ -3209,23 +3112,23 @@ ne: disabled: ट्रेसिङ्ग अनुरोध निष्कृय पारिएको छ । nothing_found: केहीपनि भेटिएन update_success: 'ट्रेसिङ्ग अनुरोध %{record_id} सफलतापूर्वक अद्यावधिक गरियो ।' - creation_success: "ट्रेसिङ्ग अनुरोधको अभिलेख सफलतापूर्वक सिर्जना गरियो । " + creation_success: 'ट्रेसिङ्ग अनुरोधको अभिलेख सफलतापूर्वक सिर्जना गरियो । ' update_success_queue: 'ट्रेसिङ्ग अनुरोध %{record_id} पृष्ठभूमिमा सफलतापूर्वक अद्यावधिक गरियो' creation_success_queue: ट्रेसिङ अनुरोधको अभिलेख पृष्ठभूमिमा सफलतापूर्वक सिर्जना गरियो । - match_action: "ट्रेस %{trace_id} सँग केस%{record_id} सफलतापूर्वक मिलान गरियो ।" - unmatch_action: "ट्रेस %{trace_id}सँग केस%{record_id} मेल नखाने कार्य सफलतापूर्वक गरियो ।" + match_action: ट्रेस %{trace_id} सँग केस%{record_id} सफलतापूर्वक मिलान गरियो । + unmatch_action: ट्रेस %{trace_id}सँग केस%{record_id} मेल नखाने कार्य सफलतापूर्वक गरियो । registry_record: messages: update_success: '%{record_id} रजिस्ट्री रेकर्डहरु सफलतापूर्वक अद्यावधिक गरिएको ।' creation_success: 'रजिस्ट्री रेकर्ड सफलतापूर्वक सिर्जना गरिएको' disabled: रजिस्ट्री रेकर्ड निस्कृय रहेको छ tracing_requests: - date_of_inquiry: "सोधपुछको मिति " + date_of_inquiry: 'सोधपुछको मिति ' disable_dialog_title: ट्रेसिङ्ग अनुरोध निष्कृय पार्नुहोस् । - disable_dialog: "'ठिक छ' मा क्लिक गर्नाले ट्रेसिङ्ग अनुरोधको स्थितिलाई निष्कृय बनाउनेछ" + disable_dialog: '''ठिक छ'' मा क्लिक गर्नाले ट्रेसिङ्ग अनुरोधको स्थितिलाई निष्कृय बनाउनेछ' disable_success: ट्रेसिङ्ग अनुरोध सफलतापूर्वक निष्कृय पारियो । - enable_dialog: "'ठिक छ' मा क्लिक गर्नाले ट्रेसिङ्ग अनुरोधको स्थितिलाई सकृय बनाउनेछ" - enable_dialog_title: "ट्रेसिङ्ग अनुरोधहरू सकृय पार्नुहोस् ?" + enable_dialog: '''ठिक छ'' मा क्लिक गर्नाले ट्रेसिङ्ग अनुरोधको स्थितिलाई सकृय बनाउनेछ' + enable_dialog_title: ट्रेसिङ्ग अनुरोधहरू सकृय पार्नुहोस् ? enable_success: ट्रेसिङ्ग अनुरोधहरू सफलतापूर्वक सकृय पारियो । id: आईडी complete: अफलाईन उपलब्ध रहेको @@ -3240,12 +3143,12 @@ ne: name: नाम register_new_tracing_request: नयाँ ट्रेसिङ्गको लागि अनुरोध selectable_date_options: - inquiry_date: "सोधपुछको मिति " + inquiry_date: 'सोधपुछको मिति ' selected_records: '%{select_records} ट्रेसिङ्ग अनुरोध (हरू) छनौट गरियो' selected_all_records: 'यो जिज्ञासासँग मेल सबै %{total_records} ट्रेसिङ्ग अनुरोधहरू छान्नुहोस् ।' show_tracing_request: 'ट्रेसिङ्ग अनुरोध आईडी%{short_id}' tracing_requests: ट्रेसिङ्ग अनुरोधहरू - export: "Export गर्नुहोस् । " + export: 'Export गर्नुहोस् । ' sort_by: क्रमबद्ध गर्नुहोस् registry_records: id: आईडी @@ -3273,24 +3176,24 @@ ne: export: निर्यात mark_for_offline: title: अफलाईनको लागि चिन्ह लगाउनुहोस् - text: "के तपाई अफलाईन हुँदा प्रयोगको लागि यी रजिस्ट्री रेकर्डहरू चिन्ह लगाउन निश्चित हुनुहुन्छ?" + text: के तपाई अफलाईन हुँदा प्रयोगको लागि यी रजिस्ट्री रेकर्डहरू चिन्ह लगाउन निश्चित हुनुहुन्छ? success: अफलाईन प्रयोगको लागि रजिस्ट्री रेकर्डहरू सफलतापूर्वक चिन्ह लगाइएको transfer: label: ट्रान्सफर - agency_label: "निकाय " - consent_from_individual_label: "के यो स्थानान्तरण गर्नको लागि तपाईंले व्यक्तिबाट सहमति पाउनु भएको छ ? " + agency_label: 'निकाय ' + consent_from_individual_label: 'के यो स्थानान्तरण गर्नको लागि तपाईंले व्यक्तिबाट सहमति पाउनु भएको छ ? ' consent_label: अभिलेखद्वारा सहमति प्रदान गरिएको छैन । - consent_override_label: "के तपाइँ यो सेटिंग ओभरराइड गर्न चाहानुहुन्छ?" - is_remote_label: "के तपाईं रिमोट सिस्टममा स्थानान्तरण गर्दै हुनुहुन्छ ? " + consent_override_label: के तपाइँ यो सेटिंग ओभरराइड गर्न चाहानुहुन्छ? + is_remote_label: 'के तपाईं रिमोट सिस्टममा स्थानान्तरण गर्दै हुनुहुन्छ ? ' location_label: स्थान notes_label: नोटहरु provided_consent_label: फारममा सहमति प्रदान गरिएको छैन । recipient_label: प्रापक select_label: छनौट गर्नुहोस् success: सफलतापूर्वक स्थानान्तरण गरियो ।  - transfer_label: "जे भए पनि स्थानान्तरण गर्ने ? " + transfer_label: 'जे भए पनि स्थानान्तरण गर्ने ? ' user_mandatory: प्रापक आवश्यक छ । - rejected_reason: "अस्वीकार गर्नुको कारण " + rejected_reason: 'अस्वीकार गर्नुको कारण ' transfer_assignment: title: स्थानान्तरण र कार्यभारहरू transition: @@ -3305,8 +3208,8 @@ ne: errors: consent: सहमति प्रदान गरिएको छैन । to_user_can_receive: यो प्रयोगकर्ता यो अभिलेख प्राप्त गर्न सक्दैन । - individual_consent: "के यो स्थानान्तरण गर्नको लागि घटना कार्यकर्तालाई व्यक्तिबाट सहमति थियो ?" - no_consent_share: "ओभरराईड गरिएको सेटिङहरु शेयर गर्न सहमति छ ?" + individual_consent: के यो स्थानान्तरण गर्नको लागि घटना कार्यकर्तालाई व्यक्तिबाट सहमति थियो ? + no_consent_share: ओभरराईड गरिएको सेटिङहरु शेयर गर्न सहमति छ ? notes: नोटहरु recipient: प्रापक rejected: कारण अस्वीकृत गरियो @@ -3314,19 +3217,19 @@ ne: service_label: सेवा responded_at: रेसपन्स गरिएको समय status: - accepted: "स्वीकार गरिएको " + accepted: 'स्वीकार गरिएको ' done: सम्पन्न - in_progress: "विचाराधीन " - inprogress: "विचाराधीन " + in_progress: 'विचाराधीन ' + inprogress: 'विचाराधीन ' rejected: अस्वीकृत revoked: खारेज गरिएको type: assign: तोक्नुहोस् । reassign: तोक्नुहोस् । - referral: "रेफेरल " - external_referral: "बाह्य रेफेरल " + referral: 'रेफेरल ' + external_referral: 'बाह्य रेफेरल ' transfer: स्थानान्तरण गर्नुहोस् । - transferRequest: "स्थानान्तरण अनुरोध " + transferRequest: 'स्थानान्तरण अनुरोध ' user: agency_office: निकाय कार्यालय (GBV क्षेत्र) code: प्रयोगकर्ता कोड @@ -3340,11 +3243,11 @@ ne: locale: स्थान location: स्थान messages: - confirmation: "के तपाईं यो प्रयोगकर्तालाई मेटाउन चाहनुहुन्छ ? मेटाएपछि पुन: पाउन सकिँदैन । प्रयोगकर्ता मेटाउन 'ठीक छ' क्लिक गर्नुहोस् ।" + confirmation: 'के तपाईं यो प्रयोगकर्तालाई मेटाउन चाहनुहुन्छ ? मेटाएपछि पुन: पाउन सकिँदैन । प्रयोगकर्ता मेटाउन ''ठीक छ'' क्लिक गर्नुहोस् ।' created: प्रयोगकर्तालाई सफलतापूर्वक सिर्जना गरियो failure: त्रुटि देखा परेकोले कृपया सहयोगको लागि सम्पर्क गर्नुहोस् । - new_confirm_html: "प्रीमेरो प्रयोग गर्नको लागि तपाईले %{identity} बाट %{username} लाई %{role} को भुमिकामा आमन्त्रित गर्न लाग्नु भएको छ । पुष्टिको लागि %{email} मा ईमेल पठाइनेछ । के तपाई अघि बढ्न चाहनुहुन्छ ?" - new_confirm_non_identity_html: "प्रीमेरो प्रयोग गर्नको लागि तपाईंले भूमिका %{role} भएको प्रयोगकर्ता %{username} लाई आमन्त्रित गर्न लाग्नु भएको छ । पुष्टिको लागि %{email} मा ईमेल पठाइने छ । के तपाई अघि बढ्न चाहनुहुन्छ ?" + new_confirm_html: प्रीमेरो प्रयोग गर्नको लागि तपाईले %{identity} बाट %{username} लाई %{role} को भुमिकामा आमन्त्रित गर्न लाग्नु भएको छ । पुष्टिको लागि %{email} मा ईमेल पठाइनेछ । के तपाई अघि बढ्न चाहनुहुन्छ ? + new_confirm_non_identity_html: प्रीमेरो प्रयोग गर्नको लागि तपाईंले भूमिका %{role} भएको प्रयोगकर्ता %{username} लाई आमन्त्रित गर्न लाग्नु भएको छ । पुष्टिको लागि %{email} मा ईमेल पठाइने छ । के तपाई अघि बढ्न चाहनुहुन्छ ? not_found: दिइएको आईडीसँग मेल खाने प्रयोगकर्ता फेला परेन । password_changed_successfully: पासवर्ड सफलतापूर्वक परिवर्तन भयो । passwords_do_not_match: वर्तमान पासवर्डसँग मिल्दैन । @@ -3352,24 +3255,24 @@ ne: updated: प्रयोगकर्तालाई सफलतापूर्वक अद्यावधिक गरिएको । organization: संस्था agency: निकाय - services_help_text: "यदि तपाईंले सेवाहरू खुलाउन भएन भने, यो प्रयोगकर्तालाई निकायमा भएका सेवाहरू प्रदान गरिनेछ ।" + services_help_text: यदि तपाईंले सेवाहरू खुलाउन भएन भने, यो प्रयोगकर्तालाई निकायमा भएका सेवाहरू प्रदान गरिनेछ । password_setting: - label: "प्रीमेरो प्रयोगकर्ताले पासवर्ड कसरी सेट गर्नुपर्छ ?" - self: "म पासवर्ड सेट गर्छु । " + label: प्रीमेरो प्रयोगकर्ताले पासवर्ड कसरी सेट गर्नुपर्छ ? + self: 'म पासवर्ड सेट गर्छु । ' user: प्रयोगकर्ताले स्वागत ईमेलको उपयोग गरी पासवर्ड सेट गर्दछन् । - help_text: "कृपया याद गर्नुहोस् कि यदि तपाईं प्रशासक हो र तपाईं पासवर्ड आफैले सेट गर्नु हुन्छ भने तपाईंले सुरक्षित तरिकाले प्रयोगकर्तालाई पासवर्ड प्रदान गर्नुपर्दछ । " + help_text: 'कृपया याद गर्नुहोस् कि यदि तपाईं प्रशासक हो र तपाईं पासवर्ड आफैले सेट गर्नु हुन्छ भने तपाईंले सुरक्षित तरिकाले प्रयोगकर्तालाई पासवर्ड प्रदान गर्नुपर्दछ । ' password_reset_header: पासवर्ड रिसेट ईमेल पठाउनुहोस् । - password_reset_text: "यदि तपाईंले 'पठाउनुहोस्' मा क्लिक गर्नु भयो भने, यो प्रयोगकर्तालाई पासवर्ड परिवर्तन गर्न एउटा लिङ्क सहितको ईमेल प्राप्त हुनेछ । " - password_reset_request: "पासवर्ड रिसेट ईमेल सूचनाहरू पठाउन चाहनुहुन्छ ?" - password: "पासवर्ड " + password_reset_text: 'यदि तपाईंले ''पठाउनुहोस्'' मा क्लिक गर्नु भयो भने, यो प्रयोगकर्तालाई पासवर्ड परिवर्तन गर्न एउटा लिङ्क सहितको ईमेल प्राप्त हुनेछ । ' + password_reset_request: पासवर्ड रिसेट ईमेल सूचनाहरू पठाउन चाहनुहुन्छ ? + password: 'पासवर्ड ' password_confirmation: पासवर्ड पुष्टी phone: फोन position: पद provider_username_help: 'Example: my.username@%{domain}' role_id: भूमिका - send_mail: "ईमेल सूचना प्राप्त गर्न चाहानुहुन्छ ?" + send_mail: ईमेल सूचना प्राप्त गर्न चाहानुहुन्छ ? user_group_unique_ids: प्रयोगकर्ता समूह - user_name: " प्रयोगकर्ता नाम" + user_name: ' प्रयोगकर्ता नाम' services: सेवाहरू welcome_email: subject: '%{system}मा स्वागत छ' @@ -3387,8 +3290,8 @@ ne: step2: '%{host}मा जानुहोस् र "प्रीमेरो प्रयोगकर्ता नामबाट लगईन गर्नुहोस्"मा क्लिक गर्नुहोस्।' step3: 'तपाँईको प्रीमेरो प्रयोगकर्ता नाम र यो अस्थाई पासवर्ड %{otp} प्रयोग गरी लगईन गर्नुहोस्।' step4: 'सङ्केत पाएपछि तपाईंको पासवर्ड रिसेट गर्नुहोस् । ' - url_label: "प्रीमेरो " - enabled_label: "स्वागत ईमेल पठाउन चाहनुहुन्छ ?" + url_label: 'प्रीमेरो ' + enabled_label: स्वागत ईमेल पठाउन चाहनुहुन्छ ? text_label: स्वागत ईमेल सन्देश   password_reset: subject: 'पासवर्ड रिसेटको निर्देशनहरू' @@ -3412,18 +3315,18 @@ ne: associated_agencies: यस प्रयोगकर्ता समूहसँग सम्बन्धित निकायहरू description: विवरण disabled: - explanation: "यदि तपाईंले यो प्रयोगकर्ता समूहलाई निष्कृय गर्नु भयो भने, तपाईंले अब उप्रान्त यो समूह प्रयोगकर्ताहरुलाई तोक्न पाउनु हुनेछैन ।" + explanation: यदि तपाईंले यो प्रयोगकर्ता समूहलाई निष्कृय गर्नु भयो भने, तपाईंले अब उप्रान्त यो समूह प्रयोगकर्ताहरुलाई तोक्न पाउनु हुनेछैन । label: निष्क्रिय पारिएको messages: created: प्रयोगकर्ता समूह सफलतापूर्वक सिर्जना भयो updated: प्रयोगकर्ता समूह सफलतापूर्वक सिर्जना भयो - name: " नाम " + name: ' नाम ' user_groups: label: प्रयोगकर्ता समूह users: label: प्रयोगकर्ताहरू headers: - full_name: "पुरा नाम " + full_name: 'पुरा नाम ' user_name: युजरनेम position: पद agency: निकाय @@ -3436,5 +3339,5 @@ ne: admin: locations: selected_records: '%{select_records}स्थान (हरु) छनौट गरियो ।' - selected_all_records: "यो प्रश्न सँग मेल खाने सबै %{total_records} घटनाहरु छान्नुहोस् । " + selected_all_records: 'यो प्रश्न सँग मेल खाने सबै %{total_records} घटनाहरु छान्नुहोस् । ' updated: '%{updated_records}स्थान(हरु) अद्यावधिक गरियो।' diff --git a/config/locales/om.yml b/config/locales/om.yml index a6d0e17d12..0e1329af8b 100644 --- a/config/locales/om.yml +++ b/config/locales/om.yml @@ -1,45 +1,38 @@ -# encoding: utf-8 -# -# This is the English localization file for Primero. It is based on the sample -# English localization file found in the repository linked below[1]. -# -# Anyone editing this file is strongly encouraged to use yamllint[2] to ensure -# that this document remains valid YAML. -# -# [1] https://github.com/svenfuchs/rails-i18n/ -# [2] https://yamllint.readthedocs.io/en/stable/ - - ---- om: - 'true': 'Eeyyen.' + 'true': 'Eeyyen' 'false': 'Miti/lakki' accepted: Fudhatama argateera. cancel: Haquu. connection_lost: Yeroo ammaantanaa haala sararaan ala keessa jiran. - connected: Walqunnamaniiru. + field_mode_offline: Yeroodhaaf hojii dirree irra jira + connected: Walqunnamaniiru + no_connection: Walitti Dhufeenya hin qabu. clear: Ifa. - sandbox_ui: " Agarsiisa." + sandbox_ui: ' Agarsiisa.' description: Ibsa. form: Guca/unka. minimum_reportable_fields: "Dirreewwan xiqqicha gabaasamuu%{record_type} danda'an." name: Maqaa. offline: Sararaan ala. + field_mode: "Haala Bobbaa" + field_mode_on: "Banaa" + field_mode_off: "Cufaa" unavailable_offline: Sararaan alatti hinargamu. online: Sarara irra. yes_label: 'Eeyyen.' - or_label: Ykn. + or_label: Ykn select_provider: Dhiyeessaa filadhaa. select_language: Qooqa/afaan filadhaa. - log_in_primero_idp: "Maqaa fayyadamaan %{idp_name}keessa seeni" + log_in_primero_idp: Maqaa fayyadamaan %{idp_name}keessa seeni offline_submitted_changes: Yeroo ammaa kana sararaan ala jirtan. Jijjiramni taasistan kan galu yoo sarara irratti deebitanidha. updated: Ammayyoomeera. + go: Deemi + select_idp_error: Maloo kennaa filadhu sync: success: "Galmeewwan%{records} haala milkaa'aan walsimaniiru." error: - create: "Uumuu hindandeenye %{record_type}.Maloo deeggarsa argadhaa." - update: "Ammayyoomsuun %{record_type}%{short_id}hin milkoofne.Maloo deeggarsa argadhaa." - + create: Uumuu hindandeenye %{record_type}.Maloo deeggarsa argadhaa. + update: Ammayyoomsuun %{record_type}%{short_id}hin milkoofne.Maloo deeggarsa argadhaa. actions: approvals: Mirkaneessummoota. button: Gochoota. @@ -51,11 +44,11 @@ om: enable: Dandeessisuu. incident_details_from_case: Taatee dabali/ida'i. incident_from_case: Taatee uumi. - next: " Itti aanee." + next: ' Itti aanee.' notes: Yaadannoo dabali. previous: Dursaa/duraa. reopen: Irra deebiin bani. - request_approval: " Mirkaneessa gaafadhaa." + request_approval: ' Mirkaneessa gaafadhaa.' revoke: Kuffisuu/fudhatama dhabsiisuu. save: Ol'kaa'i . services_from_case_creation_success: Galmeen kennisa tajaajilaa milkiin banamee jira. @@ -73,23 +66,23 @@ om: exclude_agency_from_lookups: Ejensicha kana dhimma barbaachaawwanii fi calaliiwwanii irraa baasaa/ hambisaa. exclude_agency_from_lookups_help: Ejensichi fayyadamtoota kan hin qabaannee yoo ta'e isa kana mirkanneeffadhaa/ mirkaneessaa.(fknf. ejensichi ida'ameera.Kanaafuu asxichi hojii gara alaatti erguuf nihojjeta. label: Ejensii. - logo_enabled: "Asxaa ejensii kana Piriimiiroo keessatti agarsiisaa?" - logo_enabled_help: "Asxaa ejensii kanaa Piriimiiroo keessatti agarsiisaa?" + logo_enabled: Asxaa ejensii kana Piriimiiroo keessatti agarsiisaa? + logo_enabled_help: Asxaa ejensii kanaa Piriimiiroo keessatti agarsiisaa? logo_icon: Asxaa jaalatamaa. - logo_icon_help: "Inni kun qixxaayinoota argii xiqqaatiin ,taabileetootaa fi bilbilootaa irratti mul'ata.Inni kunis rog-afree ta'utu irra jiraata." + logo_icon_help: Inni kun qixxaayinoota argii xiqqaatiin ,taabileetootaa fi bilbilootaa irratti mul'ata.Inni kunis rog-afree ta'utu irra jiraata. logo_large: Asxaa guddaa. logo_large_help: Inni kun qixxaayinoota argii gurguddaa fi gara alaatti nerguu PiiDiiEffii(PDF) keessatti mul'ata..Inni kunis reektaangilii dheerinni isaa dheerinna hojaa isaa irra dheeratu ta'uu qaba. messages: created: Ejensichi haala milkaa'aan uumameera. updated: Ejensichi haala milkaa'aan ammayyoomeera. name: Maqaa Ejensichaa. - pdf_logo_option: "Gara alaatti erguu Pii Dii Fiif asxaan akka argamu taasisuu?" + pdf_logo_option: Gara alaatti erguu Pii Dii Fiif asxaan akka argamu taasisuu? pdf_logo_option_help: 'Hubachiisa:Asxaawwan fayyadamaa ejensichaa isaaniif durtiin ni argamu.Kanaafuu isin asxaan kun fayyadamtoota hundaafuu akka argamu yoo barbaaddan qofa kan mirkaneessitan.' services: Tajaajiloota Ejensichaa. terms_of_use: Qajelfama itti fayyadamaa. terms_of_use_help: Faayiloota PiiDii Effii hayyamaman qofa. terms_of_use_download_button: PDFii buusi/fe'i. - terms_of_use_enabled: "Waliigaltee itti fayyadamaa agarsiisi?" + terms_of_use_enabled: Waliigaltee itti fayyadamaa agarsiisi? approvals: approved_by: Qaama/nama mirkaneesse. case_plan_type_label: Akaakuu/gosa karoora dhimmaa. @@ -121,7 +114,7 @@ om: status: Haala. form_export: label: Qindaayina guca/unka gara alaatti erguu. - include_hidden: "Gucaawwan dhokatanii fi dirrewwan dabalataa?" + include_hidden: Gucaawwan dhokatanii fi dirrewwan dabalataa? file_name: Maqaa faayila dhuunfaa keessanii uumaa.(filannoo) success_message: Faayilli gara alaatti ergamu milkaa'inaan uumameera. buttons: @@ -149,7 +142,7 @@ om: continue: Ittifufi. create_case: Dhimma uumi. create_incident: Taatee uumi. - create_new_record: "Haaraa uumi %{model}" + create_new_record: Haaraa uumi %{model} delete: Haqi/haquu. disable: Dadhabsiisi/Irraa kaasi. disable_photo_wall: Dhaabaa suuraa irraa kaasi. @@ -163,9 +156,9 @@ om: filter: Calallii fayyadami/hojirra oolchi. filter_clear: Calalliwwan ifa ta'an. filter_label: 'Calallii.' - filter_restore: "Gara bakka qindaayinootni sirnaa turetti deebsii. " + filter_restore: 'Gara bakka qindaayinootni sirnaa turetti deebsii. ' find_tracing_match: Walsimsiisa barbaachaa argadhaa. - flag_model: "Alaabaa%{model}." + flag_model: Alaabaa%{model}. flag_records: Alaabaa/mallattoo. flags: Alaabaawwan/mallattoowwan. guidance: Qajelfama. @@ -198,28 +191,42 @@ om: sync: Wal simsiisi/walfakkeessi. submit: Galchi. transfer: Dabarsuu. - unflag_model: "Alaabaa/mallattoo kaassi %{model}" - unflag_model_history: "Seenaa Alabaa %{model}" + unflag_model: Alaabaa/mallattoo kaassi %{model} + unflag_model_history: Seenaa Alabaa %{model} unmark_for_mobile: Mobaayilaaf mallattoo kaa'uu dhabuu. update: Haaroomsi. view: Ilaalcha/Agarsiisi. view_flags_history: Seenaa ilaalaa. return_to_case: Gara dhimmatti deebi'i. + enable_webpush: Beeksia meeshaa + dialog_yes: "Eeyyeen" + resync_records: + id: Waraqaa Eenyummaa + record_type: Gosa galmee + action: Gocha + date: Guyyaa + last_attempt: Yaalii Dhumaa + create: Uumi/Kalaqi + update: Foyyeessi + resync: Galchi case: label: Dhimma. create_new_case: Dhimma haaraa uumi. + create_case: Dhimma uumi + create: Uumi add_new: Haaraa galchi/dabali. + back_to_family_details: Gara Maatiitti gadi fageenyan Deebi'a back_to_case: Dhimmatti deebi'i. back_to_results: Gara bu'aatti deebi'uu. back_to_search: Gara qorannootti deebi'uu. search_by: Qaama barbaade. - search_for: "Barbaadi %{record_type}" + search_for: Barbaadi %{record_type} results: Bu'aalee. details: Bal'ina. select: Filadhaa. deselect: Filachuu dhiisuu. enter_id_number: Galmee jiru barbaaduuf lakkofsa eenyummeessaa galchaa. - id_search_no_results: "Sirnicha keessatti walsimuudhaaf kan ta'u wayiituuhin jiru%{search_query} maaloo galmee haaraa uumaa." + id_search_no_results: Sirnicha keessatti walsimuudhaaf kan ta'u wayiituuhin jiru%{search_query} maaloo galmee haaraa uumaa. messages: disabled: Dhimmi gufateera. update_success: 'Dhimmi %{record_id}haala milkaa''aan ammayyoomeera.' @@ -228,21 +235,30 @@ om: creation_success_queue: 'Galmeen dhimmaa haala milkaa''aan seen-duubaa keessatti uumameera.' already_matched: Gaafataan kun dursee dhimma keessan wajjiin walfakkaateera. already_matched_not_current_case: Sirnicha keessatti dhimmi gaafataa kana wajjiin walsimu duraanuu jira. - not_found_case: "Dhimmi wal-fakkaatan wayiituu hin argamne %{search_value}dhimma haaraa uumaa." + not_found_case: Dhimmi wal-fakkaatan wayiituu hin argamne %{search_value}dhimma haaraa uumaa. introductory_sentence: Maaloo tajajilloottan bulchinsa dhimmaa dhuunfaa fudhachuu fi galmeen isaanii pirimeeroo keessa akka taa'u eeyyama dhuunfaa ifteessaa. consent_agreements_required: Maaloo walii galteewwan eeyyamaa keessaa yoo xiqqatee filannoo tokko filadhaa. legitimate_basis_required: Maaloo ramaddiiwwan bu'ura seeraa qaban keessaa yoo xiqqaate filannoo tokko filadhaa. + confirm_create_case: Nama dhuunfaa kanaaf dhimma banuu barbaadu? + case_referral_pending: Dabarsi Dhimmaa (Case referral) eegamaa jira. + case_transfer_pending: Dabarsi dhimmaa hin xumuramne + case_no_approval_request: Dhimma kanaaf gaafiin mirkanneessuu hin gaafatamne + bulk_assign_limit: Yeroo tokkotti dhimmoota 100 ol kennuu hin qabdu. + bulk_assign_limit_try_again: Yeroo tokkotti dhimmoota 100 ol kennuu hin qabdu. Maloo dhimmoota 100 ykn kanaa gadiin irra deebiin yaali. + referral_rejected: Dabarsi dhimmaa fudhatama dhabee jira. + transfer_request_made: Dhimma kanaaf Gaaffiin Jijjiirraa /dabarsaa dhiyaateera. save: Dhimma kaa'ame. - save_text: "Itti fufuu keessaniin dura,maaloo jijjiramoota taasiftan dhimmicha irra ol kaayaa." + save_text: Itti fufuu keessaniin dura,maaloo jijjiramoota taasiftan dhimmicha irra ol kaayaa. skip_and_create: Irra utaaluu fi dhimma haaraa uumuu. search_existing: Dhimmoota jiran barbaadaa. - search_helper_text: "Maaliif?Dhimmotni baay'isaman akka hin uumamne ittisuudhaaf." + search_helper_text: Maaliif?Dhimmotni baay'isaman akka hin uumamne ittisuudhaaf. consent_agreements: Waliigalteewwan eeyyama ilaallatu hunda filadhaa. legitimate_basis: Ramaddiiwwan bu'ura seerummaa qaban ilaallatan hunda filaadhaa. + family_linked_subform_delete_disabled: Galmeen Unka xiqqaa kun Galmee Maatii wajjin walqabatee jira. Maaloo yookaan miseensa maatii kana galmee maatii keessaa baasuu, yookaan dhimma miseensa maatii sanaa Galmee Maatii irraa adda baasuu workflow: assessment: Sakatta'insa case_plan: Karoora Dhimmaa. - closed: " Cufaa." + closed: ' Cufaa.' created_on: Irratti kan uumame. in_progress: Adeemsa irra jira new: Haaraa. @@ -258,8 +274,9 @@ om: rejected_transfer: '%{to}Dabarsa fudhatama hinarganne%{record_type}%{record_id}.irraa %{from}' cases: action_plan: Karoora raawwii hojii. + access_denied: "Dhimma kana argachuu hin dandeessan." age: Umurii. - age_estimated: "Umurii tilmaamamu?" + age_estimated: Umurii tilmaamamu? agency: Ejensii. apply_filter: hojitti hiiki/raawwachuu/iyyachuu. approval_comments: Yaada. @@ -282,6 +299,7 @@ om: close_dialog_title: Dhimma cufi. close_success: Dhimma milkaa'inaan cufame. closure: Cufaa./cufamuu. + complete: Toora Intarneetiin ala ni argama date_of_birth: Guyyaa dhalootaa. disable_dialog: Ishii tole jettu tuquun haala dhimma kanaa gara gufachiisuutti jijjiira. disable_dialog_title: Dhimma gufachiisuu/dadhabsiisuu. @@ -292,7 +310,7 @@ om: export: Gara alaatti erguu/ergaa. mark_for_offline: title: Sararaan alatti mallattoo kaa'aa. - text: "Dhugumatti yeroo sararaan ala taatanitti dhimmoottan kanneen fayyadamuuf mallattoo kaa'uu barbaadduu? " + text: 'Dhugumatti yeroo sararaan ala taatanitti dhimmoottan kanneen fayyadamuuf mallattoo kaa''uu barbaadduu? ' success: Dhimmotni sararaan alatti fayyadamuuf haala milkaa'aan mallattoon irra kaayame. filter_by: 3month_inactivity: Ji'oota 3f+ @@ -305,14 +323,14 @@ om: agency: Ejensii. approval_status: Haala mirkaneessummaa. approvals: - approved: " Mirkanaa'eera." + approved: ' Mirkanaa''eera.' pending: Kan murtii eeggachaa jiru/Akka turu taasisame. rejected: Fudhatama hinarganne. bia: Sakatta'insa fedhii daa'imaa ol'aanaa. by_date: Guyyaan/guyyaadhaan. case_open_date: Guyyaa banaa dhimmaa. case_plan: Karoora dhimmaa. - closed: " Cufaa." + closed: ' Cufaa.' closure: Cufamuu. current_location: Iddoo ammee. date: Guyyaa. @@ -322,21 +340,21 @@ om: enabled_disabled: Dandeessisameera//dadhabsiisameera. female: Dubartii. flag: Eerameera. - flag_label: "Eerameeraa?" + flag_label: Eerameeraa? gbv_closure: Cufiinsa miidhaa koornaayaa bu'ureeffatee. high: Ol'aanaa. low: Gadi aanaa. male: Dhiira. medium: Giddugaleessa. mobile: Mobaayila. - mobile_label: "Mobaayila irratti mallattoo kaayameeraa?" + mobile_label: Mobaayila irratti mallattoo kaayameeraa? my_cases: Dhimmoota kiyya. no_action: Tarkaanfiin/Gochi wayiituu hin jiru. no_activity: Sochiin/hojiin wayiituu hin jiru. open: Bani. other: Kan biraa. photo: Suuraa. - photo_label: "Suuraa qabaa?" + photo_label: Suuraa qabaa? protection_concerns: Sodaawwan eegumsaa. protection_status: Haala sadarkaa eegumsaa. record_state: Haala galmee. @@ -355,8 +373,8 @@ om: full_name: Maqaa guutuu. gbv_closure: Cufama dhimma Miidhaa Koornaayaa Bu'ureeffatee. hide_name: Maqaa dhoksuu. - hide_name_error: "Yeroo jijjiirraawwan keessan sanitti dogongorri uumameera. Maaloo irra deebi'aa yaalaa. " - id: "# eenyumeessaa." + hide_name_error: 'Yeroo jijjiirraawwan keessan sanitti dogongorri uumameera. Maaloo irra deebi''aa yaalaa. ' + id: '# eenyumeessaa.' label: Dhimmoota. my_filters: Calaltoota kiyya. name: Maqaa. @@ -374,13 +392,13 @@ om: photos: Suuraa. quick_view: tracing_message: 'Yaadachiisa:Nama mucaa kana barbaadu wajjiin sirnicha keessatti walsiminni jira.Yoo daa''imichi fedhii kan qabu ta''e tarkaanfii dabalataatiif hojjetaa hawaasaa galmee kanaa qunnamaa/dubbisaa.' - referral_done: "\"Hojjetameera'' kan jedhu tuquun hojiin dabarsuu dhimma kanaan walqabatan xumuramuu isaa agarsiisa. Al tokko ''Hojjetame'' kan jedhu yoo tuqte kana booda galmee kana argachuu hin dandeessu." + referral_done: '"Hojjetameera'''' kan jedhu tuquun hojiin dabarsuu dhimma kanaan walqabatan xumuramuu isaa agarsiisa. Al tokko ''''Hojjetame'''' kan jedhu yoo tuqte kana booda galmee kana argachuu hin dandeessu.' referral_done_success: Walitti kenninsi/dabarsi raawwatameera. referral_accepted_header: Walitti kenna fudhadhu. - referral_accepted: "Dhuguma keessanii?Ammaa hojii walitti kennaa kanaa wajjiin walitti dhufeenya qabu xumuruuf gaafatamummaa qabdu." + referral_accepted: Dhuguma keessanii?Ammaa hojii walitti kennaa kanaa wajjiin walitti dhufeenya qabu xumuruuf gaafatamummaa qabdu. referral_accepted_success: Walitti kenna fudhatama argate. - referral_rejected: "\"Dhiisi\"kan jedhu tuquun ammaan tana walitti kennaa kanaaf gaafatamummaa fudhachuuf qophii akka hintaane mul'isa. Maaloo sababaa walitti kennaa kana gataa jirtaniif seenaa ; takkashee yoo \"dhiisi/gati\" tuqtan achii booda galmee dhimma kanaa bira gahuu hin dandeessan." - referral_rejected_success: "Walitti kenna fudhatama dhabe.," + referral_rejected: '"Dhiisi"kan jedhu tuquun ammaan tana walitti kennaa kanaaf gaafatamummaa fudhachuuf qophii akka hintaane mul''isa. Maaloo sababaa walitti kennaa kana gataa jirtaniif seenaa ; takkashee yoo "dhiisi/gati" tuqtan achii booda galmee dhimma kanaa bira gahuu hin dandeessan.' + referral_rejected_success: Walitti kenna fudhatama dhabe., register_new_case: Dhimma haaraa. registration_date: Guyyaa galmee. rejected_success_action_plan: '%{approval_label}Hin mirkannoofne.' @@ -392,24 +410,24 @@ om: reopen_dialog: Ishii tole jettu tuquun haala dhimma kanaa akka banamuu taasisa. reopen_dialog_title: Dhimma irra deebiin bani. reopen_success: Dhimma haala milkaa'aan irra deebi'ee baname. - request_approval_failure: "Dogongorri uumameera. Maaloo gargaarsa argadhaa?" + request_approval_failure: Dogongorri uumameera. Maaloo gargaarsa argadhaa? request_approval_select: Hayyama gaafadhaa. - request_approval_success_action_plan: "Mirkanneessi gaafatameera %{approval_label}guca." - request_approval_success_assessment: "Mirkanneessi kan gaafatameef %{approval_label}guca." - request_approval_success_case_plan: "Mirkanneessi kan gaafatameef %{approval_label} guca." - request_approval_success_closure: "Mirkanneessi kan gaafatameef %{approval_label}guca." - request_approval_success_gbv_closure: "Mirkanneessi kan gaafatameef %{approval_label}guca." - request_approval_type_of_case_plan: " Gosa karoora dhimmaa mirkaneessuu." - request_approve_action_plan: "Karoora raawwii mirkaneessuu?" + request_approval_success_action_plan: Mirkanneessi gaafatameera %{approval_label}guca. + request_approval_success_assessment: Mirkanneessi kan gaafatameef %{approval_label}guca. + request_approval_success_case_plan: Mirkanneessi kan gaafatameef %{approval_label} guca. + request_approval_success_closure: Mirkanneessi kan gaafatameef %{approval_label}guca. + request_approval_success_gbv_closure: Mirkanneessi kan gaafatameef %{approval_label}guca. + request_approval_type_of_case_plan: ' Gosa karoora dhimmaa mirkaneessuu.' + request_approve_action_plan: Karoora raawwii mirkaneessuu? request_approve_bia: Sakatta'insa mirkaneessuu. - request_approve_case_plan: "Karoora dhimmaa mirkaneessuu?" - request_approve_closure: "Cufiinsa mirkaneessuu?" - request_approve_gbv_closure: "Cufiinsa miidhaa koornaayaa bu'ureeffatee mirkaneessuu?" - revoke_failure: " Haqiinsa irratti dogongorri uumameera %{transition_type}Maloo deeggarsa argadhaa." - revoke_message: "\"'Haqi\" kan jedhu tuquun bira gahiinsa dhimmaa fudhataan qabu%{transition_type} dhabamsiistu. " - revoke_success_message: "Dhimma %{case_id}%{transition_type} gara %{recipient_username}haqameera." + request_approve_case_plan: Karoora dhimmaa mirkaneessuu? + request_approve_closure: Cufiinsa mirkaneessuu? + request_approve_gbv_closure: Cufiinsa miidhaa koornaayaa bu'ureeffatee mirkaneessuu? + revoke_failure: ' Haqiinsa irratti dogongorri uumameera %{transition_type}Maloo deeggarsa argadhaa.' + revoke_message: '"''Haqi" kan jedhu tuquun bira gahiinsa dhimmaa fudhataan qabu%{transition_type} dhabamsiistu. ' + revoke_success_message: Dhimma %{case_id}%{transition_type} gara %{recipient_username}haqameera. save_filter: Kaayuu. - selected_all_records: "Dhimmoota gaafii kana waliin walsimatan%{total_records} hundaa filadhu.." + selected_all_records: Dhimmoota gaafii kana waliin walsimatan%{total_records} hundaa filadhu.. selected_records: 'Dhimma(dhimmoota) %{select_records} filatamaniiru.' sex: Saala/koornaayaa. show_case: 'Eenyummeessaa dhimma:%{short_id}' @@ -423,15 +441,15 @@ om: matched: Walsimaniiru./walitti firoomaniiru. fields: consent_for_tracing: - label: " Kaayoowwan barbaachaaf/hordoffiif odeeffannoo ifa gochuuf waligalteen /hayyamni argameera." - help_text: "Yoo dirreen kun \" lakkii\" ta'e,galmeen dhimma daa'imaa kanaa gaaffii barbaaduu gaafataa waliin bifa walfakkaatuun hin ilaalamu." + label: ' Kaayoowwan barbaachaaf/hordoffiif odeeffannoo ifa gochuuf waligalteen /hayyamni argameera.' + help_text: Yoo dirreen kun " lakkii" ta'e,galmeen dhimma daa'imaa kanaa gaaffii barbaaduu gaafataa waliin bifa walfakkaatuun hin ilaalamu. wishes_child_family_tracing: - label: "Daa'imni miseensoota maatii isaa faana bu'ee argachuu barbaadaa?" + label: Daa'imni miseensoota maatii isaa faana bu'ee argachuu barbaadaa? wishes_reunification: - label: "Daa'imni maatiin walitti deebi'ee makamuu barbaadaa?" + label: Daa'imni maatiin walitti deebi'ee makamuu barbaadaa? options: - yes_as_soon_as_possible: "Eeyyen,ariitiidhaan,haga danda'ameen." - yes_but_later: "Eeyyen,garuu boodarra.." + yes_as_soon_as_possible: Eeyyen,ariitiidhaan,haga danda'ameen. + yes_but_later: Eeyyen,garuu boodarra.. not_sure: Hin dhugoomne/hin mirkanoofne. 'no': 'Miti.' data_confidentiality_link: @@ -439,14 +457,15 @@ om: child_wishes_link: label: Fedhiiwwan daa'imaa ilaalaa. survivor_code: Koodii warra miidhaa irraa hafanii. - transfer_accepted: "\"Fudhadhu\"kan jedhu tuquun dhimma kanaaf gaafatamummaa fudhatteerta jechuudha;yoo isa fudhadhu jedhu al tokko tuqxan abbaa galmee sirnichaa taatu." - transfer_managed_user_accepted: "Yoo ' Fudhi' kan jedhu tuqxe %{transitioned_to}dhimma kanaaf gaafatamaa ta'a,erga al tokko ''Fudhi' tuqxee %{transitioned_to}sirncha keessatti abbaa galmeee ta'a." - transfer_managed_user_rejected: "'Hinfudhatin/gati' kan jedhu tuquun %{transitioned_to}taasistan yeroo kanatti dhimmicha kanaaf gaafatamummaa fudhachuuf qophii akka hintaane mul'isa. Maaloo sababa dhimma kana itti kuffistaniif galchaa.Al tokko 'hinfudhatin/didi'kan jedhu yoo tuqtan %{transitioned_to}taasiftan ammaan booda gara galmee dhimmaa kana gahuu hun danddeessan." - transfer_accepted_rejected: "Dhimma %{record_id}dabarsuu fudhatama hinarganne." + transfer_accepted: '"Fudhadhu"kan jedhu tuquun dhimma kanaaf gaafatamummaa fudhatteerta jechuudha;yoo isa fudhadhu jedhu al tokko tuqxan abbaa galmee sirnichaa taatu.' + transfer_managed_user_accepted: Yoo ' Fudhi' kan jedhu tuqxe %{transitioned_to}dhimma kanaaf gaafatamaa ta'a,erga al tokko ''Fudhi' tuqxee %{transitioned_to}sirncha keessatti abbaa galmeee ta'a. + transfer_managed_user_rejected: '''Hinfudhatin/gati'' kan jedhu tuquun %{transitioned_to}taasistan yeroo kanatti dhimmicha kanaaf gaafatamummaa fudhachuuf qophii akka hintaane mul''isa. Maaloo sababa dhimma kana itti kuffistaniif galchaa.Al tokko ''hinfudhatin/didi''kan jedhu yoo tuqtan %{transitioned_to}taasiftan ammaan booda gara galmee dhimmaa kana gahuu hun danddeessan.' + transfer_accepted_rejected: Dhimma %{record_id}dabarsuu fudhatama hinarganne. transfer_accepted_success: Dabarsi dhimmaa milkaa'inaan fudhatama argateera. transfer_reject_reason_label: Sababa fudhatama dhabeef. - transfer_rejected: "\"Dhiisi\"kan jedhu tuquun ammatti dhimma kanaaf gaafatamummaa fudhachuudhaaf qophii akka hintaane mul'isa. Maaloo sababaa dhimma kan itti kuffistaniif galchaa.Al-tokko \"dhiisi\"kan jedhu erga tuqtaniin booda gara galmee dhimma kana bira gahuu hindandeessan. " + transfer_rejected: '"Dhiisi"kan jedhu tuquun ammatti dhimma kanaaf gaafatamummaa fudhachuudhaaf qophii akka hintaane mul''isa. Maaloo sababaa dhimma kan itti kuffistaniif galchaa.Al-tokko "dhiisi"kan jedhu erga tuqtaniin booda gara galmee dhimma kana bira gahuu hindandeessan. ' view_name: Maqaa agarsiisi. + sort_by: Kan adda baase change_logs: filters: form: Guca. @@ -460,7 +479,7 @@ om: change: 'Irraa %{from_value}gara%{to_value}' updated_subform: 'Ammayyoomeera%{subform_name}"iiti galumsa guca xiqqaa #%{short_id}' update_subform: 'Ammayyoomeera%{subform_name}guca xiqqaa.' - from: "Irraa," + from: Irraa, to: Gara. children: selectable_date_options: @@ -471,11 +490,11 @@ om: date_of_creation: Guyyaa itti uumame. registration_date: Guyyaa galmee. configurations: - apply_label: "Dhuguma keetii?Yoo beeksiftan/iyyattan qindaa'inoonni naannawa kana keessa jiran sirnicha irratti hojirra oolu.Qindaayinoota amma jiran hundaa nidhabdu,akkasumas dursitanii qindaayinoota biraa keessa yoo kaayachuu baattan malee deebitanii argachuu hin dandeessan." + apply_label: Dhuguma keetii?Yoo beeksiftan/iyyattan qindaa'inoonni naannawa kana keessa jiran sirnicha irratti hojirra oolu.Qindaayinoota amma jiran hundaa nidhabdu,akkasumas dursitanii qindaayinoota biraa keessa yoo kaayachuu baattan malee deebitanii argachuu hin dandeessan. apply_label_bold: Jijjiiramoonni atoo fe'amaa jiranitti primeroon daqiiqaawwan xiqqoof fayyadamaaf hin argaman. version_mismatch_tooltip: Primeeroo varshinii isa ola'aanan waan hojjetameef Konfigreeshinii gochuu hin danda'amu. Kanaafuu amma saayitiin kun primeeroon haaraan fooyya'uutti maloo konfigreeshinii taasisuuf turi. send_header: Gara oomishaatti erguu. - send_text: "Ani sirriidha jettaa?Ergi isa jedhu yoo tuqtan qindaayina kana gara buufata oomishaatti ergitu.Bulchaan buufata kana irra jiru haga harkaan hojirra oolchutti qindaayinni kun oomisha irratti hojirra hin oolu." + send_text: Ani sirriidha jettaa?Ergi isa jedhu yoo tuqtan qindaayina kana gara buufata oomishaatti ergitu.Bulchaan buufata kana irra jiru haga harkaan hojirra oolchutti qindaayinni kun oomisha irratti hojirra hin oolu. attributes: created_by: Qaama uume. date_created: Guyyaa itti uumame. @@ -485,7 +504,7 @@ om: name: Maqaa. version: Hiika qindaayinaa. primero_version: Hiika Primeeroo. - delete_label: "Dhugumatti waan kana gochuu barbaadduu?Inni kun yeroo qindaayinootni kun uumamerraa jalqabee qindaayinoota jiran cufa bakka bu'a." + delete_label: Dhugumatti waan kana gochuu barbaadduu?Inni kun yeroo qindaayinootni kun uumamerraa jalqabee qindaayinoota jiran cufa bakka bu'a. explanation: '"Kaayi"kan jedhu tuquun qindaayina galmee amma jiru (Fknf.shooraawwan,ejensiiwwan,gucoota) yeroo kanatti galmee uumaa.Eega keessan booda jijjiiramoota kanneen gara pireemiiroo biraatti dhiibuu dandeessu.Gara fulduraatiif yoo ta''e jijjirammoota duubatti deebi''uu yoo taasiftan ammoo yeroo kanatti jijjiiramoota qindaayinaa taasiftan hundaa gara dura turanitti deebisuuf galmee qindaayinaa kana hojirra oolchuu nidandeessuu.' label: Qindaayinoota. label_new: Qindaayina haaraa. @@ -508,7 +527,7 @@ om: position: Sadarkaa. primero_version: Tolfama pirimeeroo/kan pirimeeroon hojjetame. support_forum: Ardaa marii deggarsaa/waltajjii deggarsaa. - system_version: " sirna hiikaa." + system_version: ' sirna hiikaa.' info_label: Odeeffannoo qunnamtii. updated: Qunnamtiin odeeffannoo haala milkaa'aan ammayyoomeera. code_of_conduct: @@ -521,7 +540,7 @@ om: updated: Koodiin amala milkaa'inaan haaromsameera. dashboard: activity: Hojii./sochii. - admin_only: "Fayyadama irratti jijjiiramoota gochuudhaaf %{links} irratti tuqaa." + admin_only: Fayyadama irratti jijjiiramoota gochuudhaaf %{links} irratti tuqaa. all_cases: Dhimmoota hunda. all_services_implemented: Tajaajiloota hunda hojirra oolan. and: 'Fi.' @@ -575,46 +594,13 @@ om: closed_last_week: Cufameera (torbee darbe) closed_this_week: Cufameera (torbee kana) comprehensive_need_intervention: Deebii hundagaleessa. - count_new_bia_approvals: - one: '' - other: '' - count_new_case_plan_approvals: - one: '' - other: '' - count_new_closure_approvals: - one: '' - other: '' - count_pending_approval_total: - one: '' - other: '' - count_pending_transfers: - one: '' - other: '' - count_records_new: - one: '' - other: '' count_records_total: one: 'You have %{stat} total case ' other: 'Dhimmoota waliigalaa %{stat}qabda. ' - count_referrals_new: - one: '' - other: '' count_referrals_total: one: 'You have %{stat} total referral ' - other: 'Dabarsa waliigalaa%{stat} qabda.' - count_rejected_approval_total: - one: '' - other: '' - count_rejected_transfers: - one: '' - other: '' - count_risk_level_new: - one: '' - other: '' - count_risk_level_total: - one: '' - other: '' - count_waiting_for_acceptance_transfers: "Dabarsi eeyyama kee eegu %{stat}qabda." + other: Dabarsa waliigalaa%{stat} qabda. + count_waiting_for_acceptance_transfers: Dabarsi eeyyama kee eegu %{stat}qabda. current_owner: Abbaa ammee. dash_case_incident_overview: Dhimmoota kiyya. dash_group_overview: Dhimmoota garee kiyyaa. @@ -624,6 +610,9 @@ om: dash_shared_with_my_team_overview: Garee kiyya waliin qooddateera (Ilaalcha waliigalaa) dash_shared_with_others: Warra biraa waliin qooddatameera. dash_national_admin_summary: Goolaba bulchaa/gaggeessaa. + dash_violations_category_verification_status: Lakkoofsa waliigalaa taatewwan haala mirkaneessaa tokko tokkoon + dash_violations_category_region: 'Lakkoofsa waliigalaa Taateewwan mirkanaa’an naannoon ' + dash_perpetrator_armed_force_group_party_names: Lakkoofsa waliigalaa taateewwan nama yakka raawwate tokkoon date: Guyyaa. date_of_incident: Guyyaa taateen itti uumame. date_of_interview: Guyyaa gaaffii fi deebii/Af-gaaffii. @@ -649,15 +638,6 @@ om: link_see_all: Hunda isaaniituu ilaalaa. low_level: Gadi aanaa. low_risk: Dursa gadi aanaa kan itti kennamu. - manager_count_closed_total: - one: '' - other: '' - manager_count_open_total: - one: '' - other: '' - manager_transfers_totals: - one: '' - other: '' match_result: Bu'aawwan walsiman. medium_level: Giddugaleessa. medium_risk: Dursi giddugaleessaa kan itti kennaman. @@ -743,13 +723,7 @@ om: with_incidents: Taateewwan wajjiin/duukaa. with_new_incidents: Taateewwan haaraa wajjiin. without_incidents: Taateewwaniin ala. - worker_count_referrals_total: - one: '' - other: '' - worker_count_total: - one: '' - other: '' - workflow: "Yaa'insa hojii," + workflow: Yaa'insa hojii, workflow_team: Yaa'insa hojii-Dhimmoota gareewwanii. you_have: 'Qabda.' disabled: @@ -776,25 +750,50 @@ om: assign_html: '%{user}gosa galmee %{record_type}kana siif kennee jira%{record_id}' transfer_request_html: 'Fayyadamaa primeeroo1 1%(Fayyadamaa)karaa 2%(ajensii) abbummaa kana dabarsuuf gaafatamaa jira 3%(gosa-galmee) galmee2 4%(Gamlee-LK) 2 kanaaf tajaajila bulchiinsaa naannoo isaanitti 3%(gosa-galmee) ni kennu. Yoo dabarsi siin fudhatama argate maloo 3%(gosa-galmee) irratti cuqaassi 3%(gosa-galmee) banuuf LG emailii kana waliin wal-qabate' transfer_request_notes_html: ' Tokkon tokkoon nama gaafii gaafatan irraa yaadannoo fudhuu:1(gaafii-dabarsuu-yaadannoo)' + webpush_notification: + action_label: Karaa dhimmaa deemi + approval_request: + title: Gaafii Mirkanneeffaman + body: '%{type}Dhimmi garee keessan keessa jiru tokko gaaffii raggaasisuu kan hin xumuramne qaba' + approval_response: + title: Deebii Raggaasisuu + body: Dhimmi keessan tokko deebii mirkaneessaa argateera. + assign: + title: Ramaddii Haaraa + body: Ramaddii Dhimma haaraa argatteetti. + referral: + title: Rifaralaa Haaraa + body: Rifarala Dhimma haaraa argatteetti. + transfer: + title: Dabarsa haaraa + body: Dabarsa Dhimma Haaraa Fudhachu + alert_case: + title: Dhimmi Haaromfame + body: "dhimma keessan tokko irratti haaromsi ta'eera%{type}" + transfer_request: + title: Gaafii Dabarsaa + body: Gaaffii Dabarsa Dhimmaa haaraa siif dhiyaateera encrypt: export_type: Gosa/akaakuu gara alaatti erguu. file_name: Faayila mataa keessanii uumaa(filannoo) password_extra_info: Iggitaan yoo xiqqaate arfii 8 ta'utu irra jiraata.Iggitaan kun faayila gara alaatti ergamu wajjiin walqabata akkasumas fulduraaf namni faayila kana banu eenyuyyuu iggita kana galchutu irra jiraata. password_label: Maaloo jecha iggitaa faayila keessanii icciteessu galchaa. error_message: - address_fields: "Dirree %{fields}gucoota%{forms}irratti agarsiissu qabda" - address_form_fields: "Guca kana irratti dirree%{fields}agarsiisuu qabda," + address_fields: Dirree %{fields}gucoota%{forms}irratti agarsiissu qabda + address_form_fields: Guca kana irratti dirree%{fields}agarsiisuu qabda, address_subform_fields: '%{subform}dirree bu''aa hin qabne qaba%{fields}' + error_401: Keessaa baatee jirta. Mee ammas seena. + error_something_went_wrong: Waan tokkotu dogoggora ta'e. error_page: not_authorized: - code: 403 server_error: Fuula kana argachuuf mirga /aangoo hinqabdan. title: Hin hayyamamne/Seera qabeessaa miti. not_found: - code: 404 - contact_admin: "Ani kan asan jiru dogongoraan jettanii kan amantan yoo ta'e,maaloo bulchaa keessan dubbisaa." - something_went_wrong: "Dhiifama,dogoggorri wayii uumameera!" + contact_admin: Ani kan asan jiru dogongoraan jettanii kan amantan yoo ta'e,maaloo bulchaa keessan dubbisaa. + something_went_wrong: Dhiifama,dogoggorri wayii uumameera! errors: + api: + internal_server: Dogoggora Sarvarii error_loading: Galmee/galmeewwan dogongoraa fe'uu. models: agency: @@ -807,14 +806,14 @@ om: date_of_birth: Maaloo galmee dhimmaa kanaatiif guyyaa dhalootaa sirrii ta'e seensisaa. export_configuration: opt_out_field_does_not_exist: Dirreen murtaa'aan filatanii ittiin bahanii galmee irra hin jiru. - record_type: "Gosa galmee sirrii hin taane. Daa'ima, gaaffii barbaachaa ykn taatee ta'utu irra jiraata." + record_type: Gosa galmee sirrii hin taane. Daa'ima, gaaffii barbaachaa ykn taatee ta'utu irra jiraata. field: translated_options_do_not_match: Filannoowwan dirree irratti hiikaman enyummeessaawwan walfakkaatan qabachutu irraa eegama. location: admin_level_present: Duwwaa ta'uun irra hin jiraatu. code_present: Duwwaa ta'uun irra hinjiraatu. name_present: Duwwaa ta'uun irra hinjiraatu. - unique_location_code: "Iddoon koodii naannoo san wajjiin jiru durattis jira,maaloo koodii iddoo addaddaa galchaa." + unique_location_code: Iddoon koodii naannoo san wajjiin jiru durattis jira,maaloo koodii iddoo addaddaa galchaa. lookup: being_used: Barbaachi kun faayidaa irra oolaa jira kanaafuu haqamuu hin danda'u. name_present: Maqaan duwwaa ta'uu hin qabu. @@ -823,7 +822,7 @@ om: associated_record_types: Yoo xiqqaate akaakuun galmee tokko muraa kana wajjiin walsimuu qaba. form_section_ids: Yoo xiqqaate unki tokko mura kana wajjiin walsimuu qaba. name_present: Maqaan duwwaa ta'uun irra hin jiraatu. - unique_name: "Murri maqaa saniin walqabate durumaanuu jira,maaloo maqaa addaa galchaa." + unique_name: Murri maqaa saniin walqabate durumaanuu jira,maaloo maqaa addaa galchaa. report: module_presence: Muraan duwwaa ta'uu hinqabu. module_syntax: Muraawwan gabaasaa hundumtuu dursanii jiraachuu qabu. @@ -833,12 +832,17 @@ om: user: email: "Maaloo iimeelii gataa'aa galchi.(Fknf:'maqaa@fknf.org)" password_mismatch: Dirreewwan jecha iggitaa jecha iggitaa walfakkaatan hinqaban. - password_length: " Iggitaan yoo xiqqaate arfiiwwan %{min}}ta'uu qaba." - email_uniqueness: "Fayyadamaan teessoo iimeelii kanaa qabu durumaanuu jira,maaloo kan adda ta'e galchaa." + password_length: ' Iggitaan yoo xiqqaate arfiiwwan %{min}}ta''uu qaba.' + email_uniqueness: Fayyadamaan teessoo iimeelii kanaa qabu durumaanuu jira,maaloo kan adda ta'e galchaa. code_of_conduct: title_present: Mata dureen duwwaa taa'uu hinqabu. content_present: Qabiyyeen duwwaa ta'uu hinqabu. created_by_present: Inni uumame duwwaa ta'uu hinqabu. + webpush_subscription: + notification_url_present: Yaadachiisni_ url duwwaa ta'uu hin qabu + notification_url_format: Yaadachiisni-url unka URL dirqama qabaachuu qaba + auth_present: Auth duwwaa ta'uu hin qabu + p256dh_present: P2566dh duwwaa ta'uu hin qabu not_found: Galmeen/galmeewwan wayiituu hinargamne. try_again: Irra deebi'ii yaali. exports: @@ -854,9 +858,9 @@ om: all: Maamilaa. custom_exports: all: Maamilaa. - choose_fields: "Gucaaf dirreewwan nama dhuunfaa filachuu barbaadduu?" + choose_fields: Gucaaf dirreewwan nama dhuunfaa filachuu barbaadduu? empty_fields_forms: Gara alatti erguuf maaloo gucaawwan ykn dirreewwan muraasa filadhaa. - empty_format: " Maaloo dhangii gara alaa ittiin ergan filadhaa." + empty_format: ' Maaloo dhangii gara alaa ittiin ergan filadhaa.' empty_module: Maaloo muraa gara alaa ergaman filadhaa. empty_password: Maaloo jecha iggitaa faayila keessan icciteessuu danda'u galchaa. field_label: Dirree. @@ -871,10 +875,10 @@ om: header: Irraantoo/mataa gubbaa. custom_header: Irraantoo maamilaa. signatures: Mallattoodhaaf sarara dabalaa.. - include_implementation_logos: "Asxaawwan hojirra oolmaa raawwii dabalaa?" + include_implementation_logos: Asxaawwan hojirra oolmaa raawwii dabalaa? include_implementation_logos_help_text: Inni kun asxaawwan baafata naanna'iinsaa fi fuula seensaa irratti mul'atan ofkeessatti qabata. - include_agency_logo: "Asxaa ejensichaa dabalaa?" - include_other_logos: "Asxaawwan biraa dabalaa?" + include_agency_logo: Asxaa ejensichaa dabalaa? + include_other_logos: Asxaawwan biraa dabalaa? duplicate_id_csv: all: Eenyumeessaa baay'isaman. female_abbreviation: Faa. @@ -927,7 +931,6 @@ om: form: Unkaawwan Piriimeeroo. status: Haala/sadarkaa. notes: Yaadannoo. - go_to_exports: Buusuudhaaf gara fuula gara alaatti erguutti deemaa. incident_recorder_xls: all: Maashinii sagalee waraabduu taatee. @@ -945,10 +948,10 @@ om: mrm_violation_xls: all: Jeequmsaawwan Mala/tooftaa/hordoffii fi gabaasaa one: Miidhaa MRM - selected: " Mala/tooftaa/hordoffii fi gabaasaaJeequmsaawwan filataman." + selected: ' Mala/tooftaa/hordoffii fi gabaasaaJeequmsaawwan filataman.' no_records: Galmeewwan wayiituu hinjiran. pdf: - all: "pII Dii Effii {Dhokataa miti}" + all: pII Dii Effii {Dhokataa miti} one: Pii Dii Effi selected: PiiDiiEffiif filatameera. pdf_exports: @@ -968,9 +971,9 @@ om: one: Dhaabaa suuraa. reunited: Irra deebiin walitti deebi'an/walargan. selected: Dhaabaa suuraatiif filatameera. - success_message: "iddoo suuraa uumuu%{file_name}dhimmootni suura hin qabne keessatti hin qabataman" + success_message: iddoo suuraa uumuu%{file_name}dhimmootni suura hin qabne keessatti hin qabataman printed: 'Maxxane:%{date}' - queueing: "Faayila ala baasu uumuu%{file_name}" + queueing: Faayila ala baasu uumuu%{file_name} selected_xls: all: Caalmaa. one: Caalmaa. @@ -1047,7 +1050,7 @@ om: add_new_field: Dirree haaraa uumuu. add_existing_field: Dirree jiru itti dabalaa. add_field: Dirree itti dabalaa. - add_field_type: "Ida'uu%{file_type}" + add_field_type: Ida'uu%{file_type} audio: current: Sagalee dhageettii ammee. audio_upload_box: Fe'umsa sagalee dhageettii. @@ -1073,29 +1076,29 @@ om: date_range_field: Bal'ina naannoo guyyaa. date_time: Guyyaa-yeroo. db_name: Maqaa kuusa galmee/odeeffannoo. - default: "Durtii?" + default: Durtii? default_date_validation: Mirkaneessa guyyaa durtii. - default_to_current_date: "Durtiiwwan guyyaa ammaatiif ?" - default_to_current_datetime: "Guyyaa fi sa'aatii ammatiif durtiidhaa?" + default_to_current_date: Durtiiwwan guyyaa ammaatiif ? + default_to_current_datetime: Guyyaa fi sa'aatii ammatiif durtiidhaa? default_value: Sona durtii. - deleted: "Dirreen%{display_name}haqamee jira." + deleted: Dirreen%{display_name}haqamee jira. detail: Tarreeffama. disabled: Qaama miidhamaa. display_name: Maqaa ittiin yaamamu. document: comments: Yaada. - current: "Inni kun galmee ammeetii?" + current: Inni kun galmee ammeetii? date: Guyyaa galmee. name: Maqaa galmee. - is_current: "Inni kun ragaa/galmqee ammeetii?" + is_current: Inni kun ragaa/galmqee ammeetii? document_upload_box: Galmee fe'aman. edit_label: Dirree gulaali. - enabled: "Dammaqeeraa/danda'eeraa?" + enabled: Dammaqeeraa/danda'eeraa? enabled_label: Danda'eera/dammaqeera. english_text: Barruu Ingliffaa. field_name: Maqaa dirree. field_type: Akaakuu dirree. - attachment_too_large: Faayilli mb10 caalaa guddachuun irra hinjiraatu. + attachment_too_large: Faayilli 20mb ol ta'uu hin qabu file_upload_box: add_document_label: Galmee dabali. add_new_document_button_text: Galmee biraa dabali. @@ -1124,7 +1127,7 @@ om: not_future_date: Guyya egereetii miti. number_not_valid: Maaloo ragaa/deetaa lakkofsaa galchi. numeric_field: Dirree lakkofsaa. - on_collapsed_subform: "Guca xiqqaa fashalaa'e irrattii?" + on_collapsed_subform: Guca xiqqaa fashalaa'e irrattii? option_strings_add_option: Filannoo dabalaa. option_strings_source: Barbaachaawwan. option_strings_text: Filannowwan. @@ -1138,7 +1141,7 @@ om: predifined_lookups: Barbaacha dursa mutaa'etti fayyadamaa. radio_button: Qabduu/qulfii raadiyoonii. remove: Dhabamsiisi. - remove_attachment_confirmation: "Dhugumatti miltoo kana dhabamsiisuu barbaaddaa?" + remove_attachment_confirmation: Dhugumatti miltoo kana dhabamsiisuu barbaaddaa? required: Barbaachisaadha.. required_field: '%{field}ni barbaachisa' search_existing: Dirreewwan jiran barbaadaa. @@ -1147,18 +1150,28 @@ om: select_multiple: Wanta ilaallatu hunda filadhaa. select_single: (filadhaa...) separator: Foo'aa/adda baasaa. - show: "Mul'isi/Agarsiisi?" + show: Mul'isi/Agarsiisi? show_on: Irratti agarsiisi. show_on_minify_form: Guca gabaabaa. + skip_logic: + name: Loojikii Darbuu? + record_section: + title: ' Galmeesse kutaa kanaa mul''achuu qaba' + buttons: + add: Haala galmee itti dabali + subform_section: + title: ' Unki xiqqaa kutaa kanaa mul''achuu qaba' + buttons: + add: Haala unka xiqqaa itti dabali. subform: Guca xiqqaa. subform_group_by: Qaama garee uume. - subform_remove_message: "Dhugumatti Guca xiqqaa kana dhabamsiisuu barbaaddaa?" + subform_remove_message: Dhugumatti Guca xiqqaa kana dhabamsiisuu barbaaddaa? subform_section: description: Ibsa unka/guca xiqqaa. name: Mataduree Guca xiqqaa. - starts_with_one_entry: "Seensa guca xiqqaa tokkootiin eegalaa?" + starts_with_one_entry: Seensa guca xiqqaa tokkootiin eegalaa? subform_append_only: Walfakkeessa mobaayila irratti filatame. - subform_prevent_item_removal: "Seensi karaa guca xiqqaa dhabamsiisuu ni ittisaa?" + subform_prevent_item_removal: Seensi karaa guca xiqqaa dhabamsiisuu ni ittisaa? subform_sort_by: Qaama tartiiba isaa tarreesse. successfully_added: Dirreen haala milkaa'aan dabalameera. tally_field: Dirree safartuu. @@ -1181,6 +1194,10 @@ om: less: Xiqqaa. more: Caalaattti/dabalata. save_filters: Ol'kaayi/kuusi. + categories: + violations: Miidhaalee + incidents: Taatewwan/balaa + individual_victims: Miidhaamtoota Dhuunfaa flags: add_flag_tab: Alaabaa/mallattoo haaraa dabalaa. date: 'Guyyaa.' @@ -1248,17 +1265,19 @@ om: violation: Miidhaawwan/seera cabsuu. registry_details: Tarreeffamoota galmeessaa. registry_record: Galmee itti galmaa'an. + family_record: Galmee Maatii + family: Galmee Maatii required_field: '%{field}dirree barbaachissuudha' select_label: Filadhaa. settings: Qindaayinoota. show_on: Irratti mul'isi. subform_need_to_be_added: Itti dabaluu barbaachisa. subform_need_to_be_added_single: Inni kun itti dabalamuu barbaachisa. - subform_not_found: "%{subform_name}hin argamne" + subform_not_found: '%{subform_name}hin argamne' title: Mata duree gucaa. translations: edit: Hiikkaawwan gulaali. - edit_form_group: " Barbaacha garee guca gulaali." + edit_form_group: ' Barbaacha garee guca gulaali.' manage: Hiikaawwan bulchuu. no_changes_message: jijjiirama hiikaa wamaatuu hintaasisne.. note: 'Yaadannoo.' @@ -1268,6 +1287,26 @@ om: type_label: Akaakuu/gosa. visibility: Mul'atina. web_app: Iyyata saphaphuu. + skip_logic: + name: Loojikii Darbuu? + section: + title: Yoo barbaachisu unki kun mul'achuu qaba + buttons: + add: Haala dabali + conditions: + add: Haala Dabali + update: Haala foyyeessi + field_name: Maqaa Dirree + condition: Haala + empty: Haalotni dabalaman hin jiran. + type: Gosa + types: + and: + display_text: Haala kana dabali + name: fi + or: + display_text: ykn haala kana + name: YKN home: ar: Qooqa/Afaan Arabaa. ar-IQ: Qooqa/Afaan Arabaa(biyya Iraaq) @@ -1278,11 +1317,13 @@ om: current_time_zone: Argamiinsa/godina yeroo ammee. dashboard: Daashboordii. en: Ingliffa. - es: " Isphaanyool." - es-GT: Ispaanool(Guwaatmaalaa) + es: ' Isphaanyool.' + es-GT: Espaanola + es-ES: Espaanola fr: Afaan/qooqa Firaansi + hu: Magyar id: Bahaasaa. - km: "-" + km: '-' ku: Qooqa/Afaan Kurdii. ku-IQ: Kurdi. fa-AF: Qooqa/afaan Faaris(Iran) @@ -1290,21 +1331,29 @@ om: sw-KE: Qooqa/Afaan Kiisiwaahiilii (biyya Keenyaa) sw-TZ: Qooqa/Afaan Kiisiwaahiilii(biyya Tanzaaniyaa) ne: Hindii. - label: "Mana," + om: Afan Oromoo + am-ET: Afaan Amaaraa(Itiyoophiyaa) + tr: Turkii + label: Mana, language: Qooqa/Afaan. manage_system_users: Fayyadamtoota walsimsiisaa tajaajilaa bulchaa. - my: "-" + my: '-' + pl: Poliskii pt: Qooqa/Afaan Poortugiizi. pt-BR: Qooqa/Afaan Poortugiizi ( Biraaziil) records_need_attention: Galmeewwan xiyyeeffannoo barbaadan. + ro: Romanaa ru: Greece. + sk: Slovenkina so: Qooqa/Afaan Soomaalii. - th: "-" + th: '-' + uk: Українська users: Fayyadamtoota bulchuu. view_records: Galmeewwan ilaalaa. welcome: Baga gara Pirimeerootti nagaan dhuftan. zh: Kan Chaayinaa. incident: + code: Koodii taatee associated_case: "Dhimma walqbsiifama qaban." messages: creation_success: Galmeen taatee haala milkaa'aan uumameera. @@ -1313,6 +1362,7 @@ om: update_success: 'Balaan 1%(LG-Galmee) Milkaa''inaan foyya''ee jira.' update_success_queue: 'Balaan %{record_id}seen-duubee keessatti milka''iinaan foyya''ee jira.' violation: + associated_violations: "Sarbamiinsa Waliin Walqabate:" update_and_return: 'Fooyyeessuun karaa %{association}deebi''i' save_and_return: 'Ida''uun karaa%{association}deebi''i' pending: Mirkaneessa eeggachaa jira. @@ -1321,9 +1371,11 @@ om: killing: Ajjeechaa daa'immanii. maiming: Dararama daa'immanii. recruitment: Daa'imman qacaruu fi/ykn itti fayyadamuu. - sexual_violence: Dirqisiisanii gudeeduu fi /ykn miidhaawwan saal-qunnamtii bifa biraatiin raawwataman. + sexual_violence: Guddeedii fi Miidhaalee gosa biroo abduction: Butii. attack_on: Miidhaalee mana barnootaa(manneen barnootaa) fi ykn hospitaala(hospitaaloota)irratti raawwataman. + attack_on_hospitals: 'Haleellaa hospitaala(wwan) irratti raawwatame ' + attack_on_schools: 'Haleellaa manneen (wwan) irratti raawwatame ' military_use: Itti fayyadama loltummaa mana barumsaa(manneen barnootaa) fi ykn hospitaalaa(hospitaalootaa) keessattii. denial_humanitarian_access: Daa'imman dhiyeessii deggarsa namummaa dhorkachuu. incidents: @@ -1333,7 +1385,8 @@ om: enable_dialog: Ok tuquun haala taatee kanaa gara dandeessisuutti jijjiira. enable_dialog_title: Taatee danda'aman. enable_success: Taateewwan haala milkaa'aan dandeessisaman. - id: "# eenyumeessaa." + id: '# eenyumeessaa.' + complete: Toora Intarneetaa ala argama date_of_interview: Guyyaa Af-gaaffii/Gaaffii fi deebii. date_of_incident: Guyyaa taateen itti uumame. incident_location: Bakka/iddoo taatee. @@ -1341,28 +1394,74 @@ om: export: Gaara alaatti erguu. label: Taateewwan. filter_by: + filter_category: Calallii gosaan boys: Ijjoollee/ilma dhiiraa. by_date: Guyyyaan. children: Daa'imman. girls: Shamarran/intala dubraa. incident_location: Bakka/iddoo taatee. + status: Sadarkaa unaccompanied_separated_status: Haala/sadarkaa Eegumsaa. unknown: Kan hin beekamin. verification_status: Haala mirkaneessaa. violence_type: Gosa/akaakuu jequmsaa. - armed_force_group_name: Maqaa garee humna hidhataa. + armed_force_group_party_name: Humna hidhate, garee, ykn qaama biroo armed_force_group_type: Akaakuu garee humna hidhataa. + violations: Miidhaalee + individual_violations: Miidhaalee Dhunfaa + individual_age: Umrii Dhunfaa + individual_sex: Korniyaa Dhunfaa + victim_deprived_liberty_security_reasons: Bilisummaa irraa mulqame + reasons_deprivation_liberty: Sababoonni bilisummaa mulqamuu maal fa’a? + victim_facilty_victims_held: Maaloo bakka miidhamtoonni (miidhamtoonni) itti hidhamaa turan/kan itti hidhaman filadhaa + torture_punishment_while_deprivated_liberty: Daa’imni bilisummaan osoo mulqamee jiruu dararama ykn ilaalcha ykn adabbii gara jabeessa, namummaa hin qabne ykn salphina biroo irra ga’eeraa/turaniiru? + verified_ghn_reported: GHN taatee kun keessatti hammatame ibsi + weapon_type: 'Gosa meeshaa waraanaa /mala itti fayyadamnu' + facility_impact: 'Gosaa fi bal’ina dhiibbaa qaamaa' + facility_attack_type: 'Gosa sarbama seeraa fayyaa- ykn barnootaan walqabatee' + child_role: 'Daa’imni humna waraanaa/garee keessatti gahee akkamii taphate?' + abduction_purpose_single: 'Kaayyoo buttii' + military_use_type: 'Gosa itti fayyadama waraanaa' + types_of_aid_disrupted_denial: 'Gosa gargaarsa/tajaajila dhorkame.' + late_verified_violations: Sarbama seeraa yeroon booda mirkanaa’e + perpetrator_category: Gosa Yakkamaa + record_owner: Abbaa Galmee register_new_incident: Taatee haaraa. selectable_date_options: date_of_first_report: GuyyaaAf-gaaffii/ gaaffii fi deebii. + mrm_date_of_first_report: Guyyaa gabaasa jalqabaa miseensa CTFMR dhiyyaate + ctfmr_verified_date: Guyyaa Murtii Mirkaneessaa CTFMR incident_date_derived: Guyyaa taatee. selected_records: '%{select_records}balaa filataman' selected_all_records: 'Balaa/taatee gaafilee kanaan firooman %{total_records} hundaa filli' + summary_mrm: + label: Cuunfaa Taatee + fields: + children_multiple_violation: + label: Daa'imman sarbama seeraa dachaadhaan miidhaman + summary_of_incident: + label: Cuunfaa Taatee + incident_total_tally: + label: Baay'ina miidhamtootaa + boys: Daa'ima Dhiiraa + girls: Daa'ima Dubaraa + unknown: Hin Beekamu + incident_date: + label: Guyyaa taatee + incident_location: + label: Iddoo Taatee + incident_description: + label: Lakkoofsa Taateewwanii + incident_update: + label: Haaromsa Taatee survivor_code: Koodii baraaramtootaa./warra miidharraa hafanii show_incident: 'ID taatee/balaa%{short_id}' social_worker: Hojjetaa hawaasaa. + violation_type: Gosa Miidhaa violence_type: Gosa/akaakuu jeequmsaa. type_violence: Akaakuu/gosa miidhaa/jeequmsaa. + violation_summary: Cuunfaa + sort_by: Nama adda baase key_performance_indicators: label: "Pulse/KPIs" case_assessment: "Sakatta'insa dhimmaa." @@ -1396,16 +1495,18 @@ om: number_of_cases: title: "1.Lakkofsa dhimmottan galmaa'anii." reporting_site: "Buufata gabaasni itti taasisamu." - helptext: | + helptext: "Agarsiiftuu kun ji’a ji’aan iddoo gabaasaa tokkootti dhimmootni haaraa meeqa akka banamu lakkaa’a. \nIddoo gabaasaa jechuun bakka dhaabbanni fayyadamtootaa tajaajila itti kennuu fi bakka dhimmichi qaama tajaajila kennuuf itti gabaafamu jedhamee hubatama.\n" number_of_incidents: title: "2.Baay'ina taateewwan galmaa'anii." reporting_site: "Buufata gabaasni itti dhiyaatuu. " helptext: | + Agarsiiftuu kun lakkoofsa balaa/miidhaa  haaraan  ji’a ji’aan bakka  gabaasaa tokkootti  /per reporting site/ banaman lakkaa’a. Iddoon  gabaasaa bakka Dhaabbanni fayyadamtootaa tajaajila itti kennuu fibakka taateen sun tajaajila  akka kennuuf itti gabaafame jedhamee hubatama. reporting_delay: title: "3.Turiinsa gabaasuu." delay: "Turiinsa." total_incidents: "Waliigala taateewwanii." helptext: | + Agarsiiftuun  kun guyyoota  yeroonamoonni miidhaa irraa dandamatan GBVn( miidhaan koorniyaa  bu’uureffate) irra gahee /mudatee  fi  yeroo namoonni  kun dhimmicha  jalqabaaf   qaama  tajaajila kennuuf gabaase gidduu jiran lakka’uun  gosa isaatiin ramada. Kunis yeroo taateen sun jalaqaba  dhaabbata tajaajila kennuuf  itti gaabafame irratti hundaa’uun kan shallagamu ta’a.miidhaan sun yeroo jalqabaaf dhaabbata tajaajila kennuuf  yoom akka gabaafame irratti hundaa’uun shallagama.Daataan kun dheerina yeroo adda addaa (guyyaa 0-3; guyyaa 4-5; guyyaa 6-14; guyyaa 15-30; Ji'a1 ol; Ji'a 3 ol) irratti hundaa'uun ramadama. service_access_delay: title: "Bira gahinsa tajaajilaa harkifatan." delay: "Turiinsa." @@ -1415,19 +1516,26 @@ om: completed: "Xumurameera." completed_supervisor_approved: "Xumurameera akkasumas to'ataan mirkanaa'eera." helptext: | + Agarsiiftuun  kun hanga/baayina  dhimmoota adeemsa irra jiran  kan unka madaallii guutame shallaga. Sakatta’nsi  tokko  xumurame ykn guutuudha kan jennu  wantootni / dhimmoonni  foormii sakatta’insaa irra jiran hundi yoo guutame qofa. completed_case_safety_plans: title: "5.Karoorawwan nageenyummaa dhimmaa xumuraman." completed: "Karoora nageenyummaa dhimmaa xumurame." helptext: | + Agarsiiftuun kun hanga /baay’ina dhimmoota adeemsa irra jiran  kanneen karoorri nageenyaa barbaachisaa  ta’e  yaada keessa galee  fi xumurame shallaga (fkn miidhaa  namoota  walitti dhiyeenya qabaniin dhaqqabu, balaa of ajjeesuu/ajjeechaa, eegumsa daa’immanii). + Karoorri nageenyaa  xumurame kan jennu  dhimmoonni akka dirqamaatti  unka Karoora Nageenyaa keessa jiran guutamatti   yeroo xumuramedha. completed_case_action_plans: title: "6.Karoorawwan raawwii dhimmaa xumuraman." completed: "Karoora raawwii dhimmaa xumurame." label: "Karoora raawwii dhimmaa xumurame." helptext: | + Agarsiiftuun  kun hanga/baay’ina  dhimmoota adeemsa keessa galan  keessaa kan karoorri raawwoo dhimmichaa   xumurame shallaga. Karoorri hojii dhimma tokkoo xumurame kan jennu yoo wantootni  unka karoora hojii  sana keessatti akka dirqamaatti taa’ee  jiru guutamee yoo xumurame qofaadha. completed_supervisor_approved_case_action_plans: title: "7.Karoorawwan raawwii dhimmaa to'ataan mirkana'an." completed_and_approved: "Karoorawwan raawwii dhimmaa xumuramanii to'ataan mirkanaa'an." - helptext: | + helptext: |+ + Agarsiiftuun kun hanga/ pirooppoorshinii dhimmoota adeemsa keessa jiran  kanneen karoorri  hojii isaanii xumuramee fi  gaggeessaa hojichaatiin shallaga. Karoorri hojii dhimmaa akka xumurameetti kan ilaalamu yeroo qabiyyeen  unka Karoora Hojii  sana keessa jiru guutamedha. Karoorri dhimma tokkoo  akkamirkanaa’etti kan ilaalamu yeroo hojjetaan dhimmichaa  karoorichi akka mirkanaa’u  gaaffii dhiyeessuu fi  fi supparvaayizarri/ gaggeessaan karoora dhimmichaa waltajjii irratti raggaasisudha. + + services_provided: title: "8.Tajaajiloota kennaman." service: "Tajaajila." @@ -1436,38 +1544,48 @@ om: female: "Dubartii." 0-11: "0-11" 12-17: "12-17" - ">18": "18 tii ol'" + '>18': "18 tii ol'" disability: "Qaama miidhamaa." no_disability: "Miidhamni qaamaa hinjiru." - helptext: | + helptext: |+ + Agarsiiftuun kun gosa tajaajila namoota miidhaa irraa dandamataniif  adeemsa bulchiinsa dhimmaa keessatti  kennamu lakkaa’a. Tajaajila kenname jechuun tajaajila dhaabbata tajaajilamtootaatiin mana keessatti kennamu jechuu keenya malee tajaajila gara birootti ykn rifeerii ta’e/darbe kennamu jechuu keenya miti. + average_referrals: title: "9.Walitti kenninsoota giddu galaan." label: "Walitti kenniinsaa tokkoo tokkoo dhimmaa giddu galeessaan." - helptext: | + helptext: "Agarsiiftuun kun tokkoon tokkoon dhimma galmaa’eef (tajaajilagosa  hundaaf) giddugaleessa lakkoofsa rifaralaa dhimmoota hunda keessatti, dhimmichi adeemsa irra jiraachuu/banaa  ta’uu fi kan cufamee ta’uu  lakkaa’a. kunis  riferaala karaa waltajjii hojjetame qofa osoo hin taane Rifaraalacaancala dhimmaa irratti waraabame of keessatti  kan hammatu ta’a. \n\n" referrals_per_service: title: "Walitti kenniinsa tokkoo tokkoo tajaajilaatiin." average_followup_meetings_per_case: title: "10.Tokkoo tokkoon dhimaa irratti walga'iiwwan hordoffii adeemsifaman giddu galeessaan.." label: "walga'iiwwan hordoffii tokkoon tokkoo dhimmaa irratti giddu galaan." helptext: | + Agarsiiftuun  kun giddu galeessaan lakkoofsa walgahii hordoffii gaggeeffame dhimma adeemsa irra jiru kamiyyuu tokkon tokkoo hojjetaa dhimmaaf  waltajjii irratti lakkaa’a. Walgahiin hordoffii walgahii hojjetaa dhimmaa fi gidduutti taasifamuudha. time_from_case_open_to_close: title: "11.Yeroo baniinsa dhimmaa irraa haga cufiinsa dhimmaatti jiru." time: "Yeroo." percent: "Dhimmootaan dhibbeentaan." helptext: | + Agarsiiftuu kun dhimmoonni hangam akka banaa ta’an, adeemsi bulchiinsa dhimmichaa gabaasa jalqabaa Dhaabbata Fayyadamtootaaf dhiyaate irraa kaasee hanga cufamuu dhimmiitti yeroo hammamii akka fudhatu safara. Dheerinni yerooyeroo armaan gadiitiin caccaba: ji’a 1 gadi; ji’a 1 hanga 3 gidduutti; ji'a3-6 gidduutti; ji'a3-6 gidduutti. case_closure_rate: title: "12.Baay'ina lakkofsa cufiinsa dhimmaa." reporting_site: "Buufata gabaasni itti dhiyaatuu.." - helptext: | + helptext: |+ + Agarsiiftuu kun lakkoofsa dhimmoota ji’atti cufaman bakka gabaasni itti dhiyeessan tokkotti safara. Marsariitiin gabaasuusaayitii Dhaabbanni Fayyadamtootaa tajaajila itti kennu fi bakkataateen sun tajaajila kennuudhaaf itti gabaafame jedhamee hubatama. + client_satisfaction_rate: title: "13.Saffisa itti quufiinsa maamilaa." label: "Ittiquufiinsa maamilaa." invalid: "Amma kana shallaguu hindandeenyuu." - helptext: | + helptext: |+ + Agarsiiftuu kun dhibbeentaa lubbuun hafan kanneen Qorannoo Yaada Maamilaa  xumurantajaajila bulchiinsa dhimmaa isaaniif kennameen quufa qaban safara.  Agarsiiftuu kun kan beeksifame unka yaada maamilaa GBVIM irratti hojjetaa tokko irratti xumuruun yoo ta’u, hojjetaa dhimmaa kan tajaajila sana nama lubbuun hafeef kenne caalaa. + supervisor_to_caseworker_ratio: title: "14.Walgitiinsa lakkofsa to'ataa fi hojjetaa dhimmaa walbira qabanii yoo ilaalan." label: "Hojjetoota dhimmaa fi to'ataa walbira qabanii yoo ilaalan." - helptext: | + helptext: |+ + Agarsiiftuu kun baay’ina hojjettoota dhimmaa supparvaayizarri tokko to’achaa jiruudha: reeshiyoo supparvaayizarii fi casehojjetaa. Shallaggiin kun gahee sirna waltajjii irratti ramadame irratti hundaa'a. + case_load: title: "15.Fe'iinsa Dhimma " case_load: "Fe'insa dhimmaa." @@ -1477,6 +1595,7 @@ om: 21-30cases: "Dhimmoota 21-30" 30cases: "Dhimmoota 30 ol" helptext: | + Agarsiiftuu kun dhimmoota sochii qaban irratti hundaa’uun giddugaleessa fe’iinsa dhimmaa hojjetaa dhimmaa dandeessifame tokkoof safara.Reeshiyoon dhimmootaa fi hojjettoota dhimmaa caccabsa armaan gadii irratti hundaa’uun qoodameera: 10keewwan banaa gadi, dhimmoota banaa 10-20 gidduutti, 21-30 gidduutti. date_range_dialog: title: "Bal'ina guyyaa maamilaa." description: "Jijjiiramni kun al tokko hojirra oollaan,guyyoota lamaan armaan gadi jiran jiddutti deetaan filatama." @@ -1486,7 +1605,6 @@ om: aria-labels: from: "Ragaan/deetaan guyyaa kanaan booda filatama." to: "Deetaan guyyaa kanaan duratti filatama." - location: base_types: camp: Buufata. @@ -1511,6 +1629,12 @@ om: central_warehouse: Mankuusaa waaltaa/giddugalaa. warehouse: Mankuusaa. buyingstation: Buufata bittaa. + township: Iddoo isaa /Magaala + municipality: Bulchiinsa Magaalaa + autonomous_region: Naannoo Ofiin Of Bulchuu + parish: Paarishii + cercle: Nannaa'aa + sub-county: Kutaa-biyyaa label: Bakka/iddoo. name: Maqaa. code: Koodii. @@ -1518,12 +1642,12 @@ om: type: Akaakuu/gosa. hierarchy: Gulantaa/ aangawaa. import_title: Iddoo/bakka fichisiisaa. - message: "" + message: Maaloo faayila CSV dabarsuuf filadhu. Faayilli kun koodii UTF-8 fayyadamuu fi tarree mataduree lammaffaa tarjaa tokkoon tokkoo keessatti hashtags HXL hammachuu qaba. no_location: Maaloo eenyummeessaa fayyadamaa kamiinuu oso uumiin dura iddoowwan/bakkeewwan fichisiisaa. enable_title: Naannoo dammaqsi. - enable_text: "Dhugaa keetii?/sirriidha jettaa?/Iddoowwan filataman yoo dandeessiste, iddoo iddoowwan irratti akka filannoo ta'anii ni mul'atu." + enable_text: Dhugaa keetii?/sirriidha jettaa?/Iddoowwan filataman yoo dandeessiste, iddoo iddoowwan irratti akka filannoo ta'anii ni mul'atu. disable_title: Naannoo gufachiisi. - disable_text: "Dhugaa keetii ?yoo iddowwan filataman dhaamsite/dadhaabsiiste/armaan booda iddoowwan argaman irratti akka filannootti hin mul'atan." + disable_text: Dhugaa keetii ?yoo iddowwan filataman dhaamsite/dadhaabsiiste/armaan booda iddoowwan argaman irratti akka filannootti hin mul'atan. logger: actions: _approved: Mirkanaa'eera. @@ -1676,18 +1800,18 @@ om: label: Dhugoomsa/mirkaneessa iggitaa. password_match: label: Iggitaan walfakkaachuu qaba. - provider_title: "duukaa isaa/wajjiin%{provider}" + provider_title: duukaa isaa/wajjiin%{provider} title: Seeni. username: Maqaa fayyadamaa. password_reset_modal: Iggitaa deebi'ii jalqabsiisi. password_reset_modal_text: Primeeroon geessituu haaroomsuu iggitaa gara teessoo iimeelii keessanitti erga. password_reset_email: Iimeelii. - forgot_password: "Lakkofsa Iggitaa keetii ni irraanfattee?" + forgot_password: Lakkofsa Iggitaa keetii ni irraanfattee? email: label: Ii meelii lookup: create: Barbaacha haaraa. - enabled_label: "Dammaqeeraa/danda'eeraa?" + enabled_label: Dammaqeeraa/danda'eeraa? english_label: Barruu afaan Ingliffaa. label: Ilaal. language_label: Qooqa/Afaan. @@ -1700,100 +1824,220 @@ om: no_options: Barbaachi kun yeroo ammaa kana filannoo wayiituu hin qabu.. translation_label: Barruu hiikkaa. values: Filannoowan. + locked_alert_message: Kan barbaadamu cufameera. managed_reports: + generated_on: Kan maddisiifame irratti label: Qalbifannaawwan/hubannoowwan. total: Waliigala. - filter_by: + violations_total: Miidhaalee + filter_by: date: Guyyaa. verification_status: Haala mirkaneessaa. + violation_type: Gosa Miidhaa + status: Sadarkaa + status_open: Baname + status_closed: Cufame + user_group: Garee fayyadamaa + agency: Ejensii + by: Eenyun + workflow: Haala Adeemsa Hojii + cp_incident_violence_type: Gosoota Miidhaa + referral_transfer_status: Sadarkaa Dabarsa + status_options: + open: Banaa + closed: Cufame + by_options: + created_by_groups: 'Fayyadamaa Gareewwan galmee uumame ' + owned_by_groups: Fayyadamaa Gareewwan abbaa galmee + created_organization: Ejensii galmee bane + owned_by_agency_id: Ejensii abbaa galmee + referral_transfer_status_options: + in_progress: Kan hin xumurmne + accepted: Kan fudhatame + rejected: Kan fudhatama dhabe + done: Kan raawwate date_range: month: Ji'a. quarter: Kurmaana. year: Bara/woggaa. + week: Torbee date_range_options: this_quarter: Kurmaana kana. last_quarter: Kurmaana darbe. this_month: Ji'a kana. last_month: Ji'a darbe. + this_week: Torbe kana + last_week: Torbee darbe this_year: Barana/bara kana. last_year: Bara darbe/bara dheengaddaa. custom: Aadaa/maamiloo. no_data: Hubannoo kanaaf deetaan /ragaan wayiituu hin jiru. no_data_table: Hubannoo kanaaf deetaan ...wayiituu hinjiru. + incomplete_data: Odeeffannoo hin xumuramne + individual_children: + name: Daa'ima Dhuunfaa + reports: + individual_children: Daa'ima Dhunfaa + sub_reports: + individual_age: Tokkoon tokkoon daa'immanii Umuriin + individual_violation_type: Tokkoon tokkoon daa'immanii gosa miidhatiin + individual_region: Tokkoon tokkoon daa'immanii naannoon + individual_perpetrator: Tokkoon tokkoon daa'immanii gosa yakkaan + ghn_report: + name: Global Horizontal Note + reports: + ghn_report: Hubachiisa Dalgee/ Horizontal Addunyaa + sub_reports: + verified_information: Odeeffannoo Mirkanaa'e - Miidhamtoota + late_verification: ' Mirkaneessuu ture- Miidhaamtoota' + unverified_information: Odeeffannoo Hin Mirkanoofne - Miidhaamtoota. + verified_information_violations: Odeeffannoo Mirkanaa'e - miidhaamtoota + late_verification_violations: Mirkaneessuu ture - Miidhamtoota/Sarbamiinsa + unverified_information_violations: Odeeffannoo Hin Mirkanoofne - Miidhaamtoota + killing: Ajjeechaa Daa'immanii + maiming: Daa'imman qaama hir'isuu + recruitment: Qaxarrii fi/ykn daa’imman fayyadamuu + sexual_violence: Gudeeddii fi miidhaa saalaa gosa biroo + rape: Gudeeddii fi miidhaalee saalaa gosa biroo + abduction: Butamuu + attack_on_hospitals: Haleellaa hospitaala(wwan) irratti raawwatame . + attack_on_schools: Haleellaa mana/manneen barumsaa irratti raawwatamu . + military_use: Itti fayyadama waraanaa mana barumsaa fi/ykn hospitaala . + denial_humanitarian_access: Daa’imman gargaarsa namoomaa akka hin arganne dhorkuu + multiple_violations: Daa’imman miidhalee baayyeen miidhaman + detention: Hidhaa + boys: Daa'imaa Dhiiraa + girls: Daa'imaa Dubaraa + total: Waliigala + unknown: Kan hinbeekamne + associated_violations: Miidhaalee waliin kan wal-qabatu violations: name: Miidhaawwan. - description: '' filter_options: incident_date: Guyyaa taateen itti mul'ate. date_of_report: Guyyaa gabaasaa. ctfmr_verified_date: Guyyaa mirkaneessaa. + verified: Mirkanaa'eera reports: killing: Ajjeechaa daa'immanii/daa'imman ajjeesuu. maiming: Hiyyummaa daa'immanii. recruitment: Daa'imman qacaruu fi ykn itti fayyadamuu. - sexual_violence: Dirqisiisanii gudeeduu fi/ykn miidhaawwan/jequmsaawwan saal-quunnamtii biraa. + sexual_violence: Gudeeddii fi miidhaalee korniyaa gosa biroo + rape: Gudeeddii fi miidhaalee korniyaa gosa biroo abduction: Butii. - attack_on: Midhaawwan mana barumsaa/manneen barnootaa fi ykn hospitaala/hospitaaloota irra gahan. + attack_on_hospitals: Haleellaa hospitaala irratti raawwatame . + attack_on_schools: Haleellaa mana barumsaa irratti raawwatamu . military_use: Itti fayyadama loltummaa mana barumsaa(manneen barnootaa)fi ykn hospitaalaa(hospitaalootaa) denial_humanitarian_access: Daa'imman dhiyeessii gargaarsa namoomaa dhorkachuu. + detention: Hidhaa sub_reports: + children: Daa'imman combined: Miidhaawwan. + denial_humanitarian_access: Namoomaa haaluu + denial_type: Gosa hidhaa detention_detained: Akkuma hidhamanitti turu. detention_released: Gadi lakkifameera. perpetrators: Baay'ina laakkofsa daa'immanii warra yakka irratti raawwateetiin. + perpetrators_denial: Baayina miidhamtoota yakkamtootan + perpetrator_detention: Baay'ina Daa'immanii karaa Yakkamtootan + perpetrators_incidents: Baay’ina taateewwanii/balaa fi Yakkamtoota raawwataniin + reporting_location_incidents: Baay'ina taateewwanii Naannoodhaan reporting_location: Lakkofsa daa'immanii naannoodhaan. + reporting_location_detention: Baay'ina Daa'immanii Naannoodhaan + reporting_location_denial: Baay'ina Miidhaalee naannoodhaan. attack_type: Baay'ina ijoollee akaakuu midhamaatiin. boys: Ijoollee dhiiraa. girls: Shamarran. unknown: Kan hinbeekamne. total: Waliigala. + violation: Miidhaalee + sexual_violence_type: Gosa/gosoota Miidhaalee Korniyaa + detention_status: Haala Daa’imman Hidhamanii + type_of_use: Gosa itti fayyadama + factors_of_recruitment: Sababoota qacarrii + still_being_held: Ammas qabamee jira + released: 'Released' + escaped: 'Miliqe' + abduction_reasons: Sababoota Buttaa + abducted_status: Haala Buttaa + facility_attack_type: Gosa Miidhaa + received_response: Daa'imman Deebii Argatan + male: Dhiira + female: Dubara + military_use_type_of_use: Baay’ina miidhaalee gosa itti fayyadamaatiin gbv_statistics: name: Xiinannoo midhaa kornaayaa bu'ureeffatee. - description: '' filter_options: date_of_first_report: Guyyaa Af-gaaffii/gaaffii fi deebii. incident_date: Guyyaa taatee. - reports: - incidents: Taateewwan. + reports: perpetrators: Yakkamtoota. + survivors: Kan miidhaalee keessa darban + referrals: Rifaralaa + sub_reports: + service_safehouse_referral: Mana Nageenyaa /iddoo turtii nagaa Rifaralaa + service_medical_referral: Rifaarala fayyaa + service_psycho_referral: Tajaajila xin-sammuu fi hawaasummaa ykn gorsa + service_legal_referral: Tajaajila deggarsa seeraa + service_police_referral: Poolisii ykn Tajaajila Nageenyaa Gosa Biroo + service_livelihoods_referral: Tajaajila Jireenyaa + service_protection_referral: Tajaajila Eegumsa Daa'immanii + survivors_disability_type: Qaama Miidhamtoota + workflow_report: + name: Adeemsa hojii + reports: + cases_workflow: Adeemsa Hojii - Dhimmoota + incidents_workflow: Adeemsa Hojii - Taateewwan + filter_options: + registration_date: Guyyaa galmee sub_reports: - combined: Taateewwan. - total: Baay'ina lakkofsa taateewwan miidhaalee kornaayaa bu'ureeffatanii gabaasaman. - gbv_sexual_violence: Baay'ina lakkofsa taateewwan miidhaa saalaa gabaasaman. - gbv_previous_incidents: Taateewwan miidhaa koornaayaa bu'ureeffatan dura lakkofsa baay'ina taateewwanii namoota lubbuudhaan hafaniin gabaasaman.. - gbv_sexual_violence_type: Gosa/akaakuu taatee. - incident_timeofday: Yeroo taatee guyyaa. - elapsed_reporting_time: Garaagarummaa yeroo gidduu taatee fi gabaasaa gidduu jiru. - elapsed_reporting_time_rape: "Taatee dirqisiisanii gudeeduu,yeroo taatee fi guyyaa gabaasaa gidduu jiru." - incident_location_type: Bakka/iddoo Taatee. - number_of_perpetrators: Lakkofsa yakka raawwattootaa sadarkaa jalqabaa. - perpetrator_relationship: "Walittidhufeenya yakka raawwataan shakkamaan duraa nama miidhaa irraa hafe wajjiin qaban. " - perpetrator_age_group: Garee umurii yakka raawwattootaa sadarkaa jalqabaa. - perpetrator_occupation: Hojii yakka raawwataa sadarkaa jalqabaa. + case_workflow_by_sex_and_age: 'Waliigala Baay’ina Dhimmoota Korniyaa fi Umriidhan. ' + incident_workflow_by_sex_and_age: Waliigala baay'ina taatewwanii korniyaa fi Umuriidhan + referrals_transfers_report: + name: Rifaralaa fi Jijjiirraa + reports: + total_referrals: Rifaralaa + total_transfers: Dabarsa + sub_reports: + total_transfers_by_user_groups: Dabarsa waliigalaa + total_referrals_by_user_groups: Rifaralaa waliigalaa + filter_options: + registration_date: Guyyaa Galmee + violence_type_report: + name: Gosa miidhaa + reports: + cases_violence_type: Gosa Miidhaa-Dhimmoota + incidents_violence_type: Gosa miidhaa-Taatewwan + filter_options: + registration_date: Guyyaa Galmee + sub_reports: + case_violence_type_by_sex_and_age: Baay'ina waliigalaa dhimmoota Korniyaa fi Umuriin + incident_violence_type_by_sex_and_age: Baay'ina waliigala taatewwanii korniyaa fi Umriin + success_message: Faayilii al-ergii milkaa'inaan uumeera messages: - alert_items: "Gosa yaadannoo %{items}qabda." + alert_items: Gosa yaadannoo %{items}qabda. alerts_for: - approval: "mirkaneessi akka turu kan taasifameef.%{form_section_name}" + approval: mirkaneessi akka turu kan taasifameef.%{form_section_name} field_change: 'Guyyaa%{alert_time} foyya''eera%{form_section_name}' - transfer_request: "gaaffiin haaraa dabarsaa guyyaan taasifamee%{date}qaama%{user} mana hojiitiin %{agency} taasifameera." - duplicate_field: "dhimmi biroo sirnicha keessatti kana %{field_name}waliin kan walfakkaatudha." + transfer_request: gaaffiin haaraa dabarsaa guyyaan taasifamee%{date}qaama%{user} mana hojiitiin %{agency} taasifameera. + duplicate_field: dhimmi biroo sirnicha keessatti kana %{field_name}waliin kan walfakkaatudha. cannot_edit: Isa kana gulaaluu hindandeessu. confirmation_message: Tolee cuqqaassuun jijjiirama hin olkaa'iin kan balleessuu danda'uu fi karaa tarree mul'atanitti deebisa. Karaa galmeetti deebi'uuf haqqii cuqqaassi. - confirmation_message_subform: "'Tolee' tuquun jijjiiramoota maalimaa/mi'a kana irratti hin kaa'amin maqsa.Jijjiramoota taasisuu ittifufsiisuudhaaf haqi kan jedhu tuqaa." + confirmation_message_subform: '''Tolee'' tuquun jijjiiramoota maalimaa/mi''a kana irratti hin kaa''amin maqsa.Jijjiramoota taasisuu ittifufsiisuudhaaf haqi kan jedhu tuqaa.' dashboard_offline: Sararaan ala jirtu.Gara sararaatti yegguu deebitan daashboordichi guutummaa guututti hojjeta. field_name_on_form_name: '%{field_name}guca dirree/bobbii/irraa%{form_name}' - logout_confirmation: "Walga'ii kee itti fufuu barbaaddaa?" - logout_offline_warning: "Dhugumatti cuftee keessaa bahuu barbaaddaa?Yoo kana taasifte deebitee sarara irra haga galtaniitti deebitanii galuu hindandeessan.Sararaan ala taatanii jijjiramootn taasiftan kamiiyyuu hindhabaman." + logout_confirmation: Walga'ii kee itti fufuu barbaaddaa? + logout_offline_warning: Dhugumatti cuftee keessaa bahuu barbaaddaa?Yoo kana taasifte deebitee sarara irra haga galtaniitti deebitanii galuu hindandeessan.Sararaan ala taatanii jijjiramootn taasiftan kamiiyyuu hindhabaman. logout_warning: Daqiiqaa 5 keessatti akka baasamtan taasifamtu. logout_dialog_header: Sararaan ala bayeera. logout_confirmation_title: Mirkaneessa cufanii keessaa bahuu. - logout_confirmation_text: "Dhugaa keessaa bayuu ni barbaaddaa?" + logout_confirmation_text: Dhugaa keessaa bayuu ni barbaaddaa? no_changes: Jijjiiramoota dirree wayiituu hin taasisne. not_available: Hin argamu. record_list: - column_header_tooltip: "kan akka foyya'u ta'e.%{column}" + column_header_tooltip: kan akka foyya'u ta'e.%{column} of: Ka. - no_match: "Dhiifama,galmeewwan walsiman/walfakkaatan kamiyyuu hin argamne." + no_match: Dhiifama,galmeewwan walsiman/walfakkaatan kamiyyuu hin argamne. rows_per_page: Sararaawwan tokkoo tokkoon fuula isaaniitiin. sort: Fooyii kaayi/tarreessi. navigation: @@ -1813,10 +2057,12 @@ om: code_of_conduct: Dambii naamusaa. terms_of_use: Qajeelfama itti fayyadamaa. system_information: Ragaa sirna odeeffannoo. + resync: Jijjiirama Toora intarneetiin alaa galii hin taane tasks: Hojiiwwan. tracing_request: Gaaffii Maatii barbaachaa. activity_log: Yaadannoo galmee hojii/sosochii. registry_records: Mana Galmee. + families: Maatiiwwan notes: note_success: Yaadannoo haala milkaa'aan dabalaniiru. permissions: @@ -1835,18 +2081,18 @@ om: approvals_case_plan_pending: '%{approval_label}akka turu kan taasifame.' approvals_closure: '%{approval_label}mallattoo-mirkaneessa.' approvals_closure_pending: '%{approval_label}akka turu kan taasifame.' - approve_action_plan: "mirkaneessi%{approval_label} " - approve_assessment: " guca/unka/%{approval_label}mirkaneessi" + approve_action_plan: 'mirkaneessi%{approval_label} ' + approve_assessment: ' guca/unka/%{approval_label}mirkaneessi' approve_case_plan: Mirkanneessa1%(approval-label) - approve_closure: " guca/unka/%{approval_label}{approval_label}mirkaneessi" - approve_gbv_closure: "guca %{approval_label}mirkaneessi." + approve_closure: ' guca/unka/%{approval_label}{approval_label}mirkaneessi' + approve_gbv_closure: guca %{approval_label}mirkaneessi. assign: Ramaduu. assign_within_agency: Ejensicha keessatti ramaduu. assign_within_user_group: Garee fayyadamaa keessatti ramaduu. audit_log: Galmee to'annoo/odiitii. case: Dhimma. case_approvals: Mirkaneessaawwan dhimmaa. - case_assignments_referrals_transfers: "Ramaddiiwwan dhimmaa,walharkaa fudhiinsaawwanii fi dabarsaawwanii." + case_assignments_referrals_transfers: Ramaddiiwwan dhimmaa,walharkaa fudhiinsaawwanii fi dabarsaawwanii. case_exports: Dhimma gara alaatti erguu. case_overview: Dhimmoota kiyya. case_risk: Dhimmoota sadarkaa sakatta'insaan. @@ -1900,6 +2146,7 @@ om: find_tracing_match: Barbaacha walsimaa dhimma irraa barbaadaa. view_registry_record: Galmee irratti galmaa'an ilaalaa. add_registry_record: Galmee irratti galmaa'an dabalaa. + family: Maatii flag: Alaabaa. form: Gucaawwan/unka. group: Galmeewwan ykn fayyadamtoota garee kiyya keessaa jiran hunda bira gahi. @@ -1913,7 +2160,7 @@ om: manage: Bulchi. mark_for_offline: Sararaan alatti mallattoo kaayaa. matching_configuration: Qindaayina walsimaa. - metadata: "Gucaawwan/unkaawwan,barbaachaawwan." + metadata: Gucaawwan/unkaawwan,barbaachaawwan. potential_match: Dandeettii guddaa walsiman. primero_configuration: Qindaayina. read: Dubbisi. @@ -1928,17 +2175,17 @@ om: report: Gabaasa. managed_report: Hubannoowwan. request_approval: Gaaffii mirkaneessuudhaafii. - request_approval_action_plan: "Mirkanneeffannaa%{approval_label}gaafatame" - request_approval_assessment: "Mirkanneeffannaa%{approval_label}gaafatame" - request_approval_case_plan: "Mirkanneeffannaa%{approval_label}gaafatame" + request_approval_action_plan: Mirkanneeffannaa%{approval_label}gaafatame + request_approval_assessment: Mirkanneeffannaa%{approval_label}gaafatame + request_approval_case_plan: Mirkanneeffannaa%{approval_label}gaafatame request_approval_closure: Gaafii 1%(sadarkaa -mirkanneessuu) mirkanaa'e. - request_approval_gbv_closure: "Mirkanneeffannaa%{approval_label}gaafatame" - request_transfer: " Dabarsa gaafadhaa." + request_approval_gbv_closure: Mirkanneeffannaa%{approval_label}gaafatame + request_transfer: ' Dabarsa gaafadhaa.' role: Shoorawwan. save_search: Barbaachaawwan taasisaman ol'kaayaa. saved_search: Barbaacha ol'kaayame. search_owned_by_others: Galmeewwan dhimmaa fayyadamtoota biraatiin dhuunfataman/qabaman barbaadaa. - self: "Galmeewwan kiyya ykn fayyadamaa kiyyaa qofa bira gahaa. " + self: 'Galmeewwan kiyya ykn fayyadamaa kiyyaa qofa bira gahaa. ' service_provision_incident_details: Ijaarsa tarreeffamoota taatee irratti furtuu dhiyeessii tajaajilaa dabal jedhu ilaalaa. services_section_from_case: Dhimma fayyadamaa biraatiif dhiyeessii tajaajilaa dabalaa. specific_roles: Tarreessa shooraawwan sirritti adda bahanii ibsamanii bira gahaa. @@ -1959,6 +2206,7 @@ om: workflow_team: Yaa'insa hojii-dhimmoota gareewwanii. write: Barreessi. activity_log: Yaadannoo galmee hojii/sosochii. + remove_alert: Akeekkachiisa balleessi resource: kpi: actions: @@ -1969,7 +2217,7 @@ om: explanation: Dandeettii waa ilaaluu dhimmoottan si'aawaa fayyadamaan bira gahuu danda'uu ilaaluu.isaan keessaallee kutaaleen meeqaa uunka gamaaggamaa xumurame akka qaban beekuu. label: Haala sakatta'insaa. kpi_average_followup_meetings_per_case: - explanation: "Dandeettii bulchaan dhimmoota aktiifii ta'anii fayyadaman dhaqabamaa ta'an itti arguu danda'u, yeroo murtaa'e keessatti giddu-galleessan baayyina walga'ii hordoffii taasifame. " + explanation: 'Dandeettii bulchaan dhimmoota aktiifii ta''anii fayyadaman dhaqabamaa ta''an itti arguu danda''u, yeroo murtaa''e keessatti giddu-galleessan baayyina walga''ii hordoffii taasifame. ' label: Walga'iiwwan hordoffii tokkoo tokkoo dhimmaa irratti giddu galeessaan taasisame. kpi_average_referrals: explanation: Dandeettii dhimmoota si'awaa hundaa fayyadamaan bira gahuu danda'u irratti baayi'ina eeruuwwani tokkoon tokkoo akaakuu tajaajilootaaf jiddu galaan taasifame ilaaluu danda'uu. @@ -1991,10 +2239,10 @@ om: label: Karoorawwan nageenyummaa dhimmaa xumuraman. kpi_completed_supervisor_approved_case_action_plans: explanation: Dandeettii fayyadamaan dhimmoottan si'aawaa biragahuu danda'uuf karoora raawwii dhimmaa too'ataa tokkoon mirkanaa'e hangam akka ta'e ilaaluu danda'uu. - label: "Karoora raawwii too'taan xumuramee mirkanaa'e. " + label: 'Karoora raawwii too''taan xumuramee mirkanaa''e. ' kpi_goal_progress_per_need: - explanation: "Dandeettii fayyadamaan bira gahiinsa dhimmootaaf qabuu,tokkoon tokkoo qodamsa fedhii keessatti dhibbeentaan kaayyoolee meeqa galma akka gahan ilaaluu danda'uu." - label: " Fooyya'iinsa/guddinna galma gahiinsa galmaawwanii irratti taasifaman." + explanation: Dandeettii fayyadamaan bira gahiinsa dhimmootaaf qabuu,tokkoon tokkoo qodamsa fedhii keessatti dhibbeentaan kaayyoolee meeqa galma akka gahan ilaaluu danda'uu. + label: ' Fooyya''iinsa/guddinna galma gahiinsa galmaawwanii irratti taasifaman.' kpi_number_of_cases: explanation: Dandeettii dhimmottan haaraa meeqaa jia ji'aan gabasaaman tokkoon tokkoo buufataa keessatti akka banaman ilaaluu. label: Baay'ina lakkofsa dhimmoottanii. @@ -2017,7 +2265,7 @@ om: agency: actions: assign: - explanation: "" + explanation: Dandeettii dhimma tokko uumuu ykn foyyeessuu dandeessisuu.Dhimmoonni "Disabled" tarree dhimmootaa keessatti durtiidhaan hin mul'atan. 13. Fayyadamtoonni tarree keesii keessatti dhimmoota hanqifaman filter fayyadamuun arguu danda'u. Primero fayyadamtoonni keessota akka haqan waan hin hayyamneef, fayyadamaan tokko keessi akka bakka bu'aa ta'etti hanqisuu barbaadu ta'a. label: Ramaduu. create: explanation: Dandeettii ejensii uumuu. @@ -2036,47 +2284,47 @@ om: audit_log: actions: read: - explanation: "" + explanation: 'Fayyadamaan sirna keessatti raawwii raawwate maraa calaluu fi ilaaluu akka danda''u, fayyadamaan akka adda bahu,gosa hojiin, lakkofsa Galmee fi yeroo raawwii akka qabaatu eeyyamuu. Kun sadarkaa bulchiinsa biyyoolessaa fi mana hojiitti sirritti kan fayyaduudha. Kun kan agarsiisu sirna keessatti raawwii fayyadamtoota hundaa qaban ta''a. Hubachiisa: LOGiin oditii odeeffannoo dhuunfaa waa''ee galmeewwan hojii tokko tokkoo keessatt haguugame hin agarsiisu.' label: Ilaalcha. - explanation: "Tarreeffama hojiiwwanii hunda sirnicha keessatti raawwataman calalamuu danda'uu.Gaaffiiwwan dhimmootaa,taateewwanii fi ykn barbaachoota irratti odeeffannoo adda bahan tokkollee itti hin dabalu." + explanation: Tarreeffama hojiiwwanii hunda sirnicha keessatti raawwataman calalamuu danda'uu.Gaaffiiwwan dhimmootaa,taateewwanii fi ykn barbaachoota irratti odeeffannoo adda bahan tokkollee itti hin dabalu. label: Galmee to'annoo/odiitii. case: actions: add_note: - explanation: "" + explanation: Fayyadamaan galtee unka xiqqaa "Yaadannoo" keessatti akka dabalu hayyama (yeroo tokko tokkos "Yaada" jedhama). Fayyadamaan kana kan godhu qaree "Yaadannoo Dabaluu" fuula agarsiisa dhimmaa  irratti cuqaasuun. Tarkaanfiin kun keessumaa hoggantoota dandeettii dhimmoota gulaaluu hin qabneef, garuu hojjetaa dhimmichaaf dhimma tokko irratti yaadachiisa dabaluu barbaadaniif faayidaa qaba. Haala kanaan, yaadannoo dabaluun alaabaa dabaluu wajjin wal fakkaata. Faayidaan yaadannoo dabaluu, yeroo hogganaan yaadannoo dhimma tokko irratti dabalu, hojjetaan dhimmaa  yeroo isaan meeshaa moobaayilaa isaanii irratti dhimmaa  ilaalaa jiran beeksisni dhimmichaa irratti ni mul’ata. label: Dhimma tokko irratti yaadannoowwan dabali. add_registry_record: explanation: Fayyadamaan tokko tarreeffamoota guca galmeessaa irraa galmee akka dhimma wajjiin walitti fidu hayyamaaf.Akkasumas fayyadamaan tokko dursee qunnamtii mana galmee dhimmichaan walittidhufan kamiinuu akka addaan kutu dandeessisaan. label: Galmee irratti galmaa'an dhimma irraa dabalaa/ammayyomsaa. approve_action_plan: explanation: Dhimmoota hojjattoota dhimmaa hojii gaggeessan/hogganaan/ akka mirkanneessuu 1%(sadarkaa-mirkanaa'e) eeyyamu. - label: "mirkaneessi %{approval_label}mallattoo mirkaneessaa" + label: mirkaneessi %{approval_label}mallattoo mirkaneessaa approve_assessment: - explanation: "gaggeessaan/bulchaan/akka dhimmoota hojjattoota dhimmaa akka mirkaneessuu %{approval_label}danda'u hayyamaaf." - label: "guca %{approval_label}mirkaneessi." + explanation: gaggeessaan/bulchaan/akka dhimmoota hojjattoota dhimmaa akka mirkaneessuu %{approval_label}danda'u hayyamaaf. + label: guca %{approval_label}mirkaneessi. approve_bia: - explanation: "gaggeessaan/bulchaan/akka dhimmoota hojjattoota dhimmaa akka mirkaneessuu %{approval_label}danda'u hayyamaaf." - label: "guca %{approval_label}mirkaneessi." + explanation: gaggeessaan/bulchaan/akka dhimmoota hojjattoota dhimmaa akka mirkaneessuu %{approval_label}danda'u hayyamaaf. + label: guca %{approval_label}mirkaneessi. approve_case_plan: - explanation: "gaggeessaan dhimmoota hojjattoota dhimmaa isaatiif akka mirkaneessuu danda'u%{approval_label} hayyamaaf." - label: "mirkaneessi%{approval_label}" + explanation: gaggeessaan dhimmoota hojjattoota dhimmaa isaatiif akka mirkaneessuu danda'u%{approval_label} hayyamaaf. + label: mirkaneessi%{approval_label} approve_closure: - explanation: "Bulchaan dhimmoota hojjettoota hawaasummaa%{approval_label}akka mirkanneessu eeyyami." - label: "guca %{approval_label}mirkaneessi." + explanation: Bulchaan dhimmoota hojjettoota hawaasummaa%{approval_label}akka mirkanneessu eeyyami. + label: guca %{approval_label}mirkaneessi. approve_gbv_closure: - explanation: "Dhimmoota hojjettoota hawaasaa bulchaan akka mirkanneessu eeyyami%{approval_label}" - label: "guca %{approval_label}mirkaneessi." + explanation: Dhimmoota hojjettoota hawaasaa bulchaan akka mirkanneessu eeyyami%{approval_label} + label: guca %{approval_label}mirkaneessi. assign: - explanation: "" + explanation: Fayyadamaan tokko dhimma abbaa galmee isaa isa jalqabaa irraa fayyadamaa biraa sirnicha keessa jiru kamiyyuu akka ergu ni hayyama. Tarkaanfii kanaaf hayyamni daa’imaa hin barbaachisu. Jijjiirraa irraa adda ta’ee, fudhataan ramaddii fudhachuu ykn diduudhaaf carraan hin kennamu label: Ramaduu. assign_within_agency: - explanation: "" + explanation: Fayyadamaan tokko dhimma abbaa galmee isaa isa jalqabaa irraa fayyadamaa biraa kamiyyuu ejensii fayyadamaa ammaa keessatti akka ergu ni hayyama. Tarkaanfii kanaaf hayyamni daa’imaa hin barbaachisu. Jijjiirraa irraa adda ta’ee, fudhataan ramaddii fudhachuu ykn diduudhaaf carraan hin kennamu. label: Ejensii kiyya keessatti fayyadamaaf ramadi. assign_within_user_group: - explanation: "" + explanation: Fayyadamaan tokko dhimma abbaa galmee isaa jalqabaa irraa gara fayyadamaa biraa kamiyyuu gareewwan fayyadamtoota fayyadamaa ammaa keessatti akka ergu ni hayyama. Tarkaanfii kanaaf hayyamni daa’imaa hin barbaachisu. Jijjiirraa irraa adda ta’ee, fudhataan ramaddii fudhachuu ykn diduudhaaf carraan hin kennamu. label: Garee fayyadamaa kiyyaa keessatti fayyadamaadhaaf ramadi. change_log: - explanation: "" + explanation: Fayyadamaan galmeen erga uumamee kaasee seenaa jijjiirama galmee irratti godhame maraa arguu danda'a. Kunis gatiiwwan man'ee hundaaf galmaa'an of keessatti qabata. label: Galmee jijjiiraa. close: explanation: Fayyadamaan dhimma banaa akka cufuuf tolu akka haala qindeessuu dandeessisaan. @@ -2088,55 +2336,58 @@ om: explanation: Dandeettii dhimma uumuu. label: Uumuu. display_view_page: - explanation: "" + explanation: Fayyadamaan tokko dhimma isaan qaqqabummaa hin qabne barbaacha yoo raawwate, hayyamni kun fayyadamaan odeeffannoo isaa hunda ilaaluuf dhiimmaa  keessa cuqaasuu yoo dadhabellee, moodaalii xiqqaa odeeffannoo bu’uuraa waa’ee dhimmichaa qabu akka arguuf isaan dandeessisa . dirreewwan/Idowwaan/ irratti " View Modal " kana keessatti mul'atan dirreewwan/Idowwaan/gara "Unka gabaabaa irratti agarsiisi" tti qindaa'aniidha. Moodaalli kun fayyadamtoota gochoota Maatii barbaduu  fi Deebi'anii Tokkummaa raawwataniifis ni fayyada, sababiin isaas " View Modal " fayyadamaan yeroo dhimmoota Gaaffii barbaduu dhaaf akka "walsimsiisa ta'uu danda'anitti" mul'atan gamaaggamu akka argatu waan jiruuf. label: Fuula ilaalcha agarsiisaa. enable_disable_record: - explanation: "" + explanation: Dandeettii dhimma tokko akka hin hojjanne taasisuu ykn dandeessisuu. Dhimmoonni "Har'amaman" tarree dhimmootaa keessatti durtiidhaan hin mul'atan. Fayyadamtoonni tarree dhimmaa  keessatti dhimmoota  hanqifaman calaqqee fayyadamuun arguu danda'u. Primero fayyadamtoonni keessota akka haqan waan hin hayyamneef, fayyadamaan tokko keessi akka bakka bu'aa ta'etti hanqisuu barbaadu ta'a. Fakkeenyaaf, yoo fayyadamaan tokko dogoggoraa dhimma uume, ykn dhimmi  sun daataa badee qabaate, fayyadamaan sun hanqisuu qaba. label: Dandeessisuu/dadhabsiisuu. export_case_pdf: - explanation: "" + explanation: Fayyadamaan tarree haalaa ykn fuula agarsiisa dhimmaa  irraa faayilii PDF al-ergii uumuu danda'a, kunis dirrewwaan/idowwaan/ fayyadamaan ammaa qaqqabummaa qabu hunda of keessaa qabu, haala tokkoof, dachaaf, ykn haalawwan fayyadamaan qaqqabummaa qabu hundaaf. Faayilii al-ergii PDF keessatti, odeeffannoon jalqaba qubeedhaan tarreeffama, sana booda unka odeeffannoon irratti mul'atuun daran qindaa'a. label: Dhimma PDF ergi export_csv: - explanation: '' + explanation: 'Fayyadamaan tarree haalaa ykn fuula agarsiisa keesii irraa al-ergii faayilii CSV uumuu danda''a, kunis man''eewwan fayyadamaan ammaa qaqqabummaa qabu hunda of keessaa qabu, haalawwan tokkoof, dachaaf, ykn haalawwan fayyadamaan qaqqabummaa qabu hundaaf. HUBACHIISA: Al-ergiin CSV arfiilee Laatiin hin taane (fkn. Arabaa, Baanglaa) bifa dubbifamuu danda''uun hin agarsiisu.' label: Gatii/sona/qoodduu fi addaan bayanii alatti ergi. export_custom: - explanation: "" + explanation: Fayyadamaan tarree dhimmaa  ykn fuula agarsiisa dhimmaa  irraa al-ergii faayilii XLS uumuu danda'a, kunis tuuta unkaa ykn man'ee amala of keessaa qabu, haala tokkoof, dachaa, ykn haala fayyadamaan qaqqabummaa qabu hundaaf. Al-ergii kana keessatti, tokkoon tokkoon unkaa caancala mataa isaa keessatti faayilii XLS keessaa bakka bu'a. Fayyadamaan unkaalee ykn man'eelee kamtu al-ergii keessatti hammatamuu barbaadu moodaala Al-ergii Adda fayyadamuun filachuu danda'a. Hubadhaa fayyadamtoonni unkaalee fi man'eewwan al-ergii keessatti hammachuu kan danda'an yoo duraan dandeettii unkaalee fi man'eewwan sana arguu qaban yeroo dhimma tokko application keessatti ilaalan qofa. label: Maamiloo alatti ergi. export_duplicate_id_csv: - explanation: "" + explanation: Al-ergii CSV keessoowwan dirree ID Biyyaalessaa walfakkaataa qaban uuma (asxaa adda addaa qabaachuu danda'a, qindeessaa irratti hundaa'uun). Fuula tarree dhimmootaa irraa qofa raawwatama. label: Baay'isamoota gara alaa ergi. export_json: - explanation: "" + explanation: Fayyadamaan tarree haalaa ykn fuula agarsiisa dhimma irraa al-ergii faayilii JSON uumuu danda'a, kuniis mane'eewwan fayyadamaan ammaa qaqqabummaa qabu hunda of keessaa qaba, haalawwan tokkoof, dachaaf, ykn haalawwan fayyadamaan qaqqabummaa qabu hundaaf. Al-ergiin kun irra caalaa warra sirna Primero amma jiru irraa keessoowwan erguu barbaadaniif ergasii gara sirna Primero adda ta’etti, ykn gara sirna bulchiinsa odeeffannoo biraatti galchuu barbaadaniif kan ooludha. Akkaataan JSON maashiniin kan dubbifamuu fi fayyadamtoota baay'eedhaaf qabatamaa miti. label: JSON alatti ergi. export_list_view_csv: - explanation: "" + explanation: Fayyadamaan fuula tarree keesii irraa al-ergii galmee CSV uumuu danda'a kunis man'eewwan walfakkaatan kanneen fayyadamaa sanaaf tarree dhimmaa  irratti mul'atan of keessaa qabu. Fuula tarree dhimmoo irraa qofa raawwatama. label: Tarreeffama mul'annoo gatii/sona/qoodduu fi addaan bayiinsaa alatti ergi. export_pdf: - explanation: "" + explanation: Fayyadamaan tarree haalaa ykn fuula agarsiisa dhimmaa  irraa al-ergii faayilii PDF uumuu danda'a, kuniis mane'eewwan fayyadamaan ammaa qaqqabummaa qabu hunda of keessaa qabu, haalawwan tokkoof, dachaaf, ykn haalawwan fayyadamaan qaqqabummaa qabu hundaaf. Faayilii al-ergii PDF keessatti, odeeffannoon jalqaba qubeedhaan tarreeffama, sana booda unka odeeffannoon irratti mul'atuun daran qindaa'a. label: Pii Dii Effii dhimmaa alatti ergi. export_photowall: - explanation: "" + explanation: Fayyadamaan galmee tokko fuula tarree dhimmaa irraa suurawwan dhimmoota filamanii hundaa qabatee al-erguuf gargaara. Al-erguun kun irra caala kan fayyaduuf maatii adda baasuu fi hojiiwwan maatitti deebissuufidha. Kan raawwattuus fuula tarree dhimmaa qofa irraa ta'a. label: Dhaabaa suuraa gara alaatti erguu. export_unhcr_csv: label: Gatii qoodduu fi addaan kan bayee Komishinii Olaanoo Koolugaltootaa Mootummoota Gamtoomanii alatti ergi. export_xls: - explanation: '' - label: "kan caaluu {faaila XLS}alatti ergi." + explanation: 'Fayyadamaan tarree haalaa ykn fuula agarsiisa dhimmaa irraa al-ergii faayilii XLS uumuu danda''a, kunis man''eewwan fayyadamaan ammaa qaqqabummaa qabu hunda of keessaa qabu, haalawwan tokkoof, dachaaf, ykn haalawwan fayyadamaan qaqqabummaa qabu hundaaf. Al-ergii kana keessatti, tokkoon tokkoon unkaa caancala mataa isaa keessatti faayilii XLS keessaa bakka bu''a. HUBACHIISA: Akkaataan XLS arfiilee Laatiin hin taane (fkn. Arabaa, Baanglaa) bifa dubbifamuu danda''uun agarsiisa, al-ergiin CSV garuu hin agarsiisu.' + label: kan caaluu {faaila XLS}alatti ergi. find_tracing_match: - explanation: "" + explanation: Kuniis haalawwan sochii Hordoffii Maatii fi Deebi’anii Tokkummaa qabaniif qofa kan ooludha. Fayyadamtoonni hayyama kana qaban fuula agarsiisa dhimmaa irratti qaree "Find Tracing Match" jedhu ni argu. Yeroo cuqaasan, tarree gaaffii hordoffii sirna keessa jiru kanneen dhimma isaaniif walsimsiisuu danda'an bira ga'u. label: Barbaacha walsimaa/walfakkaataa dhimma irraa barbaadaa. flag: explanation: Dandeettii dhimma tokkorratti alaabaa ida'uu.Fayyadamtoonni hayyama kana qaban alaabaawwan gara dhimmaatti ida'an baasuu/haquu danda'an. label: Alaabaa. import: - explanation: "" + explanation: Fayyadamaan faayilii CSV, Excel, ykn JSON irraa galchuudhaan dhimmii  haaraa tokko ykn isaa ol akka uumu hayyama. Odeeffannoon sirriitti galfamuuf faayilii galfame *baay'ee* addatti foormaatii ta'uu qaba. Faankishiniin kun fayyadamtoota bulchiinsaa dandeettii teeknikaa olaanaa qabaniifi akkaataa daataan Primero keessatti itti foormaatii ta’u beekumsa gadi fageenya qabu qofaaf ta’uu qaba. Fuula tarree dhimmootaa irraa qofa raawwatama. label: Fichisiisi. incident_details_from_case: - explanation: "" + explanation: Dandeettii galmee unka xiqqaa bal’ina balaa dhimma bu’aawwan barbaacha keessatti argatte fi garuu kan ati hin arganne irratti dabaluu. Fayyadamaan gocha kana fuula bu'aa barbaacha irraa haala tokko ykn isaa ol filachuudhaan raawwata, sana booda sajoo gochoota irraa "Taatee Dabaluu" filachuudhaan. Fayyadamaan sana booda moodaalii man'eelee hunda unka xiqqaa Bal'ina Taatee irratti of keessaa qabu argu, bakka isaan waa'ee tajaajila tokkoo odeeffannoo galchuu fi dhiyeessu danda'u. Tarkaanfiin kun fuula bu'aa barbaacha irraa qofa raawwatamuu waan danda'uuf, gaheen tokko hayyama kana qabaachuun isaa yoo isaanis hayyama "Galmee dhimmaa fayyadamtoota birootiin qabame barbaadi" qabaatan qofa hiika qaba. label: Fuula bu'aalee barbaachaa irraa bal'inoota taatee gara dhimma fayyadamaa birootti dabalaa. incident_from_case: - explanation: "" + explanation: Hayyamni kun fayyadamaan "Create Incident" kan jedhu akka cuqaasu isa dandeessisa. Kuniis balaa/taatee odeeffannoo tokko tokko dhimmicha irraa waraabame of keessaa qabaachuu danda’u maddisiisa. Dhimmoota GBV tiif, qaree kun fuula agarsiisa dhimmii  gubbaa jira, fi odeeffannoo waa'ee dhimmaa akka waliigalaatti walsima. Haala taatee-hordoffii tokko tokko keessatti, qaree kun unka xiqqaa "Ibsa Taatee" irratti argama. Haala kana keessatti, odeeffannoon tokko tokko unka xiqqaa ibsa taatee bakka buttooni itti cuqaafame irraa, akkasumas akka waliigalaatti dhimmicha irraa waraabamuu danda'a.  Kana jechuun balaa/taatee haaraan uumame unka xiqqaa ibsa taatee dhuunfaa irraa dirree "Gosa Jeequmsaa" qabaachuu danda'a, garuu umurii fi saala dhimmichaa mataa isaa of keessaa qabaachuu danda'a. Hubadhaa hayyamni kun fayyadamaan taatee uumame sanaaf hidhaa akka argus ni hayyama. label: Dhimma irraa taatee uumaa. + remove_alert: + explanation: Hayyamni kun fayyadamaan akeekkachiisa dhimma tokko irraa akka haquuf fayyada. Akeekkachiisni yeroo kutaan tokko fooyya'an, kan akka yeroo yaadannoowwan fooyya'an uumamu. Akeekkachiisni yeroo baayyee tuqaa keelloo dhimma cinatti agarsiifama. + label: Akeekkachiiisa dhimma tokko irraa haqi manage: explanation: Fayyadamaan dalagaawwan dhimmoota irra jiran hundumaa akka raawwatu dandeessisaan.Bu'uurarraa hayyama "bulchuu"jechuun "waan hundaa"jechuudha. label: Bulchi (hayyamoota gosa qabeenya kanaa hunda) @@ -2144,55 +2395,55 @@ om: explanation: Dandeettii dhimma ilaaluu. label: Ilaalcha. receive_referral: - explanation: "" + explanation: 'Fayyadamaan dhimma dabarsaa akka fudhattuuf eeyyama. Fayyadamaan eeyyama kana qabu dhimma fudhachuu fi raawwii dabarsaaf kan danda''uudha. Fayyadamaan eeyyama kana hin qabne yeroo namni tokko dhimmi isaa moodela dabarsaa keessatti akka irraa fudhatamu yeroo barbaadu dhimma fudhachuuf kan dandeenyeedha. ' label: Walharkaafuudhiinsa fudhachuu. receive_referral_different_module: - explanation: "" + explanation: Fayyadamaan galmee moojuulii Primero adda ta'e keessatti uumame rifaralaa akka fudhatu hayyama. Fayyadamtoonni hayyama kana qaban galmee sanaaf tarkaanfii rifaralaa akka fudhattoota ta’uu danda’anitti kan mul’atan yoo ta’u, fayyadamtoonni hayyama kana hin qabne ammoo, yeroo namni tokko moodaala rifaralaa keessatti fudhataa barbaadu akka fudhattoota ta’uu danda’anitti hin mul’atan. label: Muraa garagaraa keessatti fayyadamaa tokko irraa walharkaafuudhiinsa raawwadhaa. receive_transfer: - explanation: "" + explanation: Fayyadamaan jijjiirraa akka argatu ni hayyama. Fayyadamtoonni hayyama kana qaban akka fudhattoota tarkaanfii jijjiirraa ta'uu danda'anitti kan mul'atan yoo ta'u, fayyadamtoonni hayyama kana hin qabne ammoo, yeroo namni tokko moodaala jijjiirraa keessatti fudhataa barbaadu akka fudhattoota ta'uu danda'anitti hin mul'atan. label: Dabarsa fudhachuu. referral: - explanation: "" + explanation: Fayyadamaan tokko yeroodhaaf dhimma tokko fayyadamaa biraatiif qaqqabummaa akka kennu hayyama. Fudhataan rifaralaa dhimma rifaralaa irratti tarkaanfiiwwan walfakkaatan hunda akkuma dhimma ofii isaanii irratti raawwachuu danda’an raawwachuu ni danda’a. Yeroo fudhataan kana booda dhimmicha argachuu hin barbaanne, unka xiqqaa Rifaralaa fi Jijjiirraa keessatti qaree "Raawwatame" cuqaasuu danda'u, akkasumas dhimmicha argachuu ni dhabu. Dhimma tokko fayyadamaa gaheen isaa dandeettii rifaralaa fudhachuu qabu qofaaf erguu dandeessa. label: Walharkaafuudhiinsa. referral_from_service: - explanation: "" + explanation: Fayyadamaan unka xiqqaa tajaajiloota irratti qaree " dabarsuu " akka argu hayyama. Yeroo fayyadamaan qaree kana cuqaasu, moodaalli rifaralaa Dirrewwaan/Idowwaan/ Gosa Tajaajilaa, Ejensii, Dhiyeessaa Tajaajilaa, fi bakka hanqifamee mul'ata, garuu ofumaan odeeffannoo Dirrewwaan/Idowwaan sanaa unka xiqqaa Tajaajiloota fayyadamaan qaree Wabii irratti cuqaase keessatti guutama. label: Dhimmicha guca xiqqaa tajaajilaa irraa ilaalaa. remove_assigned_users: - explanation: "" + explanation: Fayyadamaan fayyadamtoota biroo dirree/iddoo/ "Fayyadamtoota Ramadaman biroo" irraa akka haqu hayyama. Fayyadamaan tokko dhimmichaaf rifaralaa kan argate ykn dhimmichaaf jijjiirraa kan argate yoo ta’e, garuu hanga ammaatti kan hin fudhanne yoo ta’e asitti tarreeffama. Yeroo fayyadamaa dirree/iddoo/ "Fayyadamtoota Ramadaman biroo" irraa haqxu, qaqqabummaa isaanii gara dhimma ni haqta. Kanaafuu, fayyadamtoonni hayyama kana qaban fayyadamtoota kanaan dura rifaralaa ykn jijjiirraa ammallee dhimmichaaf eegamaa jiru irraa qaqqabummaa dhimmaa haquu danda’u. Hubadhu hayyamni kun kan hojjetu yoo fayyadamaan ammaa akkasumas dandeettii dhiimmaa gulaaluu qabaate qofa. label: Fayyadamtoota biroo ramadaman haqaa(fayyadamtoota eeraman keessaa bira gahinsa dhimmaa fudhachuun) reopen: explanation: Fayyadamaan dhimma dhiyeenya kana keessa cufame akka banachuu danda'u hayyamaaf/taasisa. label: Irra deebi'anii banuu request_approval_action_plan: - explanation: "Fayyadamaan (yeroo baay'ee hojjataa dhimmaa)gaggeessaan dhimma isaanii %{approval_label}haa mirkaneessuuf akka gaafatu hayyamaaf." - label: "mirkaneessa %{approval_label}gaaffii." + explanation: Fayyadamaan (yeroo baay'ee hojjataa dhimmaa)gaggeessaan dhimma isaanii %{approval_label}haa mirkaneessuuf akka gaafatu hayyamaaf. + label: mirkaneessa %{approval_label}gaaffii. request_approval_assessment: - explanation: "Fayyadaman (yeroo baayi'ee hojjataa dhimmaa)gaggeessaan dhimma isaanii %{approval_label}haa mirkaneessuuf akka gaafatu hayyamaaf." - label: "Gaafii %{approval_label}mirkanneessa" + explanation: Fayyadaman (yeroo baayi'ee hojjataa dhimmaa)gaggeessaan dhimma isaanii %{approval_label}haa mirkaneessuuf akka gaafatu hayyamaaf. + label: Gaafii %{approval_label}mirkanneessa request_approval_bia: - explanation: "Fayyadamaan (yeroo baayi'ee hojjataa dhimmaa)gaggeessaan dhimma isaanii %{approval_label}haa mirkaneessuuf akka gaafatu hayyamaaf." - label: "mirkaneessa %{approval_label}gaaffii." + explanation: Fayyadamaan (yeroo baayi'ee hojjataa dhimmaa)gaggeessaan dhimma isaanii %{approval_label}haa mirkaneessuuf akka gaafatu hayyamaaf. + label: mirkaneessa %{approval_label}gaaffii. request_approval_case_plan: - explanation: "Fayyadamaan (yeroo baayi'ee hojjataa dhimmaa)gaggeessaan dhimma isaanii%{approval_label} haa mirkaneessuuf akka gaafatu hayyamaaf. " - label: "mirkaneessa %{approval_label}gaaffii " + explanation: 'Fayyadamaan (yeroo baayi''ee hojjataa dhimmaa)gaggeessaan dhimma isaanii%{approval_label} haa mirkaneessuuf akka gaafatu hayyamaaf. ' + label: 'mirkaneessa %{approval_label}gaaffii ' request_approval_closure: - explanation: "Fayyadamaan (yeroo baayi'ee hojjataa dhimmaa)gaggeessaan dhimma isaanii %{approval_label}haa mirkaneessuuf akka gaafatu hayyamaaf." - label: "mirkaneessa %{approval_label}gaaffii." + explanation: Fayyadamaan (yeroo baayi'ee hojjataa dhimmaa)gaggeessaan dhimma isaanii %{approval_label}haa mirkaneessuuf akka gaafatu hayyamaaf. + label: mirkaneessa %{approval_label}gaaffii. request_approval_gbv_closure: - explanation: "Fayyadamaan (yeroo baayi'ee hojjataa dhimmaa)gaggeessaan dhimma isaanii %{approval_label}haa mirkaneessuuf akka gaafatu hayyamaaf." - label: "mirkaneessa %{approval_label}gaaffii." + explanation: Fayyadamaan (yeroo baayi'ee hojjataa dhimmaa)gaggeessaan dhimma isaanii %{approval_label}haa mirkaneessuuf akka gaafatu hayyamaaf. + label: mirkaneessa %{approval_label}gaaffii. request_transfer: - explanation: "" + explanation: Fuurtuu/button/  "  Gaaffii Dabarsaa"" jedhu " Moodaala Ilaali " irratti mul'isa. Furtuu  fayyadamaan ergaa yaadannoo dhuunfaa qabu karaa imeelii abbaa galmee ammaa dhimma tokkootti akka ergu kan hayyamu yoo ta'u, abbaan galmee dhimmicha fayyadamaa gaaffii ergeef akka dabarsu gaafata. Kunis haalawwan daa’immaan  yeroo baay’ee bakka jijjiiran keessatti faayidaa qaba, hojjettoonni dhimmaa galmee dachaa akka hin uumamneef hojjetaan dhimmaa duraan daa’imaa waa’ee daa’imaa odeeffannoo erguu barbaadu. label: Dabarsa gaafadhaa. search_owned_by_others: - explanation: "" + explanation: Fayyadamaan galmeewwan yeroo baay'ee argachuu hin dandeenye, yookaan dhimma sanaaf abbaa galmee waan hin taaneef, yookaan (hoggantootaaf) abbaan galmee garee fayyadamtoota isaanii keessa waan hin jirreef, barbaachaf akka raawwatu hayyama. Hubadhaa/Yadadhuu/, fayyadamaan ilaalcha bu'aa barbaacha keessatti dhimmicha yoo argu, dhimma sanaaf fuula agarsiisa dhimmaa keessa cuqaasuu hin danda'u, jechuunis waa'ee dhimmichaa odeeffannoo bal'aa tokkollee arguu hin danda'an. label: Galmeewwan abbummaa fayyadamtoota biraatiin qabaman barbaadaa. service_provision_incident_details: - explanation: "" + explanation: Fayyadamaan qaree "Dhiyeessii Tajaajilaa Qusachuu fi Dabaluu" jedhu jalatti moodaalii Taatee Dabaluu akka argu hayyama. Qabduu kana cuqaasuun odeeffannoo amma waa'ee taatee galfame qusata, sana booda fayyadamaa kallattiin gara moodaala Kenniinsa Tajaajila Dabaluutti fudhata. Tarkaanfiin kun kallattiin gochoota Taatee Dabaluu fi Kenna Tajaajila Dabaluu wajjin kan walqabatu waan ta'eef, gahee tokkoof hayyama kana kennuunis hiika kan qabu yoo gaheen sun akkasumas "Ibsa Taatee dhimma fayyadamaa biraatti Dabaluu" fi "Dhiyeessii Tajaajilaa kan fayyadamaa biraatti Dabaluu" qabaate qofa dhimmaa" hayyama kennuudhaan. label: Ibsa tarreeffamoota taatee irratti furtuu dhiyeessii kenna tajaajilaa ida'i jedhu ilaalaa. services_section_from_case: - explanation: "" + explanation: Dandeettii galmee unka xiqqaa Tajaajilootaa dhimma bu'aa barbaacha keessatti argatte irratti, garuu kan ati qaqqabummaa hin qabne irratti dabaluu. Fayyadamaan gocha kana fuula bu'aa barbaacha irraa haala tokko ykn isaa ol filachuudhaan raawwata, sana booda sajoo gochoota irraa "Dhiyeessii Tajaajilaa Dabaluu" filachuudhaan. Fayyadamaan sana booda moodaala dirrewwaan/iddowwaan/ hunda unka xiqqaa Tajaajiloota irratti of keessaa qabu argu, bakka isaan waa'ee tajaajila tokkoo odeeffannoo galchuu fi dhiyeessu danda'u. Tarkaanfiin kun fuula bu'aa barbaacha irraa qofa raawwatamuu waan danda'uuf, gaheen tokko hayyama kana qabaachuun isaa yoo isaanis hayyama "Galmee dhimmaa fayyadamtoota birootiin qabame barbaadi" qabaatan qofa hiika qaba. label: Dhimma fayyadamaa biraatiif dhiyeessii tajaajilaa dabalaa. sync_external: explanation: Dandeettii galmee sirna qabiinsa odeeffannoo ragaa alee wajjiin walsimsiisuu. @@ -2201,13 +2452,13 @@ om: explanation: Fayyadamaan dhimmoota karaan ala faayidaa irra oolan akka kaayu dandeessisan. label: Sararaan alatti mallattoo kaayaa. transfer: - explanation: "" + explanation: Fayyadamaan tokko dhimma abbaa galmee isaa ammaa irraa fayyadamaa sirnicha keessa jiru kamiyyuu dandeettii jijjiirraa fudhachuu qabutti akka ergu ni hayyama. Abbaan galmee dhimmichaa garuu hanga fudhataan jijjiirraa "fudhatutti" hin jijjiiramu. Yoo fudhataan inumaa jijjiirraa "kufaa tasis", fudhataan dhimmicha argachuu dhaba, akkasumas abbaa galmee isaa isa jalqabaa qabata. label: Dabarsa. view_photo: - explanation: "" + explanation: Fayyadamaan suuraawwan dhimma tokkoo mul'ata tarree dhimmaa irraa akka argu hayyama. Hayyama kana malee, fayyadamaan tarjaa "Suuraa" gabatee tarree dhimmaa, ykn mallattoolee suuraa kanneen achitti mul'atan hin argu. Hayyamni kun fayyadamaan suuraa daa'imaa "Moodaalii Ilaaluu" keessatti akka argus ni hayyama. label: Suuraa mul'annoo tarreessa dhimmaa irraa ilaalaa. view_incident_from_case: - explanation: "Dhimma yoo ilaaltan ,fayyadamaan tarreeffama taateewwanii dhimmicha wajjiin walittidhufanii fi tokkoon tokkoo cuunfaa odeeffannoo ilaaluu danda'a." + explanation: Dhimma yoo ilaaltan ,fayyadamaan tarreeffama taateewwanii dhimmicha wajjiin walittidhufanii fi tokkoon tokkoo cuunfaa odeeffannoo ilaaluu danda'a. label: Taateewwan dhimma irraa ilaalaa. view_protection_concerns_filter: explanation: Fayyadamaan fuula tarreessa dhimmaa irratti calaltuu sodaawwan eegumsaa akka ilaaluu danda'u taasisa.. @@ -2219,48 +2470,57 @@ om: explanation: Dandeettii furtuu"Gulaali"jettu tuquu danda'uu.Ammayyoomsa odeeffannoo dhimma keessa jiruu fi "ol kaa'i"jedhu tuqaa. label: Gulaali. accept_or_reject_transfer: - explanation: "" + explanation: Fayyadamaan fayyadamaa biraa garee kee keessa jiru bakka bu’ee jijjiirraa akka fudhatu ykn didu ni hayyama (fakkeenyaaf, supparvaayizarri jijjiirraa hojjetaa hawaasummaa isaaniif ergame fudhachuu). label: Fayyadamaa biraa garee keessan keessatti argamuuf dabarsa fudhaa ykn fudhatama dhabsiisaa. list_case_names: explanation: Gaggeessitoonni yeroo baayi'ee maqaalee dhimmootaa tarreeffamoota dhimmaa keessatti arguu hin danda'an.Gaggeessaan tokko hayyama kana yoo qabaatee tarreeffama keessatti maqqaalee jiran arguu danda'u. - label: "Hoji gaggeessaa yoo ta'e,tarreeffama dhimmaa keessatti maqaalee dhimmaa ilaaluu danda'a." + label: Hoji gaggeessaa yoo ta'e,tarreeffama dhimmaa keessatti maqaalee dhimmaa ilaaluu danda'a. mark_for_offline: explanation: Fayyadamaan sararaan alatti dhimma itti fayadamu iddoo dhoksaa kaayuu akka danda'u taasisa. label: Sararaan alatti mallattoo kaa'aa. - explanation: "Daa'ima tokko,warra miidhaa irraa baraaraman ykn fayyadamaa biraa bakka bu'a." + view_family_record: + explanation: Fayyadamtoonni unka 'Galmee Maatii' dhimmicha irratti argamu ilaaluu kan danda'an yoo ta'u, kunis galmee maatii dhimmichaa waliin kan walqabatudha. + label: Galmee maatii dhimma irraa ilaaluu + case_from_family: + explanation: Fayyadamtoonni unka xiqqaa Bal'ina Maatii keessatti miseensota maatii Dhimmichaa tokkoof Dhimma uumuu danda'u. Hubadhaa, Galmeen Maatii ofumaan dhimmoota lamaan kana walitti hidhuuf ni uuma. + label: 'Ibsa gadi fageenyaa Maatii irraa dhimma uumuu ' + link_family_record: + explanation: Fayyadamaan Galmee Maatii jiru Dhimma isaanii waliin akka barbaaduu fi akka walqabsiisu hayyama. Akkasumas fayyadamtoonni Galmee Maatii Dhimma tokko irraa akka wal-hinqabane ni hayyama. + label: Galmee Maatii Dhimma irraa hidhaa / hin hidhaana + explanation: Daa'ima tokko,warra miidhaa irraa baraaraman ykn fayyadamaa biraa bakka bu'a. label: Dhimma. dashboard: actions: approvals_action_plan: - explanation: "Kan eeggachaa jiran,gaaffiiwwan mirkanaa'an ykn akka kufan taasifaman mirkaneessa karoora raawwii keessatti baayi'ina fayyadamtoota ammaan tana jiran mul'isa." - label: "mirkaneessa %{approval_label}hojjataa dhimmaa." + explanation: Kan eeggachaa jiran,gaaffiiwwan mirkanaa'an ykn akka kufan taasifaman mirkaneessa karoora raawwii keessatti baayi'ina fayyadamtoota ammaan tana jiran mul'isa. + label: mirkaneessa %{approval_label}hojjataa dhimmaa. approvals_action_plan_pending: explanation: Gaaffiiwwan mirkaneessa karoora raawwii eeggachuu irra jiran baay'ina dhimmaa garee bulchaa keessa jianii mul'isa. - label: "mirkaneessa %{approval_label}gaggeessaa" + label: mirkaneessa %{approval_label}gaggeessaa approvals_assessment: - explanation: "Kan eeggachaa jiran,gaaffiwwan mirkanaa'an ykn gaaffiiwwan mirkaneessa gamaaggamaa akka kufan taasifamanitti fayyadamuun baayi'ina dhimmoota fayyadamaa ammaan kana jiranii mul'isa." - label: "mirkaneessa%{approval_label} hojjataa dhimmaa." + explanation: Kan eeggachaa jiran,gaaffiwwan mirkanaa'an ykn gaaffiiwwan mirkaneessa gamaaggamaa akka kufan taasifamanitti fayyadamuun baayi'ina dhimmoota fayyadamaa ammaan kana jiranii mul'isa. + label: mirkaneessa%{approval_label} hojjataa dhimmaa. approvals_assessment_pending: - explanation: "Gaaffiiwwan sakatta'insaa mirkaneessa eeggachaa jiran wajjiin baayi'ina dhimmootaa garee gaggeessaa keessa jiran mul'isa. " - label: "mirkaneessaawwan%{approval_label} gaggeessaa" + explanation: 'Gaaffiiwwan sakatta''insaa mirkaneessa eeggachaa jiran wajjiin baayi''ina dhimmootaa garee gaggeessaa keessa jiran mul''isa. ' + label: mirkaneessaawwan%{approval_label} gaggeessaa approvals_case_plan: - explanation: "Baayyina fayyadamtoota dhimmaa agarsiissuu fi gaafii mirkanneessa karoora dhimmaa rarra'e,mirkanaa'e ykn haqame." - label: "mirkaneessaawwan hojjataa dhimmaa%{approval_label}" + explanation: Baayyina fayyadamtoota dhimmaa agarsiissuu fi gaafii mirkanneessa karoora dhimmaa rarra'e,mirkanaa'e ykn haqame. + label: mirkaneessaawwan hojjataa dhimmaa%{approval_label} approvals_case_plan_pending: explanation: Gaaffiiwwan karoora dhimmaa mirkaneessa  eeggachaa jiran keessatti baayi'ina dhimmootaa garee gaggeessaa keessa jiran mul'isa. - label: "mirkaneessaawwan %{approval_label}gaggeessaa" + label: mirkaneessaawwan %{approval_label}gaggeessaa approvals_closure: - explanation: "Gaaffiiwwan hayyama cufiinsaa eeggachaa jiran,kan mirkanaa'an ykn akka kufan taasifaman fayyadamuun baayi'ina dhimmootaa fayyadamaa ammaan tana jiran muli'isa." - label: "mirkaneessaawwan%{approval_label} hojjataa dhimmaa" + explanation: Gaaffiiwwan hayyama cufiinsaa eeggachaa jiran,kan mirkanaa'an ykn akka kufan taasifaman fayyadamuun baayi'ina dhimmootaa fayyadamaa ammaan tana jiran muli'isa. + label: mirkaneessaawwan%{approval_label} hojjataa dhimmaa approvals_closure_pending: explanation: Baay'ina lakkofsa dhimmootaa garee hoji gaggeessaa keessatti gaafiiwwan mirkanneessa cufiinsaa eeggachaa jiran agarsiisa. - label: " Bulchaa 1%(sadarkaa-mirkanneessaa) Mirkanneessa" + label: ' Bulchaa 1%(sadarkaa-mirkanneessaa) Mirkanneessa' approvals_gbv_closure: - explanation: "Gaaffiiwwan mirkaneessa cufiinsa miidhaa kornaayaa bu'ureeffatanii eeggacha jiran,kan mirkanaa'an ykn akka kufan taasifaman wajjiin baayi'ina dhimmootaa fayyadamaa ammaan tana jiranii mul'isa." - label: "mirkaneessaawwan %{approval_label} hojjataa dhimmaa." + explanation: Gaaffiiwwan mirkaneessa cufiinsa miidhaa kornaayaa bu'ureeffatanii eeggacha jiran,kan mirkanaa'an ykn akka kufan taasifaman wajjiin baayi'ina dhimmootaa fayyadamaa ammaan tana jiranii mul'isa. + label: mirkaneessaawwan %{approval_label} hojjataa dhimmaa. approvals_gbv_closure_pending: explanation: Baayyina dhimmoota garee bulchaa tokko jala jiranii fi MKB ilaalchisee akka cufiinsi mirkanneeffamuuf gaafatamee otoo hin cufamiin rara'anii hafan agarsiisu. - label: "mirkaneessaawwan %{approval_label}gaggeessaa" + label: mirkaneessaawwan %{approval_label}gaggeessaa case_overview: explanation: Ibsa waliigalaa lakkoofsoota akka dhimmoottan waliigalaa fi haaraa jiran ka'umsa kaardii daash boordii fuula gubbaa irratti argamu dabalu. label: Daashboordii ilaalcha waliigalaa. @@ -2280,10 +2540,9 @@ om: explanation: Gaggeessaan tokkoo tokkoo hojjattoota dhimmaa isaaniitiif hojiiwwan kenna tajaajilaa yeroon isaanii jalaa darban meeqaa akka jiran ilaaluuf hayyama. label: Hojiiwwan tajaajilaa yeroon irra darbe. dash_case_incident_overview: - explanation: . label: Ilaalcha waliigalaa-Dhimmoota kiyya/Taateewwan. dash_cases_by_social_worker: - explanation: "" + explanation: Gabatee akkaataa baay'ina waliigalaa dhimmi daa’immaa banaa fi baay'ina dhimmoota    haaraa tokkoon tokkoon fayyadamaa gareewwan fayyadamtoota fayyadamaa ammaa keessatti bulfaman agarsiisu. Tokkoon tokkoon tarree fayyadamaa gareewwan fayyadamaa ammaa keessaa yoo ta'u, "Waliigala" fi "Haaraa" tarjaa lamaan. label: Dhimmoottan hojjetaa hawaasaatiin ilaalaa. dash_cases_to_assign: explanation: 'Baayyee Barbaachisaadha. Bulchoota qofa. Baayyina dhimmootaa fayyadamaa yeroo ammaatiin qabaman agarsiissi(Bulchaa qofa ta''uu qaba). Daash boordiin kun bulchaan dhimmoota isaa bulchuu akka hin dandeenyee kan tilmaamu fi yoo bulchaan tokko dhimma ofii isaan qabate dhimmicha hojjetaa dhimmaaf garee keessa jiruuf dabarsuu qaba. ' @@ -2292,28 +2551,28 @@ om: explanation: Tarreeffama alaabaawwanii fayyadamtoonni biroo gara galmeewwan kiyyaatti ida'an akkasumas alaabaawwan galmeewwan fayyadamtoota biroo irratti ani dabale mul'isa. label: Galmeewwan eeraman. dash_group_overview: - explanation: "Bulchaa/hoji gaggeessaa tokko dhimmoottan banaa fi cufaman fayyadamtoota garee isaanii keessa jiraniin bulan itti mul'isa. " + explanation: 'Bulchaa/hoji gaggeessaa tokko dhimmoottan banaa fi cufaman fayyadamtoota garee isaanii keessa jiraniin bulan itti mul''isa. ' label: Dhimmoottan garee kiyyaa. dash_matching_results: - explanation: "Kan hin mirkannoofne. Daash-boordiin kun kan hin hojjannee fi karaa V2 kan darbuu qabuudha. " - label: "Bu'aalee walfakkaatan ilaalaa. " + explanation: 'Kan hin mirkannoofne. Daash-boordiin kun kan hin hojjannee fi karaa V2 kan darbuu qabuudha. ' + label: 'Bu''aalee walfakkaatan ilaalaa. ' dash_protection_concerns: - explanation: "" + explanation: Gabatee baayyinaa dhimmoota yaaddoo eegumsaa jiran agarsiisu. Tokkoon tokkoon tarree dalgee gabatee yaaddoo eegumsaa jiru kan agarsiisu yoo ta'u, torri  gadee gabatichaa sadarkaa dhimmichii irra jiru kan agarsiisu ta’a ("Dhimmoota hunda," "Dhimmoota banaa," "Haaraa (torban kana)," " kan Cufame (torban kana)") label: Dhimmoottan sodaawwan egumsaatiin. dash_protection_concerns_by_location: - explanation: "" + explanation: Kun daashboordii "Yaaddoo Eegumsa mullisuu” wajjin tokko yoo ta’u, jijiramiin qabu buufata fayyadamaan irraa filatamu irratti istaatiksii babal'ina yaaddoo eegumsaa bakka sana qofa keessatti agarsiisuu danda'u isaatii. label: Sodaawwan eegumsaa iddoowwan isaaniitiin ilaalaa. dash_reporting_location: - explanation: "" + explanation: Gabatee bakka tokkoon tokkoon isaaniitti dhimmoonni meeqa akka jiran agarsiisu (sadarkaa adda ta'uu tokko kan akka "Bulchiinsa" ykn "Aanaa" irratti). Tokkoon tokkoon tarree gabatee bakka, fi tarjaawwan haala adda addaa haalawwanii agarsiisu ("DIMMOOTAA BANAA," "HAARAA (TORBEE DHUMA)," "HAARAA (TORBEE KANA)," "CUFAA (TORBEE DHUMA)," "CUFAA." Yeroo baayyee herrega hogganaa ykn bulchaaf fayyadama. label: Dhimmoottan iddoo gabaasaatiin. dash_service_provisions: - explanation: "" + explanation: Lakkoofsa dhimmoota fayyadamtoonni biroo kenniinsa tajaajilaa itti dabalan agarsiisa. Lakkoofsi kun kutaa guddaa daashboordii keessatti argama. label: Dhimmoottan akaakuu/gosa kenna tajaajilaatiin. dash_shared_from_my_team: explanation: Baay'ina/lakkofsa/dhimmootaa tokkoon tokkoo fayyadamtootaan garee isaanii keessatti to'ataman kanneen fayyadamtoota gara birootti akeekaman ykn dabarsaman bulchaatti/gaggeessaatti mul'isa. label: Garee kiyyarraa kan qoodame. dash_shared_with_me: - explanation: "Dhimmotni meeqa gara keessanitti akka ergaman ykn dabarsaman mul'isa. " + explanation: 'Dhimmotni meeqa gara keessanitti akka ergaman ykn dabarsaman mul''isa. ' label: Anaa wajjiin kan qooddatame. dash_shared_with_my_team: explanation: Baay'ina /lakkofsa/ dhimmootaa tokkoon tokkoo fayyadamtootaa garee isaanii keessa jiraniif akeekamee ykn dabarsamee bulchaatti/gaggeessaa/tti mul'isa. @@ -2321,22 +2580,31 @@ om: dash_shared_with_my_team_overview: label: Garee kiyya wajjiin qoodameera(ilaalcha waliigalaa) dash_shared_with_others: - explanation: "Dhimmotni kiyya rifaraaloota si'aawaa,dabarsaawwan akka turan taasifaman,ykn dabarsaawwan fudhatama dhabanmeeqaa akka jiranagarsiisa.Dhimmoota mataa isaaniitiin yoo too'atan malee,baratamaan gaggeessitootaaf kan ta'uu miti." + explanation: Dhimmotni kiyya rifaraaloota si'aawaa,dabarsaawwan akka turan taasifaman,ykn dabarsaawwan fudhatama dhabanmeeqaa akka jiranagarsiisa.Dhimmoota mataa isaaniitiin yoo too'atan malee,baratamaan gaggeessitootaaf kan ta'uu miti. label: Qaama biraa wajjiin kan qooddataman. + dash_violations_category_verification_status: + explanation: Tokkoon tokkoon sarbamni MRM meeqa akka uumame agarsiisa, haala mirkaneessuutiin caccabee. + label: MRM - Baay'ina miidhaa sadarkaa mirkaneessuu tokkoof + dash_violations_category_region: + explanation: Tokkoon tokkoon naannoo keessatti miidhaa MRM meeqa akka uumame agarsiisa, gosa miidhaaleen addaan bahee. + label: MRM-Baay'ina miidhaalee naannoodhaan + dash_perpetrator_armed_force_group_party_names: + explanation: Gosa yakkamaan caccabee miidhaan/ sarbamni MRM gosa tokkoon tokkoon isaa meeqa akka uumame agarsiisa. + label: MRM - Baay'ina miidhaalee nama yakka raawwaten dash_show_none_values: - explanation: "" + explanation: Daashboordii hunda irratti gosa "Sadarkaa Balaa Hin Qabne" jedhu kan dhimmoota sadarkaa balaatiin caccabsan hunda irratti dabalata. Kunis addatti qindeessoota filannoo "Balaa Hin Qabne" afraffaan dirree sadarkaa balaa qabaniif. label: Daashboordii sakatta'insaa keessatti 'dhimmoottan sadarkaa balaa kamiiyyuu hinqabne ilaalaa. dash_tasks: - explanation: "" + explanation: Fayyadamaan fuula hojiiwwan akka argu hayyama. Kunis hojjettoota dhimmaa fi tajaajila kennitootaaf fayyadamuu qaba, sababiin isaas lakkoofsi kun dhimmoota kallattiin bulchitaniif addatti waan ta’uuf. Hoggantoonni kanaa mannaa daashboordii "Haalota Hojii Yeroo Darbeen Ilaali" argachuu qabu, kunis hojiiwwan yeroon darban garee fayyadamtoota isaanii hundaaf akka argan waan isaan dandeessisuuf. label: Fuula hojiiwwanii/ hojii. dash_national_admin_summary: - explanation: "Sirnicha keessatti dhimmoota waliigalaa banaman, baay'ina dhimmoota haaraa tokkoon tokkoo torbaan lamaan darban keessatti uumamanii fi baay'ina dhimmootaa tokkoon tokkoo torbaan lamaan darban keessatti cufaman mul'isa." + explanation: Sirnicha keessatti dhimmoota waliigalaa banaman, baay'ina dhimmoota haaraa tokkoon tokkoo torbaan lamaan darban keessatti uumamanii fi baay'ina dhimmootaa tokkoon tokkoo torbaan lamaan darban keessatti cufaman mul'isa. label: Cuunfaa bulchaa. view_response: - explanation: "Tokkoon tokkoo akaakuu deebiitiif,tokkoon tokkoo sadarkaa balaa irratti dhimmootni meeqaa dhuma yeroo tajaajilaa irra akka jiranii fi ykn yeroon kan itti darbe ta'uusaa mul'isa." + explanation: Tokkoon tokkoo akaakuu deebiitiif,tokkoon tokkoo sadarkaa balaa irratti dhimmootni meeqaa dhuma yeroo tajaajilaa irra akka jiranii fi ykn yeroon kan itti darbe ta'uusaa mul'isa. label: Deebiwwan kennaman ilaalaa. workflow: - explanation: "Hojjataan dhimmaa tokko,tokkoon tokkoo sadarkaa dhimmaa irratti dhimmootiin isaanii caatoo deeloo mul'isan meeqaa akka jiran ilaaluuf hayyama." + explanation: Hojjataan dhimmaa tokko,tokkoon tokkoo sadarkaa dhimmaa irratti dhimmootiin isaanii caatoo deeloo mul'isan meeqaa akka jiran ilaaluuf hayyama. label: Dhimmoottan yaa'insa hojiitiin qoqqoodaman. workflow_team: explanation: Gaggeessaan akka gabatee dhimmoottan hojjattoota hawaasaa isaanii tokkoon tokkooadeemsa waltajjii qabiinsa dhimmaa irratti jiru mul'isu ilaalu danda'u hayyamaaf. @@ -2344,32 +2612,34 @@ om: explanation: Fuula ka'umsaa irratti cuunfaa odeeffannoo kamitu akka mul'atu ibsa. label: Daashboordii. disabled: - explanation: "Shoora kana yoo dhaamsitan/gufachiistan ,ammaan booda fayyadamaaf eenyummeessaahin dand eessan." + explanation: Shoora kana yoo dhaamsitan/gufachiistan ,ammaan booda fayyadamaaf eenyummeessaahin dand eessan. label: Qaama miidhamaa. duplicate: actions: read: - explanation: "Fayyadamaan ulaagaalee adda addaatti fayyadamee kunis maqaa.maqibsa,koornaayaa,uumurii fi lammuummaa dabalatee dhimmoota sirnicha keessa jiran hundaaf akka barbaacha olaanaa taasisu hayyamaaf." + explanation: Fayyadamaan ulaagaalee adda addaatti fayyadamee kunis maqaa.maqibsa,koornaayaa,uumurii fi lammuummaa dabalatee dhimmoota sirnicha keessa jiran hundaaf akka barbaacha olaanaa taasisu hayyamaaf. label: Agarsiisi. - explanation: "Barbaacha dhimmaa olaanaa bulchitootaaf," + explanation: Barbaacha dhimmaa olaanaa bulchitootaaf, label: Barbaacha baay'isaman. forms: case: - explanation: '' + explanation: 'Fayyadamaan tokko dhimmoota irratti unka argachuu akka hin dandeenye daangessuun odeeffannoo fayyadamaan taatee tokko irratti arguu akka danda’u daangessuudha. Fakkeenyaaf, fayyadamaan unka Abbaa Galmee qofa argachuu yoo qabaate, akkasumas odeeffannoo man''ee unka sana irratti argamu qofa arguu danda''a. Yoo fayyadamaan ammaa qaqqabummaa unkaa daangeffame qabaatee fi dandeettii qindeessaa unkaa bulchuu qabaate, qaqqabummaa unkaa isaanii daangessuun unkaalee kam qindeessuu akka danda''anis daangessa. HUBACHIISA: Yoo unkaan hin ibsamne, gaheen sun unkaalee hunda dhimmootaaf qaqqabummaa qaba jechuudha.' label: Gucoota-Dhimma. incident: - explanation: '' + explanation: 'Taateewwan irratti fayyadamaan tokko unka argachuu akka hin dandeenye daangessuun odeeffannoo fayyadamaan taatee tokko irratti argachuu danda’u daangessuudha.Fakkeenyaaf, fayyadamaan unka  Galmee qofa yoo argate, odeeffannoo unka sana irratti argamu qofa arguu danda’a. Yoo fayyadamaan dandeettii qindeessa unkaa  qabaatee garu qaqqabummaa unkaa daangeffame qabaatee, qaqqabummaa unkaa isaanii daangessuun unkaalee kam qindeessuu akka danda''anis daangessa. HUBACHIISA: Unkaan hin ibsamne yoo ta’e, gaheen sun unka taateewwaniif ta’u hunda argachuu qaba jechuudha.' label: Gucoota-Taatee. tracing_request: - explanation: '' + explanation: 'fayyadamaan unka gaaffii maatii adda baasuu akka hin argane daangessuun odeeffannoo fayyadamaan unka gaaffii maatii adda baasuu irratti arguu  danda’u daangessuu dha. Fakkeenyaaf, fayyadamaan unka Galmee qofa yoo argatee,  odeeffannoo unka sana irratti argamu qofa arguu danda''a. Yoo fayyadamaan dandeettii qindeessaa unkaa qabaate garu ammaa qaqqabummaa  unkaa daangeffame qabaatee,  qaqqabummaa unkaa isaanii daangessuun unkaalee kam qindeessuu akka danda''anis daangessa. HUBACHIISA: Yoo unkaan hin ibsamne, gaheen sun unkaalee hunda Gaaffii maatii adda baasuu argachuuf qaqqabummaa qaba jechuudha.' label: Gucoota-Gaaffii barbaachaa. registry_record: - explanation: '' + explanation: 'Taateewwan irratti fayyadamaan tokko unka argachuu akka hin dandeenye daangessuun odeeffannoo fayyadamaan taatee tokko irratti argachuu danda’u daangessuudha.Fakkeenyaaf, fayyadamaan unka Galmee qofa yoo argate, odeeffannoo unka sana irratti argamu qofa arguu danda’a. Yoo fayyadamaan dandeettii qindeessa unkaa  qabaatee garu qaqqabummaa unkaa daangeffame qabaatee, qaqqabummaa unkaa isaanii daangessuun unkaalee kam qindeessuu akka danda''anis daangessa. HUBACHIISA: Unkaan hin ibsamne yoo ta’e, gaheen sun unka taateewwaniif ta’u hunda argachuu qaba jechuudha.' label: Gucawwan-mana galmee. + family: + label: Unkaalee - Maatii group: actions: admin_only: - explanation: "" + explanation: . Kana jechuun fayyadamtoonni gahee kana qaban wantoota bulchiinsa sirnichaa wajjin walqabatan kan akka gabaasa, qindeessaa unkaa fi ilaalchaa fayyadamtoota, gahee hojii, fi garee fayyadamtootaa qofa arguu danda’u.  Dhimma dhuunfaa, gaaffii hordoffii, ykn taateewwan kamiyyuu argu hin danda'an. label: Galmeewwan wayiituu hinjiran-Hojii bulchaa qofa. agency: explanation: Shoorichi galmeewwan fayyadamtoota ejensii isaanii keessa jiraniin hogganaman hundaa argachuu danda'a. @@ -2381,10 +2651,10 @@ om: explanation: Shoorichi galmeewwan fayyadamtootaa gareewwan fayyadamtootaataan bulan hunda bira gahuu ni danda'a.Gareewwan fayyadamaa isaanii keessatti fayyadamtoota qofa argachuu kan danda'an.Gareewwan fayyadamaa isaanii qofa bira gahuu danda'anis. label: Galmeewwan ykn fayyadamtoota garee kiyya keessa jiran cufa bira gahaa. self: - explanation: "Shoorichi galmeewwan mataa isaanii (dhimmoota,gaaffiiwwan barbaachaa,ykn taateewwan) bira gahuu fi eenyummeessaa fayyadamaa mataa isaaniillee gulaaluu ni danda'u." + explanation: Shoorichi galmeewwan mataa isaanii (dhimmoota,gaaffiiwwan barbaachaa,ykn taateewwan) bira gahuu fi eenyummeessaa fayyadamaa mataa isaaniillee gulaaluu ni danda'u. label: Galmeewwan kiyya ykn fayyadama kiyya qofa bira gahaa. - explanation: "Isa kam akka galmeessu(dhimmoota,gaaffiiwwan barbaachaa ykn taateewwanii)shoorichi bira gahuu akka danda'u too'ata.Shoorichi bira gahiinsa fayyadamtootaa fi gareewwan fayyadamaa yoo qabaate kun ammoo fayyadamtoota kamii fi gareewwan fayyadamaa bira gahuu akka danda'an too'ata.Shooraawwan bira gahinsa\"Galmee hinqaabaatiin\"qaban qindaayina sirnaa kanneen akka gucootaa,fayyadamtootaa fi gabaasaawwanii qofa bira gahuu danda'an." - label: "Shoorri kun galmeewwan akkamii rratti dhiibbaa geessisa?" + explanation: Isa kam akka galmeessu(dhimmoota,gaaffiiwwan barbaachaa ykn taateewwanii)shoorichi bira gahuu akka danda'u too'ata.Shoorichi bira gahiinsa fayyadamtootaa fi gareewwan fayyadamaa yoo qabaate kun ammoo fayyadamtoota kamii fi gareewwan fayyadamaa bira gahuu akka danda'an too'ata.Shooraawwan bira gahinsa"Galmee hinqaabaatiin"qaban qindaayina sirnaa kanneen akka gucootaa,fayyadamtootaa fi gabaasaawwanii qofa bira gahuu danda'an. + label: Shoorri kun galmeewwan akkamii rratti dhiibbaa geessisa? incident: actions: change_log: @@ -2397,71 +2667,93 @@ om: explanation: Dandeettii taatee gufachiisuu ykn kakkaasuu.Taateewwan gufatan durtii tarreeffama taatee keessatti hin mul'atan.Fayyadamtoonni calalchaatti dhimma bahuun tarreeffama taatee keessatti taateewwan qaama midhamtootaa ilaaluu ni danda'an. label: Dandeessisuu/dadhabsiisuu. export_case_pdf: - explanation: "" + explanation: 'Fayyadamaan tarreeffama taateewwanii ykn fuula taateewwan agarsissuu irraa faayila PDF ergu maddisiisuu danda''a, bakkewaan fayyadamaan qaqqabuu hunda kan of keessaa  qabu; galmee tokkoof, dachaaf, ykn galmeewwan hundaaf fayyadamaan qaqqabuu danda’u. Faayilii PDF ergu keessatti, odeeffannoon jalqaba dhimmaan tarreeffama, sana booda unka odeeffannoon irratti mul''atuun daran qindaa''a. ' label: PiiDiiEffii gara alaatti ergaa. export_csv: - explanation: "" + explanation: Fayyadamaan tarreeffama taatee ykn fuula (page) taatee agarsissuu irraa faayilii CSV ergu uumuu danda'a, bakka fayyadamaan qaqqabuu danda’u hunda of keessaa qabu, tokkoof, dachaa, ykn taateewwan fayyadamaan qaqqabu hunda. label: gatii/sona/qoodduu fi addaan bayanii alatti ergi. export_custom: label: Maamila gara alaatti ergaa. export_incident_recorder_xls: - explanation: "" + explanation: Fayyadamaan meeshaa balaa galmee MKB jedhamu fayyadamuun faayila XLS addaa erguu kan daataa waljijjiiruuf hayyamu uumuu danda'a. label: Meeshaa sagalee waraabduu xis taatee alatti ergi. + export_mrm_violation_xls: + explanation: Fayyadamaan miidhaalee MRM tiif al-ergii Excel addaa (faayilii XLS) uumuu danda'a. Raawwiin kun fuula agarsiisa Taatee fi tarree Taatee irratti argama. + label: Miidhaalee MRM gara Excel (faayilii XLS) tti erguu . export_json: - explanation: "" + explanation: Fayyadamaan tarreeffama taatee ykn fuula taatee agarsissuu irraa galmee JSON ergu uumuu danda'a, bakkeewaan fayyadamaan qaqqabuu danda’u hunda of keessaa kan qabu; tokkoof, dachaaf, ykn taateewwan hundaaf fayyadamaan qaqqabuu danda’u. Al-ergiin Kun irra caalaa warra taateewwan sirna Primero amma jiru irraa gara sirna Primero adda ta’etti, ykn gara sirna bulchiinsa odeeffannoo biraatti galchuu barbaadaniif kan ooludha. Akkaataan JSON maashiniin kan dubbifamuu fi fayyadamtoota baay'eedhaaf qabatamaa miti. label: JSON alatti ergi. export_list_view_csv: - explanation: "" + explanation: Fayyadamaan fuula tarreeffama taatee irraa faayilii CSV ergamu uumuu danda'a kunis bakkewaan walfakkaataa tarreeffama taatee irratti mul'atan of keessaa kan qabu. Fuula tarree taateewwanii irraa qofa kan raawwatamu. label: Tarreeffama mul'annoo qoodduu fi addaan bayanii alatti ergi. export_pdf: - explanation: "" + explanation: Fayyadamaan tarree taateewwanii ykn fuula taateewwan agarsissuu irraa faayilii PDF ergamu uumuu danda'a, kunis bakkewaan fayyadamaan amma jiru qaqqabuu danda’u hunda of keessaa qaba, galmee tokkoof, dachaaf, ykn galmee fayyadamaan qaqqabuu qabu hundaaf. Faayilii PDF ergamu keessatti, odeeffannoon jalqaba dhimmaan tarreeffama, sana booda unka odeeffannoon irratti mul'atuun daran qindaa'a. label: Pii Dii Effii gara alaatti ergi. export_xls: - explanation: "" - label: "" + explanation: Fayyadamaan tarreeffama taateewwanii ykn fuula taateewwanii agarsiisu irraa  faayilii XLS ergamu uumuu danda'a, kunis tuuta amala unkaalee ykn bakkeewaan of keessaa kan  qabu, tokko, dachaa, ykn haalawwan fayyadamaan qaqqabuu qabu hundaaf. Faayilii ergamu kana keessatti, tokkoon tokkoon unkaa sireessuu mataa isaa keessatti faayilii XLS keessaa bakka bu'a. Fayyadamaan unkaalee ykn bakkeewaan kamtu al-ergii keessatti hammatamuu barbaadu moodaala Al-ergii Adda fayyadamuun filachuu danda'a. Hubadhaa fayyadamtoonni unkaalee fi bakkeewaan al-ergii keessatti hammachuu kan danda'an yoo duraan dandeettii unkaalee fi bakkeewwan sana arguu qaban yeroo dhimma tokko application keessatti ilaalan qofa. + label: Excel (faayilii XLS) erguu flag: - explanation: "" + explanation: Balaa tokkotti alaabaa dabaluu danda’uu. Fayyadamtoonni hayyama kana qaban alaabaa taatee tokkotti dabalanis haquu danda'u. label: Alaabaa. import: - explanation: "" + explanation: Fayyadamaan balaa haaraa tokko ykn isaa ol faayilii CSV, Excel, ykn JSON irraa galchuudhaan akka uumuuf hayyama. Faayilli galfame odeeffannoon sirnaan akka galfamuuf *baay'ee* addatti foormaatii ta'uu qaba. Faankishiniin kun fayyadamtoota bulchiinsaa dandeettii teeknikaa olaanaa fi beekumsa gadi fageenyaa akkaataa deetaan Primero keessatti foormaatii ta'u qabaniif qofa ta'uu qaba. Fuula tarree taateewwanii irraa qofa raawwatame. label: Fichisiisi. + remove_alert: + explanation: Hayyamni kun fayyadamaan akeekkachiisa dhimma tokko irraa akka haquuf fayyada. Akeekkachiisni yeroo kutaan tokko fooyya'an, kan akka yeroo yaadannoowwan fooyya'an uumamu. Akeekkachiisni yeroo baayyee tuqaa keelloo dhimma cinatti agarsiifama. + label: Taatee irraa akeekkachiisa balleessi manage: - explanation: "" + explanation: Fayyadamaan tokko taateewwan irratti gochoota jiran hunda akka raawwatu hayyama. Hayyamni "Manage" jedhu bu'uuraan "waan hunda" jechuudha. label: Bulchi (hayyamoota gosa qabeenya kanaa hunda) read: explanation: Dandeettii taatee ilaaluu. label: Ilaalcha/Agarsiisi/mul'isi. sync_mobile: - explanation: "" + explanation: Hayyamni  kun akka waliigalaatti fayyadamaan haala moobayili ittin hojiraa oluu (application mobile) akka fayyadamu kan dandeessisu. Jalqabaaa iraatti  fayyadamaan gochoota  kan gosaa  mobayilaa agarsisuu fi kan gosaa mobayilaa hin agarsinee  "Mark for Mobile" and "Un-mark for Mobile" kanneen tarree taateewwanii fi fuula agarsiisa taateewwanii irratti mul'atan akka argu isa dandeessisa. Taatee mobaayilaaf mallattoo kaa’uun odeeffannoon waa’ee taatee sanaa meeshaa moobaayilaa fayyadamaa fi aplikeeshinii weeb gidduutti walsimsiisuu akka qabu agarsiisa; yeroo taatee mobaayilaaf mallattoo irraa kaasuun walsimsiisuun kun akka hin uumamne dhaaba. Fayyadamtoonni hayyama kana malees meeshaalee moobaayilaa isaanii akka waliigalaatti  weebsayit haala moobayili ittin hojiraa oluu (application web )waliin walsimsiisuu hin danda'an, jechuunis haala moobayili ittin hojiraa oluu mobaayilaa taateewwan bulchuuf fayyadamuu hin danda'an jechuudha. label: Meeshaa sosocho'aa wajjiin walfakkeessuu. write: - explanation: "" + explanation: Dandeettii ''Sirreessii'cuqaassuu,balaa/taatee ilaalchisee oddeeffannoo fooyya'aa fi 'ka'ii' cuqaasuu. Fayyadamaan balaan tokko akka mul'atuu fi hin mul'ane taasisuu akka danda'u taasisuu. label: Gulaali. - explanation: "" + explanation: Taatee uumame bakka bu'a. Kunniin yeroo baay’ee taateewwan miidhaa ykn jeequmsaa yoo ta’an, taateewwan akka wal arguu qaamolee seera kabachiisan waliin walsimuu danda’u. Taateewwan yeroo baayyee dhimmoota waliin kan  walqabatan dha. label: Taatee. is_manager: explanation: Shoora fayyadamaa kamiyyuu walumaagalatti fayyadamtoota biroo too'atan irratti hojirra oola.Fayyadamaan kun daash boordii fi calalchuuwwan fayyadamaan garee tokko akka bulchu taasisan akka ilaalu dandeessisa. - label: "Hoji gaggeessaadhaa?" + label: Hoji gaggeessaadhaa? managed_report: actions: + managed_report_scope: + label: ' Galmee akkamii gaheen kun hubannoo keessatti arguu danda’uu qaba?' + managed_report_scope_all: + label: Hunda + managed_report_scope_group: + label: Daataa garee irratti hundaa’e qofa + managed_report_scope_agency: + label: Daataa ejensii irratti hundaa’e qofa violations: label: Miidhaawwan/jeequmsiiwwan. gbv_statistics: label: Xiinannoo/lakkofsa miidhaa kornaayaa bu'ureeffatee. + ghn_report: + label: Hubachiisa dalgee Addunyaa + individual_children: + label: Daa'imman Dhuunfaa + violence_type_report: + explanation: Dandeettii istaatiksii gosa miidhaan irratti ilaaluu. Hayyamni kun fayyadamaan deetaa insight irraa akka erguus ni hayyama. + referrals_transfers_report: + explanation: Fayyadamtootni baay'ina dhimmoota garee fayyadamtoota tokko tokko irraa karaa garee fayyadamtoota birootti rifarii ta'ee fi dabarfame ni ilaala. matching_configuration: actions: manage: - explanation: "" + explanation: Gaaffii hordoffii fi dhimmoota gidduutti walsimsiisa argachuuf dirree/fields/  kamtu wal bira qabamee akka ilaalamu to'achuu danda'uu. kun akkaataa walsimsiisni guutummaa sirna keessatti hojjetamu waan to'atuuf, hayyamni Kun akka waliigalaatti bulchaa sirnichaa qofaaf ta'uu qaba. label: Bulchi (hayyamoota akaakuu qabeenya kanaa hunda) explanation: Dirreewwan kamiintuu gaaffiiwwan barbaachaa dhimmoottan yeroo maatii barbaaduu fi walitti makuuf fayyadan walmadaalchisanii too'ata. label: Qindaayina walsiman. metadata: actions: manage: - explanation: "" + explanation: Dandeettii unkaalee uumuu , unkaa dirree/fields/ fi barbaadotaa, gulaaluu, hiikuu fi haquu. Hubadhaa! fayyadamaan hayyama kana qabu unkaalee isaan qaqqabsiisan qofa bulchuu akka danda'u qalbefachuu qaba. Fakkeenyaaf, bulchaan biyyaalessaa tokko dandeettii unka Abbaa Galmee dhimmoota irratti arguu qofa yoo qabaate, sana booda yoomiyyuu qindeessaa unka kanaaf fooyyessuu qofa danda'u. label: Bulchi (hayyamoota qabeenya kanaa hunda) explanation: Dandeettii qindaayinaa gucoota pireemiiroo fi dirreewwanii akkasumas isaan keessatti filannoowwan barbaachaa faayidarra oolan too'ata. - label: "Gucoota,barbaachaawwan." + label: Gucoota,barbaachaawwan. module: actions: cp: @@ -2475,40 +2767,49 @@ om: potential_match: actions: read: - explanation: "" + explanation: Gaaffii Hordoffii fi Walitti dhufeenya dhimma gidduu jiru bakka bu’a. Hojii Maatii barbaduu fi Maatitti deebisuu  (FTR) tiif Walsimsiisa Ta’uu Danda’an argachuun barbaachisaa dha. Fayyadamaan unka Cuunfaa Hordoffii Dhimmoota irratti akka argu hayyama. label: Ilaalcha + view_audio: + explanation: Fayyadamaan walsimsiisa hordoffii barbaadu faayilii sagalee Gaaffii Dhimma ykn Hordoffii Walsimsiisa Danda'aa wajjin walqabate arguu danda'uu isaa to'ata. + label: Vidiyoo ilaala + view_photo: + explanation: Suura ilaala + label: Suura ilaala + manage: + explanation: Fayyadamaan tokko gochoota jiran hunda Walsimsiisa Danda'aa irratti akka raawwatu hayyama. Hayyamni "Bulchi" jedhu bu'uuraan "waan hunda" jechuudha. + label: Bulchi label: Humna dhokataa cimaa walsimaa/qixa ta'e. primero_configuration: actions: manage: - explanation: "" + explanation: Dandeettii Qindaa'inoota qusachuu, hojiirra oolchuu fi erguu. Hayyamni kun yeroo baay'ee bulchaa sirnichaaf kan eegamedha. label: Bulchi (hayyammoota gosa qabeenya kanaa hunda) - label: " Qindaayina." + label: ' Qindaayina.' referral: actions: refer: - explanation: "" - label: "Shoorri kun walharkaafuudhiinsa alaatiif faayidaa irra ooluu danda'aa?" + explanation: Kana jechuun gaheen akka filannootti "Akkaataa Fudhataa" yeroo fayyadamaan rifaralaa alaa raawwatu ni mul'ata. Yoo fayyadamaan gahee kana akka gosa rifaralaa filate, al-ergiin Primero yeroo fayyadamaan rifaralaa dhiyeessu maddisiisu odeeffannoo unkaalee gaheen kun argachuu qabu keessatti argamu qofa qabaata. Kanaafuu, fakkeenyaaf, fayyadamaan akka gosa fudhataatti "Dhiyeessaa Tajaajila Yaalaa" yoo filate, fi gaheen Dhiyeessaa Tajaajila Yaalaa unkaalee Yaaddoo Eenyummaa Bu'uuraa fi Eegumsa qofa argachuuf qaqqabummaa qabaate, faayilii al-ergii Primero rifaralaa alaaf ergu qofa ni ta'a dirree/fields/ bifa lamaan sana keessa jiran of keessaa qaba. + label: Shoorri kun walharkaafuudhiinsa alaatiif faayidaa irra ooluu danda'aa? label: Walharkaafuudhiinsa. registry_record: actions: change_log: explanation: Fayyadamaan seenaa jijiiramoota uumama isaanii irraa eegalee galmee irratti taasifaman ilaaluu danda'a.Kun ammoo sonaawwan direewwan hundaaf galmaa'an dabalata. - label: "Galmee jijjjiraa," + label: Galmee jijjjiraa, create: explanation: Dandeettii galmee irratti galmaa'an uumuu. label: Uumuu. enable_disable_record: - explanation: "" + explanation: Galmeessuu guufachisuu ykn danditti damaqisuu. Galmewwaan gufaachifamaani turaan keessatti mul’ata. Fayyadamtoonni caalali faayyadamuun galmewwaan qamaa miidhamaa taree galmee keessatti laluun ni danda’ama. label: Dandeessisuu/dadhabsiisuu. export_csv: - explanation: '' + explanation: 'fayyadamaan galmee CSV alaatti erguu taree galmewwan ykn fuula agarsisaa maddisiisuu ni danda’ama, fayyadammaan ammaa jiru kunis  dirrewwan/fields/ hundaa kan qabatee, tokko, baa’yee ykn fayyadammaa hundaaf ga’uu galmewwaan galma’aan. Hubachiisa:- garaa alatti erguu /export/ CSV kun amaloota laatiin hin tanee hin dhiyessuu. (fkn. Arabaa, Baanglaa) .' label: gatii/sona/ qoodduu fi addaan bayanii alatti ergi. export_json: - explanation: "" + explanation: Fayyadamaan tarree galmee ykn fuula agarsiisa galmee irraa alatti ergamuu/expert/ faayilii JSON uumuu danda'a, kunis dirree/fields/ fayyadamaan ammaa qaqqabummaa qabu hunda of keessaa qaba. Akkaataan JSON maashiniin kan dubbifamuu fi fayyadamtoota baay'eedhaaf qabatamaa miti. label: JSON alatti ergi. export_xls: - explanation: '' + explanation: 'Fayyadamaan tarree Galmee ykn fuula agarsiisa galmee irraa alatti erguu/export/ faayilii XLS uumuu danda''a, kunis dirree/fields/  hunda fayyadamaan ammaa qaqqabummaa qabu of keessaa qaba. HUBACHIISA: Akkaataan XLS amaloota/characters/  Laatiin hin taane (fkn. Arabaa, Baanglaa) bifa dubbifamuu danda''uun agarsiisa, alatti erguu/export/  CSV garuu hin agarsiisu.' label: Eksi ellii(faayila XLS)alatti erguu. flag: explanation: Dandeettii alaabaa/mallattoo gara galmee itti galmeessaniitti ida'uu.Fayyadamtoonni hayyama kana qaban alaabaawwan gara galmee mana galmeetti ida'anii haquu/kaasuu danda'u. @@ -2520,34 +2821,90 @@ om: explanation: Dandeettii galmeewwan irratti galmaa'an arguu/ilaaluu. label: Ilaalcha. write: - explanation: "Dandeettii furtuu\"gulaaluu\"jedhu tuquu,waayee ragaa odeeffannoo mana galmee ammayyoomsuu fi \"olkaa'i\"jedhu tuquu." + explanation: Dandeettii furtuu"gulaaluu"jedhu tuquu,waayee ragaa odeeffannoo mana galmee ammayyoomsuu fi "olkaa'i"jedhu tuquu. label: Gulaali. sync_mobile: explanation: Fayyadamaan sararaan ala itti fayyadamuuf akka tolu galmeewwan iratti galmaa'an iddoo dhoksaa akka kaayu dandeessisaan. label: Sararaan alatti mallattoo kaayaa. - explanation: "" + explanation: 'kun akka dhimmatti ykn akka tatetti yoo jirataan galmee waliin walitti fiduu kan isaan barbachisaan,baay’ee baay’ee fi irraa deddebiin odeeffanoo haraan  namni dhunfaan ykn  dhabbanni bakka bu’uu danda’a.  isaan waraa barbadaan waliin wali fakkatodha,  haa ta’u malee tokkon tokkon galteedhaaf tuuta odeeffannoo walxaxaa ta''e qabu..  ' label: Galmee ittiin galmaa'an. + family: + actions: + change_log: + explanation: Fayyadamaan seenaa jijjiirama hunda erga galmeen uumamee kaasee arguu danda'a. Kunis gatiiwwan hojii dirree hundaaf galmaa'an of keessatti qabata. + label: Loogoo jijjiirri + create: + explanation: Dandeettii to Maatii tokko uumuu + label: Uumi + enable_disable_record: + explanation: Dandeettii Maatii tokko akka hin hojjanne gochuu ykn dandeessisuu. Maatiin "akka hin hojjanne taasifame" durtii tarree Maatii keessatti hin mul'atan. Fayyadamtoonni Maatii hojii dhaban tarree Maatii keessatti calaqqee fayyadamuun arguu danda'u. + label: Dandeessisuu/Akka hin hojjenne gochuu + export_csv: + explanation: 'Fayyadamaan faayilii CSV erguu tarree Maatii ykn fuula agarsiisa Maatii irraa uumuu danda''a, kunis man''eewwan hunda fayyadamaan ammaa qaqqabummaa qabu of keessaa qaba, tokkoof, baay''ee, ykn Maatii hundaaf kan fayyadamaan qaqqabummaa qabu. HUBACHIISA: Al-ergiin CSV arfiilee Laatiin hin taane hin agarsiisu (fkn. Afaan Arabaa, Baanglaa) .' + label: CSV erguu + export_json: + explanation: Fayyadamaan faayilii JSON erguu tarree Maatii ykn fuula agarsiisa Maatii irraa uumuu danda'a, kunis man'eewwan hunda fayyadamaan ammaa qaqqabummaa qabu of keessaa qaba. Akkaataan JSON maashiniin kan dubbifamuu fi fayyadamtoota baay'eedhaaf qabatamaa miti. + label: alatti ergi JSON + export_xls: + explanation: 'Fayyadamaan faayilii XLS erguu tarree Maatii ykn fuula agarsiisa Maatii irraa uumuu danda''a, kunis man''eewwan hunda fayyadamaan ammaa qaqqabummaa qabu of keessaa qaba. HUBACHIISA: Akkaataan XLS arfiilee Laatiin hin taane (fkn. Arabic, Bangla) bifa dubbifamuu danda''uun agarsiisa, al-ergiin CSV garuu hin agarsiisu.' + label: Excel (faayilii XLS) erguu + export_list_view_csv: + explanation: Fayyadamaan faayilii CSV fuula tarree Maatii irraa kan man'eewwan walfakkaatan kan fayyadamaa sanaaf tarree maatii irratti mul'atan of keessaa qabu uumuu danda'a. Fuula tarree Maatii qofa irraa raawwatame. + label: Mul'ata tarree erguu CSV + export_pdf: + explanation: Fayyadamaan faayilii PDF erguu tarree Maatii ykn fuula agarsiisa maatii irraa uumuu danda'a, kunis man'eewwan hunda fayyadamaan ammaa qaqqabummaa qabu, galmee tokkoof, baay'ee, ykn hunda fayyadamaan qaqqabummaa qabuuf. Faayilii PDF erguu keessatti, odeeffannoon jalqaba maatiidhaan tarreeffama, achiis unka odeeffannoon irratti mul'atuun caalaatti qindaa'a. + label: PDF erguu + export_custom: + label: aadaa erguu + flag: + explanation: Dandeettii Maatii tokkotti alaabaa dabaluu. Fayyadamtoonni hayyama kana qaban alaabaa Maatii tokkotti dabalanis haquu danda'u. + label: Alaabaa + manage: + explanation: Fayyadamaan tokko gochoota jiran hunda Maatii irratti akka raawwatu hayyama. Hayyamni "Bulchaa" jedhu bu'uuraan "waan hunda" jechuudha. + label: Bulchi (hayyama hunda gosa qabeenya kanaaf) . + read: + explanation: Dandeettii Maatii arguu + label: Ilaaluu + write: + explanation: Dandeettii "gulaaluu" button cuqaasuu, odeeffannoo waa'ee Maatii haaromsuu fi "kaa'ii " cuqaasuu. + label: Gulaaluu + sync_mobile: + explanation: Fayyadamaan galmeewwan maatii sarara ala fayyadamuuf akka kuusu hayyama. + label: Toora Intarneeta Alaa jechuun mallattoo godhi + close: + explanation: Fayyadamaan haalata maatii banaa gara cufameetti akka saagu hayyama. + label: Cufuu + reopen: + explanation: Fayyadamaan maatii yeroo ammaa cufame akka banu hayyama. + label: Irra deebi'iin banaa + case_from_family: + explanation: Fayyadamtoonni galmee Maatii keessaa unka xiqqaa Miseensoota Maatii irraa haala haaraa akka uumuuf hayyama. + label: Dhimma Uumuu + label: Maatii report: actions: create: explanation: Dandeettii gabaasa haaraa uumuu.Fayyadaman tokko yoo gabaasa uumuu gabaasaawwaniif fayyadamtoota "dubbisi" ykn "garee dubbisi" jedheen hundaafuu ni mul'ata. label: Uumuu. group_read: - explanation: "" + explanation: Gabaasa hunda ilaaluu danda’uu. Lakkoofsi gabaasa tokkoon tokkoo keessatti galmeewwan fayyadamtoota gareewwan fayyadamtoota fayyadamaa ammaa keessa jiraniif dhaqqabamaa ta'an qofa calaqqisiisu. Hayyamni kun yeroo baayyee bulchitoota naannoo, naannoo, ykn ejensii raawwii garee ofii isaanii ykn dhaabbata isaanii irratti hubannoo argachuuf barbaadaniif fayyadama. Hayyamni kun fayyadamaan dandeettii deetaa gabaasa irraa erguufis ni kenna. label: Ilaalcha (deetaa garee irratti hundaa'e) manage: explanation: Fayyadamaan tarkaanfiiwwan ejensiiwwan irra jiran hundaa akka raawwatu dandeessisaan.Bu'urarraa hayyama"to'achuu/bulchuu"jechuun "Waan hunda"jechuudha. label: Bulchi (hayyamoota gosa qabeenya kanaa hunda) read: - explanation: "" + explanation: Gabaasa hunda ilaaluu danda’uu. Lakkoofsi gabaasa tokkoon tokkoo keessatti galmeewwan fayyadamaan ammaa qaqqabummaa qabu qofa osoo hin taane, galmeewwan sirnicha keessa jiran hunda ni calaqqisiisu. Hayyamni kun fayyadamaan dandeettii deetaa gabaasa irraa erguufis ni kenna. label: Ilaalcha. write: explanation: Dandeettii gabaasaawwaan hundaa gulaaluu(kanneen fayyadamtoota biraatiin uumaman dabalatee) label: Gulaali. + agency_read: + explanation: Gabaasa hunda ilaaluu danda’uu. Lakkoofsi gabaasa tokkoon tokkoon keessatti argamu galmeewwan fayyadamtoota Ejensii fayyadamaa ammaa keessa jiraniif dhaqqabamaa ta’an qofa kan calaqqisiisu ta’a. Hayyamni kun yeroo baayyee bulchitoota ejensiitif fayyadama. + label: Ilaaluu (daataa ejensii irratti hundaa’e) . explanation: Meeshaa xiinxala deetaa waliigalaa.Bakka bu'insaawwan ragaa/deetaa gabatee fi caatoo of keessatti ammata/dabalata. label: Gabaasa. reporting_location_level: - explanation: '' + explanation: 'Kunis sadarkaa iddoowwan Gahee kanaaf daashboordii, filtara, moodaalota rifaralaa, fi moodaalota jijjiirraa keessatti mul''atan ni to''ata. Yoo dirree kana duwwaa dhiifte, Gaheen kun sadarkaa Bakka Gabaasaa durtii sirnichaa ni arga.' label: Shoora kanaaf gabaasa gochuudhaaf bakka akkamiittu faayidaa irra ooluu qaba. role: actions: @@ -2567,20 +2924,20 @@ om: explanation: 'Fayyadamaan tokko dalagaawwan shooraawwan irra jiran hundumaa akka raawwatu dandeessisaan.Hayyamni "bulchi"jechuu "waan hunda"jechuudha.Barbaachisaa:Kun ammoo dandeettii shooraawwan uumuu fi haquu kenna.' label: Bulchi ( hayyamoota gosa qabeenya kanaa hunda) permitted_roles: - explanation: "" + explanation: Gaheen tokko gahee tokko irratti gochoota armaan olii kamiyyuu raawwachuuf dandeettii yoo qabaate, gochoota sana gaheewwan tarree kana keessatti ibsaman irratti raawwachuu ni danda’u. Kanaafuu, fakkeenyaaf, yoo gaheen tokko gaheewwan irratti hayyama "Dubbisi" fi "Ramadi" qabaate, garuu "Hojjetaa Dhimmaa CP" fi "Hogganaa CP" qofa akka "Gahee Bulfame" isaatti tarreeffame qabaate, kanneen qofa arguu danda'a gahee lama, fi fayyadamtoota haaraa gahee lamaan sanaaf qofa ramaduu danda'a. Yoo gaheen walfakkaataan "Gahee Bulfaman" ifteessame hin qabu ta'e, gahee hunda arguu ni danda'a akkasumas herrega fayyadamaa haaraa gahee kamiyyuu sirna keessatti uumuu ni danda'a. label: Shoorawwan biraa shoora kanaan bulan. read: explanation: Dandeettii shooraawwan arguu/ilaaluu. label: Ilaalcha. write: - explanation: "Dandeettii furtuu fuula shoora agarsiisuu irratti tuquu danda'uu,hayyammoota shooraa ammayyeessuu fi shooricha olkaa'uu." + explanation: Dandeettii furtuu fuula shoora agarsiisuu irratti tuquu danda'uu,hayyammoota shooraa ammayyeessuu fi shooricha olkaa'uu. label: Gulaali. explanation: Fayyadamaan tokko piremeeroo keessatti tarkaanfiiwwan kamiin fudhachuu akka qabu labsa/ibsa. label: Shoora/shooraawwan. system: actions: manage: - explanation: "Dandeettii sirna odeeffannoo qunnamtii,beeksisa durtii fi qindaayinootaIi meelii baga nagaan dhuftanii fi kaadimaa walsimatanii odeeffannoo ilaaluu fi ammayyeessuu danda'uu.Hayyamni kun yeroo baayi'ee bulchaa sirnichaa qofaaf kan eegameedha." + explanation: Dandeettii sirna odeeffannoo qunnamtii,beeksisa durtii fi qindaayinootaIi meelii baga nagaan dhuftanii fi kaadimaa walsimatanii odeeffannoo ilaaluu fi ammayyeessuu danda'uu.Hayyamni kun yeroo baayi'ee bulchaa sirnichaa qofaaf kan eegameedha. label: Bulchi (hayyamoota gosa qabeenya kanaa hunda) explanation: Sirna walmakee-qindaayinoota bal'aa qabu. label: Sirna. @@ -2593,34 +2950,34 @@ om: explanation: Dandeettii gaaffii barbaachaa uumuu. label: Uumi. enable_disable_record: - explanation: "" + explanation: Dandeettii Gaaffii Hordoffii hanqisuu ykn dandeessisuu. Gaaffiiwwan Hordoffii "Disabled" tarree Gaaffiiwwan Hordoffii keessatti durtii hin mul'atan. Fayyadamtoonni Gaaffii Hordoffii hanqifame tarree Gaaffii Hordoffii keessatti calaqqee hojiirra oolchuudhaan arguu danda'u. label: Dandeessisi/dammaqsi/gufachiisi. export_case_pdf: - explanation: "" + explanation: Fayyadamaan tarree gaaffiiwwan hordoffii ykn fuula agarsiisa gaaffii hordoffii irraa faayilii PDF erguu uumuu danda'a, kunis man'eewwan hunda fayyadamaan ammaa qaqqabummaa qabu, galmee tokkoof, baay'ee, ykn hunda fayyadamaan qaqqabummaa qabuuf. Faayilii al-ergii PDF keessatti, odeeffannoon jalqaba haala tokkoon tarreeffama, achiis unka odeeffannoon irratti mul'atuun caalaatti qindaa'a. label: PiiDiiEffii gara alaatti ergi. export_csv: - explanation: "" + explanation: Fayyadamaan tarree gaaffii hordoffii ykn fuula agarsiisa gaaffii hordoffii irraa erguu faayilii CSV uumuu danda'a, kunis man'eewwan hunda fayyadamaan ammaa qaqqabummaa qabu, tokkoof, baay'ee, ykn gaaffii hordoffii hundaaf fayyadamaan qaqqabummaa qabuuf. label: Gatii/sona/ qoodduu fi addaan bayanii alatti ergi. export_custom: - explanation: "" + explanation: Fayyadamaan tarree gaaffii hordoffii ykn fuula agarsiisa gaaffii hordoffii irraa erguu faayilii XLS uumuu danda'a, kunis tuuta amala unkaalee ykn man'eewwan of keessaa qaba, gaaffii hordoffii tokkoof, baay'ee, ykn hundaaf fayyadamaan qaqqabummaa qabuuf. Al-ergii kana keessatti, tokkoon tokkoon unkaa caancala mataa isaa keessatti faayilii XLS keessaa bakka bu'a. Fayyadamaan unkaalee ykn man'eewwan kam akka al-ergii keessatti hammatamuu barbaadu moodaala Al-ergii Adda fayyadamuun filachuu danda'a. Maaloo hubadhu fayyadamtoonni unkaalee fi man'eewwan al-ergii keessatti hammachuu kan danda'an yoo duraan dandeettii unkaalee fi man'eewwan sana yeroo gaaffii hordoffii aplikeeshinii keessatti ilaalan qabaatan qofa. label: Maamila gara alaatti ergi. export_json: - explanation: "" + explanation: Fayyadamaan tarree gaaffii hordoffii ykn fuula agarsiisa gaaffii hordoffii irraa faayilii JSON erguu danda'a, kunis man'eewwan hunda fayyadamaan ammaa qaqqabummaa qabu, tokkoof, baay'ee, ykn gaaffii hordoffii hundaaf fayyadamaan qaqqabummaa qabuuf. Al-ergiin kun irra caalaa warra gaaffii hordoffii sirna Primero amma jiru irraa erguu barbaadaniif ergasii gara sirna Primero adda ta'etti galchuu barbaadaniif, ykn gara sirna bulchiinsa odeeffannoo biraatti. Akkaataan JSON maashiniin kan dubbifamuu fi fayyadamtoota baay'eedhaaf qabatamaa miti. label: JSON alatti ergi. export_list_view_csv: - explanation: "" + explanation: Fayyadamaan faayilii CSV fuula tarree gaaffii hordoffii irraa kan man'eewwan walfakkaatan kan fayyadamaa sanaaf tarree gaaffii hordoffii irratti mul'atan of keessaa qabu uumuu danda'a. Fuula tarree gaaffii hordoffii qofa irraa raawwatame. label: Tarreeffama mul'annoo gatii/sona/qoodduu fi kan addaan bayanii alatti ergi. export_pdf: - explanation: "" + explanation: Fayyadamaan tarreeffamaa gaaffiiwwan maatii barbaaduu ykn fuula (page)  gaaffiiwaan maatii barbaaduu agarsissuu irraa  faayilii PDF ergamu uumuu danda'a, kunis  bakkeewwan hunda fayyadamaan yeroo amma jiru  qaqqabuu dandaa’u of keessaa qaba, galmee tokkoof, dachaa, ykn galmee fayyadamaan qaqqabuu qabu hundaaf. Faayilii al-ergii PDF keessatti, odeeffannoon jalqaba dhimmaan tarreeffama, sana booda unka odeeffannoon irratti argamuun daran qindaa'a. label: PiiDiiEffii gara alaatti ergi. export_xls: - explanation: '' + explanation: 'Fayyadamaan tarreeffama Gaaffii maatii barbaaduu ykn fuula (page)  Gaaffii maatii barbaaduu agarsiissu irraa  faayilii XLS ergamu  uumuu danda''a, kunis bakkeewwan hunda fayyadamaan yeroo ammaa  jiru  qaqqabuu danda’u of keessaa qaba, tokkoof, dachaa, ykn Gaaffiiwwan maatii barbaaduu  hundaaf fayyadamaan qaqqabuu danda’u. faayilii ergamu kana keessatti, tokkoon tokkoon unkaa caancala mataa isaa keessatti faayilii XLS keessaa bakka bu''a. HUBACHIISA: Akkaataan XLS amala Laatiin kan hin qabne (fkn. Arabaa, Baanglaa) bifa dubbifamuu danda''uun agarsiisa, al-ergiin CSV garuu hin agarsiisu.' label: Eksi ellii(faayila XLS) gara alaatti ergi. flag: explanation: Dandeettii alaabaa/mallattoo gara gaaffii barbaachaatti dabaluu.Fayyadamtoonni hayyama kana qaban ammallee alaabaawwan/mallattoowwan gara gaaffii barbaachaatti ida'an haquu/kaasuu danda'an. label: Alaabaa. import: - explanation: "" + explanation: Fayyadamaan CSV, Excel, ykn JSON irra faayilii galchuudhaan keessi haaraa tokkoo fi isaa ol akka uummu hayyama. Odeeffannoon sirriitti galfamuuf faayiliin galfamu *baay'ee* addatti baaffamee foormaatii ta'uu qaba. Faankishiniin kun fayyadamtoota bulchiinsaa dandeettii teeknikaa olaanaa qabanii fi akkaataa daataan Primero keessatti itti foormaatii ta’u beekumsa gadi fageenya qabu qofaaf ta’uu qaba. Fuula tarreeffamaa dhimmootaa irraa qofa raawwatama. label: Fichisiisi/seensis. manage: explanation: Fayyadamaan tarkaanfiiwwan hunda gaaffii barbaachaa irra jiran akka raawwattu dandeessissaan.Hayyama "To'achuu/bulchuu" jechuun barbaachisummaadhaan "Waan hunda"jechuudha. @@ -2629,20 +2986,20 @@ om: explanation: Dandeettii gaaffii barbaachaa agarsiisuu.Shooraawwan dandeettii gaaffiiwwan barbaachaa ilaaluu danda'an akkasuma dandeettii akaakuu galmee humna kuufamaa qabu ilaaluu qabaachutu irra jiraata. label: Ilaalcha. write: - explanation: "Dandeettii furtuu \"gulaalii\"tuquu.Waayeegaaffii barbaachaa ragaa odeeffannoo ammayyoomsuu fi \"ol kaa'ii\"tuquu,akkasumas fayyadamaan gaaffii barbaachaa akka dhaamsu ykn akka kakkaasu dandeessisan." + explanation: Dandeettii furtuu "gulaalii"tuquu.Waayeegaaffii barbaachaa ragaa odeeffannoo ammayyoomsuu fi "ol kaa'ii"tuquu,akkasumas fayyadamaan gaaffii barbaachaa akka dhaamsu ykn akka kakkaasu dandeessisan. label: Gulaali. explanation: Nama agarsiisuu fi deebisanii walitti makuu dhimma nama waliin hinjirree fi addaan bayanii deebi'ee walitti fiduuf yaaluu bakka bu'a. label: Gaaffii barbaachaa. transfer: actions: transfer: - explanation: "" - label: "Shoorri kun dabarsaawwan alaatiif faayidaa irra ooluu danda'aa?" + explanation: Kana jechuun gaheen akka filannootii "Akkaataa Fudhataa" yeroo fayyadamaan rifaralaa alaa raawwatu ni mul'ata. Yoo fayyadamaan gahee kana akka gosa dabarsootti filate, al-ergiin Primero yeroo fayyadamaan jijjiirraa dhiyeessu maddisiisu odeeffannoo unkaalee gaheen kun qaqqabummaa qabu keessatti argamu qofa qabaata. Kanaafuu, fakkeenyaaf, fayyadamaan akka gosa fudhataatti "Dhiyeessaa Tajaajila Yaalaa" yoo filate, fi gaheen Dhiyeessaa Tajaajila Fayyaa unkaalee Yaaddoo Eenyummaa Bu'uuraa fi Eegumsa qofa argachuu yoo qabaate, faayilii al-ergii Primero dabarsoo alaatiif ergu qofa ta'a bakkeewwan bifa lamaan sana keessa jiran of keessaa qaba. + label: Shoorri kun dabarsaawwan alaatiif faayidaa irra ooluu danda'aa? label: Dabarsa. user: actions: agency_read: - explanation: "" + explanation: Ejensii fayyadamtoota amma fayyadamaa jiran keessatti dandeettii herreega fayyadamtootaa ilaaluu. Kunis herrega fayyadamaa kam irratti fayyadamaan gochoota biroo raawwachuu akka danda'us dhiibbaa qaba. Fakkeenyaaf, fayyadamaan fayyadamtoota irratti hayyama "Barreessuu" yoo qabaate, Aakkasumaas hayyama Dubbisaa Ejensii yoo qabaate, herrega fayyadamaa ejensii mataa isaanii keessa jiran qofa gulaaluu danda'u. Haaluma walfakkaatuun, fayyadamaan fayyadamtoota irratti hayyama "Manage" yoo qabaate, garuu hayyama "Agency Read" yoo qabaate, fayyadamtoota ejensii mataa isaanii qofaaf uumuu danda'u. label: Ilaalcha (Ejensicha keessatti) create: explanation: Dandeettii enyummeessa/herrega fayyadamaa uumuu. @@ -2654,14 +3011,14 @@ om: explanation: dandeettii eenyumeessaawwan/herrega fayyadamaa ilaaluu.Durtiidhaan fayyadamaan kamiiyyuu dandeettii eenyummeessa/herrega mataa isaanii (fknf. iggitaa.Iimeelii)ilaaluu fi odeeffannoo/ragaa gulaaluu qaban. label: Ilaalcha/agarsiisi. write: - explanation: "Dandeettii furtuu fuula agarsiistuu fayyadamaa irratti \"gulaali\"jedhu tuquu,waayee ammayyomsuu ragaa fayyadamaa fi olkaa'ii. Maaloo hayyamni kun dandeettii herregaawwan fayyadamaa gufachiisuu akka kennuu danda'u yaadadhaa." + explanation: Dandeettii furtuu fuula agarsiistuu fayyadamaa irratti "gulaali"jedhu tuquu,waayee ammayyomsuu ragaa fayyadamaa fi olkaa'ii. Maaloo hayyamni kun dandeettii herregaawwan fayyadamaa gufachiisuu akka kennuu danda'u yaadadhaa. label: Gulaali. explanation: Herrega fayyadamaa dhuunfaa bakka bu'a. label: Fayyadamtoota. user_group: actions: assign: - explanation: "" + explanation: Yeroo herrega fayyadamaa uumtu ykn gulaaltu dandeetii gareewwan fayyadamtootaa filachuu. Hubadhaa, fayyadamaan sadarkaa qaqqabummaa "galmeewwan ykn fayyadamtoota garee koo keessa jiran qofa" yoo qabaate, herrega fayyadamaa isaan uumuu ykn gulaaluuf garee fayyadamaa *ofii isaanii* keessaa tokko ykn isaa ol qofa filachuu akka danda'u. Kana jechuun hogganaan dandeettii gareewwan fayyadamtootaa ramaduu qabu tokko gareewwan fayyadamtootaa hogganaan yeroo ammaa keessa jirutti fayyadamaa dabaluu qofa danda'a ture. Hayyamni kun gahee kamiyyuu kan herrega fayyadamaa uumuu ykn gulaaluu ta'uuf barbaachisaadha. label: Ramadi. create: explanation: Dandeettii garee fayyadamaa uumuu. @@ -2696,7 +3053,6 @@ om: label: Haqi. manage: label: Bulchi (hayyamoota gosa qabeenya kanaa hundaaf) - explanation: activity_log: actions: transfer: @@ -2704,14 +3060,13 @@ om: label: Dabarsaawwan. manage: label: Bulchi (hayyamoota gosa qabeenya kanaa hunda) - explanation: label: Galmee sosochii/hojii. potential_match: case_id: Eenyummeessaa dhimmaa. child_age: Umurii child_gender: Kornaayaa. - child_id: "# eenyumeessaa daa'imaa." - inquirer_id: "# eenyummeessaa gaafataa." + child_id: '# eenyumeessaa daa''imaa.' + inquirer_id: '# eenyummeessaa gaafataa.' inquirer_tr_name: Gaaffii barbaachaa. inquiry_date: Guyyaa gaaffii. name: Maqaa. @@ -2723,10 +3078,10 @@ om: likelihood_likely: Tarii. likelihood_possible: Nidanda'ama. potential_matches: - display: "Firoomsaawwan %{type}%{id}walgituu danda'an mul'isuu irratti." + display: Firoomsaawwan %{type}%{id}walgituu danda'an mul'isuu irratti. reassign: multiple_error: Dogoggora ta'e uumameera.%1 (galmeewwan- filadhaa) Dhimmi/dhimmootni hin hin ramadamine. - multiple_successfully: '%{select_records}Dhimmotni haala milkaa''aan itti ramadamaniiru.' + multiple_successfully: Primero Dhimma irra deebi'ee%{select_records} ramadaa jira. Dhimmi kun hundi haaromfamuuf daqiiqaa hedduu fudhachuu danda’a notes_label: Yaadannoowwan. successfully: Milkaa'inaan irradeebi'amee ramadameera. user_mandatory_label: Fudhataan barbaachisaadha. @@ -2753,14 +3108,14 @@ om: type_of_recipient: Akaakuu fudhataa. type_of_referral_required: Akaakuun walharkaafuudhiinsaa ni barbaachisa. agency_label: Ejensii. - is_remote_label: "Gara sirna fagoo mul'isaa jirtuu?" + is_remote_label: Gara sirna fagoo mul'isaa jirtuu? location_label: Iddoo. notes_label: Yaadannoo. notes_on_referral: Yaadannoo walitti kenna irratti. note_on_referral_from_provider: Yaadannoo walharkaafudhiinsa irratti dhiheessaa tajaajilaa irraa. provided_consent_label: Eeyyamni gucoota keessatti hinkennamne. recipient_label: Fudhataa. - refer_anyway_label: "Maalumaafuu eeraai?" + refer_anyway_label: Maalumaafuu eeraai? service_label: Tajaajila. success: '%{record_type}%{id}Haala milkaa''aan dabarsameera/akeekameera/.' user_mandatory_label: Fudhataan barbaachisaadha. @@ -2774,12 +3129,12 @@ om: date: Guyyaa. month: Ji'a. quarter: Kurmaana. - quarter_abbr: "K1%{Kurmaana}" + quarter_abbr: K1%{Kurmaana} week: Torbee/torban. year: Bara/waggaa. description: Ibsa. disabled: - explanation: "Gabaasa kana yoo gufachiistan,gabaasaawwan jiran keessatti hin mul'atu." + explanation: Gabaasa kana yoo gufachiistan,gabaasaawwan jiran keessatti hin mul'atu. label: Qaama miidhamaa. exclude_empty_rows: Sarara duwwaa hin agarsiisin. disaggregate_by: Garee bo'oo isaaniitiin. @@ -2788,7 +3143,7 @@ om: label_new: Calallii gabaasa haaraa. attribute: Calaltuu. value: Isa waliin. - not_null: "Duwwaa/banaa miti?" + not_null: Duwwaa/banaa miti? less_than: Isaa gadi. greater_than: Isarra caala/isaa ol. equal_to: Walqixa. @@ -2796,10 +3151,10 @@ om: is: ..dha. before: Duratti. after: Booda. - delete_filter_message: "Dhugumatti calallii kana haquu barbaaddaa?" + delete_filter_message: Dhugumatti calallii kana haquu barbaaddaa? group_ages: Daangaawwan umurii fayyadamaa. group_dates_by: Daangaawwan guyyaa fayyadamaa. - is_graph: "Caatoo maddisiisuu?" + is_graph: Caatoo maddisiisuu? messages: delete_success: Gabaasni haala milkaa'aan haqameera. success: Gabaasni haala milkaa'aan uumameera. @@ -2813,16 +3168,17 @@ om: record_type: Akaakuu/gosa galmee. total: Waliigala. value: Sona/gatii. + incomplete_data: Daataa Guutuu Hin Taane reports: delete_report: Gabaasa haqi. - delete_report_message: "Dhugumatti gabaasa kana haquu barbaaddaa?Haquu duubatti deebisuun hin danda'amu.Gabaasicha haquudhaaf ishii tole jettu tuqi." + delete_report_message: Dhugumatti gabaasa kana haquu barbaaddaa?Haquu duubatti deebisuun hin danda'amu.Gabaasicha haquudhaaf ishii tole jettu tuqi. label: Gabaasaawwan. register_new_report: Gabaasa uumaa. translations: edit: Hiikaawwan gulaali. manage: Hiikaawwan bulchuu. select_language: Qooqa filadhaa. - error_loading: "Gabaasa(gabaasawwan )fe'insa dogongora. " + error_loading: 'Gabaasa(gabaasawwan )fe''insa dogongora. ' request_transfer: notes_label: Yaadannoo. submit_label: Gaaffii erguu. @@ -2836,23 +3192,23 @@ om: description: Ibsa. edit: Shoora gulali. error_in_updating: Dogongora tarreeffamoota shooraa ammayeessuu irratti uumame. - group_permission_label: "Shoorri kun galmeewwan maal irratti dhiibbaa uumuu danda'a?" + group_permission_label: Shoorri kun galmeewwan maal irratti dhiibbaa uumuu danda'a? label: Shoora/gahee. manager: Hoji gaggeessaa. messages: - confirmation: "Dhugumatti shoora kana haquu barbaaddaa?Haquun duubatti deebi'uu hindanda'u.Shora san haquudhaaf tole kan jedhu tuqi." + confirmation: Dhugumatti shoora kana haquu barbaaddaa?Haquun duubatti deebi'uu hindanda'u.Shora san haquudhaaf tole kan jedhu tuqi. created: Shoorri haala milkaa'aan uumameera. deleted: Shoorri haala milkaa'aan haqameera. updated: Shoorri haala milkaa'aan ammayyoomeera. name: Maqaa. - referral_label: "Shoorri kun walharkaafuudhiinsaaf faayidaa irra ooluu danda'aa?" - reporting_location_level_label: "Shoora kanaaf gabaasa gochuuf iddoo akkamiittu faayidaa irra ooluu qaba?" + referral_label: Shoorri kun walharkaafuudhiinsaaf faayidaa irra ooluu danda'aa? + reporting_location_level_label: Shoora kanaaf gabaasa gochuuf iddoo akkamiittu faayidaa irra ooluu qaba? role_ids_label: Shooraawwan biraa shoora kanaan bulan. successfully_updated: Tarreeffamotni shooraa haala milkaa'aan ammayyoomeera. - transfer_label: "Shoorri kun dabarsaaf faayidaa irra ooluu danda'aa?" + transfer_label: Shoorri kun dabarsaaf faayidaa irra ooluu danda'aa? hide: Dhoksuu. read: Mul'isi. - read_write: "Agarsiisiitii gulaali. " + read_write: 'Agarsiisiitii gulaali. ' roles: label: Shooraawwan. saved_search: @@ -2861,7 +3217,7 @@ om: no_filters: Calalliiwwan filatamaan hinjiran. save_success: Barbaachi haala milkaa'aan kaa'amaniiru. saved_searches_tab: Barbaachawwan ol'kaayaman. - title_description: "Dhugumatti barbaacha ol kaa'ame kana haquu barbaaddaa?" + title_description: Dhugumatti barbaacha ol kaa'ame kana haquu barbaaddaa? title_modal: Barbaachawwan ol'kaayaman haqaa. saved_searches: no_save_searches: Barbaachaawwan ol'kaayaman hin qabdan. @@ -2884,7 +3240,7 @@ om: label: Qindaa'inooota sirnaa. task: due_date: Guyyaa dhumaa itti galchan. - id: "# eenyumeessaa." + id: '# eenyumeessaa.' name: Maqaa priorities: high_level: Ol'aanaa. @@ -2913,6 +3269,10 @@ om: match: Firoomsuu/walsimsiisuu. matches: Walsimaa. unmatch: Kan wal hin simne. + tracing_request_photos: Suuraalee Gaaffii barbaaduu kanaaf + case_photos: Suuraalee Dhimma kanaaf + tracing_request_audios: Sagalee Gaaffii barbaaduu kanaaf + case_audios: ' Dhimma kanaaf sagalee' messages: already_matched: Gaafataa mucaa kana barbaadu waliin durumaanuu sirnicha keessa walsimni jira. disabled: Gaaffiin barbaachaa gufateera. @@ -2921,8 +3281,8 @@ om: creation_success: Galmeen gaaffii barbaachaa haala milkaa'aan uumameera. update_success_queue: 'Gaaffiin barbaachaa%{record_id} seenaaduubee keessatti haala milkaa''aan ammayyoomaniiru.' creation_success_queue: Galmeen gaaffii barbaachaa haala milkaa'aan duub duubee keessatti uumameera. - match_action: "Barbaacha dhimma wajjiin %{trace_id}%{record_id}haala milkaa'aan walgitan." - unmatch_action: "Barbaacha dhimma wajjiin %{trace_id}%{record_id}haala milkaa'aan wal hingitne." + match_action: Barbaacha dhimma wajjiin %{trace_id}%{record_id}haala milkaa'aan walgitan. + unmatch_action: Barbaacha dhimma wajjiin %{trace_id}%{record_id}haala milkaa'aan wal hingitne. registry_record: messages: update_success: 'galmeen warraabbii %{record_id}haala milkaa''aan ammayyoomeera.' @@ -2937,6 +3297,7 @@ om: enable_dialog_title: Gaaffii barbaachaa milkaa'e. enable_success: Haala milkaa'aan gaaffiin barbaachaa ta'eera/dammaqeera. id: Eenyumeessaa. + complete: Toora intarneetii Alaa Ni Argama filter_by: by_date: Guyyaan. location_separation: Iddoo addaan bahinsaa. @@ -2954,6 +3315,7 @@ om: show_tracing_request: 'eenyumeessaa gaaffii barbaachaa/faana dhawuu%{short_id}' tracing_requests: Gaaffiwwan barbaachaa. export: Alatti ergi. + sort_by: akkaatan secca'uu registry_records: id: Lakkoofsa eenyummaa. label: Galmeewwan ittiin galmaa'an. @@ -2969,6 +3331,7 @@ om: enable_dialog_title: Galmee ittiin galmaa'an jabeessi/dammaqsi. enable_dialog: Ok tuquun haala galmee ittiin galmaa'anii kana gara dandeessisuutti jijjiira. enable_success: Galmee galmeessaa haala milkaa'aan qophaa'e. + complete: Toora intarneetii Alaa Ni Argama filter_by: by_date: Guyyaan. status: Haala. @@ -2979,22 +3342,58 @@ om: export: Gara alaatti erguu. mark_for_offline: title: Sararaan alatti mallattoo kaa'aa. - text: "Dhugumatti yeroo sararaan ala taatanitti galmeewwan ittiin galmaa'an kanneen fayyadamuuf mallattoo kaayuu barbaadduu?" + text: Dhugumatti yeroo sararaan ala taatanitti galmeewwan ittiin galmaa'an kanneen fayyadamuuf mallattoo kaayuu barbaadduu? success: Galmeewwan ittiin galmaa'an haala milkaa'aan akka sararaan alatti faayidaa irra akka oolan mallattoon irra kaayameera. + families: + id: Waraqaa eenyummaa + label: Maattiiwwan + family_id: Waraqaa Eenyummaa maatii + family_number: Laakkofsa maatii + family_name: Maqaa Maatii + family_registration_date: Guyyaa Galmee + family_location_current: Iddoo Jireenya maatii + export: Alergii + register_new_family: Maatii Haaraa + show_family: '%{short_id}Waqaqaa eenyummaa maatii' + disable_dialog_title: Maatii Qaama Miidhamaa + disable_dialog: Tolee cuqaasuun haalata Maatii kanaa gara qaama miidhamatti + selected_records: '%{select_records}galmee(wwan) maatii filataman' + selected_all_records: 'Maatii hunda %{total_records}kan gaaffii kanaan walsimu filadhu.' + mark_for_offline: + title: Toora intarneeta alaaf mallattoo kaa'i. + text: 'Galmee maatii kana yeroo toora intarneetiin ala jirtu fayyadamuuf mirkanneeffate? ' + success: Galmeewwan Maatii milkaa'inaan itti fayyadama toora intarneetan alaa ta'eef mallatteeffaman + filter_by: + by_date: Guyyaadhan + status: Sadarkaan/haalan + current_location: Iddoo maatii + family: + family_member: + case_id: Koodii Dhimmaa + update_and_return: Haromsuu fi Deebisuu + save_and_return: Ida'uu fi deebisuu + create_case: Dhimma Uumuu + back_to_family_members: Gara Miseensota Maatiitti Deebi'aa + create: Uumuu + messages: + update_success: 'Maatiin %{record_id}milkaa''inaan haaromfameera.' + creation_success: 'Maatii milkaa''inaan uumame.' + disabled: Maatii qaama miidhamaa + confirm_create_case: Nama dhuunfaa kanaaf dhimma banuu/ uumuu ni barbaadduu? transfer: label: Dabarsa. agency_label: Ejensii. - consent_from_individual_label: "Dabarsa kana taasisuudhaaf namicharraa eeyyama qabdaa?" + consent_from_individual_label: Dabarsa kana taasisuudhaaf namicharraa eeyyama qabdaa? consent_label: Galmeewwan eeyyama hin kennine. - consent_override_label: "Qindaa'ina kana fudhatama dhabsiisuu/kuffisuu barbaadduu?" - is_remote_label: "Gara sirna fagootti dabraa jirtuu?" + consent_override_label: Qindaa'ina kana fudhatama dhabsiisuu/kuffisuu barbaadduu? + is_remote_label: Gara sirna fagootti dabraa jirtuu? location_label: Iddoo. notes_label: Yaadannoo. provided_consent_label: Eeyyamni/waliigalteen unkaawwan irratti hinkennamne. recipient_label: Fudhataa. select_label: Filadhaa. success: Haala milkaa'an dabarsameera. - transfer_label: "Karumata'een/wamafedheenuu dabarsuu?" + transfer_label: Karumata'een/wamafedheenuu dabarsuu? user_mandatory: Fudhataan ni barbaachisa. rejected_reason: Sababa fudhatama dhabe. transfer_assignment: @@ -3011,13 +3410,13 @@ om: errors: consent: Eeyyamni/Waliigalteen hin kennamne. to_user_can_receive: Fayyadamaan kun galmee kana fudhachuu hindanda'u. - individual_consent: "Hojjetaan dhimmaa dabarsa kana raawwachuudhaaf waliigaltee nama sanii qaba turee?" - no_consent_share: "Qindaayinicha waliif qooduuf waliigaltaniirtuu?" + individual_consent: Hojjetaan dhimmaa dabarsa kana raawwachuudhaaf waliigaltee nama sanii qaba turee? + no_consent_share: Qindaayinicha waliif qooduuf waliigaltaniirtuu? notes: Yaadannoo/ recipient: Fudhataa. rejected: Sababa fudhatama dhabeef. requested_by: Qaama gaafate. - service_label: "Tajaajila," + service_label: Tajaajila, responded_at: Deebiin irratti kennameera. status: accepted: Fudhateera/fudhatama argateera. @@ -3046,11 +3445,12 @@ om: locale: Kan naannoo. location: Bakka/iddoo. messages: - confirmation: "Dhugumatti fayyadamaa kana haquu barbaaddaa?Haqiinsi duubatti deebi'uu hindanda'u.Fayyadamaa kana haquudhaaf Tole kan jedhu tuqaa." + records_update: Primero galmee fayyadamaa kanaa jijjiirama ati goote akka calaqqisuuf fooyyessaa jira. Dashboards fi reports update gochuuf yeroo xiqqoo fudhachuu danda'a. + confirmation: Dhugumatti fayyadamaa kana haquu barbaaddaa?Haqiinsi duubatti deebi'uu hindanda'u.Fayyadamaa kana haquudhaaf Tole kan jedhu tuqaa. created: Fayyadamaan haala milkaa'aan uumameera. failure: Dogongorri tokko uumameera.Maaloo deeggarsa argadhaa. - new_confirm_html: "Amma fayyadamaa tokko %{username} irraa %{identity}gahee %{role}primeerootti fayyadamuu akka danda'uu affeerutti jirta.Iimeeliin dhugoomsa isaa siif ergama.%{email}Itti fufisiisuu barbaaddaa?" - new_confirm_non_identity_html: "Amma fayyadamaa tokko %{username} irraa %{identity}gahee %{role}primeerootti fayyadamuu akka danda'uu affeerutti jirta.Iimeeliin dhugoomsa isaa siif ergama %{email}3 Itti fufisiisuu barbaaddaa?" + new_confirm_html: Amma fayyadamaa tokko %{username} irraa %{identity}gahee %{role}primeerootti fayyadamuu akka danda'uu affeerutti jirta.Iimeeliin dhugoomsa isaa siif ergama.%{email}Itti fufisiisuu barbaaddaa? + new_confirm_non_identity_html: Amma fayyadamaa tokko %{username} irraa %{identity}gahee %{role}primeerootti fayyadamuu akka danda'uu affeerutti jirta.Iimeeliin dhugoomsa isaa siif ergama %{email}3 Itti fufisiisuu barbaaddaa? not_found: Fayyadamaan eenyummeessaa kennameef qabu hin argamne. password_changed_successfully: Iggitaan haala milkaa'aan jijjirameera. passwords_do_not_match: Iggitaa ammaa kanaan walhinsimu. @@ -3058,12 +3458,12 @@ om: updated: Fayyadamaan haala milkaa'aan ammayyomsameera. organization: Dhaabbata/jaarmiyaa. agency: Ejensii. - services_help_text: "Tajaajiloota yoo ibsuu baattan,,fayyadamaan kun tajaajioota walfakkaataa ejensichi qabu ni kennamaafi." + services_help_text: Tajaajiloota yoo ibsuu baattan,,fayyadamaan kun tajaajioota walfakkaataa ejensichi qabu ni kennamaafi. password_setting: - label: "Pirimeeroon iggitaa fayyadamaa akkamitti qopheessuu qaba?" + label: Pirimeeroon iggitaa fayyadamaa akkamitti qopheessuu qaba? self: Iggitaa niqindeessa/nan qopheessa. user: Fayyadamaan iimeelii baga nagaan dhuftanii fayyadamuun iggita ni qindeessa. - help_text: "Maaloo qaabadhaa,isin bulchaan iggitaa ofiikeessaniin kan qopheessitan yoo ta'e haala karaa nageenyi isaa eegameen fayyadamaaf qooduu isin barbaachisa. " + help_text: 'Maaloo qaabadhaa,isin bulchaan iggitaa ofiikeessaniin kan qopheessitan yoo ta''e haala karaa nageenyi isaa eegameen fayyadamaaf qooduu isin barbaachisa. ' password_reset_header: Iimeelii deebi'anii eegalsiisuu/haaroomsuu iggitaa ergi. password_reset_text: Yoo "ergi"kan jedhu tuqtan fayyadamaan kun iimeelii iggitaa san deebi'ee eegalsiisuuf iimeeliin walqunnamsiistuu isa gaha. password_reset_request: Iimeelii iggitaa irra deebiin eegalsiisuu ergi. @@ -3073,7 +3473,11 @@ om: position: Gita/sadarkaa/teessumma. provider_username_help: 'Fakkeenyaaf:maqaa itti fayyadama kiyya%{domain}' role_id: Shoora. - send_mail: "Beeksisoota Iimeelii fudhaa?" + send_mail: Beeksisoota Iimeelii fudhaa? + receive_webpush: + label: Beeksisa dhiibbaa argachuu? + help_text: Hubadhaa ammallee beeksisa dhiibaa biraawzari meeshaa keessanii irratti hayyamuu isin barbaachisa + tooltip: Dura akkaawuntii kee gulaaluu fi beeksisa dhiibbaa fayyadamaa keetii dandeessisuu qabda. user_group_unique_ids: Gareewwan fayyadamaa. user_name: Maqaa fayyadamaa services: Tajaajiloota. @@ -3094,13 +3498,13 @@ om: step3: 'Maqaa itti fayyadama keessanii fi iggitaa yeroodhaaf fayyadamtaniin seenaa.%1(otp)' step4: 'Yoo gaafatamtan, iggitaa keessan irra deebi''aa eegalsiisaa.' url_label: Piriimeeroo. - enabled_label: "Iimeelii baga nagaan dhuftanii ergi?" + enabled_label: Iimeelii baga nagaan dhuftanii ergi? text_label: Barruu iimeelii anaa dhufuu. password_reset: subject: 'Qajeelfama iggitaa irra deebiin jalqabsiisi.' email_greeting: "Jaalatamoo %1 (maqaa-guutuu)" email_body1: "Namni wayii iggitaa kee %{host_href}qindeessuuf gaafateera.Jalqabuudhaaf url gadi jiru tuqaa." - email_body2: "" + email_body2: "Hidhiin kun sa'aatii %{hours} keessatti kan xumuramu yoo ta'u al tokko qofa fayyadamuun ni danda'ama.  gaaffii jecha icciitii deebisanii kaa'uu yoo hin dhiheessine ykn fayyadamaan Primero haaraan bakka kee bu'ee hin galmoofne ta'e email kana bira darbi. Yoo hidhiin armaan olii yeroon isaa darbe, gaaffii jecha icciitii irra deebi'ii galchuuf %{reset_request_href} cuqaasi." email_body_link: Addana/gamana. request_submitted: "Gaaffin irra deebiin eegalsiisuu iggitaa galeera.." success: "Iggitaan milkaa'inaan jijjiirameera." @@ -3118,7 +3522,7 @@ om: associated_agencies: Ejensiiwwan garee fayyadamaa kanaa wajjiin walitti hidhatama qaban. description: Ibsa. disabled: - explanation: "Yoo garee fayyadmaa kana gufachiistan ,ammaan booda gara herregawwan fayyadamaatti ramaduu hin dandeessan." + explanation: Yoo garee fayyadmaa kana gufachiistan ,ammaan booda gara herregawwan fayyadamaatti ramaduu hin dandeessan. label: Qaama miidhamaa/ naafa. messages: created: Gareen fayyadamaa haala milkaa'aan uumameera. @@ -3142,5 +3546,11 @@ om: admin: locations: selected_records: '1% (galmeewwan - filadhaa) Iddoo/Iddoowwan filatamaniiru.' - selected_all_records: "Gaafii kanaaf dhimmoota firooman hundaa%{total_records}filadha." + selected_all_records: Gaafii kanaaf dhimmoota firooman hundaa%{total_records}filadha. updated: '%1 (galmeewwan-ammayyoomaniiru)Iddowwan/bakkeewwan ammayyoomaniiru.' + push_notifications_dialog: + title: Beeksisa Meeshaa + body_blocked: + message: Meeshaa kana irratti beeksisa Primero uggurttaniittu. Kana sirreessuuf beeksisa Hayyamaa ibsuu qabda. + android: "Android: Gara Settings jedhutti deemaa. Apps irratti cuqaasaa. Tarree appii keessaa Primero barbaadaa kana cuqaasaa. Beeksisa cuqaasi. Toggle beeksisaaf gara bakka on tti jijjiiri." + ios: "iOS: Gara appii Settings jedhutti deemaa. Notifications kan jedhu cuqaasaa. Gara tarree Apps gadi bu'uun Primero barbaadi. Toggle Primero gara bakka irratti jijjiiri." diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 9946af47cc..df9e343774 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -15,7 +15,6 @@ pl: unavailable_offline: Niedostępne Offline online: Online yes_label: 'Tak' - or_label: lub select_provider: Wybierz dostawcę select_language: Wybierz język log_in_primero_idp: 'zaloguj się z następującą nazwą użytkownika: %{idp_name} ' @@ -1111,7 +1110,6 @@ pl: english_text: Tekst po Angielsku field_name: Nazwa Pola field_type: Typ Pola - attachment_too_large: Plik nie powinien przekraczać 10MB file_upload_box: add_document_label: Dodaj Dokument add_new_document_button_text: Dodaj kolejny dokument @@ -1295,7 +1293,6 @@ pl: dashboard: Zestawienie en: English es: Español - es-GT: Español (Guatemala) fr: Français id: Bahasa km: ភាសាខ្មែរ @@ -1337,7 +1334,6 @@ pl: killing: Zabójstwa Dzieci maiming: Okaleczanie Dzieci recruitment: Rekrutacja i/lub wykorzystywanie dzieci - sexual_violence: Gwałt i//lub inne formy przemocy seksualnej abduction: Uprowadzenie attack_on: Ataki na szkołę(y) i/lub szpital(e) military_use: Użycie szkoły(ół) i/lub szpitala(i) do celów militarnych @@ -1366,7 +1362,6 @@ pl: unknown: Nieznane verification_status: Status Weryfikacji violence_type: Rodzaj Przemocy - armed_force_group_name: Nazwa Grupy Zbrojnej armed_force_group_type: Rodzaj Grupy Zbrojnej register_new_incident: Nowe Zdarzenie selectable_date_options: @@ -1771,9 +1766,7 @@ pl: killing: Zabójstwa Dzieci maiming: Okaleczanie Dzieci recruitment: Rekrutacja i/lub wykorzystywanie dzieci - sexual_violence: Gwałt i//lub inne formy przemocy seksualnej abduction: Uprowadzenie - attack_on: Ataki na szkołę(y) i/lub szpital(e) military_use: Użycie szkoły(ół) i/lub szpitala(i) do celów militarnych denial_humanitarian_access: Odmowa pomocy humanitarnej dla dzieci sub_reports: @@ -1793,22 +1786,7 @@ pl: date_of_first_report: Data Wywiadu incident_date: Data Zdarzenia reports: - incidents: Zdarzenia perpetrators: Sprawcy - sub_reports: - combined: Zdarzenia - total: 'Liczba zgłoszonych zdarzeń Przemocy ze względu na płeć ' - gbv_sexual_violence: Liczba Zgłoszonych Incydentów Przemocy Seksualnej - gbv_previous_incidents: Liczba Zdarzeń Zgłoszonych przez Ocalałych z wcześniejszymi Zdarzeniami Przemocy ze względu na płeć - gbv_sexual_violence_type: Rodzaj Zdarzenia - incident_timeofday: Pora Dnia Zdarzenia - elapsed_reporting_time: Czas pomiędzy zdarzeniem a datą raportu - elapsed_reporting_time_rape: 'Przypadki Gwałtu, Czas Jaki Upłynął pomiędzy Zdarzeniem a Datą Zgłoszenia ' - incident_location_type: Miejsce Zdarzenia - number_of_perpetrators: Liczba głównych sprawców - perpetrator_relationship: 'Domniemana Relacja Głównego Sprawcy w Stosunku do Ocalałego/ej ' - perpetrator_age_group: Grupa Wiekowa Domniemanych Sprawców - perpetrator_occupation: Zajęcie Domniemanych Sprawców messages: alert_items: 'Masz %{items} pozycje wymagające uwagi. ' alerts_for: @@ -2301,7 +2279,6 @@ pl: explanation: Pozwala managerowi zobaczyć ile spraw każdego z pracowników ma zaległe zadania Świadczenia. label: Zaległe zadania Świadczenia dash_case_incident_overview: - explanation: . label: Przegląd - Moje Sprawy/Zdarzenia dash_cases_by_social_worker: label: Podgląd Spraw według Pracownika Socjalnego @@ -2720,7 +2697,6 @@ pl: display: Wyświetlanie potencjalnych dopasowań do %{type} %{id} reassign: multiple_error: Wystąpił błąd. Sprawa(y) %{select_records} nie przypisana/e. - multiple_successfully: '%{select_records} sprawa(y) przypisana/e pomyślnie ' notes_label: Uwagi successfully: Przepisano pomyślnie user_mandatory_label: Odbiorca jest wymagany diff --git a/config/locales/ps-AF.yml b/config/locales/ps-AF.yml index ce626334a9..39da59f591 100644 --- a/config/locales/ps-AF.yml +++ b/config/locales/ps-AF.yml @@ -1493,7 +1493,6 @@ ps-AF: explanation: 'مدیر ته اجازه ورکوي چې وګوري چې د دوی هرې قضیې کارمندانو څومر قضییې د وخت وروسته ورته خدمات ارایه شوی. ' label: ټاکلی وخت وروسته خدمات dash_case_incident_overview: - explanation: . label: مشاهد-زما قضيې/پیښی dash_cases_by_social_worker: explanation: هغه جدول دی کوم چې ښیې چې څنګه د خلاص قضیو مجموعی شمیره او د نوي قضیو شمیر کوم چی د هر کارن لخوا په کارونکو په ډله کی ترتیب شوی . هر قطار د اوسني کارونکي ګروپونو کې شتون لری، پداسې حال کې چې "بشپړ" او "نوي" دوه کالمونه دي. @@ -1819,7 +1818,6 @@ ps-AF: display: د مهمو تطابقتونو لپاره ښودنه reassign: multiple_error: یوه تېروتنه رامینځ ته شوه. ٪ {ټاکنې_ ریکارډونه} قضیې نه دي ټاکل شوې. - multiple_successfully: 'به بریالیتوب سره قضیه وسپارل شوه' notes_label: یادونه successfully: په بریالیتوب سره بیا وټاکل شو user_mandatory_label: اړین ترلاسه کول diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 7bacac7c3f..6196052709 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -14,7 +14,6 @@ pt-BR: unavailable_offline: Indisponível offline online: Online yes_label: 'Sim' - or_label: ou select_provider: Selecione o provedor select_language: Selecione o idioma log_in_primero_idp: faça login com nome de usuário %{idp_name} @@ -537,42 +536,55 @@ pt-BR: comprehensive_need_intervention: 'Resposta Abrangente ' count_new_bia_approvals: one: '%{stat}novas%{stat_type} aprovações' + many: '%{stat} Aprovações de %{stat_type} novas' other: '%{stat} Aprovações de %{stat_type} novas' count_new_case_plan_approvals: one: '%{stat}novas %{stat_type}aprovações' + many: '%{stat}Aprovações de %{stat_type} novas' other: '%{stat}Aprovações de %{stat_type} novas' count_new_closure_approvals: one: '%{stat}novas %{stat_type}aprovações' + many: '%{stat}Aprovações de %{stat_type} novas' other: '%{stat}Aprovações de %{stat_type} novas' count_pending_approval_total: one: Você tem%{stat} aprovações %{stat_type}pendentes + many: Você tem %{stat}aprovações de %{stat_type} pendentes other: Você tem %{stat}aprovações de %{stat_type} pendentes count_pending_transfers: one: Você tem transferências pendentes + many: Você tem %{stat} Transferências pendentes other: Você tem %{stat} Transferências pendentes count_records_new: one: e%{stat} novos casos + many: e%{stat} novos casos other: e%{stat} novos casos count_records_total: one: Você tem %{stat}casos totais + many: 'Você tem um total de %{stat} Casos ' other: 'Você tem um total de %{stat} Casos ' count_referrals_new: one: e%{stat} novas referências + many: e %{stat}novos encaminhamentos other: e %{stat}novos encaminhamentos count_referrals_total: one: Você tem %{stat}referências totais + many: Você tem %{stat} encaminhamentos other: Você tem %{stat} encaminhamentos count_rejected_approval_total: one: e%{stat} aprovações%{stat_type} rejeitadas + many: e %{stat}Aprovações de %{stat_type}rejeitadas other: e %{stat}Aprovações de %{stat_type}rejeitadas count_rejected_transfers: one: e %{stat}transferências rejeitadas + many: e%{stat} Transferências rejeitadas other: e%{stat} Transferências rejeitadas count_risk_level_new: one: e %{stat}novos%{stat_type} casos de risco + many: e %{stat} novos %{stat_type} de casos de risco other: e %{stat} novos %{stat_type} de casos de risco count_risk_level_total: one: Você tem%{stat}%{stat_type} casos de risco + many: Você tem %{stat} %{stat_type} de casos de risco other: Você tem %{stat} %{stat_type} de casos de risco count_waiting_for_acceptance_transfers: Você tem %{stat} Transferências aguardando seu aceite current_owner: 'Proprietário Atual ' @@ -596,7 +608,7 @@ pt-BR: forms: 'Guia de FORMULÁRIOS ' geographic_area: 'Área Geográfica ' group_overview_closed: Encerrado - group_overview_open: Abrir + group_overview_open: Aberto high_level: Alto high_risk: 'Prioridade Alta ' immediate_response: 'Resposta Imediata ' @@ -610,12 +622,15 @@ pt-BR: low_risk: 'Prioridade Baixa ' manager_count_closed_total: one: e%{stat} casos fechados + many: e %{stat}casos encerrados other: e %{stat}casos encerrados manager_count_open_total: one: Você tem%{stat} casos abertos + many: Você tem %{stat} casos abertos other: Você tem %{stat} casos abertos manager_transfers_totals: one: Você tem%{stat}%{stat_type} transferências + many: Você tem %{stat} Transferências %{stat_type} other: Você tem %{stat} Transferências %{stat_type} match_result: 'Resultados Correspondentes ' medium_level: Médio @@ -701,9 +716,11 @@ pt-BR: without_incidents: Sem Incidentes worker_count_referrals_total: one: '%{case_worker}tem %{stat}referências totais' + many: '%{case_worker} tem um total de %{stat} encaminhamentos' other: '%{case_worker} tem um total de %{stat} encaminhamentos' worker_count_total: one: '%{case_worker}tem %{stat}total de casos' + many: '%{case_worker}tem um total de %{stat} casos' other: '%{case_worker}tem um total de %{stat} casos' workflow: Fluxo de Trabalho workflow_team: Fluxo de Trabalho - Casos de Equipes @@ -1028,7 +1045,6 @@ pt-BR: english_text: Texto em Inglês field_name: Nome do Campo field_type: Tipo de Campo - attachment_too_large: O arquivo não deve ser maior que 10 MB file_upload_box: add_document_label: Adicionar Documento add_new_document_button_text: 'Adicionar outro documento ' @@ -1355,16 +1371,9 @@ pt-BR: title: "8. Serviços Prestados" service: "Serviço" count: "Vezes Prestados" - helptext: | - Este indicador conta o(s) tipo(s) de serviço(s) prestado(s) aos sobreviventes no processo de gestão de casos. Chamamos de serviço prestado o serviço que é prestado pela organização do Usuário - internamente, não serviço prestado por encaminhamentos a outros serviços. average_referrals: title: "9. Média de Encaminhamentos" label: "Média de encaminhamentos por caso" - helptext: | - Este indicador conta o número médio de encaminhamentos para cada caso registrado (para todos os tipos de - serviços) em todos os casos. Inclui encaminhamentos registrados na guia do caso, não apenas encaminhamentos feitos - através da plataforma. referrals_per_service: title: "Encaminhamentos Por Serviço" average_followup_meetings_per_case: @@ -1374,21 +1383,7 @@ pt-BR: Este indicador conta o número médio de reuniões de acompanhamento realizadas para cada caso ativo por responsável pelo caso na plataforma. Uma reunião de acompanhamento é uma reunião entre o responsável pelo caso e o sobrevivente após a entrevista/ relato inicial. - goal_progress_per_need: - title: "11. Progresso Feito em Direção às Metas" - need: "Necessidade" - safety: "Segurança" - health: "Saúde" - psychosocial: "Psicossocial" - justice: "Justiça" - other: "Outros" - helptext: | - Este indicador mede a porcentagem de casos em que as metas foram atingidas ou estão em - progresso por tipo de necessidades (segurança, saúde, psicossocial, legal/justiça). Este indicador é informado - pela seção ‘Progresso Feito em Direção às Metas’ na seção ‘Acompanhamento’ do formulário - de Plano de Ação. time_from_case_open_to_close: - title: "12. Tempo desde a Abertura do Caso até o Encerramento do Caso" time: "Tempo" percent: "Porcentagem de Casos" helptext: | @@ -1397,14 +1392,12 @@ pt-BR: dividido pelo seguinte intervalo de tempo: menos de 1 mês; entre 1 e 3 meses; entre 3-6 meses; mais de 6 meses. case_closure_rate: - title: "13. Taxa de Encerramento de Caso" reporting_site: "Site de Relatório" helptext: | Este indicador mede a contagem de casos fechados por mês por site de relatório. Um site de relatórios é entendido como o site onde a Organização do Usuário está prestando serviços e onde o incidente foi relatado ao prestador de serviços. client_satisfaction_rate: - title: "14. Nível de Satisfação do Cliente" label: "Satisfação do Cliente" helptext: | Este indicador mede a porcentagem de sobreviventes que completaram a Pesquisa de Feedback do Cliente @@ -1412,12 +1405,9 @@ pt-BR: informado pelo preenchimento do formulário de Feedback do Cliente no GBVIMS+ por um membro da equipe que não seja o responsável pelo caso que prestou o serviço ao sobrevivente. supervisor_to_caseworker_ratio: - title: "15. Proporção de Supervisor para Responsável pelo Caso" label: "Responsável pelo Caso por Supervisor" helptext: "Este indicador é o número de responsáveis ​​pelo caso que um supervisor está supervisionando: o supervisor para \na proporção de responsável pelo caso. Este cálculo é baseado nas funções do sistema alocadas na plataforma.\n" case_load: - title: "16. Quantidade de Caso" - case_load: "Quantidade de Caso" percent: "Porcentagem de Responsável pelo Caso com quantidade de casos" 10cases: "<10 Casos" 20cases: "11 - 20 Casos" @@ -1802,7 +1792,6 @@ pt-BR: services_section_from_case: 'Adicionar Prestação de Serviço para o Caso de outro usuário ' specific_roles: Acessar lista de funções especificadas sync_external: Sincronizar com um sistema de gerenciamento de informações externo - sync_mobile: 'Sincronizar com dispositivo móvel ' system: 'Sistema ' tracing_request: Solicitação de Rastreamento transfer: Pode ser usado para Transferência @@ -1833,10 +1822,8 @@ pt-BR: label: Média de Encaminhamentos kpi_case_closure_rate: explanation: Habilidade de ver quantos casos foram encerrados em cada site por mês. - label: Taxa de Fechamento de Caso kpi_case_load: explanation: Habilidade de ver o número médio de Casos abertos que cada Responsável pelo Caso possui. - label: Quantidade de Casos kpi_client_satisfaction_rate: explanation: Habilidade de ver, para cada caso ao qual o usuário tem acesso, qual proporção de sobreviventes que completaram a Pesquisa de Feedback foi satisfeita. label: Taxa de Satisfação do Cliente @@ -1869,7 +1856,6 @@ pt-BR: label: Proporção de Supervisor para Responsável pelo Caso kpi_time_from_case_open_to_close: explanation: Habilidade de ver, para todos os casos aos quais o usuário tem acesso, por quanto tempo os Casos permanecem abertos. - label: Tempo desde a Abertura até o Encerramento do Caso label: KPI agency: actions: @@ -2046,9 +2032,6 @@ pt-BR: sync_external: explanation: Habilidade de sincronizar um Registro com um sistema de gerenciamento de informações externo label: Sincronizar com um sistema de gerenciamento de informações externo - sync_mobile: - explanation: Essa permissão geralmente permite que o usuário use o aplicativo móvel. Primeiro, permite que o usuário veja as ações "Marcar para Dispositivo Móvel" e "Desmarcar para Dispositivo Móvel", que aparecem na lista de casos e nas páginas de exibição de casos. Marcar um caso para dispositivo móvel indica que as informações sobre esse caso devem ser sincronizadas entre o dispositivo móvel do usuário e o aplicativo da web, enquanto desmarcar um caso para celular impede que essa sincronização aconteça. Os usuários sem essa permissão também não podem sincronizar seus dispositivos móveis com o aplicativo da web em geral, o que significa que eles não podem usar o aplicativo móvel para gerenciar casos. - label: Sincronizar com dispositivo móvel transfer: explanation: Permite que um usuário envie um caso de seu proprietário do registro atual para qualquer usuário no sistema com a capacidade de receber transferências. O proprietário do registro do caso não muda, entretanto, até que o destinatário da transferência a "aceite". Se, em vez disso, o destinatário "rejeitar" a transferência, ele perderá o acesso ao caso e manterá o proprietário original do registro. label: Transferir @@ -2113,7 +2096,6 @@ pt-BR: explanation: Permite que um gerente veja quantos casos têm tarefas de Serviço atrasadas para cada um de seus Responsáveis ​​pelos Casos. label: Tarefas de Serviço Atrasadas dash_case_incident_overview: - explanation: . label: Visão Geral - Meus Casos / Incidentes dash_cases_by_social_worker: explanation: Tabela que mostra como o número total de casos abertos e o número de novos casos gerenciados por cada usuário nos grupos de usuários do usuário atual. Cada linha é um usuário nos grupos de usuários do usuário atual, enquanto "Total" e "Novo" são as duas colunas. @@ -2163,9 +2145,6 @@ pt-BR: dash_national_admin_summary: explanation: Mostra o total de Casos abertos no sistema, o número de novos Casos criados em cada uma das últimas duas semanas, e o número de Casos encerrados em cada uma das duas últimas semanas. label: Resumo do Administrador - view_protection_concerns_filter: - explanation: Permite que o usuário veja um filtro de Preocupações de Proteção na página da lista de casos. - label: Visualizar filtro de Preocupações de Proteção na página da lista de casos view_response: explanation: Para cada tipo de resposta, mostra quantos casos em cada nível de risco têm serviços que estão próximos do prazo ou com conclusão vencida. label: Visualizar Respostas @@ -2190,7 +2169,6 @@ pt-BR: explanation: 'Limitar o acesso de um usuário a formulários em casos limita quais informações o usuário pode ver em um incidente. Por exemplo, se o usuário só tiver acesso ao formulário Proprietário do Registro, ele também poderá ver apenas as informações contidas nos campos desse formulário. Se o usuário atual tiver acesso limitado ao formulário e puder gerenciar a configuração do formulário, limitar o acesso ao formulário também limitará os formulários que ele pode configurar. NOTA: Se nenhum formulário for especificado, significa que a função tem acesso a todos os formulários para os casos.' label: Formulários - Caso incident: - explanation: 'Limitar o acesso de um usuário a formulários sobre solicitações de rastreamento limita quais informações o usuário pode ver em um incidente. Por exemplo, se o usuário só tiver acesso ao formulário Proprietário do Registro, ele também poderá ver apenas as informações contidas nos campos desse formulário. Se o usuário atual tiver acesso limitado ao formulário e puder gerenciar a configuração do formulário, limitar o acesso ao formulário também limitará os formulários que ele pode configurar. NOTA: Se nenhum formulário for especificado, significa que a função tem acesso a todos os formulários para incidentes.' label: Formulários - Incidente tracing_request: explanation: 'Limitar o acesso de um usuário a formulários sobre solicitações de rastreamento limita as informações que o usuário pode ver em uma solicitação de rastreamento. Por exemplo, se o usuário só tiver acesso ao formulário Proprietário do Registro, ele também poderá ver apenas as informações contidas nos campos desse formulário. Se o usuário atual tiver acesso limitado ao formulário e puder gerenciar a configuração do formulário, limitar o acesso ao formulário também limitará os formulários que ele pode configurar. NOTA: Se nenhum formulário for especificado, significa que a função tem acesso a todos os formulários para Solicitações de Rastreamento.' @@ -2474,7 +2452,6 @@ pt-BR: display: Exibindo potenciais correspondências para %{type} %{id} reassign: multiple_error: Um erro ocorreu. %{select_records}caso(s) não atribuído(s). - multiple_successfully: '%{select_records}caso(s) atribuído(s) com sucesso.' notes_label: 'Notas ' successfully: Reatribuído com sucesso user_mandatory_label: O Destinatário é obrigatório @@ -2706,8 +2683,6 @@ pt-BR: success: Transferido com sucesso transfer_label: Transferir mesmo assim? user_mandatory: Destinatário é obrigatório - transfer_assignment: - title: TRANSFERÊNCIAS E ATRIBUIÇÕES transition: agency_label: Agência assigned_by: Atribuído Por diff --git a/config/locales/ro.yml b/config/locales/ro.yml index a0caa0f503..d0b9a61b73 100644 --- a/config/locales/ro.yml +++ b/config/locales/ro.yml @@ -1895,35 +1895,10 @@ ro: date_of_first_report: Data intervievării incident_date: Dată incident reports: - incidents: Incidente perpetrators: Făptuitori survivors: Supraviețuitori referrals: Referiri sub_reports: - combined: Incidente - total: Număr incidente GBV/ Violență pe bază de gen raportate - gbv_sexual_violence: Numărul incidentelor de violență sexuală raportate - gbv_previous_incidents: Număr Incidente raportate în funcție de Supraviețuitori cu Incidente GBV/ Violență pe bază de gen anterioare - gbv_sexual_violence_type: Tip incident - incident_timeofday: Moment incident - elapsed_reporting_time: Intervalul de timp dintre incident și data raportării - elapsed_reporting_time_rape: Incidente precum Viol, Intervalul de timp scurs între Incident și Dată raportare - elapsed_reporting_time_rape_health_referral: Incidente de Viol, Timpul scurs între Incident și Data raportării (serviciu de sănătate sau referire) - incident_location_type: Locație incident - number_of_perpetrators: Număr făptuitori - perpetrator_relationship: Presupusa legătură dintre Făptuitor și Supraviețuitor - perpetrator_age_group: Grupă vârstă Presupus autor principal - perpetrator_occupation: Ocupația Presupusului autor principal - age: Număr Supraviețuitori în funcție de Vârstă - sex: Număr Supraviețuitori în funcție de Sex - marital_status: Statut marital Supraviețuitori - displacement_status: Status relocare Supraviețuitor - displacement_incident: Status relocare la momentul Incidentului - gbv_case_context: Context Caz - incidents_first_point_of_contact: Numărul de incidente pentru care organizația dumneavoastră este primul punct de contact - incidents_from_other_service_provider: Incidentele referite de alți furnizori de servicii - number_of_services_provided: Număr servicii furnizate pentru incidente - number_of_services_provided_other: Noi referiri de incidente către alți furnizori de servicii service_safehouse_referral: Referire Locație/ Adăpost sigur service_medical_referral: Referire pentru Sănătate/ Medicală service_psycho_referral: Servicii consiliere psihologică @@ -1931,7 +1906,6 @@ ro: service_police_referral: Poliție sau alt tip de servicii de securitate service_livelihoods_referral: Servicii mijloace de subzistență service_protection_referral: Servicii protecția copilului - vulnerable_populations: Grupuri vulnerabile survivors_disability_type: Cu Dizabilități success_message: Fișier export generat cu succes messages: @@ -2445,7 +2419,6 @@ ro: explanation: Permite unui coordonator să vadă câte înregistrări au sarcini restante de Servicii pentru fiecare dintre utilizatori. label: Sarcini restante Servicii dash_case_incident_overview: - explanation: . label: Sumar - Înregistrările mele/ Incidente dash_cases_by_social_worker: explanation: Tabel care arată cum sunt gestionate de către fiecare utilizator din grupurile de utilizatori ale utilizatorului curent totalul de cazuri deschise și numărul de cazuri noi. Fiecare rând reprezintă un utilizator din grupurile de utilizatori ale utilizatorului curent, în timp ce „Total” și „Nou” sunt cele două coloane. @@ -2917,7 +2890,6 @@ ro: display: Afișează potențiale potriviri pentru %{type}%{id} reassign: multiple_error: S-a produs o eroare. %{select_records} caz(uri) neasignate. - multiple_successfully: '%{select_records} caz(uri) asignat(e) cu succes' notes_label: Notițe successfully: Reasignate cu succes user_mandatory_label: Beneficiarul este obligatoriu diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 412f093fb2..c57f6990a3 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -15,7 +15,6 @@ ru: unavailable_offline: Недоступен в режиме оффлайн online: Онлайн yes_label: 'Да' - or_label: или select_provider: Выбрать провайдера select_language: Выбрать язык log_in_primero_idp: 'Войти в систему с %{idp_name}именем ' @@ -1023,7 +1022,6 @@ ru: english_text: Английский текст field_name: Поле Имя field_type: Тип поля - attachment_too_large: Файл не должен быть больше 10mb file_upload_box: add_document_label: Добавить документ add_new_document_button_text: Добавить другой документ @@ -1207,7 +1205,6 @@ ru: dashboard: Информационная панель en: English es: Español - es-GT: Español (Guatemala) fr: Français id: Bahasa km: ភាសាខ្មែរ @@ -1249,7 +1246,6 @@ ru: killing: Убийство детей maiming: Калечение детей recruitment: Вербовка и/или использование детей - sexual_violence: Насилование и/или другие формы сексуального насилия abduction: Похищение attack_on: Атака на школу(ы) и/или больницу (ы) military_use: Военное использование школ(ы) и/или больниц(ы) @@ -1278,7 +1274,6 @@ ru: unknown: Неизвестно verification_status: Статус проверки violence_type: Тип насилия - armed_force_group_name: Название военной организованной группировки armed_force_group_type: Тип военной организованной группировки register_new_incident: Новый инцидент selectable_date_options: @@ -1678,9 +1673,7 @@ ru: killing: Убийство детей maiming: Калечение детей recruitment: Вербовка и/или использование детей - sexual_violence: Насилование и/или другие формы сексуального насилия abduction: Похищение - attack_on: Атака на школу(ы) и/или больницу (ы) military_use: Военное использование школ(ы) и/или больниц(ы) denial_humanitarian_access: Отказ в гуманитарном доступе к детям sub_reports: @@ -1700,22 +1693,7 @@ ru: date_of_first_report: Дата интервью incident_date: Дата инцидента reports: - incidents: Инциденты perpetrators: Преступник - sub_reports: - combined: Инциденты - total: Количество инцидентов GBV заявленных - gbv_sexual_violence: 'Количество заявленных инцидентов сексуального насилия ' - gbv_previous_incidents: Количество инцидентов заявленных выжившими с предыдущими GBV инцидентами - gbv_sexual_violence_type: Тип инцидента - incident_timeofday: Время суток инцидента - elapsed_reporting_time: Время между инцидентом и датой отчета - elapsed_reporting_time_rape: Инциденты насилия, время между инцидентом и датой заявления - incident_location_type: Место инцидента - number_of_perpetrators: Количество основных преступников - perpetrator_relationship: Предполагаемые взаимоотношени основных преступников и выжившего - perpetrator_age_group: Возрастная группа предполагаемых основных преступников - perpetrator_occupation: Профессия предполагаемых основных преступников messages: alert_items: У Вас %{items}примечаний alerts_for: @@ -2226,7 +2204,6 @@ ru: explanation: Позволяет менеджеру увидеть сколько кейсов имеют просроченные сервисные задания по отслеживанию для каждого из его работников. label: Просроченные задания по сервису dash_case_incident_overview: - explanation: . label: Обзор - Мои кейсы/инциденты dash_cases_by_social_worker: explanation: Таблица, которая показывает сколько всего открытых кейсов и новых кейсов, которые ведет каждый пользователь в этой группе. Каждый ряд это группа пользователя, а "Всего" и "Новый" это две колонки. @@ -2670,7 +2647,6 @@ ru: display: Отображение потенциальных совпадений для %{type}%{id} reassign: multiple_error: Произошла ошибка. %{select_records}кейс (ов) не назначены. - multiple_successfully: '%{select_records}кейс(ов) успешно назначены' notes_label: Заметки successfully: Успешно переназначен user_mandatory_label: Требуется получатель diff --git a/config/locales/sk.yml b/config/locales/sk.yml index 56bf2ec69a..33e61da110 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -15,7 +15,6 @@ sk: unavailable_offline: Nedostupný offline online: Online yes_label: 'Áno' - or_label: alebo select_provider: vybrať dodávateľa select_language: Zvoliť si jazyk log_in_primero_idp: 'prihláste sa s používateľským menom %{idp_name} ' @@ -1114,7 +1113,6 @@ sk: english_text: Anglický text field_name: Názov Políčka field_type: Typ Políčka - attachment_too_large: Súbor nemôže byť väčší ako 10MB file_upload_box: add_document_label: Pridajte dokument add_new_document_button_text: Pridajte ďalší dokument @@ -1300,7 +1298,6 @@ sk: dashboard: Palubná doska en: Anglický es: 'Španielsky ' - es-GT: Španielsky (Guatemala) fr: Francúzky id: Bahasa km: ភាសាខ្មែរ @@ -1342,7 +1339,6 @@ sk: killing: Zabíjanie detí maiming: Mrzačenie detí recruitment: Nábor a/alebo využívanie detí - sexual_violence: Znásilnenie a/alebo iný druh sexuálneho násilia abduction: Únos attack_on: Útok na školu(y) a/alebo nemocnicu(e) military_use: Vojenské využitie školy (škôl) a/alebo nemocnice (nemocníc) @@ -1371,7 +1367,6 @@ sk: unknown: Neznáme verification_status: Stav overenia violence_type: Typ násilia - armed_force_group_name: Názov skupiny ozbrojených síl armed_force_group_type: Typ skupiny ozbrojených síl register_new_incident: Nový incident selectable_date_options: @@ -1794,9 +1789,7 @@ sk: killing: Zabíjanie detí maiming: Mrzačenie detí recruitment: Nábor a/alebo využívanie detí - sexual_violence: Znásilnenie a/alebo iný druh sexuálneho násilia abduction: Únos - attack_on: Útok na školu(y) a/alebo nemocnicu(e) military_use: Vojenské využitie školy (škôl) a/alebo nemocnice (nemocníc) denial_humanitarian_access: Zamietnutie prístupu k humanitárnej pomoci deťom sub_reports: @@ -1816,22 +1809,7 @@ sk: date_of_first_report: Dátum pohovoru incident_date: Dátum incidentu reports: - incidents: Incidenty perpetrators: Páchatelia - sub_reports: - combined: Incidenty - total: Počet nahlásených incidentov rodovo motivovaného násilia (GBV) - gbv_sexual_violence: Počet nahlásených prípadov sexuálneho násilia - gbv_previous_incidents: Počet incidentov nahlásených obeťami s predchádzajúcimi incidentmi rodovo motivovaného násilia (GBV) - gbv_sexual_violence_type: Typ incidentu - incident_timeofday: Denná doba incidentu - elapsed_reporting_time: Čas medzi incidentom a dátumom nahlásenia - elapsed_reporting_time_rape: Incidenty znásilnenia, čas, ktorý uplynul medzi incidentom a dátumom nahlásenia - incident_location_type: Miesto Incidentu - number_of_perpetrators: Počet primárnych páchateľov - perpetrator_relationship: Údajný vzťah primárneho páchateľa s obeťou - perpetrator_age_group: Veková skupina údajných primárnych páchateľov - perpetrator_occupation: Údajné povolanie hlavného páchateľa messages: alert_items: Máte %{items} poznámky. alerts_for: @@ -2342,7 +2320,6 @@ sk: explanation: Umožňuje manažérovi vidieť, koľko prípadov má omeškané Servisné úlohy u každého z ich pracovníkov zaoberajúcich sa prípadom. label: ' Oneskorené servisné úlohy' dash_case_incident_overview: - explanation: . label: Prehľad – Moje prípady / Incidenty dash_cases_by_social_worker: explanation: Tabuľka, ktorá zobrazuje celkový počet otvorených prípadov a počet nových prípadov spravovaných každým používateľom v skupinách používateľov aktuálneho používateľa. Každý riadok predstavuje používateľa v skupinách používateľov aktuálneho používateľa, zatiaľ čo „Celkom“ a „Nový“ sú dva stĺpce. @@ -2786,7 +2763,6 @@ sk: display: Zobrazujú sa možné zhody pre %{type} %{id} reassign: multiple_error: Nastala chyba. %{select_records} prípadov nepriradených. - multiple_successfully: '%{select_records} prípadov bolo úspešne priradených' notes_label: Poznámky successfully: Úspešne preradené user_mandatory_label: Príjemca je povinný @@ -3111,7 +3087,7 @@ sk: failure: Vyskytla sa chyba, kontaktujte podporu. new_confirm_html: Chystáte sa pozvať používateľa %{username} z %{identity} s rolou%{role} používať Primero. Potvrdzujúci e-mail bude odoslaný na adresu %{email}. Chcete pokračovať? new_confirm_non_identity_html: Chystáte sa pozvať používateľa %{username} s rolou %{role} používať Primero. Potvrdzujúci e-mail bude odoslaný na adresu %{email}. Chcete pokračovať? - not_found: Používateľ s daným IČ sa nenašiel + not_found: Používateľ s daným ID sa nenašiel password_changed_successfully: Heslo úspešne zmenené passwords_do_not_match: nezhoduje sa so súčasným heslom time_zone_updated: Zmena bola úspešne aktualizovaná. diff --git a/config/locales/so.yml b/config/locales/so.yml index 14045fc34f..026a6c0aa9 100644 --- a/config/locales/so.yml +++ b/config/locales/so.yml @@ -4,29 +4,36 @@ so: accepted: aqbalay cancel: Kanoqo connection_lost: Hawada ayuu ka maqanyahay + field_mode_offline: Hadda Nooca Fiildhiga connected: 'Xidhidhsan ' + no_connection: 'malaha khadka Internetka ' clear: Tirtir sandbox_ui: Tijaabo description: Tafaasiil form: Foomka - minimum_reportable_fields: "Goobaha ugu yaran qaybaha laga warbixin karo %{Nooca_Xogta}" + minimum_reportable_fields: "Goobaha ugu yaran qaybaha laga warbixin karo %{record_type}" name: magaca offline: ka maqan hawada + field_mode: "Habka Fiildhiga: %{mode}" + field_mode_on: "shid" + field_mode_off: "dhami" unavailable_offline: 'Aan khad internet la''aan ama offline laga heli karin  ' online: 'Hawada ku jira ' yes_label: 'Haa' - or_label: Ama + or_label: ama select_provider: Xula Adeeg bixiyaha select_language: Xula Luuqada log_in_primero_idp: 'gal magaca %{idp_name} isticmaalaha ' offline_submitted_changes: Hadda waxaad tahay offline Isbedeladaada waxaa la soo gudbin doonaa markaad internetka ku soo noqoto. updated: Waa lacusbooneysiiyay + go: gal + select_idp_error: Fadlan dooro adeeg bixiyaha sync: - success: "Diiwaangalintan waa lagu guuleystay in laqaada" + success: "%{records} Diiwaanadda waa lagu guuleystay in la qaado " error: - create: Howshan waa lagu guuldareystay boqolkiiba hal in lasameyo. fadlan Taagero dalbo + create: Howshan waa lagu guuldareystay in lasameyo %{record_type}. Fadlan Taagero dalbo update: Cusbooneysii %{record_type} %{short_id} waa guuldareystay. Fadlan la xidhiidh taageerada actions: approvals: Ansiximaha @@ -193,35 +200,44 @@ so: view: Aragti view_flags_history: Aaragtida Taariikhda return_to_case: Dib ugu laabo kiiska + enable_webpush: Ogeysiiska Aalada + dialog_yes: "Haa" + resync_records: + id: Sumad + record_type: 'Nooca Diwaanka ' + action: 'Talaabada la qaadayo ' + date: 'Taariikhda ' + last_attempt: 'Iskudaygii ugu Dambeeyay ' + create: Samee + update: Cusbooneysii + resync: gudbi case: label: Kiiska create_new_case: Samee Kiis cusub + create_case: Samee Kiis + create: Samee add_new: Kudar mid cusub + back_to_family_details: Dib ugu laabo Faahfaahinta Qoyska back_to_case: 'Kulaabo kiiska ' back_to_results: Ku Laabo Natiijooyinka back_to_search: Ku Laabo raadinta search_by: Raadiyey - search_for: Raadi %{wiiwaanka_Noociisa} + search_for: Raadi %{record_type} results: Natiijooyin details: Faah-Faahinta select: Dooro deselect: Ka laabo Doorashada enter_id_number: 'Ku raadi diiwaan hore u jiray nambarkiisa garashada ' - id_search_no_results: Ma jiro wax u dhigma nidaamka "%{raadi_weydiimaha}". Fadlan samee rikoor cusub + id_search_no_results: Ma jiro wax u dhigma nidaamka "%{search_query}". Fadlan samee rikoor cusub messages: disabled: kiiska waa laxidhay - update_success: 'Kiiska %{Diiwaangali_Aqoonsiga} si guul leh ayaa loo cusboonaysiiyay' - update_success_queue: 'Kiiska %{Diiwaangalinta_Aqoonsi} si guul leh ayaa gadaal loogu cusboonaysiiyay' + update_success: 'Kiiska %{record_id} si guul leh ayaa loo cusboonaysiiyay' + update_success_queue: 'Kiiska %{record_id} si guul leh ayaa gadaal loogu cusboonaysiiyay' creation_success: 'Diiwaangalinta kiiska sameyntisa waa lagu guuleystay' creation_success_queue: 'diiwaangalinta kiiska waxaa loosameyay si daahson' already_matched: Weydiimahan ayaa mar horeba la mid ah kiiskaaga already_matched_not_current_case: Waxa horey u jiray kiis nidaamka la mid ah waydiimahan - not_found_case: 'Lama helin kiis u dhigma "%{Raadi qiimaha}". Abuur Kiis cusub - -   - - -  ' + not_found_case: Lama helin kiis u dhigma "%{search_value}". Abuur Kiis cusub introductory_sentence: Fadlan sheeg ogolaanshaha qofka si uu u helo adeegyada maaraynta kiiska iyo in xogtoodu noqoto lagu keydiyo Primero ga consent_agreements_required: Fadlan ka dooro ugu yaraan hal doorasho heshiisyada ogolaanshaha. legitimate_basis_required: 'Fadlan ka dooro ugu yaraan hal ikhtiyaar oo kala soocida ku saleysan kala saarid @@ -230,6 +246,14 @@ so:  ' + confirm_create_case: Ma rabtaa in aad Kiis u samayso shaqsigan + case_referral_pending: ugudbinta kiiskqn ayaa la sugayaa + case_transfer_pending: Gudbinta kiiska ayaa la sugayaa + case_no_approval_request: Ma jiraan codsiyo ansixin ah kiiskan. + bulk_assign_limit: Ma amri kartid in ka badan 100 kiis hal mar + bulk_assign_limit_try_again: Ma amri kartid kartid in ka badan 100 kiis hal mar. Fadlan dooro 100 kiis ama in ka yar ka dibna isku day mar kale. + referral_rejected: gudbinta kiiska waa la diiday + transfer_request_made: 'Kiiskan in in adeeg kale loo wareejiyo ayaa la codsaday ' save: Keydin kiis save_text: Kahor intaadan sii wadin, fadlan ku keydi isbedeladaada Kiiska. skip_and_create: Ka bood oo Samee Kiis Cusub @@ -237,6 +261,7 @@ so: search_helper_text: Waa maxay sababtu? Si looga hortago abuurista kiisas nuqul ah consent_agreements: Dooro dhammaan heshiisyada oggolaanshaha ee khuseeya legitimate_basis: Dooro dhammaan kala soocida ku saleysan kala saarida ee khuseeya + family_linked_subform_delete_disabled: 'Foom hoosaadkani wuxuu ku xidhanyahay diiwaan qoys. Fadlan ama kasaar kamid ahaanshihiisa Diwaanka qoyska ama ha la xidhiidhin Diwaanka qoyska ' workflow: assessment: Daraasad case_plan: Qorshaha kiiska @@ -252,10 +277,11 @@ so: label: Dhacdooyinka xidhiidhsan activity_log: label: Howlaha calamada - accepted_transfer: '%{ku} wareejinta la aqbalay %{Nooca diiwaanka} %{aqoonsiga diiwaanka} ka %{ka}' - rejected_transfer: '%{ku} wareejinta la aqbalay %{Nooca diiwaanka} %{aqoonsiga diiwaanka} ka %{ka}' + accepted_transfer: '%{to} wareejinta la aqbalay %{record_type}%{record_id} ka %{from}' + rejected_transfer: '%{to} wareejinta la aqbalay %{record_type}%{record_id} ka %{from}' cases: action_plan: Qorshaha ficilka + access_denied: "laguma ogola inaad gasho kiiskan" age: Da'da age_estimated: Da'da lagu qiyaasay agency: Xafiis @@ -265,12 +291,12 @@ so: approval_radio_accept: Ansixin approval_radio_reject: Lama ansixin approval_select: foomka loogu talagalay - approved_success_action_plan: '%{ansixinta_calamad} - Waa la ansixiyay' - approved_success_assessment: '%{ansixinta_calamada} - Waa la ansixiyay' - approved_success_bia: '%{ansixinta_calamada} - Waa la ansixiyay' - approved_success_case_plan: '%{ansixinta_calamada} - Waa la ansixiyay' - approved_success_closure: '%{ansixinta_calamada} - Waa la ansixiyay' - approved_success_gbv_closure: '%{ansixinta_calamada} - Waa la ansixiyay' + approved_success_action_plan: '%{approval_label} - Waa la ansixiyay' + approved_success_assessment: '%{approval_label} - Waa la ansixiyay' + approved_success_bia: '%{approval_label} - Waa la ansixiyay' + approved_success_case_plan: '%{approval_label} - Waa la ansixiyay' + approved_success_closure: '%{approval_label} - Waa la ansixiyay' + approved_success_gbv_closure: '%{approval_label} - Waa la ansixiyay' assessment: Daraasad case_opening_date: kiis taariikh furan case_plan: Qorshaha kiiska @@ -280,6 +306,7 @@ so: close_dialog_title: Xidh kiiska close_success: Waxaad si sax uu xidhay kiiski closure: Xidhataan + complete: 'Khad la''aan ayaa lagu heli karaa ' date_of_birth: 'Maalinta Dhalashada ' disable_dialog: In aad haye tujisid waxay badleysa kiiska curyaan disable_dialog_title: 'Kiisaska laga guuray ' @@ -347,7 +374,7 @@ so: transferred: La wareejiyey type_of_risk: 'Nooca Khatarta ' urgent_protection_concern: 'Wax ka qabasha Dag dag ah ' - user_group: 'KOOXAD ISTCIMALYAAL AH ' + user_group: Kooxda Isticmaalaha workflow: 'GEEDI SOCODKA KIISASKA ' flag_summary: SO KOOBID CALMAAD CALAN full_name: Magaca Buuxa @@ -381,29 +408,29 @@ so: referral_rejected_success: Gudbinta Waa ladiiday register_new_case: kiis cusub registration_date: Waqtiga ladiiwaangali - rejected_success_action_plan: '% {ansxinta calamada} - Lama ogola' - rejected_success_assessment: '% {ansxinta calamada} - Lama ogola' - rejected_success_bia: '% {ansxinta calamada} - Lama ogola' - rejected_success_case_plan: '% {ansxinta calamada} - Lama ogola' - rejected_success_closure: '% {ansxinta calamada} - Lama ogola' - rejected_success_gbv_closure: '% {ansxinta calamada} - Lama ogola' + rejected_success_action_plan: '%{approval_label} - Lama ogola' + rejected_success_assessment: '%{approval_label} - Lama ogola' + rejected_success_bia: '%{approval_label} - Lama ogola' + rejected_success_case_plan: '%{approval_label} - Lama ogola' + rejected_success_closure: '%{approval_label} - Lama ogola' + rejected_success_gbv_closure: '%{approval_label} - Lama ogola' reopen_dialog: Riix OK waxay bedeli doontaa xaalada kiiskan si aad u furi doonta reopen_dialog_title: Dib ufurida kiiska reopen_success: Waa lagu guuleystay in dib loofuro kiiska request_approval_failure: Khalad ayaa dhacay, ee fadlan la xidhiidh taageerida request_approval_select: Waa la ansixiyay codsigada - request_approval_success_action_plan: Oggolaanshaha ayaa la codsaday %{Ansixi_calamada}foomka - request_approval_success_assessment: Oggolaanshaha ayaa la codsaday hal%{Ansixi_calamada}foomka - request_approval_success_case_plan: Oggolaanshaha ayaa la codsaday hal %{Ansixi_calamada}foomka - request_approval_success_closure: Oggolaanshaha ayaa la codsaday hal %{Ansixi_calamada}foomka - request_approval_success_gbv_closure: Oggolaanshaha ayaa la codsaday hal %{Ansixi_calamada}foomka + request_approval_success_action_plan: Oggolaanshaha ayaa la codsaday %{approval_label} foomka + request_approval_success_assessment: Oggolaanshaha ayaa la codsaday hal%{approval_label} foomka + request_approval_success_case_plan: Oggolaanshaha ayaa la codsaday hal %{approval_label} foomka + request_approval_success_closure: Oggolaanshaha ayaa la codsaday hal %{approval_label} foomka + request_approval_success_gbv_closure: Oggolaanshaha ayaa la codsaday hal %{approval_label} foomka request_approval_type_of_case_plan: Nooca qorshaha kiiska ee la ansixi request_approve_action_plan: Ansixi qorshaha ficilka request_approve_bia: Ansixinta darasadka request_approve_case_plan: Ansixinta qorshaha kiiska request_approve_closure: Mo ogolyahay xidhitaanka request_approve_gbv_closure: Ma ogolyahay xidhitanka tacadiga kadhanka ah jinsiga - revoke_failure: Khalad ayaa dhacay markii la burinayay %{nooca kala guurka}, fadlan la xidhiidh cid kucaawisa + revoke_failure: Khalad ayaa dhacay markii la burinayay %{transition_type}, fadlan la xidhiidh cid kucaawisa revoke_message: marka aad taabato waan'diiday', waxaa laga saarayaa %{transition_type}cidii heli lahayd kiiska inay awood u yeeshaan. revoke_success_message: Kiis %{case_id} %{transition_type} to %{recipient_username} waa la buriyay. save_filter: Badbaado @@ -445,6 +472,7 @@ so: transfer_reject_reason_label: Sababta loodiiday transfer_rejected: Marka aad taabato waan "Diiday" waxay tusinaysaa inaanad ka masuul ahayn kiiskan wakhti xaadirkan. Adigoo mahadsan gali sababtta aad u diiday kiiskan, isla markaad taabato " Diiday" uma yeelan doontid awood dambe diwaangalinta kiiskaa. view_name: Daawo Magaca + sort_by: u kala horeysii change_logs: filters: form: Foomka @@ -587,7 +615,7 @@ so: other: waxaad haystaa %{stat} kiisas %{stat_type} aan wali la ansixin count_pending_transfers: one: 'waxaad haystaa kiisas ama kiisas aan wali la gudbin ' - other: waxaad haysataa %{stat} kiisas aan wali lagudbin + other: Waxaad haysataa %{stat} kiisas ah oo aan wali lagudbin count_records_new: one: 'iyo %{stat} kiisas cusub ' other: iyo %{stat} kiisas cusub @@ -622,6 +650,9 @@ so: dash_shared_with_my_team_overview: La wadaagay kooxdayda (Aragtida guud) dash_shared_with_others: La wadaagay qaar kale dash_national_admin_summary: Gunaanadka gudoomiyaha + dash_violations_category_verification_status: 'Wadarta dhacdooyinka ee la cadeeyay ' + dash_violations_category_region: wadarta dhacdooyinka la cadeeyay ee deegaan kasta + dash_perpetrator_armed_force_group_party_names: 'wadarta dhacdooyinka ee eedaysane kasta ' date: Taariikh date_of_incident: Taariikhda dhacdada date_of_interview: Taariikhda Waraysiga @@ -765,24 +796,51 @@ so: transfer: '%{user}Waxaa laguu soo wareejiyay %{record_type}kuwan adiga %{record_id}' transfer_request_subject: 'Codsi wareejin ah ayaa nooga yimi mid ka mid ah kiisaskaagii ' transfer_subject: '%{record_type}:%{id}Wareejin' - referral_subject: 'Gudbis' - transfer_request: 'Laanta Birimeero waxay kaa codsanaysaa inaad u wareejiso diiwaankooda, sidaas darteed waxay adeeg ku siin karaan halka ay joogaan. Haddii ay wareejintu macquul kuu tahay adiga, fadlan taabo isku-xidhaha gaar ka u ah Birimeero si aad u bilowdo wareejinta.' + referral_subject: '%{record_type}: %{id} - u gdbinta adeeg kale' + transfer_request: 'isticmaalaha ama userka Primero %{user} ee ka socda %{agency} wuxuu codsanaysaa inaad ku wareejiso masuuliyada diiwaanka xogtan %{record_type}%{record_id} sidaas darteed waxay adeeg ku siin karaan halka ay joogaan %{record_type}. Haddii ay wareejintu macquul kuu tahay adiga, fadlan taabo %{record_type} sumada linkiga Emailkan si aad u furto %{record_type} ee Primero una bilowdo wareejinta.' approval_request_html: 'Laanta %{user}waxay codsanaysaa %{approval_type}in loo ansixiyo kiiska%{case_id}' approval_response_html: '%{user}Waxaad haysaa%{status} codsi si loo ansixiyo %{approval_type}kiiska%{case_id}' referral_html: '%{user}Waxaa laguu soo%{agency} gudbiyay %{record_type}kuwan adiga%{record_id} ah%{service_type}' transfer_html: '%{user}Waxaa laguu soo wareejiyay kuwan%{record_type} adiga%{record_id}' assign_html: 'Waxaa laguugu tala galay kuwan adiga ' - transfer_request_html: 'Laanta Birimeero waxay kaa codsanaysaa inaad u wareejiso diiwaankooda, sidaas darteed waxay adeeg ku siin karaan halka ay joogaan. Haddii ay wareejintu macquul kuu tahay adiga, fadlan taabo isku-xidhaha gaar(Fariin sidaha Iimaylka) ka u ah Birimeero si aad u bilowdo wareejinta.' - transfer_request_notes_html: 'Qoraalo kookooban ayay ash-khaasi codsi kuugu soo sameeyeen' + transfer_request_html: 'isticmaalaha Primwro %{user} ee ka socda %{agency} wuxuu codsanayaa inaad u wareejiso masuululiyada %{record_type} Diwaanka xogtan %{record_id} sidaas darteed waxay adeeg %{record_type} ku siin karaan halka ay joogaan. Haddii ay wareejintu macquul kuu tahay adiga, fadlan taabo %{record_type} ee linkiga emailkan si aad u furto %{record_type} ee Primero una bilowdo gudbinta. ' + transfer_request_notes_html: 'Qoraalo kooban oo laga helay shaqsiyaadka codsiga sameeyey: %{request_transfer_notes}' + alert: '%{record_type} %{id}-%{form_name} waa la cusbooneysiiyay. Fadlan gal Primero si aad dib ugu eegto isbedelka.' + alert_subject: '%{record_type}: %{id} - %{form_name} waa la cusbooneysiiyay.' + webpush_notification: + action_label: u kac ama aad kiiska + approval_request: + title: Codso Ansixin + body: Kiiska kooxdaada ayaa wali sugaya codsiga Aqbalaada %{type}. + approval_response: + title: Jawaabta Aqbalaada + body: Mid kamid ah Kiisaskaaga ayaa la aqbalay + assign: + title: 'Shaqo cusub ' + body: 'Waxaad laguu xilsaaray shaqada kiis cusub ' + referral: + title: Gudbin cusub + body: Waxaad heshay gudbinta Kiis cusub + transfer: + title: 'Wareejin kiis oo cusub ' + body: Waxaad heshay wareejinta Kiis cusub + alert_case: + title: 'Kiiska waa la cusboonaysiiyay ' + body: "%{type} mid kamida kiisaskaaga ayaa la cusboonaysiiyay." + transfer_request: + title: Codsiga Wareejinta kiiska + body: Waxaad heshay Codsiga Wareejinta Kiis cusub encrypt: export_type: Nooca qaadista file_name: Magacaaga ku Samee diiwaan ( Ikhtiyaarkaaga) - password_extra_info: Nambarka sirta ahi waa inuu ugu yaraan ka koobnaado sideed astaamood. Nambarkan sirta ah waxaa wehelin doonna fayl kii aad soo qaaday waxaana loo baahan yahay inuu galiyo qof waliba markuu furayo faylka mustaqbalka + password_extra_info: Nambarka sirta ahi waa inuu ugu yaraan ka koobnaado 8 astaamood. Nambarkan sirta ah wuxuu la xidhiidhaa fayl kii aad soo qaaday waxaana loo baahan yahay inuu gali karo qof waliba oo doonaya inuu furo faylkan markasta password_label: Fadlan gali nambarka sirta ah si uu xadidnaado faylku error_message: - address_fields: 'Waxaad u baahan tahay inaad kala meelayso faylasha goobaha ' + address_fields: Waxaad u baahan tahay inaad kala cadayso qaybaha %{fields} ka midka ah foormiga %{forms} address_form_fields: 'Waxaad u baahan tahay inaad kala meelayso faylasha goobaha ' - address_subform_fields: 'Goobahani maaha kuwo sax ah' + address_subform_fields: '%{subform} Qaybahani %{fields} maaha kuwo sax ah' + error_401: Waad ka baxday, Fadlan dib usoo gal ciwaankaaga + error_something_went_wrong: Waxbaa ka khaldanay. error_page: not_authorized: server_error: Awood uuma lihid inaad isticmaashid shabakadan. @@ -791,6 +849,8 @@ so: contact_admin: Haddii aad rumaysan tahay inaad halkan si khaldan ku timi, fadlan la xidhiidh Maamulaha. something_went_wrong: Waan ka xumahay, wax baa khaldamay! errors: + api: + internal_server: Khalad dhanka Sarfarka ah error_loading: Waxaa soo baxaya khaladka diiwaanka(nada) models: agency: @@ -835,6 +895,11 @@ so: title_present: Mansabku waa in aanu banaanaan content_present: Dulucdu waa inaanay banaanaan created_by_present: Hebel baa sameeyay waa inaanay banaanaan + webpush_subscription: + notification_url_present: url_ogaysiisku waa ay noqon mid madhan + notification_url_format: url_ogaysiisku waa inuu lahaa qaab URL + auth_present: Ansixinta waa in aysan madhnaan ama banaanaan + p256dh_present: p256dh waa inaysan madhnaan ama banaanaan not_found: Wax diiwaan(no) ah lama helin try_again: Mar labaad isku day exports: @@ -929,7 +994,7 @@ so: one: Diiwaangaliyaha dhacdada selected: Dooro diiwaangaliyaha dhacdada json: - all: 'JavaScript Object Notation ' + all: JavaScript Object Notation JSON one: JavaScript Object Notation selected: Waxaa la doortay JavaScript Object Notation list_view_csv: @@ -1015,7 +1080,7 @@ so: success: Goobaha si guul leh ayaa loo soo dejiyay no_data: 'Soo Dejinta Lama Sameeyo: Wax xog ah oo la gudbiyay' csv_parse_error: 'Soo Dejinta Lama Hawl-Galo: Cilad baadhida xogta CSV' - error: 'Saf %{row_number} Lama socodsiin: %{fariinta}' + error: 'Saf %{row_number} Lama socodsiin: %{message}' db_error: 'Khalad abuurista %{location_code}: %{message}' locale_invalid: 'Ka boodista %{column_name}: Degaanku sax maaha' insert_all_error: 'Soo dejinta Looma Hawl-Galin Cilad database: %{message}' @@ -1025,7 +1090,7 @@ so: no_data: 'Soo Dejinta Lama Sameeyo: Wax xog ah oo la gudbiyay' no_file: 'Soo Dejinta Lama Shaacin: Faylku ma jiro' csv_parse_error: 'Soo Dejinta Lama Hawl-Galo: Cilad baadhida xogta CSV' - error: 'Saf %{row_number} Lama socodsiin: %{fariinta}' + error: 'Saf %{row_number} Lama socodsiin: %{message}' db_error: 'Khalad abuurista %{location_code}: %{message}' locale_invalid: 'Ka boodista %{column_name}: Deegaan sax ah' insert_all_error: 'Soo dejinta Looma Hawl-Galin Cilad database: %{message}' @@ -1090,7 +1155,7 @@ so: english_text: Qoraalka Ingiriisiga field_name: Magaca Goobta field_type: Nooca goobta - attachment_too_large: Faylku waa inuusan ka badnaan 10mb + attachment_too_large: faylku waa inuusan kawaynaan 20mb file_upload_box: add_document_label: Kudar Dukumeenti add_new_document_button_text: Ku dar dukumeenti kale @@ -1150,6 +1215,18 @@ so: show: Muuji? show_on: Muuji show_on_minify_form: Qaab gaaban + skip_logic: + name: iska daa Sababata + record_section: + title: Qaybtani Waa inay muuqaataa haddii la kaydiyay + buttons: + add: 'Ku dar Xaaladda Diwaanka ' + subform_section: + title: 'Qaybtan waa in la arki karo + + Haddii ay Foom hosaad tahay ' + buttons: + add: 'Ku dar Xaaladda Foom hoosaadka ' subform: Hoos-u-dhigid subform_group_by: Koox by subform_remove_message: Xaqiiji inaad ka saarto Foom hoosaadka @@ -1159,7 +1236,7 @@ so: starts_with_one_entry: Bilow Buuxinta Hal Foom Hoosaad subform_append_only: u dooro inuu moobilke la waddaago subform_prevent_item_removal: Ka ilaali in Foom-hoosaadka laga laga saaro? - subform_sort_by: Iskugu Xiji + subform_sort_by: u kala horeysii successfully_added: Waad ku guulaysatey inaad ku darto qaybta tally_field: Tirada Qaybta tally_items: Tirada Shay'yada @@ -1181,6 +1258,10 @@ so: less: Ka yar more: Ka badan save_filters: Kaydso + categories: + violations: Xadgudubyo + incidents: 'dhacdooyinka ' + individual_victims: Shaqsiga Dhibanaha ah flags: add_flag_tab: Kudar Calaamad Calan Cusub date: 'Taariikhda' @@ -1248,6 +1329,8 @@ so: violation: Waxyeelo registry_details: xogta diwaanka oo faah faahsan registry_record: Kaydinta Diwaanka + family_record: 'Diwaanka Qoyska ' + family: 'Diwaanka Qoyska ' required_field: '%{field} waa goob loo baahan yahay' select_label: Calaamee settings: Hagaajinta @@ -1268,6 +1351,26 @@ so: type_label: Nooc visibility: La arki karayo web_app: Ablikeeshinka Shabakada + skip_logic: + name: iska daa Sababata + section: + title: Foomkani waa inuu muuqdaa haddii + buttons: + add: Kudar xaalad + conditions: + add: kudar xaalad + update: Cusboonaysii Xaalada + field_name: Magaca Qaybta + condition: Xaalad + empty: Majiro Xaalad lagu daray + type: Nooc + types: + and: + display_text: iyo kudar xaalad + name: iyo + or: + display_text: Ama Xaaladan + name: Ama home: ar: carabi ar-IQ: carabta iyo (ciraqda) @@ -1279,8 +1382,10 @@ so: dashboard: Dashboard-ka en: English es: Español - es-GT: Spanish ka( Guatsmala) + es-GT: Español + es-ES: spañol (España) fr: Français + hu: Magyar id: Bahasa km: Khmer language ku: kurdish @@ -1290,40 +1395,51 @@ so: sw-KE: Af Sawaaxiliga dalka (kenya) sw-TZ: Af Sawaaxiliga dalka ( Tansaaniya) ne: Nepali language + om: Oromo + am-ET: Amharic (Ethiopia) + tr: 'Turkiga ' label: Sabo language: Luuqad manage_system_users: Maamul Isticmaalayaasha Isku-xidhka Server-ka my: Burmese + pl: Polski pt: Burtuqiis pt-BR: Burtuqiis( Baraasiil) - records_need_attention: Diiwaannadu waxay u baahan yihiin in laga taxadiro + records_need_attention: 'Diiwaannadu waxay u baahan yihiin in laga taxadaro ' + ro: Romana ru: Русский + sk: Slovencina so: Af-Soomaali th: Thailand + uk: Українська users: Maamul Isticmaalayaasha view_records: Daawo Diiwaanada welcome: Ku soo dhawoow Primero zh: 中文 incident: + code: Sumada Dhacdada associated_case: "Kiis La xidhiidha" messages: creation_success: 'waad ku guulaysatey samaynta diwaangalinta dhacdada ' creation_success_queue: waad ku guulaysatey samayta samaynnta keydinta dhacdada si dahsoon disabled: Dhacdadan waa laga tanaasulay - update_success: 'waa lagu guulaystey cusboonaysiinta dhacdada %{Sumada xogta}' - update_success_queue: 'waa lagu guulaystey in la cusboonaysiiyo dhacdada si dahsoon %{diwaanka_aqoonsiga}' + update_success: 'waa lagu guulaystey cusboonaysiinta dhacdada %{record_id}' + update_success_queue: 'waa lagu guulaystey in la cusboonaysiiyo dhacdada si dahsoon %{record_id}' violation: + associated_violations: "Xadgudubyada Laxidhiidha" update_and_return: '%{association}cusboonaysii kana laabo ' - save_and_return: 'Ku dar kuna laabo halkii hore %{la xidhiidha}' + save_and_return: 'Ku dar kuna laabo halkii hore %{association}' pending: Sugaya In la Cadeeyo title: Waxyeelooyin ama Xadgudubyo types: killing: Dilidda Caruurta maiming: Dhaawicida caruureta recruitment: Shaqaalaysiinta ama isticmaalka caruurta - sexual_violence: Kufsi ama noocyo kale oo xadgudub galmo ah + sexual_violence: Kufsi iyo noocyada kale ee xadgudubka galmo abduction: Afduub attack_on: lagu weeraray dugsiga(yada) ama Cusbitaalka(ada) + attack_on_hospitals: Weerar Cusbitaalka(lada)ah + attack_on_schools: weerer Dugsiga (yada) military_use: Askar xaramo ka dhagata dugsiga(yada) ama Cusbitaalka(ada) denial_humanitarian_access: In loo diido caruurta helida adeegayada binaadanimo incidents: @@ -1334,6 +1450,7 @@ so: enable_dialog_title: Fasax ama ogolow Dhacdada enable_success: waad ku guulaysatey fasixida dhacdada id: Sumada# + complete: 'lagu heli karo khad la''aan ama offline ' date_of_interview: Taariikhda Waraysiga date_of_incident: Taariikhda Dhacdada incident_location: Goobta dhacdada @@ -1341,28 +1458,74 @@ so: export: u wareeji label: Dhacdooyinka filter_by: + filter_category: Shaandee Qaybaha boys: wiilal by_date: ' taariikh ahaan' children: caruur girls: Gabdho incident_location: goobta dhacdada + status: 'Heerka ' unaccompanied_separated_status: Heerka daryeelka unknown: aan la garanayn verification_status: heerka xaqiijinta violence_type: Nooca Xadgudubka - armed_force_group_name: 'Magaca Kooxda Xooga Ciidamada ' + armed_force_group_party_name: Kooxaha, ciidamada hubaysan armed_force_group_type: Nooca Xooga Ciidama + violations: Xadgudubyada + individual_violations: Xadgudubyo Shaqsiyeed + individual_age: Da'da Shaqsiga + individual_sex: Jinsiga Shaqsiga + victim_deprived_liberty_security_reasons: Xorriyadda laga qaaday + reasons_deprivation_liberty: Waa maxay sababaha Xorriyadda looga qaaday? + victim_facilty_victims_held: Fadlan door xarunta dhibbanaha(yaasha) lagu hayay + torture_punishment_while_deprivated_liberty: Ma ahaa ilmahu (carruurtu) kuwo loo geystay jirdil ama ciqaab arxan darro ah, ama loola dhaqmay si bini'aadantinimada ka baxsan iyadoo xorriyadda laga qaaday? + verified_ghn_reported: Cadee GHN ku jirey dhacdadan + weapon_type: 'Nooca hub/xeelad ee loo isticmaalay ' + facility_impact: 'Nooca iyo baaxadda saamaynta waxyeelada jireed' + facility_attack_type: 'Nooca caafimaadka- ama waxbarasho- ee la xidhiidha xadgudubka' + child_role: 'Doorkee ayay ilmahu (caruurtu) ka ciyaareen ciidanka qalabka sida?' + abduction_purpose_single: 'Ujeedada afduubka' + military_use_type: 'Nooca Militarigu u isticmaalo ' + types_of_aid_disrupted_denial: 'Nooca Caawimo/adeeg ee loo diidday/laga joojiyay ' + late_verified_violations: Xadgudubyada la xaqiijiyay xilli dambe + perpetrator_category: Nooca Dambiilaha + record_owner: diwaangaliyaha register_new_incident: Dhacdo Cusub selectable_date_options: date_of_first_report: Taariikhda Waraysiga + mrm_date_of_first_report: Taariikhda warbixinta bilowga ah ee xubnaha CTFMR + ctfmr_verified_date: Taariikhda go'aanka xaqiijinta ee CTFMR incident_date_derived: Taariikhda Dhacdada - selected_records: 'dhacdada (dhacdooyinka) la doortey %{Dooro_Diwaanada}' - selected_all_records: 'Calaamadee dhamaan dhacdooyinka la nooca dhacdadan % {Wadarta_diwaanada}' + selected_records: 'dhacdada (dhacdooyinka) la doortey %{select_records}' + selected_all_records: 'Calaamadee dhamaan dhacdooyinka la nooca dhacdadan %{total_records}' + summary_mrm: + label: Soo koobida dhacdada + fields: + children_multiple_violation: + label: 'Caruurta ay saamaysay xadgudubyo farabadan ' + summary_of_incident: + label: 'Soo koobida dhacdada ' + incident_total_tally: + label: Tirada Dhibanayaasha + boys: Wiilal + girls: Gabdho + unknown: 'Aan la garanayn ' + incident_date: + label: Taariikhda dhacdada + incident_location: + label: Goobta dhacdada + incident_description: + label: xogta dhacdada + incident_update: + label: Cusbooneysii Dhacdada survivor_code: Sumada Badbaadaha - show_incident: 'Aqoonsiga Dhacdada %{Sumada Aqoonsiga gaaban}' + show_incident: 'Aqoonsiga Dhacdada %{short_id}' social_worker: u adeegaha bulshada + violation_type: Nooca Xadgudubka violence_type: Nooca Xadgudubka type_violence: Nooca Xadgudubka + violation_summary: Soo koobid + sort_by: u kala horeysii key_performance_indicators: label: "Garaaca/KPIs" case_assessment: "Baadhista Kiiska" @@ -1534,6 +1697,12 @@ so: central_warehouse: 'Xarunta Dhexe ee Bakhaarka ' warehouse: Bakhaar buyingstation: Goob wax laga iibsado + township: 'Magaalada ' + municipality: 'Maamul magaalada ' + autonomous_region: 'ismaamul Goboleed ' + parish: Parish + cercle: Cercle + sub-county: Wadan-hoosaad label: Goobta name: Magaca code: Sumadda @@ -1699,7 +1868,7 @@ so: label: Xaqiijinta erayga sirta ah password_match: label: Furaha waa inuu iswaafaqaa - provider_title: leh %{bixiyaha} + provider_title: leh %{provider} title: Soo gal username: Magaca isticmaalaha password_reset_modal: Dib u deji erayga sirta ah @@ -1723,74 +1892,196 @@ so: no_options: Raadintan hadda ma laha wax ikhtiyaar ah. translation_label: Qoraalka Turjumaada values: Ikhtiyaarada + locked_alert_message: Raadintan way xidhantahay. managed_reports: + generated_on: La soo saaray label: Aragtida total: Wadarta + violations_total: Xadgudubyada filter_by: date: Taariikhda verification_status: Xaalada Xaqiijinta + violation_type: Nooca Xadgudubka + status: 'Heerka ' + status_open: Fur + status_closed: Wa la xidhay + user_group: Kooxda Isticmaalaha + agency: Haayada + by: ee + workflow: 'Heerka Shaqada Socota ' + cp_incident_violence_type: Nooca Xadgudubka + referral_transfer_status: Heerka Gudbinta/Wareejinta + status_options: + open: Fur + closed: 'xidhan ' + by_options: + created_by_groups: 'Kooxaha isticmaalaha diiwaanka samaysay ' + owned_by_groups: 'Kooxda Isticmaalaha ee diwaanka iskaleh ' + created_organization: 'Haayada Diwaanka samaysay ' + owned_by_agency_id: Haayada Diwaanka Leh + referral_transfer_status_options: + in_progress: 'La sugayo ' + accepted: La aqbalay + rejected: La diiday + done: 'La qabtey ama la sameeyay ' date_range: month: bisha quarter: Rubuc year: year + week: Todobaad date_range_options: this_quarter: Rubacan last_quarter: Rubucii u danbeyay this_month: bishan gudaheda last_month: bishii u danbaysay + this_week: Todobaadkan + last_week: 'Todobaadkii hore ' this_year: sanadkan last_year: sanadki hore custom: caddada no_data: wax xog ah kuma jirto halkan no_data_table: wax xog ah kama hayno shaxdan + incomplete_data: Xog aan dhamaystirnayn + individual_children: + name: 'Caruur gaar ah ' + reports: + individual_children: Caruur gaar ah + sub_reports: + individual_age: caruurta iyadoo lagu salaynayo da'dooda + individual_violation_type: Caruurta iyadoo lagu samaynayo nooca xadgudubka + individual_region: caruurta iyadoo lagu salaynayo deegaankooda + individual_perpetrator: caruurta iyadoo lagu salaynayo cida dhibka u gaysatey + ghn_report: + name: 'Xusuus Qorka Heer Caalami ah ' + reports: + ghn_report: 'Xusuus Qorka Heer Caalami ah ' + sub_reports: + verified_information: Xogta ay xaqiijiyeen - dhibaneyaasha + late_verification: xogta xili dambe ay xaqiijiyeen - dhivaneyaasha + unverified_information: Macluumaad Aan La Xaqiijin - Dhibanayaasha + verified_information_violations: Xogta La Xaqiijiyay - Xadgudubyada + late_verification_violations: Xaqiijinta goor dambe - Xadgudubyada + unverified_information_violations: Macluumaad Aan La Xaqiijin - Xadgudubyada + killing: 'dilista caruurta ' + maiming: Dhaawicida Caruurta + recruitment: shaqaalaysiinta ama kushaqaysiga caruurta + sexual_violence: Kufsi iyo noocyada kale ee xadgudubka galmo + rape: Kufsiga iyo noocyada kale ee xadgudubyada galmada + abduction: Afduub + attack_on_hospitals: Weerarada isbitaalka(lada) + attack_on_schools: Weerarada dugsiga(yada) + military_use: Isticmaalka militariga ee iskuulka(lada) iyo/ama isbitaalka(lada) + denial_humanitarian_access: Caruurta loo diido helida adeega gargaarka bini'aadantinimo + multiple_violations: Carruurta ay saameeyeen xadgudubyo farabadan + detention: 'Xadhiga Booliska ' + boys: 'Wiilasha ' + girls: 'Gabdhaha ' + total: Wadar + unknown: Aan lagaranayn + associated_violations: 'Xadgudubyada La Xidhiidha ' violations: name: xad gudug filter_options: incident_date: xogta dhacdada date_of_report: wakhtiga xogta la gudbiyay ctfmr_verified_date: wakhtiga la xaqijyay + verified: 'La Xaqiijiyay ' reports: killing: dilka caruurta maiming: dhicida caruurta recruitment: shaqalaysinta caaruurta - sexual_violence: kufsiga iyo tacadiyada kale + sexual_violence: Kufsiga iyo noocyada kale ee xadgudubyada galmada + rape: Kufsiga iyo noocyada kale ee xadgudubyada galmada abduction: afduub - attack_on: dorashada gobaha wax barasho(oyin) iyo xarunta(xarumaha) cafimadka + attack_on_hospitals: Weerarada Isbitaalka(lada) + attack_on_schools: Weerarada dugsiga(yada) military_use: Isticmaalka militariga ee iskuulada iyo/ama isbitaalada denial_humanitarian_access: Diidmada gargaarka bini'aadantinimo ee carruurta + detention: 'Xadhiga Booliska ' sub_reports: + children: 'Caruurta ' combined: Xadgudubyada + denial_humanitarian_access: 'Diidmada gargaarka biniadamnimo ' + denial_type: Nooca Diidmada detention_detained: Ku sii xirnaan detention_released: La sii daayay perpetrators: Tirada carruurta ay dhaleen dembiilayaasha + perpetrators_denial: Tirada xad-gudubyada ay geystaan dambiilayaasha + perpetrator_detention: Tirada carruurta ay waxyeelo loogaysteen dembiilayaasha + perpetrators_incidents: 'Tirada dhacdooyinka ay gaysteen Dembiilayaasha ' + reporting_location_incidents: Tirada dhacdada ee deegaan reporting_location: Tirada carruurta gobol ahaan + reporting_location_detention: Tirada Caruurta ee deegaan + reporting_location_denial: Tirada Xadgudubyada ee deegaan attack_type: Tirada Carruurta ee Nooca Weerarka boys: wilasha girls: hablaha unknown: an la garanayn total: guud ahan + violation: Xadgudubyada + sexual_violence_type: 'Nooca(yada) Xadgudubyada galmada ' + detention_status: 'Xaaladda Caruurta Booliska ku xidhan ' + type_of_use: 'Nooca isticmaalka ' + factors_of_recruitment: Sababaha Shaqaalaysiinta + still_being_held: Wali xidhan + released: 'La sii daayay ' + escaped: 'Baxsaday ' + abduction_reasons: Sababaha Afduubka + abducted_status: Xaaladda Afduubka + facility_attack_type: Nooca Xadgudubka + received_response: Carruurtu Waxay Heleen Adeeg Jawaab celin + male: Lab + female: Dhadig + military_use_type_of_use: Tirada Xadgudubyada ee Nooca isticmaalka gbv_statistics: name: tacadiyada ka dhanka ah jinsiga filter_options: date_of_first_report: Taariikhda Wareysiga incident_date: Taariikhda Dhacdada reports: - incidents: Dhacdada perpetrators: Dembiilayaasha + survivors: Badbaadeyaasha + referrals: 'Referaalada/adeeg gudbinta ' sub_reports: - combined: dhacdada - total: Tirada Dhacdooyinka GBV ee la soo sheegay - gbv_sexual_violence: Tirada Dhacdooyinka Xadgudubka Galmada ee la soo sheegay - gbv_previous_incidents: Tirada Dhacdooyinka ay Sheegeen Badbaadayaashu Dhacdooyin hore oo GBV ah - gbv_sexual_violence_type: Dhacdada Nooca - incident_timeofday: dhacdo Time of Day - elapsed_reporting_time: Waqtiga u dhexeeya Dhacdada iyo Taariikhda Warbixinta - elapsed_reporting_time_rape: Dhacdooyinka Kufsiga, Wakhtiga Dhex maray Dhacdada iyo Taariikhda Warbixinta - incident_location_type: dhacdo Location - number_of_perpetrators: Tirada dambiilayaasha aasaasiga ah - perpetrator_relationship: Xidhiidhka Dambiilaha Koowaad ee Lagu Eedeyay Badbaadiyaha - perpetrator_age_group: Kooxda da'da dembiilayaasha aasaasiga ah ee lagu eedeeyay - perpetrator_occupation: lagu eedeeyay Shaqadii Dambiilaha Koowaad + service_safehouse_referral: Gudbinta ama referral Hoy badbaado leh/Guri badbaado leh + service_medical_referral: 'Gudbinta ama Referral Adeegga Caafimaadka/daawaynta ' + service_psycho_referral: 'Adeegyada Niyad dhiska/Latalinta ' + service_legal_referral: Adeegyada Taageerada Sharci + service_police_referral: 'Booliska ama noocyada kale ee adeegga nabadgelyada ' + service_livelihoods_referral: Adeegyada Nolol Maalmeedka + service_protection_referral: 'Adeegyada Daryeelka Carruurta ' + survivors_disability_type: Naafada ah + workflow_report: + name: ' Shaqada Socoto' + reports: + cases_workflow: Kiisaska - Shaqadoodu Socoto + incidents_workflow: Dhacdooyinka - Shaqadoodu Socoto + filter_options: + registration_date: Taariikhda Diwaangalinta + sub_reports: + case_workflow_by_sex_and_age: Wadarta kiisaska oo u habaysan Jinsiga iyo da'da + incident_workflow_by_sex_and_age: Wadarta kiisaska oo u habaysan Jinsiga iyo da'da + referrals_transfers_report: + name: Gudbinta iyo Wareejinta + reports: + total_referrals: 'Gudbinta ' + total_transfers: Wareejinta + sub_reports: + total_transfers_by_user_groups: Wadarta Wareejinta + total_referrals_by_user_groups: 'Wadarta Gudbinta ' + filter_options: + registration_date: Taariikhda Diwaangalinta + violence_type_report: + name: Nooca Xadgudubka + reports: + cases_violence_type: Nooca Xadgudubka - Kiisaska + incidents_violence_type: 'Nooca Xadgudubka - Dhacdooyinka ' + filter_options: + registration_date: 'Taariikhda Diwaangalinta ' + sub_reports: + case_violence_type_by_sex_and_age: Wadarta kiisaska oo u habaysan Jinsiga iyo da'da + incident_violence_type_by_sex_and_age: Wadarta kiisaska oo u habaysan Jinsiga iyo da'da + success_message: Sooqaadida feylka waa lagu guuleystay messages: alert_items: waxa haysta %{items} qoraalo kookoobanoo dhawr ah. alerts_for: @@ -1834,10 +2125,12 @@ so: code_of_conduct: Xeerka hosadka terms_of_use: Shuruudaha isticmaalka system_information: nidamka maclumadka + resync: 'Xogta khad la''aan lagu diyaariyay ee aan la gudbin ' tasks: hawlaha tracing_request: Codsiga Baafinta activity_log: hawlaha diwanka registry_records: Diiwaanka + families: Qoysas notes: note_success: Si guul leh aya loogu daray qoraal permissions: @@ -1912,7 +2205,7 @@ so: export_custom: kastamka dhoofinta export_duplicate_id_csv: Dhoofinta nuqullada export_json: Dhoofinta json - export_list_view_csv: Dhoofinta liiska aragtida csv + export_list_view_csv: U badal liiska CSV export_mrm_violation_xls: Dhoofinta mrm xadgudub xls export_pdf: Dhoofinta pdf export_photowall: Dhoofinta sawirka darbiga @@ -1921,6 +2214,7 @@ so: find_tracing_match: Ka hel baafinta u dhiganta kiis view_registry_record: Eeg diiwaanka la dhigay add_registry_record: Ku dar diiwaanka diiwaanka + family: Qoys flag: Calamad Calan form: Foomamka group: Soo gal dhammaan diiwaanada ama isticmaalayaasha kooxdayda @@ -1980,6 +2274,7 @@ so: workflow_team: Socodka shaqada - Kiisaska kooxaha write: Qor activity_log: Diiwaanka Hawlaha + remove_alert: Kasaar Alertiga ama feejignaanta resource: kpi: actions: @@ -2136,7 +2431,7 @@ so: label: Dhoofinta JSON export_list_view_csv: explanation: Isticmaaluhu waxa uu ka soo saari karaa faylka CSV ka dhoofinta bogga liiska kiisaska kaas oo ka kooban qaybo isku mid ah kuwaas oo u muuqda isticmaalaha liiska kiisaska. Kaliya laga sameeyay bogga liiska kiisaska. - label: Gedinta liiska aragtida CSV + label: U badal liiska CSV export_pdf: explanation: Isticmaaluhu wuxuu ka soo saari karaa dhoofinta faylka PDF liiska kiisaska ama bogagga bandhiga kiiska, kaas oo ka kooban dhammaan goobaha uu isticmaaluhu hadda geli karo, hal, badan, ama dhammaan kiisaska uu isticmaaluhu geli karo. Faylka dhoofinta PDF, macluumaadka waxaa lagu taxay marka hore kiis, ka dibna waxaa lagu sii habeeyey foomka ay macluumaadka ku soo baxayaan. label: U badal kiiska PDF ahan @@ -2165,6 +2460,9 @@ so:  ' label: Ka abuur dhacdo kiiska + remove_alert: + explanation: Fasaxani wuxuu u oggolaanayaa inuu isticmaaluhu uu Aletiga digniinta kasaaro. Alertiga digniinta ayaa soo baxa marka qayb kamid ah qoraalka la badalo sida marka xusuus qorka la cusboonaysiiyo. Alertiga digniinta waa calaamad huruud ah ee kuxigta kiiska + label: Kasaar Alertiga digniinta kiiska manage: explanation: U oggolow isticmaaluhu inuu sameeyo dhammaan ficillada la heli karo ee kiisaska. Oggolaanshaha "Maamul" asal ahaan macnaheedu waa "wax walba" label: Maamul (dhammaan oggolaanshaha noocyada kheyraadkan) @@ -2255,6 +2553,15 @@ so: mark_for_offline: explanation: Waxay u ogolaataa isticmaalaha inuu kaydiyo Kiis si loogu isticmaalo offline. label: Ku calaamadee khadka offline + view_family_record: + explanation: Isticmaaleyaashu waxay arli karaan Foomka 'Diwaanka qoyska' ee kiiska + label: Arag diwaanka qoyska ee kiiska + case_from_family: + explanation: Isticmaalayaashu waxay ka dhex samayn karaan Kiis mid ka mid ah xubnaha qoyska xogta kujitta foom hoosaadka qoyska. Xusuusnoow in sib ootomaatik ah looga samayn karo si loo xidhiidhiyo labo kiis + label: ka samee kiis xogta qoyska + link_family_record: + explanation: Tani waxy u ogolaataa isticmaaluhu inuu raadiyo oo ku xidho kiis diiwaanka qoyska kaasoo horey ugu jirey kayda. Sidoo kale waxay u ogolaadaa isticmaalayaasha in ay kiis ka dhex saaraan diiwaanka qoyska + label: Kiiskan ku xidh/haku xidhin diiwaan qoys explanation: Waxay matashaa ilmo gaar ah, badbaade, ama ka faa'iidayste kale. label: Kiis dashboard: @@ -2308,7 +2615,6 @@ so: explanation: Waxay u ogolaataa maareeyaha inuu arko inta kiis ee leh hawlaha adeegga ee mid kasta oo ka mid ah shaqaalahooda. label: Hawlaha Adeegga ee wakhtigoodii dash_case_incident_overview: - explanation: . label: Dulmar - Kiisaskayga / Dhacdooyinkayga dash_cases_by_social_worker: explanation: Shaxda taas oo tuseysa sida wadarta tirada kiisaska furan iyo tirada kiisaska cusub ee uu maareeyo isticmaale kasta oo ka tirsan kooxaha isticmaalaha hadda. Saf kastaa waa isticmaale kooxaha isticmaale ee hadda jira, halka "Total" iyo "New" ay yihiin labada tiir. @@ -2351,6 +2657,15 @@ so: dash_shared_with_others: explanation: Waxay tustaa inta kiiskeyga ka mid ah ee leh tixraac firfircoon, wareejinta sugaysa, ama wareejinta la diiday. Caadi ahaan maareeyayaasha, ilaa ay iyagu maareeyaan kiisaska. label: La wadaaga dadka kale + dash_violations_category_verification_status: + explanation: Waxay tusinaysaa inta xadgudubyada MRM ee Nooc kasta kuwaasoo lagu kala saaray heerka xaqiijintooda + label: 'MRM - Tirada xadgudubyad ee heerka xaqiijintooda ' + dash_violations_category_region: + explanation: Waxay tusinaysaa inta xadgudubyada MRM ee ka dhacay Deegaan. kuwaas oo lagu kala saaray nooca xadgudubka + label: MRM - Tirada xadgudubyada ee Deegaan kasta + dash_perpetrator_armed_force_group_party_names: + explanation: Waxay tusinaysaa inta xadgudubyada MRM noocyadiisa kala duwan ee dhacay kuwaas oo lagu kala saaray Dambiilaha + label: MRM - Tirada xadgudubyada ee Dambiilaha dash_show_none_values: explanation: Waxay ku daraysaa qayb dheeraad ah "Heerka Khatarta" dhammaan dashboards-ka kaas oo u kala qaybiya kiisaska heerka khatarta. Tani waxay si gaar ah ugu socotaa habaynta kuwaas oo leh ikhtiyaarka afraad "Khatarta ma jirto" ee goobaha heerka khatarta. label: Ku arag kiisaska 'Heerka Halis malaha' ee ku jira Dashboardka Qiimaynta @@ -2404,6 +2719,8 @@ so: registry_record: explanation: 'Xakamaynta gelitaanka isticmaalaha foomamka diiwaanka ayaa xaddidaya macluumaadka uu isticmaaluhu ku arki karo diiwaanka. Tusaale ahaan, haddii isticmaaluhu uu kaliya heli karo foomka Mulkiilaha Diiwaanka, waxay sidoo kale awoodi doonaan oo kaliya inay arkaan macluumaadka ku jira goobaha foomkaas. Haddii isticmaaleha hadda uu leeyahay qaab xaddidan oo uu awood u leeyahay inuu maareeyo qaabeynta foomka, xaddididda gelitaanka foomka waxay sidoo kale xaddideysaa foomamka ay habeyn karaan. FIIRO GAAR AH: Haddii aan foomam la cayimin, waxay la macno tahay doorku inuu galo dhammaan foomamka diiwaangelinta.' label: Foomamka - Diiwaangelinta + family: + label: Foomamka - Qoys group: actions: admin_only: @@ -2450,6 +2767,9 @@ so: export_incident_recorder_xls: explanation: Isticmaaluhu waxa uu dhalin karaa dhoofinta faylalka XLS ee khaaska ah kaas oo u oggolaanaya in lagu beddelo xogta qalabka Diiwaangelinta Dhacdada GBV. label: U Badal duubaha dhacdada xls + export_mrm_violation_xls: + explanation: Isticmaaluhu wuxuu soo saari karaa fayl gaar ah oo Excel ah (faylka XLS) midkaas oo uu u badali karo xadgudubyada MRM. Tallaabadan ayaa laga heli karaa bogga bandhigga Dhacdada iyo Liiska Dhacdada. + label: Faylka Xadgudubyada MRM Ubadal fayl Microsoft Excel ah (XLS fayl) export_json: explanation: Isticmaaluhu wuxuu ka soo saari karaa dhoofinta faylka JSON liiska dhacdada ama bogagga bandhiga dhacdada, oo ka kooban dhammaan goobaha uu isticmaaluhu galo, hal, badan, ama dhammaan shilalka uu isticmaaluhu geli karo. Dhoofintan waxaa inta badan loo isticmaalaa kuwa doonaya inay shilalka ka dhoofiyaan nidaamka Primero ee hadda jira ka dibna u soo dhoofiya nidaam Primero ka duwan, ama nidaam kale oo maareynta macluumaadka. Habka JSON waa mashiinka-akhrisan karo mana aha mid la taaban karo inta badan isticmaalayaasha. label: U Badal JSON @@ -2468,6 +2788,9 @@ so: import: explanation: U oggolow isticmaaluhu inuu abuuro hal ama dhowr shil oo cusub isagoo ka soo dejinaya faylka CSV, Excel, ama JSON. Faylka la soo dejiyay waa in loo qaabeeyaa *aad* gaar ahaan si macluumaadka loogu soo dejiyo si sax ah. Shaqadani waa in ay ahaataa oo kaliya dadka isticmaala maamulka ee leh xirfado farsamo oo horumarsan iyo aqoon qoto dheer oo ku saabsan sida xogta loo qaabeeyey Primero. Kaliya laga sameeyay bogga liiska dhacdada. label: Soo dejinta + remove_alert: + explanation: Fasaxani wuxuu u oggolaanayaa inuu isticmaaluhu uu Aletiga digniinta kasaaro. Alertiga digniinta ayaa soo baxa marka qayb kamid ah qoraalka la badalo sida marka xusuus qorka la cusboonaysiiyo. Alertiga digniinta waa calaamad huruud ah ee kuxigta kiiska + label: Kasaar Alertiga digniinta kiiska manage: explanation: U oggolow isticmaaluhu inuu sameeyo dhammaan ficillada la heli karo ee shilalka. Oggolaanshaha "Maamul" asal ahaan macnaheedu waa "wax walba". label: Maamul (dhammaan oggolaanshaha nooca kheyraadkan) @@ -2487,10 +2810,26 @@ so: label: Maareeye miyaa? managed_report: actions: + managed_report_scope: + label: Diwaanadee ayuu arki karaa isticmaalahan? + managed_report_scope_all: + label: 'Dhamaan ' + managed_report_scope_group: + label: Xog ku salaysan koox kaliya + managed_report_scope_agency: + label: Xog kusalaysan haayad kaliya violations: label: Xadgudubyada gbv_statistics: label: Tirakoobka GBV + ghn_report: + label: 'Xusuus Qorka Heer Caalami ah ' + individual_children: + label: Caruur gaar ah + violence_type_report: + explanation: Awoodda lagu eego tirakoobyada Nooca Tacadiyada. Oggolaanshahan ayaa sidoo kale u ogolaanaya isticmaalaha in uu u badalo xogta Aragtida + referrals_transfers_report: + explanation: Isticmaalayaashu waxay arkaan tirada kiisaska loo gudbiyay oo laga wareejiyay koox kasta oo isticmaale ah midba midka kale matching_configuration: actions: manage: @@ -2520,6 +2859,15 @@ so: read: explanation: Waxay ka tarjumaysaa xidhiidhka ka dhexeeya Codsiga Baafinta iyo Kiis. Helitaanka Ciyaaraha suurtagalka ah ayaa lagama maarmaan u ah Baafinta Qoyska iyo Dib-u-midaynta (FTR). Waxay u ogolaataa isticmaalaha inuu arko foomka Soo koobida Baafinta ee Kiisaska. label: Fiiri + view_audio: + explanation: waxay kontoroolaysaa haddii isticmaale raadiniya Baafin lamid ah inuu arki karo faylka codka maqalka ah ee kiiska ama Codsi Baafin la xidhiidha ama leh tilmaamo isku ekaansho oo macquul ah. + label: Dhagayso Codka + view_photo: + explanation: waxay kontoroolaysaa haddii isticmaale raadiniya Baafin lamid ah inuu arki karo sawirada kiiska ama Codsi Baafin la xidhiidha ama leh tilmaamo isku ekaansho oo macquul ah. + label: 'Fiiri ama daawo Sawirada ' + manage: + explanation: U oggolow isticmaaluhu inuu sameeyo dhammaan ficillada la heli karo ee ku saabsan tilmaamaha isku ekaanshaha macquulka ah. Oggolaanshaha "Maamul" asal ahaan macnaheedu waa "wax walba". + label: Maaree label: Ciyaarta suurtagalka ah primero_configuration: actions: @@ -2570,6 +2918,49 @@ so: label: Ku calaamadee khadka offline explanation: Tani waxay matali kartaa shakhsi ama hay'ad u baahan in lagu xidho diiwaanada kale sida kiisaska ama dhacdooyinka, aad u badan, oo marar badan lagu cusboonaysiiyo macluumaad cusub. Waxay la mid yihiin raadinta, laakiin leh xog aad u adag oo gelitaan kasta ah. label: Diiwaanka + family: + actions: + change_log: + explanation: Isticmaaluhu wuxuu arki karaa taariikhda dhammaan isbeddellada lagu sameeyay diiwaanka tan iyo markii la sameeyay. Tan waxaa ku jira qiyamka loo diiwaan geliyay dhammaan goobaha. + label: Badal qaabka + create: + explanation: Awooda in la sameeyo diiwaan qoys + label: Samee + enable_disable_record: + explanation: Kartida lagu curyaamin karo ama awood u yeelan karo Qoyska. Qoysaska "Naafada" si caadi ah ugama soo muuqdaan liiska qoyska. Isticmaalayaashu waxay ku arki karaan Qoyska naafada ah liiska qoyska iyagoo isticmaalaya filter + label: Daar/Dami + export_csv: + explanation: 'Qoyska. Qoysaska "Naafada" si caadi ah ugama soo muuqdaan liiska qoyska. Isticmaalayaashu waxay ku arki karaan qoysaska naafada ah ee ku jira liiska qoyska iyagoo isticmaalaya filtar Isticmaaluhu wuxuu soo saari karaa dhoofinta faylka CSV ee liiska qoyska ama boggaga qoyska, kaas oo ka kooban dhammaan goobaha uu isticmaaluhu hadda galo, mid, badan, ama dhammaan Qoysaska isticmaalaha ayaa marin u leh. FIIRO GAAR AH: dhoofinta CSV ma keento xuruuf aan Latin ahayn ( tusaale Carabi, Bangla)' + label: U badal CSV + export_json: + label: U badal JSON + export_xls: + label: U badal Excel (Nooca faylka XLS) + export_list_view_csv: + label: U badal liistada CSV + export_pdf: + label: ubadalid PDF + export_custom: + label: Habaynta faylasha la badalayo. + flag: + label: Calaamad Calan + manage: + label: Maaree (dhamaan fasaxyada nooca xogtan) + read: + explanation: awooda inuu arko ama fiiriyo xogta qoyska + label: araga + write: + explanation: awooda inuu wax ka badalo, 'Edit gareeyo', cusboonaysiiyo xogta qoyska kadibna uu 'Kaydiyo ama save gareeyo + label: Wax kabadal + close: + label: Xidh + reopen: + explanation: Tani waxay isticmaalaha u ogolaanaysaa inuu furo xogta qoys kasoo wakhtigan lajoogo xidhan + label: Dib u fur + case_from_family: + explanation: 'u ogolaanaya in isticmaalayaashu sameeyaan kiis cusub iyagoo ka dhex samaynaya foom hoosaadka xubnaha qoyska ee diwaanka qoyska ' + label: Samee Kiis + label: Qoyska report: actions: create: @@ -2592,6 +2983,9 @@ so: write: explanation: Awoodda wax ka beddelka dhammaan warbixinnada (ay ku jiraan kuwa ay abuureen isticmaaleyaasha kale). label: Wax ka beddel + agency_read: + explanation: Awoodda lagu eego dhammaan warbixinnada Tirooyinka ku jira warbixin kasta waxay ka turjumi doonaan oo keliya diiwaannada ay heli karaan isticmaalayaasha Wakaaladda isticmaalahan Oggolaanshahan waxaa badanaa loo isticmaalaa maamulayaasha wakaalada. + label: 'Fiiri ama arag (xogta ku salaysan wakaalada) ' explanation: Qalabka falanqaynta xogta wadarta Waxaa ku jira jaantusyada shaxda iyo garaafyada xogta. label: Warbixin reporting_location_level: @@ -2777,7 +3171,6 @@ so: display: Ka muuqato aad isugu eekaansho %{type}%{id} reassign: multiple_error: Khalad baa dhacay. %{select_records} kiiska(kiisaska) lama meelayn. - multiple_successfully: '%{select_records} kiiska(kiisaska) waa lagu guulaystay in la meeleeyo' notes_label: Xusuusin successfully: Si guul leh ayaa dib loogu magacaabay user_mandatory_label: Qaataha ayaa loo baahan yahay @@ -2864,6 +3257,7 @@ so: record_type: Nooca diiwaanka total: Wadarta value: Qiimaha + incomplete_data: Xog aan dhamaystirnayn reports: delete_report: Tirtir Warbixinta delete_report_message: Ma hubtaa inaad doonayso inaad tirtirto warbixintan? Tirtirka lama celin karo Guji OK si aad u tirtirto warbixinta @@ -2964,6 +3358,10 @@ so: match: Isku beeg matches: Tartamada unmatch: Isku-dheelid la'aan + tracing_request_photos: Sawirada Codsigan Baafinta + case_photos: Sawirada Kiiskan + tracing_request_audios: Codka Codsigan Baafinta + case_audios: 'Maqalka kiiskan ' messages: already_matched: Waxa horeba u jiray hab isku mid ah oo uu la socdo qof wax waydiinaya oo raadinaya ilmahan. disabled: Codsiga baafinta waa la joojiyay @@ -2988,6 +3386,7 @@ so: enable_dialog_title: Ku Darida Codsiga Baafinta enable_success: Si guul leh ayaa u suurtageliyay codsiga raadinta id: aqoonsi + complete: 'lagu heli karo khad la''aan ama offline ' filter_by: by_date: By Taariikhda location_separation: Goobta Kala Saarida @@ -3002,9 +3401,10 @@ so: inquiry_date: Taariikhda Weydiinta selected_records: '%{select_records} codsiga(yada) raadinta ee la doortay' selected_all_records: 'Dooro dhammaan %{total_records} codsiyada raadinta ee ku habboon weydiintan.' - show_tracing_request: 'Baafinta Codsiga Aqoonsiga %{gaaban_id}' + show_tracing_request: 'Baafinta Codsiga Aqoonsiga %{short_id}' tracing_requests: Codsiga Radinta export: U badal + sort_by: u kala horeysii registry_records: id: aqoonsi label: Diiwaanka Diiwaangelinta @@ -3020,6 +3420,7 @@ so: enable_dialog_title: Daar Diiwaanka Diiwaangelinta enable_dialog: Gujista OK waxay bedeli doontaa heerka diiwangelintan oo u beddeli doonta karti. enable_success: Si guul leh ayaa u suurtageliyay diiwaanka diiwaangelinta + complete: 'lagu heli karo khad la''aan ama offline ' filter_by: by_date: By Taariikhda status: Xaalada @@ -3032,6 +3433,42 @@ so: title: 'muji ka maqanaasho hawada ' text: ma hubta in aad muujiso in la isticmaalo diwaankan adiga oo hawada ka maqan success: Adeegsiga diwaankan waxaa uu muujiisanyahay ka maqanasho hawo. + families: + id: Summad + label: 'Qoysaska ' + family_id: 'Summada Qoyska ' + family_number: 'Lambarka Qoyska ' + family_name: 'Magaca Qoyska ' + family_registration_date: Taariikhda Diwaangalinta + family_location_current: 'Goobta Qoyska ' + export: U badal + register_new_family: 'Qoys Cusub ' + show_family: 'Sumadda Qoyska %{short_id}' + disable_dialog_title: Dami ama qari Xogta qoyska + disable_dialog: Taabashada OK waxay badali doontaa xigta qoyska mid qarsoon + selected_records: '%{select_records}® Diwaanka(nada) qoyska la doortay ' + selected_all_records: 'Dooro dhamaan %{total_records} qoysaska la mid ah xogtan' + mark_for_offline: + title: Kadhig mid lagu heli karo khad la'aan ama offline. + text: Ma hubtaa inaad doonayso inaad ka dhigto diwaanada qoyska kuwo aad isticmaasho markaad khad la'aan tahay ama offline. + success: 'Diwaanada qoyska waxaad ka dhigtey kuwo aad isticmaali karto marka aad khad la''aan tahay ama offline ' + filter_by: + by_date: 'Ee Taariikh ' + status: 'Heerka ' + current_location: 'Goobta Qoyska ' + family: + family_member: + case_id: Summada Kiiska + update_and_return: Cusbooneysii kadibna dib ooga noqo + save_and_return: Kudar kadibna dib ooga noqo + create_case: Samee Kiis + back_to_family_members: 'Dib ugu noqo Xubnaha Qoyska ' + create: Samee + messages: + update_success: 'Xogta Qoyska %{record_id} ®Waa La Cusboonaysiiyay.' + creation_success: 'Waad ku guuleystay inaad Xog Qoys Samayso' + disabled: 'Xogta Qoyska Waa la qariyay ' + confirm_create_case: Miyaad doonaysaa inaad Kiis u samayso shaqsigan transfer: label: wareeji agency_label: Xafiis @@ -3125,13 +3562,17 @@ so: provider_username_help: 'Tusaale . magaca isticmaalaha@%{domain}' role_id: Doorka send_mail: Hel ogeysiis iimaylka? + receive_webpush: + label: 'Hell Ogaysiisyada ' + help_text: 'Fiiro Gaar ah: waxaad wali u baahantahay inaad u fasaxdo helida ogaysiisyada sooftiweerka barawsarka aaladaada' + tooltip: 'Uguhorayn Waa inaad ciwaankaaga ka hagaajiso fasaxa helida ogaysiisyada ee isticmaalahaaga ' user_group_unique_ids: Kooxaha Isticmaalayaasha user_name: Magaca isticmaale services: Adeegyada welcome_email: subject: 'Ku soo dhawoow %{system}!' greeting: 'Ku soo dhawoow %{system}!' - body_native: 'Waxaa lagugu daray %{role_name} Fadlan la xidhiidh %{admin_full_name} (%{admin_email}) si aad ula socoto tilmaamaha si aad u bilowdo la shaqaynta%{host' + body_native: 'Waxaa lagugu daray %{role_name} Fadlan la xidhiidh %{admin_full_name} (%{admin_email}) si aad ula socoto tilmaamaha si aad u bilowdo la shaqaynta %{host}' sso: body: 'Waxaa lagugu daray %{role_name}' step1: 'Aad %{host} oo dhagsii %{identity_provider}.' @@ -3149,9 +3590,9 @@ so: text_label: Ku Soo Dhawoow Emailka Qoraalka password_reset: subject: 'Dib u deji tilmaamaha erayga sirta ah' - email_greeting: "Gacaliye %{Magaca oo dhamaystiran}" + email_greeting: "Gacaliye %{full_name}" email_body1: "Qof ayaa codsaday inuu dejiyo eraygaaga sirta ah %{host_href}. Guji url-ka hoose si aad u bilowdo:" - email_body2: "Xiriirintani waxa ay dhacaysaa %{saacado} saacadood oo waxa la isticmaali karaa hal mar oo kaliya. Fadlan iska ilow iimaylkan haddii aadan samayn codsi dib u dejin sirta ah ama isticmaale Primero cusub aan loo diwaan gashanayn magacaaga. Haddii xidhiidhka sare uu dhacay, fadlan dhagsii %{reset_request_href} si aad dib ugu soo gudbiso codsiga dib u dejinta erayga sirta ah." + email_body2: "Xiriirintani waxa ay dhacaysaa %{hours} saacadood oo waxa la isticmaali karaa hal mar oo kaliya. Fadlan iska ilow iimaylkan haddii aadan samayn codsi dib u dejin sirta ah ama isticmaale Primero cusub aan loo diwaan gashanayn magacaaga. Haddii xidhiidhka sare uu dhacay, fadlan dhagsii %{reset_request_href} si aad dib ugu soo gudbiso codsiga dib u dejinta erayga sirta ah." email_body_link: halkan request_submitted: "Codsiga dib u habeynta erayga sirta ah waa la gudbiyay" success: "Si guul leh ayaa loo beddelay erayga sirta ah" @@ -3159,10 +3600,10 @@ so: reset_password_token: "Calaamada dib u habeynta erayga sirta ah ee aan ansax ahayn" password_confirmation: "Erayada sirta ah waa inay iswaafaqaan" onboard_email: - subject: "U fuulida %{Nidaamka}" - greeting: "Gacaliye%{magac oo dhamaystiran}," + subject: "U fuulida %{system}" + greeting: "Gacaliye %{full_name}," body1: "Ku soo dhawoow Primero!" - body2: "Waxaa laguu magacaabay maamulaha fulinta %{host_href}. %{reset_ogaysiis}" + body2: "Waxaa laguu magacaabay maamulaha fulinta %{host_href}. %{reset_notification}" body2_reset_notification: "Waxaad heli doontaa iimayl dheeraad ah oo kugu dhiirigelinaya inaad dib u dejiso eraygaaga sirta ah." body3: "Adiga ayaa mas'uul ka ah xaqiijinta amniga iyo hirgelinta waqtiga. Dib-u-dejin kasta, waa inaad ku dhammaystirtay Qorshaha Hirgelinta oo leh istaraatijiyadda maamulka isticmaale iyo borotokoolka wadaagga macluumaadka. Waxaad sidoo kale mas'uul ka tahay inaad hubiso in Shuruudaha Isticmaalka ee saxeexan uu ku jiro faylka dhammaan ururada isticmaala." user_group: @@ -3192,6 +3633,10 @@ so: last_attempt: "waxaa ku hadhday hal mar in aad isku daydo" admin: locations: - selected_records: '%{Dooro diiwaangaliyaha} goobta(yada) la doortay' + selected_records: '%{select_records} goobta(yada) la doortay' selected_all_records: Dooro dhamaan %{total_records}kiisaska waafaqsan nidaamkan - updated: '%{Dooro diiwaangaliyaha} goobta(yada) la doortay' + updated: '%{updated_records} goobta(yada) la doortay' + push_notifications_dialog: + title: Ogaysiiska Aalada + body_blocked: + message: Waxaad xidhay helida ogaysiisyada Primero ee aalada. Si aad u hagaajiso midan, waxaad u baahantahay inaad furto ama aad shido fasaxa ogaysiiska diff --git a/config/locales/sw-TZ.yml b/config/locales/sw-TZ.yml index 5532056939..99578638d4 100644 --- a/config/locales/sw-TZ.yml +++ b/config/locales/sw-TZ.yml @@ -1,447 +1,465 @@ -sw_TZ: +sw-TZ: 'true': 'Ndio' 'false': 'Hapana' accepted: Imekubalika - cancel: Sitisha / Futa + cancel: 'Sitisha ' connection_lost: Hakuna mtandao kwa sasa + field_mode_offline: Inatumika kwa sasa connected: Imeunganishwa - clear: 'Iko wazi ' - sandbox_ui: Onesha - description: maelezo + no_connection: Haijaunganishwa + clear: Iko sahihi + sandbox_ui: Majaribio + description: Maelezo form: Fomu - minimum_reportable_fields: "%{record_type}Sehemu za chini zinazoweza kuripotiwa " + minimum_reportable_fields: "%{record_type}Kiwango cha chini kinachoweza kuripotiwa " name: Jina offline: Nje ya mtandao - unavailable_offline: Haipatikani nje ya mtandao - online: katika mtandao + field_mode: "Field Mode: %{mode}" + field_mode_on: "Washa" + field_mode_off: "Zima" + unavailable_offline: Haupatikani nje ya mtandao + online: Kwenye Mtandao yes_label: 'Ndio' or_label: au select_provider: chagua mtoa huduma select_language: Chagua lugha log_in_primero_idp: 'Ingia kwa 1%{idp_jina} jina la mtumiaji ' offline_submitted_changes: Kwa sasa upo nje ya mtandao. Marekebisho yako yatawasilishwa utakaporejea kwenye mtandao. - updated: Imesasishwa + updated: Imerekebishwa + go: Nenda + select_idp_error: Tafadhali chagua mtoa huduma sync: - success: "1%{kumbukumbu} kumbukumbu zako zimehusianishwa vizuri" + success: "1%{kumbukumbu} kumbukumbu zimeunganishwa vizuri" error: - create: Imeshindwa kuunda 1%{ainaya_kumbukumbu}. Tafadhali wasiliana kwa msaada. - update: Imeshindwa Kusashisha 1%{aina_rekodi} 2%{tambulisho_fupi} Tafadhali wasiliana kwa msaada + create: Imeshindwa kutengenezwa 1%{ainaya_kumbukumbu}. Tafadhali wasiliana kwa msaada. + update: Imeshindikana kurekebishwa 1%{aina_rekodi} 2%{tambulisho_fupi} Tafadhali wasiliana kwa msaada actions: approvals: Idhini - button: Vitendo + button: Hatua close: Funga description: - invalid: Rekodi batili - valid: Rekodi sahihi + invalid: Kumbukumbu zisizofaa + valid: Kumbukumbu zinazofaa disable: Zuia enable: Wezesha - incident_details_from_case: Ongeza tukio + incident_details_from_case: Ingiza tukio incident_from_case: Tengeneza tukio - next: nyingine - notes: Ongeza maelezo + next: nyengine + notes: Ingiza maelezo previous: Iliyopita - reopen: fungua tena + reopen: Fungua tena request_approval: Omba Idhini revoke: Batilisha - save: Tunza - services_from_case_creation_success: Rekodi ya Utoaji wa Huduma imefanikiwa kuundwa - services_section_from_case: Ongeza Utoaji wa Huduma - mark_for_offline: Alama kwa Nje ya Mtandao + save: Hifadhi + services_from_case_creation_success: Kumbukumbu ya Utoaji wa Huduma imekamilika + services_section_from_case: Ingiza Huduma inayotolewa + mark_for_offline: Alama Nje ya Mtandao agencies: - label: Shirika + label: Taasisi translations: - manage: Dhibiti Tafsiri + manage: Simamia Tafsiri agency: - agency_logos: Nembo za Mashirika - code: Code ya Shirika + agency_logos: Nembo za Taasisi + code: Msimbo wa Taasisi description: Maelezo disabled: Imezuiliwa - exclude_agency_from_lookups: Ondoa shirika hili katika upekuzi na uchunguzi - exclude_agency_from_lookups_help: Chunguza kama shirika hili halina watumiaji (mfano, Shirika lilijumuishwa ili nembo itumike kwa ajili ya utumaji - label: Shirika - logo_enabled: 'Ungependa kuonyesha nembo ya shirika hili katika Primero? ' - logo_enabled_help: 'Ungependa kuonyesha nembo ya shirika hili katika Primero? ' + exclude_agency_from_lookups: Ondoa Taasisi hii katika uchambuzi na upembuzi + exclude_agency_from_lookups_help: Hakiki kama Taasisi hii haina watumiaji (mfano, Taasisi ilioingizwa ambayo nembo yake inaweza kutumika kuhamishia. + label: Taasisi + logo_enabled: 'Je, Nembo ya Taasisi hii ioneshe katika Primero? ' + logo_enabled_help: 'Je, Nembo ya Taasisi hii ioneshe katika Primero? ' logo_icon: Alama ya nembo - logo_icon_help: Hii itaonekana kwenye saizi ndogo za skrini, tablets, na simu. Hii inapaswa kuwa mraba. + logo_icon_help: Hii itaonekana kwenye saizi ndogo za skrini, Vishkwambi, na simu janja. Hii inapaswa kuwa mraba. logo_large: Nembo Kubwa logo_large_help: 'Hii itaonekana kwenye saizi kubwa za skrini na katika muundo wa PDF. Hii inapaswa kuwa mstatili, na urefu mkubwa kuliko upana. ' messages: - created: Shirika limefanikiwa kutengenezwa - updated: Shirika limesasishwa vyema - name: Jina la Shirika + created: Taasisi imefanikiwa kutengenezwa vyema + updated: Taasisi imesawazishwa vyema + name: Jina la Taasisi pdf_logo_option: Fanya nembo ionekane katika muundo wa PDF? - pdf_logo_option_help: 'Kumbuka: nembo za mashirika ya watumiaji zinapatikana kwao kwa msingi, kwa hivyo angalia ikiwa unataka nembo hii ipatikane kwa watumiaji wote. ' - services: Huduma za Mashirika + pdf_logo_option_help: 'Kumbuka: nembo za Taasisi za watumiaji zinapatikana kwao wenyewe, hivyo unaweza ukitaka nembo hii ipatikane kwa watumiaji wote. ' + services: Huduma za Taasisi terms_of_use: Masharti ya matumizi terms_of_use_help: 'Zinaruhusiwa Faili za PDF tu. ' terms_of_use_download_button: Pakua PDF terms_of_use_enabled: 'Onyesha Masharti ya Matumizi? ' approvals: - approved_by: Imeidhinishwa na - case_plan_type_label: Aina ya mpango wa kesi - manager_comments_label: Dhibiti Maoni + approved_by: Imethibitishwa na + case_plan_type_label: Aina ya mpango wa Shauri + manager_comments_label: Maoni ya Meneja rejected_by: 'Imekataliwa na ' requested_by: Imeombwa na - requested_for_label: Idhini iliyoombwa kwa - requested_for_title: Ombi la idhini - response_for_label: 'Idhini kwa ' - response_for_title: Idhini + requested_for_label: Uthibitisho uliyoombwa kwa + requested_for_title: Ombi la Uthibitisho + response_for_label: 'Uthibitisho kwa ' + response_for_title: Ithibati action_plan: Mpango wa utekelezaji gbv_closure: Kufungwa kwa Udhalilishaji wa Kijinsia status: - approved: Imeidhinishwa + approved: Imethibitishwa pending: Inasubiri rejected: Imekataliwa requested: Imeombwa audit_log: - action: Hatua / Kitendo + action: 'Hatua ' description: Maelezo - record_owner: Mmiliki wa rekodi - timestamp: Wakati / Muda - user_name: 'Uliofanywa na ' + record_owner: Mmiliki wa kumbukumbu + timestamp: Muda + user_name: 'Iliyotekelezwa na ' bulk_export: file_name: Faili record_type: Aina - retry: Usafirishaji huu ni batili. Tafadhali jaribu kurudisha / kurekebisha usafirishaji wako + retry: 'Uhamishaji huu ni batili. Tafadhali jaribu kuhamisha tena ' started_on: Ilianza - status: Hali + status: Hatua form_export: - label: 'Usanidi wa Fomu ya kuuza nje ' - include_hidden: Ni pamoja na fomu na uwanja uliofichwa + label: Usanidi wa Fomu ya uhamisho + include_hidden: Zikiwemo fomu na sehemu zilizojificha file_name: Tengeneza jina la faili lako (hiari) - success_message: Imefanikiwa kutengeneza faili la kuuza nje + success_message: Faili la uhamisho limefanikiwa kutengenezwa vyema buttons: accept: Kubali - add: Ongeza - add_another_option: Ongeza chaguo jingine - add_note: Ongeza Maelezo - apply: Omba / Tumia - approvals: Idhini - approve_action_plan: Idhinisha Mpango wa Utekelezaji + add: Ingiza + add_another_option: Ingiza chaguo jengine + add_note: Ingiza Maelezo + apply: Kuomba + approvals: Ithibati + approve_action_plan: Thibitisha Mpango wa Utekelezaji approve_bia: Idhinisha B/A - approve_case_plan: Idhinisha Mpango wa Kesi - approve_closure: Idhinisha Kufungwa - approve_gbv_closure: Idhinisha Kufungwa kwa Ukatili wa Kijinsia - back: Nyuma - bundle_export: Kifurushi cha Mpangilio - bundle_import: Kifurushi cha Mpangilio - cancel: Futa / Ghairi - change_password: Badilisha Neno la Siri - check_status: Angalia Hali - clear_default: Weka wazi chaguo lamsingi - clear_selection: Uteuzi ulioko wazi - clear: Wazi - close: Funga / Karibu + approve_case_plan: Thibitisha mpango wa shauri + approve_closure: 'Thibitisha Ufungaji ' + approve_gbv_closure: Thibitisha ufungaji wa Ukatili wa Kijinsia GBV + back: Rudi + bundle_export: Kifurushi cha Usanidi + bundle_import: Kifurushi cha Usanidi + cancel: Ghairisha + change_password: Badili Neno la Siri + check_status: Angalia Hatua + clear_default: Weka sawa chaguo la msingi + clear_selection: Futa Kilichochaguliwa + clear: Futa + close: 'Funga ' continue: Endelea - create_case: Tengeneza Kesi + create_case: Tengeneza Shauri create_incident: Tengeneza Tukio - create_new_record: Unda Mpya / Tengeneza Mpya %{model} + create_new_record: Tengeneza Mpya %{model} delete: Futa - disable: Lemaza - disable_photo_wall: Lemaza ukuta wa picha + disable: Zuia + disable_photo_wall: Zuia ukuta wa picha done: Kumaliza - download: Kupakua - edit: Kuhariri - edit_subform: Hariri Fomu ndogo + download: Pakua + edit: Rekebisha + edit_subform: Rekebisha Fomu ndogo enable: Wezesha enable_photo_wall: Wezesha ukuta wa picha - export: Kuuza nje - filter: Tumia Kichujio - filter_clear: Weka wazi Vichujio / Vichujio Vilivyoko wazi - filter_label: 'Chujio' - filter_restore: Rejesha kwa Mipangilio ya Mfumo - find_tracing_match: Tafuta Kufuatilia mechi / yanayolingana - flag_model: Bendera%{model} - flag_records: Bendera + export: 'Kuhamisha ' + filter: Tumia Upembuzi + filter_clear: Futa Upembuzi + filter_label: 'Upembuzi' + filter_restore: Rejesha katika Mpangilio wa Mfumo + find_tracing_match: Tafuta yanayolingana + flag_model: Kibendera%{model} + flag_records: Kibendera flags: Bendera guidance: Muongozo - guiding_questions: Maswali ya Kuongoza - import: Kuagiza + guiding_questions: Maswali ya Kukuongoza + import: Ingiza login: Ingia - logout: Toka nje + logout: 'Toka ' mark_for_mobile: Alama ya simu ya mkononi new: Mpya ok: Sawa print: Chapisha - reassign: Mpe + reassign: Kabidhi referral: Rejea referral_again: 'Rejea Tena ' - reject: Kukataa - remove_referrals: Ondoa marejeo + reject: Kataa + remove_referrals: Ondoa rufaa reorder: Panga upya - request_approval: Omba Idhini + request_approval: Omba Uthibitisho request_transfer: Omba Uhamisho - reunite: Kuungana tena - save: Kuokoa - save_and_add_service_provision: Kuokoa na Kuongeza Utoaji wa Huduma - save_and_return: Kuokoa na Kurudi - save_continue: Kuokoa na Kuendelea - save_changes: Hifadhi mabadiliko + reunite: 'Kuungana ' + save: Hifadhi + save_and_add_service_provision: Ingiza na Hifadhi Utoaji wa Huduma + save_and_return: Hiifadhi na Rudi + save_continue: Hifadhi na Uendelee + save_changes: Hifadhi marekebisho select: Chagua send: Tuma - sort_by_case: Kesi - sort_by_tr: Kufuatilia Ombi - sync: Usawazishaji + sort_by_case: Shauri + sort_by_tr: Maombi ya Utafutaji + sync: Unganisha submit: Wasilisha transfer: Uhamisho - unflag_model: Kufungua%{model} - unflag_model_history: Historia ya Bendera%{model} - unmark_for_mobile: Ondoa alama kwa simu ya mkononi - update: Kuingiza toleo jipya - view: Angalia / Mtazamo - view_flags_history: 'Angalia / Tazama Historia ' - return_to_case: Kurudi kwenye Kesi + unflag_model: Ondoa kibendera%{model} + unflag_model_history: Taarifa ya Kibendera%{model} + unmark_for_mobile: Ondoa alama ya simu ya mkononi + update: Rekebisha + view: 'Angalia ' + view_flags_history: 'Angalia Historia ' + return_to_case: Rudi kwenye Shauri + resync_records: + id: Utambulisho + record_type: Aina ya Kumbukumbu + action: Hatua + date: Tarehe + last_attempt: Jaribio la Mwisho + create: Tengeneza + update: Rekebisha + resync: Wasilisha case: - label: Kesi - create_new_case: Tengeneza Kesi Mpya - add_new: Ongeza Mpya - back_to_case: Rudi kwenye Kesi + label: Shauri + create_new_case: Tengeneza Shauri Jipya + add_new: Ingiza Mpya + back_to_case: Rudi kwenye Shauri back_to_results: Rudi kwenye Matokeo back_to_search: Rudi Kutafuta - search_by: Tafuta kwa - search_for: Tafuta %{record_type} + search_by: Tafuta kwa Kutumia + search_for: Tafuta kwa %{record_type} results: Matokeo - details: Maelezo ya Kina + details: 'Maelezo ' select: Chagua - deselect: Ondoa Chaguo - enter_id_number: Ingiza nambari ya kitambulisho ili kutafuta rekodi iliyopo - id_search_no_results: Hakuna kitu kilichofanana katika mfumo. kwa %{search_query}Tafadhali tengheneza rekodi mpya + deselect: Usichague + enter_id_number: Ingiza nambari ya Utambulisho ili kutafuta Kumbukumbu zilizopo + id_search_no_results: Hakuna uwiano katika mfumo kwa %{search_query}Tafadhali tengeneza kumbukumbu mpya messages: - disabled: Kesi imelemazwa - update_success: 'Taarifa mpya ziliwekwa %{record_id}kwenye kesi kwa mafanikio ' - update_success_queue: 'Kesi %{record_id}iliwekwa taarifa mpya katika mafanikio katika sehemu yake ya historia' - creation_success: 'Rekodi ya kesi imetayarishwa kwa mafanikio' - creation_success_queue: 'Rekodi ya kesi imetayarishwa kwa mafanikio katika sehemu ya historia' - already_matched: Muulizaji tayari ameshafananishwa na kesi yako - already_matched_not_current_case: Tayari iko kesi katika mfumo ambayo imefananishwa na muulizaji - not_found_case: Hakuna kesi inayolingana iliyopatikana%{search_value} Tayarisha kesi nyingine - introductory_sentence: Tafadhali taja idhini ya mtu binafsi atakayepokea huduma za usimamizi wa kesi na taarifa zao kuhifadhiwa katika Primero - consent_agreements_required: Tafadhali chagua angalau chaguo moja kutoka kwenye makubaliano ya idhini - legitimate_basis_required: Tafadhali chaguo angalau chaguo moja kutoka kwenye uainishaji wa msingi halali - save: Ihifadhi kesi - save_text: Kabla ya kuendelea, tafadhali yahifadhi mabadiliko yako kwenye kesi - skip_and_create: Ruka na Utengeneze Kesi Mpya - search_existing: Tafuta kesi zilizopo - search_helper_text: Kwa nini? Kuzuiya utengenezwaji wa kesi zinazojirudia - consent_agreements: Chagua makubaliano yote ya idhini ambayo yanatumika - legitimate_basis: 'Chagua uainishaji wa msingi halali unaotumika ' + disabled: Shauri limezuiliwa + update_success: 'Shauri %{record_id}limefanikiwa kurekebishwa ' + update_success_queue: 'Shauri %{record_id}Limefanikiwa kurekebishwa mwanzoni' + creation_success: 'Umefanikiwa Kutengeza Kumbukumbu ya Shauri ' + creation_success_queue: 'Kumbukumbu shauri limefanikiwa kurekebishwa mwanzoni' + already_matched: Kilichoulizwa kinaendana na shauri lako + already_matched_not_current_case: 'Tayari shauri lililomo kwenye mfumo linaendana na kilichoulizwa ' + not_found_case: Hakuna shauri linalofanana, tengeneza shauri lipya + introductory_sentence: Tafadhali ainisha ridhaa ya mtu atakayepewa huduma za usimamizi wa shauri na taarifa zao kuhifadhiwa kwenye Primero + consent_agreements_required: Tafadhali chagua angalau chaguo moja kutoka kwenye makubaliano ya ridhaa + legitimate_basis_required: Tafadhali chaguo angalau chaguo moja kutoka kwenye yalioanishwa kutokana na msingi wa kisheria + save: Hifadhi Shauri + save_text: Kabla ya kuendelea, tafadhali yahifadhi mabadiliko yako kwenye Shauri + skip_and_create: Ruka na tengeneza Shauri jipya + search_existing: Tafuta Shauri zilizopo + search_helper_text: Kwa nini? Kuzuiya utengenezwaji wa shauri zilizojirudia + consent_agreements: Chagua makubaliano yote ya ridhaa ambayo yanatumika + legitimate_basis: Chagua makubaliano yote halali ambayo yanaweza kutumika kutoka na msingi wa kisheria workflow: assessment: Tathmini - case_plan: Mpango - closed: Imefungwa - created_on: 'Imeundwa / Imetayarishwa tarehe ' + case_plan: Mpango wa Shauri + closed: Limefungwa + created_on: Limetengenezwa in_progress: Inaendelea new: Mpya - on_label: 'Juu / Kuwasha ' + on_label: 'katika' reopened: Imefunguliwa tena - service_implemented: Huduma imetekelezwa - services_implemented: Huduma imetekelezwa + service_implemented: Huduma iliyotolewa + services_implemented: Huduma iliyotolewa linkedincidents: - label: Tukio Lililounganishwa + label: Matukio yanayohusiana activity_log: - label: Logi ya Vitendo/Shughuli + label: Logi ya Vitendo accepted_transfer: '%{to}Uhamisho uliokubalika wa %{record_type}%{record_id}kutoka %{from}' rejected_transfer: '%{to}uhamisho uliokataliwa wa %{record_type}%{record_id}Kutoka %{from}' cases: action_plan: Mpango wa Utekelezaji age: Umri - age_estimated: Makadirio ya Umri? - agency: Wakala - apply_filter: Tumia / Omba + age_estimated: Je, Umri umekadiriwa? + agency: Taasisi + apply_filter: Onesha approval_comments: Maoni approval_radio: 'Ningependa ' - approval_radio_accept: Idhinisha - approval_radio_reject: Kutokubali - approval_select: Fomu kwa - approved_success_action_plan: '%{approval_label}imeidhinishwa' - approved_success_assessment: '%{approval_label}mekubalika' - approved_success_bia: '%{approval_label}imeidhinishwa' - approved_success_case_plan: '%{approval_label}iImeidhinishwa' - approved_success_closure: '%{approval_label}Imeidhinishwa' - approved_success_gbv_closure: '%{approval_label}imeidhinishwa' + approval_radio_accept: Thibitisha + approval_radio_reject: Kutothibitisha + approval_select: Fomu kwa ajili ya + approved_success_action_plan: '%{approval_label}imethibitishwa' + approved_success_assessment: '%{approval_label}imethibitishwa' + approved_success_bia: '%{approval_label}imethibitishwa' + approved_success_case_plan: '%{approval_label}imethibitishwa' + approved_success_closure: '%{approval_label}imethibitishwa' + approved_success_gbv_closure: '%{approval_label}imethibitishwa' assessment: Tathmini - case_opening_date: Tarehe ya kufungua kesi - case_plan: Mpango wa Kesi - case_worker_code: Alama ya Mfanyakazi wa Kesi - clear_filter: Iko Wazi - close_dialog: Kubonyeza sawa itabadilisha hali ya kesi hii kuwa imefungwa - close_dialog_title: Funga kesi - close_success: Kesi iliyofungwa kwa mafanikio + case_opening_date: Tarehe ya kufungua Shauri + case_plan: Mpango wa Shauri + case_worker_code: Msimbo wa Msimamizi wa Shauri + clear_filter: Futa + close_dialog: Kubonyeza sawa itabadilisha hali ya shauri hili kuwa limefungwa + close_dialog_title: Funga Shauri + close_success: Shauri limefanikiwa kufungwa closure: Kufungwa + complete: Unapatikana bila ya mtandao date_of_birth: Tarehe ya kuzaliwa - disable_dialog: Kubonyeza SAWA kutabadilisha hali ya kesi hii kuwa iliyozimwa - disable_dialog_title: Lemaza / Zima Kesi - disable_success: Kesi imezimwa / imelemazwa Kikamilifi - enable_dialog: Kubonyeza sawa itabadilisha hali ya kesi hii kuwa Iliyowezeshwa - enable_dialog_title: Wezesha Kesi - enable_success: Kesi imewezeshwa kikamilifu - export: Kuuza nje + disable_dialog: Kubonyeza SAWA kutabadilisha hali ya shauri hili kuwa limezuiliwa + disable_dialog_title: Zuia Shauri + disable_success: Shauri limezuiliwa kikamilifu + enable_dialog: Kubonyeza SAWA itabadilisha hali ya Shauri hili kuwa linaonekana + enable_dialog_title: Onesha Shauri + enable_success: Shauri linaonekana kikamilifu + export: Kuhamisha mark_for_offline: - title: Alama kwa Nje ya Mtandao - text: Je unahakika unataka kuzitumia Kesi hizi ukiwa huko kwenye mtandao - success: Kesi zimefanikiwa kuwekwa alama kwa matumizi bila ya mtandao + title: Alama Nje ya Mtandao + text: Je, unahakika unataka kuweka alama Mashauri haya ili kuyatumia nje ya mtandao? + success: Mashauri yamewekwa alama kikamilifu kwa matumizi nje ya mtandao filter_by: - 3month_inactivity: Kwa zaidi ya miezi 3 + 3month_inactivity: Kwa miezi 3 na zaidi action_plan: 'Mpango wa utekelezaji ' age_0_5: 0 - 5 age_12_17: 12 - 17 age_18_more: 18 na zaidi age_6_11: 6 - 11 - age_range: Kiwango cha umri - agency: Wakala - approval_status: Hadhi ya Vibali + age_range: Rika + agency: Taasisi + approval_status: Hali ya Ithibati approvals: - approved: Imeidhinishwa + approved: Ithibitishwa pending: Inasubiri rejected: Imekataliwa - bia: B/A + bia: 'Tathmini ya Mashali Bora ' by_date: Kwa Tarehe - case_open_date: Tarehe ya Kufungua Kesi - case_plan: Mpango wa Kesi - closed: Imefungwa + case_open_date: Tarehe ya Kufungua Shauri + case_plan: Mpango wa Shauri + closed: Limefungwa closure: Kufungwa current_location: Eneo la Sasa date: Tarehe displacement_status: Hali ya Kuhamishwa district: Wilaya - duplicate: Kurudia - enabled_disabled: Imewezeshwa / Imelemazwa - female: Kike - flag: Zimepigwa alama - flag_label: Zimetiwa alama? - gbv_closure: Kufungwa kwa Ukatili wa Kijinsia - high: Juu - low: Chini - male: Kiume - medium: Kati - mobile: Simu - mobile_label: Imetiwa alama kwenye simu? - my_cases: Kesi Zangu - no_action: Hakuna Hatua - no_activity: Hakuna Shughuli - open: Fungua / Wazi - other: Nyingine + duplicate: Nakala + enabled_disabled: Onesha / Zuia + female: Mwanamke + flag: Limewekewa Kibendera + flag_label: Je, limewekewa Kibendera? + gbv_closure: Kufungwa kwa Shauri la Ukatili wa Kijinsia GBV + high: Kubwa + low: Ndogo + male: Mwanamme + medium: Kati na Kati + mobile: Simu ya mkononi + mobile_label: Imewekwa alama kwa ajili ya simu + my_cases: Mashauri yangu + no_action: Haikufanyiwa kazi + no_activity: Hakuna shughuli ya kufanya + open: Imefunguliwa + other: Nyengine photo: Picha - photo_label: Ina Picha? - protection_concerns: Wasiwasi wa Ulinzi - protection_status: Hali ya Ulinzi - record_state: Hali ya Rekodi / Kumbukumbu - referred_cases: Kesi zilizoletwa kwangu + photo_label: Je, ina Picha? + protection_concerns: Shaka ya Udhalilishaji + protection_status: Hali ya Udhalilishaji + record_state: Hali ya Kumbukumbu + referred_cases: Mashauri niliyoletewa registration_date: Tarehe ya Usajili risk_level: Kiwango cha Hatari - sex: Jinsi / Ngono - social_worker: Eneo la Kesi / Mfanyakazi wa Kijamii + sex: Jinsi + social_worker: Eneo/ Shauri / Mhudumu wa Kijamii status: Hali - transferred: Kuhamishwa + transferred: Lilihamishwa type_of_risk: Aina ya Hatari - urgent_protection_concern: Wasiwasi wa Haraka wa Ulinzi - user_group: Kikundi cha / Kundi la Watumiaji - workflow: Kesi na Mtiririko wa Kazi - flag_summary: Muhtasari wa bendera + urgent_protection_concern: Hatua za haraka dhidi ya Shaka ya Udhalilishaji + user_group: Kundi la Watumiaji + workflow: Mtiririko wa hatua za Mashauri + flag_summary: Kidokezo cha kibendera full_name: Jina kamili - gbv_closure: Kufungwa kwa Ukatili wa Kijinsia + gbv_closure: Kufungwa kwa Shauri la Ukatili wa Kijinsia GBV hide_name: Ficha Jina - hide_name_error: Hitilafu ilitokea wakati wa kuhifadhi mabadiliko yako. Tafadhali jaribu tena - id: Nambari ya Kitambulisho - label: Kesi - my_filters: Vichujio Vyangu + hide_name_error: Imetokea hitilafu wakati wa kuhifadhi taarifa yako. Tafadhali jaribu tena + id: Nambari ya Utambulisho + label: Shauri + my_filters: Vipembuzi Vyangu name: Jina - notes_dialog_title: Ongeza Maelezo + notes_dialog_title: Ingiza Maelezo notes_form_notes: Maelezo - notes_form_subject: Somo + notes_form_subject: Mada ok: Sawa order_by: - label: Agiza kwa - most_recently: Hivi Karibuni + label: Pangilia kwa + most_recently: Za Hivi Karibuni name: Jina - owned_by: Mmiliki wa rekodi - owned_by_agency: Wakala wa Mmiliki wa Rekodi + owned_by: Mmiliki wa Kumbukumbu + owned_by_agency: Taasisi ya Mmiliki wa Kumbukumbu photo: Picha - photos: Photo + photos: Picha quick_view: - tracing_message: 'Angalizo / Kumbuka: kuna mtu kwenye mfumo anayelingana na muulizaji anayemtafuta mtoto huyu. Wasiliana na mfanyakazi wa jamii anyehusika na rekodi hii kwa hatua zaidi ikiwa mtot atapenda / anataka' - referral_done: 'Kubonyeza ''imemalizika'' inaashiria kuwa umekamilisha kazi ya rufaa inayohusishwa na kesi hii. Mara tu utakapobonyeza ''umemaliza'' hutaweza tena kuipata rekodi hii ' - referral_done_success: Rufaa imefanywa + tracing_message: 'Kumbuka: kwenye mfumo kuna muulizaji anayemtafuta mtoto huyu. Wasiliana na mhudumu wa jamii anayehusika na taarifa hizi kwa hatua zaidi ikiwa mtoto ataridhia' + referral_done: 'Kubonyeza ''imekamilika'' inamaanisha umekamilisha kazi ya rufaa inayohusu shauri hili na hutoweza tena kuifanyia kazi taarifa hii ' + referral_done_success: Rufaa imekamilika referral_accepted_header: Kubali rufaa - referral_accepted: Una uhakika? Kuanzia sasa hivi wewe ndiye utakaewkuwa na wajibu wa kukamilisha kazi inayohusiana na rufaa hii + referral_accepted: Je, una hakika? Kuanzia sasa hivi wewe ndiye utakaye wajibika kukamilisha kazi inayohusu rufaa hii referral_accepted_success: Rufaa imekubalika - referral_rejected: 'Kwa kubonyeza ''Kataa'' unaashiria kuwa huko tayari kukubali jukumu la rufaa hii kwa wakati / muda huu. Tafadhali ingiza sababu ya kuikataa rufaa hii; mara tu baada ya kubonyeza ''Kataa'' hutaweza tena kuipata rekodi ya kesi hii ' + referral_rejected: 'Kwa kubonyeza ''Kataa'' unamaanisha kuwa huko tayari kukubali jukumu la rufaa hii kwa muda huu. Tafadhali toa sababu ya kuikataa rufaa hii; mara tu baada ya kubonyeza ''Kataa'' hutaweza tena kupata taarifa ya shauri hili ' referral_rejected_success: Rufaa imekataliwa - register_new_case: Kesi Mpya + register_new_case: Shauri Jipya registration_date: Tarehe ya usajili - rejected_success_action_plan: '%{approval_label}Haijaidhinishwa' - rejected_success_assessment: '%{approval_label}Haijaidhinishwa' - rejected_success_bia: '%{approval_label}Haijaidhinishwa' - rejected_success_case_plan: '%{approval_label}Haijaidhinishwa' - rejected_success_closure: '%{approval_label}Haijaidhinishwa' - rejected_success_gbv_closure: '%{approval_label}Haijaidhinishwa' - reopen_dialog: Kubonyeza Sawa itabadilisha hali ya kesi hii na Kuifungua - reopen_dialog_title: Fungua tena kesi - reopen_success: Kesi imefunguliwa tena kwa mafanikio - request_approval_failure: Hitilafu imetokea, tafadhali wasiliana na sehemu ya msaada - request_approval_select: 'Omba idhini ya ' - request_approval_success_action_plan: '%{approval_label}Idhini iliyoombwa kwa fomu' - request_approval_success_assessment: Idhini iliyoombwa kwa fomu%{approval_label} - request_approval_success_case_plan: Idhini iliyoombwa kwa fomu%{approval_label} - request_approval_success_closure: Idhini iliyoombwa kwa %{approval_label}fomu - request_approval_success_gbv_closure: Idhini iliyoombwa kwa %{approval_label}fomu - request_approval_type_of_case_plan: Aina ya Idhini ya Mpango wa Kesi - request_approve_action_plan: Mpango wa Utekelezaji Uidhinishwe? - request_approve_bia: Tathmini iidhinishwe? - request_approve_case_plan: Mpango wa kesi uidhinishwe? - request_approve_closure: Kufungwa Kuidhinishwe? - request_approve_gbv_closure: Kuidhinishwe kufungwa kwa Ukatili wa Kijinsia? - revoke_failure: Hitilafu ilitokea wakati wa kubatilisha;%{transition_type} tafadhali wasiliana kwenye msaada - revoke_message: 'Kwa kubonyeza ''Batilisha'' utaondoa %{transition_type}uwezo wa mpokeaji kuifikia kesi hiyo ' - revoke_success_message: Kesi %{case_id}%{transition_type}kwenda %{recipient_username}kufutwa + rejected_success_action_plan: '%{approval_label}Haijathibitishwa' + rejected_success_assessment: '%{approval_label}Haijathibitishwa' + rejected_success_bia: '%{approval_label}Haijathibitishwa' + rejected_success_case_plan: '%{approval_label}Haijathibitishwa' + rejected_success_closure: '%{approval_label}Haijathibitishwa' + rejected_success_gbv_closure: '%{approval_label}Haijathibitishwa' + reopen_dialog: Kubonyeza SAWA itabadilisha hali ya shauri hili na Kuwa linaloendelea + reopen_dialog_title: Fungua tena Shauri + reopen_success: Shauri limefunguliwa tena kikamilifu + request_approval_failure: Hitilafu imetokea, tafadhali wasiliana na mtoa msaada + request_approval_select: 'Omba uthibitisho kwa ajili ya ' + request_approval_success_action_plan: Uthibitisho uliyoombwa kwa ajili ya %{approval_label}fomu. + request_approval_success_assessment: Uthibitisho uliyoombwa kwa ajili ya%{approval_label}fomu. + request_approval_success_case_plan: Uthibitisho uliyoombwa kwa ajili ya%{approval_label}fomu. + request_approval_success_closure: Uthibitisho uliyoombwa kwa ajili ya %{approval_label}fomu + request_approval_success_gbv_closure: Uthibitisho uliyoombwa kwa ajili ya %{approval_label}fomu + request_approval_type_of_case_plan: Aina ya Uthibitisho wa Mpango wa Shauri + request_approve_action_plan: Je, mpango wa Utekelezaji Uidhinishwe? + request_approve_bia: Je, Tathmini iidhinishwe? + request_approve_case_plan: Je, mpango wa Shauri uidhinishwe? + request_approve_closure: Je, ufungwaji Uidhinishwe? + request_approve_gbv_closure: Je, Kufungwa kwa Shauiri la Udhalilishaji wa Kijinsia kuidhinishwe? + revoke_failure: Hitilafu ilitokea wakati wa kubatilisha;%{transition_type} tafadhali wasiliana na mtoa msaada + revoke_message: Kwa kubonyeza 'Batilisha' utaondosha%{transition_type}uwezo wa mpokeaji kulifikia shauri + revoke_success_message: Shauri %{case_id}%{transition_type}kwenda %{recipient_username}limeondolewa save_filter: Hifadhi - selected_all_records: 'Zichague kesi zote %{total_records}zinazoendana / zinazolingana na swali ' - selected_records: '%{select_records}Kesi (zi)lizochaguliwa.' - sex: Jinsi / Ngono - show_case: 'Kitambulisho cha Kesi%{short_id}' - social_worker: Mfanyakazi wa Kijamii + selected_all_records: Chagua mashauri yote %{total_records}yanayoendana na hoja hii + selected_records: '%{select_records}Mashauri yaliyochaguliwa.' + sex: 'Jinsi ' + show_case: 'Utambulisho wa Shauri%{short_id}' + social_worker: Muhudumu wa Kijamii status: Hali summary: label: Muhtasari - find_match: Tafuta Zinazolingana / Zinazofanana - matched_trace: 'Linganisha nambari%{trace_id}' - cannot_find_matches: Hakuna zinazolingana. Idhini haikupatikana kutoka kwa Kesi hii kufichua taarifa kwa lengo la ufuatiliaji - matched: Zinaendana / Zinafanana + find_match: Tafuta Zinazolingana + matched_trace: 'Linganisha #%{trace_id}' + cannot_find_matches: Hakuna zinazolingana. Ridhaa haikupatikana kutoka kwenye Shauri hii kwa ajili ya kutafuta na kupata taarifa + matched: Zinalingana fields: consent_for_tracing: - label: Idhini imepatikana ya kufichua taarifa kwa lengo la ufuatiliaji - help_text: Ikiwa imeandikwa ''Hapana', rekodi ya kesi ya mtoto haitaonekana kwenye Kulinganisha na Ombi la Ufuatiliaji la Muulizaji + label: Ridhaa haikupatikana kutoka kwenye Shauri hii kwa ajili ya kutafuta na kupata taarifa + help_text: Ikiwa imejazwa ''Hapana', kumbukumbu ya shauri la mtoto haitoonesha ulingano na Ombi la Ufuatiliaji la Muulizaji wishes_child_family_tracing: - label: Je, mtoto anataka kuwafuatilia wanafamilia? + label: Je, mtoto anataka kuwatafuta wanafamilia? wishes_reunification: label: Je, mtoto anataka kuunganishwa tena na familia yake? options: yes_as_soon_as_possible: Ndio, haraka iwezekanavyo - yes_but_later: Ndio, lakini baadaye - not_sure: Sina hakika + yes_but_later: Ndio, lakini kwa baadae + not_sure: Hakuna uhakika 'no': 'Hapana' data_confidentiality_link: - label: Angalia taarifa/data / Usiri + label: Angalia Usiri wa taarifa child_wishes_link: label: Angalia Matakwa ya Mtoto - survivor_code: Alama ya Manusura - transfer_accepted: Kwa kubonyeza 'Kubali' unakubali kuwajibika kwa kesi hii, ukibonyeza 'Kubali' utakuwa mmiliki wa rekodi kwenye mfumo - transfer_managed_user_accepted: Ikiwa unatabonyeza 'Kubali' %{transitioned_to}Utawajibika kwa kesi hii; mara tu untakapo bonyeza 'Kubali', %{transitioned_to}utakuwa mmiliki wa rekodi/taarifa katika mfumo huu. - transfer_managed_user_rejected: Kwa kubonyeza 'Kataa' unamaanisha kuwa %{transitioned_to}huko tayari kukubali jukumu la kesi hii kwa wakati huu. Tafadhali ingiza sababu ya kuwa wewe unaikataa kesi hii;vmara tu utakapo bonye za 'Kataa' %{transitioned_to}hutaweza tena kuzifikia kumbukumbu/rekodi za Kesi hii. - transfer_accepted_rejected: Uhamisho wa kesi%{record_id} umekataliwa - transfer_accepted_success: Uhamisho wa kesi umekubaliwa kwa mafanikio + survivor_code: Msimbo wa Mteja + transfer_accepted: Kwa kubonyeza 'Kubali' unaridhia jukumu la Shauri hili, mara baada ya kubonyeza 'Kubali' utakuwa mmiliki wa kumbukumbu kwenye mfumo huu + transfer_managed_user_accepted: Ikiwa utabonyeza 'Kubali' %{transitioned_to}Utawajibika kwa Shauri hili; mara tu utakapo bonyeza 'Kubali', %{transitioned_to}utakuwa mmiliki wa kumbukumbu katika mfumo huu. + transfer_managed_user_rejected: Kwa kubonyeza 'Kataa' unamaanisha kuwa %{transitioned_to}huko tayari kupokea jukumu la shauri hili kwa wakati huu. Tafadhali toa sababu ya kukataa kwako; mara tu utakapo bonyeza 'Kataa' %{transitioned_to}hutaweza tena kuzifikia kumbukumbu za Shauri hili. + transfer_accepted_rejected: Uhamisho wa Shauri%{record_id} umekataliwa + transfer_accepted_success: Uhamisho wa shauri umekubaliwa kikamilifu transfer_reject_reason_label: Sababu ya Kukataliwa - transfer_rejected: Kwa kubonyeza 'Kataa' unaashirian kuwa huko tayari kukubali jukumu la kesi hii kwa wakati / muda huu. Tafadhali ingiza sababu ya kukataa kesi hii; mara tu baada ya kubonyeza 'Kataa' hutaweza tena kuipata rekodi ya kesi hii. + transfer_rejected: Kwa kubonyeza 'Kataa' unamaanisha kuwa huko tayari kupokea jukumu la shauri hili kwa muda huu. Tafadhali toa sababu ya kutopokea shauri hili; mara tu baada ya kubonyeza 'Kataa' hutaweza tena kuipata kumbukumbu ya shauri hili. view_name: Angalia Jina + sort_by: Panga kwa change_logs: filters: form: Fomu - field: Uwanja - add_subform: 'Imeongezwa %{subform_name}nambari ya kuingia kwenye fomu ndogo%{short_id}' - changes_subform: 'Badili kuwa /%{subform_name}Form ndogo' - create: Rekodi iliyotengenezwa / iliyotayarishwa - deleted_subform: 'Nambari ya kuingiza fomu ndogo%{subform_name} iliyoondolewa%{short_id}' - label: Badilisha log + field: Eneo + add_subform: 'Imeongezwa %{subform_name}namba ya fomu ndogo iliyoingizwa%{short_id}' + changes_subform: 'Mabadiliko ya %{subform_name}Fomu ndogo' + create: 'Kumbukumbu iliyotengenezwa ' + deleted_subform: 'Imeondolewa%{subform_name} Nambari ya kuingiza fomu ndogo%{short_id}' + label: Badilisha logi see_details: Angalia maelezo change: 'Kutoka %{from_value}kwa%{to_value}' updated_subform: 'Nambari ya kuingiza fomu ndogo%{subform_name} imeingizwa taarifa mpya%{short_id}' @@ -508,199 +526,202 @@ sw_TZ: dashboard: activity: Shughuli admin_only: Bonyeza%{links} ili kufanya mabadiliko kwenye programu - all_cases: Kesi Zote - all_services_implemented: Huduma Zote Zinazotekelezwa + all_cases: Mashauri yote + all_services_implemented: Huduma Zote Zilizotolewa and: 'na' - approval_action_plan_approved: Kuidhinishwa / Kupitishwa + approval_action_plan_approved: Limethibitishwa approval_action_plan_pending: Inasubiri approval_action_plan_pending_group: Mpango Kazi - approval_action_plan_rejected: 'Imekataliwa ' - approval_assessment_approved: Imeidhinishwa / Imepitishwa - approval_assessment_pending: Inasubiri + approval_action_plan_rejected: 'Limekataliwa ' + approval_assessment_approved: Limethibitishwa + approval_assessment_pending: Linasubiri approval_assessment_pending_group: Tathmini - approval_assessment_rejected: Imekataliwa - approval_case_plan_approved: Imethibitishwa / Imepitishwa - approval_case_plan_pending: Inasubiri - approval_case_plan_pending_group: 'Mpango wa Kesi ' - approval_case_plan_rejected: Imekataliwa - approval_closure_approved: Imethibitishwa / Imepitishwa - approval_closure_pending: Inasubiri + approval_assessment_rejected: Limekataliwa + approval_case_plan_approved: Limethibitishwa + approval_case_plan_pending: Linasubiri + approval_case_plan_pending_group: Mpango wa Shauri + approval_case_plan_rejected: Limekataliwa + approval_closure_approved: Limethibitishwa + approval_closure_pending: Linasubiri approval_closure_pending_group: Kufungwa - approval_closure_rejected: Imekataliwa - approval_gbv_closure_approved: Imethibitishwa - approval_gbv_closure_pending: Inasubiri - approval_gbv_closure_pending_group: Kufungwa kwa Udhalilishaji wa Kijinsia - approval_gbv_closure_rejected: Imekataliwa - approvals: Vibali + approval_closure_rejected: Limekataliwa + approval_gbv_closure_approved: Limethibitishwa + approval_gbv_closure_pending: Linasubiri + approval_gbv_closure_pending_group: Kufungwa kwa shauri la Ukatili wa kijinsia + approval_gbv_closure_rejected: Limekataliwa + approvals: Uthibitisho approvals_action_plan: Mpango Kazi approvals_assessment: Tathmini - approvals_case_plan: Mpango wa Kesi + approvals_case_plan: Mpango wa shauri approvals_closure: Kufungwa - approvals_gbv_closure: Kufungwa kwa Udhalilishaji wa Kijinsia - approved: Imethibitishwa / Imepitishwa + approvals_gbv_closure: Kufungwa kwa shauri la ukatili wa kijinsia + approved: Limethibitishwa assessment: Tathmini - awaiting_acceptance: Wakisubiri Kukubalika + awaiting_acceptance: Yanasubiri kukubaliwa cases_by_social_worker_total: Jumla - cases_by_social_worker_new_or_updated: Mpya na imeingizwa / Imewekewa toleo jipya - case_id: 'Nambari ya Kitambulisho cha Kesi' - case_management_service: Huduma za Usimamizi wa Kesi - case_overview: Kesi Zangu - case_plan: Mpango wa Kesi - case_risk: Kesi kwa Kiwango cha Tathmini - case_stat_by_approval_type: Vibali - case_stat_by_assessment_level: Kesi kwa Kiwango cha Tathmini + cases_by_social_worker_new_or_updated: Jipya na Limeboreshwa + case_id: 'Nambari ya utambulisho wa shauri' + case_management_service: Huduma ya Usimamizi wa shauri + case_overview: Mashauri yangu + case_plan: Mpango wa shauri + case_risk: Mashauri kwa hatua ya tathmini + case_stat_by_approval_type: Uthibitisho + case_stat_by_assessment_level: Mashauri kwa hatua ya tathmini case_stat_referrals: Rufaa - case_stats: Kesi - case_worker: Mfanyakazi wa Kesi - cases_by_social_worker: Kesi na mfanyakazi wa kijamii + case_stats: Mashauri + case_worker: Msimamizi wa shauri + cases_by_social_worker: Mashauri kwa afisa ustawi cases_by_task_overdue: Kazi zilizochelewa - cases_by_workflow: Kesi Kwa Mtiririko wa Kazi - cases_this_week: Kesi za Wiki Hii - cases_to_assign: Kesi Za Kuwapa - closed: Imefungwa - closed_last_week: Imefungwa (wiki iliyopita) - closed_this_week: Imefungwa (wiki hii) - comprehensive_need_intervention: Majibu ya Kina + cases_by_workflow: Mashauri Kwa Mtiririko wa Kazi + cases_this_week: Mashauri ya Wiki Hii + cases_to_assign: Mashauri ya kufanyiwa kazi + closed: Limefungwa + closed_last_week: Lilifungwa (wiki iliyopita) + closed_this_week: Limefungwa (wiki hii) + comprehensive_need_intervention: Hatua inayofaa count_new_bia_approvals: one: '%{stat} Mpya %{stat_type} Idhini' - other: '%{stat} Mpya %{stat_type} idhini' + other: '%{stat}Uthibisho Mpya %{stat_type} ' count_new_case_plan_approvals: one: '%{stat} Idhini Mpya%{stat_type} ' - other: '%{stat} Vibali vipya%{stat_type} ' + other: '%{stat} Uthibitisho mppya%{stat_type} ' count_new_closure_approvals: one: '%{stat} Vibali vipya%{stat_type} ' - other: '%{stat} Vibali vipya%{stat_type} ' + other: '%{stat} Uthibitisho mpya%{stat_type} ' count_pending_approval_total: one: Una %{stat} Inasubiri %{stat_type} Idhini - other: 'Una %{stat} Vinasubiri%{stat_type} Vibali ' + other: 'Una uthibitisho unaosubiri%{stat} %{stat_type} ' count_pending_transfers: one: Una%{stat}inasubiri uhamisho - other: Unazo %{stat}zinazosubiri uhamisho + other: Una uhamisho unaosubiri %{stat} count_records_new: one: na %{stat}kesi mpya - other: na %{stat}kesi mpya + other: na mashauri mapya %{stat} count_records_total: one: una %{stat}jumla ya kesi - other: Una %{stat}jumla ya kesi + other: Una jumla ya mashauri %{stat} count_referrals_new: one: na %{stat}rufaa mpya - other: na %{stat}rufaa mpya + other: na rufaa mpya %{stat} count_referrals_total: one: unayo %{stat} jumla rufaa - other: unazo %{stat} jumla ya rufaa + other: 'una jumla ya rufaa %{stat} ' count_rejected_approval_total: one: na %{stat} iliyokataliwa %{stat_type} Idhini - other: na %{stat} vilizokataliwa %{stat_type} vibali + other: 'na uthibitisho uliokataliwa %{stat} %{stat_type} ' count_rejected_transfers: one: na %{stat} uhamisho uliokataliwa - other: na %{stat} uhamisho uliokataliwa + other: 'na uhamisho uliokataliwa %{stat} ' count_risk_level_new: one: na %{stat} mpya %{stat_type} kesi hatarishi - other: na %{stat} mpya %{stat_type} kesi hatarishi + other: 'na mashauri mapya hatarishi%{stat} %{stat_type} ' count_risk_level_total: one: unayo %{stat} %{stat_type} kesi ya hatari - other: unazo %{stat} %{stat_type} kesi za hatari - count_waiting_for_acceptance_transfers: Unao%{stat}Uhamisho unaosubiri kukubalika kwako - current_owner: Mmiliki wa sasa hivi - dash_case_incident_overview: Kesi zangu - dash_group_overview: Kesi za kundi langu - dash_shared_from_my_team: Imeshirikishwa kutoka kwenye timu yangu - dash_shared_with_me: Imeshirikishwa nami - dash_shared_with_my_team: Iliyoshirikishwa na timu yangu - dash_shared_with_my_team_overview: Shirikisha Timu yangu (Muhtasari) - dash_shared_with_others: 'Imeshirikishwa na wengine ' + other: 'Unayo mashauri yaliyo katika hali ya hatari %{stat} %{stat_type} ' + count_waiting_for_acceptance_transfers: Upo uhamisho unaosubiri kukubaliwa%{stat} + current_owner: 'Mmiliki wa sasa ' + dash_case_incident_overview: Mashauri yangu + dash_group_overview: Mashauri ya kundi langu + dash_shared_from_my_team: Lililotumwa kutoka kwenye timu yangu + dash_shared_with_me: Yaliyotumwa kwangu + dash_shared_with_my_team: Yaliyotumwa na timu yangu + dash_shared_with_my_team_overview: Yaliyotumwa na timu yangu (Muhtasari) + dash_shared_with_others: 'Yaliotumwa kwa wengine ' dash_national_admin_summary: Muhtasari wa Msimamizi + dash_violations_category_verification_status: 'Idadi ya matukio yaliyohakikiwa ' + dash_violations_category_region: 'Idadi ya matukio yaliyohakikiwa kimkoa ' + dash_perpetrator_armed_force_group_party_names: Idadi ya matukio kwa mujibu wa mtuhumiwa date: Tarehe date_of_incident: Tarehe ya tukio date_of_interview: Tarehe ya usaili - due: Imechelewa - flagged: Iliyotiwa Alama - flagged_by: 'Imeripotiwa na ' - flagged_by_me: Iliyotiwa Alama na mimi - flagged_by_other: Imeripotiwa Na Mtu Mwingine - flagged_cases: Kesi zilizoripotiwa - follow_up: Fuatilia - forms: Kichupo cha FOMU + due: Limechelewa + flagged: Lililowekewa kibendera + flagged_by: 'Imewekewa kibendera na' + flagged_by_me: Nilioiwekea kibendera + flagged_by_other: 'Limewekewa kibendera na mwengine ' + flagged_cases: Mashauri yaliowekewa kibendera + follow_up: Fuatiliaji + forms: Kitufe cha FOMU geographic_area: Eneo la Kijiografia - group_overview_closed: Imefungwa - group_overview_open: Fungua / Iko wazi - high_level: Juu + group_overview_closed: Limefungwa + group_overview_open: Fungua / Iiko wazi + high_level: Kiwango cha juu high_risk: Kipaumbele cha Juu - immediate_response: Majibu ya papo hapo - in_progress: Inaendelea - incident_id: 'Nambari ya Kitambulisho cha Tukio' + immediate_response: Hatua za haraka + in_progress: Linaendelea + incident_id: 'Nambari ya utambulisho wa tukio' incident_location: Eneo la Tukio - incident_status_open: Fungua / Iko wazi - last_updated: Iliingizwa Toleo Jipya Mwisho - link_see_all: Ona yote / Angalia zote - low_level: Chini + incident_status_open: Fungua / Iiko wazi + last_updated: Maboresho ya mwisho + link_see_all: Angalia yote + low_level: Kiwango cha chini low_risk: Kipaumbele cha Chini manager_count_closed_total: one: na %{stat} kesi iliyofungwa - other: na %{stat} kesi zilizofungwa + other: 'na msahauri yaliyofungwa%{stat} ' manager_count_open_total: one: anayo %{stat} kesi inayoendelea - other: unazo %{stat} kesi zinazoendelea + other: 'Unayo mashauri yaliyofunguliwa %{stat} ' manager_transfers_totals: one: unayo %{stat} %{stat_type} ya Uhamisho - other: unayo %{stat} %{stat_type} za Uhamisho + other: una mashauri %{stat} %{stat_type} yaliohamishwa match_result: Matokeo Yanayolingana - medium_level: Kati + medium_level: Kiwanago cha kati medium_risk: Kipaumbele cha Kati - missed_cases: Kesi zilizokosekana + missed_cases: ' Mashauri yasiyofanyiwa kazi' name: Jina name_or_survivor_code: Jina au msimbo wa aliyenusurika near_deadline: Karibu na tarehe ya mwisho - new: Mpya na Iliyoingizwa Toleo Jipya - new_child_assigned_to_you: Kesi Mpya Ulizokabidhiwa - new_incident: Matukio Mepya - new_incident_assigned_to_you: Matukio Mepya Yaliyotolewa - new_last_week: Mpya (Wiki Iliyopita) - new_or_updated: Mpya au Imeingizwa Toleo Jipya + new: Jipya na lililoboreshwa + new_child_assigned_to_you: Mashauri Mapya unayotakiwa kuyafanyia kazi + new_incident: Matukio Mapya + new_incident_assigned_to_you: Matukio Mapya ya kuyafanyia kazi + new_last_week: Mapya (Wiki Iliyopita) + new_or_updated: Mapya au yaliyoboreshwa new_referred: Rufaa Mpya - new_service_provision: Masharti Mapya ya Huduma - new_this_week: Mpya (wiki hii) + new_service_provision: Huduma mpya iliyotolewa + new_this_week: Mapya (wiki hii) no_action_risk: Hakuna Hatua - no_case_stats: Hakuna Takwikmu za Kesi - no_caseworker_data: Hakuna Taarifa / Data ya Mfanyakazi wa Kesi - no_flagged_child: Hakuna Kesi iliyoripotiwa - no_flagged_incident: Hakuna Matukio Yaliyoripotiwa - no_open_incidents: Hakuna Matukio ya Wazi + no_case_stats: Hakuna Takwikmu za shauri + no_caseworker_data: 'Hakuna Taarifa za msimamizi wa shauri ' + no_flagged_child: Hakuna mashauri yaliyowekewa kibendera + no_flagged_incident: Hakuna Matukio Yaliyowekewa kibendera + no_open_incidents: Hakuna Matukio yaliyofunguliwa no_overdue_activities: Hakuna Shughuli zilizocheleweshwa no_recent_activities: Hakuna Shughuli za Hivi Karibuni no_scheduled_activities: 'Hakuna Shughuli Zilizopangwa ' none_risk: Hakuna Kipaumbele - number_of_victims: Idadi ya waathirika + number_of_victims: Idadi ya waathiriwa number_of_violations: Idadi ya Ukiukwaji - number_of_violations_verified: Ukiukaji umethibitishwa + number_of_violations_verified: Ukiukwaji uliothibitishwa open: Wazi - open_cases: 'Fungua Kesi / Kesi zilizokowazi ' - open_incidents: 'Matukio Ya Wazi ' + open_cases: Mashauri yaliyowazi/ yaliyofunguliwa + open_incidents: Matukio Yaliyowazi outstanding_transfers: Uhamisho ambao Haujakamilika - overdue_activities: Kazi Zilizocheleweshwa - overdue_cases_to_assign: Kesi Zilizochelewa Kukabidhiwa + overdue_activities: Shughuli Zilizocheleweshwa + overdue_cases_to_assign: Mashauri yaliochelewa kufanyiwa kazi overdue_cases_to_assign_high: Umekuwa nazo kesi hizi kwa zaidi ya saa 1 - overdue_cases_to_assign_low: Umekuwa nazo kesi hizi kwa zaidi ya saa tatu + overdue_cases_to_assign_low: Umekuwa na msahuri haya kwa zaidi ya saa tatu overview: Muhtasari - pending: Inasubiri - pending_approvals: 'IUhamisho Unaosubiri ' - pending_transfers: Kazi Zilizochelewa Kukabidhiwa - protection_concern: Wasiwasi wa Ulinzi - protection_concerns: Wasiwasi wa Ulinzi - range12+: Zaidi ya 12 + pending: Linalosubiri + pending_approvals: 'Uthibitisho Unaosubiri ' + pending_transfers: Uhamisho unaosubiri + protection_concern: Shaka ya hifadhi + protection_concerns: Shaka za hifadhi + range12+: Zaidi ya saa 12 range4: 0-4 range4_8: 4-8 range8_12: 8-12 recent_activities: Shughuli za Hivi Karibuni - recently_flagged_child: Kesi Zilizoripotiwa Hivi Karibuni - recently_flagged_incident: Matukio Yaliyoripotiwa Hivi Karibuni - referrals_by_social_worker: Rufaa kutoka kwa mfanyakazi wa kijamii + recently_flagged_child: Mashauri yaliyowekewa kibendera hivi karibuni + recently_flagged_incident: Matukio Yaliyowekewa kibendera Hivi Karibuni + referrals_by_social_worker: Rufaa kutoka kwa Afisa Ustawi wa Jamii registration: Usajili rejected: Kukataliwa rejected_transfers: Uhamisho Uliokataliwa - response: Majibu (Yanaendelea) + response: Hatua (zinaendelea) scheduled_activities: Shughuli Zilizopangwa - score_range: Alama Mbalmbali + score_range: Mpishano wa matokeo screening_service: Huduma za Uchunguzi services: 'Huduma ' services_implemented: Huduma Zinazotekelezwa @@ -709,8 +730,8 @@ sw_TZ: shared_from_my_team_rejected_transfers: Uhamisho Uliokataliwa shared_with_me_new_referrals: Rufaa Mpya shared_with_me_total_referrals: Jumla ya Rufaa - shared_with_me_transfers_awaiting_acceptance: Uhamisho Unaosubiri Kukubalika - shared_with_my_team_pending_transfers_overview: Uhamisho unaosubiri kukubalika + shared_with_me_transfers_awaiting_acceptance: Uhamisho Unaosubiri Kukubaliwa + shared_with_my_team_pending_transfers_overview: Uhamisho unaosubiri kukubaliwa shared_with_my_team_pending_transfers: Uhamisho Unaosubiri shared_with_my_team_referrals: Rufaa shared_with_others_pending_transfers: Uhamisho Unaosubiri @@ -719,111 +740,145 @@ sw_TZ: status_of_cases: 'Hali ya Kesi ' system_user: Mfumo total: 'Jumla ' - total_cases: Jumla ya Kesi + total_cases: Jumla ya mashauri total_referred: Jumla ya Rufaa - tr_stats: 'Kufuatilia Maombi ' + tr_stats: 'Ufuatiliaji wa Maombi ' transers_awaiting_acceptance: Uhamisho Unaosubiri Kukubaliwa - transfers_by_social_worker: Uhamisho na Mfanyakazi wa Kijamii - users: Ikoni ya Mazingira / Mipangilio - violence_type: Aina ya Vurugu - with_incidents: 'Na Matukio ' - with_new_incidents: Na Matukio Mapya + transfers_by_social_worker: Uhamisho uliotolewa na Afisa Ustawi + users: Alama ya mpangilio + violence_type: Aina ya ukatili + with_incidents: 'Pamoja Na Matukio ' + with_new_incidents: Pamoja Na Matukio Mapya without_incidents: Bila ya Matukio worker_count_referrals_total: one: '%{case_worker} unayo %{stat} jumla ya rufaa' - other: '%{case_worker} inazo %{stat} jumla ya rufaa' + other: '%{case_worker} ina jumla ya rufaa %{stat} ' worker_count_total: one: '%{case_worker} unayo %{stat} jumla ya kesi' - other: '%{case_worker} unzo %{stat} jumla ya kesi' + other: '%{case_worker} una jumla ya mashauri %{stat}' workflow: Mtiririko wa Kazi - workflow_team: Mtririko wa Kazi - Kesi za Timu + workflow_team: Mtririko wa Kazi - Mashauri ya Timu you_have: 'Unayo' disabled: status: - disabled: Walemavu - enabled: 'Kuwezeshwa ' + disabled: Zuia + enabled: Wezesha email_notification: - assign: '%{user}Amekabidhi yafuatao %{record_type}kwako%{record_id}' - assign_subject: '%{record_type}%{id}Umekabidhiwa wewe' - approval_request: 'Mtumiaji%{user} anaomba idhini kwa%{approval_type} kesi %{case_id}' - approval_request_subject: 'Kesi: %{id}Ombi la Idhini ' - approval_response: '%{user}Ina%{status} ombi la kupitishwa %{approval_type}kwa kesi %{case_id}' - approval_response_subject: 'Kesi: %{id}Jibu la Idhini ' - referral: '%{user} kutoka %{agency}ameleta wafuatao %{record_type}kwako. %{record_id}kwa %{service_type}' - transfer: '%{user}amewahamisha wafuatayo%{record_type} kuja kwako%{record_id}' - transfer_request_subject: 'Ombi la Uhamisho kwa moja ya kesi zako ' + assign: '%{user}Amekukabidhi yafuatayo %{record_type}%{record_id}' + assign_subject: '%{record_type}%{id}Umekabidhiwa' + approval_request: 'Mtumiaji%{user} anaomba idhini ya kuthibitisha%{approval_type} shauri%{case_id}' + approval_request_subject: 'Shauri %{id}Ombi la kuthibitisha' + approval_response: '%{user}ana%{status} ombi la kuthibitishwa %{approval_type}shauri%{case_id}' + approval_response_subject: 'Shauri %{id}Majibu ya uthibitisho' + referral: '%{user} kutoka %{agency}ameleta rufaa ya wafuatao %{record_type}kwako. %{record_id}kwa ajili ya %{service_type}' + transfer: '%{user}amewahamisha wafuatao%{record_type} kuja kwako%{record_id}' + transfer_request_subject: Ombi la Uhamisho wa moja kati ya mashauri yako transfer_subject: '%{record_type}%{id}- Uhamisho' referral_subject: '%{record_type}%{id}Rufaa' - transfer_request: '%{user}Mtumiaji wa Primero kutoka %{agency}anakuomba uhamishe umili wako %{record_type}wa rekodi %{record_id}ili waweze kukupa %{record_type}huduma za usimamizi kwa mtu binafsi katika maeneo yao. Ikiwa uhamisho huu unakubalika kwako, tafadhali bonyeza %{record_type}kwenye kiungo cha kitambulisho katika barua pepe hii kufungua %{record_type}Primero na uanzishe uhamisho.' - approval_request_html: 'Mtumiaji %{user}anaomba ruhusa kwa %{approval_type}kuhusu kesi %{case_id}' - approval_response_html: '%{user}anayo %{status} ombi la kuidhinishwa kwa %{approval_type}kesi %{case_id}' - referral_html: '%{user}kutoka%{agency}amewaleta wafuatao %{record_type}kuja kwako%{record_id}kwa %{service_type}' - transfer_html: '%{user}amewahamisha wafuatao %{record_type}kuja kwako %{record_id}' - assign_html: '%{user}amewakabidhi wafuatao %{record_type}kuja kwako%{record_id}' - transfer_request_html: 'Mtumiaji wa Primero %{user}kutoka %{agency}anakuomba uhahishe umiliki wa hii %{record_type}rekodi%{record_id}ili waweze kutoa %{record_type}huduma za usimamizi kwa watu binafsi katika maeneo yao . Ikiwa utaukubali uhamisho huu bonyeza %{record_type}Kiungo cha Kitambulisho katika baruapepe hii ya kufungulia %{record_type}katika Primero uanzishe uhamisho.' - transfer_request_notes_html: 'Maelezo kutoka kwa mtu binafsi anayeomba %{request_transfer_notes}' + transfer_request: 'Mtumiaji wa Primero %{user} kutoka %{agency}anaomba umiliki wa uhamisho wa %{record_type}wa rekodi %{record_id}ili waweze kutoa huduma za usimamizi za %{record_type} katika eneo lao. Ikiwa uhamisho huu unakubalika kwako, tafadhali bonyeza %{record_type}kwenye kiungo cha utambulisho katika barua pepe hii ili kufungua %{record_type}Primero na kuanza uhamisho.' + approval_request_html: 'Mtumiaji %{user}anaomba ruhusa ya uthibitisho wa %{approval_type} shauri %{case_id}' + approval_response_html: '%{user}ana %{status} ombi la kuthibitishwa kwa %{approval_type}shauri %{case_id}' + referral_html: '%{user}kutoka%{agency}ameleta yafuatayo %{record_type} kwako%{record_id}kwa %{service_type}' + transfer_html: '%{user}amehamisha yafuatayo %{record_type} kwako %{record_id}' + assign_html: '%{user}ameleta yafuatayo %{record_type} kwako%{record_id}' + transfer_request_html: 'Mtumiaji wa Primero %{user}kutoka %{agency}anakuomba uhamisho wa umiliki wa %{record_type}rekodi%{record_id}ili waweze kutoa huduma za usimamizi za%{record_type} kwa watu binafsi katika maeneo yao . Ikiwa utaukubali uhamisho huu bonyeza %{record_type}kwenye Kiungo cha Kitambulisho katika baruapepe hii ili kufungulia %{record_type}Primero na kuanza uhamisho.' + transfer_request_notes_html: 'Maelezo ya mtu anaefanya maomba %{request_transfer_notes}' + alert: '%{record_type}%{id}%{form_name}Imeshaboreshwa. Tafadhali ingia kwenye Primero kwa ajili ya kuona mabadiliko' + alert_subject: '%{record_type}:%{id}-%{form_name} Lililoboreshwa' + webpush_notification: + action_label: Nenda kwenye Shauri + approval_request: + title: Ombi la Uthibitisho + body: Shauri kwenye timu yako linasubiri ombi la kuthibitishwa %{type} + approval_response: + title: Hatua ya Uthibitisho + body: Moja kati ya mashauri yako limethibitishwa + assign: + title: Kazi mpya + body: Umepokea kazi ya shauri jipya + referral: + title: Rufaa Mpya + body: Umepokea rufaa ya Shauri Jipya + transfer: + title: Uhamisho Mpya + body: Umepokea uhamisho wa shauri jipya + alert_case: + title: Shauri Limeporeshwa + body: "%{type} limeboreshwa katika moja ya mashauri yako " + transfer_request: + title: Ombi la Uhamisho + body: Umepokea Ombi Jipya la uhamisho wa shauri encrypt: export_type: Aina ya usafirishaji file_name: Tengeneza jina la faili lako (hiari) - password_extra_info: Nenosiri liwe na angalau herufi 8. Nenosiri hili litahusishwa na faili na litabidi kuingizwa na mtu yeyote yule atakayefungua faili hili katika siku za usoni - password_label: Tafadhali ingiza nenosiri litakalokomea faili lako + password_extra_info: Neno la siri lazima liwe na angalau herufi 8. Neno hili la siri litahusishwa na faili lililohamishwa na liweze kutumika na mtu yeyote atakaefungua faili hilo katika siku za baade. + password_label: Tafadhali ingiza neno la siri litakaloongeza usalama wa faili lako error_message: - address_fields: Unahitaji kushughulikia%{fields} maeneo katika %{forms}fomu - address_form_fields: Unahitaji kushughulikia%{fields} maeneo katika fomu hii - address_subform_fields: '%{subform}Ina %{fields}maeneo batili' + address_fields: Unahitaji kushuhulikia maeneo haya%{fields} katika fomu %{forms} + address_form_fields: Unahitaji kushughulikia maeneo haya%{fields} katika fomu hii + address_subform_fields: '%{subform}Ina %{fields}maeneo yasiyotumika' + error_401: Umetolewa. Tafadhali ingia tena + error_something_went_wrong: Kuna kitu hakipo sawa error_page: not_authorized: - server_error: Hujaidhinishwa kufikia ukurasa huu + server_error: Hujaidhinishwa kuingia kwenye ukurasa huu title: Haijaidhinishwa not_found: - contact_admin: Ikiwa unaamini uko hapa kimakosa, tafadhali wasiliana na msimamizi wako - something_went_wrong: Samahani, kunakitu kilikosewa/kilienda vibaya! + contact_admin: Ikiwa unadhani uko hapa kimakosa, tafadhali wasiliana na msimamizi wa mfumo + something_went_wrong: Samahani, kunakitu hakiko sawa errors: - error_loading: Hitilafu ya Upakiaji rekodi (moja au zaidi) + api: + internal_server: Tatizo kwenye seva + error_loading: Tatizo katika upatikanaji wa taarifa () models: agency: - code_present: Lasima Isiwe tupu - logo_format: Faili linatakiwa kuwa la png - terms_of_use_format: Faili linatakiwa kuwa la png - name_present: Lasima Isiwe tupu + code_present: Haipaswi kuwa wazi + logo_format: Faili linatakiwa kuwa la PNG + terms_of_use_format: Faili linatakiwa kuwa la PNG + name_present: Halipaswi kuwa wazi child: age: Umri ni lazima uwe kati ya 0 mpaka 130 - date_of_birth: Tafadhali ingiza tarehe halali ya kuzaliwa kwaajili ya suala hili + date_of_birth: Tafadhali ingiza tarehe sahihi ya kuzaliwa kwaajili ya kumbukumbu ya shauri hili export_configuration: - opt_out_field_does_not_exist: Bainisha sehemu ya kuchagua kutoka haipo kwenye rekodi hii - record_type: Aina batili ya rekodi. Lazima awe mtoto, Ombi la kufuatilia, au Tukio + opt_out_field_does_not_exist: Bainisha eneo lililotolewa ambalo halipo katika kumbukumbu hii + record_type: Aina ya taarifa sio sahihi. Lazima iwe mtoto, Ombi la ufuatiliaji, au Tukio field: - translated_options_do_not_match: Chaguo la Sehemu zilizotafsiriwa lazima ziwe na utambulisho sawa + translated_options_do_not_match: Chaguo la Sehemu zilizotafsiriwa lazima ziwe na utambulisho ulio sawa location: - admin_level_present: Lasima Isiwe tupu - code_present: Lasima Isiwe tupu - name_present: Lasima Isiwe tupu - unique_location_code: Eneo lenye utambulisho huu tayari lipo, tafadhali ingiza utambulisho mwengine wa eneo. + admin_level_present: Halipaswi kuwa wazi + code_present: Halipaswi kuwa wazi + name_present: Halipaswi kuwa wazi + unique_location_code: Eneo lenye nambari ya utambulisho huo tayari lipo, tafadhali ingiza nambari nyengine ya utambulisho wa eneo. lookup: being_used: Sehemu hii inatumika kwa sasa na haiwezi kufutwa - name_present: Jina lazima liandikwe/lijazwe - values_ids_blank: Utambulisho unaoangalia haujajazwa + name_present: Jina lazima liandikwe + values_ids_blank: Utambulisho wa taarifa haujajazwa primero_module: - associated_record_types: Angalau aina moja ya rekodi lazima ihusishwe na moduli hii + associated_record_types: Angalau aina moja ya taarifa lazima ihusishwe na moduli hii form_section_ids: Angalau fomu moja ihusishwe na moduli hii - name_present: Jina lazima liandikwe/lijazwe - unique_name: Moduli yenye jina hilo tayari ipo, tafadhali ingiza jina jingine tofauti + name_present: Jina lazima liandikwe + unique_name: Moduli yenye jina hilo tayari ipo, tafadhali ingiza jina jingine report: - module_presence: Moduli lazima iandikwe / ijazwe - module_syntax: Moduli zote za ripoti lazima ziwe tayari - name_presence: Jina lazima liandikwe/lijazwe + module_presence: Moduli haipaswi kuwa wazi + module_syntax: Moduli zote za ripoti lazima ziwepo + name_presence: Jina lazima liandikwe role: - permission_presence: Tafadhali chagua angalau ruhusa moja + permission_presence: Tafadhali chagua angalau sehemu moja user: - email: "Tafadhali ingiza baruapepe (mfano: 'name@example.org')" - password_mismatch: Sehemu ya neno siri haina nenosiri sawa - password_length: Nenosiri liwe na angalau %{min}herufi - email_uniqueness: Mtumiaji mwenye anuani ya barua pepe hii tayari yupo. Tafadhali ingiza anuani tofauti + email: "Tafadhali ingiza baruapepe sahihi (mfano: 'name@example.org')" + password_mismatch: Neno la siri halifanani + password_length: Neno la siri liwe na angalau herufi %{min} + email_uniqueness: Mtumiaji wa anuani ya barua pepe hii tayari yupo. Tafadhali ingiza anuani tofauti code_of_conduct: - title_present: Kichwa cha maneno / habari lazima kiandikwe / kijazwe + title_present: Kichwa cha habari lazima kiandikwe content_present: Maudhui lazima yaandikwe created_by_present: Aliyetengeneza lazima aandikwe - not_found: Hakuna Rekodi (I ) Zilizoonekana + webpush_subscription: + notification_url_present: Maelezo ya URL lazima yaandikwe + notification_url_format: 'Maelezo ya URL lazima yawe na mpangilio ' + auth_present: Mwandishi lazima yaandikwe + p256dh_present: p256dh lazima iandikwe + not_found: Hakuna taarifa (I ) Zilizoonekana try_again: Jaribu tena exports: case_pdf: @@ -835,536 +890,632 @@ sw_TZ: one: CSV selected: Iliyochaguliwa kwenye CSV custom: - all: Desturi + all: Iliyozoeleka custom_exports: - all: Desturi - choose_fields: Je, ungependa kuchagua nyanja za kibinafsi kwenye fomu? - empty_fields_forms: 'Tafadhali chagua baadhi ya fomu au sehemu za kusafirisha ' - empty_format: 'Tafadhali chagua muundo wa usafirishaji ' - empty_module: 'Tafadhali chagua ya kusafirisha ' - empty_password: Tafadhali ingiza neosiri ambalo lita encrypt faili lako - field_label: Uwanja / Eneo - fields: Chagua Sehemu za kuhamisha + all: Iliyozoeleka + choose_fields: Je, ungependa kuchagua sehemu ya taarifa binafsi kwenye fomu? + empty_fields_forms: 'Tafadhali chagua baadhi ya fomu au sehemu za kuzitoa ' + empty_format: Tafadhali chagua muundo wa kutoa + empty_module: Tafadhali chagua moduli ya kuitoa + empty_password: Tafadhali ingiza neno la siri litakaloweka faili lako kuwa salama zaidi + field_label: Sehemu + fields: Chagua Sehemu za kutoa form_label: Fomu - format_label: Chagua Mfumo - forms: ChaguabFomu za kusafirisha - label: 'Mauzo Maalum ya Nje ' + format_label: Chagua Muundo + forms: Chagua Fomu za kutoa + label: Utoaji uliozoeleka module_placeholder: 'Tafadhali chagua moduli ' select_module: 'Chagua Moduli ' submit: 'Sawa ' - header: Kichwa - custom_header: 'Kichwa Maalum ' - signatures: 'Ingiza Mistari ya Kuweka Saini ' + header: 'Mada ' + custom_header: Mada ya kawaida + signatures: 'Weka Mistari kwa ajili ya Saini ' include_implementation_logos: Weka nembo za utekelezaji include_implementation_logos_help_text: Hii itakuwa ni pamoja na nembo ya urambazaji na au ukurasa wa kuingia - include_agency_logo: Weka nembo ya shirika - include_other_logos: Ni pamoja na nembo nyingine? + include_agency_logo: Je, iwekwe nembo ya taasisi? + include_other_logos: Je, unaongeza na nembo nyengine? duplicate_id_csv: - all: Rudufu ya Vitambulisho - female_abbreviation: F /Mke + all: Rudufu ya utambulisho + female_abbreviation: Mwanamke headers: age: Umri - case_id: Kitambulisho cha Kesi + case_id: Utambulisho wa shauri child_name_last_first: Jina la Mtoto family_size: Ukubwa wa Familia - moha_id: KITAMBULISHO CHA MOHA KIMESHUKA THAMANI + moha_id: Utambulisho wa Wizara ya Mambo ya ndani uliowachwa national_id_no: Nambari ya Kitambulisho cha Taifa - progress_id: Kitambulisho cha Maendeleo - sex_mapping_m_f_u: Jinsia + progress_id: Utambulisho wa Maendeleo ya shauri + sex_mapping_m_f_u: Jinsi other_agency_id: Utambulisho wa Hospitali na nambari ya mgonjwa - male_abbreviation: M / Mume + male_abbreviation: Mwanmme unknown_abbreviation: U - exported: Faili la usafirishaji limetengenezwa kwa mafanikio - exported_error: Hitilafu imetokea wakati wa kutengeneza faili la usafirishaji + exported: Faili limefanikiwa kutolewa kikamilifu + exported_error: Hitilafu imetokea wakati wa kutoa faili forms: - button: Fomu za Usafirishaji - label: Kusafirisha nje + button: Toa fomu + label: Toa header: - form_group: Kuunda Kikundi + form_group: Kundi la fomu form_name: Jina la Fomu - field_id: Sehemu ya Utambulisho - field_type: Aina ya Eneo + field_id: 'Sehemu ya utambulisho ' + field_type: Sehemu ya aina field_name: Sehemu ya Jina - required: Inahitajika / Muhimu - on_mobile: Kwenye simu + required: 'Inahitajika ' + on_mobile: Kwa simu on_short_form: Kwa kifupi - option_ids: Chaguo la Kitambulisho + option_ids: Chaguo la utambulisho options: Chaguo - options_lookup: Tafuta / Taza juu - help_text: Msaada wa Kimaandishi - guiding_questions: Maswali ya muongozo + options_lookup: Tafuta + help_text: Maandishi yanayoongoza kupata msaada + guiding_questions: 'Maswali yanayoongoza ' visible: Inayoonekana - lookup_id: Tafuta Kitambulisho + lookup_id: Tafuta utambulisho lookup_name: Tafuta Jina - option_id: Chaguo la Kitambulisho - option_name: Jina la Chaguo + option_id: Chaguo la Utambulisho + option_name: 'Chaguo la Jina ' options: location: Maeneo - agency: Mashirika + agency: Taasisi user: Watumiaji - reportinglocation: Eneo la Kuripoti / Eneo la kutoa Taarifa + reportinglocation: Maeneo ya kutoa Taarifa subforms: 'Fomu ndogo%{subform_name}' collapsed_fields: 'Maeneo yaliyochanganywa %{fields}' country: Nchi summary_header: - form_group: Kikundi cha form ya Primerou + form_group: Kikundi cha la fomu ya Primero form: Fomu za Primero status: Hali notes: Maelezo - go_to_exports: Nenda kwenye Ukurasa wa Usafirishaji ili upakue + go_to_exports: Nenda kwenye Ukurasa wa kutoa ili upakue incident_recorder_xls: - all: Kifaa chenye Kurekodi Matukio - one: Kifaa chenye Kurekodi Matukio - selected: Kuchaguliwa kwa Kinasa Sauti + all: Kifaa cha kuweka kumbukumbu za Matukio + one: Kifaa cha kuweka kumbukumbu za Matukio + selected: Imechaguliwa kwenye kifaa cha kuweka kumbukumbu za matukio json: all: JSON one: JSON selected: Imechaguliwa kwenye JSON list_view_csv: - all: Muonekano wa Orodha ya Kusafirishwa + all: Muonekano wa Orodha ya Kutoa selected: Imechaguliwa kwenye CSV messages: - no_exporter: Hakuna Msafirishaji Aliyebainishwa + no_exporter: Hakuna Mtoaji Aliyebainishwa mrm_violation_xls: all: Ukiukwaji wa MRM one: Ukiukwaji wa MRM - selected: Kuchaguliwa kwa Ukiukaji wa MRM - no_records: Hakuna rekodi / Kumbukumbu Zinazopatikana + selected: Imechaguliwa kwenye Ukiukwaji wa MRM + no_records: Hakuna taarifa! pdf: - all: PDF (Halijakomewa) + all: PDF (Haiko kwenye hali ya usalama) one: PDF selected: Imechaguliwa kwenye PDF pdf_exports: label: PDF recipient: Mpokeaji - case_worker: Mfanyakazi wa Kesi + case_worker: Msimamizi wa shauri client: Mteja date: Tarehe recipient_name: Jina la Mpokeaji - recipient_agency: Wakala wa Mpokeaji - caseworker_name: Jina la Mfanyakazi - caseworker_agency: Wakala wa Mfanyakazi wa Kesi + recipient_agency: Taasisi ya Mpokeaji + caseworker_name: Jina la Msimamizi wa shauri + caseworker_agency: Tasisi ya msimamizi wa shauri photowall: - all: Ukuta wa Picha - flag_suspect_record: Iliyotiwa alama kama Rekodi ya Mtuhumiwa + all: Ukurasa wa Picha + flag_suspect_record: 'Kumbukumbu ya Mtuhumiwa Iliyowekwa alama ' no_photos_available: Hakuna picha zinazopatikana - one: Ukuta wa Picha + one: Ukurasa wa Picha reunited: Kuunganishwa tena - selected: Imechaguliwa kwenye Ukuta wa Picha - success_message: Kutengeneza Ukuta wa Picha %{file_name}Kesi ambazo hazina picha hazitajumuishwa + selected: Imechaguliwa kwa ajili ya ukurasa wa Picha + success_message: Kutengeneza ukurasa wa Picha %{file_name}Mashauri yasiyo na picha hayatozingatiwa printed: 'Iliyochapishwa: %{date}' - queueing: Kutengeneza faili la usafirishaji%{file_name} + queueing: Kutengeneza faili la utoaji%{file_name} selected_xls: - all: 'Bora ' - one: Bora - selected: Kuchaguliwa kwa Ubora + all: 'Excel ' + one: Excel + selected: Imechaguliwa kwa ajili ya Excel selected_fields: Sehemu Zilizochaguliwa unhcr_csv: - all: 'Shirika la Umoja wa Mataifa la ' + all: Shirika la Wakimbizi la Umoja wa Mataifa female_abbreviation: Mwanamke headers: age: Umri - case_status: Hali ya Kesi + case_status: Hatua ya Shauri causes_of_separation: 'Sababu za Kutengana ' country_of_origin: Nchi ya Asili - cpims_code: Alama ya CPMS - current_care_arrangement: Mpangilio wa Kesi ya Sasa + cpims_code: Alama ya CPIMS + current_care_arrangement: Mpangilio wa Sasa wa Malezi date_of_birth: Tarehe ya Kuzaliwa - date_of_identification: Tarehe ya Kitambulisho - family_count_no: Nambari ya Mahakama ya Familia - governorate_country: Nchi ya Ugavana - id: Utambulisho - individual_progress_id: Kitambulisho cha Maendeleo ya Mtu Binafsi - locations_by_level: Anuani (Kambi, Nyumba na viwango vingine vya anuani vinavyotumika, kama vile makazi na viratibu vya GPS) - long_id: 'Kitambulisho Kirefu ' - moha_id: Kitambulisho cha MOHA + date_of_identification: Tarehe ya Utambulisho + family_count_no: Idadi ya Wanafamilia + governorate_country: Mkoa - Nchi + id: 'Utambulisho ' + individual_progress_id: Utambulisho wa hatua ya Mtu Binafsi + locations_by_level: Anuani (Kambi, Nyumba na aina nyengine za anuani vinavyotumika, kama vile makazi na viratibu vya GPS) + long_id: 'Utambulisho Mrefu ' + moha_id: Utambulisho wa MOHA name_of_caregiver: Jina kamili la mlezi name_of_child_last_first: Jina kamili la mtoto - primary_protection_concerns: Masuala ya Msingi ya Ulinzi - progres_id: 'Kitambulisho cha Maendeleo ' + primary_protection_concerns: Shaka za Msingi za Hifadhi + progres_id: Utambulisho wa hatua reunification_status: Hali ya Kuunganishwa tena - secondary_protection_concerns: Masuala ya Ulinzi wa Pili - sex: Jinsia + secondary_protection_concerns: Shaka Zaidi za Hifadhi + sex: Jinsi sex_mapping_m_f_u: Jinsi - short_id: Kitambulisho Kifupi + short_id: Utambulisho Mfupi vulnerability_code: Alama ya Mazingira Magumu vulnerability_details_code: Alama ya Maelezo ya Mazingira Magumu male_abbreviation: Mwanamme one: Shirika la Umoja wa Mataifa la Wakimbizi - selected: Imechaguliwa nkwenye Shirika la Umoja wa Mataifa la Wakimbizi + selected: Imechaguliwa kwenye Shirika la Umoja wa Mataifa la Wakimbizi unknown_abbreviation: U xlsx: - all: Bora - one: Bora - selected: Imechaguliwa kwenye Ubora + all: Excel + one: Excel + selected: Imechaguliwa kwa ajili ya Excel imports: csv_hxl_location: messages: - success: Maeneo yaliletwa kwa ufanisi - no_data: 'Uagizaji Haujafanyika. Hakuna Taarifa / Data Iliyopitishwa ' - csv_parse_error: 'Uagizaji Haujafanyika. Hitilafu katika Kuchanganua Taarifa / Data ya CSV' - error: 'Safu %{row_number} Haijachakatwa%{message}' - db_error: 'Kutengeneza Hitilafu%{location_code}%{message}' - locale_invalid: 'Kuruka. %{column_name} Eneo batili' - insert_all_error: 'Kuagiza Hakujafanyika. Hitilafu ya Kanzidata%{message}' + success: Maeneo yameingizwa kikamilifu + no_data: 'Ungizaji Haujafanyika. Hakuna Taarifa Iliyopitishwa ' + csv_parse_error: 'Uingizaji Haujafanyika. Kuna tatizo katika Kuchanganua Taarifa ya CSV' + error: 'Safu %{row_number} Haijafanyiwa kazi%{message}' + db_error: 'Hitilafu katika utengenezaji wa %{location_code}%{message}' + locale_invalid: 'Kukiuka %{column_name} Sehemu sio sahihi' + insert_all_error: 'Uingizaji haujafanyika. Hitilafu ya Kanzidata%{message}' csv_record: messages: - success: Rekodi /kumbukumbu ziliingizwa kwa ufanisi - no_data: 'Uagizaji haujashughulikiwa. Hakuna data /taarifa iliyopitishwa' - no_file: 'Uagizaji Haujashughulikiwa. Faili halipo ' - csv_parse_error: 'Uagizaji Haujashughulikiwa. Hitilafu katika kuchanganua taarifa /data ya CSV ' - error: 'Safu %{row_number}Haijashughulikiwa %{message}' - db_error: 'Hitilafu katika kuunda /kutengeneza %{location_code} : %{message}' - locale_invalid: 'Kuruka %{column_name} : Eneo ni batili' - insert_all_error: 'Uagizaji Haujashughulikiwa. Hitilafu ya kanzidata: %{message}' + success: Taarifa zimeingizwa kikamilifu + no_data: 'Uingizaji haukufanyika. Hakuna data iliyopitishwa' + no_file: 'Uagizaji Haukufanyika. Faili halipo ' + csv_parse_error: 'Uagizaji Haukufanyika. Hitilafu katika kuchanganua data ya CSV ' + error: 'Safu %{row_number}Haikufanyiwa kazi %{message}' + db_error: 'Hitilafu katika utengenezaji wa%{location_code} : %{message}' + locale_invalid: 'Kukiuka %{column_name} : Eneo sio sahihi' + insert_all_error: 'Uagizaji Haukufanyika. Hitilafu katika kanzidata: %{message}' sync_record: failed: 'Usawazishaji wa Mwisho Haukufanikiwa' - last: 'Usawazishajio wa Mwisho%{date_time}' - not_found: 'Data / Taarifa za Uwezeshaji wa Mwisho Hazikuonekana / Hazijapatikana ' - retrieving: Kurejesha Data / Taarifa + last: 'Usawazishaji wa Mwisho%{date_time}' + not_found: 'Usawazishaji wa mwisho Taarifa Hazikuonekana ' + retrieving: Kurejesha Taarifa/ data see_details: Angalia / Tazama Maelezo fields: - action: Kitendo / Hatua - actions: Vitendo / Hatua - add: Ongeza / Jumlisha - add_new_field: Tengeneza Eneo / Sehemu / Uwanja Mpya - add_existing_field: Ongeza Eneo / Sehemu Iliyopo - add_field: Ongeza Sehemu / Uwanja + action: Hatua + actions: Hatua + add: Ongeza + add_new_field: Tengeneza Eneo jipya + add_existing_field: Ongeza Eneo Iiliyopo + add_field: Ongeza eneo add_field_type: Ongeza %{file_type} audio: current: Sauti ya Sasa - audio_upload_box: Upakiaji wa Sauti - bia_document: Hati ya BIIA - bid_document: Hati ya BID - check_box: Angalia Masanduku / Masnduku ya Kuangalia - clear_group_by: Weka Wazi / Kisafishe Kikundi Na - clear_sort_by: Kupanga kwa Uwazi kwa - copy_from_another_form: Uwanja huu ulinakiliwa kutoka kwenye fomu nyingine - create_field: Tengeneza Sehemu / Eneo / Uwanja - create_unique_values: Tengeneza / Unda maadili ya Kipekee + audio_upload_box: Ingiza Sauti + bia_document: Waraka wa BIA + bid_document: Waraka wa BID + check_box: Kisanduku cha kuchagua + clear_group_by: Kiondoshe kikundi kwa + clear_sort_by: Panga kwa + copy_from_another_form: Sehemu hii imenakiliwa kutoka kwenye fomu nyengine + create_field: 'Tengeneza Sehemu ' + create_unique_values: Tengeneza data ya kipekee date_field: Sehemu ya Tarehe date_help: siku-mwezi-mwaka - date_help_with_time: siku-mwezi-mwaka /saa.dakika - date_not_valid: Tarehe hii si halali + date_help_with_time: siku-mwezi-mwaka - saa:dakika + date_not_valid: Tarehe hii sio sahihi time: Muda date_range: date: Tarehe - date_range: Safu ya Tarehe - from: Kutoka / Kuanzia - to: Kwa / Mpaka - view_by: Tazama Kwa /Angalia Kwa - date_range_field: Safu ya Tarehe + date_range: Mpangilio wa Tarehe + from: ' Kuanzia' + to: Mpaka + view_by: Angalia Kwa + date_range_field: Mpangilio wa Tarehe date_time: Tarehe-Saa - db_name: Jina la Kihifadhidata - default: Chaguo-msingi? - default_date_validation: Uthibitishaji wa tarehe chaguo-msingi - default_to_current_date: Chaguo-msingi kwa Tarehe ya sasa? - default_to_current_datetime: Chaguo-msingi kwa tarehe na wakati wa sasa? - default_value: Thamani Chaguo-msingi - deleted: Eneo%{display_name} lmefutwa - detail: Undani - disabled: Walemavu - display_name: Onyesha jina + db_name: Jina la Kanzidata + default: Chaguo la msingi? + default_date_validation: Uthibitishaji wa tarehe chaguo la msingi + default_to_current_date: Chaguo la msingi kwa Tarehe ya sasa? + default_to_current_datetime: Chaguo la msingi kwa tarehe na wakati wa sasa? + default_value: Thamani ya Chaguo la msingi + deleted: Eneo%{display_name} limefutwa + detail: Kwa kina + disabled: Zuia + display_name: Onesha jina document: comments: Maoni - current: Je, hii ndio hati ya sasa? - date: Tarehe ya Hati - name: Jina la Hati - is_current: Je, hii ndio hati ya sasa? - document_upload_box: Upakiaji wa Hati - edit_label: Hariri Uga / Eneo + current: Je, huu ni waraka wa sasa? + date: Tarehe ya waraka + name: Jina la waraka + is_current: Je, huu ni waraka wa sasa? + document_upload_box: Uwekaji wa waraka + edit_label: Rekebisha sehemu enabled: Imewezeshwa? enabled_label: Kuwezeshwa - english_text: Maandishi ya Kiingereza - field_name: Jina la Eneo / Uwanja - field_type: Aina ya eneo / Uwanja - attachment_too_large: Ukubwa wa faili usizidi 10mb + english_text: Maelezo ya Kiingereza + field_name: Jina la sehemu + field_type: Aina ya sehemu + attachment_too_large: Faili lisiwe kubwa zaidi ya 20mb  file_upload_box: - add_document_label: Ongeza Hati - add_new_document_button_text: Ongeza hati nyingine - add_new_photo_button_text: Ongeza picha nyingine - add_photo_label: Ongeza Picha - document_description: Maelezo ya Hati - document_file_restrictions_message: Ukubwa wa faili usizidi 2MB (faili inayoweza kutekelezwa (exe) haiwezi kupakiwa). + add_document_label: Ingiza waraka + add_new_document_button_text: 'Ingiza waraka mwengine ' + add_new_photo_button_text: Ingiza picha nyingine + add_photo_label: Ingiza Picha + document_description: Maelezo ya nyaraka + document_file_restrictions_message: Ukubwa wa faili usizidi 2MB (unaloweza kulifanyia kazi (exe) faili haliwezi kupakiwa). no_file_selected: Hakuna faili lililochaguliwa photo_file_restrictions_message: 'Ukubwa wa picha usizidi 10mb. Ukubwa wa faili za sauti usizidi 10mb. Kila inapokuwa ndogo ndio vizuri zaidi ' recorded_audio_label: Sauti iliyorekodiwa select_file_button_text: Chagua Faili - find_lookup: Tafuta Tafuta + find_lookup: Tafuta form_name: Jina la Fomu. - future_date_not_valid: Haiwezikuwa siku zijazo + future_date_not_valid: Haiwezi kuwa ya baadae guidance: Muongozo - guiding_questions: Maswali ya Muongozo - help_text: Maandishi ya Msaada + guiding_questions: 'Maswali yanayo ongoza ' + help_text: Maelezo ya Msaada hide_on_view_page: Onyesha ukurasa - label: Eneo / Viwanja /Nyanja + label: Sehemu mobile_visible: Programu ya simu - move_to: Hamia / Sogeza + move_to: Peleka kwa multi_select: Inaweza kuchagua chaguzi nyingi - multi_select_box: Uteuzi mbalimbali + multi_select_box: Chaguzi mbalimbali must_be_english: Ni lazima iingizwe kwa Kiingereza name: Jina - not_future_date: Si tarehe ya siku zijazo + not_future_date: Sio tarehe ya baadae number_not_valid: Tafadhali ingiza data ya nambari numeric_field: Eneo la kuweka Nambari - on_collapsed_subform: Katika fomu ndogo iliyofupishwa + on_collapsed_subform: Katika fomu ndogo iliyovunjwa option_strings_add_option: Ongeza Chaguo - option_strings_source: Tafuta / Tazama juu + option_strings_source: Tafuta option_strings_text: Chaguo - option_strings_text_display: Maandishi ya Chaguo - option_strings_text_key: Ufunguo wa Chaguo - options_indications_lookup_values: Unaweza kutumia utafutaji uliofafanuliwa kabla au kuunda maadili ya kipekee - options_indications_restrictions: 'Huwezi kufanya vyote viwili ' - options_or_lookup_warning: Tafadhali ongeza Chaguzi au chagua Tafuta / Tazama juu. Usiingize yote mmawili - other_documents: Hati Nyingine - photo_upload_box: Kupakia Picha + option_strings_text_display: Maelezo ya Chaguo + option_strings_text_key: Muongozo wa Chaguo + options_indications_lookup_values: Unaweza kutumia utafutaji uliofafanuliwa kabla au kuunda data ya kipekee + options_indications_restrictions: Huwezi kufanya yote mawili + options_or_lookup_warning: Tafadhali ongeza Chaguo au tafuta. Usiingize yote mawili + other_documents: Waraka mwengine + photo_upload_box: Kuweka Picha predifined_lookups: Tumia utafutaji ulioainishwa awali radio_button: Kitufe cha Redio remove: Ondoa - remove_attachment_confirmation: Je, unahakika unataka kukiondoa kiambatisho hiki? + remove_attachment_confirmation: Je, una uhakika unataka kukiondoa kiambatisho hichi? required: Inahitajika required_field: '%{field}Inahitajika ' - search_existing: Tafuta eneo lililopo / Tafuta Uwanja uliopo - select_box: Chagua Chakuangusha Chini - select_date_validation: Chagua Njia ya Kuhalalisha tarehe - select_multiple: Chagua yote yanayotumumika + search_existing: 'Tafuta sehemu ililyopo ' + select_box: Chagua orodha ya kuendea Chini + select_date_validation: Chagua Njia ya Kuthibitisha tarehe + select_multiple: Chagua yote yanayohitajika select_single: (Chagua...) - separator: Mgawanyiko - show: Onyesha? - show_on: Onyesha - show_on_minify_form: Fomu fuoi/ Kwa ufupi - subform: Fomu ndodo - subform_group_by: Kundi kwa / Kusanya kwa - subform_remove_message: Je, una hakika unatakaa kuiondoa fomu hii ndogo? + separator: Kigawio + show: Onesha? + show_on: Onesha + show_on_minify_form: Kwa ufupi + skip_logic: + name: Kuacha Mantiki? + record_section: + title: 'Sehemu hii inatakiwa ionekane ikiwa kumbukumbu ' + buttons: + add: Ongeza sharti la taarifa + subform_section: + title: 'Sehemu hii inatakiwa ionekane ikiwa ni fomu ndogo ' + buttons: + add: Ongeza sharti la fomu ndogo + subform: Fomu ndogo + subform_group_by: Kusanya kwa + subform_remove_message: Je, una uhakika unataka kuiondoa fomu hii ndogo? subform_section: description: Maelezo ya fomu ndogo - name: Mada Ndogo Kichwa cha habari cha fomu ndogo - starts_with_one_entry: Tuanze kwa kuingiza fomu ndogo moja? - subform_append_only: Ulandanishi/ Uoanishaji Uliochaguliwa kwenye Simu ya Mkononi - subform_prevent_item_removal: Zuiya kuondolewa kwa kuingizwa kwa fomu ndogo? + name: Mada ya fomu ndogo + starts_with_one_entry: Je, unataka kuanza kujaza fomu moja ndogo? + subform_append_only: Uoanishaji Uliochaguliwa kwenye Simu ya Mkononi + subform_prevent_item_removal: 'Je, tuzuie kuondolewa kwa fomu ndogo iliojazwa? ' subform_sort_by: Panga kwa successfully_added: Eneo limefanikiwa kuongezwa - tally_field: Eneo / Uwanja wa Hesabu - tally_items: Vitu vinavyooana / vinavyolingana + tally_field: Eneo linganifu + tally_items: Vitu vinavyolingana tally_items_maximum: (5 Kiwango cha juu) - text_area: Eneo la Maandishi - text_field: Eneo / Uwanja wa Maandishi - textarea: Eneo la Maandishi + text_area: Sehemu ya Maandishi + text_field: Sehemu ya Maandishi + textarea: Sehemu ya Maandishi tick_box: Kisanduku cha Kuweka Alama tick_box_label: Lebo ya Kisanduku cha Kuweka Alama translation_text: Maandishi ya Tafsiri total: Jumla - type: Aina / Chapa - updated: 'Eneo llimewekwa toleo jipya ' - visibility: Kuonekana + type: Aina + updated: 'Sehemu iliyoboreshwa ' + visibility: Muonekano web_app: Programu ya Tovuti filters: - apply_filters: Omba - clear_filters: Wazi - less: Kidogo - more: Zaidi + apply_filters: Tumia + clear_filters: Futa + less: Kidogo..... + more: Zaidi..... save_filters: 'Hifadhi ' + categories: + violations: Ukiukwaji + incidents: Matukio + individual_victims: Wahanga flags: - add_flag_tab: Ongeza Bendera Mpya - date: 'Tarehe' - flag_added: Bendera imeongezwa kwa mafanikio - flag_date: Tarehe ya Bendera - flag_reason: 'Sababu ya Bendera ' + add_flag_tab: Ongeza Kibendera Kipya + date: 'Tarehe:' + flag_added: 'Kibendera kimefanikiwa kuongezwa ' + flag_date: Tarehe iliyowekwa Kibendera + flag_reason: 'Sababu ya kuwekwa Kibendera ' flag_reason_maximun_label: Zisizidi herufi 255 - flag_resolved: Bendera Kutatuliwa - flags_tab: Bendera - no_flags: Hakuna bendera zilizoonekana - resolve_button: Kutatua - resolve_flag: Kutatua Bendera - resolve_reason: Kutatua Sababu - resolved: Bendera Zilizotatuliwa - resolved_date: 'Imetatuliwa' - resolved_reason: 'Kutatua Sababu' - title: Bendera + flag_resolved: Kibendera Kimefanyiwa kazi + flags_tab: Vibendera + no_flags: Hakuna kibendera kilichoonekana + resolve_button: Kimefanyiwa kazi + resolve_flag: Fanyia kazi Vibendera + resolve_reason: Sababu ya Kufanyiwa kazi + resolved: Vibendera Vilivyofanyiwa Kazi + resolved_date: 'Kimefanyiwa Kazi' + resolved_reason: 'Sababu ya Kufanyiwa kazi' + title: Vibendera followup_reminders: system_generated_followup_flag: 'Ziara ya lazima ya ufuatiliaji ' form_section: form_name: Jina la Fomu module: Moduli name: 'Jina ' - record_type: Aina ya rekodi + record_type: Aina ya Taarifa required_field: '%{field}Inahitajika' forms: add: Ongeza Fomu description: 'Maelezo ya Fomu ' - fields: Maeneo + fields: Sehemu form_description: Maelezo - form_group: Unda Kikundi + form_group: Kundi la Fomu form_title: Kichwa cha habari cha fomu help_text: - must_be_english: 'Lazima iingizwe / iandikwe kwa Kiingereza ' - related_groups: Iweke fomu katika kikundi kinachohusiana na watumiaji - summariaze_purpose: Muhtasari wa madhumuni ya fomu. Lazima uingizwe / uandikwe kwa Kiingereza - invalid_characters_field: '%{field}Ina herufi batili' + must_be_english: 'Lazima ijazwe kwa Kiingereza ' + related_groups: Ziweke fomu zinazohusiana kwa ajili ya watumiaji + summariaze_purpose: Fupisha lengo la fomu. Lazima Lijazwe kwa Kiingereza + invalid_characters_field: '%{field}Ina herufi zisizohitajika' label: Fomu manage: Kusimamia messages: - created: Sehemu ya fomu imetengenezwa kwa mafanikio - fields_with_same_name: Fomu haziwezi kuwa na eneo lenye jina linalofanan - save_success: Sehemu ya fomu umeongezwa tole jipya kwa mafanikio - save_with_errors: Kulikuwa na tatizo na sehemu nyingine za fomu hazikuongezwa matleo mepya - updated: Sehemu ya fomu imeongezwa toleo jipya kwa mafanikio - use_existing: 'Tunakuhimiza utumie fomu zilizopo kwa sababu kufanya hivyo kutarahisisha kubadilishana data na kuunganisha data baina ya taasisi. ' + created: Sehemu ya fomu imetengenezwa kikamilifu + fields_with_same_name: Fomu haziwezi kuwa na sehemu zenye majina yanayofanana + save_success: Sehemu ya fomu imeboreshwa kikamilifu + save_with_errors: Kulikuwa na tatizo na sehemu nyingine za fomu hazikuboreshwa + updated: Sehemu ya fomu imeboreshwa kikamilifu + use_existing: 'Tunakuhimiza utumie fomu zilizopo kwa sababu kufanya hivyo kutarahisisha kubadilishana na kuunganisha data baina ya taasisi. ' mobile_app: Programu ya simu module: Moduli - no_subform_filters_added: Kwa sasa Fomu hii ndogo haina eneo / nyuga - record_type: Aina ya Rekodi + no_subform_filters_added: Fomu hii ndogo Kwa sasa haina sehemu ya kuingizia taarifa + record_type: Aina ya taarifa record_types: - approvals: Vibali - case: Kesi - child: Kesi + approvals: Uthibitisho + case: Shauri + child: Shauri incident: Tuklio - individual_victim: Muathirika Binafsi + individual_victim: Muhanga potential_match: Inauwezekano wa Kulingana - record_information: Irewkodi Taarifa / Habari + record_information: Taarifa ya Kumbukumbu referrals: Rufaa - reportable_follow_up: Fuatilia - reportable_protection_concern: Wasiwasi wa Ulinzi + reportable_follow_up: Ufuatiliaji + reportable_protection_concern: Shaka ya hifadhi reportable_service: Huduma - tracing_request: Ombi la Kufuatilia - transfers_assignments: Uhamisho / Kazi - violation: Ukiukaji + tracing_request: Ombi la Ufuatiliaji + transfers_assignments: Uhamisho/ Kazi + violation: Ukiukwaji registry_details: Maelezo ya Usajili - registry_record: Rekodi za Usajili - required_field: '%{field}Ni eneo linalohitajika' + registry_record: Taarifa za Usajili + family_record: Taarifa za Familia + family: Taarifa za Familia + required_field: '%{field}Ni sehemu inayohitajika' select_label: Chagua settings: Mipangilio - show_on: Onyesha - subform_need_to_be_added: Wanahitaji kuongezwa + show_on: Onesha + subform_need_to_be_added: Zinahitaji kuongezwa subform_need_to_be_added_single: Hii inahitaji kuongezwa - subform_not_found: Hapana %{subform_name} kupatikana + subform_not_found: ' %{subform_name}haikuonekana' title: Kichwa cha Habari cha Fomu translations: - edit: Hariri tafsiri - edit_form_group: Hariri Utafutaji Fomu ya Kikundi - manage: Simamia / dhibiti tafsiri - no_changes_message: 'Hukufanya mabadiliko ya tafsiri ' - note: 'Kumbuka:' - note_form_group: 'Ili kuongeza tafsiri kwa kikundi cha fomu utahitaji kuhariri tafsiri ya kuangalia kikundi ' + edit: Rekebisha tafsiri + edit_form_group: Rekebisha kundi la fomu linaloonekana + manage: Shughulikia tafsiri + no_changes_message: 'Hukufanya mabadiliko yoyote ya tafsiri ' + note: 'Zingatia' + note_form_group: 'Ili kuongeza tafsiri kwa kundi la fomu, utahitaji kurekebisha tafsiri ' select_language: Chagua lugha title: Tafsiri type_label: Aina visibility: 'Kuonekana ' web_app: Programu ya Tovuti + skip_logic: + name: Kuacha Mantiki? + section: + title: Fomu hii inatakiwa kuonekana ikiwa + buttons: + add: Ongeza sharti + conditions: + add: Ongeza sharti + update: Boresha sharti + field_name: Sehemu ya Jina + condition: Sharti + empty: Hakuna sharti lililoongezwa + type: Aina + types: + and: + display_text: Na sharti hili + name: NA + or: + display_text: Au shari hili + name: AU home: - ar: العربية - ar-IQ: العربية (العراقية) - ar-JO: العربية (الأردنية) - ar-LB: العربية (اللبنانية) - ar-SD: العربية (السودانية) - bn: বাংলা - current_time_zone: Saa za eneo la sasa + ar: Kiarabu + ar-IQ: Kiarabu (cha Iraqi) + ar-JO: Kiarabu (cha Jordan) + ar-LB: Kiarabu (Cha Lebanon) + ar-SD: Kiarabu (Cha Sudan) + bn: Kihindi + current_time_zone: Muda wa eneo uliopo dashboard: Dashbodi en: 'Kiingerza ' es: Kihispania - es-GT: Español (Guatemala) - fr: Français - id: Bahasa - km: ភាសាខ្មែរ - ku: کوردی - ku-IQ: کوردی (بادینی) - fa-AF: فارسی (افغانستان) - ps-AF: پښتو (افغانستان) + es-GT: Kihispania + es-ES: Kihispaniola (Spain) + fr: Kifaransa + hu: Kihungaria + id: Kibahasa + km: Thai + ku: Kikurdi + ku-IQ: Kikurdi (cha Badini) + fa-AF: Uajemi (Afghanistan) + ps-AF: Pasto (Afghanistan) sw-KE: Kiswahili (Kenya) sw-TZ: Kiswahili (Tanzania) - ne: नेपाली + ne: Kinepali + om: Ethiopia ya kati + am-ET: Amharik (Ethiopia) + tr: Kituruki label: Nyumbani language: Lugha - manage_system_users: Tukio limeongezwa toleo jipya kwenye historia kwa mafanikio - my: ဗမာစာ - pt: Português - pt-BR: Português (Brasil) - records_need_attention: Rikodi zinahitaji Kushughulikiwa - ru: Русский - so: Af-Soomaali - th: ไทย - users: Dhibiti Watumiaji - view_records: Angalia Rekodi / Kumbukumbu + manage_system_users: 'Simamia Seva kwa Kusawazisha watumiaji ' + my: Kimyanmar + pl: Kipolandi + pt: Kireno + pt-BR: Kireno (cha Brazil) + records_need_attention: Taarifa zinahitaji Umakini + ro: Roman + ru: Kirusi + sk: Slovensina + so: Kisomali + th: Thailand Penisula + uk: Kiyukrain + users: Simamia Watumiaji + view_records: Angalia Kumbukumbu welcome: Karibu kwenye Primero - zh: 中文 + zh: Kichina incident: - associated_case: "Kesi inayohusiana" + code: Namba ya tukio + associated_case: "Shauri Linalohusiana" messages: - creation_success: Rekodi ya tukio imetengenezwa kwa mafanikio - creation_success_queue: Rekodi ya tukio imetengenezwa katika sehemu ya historia - disabled: Tukio limezimwa - update_success: 'Tukio%{record_id} limeongezwa toleo jipya kwa mafanikio' - update_success_queue: 'Tukio%{record_id} limeongezwa toleo jipya kwnye historia kwa mafanikio' + creation_success: Kumbukumbu ya tukio imefanikiwa kutengenezwa kikamilifu + creation_success_queue: 'Kumbukumbu ya tukio imefanikiwa kutengenezwa kikamilifu kunakohusika ' + disabled: Tukio limezuiliwa + update_success: 'Tukio%{record_id}limeboreshwa kikamilifu ' + update_success_queue: 'Tukio%{record_id} limefanikiwa kuboreshwa kikamilifu kunakohusika' violation: - update_and_return: 'Ongeza taarifa na uirejeshe kwa %{association}' - save_and_return: 'Ongeza na Uirudishe kwa %{association}' + associated_violations: "Ukiukwaji uliohusiana" + update_and_return: 'Boresha na rudisha kwa %{association}' + save_and_return: 'Ongeza na rudisha kwa %{association}' pending: Inasubiri Kuthibitishwa - title: Ukiukaji + title: Ukiukwaji types: killing: Mauaji ya Watoto - maiming: Kuiga Watoto - recruitment: Kuajiri na/au matumia ya watoto - sexual_violence: Ubakaji na/au aina nyengine za udhalilishaji wa kijinsia + maiming: Kulemaza Watoto + recruitment: Uajiri na/au kuwatumia watoto + sexual_violence: Ubakaji na aina nyengine za ukatili wa kingono abduction: Utoroshaji/Utekaji nyara - attack_on: Kushambulia skuli na/ au hospitali - military_use: Matumizi ya Kijeshi ya Skuli na/au hospitali - denial_humanitarian_access: Kunyimwa Ufikiaji wa kibiniaadamu kwa watoto + attack_on: Ushambuliaji wa ()skuli na/ au hospitali() + attack_on_hospitals: Ushambuliaji ya Hospitali () + attack_on_schools: Mashambulizi ya skuli () + military_use: Matumizi ya Skuli ()na/au hospitali kwa shughuli za kijeshi() + denial_humanitarian_access: Kunyimwa Ufikiaji wa misaada ya kibiniaadamu kwa watoto incidents: - disable_dialog: Kubonyeza SAWA kutabadilisha hali ya tukio hili kuwa ya walemavu - disable_dialog_title: Kuzima Tukio - disable_success: Tukio limezimwa kwa mafanikio - enable_dialog: Kubonyeza SAWA kutaibadilisha hali ya tukio hili kuwa ni lenye kuwezeshwa - enable_dialog_title: Tukio lililo wezeshwa - enable_success: Tukio limewezeshwa kwa mafanikio - id: Nambari ya Kitambulisho + disable_dialog: Kubonyeza SAWA kutabadilisha hali ya tukio hili lisionekane + disable_dialog_title: Zuia tukio + disable_success: Tukio limezuiwa kikamilifu + enable_dialog: Kubonyeza SAWA kutaibadilisha hali ya tukio hili kuwa ni lenye kuonekana + enable_dialog_title: Wezesha kuonekana tukio + enable_success: Tukio limefanikiwa kuonekana kikamilifu + id: Nambari ya Utambulisho + complete: Inapatikana nje ya mtandao date_of_interview: Tarehe ya Usaili date_of_incident: Tarehe ya Tukio incident_location: Eneo la Tukio - violations: Ukiukaji - export: Kuuza Nje + violations: Ukiukwaji + export: 'kutoa ' label: Matukio filter_by: + filter_category: Kigezo cha Kuchuja boys: Watoto wa Kiume by_date: Kwa Tarehe children: Watoto girls: Watoto wa Kike incident_location: Eneo la Tukio - unaccompanied_separated_status: Hali ya Hifadha / Ulinzi + status: Hali + unaccompanied_separated_status: Hali ya Uhifadhi unknown: Haijuilikani - verification_status: Hali ya uthibitishaji + verification_status: Hali ya uthibitisho violence_type: Aina ya Udhalilishaji - armed_force_group_name: Jina la Kundi cha Jeshi + armed_force_group_party_name: Vikosi vya kijeshi, Makundi au makundi mengine armed_force_group_type: Aina ya Kikundi cha Kijeshi + violations: Ukiukwaji + individual_violations: 'Ukiukwaji wa mtu ' + individual_age: Umri wa mtu + individual_sex: Jinsi + victim_deprived_liberty_security_reasons: Kunyimwa Uhuru + reasons_deprivation_liberty: Ni sababu zipi za kunyimwa uhuru? + victim_facilty_victims_held: Tafadhali chagua mahali gani muhanga( wahanga) waliwekwa + torture_punishment_while_deprivated_liberty: Je, Mtoto (Watoto) waliteswa au walifanyiwa ukatili mwengine usiokuwa wa kibinaadamu au walidhalilishwa au walipewa adhabu wakati waliponyimwa uhuru? + verified_ghn_reported: Ainisha GHN ambayo tukio hilo lilijumuisha + weapon_type: 'Aina ya silaha/ njia au mbinu zilizotumika' + facility_impact: 'Aina na ukubwa wa athari za kimwili' + facility_attack_type: 'Aina ya ukiukwaji inayohusiana na afya au elimu ' + child_role: 'Ni kazi gani ambayo Mtoto(Watoto) walishiriki katika vikosi vya kijeshi/makundi?' + abduction_purpose_single: 'Sababu ya utoroshaji' + military_use_type: 'Aina ya matumizi ya kijeshi' + types_of_aid_disrupted_denial: 'Aina ya msaada/huduma walizonyimwa/walizozuiliwa' + late_verified_violations: Ukiukwaji uliochelewa kuthibitishwa + perpetrator_category: Aina ya muhalifu + record_owner: Mmiliki wa kumbukumbu register_new_incident: Tukio jipya selectable_date_options: date_of_first_report: Tarehe ya Usaili + mrm_date_of_first_report: Tarehe ya taarifa za awali za mwanachama wa CTFMR kamati ya kitaifa ya kupinga udhalilishaji + ctfmr_verified_date: Tarehe ya maamuzi ya uthibitisho kwa CTFMR kamati ya kitaifa ya kupinga udhalilishaji incident_date_derived: Tarehe ya tukio selected_records: '%{select_records} (Ma)tukio yaliyochaguliwa' - selected_all_records: 'Chagua yote%{total_records} Matukio yaliyofanana na swali' - survivor_code: Alama ya Aliyenusurika - show_incident: 'kitambulisho cha tukio%{short_id}' - social_worker: Mfanyakazi wa Kijamii - violence_type: Aina ya Udhalilishaji - type_violence: Aina ya Udhalilishaji + selected_all_records: 'Chagua yote%{total_records} Matukio yanayohusiana na suala hili' + summary_mrm: + label: Muhtasari wa tukio + fields: + children_multiple_violation: + label: Watoto walioathiriwa na udhalilishaji zaidi ya mmoja + summary_of_incident: + label: Muhtasari wa tukio + incident_total_tally: + label: Idadi ya wahanga + boys: Watoto wa kiume + girls: Watoto wa kike + unknown: Haijuilikani + incident_date: + label: Tarehe ya tukio + incident_location: + label: Sehemu ya tukio + incident_description: + label: Idadi ya matukio + incident_update: + label: Nyongeza za taarifa ya tukio + survivor_code: Nambari ya utambulisho wa manusura + show_incident: 'Utambulisho wa tukio%{short_id}' + social_worker: Afisa Ustawi + violation_type: Aina ya Ukiukwaji + violence_type: Aina ya Ukatili + type_violence: Aina ya Ukatili + violation_summary: Muhtasari + sort_by: Panga kwa key_performance_indicators: - label: "Mapigo ya Moyo /KPIs" - case_assessment: "Mgao wa kesi" - case_action_planning: "Mpango wa Utekelezaji wa kesi" - case_action_plan_implementation: "Utekelezaji wa Mpango kazi wa kesi" - case_follow_up: "Ufuatiliaji wa Kesi" - case_closure: "Kufungwa kwa kesi" - feedback: "Mrejesho / Maoni" - other: "Nyengine" + label: "Kipimo /viashiria muhimu vya utendaji" + case_assessment: "Tathmini ya shauri" + case_action_planning: "Mpango wa Utekelezaji wa shauri" + case_action_plan_implementation: "Mpango wa Utekelezaji wa Shauri" + case_follow_up: "Ufuatiliaji wa shauri" + case_closure: "Kufungwa kwa shauri" + feedback: "Mrejesho" + other: "Mengineyo" date_format: "%b %Y" date_range_select: - custom_range: 'Desturi' + custom_range: 'Iliyozoeleka' long_date_format: "Siku/Mwezi/Mwaka" time_periods: - all_time: 'Makati wote' + all_time: 'Muda wote' current_month: "Mwezi huu" last_3_months: "Miezi 3 iliyopita" last_6_months: "Miezi 6 iliyopita" - last_1_year: "Mwaka uliopita /Mwaka jana" + last_1_year: "Mwaka uliopita " 0-3days: "Siku 0 - 3" 4-5days: "Siku 4 - 5" 6-14days: "Siku 6 - 14" @@ -1375,26 +1526,28 @@ sw_TZ: 3-6months: "Miezi 3 - 6" 7-months: "Zaidi ya Miezi 6" helptext: - helptext: "Jifunze kuhusu KPI hizi" + helptext: "Jifunze kuhusu vipimo hivi vya utendaji KPI" number_of_cases: - title: "1. Nambari ya kesi zilizorikodiwa" - reporting_site: "Tovuti ya Kuripoti/Kutoa taarifa" + title: "1. Idadi ya Mashauri yaliyorikodiwa" + reporting_site: "Eneo la kutoa taarifa" helptext: | - Kiashiria kinahesabu ni kesi ngapi mpya zinazofunguliwa kila mwezi katika tovuti inayotoa ripoti. - Tovuti inayotoa ripoti unafahamika kama tovuti ambayo Shirika la Mtumiaji hutoa huduma na pahala ambapo kesi iliripotiwa kwa mtoa huduma. + Kiashiria hichi kinaonesha ni mashauri mangapi mapya yamefunguliwa kwa kila mwezi kwa kila eneo la kutoa taarifa + Eneo la kutoa taarifa linafahamika kama eneo ambalo shirika mtumiaji anatoa huduma na + pale ambapo shauri lilitolewa taarifa kwa mtoa huduma number_of_incidents: - title: "2. Nambari ya matukio yaliyoripotiwa" - reporting_site: "Tovuti ya Kuripoti/Kutoa taarifa" + title: "2. Idadi ya matukio yaliyotolewa taarifa" + reporting_site: "Eneo la kutoa taarifa" helptext: | - Kiashiria hiki kinahesabu idadi ya matukio mepya yaliyofunguliwa kila mwezi katika tovuti ya kuripoti. Tovuti ya kuripoti inafahamika kama tovuti ambayo aShirika la Mtumiaji linatoa huduma na ambapo tukio liliripotiwa kwa mtoa huduma + Kiashiria hichi kinaonesha ni mashauri mangapi mapya yamefunguliwa kwa kila mwezi kwa kila eneo la kutoa taarifa + Eneo la kutoa taarifa linafahamika kama eneo ambalo shirika mtumiaji anatoa huduma na + pale ambapo shauri lilitolewa taarifa kwa mtoa huduma reporting_delay: - title: "3. Kuchelewa kuripoti" + title: "3. Kuchelewa kutoa taarifa" delay: "Kuchelewa " total_incidents: "Jumla ya Matukio" - helptext: | - Kiashiria hiki huhesabu na kuainisha idadi ya siku ambazo zimepita kati ya aliyenusurika / muathirika alipofanyiwa Udhalilishaji wa Kijinsia na siku ambayo muathirika aliripoti kwa mara ya kwanza kwa mtoa huduma. Inahesabiwa kulingana na lini tukio liliripotiwa kwa mara ya kwanza katika Shirika la Mtumiaji. Data / Taarifa huainishwa kutokana na urefu wa muda (siku 0-3; siku 4-5; siku 6-14; siku 15-30; Zaidi ya ya mwezi mmoja; Zaidi ya miezi mitatu) + helptext: "Kiashiria hichi huhesabu na kuainisha idadi ya siku ambazo zimepita pale ambapo\nManusura alienusurika na udhalilishaji wa kijinsia na pale manusura alipotoa taarifa ya mwanzo kwa taasisi mtumiaji. ni\n Imehesabiwa kulingana na lini tukio lilitolewa taarifa mwanzo kwa taasisi mtumiaji.\nTaarifa zimegawiwa kulingana na urefu wa muda (siku 0-3; siku 4-5; siku 6-14; siku 15-30; Zaidi \nya mwezi mmoja; Zaidi ya miezi mitatu)\n" service_access_delay: - title: "Ucheleweshaji wa Upatikanaji wa Huduma" + title: "kuchelewa kwa upatikanaji huduma" delay: "Kuchelewa" total_incidents: "Jumla ya Matukio" assessment_status: @@ -1402,91 +1555,86 @@ sw_TZ: completed: "Imekamilika" completed_supervisor_approved: "Imekamilika na Kuthibitishwa na Muangalizi" helptext: | - Kiashiria hiki kinahesabu uwiano wa kesi hai /zinazoendelea ambazo fomu zao za tathmini zimejazwa / zimekamilishwa. Tathmini inachukuliwa kuwa imekamilika ikiwa maeneo yote ya lazima katika fomu ya Tathmini ya Muathirika yatakuwa yamekamilika + Kiashiria hichi kinahesabu uwiano wa mashauri yaliokuwa hai ambayo yanaendelea kufanyiwa kazi ambapo fomu zake za tathmini zimekamilika. + Tathmini inachukuliwa kuwa imekamilika ikiwa maeneo yote ya lazima katika fomu ya Tathmini ya + Manusura yatakuwa yamekamilika completed_case_safety_plans: - title: "5 Mpango wa Usalama wa Kesi Uliokamilika" - completed: "Mpango wa Usalama wa Kesi Uliokamilika" - helptext: | - Kiashiria hiki kinahesabu uwiano wa kesi hai / zinazoendelea ambazo mpango wa usalama ulionekana nai muhimu kuzingatiwa na ulikamilishwa (mfano, udhalilishaji wa mpenzi wa karibu; hatari ya kujiua / mauaji; ulinzi wa mtoto) Mpango wa usalama huchukuliwa kuwa umekamilika pale ambapo maeneo yote ya lazima katika fomu ya Mpango wa Usalama imekamilishwa. + title: "5 Mipango ya Usalama ya shauri imekamilika" + completed: " Mpango wa Usalama wa shauri umekamilika" + helptext: "Kiashiria hichi kinahesabu uwiano wa mashauri yaliokuwa hai ambayo yanaendelea kufanyiwa kazi ambapo mpango wa usalama ulionekana unafaa \nna umekamilika (kwa mfano ukatili wa walio kwenye mahusiano, hatari ya mauaji, hifadhi ya mtoto).\nMpango wa usalama unazingatiwa kuwa umekamilika sehemu za lazima katika fomu ya mpango wa usalama zimekamilika\n" completed_case_action_plans: - title: "6. Mpango wa Usalama wa Kesi Uliokamilika" - completed: "Mpango wa Usalama wa Kesi Uliokamilika" - label: "Mpango wa Usalama wa Kesi uliokamilika" + title: "6. Mpango kazi wa shauri umekamilika" + completed: "Mpango kazi wa shauri umekamilika" + label: "Mpango wa kazi wa shauri umekamilika" helptext: |+ - Kiashiria hiki kinahesabu uwiano wa kesi hai / zinazoendelea ambapo Mpango wa Utekelezaji wa Kesi ulikamilishwa. Mpango wa Utekelezaji wa kesi huchukuliwa kama umekamiliwa pale ambapo maeneo ya lazima katika fomu ya Mpango wa Utekelezaji umekamilika. + Kiashiria hichi kinahesabu uwiano wa mashauri hai ambapo Mpango wa Utekelezaji wa shauri umekamilika + Mpango wa Utekelezaji wa shauri unazingatiwa kuwa umekamilika ambapo maeneno ya lazima katika fomu ya Mpango wa Utekelezaji umekamilika. completed_supervisor_approved_case_action_plans: - title: "7. Mipango ya Utekelezaji wa Kesi Imepitishwa na Msimamizi" - completed_and_approved: "Mipango ya Utekelezaji wa Kesi Iliyokamilika Imepitishwa na Msimamizi" - helptext: |+ - Kiashiria hiki kinahesabu uwiano wa kesi hai / zinazoendelea na kupitishwa na msimamizi. Mpango wa utekelezaji wa kesi unachukuliwa kama umekamilika pale ambapo maeneo ya lazima katika fomu ya Mpango wa Utekelezaji yamekamilishwa. Mpango wa kesi unachukuliwa kama umepitishwa pale ambapo fanyakazi wa kesi anaomba kuthibitishwa kwa mpango wa kesi na msimamizi anaupitisha mpango wa kesi kwenye jukwaa - - + title: "7. Mipango ya Utekelezaji wa shauri Imethibitishwa na Msimamizi" + completed_and_approved: "Mipango ya Utekelezaji wa shauri Iliyokamilika Imethibitishwa na Msimamizi" + helptext: "Kiashiria hichi kinahesabu uwiano wa mashauri hai ambapo utekelezaji wa mpango wa shauri umekamilika na kuthibitishwa na msimamizi\n Mpango wa utekelezaji wa shauri unazingatiwa kukamilika pale ambapo maeneo ya lazima katika fomu ya Mpango wa Utekelezaji yamekamilishwa. \nMpango wa shauri unazingatiwa kuwa umethibtishwa pale ambapo msimamizi wa shauri anapoomba kuthibitishwa kwa mpango wa shauri na msimamizi anapothibitisha mpango wa shauri katika mfumo\n" services_provided: - title: "8. Huduma Zinazotolewa" + title: "8. Huduma Zilizotolewa" service: "Huduma" - count: "Nyakati Zinazotolewa" + count: "Muda ambao zimetolewa" male: "Mwanamme" female: "Mwanamke" 0-11: "0-11" 12-17: "12-17" '>18': "Zaidi ya 18" - disability: "Ulemavu" - no_disability: "Hakuna Ulemavu" - helptext: | - Kiashiria hiki kinahesabu aina ya/ za huduma (zi)inayotolewa kwa waathirika katika mchakato wa usimamizi wa kesi. Kutokana na huduma inayotolewa, tunakusudia huduma ambayo inatolewa na shirika la mtumiaji ya ndani, na siyo huduma ya rufaa kutoka kwenye huduma nyingine au rufaa. + disability: "Hali ya Ulemavu" + no_disability: "Hakuna hali ya Ulemavu" + helptext: "Kiashiria hichi kinahesabu aina ya huduma (zilizo)iliyotolewa kwa wahanga katika hatua za usimamizi wa shauri. \nhuduma iliyotolewa, tunakusudia huduma ambayo inayotolewa na taasisi mtumiaji, \nna siyo rufaa iliyotolewa au kupokelewa kutoka taasisi nyengine\n" average_referrals: title: "9. Wastani wa Rufaa" - label: "Wastani wa Rufaa kwa Kesi" + label: "Wastani wa Rufaa kwa shauri" helptext: | - Kiashiria hiki kinahesabu idadi ya wastani wa rufaa kwa kila kesi iliyowekewa rekodi (kwa aina zote za huduma) kwa kesi zote, ikiwa kesi inaendelea /iko wazi au imefungwa. Inajumuisha rufaa zilizorikodiwa katika kichupo cha kesi, siyo rufaa zilizofanyika kwa kupitia jukwaa. + Kiashiria hichi kinahesabu wastani wa rufaa kwa kila shauri lililowekewa kumbukumbu (kwa aina zote za huduma) + kwa mashauri yote, ikiwa shauri linaendelea /liko wazi au limefungwa. + kinajumuisha rufaa zilizowekewa kumbukumbu kwenye eneo la shauri, siyo rufaa iliyofanyika kwa kupitia mfumo pekee referrals_per_service: title: "Rufaa kwa kila Huduma" average_followup_meetings_per_case: - title: "10. Wastani wa Vikao vya Ufuatiliaji kwa kila Kesi" - label: "Wastani wa vikao vya ufuatiliaji kwa kila kesi" - helptext: "Kiashiria hiki kinahesabu wastani wa idadi ya vikao vilivyofanyika kwa kila kesi inayoendelea kwa kila mfanyakazi wa kesi kwenye jukwaa.Kikao cha ufuatiliaji ni kikao kati ya mfanyakazi wa kesi na muathirika baada ya mahojiano ya awali \n" + title: "10. Wastani wa Vikao vya Ufuatiliaji kwa kila shauri" + label: "Wastani wa vikao vya ufuatiliaji kwa kila shauri" + helptext: "Kiashiria hichi kinahesabu wastani wa idadi ya vikao vya ufuatiliaji vilivyofanywa kwa kila shauri linaloendelea kwa kila msimamizi wa shauri wa mfumo.\nKikao cha ufuatiliaji ni kikao kati ya msimamizi wa shauri na manusura baada ya mahojiano ya awali \n" time_from_case_open_to_close: - title: "11. Muda Kati ya Kufunguliwa kwa Kesi Mpaka Kufungwa Kwake" + title: "11. Muda Kati ya Kufunguliwa kwa shauri Mpaka Kufungwa Kwake" time: "Wakati" - percent: "Asilimia ya Kesi" - helptext: |+ - Kiashiria hiki kinapima muda gani ambao kesi zinawekwa wazi, ni muda gani mchakato wa usimamizi wa kesi unachukua kutoka ripoti ya awali kwa Shirika la Mtumiaji mpaka kufikia kufungwa kwa kesi. Urefu wa muda unavunjwa vunjwa kwa kutumia muda huu: chini ya mwezi 1; kati ya mwezi 1 na miezi 3, kati ya miezi 3-6; zaidi ya miezi 6 - + percent: "Asilimia ya mashauri" + helptext: "Kiashiria hichi kinapima ni muda gani mashauri yamekuwa wazi, ni muda gani hatua ya usimamizi wa shauri unachukua kutoka taarifa ya awali ilipotolewa kwenye Taasisi Mtumiaji hadi kufungwa kwa shauri. \nUrefu wa muda unagawiwa kwa kutumia mpangilio huu: chini ya mwezi 1; kati ya mwezi 1 na miezi 3, kati ya miezi 3-6; zaidi ya miezi 6\n" case_closure_rate: - title: "I12. dadi ya Kesi Zitakazofungwa" - reporting_site: "Tovuti ya Kuripoti" - helptext: "Kiashiria hiki kinapima idadi yankesi zinazofungwa kila mwezi kwa kila moja ya tovuti ya kuripoti. Tovuti ya kuripoti inafahamika kama tovuti ambayo Shirika la Mtumiaji linatoa huduma na pale ambapo tukio liliripotiwa kwa mtoa huduma. \n" + title: "12. Idadi ya mashauri yatakayofungwa" + reporting_site: "Sehemu ya kutoa taarifa" + helptext: "Kiashiria hichi kinapima idadi ya mashauri yaliyofungwa kwa mwezi kwa kila eneo la kutoa taarifa \nsehemu ya kutoa taarifa inafahamika kama ni sehemu ambalo Taasisi Mtumiaji inatoa huduma na ambapo tukio lilitolewa taarifa kwa mtoa huduma. \n" client_satisfaction_rate: title: "13. Kiwango cha Kuridhika kwa Mteja" label: "Kuridhika kwa Mteja" - invalid: "Hatuwezi kuikokotoa hii kwa sasa" - helptext: |+ - Kiashiria hiki kinapima asilimia ya waathirika waliokamilisha Utafiti wa Mrejesho wa Mteja ambao wameridhika na huduma za usimamizi wa kesi zinazotolewa kwao. Kiashiria hiki kinaongozwa na kukamilishwa kwa fomu ya Maoni ya Mteja au kuhusu Mfumo wa Usimamizi wa Taarifa za Udhalilishaji wa Kijinsia kwa mfanyakazi mwengine ambaye siye mfanyakazi wa kesi aliyeto huduman kwa muathirika - + invalid: "Hatuwezi kuhesabu kwa sasa" + helptext: "Kiashiria hichi kinapima asilimia ya waathirika waliokamilisha Utafiti wa Maoni ya Mteja ambao wameridhika na huduma za usimamizi wa shauri zilizotolewa kwao. \nKiashiria hichi kinaongozwa kwa kukamilishwa kwa fomu ya Maoni ya Mteja inayohusiana na Mfumo wa Usimamizi wa Taarifa za Udhalilishaji wa Kijinsia kutoka kwa mfanyakazi mwengine ambaye si msiamamizi wa shauri aliyetoa huduma kwa manusura\n" supervisor_to_caseworker_ratio: - title: "14. Uwiano wa Msimamizi na Wafanyakazi wa Kesi" - label: "Mfanyakazi wa kesi kwa msimamizi" - helptext: | - Kiashiria hiki ni idadi ya wafanyakazi wa kesi ambao msimamizi anawasimamia ; msimamizi kwa uwiano wa mfanyakazi wa kesi. Kukokotoa huku kunatokana na majukumu ya mfumo yaliyotengwa kwenye jukwaa. + title: "14. Uwiano wa Muangalizi na msimamizi wa shauri" + label: "Wasimamizi wa shauri kwa Muangalizi" + helptext: "Kiashiria hichi ni cha idadi ya wasimamizi wa shauri ambao mwangalizi anawaangalia; uwiano wa mwangalizi kwa msimamizi wa shauri. \nHesabu hii imejikita katika majukumu yalioainishwa katika mfumo.\n" case_load: - title: "15. Wingi wa kesi" - case_load: "Wingi / Mzigo wa kesi" - percent: "asilimia ya wafanyakazi wa kesi na mzigo / wingi wa kesi" - 10cases: "<10 Kesi" - 20cases: "11-20 Kesi " - 21-30cases: "21-30 Kesi" - 30cases: "Zaidi ya 30 Kesi" - helptext: "Kiashiria hiki kinapima wastani wa uzito/ wingi wa kesi kwa kila mfanyakazi wa kesi aliyewezeshwa kwa kesi zinazoendelea.Uwiano wa kesi kwa wafanyakazi wa kesi hugawanywa kwa kuzingatia mgawanyo huu: chini ya kesi kumi zilizoko wazi / zinazoendelea, kati ya kesi 10-20, kati ya kesi 21-30, zaidi ya kesi 30 zinazoendelea \n" + title: "15. Wingi wa mashauri" + case_load: "Wingi wa mashauri" + percent: "asilimia ya wasimamizi wa mashauri kwa wingi wa mashauri " + 10cases: "< chini ya mashauri 10 " + 20cases: "Mashauri 11-20 " + 21-30cases: "Mashauri 21-30 " + 30cases: "Zaidi ya mashauri 30 " + helptext: "Kiashiria hichi kinapima wastani wa wingi wa mashauri kwa kila msimamizi wa shauri aliepewa jukumu kwa mashauri yanayoendelea. Uwiano wa mashauri kwa wasimamizi umegawanywa kwa kuzingatia mgawanyo ufuatao: chini ya mashauri 10 yanayoendelea, kati ya mashauri 10-20, kati ya mashauri 21-30, zaidi ya mashauri 30 yanayoendelea \n" date_range_dialog: - title: "Tarehe Maalum" - description: "Mabadiliko yakitekelezwa,data / taarifa itachaguliwa kati ya tarehe mbili zilizopo hapo chini" - apply: 'Kuomba' - from: 'Kutoka ' - to: 'Kwa' + title: "Mpangilio wa tarehe uliozoeleka" + description: "Mabadiliko yakitekelezwa, taarifa itachaguliwa kati ya tarehe mbili zilizopo hapo chini" + apply: 'Tumia' + from: 'Kuanzia' + to: 'Mpaka' aria-labels: - from: "Data / Taarifa itachaguliwa baada ya tarehe hii" - to: "Data / Taarifa itachaguliwa kabla ya tarehe hii" + from: "Taarifa itachaguliwa baada ya tarehe hii" + to: "Taarifa itachaguliwa kabla ya tarehe hii" location: base_types: camp: Kambi @@ -1494,1042 +1642,1280 @@ sw_TZ: city: Jiji community: Jamii country: Nchi - county: Kata + county: Kaunti district: Wilaya governorate: Mkoa locality: Eneo - other: Nyingine + other: Mengine province: Jimbo region: Mkoa - site: Tovuti - state: Jimbo /Nchi + site: Eneo + state: Taifa sub-district: Wilaya ndogo village: Kijiji - zone: 'Eneo / Ukanda ' - association: Muungano + zone: 'Ukanda ' + association: Uhusiano division: Mgawanyiko central_warehouse: Ghala kuu warehouse: Ghala buyingstation: Kituo cha Manunuzi + township: Mjini + municipality: Manispaa + autonomous_region: Mkoa unaojitegemea + parish: Parokia + cercle: Wilaya + sub-county: Kaunti ndogo label: Eneo name: Jina - code: Alama / Kanuni + code: Namba admin_level: Ngazi ya Utawala type: Aina - hierarchy: 'Uongozi ' - import_title: Eneo la Kuagiza - message: 'Tafadhali chagua faili la CSV kwa kupakia. Faili hili linatakiwa kutumia UTF-8 kwa usimbaji na inajumuisha HXL lebo za reli kwenye kichwa cha pili cha kila safu. ' - no_location: 'Tafadhali ingiza Eneo kabla ya kutengeneza Akaunti za watumiaji ' + hierarchy: Mpangilio + import_title: Ingiza katika eneo + message: 'Tafadhali chagua faili la CSV kwa kupakia. Faili hili lazima litumie mfumo wa UTF-8 na ijumuishe HXL kwenye kichwa cha pili cha kila safu. ' + no_location: 'Tafadhali ingiza eneo kabla ya kutengeneza Akaunti za watumiaji ' enable_title: Wezesha Eneo - enable_text: Je, una hakika? Ikiwa utayawezesha maeneo yaliyochagliwa, yatajitokeza / yataonekana kama chaguo katika Uga wa eneo - disable_title: Zima Eneo - disable_text: Je, unahakika? Ikiwa utayazima Maeneo yaliyochaguliwa, hayataonekana tena kama chaguo katika Eneo + enable_text: Je, una hakika? Ikiwa utayawezesha maeneo yaliyochaguliwa, yatajitokeza / yataonekana katika sehemu za eneo la chaguo + disable_title: Zuia Eneo + disable_text: Je, unahakika? Ikiwa utayazuia Maeneo yaliyochaguliwa, hayataonekana tena kama sehemu katika Eneo la chaguo logger: actions: - _approved: Kupitishwa - _rejected: Iliyokataliwa / Kukuataliwa - _requested: Aliomba / Iliombwa + _approved: Kuthibitishwa + _rejected: Iliyokataliwa + _requested: ' Iliyoombwa' add_note: Ongeza maelezo - assign: Kabidhi - assign_to: 'Kabidhi kwa ' - attach: Funganisha - bulk_assign: Kugawa kwa Wingi + assign: Kabidhi kazi + assign_to: 'Kabidhi kazi kwa ' + attach: Ambatisha + bulk_assign: Kazi kwa pamoja bulk_create: 'Tengeneza kwa wingi ' - bulk_index: Vielezo vilivyowekwa pamoja - case_plan_approved: Mpango wa kesi umepitishwa - case_plan_rejected: Mpango wa kesi umekataliwa - case_plan_requested: Mpango wa Kesi umekataliwa - close: Funga / Karibu - create: Tengeneza / Unda - create_bulk: Tengeneza kwa wngi + bulk_index: Vielezo vingi + case_plan_approved: Mpango wa shauri umethibitishwa + case_plan_rejected: Mpango wa shauri umekataliwa + case_plan_requested: Mpango wa shauri uliombwa + close: 'Funga ' + create: 'Tengeneza ' + create_bulk: Tengeneza kwa wingi delete: Futa - destroy: Kuharibu + destroy: Haribu detach: Tenganisha - enable_disable_record: 'Wezesha kuzima rekadi ' - export: Kuuza nje - flag: Bendera - import: Kuagiza - incident_details_from_case: Maelezo ya tukio kutoka kwenye kesi + enable_disable_record: Wezesha kumbukumbu iliozuiliwa + export: Kutoa + flag: Kibendera + import: Kuingiza + incident_details_from_case: Maelezo ya tukio kutoka kwenye shauri index: Kielezo list: Orodha login: 'Ingia ' - password_reset: Kuweka upya nenosiri - password_reset_request: Ombi la kuweka upya neno siri - refer: Rejea - refer_accepted: Rejeleo Limekubalika - refer_done: Rejea imefanyika - refer_rejected: Rejea imekataliwa - refer_revoke: Rejea imebatilishwa - refer_to: Rejea kwa + password_reset: Kutengeneza upya neno la siri + password_reset_request: Ombi la kutengeneza upya neno la siri + refer: Rufaa + refer_accepted: Rufaa imekubalika + refer_done: Rufaa imefanyika + refer_rejected: Rufaa imekataliwa + refer_revoke: Rufaa imebatilishwa + refer_to: Rufaa kwa reopen: Fungua upya - services_section_from_case: Sehemu ya huduma kutoka kwenye kesi - show: Onyesha - show_alerts: Onyesha tahadhari / arifa - traces: Athari + services_section_from_case: Sehemu ya huduma kutoka kwenye shauri + show: Onesha + show_alerts: 'Onesha tahadhari ' + traces: Kutafuta transfer: Uhamisho transfer_accepted: Uhamisho umekubaliwa transfer_rejected: Uhamisho umekataliwa transfer_request: Ombi la uhamisho transfer_to: Uhamisho kwenda - unflag: Ondoa bendera - update: Ongeza toleo jipya - user_password_reset_request: Ombi la kuweka upya nenosiri la mtumiaji + unflag: Ondoa kibendera + update: Boresha + user_password_reset_request: Ombi la kutengeneza upya neno la siri la mtumiaji webhook: Mtandao approve_form: action_plan: Fomu ya Mpango kazi - bia: Fomu ya B/A - case_plan: Fomu ya Mpango wa Kesi - closure: Fomu ya kufungwa + bia: Fomu ya BIA + case_plan: Fomu ya Mpango wa shauri + closure: Fomu ya kufungia 'false': Kukataa - gbv_closure: 'Fomu ya Kufungwa kwa Udhalilishaji wa Kijinsia ' - 'true': Kuidhinishwa + gbv_closure: 'Kufungwa kwa fomu ya Udhalilishaji wa Kijinsia ' + 'true': Kuidhinisha assessment_approved: "%{approval_label}Imeidhinishwa kwa " assessment_requested: "%{approval_label}imeombwa kwa" bulk_index: Orodhesha vyote by_user: Kwa mtumiaji case_plan_approved: "%{approval_label}Imeidhinishwa kwa " case_plan_requested: "%{approval_label}Imeombwa kwa" - close: Funga / Karibu + close: Funga closure_approved: "%{approval_label}Imeidhinishwa kwa" closure_requested: "%{approval_label}Imeombwa kwa" - consent_count: Hesabu ya Idhini + consent_count: Idadi ya ridhaa copy: Kunakili - create: Kuunda / Kutengeneza / Kutayarisha - create_subform: Kutayarisha Fomu ndogo + create: 'Kutengeneza ' + create_subform: Kutengeneza Fomu ndogo destroy: Kufuta - edit: Kuhariri - enable_disable_record: 'Kuwezesha / Kulemaza ' - export: 'Kusafirisha data kwa ' - flag: Kuashiria /Kuripoti - flag_records: Kuashiria / Kuripoti - graph_data: Kuangalia data / taarifa ya mchoro + edit: Kurekebisha + enable_disable_record: 'Kuwezesha/Kuzuia ' + export: 'Kuzitoa taarifa kwa ' + flag: Kuweka kibendera + flag_records: Kuweka kibendera + graph_data: Kuangalia taarifa ya mchoro hide_name: protect: Ficha Jina - view: Angalia / Tazama Jina - index: Kuorodhesha Rekodi + view: Angalia Jina + index: Kuorodhesha kumbukumbu list: Orodha login: Ingia - logout: Toka / Ondoka - lookups_for_field: Utafutaji wa eneo + logout: Toka + lookups_for_field: Tafuta sehemu mark_for_mobile: - 'false': Ondoa alama kwenye simu ya mkononi - 'true': ' Alama kwa simu ya mkononi' - match_record: Rekodi inayolingana - permitted_field_list: Orodha ya sehemu / eneo / uga inayokubaliwa - quick_view: Kutazama Mtazamo wa Haraka - reassign: Kugawa + 'false': Ondoa alama simu ya mkononi + 'true': ' Weka alama ya simu ya mkononi' + match_record: Kumbukumbu zinazolingana + permitted_field_list: Orodha ya sehemu iliyoruhusiwa + quick_view: Kuangalia kwa Mtazamo wa Haraka + reassign: Kugawa kazi resources: - audit_log: 'Daftari la ukaguzi ' + audit_log: 'Ukurasa wa ukaguzi ' user: Mtumiaji - agency: Shirika + agency: Taasisi user_group: Kundi la watumiaji child: Mtoto alert: Tahadhari form_section: Fomu - lookup: Tafuta / Tazama juu + lookup: 'Tafuta ' system_settings: Mpangilio wa mfumo permission: Ruhusa - dashboard: Dashbodi - report: Ripoti - bulk_export: Mauzo ya nje kwa wingi - saved_search: Utafutaji uliohifadhiwa + dashboard: Dashibodi + report: Taarifa + bulk_export: Kutoa kwa wingi + saved_search: Tafuta ulichokihifadhi role: Jukumu incident: Tuklio location: Eneo - primero_configuration: Usandi wa Primero + primero_configuration: Usanidi wa Primero code_of_conduct: Kanuni za maadili task: Kazi record_state: - 'false': Kulemaza + 'false': Kuzuia 'true': Kuwezesha - refer: Rejea - refer_to: Tafuta Mpokeaji Rufaa - referral: Akimaanisha - relinquish_referral: Kuachilia rufaa Kufanywa + refer: Rufaa + refer_to: Tafuta Mpokeaji wa Rufaa + referral: Kufanya rufaa + relinquish_referral: Achana na rufaa zilizokamilika reopen: Fungua upya reopen_case: 'Kufungua upya ' request_approval: - action_plan: Kuomba Kibali cha fomu ya Mpango wa Utekelezaji - bia: Kuomba Kibali cha fomu ya B/A - case_plan: Kuomba Kibali cha fomu ya Mpango wa Kesi - closure: Kuomba Kibali cha fomu ya Kufungwa - gbv_closure: Kuomba Kibali cha fomu ya Kufungwa Udhalilishaji wa Kijinsia - request_transfer: Kupeleka Ombi la Uhamisho - request_transfer_view: Kuangalia Uhamisho wa Ombi + action_plan: Ommbi la uthibiti kwa fomu ya mpango wa utekelezaji + bia: Ombi la uthibitishaji wa fomu ya BIA + case_plan: Ombi la uthibitisho kwa ajili ya fomu ya mpango wa shauri + closure: Ombi la uthibitisho kwa ufungaji wa fomu + gbv_closure: Ombi la uthibitisho kwa ufungaji wa fomu ya Udhalilishaji wa Kijinsia + request_transfer: 'Peleka ombi la kuhamisha ' + request_transfer_view: 'Kuangalia ombi la Uhamisho ' save_subform: Kuihifadhi Fomu ndogo search: Utafutaji wa API show: Kutazama - show_alerts: Kuangalia tahadhari za + show_alerts: Kuangalia tahadhari kwa to: Kwa to_user: Kwa mtumiaji transfer: Kuhamisha transfer_status: Accepted: Uhamisho Uliokubalika Rejected: Uhamisho Uliokataliwa - unflag: Kuondoa bendera - update: Kuingiza toleo jipya + unflag: Kuondoa kibendera + update: Uboreshaji login: label: Ingia password: - label: Nenosiri + label: Neno la siri password_confirmation: - label: Kuthibitisha Nenosiri + label: Kuthibitisha Neno la siri password_match: - label: Nenosiri Lazima Lilingane + label: Neno la siri Lazima Lilingane provider_title: Na %{provider} title: 'Ingia ' username: Jina la Mtumiaji - password_reset_modal: Weka upya Nenosiri - password_reset_modal_text: Primero itakutumia kiungo cha kuweka upya nenosiri katika barua pepe + password_reset_modal: Unda upya Neno la siri + password_reset_modal_text: Primero itatuma kiunganishi cha kuunda tena neno la siri katika barua pepe yako password_reset_email: Baruapepe - forgot_password: Umesahau nenosiri lako? + forgot_password: Je, Umesahau neno lako la siri? email: label: Baruapepe lookup: create: Utafutaji Mpya enabled_label: Imewezeshwa? - english_label: Jaribio la Kiingereza - label: Tafuta / Angalia juu + english_label: Maelezo ya Kiingereza + label: 'Tafuta ' language_label: Lugha messages: - cannot_create: Utafutaji haukuweza kutengenezwa /kuundwa - correct_errors: 'Tafadhali rekebisha makosa yafuatayo na uwasilishe tena' - created: Utafutaji uliundwa / ulitengezwa kwa mafanikio - updated: Utafutaji uliongezwa toleo jipya kwa mafanikio + cannot_create: Utafutaji haukuweza kutengenezwa + correct_errors: 'Tafadhali rekebisha makosa yafuatayo na uwasilishe tena:' + created: Utafutaji ulitengenezwa kikamilifu + updated: Utafutaji uliboreshwa kikamilifu name: Jina no_options: Utafutaji huu kwa sasa hauna chaguo - translation_label: Maandishi ya Tafsiri + translation_label: Maelezo yaliotafsiriwa values: Chaguo + locked_alert_message: Utafutaji huu umefungwa managed_reports: + generated_on: Yanayotokana na label: Utambuzi total: Jumla + violations_total: Ukiukwaji filter_by: date: Tarehe - verification_status: Hali ya uthibitishaji + verification_status: Hali ya uthibitisho + violation_type: Aina ya Ukiukwaji + status: Hali + status_open: Wazi + status_closed: Imefungwa + user_group: Kikundi cha watumiaji + agency: Taasisi + by: Kwa + workflow: Hatua ya mtiririko wa kazi + cp_incident_violence_type: Aina ya ukatili + referral_transfer_status: Hali ya rufaa/uhamisho + status_options: + open: Wazi + closed: Imefungwa + by_options: + created_by_groups: Kikundi cha watumiaji cha watengenezaji kumbukumbu + owned_by_groups: Kikundi cha watumiaji wanaomiliki kumbukumbu + created_organization: Taasisi ya watengenezaji wa kumbukumbu + owned_by_agency_id: Taasisi ya wamiliki wa kumbukumbu + referral_transfer_status_options: + in_progress: Inasubiri + accepted: Imekubaliwa + rejected: Imekataliwa + done: Imeshafanyika date_range: - month: Month - quarter: 'Ribo ' + month: Mwezi + quarter: Robo year: Mwaka + week: Wiki date_range_options: this_quarter: Robo hii last_quarter: Robo iliyopita this_month: Mwezi huu last_month: Mwezi Uliopita + this_week: Wiki hii + last_week: Wiki iliopita this_year: Mwaka Huu last_year: Mwaka Jana - custom: Desturi - no_data: Hakuna data iliyopo kwa maarifa haya - no_data_table: Hakuna data ya Jadweli iliyopo kwa maarifa haya + custom: Iliyozoeleka + no_data: Hakuna taarifa iliyopo kwenye utafutaji huu + no_data_table: Hakuna Jadweli la taarifa iliyopo kwa utafutaji huu + incomplete_data: Taarifa haikukamilika + individual_children: + name: Watoto + reports: + individual_children: Watoto + sub_reports: + individual_age: Watoto kwa umri + individual_violation_type: Watoto kwa aina ya ukatili + individual_region: Watoto kwa mkoa + individual_perpetrator: Watoto kwa uhalifu + ghn_report: + name: Maelezo ya ripoti ya ulimwengu + reports: + ghn_report: Maelezo ya ripoti ya ulimwengu + sub_reports: + verified_information: Taarifa iliothibitishwa- wahanga + late_verification: Uhibitisho uliochelewa - wahanga + unverified_information: Hakuna uthibitisho wa taarifa- wahanga + verified_information_violations: Uthibibitisho wa taarifa- za wahanga + late_verification_violations: Uthibitisho uliochelewa- Ukiukwaji + unverified_information_violations: Hakuna uthibitisho wa taarifa- Ukiukwaji + killing: Mauaji ya watoto + maiming: Kulemaza watoto + recruitment: Ajira za na/au kuwatumia watoto + sexual_violence: Ubakaji na aina nyengine za ukatili wa kingono + rape: Ubakaji na aina nyengine za ukatili wa kingono + abduction: Utoroshaji + attack_on_hospitals: Mashambulizi kwenye hospitali () + attack_on_schools: Mashambulizi skuli () + military_use: Mashambulizi ya kijeshi skuli () na hopitali () + denial_humanitarian_access: Kunyimwa ufikiaji wa misaada ya kibinaadamu kwa watoto + multiple_violations: 'Watoto waioathiriwa na aina ya ukatili zaidi ya mmoja ' + detention: Kizuizini + boys: Watoto wa kiume + girls: Watoto wa kike + total: Jumla + unknown: Haijuilikani + associated_violations: Ukiukwaji unaohusiana violations: - name: Ukiukaji + name: Ukiukwaji filter_options: incident_date: Tarehe ya Tukio - date_of_report: Tarehe ya Repoti + date_of_report: Tarehe ya kutolewa taarifa ctfmr_verified_date: Tarehe ya Uthibitisho + verified: Imethibitishwa reports: killing: Mauaji ya Watoto - maiming: Kuiga Watoto - recruitment: Kuwaajiri na/au kuwatumia watoto - sexual_violence: Ubakaji na/au aina nyingine za udhalilishaji wa kijinsia - abduction: Kutorosha /Kuteka Nyara - attack_on: Mashambulizi ya skuli na/au hospitali - military_use: Matumizi ya kijeshi ya skuli na/au hospitali - denial_humanitarian_access: Kunyimwa ufikiaji wa kibinaadamu kwa watoto + maiming: Kuwalemaza Watoto + recruitment: Ajira za na/au kuwatumia watoto + sexual_violence: Ubakaji na aina nyengine za ukatili wa kingono + rape: Ubakaji na aina nyengine za ukatili wa kingono + abduction: Kutorosha + attack_on_hospitals: Mashambulizi kwenye hospitali () + attack_on_schools: Mashambulizi kwenye skuli () + military_use: Mashambulizi ya kijeshi skuli () na hopitali () + denial_humanitarian_access: Kunyimwa ufikiaji wa misaada ya kibinaadamu kwa watoto + detention: Kuwekwa kizuizini sub_reports: - combined: Ukiukaji + children: Watoto + combined: Ukiukwaji + denial_humanitarian_access: Kunyimwa kwa misaada ya kibinaadamu + denial_type: Aina ya huduma walizonyimwa detention_detained: Kubaki Kizuizini - detention_released: Kutolewa /Kuachiwa + detention_released: Kuachiwa huru perpetrators: Idadi ya Watoto kwa Wahalifu + perpetrators_denial: Idadi ya ukatili kwa Wahalifu + perpetrator_detention: Idadi ya Watoto kwa Wahalifu + perpetrators_incidents: Idadi ya matukio kwa Wahalifu + reporting_location_incidents: Idadi ya matukio kwa mkoa reporting_location: Idadi ya Watoto kwa Mkoa + reporting_location_detention: Idadi ya Watoto kwa mkoa + reporting_location_denial: Idadi ya ukatili kwa mkoa attack_type: Idadi ya Watoto kwa Aina ya Mashambulizi boys: Watoto wa Kiume girls: Watoto wa Kike unknown: Haijuilikani total: Jumla + violation: Ukiukwaji + sexual_violence_type: Aina ya (za) udhalilishaji wa kingono + detention_status: Hali ya watoto walioko kizuizini + type_of_use: Aina ya matumizi + factors_of_recruitment: Sababu ya uajiri + still_being_held: Bado kashikiliwa + released: 'Ameachiwa huru' + escaped: 'Alitoroka' + abduction_reasons: Sababu ya kutoroshwa + abducted_status: Hali ya aliyetoroshwa + facility_attack_type: Aina ya ukatili + received_response: Watoto waliohudumiwa + male: Wanaume + female: Wanawake + military_use_type_of_use: Idadi ya ukatili kwa aina ya matumizi gbv_statistics: name: Takwimu za Udhalilishaji wa Kijinsia filter_options: date_of_first_report: Tarehe ya Mahojiano incident_date: Tarehe ya Tukio reports: - incidents: Matukio perpetrators: Wahalifu + survivors: Manusura + referrals: Rufaa + sub_reports: + service_safehouse_referral: Nyumba salama/Rufaa kwa nyumba salama + service_medical_referral: 'Afya/ Rufaa ya Matibabu ' + service_psycho_referral: Huduma ya saikologia ya kijamii/huduma ya unasihi + service_legal_referral: Huduma za msaada wa kisheria + service_police_referral: Polisi au aina nyengine za huduma za kiusalama + service_livelihoods_referral: Huduma za kujikimu + service_protection_referral: Huduma za hifadhi ya mtoto + survivors_disability_type: Wenye hali ulemavu + workflow_report: + name: Mtiririko wa kazi + reports: + cases_workflow: Mtiririko wa kazi- mashauri + incidents_workflow: Mtiririko wa kazi- matukio + filter_options: + registration_date: Tarehe ya usajili + sub_reports: + case_workflow_by_sex_and_age: Jumla ya idadi ya mashauri kwa jinsi na umri + incident_workflow_by_sex_and_age: Jumla ya idadi ya matukio kwa jinsi na umri + referrals_transfers_report: + name: Rufaa na uhamisho + reports: + total_referrals: Rufaa + total_transfers: Uhamisho sub_reports: - combined: Matukio - total: Idadi ya Matukio ya Udhalilishaji wa Kijinsia Yaliyoripotiwa - gbv_sexual_violence: Idadi ya Matukio ya Ukatili wa Kijinsia Yaliyotolewa Taarifa - gbv_previous_incidents: Idadi ya Matukio Yaliyoripotiwa na Walioathirika na Matukio ya Ukatili wa Kijinsia hapo Kabla - gbv_sexual_violence_type: Aina ya Tukio - incident_timeofday: Wakati wa Siku ya Tukio - elapsed_reporting_time: Muda kati ya Tukio na Tarehe liliporipotiwa - elapsed_reporting_time_rape: Matukeo ya Ubakaji, Muda Uliopita kati ya Tukio na TareheLlililoripotiwa - incident_location_type: Eneo la Tukio - number_of_perpetrators: Idadi ya Wahusika Wakuu - perpetrator_relationship: Uhusiano kati ya Wahalifu Wakuu na Muhanga / Aliyenusurika - perpetrator_age_group: Kikundi cha Umri wa Anayedaiwa kuwa Muhisika Mkuu - perpetrator_occupation: Kazi ya Anayetuhumiwa kuwa Muhusika Mkuu + total_transfers_by_user_groups: Jumla ya uhamisho + total_referrals_by_user_groups: Jumla ya rufaa + filter_options: + registration_date: Tarehe ya usajili + violence_type_report: + name: Aina ya ukatili + reports: + cases_violence_type: Aina ya ukatili- mashauri + incidents_violence_type: Aina ya ukatili- matukio + filter_options: + registration_date: Tarehe ya usajili + sub_reports: + case_violence_type_by_sex_and_age: Jumla ya idadi ya mashauri kwa jinsi na umri + incident_violence_type_by_sex_and_age: Jumla ya idadi ya matukio kwa jinsi na umri + success_message: Faili la kutolewa limetengenezwa kikamilifu messages: alert_items: Unavyo %{items}vitu vya kuzingatia alerts_for: - approval: Idhini inasubiri kwa%{form_section_name} - field_change: '%{form_section_name}iliingizwa toleo jipya saa%{alert_time}' - transfer_request: Ombi Jipya la Uhamisho Lilifanyiwa %{date}na%{user}kwenye%{agency} - duplicate_field: Kesi Nyingine kwenye mfumo inayo %{field_name} kama hii - cannot_edit: Huwezi kuihariri hii - confirmation_message: Kubonyeza SAWA kutaondoa mabadiliko yasiyohifadhiwa na kurudi kwenye muonekano wa orodha. Bonyeza ghairi ili kurudi kwenye rekodi - confirmation_message_subform: Kubonyeza OK /sawa kutayatupa mabadiliko yoyote ambayo hayajahifadhiwa katika kipengele hiki. Bonyeza ghairi ili kuendelea kufanya mabadiliko. - dashboard_offline: 'Uko nje ya mtandao / Hujaunganishwa. Dashbodi itafanya kazi kikamilifu utakaporejea kwenye mtandao / Utakapounganishwa tena. ' + approval: Uthibitisho unasubiri kwa%{form_section_name} + field_change: '%{form_section_name}liliboreshwa katika%{alert_time}' + transfer_request: Ombi Jipya la Uhamisho Lilifanywa tarehe%{date}na%{user}kwenye%{agency} + duplicate_field: Shauri jengine katika mfumo linalingana na jina %{field_name} kama hili + cannot_edit: Huwezi kurekebisha hili + confirmation_message: Kubonyeza SAWA kutaondoa mabadiliko yasiyohifadhiwa na kurudi kwenye muonekano wa orodha. Bonyeza ghairi ili kurudi kwenye taarifa + confirmation_message_subform: Kubonyeza SAWA kutaondoa mabadiliko yasiyohifadhiwa na kurudi kwenye muonekano wa orodha. Bonyeza ghairi ili kuendelea kufanya mabadiliko + dashboard_offline: Uko nje ya mtandao. Dashibodi itafanya kazi kikamilifu utakaporejea kwenye mtandao. field_name_on_form_name: '%{field_name}eneo kwenye%{form_name} fomu' - logout_confirmation: Je, unataka kuendelea na kikao chako? - logout_offline_warning: Unahakika unataka kutoka / kuondoka? Ukitoka hutaweza kuingia tena mpaka uwe mtandaoni tena. Mabadiliko yoyote uliyoyafanya ukiwa nje ya mtandao yatapotea. - logout_warning: Utaondolewa baada ya dakika 5 + logout_confirmation: Je, unataka kuendelea na kipindi chako? + logout_offline_warning: Je, Una uhakika unataka kutoka? Ukitoka hutaweza kuingia tena mpaka utakaporudi tena mtandaoni. Mabadiliko yoyote uliyoyafanya ukiwa nje ya mtandao yatapotea. + logout_warning: Utatolewa baada ya dakika 5 logout_dialog_header: Nje ya mtandao. Toka - logout_confirmation_title: Uthibitisho wa kutoka / kuondoka - logout_confirmation_text: Je, unahakika unataka kutoka nje? - no_changes: Hukufanya mabadiliko yoytote ya eneo / uwanja + logout_confirmation_title: Uthibitisho wa kutoka + logout_confirmation_text: Je, unahakika unataka kutoka? + no_changes: Hukufanya mabadiliko ya sehemu yoyote not_available: Haipatikani record_list: column_header_tooltip: Panga kwa%{column} of: 'ya ' - no_match: Samahani, hakuna rekodi inayolingana iliyopatikana - rows_per_page: Safu kwa kila ukurasa + no_match: Samahani, hakuna taarifa inayolingana iliyopatikana + rows_per_page: Safu mlalo kwa kila ukurasa sort: Panga navigation: - bulk_exports: Kuuza nje - cases: Kesi + bulk_exports: Toa + cases: Mashauri home: Nyumbani - key_performance_indicators: Mapigo ya moyo / KPls + key_performance_indicators: Kipimo /viashiria muhimu vya utendaji incidents: Matukio - logout: Toka nje - reports: 'Ripoti / Kumbukumbu ' + logout: 'Toka ' + reports: 'Kumbukumbu ' insights: Utambuzi search: Tafuta settings: Mipangilio support: Msaada support_menu: - contact_information: Maelezo / Taarifa ya Mawasiliano + contact_information: Taarifa za Mawasiliano code_of_conduct: Kanuni za Maadili terms_of_use: Masharti ya Matumizi - system_information: Habari ya Mfumo + system_information: Taarifa kuhusu Mfumo + resync: 'Mabadiliko nje ya mtandao yasiyowasilishwa ' tasks: kazi - tracing_request: Ombi la Kufuatilia - activity_log: Logi la Vitendo /Shughuli + tracing_request: Ombi la Utafutaji + activity_log: Ukurasa wa Shughuli registry_records: Usajili + families: Familia notes: - note_success: Umefaulu kuongeza dokezo + note_success: Maelezo yameongezwa kikamilifu permissions: label: Ruhusa permission: - All: Zote / Wote / Yote + All: Zote add_note: 'Ongeza Maelezo ' - admin_only: Hakuna kumbukumbu - Ni kwa kazi / matumizi ya Msimamizi pekee - administrator_read: Soma Msimamizi - agency: Shirika - agency_read: Shirika Kusoma - all: Fikia rekodi / kumbukumbu zote au watumiaji + admin_only: Hakuna kumbukumbu - Ni kwa matumizi ya Msimamizi wa mfumo pekee + administrator_read: Iliyosomwa na Msimamizi + agency: Taasisi + agency_read: Iliyosomwa na taasisi + all: Pata taarifa zote au za watumiaji approvals_assessment: '%{approval_label}' approvals_assessment_pending: '%{approval_label}Inasubiri' approvals_case_plan: '%{approval_label}' approvals_case_plan_pending: '%{approval_label}Inasubiri' approvals_closure: '%{approval_label}' approvals_closure_pending: '%{approval_label}Inasubiri' - approve_action_plan: Kidhinisha%{approval_label} - approve_assessment: Kupitisha %{approval_label}fomu - approve_case_plan: Kuidhinisha%{approval_label} - approve_closure: Kupitisha %{approval_label}fomu - approve_gbv_closure: Kupitisha %{approval_label}fomu + approve_action_plan: Thibitisha%{approval_label} + approve_assessment: Thibitisha %{approval_label}fomu + approve_case_plan: Thibitisha%{approval_label} + approve_closure: Thibitisha%{approval_label}fomu + approve_gbv_closure: Thibitisha %{approval_label}fomu assign: Kabidhi - assign_within_agency: Kugawa ndani ya wakala - assign_within_user_group: Gawa ndani ya kikundi cha watumiaji - audit_log: Daftari la Ukaguzi - case: Kesi - case_approvals: Vibali vya Kesi - case_assignments_referrals_transfers: Mgao wa kesi, rufaa na uhamisho - case_exports: Kesi Nje ya Nchi - case_overview: Kesi Zangu - case_risk: Kesi kwa Kiwango cha Tathmini - cases_by_task_overdue_assessment: Tazama kesi kwa Tathmini ya Kuchelewa kwa Kazi - cases_by_task_overdue_case_plan: Tazama Kesi kwa Mpango wa Kesi uliochelewa - cases_by_task_overdue_followups: Tazama Kesi kwa Huduma Zilizopitwa na Wakati - cases_by_task_overdue_services: Tazama Kesi kwa Huduma Zilizopitwa na Wakati - cases_managed_other_users: Kesi kusimamiwa na watumiaji wengine - close: Karibu / Funga - consent_override: Idhini imechelewa - copy: Nakala / Nakili + assign_within_agency: Kugawa ndani ya Taasisi + assign_within_user_group: Kabidhi ndani ya kikundi cha watumiaji + audit_log: Ukurasa wa ukaguzi + case: Shauri + case_approvals: Uthibitisho wa shauri + case_assignments_referrals_transfers: Mgao wa Mashauri, rufaa na uhamisho + case_exports: Kutoa mashauri + case_overview: Mashauri yangu + case_risk: Mashauri kwa hatua ya Tathmini + cases_by_task_overdue_assessment: 'Tazama mashauri kwa Tathmini zilizochelewa ' + cases_by_task_overdue_case_plan: Angalia mashauri kwa Mpango wa shauri uliochelewa + cases_by_task_overdue_followups: Angalia mashauri kwa huduma zilizochelewa + cases_by_task_overdue_services: Angalia mashauri kwa huduma zilizochelewa + cases_managed_other_users: Mashauri yaliyosimamiwa na watumiaji wengine + close: ' Funga' + consent_override: Ridhaa imeondolewa + copy: Nakili copy_of: Nakala ya - create: Kutengeneza / Kuunda - dash_case_incident_overview: Kesi Zangu / Matukio Yangu - dash_cases_by_social_worker: Tazama Kesi kwa Wafanyakazi wa Jamii - dash_cases_by_task_overdue: Tazama Kesi kwa Kazi Iliyochelewa - dash_cases_by_workflow: Tazama Kesi kwa Mtiririko wa Kazi - dash_cases_to_assign: Tazama Kesi Za Kugawa - dash_group_overview: Kesi za Vikundi vyangu - dash_manager_transfers: Tazama Uhamishaji wa Msimamizi - dash_matching_results: Tazama Matokeo Yanayolingana - dash_protection_concerns: Angalia Masuala ya Ulinzi - dash_protection_concerns_by_location: Angalia Masuala ya Ulinzi Kulingana na Eneo - dash_referrals_by_socal_worker: Tazama Marejeo ya Mfanyakazi wa Kijamii - dash_reporting_location: 'Tazama Maeneo ya Kuripoti ' - dash_service_provisions: Tazama Masharti ya Huduma - dash_shared_from_my_team: Imesambazwa kutoka kwa Timu Yangu - dash_shared_with_me: Imeletwa kwangu - dash_shared_with_my_team: Imesambazwa kwenye Timu Yangu - dash_shared_with_others: Imesambazwa kwa Wengine - dash_show_none_values: 'Usione Maadili yoyote ' - dash_tasks: Tazama Kazi - dash_transfers_by_socal_worker: Tazama Uhamishaji wa Wafanyakazi wa Kijamii + create: 'Kutengeneza ' + dash_case_incident_overview: 'Mashauri yangu / Matukio ' + dash_cases_by_social_worker: 'Tazama mashauri kwa Maafisa Ustawi ' + dash_cases_by_task_overdue: Tazama Mashauri kwa Kazi zilizochelewa + dash_cases_by_workflow: Tazama mashauri kwa Mtiririko wa Kazi + dash_cases_to_assign: Tazama mashauri ya kuwapa watu wengine + dash_group_overview: Mashauri ya kikundi changu + dash_manager_transfers: Angalia Uhamisho wa Meneja + dash_matching_results: Angalia Matokeo Yanayolingana + dash_protection_concerns: Angalia shaka za hifadhi + dash_protection_concerns_by_location: Angalia shaka za hifadhi Kwa Eneo + dash_referrals_by_socal_worker: 'Angalia rufaa kwa Maafisa Ustawi ' + dash_reporting_location: Angalia Maeneo ya Kutolea taarifa + dash_service_provisions: Angalia utoaji wa Huduma + dash_shared_from_my_team: Lililotumwa kutoka kwenye timu yangu + dash_shared_with_me: Lililotumwa kwangu + dash_shared_with_my_team: Lililotumwa kwenye Timu Yangu + dash_shared_with_others: Lililotumwa kwa Wengine + dash_show_none_values: Angalia zisizokuwa na thamani + dash_tasks: Angalia Kazi + dash_transfers_by_socal_worker: 'Angalia uhamisho kwa Afisa Ustawi ' dash_national_admin_summary: Muhtasari wa Msimamizi - dashboard: Dashbodi + dashboard: Dashibodi delete: Futa - display_view_page: Onyesha Ukurasa wa Kutazama - duplicate: Utafutaji wa Nakala - enable_disable_record: Lemaza - export_case_pdf: PDF la Kesi za Nje - export_csv: Kuuza Nje csv - export_custom: Desturi ya Kuuza nje - export_duplicate_id_csv: Nakala za Usafirishaji ? Usafirishaji wa Nakala - export_json: Kuuza nje json - export_list_view_csv: Muonekano wa Orodha ya kuuza nje csv - export_mrm_violation_xls: Usafirishaji mrm udhalilishaji xls - export_pdf: Kuuza nje pdf / pdf ya kuuza nje - export_photowall: Usafirishaji wa picha - export_unhcr_csv: Safirisha csv za Shirika la Umoja wa Mataifa la Wakimbizi - export_xls: Kuuza nje xls - find_tracing_match: Kupata kufuatilia yaliyofanana kutoka kwenye kesi - view_registry_record: Tazama rekodi ya usajili - add_registry_record: Ongeza rekodi ya usajili - flag: 'Bendera ' + display_view_page: 'Onesha kuona Ukurasa ' + duplicate: Utafutaji uliojirejea + enable_disable_record: Zuia + export_case_pdf: Toa shauri kwa mfumo wa PDF + export_csv: Toa kwa Mfumo wa CSV + export_custom: Utoaji Uliozoeleka + export_duplicate_id_csv: Utoaji uliojirudia + export_json: Utoaji kwa mfumo wa json + export_list_view_csv: Toa orodha ya kuangalia Kwa Mfumo wa csv + export_mrm_violation_xls: Toa faili la mrm la ukatili kwa mfumo wa xls + export_pdf: Toa kwa Mfumo wa PDF + export_photowall: Toa kwa ukurasa wa picha + export_unhcr_csv: Toa faili la shirika la umoja wa mataifa kwa Mfumo wa csv + export_xls: Toa kwa mfumo wa xls + find_tracing_match: 'Tafuta yanayofanana kutoka kwenye shauri ' + view_registry_record: Angalia taarifa za usajili + add_registry_record: Ongeza taarifa za usajili + family: Familia + flag: Kibendera form: Fomu - group: Fikia rekodi zote au watumiaji wote katika kikundi changu + group: Tumia taarifa zote au watumiaji wote katika kikundi changu group_read: Kikundi Kimesomwa import: 'Kuagiza ' incident: Tukio - incident_details_from_case: Ongeza Maelezo ya Tukio kwenye kesi ya mtumiaji mwingine - incident_from_case: Tengeneza tukio kutoka kwenye Kesi - kpi: Mapigo ya Moyo / KPls. - lookup: 'Tazama /Angalia ' + incident_details_from_case: Ongeza Maelezo ya Tukio kwenye shauri la mtumiaji mwengine + incident_from_case: Tengeneza tukio kutoka kwenye shauri + kpi: Kipimo /viashiria muhimu vya utendaji + lookup: 'Angalia ' manage: Kusimamia - mark_for_offline: Alama kwa Nje ya Mtandao - matching_configuration: Kuoanisha Mifumo - metadata: Tazama / Tafuta. Fomu + mark_for_offline: Alama ya Nje ya Mtandao + matching_configuration: Usanidi unaolingana + metadata: Fomu, Tafuta potential_match: Inayoweza Kulingana - primero_configuration: Mpangilio - read: Soma / Iliyosomwa - reassign: Gawa upya + primero_configuration: usanidi + read: Soma + reassign: Toa tena receive_referral: Pokea Rufaa receive_transfer: Pokea Uhamisho referral: Inaweza kutumika kwa rufaa - referral_from_service: Rejelea Kesi kutoka kwenye fomu ya Huduma + referral_from_service: Rejea Shauri kutoka kwenye fomu ya Huduma registry_record: Usajili - remove_assigned_users: Ondoa watumiaji wengine (rufaa) - reopen: Fungua upya - report: Ripoti + remove_assigned_users: Ondoa watumiaji wengine (waliopewa rufaa) + reopen: Fungua tena + report: Taarifa managed_report: Utambuzi - request_approval: Ombi la kupitishwa / kkuidhinishwa - request_approval_action_plan: '%{approval_label}Ombi la kibali' - request_approval_assessment: '%{approval_label}Ombi la kibali' - request_approval_case_plan: '%{approval_label}Ombi la kibali' - request_approval_closure: '%{approval_label}Ombi la kibali' - request_approval_gbv_closure: '%{approval_label}Ombi la kibali' + request_approval: Ombi la uthibitisho + request_approval_action_plan: '%{approval_label}Ombi la Uthibitisho' + request_approval_assessment: '%{approval_label}Ombi la Uthibitisho' + request_approval_case_plan: '%{approval_label}Ombi la Uthibitisho' + request_approval_closure: '%{approval_label}Ombi la Uthibitisho' + request_approval_gbv_closure: '%{approval_label}Ombi la Uthibitisho' request_transfer: Omba Uhamisho role: Majukumu save_search: Hifadhi Utafutaji saved_search: Utafutaji Uliohifadhiwa - search_owned_by_others: 'Tafuta rekodi / kumbukumbu za kesi zinazomilikiwa na watumiaji wengine ' - self: Fikia rekodi zangu tu au mtumiaji pekee - service_provision_incident_details: Angalia Ongeza Kitufe cha Utoaji Huduma au Mfano wa Maelezo ya Matukio - services_section_from_case: Ongeza utoaji wa Huduma kwenye kesi ya mtumiaji mwengine - specific_roles: Fikia orodha maalumu ya majukumu - sync_external: Sawazisha na mfumo wa usimamizi wa habari wa nje - sync_mobile: Alama kwa Nje ya Mtandao + search_owned_by_others: 'Tafuta kumbukumbu za shauri zinazomilikiwa na watumiaji wengine ' + self: 'Pata kumbukumbu zangu tu au za mtumiaji ' + service_provision_incident_details: Angalia Kitufe cha ongeza Utoaji Huduma kinachohusiana na Maelezo ya Matukio + services_section_from_case: Ongeza utoaji wa Huduma kwa mtumiaji mwengine wa shauri + specific_roles: Tumia orodha maalumu ya majukumu + sync_external: Sawazisha pamoja na mfumo wa usimamizi wa taarifa + sync_mobile: Alama ya Nje ya Mtandao system: Mfumo - tracing_request: 'Ombi la kufuatilia ' - transfer: Inaweza klutumika kwa uhamisho + tracing_request: Ombi la utafutaji + transfer: Inaweza kutumika kwa uhamisho user: Watumiaji - user_group: Vikundi vya Watumiaji - view_approvals: Tazama Vibali - view_assessment: Tazama / Angalia Tathmini - view_photo: Tazama / Anglia Picha - view_protection_concerns_filter: Tazama / Angalia Vichungio vya Masuala ya Ulinzi - view_response: 'Tazama / Angalia Majibu ' + user_group: Makundi ya Watumiaji + view_approvals: Angalia Uthibitisho + view_assessment: Angalia Tathmini + view_photo: Anglia Picha + view_protection_concerns_filter: Angalia mchujo wa shaka za hifadhi + view_response: 'Angalia Hatua zilizochukuliwa ' webhook: Mtandao - workflow: Mtiririko wa kazi - Kesi za Mtu mmoja mmoja - workflow_team: Mtiririko wa kazi - Kesi za kikundi - write: Kuandika - activity_log: Logi la Vitendo /Shughuli + workflow: Mtiririko wa kazi - Mashauri ya Mtu mmoja mmoja + workflow_team: Mtiririko wa kazi - Mashauri ya Timu + write: Andika + activity_log: Ukurasa wa Shughuli + remove_alert: Ondoa Tahadhari resource: kpi: actions: read: - explanation: Uwezo wa kufikia ukurasa wa mapigo ya moyo/KPI - label: Kufikia ukurasa wa mapigo ya moyo/KPI + explanation: Uwezo wa kufikia Kipimo /ukurasa wa viashiria muhimu vya utendaji + label: Kufikia Kipimo /ukurasa wa viashiria muhimu vya utendaji kpi_assessment_status: - explanation: Uwezo wa kuona, kwa kesi zinazoendelea ambazo mtumiaji anaweza kufikia, kiwango gani fomu zao za tathmini zimejazwa/zimekamilishwa. - label: Hali ya Tathmini + explanation: Uwezo wa kuyaona mashauri yanayoendelea ambayo mtumiaji anaweza kuyafikia, na kwa kiwango gani mashauri hayo yana fomu za tathmini zilizokamilika + label: Hatua ya Tathmini kpi_average_followup_meetings_per_case: - explanation: Uwezo wa kuona, kwa kesi hai / zinazoendelea ambazo mtumiaji anauwezo wa kufikia, wastani wa idadi ya vikao vya ufuatiliaji vilivyofanyika katika kipindi cha muda malum - label: Wastani wa Vikao vya Ufuatiliaji kwa kila Kesi + explanation: Uwezo wa kuona, kwa mashauri yanayoendelea ambayo mtumiaji anauwezo wa kufikia, na wastani wa idadi ya vikao vya ufuatiliaji vilivyofanyika katika kipindi cha muda maalumu. + label: Wastani wa Vikao vya Ufuatiliaji kwa kila shauri kpi_average_referrals: - explanation: Uwezo wa kuziona tena kesi hai / zinazoendelea zote ambazo mtumiaji anauwezo wa kuzifikia, kwa wastani wa idadi ya rufaa zilizofanywa kwa kila aina ya huduma + explanation: Uwezo wa kuyaona tena mashauri yanayoendelea ambayo mtumiaji anauwezo wa kuyafikia, kwa wastani wa idadi ya rufaa zilizofanywa kwa kila aina ya huduma label: Wastani wa Rufaa kpi_case_closure_rate: - explanation: 'Uwezo wa kuona idadi ya kesi zilizofungwa katika kila tovuti kila mwezi ' - label: Idadi ya Kesi za Kufungwa + explanation: 'Uwezo wa kuona idadi ya mashauri mangapi yaliyofungwa katika kila eneo kwa mwezi ' + label: Idadi ya mashauri yaliyofungwa kpi_case_load: - explanation: Uwezo wa kuona wastani wa idadi ya kesi ambazo kila mfanyakazi wa kesi alizonazo - label: Wingi wa kesi / Mzigo wa kesi + explanation: 'Uwezo wa kuona wastani wa idadi ya mashauri yaliyowazi aliyonayo kila Afisa Ustawi ' + label: Wingi wa mashauri kpi_client_satisfaction_rate: - explanation: Uwezo wa kuona, kwa kila kesi ambayo mtumiaji anyoweza kuifikia, ni uwiano gani wa waathirika waliokamilisha Uchunguzi wa Maoni walikuwa wameridhika. + explanation: Uwezo wa kuona, kwa kila shauri ambalo mtumiaji anaeweza kuifikia, ni uwiano gani wa manusura waliotoa Maoni ambao wameridhika. label: Kiwango cha Kuridhika kwa Mteja kpi_completed_case_action_plans: - explanation: Uwezo wa kuona kwa kesi hai / zinazoendelea ambazo mtumiaji anauwezo wa kuzifikia, ni sehemu gani wamekamilisha Mpango wa Utekelezaji wa Kesi - label: Mipango ya Utekelezaji wa Kesi Iliyokamilika + explanation: Uwezo wa kuona mashauri yanayoendelea ambayo mtumiaji anaweza kuyafikia, ni sehemu gani ya Mpango wa Utekelezaji wa shauri imekamilika + label: Mipango ya Utekelezaji wa shauri Iliyokamilika kpi_completed_case_safety_plans: - explanation: Uwezo wa kuona, kesi hai / zinazoendelea ambazo mtumiaji anaouwezo wa kuzifikia, ni kwa uwiano gani zinahitaji na zimekamilisha Mpango wa Usalama - label: Mpango wa Usalama wa Kesi Uliokamilika + explanation: Uwezo wa kuyaona, mashauri yanayoendelea ambayo mtumiaji anaouwezo wa kuzifikia, ni kwa uwiano gani zinahitaji na zimekamilisha Mpango wa hifadhi + label: Mpango wa hifadhi wa shauri Uliokamilika kpi_completed_supervisor_approved_case_action_plans: - explanation: Uwezo wa kuona, kesi hai / zinazoendelea ambazo mtumiaji anauwezo wa kuzifikia, ni kwa uwiano gani walikamilisha Mpango wa Utekelezaji wa Kesi ambazo zilipitishwa na msimamizi - label: Mpango wa Utekelezaji Uliokamilika na Kuidhinishwa na Msimamizi + explanation: Uwezo wa kuyaona, mashauri yanayoendelea ambayo mtumiaji anaouwezo wa kuzifikia, ni kwa uwiano gani zimekamilisha Mpango wa hifadhi ambao uliothibitishwa na msimamizi + label: Mpango wa Utekelezaji Uliokamilika na uliothibitishwa na Msimamizi kpi_goal_progress_per_need: - explanation: Uwezo wa kuona, kesi ambazo mtumiaji anauwezo wa kuzifikia, ni asilimia ngapi ya malengo katika kila aina ya mahitaji yametimizwa - label: Maendeleo yaliyofanyika Kufikia Malengo + explanation: Uwezo wa kuona, mashauri ambayo mtumiaji anauwezo wa kuyafikia, ni asilimia ngapi ya malengo katika kila kipengele cha mahitaji yamefikiwa + label: Hatua zilizochukuliwa Kufikia Malengo kpi_number_of_cases: - explanation: Uwezo wa kuona ni kesi ngapi mpya zilizoripotiwa hufunguliwa kila mwezi kwa kila tovuti - label: Idadi ya Kesi + explanation: Uwezo wa kuona ni mashauri mangapi mapya yametolewa taarifa na yamefunguliwa kwa mwezi kwa kila eneo + label: Idadi ya mashauri kpi_number_of_incidents: - explanation: Uwezo wa kuona ni matukio mangapi mepya yaliyoripotiwa hufunguliwa kila mwezi kwa kila wovuti + explanation: Uwezo wa kuona ni matukio mangapi mapya yaliyotolewa taarifa hufunguliwa kila mwezi kwa kila eneo label: Idadi ya Matukio kpi_reporting_delay: - explanation: Uwezo wa kuona, kwa matukio yote ambayo mtumiaji anaouwezo wa kuyafikia, ni siku ngapi zimepita kati ya muathirika kufanyiwa Udhalilishaji wa Kijinsia na pale muathirika aliporipoti kwa mtoa huduma - label: Kuchelewa Kuripoti + explanation: Uwezo wa kuona, kwa matukio yote ambayo mtumiaji anaouwezo wa kuyafikia, ni siku ngapi zimepita kati ya kufanyiwa Udhalilishaji wa kijinsia kwa manusura na pale manusura alipotoa taarifa kwa mtoa huduma + label: Ucheleweshwaji wa kutolewa taarifa kpi_services_provided: - explanation: Uwezo wa kuona, kesi zote ambazo mtumiaji anaouwezo wa kuzifikia, ni aina gani ya huduma zilizotolewa na shirika nyumbani + explanation: Uwezo wa kuona, kati ya mashauri yote ambayo mtumiaji anaouwezo wa kuyafikia, ni aina gani ya huduma zilizotolewa ndani ya taasisi husika label: Huduma Zilizotolewa kpi_supervisor_to_caseworker_ratio: - explanation: Uwezo wa kuona uwiano wa wafanyakazi wa kesi kwa wasimamizi - label: Uwiano wa Wasimamizi kwa Wafanyakazi wa Kesi + explanation: Uwezo wa kuona uwiano wa waendesha mashauri kwa wasimamizi + label: Uwiano wa muendesha shauri na msimamizi kpi_time_from_case_open_to_close: - explanation: Uwezo wa Kuona, kwa kesi zote ambazo mtumiaji anaouwezo wa kuzifikia, ni kwa muda gani kesi zinakuwa wazi / zinaendelea - label: Muda ambao Kesi Inafunguliwa mpaka Kesi Inapofungwa - label: 'Kiashiria Muhimu cha Utendaji / ' + explanation: Uwezo wa Kuona, kwa mashauri yote ambayo mtumiaji anaouwezo wa kuyafikia, Je, ni kwa muda gani shauri litakuwa wazi? + label: Muda kati ya kufunguliwa na kufungwa kwa shauri + label: 'Vipimo hivi vya utendaji ' agency: actions: assign: - explanation: Uwezo wa kuchagua wakala wakati wa kutengeneza / kufungua akaunti ya mtumiaji. Ikiwa mtumiaji wa sasa anayo ruhusa pamoja na ruhusa ya "Shirika Kusoma'" kwa watumiaji, watakuwa na uwezo wa kuongeza mtumiaji kwa wakala wao + explanation: Uwezo wa kuchagua Taasisi wakati wa kutengeneza / kurekebisha akaunti ya mtumiaji. Ikiwa mtumiaji wa sasa anayo ruhusa pamoja na ruhusa ya "Taasisi imetambulika'" kwa watumiaji, watakuwa na uwezo wa kuongeza mtumiaji kwa taasisi yao label: Kabidhi create: - explanation: Uwezo wa kutengeneza / kutayarisha wakala - label: Tengeneza / Unda / Fungua + explanation: Uwezo wa kutengeneza Taasisi + label: 'Tengeneza ' manage: - explanation: 'Inaruhusu mtumiaji kufanya shughuli zote zinazopatikana kwenye Wakala. Ruhusa ya "Kusimamia" inamaanisha "kila kitu" MUHIMU: Hii inatoa pia uwezo wa kutengeneza wakala mpya.' - label: Kusimamia (ruhusa zote kwa aina ya rasilimali) + explanation: 'Inaruhusu mtumiaji kufanya shughuli zote zinazopatikana kwenye Taasisi. Ruhusa ya Simamia" inamaana ya "kila kitu" MUHIMU: Hii inatoa pia uwezo wa kutengeneza Taasisi mpya.' + label: Simamia (ruhusa zote kwa aina ya rasilimali) read: - explanation: Uwezo wa kuwaona wakala + explanation: Uwezo wa kuziona Taasisi label: Mtazamo write: - explanation: Uwezo wa kuhariri taarifa kuhusu wakala. Tafadhali kumbuka kwamba hii ni kwa mawakala wote kwenye mfumao - label: Hariri - explanation: 'Inawakilisha shirika lenye wajumbe wanaotumia Primero. Mashirika yapo bila ya Makundi ya Watumiaji ' - label: Wakala + explanation: Uwezo wa kurekebisha taarifa kuhusu Taasisi. Tafadhali kumbuka kwamba hii ni kwa Taasisi zote kwenye mfumo + label: Rekebisha + explanation: 'Inawakilisha Taasisi yenye wajumbe wanaotumia Primero. Taasisi ambazo zinajitegemea wenyewe bila ya Makundi ya Watumiaji ' + label: Taasisi audit_log: actions: read: - explanation: Inaruhusu mtumiaji kuona na kuchuja orodha ya vitendo / shughuli zote zinazofanyika katika mfumo, imegawanywa kulingana na aina ya kitendo cha mtumiaji, kitambulisho cha rekodi na wakati wa kitendo. Hii inafaa zaidi kwa wasimamizi wa ngazi ya kitaifa au wakala, kwa vile hii inaonesha vitendo / shughuli zote zinazofanywa na watumiaji wote katika mfumo. Tafadhali kumbuka kwamba daftari la ukaguzi halionyeshi taarifa inayomtambulisha mtu binafsi kuhusu rekodi zilnazohusika katika kila kitendo. - label: Mtazamo - explanation: Orodha ya vitendo /shughuli inayoweza kuchujwa katika mfumo. Haijumuishi taarifa yoyote inayotambulika ya Kesi, Matukio, au Kufuatilia Maombi - label: Daftari la Ukaguzi + explanation: Inaruhusu mtumiaji kuona na kuchuja orodha ya shughuli zote zinazofanyika katika mfumo, imegawanywa kulingana na mtumiaji, aina ya shughuli, chakumbukumbu ya utambulisho, na wakati wa shughuli. Hii inafaa zaidi kwa wasimamizi wa ngazi ya kitaifa au wasimamizi katika ngazi ya Taasisi, kwa vile hii inaonesha shughuli zote zinazofanywa na watumiaji wote katika mfumo. Tafadhali kumbuka kwamba daftari la ukaguzi halionyeshi taarifa inayomtambulisha mtu binafsi kuhusu rekodi zilnazohusika katika kila hatua + label: Angalia + explanation: Orodha ya upembuzi wa shughuli inayoweza kupembuliwa katika mfumo. Haijumuishi taarifa yoyote inayotambulika ya shauri, Matukio, au ufuatiliaji wa Maombi + label: Ukurasa wa ukaguzi case: actions: add_note: - explanation: Inaruhusu mtumiaji kuongeza ingizo kwenye fomu ndogo ya "Maelezo / Madokezo" (ambayo mara nyingine huitwa "maoni"). Mtumiaji hufanya hivi kwa kubonyeza kitufe cha "Ongeza Maelezo" katika ukurasa wa kuonyesha kesi. Kitendo hiki hufanywa hasa na wasimamizi ambao hawana uwezo wa kuhariri kesi, lakini unataka kuongeza ukumbusho / angalizo kwenye kesi kwa ajili ya mfanyakazi wa kesi. Kwa kufanya hivi, kuongeza maelezo ni sawa na kuogeza bendera. Faida ya kuongeza maelezo ni kwamba, msimamizi anapoongeza maelezo kwenye kesi, alama / arifa itaonekana kwenye kesi kwa ajili ya mfanyakazi wa kesi anapoangalia kesi kwenye kifaa chake cha mkononi - label: Ongeza Maelezo kwenye Kesi + explanation: Inamruhusu mtumiaji kuongeza maelezo kwenye fomu ndogo (ambayo mara nyingine huitwa "maoni"). Mtumiaji hufanya hivi kwa kubonyeza kitufe cha "Ongeza Maelezo" katika ukurasa wa kuonyesha shauri. Kitendo hichi hufanywa hasa na meneja ambao hawana uwezo wa kurekebisha shauri, lakini unataka kuongeza ukumbusho kwenye shauri kwa ajili ya mwendesha shauri. Kwa kufanya hivi, kuongeza maelezo ni sawa na kuogeza kibendera. Umuhimu wa kuongeza maelezo ni kwamba, meneja anapoongeza maelezo kwenye shauri, ujumbe utaonekana kwenyeshauri kwa muendesha shauri anapoangalia shauri kwenye kifaa chake cha mkononi + label: Ongeza Maelezo kwenye shauri add_registry_record: - explanation: 'Inamuwezesha mtumiaji kuunganisha Usajili na Kesi kutoka kwenye fomu ya maelezo ya Usajili. Pia inamuwezesha mtumiaji kuondoa Usajili wowote ambao umeunganishwa kwenye Kesi ' - label: Ongeza / ingiza taarifa mpya ya rekodi ya Usajili kuoka kwenye kesi + explanation: 'Inamruhusu mtumiaji kuunganisha Usajili katika shauri kutoka kwenye fomu ya maelezo ya Usajili. Pia inamruhusu mtumiaji kutounganisha Usajili wowote ambao umeunganishwa kwenye shauri ' + label: Ongeza/boresha taarifa ya kumbukumbu ya Usajili kutoka kwenye shauri approve_action_plan: - explanation: Inamruhusu meneja kuidhinisha %{approval_label}kwa kesi za wafanyakazi wao wa kesi - label: Kuidhinisha %{approval_label} + explanation: Inamruhusu meneja kuthibitisha%{approval_label}kwa shauri ya waendesha mashauri + label: Thibitisha%{approval_label} approve_assessment: - explanation: Inamruhusu meneja kuidhinisha %{approval_label}kwa kesi za wafanyakazi wa kesi - label: Kupitisha %{approval_label}fomu + explanation: Inamruhusu meneja kuthibitisha %{approval_label}kwa shauri ya waendesha mashauri + label: Thibitisha%{approval_label}fomu approve_bia: - explanation: Inamruhusu meneja kuidhinisha %{approval_label}kwa kesi za wafanyakazi wao wa kesi - label: Kupitisha %{approval_label}fomu + explanation: Inamruhusu meneja kuthibitisha %{approval_label}kwa shauri ya waendesha mashauri + label: Thibitisha %{approval_label}fomu approve_case_plan: - explanation: Inamruhusu meneja kuidhinish %{approval_label}ya kesi za wafanyakazi wao wa kesi - label: Kuidhinisha %{approval_label} + explanation: Inamruhusu meneja kuthibitisha %{approval_label}kwa shauri ya waendesha mashauri + label: Thibitisha %{approval_label} approve_closure: - explanation: Inamruhusu meneja kuidhinisha %{approval_label}ya kesi za wafanyakazi waon wa kesi - label: Kupitisha %{approval_label}fomu + explanation: Inamruhusu meneja kuthibitisha %{approval_label}kwa shauri ya waendesha mashauri + label: Thibitisha %{approval_label}fomu approve_gbv_closure: - explanation: Inamruhusu meneja kuidhinisha %{approval_label}ya kesi za wafanyakazi wao wa kesi - label: Kupitisha%{approval_label}fomu + explanation: Inamruhusu meneja kuthibitisha %{approval_label}kwa shauri ya waendesha mashauri + label: Thibitisha%{approval_label}fomu assign: - explanation: 'Inamruhusu mtumiaji kupeleka kesi kutoka kwa mmiliki wa rekodi wa asili kwenda kwa mtumiaji yeyote mwengine aliyeko kwenye mfumo. Idhini ya mtoto haihitajiki katika kufanya hivyo. Kinyume na uhamisho, mpokeaji hapewi nafasi ya kukubali au kukataa mgao huo. ' - label: Kabidhi / gawa + explanation: 'Inamruhusu mtumiaji kupeleka shauri kutoka kwa mmiliki wa asili wa kumbukumbu kwenda kwa mtumiaji yeyote mwengine aliyeko kwenye mfumo. Ridhaa ya mtoto haihitajiki katika hatua hii. Kinyume na uhamisho, mpokeaji hapewi nafasi ya kukubali au kukataa agizo hilo. ' + label: 'Kabidhi ' assign_within_agency: explanation: 'Inamruhusu mtumiaji kupeleka kesi kutoka kwa mmiliki wa rekodi wa asilikwenda kwa mtumiaji yeyote mwengine aliyeko katika wakala wa sasa hivi wa mtumiaji. Idhini ya mtoto haihitajiki katika kufanya hivi. Kinyume na uhamisho, mpokeaji hapewi nafasi ya kukubali au kukataa mgao huu. ' - label: Gawa kwa mtumiaji ndani ya wakala wangu + label: Kabithi kwa mtumiaji ndani ya Taasisi wangu assign_within_user_group: - explanation: Inamruhusu mtumiaji kupeleka kesi kutoka kwa mmiliki wa asili wa rekodi kwenda kwa mtumiaji mwengine yeyote katika kikundi cha mtumiaji wa sasa. Idhini ya mtoto haihitajiki kwa kufanya hvyo. Kinyume na uhamisho, mpokeaji hapewi nafasi ya kukubali au kukataa mgao huo. - label: Gawa kwa mtumiaji ndani ya kikundi changu cha watumiaji + explanation: Inamruhusu mtumiaji kutuma shauri kutoka kwa mmiliki wa asili wa kumbukumbu kwenda kwa mtumiaji mwengine yeyote katika kikundi cha watumiaji wa sasa. Ridhaa ya mtoto haihitajiki katika hatua hii. Kinyume na uhamisho, mpokeaji hapewi nafasi ya kukubali au kukataa agizo hilo. + label: Kabithi kwa mtumiaji ndani ya kikundi changu cha watumiaji change_log: - explanation: Mtumiaji anaweza kuona historia ya mabadiliko yote kuanzia ilipotengenezwa. Hii ni pamoja na thamani zilizorekodiwa kwa nyanja zote - label: Badilisha Daftari + explanation: Mtumiaji anaweza kuona historia ya mabadiliko yote kuanzia ilipotengenezwa. Hii inajumuisha thamani zilizorekodiwa kwa nyanja zote + label: Badilisha kurasa close: - explanation: Inarmuhusu mtumiaji kuweka hali ya kesi iliyofunguliwa kuwa imefungwa - label: Karibu / Funga + explanation: Inarmuhusu mtumiaji kuweka hali ya shauri iliyofunguliwa kuwa limefungwa + label: ' Funga' consent_override: - explanation: Inamruhusu mtumiaji kufanya rufaa au uhamisho kwa kesi ambayo haina kibali / haijatoa kibali - label: Batilisha ukosefu wa idhini wakati wa kurejea au kuhamisha + explanation: Inamruhusu mtumiaji kufanya rufaa au uhamisho kwa shauri ambalo halijaidhinishwa + label: Batilisha ridhaa unapofanya rufaa au uhamisho create: - explanation: Uwezo wa kutengeneza kesi - label: Kutengeneza/Kuunda + explanation: Uwezo wa kutengeneza shauri + label: Kutengeneza display_view_page: - explanation: Ikiwa mtumiaji anatafuta kesi ambayo hana ufikiaji nayo / hawezi kuifikia, ruhusa hii inamruhusu aweze kuona mfano mdogo / modal ndogo, wenye taarifa za msingi za kesi hata kama mtumiaji hataweza kubonyeza kuingia kwenye kesi kuona taarifa yote. Sehemu / Eneo linaloonekana katika ""Ona Mfano" ni eneo lililowekwa kwenye mpangilio wa "Onyesha kwa ufupi". Mfano hjuu ni muhimu kwa watumiaji wanaotfanya shughuli za Kutafuta Familia na Kuziunganisha, kwa vile "Ona Mfano" huweza kufikiwa na watumiaji wakati wanapopitia kesi ambazo huonekana kama "Huenda Zikafanana'" kwa Ombi la Kufuatilia. - label: Onyesha Ukurasa wa Kutazama/Kuchagua + explanation: Ikiwa mtumiaji anatafuta shauri ambalo hana uwezo wa kulifikia, ruhusa hii inawawezesha kuona mfano mdogo wenye taarifa za msingi kuhusu shauri, hata kama mtumiaji hataweza kubonyeza kuingia kwenye shauri  kuona taarifa zote. Maeneo yatakayoonekana katika "Ona Mfano" ni maeneo ambayo yanaweza kusanidiwa "Onyesha kwa ufupi". Mfano huu pia ni muhimu kwa watumiaji wanaotafuta Familia na hatua za Kuwaunganisha tena, kwa vile "kuona Mfano" unapatikana kwa watumiaji kufikia wakati wanapopitia mashauri ambayo yametokea kama “mfanano wenye kulingana”  kwa Ombi la Kutafuta. + label: Onesha kuona Ukurasa enable_disable_record: - explanation: Uwezo wa kuilemza au kuiwezesha kesi . Kesi "Zilizolemazwa" hazionekani kama chaguo la msingi kwenye orodha ya kesi. Mtumiaji anaweza kuziona kesi zilizolemazwa katika orodha ya kesi kwa kutumia kichujo. Kwa vile Primero hairuhusu watumiaji kuzifuta kesi , mtumiaji anaweza kuamua kuilemaza kesi kama mbadala. Kwa mfano ikiwa mtumiaji alitengeneza kesi kimakosa, au kesi ikawa na data mbaya, mtumiaji itambidi ailemaze kesi hiyo. - label: Kuwezesha / Kulemaza + explanation: Uwezo wa kuzuia au kuwezesha shauri.  Mashauri ‘’yaliozuiliwa" hayaonekani kwenye uhalisia wa orodha yake. Mtumiaji anaweza kuyaona mashauri yaliyozuiliwa kwa kutumia kichujio. Kwa vile Primero hairuhusu watumiaji kufuta mashauri , mtumiaji anaweza kuamua kuzuia shauri kama  mbadala. Kwa mfano, ikiwa mtumiaji alitengeneza shauri kimakosa, au shauri likawa na taarifa mbaya, mtumiaji itambidi alizuiye. + label: 3QKuwezesha / Zuia export_case_pdf: - explanation: 'Mtumiaji anaweza kutengeneza faili la PDF la usafirishaji kutoka kwenye orodha ya kesi au ukurasa wa onyesho la kesi, ambalo mtumiaji wa sasa anaouwezo wa kuifikia kesi moja, nyingi au hata zote . Katika faili la kusafirisha la PDF, taarifa huorodheshwa kwanza kwa kesi na baada ya hapo kupangwa kwa fomu ambazo taarifa hujitokeza. ' - label: Safirisha kesi kwenda PDF + explanation: 'Mtumiaji anaweza kutengeneza faili la PDF la usafirishaji kutoka kwenye orodha ya shauri au onesha ukurasa, ambao umekusanya maeneo yote ambayo mtumiaji wa sasa anaouwezo wa kuifikia shauri moja, zaidi ya moja au hata zote . Katika faili la kutolewa la PDF, taarifa huorodheshwa kwanza kwa shauri na baadae kupangwa kwa fomu ambazo taarifa hujitokeza. ' + label: Toa shauri kwa PDF export_csv: - explanation: 'Mtumiaji anaweza kutengeneza faili la usafirishaji la CSV kutoka kwenye orodha ya kesi au ukurasa wa onyesho la kesi, ambao una maeneo yote ambayo mtumiaji wa sasa anaouwezo wa kufikia kesi moja, nyingi, au zote. ANGALIZO, Usafirishaji wa CSV hautoi herufi zisizokuwa za Kilatini (mfano Kiarabu, Kibengali) katika muundo unaoweza kusomeka ' - label: Safirisha kwenda CSV + explanation: 'Mtumiaji anaweza kutengeneza faili la utoaji kwa CSV kutoka kwenye orodha ya mashauri au ukurasa wa onyesho, ambao umekusanya maeneo yote ambayo mtumiaji wa sasa anaouwezo wa kuifikia shauri moja, zaidi ya moja au hata zote . ambayo mtumiaji anaweza kuyafikia. ZINGATIA: CSV hautoi herufi zisizokuwa za Kilatini (mfano Kiarabu, Kibengali) katika muundo unaoweza kusomeka ' + label: Toa kwa CSV export_custom: - explanation: 'Mtumiaji anaweza kutengeneza faili la kusafirisha la XLS kutoka kwenye orodha ya kesi au ukurasa wa onyesho la kesi, ambao una seti maalum ya fomu, au eneo kwa kesi moja, nyingi au zote ambazo mtumiaji anaweza kuzifikia. Katika usafirishaji huu, kila fomu moja inawakilishwa na kichupo (tab) chake katika faili la XLS. Mtumiaji anaweza kuchagua ni fomu zipi au maeneo gani wangependa yaingizwe katika usafirishaji kwa kutumia muundo Maalum wa Usafirishaji. Tafadhali kumbuka kuwa watumiaji wanaweza kuingiza fomu na maeneo katika usafirishaji, ikiwa watakuwa tayari wano uwezo wa kuziona fomu hizo na maeneo hayo pale watakapokuwa wakiiangalia kesi katika maombi. ' - label: Desturi za Usafirishaji i + explanation: Mtumiaji anaweza kutengeneza faili la kutoa la XLS kutoka kwenye orodha yashauri au ukurasa wa onyesho la shauri, ambao imejumuisha fomu mbalimbali, au maeneo, kwa shauri moja au zaidi, ambayo mtumiaji anaweza kuyafikia. Katika kutoa, kila fomu itawakilisha katika eneo lake faili la XLS. Mtumiaji anaweza kuchagua fomu au maeneo gani wangependa yaingizwe katika kuyatoa kwa kutumia muundo Maalum wa Usafirishaji. Tafadhali kumbuka kwamba watumiaji wanaweza kuingiza fomu na maeneo katika kutoa, ikiwa watakuwa tayari wanao uwezo wa kuona maeneo na fomu hizo wanapoangalia maombi ya shauri. + label: Utoaji wa kawaida export_duplicate_id_csv: - explanation: 'Tengeneza usafirishaji wa kesi kwa CSV ambao una eneo la aina moja la Kitambulisho cha Taifa (inaweza kuwa na lebo /utambulisho tofauti kwa kutegemea mpangilio) unaotekelezwa kutoka kwenye ukurasa wa kesi tu. ' - label: Usafirishaji wa Nakala + explanation: 'Tengeneza usafirishaji wa kesi kwa CSV ambao una eneo la aina moja la Kitambulisho cha Taifa (inaweza kuwa na alama zaidi ya moja kutegemeana na usanidi). Inayotekelezwa kutoka kwenye ukurasa wa shauri tu. ' + label: Imetolewa Nakala export_json: - explanation: Mtumiaji anaweza kutengeneza faili la kusafirisha la JSON kutoka kwenye orodha ya kesi au ukurasa wa onyesho la kesi, wenye maeneo yote ambayo mtumiaji anao uwezo wa kuifikia kesi moja, nyingi, au zote. Usafirishaji huu hutumiwa zaidi na wale wanaotaka kusafirisha kesi kutoka kwenye mfumo wa sasa wa Primero na baadae kuziingiza katika mfumo tofauti wa Primero au katika mfumo mwengine wa usimamizi wa taarifa. Mfumo wa JSON unasomwa kwa kutumia mashine na kwa hivyo watumiaji walio wengi hawawezi kuutumia - label: Safirisha JSON + explanation: Mtumiaji anaweza kutengeneza faili la kutoa la JSON kutoka kwenye orodha ya shauri au ukurasa wa onyesho, wenye maeneo yote ambayo mtumiaji anao uwezo wa kufikia,  kwa shauri moja au zaidi, ambayo mtumiaji anaweza kuyafikia. Utoaji huu hutumiwa zaidi na wale wanaotaka kutoa shauri kutoka kwenye mfumo wa sasa wa Primero na baadae kuziingiza katika mfumo tofauti wa Primero au katika mfumo mwengine wa usimamizi wa taarifa. Mfumo wa JSON unasomwa kwa kutumia mashine na kwa hivyo watumiaji walio wengi hawawezi kuutumia + label: Toa JSON export_list_view_csv: - explanation: Mtumiaji anaweza kutengeneza faili la kusafirisha la CSV kutoka kwenye ukurasa wa orodha ya kesi wenye maeneo sawa na yale yanayoonekana na mtumiaji huyo katika orodha ya kesi. Yaliyofanyiwa kazi kwenye ukurasa wa kesi tu. - label: 'Hamisha muonekano wa orodha kwenda CSV ' + explanation: Mtumiaji anaweza kutengeneza faili la kutoa la CSV kutoka kwenye ukurasa wa orodha ya shauri wenye maeneo sawa na yale yanayoonekana na mtumiaji huyo katika orodha ya mashauri. Yaliyofanyiwa kazi kwenye ukurasa huo. + label: 'Toa orodha inayoonekana kwa CSV ' export_pdf: - explanation: Mtumiajia anaweza kutengeneza faili la usafirishaji la PDF kutoka kwenye orodha ya kesi au kurasa za kuonyesha kesi ambazo zinazyomaeneo yote ambayo mtumiaji wa sasa anao uwezo wa kuyafikia kwa kesi moja, nyingi au zote. Katika faili la usafirishaji la PDF, taarifa imeandikwa kwanza kwa kesi, na baada ya hapo limepangiliwa katika fomu ambayo taarifa inaonekana. - label: Safirisha kesi kwenda PDF + explanation: Mtumiajia anaweza kutengeneza faili la PDF kwa kulitoa kutoka kwenye orodha ya mashauri au kurasa za kuonyesha mahsauri, ambazo zimejumuisha maeneo yote ambayo mtumiaji wa sasa anao uwezo wa kuyafikia kwa shauri moja au zaidi, ambalo mtumiaji anaweza kufikia. Katika faili la la kusafirisha la PDF, taarifa imeorodheshwa kwa shauri baadae imepangiliwa kutokana na taarifa zilizojitokeza. + label: Toa shauri kwa PDF export_photowall: - explanation: Inamruhusu mtumiaji kusafirisha faili kutoka kwenye ukurasa wenye picha zote za kesi zilizochaguliwa, Ripoti hii inatumika hasa kufuatilia mambo ya familia na shughuli za kuwaungngabisha watu. Iliyotekelezwa kutoka kwenye ukurasa wa orodha ya peji. - label: Itifaki ya Kusafirisha nje + explanation: Inamruhusu mtumiaji kutoa faili kutoka kwenye ukurasa ambao umejumuisha picha zote za mashauri yaliyochaguliwa. Utoaji huu unatumika zaidi katika shughuli za kutafuta na kuunganisha familia. Iliyotekelezwa kutoka kwenye ukurasa wa orodha. + label: Toa kwa ukurasa wa picha export_unhcr_csv: - label: 'Usafirishaji kwa CSV ya Shirika la Wakimbizi la Umoja wa Mataifa ' + label: Utoaji wa faili la Shirika la Wakimbizi la Umoja wa Mataifa kwa CSV export_xls: - explanation: 'Mtumiaji anaweza kutengeneza faili la usafirishaji la XLS kutoka kwenye orodha ya kesi au kurasa za kuonyesha kesi, zenye maeneo yote ambayo mtumiaji wa sasa anao uwezo wa kuyafikia kwa kesi moja, nyingi au zote. Katika usafirishaji huu, kila fomu moja inawakilishwa na kichupo chake kwenye faili la XLS. ANGALIZO, Usafirishaji wa XLS hutoia herufi zisizokuwa za Kilatin (mfano, Kiarabu , Kibengali) katika mfumo unaoweza kusomeka, wakati usafitishaji wa CSV hautoi huduma hiyo. ' - label: 'Usafirishaji wa Excel (kwa faili la XLS) ' + explanation: 'Mtumiaji anaweza kutengeneza faili la kutoa la XLS kutoka kwenye orodha yashauri au ukurasa wa onyesho la shauri, ambao imejumuisha fomu mbalimbali, au maeneo, kwa shauri moja au zaidi, ambayo mtumiaji anaweza kuyafikia. Katika kutoa, kila fomu itawakilisha katika eneo lake faili la XLS. ANGALIZO, Muundo wa XLS hautoi herufi zisizokuwa za Kilatin (mfano, Kiarabu , Kibengali) katika mfumo unaoweza kusomeka, wakati utoaji wa CSV hautoi huduma hiyo.' + label: 'Utoaji wa Excel (kwa faili la XLS) ' find_tracing_match: - explanation: Hii hutumika katika mazingira ya kushughulikia Kutafuta / Kufuatilia na Kuunganisha Familia tu. Watumiaji wenye ruhusa ya kufanya hivi wataona kitufe cha "Tafuta Ulinganisho" katika ukurasa wa kuonyesha kesi" Watakapobonyeza kitufe hiki, wataingia katika orodha ya ombi la kutafuta katika mfumo ambao unaonesha ulinganisho unaowezekana kwa kesi zao. - label: Tafuta kulinganisha kunakoweza kuonekana kutoka kwenye kesi + explanation: Hii hutumika katika mazingira ya kushughulikia Kutafuta na Kuunganisha Familia tu. Watumiaji wenye ruhusa ya kufanya hivi wataona kitufe cha "Tafuta Ulinganisho" katika ukurasa wa kuonyesha shauri" Watakapobonyeza kitufe hiki, wataingia katika orodha ya ombi la kutafuta katika mfumo ambao unaonesha ulinganisho unaowezekana kwa shauri + label: Tafuta ulinganisho kutoka kwenye Shauri flag: - explanation: Uwezo wa kuongeza bendera kwenye kesi. Watumiaji wenye ruhusa ya kufanya hivi wanaweza pia kuziondoa bendera walizoziweka hapo awali. - label: Bendera + explanation: Uwezo wa kuongeza kibendera kwenye shauri. Watumiaji wenye ruhusa wanaweza pia kuviondoa vibendera walivyoviweka hapo awali. + label: Kibendera import: - explanation: 'Inamruhusu mtumiaji kuweza kutengeneza kesi nyingine moja au zaidi mpya kwa kuziagiza kutoka kwenye faili la CSV, Excel au JSON. Faili ambalo linaagizwa lazima liwe limetengenezwa mahsusi "kabisa'' kwa taarifa kuweza kuingizwa ipasavyo. Kipengele hiki kiwe kinapatikana kwa watumiaji wa utawala / usimamizi ambao wenye ujuzi wa hali ya juu wa kiufundi na ufahamu wa kina kuhusu namna ambayo data / taarifa inavyopangwa katika Primero. Inatekelezwa kutoka kwa ukurasa wa orodha ya kesi tu. ' + explanation: 'Inamruhusu mtumiaji kutengeneza shauri moja jipya au Zaidi, kwa kuyaingiza kutoka kwenye faili la CSV, Excel au JSON. Faili lililoingizwa lazima liwe limetengenezwa mahsusi *kabisa* kwa taarifa zilizoingizwa ipasavyo. Kipengele hichi kiwe kinapatikana kwa watumiaji wa utawala/wasimamizi ambao wenye ujuzi na taaluma ya hali ya juu na ufahamu wa kina kuhusu namna ambayo data zinavyopangwa katika Primero. Inatekelezwa kutoka kwa ukurasa wa orodha ya shauri tu. ' label: Kuagiza incident_details_from_case: explanation: Uwezo wa kuongeza kitu kingine katika fomu ndogo ya Maelezo ya Tukio katika kesi uliyoiona katika matokeo ya utfutaji lakini huna uwezo wa kuifikia,. Mtumiaji anaweza kufanya kazi hii kutoka kwenye ukurasa wa matokeo ya utafutaji kwa kuchagua kesi moja au zaidi kutoka kwenue menyu ya vitendo. Baada ya hapo, mtumiaji ataona muundo wenye maeneo yote au fomu ndogo ya maelezo ya tukio sehemu ambayo ambapo wanaweza kuingia na kutoa taarifa kuhusu huduma , Kwa sababu shughuli hii inaweza kufanya kutoka kwenye ukurasa wa matokeo ya utafutaji tu. Italeta maana pale tu ambapo mtu huyo atakuwa pia na ruhusa ya "kutafuta kwa rekodi ya kesi ambayo zinazomilikiwa na watu wengine" - label: 'Ongeza Maelezo ya Tukio la mtumiaji mwingine wa kesi kutoka kwenye ukurasa wa matokeo ya utafutaji. ' + label: 'Ongeza Maelezo ya Tukio kwa shauri la mtumiaji mwingine kutoka kwenye ukurasa wa utafutaji matokeo ' incident_from_case: - explanation: Ruhusa hii inaruhusu mtumiaji kubonyeza kitufe cha "Tengeneza Tukio" . Hii itatengeneza tukio ambalo linaweza kuwa na taarifa iliyonakiliwa kutoka kwenye kesi. Kwa kesi za Udhalilishaji wa Kijinsia, kitufe kiko juu katika ukurasa wa maonyesho ya kesi na inalingana na taarifa kuhusu kesi yote kwa jumla.. Kwenye baadhi ya muktadha wa ufuati;liaji wa matukio, kitufe kiko kwenye fomu ndogo ya "Maelezo ya Tukio". Katika hali hii, baadhi ya taarifa huenda ikawa imenakiliwa kutoka kwenye fomu ndogo ya maelezo ya tukio, ambapo kitufe kilibonyezwa, pamoja na kutoka kwenye kesi yenyewe kwa jumla. hii ni kwamba tukio jipya lililo tengenezwa linaweza kuwa na eneo / sehemu ya "Aina ya Udhalilishaji" kutoka kwenye fomu ndogo ya kmtu binafsi yenye maelezo ya tukio, lakini inaweza pia kuwa na umri na jinsia ya kesi yenyewe. Kumbuka kuwa ruhusa hii inamruhusu pia mtumiaji kuwewza kuona kiunganishi kinachokwenda kwenye tukio lililotengenezwa. - label: Tengeneza tukio kutoka kwenye kesi + explanation: Ruhusa hii inamruhusu mtumiaji kubonyeza kitufe cha "Tengeneza Tukio" . Hii itatengeneza tukio ambalo linaweza kuwa na taarifa iliyonakiliwa kutoka kwenye shauri. Kwa mashauri ya Udhalilishaji wa Kijinsia, kitufe hicho kiko juu katika ukurasa wa maonyesho ya mashauri, na inalingana na taarifa kuhusu mashauri yote. Kwenye baadhi ya muktadha wa ufuatiliaji wa matukio, kitufe hicho kipo kwenye fomu ndogo ambapo kitufe kilibonyezwa, pamoja na kutoka kwenye shauri lenyewe kwa jumla. Hii ni kwamba tukio jipya lililo tengenezwa linaweza kuwa na sehemu ya "Aina ya Ukatili" kutoka kwenye fomu ndogo ya mtu binafsi yenye maelezo ya tukio, lakini inaweza pia kujumuisha umri na jinsi ya shauri lenyewe. Kumbuka kwamba ruhusa hii pia inamruhusu mtumiaji kuwewza kuona kiunganishi ambacho kilitengenezwa. + label: Tengeneza tukio kutokana na shauri + remove_alert: + explanation: Hii inamruhusu mtumiaji kuondoa tahadhari kutoka kwenye shauri. Tahadhari kwa kawaida inatengenezwa pale ambapo sehemu husika inaporekebishwa, kama vile maelezo yanapoboreshwa. tahadhari kwa kawaida inaoneshwa kwa alama ya njano mbele ya shauri + label: Ondoa tahadhari katika shauri manage: - explanation: Inatoa ruhusa kwa mtumiaji kutekeleza shughuli zote zinazopatikana kuhusu kesi. Ruhusa ya "Kusimamia" ina maana ya "kila kitu" + explanation: inamruhusu mtumiaji kutekeleza shughuli zote zinazopatikana kuhusu shauri. Ruhusa ya "Kusimamia" ina maana ya "kila kitu" label: Simamia (ruhusa zote za aina hii ya rasilimali) read: - explanation: Uwezo wa kutazama / kuangalia kesi - label: Mtazamo / Tazama + explanation: Uwezo wa kuangalia shauri + label: Angalia receive_referral: explanation: Inamruhusu mtumiaji kupokea rufaa. Watumiaji wenye ruhusa wataonekana kama watu wenye uwezekano wa kushughulikia rufaa, wakati watumiaji ambao hawana ruhusa hiyo, hawataonekana kama ni watu wenye uwezekano huo wakati mtu atakapokuwa anaangalia mpokeaji katika mfumo wa rufaa - label: Kupokea Rufaa + label: Pokea Rufaa receive_referral_different_module: - explanation: Inaruhusu mtumiaji kupokea rufaa ya rekodi ambayo imetengenezwa katika moduli tofauti ya Primero. Watumiaji wenye ruhusa wataonekana kama watu wenye uwezekano wa kushughulikia rufaa kwa rekodi hiyo, wakati ambapo watumiaji ambao hawana ruhusa hiyo hawataonekana kuwa ni watu wenye uwezekano wa kupokea rufaa wakati mtu atakapotafuta mpokeaji katika mfumo wa rufaa. - label: Kupokea Rufaa kutoka kwa mtumiaji kutoka kwenye moduli tofauti + explanation: Inaruhusu mtumiaji kupokea rufaa ya kumbukumbu ambayo imetengenezwa nje ya Primero. Watumiaji wenye ruhusa wataonekana kama watu wenye uwezekano wa kushughulikia rufaa, wakati watumiaji ambao hawana ruhusa hiyo, hawataonekana kama ni watu wenye uwezekano huo wakati mtu atakapokuwa anaangalia mpokeaji katika mfumo wa rufaa + label: Kupokea Rufaa kutoka kwa mtumiaji kutoka nje ya moduli receive_transfer: - explanation: Inamruhusu mtumiaji kupokea uhamisho. Watumiaji wenye ruhusa hii wataonekana kama watu wenye uwezekano wa kupokea shughuli za uhamisho, wakati wale ambao hawana ruhusa hiyo, hawataonekana kama watu wenye uwezekano wa kupokea, pale ambapo mtu atakuwa anaangalia mpokeaji katika mfumo wa uhamisho. - label: Kupokea Uhamisho + explanation: Inamruhusu mtumiaji kupokea uhamisho. Watumiaji wenye ruhusa wataonekana kama wenye uwezo wa kushughulikia uhamishaji, wakati watumiaji ambao hawana ruhusa hiyo, hawataonekana kuwa ni wenye uwezo huo wakati mtu atakapokuwa anaangalia mpokeaji katika mfumo wa kuhamisha + label: Pokea Uhamisho referral: - explanation: 'Inamruhusu mtumiaji kuweza kumpa mtumiaji mwengine ufikiaji wa muda wa kesi. Mpokeaji wa rufaa ataweza kufanya shughuli zote za rufaa ya kesi iliyoletwa kama vile ambavyo wangeweza kufanya katika kesi zao wenyewe. Pale ambapo mpokeaji hahitaji tena kuifikia kesi hiyo, atabonyeza kitufe cha "Imekamilika" katika fomu ndogo ya Rufaa na Uhamisho, na hawatakuwa tena na uwezo wa kuifikia kesi hiyo. Unaweza kupeleka rufaa ya kesi kwa mtumiaji ambaye jukumu lake linamuwezesha kupkea rufaa. ' + explanation: Inamruhusu mtumiaji kumpa ruhusa ya muda mfupi mtumiaji mwengine kuweza kufikia shauri. Mpokeaji wa rufaa ataweza kufanya shughuli zote za rufaa ya shauri kama vile ambavyo wangeweza kufanya katika mashauri yao wenyewe. Pale ambapo mpokeaji hahitaji tena kuifikia shauri, atabonyeza kitufe cha "Imekamilika" katika fomu ndogo ya Rufaa na Uhamisho, na hawatakuwa na uwezo wa kuifikia shauri hilo. Unaweza kupeleka rufaa ya shauri kwa mtumiaji ambaye jukumu lake linamuwezesha kupokea rufaa. label: Rufaa referral_from_service: - explanation: Inamruhusu mtumiaji kukiona kitufe cha "Rufaa" katika fomu ndogo ya Huduma. Mtumiaji atakapobonyeza kitufe hiki, mfumo wa rufaa utaonekana ukiwa na maandishi yafuatayo, Aina ya Huduma, Wakala, Mtoa Huduma, na sehemu za Eneo zimezimwa, lakini zimejazwa taarifa kiotomatiki katika fomu ndogo ya Huduma ambayo mtumiaji alibonyeza kitufe cha Rufaa. - label: Rejea Kesi kutoka fomu ndogo ya Huduma + explanation: Inamruhusu mtumiaji kuona kitufe cha "Rufaa" katika fomu ndogo ya Huduma. Mtumiaji atakapobonyeza kitufe hicho, mfumo wa rufaa utaonekana ukiwa na maandishi yafuatayo, Aina ya Huduma, Taasisi, Mtoa Huduma, na sehemu za Eneo zimezimwa, lakini taarifa zinajijaza wenyewe katika fomu ndogo ya Huduma ambayo mtumiaji alibonyeza kitufe cha Rufaa. + label: Angalia shauri kutoka fomu ndogo ya Huduma remove_assigned_users: - explanation: 'Inamruhusu mtumiaji kuwaondoa watumiaji wengine kutoka kwenye sehemu ya "Watumiaji Wengine Waliopewa Ruhusa". Mtumiaji huorodheshwa hapa ikiwa atakuwa amepokea rufaa ya kesi au amepokea uhamisho wa kesi, lakini bado hajaikubali au kuikataa. Utakapomtoa mtumiaji kutoka kwenye sehemu ya "Watumiaji Wengine Waliopewa Ruhusa", unawaondolea uwezo wao wa kuifikia kesi. Kwa hivyo watumiaji waliopewa ruhusa hii wanaweza kuwazuiya watumiaji wengine ambao waliwahi kupokea rufaa au waanaosubiri kupokea kesi za uhamisho, wasiweze tena kufikia kesi hizo. Kumbuka kuwa ruhusa hii inafanya kazi pale tu ambapo mtumiaji wa sasa anao uwezo wa kuhariri kesi. ' - label: Ondoa watumiaji wengine waliopewa ruhusa (Kuondoa ufikiaji wa kesi kwa watumiaji waliorejelewa kesi) + explanation: Inamruhusu mtumiaji kuwaondoa watumiaji wengine kutoka kwenye sehemu ya "Watumiaji Wengine Waliopewa Ruhusa". Mtumiaji huorodheshwa hapa ikiwa atakuwa amepokea rufaa ya shauri au amepokea uhamisho wa mashauri, lakini bado hajaikubaliwa au kuikataa. Utakapomtoa mtumiaji kutoka kwenye sehemu ya "Watumiaji Wengine Waliopewa Ruhusa", unawaondolea uwezo wao wa kuifikia shauri. Kwa hivyo watumiaji waliopewa ruhusa hii wanaweza kuondoa uwezo wa kufikia shauri kwa watumiaji wengine ambao waliwahi kupokea rufaa au wanaosubiri kupokea hamisho la shauri, Zingatia kwamba, ruhusa hii inafanya kazi pale tu ambapo mtumiaji wa sasa anao uwezo wa kurekebisha shauri. + label: Ondoa watumiaji wengine waliopewa ruhusa (Rudisha mashauri kutoka kwa aliyepewa rufaa kwenda kwa mtumiaji) reopen: - explanation: Inamruhusu mtumiaji kufungua kesi ambayo kwa sasa imefungwa + explanation: Inamruhusu mtumiaji kufungua shauri ambayo kwa sasa imefungwa label: Fungua tena request_approval_action_plan: - explanation: Inamruhusu mtumiaji (mara nyingi anakuwa ni mfanyakazi wa kesi) kumuomba meneja wao aidhinishe kesi zake%{approval_label} - label: 'Omba %{approval_label}kibali ' + explanation: Inamruhusu mtumiaji (kwa kawaida muendesha shauri) kumuomba meneja wao athibitishe shauri lao%{approval_label} + label: Ombi %{approval_label}Uthibitisho request_approval_assessment: - explanation: Inamruhusu mtumiaji (mara nyingi anakuwa ni mfanyakazi wa kesi) aombe meneja wao aidhinishe kesi zake%{approval_label} - label: Omba %{approval_label}kibali + explanation: Inamruhusu mtumiaji (kwa kawaida muendesha shauri) kumuomba meneja wao athibitishe shauri lao%{approval_label} + label: Ombi %{approval_label}Uthibitisho request_approval_bia: - explanation: Inamruhusu mtumiaji (mara nyingi anakuwa ni mfanyakazi wa kesi) kuomba meneja wao aidhinishe kesi zake%{approval_label} - label: Omba %{approval_label}Kibali + explanation: Inamruhusu mtumiaji (kwa kawaida muendesha shauri) kumuomba meneja wao athibitishe shauri lao%{approval_label} + label: Ombi %{approval_label}Uthibitisho request_approval_case_plan: - explanation: Inamruhusu mtumiaji (mara nyingi anakuwa ni mfanyakazi wa kesi) kuomba meneja wao aidhinishe kesi zake%{approval_label} - label: Omba %{approval_label}Kibali + explanation: Inamruhusu mtumiaji (kwa kawaida muendesha shauri) kumuomba meneja wao athibitishe shauri lao%{approval_label} + label: Ombi %{approval_label}Uthibitisho request_approval_closure: - explanation: Inamruhusu mtumiaji (mara nyingi anakuwa ni mfanyakazi wa kesi) kuomba meneja wao aidhinishe kesi zake%{approval_label} - label: Omba %{approval_label}Kibali + explanation: Inamruhusu mtumiaji (kwa kawaida muendesha shauri) kumuomba meneja wao athibitishe shauri lao%{approval_label} + label: Ombi %{approval_label}Uthibitisho request_approval_gbv_closure: - explanation: Inamruhusu mtumiaji (mara nyingi anakuwa ni mfanyakazi wa kesi) kuomba meneja wao aidhinishe kesi zake %{approval_label} - label: Omba %{approval_label}Kibali + explanation: Inamruhusu mtumiaji (kwa kawaida muendesha shauri) kumuomba meneja wao athibitishe shauri lao%{approval_label} + label: Ombi %{approval_label}Uthibitisho request_transfer: - explanation: 'Inaonyesha kitufe cha "Omba Uhamisho" kwenye "Tazama Mfumo". Kitufe kinamruhusu mtumiaji kutuma ujumbe wenye maelezo ya kibinafsi kwa kupitia baruapepe kwenda kwa mmiliki wa rekodi ya kesi wa sasa hivi, akimuomba mmiliki wa rekodi kuihamisha kesi kwenda kwa mtumiaji aliyetuma ombi hilo. Hii inasaidia sana katika mazingira ambayo watoto wanabadilisha maeneo yao mara kwa mara, na ambapo wafanyakazi wa kesi watahitaji mfanyakazi wa kesi aliyeishughulikia hapo awali atume taarifa kuhusu mtoto huyo ili wasijekutengeneza nakala nyingine ya rekodi. ' + explanation: 'Inaonyesha kitufe cha "Omba Uhamisho" kwenye "Sehemu ya Kutazama". Kitufe kinamruhusu mtumiaji kutuma ujumbe wenye maelezo binafsi kwa kupitia baruapepe kwenda kwa mmiliki wa sasa wa kumbukumbu ya shauri, akimuomba mmiliki wa kumbukumbu kulihamisha shauri kwenda kwa mtumiaji aliyetuma ombi hilo. Hii inasaidia sana katika mazingira ambayo watoto wanabadilisha maeneo yao mara kwa mara, na waendesha shauri watahitaji muendesha shauri la mtoto aliyeishughulikia hapo kabla atume taarifa kuhusu mtoto huyo ili kuepusha kurejea kwa kumbukumbu ' label: Omba Uhamisho search_owned_by_others: - explanation: 'Inamruhusu mtumiaji kufanya utafiti wa rekodi ambazo kwa kawaida hawana uwezo wa kuzifikia, huenda ni kwa sababu sio wamiliki wa rekodi za kesi hiyo au (kwa mameneja) kwa sababu wamiliki wa rekodi hizo hawamo katika kikundi chao cha watumiaji. Kumbuka kwamba ingawa mtumiaji ataiona kesi katika matokeo ya utafiti wake, hawataweza kubonyeza kwenye ukurasa wa onyesho la kesi kwa kesi hiyo, ikiwa na maana kuwa hawatakuwa na uwezo wa kuona taarifa ya kina kuhusu kesi hiyo. ' - label: Tafuta rekodi nyingine za kesi zinazomilikiwa na watumiaji wengine + explanation: Inamruhusu mtumiaji kutafuta kumbukumbu ambazo kwa kawaida hawana uwezo wa kuzifikia, huenda ni kwa sababu sio wamiliki wa kumbukumbu za shauri hilo au (kwa mameneja) kwa sababu mmiliki wa kumbukumbu hizo sio miongoni mwa kikundi cha watumiaji. Kumbuka kwamba, ingawa mtumiaji ataliona shauri katika matokeo ya kutafuta kwake, hawataweza kubonyeza kwenye ukurasa wa onyesho la shauri hilo, ikiwa na maana kuwa hawatakuwa na uwezo wa kuona taarifa ya kina kuhusu shauri hilo. + label: Tafuta kumbukumbu za shauri zinazomilikiwa na watumiaji wengine service_provision_incident_details: - explanation: Inamruhusu mtumiaji kukiona kitufe kilichoandikwa "Hifadhi na Ongeza Utoaji wa Huduma" upande wa chini wa mfumo wa Ongeza Tukio. Kubonyeza kitufe hiki kutaihifadhi taarifa ambayo imeingizwa sasa hivi kuhusu tukio, na baada ya hapo kumchukua mtumiaji kwenda kwenye mfumo wa shughuli za Ongezab Utoaji wa Huduma. Kwa vile kitendo hiki kimeunganishwa moja kwa moja na vitendo vya Ongeza Tukio na Ongeza Huduma. Italeta maana ikiwa kupewa ruhusa hii kutafunganishwa na jukumu ikiwa jukumu hilo llinayo ruhusa ya "Ongeza Maelezo ya Tuklio kwenda kwa mtumiaji mwingine wa kesi" na "Ongeza utoaji wa Huduma kweenda kwa mtumiaji mwingine wa kesi" - label: Angalia Kitufe cha Ongeza Utowaji wa Huduma au Mfumo wa Maelezo ya Tukio. + explanation: 'Inamruhusu mtumiaji kuona kitufe kilichoandikwa "Hifadhi na ongeza utoaji wa huduma” upande wa chini wa Ongeza sehemu ya Tukio. Kubonyeza kitufe hichi kutaihifadhi taarifa ambayo imeingizwa sasa hivi kuhusu tukio, na baada ya hapo kumchukua mtumiaji mojakwamoja kwenye mfumo katika sehemu ya Ongeza Utoaji wa Huduma. Kwa vile kitendo hiki kimeunganishwa moja kwa moja na vitendo vya Ongeza Tukio na Ongeza Huduma. Italeta maana kutoa ruhusa hii la jukumu ikiwa jukumu hilo llinayo ruhusa ya "Ongeza Maelezo ya Tukio kwenda kwa mtumiaji mwengine wa shauri" na "Ongeza utoaji wa Huduma kwenda kwa mtumiaji mwingine wa kuruhusu shauri" ' + label: Angalia Kitufe cha kuongeza sehemu ya maelezo ya tukio services_section_from_case: - explanation: Uwezo wa kuongeza kiingilio cha fomu ndogo ya Huduma au kwenye kesi uliyoiona katika matokeo ya utafiti, lakini ambayo wewe huwezi kuifikia. Mtumiaji anafanya kitendo hiki kutoka kwenye ukurasa wa matokeo ya utafiti kwa kuchagua kesi moja ua zaidi, na baada ya hapo kuchagua "Ongeza Utoaji Huduma" kutoka kwenye orodha ya vitendo. Baada ya hapo mtumiaji ataona mfumo wenye maeneo yote katika fomu ndogo ya Huduma, pahala ambapo wataweza kuingia na kuwasilisha taarifa kuhusu huduma. Kwa sababu kitendo hiki kinaweza kufanyika kutoka kwenye ukurasa wa matokeo ya utafiti pekee, italeta maana ikiwa mwenye jukumu aitakaekuwa na ruhusa hii atakuwa pia na ruhusa ya "Kutafuta rekodi za kesi zinazomilikiwa na watumiaji wengine" - label: Ongeza utoaji wa Huduma kwa mtumiaji mwengine wa kesi + explanation: Uwezo wa kuongeza kiingilio cha fomu ndogo ya Huduma katika shauri uliyoiona katika matokeo ya utafutaji, lakini ambayo wewe huwezi kuifikia. Mtumiaji anafanya kitendo hichi kutoka kwenye ukurasa wa matokeo ya utafutaji kwa kuchagua shauri  moja ua zaidi, na baada ya hapo kuchagua "Ongeza Utoaji wa Huduma" kutoka kwenye orodha ya vitendo. Baada ya hapo mtumiaji ataona mfumo wenye maeneo yote katika fomu ndogo ya Huduma, ambapo wataweza kuingiza na kuwasilisha taarifa kuhusu huduma. Kwa sababu kitendo hiki hufanyika kutoka kwenye ukurasa wa matokeo ya utafutaji pekee, italeta maana ikiwa mwenye jukumu atakaekuwa na ruhusa hii atakuwa pia na ruhusa ya "Kutafuta kumbukumbu ya shauri linalomilikiwa na watumiaji wengine" + label: Ongeza utoaji wa Huduma kwa mtumiaji mwengine wa shauri sync_external: - explanation: 'Uwezo wa kusawazisha Rekodi pamoja na mfumo wa nje wa usimamizi wa taarifa ' - label: 'Kusawazisha na mfumo wa nje wa usimamizi wa taarifa ' + explanation: 'Uwezo wa kusawazisha kumbukumbu pamoja na mfumo wa nje wa usimamizi wa taarifa ' + label: 'Kusawazisha kumbukumbu pamoja na mfumo wa nje wa usimamizi wa taarifa ' sync_mobile: - explanation: Inamuwezesha mtumiaji kuzihifadhi kesi kwa matumizi nje ya mtandao + explanation: Inamuwezesha mtumiaji kuhifadhi shauri kwa matumizi ya nje ya mtandao label: Alama kwa Nje ya Mtandao transfer: - explanation: Inamruhusu mtumiaji kutuma / kupeleka kesi kutoka kwa mmiliki wa rekodi wa sasa kwenda kwa mtumiaji yeyote kwenye mfumo ambaye anao uwezo wa kupokea uhamisho. Umiliki wa rekodi ya kesi haubadiliki, hata hivyompaka hapo mpokeaji wa uhamisho huo "atakapoikubali". Ikiwa mpokeaji "ataukataa" uhamisho ho, mpokeaji huyo atakuwa hawezi tena kuifikia kesi hiyo, na rekodi hiyo itabaki na mmiliki wake wa asili + explanation: Inamruhusu mtumiaji kutuma shauri kutoka kwa mmiliki wa kumbukumbu wa sasa kwenda kwa mtumiaji yeyote kwenye mfumo ambaye anao uwezo wa kupokea uhamisho. Umiliki wa kumbukumbu wa shauri habadiliki, hata hivyo mpaka hapo mpokeaji wa uhamisho huo "atakapokubali". Ikiwa mpokeaji "ataukataa" uhamisho, mpokeaji huyo atakuwa atapoteza uwezo wa kulifikia shauri hilo na litabaki kwa mmiliki wake wa awali label: Uhamisho view_photo: - explanation: 'Inamruhusu mtumiaji kuweza kuona picha za kesi kutoka kwenye muonekano wa orodha ya kesi. Bila ya kuwa na ruhusa, mtumiaji hawezi kuiona safu wima ya "Picha" ya jadweli ya orodha ya kesi, au aikon za picha zinazoonekana hapo. Ruhusa hii inamruhusu pia mtumiaji kuziona picha za mtoto katika "Tazama Mfumo" ' - label: Tazama Picha kutoka kwenye orodha ya kuona kesi + explanation: Inamruhusu mtumiaji kuweza kuona picha ya shauri kutoka kwenye muonekano wa orodha ya shauri. Bila ya ruhusa hii mtumiaji hawezi kuiona picha katika upande wa orodha ya jaduweli. au alama ya picha inayojitokeza hapo. Ruhusa hii inamruhusu pia mtumiaji kuziona picha ya mtoto katika sehemu ya kuona + label: Angalia Picha kutoka kwenye orodha ya kuona shauri view_incident_from_case: - explanation: Wakati wa kuangalia Kesi, Mtumiaji ataweza kuona orodha ya Matukio iiliyounganishwa na Kesi, pamoja na taarifa fupi ya kila kesi. - label: Tazama Matukio kutoka kwenye Kesi + explanation: Wakati wa kuangalia shauri, Mtumiaji ataweza kuona orodha ya Matukio yaliyounganishwa na shauri, pamoja na taarifa kwa muhtasari kwa kila moja + label: Angalia matukio kutoka kwenye shauri view_protection_concerns_filter: - explanation: Inamuwezesha mtumiaji kuona kichujo cha masuala ya hifadhi katika ukurasa wa orodha ya kesi - label: Tazama kichujo cha Masuala ya Hifadhi katika ukurasa wa orodha ya kesi + explanation: Inamuwezesha mtumiaji kuona kichujo cha shaka ya hifadhi katika ukurasa wa orodha ya shauri + label: Tazama kichujo cha Shaka ya Hifadhi katika ukurasa wa orodha ya shauri view_registry_record: - explanation: Inamuwezesha mtumiaji kuziona taarifa za Usajili zilizounganishwa na Kesi. Pia inamuwezesha mtumiaji kuiona fomu ya maelezo ya Usajili kuhusu Kesi - label: Tazama rekodi ya Usajili kutoka kwenye Kesi + explanation: Inamuwezesha mtumiaji kuziona taarifa za Usajili zilizounganishwa na Shauri. Pia inamuwezesha mtumiaji kuiona fomu ya maelezo ya Usajili kuhusu Shauri + label: Tazama Kumbukumbu ya Usajili kutoka kwenye Shauri write: - explanation: Uwezo wa kubonyeza kitufe cha "Kuhariri", ingeza taarifa mpya kwenye kesi na ubonyeze "Hifadhai" - label: Kuhariri + explanation: Uwezo wa kubonyeza kitufe cha "Kurekebisha", Boresha taarifa ya shauri na ubonyeze "Hifadhi" + label: Rekebisha accept_or_reject_transfer: - explanation: Inamuwezesha mtumiaji kukubali au kukataa uhamisho kwa niaba ya mtumiaji mwengine ambaye yuko katika timu yako (kwa mfano, msimamizi kuukubali uhamisho ambao umepelekwa kwa mfanyakazi wao wa kijamii) + explanation: Inamuwezesha mtumiaji kukubali au kukataa uhamisho kwa niaba ya mtumiaji mwengine ambaye yuko katika timu yako (kwa mfano, msimamizi kuukubali uhamisho ambao uliotumwa kwa Afisa Ustawi) label: Kubali au kataa uhamisho kwa mtumiaji mwengine kwenye timu yako list_case_names: - explanation: Wasimamizi kwa kawaida hawawezi kuona majina ya Kesi kwenye Orodha ya Kesi. Ikiwa msimamizi atakuwa na ruhusa hii, atakuwa na uwezo wa kuyaona majina kwenye orodha - label: Ikiwa msimamizi ataweza kuyaona majina ya Kesi katika Orodha ya Kesi + explanation: Meneja kwa kawaida hawawezi kuona majina ya Shauri kwenye Orodha ya mashauri. Ikiwa meneja atakuwa na ruhusa hii, atakuwa na uwezo wa kuyaona majina kwenye orodha + label: Ikiwa meneja ataweza kuyaona majina ya Shauri katika Orodha ya mashauri mark_for_offline: - explanation: Inamuwezesha mtumiaji kuihifadhi Kesi kwa matumizi nje ya mtandao + explanation: Inamuwezesha mtumiaji kuhifadhi Shauri kwa matumizi nje ya mtandao label: Alama kwa Nje ya Mtandao - explanation: Inamuwakilisha mtoto binafsi, aliyenusurika au mnufaika mwengine - label: Kesi + view_family_record: + explanation: Mtumiaji anaweza kuona fomu ya "Kumbukumbu ya Familia" kwenye shauri inayojumuisha kiunganishi katika kumbukumbu ya familia kwenye shauri + label: Angalia kumbukumbu ya familia kwenye shauri + case_from_family: + explanation: Watumiaji wanaweza kutengeneza shauri kwa ajili ya mmoja kati ya wanafamilia kwenye maelezo ya fomu ndogo ya familia. Zingatia kwamba kumbukumbu za familia zitajitengeza wenyewe ili kuunganisha mashauri haya mawili + label: Tengeneza shauri kwa maelezo ya familia + link_family_record: + explanation: Inamruhusu mtumiaji kutafuta na kuunganisha kumbukumbu ya familia iliyopo kwenye shauri lao. Pia inawaruhusu watumiaji kutounganisha kumbukumbu ya familia kwenye shauri + label: Kuunga/ kutounga kumbukumbu ya familia kwenye shauri + explanation: Inamuwakilisha mtoto binafsi, manusura au mnufaika mwengine + label: Shauri dashboard: actions: approvals_action_plan: - explanation: Inaonyesha nambari ya kesi ya mtumiaji wa sasa pamoja na maombi ya kuidhinishwa kwa Mpango wa Utekelezaji ambayo bado Yanasubiri, Yaliyoidhinishwa, au Yaliyokataliwa. - label: Vibali vya %{approval_label}Mfanyakazi wa kesi. + explanation: Inaonyesha idadi ya mashauri ya mtumiaji kwa sasa pamoja na maombi ya kuthibitishwa kwa Mpango wa Utekelezaji ambayo bado Yanasubiri, Yaliyothibitishwa, au Yaliyokataliwa. + label: Mwendesha shauri %{approval_label}uthibitisho. approvals_action_plan_pending: - explanation: 'Inaonyesha idadi ya kesi katika timu ya meneja ambazo zinayo maombi yanayosubiri ya kuidhinishwa Mpango wa Utekelezaji ' - label: Vibali / Idhini%{approval_label}ya Meneja + explanation: 'Inaonyesha idadi ya mashauri katika timu ya meneja ambazo zina maombi yanayosubiri ya kuthibitishwa Mpango wa Utekelezaji ' + label: Meneja%{approval_label}Uthibitisho approvals_assessment: - explanation: 'Inaonyesha idadi ya kesi za mtumiaji wa sasa zenye maombi ya idhini ya tathmini ambayo Yanasubiri, Yaliyokubalika / Yaliyoidhinishwa au Yaliyokataliwa. ' - label: Vibali %{approval_label}vya wafanyakazi wa kesi + explanation: 'Inaonesha idadi ya mashauri ya mtumiaji wa sasa zenye maombi ya tathmini yaliyothibitishwa ambayo Yanasubiri, Yaliyothibitishwa au Yaliyokataliwa. ' + label: Muendesha Shauri %{approval_label}Uthibitisho approvals_assessment_pending: - explanation: Inaonyesha idadi ya kesi katika timu ya meneja yenye maombi ya kuidhinishwa Tathmini ambayo bado yanasubiri - label: Vibali / Idhini %{approval_label}ya meneja + explanation: 'Inaonesha idadi ya mashauri katika timu ya meneja yenye maombi ya Tathmini yanayo subiri kuthibitishwa ' + label: Meneja %{approval_label}Uthibitisho approvals_case_plan: - explanation: Inaonyesha idadi ya kesi ya mtumiaji wa sasa zenye maombi ya kuidhinishwa kwa Mpango wa Kesi ambayo Yanasubiri, Yameidhinishwa, au Yamekataliwa. - label: Vibali %{approval_label}vya mfanyakazi wa kesi + explanation: Inaonesha idadi ya mashauri ya watumiaji kwa sasa zenye maombi ya kuithibitishwa kwa Mpango wa shauri ambao Unasubiri, Umethibitishwa, au Umekataliwa. + label: Muendesha Shauri%{approval_label}Uthibitisho approvals_case_plan_pending: - explanation: Inaonyesha idadi ya kesi kwenye timu ya meneja yenye maombi ya kuidhinishwa kwa Mpango wa Kesi ambayo yanasubiri - label: Vibali / Idhini %{approval_label}ya meneja + explanation: Inaonesha idadi ya mashauri katika timu ya meneja yenye maombi ya Tathmini yanayo subiri kuthibitishwa + label: Meneja %{approval_label}Uthibitisho approvals_closure: - explanation: Inaonyesha idadi ya kesi za mtumiaji wa sasa zenye maombi ya kuidhinishwa Kufungwa ambayo bado Yanasubiri, Yameidhinishwa, au Yamekataliwa - label: Vibali %{approval_label}vya Mfanyakazi wa kesi + explanation: Inaonesha Idadi ya mashauri ya watumiaji wa sasa yenye maombi ya kuthibitishwa kufungwa ambayo yanasuburi, Yaliothibitishwa, Yaliokataliwa. + label: Muendesha Shauri %{approval_label}Uthibitisho approvals_closure_pending: - explanation: Inaonyesha idadi ya kesi kwenye timu ya meneja zenye maombi yanayosubiri ya kuidhinishwa Kufungwa. - label: Vibali / Idhini %{approval_label}ya meneja + explanation: Inaonesha idadi ya mashauri kwenye timu ya meneja ambayo yanayosubiri maombi ya Uthibitisho wa Kufungwa. + label: Meneja %{approval_label}Uthibitisho approvals_gbv_closure: - explanation: Inaonyesha idadi ya kesi za mtumiaji wa sasa zenye maombi ya kuidhinishwa Kufungwa kwa kesi za Udhalilishaji wa Kijinsia ambayo Yanasubiri, Yameidhinishwa, au Yamekataliwa - label: Vibali %{approval_label}vya mfanyakazi wa kesi + explanation: Inaonesha idadi ya mashauri ya watumiaji wa sasa ambayo yana maombi ya uthibitisho wa Kufungwa kwa Udhalilishaji wa Kijinsia ambayo Yanasubiri, Yaliyothibitishwa, au Yaliyokataliwa + label: Muendesha Shauri %{approval_label}Uthibitisho approvals_gbv_closure_pending: - explanation: 'Inaonyesha idadi ya kesi kwenye timu ya meneja zenye maombi yanayosubiri kuidhinishwa Kufungwa kwa kesi ya Udhalilishaji wa Kijinsia ' - label: Vibali / Idhini %{approval_label}ya meneja + explanation: 'Inaonesha idadi ya mashauri kwenye timu ya meneja yenye maombi yanayosubiri Uthibitisho wa Kufungwa kwa Udhalilishaji wa Kijinsia ' + label: Meneja %{approval_label}Uthibitisho case_overview: - explanation: Kadi ya dashbodi ya muhtasari iliyopo juu kwenye ukurasa wa nyumbani, ambayo inajumuisha takwimu kama vile Jumla na Kesi mpya + explanation: Ukurasa wa Mwanzo unaonesha Mukhtasari wa idadi ya mashauri kama vile jumla na mashauri mapya label: Dashbodi ya Muhtasari case_risk: - explanation: Inaonyesha ni kesi ngapi ziko katika kiwango cha hatari - label: Kesi kwa kiwango cha hatari + explanation: Inaonesha mashauri mangapi yapo katika kiwango cha hatari + label: Mashauri kwa kiwango cha hatari cases_by_task_overdue_assessment: - explanation: Inamruhusu meneja kuweza kuona idadi ya kesi zenye kazi za tathmini zilizochelewa kwa kila mmoja ya mfanyakazi wa kesi + explanation: Inamruhusu meneja kuweza kuona mashauri ambayo tathmini zake zimechelewa kwa kila mmoja ya waendesha mashauri label: Kazi za Tathmini zilizochelewa cases_by_task_overdue_case_plan: - explanation: Inamruhusu meneja kuona ni kesi ngapi ambazo zinazo kazi za Mpango wa Kazi zilizochelewa kwa kila mfanyakazi wa kesi. - label: Kazi za Mpango wa Kesi zilizochelewa. + explanation: Inamruhusu meneja kuona mashauri mangapi ambayo Mpango Kazi wa mashauri umechelewa kwa kila mmoja ya waendesha mashauri + label: Mpango kazi wa Shauri uliochelewa cases_by_task_overdue_followups: - explanation: Inamruhusu meneja kuona ni kesi ngapi zenye kazi za Ufuatiliaji zilizochelewa kwa kila mmoja ya wafanyakazi wa kesi - label: Kazi za Ufuatiliaji zilizochelewa + explanation: Inamruhusu meneja kuona mashauri mangapi ambayo Ufuatiliaji wake umechelewa kwa kila mmoja ya waendesha mashauri. + label: Kuchelewa kwa kazi ya Ufatiliaji cases_by_task_overdue_services: - explanation: Inamruhusu meneja kuona idadi ya kesi zenye kazi za Huduma zilizocheleweshwa kwa kila mmoja ya wafanyakazi wa kesi - label: Kazi za Huduma Zilizocheleweshwa. + explanation: Inamruhusu meneja kuona mashauri mangapi ambayo utoaji wa huduma umechelewa kwa kila mmoja ya waendesha mashauri. + label: Uchelewaji wa kutoa huduma dash_case_incident_overview: - explanation: . - label: Muhtasari wa - Kesi Zangu / Matukio Yangu + label: Muhtasari wa - Mashauri yangu / Matukio dash_cases_by_social_worker: - explanation: Jedwali linaloonesha ni kwa namna gani jumla ya kesi zilizofunguliwa na idadi ya kesi mpya zinazosimamiwa na kila mtumiaji katika kikundi cha watumiaji wa sasa. Kila safuni mtumiaji katika vikundi vya watumiaji wa sasa, wakati "Jumla" na "Mpya"ni safu wima mbili. - label: Kuangalia Kesi na Wafanyakazi wa Kijamii + explanation: Jedwali linaloonesha ni kwa namna gani jumla ya mashauri yaliyofunguliwa na idadi ya mashauri mapya zinazosimamiwa na kila mtumiaji katika kikundi cha watumiaji wa sasa. Kila safu inawakilisha mtumiaji katika vikundi vya watumiaji wa sasa, wakati "Jumla" na "Mpya"ni safu wima mbili. + label: Kuangalia mashauri kwa Afisa Ustawi dash_cases_to_assign: - explanation: 'MUHIMU: Kwa mameneja tu,. Inaonyesha idadi ya kesi zinazomilikiwa moja kwa moja na mmiliki wa sasa (ni lazima awe meneja). Dashbodi hii inachukulia kuwa meneja hawasimamii kesi zao wenyewe, na ikiwa meneja atakuwa na kesi yake, mwenyewe, itawabidi wamkabidhi mfanyakazi wa kesi katika timu yake.' - label: Kwa Kesi za (Mameneja) Inabidi niwakabidhi watu kwenye timu yangu + explanation: 'MUHIMU: Kwa mameneja tu. Inaonyesha idadi ya mashauri yanayomilikiwa moja kwa moja na utumiaji wa sasa (ni lazima awe meneja). Dashbodi hii inachukulia kuwa mameneja hawasimamii mashauri yao wenyewe, na ikiwa meneja atakuwa na mashauri yake mwenyewe, itawabidi wamkabidhi waendehsa mshauri wa timu yake.' + label: (Kwa Mameneja) mashauri ninayohitaji kukabidhi kwa timu yangu. dash_flags: - explanation: Inaonyesha orodha ya bendera ambazo watumiaji wengine wameziongeza kwenye rekodi zangu, pamoja na bendera nilizoziongeza mimi mwenyewe kwenye rekodi za watumiaji wengingine. - label: Rekodi zilizotiwa Alama + explanation: Inaonesha orodha ya vibendera ambavyo watumiaji wengine wameziongeza kwenye kumbukumbu zangu, pamoja na vibendera nilivyoviongeza kwenye rekodi za watumiaji wengine. + label: Kumbukumbu zilizowekwa vibendera dash_group_overview: - explanation: Inamuonyesha meneja idadi ya kesi zilizoko wazi / zinazoendelea na zilizofungwa zinazosimamiwa na watumiaji katika timu zao - label: Kesi za Kikundi Changu + explanation: Inamuonyesha meneja idadi ya mashauri yaliyowazi na waliyofungwa ambayo yamesimamiwa na watumiaji wa kwenye timu yao + label: Mashauri ya Kundi langu dash_matching_results: - explanation: 'IMESHUKA THAMANI: Dasbodi hii haifanyi kazi na itaondolewa ndani ya x2.' - label: Tazama Matokeo Yanayolingana + explanation: 'KUKATALIWA: Dasbodi hii haifanyi kazi na itaondolewa ndani ya v2.' + label: Tazama Matokeo Yanayowiyana dash_protection_concerns: - explanation: 'Jedwali linaloonyesha ni kesi ngapi zina masuala ya kila ulinzi. Kila safu moja ya Jedwali ni suala la ulinzi, wakati safu wima zinaonyesha hadhi tofauti kwa kesi ("Kesi Zote", "Kesi zilizoko Wazi/ Zinazoendelea", "Mpya (za wiki hii)", "Zimefungwa (wiki hii)") ' - label: Kesi kwa Masuala ya Ulinzi + explanation: 'Jedwali linaloonyesha ni mashauri mangapi yenye shaka ya hifadhi. Kila safu ya Jedwali ni shaka ya hifadhi, wakati safu wima inaashiria hali tofauti za mashauri ("Mashauri yote", "Mashauri ya Wazi" "Mpya (za wiki hii)", "Zimefungwa (wiki hii)") ' + label: Mashauri kwa Shaka ya Hifadhi dash_protection_concerns_by_location: - explanation: Hii ni sawa na dashbodi ya "Tazama Masuala ya Ulinzi" isipokuwa hapa ni kuwa mtumiaji anaweza kuchagua eneo kutoka kwenye orodha inayoonyesha takwimu za kuenea kwa masuala /wasiwasi wa ulinzi katika eneo. - label: Tazama Masuala ya Ulinzi Kwa Eneo + explanation: Hii ni sawa na "Tazama Shaka ya Hifadhi" kwenye dashbodi isipokuwa hapa ni kuwa mtumiaji anaweza kuchagua eneo liliopo inayoonyesha takwimu za shaka ya hifadhi inayojitokeza katika eneo hili. + label: Tazama Shaka ya Hifadhi kwa eneo dash_reporting_location: - explanation: 'Jedwali linaloonyesha ni kesi ngapi zipo katika kila eneo (katika ngazi moja maalum kama vile "Mkoa" au "Wilaya"). Kila safu ya Jedwali ni eneo na safu wima inaashiria hadhi tofauti ya kesi hiyo ("KESI ZILIZOKO WAZI/ ZINAZOENDELEA", "MPYA (WIKI ILIYOPITA)", "MPYA (WIKI HII)", "IMEFUNGWA (WIKI ILIYOPITA)", IMEFUNGWA (WIKI HII)'' ). Mara nyingi hutumika kwa meneja au akaunti za usimamizi. ' - label: Kesi kwa Eneo la kutoa Ripoti + explanation: 'Jedwali linaloonyesha mashauri mangapi yapo katika kila eneo (katika ngazi moja maalum kama vile "Jimbo" au "Wilaya"). Kila safu mlalo ya Jedwali ni eneo na safu wima linaonesha hali tofauti ya mashauri ("SHAURI LILILOWAZI", "JIPYA (WIKI ILIYOPITA)", "JIPYA (WIKI HII)", "LILILOFUNGWA (WIKI ILIYOPITA)", LILILOFUNGWA (WIKI HII)'' ). Kwa Kawaida hutumika kwa akaunti ya meneja au msimamizi wa mfumo. ' + label: Mashauri kwa Eneo linalotolewa Taarifa dash_service_provisions: - explanation: 'Inaonyesha idadi ya kesi ambazo ziliwahi kuwa na watumiaji wegine ambao waliwahi kuongezewa masharti ya huduma kwao. Idadi hiyo itaonekana katika sehemu kubwa ya dasbodi ' - label: Kesi kwa aina ya Utoaji wa Huduma + explanation: 'Inaonyesha idadi ya mashauri waliokuwanayo watumiaji wengine ambao waliwahi kuongezewa utoaji wa huduma. Idadi hii inaonekana katika eneo kuu la dashbodi ' + label: Mashauri kwa aina ya Utoaji wa Huduma dash_shared_from_my_team: - explanation: Inamuonesha meneja idadi ya kesi zinazosimamiwa na kila mtumiaji katika timu, ambazo zinapelekwa rufaa au zinahamishwa kwenda kwa watumiaji wengine. - label: Imesambazwa Kutoka kwenye Timu Yangu + explanation: Inamuonesha meneja idadi ya mashauri yaliosimamiwa na kila mtumiaji katika timu, ambayo yamefanyiwa rufaa au yamehamishiwa kwa watumiaji wengine. + label: Imetumwa kutoka kwenye timu yangu dash_shared_with_me: - explanation: Inaonyesha ni kesi ngapi zilizoltwa kama rufaa au uhamisho kuja kwako - label: Zimewasilishwa Kwangu + explanation: Inaonesha ni mashauri mangapi yaliyofanyiwa rufaa au yaliyohamishwa kuja kwako + label: Yaliyotumwa kwangu dash_shared_with_my_team: - explanation: Inamuonyesha meneja idadi ya kesi zilizoletwa kama rufaa au uhamisho kwa kila mtumiaji mmoja katika timu yao - label: Imesambazwa kwa Timu Yangu + explanation: Inamuonesha meneja idadi ya mashauri yaliyofanyiwa rufaaa au yaliohamishwa kwa kila mtumiaji mmoja katika timu yao + label: Imetumwa kwenye Timu Yangu dash_shared_with_my_team_overview: - label: Imeshirikisha Timu yangu (Muhtasari) + label: Imetumwa kwenye Timu Yangu (Muhtasari) dash_shared_with_others: - explanation: Inaonyesha ni kiasi gani cha kesi zangu zina rufaa zinazoendelea kufanyiwa kazi, uhamisho unaosubiri, au uhamisho uliokataliwa. Hii si kwa meneja ispokuwa pale tu ambapo meneja anasimamia kesi yeye mwenyewe - label: Imesambazwa Kwa Wengine + explanation: Inaonesha ni mashauri yangu mangapi yana rufaa zinazoendelea, uhamisho unaosubiri, au uhamisho uliokataliwa. Hii si kwa ajili ya meneja isipokuwa pale ambapo simamia mashauri wao mwenyewe + label: Imetumwa kwenye Timu Yangu + dash_violations_category_verification_status: + explanation: Inaonesha kwa kiasi gani na aina gani ya ukiukwaji wa MRM umetokea, uliogawanywa kwa hali ya uthibitisho + label: MRM - Idadi ya ukiukwaji kwa hali ya uthibitisho + dash_violations_category_region: + explanation: Inaonesha kwa kiasi gani ya ukiukwaji wa MRM umetokea kwa kila mkoa, uliogawanywa kwa aina ya ukatili + label: MRM - Idadi ya Ukiukwaji kwa Mkoa + dash_perpetrator_armed_force_group_party_names: + explanation: Inaonesha kwa kiasi gani na aina gani ya ukiukwaji wa MRM umetokea, uliogawanywa kwa mhalifu + label: MRM - Idadi ya ukiukwaji kwa Mhalifu dash_show_none_values: - explanation: Inaongeza uwanja wa ziada wa 'Hakuna Kiwango cha Hatari' kwadashbodi zote ambazo zinazigawa kesi kutokana na kiwango cha hatari. Hii ni mahsusi kwa wale wanaotengeneza mifumo ambayo inzipanga kesi kwa kiwango cha hatari. Hii ni mahsusi kwa mifumo ambayo inayo chaguo la nne la "Hakuna Hatari" linalotumika katika maeneo ya kuchagua ya hatua ya hatari. - label: Angalia kesi ambazo 'Hazina Kiwango cha Hatari' katika Dashbodi ya Tathmini. + explanation: Inaongeza kipengele cha ziada cha 'Hakuna Kiwango cha Hatari' kwa dashbodi zote ambazo zinayagawa mashauri kwa kiwango cha hatari. Hii ni mahsusi kwa usanidi ambao una chaguo la nne la "Hakuna Hatari". katika maeneo ya kiwango cha hatari. + label: Angalia mashauri yenye 'Hakuna Kiwango cha Hatari' katika Dashbodi ya Tathmini. dash_tasks: - explanation: Inamruhusu mtumiaji kuona ukurasa wa . Hii inatakiwa itumike kwa wafanyakazi wa kesi na watoaji huduma, kwa vile nambari zitakuwa ni maalum kwa kesi unazozisimamia moja kwa moja. Meneja badala yake itambidi apate dashbodi ya "Angalia /Tazama Kesi kwa Kazi Iliyochelewa", kwa sababu hii itawawezesha kuona kazi zilizochelewa za kila mtu katika kikundi chao cha watumiaji + explanation: Inamruhusu mtumiaji kuona ukurasa wa kazi. Hii inatakiwa itumike kwa waendesha mashauri na watoa huduma, kwa vile idadi zitakuwa ni maalum kwa mashauri unayoyasimamia moja kwa moja. Mameneja badala yake wataona dashbodi ya "Tazama Mashauri kwa Kazi Iliyochelewa", kwa sababu hii itawawezesha kuona kazi zilizochelewa za kila mtu katika kikundi chao cha watumiaji label: Ukurasa wa Majukumu. dash_national_admin_summary: - explanation: Inaonyesha jumla ya Kesi zote zilizoko wazi / zinazoendelea katika mfumo, idadi ya Kesi mpya zilizofunguliwa katika kila wiki kwa kipindi cha wiki mbili zilizopita, na idadi ya Kesi zilizofungwa katika kila wiki kwa kipindi cha wiki mbili zilizopita. + explanation: Inaonesha jumla ya mashauri yaliyowazi katika mfumo, idadi ya mashauri mapya yaliyotengenezwa kwa kila wiki mbili zilizopita, na idadi ya mashauri yaliyofungwa kwa kila wiki wiki mbili zilizopita. label: Muhtasari wa Msimamizi view_response: - explanation: Kwa kila aina ya jibu, inaonyesha ni kesi ngapi katika kila hatua ya hatari ina huduma ambazo karibu zitamalizika muda wake au kuchelewa kukamilika. - label: Tazama Majibu + explanation: Kwa kila aina ya hatua, inaonesha nmashauri mangapi katika kila hali ya hatari ya utoaji wa huduma ambayo yanakaribia kumalizika kwa muda wake au kuchelewa kukamilika. + label: 'Tazama hatua ' workflow: - explanation: Inamruhusu mfanyakazi wa kesi kuiona chati ya duara (pai) inayoonyesha ni idadi gani ya kesi zao ziko katika kila hatua ya mtiririko wa usimamizi wa kesi - label: Kesi zilizogawanywa kwan uzito / wingi wa kesi + explanation: Inamruhusu mwendesha shauri kuona grafu la pai linaloonesha idadi ya mashauri yao kwa kila hatua ya mtiririko wa usimamizi wa shauri + label: Mashauri yaliyogawiwa kwa mtiririko wa kazi workflow_team: - explanation: 'Inamruhusu meneja kuona jedwali linaloonyesha ni kesi ngapi za wafanyakazi wao zilizoko katika kila hatua ya mchakato wa usimamizi wa kesi ' - label: Kesi kwa Wingi wa Kesi na Mfanyakazi wa Kesi - explanation: Inaelekeza ni habari ipi ya muhtasari ionekane kwenye ukurasa wa nyumbani - label: Dashbodi + explanation: Inamruhusu meneja kuona jaduweli linaloonesha ni mashauri mangapi kwa kila Afisa Ustawi na kila hatua ya usimamizi wa mashauri + label: Mashauri kwa mtiririko wa kazi na kwa mwendesha shauri + explanation: Inaelekeza ni habari ipi ya muhtasari ionekane kwenye ukurasa wa mwanzo + label: Dashibodi disabled: - explanation: Ikiwa utaiondoa Jukumu hili, hutaweza tena kulkabidhi kwa akaunti ya mtumiaji - label: Imelemazwa / Imezimwa + explanation: Ikiwa utalizuia Jukumu hili, hutaweza tena kulikabidhi kwa akaunti za mtumiaji + label: Imezuiwa duplicate: actions: read: - explanation: Inamruhusu mtumiaji kufanya utafiti wa hali ya juu kuhusu kesi zote zilizoko kwenye mfumo kwa kutumia vigezo kadhaa, ikiwa ni pamoja na Jina, Jina la utani, Jinsia, na Uraia /Utaifa - label: Mtazamo - explanation: Utafutaji wa hali ya juu kwa utawala - label: Utafutaji wa Nakala + explanation: Inamruhusu mtumiaji kufanya utafutaji wa kina kwa mashauri yote yalio kwenye mfumo, kwa kutumia vigezo kadhaa, ikijumuisha Jina, Jina la umaarufu, Jinsi, umri na Utaifa + label: Tazama + explanation: Utafutaji wa kina kwa wasimamizi wa mfumo + label: Utafutaji uliojirejea forms: case: - explanation: 'Kuzuiya watumiaji wasizifikie fomu za kesi kunaweka mipaka kuhusu taarifa ambayo mtumiaji anaweza kuiona kuhusu tukio. Kwa mfano, ikiwa mtumiaji atakuwa na uwezo wa kuzifikia fomu za Mmiliki wa Rekodi, wataweza pia kuona taarifa katika maeneo ya fomu hiyo. Ikiwa mtumiaji wa sasa atakuwa na ufikiaji mdogo wa fomu na ana uwezo wa kusimamia mpangilio wa fomu, uwezo wao mdogo wa kuzifikia fomu unapunguza pia uwezo wao wa idadi ya fomu watakazoweza kuzipangilia. KUMBUKA: Ikiwa hakuna fomu zilizowekwa maalum, inamaanisha kuwa mtu mwenye jukumu hili anaweza kuzifikia fomu zote za kesi.' - label: Fomu - Kesi + explanation: 'Kuweka mipaka kwa mtumiaji kufikia fomu za mashauri inamaanisha kumuekea mipaka juu ya taarifa gani anaweza kuziona kuhusiana na tukio. Kwa mfano, ikiwa mtumiaji atakuwa na uwezo wa kuzifikia fomu za mmiliki wa kumbukumbu, wataweza pia kuona taarifa zilizomo katika fomu hiyo. Ikiwa mtumiaji wa sasa atakuwa na ufikiaji mdogo wa fomu na ana uwezo wa kusimamia usanidi wa fomu, uwezo wao mdogo wa kuzifikia fomu unapunguza pia uwezo wao wa kusanidi fomu. ZINGATIA: Ikiwa fomu hazijaainishwa, inamaanisha kuwa mtu mwenye jukumu hili anaweza kuzifikia fomu zote za mashauri.' + label: Fomu - Shauri incident: - explanation: 'Kuzuiya ufikiaji wa mtumiaji wa fomu za matukio kunaweka mipaka ni taarifa gani mtumiaji anayoweza kuiona kuhusu tukio. Kwa mfano, ikiwa mtumiaji atakuwa na uwezo wa kuifikia fomu ya Mmiliki wa Rekodi, atweza pia kuona taarifa iliyomo katika maeneo ya fomu hiyo tu. Ikiwa mtumiaji wa sasa ana ufikiaji mdogo wa fomu na anauwezo wa kuusimamia mpangilio wa fomu, ufikiaji mdogo wa fomu pia unazuiya fomu gani wanaweza kuziwekea mpangilio wake. IKUMBUKA kiwa hakuna fomu maalum zilizotajwa, ina maana ya kuwa analojukumu la ufikiaji wa fomu zote za matukio ' + explanation: 'Kuweka mipaka kwa mtumiaji kufikia fomu za matukio inamaanisha kumuekea mipaka juu ya taarifa gani anaweza kuziona kuhusiana na tukio. Kwa mfano, ikiwa mtumiaji atakuwa na uwezo wa kuzifikia fomu za mmiliki wa kumbukumbu, wataweza pia kuona taarifa zilizomo katika fomu hiyo. Ikiwa mtumiaji wa sasa atakuwa na ufikiaji mdogo wa fomu na ana uwezo wa kusimamia usanidi wa fomu, uwezo wao mdogo wa kuzifikia fomu unapunguza pia uwezo wao wa kusanidi fomu. ZINGATIA: Ikiwa fomu hazijaainishwa, inamaanisha kuwa mtu mwenye jukumu hili anaweza kuzifikia fomu zote za matukio' label: Fomu - Tukio tracing_request: - explanation: 'Kupunguza uwezo wa mtumiaji wa kuzifikia fomu zenye maombi ya kufuatilia , kunapunguza kiwango cha taarifa ambacho mtumiaji anaweza kuziona. Kwa mfano, ikiwa mtumiaji ana uwezo wa kufikia fomu ya Mmiliki wa Rewkodi tu, ataweza pia kuona taarifa katika maeneo ya fomu hiyo tu. Ikiwa mtumiaji wa sasa atakuwa na ufikiaji mdogo wa fomu, na ana uwezo wa kusimamia mpangilio wa fomu, uwezo wake mdogo wa kuzifikia fomu utapunguza pia uwezo wake wa idadi ya fomu atakazoweza kuzipangilia. KUMBUKA, ikiwa hakuna fomu zilizowekwa maalum, inamaanisha kuwa mwenye jukumu hili ataweza kuzifikia fomu zote zenye Maombi ya Kufuatilia ' - label: Fomu - Ombi la Kufuatilia + explanation: 'Kuweka mipaka kwa mtumiaji kufikia maombi ya utafutaji inamaanisha kumuekea mipaka juu ya taarifa gani anaweza kuziona kuhusiana na ombi la utafutaji. Kwa mfano, ikiwa mtumiaji atakuwa na uwezo wa kuzifikia fomu za mmiliki wa kumbukumbu, wataweza pia kuona taarifa zilizomo katika fomu hiyo. Ikiwa mtumiaji wa sasa atakuwa na ufikiaji mdogo wa fomu na ana uwezo wa kusimamia usanidi wa fomu, uwezo wao mdogo wa kuzifikia fomu unapunguza pia uwezo wao wa kusanidi fomu. ZINGATIA: Ikiwa fomu hazijaainishwa, inamaanisha kuwa mtu mwenye jukumu hili anaweza kuzifikia fomu zote za maombi ya utafutaji. ' + label: Fomu - Ombi la utafutaji registry_record: - explanation: 'Kuzuiya ufikiaji wa mtumiaji wenye fomu au usajili kunatoa ufikiaji mdodgo wa aina ya taarifa ambazo mtumiaji anaweza kuziona kuhusu usajili. Kwa mfano, ikiwa mtumiaji anauwezo wa kuifikia fomu ya Mmiliki wa fomu ya Usajili, wataweza kuona taarifa ya maeneo ya fomu ile tu. Ikwa mtumiaji wa sasa ana uwez omdogo wa kuzifikia fomu na anauwezo wa kusimamia mpagilio uwezo mdogo wa kufikia fomu pia una athiri namna ambavyo anaweka kuisimamia miipangilio ya fomu zenyewe. KUMBUKA Ikiwa hakuna fomu maalum, inamaana mwenye jukumu anaweza kuzifikia fomu zote za usajili ' + explanation: 'Kuweka mipaka kwa mtumiaji kufikia fomu za usajili inamaanisha kumuekea mipaka juu ya taarifa gani anaweza kuziona kuhusiana na usajili. Kwa mfano, ikiwa mtumiaji atakuwa na uwezo wa kuzifikia fomu za mmiliki wa kumbukumbu, wataweza pia kuona taarifa zilizomo katika fomu hiyo. Ikiwa mtumiaji wa sasa atakuwa na ufikiaji mdogo wa fomu na ana uwezo wa kusimamia usanidi wa fomu, uwezo wao mdogo wa kuzifikia fomu unapunguza pia uwezo wao wa kusanidi fomu. ZINGATIA: Ikiwa fomu hazijaainishwa, inamaanisha kuwa mtu mwenye jukumu hili anaweza kuzifikia fomu zote za mashauri.umu anaweza kuzifikia fomu zote za usajili ' label: Fomu - Usajili + family: + label: Fomu - Familia group: actions: admin_only: - explanation: 'Hii ina maana kuwa mtumiaji mwenye jukumu hili ataweza kuona mambo yanayohusiana na utawala wa mfumo tu, kama vile ripoti, fomu na mpangilio wa kuangalia, watumiaji, majukumu na vikundi vya watumiaji. Hawataweza kuziwaona kesi za watu binafsi, maombi ya kufuatilia, au matukio. ' - label: Hakuna rekodi - Kwa ufanyaji kazi wa msimamizi tu + explanation: 'Hii ina maana kuwa watumiaji wenye jukumu hili wataweza kuona mambo yanayohusiana na usimamizi wa mfumo tu, kama vile ripoti, fomu na usanidi wa utafutaji, watumiaji, majukumu na vikundi vya watumiaji. Hawataweza kuona mashauri ya watu binafsi, maombi ya utafutaji, au matukio. ' + label: Hakuna kumbukumbu - Kwa matumizi ya msimamizi tu agency: - explanation: Mwenye jukumu hili anaweza kuifikia usimamizi wa kumbukumbu kwa watumiaji wote katika wakala wao. - label: Rekodi / Kumbukumbu zote za watumiaji katika wakala wangu. + explanation: Jukumu hili linawezesha kufikia kumbukumbu zilizosimamiwa na watumiaji wote kwenye taasisi zao. Ikiwa mtumiaji ana uwezo wa kuwafikia watumiaji wengine, ataweza kuwafikia watumiaji wote katika taasisi zao. + label: Kumbukumbu zote za watumiaji katika taasisi yangu. all: - explanation: 'Jukumu hili linaweza kufikia rekodi zote, watumiaji na vikundi vya watumiaji katika mfumo, bila ya kujali kikundi gani cha watumiaji wao wenyewe wamo. ' - label: Fikia rekodi zote au watumiaji + explanation: Jukumu hili linawezesha kufikia kumbukumbu zote, watumiaji wote na vikundi vya watumiaji vyote katika mfumo, bila ya kujali wapo katika kikundi gani cha watumiaji. + label: Fikia kumbukumbu zote au watumiaji group: - explanation: Jukumu hili linaweza kufikia rekodi zinazosimamiwa na watumiaji wote katika vikundi vyao vya watumiaji. Wanaweza kuwafikia watumiaji katika vikundi vyao vya watumiaji tu. Wanaweza kufikia vikundi vyao vya watumiaji pekee. - label: Fikia rekodi zote au watumiaji katika kikundi changu + explanation: Jukumu hili linawezesha kufikia kumbukumbu zinazosimamiwa na watumiaji wote katika vikundi vyao vya watumiaji. Wanaweza kuwafikia watumiaji katika vikundi vyao vya watumiaji pekee. Wanaweza kufikia vikundi vyao vya watumiaji pekee. + label: Fikia kumbukumbu zote au watumiaji katika kikundi changu self: - explanation: Majukumu haya yanaweza kufikia rekodi zao wenyewe (kesi, maombi ya kutafuta, au matuklio), na wanaweza kuhariri akaunti zao za mtumiaji - label: Fikia rekodi zangu tu au mtumiaji - explanation: 'inadhibiti rekodi ambazo jukumu hili linaweza kuzifikia (Kesi, Kufuatilia Maombi, au Matukio), Ikiwa jukumu litakuwa na uwezo wa kufikia Watumiaji na Vikundi vya Watumiaji, hii inazuiya ni Watumiaji wepi na Vikundi vya Watumiaji wanavyoweza kuvifikia. Majukumu yenye ufikiaji wa "Hakuna Rekodi / Kumbukumbu" yanaweza kufikia mpangilio wa mfumo kama vile Fomu, Watumiaji, na Ripoti tu. ' - label: Jukumu hili linaathiri recodi zipi / gani? + explanation: Jukumu hili linawezesha kufikia kumbukumbu zao wenyewe (mashauri, maombi ya utafutaji, au matukio), na wanaweza kurekebisha akaunti zao za mtumiaji + label: Fikia kumbukumbu zangu pekee au mtumiaji + explanation: 'Inadhibiti kumbukumbu ambazo jukumu hili linaweza kuzifikia (Mashauri, Maombi ya Utafutaji, au Matukio), Ikiwa jukumu hili litawezesha kufikia Watumiaji na Vikundi vya Watumiaji, hili pia linadhibiti watumiaji wa vikundi gani wanaweza kufikia. Majukumu yenye ufikiaji wa "Hakuna Kumbukumbu" yanaweza kufikia usanidi wa mfumo tu kama vile Fomu, Watumiaji, na Ripoti. ' + label: 'kumbukumbu gani zinaathiri jukumu hili? ' incident: actions: change_log: - explanation: Mtumiaji anaweza kuona historia ya mabadiliko yote yaliyofanywa kuanzia ilipotengenezwa. Hii ni pamoja na thamani zilizorekodiwa kwa maeneo yote - label: Badilisha Daftari / Badilisha Logi + explanation: Mtumiaji anaweza kuona historia ya mabadiliko yote ya kumbukumbu yaliyofanywa kuanzia ilipotengenezwa. Hii ni pamoja na taarifa zilizorekodiwa kwenye maeneo yote + label: Badilisha kurasa create: explanation: Uwezo wa kutengeneza tukio - label: Kutengeneza / Kuunda + label: Kutengeneza enable_disable_record: - explanation: Uwezo wa kuzima au kuwezesha tukio. Matukio "Yaliyozimwa" hayaonekani kwenye chaguo - msingi katika orodha ya tukio. Watumiaji wanaweza kuyaona matukio yaliyozimwa katika orodha ya matukio kwa kutumia kichujio. - label: Kuwezesha / Kulemaza + explanation: Uwezo wa kuzuia au kuwezesha tukio. Matukio "Yaliyozuiliwa" hayatajionesha katika orodha ya tukio. Watumiaji wanaweza kuyaona matukio yaliyozuiliwa katika orodha ya tukio kwa kutumia kichujio. + label: Wezesha / Zuia export_case_pdf: - explanation: 'Mtumiaji anawerza kutengeneza faili la usafirishaji la PDF kutoka kwenye orodha ya matukio au kurasa za maonyesho ya matukio, ambazo zinayo maeneo ambayo mtumiaji wa sasa anao uwezo wa kufikia rekodi moja, nyingi au zote. Katika faili la usafirishaji la PDF, taarifa imeandikwa kwanza kwa kesi, na baada ya hapo imepangiliwa katika mtiririko ambao taarifa inaonekana. ' - label: Kusafirisha PDF / PDF ya Kuuza nje + explanation: Mtumiaji anaweza kutengeneza faili la kutoa la PDF kutoka kwenye orodha ya matukio au kurasa za maonesho ya matukio, zilizo na maeneo ambayo mtumiaji wa sasa anaweza kuyafikia kwa kumbukumbu moja, zaidi ya moja au zote. Katika faili la kutoa la PDF, taarifa zimeorodheshwa kwa shauri na baadae zimepangiliwa kwa fomu kwa mujibu wa taarifa zinavyoonekana. + label: Toa kwa PDF export_csv: - explanation: Mtumiaji anaweza kutengeneza faili la usafirishaji la CSVkutoka kwenye orodha ya matukio au kurasa za maonyesho ya matukioambazo zina maeneo yote ambayo mtumiaji wa sasa ana uwezo wa kufikia tukio moja, mengi au yote. - label: Safirisha kwenda CSV / Usafirishaji kwa CSV + explanation: 'Mtumiaji anaweza kutengeneza faili la kutoa la CSV kutoka kwenye orodha ya matukio au kurasa za maonesho zilizo na maeneo ambayo mtumiaji wa sasa anaweza kuyafikia kwa kumbukumbu moja, zaidi ya moja au zote. ' + label: Toa kwa CSV export_custom: - label: Safirisha desturi / Desturi ya kuuza nje + label: Utoaji wa kawaida export_incident_recorder_xls: - explanation: Mtumiaji anaweza kutengeneza usafirishaji maalum wa faili ya XLS ambalo litaruhusu kubadilishana data / taarifa na zana ya Kurekodi Matukio ya Udhalilishaji wa Kijinsia - label: Tuma xls ya rekodi za matukio + explanation: Mtumiaji anaweza kutengeneza faili la kutoa la XLS ambalo linaruhusu kubadilishana taarifa na zana ya kuweka kumbukumbu ya Matukio ya Udhalilishaji wa Kijinsia + label: 'Kinasa tukio cha kutoa kwa njia ya xls ' + export_mrm_violation_xls: + explanation: Mtumiaji anaweza kutengeneza faili la kutoa la (XLS faili) la ukiukwaji wa MRM. Hatua hii inapatikana kwenye ukurasa wa kuonesha matukio na orodha ya matukio. + label: Toa ukiukwaji wa MRM kwenda kwenye faili la (XLS file) export_json: - explanation: 'Mtumiaji anaweza kutengeneza faili la kusafirisha la JSON kutoka kwenye orodha ya matukio au kurasa za maonyesho ya matukio wenye maeneo yote ambayo mtumiaji wa sasa anao uwezo wa kufikia tukio moja, menigi au yote. Usafirishaji huu hutumiwa zaidi na wale wanaotaka matukio kutoka kwenye mfumo wa sasa wa Primero na baadaye kuyaingiza katika mfumo tofauti wa Primero au katika mfumo mwengine wa usimamizi wa taarifa. Mfumo wa JSON unasomwa kwa kutumia mashine na kwa hivyo watumiaji walio wengi hawawezi kuutumia. ' - label: Safirisha JSON + explanation: Mtumiaji anaweza kutengeneza faili la kutoa la JSON kutoka kwenye orodha ya tukio au ukurasa wa onyesho, wenye maeneo yote ambayo mtumiaji anao uwezo wa kufikia,  kwa shauri moja au zaidi, ambayo mtumiaji anaweza kuyafikia. Utoaji huu hutumiwa zaidi na wale wanaotaka kutoa shauri kutoka kwenye mfumo wa sasa wa Primero na baadae kuziingiza katika mfumo tofauti wa Primero au katika mfumo mwengine wa usimamizi wa taarifa. Mfumo wa JSON unasomwa kwa kutumia mashine na kwa hivyo watumiaji walio wengi hawawezi kuutumia + label: Toa kwa JSON export_list_view_csv: - explanation: 'Mtumiaji anaweza kutengeneza faili la kusafirisha la CSVkutoka kwenye ukurasa wa orodha ya matukio wenye maeneo sawa na yale yanayoonekana na mtumiaji huyo katika orodha ya matukio. Yaliyofanyiwa kazi kwenye ukurasa wa matukio tu. ' - label: Hamisha muonekano wa orodha kwenda CSV + explanation: 'Mtumiaji anaweza kutengeneza faili kwa kulitoa kwa CSV kutoka kwenye ukurasa wa orodha ya matukio wenye maeneo sawa na yale yanayoonekana na mtumiaji huyo katika orodha ya matukio. Yaliyofanyiwa kazi kwenye ukurasa wa matukio pekee. ' + label: Toa kwa orodha ya CSV export_pdf: - explanation: 'Mtumiaji anaweza kutengeneza faili la usafirishaji la PDF kutoka kwenye orodha ya matukio au kurasa za maonyesho ya matukio ambazo zinayo maeneo ambayo mtumiaji wa sasa anao uwezo wa kufikia rekodi moja, nyingi au zote. Katika faili la usafirishaji la PDF, taarifa imeandikwa kwanza kwa kesi, na baada ya hapo imepangiliwa katika mtiririko ambao taarifa inaonekana. ' - label: Kusafirisha PDF / PDF ya kuuza nje + explanation: Mtumiaji anaweza kutengeneza faili la kutoa la PDF kutoka kwenye orodha ya matukio au kurasa za maonesho ya matukio, zilizo na maeneo ambayo mtumiaji wa sasa anaweza kuyafikia kwa kumbukumbu moja, zaidi ya moja au zote. Katika faili la kutoa la PDF, taarifa zimeorodheshwa kwa mshauri na baadae zimepangiliwa kwa fomu kwa mujibu wa taarifa zinavyoonekana. + label: 'Toa kwa PDF ' export_xls: - explanation: 'Mtumiaji anaweza kutengeneza faili la kusafirisha la XLS kutoka kwenye orodha ya matukio au kurasa za maonyesho za matukio ambazo zina seti mkaalum za fomu au maeneo kwa kesi moja, nyingi au zote ambazo mtumiaji anaweza kuzifikia. Katika usafirishaji huu, kila fomu moja inawakilishwa na kichupo chake katika faili la XLS. Mtumiaji anaweza kuchagua ni fomu zipi au maeneo gani anependa yaingizwe katika usafirishaji kwa kutumia muundo Maalum wa Usafirishaji.. Tafadhali kumbuka kuwa watumiaji wanaweza kuingiza fomu na maeneo katika usafirishaji ikiwa watakuwa tayari wanao uwewzo wa kuziona fomu hizo na maeneo hayo pale watakapokuwa wakiangalia kesi katika maombi. ' - label: Usafirishaji wa Excel (kwa faili la XLS) + explanation: Mtumiaji anaweza kutengeneza faili la kutoa la XLS kutoka kwenye orodha yashauri au ukurasa wa onyesho la shauri, ambao imejumuisha fomu mbalimbali, au maeneo, kwa shauri moja au zaidi, ambayo mtumiaji anaweza kuyafikia. Katika kutoa, kila fomu itawakilisha katika eneo lake faili la XLS. Mtumiaji anaweza kuchagua fomu au maeneo gani wangependa yaingizwe katika kuyatoa kwa kutumia muundo Maalum wa Usafirishaji. Tafadhali kumbuka kwamba watumiaji wanaweza kuingiza fomu na maeneo katika kutoa, ikiwa watakuwa tayari wanao uwezo wa kuona maeneo na fomu hizo wanapoangalia maombi ya shauri. + label: Utoaji kwa njia ya Excel (XLS) flag: - explanation: Uwezo wa kuongeza bendera kwenye tukio. Watumiaji wenye ruhusa ya kufanya hivi wanaweza pia kuziondoa bendera walizoziongeza katika tukio. - label: Bendera + explanation: Uwezo wa kuongeza kibendera kwenye tukio. Watumiaji wenye ruhusa ya kufanya hivi pia wanaweza kuviondoa vibendera walivovioviongeza katika tukio. + label: Kibendera import: - explanation: 'Inamruhusu mtumiaji kuweza kutengeneza tukio moja au zaidi mpya kwa kuyaagiza kutoka kwenye faili la CSV, Excel au JSON. Faili ambalo litaagizwa lazima liwe limetengenezwa mahsusi "kabisa" kwa taarifa kuweza kuingizwa ipasavyo. Kipengele hiki kiwe kinapatikana kwa watumiaji wa utawala / usimamizi ambao wenye ujuzi wa hali ya juu wa kiufundi na ufahamu wa kina kuhusu namna ambayo data/ taarifa inavyopangwa katika Primero. Inatekelezwa kutoka kwenye ukurasa wa orodha ya matukio tu. ' - label: Kuagiza + explanation: 'Inamruhusu mtumiaji kutengeneza shauri moja jipya au Zaidi, kwa kuyaingiza kutoka kwenye faili la CSV, Excel au JSON. Faili lililoingizwa lazima liwe limetengenezwa mahsusi *kabisa* kwa taarifa zilizoingizwa ipasavyo. Kipengele hichi kiwe kinapatikana kwa watumiaji wa utawala/wasimamizi ambao wenye ujuzi na taaluma ya hali ya juu na ufahamu wa kina kuhusu namna ambayo data zinavyopangwa katika Primero. Inatekelezwa kutoka kwa ukurasa wa orodha ya shauri tu. ' + label: Ingiza + remove_alert: + explanation: Ruhusa hii inamruhusu mtumiaji kuondoa tahadhari kutoka katika tukio. tahadhari inatengenezwa iwapo kuna eneo limefanyiwa marekebisho, kama vile maelezo yanapoboreshwa. kwa kawaida tahadhari zinaoneshwa kwa alama ya njano mbele ya tukio. + label: Ondoa tahadhari kutoka kwenye tukio manage: - explanation: Inatoa ruhusa kwa mtumiaji kutekeleza shughuli zote zinazopatikana kuhusu matukio. Ruhusa ya "Kusimamia" ina maana ya "Kila kitu" - label: Kusimamia (ruhusa zote kwa aina ya rasilimali) + explanation: Inamruhusu mtumiaji kutekeleza shughuli zote zinazopatikana kuhusu matukio. Ruhusa ya "Kusimamia" ina maana ya "Kila kitu" + label: Simamia (ruhusa zote kwa aina hii ya taarifa) read: - explanation: Uwezo wa kutazama tukio. - label: Mtazamo + explanation: Uwezo wa kuangalia tukio. + label: Tazama sync_mobile: - explanation: Ruhusa hii kwa kawaida inamruhusu mtumiaji kutumia kifaa chake cha mkononi. Kwa kuanzia inamruhusu mtumiaji kuziona shughuli zote za "Weka Alama kwenye Simu" na "Ondoa Alama kwenye Simu"ambazo huonekana kwenye orodha ya matukio na kurasa za kuonyesha matukio. Kuweka alama ya tukio kwenye simuinamaanisha kuwa taarifa kuhus tukio hilo itabidi isawazishwe kati ya kifaa cha mkononi cha mtumiaji na programu ya tovuti, wakati kuondoa alama kwenye tukio la kifaa cha mkononi kunazuiya uunganishaji usitokee. Watumiaji ambao hawana ruhusa hii pia hawawezi kuunganisha vifaa vyao vya mkononi na tovuti, kwa hivyo hawataweza kutumia simu zao kusimamia matukio hayo. - label: 'Sawazisha /Unganisha na vifaa vya / simu za mkononi. ' + explanation: Ruhusa hii kwa kawaida inamruhusu mtumiaji kutumia simu yake ya mkononi. Kwanza, inamruhusu mtumiaji kuona shughuli zote za "Weka Alama kwenye Simu" na "Ondoa Alama kwenye Simu"ambazo huonekana kwenye orodha ya matukio na kurasa wa orodha ya matukio. Kuweka alama ya tukio kwenye simu inamaanisha kuwa taarifa kuhusu tukio hilo itabidi isawazishwe baina ya mtumiaji wa simu kati ya kifaa cha mkononi cha mtumiaji na programu ya tovuti, wakati kuondoa alama kwenye tukio lasimu yako ya mkononi kunazuiya uunganishaji usitokee. Watumiaji ambao hawana ruhusa hii pia hawawezi kuunganisha vifaa vyao vya mkononi na tovuti, kwa hivyo hawataweza kutumia simu zao kusimamia matukio hayo + label: 'Sawazisha kwenye kifaa cha mkononi. ' write: - explanation: 'Uwezo wa kubonyeza kitufe cha "Kuhariri", kinaingiza taarifa mpya kuhusu tukio na kubonyeza "Hifadhi" Pia kunamruhusu mtumiaji kuzima/ kulemaz au kuwezesha tukio. ' - label: Kuhariri - explanation: Inawakilisha tukio lililotokea . Haya mara nyingi niatukio matukio ya udhalilishaji au ukatili ingawaje pia wanaweza kuwasiliana na matukio yanayoweza kukutana, na wasimamizi wa sheria . Matukio mara nyingi yanaungana na Kesi + explanation: 'Uwezo wa kubonyeza kitufe cha "Kurekebisha", kuboresha taarifa mpya kuhusu tukio na kubonyeza "Hifadhi" Pia kunamruhusu mtumiaji kuzuia au kuwezesha tukio. ' + label: Rekebisha + explanation: Inawakilisha tukio lililotokezea. Haya mara nyingi ni matukio ya udhalilishaji au ukatili, japokuwa yanaweza kuhusiana na matukio yanayopelekea kukutana na vyombo vya sheria, Matukio mara nyingi yanaunganishwa na mashauri label: Tuklio is_manager: - explanation: Inatumika kwa mtumiaji yeyoteambaye kwa kawaida anawasimamia watumiaji wengine. Hii humruhusu mtumiaji kuona dashbodi na vichujio ambavyo vinamsaidia mtumiaji kuisimamia timu. - label: Ni Meneja? + explanation: Inatumika kwa jukumu lolote la mtumiaji ambaye kwa kawaida anawasimamia watumiaji wengine. Hii humruhusu mtumiaji kuona dashibodi na vichujio ambavyo vinamsaidia mtumiaji kuisimamia timu. + label: Je, ni Meneja? managed_report: actions: + managed_report_scope: + label: Ni kumbukumbu gani ziweze kuonekana na jukumu hili? + managed_report_scope_all: + label: Yote + managed_report_scope_group: + label: Taarifa za kundi tu + managed_report_scope_agency: + label: Taarifa za Taasisi tu violations: - label: Ukiukaji + label: Ukiukwaji gbv_statistics: label: Takwimu za Udhalilishaji wa Kijinsia + ghn_report: + label: Maelezo ya ripoti ya ulimwengu + individual_children: + label: Mtoto mmoja mmoja + violence_type_report: + explanation: Uwezo wa kuona takwimu za aina ya ukatili. ruhusa hii inamruhuu mtumiaji kutoa taarifa kwenye uchambuzi + referrals_transfers_report: + explanation: 'Watumiaji wanaweza kuona idadi ya mashauri yaliyofanyiwa rufaa na uhamisho kutoka kwenye kikundi cha watumiaji mpaka kwenye kikundi chengine cha watumaji. ' matching_configuration: actions: manage: - explanation: 'Uwezo wa kudhibiti ni maeneo gani yanalinganishwa na kutafuta yaliyolingana kati ya ombi la kutafuta na kesi. Kwa vile hii inadhibiti namna ambavyo ulinganishaji unavyoendeshwa katika mfumo mzima, ruhusa hii kwa kawaida inabidi itumiwe na wasimamizi wa mfumo tu. ' - label: Kusimamia (ruhusa zote kwa aina ya rasilimali) - explanation: Inadhibiti maeneo gani yanatumika kulinganisha Ombi la Kufuatilia na Kesi wakati wa Ufuatiliaji wa Familia na Kuunganisha tena. - label: Kuoanisha Mfumo + explanation: Uwezo wa kudhibiti ni maeneo gani yamelinganishwa na kutafuta mfanano baina ya utafutaji wa ombi na mashauri. Kwa vile hali hii inadhibiti vipi mfanano unavyo fanya kazi kwenye mfumo, ruhusa hii kwa kawaida inapatikana pekee kwa msimamizi wa mfumo tu. + label: Kusimamia (ruhusa zote kwa aina hii ya taarifa) + explanation: 'Inadhibiti maeneo gani yanatumika kulinganisha Ombi la Kufuatilia na Shauri wakati wa Ufuatiliaji na unganishaji wa Familia ' + label: usadini unaofanana metadata: actions: manage: - explanation: Uwezo wa kutengeneza, kuhariri, kutafsiri, na kufuta fomu, maeneo katika fomu, na kutafuta. Tafadhali kumbuka kuwa mtumiaji mwenye ruhusa hii ataweza kuzisimamia fomu ambazo anaweza kuzifikia tu. Kwa mfano, ikiwa msimamizi wa kitaifa ana uwezo wa kuziona fomu za kesi za Mmiliki wa Rekodi tu, watakuwa na uwezo wa kuingiza toleo jipya katika mfumo wa fomu hiyo tu. - label: Kusimamia (ruhusa zote kwa aina ya rasilimali) - explanation: Inadhibiti uwezo wa kuweka mpangilio wa Fomu za Primero na maeneo, pamoja na kutafuta chaguo zinazotumika ndani yake - label: Tazama/ Tafuta Fomu + explanation: Uwezo wa kutengeneza, kurekebisha, kutafsiri, na kufuta fomu, maeneo katika fomu, na utafutaji. Tafadhali zinanatia kwamba mtumiaji mwenye ruhusa hii ataweza kuzisimamia fomu ambazo anaweza kuzifikia tu. Kwa mfano, ikiwa msimamizi wa mfumo ana uwezo wa kuziona fomu za Mmiliki wa Kumbukumbu kuhusu mashauri, Pia watakuwa na uwezo wa kufanya maboresho ya usanidi katika fomu hii + label: Kusimamia (ruhusa zote kwa aina hii ya taarifa) + explanation: Inadhibiti uwezo wa kusanidi wa Fomu za Primero na maeneo yake, pamoja na chaguo za utafutaji zilizotumika. + label: Fomu, Utafutaji module: actions: cp: - label: Ulinzi wa Mtoto + label: Hifadhi ya Mtoto gbv: label: Udhalilishaji wa Kijinsia mrm: label: MRM - explanation: Inadhibiti ni moduli zipi jukumu hili linahusiana nalo + explanation: Inadhibiti ni moduli zipi jukumu hili linahusiana nazo label: Moduli potential_match: actions: read: - explanation: Inawakilisha kiunganisho kati ya Ombi la Kutafuta na Kesi. Ufikiaji wa vyenye uwezekano wa Kulingana ni lazima kwa kazi ya Ufuatiliaji wa Familia na Kuunganishwa tena (FTR). Inamruhusu mtu,miaji kuona fomu ya Muhtasari wa Ufuatiliaji kuhusu kesi - label: Mtazamo - label: Inauwezekano wa Kulingana + explanation: Inawakilisha kiunganisho kati ya Ombi la utafutaji na Shauri. Ufikiaji wa ulinganisho unaowezekana ni lazima kwa kazi ya utafutaji na unganishaji wa familia (FTR). Inamruhusu mtumiaji kuona fomu ya Muhtasari wa utafutaji kuhusu mashauri + label: Tazama + view_audio: + explanation: Inadhibiti iwapo mtumiaji anaetafuta mfanano anaweza kuona faili la sauti la shauri au ombi la utafutaji lililohusiana na ulingano unaowezekana + label: Angalia Sauti + view_photo: + explanation: Inadhibiti iwapo mtumiaji anaetafuta mfanano anaweza kuona faili la picha la shauri au ombi la utafutaji lililohusiana na ulingano unaowezekana + label: Angalia Picha + manage: + explanation: Inamruhusu mtumiaji kufanya shughuli zote zinazopatikana kwenye uliongano unaowezekana. Ruhusa ya "Simamia" maana yake "kila kitu". + label: Simamia + label: 'Ulingano unaowezekana ' primero_configuration: actions: manage: - explanation: 'Uwezo wa kuhifadhi, kutumia na na kutuma mipangilio. Ruhusa hii kwa kawaida ni kwa msimamizi wa mfumo. ' - label: Kusimamia (ruhusa zote kwa aina hii ya rasilimali) - label: Mpangilio + explanation: 'Uwezo wa kuhifadhi, kutumia na kutuma usanidi. Ruhusa hii kwa kawaida imewekwa kwa msimamizi wa mfumo. ' + label: Kusimamia (ruhusa zote kwa aina hii ya taarifa) + label: Usanidi referral: actions: refer: - explanation: Hii ina maana ya kuwa endapo mtumiaji atafanya rufaa ya nje,, jukumu hili litajitokeza kama chaguo kwa "Aina ya Mpokeaji". Ikiwa mtumiaji ataatachagua jukumu hili kuwa aina ya rufaa, usafirishaji ambao Primero utazalisha pale mtumiaji atakapowasilisha rufaa, utakuwa na taarifa inayopatikana kwenye fomu ambayo jukumu hili lina uwezo wa kuzifikia tu. Kwa hivyo, kwa mfano, ikiwa mtumiaji atachagua "Mtoa Huduma za Matibabu" kama aina ya mpokeaji, na ikawa jukumu la Mtoa Huduma za Matibabu linaweza kuzifikia fomu za Utambulisho wa Msingi na Masuala ya Ulinzi tu, faili la usafirishaji ambalo Primero inatumia kusafirisha nje rufaa litakuwa na maeneo ambayo yamo kwenye fomu hizi mbili tu. + explanation: Hii ina maana ya kuwa Jukumu litaonekana ni kama chaguo kwa “Aina ya Mpokeaji”, pale ambapo mtumiaji atafanya rufaa kwenye taasisi nyengine. Ikiwa mtumiaji atachagua jukumu hili kama ni aina ya rufaa, utoaji ambao Primero utatengeneza  pale mtumiaji atakapowasilisha rufaa, utakuwa na taarifa inayopatikana kwenye fomu ambayo jukumu hili lina uwezo wa kuzifikia tu. Kwa hivyo, kwa mfano, ikiwa mtumiaji atachagua "Mtoa Huduma za Matibabu" kama aina ya mpokeaji, na ikawa jukumu la Mtoa Huduma za Matibabu linaweza kuzifikia fomu za Utambulisho wa Msingi na Shaka ya Hifadhi, utoaji wa faili ambalo Primero itatoa kwa ajili ya rufaa kwa taasisi nyengine utajumuisha  maeneo ambayo yamo kwenye fomu hizi mbili tu. label: Je, jukumu hili linaweza kutumika kwa Rufaa za nje? label: Rufaa registry_record: actions: change_log: - explanation: 'Mtumiaji anaweza kuona historia ya mabadiliko yote yaliyofanywa kwenye rekodi tokea zilipoanzishwa. Hii ni pamoja na thamani zilizorekodiwa kwa maeneo yote ' - label: Badilisha Daftari / Badilisha Logi + explanation: 'Mtumiaji anaweza kuona historia ya mabadiliko yote yaliyofanywa kwenye kumbukumbu tokea zilipotengenezwa. Hii inajumuisha taarifa zilizoekewa kumbukumbu kwa maeneo yote ' + label: Badilisha Logi create: - explanation: Uwezo wa kutengeneza rekodi ya Usajili - label: Kutengeneza / Kuunda + explanation: Uwezo wa kutengeneza kumbukumbu ya Usajili + label: Tengeneza enable_disable_record: - explanation: Uwezo wa kuzima au kuwezesha rekodi ya Usajili. Matukio "Yaliyozimwa" hayaonekani katika chaguo -msingi kwenye orodha ya Usajili. Watumiaji wanaweza kuziona rekodi za Usajili zilizozimwa katika orodha ya Usajili kwa kutumia kichujo. - label: Kuwezesha / Kulemaza + explanation: Uwezo wa kuzuia au kuwezesha kumbukumbu ya Usajili. Kumbukumbu "Zilizozuiliwa" hazionekani moja kwa moja -katika orodha ya Usajili. Watumiaji wanaweza kuziona Kumbukumbu za Usajili zilizozuiliwa katika orodha ya Usajili kwa kutumia kichujo. + label: 'Wezesha / Zuia ' export_csv: - explanation: 'Mtumiaji anaweza kutayarisha faili la usafirishaji la CSV kutoka kwenye orodha ya Usajili au kurasa za maonesho za Usajili zenye maeneo yote ambayo mtumiaji wa sasa anaweza kuzifikia moja, nyingi au rekodi za Usajili zote ambazo mtumiaji anauwezo wa kuzifikia. ANGALIZO Usafirshaji wa CSV hautoi herufi zisizokuwa za Kilatini (mfano Kiarabu, Kibengali) katika muundo unaoweza kusomeka ' - label: Peleka kuwa CSV + explanation: 'Mtumiaji anaweza kutengeneza faili la utoaji la CSV kutoka kwenye orodha ya Usajili au kurasa za mwanzo za Usajili zinazojumuisha maeneo yote ambayo mtumiaji wa sasa anaweza kuyafikia moja, zaidi ya moja au kumbukumbu za Usajili zote ambazo mtumiaji anauwezo wa kuzifikia. ZINGATIA Utoaji wa CSV hautoi herufi zisizokuwa za Kilatini (mfano Kiarabu, Kibengali) ' + label: Toa kwa CSV export_json: - explanation: Mtumiaji anaweza kutengeneza faili la usafirishaji la JSON kutoka kwenye orodha ya Usajili au karatasi za maonesho za Usajili zenye maeneo yote ambayo mtumiaji wa sasa anaweza kuyafikia. Mfumo wa JSON unasomwa kwa mashine na kwa hivyo sio rafiki kwa watumiaji walio wengi - label: Peleka kuwa JSON + explanation: Mtumiaji anaweza kutengeneza faili la kutoa la JSON kutoka kwenye orodha ya Usajili au kurasa za mwanzo za Usajili zinazojumuisha maeneo yote ambayo mtumiaji wa sasa anaweza kuyafikia. Mfumo wa JSON ni mashine inayoweza kusomwa kwa mashine na hivyo haitumiki sana na watumiaji walio wengi + label: Toa kwa JSON export_xls: - explanation: 'Mtumiaji anaweza kutengeneza faili la usafirishaji la XLS kutoka kwenye orodha ya Usajili au kwenye kurasa za maonesho za Usajili ambazo mtumiaji wa sasa anao uwezo wa kuzifika. ANGALIZO Mfumo wa usafirishaji wa XLS hutoa herufi zisizokuwa za Kilatini (mfano Kiarabu, Kibengali) katika mfumo unaoweza kuonekana, wakati usafirishaji wa CSV hautoi huduma hiyo. ' - label: Peleka kuwa Excel (faili XLS) + explanation: 'Mtumiaji anaweza kutengeneza faili la kutoa la XLS kutoka kwenye orodha ya Usajili au kurasa za mwanzo za Usajili zinazojumuisha maeneo yote ambayo mtumiaji wa sasa anaweza kuyafikia. ZINGATIA Mfumo wa kutoa wa XLS unatoa herufi zisizokuwa za Kilatini (mfano Kiarabu, Kibengali) katika mfumo unaoweza kusomeka, wakati mfumo wa kutoa wa CSV hauwezi kufanya hivyo. ' + label: Toa kwa Excel (faili la XLS) flag: - explanation: Uwezo wa kuongeza bendera kwenye rekodi ya Usajili. Watumiaji wenye ruhusa ya kufanya hivi wanaweza pia kuziondoa bendera walizoziongeza katika rekodi ya Usajili. - label: Bendera + explanation: Uwezo wa kuweka kibendera kwenye kumbukumbu ya Usajili. Watumiaji wenye ruhusa hii anaweza kuviondoa vibendera vilivyowekwa katika kumbukumbu ya Usajili. + label: Kibendera manage: - explanation: Inamuwezesha mtumiaji kutekeleza shughuli zote zinazopatikana kuhusu rekodi za Usajili. Ruhusa ya "Kusimamia" kimsingi ina maana ya "kila kitu" - label: Kusimamia (ruhusa zote kwa aina hii ya rasilimali) + explanation: Inamruhusu mtumiaji kutekeleza shughuli zote zinazopatikana kuhusu kumbukumbu ya Usajili. Ruhusa ya "Kusimamia" ina maana ya "Kila kitu" + label: Kusimamia (ruhusa zote kwa aina hii ya taarifa) read: - explanation: Uwezo wa kuziona rekodi za Usajili. - label: Mtazamo + explanation: Uwezo wa kuziona kumbukumbu za Usajili. + label: Angalia write: - explanation: Uwezo wa kubonyeza kitufe cha "Hariri", ingiza taarifa mpya kuhusu rekodi za Usajili na kubonyeza "Hifadhi" - label: Kuhariri + explanation: Uwezo wa kubonyeza kitufe cha "Rekebisha", boresha taarifa kuhusu kumbukumbu za Usajili na bonyeza "Hifadhi". + label: Rekebisha sync_mobile: - explanation: Humuwezesha mtumiaji kuhifadhi rekodi za usajili kwa matumizi nje ya mtandao. + explanation: Humuwezesha mtumiaji kuhifadhi kumbukumbu za usajili kwa matumizi nje ya mtandao. label: Alama kwa Nje ya Mtandao - explanation: "Hii inaweza kumuwakilisha mtu binafsi au taasisi inayohitaji kuunganishwa na rekodi nyingine kama vile kesi au matukio, ni wengi sana, na huongezwa taarifa mpya mara kwa mara. Inafanana na uchunguzi lakini ina taarifa mchanganyiko kwa kila ingizo. \n. " - label: Rekodi za Usajili + explanation: "Hii inaweza kumuwakilisha mtu binafsi au taasisi inayohitaji kuunganishwa na kumbukumbu nyingine kama vile mashauri au matukio, ni mengi sana, na huboreshwa kwa taarifa mpya mara kwa mara. Zinafanana na utafutaji lakini ina taarifa mchanganyiko kwa kila ingizo. \n. " + label: Kumbukumbu ya Usajili + family: + actions: + change_log: + explanation: 'Mtumiaji anaweza kuona historia ya mabadiliko yote yaliyofanywa kwenye kumbukumbu tokea zilipotengenezwa. Hii inajumuisha taarifa zilizoekewa kumbukumbu kwa maeneo yote ' + label: Badilisha Logi + create: + explanation: Uwezo kutengeneza familia + label: Tengeneza + enable_disable_record: + explanation: Uwezo wa Kuizuia au kuiwezesha familia. "Imezuiwa" Familia hazitonekani moja kwa koja kwenye orodha ya familia. Watumiaji wanaweza kuoa familia zilizozuiliwa katika orodha ya familia kwa kutumia kichujio. + label: Wezesha / Zuia + export_csv: + explanation: 'Mtumiaji anaweza kutengeneza faili la utoaji la CSV kutoka kwenye orodha ya Familia au kurasa za mwanzo za Familia zinazojumuisha maeneo yote ambayo mtumiaji wa sasa anaweza kuyafikia moja, zaidi ya moja au kumbukumbu za Familia zote ambazo mtumiaji anauwezo wa kuzifikia. ZINGATIA Utoaji wa CSV hautoi herufi zisizokuwa za Kilatini (mfano Kiarabu, Kibengali) ' + label: Toa kwa CSV + export_json: + explanation: Mtumiaji anaweza kutengeneza faili la kutoa la JSON kutoka kwenye orodha ya Familia au kurasa za mwanzo za Familia zinazojumuisha maeneo yote ambayo mtumiaji wa sasa anaweza kuyafikia. Mfumo wa JSON ni mashine inayoweza kusomwa kwa mashine na hivyo haitumiki sana na watumiaji walio wengi + label: Toa kwa JSON + export_xls: + explanation: 'Mtumiaji anaweza kutengeneza faili la kutoa la XLS kutoka kwenye orodha ya Familia au kurasa za mwanzo za Familia zinazojumuisha maeneo yote ambayo mtumiaji wa sasa anaweza kuyafikia. ZINGATIA Mfumo wa kutoa wa XLS unatoa herufi zisizokuwa za Kilatini (mfano Kiarabu, Kibengali) katika mfumo unaoweza kusomeka, wakati mfumo wa kutoa wa CSV hauwezi kufanya hivyo.' + label: Toa kwa Excel (faili la XLS) + export_list_view_csv: + explanation: 'Mtumiaji anaweza kutengeneza faili kwa kutoa kwa CSV kutoka kwenye ukurasa wa orodha ya familia yenye maeneo sawa na yale yanayoonekana na mtumiaji huyo katika orodha ya familia. Yaliyofanyiwa kazi kwenye ukurasa wa orodha ya familia pekee. ' + label: Angalia orodha ya kutoa kwa CSV + export_pdf: + explanation: Mtumiaji anaweza kutengeneza faili la kutoa la PDF kutoka kwenye orodha ya familia au kurasa za maonesho ya familia, zilizo na maeneo ambayo mtumiaji wa sasa anaweza kuyafikia kwa kumbukumbu moja, zaidi ya moja au zote. Katika faili la kutoa la PDF, taarifa zimeorodheshwa kwa familia na baadae zimepangiliwa kwa fomu kwa mujibu wa taarifa zinavyoonekana. + label: Toa kwa PDF + export_custom: + label: Toa kwa kawaida + flag: + explanation: Uwezo wa kuongeza kibendera kwenye familia. Watumiaji wenye ruhusa ya kufanya hivi pia wanaweza kuviondoa vibendera walivovioviongeza katika familia. + label: Kibendera + manage: + explanation: Inamruhusu mtumiaji kutekeleza shughuli zote zinazopatikana kuhusu familia. Ruhusa ya "Kusimamia" ina maana ya "Kila kitu" + label: Kusimamia (ruhusa zote kwa aina hii ya taarifa) + read: + explanation: Uwezo wa kuona Familia + label: Angalia + write: + explanation: Uwezo wa kubonyeza kitufe "rekebisha", boresha Taarifa kuhusu familia na bonyeza "Hifadhi" + label: Rekebisha + sync_mobile: + explanation: Inamruhusu mtumiaji kuhifadhi kumbukumbu ya familia kwa matumizi ya nje ya mtandao + label: Alama Nje ya Mtandao + close: + explanation: Inamruhusu utumiaji kupanga hali ya familia zilizowazi na kuweza kufunga. + label: Funga + reopen: + explanation: Inaruhusu mtumiaji kufungua faili la familia ambayo imefungwa kwa sasa. + label: Fungua Tena + case_from_family: + explanation: Inaruhusu watumiaji kutengeza shauri mpya kutoka kwa fomu ndogo ya Wanafamilia ndani ya kumbukumbu ya Familia. + label: Tengeza Shauri + label: Familia report: actions: create: - explanation: Uwezo wa kutengeneza ripoti mpya. Mtumiaji anapotengeneza ripoti, huwa inaonekana na watumiajin wote wenye uwezo wa kuzifikia ripoti kwa kupitia "Soma" au "Usomaji wa Kikundi" - label: Kutengeneza / Kuunda + explanation: Uwezo wa kutengeneza ripoti mpya. Wakati Mtumiaji anapotengeneza ripoti, huwa inaonekana na watumiaji wote wenye uwezo wa kuzifikia ripoti kwa kupitia "Soma" au "Usomaji wa Kikundi" + label: Kutengeneza group_read: explanation: 'Uwezo wa kuziona ripoti zote. Idadi katika kila ripoti itaonyesha rekodi zile tu zinazoweza kufikiwa na watumiaji katika kikundi cha watumiaji wa sasa. Ruhusa mara nyingi inatumika kwa wasimamizi wa ndani, wa kikanda au wakala wanataka kupata maarifa kuhusu utendaji wa timu zao au wa shirika. Ruhusa hii inampa mtumiaji pia uwezo wa kusafirisha data / taarifa kutoka kwenye ripoti. ' label: Angalia (data / Taarifa ya Kikundi) @@ -2722,7 +3108,6 @@ sw_TZ: display: Kuonyesha uwezekano wa kulingana kwa%{type}%{id} reassign: multiple_error: Hitilafu ilitokea %{select_records}kesi (moja au zaidi) hazikukabidhiwa / hazikugawanywa - multiple_successfully: '%{select_records}kesi (moja au zaidi) ziligawanywa kwa mafanikio' notes_label: Maelezo successfully: Imekabidhiwa upya kwa ufanisi user_mandatory_label: Mpokeaji anahitajika @@ -3089,8 +3474,8 @@ sw_TZ: step2: 'Nenda%{host}na ubonyeze "Ingia kwa kutumia jina la mtumiaji la Primero''' step3: 'Ingia kwa kutumia jina lako la mtumiaji na nenosiri la muda%{otp}' step4: 'Utakapo hamasishwa, weka upya nenosiri lako' - url_label: Primetro - enabled_label: Kuuma Baruapepe ya Kukaribisha? + url_label: Primero + enabled_label: Kutuma Baruapepe ya Kukaribisha? text_label: Maandishi ya Baruapepe ya Kukaribisha password_reset: subject: 'Weka upya maagizo ya nenosiri' diff --git a/config/locales/tet.yml b/config/locales/tet.yml index 078cc018b5..79f6cdf8a6 100644 --- a/config/locales/tet.yml +++ b/config/locales/tet.yml @@ -1,18 +1,3 @@ -# encoding: utf-8 - -# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. -# -# This is the English localization file for Primero. It is based on the sample -# English localization file found in the repository linked below[1]. -# -# Anyone editing this file is strongly encouraged to use yamllint[2] to ensure -# that this document remains valid YAML. -# -# [1] https://github.com/svenfuchs/rails-i18n/ -# [2] https://yamllint.readthedocs.io/en/stable/ - - ---- tet: 'true': 'Loos' 'false': 'Lae' @@ -35,10 +20,10 @@ tet: unavailable_offline: La disponivel offline online: Online yes_label: 'Loos' - or_label: "ka," + or_label: ka, select_provider: Hili fornesedór select_language: Hili dalen - log_in_primero_idp: "Tama ho naran utilizadór%{idp_name}" + log_in_primero_idp: Tama ho naran utilizadór%{idp_name} offline_submitted_changes: Atualmente ita offline. Mudansa ne’ebé ita halo sei bele submete bainhira ita online filafali. updated: Atualizadu go: Bá @@ -46,9 +31,8 @@ tet: sync: success: "%{records} rejistu sira sikronizadu ho susesu" error: - create: "La konsege kria %{record_type}. Favór kontaktu apoiu." - update: "Falla ona atualizasaun ba %{record_type}%{short_id}. Favór kontaktu apoiu." - + create: La konsege kria %{record_type}. Favór kontaktu apoiu. + update: Falla ona atualizasaun ba %{record_type}%{short_id}. Favór kontaktu apoiu. actions: approvals: Aprovasaun button: Asaun sira @@ -58,7 +42,7 @@ tet: valid: Rejistu válidu disable: Dezativa enable: Ativa - incident_details_from_case: "Aumenta Insidente " + incident_details_from_case: 'Aumenta Insidente ' incident_from_case: Kria Insidente next: Tuir mai notes: Aumenta Notas @@ -80,19 +64,19 @@ tet: description: Deskrisaun disabled: Dezativadu exclude_agency_from_lookups: Esklui ajénsia ida-ne'e husi peskiza no filtru sira - exclude_agency_from_lookups_help: "Marka ida-ne'e se Ajénsia ne'e laiha utilizadór (ezemplu, aumenta Ajénsia ne'e atu nune'e bele aplika logo ba esportasaun." + exclude_agency_from_lookups_help: Marka ida-ne'e se Ajénsia ne'e laiha utilizadór (ezemplu, aumenta Ajénsia ne'e atu nune'e bele aplika logo ba esportasaun. label: Ajénsia - logo_enabled: "Hatudu ajénsia ne'e nia logo iha Primero?" - logo_enabled_help: "Hatudu ajénsia ne'e nia logo iha Primero?" + logo_enabled: Hatudu ajénsia ne'e nia logo iha Primero? + logo_enabled_help: Hatudu ajénsia ne'e nia logo iha Primero? logo_icon: Ikon Logo - logo_icon_help: "Ida ne'e sei mosu iha kuadru tamaño kiik, tableta no telefone. Ida ne'e tenke sai forma kuadradu ida." + logo_icon_help: Ida ne'e sei mosu iha kuadru tamaño kiik, tableta no telefone. Ida ne'e tenke sai forma kuadradu ida. logo_large: Logo Boot - logo_large_help: "Ida ne'e sei mosu iha kuadru tamaño boot no iha esportasaun PDF. Ne'e tenke sai nu'udar retángulu, ho ninia luan naruk liu fali ninia aas." + logo_large_help: Ida ne'e sei mosu iha kuadru tamaño boot no iha esportasaun PDF. Ne'e tenke sai nu'udar retángulu, ho ninia luan naruk liu fali ninia aas. messages: created: Ajénsia kria ona ho susesu. updated: Ajénsia atualiza ona ho susesu. name: Naran Ajénsia  - pdf_logo_option: "Halo logo disponivel ba esportasaun PDF?" + pdf_logo_option: Halo logo disponivel ba esportasaun PDF? pdf_logo_option_help: 'Nota: logo Ajénsia utilizador nian disponivel ba sira tuir padraun, nune''e ita bele marka de''it ida ne''e bainhira ita hakarak logo ida ne''e disponivel ba utilizador hotu-hotu.' services: Servisu sira Ajénsia nian terms_of_use: Termu ba Utilizasaun @@ -110,7 +94,7 @@ tet: response_for_label: Aprovasaun Ba response_for_title: Aprovasaun action_plan: Planu Asaun - gbv_closure: " Terminasaun VBJ" + gbv_closure: ' Terminasaun VBJ' status: approved: Aprovadu pending: Pendente @@ -130,7 +114,7 @@ tet: status: Status form_export: label: Konfigurasaun Formatu Esportasaun - include_hidden: "Inklui formatu no kampu okultu/subar?" + include_hidden: Inklui formatu no kampu okultu/subar? file_name: Kria ita nia arkivu nia naran (Opsional) success_message: Kria ona arkivu esportasaun ho susesu buttons: @@ -158,7 +142,7 @@ tet: continue: Kontinua create_case: Kria Kazu create_incident: Kria Insidente - create_new_record: "Kria Foun%{model}" + create_new_record: Kria Foun%{model} delete: Hamoos disable: Dezativa disable_photo_wall: Dezativa fotografia parede @@ -172,9 +156,9 @@ tet: filter: Aplika Filtru filter_clear: Hamoos Filtru filter_label: 'Filtru:' - filter_restore: "Restaura ba Sistema Konfigurasaun " + filter_restore: 'Restaura ba Sistema Konfigurasaun ' find_tracing_match: Buka Mapa Korespondensia - flag_model: "Flag %{model}" + flag_model: Flag %{model} flag_records: Flag flags: Flags guidance: Matadalan @@ -207,8 +191,8 @@ tet: sync: Sinkroniza submit: Submete transfer: Transfere - unflag_model: "Unflag %{model}" - unflag_model_history: "Istória Flag %{model}" + unflag_model: Unflag %{model} + unflag_model_history: Istória Flag %{model} unmark_for_mobile: Hamoos marka ba telefone update: Atualiza view: Haree @@ -236,13 +220,13 @@ tet: back_to_results: Filafali ba Rezultadu back_to_search: Filafali ba Buka search_by: Buka Tuir - search_for: "Buka ba %{record_type}" + search_for: Buka ba %{record_type} results: Rezultadu details: Detallu select: Hili deselect: Hamoos Hili enter_id_number: Hatama númeru ID atu buka rejistu ida ne'ebé eziste - id_search_no_results: "Laiha korespondensia ho sistema ba %{search_query}\". Favór kria rejistu foun." + id_search_no_results: Laiha korespondensia ho sistema ba %{search_query}". Favór kria rejistu foun. messages: disabled: Kazu dezativa update_success: 'Kazu %{record_id} atualiza ona ho susesu' @@ -251,26 +235,25 @@ tet: creation_success_queue: 'Rejistu kazu kria ona ho susesu iha kotuk' already_matched: Inkiridor ida ne'e koresponde ona ba ita-boot nia kazu already_matched_not_current_case: Iha ona kazu ida iha sistema koresponde ho inkiridor ida ne'e. - not_found_case: "Laiha kazu hetan korespondensia \"%{search_value}\". Kria kazu foun." + not_found_case: Laiha kazu hetan korespondensia "%{search_value}". Kria kazu foun. introductory_sentence: Favór espesifika konsentimentu individu ne'e nian atu hetan fasilidade jestaun kazu no rai sira nia dadus iha Primero. - consent_agreements_required: "Favór hili pelumenus opsaun ida hosi akordu konsentimentu. " + consent_agreements_required: 'Favór hili pelumenus opsaun ida hosi akordu konsentimentu. ' legitimate_basis_required: Favór hili pelumenus opsaun ida hosi klasifikasaun baze lejítimu. - confirm_create_case: "Ita hakarak atu kria kazu ida ba indivídu ida ne'e?" + confirm_create_case: Ita hakarak atu kria kazu ida ba indivídu ida ne'e? case_referral_pending: Kazu referál ne'e pendente hela. case_transfer_pending: Kazu transferénsia ne'e pendente hela. case_no_approval_request: Laiha pedidu aprovasaun ba Kazu ida ne'e. bulk_assign_limit: Ita labele atribui liu husi kazu 100 dala ida. bulk_assign_limit_try_again: Ita labele atribui Kazu liu 100 dala ida. Favór hili Kazu 100 ka menus depois koko fila-fali. - referral_rejected: "Referál Rejeita ona " + referral_rejected: 'Referál Rejeita ona ' transfer_request_made: Pedidu Transferénsia kria ona ba Kazu ida ne'e. save: Salva Kazu - save_text: "Molok kontinua, Favór salva ita-boot nia mundansa sira ba Kazu." + save_text: Molok kontinua, Favór salva ita-boot nia mundansa sira ba Kazu. skip_and_create: Haksoit no kria Kazu Foun. search_existing: Buka kazu eziste - search_helper_text: "Tanba sa? Atu prevene kriasaun ba duplikasaun kazu." + search_helper_text: Tanba sa? Atu prevene kriasaun ba duplikasaun kazu. consent_agreements: Hili akordu konsentimentu hotu ne'ebé aplika legitimate_basis: Hili klasifikasaun baze lejítimu hotu ne'ebé aplika - family_linked_subform_delete_disabled: "" workflow: assessment: Avaliasaun case_plan: Planu Kazu @@ -292,7 +275,7 @@ tet: action_plan: Planu Asaun access_denied: "Ita lahetan asesu ba Kazu ida ne'e." age: Tinan - age_estimated: "Estimasaun Tinan?" + age_estimated: Estimasaun Tinan? agency: Ajénsia apply_filter: Aplika approval_comments: Komentáriu @@ -326,7 +309,7 @@ tet: export: Esporta mark_for_offline: title: Marka ba Offline - text: "Ita iha serteza ita hakarak marka Kazu hirak-ne'e hodi uza bainhira ita offline?" + text: Ita iha serteza ita hakarak marka Kazu hirak-ne'e hodi uza bainhira ita offline? success: Kazu marka ona ho susesu ba uza offline filter_by: 3month_inactivity: Ba fulan 3+ @@ -335,7 +318,7 @@ tet: age_12_17: 12 - 17 age_18_more: 18+ age_6_11: 6 - 11 - age_range: "Faixa Tinan " + age_range: 'Faixa Tinan ' agency: Ajénsia approval_status: Status Aprovasaun approvals: @@ -356,21 +339,21 @@ tet: enabled_disabled: Ativadu / Dezativadu female: Feto flag: Flagged - flag_label: "Flagged?" - gbv_closure: " Terminasaun VBJ" + flag_label: Flagged? + gbv_closure: ' Terminasaun VBJ' high: Aas low: Badak male: Mane medium: Médiu mobile: Telefone - mobile_label: "Marka ba telefone?" + mobile_label: Marka ba telefone? my_cases: Ha'u nia Kazu Sira no_action: La iha Asaun no_activity: La iha Atividade open: Loke other: Seluk photo: Fotografia - photo_label: "Iha Fotografia?" + photo_label: Iha Fotografia? protection_concerns: Prekupasaun ba Protesaun protection_status: Status Protesaun record_state: Estadu Rejistu @@ -387,10 +370,10 @@ tet: workflow: Kazu tuir Workflow flag_summary: Sumáriu flag full_name: Naran Kompletu - gbv_closure: " Terminasaun VBJ" + gbv_closure: ' Terminasaun VBJ' hide_name: Subar Naran hide_name_error: Akontese erru bainhira salva ita-boot nia mudansas. Favór koko dala ida tan. - id: "#ID" + id: '#ID' label: Kazu Sira my_filters: Ha'u nia Filtru sira name: Naran @@ -411,10 +394,10 @@ tet: referral_done: Hanehan 'Remata' signifika katak ita kompleta ona servisu referál ne'ebé asosiadu ho kazu nee. Bainhira ita klike 'Remata' ita sei la iha ona asesu ba rejistu nee. referral_done_success: Referál Remata. referral_accepted_header: Simu Referál - referral_accepted: "Ita iha serteza? Agora ita sei sai nu'udar responsavel atu kompleta serbisu ne'ebé asosiadu ho Referál ne'e." + referral_accepted: Ita iha serteza? Agora ita sei sai nu'udar responsavel atu kompleta serbisu ne'ebé asosiadu ho Referál ne'e. referral_accepted_success: Simu ona Referál. - referral_rejected: "Wainhira hanehan 'Rejeita' ita indika katak oras ne'e daudaun ita seidauk prontu atu simu responsabilidade ba referál ne'e. Favór mensiona razaun ida katak ita rejeita Referál ne'e; bainhira hanehan 'Rejeita' ita sei la iha ona asesu ba rejistu kazu ne'e. " - referral_rejected_success: "Referál Rejeita ona " + referral_rejected: 'Wainhira hanehan ''Rejeita'' ita indika katak oras ne''e daudaun ita seidauk prontu atu simu responsabilidade ba referál ne''e. Favór mensiona razaun ida katak ita rejeita Referál ne''e; bainhira hanehan ''Rejeita'' ita sei la iha ona asesu ba rejistu kazu ne''e. ' + referral_rejected_success: 'Referál Rejeita ona ' register_new_case: Kazu Foun registration_date: Data Rejistrasaun rejected_success_action_plan: '%{approval_label} - La Aprovadu' @@ -426,24 +409,24 @@ tet: reopen_dialog: Hanehan OK sei muda status husi kazu ne'e ba Nakloke reopen_dialog_title: Kazu Loke Filafali reopen_success: Kazu loke filafali ho susesu - request_approval_failure: "Akontese erru ida, favór kontaktu apoiu." + request_approval_failure: Akontese erru ida, favór kontaktu apoiu. request_approval_select: Pedidu Aprovasaun ba - request_approval_success_action_plan: "Pedidu aprovasaun ba formuláriu %{approval_label}" - request_approval_success_assessment: "Pedidu aprovasaun ba formuláriu %{approval_label}" - request_approval_success_case_plan: "Pedidu aprovasaun ba formuláriu %{approval_label}" - request_approval_success_closure: "Pedidu aprovasaun ba formuláriu %{approval_label}" - request_approval_success_gbv_closure: "Pedidu aprovasaun ba formuláriu %{approval_label}" + request_approval_success_action_plan: Pedidu aprovasaun ba formuláriu %{approval_label} + request_approval_success_assessment: Pedidu aprovasaun ba formuláriu %{approval_label} + request_approval_success_case_plan: Pedidu aprovasaun ba formuláriu %{approval_label} + request_approval_success_closure: Pedidu aprovasaun ba formuláriu %{approval_label} + request_approval_success_gbv_closure: Pedidu aprovasaun ba formuláriu %{approval_label} request_approval_type_of_case_plan: Tipu husi Aprovasaun Planu Kazu - request_approve_action_plan: "Aprova Planu Asaun?" - request_approve_bia: "Aprova avaliasaun?" + request_approve_action_plan: Aprova Planu Asaun? + request_approve_bia: Aprova avaliasaun? request_approve_case_plan: Aprova Planu Kazu - request_approve_closure: "Aprova Terminasaun?" - request_approve_gbv_closure: "Aprova Terminasaun VBJ?" - revoke_failure: "Akontese erru ida bainhira revoga %{transition_type}, favór kontaktu apoiu." - revoke_message: "Bainhira hanehan 'Revoga' ita sei elimina %{transition_type}benefisiáriu ninia asesu ba kazu." - revoke_success_message: "Kazu %{case_id}%{transition_type}to'o%{recipient_username} revoga ona." + request_approve_closure: Aprova Terminasaun? + request_approve_gbv_closure: Aprova Terminasaun VBJ? + revoke_failure: Akontese erru ida bainhira revoga %{transition_type}, favór kontaktu apoiu. + revoke_message: Bainhira hanehan 'Revoga' ita sei elimina %{transition_type}benefisiáriu ninia asesu ba kazu. + revoke_success_message: Kazu %{case_id}%{transition_type}to'o%{recipient_username} revoga ona. save_filter: Salva - selected_all_records: "Hili hotu %{total_records}kazu sira ne'ebé koresponde ho pergunta ne'e." + selected_all_records: Hili hotu %{total_records}kazu sira ne'ebé koresponde ho pergunta ne'e. selected_records: '%{select_records} kazu(s) selesionadu' sex: Sexu show_case: 'ID kazu: %{short_id}' @@ -458,25 +441,25 @@ tet: fields: consent_for_tracing: label: Hetan ona konsentimentu atu loke informasaun ba objetivu hodi buka tuir - help_text: "Bainhira kampu ida ne'e 'Lae', labarik nia rejistu kazu sei la hatudu iha Korespondensia ho Inkeridor Pedidu Buka Tuir" + help_text: Bainhira kampu ida ne'e 'Lae', labarik nia rejistu kazu sei la hatudu iha Korespondensia ho Inkeridor Pedidu Buka Tuir wishes_child_family_tracing: - label: "Labarik ne'e hakarak buka tuir ninia membru família sira?" + label: Labarik ne'e hakarak buka tuir ninia membru família sira? wishes_reunification: - label: "Labarik ne'e hakarak reunifikasaun família?" + label: Labarik ne'e hakarak reunifikasaun família? options: - yes_as_soon_as_possible: "Loos, posivel ho lalais liu tan" - yes_but_later: "Loos, maibe depois" + yes_as_soon_as_possible: Loos, posivel ho lalais liu tan + yes_but_later: Loos, maibe depois not_sure: La serteza 'no': 'Lae' data_confidentiality_link: - label: "Haree Dadus nia Konfidensialidade " + label: 'Haree Dadus nia Konfidensialidade ' child_wishes_link: label: Haree Labarik nia Hakarak survivor_code: Kódigu Sobrevivente transfer_accepted: Wainhira hanehan 'Simu' ita simu responsabilidade ba kazu ida ne'e; bainhira ita hanehan 'Simu' ita sei sai na'in ba rejistu ne'e iha sistema. - transfer_managed_user_accepted: "Se ita hanesan 'Simu', %{transitioned_to}sei sai responsavel ba kazu ne'e; bainhira ita hanehan 'Simu', %{transitioned_to}sei sai hanesan na'in ba rejistu iha sistema." - transfer_managed_user_rejected: "Wainhira hanehan 'Rejeita' ita indika katak oras ne'e daudaun %{transitioned_to} seidauk prontu atu simu responsabilidade ba kazu ne'e. Favór dehan razaun ida tansa ita rejeita kazu ne'e; bainhira ita hanehan 'Rejeita' %{transitioned_to} sei laiha ona asesu ba rejistu kazu ne'e." - transfer_accepted_rejected: "Kazu %{record_id} transferensia rejeita ona." + transfer_managed_user_accepted: Se ita hanesan 'Simu', %{transitioned_to}sei sai responsavel ba kazu ne'e; bainhira ita hanehan 'Simu', %{transitioned_to}sei sai hanesan na'in ba rejistu iha sistema. + transfer_managed_user_rejected: Wainhira hanehan 'Rejeita' ita indika katak oras ne'e daudaun %{transitioned_to} seidauk prontu atu simu responsabilidade ba kazu ne'e. Favór dehan razaun ida tansa ita rejeita kazu ne'e; bainhira ita hanehan 'Rejeita' %{transitioned_to} sei laiha ona asesu ba rejistu kazu ne'e. + transfer_accepted_rejected: Kazu %{record_id} transferensia rejeita ona. transfer_accepted_success: Kazu transferensia simu ona ho susesu. transfer_reject_reason_label: Razaun Rejeisaun transfer_rejected: Wainhira hanehan 'Rejeita' ita indika katak oras ne'e daudaun ita seidauk prontu atu simu responsabilidade ba kazu ne'e. Favór dehan razaun ida tansa ita rejeita kazu ne'e; bainhira hanehan ona 'Rejeita' ita sei laiha ona asesu ba rejistu kazu ne'e. @@ -506,11 +489,11 @@ tet: date_of_creation: Data Kriasaun registration_date: Data Rejistrasaun configurations: - apply_label: "Ita iha serteza? Karik ita aplika, instalasaun sira iha konfigurasaun ne'e sei aplika ba sistema. Ita sei lakon instalasaun atual hotu no sei la bele hetan filafali anaunser ita salva ona iha Konfigurasaun seluk." + apply_label: Ita iha serteza? Karik ita aplika, instalasaun sira iha konfigurasaun ne'e sei aplika ba sistema. Ita sei lakon instalasaun atual hotu no sei la bele hetan filafali anaunser ita salva ona iha Konfigurasaun seluk. apply_label_bold: Primero sei la disponivel ba utilizador sira iha minutu balun wainhira mudansa lao hela. - version_mismatch_tooltip: "Ita labele aplika konfigurasaun ne'e, tamba ida ne'e kria tiha ona utiliza versaun ne'ebé aas liu husi Primero duké ida ne'ebé ita nia sítiu uza hela. Favór hein atu aplika konfigurasaun ne'e to'o bainhira ita uza versaun foun Primero nian." + version_mismatch_tooltip: Ita labele aplika konfigurasaun ne'e, tamba ida ne'e kria tiha ona utiliza versaun ne'ebé aas liu husi Primero duké ida ne'ebé ita nia sítiu uza hela. Favór hein atu aplika konfigurasaun ne'e to'o bainhira ita uza versaun foun Primero nian. send_header: Haruka ba Produsaun - send_text: "Ita iha serteza? Karik ita hanehan Haruka, ita sei haruka konfigurasaun ne'e ba ita nia sítiu Produsaun. Konfigurasaun ne'e sei la aplika iha Produsaun to'o bainhira administradór husi sítiu ne'e aplika manualmente." + send_text: Ita iha serteza? Karik ita hanehan Haruka, ita sei haruka konfigurasaun ne'e ba ita nia sítiu Produsaun. Konfigurasaun ne'e sei la aplika iha Produsaun to'o bainhira administradór husi sítiu ne'e aplika manualmente. attributes: created_by: Kria Husi date_created: Data Kriasaun @@ -520,7 +503,7 @@ tet: name: Naran version: Versaun Konfigurasaun primero_version: Versaun Primero - delete_label: "Ita iha serteza ita hakarak halo ne'e? Ida ne'e reprezenta instalasaun hotu hahu husi Konfigurasaun ne'e kria. Ita sei labele filafali no rekopera instalasaun hirak ne'e bainhira ita hamoos ona husi konfigurasaun ne'e. " + delete_label: 'Ita iha serteza ita hakarak halo ne''e? Ida ne''e reprezenta instalasaun hotu hahu husi Konfigurasaun ne''e kria. Ita sei labele filafali no rekopera instalasaun hirak ne''e bainhira ita hamoos ona husi konfigurasaun ne''e. ' explanation: 'Hanehan Salva sei kria rejistu ba konfigurasaun atual sira (ezemplu: Knaar sira, Ajénsia sira, Formuláriu sira) iha momentu ida ne''e. Hafoin ita salva, ita bele haruka mudansa hirak ne''e ba instánsia seluk Primero nian. Karik, iha futuru, ita halo mudansa iha konfigurasaun ida ne''ebé ita hakarak atu filafali ba kotuk, ita bele aplika rejistu Konfigurasaun ne''e atu restaura mudansa hotu iha konfigurasaun ne''ebé ita halo ona iha momentu ida ne''e.' label: Konfigurasaun label_new: Konfigurasaun Foun @@ -529,7 +512,7 @@ tet: created: Konfigurasaun kria ona ho susesu. deleted: Konfigurasaun hamoos ona ho susesu. updated: Konfigurasaun atualiza ona ho susesu. - sent: "Haruka konfigurasaun ba produsaun. Favór verifika sítiu produsaun atu haree karik ita nia konfigurasaun to'o ona. " + sent: 'Haruka konfigurasaun ba produsaun. Favór verifika sítiu produsaun atu haree karik ita nia konfigurasaun to''o ona. ' not_allowed: La autoriza unavailable_server: Servidor la disponivel temporariamente . contact: @@ -556,7 +539,7 @@ tet: updated: Kódigu Konduta atualiza ona ho susesu. dashboard: activity: Atividade - admin_only: "Hanehan iha %{links} atu halo mudansa ba aplikasaun." + admin_only: Hanehan iha %{links} atu halo mudansa ba aplikasaun. all_cases: Kazu Hotu-hotu all_services_implemented: Servisu Hotu-hotu ne'ebé implementa ona and: 'ho' @@ -578,14 +561,14 @@ tet: approval_closure_rejected: Rejeitadu approval_gbv_closure_approved: Aprovadu approval_gbv_closure_pending: Pendente - approval_gbv_closure_pending_group: " Terminasaun VBJ" + approval_gbv_closure_pending_group: ' Terminasaun VBJ' approval_gbv_closure_rejected: Rejeitadu approvals: Aprovasaun approvals_action_plan: Planu Asaun approvals_assessment: Avaliasaun approvals_case_plan: Planu Kazu approvals_closure: Terminasaun - approvals_gbv_closure: " Terminasaun VBJ" + approvals_gbv_closure: ' Terminasaun VBJ' approved: Aprovadu assessment: Avaliasaun awaiting_acceptance: Hein atu simu @@ -617,26 +600,26 @@ tet: count_new_closure_approvals: other: '%{stat} foun %{stat_type} Aprovasaun' count_pending_approval_total: - other: 'Ita iha %{stat}pendente%{stat_type}Aprovasaun' + other: Ita iha %{stat}pendente%{stat_type}Aprovasaun count_pending_transfers: - other: 'Ita iha %{stat}Transferensia pendente' + other: Ita iha %{stat}Transferensia pendente count_records_new: other: ho %{stat}kazu foun count_records_total: - other: 'Ita iha %{stat}totál kazu' + other: Ita iha %{stat}totál kazu count_referrals_new: other: ho %{stat}referál foun count_referrals_total: other: 'Ita iha %{stat}referál totál ' count_rejected_approval_total: - other: 'ho %{stat} rejeitadu %{stat_type}Aprovasaun' + other: ho %{stat} rejeitadu %{stat_type}Aprovasaun count_rejected_transfers: - other: 'ho %{stat} Transferensia rejeitadu' + other: ho %{stat} Transferensia rejeitadu count_risk_level_new: other: ho %{stat}foun%{stat_type}kazu risku count_risk_level_total: - other: 'Ita iha %{stat}%{stat_type}kazu risku' - count_waiting_for_acceptance_transfers: "Ita iha %{stat}Transferensia hein atu ita simu" + other: Ita iha %{stat}%{stat_type}kazu risku + count_waiting_for_acceptance_transfers: Ita iha %{stat}Transferensia hein atu ita simu current_owner: Nain Atual dash_case_incident_overview: Ha'u nia Kazu dash_group_overview: Ha'u nia Grupu nia Kazu @@ -655,10 +638,10 @@ tet: due: Tarde flagged: Flagged flagged_by: 'Flagged tuir:' - flagged_by_me: "Flagged Husi Ha'u:" + flagged_by_me: 'Flagged Husi Ha''u:' flagged_by_other: Flagged Husi Ema Seluk flagged_cases: Kazu Flagged - follow_up: " Akompañamentu" + follow_up: ' Akompañamentu' forms: Tab FORMATU geographic_area: Area Jeográfiku group_overview_closed: Taka ona @@ -675,11 +658,11 @@ tet: low_level: Ki'ik low_risk: Prioridade Ki'ik manager_count_closed_total: - other: 'ho %{stat}kazu terminadu' + other: ho %{stat}kazu terminadu manager_count_open_total: - other: 'Ita iha %{stat}kazu loke' + other: Ita iha %{stat}kazu loke manager_transfers_totals: - other: 'Ita iha %{stat}%{stat_type}Transferensia' + other: Ita iha %{stat}%{stat_type}Transferensia match_result: Rezultadu Korespondente medium_level: Médiu medium_risk: Prioridade Médiu @@ -794,15 +777,14 @@ tet: referral_html: '%{user}hosi %{agency}refere ona %{record_type}ba ita: %{record_id}ba%{service_type}.' transfer_html: '%{user}transfere ona %{record_type}ba ita: %{record_id}.' assign_html: '%{user}atribui ona %{record_type}ba ita: %{record_id}.' - transfer_request_html: 'Utilizador Primero%{user}hosi%{agency}hato''o pedidu ba ita katak na''in ba transferensia husi %{record_type}rejistu %{record_id}atu nun''e sira be''e fornese %{record_type}jestaun servisu ba individu ne''e iha sira nia area. Bainhira ita simu transferensia ne''e, favór hanehan iha %{record_type}ligasaun ID iha email atu loke %{record_type}iha Primero no hahu halo transferensia.' + transfer_request_html: 'Utilizador Primero%{user} hosi %{agency} hato''o pedidu ba ita katak na''in ba transferensia husi %{record_type} rejistu %{record_id} atu nun''e sira be''e fornese %{record_type} jestaun servisu ba individu ne''e iha sira nia area. Bainhira ita simu transferensia ne''e, favór hanehan iha %{record_type} ligasaun ID iha email atu loke %{record_type} iha Primero no hahu halo transferensia.' transfer_request_notes_html: 'Notas husi individu ne''ebé mak hato''o pedidu: %{request_transfer_notes}' - alert: '' alert_subject: '%{record_type}:%{id}-%{form_name}Atualiza ona' webpush_notification: action_label: Ba Kazu approval_request: title: Pedidu Aprovasaun - body: "Kazu ida iha ita nia ekipa iha pedidu aprovasaun pendente ba %{type}." + body: Kazu ida iha ita nia ekipa iha pedidu aprovasaun pendente ba %{type}. approval_response: title: Resposta Aprovasaun body: Ita nia Kazu ida hetan ona resposta aprovasaun. @@ -827,20 +809,17 @@ tet: password_extra_info: Seña tenke ho karatér mínimu 8. Seña ida ne'e sei asosiadu ho arkivu esportadu no sei presiza hatama husi ema ruma ne'ebé loke arkivu ne'e iha futuru. password_label: Favór hatama seña ida ne'ebé sei kriptografa ita nia arkivu. error_message: - address_fields: "Ita presiza diriji kampu %{fields}ba formatu %{forms}" - address_form_fields: "Ita presiza diriji kampu %{fields}ba formatu ida ne'e" + address_fields: Ita presiza diriji kampu %{fields}ba formatu %{forms} + address_form_fields: Ita presiza diriji kampu %{fields}ba formatu ida ne'e address_subform_fields: '%{subform}iha %{fields}kampu inválidu' - error_401: "" error_something_went_wrong: Buat ruma lafunsiona ho loos. error_page: not_authorized: - code: 403 server_error: Ita la hetan autorizasaun atu asesu pájina ida ne'e. title: La Hetan Autorizasaun not_found: - code: 404 - contact_admin: "Se ita fiar iha ne'e tanba kauza husi erru, favór kontaktu ita nia admin." - something_went_wrong: "Deskulpa, iha fallansu ruma!" + contact_admin: Se ita fiar iha ne'e tanba kauza husi erru, favór kontaktu ita nia admin. + something_went_wrong: Deskulpa, iha fallansu ruma! errors: api: internal_server: Erru iha servidor @@ -856,14 +835,14 @@ tet: date_of_birth: Favór hatama data moris válidu ida ba kazu rejistu ida ne'e export_configuration: opt_out_field_does_not_exist: Kampu espesífiku opt_out la eziste iha rejistu ne'e. - record_type: "Tipu rejistu inválidu. Tenke Labarik, Pedidu Buka Tuir, ka Insidente." + record_type: Tipu rejistu inválidu. Tenke Labarik, Pedidu Buka Tuir, ka Insidente. field: translated_options_do_not_match: Kampu opsaun tradusaun tenke iha ids hanesan location: admin_level_present: Labele husik mamuk code_present: Labele husik mamuk name_present: Labele husik mamuk - unique_location_code: "Fatin ho kódigu fatin hanesan ne'e eziste ona, favór hatama kódigu fatin seluk " + unique_location_code: 'Fatin ho kódigu fatin hanesan ne''e eziste ona, favór hatama kódigu fatin seluk ' lookup: being_used: Peskiza ne'e uza tiha ona no labele hamoos name_present: Naran labele husik mamuk @@ -872,7 +851,7 @@ tet: associated_record_types: Pelu menus tipu rejistu ida tenke asosiadu ho modulu ne'e form_section_ids: Pelu menus formatu ida tenke asosiadu ho modulu ne'e name_present: Naran labele husik mamuk - unique_name: "Modulu ho naran hanesan ne'e eziste ona, favór hatama naran seluk" + unique_name: Modulu ho naran hanesan ne'e eziste ona, favór hatama naran seluk report: module_presence: Modulu labele husik mamuk module_syntax: Relatóriu modulu hotu-hotu tenke eziste ona @@ -882,7 +861,7 @@ tet: user: email: "Favór hatama email válidu ida (ezemplu: 'naran@ezemplu.org') " password_mismatch: Kampu seña laiha seña ne'ebé hanesan - password_length: "Seña tenke pelu menus iha karater %{min}" + password_length: Seña tenke pelu menus iha karater %{min} email_uniqueness: Utilizador ida ho naran email ida ne'e eziste ona. Favór hatama naran seluk ida code_of_conduct: title_present: Títulu labele husik mamuk @@ -893,7 +872,7 @@ tet: notification_url_format: notifikasaun_url tenke iha formatu URL auth_present: Auth tenke labele husik mamuk p256dh_present: p256dh tenke labele husik mamuk - not_found: "La hetan Rejistu(s) " + not_found: 'La hetan Rejistu(s) ' try_again: Koko tan exports: case_pdf: @@ -908,7 +887,7 @@ tet: all: Personalizadu custom_exports: all: Personalizadu - choose_fields: "Ita hakarak atu hili kampu individual ba formatu ida?" + choose_fields: Ita hakarak atu hili kampu individual ba formatu ida? empty_fields_forms: Favór hili formatu ka kampu balun atu esporta. empty_format: Favór hili formatu ida atu esporta. empty_module: Favór hili modulu ida atu esporta. @@ -925,10 +904,10 @@ tet: header: Header custom_header: Header Personalizadu signatures: Inklui liña asinatura ba - include_implementation_logos: "Inklui logo implementasaun?" + include_implementation_logos: Inklui logo implementasaun? include_implementation_logos_help_text: Ida ne'e sei inklui logo ne'ebé mosu iha menu navegasaun no iha pájina rejistu tama. - include_agency_logo: "Inklui logo ajénsia?" - include_other_logos: "Inklui logo seluk?" + include_agency_logo: Inklui logo ajénsia? + include_other_logos: Inklui logo seluk? duplicate_id_csv: all: Duplika ID female_abbreviation: F @@ -981,7 +960,6 @@ tet: form: Formuláriu Primero status: Status notes: Notas - go_to_exports: Ba pájina Esportasaun atu download incident_recorder_xls: all: Rejistrador Insidente @@ -1022,9 +1000,9 @@ tet: one: Fotografia Parede reunited: Reunidu selected: Hili ba Fotografia Parede - success_message: "Kria Fotografia Parede %{file_name}Kazu la iha fotografia sei labele inklui." - printed: 'Imprimi ona:%{date}' - queueing: "Kria arkivu esportasaun %{file_name}" + success_message: Kria Fotografia Parede %{file_name} Kazu la iha fotografia sei labele inklui. + printed: 'Imprimi ona: %{date}' + queueing: Kria arkivu esportasaun %{file_name} selected_xls: all: Excel one: Excel @@ -1046,7 +1024,7 @@ tet: governorate_country: Governador - Nasaun id: ID individual_progress_id: ID Progresu Individual - locations_by_level: "Hela Fatin (Aldeia, Suku, no nivel hela fatin ne'ebé aplikavel, hanesan kordenasaun GPS uma-mahon)" + locations_by_level: Hela Fatin (Aldeia, Suku, no nivel hela fatin ne'ebé aplikavel, hanesan kordenasaun GPS uma-mahon) long_id: ID Naruk moha_id: ID MOHA name_of_caregiver: Naran Kompletu husi Kuidadu Nain @@ -1074,8 +1052,8 @@ tet: success: Fatin importa ona ho susesu no_data: 'La Prosesa Importasaun: Laiha data mak tama' csv_parse_error: 'La Prosesa Importasaun: Erru analiza dadus CSV' - error: 'Liña %{row_number}La Prosesa: %{message}' - db_error: 'Erru iha kriasaun %{location_code}:%{message}' + error: 'Liña %{row_number} La Prosesa: %{message}' + db_error: 'Erru iha kriasaun %{location_code}: %{message}' locale_invalid: 'Haksoit %{column_name}: Lokál inválidu' insert_all_error: 'La Prosesa Importasaun. Erru iha Baze Dadus: %{message}' csv_record: @@ -1084,8 +1062,8 @@ tet: no_data: 'La Prosesa Importasaun: Laiha data mak tama' no_file: 'La Prosesa Importasaun: Arkivu la eziste' csv_parse_error: 'La Prosesa Importasaun: Erru analiza dadus CSV' - error: 'Liña %{row_number}La Prosesa: %{message}' - db_error: 'Erru iha kriasaun %{location_code}:%{message}' + error: 'Liña %{row_number} La Prosesa: %{message}' + db_error: 'Erru iha kriasaun %{location_code}: %{message}' locale_invalid: 'Haksoit %{column_name}: Lokál inválidu' insert_all_error: 'La Prosesa Importasaun. Erru iha Baze Dadus: %{message}' sync_record: @@ -1101,7 +1079,7 @@ tet: add_new_field: Kria Kampu Foun add_existing_field: Aumenta Kampu Ne'ebé Eziste ona add_field: Aumenta Kampu - add_field_type: "Aumenta %{file_type}" + add_field_type: Aumenta %{file_type} audio: current: Áudio Atual audio_upload_box: Hatama Áudio @@ -1115,7 +1093,7 @@ tet: create_unique_values: Kria valór úniku date_field: Data Kampu date_help: ll-ff-tttt - date_help_with_time: "ll-fff-tttt oo:mm" + date_help_with_time: ll-fff-tttt oo:mm date_not_valid: Data ida ne'e la válidu. time: Oras date_range: @@ -1127,24 +1105,24 @@ tet: date_range_field: Faixa Data date_time: Data-Oras db_name: Naran Baze de Dadus - default: "Padraun?" + default: Padraun? default_date_validation: Data validasaun padraun - default_to_current_date: "Data atual padraun?" - default_to_current_datetime: "Data no oras atual padraun?" + default_to_current_date: Data atual padraun? + default_to_current_datetime: Data no oras atual padraun? default_value: Valór Padraun - deleted: "Kampu %{display_name}hamoos tiha ona." + deleted: Kampu %{display_name} hamoos tiha ona. detail: Detallu disabled: Dezativadu display_name: Naran atu Hatudu document: comments: Komentáriu - current: "Ida ne'e mak dokumentu atual?" + current: Ida ne'e mak dokumentu atual? date: Data Dokumentu name: Naran Dokumentu - is_current: "Ida ne'e mak dokumentu atual?" + is_current: Ida ne'e mak dokumentu atual? document_upload_box: Hatama Dokumentu edit_label: Hadia Kampu - enabled: "Ativadu?" + enabled: Ativadu? enabled_label: Ativadu english_text: Testu Inglés field_name: Naran Kampu @@ -1157,7 +1135,7 @@ tet: add_photo_label: Aumenta Fotografia document_description: Deskrisaun Dokumentu document_file_restrictions_message: Arkivu labele bo'ot liu 2 MB (Arkivu ne'ebé ezekuta (.exe) labele hatama). - no_file_selected: "Seidauk hili Arkivu " + no_file_selected: 'Seidauk hili Arkivu ' photo_file_restrictions_message: Fotografia labele bo'ot liu 10mb. Arkivu áudio labele bo'ot liu 10mb. Ki'ik liu di'ak liu tan. recorded_audio_label: Áudio Gravadu select_file_button_text: Hili Arkivu @@ -1178,7 +1156,7 @@ tet: not_future_date: La'os data iha futuru number_not_valid: Favór hatama dadus numériku numeric_field: Kampu Numériku - on_collapsed_subform: "Iha subfomuláriu naksobu?" + on_collapsed_subform: Iha subfomuláriu naksobu? option_strings_add_option: Aumenta Opsaun option_strings_source: Peskiza option_strings_text: Opsaun @@ -1192,20 +1170,20 @@ tet: predifined_lookups: Uza peskiza pre-definidu radio_button: Butaun Rádiu remove: Hasai - remove_attachment_confirmation: "Ita iha serteza ita hakarak hasai aneksu ida ne'e?" + remove_attachment_confirmation: Ita iha serteza ita hakarak hasai aneksu ida ne'e? required: Obrigatóriu - required_field: '%{field}ne''e obrigatóriu' + required_field: '%{field} ne''e obrigatóriu' search_existing: Buka kampu ne'ebé eziste select_box: Hili Drop Down - select_date_validation: "Hili data métodu validasaun " + select_date_validation: 'Hili data métodu validasaun ' select_multiple: Hili saida de'it mak aplika select_single: (Hili...) separator: Separador - show: "Hatudu?" + show: Hatudu? show_on: Hatudu iha show_on_minify_form: Formuláriu badak skip_logic: - name: "Halo liu tiha Lójiku?" + name: Halo liu tiha Lójiku? record_section: title: Kampu ne'e tenke vízivel se rejistu buttons: @@ -1216,13 +1194,13 @@ tet: add: Aumenta kondisaun subformuláriu subform: Subformuláriu subform_group_by: Grupu tuir - subform_remove_message: "Ita iha serteza ita hakarak hasai subformuláriu ida ne'e?" + subform_remove_message: Ita iha serteza ita hakarak hasai subformuláriu ida ne'e? subform_section: description: Deskrisaun Subformuláriu name: Títulu Subformuláriu - starts_with_one_entry: "Hahu ho hatama subformuláriu ida?" + starts_with_one_entry: Hahu ho hatama subformuláriu ida? subform_append_only: Sikronizasaun Seletivu iha Telefone - subform_prevent_item_removal: "Prevene eliminasaun hatama subformuláriu?" + subform_prevent_item_removal: Prevene eliminasaun hatama subformuláriu? subform_sort_by: Ordena tuir successfully_added: Kampu aumenta ona ho susesu tally_field: Konta Kampu  @@ -1258,7 +1236,7 @@ tet: flag_reason_maximun_label: Karater Másimu 255 flag_resolved: Flag rezolve ona flags_tab: Flags - no_flags: "La hetan Flag " + no_flags: 'La hetan Flag ' resolve_button: Rezolve resolve_flag: Rezolve Flags resolve_reason: Rezolve Razaun @@ -1273,7 +1251,7 @@ tet: module: Modulu name: Naran record_type: Tipu Rejistu - required_field: '%{field}ne''e obrigatóriu' + required_field: '%{field} ne''e obrigatóriu' forms: add: Aumenta Formuláriu description: Deskrisaun Formuláriu @@ -1285,7 +1263,7 @@ tet: must_be_english: Tenke hatama iha dalen Inglés related_groups: Tau formuláriu iha grupu relasionadu ba utilizador summariaze_purpose: Sumariza objetivu formuláriu. Tenke hatama iha dalen Inglés - invalid_characters_field: '%{field}iha karater inválidu.' + invalid_characters_field: '%{field} iha karater inválidu.' label: Formuláriu sira manage: Jere messages: @@ -1308,7 +1286,7 @@ tet: potential_match: Korespondente Potensial record_information: Rejistu Informasaun referrals: Referál - reportable_follow_up: " Akompañamentu" + reportable_follow_up: ' Akompañamentu' reportable_protection_concern: Prekupasaun ba Protesaun reportable_service: Servisu tracing_request: Pedidu Buka-Tuir @@ -1318,13 +1296,13 @@ tet: registry_record: Grava Rejistrasaun family_record: Arkivu Família family: Arkivu Família - required_field: '%{field}ne''e kampu obrigatóriu ida' + required_field: '%{field} ne''e kampu obrigatóriu ida' select_label: Hili settings: Konfigurasaun show_on: Hatudu iha subform_need_to_be_added: Presiza atu aumenta sira hirak ne'e. subform_need_to_be_added_single: Presiza atu aumenta ida ne'e. - subform_not_found: "%{subform_name}la hetan." + subform_not_found: '%{subform_name} la hetan.' title: Títulu Formuláriu translations: edit: Hadi'a tradusaun @@ -1332,14 +1310,14 @@ tet: manage: Jere tradusaun no_changes_message: Ita seidauk halo mudansa ba tradusaun note: 'Nota:' - note_form_group: "Atu aumenta tradusaun ba Grupu Fomuláriu, ita presiza hadia Grupu Formuláriu peskiza nia tradusaun." + note_form_group: Atu aumenta tradusaun ba Grupu Fomuláriu, ita presiza hadia Grupu Formuláriu peskiza nia tradusaun. select_language: Hili dalen title: Tradusaun type_label: Tipu visibility: Vizivilidade web_app: Web App skip_logic: - name: "Halo liu tiha Lójiku?" + name: Halo liu tiha Lójiku? section: title: Formuláriu ida ne'e tenke vízivel se kuandu buttons: @@ -1410,8 +1388,8 @@ tet: creation_success: Rejistu Insidente kria ona ho susesu. creation_success_queue: Rejistu kazu kria ona ho susesu iha background disabled: Insidente dezativadu - update_success: 'Insidente %{record_id}atualiza ona ho susesu.' - update_success_queue: 'Insidente %{record_id}atualiza ona ho susesu iha background.' + update_success: 'Insidente %{record_id} atualiza ona ho susesu.' + update_success_queue: 'Insidente %{record_id} atualiza ona ho susesu iha background.' violation: associated_violations: "Violasaun Asosiadu:" update_and_return: 'Atualiza no Filafali ba %{association}' @@ -1436,7 +1414,7 @@ tet: enable_dialog: Hanehan OK sei muda status hosi insidente ne'e ba Ativadu. enable_dialog_title: Ativa Insidente enable_success: Insidente ativadu ho susesu. - id: "#ID" + id: '#ID' complete: Disponivel Offline date_of_interview: Data Entrevista date_of_incident: Data Insidente @@ -1456,17 +1434,17 @@ tet: unknown: Deskoñesidu verification_status: Status Verifikasaun violence_type: Tipu Violénsia - armed_force_group_party_name: "Forsa Armada, grupu, ka parte sira seluk" + armed_force_group_party_name: Forsa Armada, grupu, ka parte sira seluk armed_force_group_type: Tipu Grupu Forsa Armada violations: Violasaun individual_violations: Violasaun Individual individual_age: Tinan Individual individual_sex: Sexu Individual victim_deprived_liberty_security_reasons: La iha Liberdade - reasons_deprivation_liberty: "Saida de'it maka sai hanesan razaun ba la iha liberdade?" + reasons_deprivation_liberty: Saida de'it maka sai hanesan razaun ba la iha liberdade? victim_facilty_victims_held: Favór hili fasilidade ne'ebé vítima iha ba - torture_punishment_while_deprivated_liberty: "Labarik sira hetan tortura ka tratamentu ka kastigu ne'ebé aat, dezumanu no degradante bainhira la iha liberdade?" - verified_ghn_reported: "Espesifika GHN iha ne'ebé inklui insidente ne'e " + torture_punishment_while_deprivated_liberty: Labarik sira hetan tortura ka tratamentu ka kastigu ne'ebé aat, dezumanu no degradante bainhira la iha liberdade? + verified_ghn_reported: 'Espesifika GHN iha ne''ebé inklui insidente ne''e ' weapon_type: 'Uza tipu husi arma/métodu saida' facility_impact: 'Tipu no estensun husi impaktu fíziku' facility_attack_type: 'Tipu violasaun relasiona ho saude ka edukasaun' @@ -1484,7 +1462,7 @@ tet: ctfmr_verified_date: Data desizaun Verifikasaun husi CTFMR incident_date_derived: Data Insidente selected_records: 'Hili ona insidente %{select_records}' - selected_all_records: 'Hili hotu %{total_records}insidente sira ne''ebé koresponde ho pergunta ne''e.' + selected_all_records: 'Hili hotu %{total_records} insidente sira ne''ebé koresponde ho pergunta ne''e.' summary_mrm: label: Sumáriu husi Insidente fields: @@ -1546,25 +1524,16 @@ tet: number_of_cases: title: "1. Númeru Kazu sira ne'ebé rejistadu" reporting_site: "Sítiu ba Relatóriu" - helptext: | - Indikador ida ne'e sura kazu foun hira mak loke ona kada fulan tuir sítiu relatóriu. Sítiu relatóriu ne'e konsidera hanesan sítiu ne'ebé Organizasaun Utilizador fornese servisu no - - iha ne'ebé kazu sira ne'e relata ba fornesedor servisu. + helptext: "Indikador ida ne'e sura kazu foun hira mak loke ona kada fulan tuir sítiu relatóriu. Sítiu relatóriu ne'e konsidera hanesan sítiu ne'ebé Organizasaun Utilizador fornese servisu no \n\niha ne'ebé kazu sira ne'e relata ba fornesedor servisu.\n" number_of_incidents: title: "2. Númeru Insidente sira ne'ebé rejistadu" reporting_site: "Sítiu ba Relatóriu" - helptext: | - Indikador ida ne'e sura númeru insidente foun hira mak loke ona kada fulan tuir sítiu relatóriu. Sítiu relatóriu ne'e konsidera hanesan sítiu ne'ebé Organizasaun Utilizador fornese servisu no - - iha ne'ebé kazu sira ne'e relata ba fornesedor servisu. + helptext: "Indikador ida ne'e sura númeru insidente foun hira mak loke ona kada fulan tuir sítiu relatóriu. Sítiu relatóriu ne'e konsidera hanesan sítiu ne'ebé Organizasaun Utilizador fornese servisu no \n\niha ne'ebé kazu sira ne'e relata ba fornesedor servisu.\n" reporting_delay: title: "3. Relatóriu Atrazu" delay: "Atrazu" total_incidents: "Totál Insidente" - helptext: | - Indikador ida ne'e konta no kategoriza númeru loron sira ne'ebé akontese entre bainhira sobrevivente esperiénsia VBJ no bainhira sobrevivente relata dahuluk ba fornesedór servisu ida. - Ida ne'e kalkula bazeia ba akontesimentu ne'ebé relata dahuluk ba Organizasaun Utilizador. - Dadus ne'e kategoria tuir tempu ne'ebé la hanesan (Loron 0-3; loron 4-5; loron 6-14; loron 15-30; Liu fulan 1; Liu fulan 3). + helptext: "Indikador ida ne'e konta no kategoriza númeru loron sira ne'ebé akontese entre bainhira sobrevivente esperiénsia VBJ no bainhira sobrevivente relata dahuluk ba fornesedór servisu ida. \nIda ne'e kalkula bazeia ba akontesimentu ne'ebé relata dahuluk ba Organizasaun Utilizador. \nDadus ne'e kategoria tuir tempu ne'ebé la hanesan (Loron 0-3; loron 4-5; loron 6-14; loron 15-30; Liu fulan 1; Liu fulan 3).\n" service_access_delay: title: "Atrazu Asesu Servisu" delay: "Atrazu" @@ -1573,33 +1542,20 @@ tet: title: "4. Status Avaliasaun" completed: "Kompleta Ona" completed_supervisor_approved: "Kompleta ona & Aprovadu husi Supervizor" - helptext: | - Indikador ida ne'e kalkula proporsaun husi kazu ativu sira ne'ebé formuláriu avaliasaun ida kompleta ona. - Avaliasaun ida konsidera kompleta ona bainhira kampu mandatóriu balun iha formuláriu - Avaliasaun Sobrevivente nian kompleta ona. + helptext: "Indikador ida ne'e kalkula proporsaun husi kazu ativu sira ne'ebé formuláriu avaliasaun ida kompleta ona. \nAvaliasaun ida konsidera kompleta ona bainhira kampu mandatóriu balun iha formuláriu \nAvaliasaun Sobrevivente nian kompleta ona.\n" completed_case_safety_plans: title: "5. Kompleta Ona Planu Seguransa Kazu " completed: "Kompleta Ona Planu Seguransa Kazu " - helptext: | - Indikador ida ne'e kalkula proporsaun husi kazu ativu sira iha ne'ebé planu seguransa konsidera - nesesáriu no kompleta ona (ezemplu: violénsia parseiru íntimu, risku suisidu/omisidu, protesaun labarik). - Planu seguransa ida konsidera kompleta ona bainhira kampu mandatóriu balun iha fomuláriu Planu Seguransa kompleta ona. + helptext: "Indikador ida ne'e kalkula proporsaun husi kazu ativu sira iha ne'ebé planu seguransa konsidera \nnesesáriu no kompleta ona (ezemplu: violénsia parseiru íntimu, risku suisidu/omisidu, protesaun labarik).\nPlanu seguransa ida konsidera kompleta ona bainhira kampu mandatóriu balun iha fomuláriu Planu Seguransa kompleta ona.\n" completed_case_action_plans: title: "6. Kompleta Ona Planu Asaun Kazu" completed: "Kompleta Ona Planu Asaun Kazu" label: "Kompleta Ona Planu Asaun Kazu" - helptext: | - Indikador ida ne'e kalkula proporsaun husi kazu ativu sira ne'ebé kompleta ona Planu Asaun Kazu ida. - Planu Asaun Kazu ida konsidera kompleta ona bainhira kampu mandatóriu balun iha - formuláriu Planu Asaun kompleta ona. + helptext: "Indikador ida ne'e kalkula proporsaun husi kazu ativu sira ne'ebé kompleta ona Planu Asaun Kazu ida.\nPlanu Asaun Kazu ida konsidera kompleta ona bainhira kampu mandatóriu balun iha \nformuláriu Planu Asaun kompleta ona.\n" completed_supervisor_approved_case_action_plans: title: "7. Planu Asaun Kazu Aprovadu husi Supervizor" completed_and_approved: "Planu Asaun Kazu Ne'ebé Kompleta Ona Aprovadu husi Supervizor" - helptext: | - Indikador ida ne'e kalkula proporsaun kazu ativa sira ne'ebé Planu Asaun Kazu kompleta ona no aprovadu husi supervizor ida. - Planu asaun kazu ida konsidera kompleta ona bainhira kampu mandatóriu balun iha formuláriu Planu Asaun kompleta ona. - Planu kazu ida konsidera aprovadu bainhira serbisu nain kazu halo pedidu aprovasaun ba planu kazu ne'e no supervizor - aprova planu kazu ne'e iha plataforma. + helptext: "Indikador ida ne'e kalkula proporsaun kazu ativa sira ne'ebé Planu Asaun Kazu kompleta ona no aprovadu husi supervizor ida. \nPlanu asaun kazu ida konsidera kompleta ona bainhira kampu mandatóriu balun iha formuláriu Planu Asaun kompleta ona. \nPlanu kazu ida konsidera aprovadu bainhira serbisu nain kazu halo pedidu aprovasaun ba planu kazu ne'e no supervizor \naprova planu kazu ne'e iha plataforma.\n" services_provided: title: "8. Fornese ona Servisu" service: "Servisu" @@ -1608,30 +1564,20 @@ tet: female: "Feto" 0-11: "0-11" 12-17: "12-17" - ">18": ">18" + '>18': ">18" disability: "Defisiénsia" no_disability: "La iha Defisiénsia" - helptext: | - Indikador ida ne'e sura tipu servisu sira fornese ona ba sobrevivente sira iha prosesu jestaun kazu. - Fornese ona servisu signifika servisu ne'ebé fornese husi organizasaun Utilizador in-house, - la'os serbisu fornese ona husi referál sira ba serbisu seluk ka referál internal sira. + helptext: "Indikador ida ne'e sura tipu servisu sira fornese ona ba sobrevivente sira iha prosesu jestaun kazu.\nFornese ona servisu signifika servisu ne'ebé fornese husi organizasaun Utilizador in-house, \nla'os serbisu fornese ona husi referál sira ba serbisu seluk ka referál internal sira.\n" average_referrals: title: "9. Referál Médiu" label: "Referál médiu pur kazu" - helptext: | - Indikador ida ne'e konta númeru médiu husi referál sira ba rejistu kazu ida-idak - (ba tipu servisu hotu-hotu) - liu-husi kazu hotu-hotu, Maske kazu ne'e ativu/loke ka taka ona. Ne'e inklui referál - sira ne'ebé rejistadu iha tab kazu, la'os deit referál sira ne'ebé remata ona liu-husi plataforma. + helptext: "Indikador ida ne'e konta númeru médiu husi referál sira ba rejistu kazu ida-idak\n(ba tipu servisu hotu-hotu)\nliu-husi kazu hotu-hotu, Maske kazu ne'e ativu/loke ka taka ona. Ne'e inklui referál \nsira ne'ebé rejistadu iha tab kazu, la'os deit referál sira ne'ebé remata ona liu-husi plataforma.\n" referrals_per_service: title: "Referál pur Servisu" average_followup_meetings_per_case: title: "10. Sorumutuk Akompañamentu Médiu pur Kazu" label: "Sorumutuk Akompañamentu Médiu pur Kazu" - helptext: | - Indikador ida ne'e konta númeru média enkontru follow-up sira ne'ebé konduta ona ba kazu ativu ida-idak pur serbisu nain kazu iha plataforma. - Sorumutuk follow-up mak enkontru entre servisu nain kazu no sobrevivente - hodi akompaña entrevista dahuluk. + helptext: "Indikador ida ne'e konta númeru média enkontru follow-up sira ne'ebé konduta ona ba kazu ativu ida-idak pur serbisu nain kazu iha plataforma.\nSorumutuk follow-up mak enkontru entre servisu nain kazu no sobrevivente \nhodi akompaña entrevista dahuluk.\n" time_from_case_open_to_close: title: "11. Oras Husi Loke Kazu to'o Taka Kazu" time: "Oras" @@ -1643,10 +1589,7 @@ tet: case_closure_rate: title: "12. Kontajen ba Terminasaun Kazu" reporting_site: "Sítiu ba Relatóriu" - helptext: | - Indikador ida ne'e sura kontajen husi kazu ne'ebé taka ona kada fulan kada sítiu relatóriu. - Sítiu relatóriu konsidera hanesan sítiu ida ne'ebé Organizasaun Utilizador fornese servisu sira - no iha ne'ebé insidente relatadu ba fornesedor servisu. + helptext: "Indikador ida ne'e sura kontajen husi kazu ne'ebé taka ona kada fulan kada sítiu relatóriu.\nSítiu relatóriu konsidera hanesan sítiu ida ne'ebé Organizasaun Utilizador fornese servisu sira \nno iha ne'ebé insidente relatadu ba fornesedor servisu.\n" client_satisfaction_rate: title: "13. Taxa Satisfasaun husi Kliente" label: "Kliente nia Satisfasaun" @@ -1657,9 +1600,7 @@ tet: supervisor_to_caseworker_ratio: title: "14. Proporsaun Supervizor ho Serbisu Nain Kazu" label: "Serbisu Nain Kazu pur Supervizor" - helptext: | - Indikador ida ne'e mak númeru servisu nain kazu sira ne'ebé supervizor ida superviziona hela: - proporsaun supervizor ho sevisu nain kazu. Kalkulasaun ida ne'e bazeia ba funsaun sistema aloka ona iha plataforma ne'e. + helptext: "Indikador ida ne'e mak númeru servisu nain kazu sira ne'ebé supervizor ida superviziona hela: \nproporsaun supervizor ho sevisu nain kazu. Kalkulasaun ida ne'e bazeia ba funsaun sistema aloka ona iha plataforma ne'e.\n" case_load: title: "15. Naha Kazu" case_load: "Naha Kazu" @@ -1681,7 +1622,6 @@ tet: aria-labels: from: "Sei hili dadus depois de data ida ne'e" to: "Sei hili dadus depois de data ida ne'e" - location: base_types: camp: Akampamentu @@ -1710,8 +1650,6 @@ tet: municipality: Munisipalidade autonomous_region: Rejiaun Autónomu parish: Parókia - cercle: "" - sub-county: "" label: Fatin name: Naran code: Kódigu @@ -1722,9 +1660,9 @@ tet: message: Favór hili arkivu CSV ida atu upload. Arkivu ne'e tenke uza kodifikasaun UTF-8 no inklui hashtags HXL iha liña daruak husi header iha kada koluna. no_location: Favór importa Fatin molok kria konta Utilizador sira seluk. enable_title: Ativa Fatin - enable_text: "Ita iha serteza? Se ita ativa fatin sira ne'e, sira sei mosu hanesan opsaun iha kampu Fatin" + enable_text: Ita iha serteza? Se ita ativa fatin sira ne'e, sira sei mosu hanesan opsaun iha kampu Fatin disable_title: Dezativa Fatin - disable_text: "Ita iha serteza? Se ita dezativa fatin sira ne'e, sira sei la mosu tan hanesan opsaun iha kampu Fatin" + disable_text: Ita iha serteza? Se ita dezativa fatin sira ne'e, sira sei la mosu tan hanesan opsaun iha kampu Fatin logger: actions: _approved: Aprovadu @@ -1782,17 +1720,17 @@ tet: case_plan: Formuláriu Planu Kazu closure: Fomuláriu Terminasaun 'false': Rejeita - gbv_closure: " Terminasaun VBJ" + gbv_closure: ' Terminasaun VBJ' 'true': Aprova - assessment_approved: "%{approval_label}aprovadu ba" - assessment_requested: "%{approval_label}rekeridu ba" + assessment_approved: "%{approval_label} aprovadu ba" + assessment_requested: "%{approval_label} rekeridu ba" bulk_index: Alista hotu-hotu by_user: tuir utilizador - case_plan_approved: "%{approval_label}aprovadu ba" - case_plan_requested: "%{approval_label}rekeridu ba" + case_plan_approved: "%{approval_label} aprovadu ba" + case_plan_requested: "%{approval_label} rekeridu ba" close: Taka - closure_approved: "%{approval_label}aprovadu ba" - closure_requested: "%{approval_label}rekeridu ba" + closure_approved: "%{approval_label} aprovadu ba" + closure_requested: "%{approval_label} rekeridu ba" consent_count: Kontajen Konsentimentu copy: Kopia hela create: Kria hela @@ -1820,7 +1758,7 @@ tet: quick_view: Haree hela Quick View reassign: Atribui hela resources: - audit_log: "Log Auditoria " + audit_log: 'Log Auditoria ' user: Utilizador agency: Ajénsia user_group: Grupu Utilizador @@ -1877,18 +1815,18 @@ tet: label: Konfirmasaun Seña password_match: label: Seña tenke koresponde - provider_title: "ho %{provider}" + provider_title: ho %{provider} title: Log In username: Naran Utilizador password_reset_modal: Reestabelese seña password_reset_modal_text: Primero sei manda link ba reestabelese seña ba ita nia email password_reset_email: Email - forgot_password: "Haluha ita nia seña?" + forgot_password: Haluha ita nia seña? email: label: Email lookup: create: Lookup foun - enabled_label: "Ativadu?" + enabled_label: Ativadu? english_label: Testu Inglés label: Peskiza language_label: Dalen @@ -1953,7 +1891,6 @@ tet: incomplete_data: Dadus Inkompleta individual_children: name: Labarik Individual - description: '' reports: individual_children: Labarik Individual sub_reports: @@ -1963,7 +1900,6 @@ tet: individual_perpetrator: Labarik Individual tuir Perpetrador ghn_report: name: Nota Orizontal Global - description: '' reports: ghn_report: Nota Orizontal Global sub_reports: @@ -1992,7 +1928,6 @@ tet: associated_violations: Violasaun Asosiadu violations: name: Violasaun - description: '' filter_options: incident_date: Data Insidente date_of_report: Data Relatóriu @@ -2032,7 +1967,7 @@ tet: total: Totál violation: Violasaun sexual_violence_type: Forma husi violénsia seksual - detention_status: "Status ba Labarik iha Detensaun " + detention_status: 'Status ba Labarik iha Detensaun ' type_of_use: Tipu husi uza factors_of_recruitment: Razaun ba rekrutamentu still_being_held: Sei iha hela kapturasaun @@ -2047,40 +1982,14 @@ tet: military_use_type_of_use: Númeru Violasaun tuir tipu husi uza gbv_statistics: name: Estístika VBJ - description: '' filter_options: date_of_first_report: Data Entrevista incident_date: Data Insidente reports: - incidents: Insidente perpetrators: Perpetrador survivors: Sobrevivente referrals: Referál sub_reports: - combined: Insidente - total: Númeru Relata Insidente VBJ - gbv_sexual_violence: Númeru Relata Insidente husi Violénsia Seksual - gbv_previous_incidents: Númeru Insidente Relata husi Sobrevivente sira molok Insidente VBJ - gbv_sexual_violence_type: Tipu Insidente - incident_timeofday: Oras no Loron Insidente - elapsed_reporting_time: Oras Entre Insidente no Data Relatóriu - elapsed_reporting_time_rape: "Insidente Abuzu Seksual, Tempu kaduka entre Insidente no Data halo Relatóriu" - elapsed_reporting_time_rape_health_referral: "Insidente Abuzu Seksual, Tempu kaduka entre Insidente no Data halo Relatóriu (Servisu Saude ka Referál)" - incident_location_type: Fatin Insidente - number_of_perpetrators: Númeru Perpetrador - perpetrator_relationship: Alegadu Relasaun Perpetrador Prinsipal ho Sobrevivente - perpetrator_age_group: "Grupu Tinan Husi Alegadu Perpetrador Prinsipal " - perpetrator_occupation: Okupasaun husi Alegadu Perpetrador Prinsipal - age: Númeru Sobrevivente tuir Tinan - sex: Númeru Sobrevivente tuir Sexu - marital_status: Estadu Sivil husi Sobrevivente sira - displacement_status: Status Dezlokamentu husi Sobrevivente sira - displacement_incident: Nivel Dezlokamentu husi Sobrevivente sira - gbv_case_context: Kontestu Kazu - incidents_first_point_of_contact: Númeru Insidente iha ne'ebé ita nia organizasaun sai hanesan pontu kontaktu dahuluk - incidents_from_other_service_provider: Insidente Refere husi Fornesedor Servisu sira seluk - number_of_services_provided: Númeru Servisu Fornese ona ba Insidente - number_of_services_provided_other: Referál Insidente Foun ba Fornesedor Servisu sira seluk service_safehouse_referral: Referál ba Uma Mahon service_medical_referral: Referál ba Saude/Médiku service_psycho_referral: Servisu Psikososial/Akonsellamentu @@ -2088,11 +1997,9 @@ tet: service_police_referral: Polísia ka Tipu Seluk husi Servisu Seguransa service_livelihoods_referral: Servisu Subsisténsia sira service_protection_referral: Servisu Protesaun Labarik - vulnerable_populations: Populasaun Vulneravel survivors_disability_type: Ho Defisiénsia workflow_report: name: Workflow - description: '' reports: cases_workflow: Workflow - Kazu sira incidents_workflow: Workflow - Insidente sira @@ -2103,7 +2010,6 @@ tet: incident_workflow_by_sex_and_age: Númeru Insidente Total tuir Sexu no Tinan referrals_transfers_report: name: Referál no Transferénsia - description: '' reports: total_referrals: Referál total_transfers: Transfere @@ -2114,7 +2020,6 @@ tet: registration_date: Data Rejistrasaun violence_type_report: name: Tipu husi Violénsia - description: '' reports: cases_violence_type: Tipu husi Violénsia - Kazu sira incidents_violence_type: Tipu husi Violénsia - Insidente sira @@ -2125,29 +2030,29 @@ tet: incident_violence_type_by_sex_and_age: Númeru Insidente Total tuir Sexu no Tinan success_message: Kria ona arkivu esportasaun ho susesu messages: - alert_items: "Ita iha nota %{items}items" + alert_items: Ita iha nota %{items} items alerts_for: - approval: "Aprovasaun pendente hela ba %{form_section_name}" - field_change: '%{form_section_name}atualia ona iha %{alert_time}' - transfer_request: "Pedidu Transferensia foun ida halo ona iha %{date}husi %{user}iha%{agency}" - duplicate_field: "Kazu seluk iha sistema iha %{field_name}hanesan ho ida ne'e." + approval: Aprovasaun pendente hela ba %{form_section_name} + field_change: '%{form_section_name} atualia ona iha %{alert_time}' + transfer_request: Pedidu Transferensia foun ida halo ona iha %{date} husi %{user} iha %{agency} + duplicate_field: Kazu seluk iha sistema iha %{field_name} hanesan ho ida ne'e. cannot_edit: Ita labele hadi'a ida ne'e confirmation_message: Hanehan OK sei rejeita mudansa hirak ne'ebé seidauk salva no filafali ba lista haree. Hanehan kansela atu filafali ba rejistu. confirmation_message_subform: Hanehan OK sei rejeita mudansa hirak ne'ebé ihaitem ne'e. Hanehan kansela atu kontinua halo mudansa sira. dashboard_offline: Ita offline hela. Painel sei bele funsiona ho di'ak bainhira ita filafali online. field_name_on_form_name: '''%{field_name}'' kampu iha ''%{form_name}'' formuláriu.' - logout_confirmation: "Ita hakarak kontinua ita-nia sesaun?" - logout_offline_warning: "Ita iha serteza ita hakarak log out? Se ita hakarak, ita sei labele asesu filafali to'o bainhira ita online fali. Mudansa balun ita halo durante offline sei lakon hotu." + logout_confirmation: Ita hakarak kontinua ita-nia sesaun? + logout_offline_warning: Ita iha serteza ita hakarak log out? Se ita hakarak, ita sei labele asesu filafali to'o bainhira ita online fali. Mudansa balun ita halo durante offline sei lakon hotu. logout_warning: Ita sei logged off iha minutu 5 mai logout_dialog_header: Offline Log Out logout_confirmation_title: Konfirmasaun Log out - logout_confirmation_text: "Ita iha serteza ita hakarak log out?" + logout_confirmation_text: Ita iha serteza ita hakarak log out? no_changes: Ita lahalo mudansa iha kampu not_available: La disponivel record_list: - column_header_tooltip: "Ordena ba %{column}" + column_header_tooltip: Ordena ba %{column} of: husi - no_match: "Deskulpa, laiha rejistu korespondensia" + no_match: Deskulpa, laiha rejistu korespondensia rows_per_page: Liña kada pájina sort: Ordena navigation: @@ -2191,18 +2096,18 @@ tet: approvals_case_plan_pending: '%{approval_label} Pendente hela' approvals_closure: '%{approval_label}' approvals_closure_pending: '%{approval_label} Pendente hela' - approve_action_plan: "Aprova %{approval_label}" - approve_assessment: "Aprova formuláriu %{approval_label}" - approve_case_plan: "Aprova %{approval_label}" - approve_closure: "Aprova formuláriu %{approval_label}" - approve_gbv_closure: "Aprova formuláriu %{approval_label}" + approve_action_plan: Aprova %{approval_label} + approve_assessment: Aprova formuláriu %{approval_label} + approve_case_plan: Aprova %{approval_label} + approve_closure: Aprova formuláriu %{approval_label} + approve_gbv_closure: Aprova formuláriu %{approval_label} assign: Atribui assign_within_agency: Atribui iha Ajénsia Laran assign_within_user_group: Atribui iha grupu utilizador laran audit_log: Log Auditoria case: Kazu case_approvals: Aprovasaun Kazu - case_assignments_referrals_transfers: "Atribuisaun, referál no transferensia kazu" + case_assignments_referrals_transfers: Atribuisaun, referál no transferensia kazu case_exports: Esportasaun Kazu case_overview: Ha'u nia Kazu Sira case_risk: Kazu tuir Nivel Avaliasaun @@ -2270,7 +2175,7 @@ tet: manage: Jere mark_for_offline: Marka ba Offline matching_configuration: Konfigurasaun Korespondente - metadata: "Formuláriu sira, Peskiza sira" + metadata: Formuláriu sira, Peskiza sira potential_match: Korespondente Potensial primero_configuration: Konfigurasaun read: Lee @@ -2285,11 +2190,11 @@ tet: report: Relatóriu managed_report: Insights request_approval: Pedidu Aprovasaun - request_approval_action_plan: "Pedidu %{approval_label}aprovasaun" - request_approval_assessment: "Pedidu %{approval_label}aprovasaun" - request_approval_case_plan: "Pedidu %{approval_label}aprovasaun" - request_approval_closure: "Pedidu %{approval_label}aprovasaun" - request_approval_gbv_closure: "Pedidu %{approval_label}aprovasaun" + request_approval_action_plan: Pedidu %{approval_label} aprovasaun + request_approval_assessment: Pedidu %{approval_label} aprovasaun + request_approval_case_plan: Pedidu %{approval_label} aprovasaun + request_approval_closure: Pedidu %{approval_label} aprovasaun + request_approval_gbv_closure: Pedidu %{approval_label} aprovasaun request_transfer: Pedidu Transferensia role: Knaar Sira save_search: Salva Peskiza Sira @@ -2298,7 +2203,7 @@ tet: self: Asesu de'it ha'u nia rejistu ka utilizador service_provision_incident_details: Haree Aumenta Butaun Prestasaun Servisu iha Modal Detallu Insidente services_section_from_case: Aumenta Prestasaun Servisu ba utilizador nia kazu ida seluk - specific_roles: "Asesu lista espesífiku husi knaar sira " + specific_roles: 'Asesu lista espesífiku husi knaar sira ' sync_external: Sinkroniza ho sistema jestaun informasaun esternal ida sync_mobile: Marka ba Offline system: Sistema @@ -2324,13 +2229,13 @@ tet: explanation: Abilidade atu asesu pájina Pulse/KPIs label: Asesu Pájina Pulse/KPIs kpi_assessment_status: - explanation: "Abilidade atu haree, ba kazu ativu sira ne'ebé utilizador ne'e presiza atu asesu, proporsaun saida de'it husi sira iha ona fomuláriu avaliasaun ne'ebé kompleta ona." + explanation: Abilidade atu haree, ba kazu ativu sira ne'ebé utilizador ne'e presiza atu asesu, proporsaun saida de'it husi sira iha ona fomuláriu avaliasaun ne'ebé kompleta ona. label: Status Avaliasaun kpi_average_followup_meetings_per_case: - explanation: "Abilidade atu haree, ba kazu ativu sira ne'ebé utilizador ne'e presiza atu asesu, númeru média enkontru follow-up sira konduta ona iha periódu tempu balun." + explanation: Abilidade atu haree, ba kazu ativu sira ne'ebé utilizador ne'e presiza atu asesu, númeru média enkontru follow-up sira konduta ona iha periódu tempu balun. label: Númeru média enkontru Follow-upcsira kada Kazu kpi_average_referrals: - explanation: "Abilidade atu haree, ba kazu ativu sira hotu-hotu ne'ebé utilizador ne'e presiza atu asesu, númeru média husi referál sira halo ba tipu servisu sira ida-idak." + explanation: Abilidade atu haree, ba kazu ativu sira hotu-hotu ne'ebé utilizador ne'e presiza atu asesu, númeru média husi referál sira halo ba tipu servisu sira ida-idak. label: Referál Média kpi_case_closure_rate: explanation: Abilidade atu haree kazu hira ona maka taka ona iha sítiu ida-idak kada fulan. @@ -2339,19 +2244,19 @@ tet: explanation: Abilidade atu haree númeru média kazu nakloke sira servisu nain kazu ida-idak iha. label: Naha Kazu kpi_client_satisfaction_rate: - explanation: "Abilidade atu haree, ba kazu ida-idak ne'ebé utilizador asesu ba, proporsaun sobrevivente sira ne'ebé kompleta ona Peskiza Feedback satisfeita ona." + explanation: Abilidade atu haree, ba kazu ida-idak ne'ebé utilizador asesu ba, proporsaun sobrevivente sira ne'ebé kompleta ona Peskiza Feedback satisfeita ona. label: Taxa Satisfasaun Kliente kpi_completed_case_action_plans: - explanation: "Abilidade atu haree, ba kazu ativu sira ne'ebé utilizador iha asesu ba, proporsaun saida mak iha Planu Kazu Asaun ne'ebé kompleta ona." + explanation: Abilidade atu haree, ba kazu ativu sira ne'ebé utilizador iha asesu ba, proporsaun saida mak iha Planu Kazu Asaun ne'ebé kompleta ona. label: Kompleta Ona Planu Asaun Kazu kpi_completed_case_safety_plans: - explanation: "Abilidade atu haree, ba kazu ativu sira ne'ebé utilizador iha asesu ba, proporsaun saida mak presija no kompleta ona Planu Seguransa." - label: "Kompleta Ona Planu Seguransa Kazu " + explanation: Abilidade atu haree, ba kazu ativu sira ne'ebé utilizador iha asesu ba, proporsaun saida mak presija no kompleta ona Planu Seguransa. + label: 'Kompleta Ona Planu Seguransa Kazu ' kpi_completed_supervisor_approved_case_action_plans: - explanation: "Abilidade atu haree, ba kazu ativu sira ne'ebé utilizador iha asesu ba, proporsaun saida mak kompleta ona Planu Asaun Kazu ne'ebé supervizor ida aprova ona." + explanation: Abilidade atu haree, ba kazu ativu sira ne'ebé utilizador iha asesu ba, proporsaun saida mak kompleta ona Planu Asaun Kazu ne'ebé supervizor ida aprova ona. label: Planu Asaun Kazu Ne'ebé Kompleta Ona Aprovadu husi Supervizor kpi_goal_progress_per_need: - explanation: "Abilidade atu haree, ba kazu sira ne'ebé utilizador iha asesu ba, persentajen husi metas iha kategoria nesesidade ida-idak ne'ebé atinji ona." + explanation: Abilidade atu haree, ba kazu sira ne'ebé utilizador iha asesu ba, persentajen husi metas iha kategoria nesesidade ida-idak ne'ebé atinji ona. label: Progresu ne'ebé Atinji Tuir Metas kpi_number_of_cases: explanation: Abilidade atu haree kazu foun hira maka relata ona ne'ebé nakloke kada fulan kada sítiu. @@ -2360,22 +2265,22 @@ tet: explanation: Abilidade atu haree insidente foun hira maka relata ona ne'ebé nakloke kada fulan kada sítiu. label: Númeru Insidente sira kpi_reporting_delay: - explanation: "Abilidade atu haree, ba insidente hotu-hotu ne'ebé utilizador ne'e hetan asesu ba, númeru loron kaduka ona durante bainhira sobrevivente ne'e esperiensia VBJ ho bainhira sobrevivente ne'e hato'o relatóriu ba fornesedór servisu ida." + explanation: Abilidade atu haree, ba insidente hotu-hotu ne'ebé utilizador ne'e hetan asesu ba, númeru loron kaduka ona durante bainhira sobrevivente ne'e esperiensia VBJ ho bainhira sobrevivente ne'e hato'o relatóriu ba fornesedór servisu ida. label: Relatóriu Atrazu kpi_services_provided: - explanation: "Abilidade atu haree, ba kazu hotu-hotu ne'ebé utilizador iha asesu ba, tipu servisu saida de'it maka fornese ona husi organizasaun ne'e internalmente." + explanation: Abilidade atu haree, ba kazu hotu-hotu ne'ebé utilizador iha asesu ba, tipu servisu saida de'it maka fornese ona husi organizasaun ne'e internalmente. label: Fornese ona Servisu kpi_supervisor_to_caseworker_ratio: explanation: Abilidade atu haree proporsaun husi servisu nain kazu ho supervizor sira. label: Proporsaun Supervizor ho Serbisu Nain Kazu kpi_time_from_case_open_to_close: - explanation: "Abilidade atu haree, ba kazu hotu-hotu ne'ebé utilizador iha asesu ba, durasaun tempu hira mak kazu sira husik nakloke hela." + explanation: Abilidade atu haree, ba kazu hotu-hotu ne'ebé utilizador iha asesu ba, durasaun tempu hira mak kazu sira husik nakloke hela. label: Durasaun tempu husi Kazu Nakloke to'o Terminasaun Kazu label: KPI agency: actions: assign: - explanation: "Abilidade atu hili ajénsia ida wainhira kria ka hadi'a hela utilizador ida nia konta. Se utilizador atual iha permisaun ida ne'e nune'e mós \"Lee Ajénsia\", sira sei bele aumenta utilizador ida ba sira nia ajénsia rasik." + explanation: Abilidade atu hili ajénsia ida wainhira kria ka hadi'a hela utilizador ida nia konta. Se utilizador atual iha permisaun ida ne'e nune'e mós "Lee Ajénsia", sira sei bele aumenta utilizador ida ba sira nia ajénsia rasik. label: Atribui create: explanation: Abilidade atu kria ajénsia ida. @@ -2394,44 +2299,44 @@ tet: audit_log: actions: read: - explanation: "Permite utlizador ne'e atu haree no filtra lista husi asaun hotu-hotu ne'ebé sistema halo, fahe husi utilizador, tipu asaun, rejistu ID, no tempu husi asaun. Ida ne'e di'al loos ba nivel administrador nasional no ajénsia, desde ne'e hatudu asaun halo husi utilizador sira hotu iha sistema ne'e. Favór anota katak rejistu auditoria la hatudu informasaun idenfikasaun pesoal kona-ba rejistu sira ne'ebé involve iha asaun ida-idak." + explanation: Permite utlizador ne'e atu haree no filtra lista husi asaun hotu-hotu ne'ebé sistema halo, fahe husi utilizador, tipu asaun, rejistu ID, no tempu husi asaun. Ida ne'e di'al loos ba nivel administrador nasional no ajénsia, desde ne'e hatudu asaun halo husi utilizador sira hotu iha sistema ne'e. Favór anota katak rejistu auditoria la hatudu informasaun idenfikasaun pesoal kona-ba rejistu sira ne'ebé involve iha asaun ida-idak. label: Haree - explanation: "Lista ne'ebé bele filtra iha asaun hotu-hotu halo iha sistema ne'e. La inklui kulaker informasaun ne'ebé bele identifika iha kazu sira, insidente sira, ka Pedidu Buka-Tuir sira." + explanation: Lista ne'ebé bele filtra iha asaun hotu-hotu halo iha sistema ne'e. La inklui kulaker informasaun ne'ebé bele identifika iha kazu sira, insidente sira, ka Pedidu Buka-Tuir sira. label: Log Auditoria case: actions: add_note: - explanation: "Permiti utilizador ida atu aumenta entrada ida ba subformuláriu \"Notas\" (No mós dalaruma bolu ho naran \"Komentáriu sira\"). Utilizador halo ida ne'e liu husi hanehan butaun \"Aumenta Notas\" iha pájina hatudu kazu. Asaun ida ne'e partikularmente útil ba jestor sira ne'ebé laiha abilidade atu hadi'a kazu sira, maibe hakarak aumenta lembrete sira ba kazu ida ba servisu nain kazu. Tempu agora, aumenta nota ida konsidera hanesan mós aumenta sinal bandeira/flag ida. Vantajen husi aumenta nota maka, wainhira jestor ne'e aumenta nota ida ba kazu ida, sei mosu notifikasaun ida iha kazu ba servisu nain kazu bainhira sira haree kazu ne'e iha sira nia telefone." + explanation: Permiti utilizador ida atu aumenta entrada ida ba subformuláriu "Notas" (No mós dalaruma bolu ho naran "Komentáriu sira"). Utilizador halo ida ne'e liu husi hanehan butaun "Aumenta Notas" iha pájina hatudu kazu. Asaun ida ne'e partikularmente útil ba jestor sira ne'ebé laiha abilidade atu hadi'a kazu sira, maibe hakarak aumenta lembrete sira ba kazu ida ba servisu nain kazu. Tempu agora, aumenta nota ida konsidera hanesan mós aumenta sinal bandeira/flag ida. Vantajen husi aumenta nota maka, wainhira jestor ne'e aumenta nota ida ba kazu ida, sei mosu notifikasaun ida iha kazu ba servisu nain kazu bainhira sira haree kazu ne'e iha sira nia telefone. label: Aumenta Notas ba kazu ida add_registry_record: explanation: Permiti utilizador ida atu link Rejistrasaun ida ho Kazu ida husi formulá detallu Rejistrasaun. Permiti mós utilizador ida atu un-link kualker Rejistrasaun ne'ebé mak link ona ba Kazu ne'e. label: Aumenta / Atualiza Grava Rejistrasaun husi Kazu approve_action_plan: - explanation: "Permiti jestor ida atu aprova %{approval_label}ba sira nia servisu Nain Kazu sira-nia kazu." - label: "Aprova %{approval_label}" + explanation: Permiti jestor ida atu aprova %{approval_label} ba sira nia servisu Nain Kazu sira-nia kazu. + label: Aprova %{approval_label} approve_assessment: - explanation: "Permiti jestor ida atu aprova %{approval_label}ba sira nia servisu Nain Kazu sira-nia kazu." - label: "Aprova formuláriu %{approval_label}" + explanation: Permiti jestor ida atu aprova %{approval_label} ba sira nia servisu Nain Kazu sira-nia kazu. + label: Aprova formuláriu %{approval_label} approve_bia: - explanation: "Permiti jestor ida atu aprova %{approval_label}ba sira nia servisu Nain Kazu sira-nia kazu." - label: "Aprova formuláriu %{approval_label}" + explanation: Permiti jestor ida atu aprova %{approval_label} ba sira nia servisu Nain Kazu sira-nia kazu. + label: Aprova formuláriu %{approval_label} approve_case_plan: - explanation: "Permiti jestor ida atu aprova %{approval_label}ba sira nia servisu nain kazu sira-nia kazu." - label: "Aprova %{approval_label}" + explanation: Permiti jestor ida atu aprova %{approval_label} ba sira nia servisu nain kazu sira-nia kazu. + label: Aprova %{approval_label} approve_closure: - explanation: "Permiti jestor ida atu aprova %{approval_label}ba sira nia servisu Nain Kazu sira-nia kazu." - label: "Aprova formuláriu %{approval_label}" + explanation: Permiti jestor ida atu aprova %{approval_label} ba sira nia servisu Nain Kazu sira-nia kazu. + label: Aprova formuláriu %{approval_label} approve_gbv_closure: - explanation: "Permiti jestor ida atu aprova %{approval_label}ba sira nia servisu Nain Kazu sira-nia kazu." - label: "Aprova formuláriu %{approval_label}" + explanation: Permiti jestor ida atu aprova %{approval_label} ba sira nia servisu Nain Kazu sira-nia kazu. + label: Aprova formuláriu %{approval_label} assign: - explanation: "Permiti utilizador ida atu manda kazu ida husi kazu ne'e ninian na'in rejistu orijinal ba utilizador sira seluk iha sistema. La presiza konsentimentu husi labarik ba asaun ida ne'e. Lahanesan ho transferensia sira, benefisiariu ne'e la hetan oportunidade atu simu ka rejeita atribuisaun ne'e." + explanation: Permiti utilizador ida atu manda kazu ida husi kazu ne'e ninian na'in rejistu orijinal ba utilizador sira seluk iha sistema. La presiza konsentimentu husi labarik ba asaun ida ne'e. Lahanesan ho transferensia sira, benefisiariu ne'e la hetan oportunidade atu simu ka rejeita atribuisaun ne'e. label: Atribui assign_within_agency: - explanation: "Permiti utilizador ida atu manda kazu ida husi kazu ne'e ninian na'in rejistu orijinal ba utilizador sira seluk iha utilizador ne'e nia ajénsia atual. La presiza konsentimentu husi labarik ba asaun ida ne'e. Lahanesan ho transferensia sira, benefisiariu ne'e la hetan oportunidade atu simu ka rejeita atribuisaun ne'e." + explanation: Permiti utilizador ida atu manda kazu ida husi kazu ne'e ninian na'in rejistu orijinal ba utilizador sira seluk iha utilizador ne'e nia ajénsia atual. La presiza konsentimentu husi labarik ba asaun ida ne'e. Lahanesan ho transferensia sira, benefisiariu ne'e la hetan oportunidade atu simu ka rejeita atribuisaun ne'e. label: Atribui ba utilizador iha ha'u-nia ajénsia laran assign_within_user_group: - explanation: "Permiti utilizador ida atu manda kazu ida husi kazu ne'e ninian na'in rejistu orijinal ba utilizador sira seluk iha utilizador ne'e nia grupu atual. La presiza konsentimentu husi labarik ba asaun ida ne'e. Lahanesan ho transferensia sira, benefisiariu ne'e la hetan oportunidade atu simu ka rejeita atribuisaun ne'e." + explanation: Permiti utilizador ida atu manda kazu ida husi kazu ne'e ninian na'in rejistu orijinal ba utilizador sira seluk iha utilizador ne'e nia grupu atual. La presiza konsentimentu husi labarik ba asaun ida ne'e. Lahanesan ho transferensia sira, benefisiariu ne'e la hetan oportunidade atu simu ka rejeita atribuisaun ne'e. label: Atribui ba utilizador iha ha'u-nia grupu utilizador laran change_log: explanation: Utilizador bele haree istoria husi mudansa hotu-hotu ne'ebé akontese ona ba rejistu ne'e desde faze kriasaun rejistu ne'e. Ida ne'e inklui valor sira ne'ebé grava ona ba kampu sira hotu-hotu. @@ -2446,31 +2351,31 @@ tet: explanation: Abilidade atu kria kazu ida. label: Kria display_view_page: - explanation: "Se utilizador ida halo peskiza ba kazu ida ne'ebé sira laiha asesu ba, permisaun ida ne'e permiti sira atu haree modal ki'ik ida ho informasaun báziku kona-ba kazu ne'e, maske utilizador ne'e labele hanehan ba kazu ne'e atu haree kazu ne'e ninia informasaun hotu-hotu. Kampu sira ne'ebé mosu iha \"Hare Modal\" ne'e hanesan kampu sira ne'ebé konfigura ona ba \"Hatudu iha Formatu Badak.\" Modal ida ne'e útil ba utilizador sira ne'ebé halo asaun Buka-Tuir Familia no Reunifikasaun, desde \"Haree Modal\" ne'e diponivel ba utilizador atu asesu bainhira sira revee kazu sira ne'ebé mosu ona hanesan \"Korespondente Potensial sira\" ba Pedidu Buka-Tuir ida." + explanation: Se utilizador ida halo peskiza ba kazu ida ne'ebé sira laiha asesu ba, permisaun ida ne'e permiti sira atu haree modal ki'ik ida ho informasaun báziku kona-ba kazu ne'e, maske utilizador ne'e labele hanehan ba kazu ne'e atu haree kazu ne'e ninia informasaun hotu-hotu. Kampu sira ne'ebé mosu iha "Hare Modal" ne'e hanesan kampu sira ne'ebé konfigura ona ba "Hatudu iha Formatu Badak." Modal ida ne'e útil ba utilizador sira ne'ebé halo asaun Buka-Tuir Familia no Reunifikasaun, desde "Haree Modal" ne'e diponivel ba utilizador atu asesu bainhira sira revee kazu sira ne'ebé mosu ona hanesan "Korespondente Potensial sira" ba Pedidu Buka-Tuir ida. label: Hatudu Haree Pájina enable_disable_record: - explanation: "Abilidade atu dezativa ka ativa kazu ida. \"Dezativadu\" kazu labele mosu tuir personalizadu iha lista kazu ne'e. Utilizador sira bele haree kazu dezativadu sira iha lista kazu liu husi filtru ida. Desde Primero la permiti utilizador sira atu hamoos kazu sira, utilizador ida bele iha dezeju atu dezativa kazu ida hanesan suplente ida. Pur ezemplu, se utilizador ida sala kria ona kazu, ka kazu ne'e iha dadus ne'ebé la akuradu, utilizador ne'e tenke dezativa tiha." + explanation: Abilidade atu dezativa ka ativa kazu ida. "Dezativadu" kazu labele mosu tuir personalizadu iha lista kazu ne'e. Utilizador sira bele haree kazu dezativadu sira iha lista kazu liu husi filtru ida. Desde Primero la permiti utilizador sira atu hamoos kazu sira, utilizador ida bele iha dezeju atu dezativa kazu ida hanesan suplente ida. Pur ezemplu, se utilizador ida sala kria ona kazu, ka kazu ne'e iha dadus ne'ebé la akuradu, utilizador ne'e tenke dezativa tiha. label: Ativa / Dezativa export_case_pdf: - explanation: "Utilizador bele halo arkizu PDF ida esporta husi lista kazu ka pájina sira hatudu kazu, ne'ebé kontén kampu hotu-hotu ne'ebé utilizador atual ne'e iha asesu, ba kazu ida, multiplu ka kazu hotu-hotu ne'ebé utilizador ne'e iha asesu. Iha arkivu esportasaun PDF, informasaun sira alista uluk tuir kazu, no depois organiza fali tuir formatu ne'ebé informasaun ne'e mosu." + explanation: Utilizador bele halo arkizu PDF ida esporta husi lista kazu ka pájina sira hatudu kazu, ne'ebé kontén kampu hotu-hotu ne'ebé utilizador atual ne'e iha asesu, ba kazu ida, multiplu ka kazu hotu-hotu ne'ebé utilizador ne'e iha asesu. Iha arkivu esportasaun PDF, informasaun sira alista uluk tuir kazu, no depois organiza fali tuir formatu ne'ebé informasaun ne'e mosu. label: Esporta kazu PDF export_csv: explanation: 'Utilizador bele halo arkizu CSV ida esporta husi lista kazu ka pájina sira hatudu kazu, ne''ebé kontén kampu hotu-hotu ne''ebé utilizador atual ne''e iha asesu, ba kazu ida, multiplu ka kazu hotu-hotu ne''ebé utilizador ne''e iha asesu. NOTA: Esportasaun CSV la lee karater non-Latina sira (e.g. Arabic, Bangla) iha formatu ne''ebé lezivel.' label: Esporta CSV export_custom: - explanation: "Utilizador bele halo arkizu XLS ida esporta husi lista kazu ka pájina sira hatudu kazu, ne'ebé kontén formulariu ka kampu personalizadu, ba kazu ida, multiplu ka kazu hotu-hotu ne'ebé utilizador ne'e iha asesu. Iha esportasaun ida ne'e, formulariu ida-idak reprezenta ona iha sira nia tab rasik iha arkizu XLS nia laran. Utilizador bele hili formulariu ka kampu sira ne'ebe sira hakarak atu inklui iha esportasaun uza modal Esportasaun Personalizadu. Favo anota katak utilizador bele inklui dei't formulariu ka kampu sira iha esporta se sira iha ona abilidade atu haree formulariu ka kampu sira ne'e bainhira haree kazu ida iha aplikasaun." + explanation: Utilizador bele halo arkizu XLS ida esporta husi lista kazu ka pájina sira hatudu kazu, ne'ebé kontén formulariu ka kampu personalizadu, ba kazu ida, multiplu ka kazu hotu-hotu ne'ebé utilizador ne'e iha asesu. Iha esportasaun ida ne'e, formulariu ida-idak reprezenta ona iha sira nia tab rasik iha arkizu XLS nia laran. Utilizador bele hili formulariu ka kampu sira ne'ebe sira hakarak atu inklui iha esportasaun uza modal Esportasaun Personalizadu. Favo anota katak utilizador bele inklui dei't formulariu ka kampu sira iha esporta se sira iha ona abilidade atu haree formulariu ka kampu sira ne'e bainhira haree kazu ida iha aplikasaun. label: Esporta Personalizadu export_duplicate_id_csv: - explanation: "Kria CSV ida esporta kazu sira ne'ebé iha naran kampu ID Nasional ne'ebé hanesan (maske iha lebel ne'ebé lahanesan, depende ba konfigurasaun). Bele halo dei't husi pájina lista kazu." + explanation: Kria CSV ida esporta kazu sira ne'ebé iha naran kampu ID Nasional ne'ebé hanesan (maske iha lebel ne'ebé lahanesan, depende ba konfigurasaun). Bele halo dei't husi pájina lista kazu. label: Esporta duplikasaun sira export_json: - explanation: "Utilizador bele kria arkivu JSON ida esporta husi lista kazu ka pajina sira hatudu kazu, ne'ebe kontein kampu sira hotu-hotu ne'ebe utilizador atual iha asesu, ba kazu ida, multiplu, ka kazu hotu-hotu ne'ebe utilizador iha asesu. Esporta ida ne'e prinsipalmente uza ba sira ne'ebe hakarak atu esporta kazu sira husi sistema Primero atual no depois importa kazu sira ne'e ba sistema Primero ida seluk, ka esporta ba jestaun sistema informasaun sira seluk. Formatu JSON ne'e lezivel husi makina no la pratikal ba maioria utilzador sira seluk." + explanation: Utilizador bele kria arkivu JSON ida esporta husi lista kazu ka pajina sira hatudu kazu, ne'ebe kontein kampu sira hotu-hotu ne'ebe utilizador atual iha asesu, ba kazu ida, multiplu, ka kazu hotu-hotu ne'ebe utilizador iha asesu. Esporta ida ne'e prinsipalmente uza ba sira ne'ebe hakarak atu esporta kazu sira husi sistema Primero atual no depois importa kazu sira ne'e ba sistema Primero ida seluk, ka esporta ba jestaun sistema informasaun sira seluk. Formatu JSON ne'e lezivel husi makina no la pratikal ba maioria utilzador sira seluk. label: Esporta JSON export_list_view_csv: explanation: Utilizador bele kria arkivu CSV ida husi lista pajina lista kazu ne'ebe kontein kampu sira ne'ebe hanesan ne'ebe mosu ba utilizador ida ne'eba iha lista kazu. Bele halo de'it husi pajina lista kazu. label: Esporta lista haree CSV export_pdf: - explanation: "Utilizador bele halo arkivu PDF ida esporta husi lista kazu ka pajina sira hatudu kazu nian, ne'ebe kontein kampu sira hotu-hotu iha ne'ebe utilizador atual iha asesu, ba kazu ida, multiplu, ka kazu hotu-hotu iha ne'ebe utilizador iha asesu. Iha PDF arkivu esportasaun ne'e, informasaun sira alista dahuluk tuir kazu, no depois organiza tan tuir formulariu iha ne'ebe informasaun mosu ba." + explanation: Utilizador bele halo arkivu PDF ida esporta husi lista kazu ka pajina sira hatudu kazu nian, ne'ebe kontein kampu sira hotu-hotu iha ne'ebe utilizador atual iha asesu, ba kazu ida, multiplu, ka kazu hotu-hotu iha ne'ebe utilizador iha asesu. Iha PDF arkivu esportasaun ne'e, informasaun sira alista dahuluk tuir kazu, no depois organiza tan tuir formulariu iha ne'ebe informasaun mosu ba. label: Esporta kazu PDF export_photowall: explanation: Permiti utilizador atu esporta arkivu ida husi pajina lista kazu ne'ebe kontein fotografia husi kazu sira ne'ebe hili ona. Esportasaun ida ne'e prinsipalmente uza ba atividade Buka-Tuir Familia no Reunifikasaun. Bele halo de'it husi pajina lista kazu. @@ -2481,79 +2386,78 @@ tet: explanation: 'Utilizador bele halo arkizu XLS ida esporta husi lista kazu ka pájina sira hatudu kazu, ne''ebé kontén kampu hotu-hotu ne''ebé utilizador atual ne''e iha asesu, ba kazu ida, multiplu ka kazu hotu-hotu ne''ebé utilizador ne''e iha asesu. Iha esportasaun ida ne''e, formulariu ida-idak reprezenta ninia tab rasik iha arkivu XLS nia laran. NOTA: Formatu XLS la lee karater non-Latina sira (e.g. Arabic, Bangla) iha formatu ne''ebé lezivel, desde esportasaun CSV labele halo.' label: Esporta Excel (Arkivu XLS) find_tracing_match: - explanation: "Ida ne'e uza eskluzivamente ba kontestu atividade Buka-Tuir Familia no Reunifikasaun. Utilizador sira ne'ebe ho permisaun ida ne'e sei haree butaun \"Buka Korespondensia Bukat-Tuir\" iha pajina hatudu kazu. Wainhira sira hanehan iha ne'eba, sira sei ba iha pedidu lista buka-tuir ida iha sistema iha ne'ebe iha korespondente potensial sira ba sira nia kazu." + explanation: Ida ne'e uza eskluzivamente ba kontestu atividade Buka-Tuir Familia no Reunifikasaun. Utilizador sira ne'ebe ho permisaun ida ne'e sei haree butaun "Buka Korespondensia Bukat-Tuir" iha pajina hatudu kazu. Wainhira sira hanehan iha ne'eba, sira sei ba iha pedidu lista buka-tuir ida iha sistema iha ne'ebe iha korespondente potensial sira ba sira nia kazu. label: Buka korespondensia buka-tuir husi kazu flag: explanation: Abilidade atu aumenta flag ida ba kazu ida. Utilizador sira ho permisaun ida ne'e bele mos hasa'i flag sira ne'ebe sira aumenta ona ba kazu ida. label: Flag import: - explanation: "Permiti utilizador ida atu kria kazu foun ida ka barak liu husi importa sira husi arkivu CSV, Excel ka JSON. Arkivu ne'ebe atu importa tenke iha formatu *very* espesifikamente ba informasuan atu importa ho apropriadu. Funsaun ida ne'e tenke disponivel de'it ba utilizador administrador sira ne'ebe mak iha konesimentu tekniku ne'ebe avansadu no iha konesimentu klean kona-ba oinsa halo formatu ba dadus iha Primero. Bele halo de'it husi pajina lista kazu." + explanation: Permiti utilizador ida atu kria kazu foun ida ka barak liu husi importa sira husi arkivu CSV, Excel ka JSON. Arkivu ne'ebe atu importa tenke iha formatu *very* espesifikamente ba informasuan atu importa ho apropriadu. Funsaun ida ne'e tenke disponivel de'it ba utilizador administrador sira ne'ebe mak iha konesimentu tekniku ne'ebe avansadu no iha konesimentu klean kona-ba oinsa halo formatu ba dadus iha Primero. Bele halo de'it husi pajina lista kazu. label: Importa incident_details_from_case: - explanation: "Abilidade atu aumenta entrada ida ba subformulariu Detallu Insidente iha kazu ida ne'ebe ita hetan ona iha rezultadu peskiza, maibe ba ida ne'ebe ita laiha asesu. Utilizador ne'e halo asaun ida ne'e husi pajina rezultadu peskiza liu husi hili kazu ida ka barak, depois hili \"Aumenta Insidente\" husi menu asaun sira. Utilizador ne'e depois sei haree modal ida ne'ebe kontein kampu hotu-hotu husi subformulariu Detallu Insidente, iha ne'ebe sira bele tama no submete informasaun kona-ba servisu ida. Tanba asaun ida ne'e bele halo de'it husi pajina rezultadu peskiza, nia sei iha sentidu ba knaar ida atu iha permisaun ida ne'e se sira mos iha permisaun \"Peskiza na'in ba rejistu kazu sira tuir utilizador sira seluk\"." + explanation: Abilidade atu aumenta entrada ida ba subformulariu Detallu Insidente iha kazu ida ne'ebe ita hetan ona iha rezultadu peskiza, maibe ba ida ne'ebe ita laiha asesu. Utilizador ne'e halo asaun ida ne'e husi pajina rezultadu peskiza liu husi hili kazu ida ka barak, depois hili "Aumenta Insidente" husi menu asaun sira. Utilizador ne'e depois sei haree modal ida ne'ebe kontein kampu hotu-hotu husi subformulariu Detallu Insidente, iha ne'ebe sira bele tama no submete informasaun kona-ba servisu ida. Tanba asaun ida ne'e bele halo de'it husi pajina rezultadu peskiza, nia sei iha sentidu ba knaar ida atu iha permisaun ida ne'e se sira mos iha permisaun "Peskiza na'in ba rejistu kazu sira tuir utilizador sira seluk". label: Aumenta Detallu INsidente ba utilizador ida seluk nia kazu husi pajina rezultadu peskiza incident_from_case: - explanation: "Permisaun ida ne'e permiti utilizador ne'e atu hanehan butaun \"Kria Insidente\". Ida ne'e kria insidente ida ne'ebe bele kontein informasaun balun kopia husi kazu ne'e. Ba kazu VBJ sira, butaun ida ne'e iha pajina hatudu kazu nia leten, no koresponde ba informasaun kona-ba kazu en jeral. Iha kontestu monitor insidente balun, butaun ida ne'e iha subformulariu \"Detallu Insidente\" ida. Iha situasuan ida ne'e, informasaun balun bele hetan kopia husi subformulariiu detallu insidente iha ne'ebe butaun ne'e hanehan ona, nune'e mos husi kazu ne'e en jeral. I.e. insidente foun ne'ebe kria ona bele kontein kampu \"Tipu husi Violensia\" husi subformulariu detallu insidente individual, maibe bele mos kontein tinan no kazu husi kazu ne'e rasik. Anota katak permisaun ida ne'e permiti utilizador atu haree link ida ba insidente ne'ebe kria tiha ona." + explanation: Permisaun ida ne'e permiti utilizador ne'e atu hanehan butaun "Kria Insidente". Ida ne'e kria insidente ida ne'ebe bele kontein informasaun balun kopia husi kazu ne'e. Ba kazu VBJ sira, butaun ida ne'e iha pajina hatudu kazu nia leten, no koresponde ba informasaun kona-ba kazu en jeral. Iha kontestu monitor insidente balun, butaun ida ne'e iha subformulariu "Detallu Insidente" ida. Iha situasuan ida ne'e, informasaun balun bele hetan kopia husi subformulariiu detallu insidente iha ne'ebe butaun ne'e hanehan ona, nune'e mos husi kazu ne'e en jeral. I.e. insidente foun ne'ebe kria ona bele kontein kampu "Tipu husi Violensia" husi subformulariu detallu insidente individual, maibe bele mos kontein tinan no kazu husi kazu ne'e rasik. Anota katak permisaun ida ne'e permiti utilizador atu haree link ida ba insidente ne'ebe kria tiha ona. label: Kria insidente ida husi kazu ida remove_alert: - explanation: "" label: Elimina alerta husi kazu ida manage: - explanation: "Permiti utilizador ida atu halo asaun sira ne'ebé disponivel iha kazu sira. Permisaun \"Jere\" esensialmente signifika \"Buat hotu-hotu\". " + explanation: 'Permiti utilizador ida atu halo asaun sira ne''ebé disponivel iha kazu sira. Permisaun "Jere" esensialmente signifika "Buat hotu-hotu". ' label: Jere (Permisaun hotu-hotu ba tipu rekursu ida ne'e) read: explanation: Abilidade atu haree kazu ida. label: Haree receive_referral: - explanation: "Permiti utilizador ida atu simu referal. Utilizador sira ne'ebe ho permisaun ne'e sei mosu hanesan benefisiariu potensial husi asaun referal, enkuantu utilizador sira ne'ebe laiha permisaun ida ne'e, sei la mosu hanesan benefisiariu potensial wainhira ema ruma buka benefisiariu ida iha modal referal ne'e." + explanation: Permiti utilizador ida atu simu referal. Utilizador sira ne'ebe ho permisaun ne'e sei mosu hanesan benefisiariu potensial husi asaun referal, enkuantu utilizador sira ne'ebe laiha permisaun ida ne'e, sei la mosu hanesan benefisiariu potensial wainhira ema ruma buka benefisiariu ida iha modal referal ne'e. label: Simu Referál receive_referral_different_module: - explanation: "Permiti utilizador ida atu simu referal ida husi rejisti ida ne'ebe kria iha modulu Primero oin seluk. Utilizador sira ne'ebe ho permisaun ne'e sei mosu hanesan benefisiariu potensial sira husi asaun referal ba rejistu ne'e, enkuantu utilizador sira ne'ebe laiha permisaun ida ne'e, sei la mosu hanesan benefisiariu potensial wainhira ema ruma buka benefisiariu ida iha modal referal ne'e." + explanation: Permiti utilizador ida atu simu referal ida husi rejisti ida ne'ebe kria iha modulu Primero oin seluk. Utilizador sira ne'ebe ho permisaun ne'e sei mosu hanesan benefisiariu potensial sira husi asaun referal ba rejistu ne'e, enkuantu utilizador sira ne'ebe laiha permisaun ida ne'e, sei la mosu hanesan benefisiariu potensial wainhira ema ruma buka benefisiariu ida iha modal referal ne'e. label: Simu Referal husi utilizador ida iha modulu oin seluk. receive_transfer: - explanation: "Permiti utilizador ida atu simu transferensia. Utilizador sira ne'ebe ho permisaun ne'e sei mosu hanesan benefisiariu potensial husi asaun referal, enkuantu utilizador sira ne'ebe laiha permisaun ida ne'e, sei la mosu hanesan benefisiariu potensial wainhira ema ruma buka benefisiariu ida iha modal transferensia ne'e." + explanation: Permiti utilizador ida atu simu transferensia. Utilizador sira ne'ebe ho permisaun ne'e sei mosu hanesan benefisiariu potensial husi asaun referal, enkuantu utilizador sira ne'ebe laiha permisaun ida ne'e, sei la mosu hanesan benefisiariu potensial wainhira ema ruma buka benefisiariu ida iha modal transferensia ne'e. label: Simu Transferénsia referral: - explanation: "Permiti utilizador ida atu etrega asesu kazu ida temporariamente ba utilizador ida seluk. Benefisiariu husi referal sei bele atu halo asaun hotu-hotu ne'ebe hanesan iha kazu referal ne'e hanesan sira bele halo iha sira nia kazu rasik. Bainhira benefisiariu la presiza ona asesu ba kazu ne'e, sira bele hanehan butaun \"Remata\" iha subformulariu Referal no Transferensia, no sira sei lakon asesu ba kazu ne'e. Ita so bele refere kazu ida ba utilizador ida ne'ebe nia knaar tomak iha abilidade atu simu referal sira." + explanation: Permiti utilizador ida atu etrega asesu kazu ida temporariamente ba utilizador ida seluk. Benefisiariu husi referal sei bele atu halo asaun hotu-hotu ne'ebe hanesan iha kazu referal ne'e hanesan sira bele halo iha sira nia kazu rasik. Bainhira benefisiariu la presiza ona asesu ba kazu ne'e, sira bele hanehan butaun "Remata" iha subformulariu Referal no Transferensia, no sira sei lakon asesu ba kazu ne'e. Ita so bele refere kazu ida ba utilizador ida ne'ebe nia knaar tomak iha abilidade atu simu referal sira. label: Referál referral_from_service: - explanation: "Permiti utilizador ne'e atu haree butaun \"Refere\" iha subformulariu Servisu sira. Wainhira utilizador ne'e hanehan iha butaun ne'e, modal referal sei mosu ho Tipu Servisu, Ajensia, Fornesedor Servisu, no Fatin dezativadu kampu sira, maibe automatikamente prense informasaun ba kampu sira ne'e iha subformulariu Servisu sira iha ne'ebe utilizador ne'e hanehan ona butaun Refere." + explanation: Permiti utilizador ne'e atu haree butaun "Refere" iha subformulariu Servisu sira. Wainhira utilizador ne'e hanehan iha butaun ne'e, modal referal sei mosu ho Tipu Servisu, Ajensia, Fornesedor Servisu, no Fatin dezativadu kampu sira, maibe automatikamente prense informasaun ba kampu sira ne'e iha subformulariu Servisu sira iha ne'ebe utilizador ne'e hanehan ona butaun Refere. label: Refere Kazu husi subformuláriu Servisu remove_assigned_users: - explanation: "Permiti utilizador ne'e atu hasai utilizador sira seluk husi kampu \"Utilizador Atribuidu Sira seluk\". Utilizador ida alista iha ne'e se sira simu ona referal ida ba kazu ne'e ka simu ona transferensia ba kazu ne'e, maibe seidauk aseita ka rejeita. Wainhira ita hasai utilizador ida husi kampu \"Utilizador Atribuidu Sira seluk\", ita hasai sira nia asesu ba kazu ne'e. Nune'e, utilizador sira ne'ebe ho permisaun ne'e bele hasai asesu kazu husi utilizador sira ne'ebe simu ona referal anteriormente ka transferensia ne'ebe pendente hela ba kazu ne'e. Nota katak permisaun ida ne'e bele servisu ho di'ak se utilizador atual ne'e mos iha abilidade atu hadi'a kazu ne'e." + explanation: Permiti utilizador ne'e atu hasai utilizador sira seluk husi kampu "Utilizador Atribuidu Sira seluk". Utilizador ida alista iha ne'e se sira simu ona referal ida ba kazu ne'e ka simu ona transferensia ba kazu ne'e, maibe seidauk aseita ka rejeita. Wainhira ita hasai utilizador ida husi kampu "Utilizador Atribuidu Sira seluk", ita hasai sira nia asesu ba kazu ne'e. Nune'e, utilizador sira ne'ebe ho permisaun ne'e bele hasai asesu kazu husi utilizador sira ne'ebe simu ona referal anteriormente ka transferensia ne'ebe pendente hela ba kazu ne'e. Nota katak permisaun ida ne'e bele servisu ho di'ak se utilizador atual ne'e mos iha abilidade atu hadi'a kazu ne'e. label: Hasai utilizador atribuidu sira seluk (foti filafali asesu kazu husi refere ba utilizador sira) reopen: explanation: Permiti utilizador ida atu loke kazu ida ne'ebe mak atualmente taka hela. label: Loke filafali request_approval_action_plan: - explanation: "Permiti utilizador ida (bai-bain servisu nain kazu ida) atu rekere katak sira nia jestor aprova sira-nia kazu nia %{approval_label}." - label: "Pedidu %{approval_label}aprovasaun" + explanation: Permiti utilizador ida (bai-bain servisu nain kazu ida) atu rekere katak sira nia jestor aprova sira-nia kazu nia %{approval_label}. + label: Pedidu %{approval_label} aprovasaun request_approval_assessment: - explanation: "Permiti utilizador ida (bai-bain servisu nain kazu ida) atu rekere katak sira nia jestor aprova sira-nia kazu %{approval_label}." - label: "Pedidu %{approval_label}aprovasaun" + explanation: Permiti utilizador ida (bai-bain servisu nain kazu ida) atu rekere katak sira nia jestor aprova sira-nia kazu %{approval_label}. + label: Pedidu %{approval_label} aprovasaun request_approval_bia: - explanation: "Permiti utilizador ida (bai-bain servisu nain kazu ida) atu rekere katak sira nia jestor aprova sira-nia kazu %{approval_label}." - label: "Pedidu %{approval_label}aprovasaun" + explanation: Permiti utilizador ida (bai-bain servisu nain kazu ida) atu rekere katak sira nia jestor aprova sira-nia kazu %{approval_label}. + label: Pedidu %{approval_label} aprovasaun request_approval_case_plan: - explanation: "Permiti utilizador ida (bai-bain servisu nain kazu ida) atu rekere katak sira nia jestor aprova sira-nia kazu %{approval_label}." - label: "Pedidu %{approval_label}aprovasaun" + explanation: Permiti utilizador ida (bai-bain servisu nain kazu ida) atu rekere katak sira nia jestor aprova sira-nia kazu %{approval_label}. + label: Pedidu %{approval_label} aprovasaun request_approval_closure: - explanation: "Permiti utilizador ida (bai-bain servisu nain kazu ida) atu rekere katak sira nia jestor aprova sira-nia kazu %{approval_label}." - label: "Pedidu %{approval_label}aprovasaun" + explanation: Permiti utilizador ida (bai-bain servisu nain kazu ida) atu rekere katak sira nia jestor aprova sira-nia kazu %{approval_label}. + label: Pedidu %{approval_label} aprovasaun request_approval_gbv_closure: - explanation: "Permiti utilizador ida (bai-bain servisu nain kazu ida) atu rekere katak sira nia jestor aprova sira-nia kazu nia %{approval_label}." - label: "Pedidu %{approval_label}aprovasaun" + explanation: Permiti utilizador ida (bai-bain servisu nain kazu ida) atu rekere katak sira nia jestor aprova sira-nia kazu nia %{approval_label}. + label: Pedidu %{approval_label} aprovasaun request_transfer: - explanation: "Hatudu butaun \"Pedidu Transferensia\" iha \"Haree Modal\". Butaun ne'e permiti utilizador atu manda mensajen ho nota personalizadu ida via email ba kazu rejistu nia na'in atual , rekere hela katak na'in ba rejistu ne'e trasfere kazu ne'e ba utilizador ne'ebe manda ona pedidu ne'e. Ida ne'e util iha kontestu bainhira labarik sira muda fatin bei-beik, no serivsu nain kazu sira presiza labarik nia servisu nain kazu anterior atu manda informasaun kona-ba labarik ne'e atu hasees husi kriasaun rejistu ne'ebe duplikadu." + explanation: Hatudu butaun "Pedidu Transferensia" iha "Haree Modal". Butaun ne'e permiti utilizador atu manda mensajen ho nota personalizadu ida via email ba kazu rejistu nia na'in atual , rekere hela katak na'in ba rejistu ne'e trasfere kazu ne'e ba utilizador ne'ebe manda ona pedidu ne'e. Ida ne'e util iha kontestu bainhira labarik sira muda fatin bei-beik, no serivsu nain kazu sira presiza labarik nia servisu nain kazu anterior atu manda informasaun kona-ba labarik ne'e atu hasees husi kriasaun rejistu ne'ebe duplikadu. label: Pedidu Transferénsia search_owned_by_others: - explanation: "Permiti utilizador ida atu halo peskiza ba rejistu sira ne'ebe sira bai-bain laiha asesu ba, dalaruma tanba sira la'os nain ba rejistu husi kazu ne'e, ka (ba jestor sira) tanba nain ba rejistu ne'e laiha sira nia grupu utilizador sira. Anota katak, maske utilizador sei haree kazu iha haree rezultadu peskiza, sira sei labele hanehan ba pajina hatudu kazu ba kazu ne'e, signfika sira sei labele haree kualker detallu informasaun kona-ba kazu ne'e." + explanation: Permiti utilizador ida atu halo peskiza ba rejistu sira ne'ebe sira bai-bain laiha asesu ba, dalaruma tanba sira la'os nain ba rejistu husi kazu ne'e, ka (ba jestor sira) tanba nain ba rejistu ne'e laiha sira nia grupu utilizador sira. Anota katak, maske utilizador sei haree kazu iha haree rezultadu peskiza, sira sei labele hanehan ba pajina hatudu kazu ba kazu ne'e, signfika sira sei labele haree kualker detallu informasaun kona-ba kazu ne'e. label: Peskiza rejistu kazu na'in husi utilizador sira seluk service_provision_incident_details: - explanation: "Permiti utilizador ne'e atu haree butaun ida ho lebel \"Salva no Aumenta Prestasaun Servisu\" iha modal Aumenta Insidente nia okos. Hanehan butaun ida ne'e atu salva informasaun kona-ba insidente ne'ebe foin hatama lalais ne'e, no depois lori utilizador ne'e diretamente ba modal Aumenta Prestasaun Servisu. Tanba asaun ne'e konekta diretamente ho asaun Aumenta Insidente no Aumenta Prestasaun Servisu, nia sei iha sentidu atu fornese permisaun ba knaar ida se knaar ne'e mos iha permisaun \"Aumenta Detallu Insidente ba utilizador nia kazu ida seluk\" no \"Aumenta prestasaun servisu ba utilizador nia kazu ida seluk\"." + explanation: Permiti utilizador ne'e atu haree butaun ida ho lebel "Salva no Aumenta Prestasaun Servisu" iha modal Aumenta Insidente nia okos. Hanehan butaun ida ne'e atu salva informasaun kona-ba insidente ne'ebe foin hatama lalais ne'e, no depois lori utilizador ne'e diretamente ba modal Aumenta Prestasaun Servisu. Tanba asaun ne'e konekta diretamente ho asaun Aumenta Insidente no Aumenta Prestasaun Servisu, nia sei iha sentidu atu fornese permisaun ba knaar ida se knaar ne'e mos iha permisaun "Aumenta Detallu Insidente ba utilizador nia kazu ida seluk" no "Aumenta prestasaun servisu ba utilizador nia kazu ida seluk". label: Haree Aumenta Butaun Prestasaun Servisu iha Modal Detallu Insidente services_section_from_case: - explanation: "Abilidade atu aumenta entrada ida ba subformuláriu Servisu sira iha kazu ida ne'ebé ita hetan ona iha rezultadu peskiza, maibe ba ida ne'ebé ita laiha asesu. Utilizador ne'e halo asaun ida ne'e husi pajina rezultadu peskiza liu husi hili kazu ida ka barak, depois hili \"Aumenta Prestasaun Servisu\" husi menu asaun sira. Utilizador ne'e depois sei haree modal ida ne'ebé kontein kampu hotu-hotu husi subformuláriu Servisu sira, iha ne'ebe sira bele tama no submete informasaun kona-ba servisu ida. Tanba asaun ida ne'e bele halo de'it husi pajina rezultadu peskiza, nia sei iha sentidu ba knaar ida atu iha permisaun ida ne'e se sira mos iha permisaun \"Peskiza na'in ba rejistu kazu sira tuir utilizador sira seluk\"." + explanation: Abilidade atu aumenta entrada ida ba subformuláriu Servisu sira iha kazu ida ne'ebé ita hetan ona iha rezultadu peskiza, maibe ba ida ne'ebé ita laiha asesu. Utilizador ne'e halo asaun ida ne'e husi pajina rezultadu peskiza liu husi hili kazu ida ka barak, depois hili "Aumenta Prestasaun Servisu" husi menu asaun sira. Utilizador ne'e depois sei haree modal ida ne'ebé kontein kampu hotu-hotu husi subformuláriu Servisu sira, iha ne'ebe sira bele tama no submete informasaun kona-ba servisu ida. Tanba asaun ida ne'e bele halo de'it husi pajina rezultadu peskiza, nia sei iha sentidu ba knaar ida atu iha permisaun ida ne'e se sira mos iha permisaun "Peskiza na'in ba rejistu kazu sira tuir utilizador sira seluk". label: Aumenta Prestasaun Servisu ba utilizador nia kazu ida seluk sync_external: explanation: Abilidade atu sinkroniza Rejistu ida ho sistema jestaun informasaun esternal ida @@ -2562,13 +2466,13 @@ tet: explanation: Permiti utilizador ne'e atu cache kazu sira ne'e ba utilizasaun durante offline. label: Marka ba Offline transfer: - explanation: "Permiti utilizador ida atu manda kazu ida husi ninia nain rejistu atual ba kualker utilizador iha sistema ne'ebe iha abilidade atu simu transferensia. Nain ba rejistu kazu ne'e sei laiha mudansa, maibe, to'o benefisiariu transferensia ne'e \"aseita\". Se benefisiariu ne'e \"rejeita\" transferensia ne'e, benefisiariu sei lakon asesu ba kazu ne'e, no nafatin rai ninia nain rejistu orijinal." + explanation: Permiti utilizador ida atu manda kazu ida husi ninia nain rejistu atual ba kualker utilizador iha sistema ne'ebe iha abilidade atu simu transferensia. Nain ba rejistu kazu ne'e sei laiha mudansa, maibe, to'o benefisiariu transferensia ne'e "aseita". Se benefisiariu ne'e "rejeita" transferensia ne'e, benefisiariu sei lakon asesu ba kazu ne'e, no nafatin rai ninia nain rejistu orijinal. label: Transfere view_photo: - explanation: "Permiti utilizador ida atu haree fotografia husi kazu ida husi haree lista kazu. La ho permisaun ne'e, utilizador labele haree koluna \"Fotografia\" husi tabela lista kazu, ka ikon fotografia ne'ebe mosu iha ne'eba. Permisaun ida ne'e mos permiti utilizador ne'e atu haree fotografia husi labarik ne'e iha \"Haree Modal\"." + explanation: Permiti utilizador ida atu haree fotografia husi kazu ida husi haree lista kazu. La ho permisaun ne'e, utilizador labele haree koluna "Fotografia" husi tabela lista kazu, ka ikon fotografia ne'ebe mosu iha ne'eba. Permisaun ida ne'e mos permiti utilizador ne'e atu haree fotografia husi labarik ne'e iha "Haree Modal". label: Haree Fotografia husi haree lista kazu view_incident_from_case: - explanation: "\"Bainhira haree hela Kazu ida, Utilizador bele haree lista insidente sira ne'ebe link ona ba Kazu ne'e no mos sumariu informasaun balun kona-ba kazu ida-idak." + explanation: '"Bainhira haree hela Kazu ida, Utilizador bele haree lista insidente sira ne''ebe link ona ba Kazu ne''e no mos sumariu informasaun balun kona-ba kazu ida-idak.' label: Haree Insidente husi Kazu view_protection_concerns_filter: explanation: Permiti utilizador atu haree filtru prekupasaun kona-ba protesaun iha pájina lista kazu ne'e. @@ -2577,62 +2481,57 @@ tet: explanation: Permiti utilizador ida atu haree informasaun husi kualker Rejistrasaun ne'ebe mak konekta ona ba kazu ida. No mos permiti utilizador ne'e atu haree formuláriu detallu Rejistrasaun sira iha Kazu ne'e. label: Haree arkivu Rejistrasaun husi Kazu write: - explanation: "Abilidade atu hanehan butaun \"Hadi'a\", atualiza informasaun iha kazu ne'e no hanehan \"Salva\"" + explanation: Abilidade atu hanehan butaun "Hadi'a", atualiza informasaun iha kazu ne'e no hanehan "Salva" label: Hadi'a accept_or_reject_transfer: - explanation: "Permiti utilizador ne'e atu aseita ka rejeita transferensia ida iha utilizador ida nia fatin ne'ebe mak iha ita nia ekipa (pur ezemplu, supervizor ida aseita hela transferensia ida ne'ebe maka manda ona ba sira nia servisu nain sosial)." + explanation: Permiti utilizador ne'e atu aseita ka rejeita transferensia ida iha utilizador ida nia fatin ne'ebe mak iha ita nia ekipa (pur ezemplu, supervizor ida aseita hela transferensia ida ne'ebe maka manda ona ba sira nia servisu nain sosial). label: Aseita ka rejeita transferensia ba utilizador seluk iha ita-nia ekipa. list_case_names: - explanation: "Jestor sira bai-bain labele haree naran sira husi Kazu iha Lista Kazu. Se jestor ida iha permisaun ida ne'e, sira sei bele haree naran sira iha lista ne'e." - label: "Se jestor, bele haree naran Kazu iha Lista Kazu." + explanation: Jestor sira bai-bain labele haree naran sira husi Kazu iha Lista Kazu. Se jestor ida iha permisaun ida ne'e, sira sei bele haree naran sira iha lista ne'e. + label: Se jestor, bele haree naran Kazu iha Lista Kazu. mark_for_offline: explanation: Permiti utilizador ne'e atu cache kazu sira ne'e ba utilizasaun durante offline. label: Marka ba Offline view_family_record: - explanation: "" - label: Haree arkivu família husi Kazu + label: Haree arkivu família husi Kazu case_from_family: - explanation: "" label: Kria Kazu husi Detallu Família - link_family_record: - explanation: "" - label: "" - explanation: "Reprezenta labarik individual, sobrevivente, ka benefisiariu sira seluk." + explanation: Reprezenta labarik individual, sobrevivente, ka benefisiariu sira seluk. label: Kazu dashboard: actions: approvals_action_plan: - explanation: "Hatudu númeru husi kazu husi utilizador atual ninian ho pedidu aprovasaun Planu Asaun ne'ebé mak Pendente hela, Aprovadu, ka Rejeitadu." - label: "Servisu Nain Kazu %{approval_label}aprovasaun" + explanation: Hatudu númeru husi kazu husi utilizador atual ninian ho pedidu aprovasaun Planu Asaun ne'ebé mak Pendente hela, Aprovadu, ka Rejeitadu. + label: Servisu Nain Kazu %{approval_label}aprovasaun approvals_action_plan_pending: explanation: Hatudu númeru kazu sira iha jestor nia ekipa ne'ebé ho pedidu aprovasaun Planu Asaun mak pendente hela. - label: "Jestor %{approval_label}aprovasaun" + label: Jestor %{approval_label} aprovasaun approvals_assessment: - explanation: "Hatudu númeru husi utilizador atual ninian kazu sira ho pedidu aprovasaun Avaliasaun ne'ebé mak Pendente hela, Aprovadu, ka Rejeitadu." - label: "Servisu Nain Kazu %{approval_label}aprovasaun" + explanation: Hatudu númeru husi utilizador atual ninian kazu sira ho pedidu aprovasaun Avaliasaun ne'ebé mak Pendente hela, Aprovadu, ka Rejeitadu. + label: Servisu Nain Kazu %{approval_label} aprovasaun approvals_assessment_pending: explanation: Hatudu númeru kazu sira iha jestor nia ekipa ne'ebé ho pedidu aprovasaun Avaliasaun mak pendente hela. - label: "Jestor %{approval_label}aprovasaun" + label: Jestor %{approval_label} aprovasaun approvals_case_plan: - explanation: "Hatudu númeru husi utilizador atual ninian kazu sira ho pedidu aprovasaun Planu Kazu ne'ebé mak Pendente hela, Aprovadu, ka Rejeitadu." - label: "Servisu Nain Kazu %{approval_label}aprovasaun" + explanation: Hatudu númeru husi utilizador atual ninian kazu sira ho pedidu aprovasaun Planu Kazu ne'ebé mak Pendente hela, Aprovadu, ka Rejeitadu. + label: Servisu Nain Kazu %{approval_label} aprovasaun approvals_case_plan_pending: explanation: Hatudu númeru kazu sira iha jestor nia ekipa ne'ebé ho pedidu aprovasaun Planu Kazu mak pendente hela. - label: "Jestor %{approval_label}aprovasaun" + label: Jestor %{approval_label} aprovasaun approvals_closure: - explanation: "Hatudu numeru husi utilizador atual ninian kazu sira ho pedidu aprovasaun Terminasaun ne'ebe mak Pendente hela, Aprovadu, ka Rejeitadu." - label: "Servisu Nain Kazu %{approval_label}aprovasaun" + explanation: Hatudu numeru husi utilizador atual ninian kazu sira ho pedidu aprovasaun Terminasaun ne'ebe mak Pendente hela, Aprovadu, ka Rejeitadu. + label: Servisu Nain Kazu %{approval_label} aprovasaun approvals_closure_pending: explanation: Hatudu numeru kazu sira iha jestor nia ekipa ne'ebe ho pedidu aprovasaun Terminasaun mak pendente hela. - label: "Jestor %{approval_label}aprovasaun" + label: Jestor %{approval_label} aprovasaun approvals_gbv_closure: - explanation: "Hatudu numeru husi utilizador atual ninian kazu sira ho pedidu aprovasaun Terminasaun VBJ ne'ebé mak Pendente hela, Aprovadu, ka Rejeitadu." - label: "Servisu Nain Kazu %{approval_label}aprovasaun" + explanation: Hatudu numeru husi utilizador atual ninian kazu sira ho pedidu aprovasaun Terminasaun VBJ ne'ebé mak Pendente hela, Aprovadu, ka Rejeitadu. + label: Servisu Nain Kazu %{approval_label} aprovasaun approvals_gbv_closure_pending: explanation: Hatudu numeru kazu sira iha jestor nia ekipa ne'ebé ho pedidu aprovasaun Terminasaun VBJ mak pendente hela. - label: "Jestor %{approval_label}aprovasaun" + label: Jestor %{approval_label} aprovasaun case_overview: - explanation: "Vizaun Jerál kartaun painel iha pajina home nia leten, ne'ebe mak inklui figura sira hanesan Total kazu no kazu Foun sira" + explanation: Vizaun Jerál kartaun painel iha pajina home nia leten, ne'ebe mak inklui figura sira hanesan Total kazu no kazu Foun sira label: Painel Vizaun Jeral case_risk: explanation: Hatudu kazu hira maka iha nivel risku ida-idak. @@ -2650,16 +2549,15 @@ tet: explanation: Permiti jestor ida atu haree kazu hira maka iha tarefa Servisu atrazadu ba ida-idak husi sira nia servisu nain kazu sira. label: Tarefa Aervisu Atrazadu dash_case_incident_overview: - explanation: . label: Vizaun Jerál - Ha'u nia Kazu sira /Insidente sira dash_cases_by_social_worker: - explanation: "Tabela ne'ebé hatudu oinsa numeru total husi kazu nakloke sira no numeru husi kazu foun sira jere husi utilizador ida-idak iha utilizador atual sira-nia grupu utilizador sira. Liña ida-idak maka utilizador iha utilizador atual sira-nia grupu utilizador sira, enkuantu \"Total\" no \"Foun\" maka koluna rua ne'e." + explanation: Tabela ne'ebé hatudu oinsa numeru total husi kazu nakloke sira no numeru husi kazu foun sira jere husi utilizador ida-idak iha utilizador atual sira-nia grupu utilizador sira. Liña ida-idak maka utilizador iha utilizador atual sira-nia grupu utilizador sira, enkuantu "Total" no "Foun" maka koluna rua ne'e. label: Kazu tuir Servisu Nain Sosial dash_cases_to_assign: explanation: 'IMPORTANTE: Ba de''it jestor sira. Hatudu numeru kazu sira ne''ebé maka utilizador atual ne''e nu''udar sai nain (tenke jestor ida). Painel ida ne''e asumi katak jestor sira labele jere sira nia kazu rasik, no nune''e se jestor ida iha sira nia kazu rasik, sira sei atribui kazu sira ne''e ba servisu nain kazu sira ne''ebé iha sira nia ekipa.' label: (Ba Jestor sira) Kazu sira ne'ebé ha'u presiza atu atribui ba ema sira iha ha'u nia ekipa dash_flags: - explanation: "Hatudu lista ida husi flags ne'ebé utilizador sira seluk aumenta ona mai ha'u nia rejistu sira, no inklui mos flags ne'ebe ha'u aumenta ona ba rejistu utilizador sira seluk nian." + explanation: Hatudu lista ida husi flags ne'ebé utilizador sira seluk aumenta ona mai ha'u nia rejistu sira, no inklui mos flags ne'ebe ha'u aumenta ona ba rejistu utilizador sira seluk nian. label: Rejistu Flagged sira dash_group_overview: explanation: Hatudu jestor ida númeru husi kazu nakloke no taka sira ne'ebe maka jere husi utilizador sira iha sira nia ekipa. @@ -2668,19 +2566,19 @@ tet: explanation: DEPREKADU. Painel ida ne'e non-funsional no sei hasai husi v2. label: Haree Rezultadu Korespondensia dash_protection_concerns: - explanation: "Tabela ne'ebé hatudu kazu hira ona maka iha ninia prekupasaun ba protesaun ida-idak. Kada liña husi tabela ne'e maka prekupasaun ba protesaun ida, enkuantu koluna ne'e indika status oi-oin ba kazu sira (\"Kazu hotu-hotu,\" \"Kazu nakloke sira,\" \"Foun (semana ne'e),\" \"Taka ona (semana ne'e)\")" + explanation: Tabela ne'ebé hatudu kazu hira ona maka iha ninia prekupasaun ba protesaun ida-idak. Kada liña husi tabela ne'e maka prekupasaun ba protesaun ida, enkuantu koluna ne'e indika status oi-oin ba kazu sira ("Kazu hotu-hotu," "Kazu nakloke sira," "Foun (semana ne'e)," "Taka ona (semana ne'e)") label: Kazu sira tuir Prekupasaun ba Protesaun dash_protection_concerns_by_location: - explanation: "Ida ne'e hanesan painel \"Haree Prekupasaun ba Protesaun\", naran katak utilizador ne'e bele hili fatin ida husi dropdown ida atu hatudu estatistika husi prekupasaun ba protesaun prevalensia de'it iha fatin ne'eba." + explanation: Ida ne'e hanesan painel "Haree Prekupasaun ba Protesaun", naran katak utilizador ne'e bele hili fatin ida husi dropdown ida atu hatudu estatistika husi prekupasaun ba protesaun prevalensia de'it iha fatin ne'eba. label: Haree Prekupasaun ba Protesaun tuir Fatin dash_reporting_location: - explanation: "Tabela ne'ebé hatudu kazu hira ona maka iha fatin ida-idak (iha nivel singular husi espesifidade hanesan \"Provinsia\" ka \"Distritu\"). Kada liña husi tabela maka fatin ida, no koluna ne'e indika status oin-oin husi kazu sira ne'e (\"KAZU NAKLOKE,\" \"FOUN (SEMANA KOTUK),\" \"FOUN (SEMANA NE'E),\" \"TAKA ONA (SEMANA KOTUK),\" \"TAKA ONA (SEMANA NE'E)\"). Bai-bain uza ba konta jestor ka administrador." + explanation: Tabela ne'ebé hatudu kazu hira ona maka iha fatin ida-idak (iha nivel singular husi espesifidade hanesan "Provinsia" ka "Distritu"). Kada liña husi tabela maka fatin ida, no koluna ne'e indika status oin-oin husi kazu sira ne'e ("KAZU NAKLOKE," "FOUN (SEMANA KOTUK)," "FOUN (SEMANA NE'E)," "TAKA ONA (SEMANA KOTUK)," "TAKA ONA (SEMANA NE'E)"). Bai-bain uza ba konta jestor ka administrador. label: Kazu sira tuir Fatin Relatóriu dash_service_provisions: explanation: Hatudu numeru husi kazu sira ne'ebé iha ona utilizador sira seluk aumenta prestasaun servisu ba sira. Númeru ida ne'e mosu iha seksaun prinsipal husi painel ne'e. label: Kazu sira tuir tipu Prestasaun Servisu dash_shared_from_my_team: - explanation: "Hatudu jestor ida numeru husi kazu sira ne'ebe jere ona husi kada utilizador iha sira nia ekipa, ne'ebé mak hetan refere ka transfere ona ba utilizador sira seluk." + explanation: Hatudu jestor ida numeru husi kazu sira ne'ebe jere ona husi kada utilizador iha sira nia ekipa, ne'ebé mak hetan refere ka transfere ona ba utilizador sira seluk. label: Fahe ona husi Ha'u nia Ekipa dash_shared_with_me: explanation: Hatudu kazu hira maka refere ka transfere ona ba ita. @@ -2691,28 +2589,28 @@ tet: dash_shared_with_my_team_overview: label: Fahe ona Ho Ha'u nia Ekipa (Vizaun-Jerál) dash_shared_with_others: - explanation: "Hatudu ha'u nia kazu hira maka iha referal ativu, transferensia pendente, ka transferensia rejeitadu. La'os tipikalmente ba jestor sira, se karik sira jere mesak kazu sira ne'e." + explanation: Hatudu ha'u nia kazu hira maka iha referal ativu, transferensia pendente, ka transferensia rejeitadu. La'os tipikalmente ba jestor sira, se karik sira jere mesak kazu sira ne'e. label: Fahe ona ho Ema Seluk dash_violations_category_verification_status: - explanation: "Hatudu violasaun MRM hira husi kada tipu mak akontese ona, fahe tutan tuir status verifikasaun." + explanation: Hatudu violasaun MRM hira husi kada tipu mak akontese ona, fahe tutan tuir status verifikasaun. label: MRM - Númeru violasaun kada status verifikasaun dash_violations_category_region: - explanation: "Hatudu violasaun MRM hira husi kada tipu mak akontese ona iha kada rejiaun, fahe tutan tuir tipu violasaun." + explanation: Hatudu violasaun MRM hira husi kada tipu mak akontese ona iha kada rejiaun, fahe tutan tuir tipu violasaun. label: MRM - Númeru Violasaun kada Rejiaun dash_perpetrator_armed_force_group_party_names: - explanation: "Hatudu violasaun MRM hira husi kada tipu mak akontese ona, fahe tutan tuir perpetrador." + explanation: Hatudu violasaun MRM hira husi kada tipu mak akontese ona, fahe tutan tuir perpetrador. label: MRM - Númeru Violasaun kada Perpetrador dash_show_none_values: explanation: Aumenta kategoria adisional ida "Laiha Nivel Risku" ba painel hotu-hotu ne'ebe fahe tutan kazu sira tuir nivel risku. Ida ne'e espesifikamente ba konfigurasaun sira ne'ebe iha opsaun dahaat "Laiha Risku" ba kampu sira nivel risku nian. label: Haree kazu sira ho 'Laiha Nivel Risku' iha Painel Avaliasaun dash_tasks: - explanation: "Permiti utilizador ne'e atu haree pájina tarefa sira. Ida ne'e tenke uza ba servisu nain kazu no fornesedor servisu sira, desde númeru sira sei espesifikamente ba kazu sira ne'ebé ita jere diretamente. Jestor sira tenke iha painel \"Haree Kazu sira Tuir Tarefa Atrazadu\", desde ne'e permiti sira atu haree tarefa sira ne'ebé tarde ba ema ida-idak iha sira nia grupu utilizador sira." + explanation: Permiti utilizador ne'e atu haree pájina tarefa sira. Ida ne'e tenke uza ba servisu nain kazu no fornesedor servisu sira, desde númeru sira sei espesifikamente ba kazu sira ne'ebé ita jere diretamente. Jestor sira tenke iha painel "Haree Kazu sira Tuir Tarefa Atrazadu", desde ne'e permiti sira atu haree tarefa sira ne'ebé tarde ba ema ida-idak iha sira nia grupu utilizador sira. label: Pajina Tarefa sira dash_national_admin_summary: - explanation: "Hatudu total Kazu nakloke sira iha sistema, numeru Kazu foun sira ne'ebé kria ona iha kada semana rua kotuk, no numeru Kazu sira taka ona iha kada semana rua kotuk ba." + explanation: Hatudu total Kazu nakloke sira iha sistema, numeru Kazu foun sira ne'ebé kria ona iha kada semana rua kotuk, no numeru Kazu sira taka ona iha kada semana rua kotuk ba. label: Sumáriu Administrador view_response: - explanation: "Ba kada tipu resposta, hatudu kazu hira maka iha kada nivel risku iha servisu sira ne'ebe besik ona prazu final ka atrazadu atu kompleta." + explanation: Ba kada tipu resposta, hatudu kazu hira maka iha kada nivel risku iha servisu sira ne'ebe besik ona prazu final ka atrazadu atu kompleta. label: Haree Resposta sira workflow: explanation: Permiti servisu nain kazu ida atu haree grafika pie ida hatudu kazu hira maka iha kada etapa husi workflow jestaun kazu nian. @@ -2723,12 +2621,12 @@ tet: explanation: Determina sumáriu informasaun saida de'it maka mosu iha pájina inisial. label: Painel disabled: - explanation: "Se ita dezativa knaar ida ne'e, ita sei labele ona atu atribui ne'e ba konta Utilizador sira." + explanation: Se ita dezativa knaar ida ne'e, ita sei labele ona atu atribui ne'e ba konta Utilizador sira. label: Dezativadu duplicate: actions: read: - explanation: "Permiti utilizador ne'e atu halo peskiza ida ne'ebé avansadu ba kazu sira hotu-hotu iha sistema, utiliza kriteria oi-oin, inklui Naran, Naran Bolu, sexu, Tinan, no Nasionalidade." + explanation: Permiti utilizador ne'e atu halo peskiza ida ne'ebé avansadu ba kazu sira hotu-hotu iha sistema, utiliza kriteria oi-oin, inklui Naran, Naran Bolu, sexu, Tinan, no Nasionalidade. label: Haree explanation: Peskiza kazu avansadu ba administrador sira. label: Duplika Peskiza @@ -2750,22 +2648,22 @@ tet: group: actions: admin_only: - explanation: "Ida ne'e signifika katak utilizador sira ne'ebe ho knaar ne'e sei bele de'it haree buat saida de'it mak relasiona ba sistema administrasaun, mak hanesan relatoriu sira, formuláriu no konfigurasaun lookup, utilizador sira, knaar sira, no grupu utilizador sira. Sira sei labele haree kualker kazu individual sira, pedidu buka-tuir sira, ka insidente sira." + explanation: Ida ne'e signifika katak utilizador sira ne'ebe ho knaar ne'e sei bele de'it haree buat saida de'it mak relasiona ba sistema administrasaun, mak hanesan relatoriu sira, formuláriu no konfigurasaun lookup, utilizador sira, knaar sira, no grupu utilizador sira. Sira sei labele haree kualker kazu individual sira, pedidu buka-tuir sira, ka insidente sira. label: Laiha Rejistu sira - Funsionalidade Admin de'it agency: - explanation: "Knaar ne'e bele asesu rejistu ne'ebe jere husi utilizador hotu-hotu iha sira nia ajensia. Se utilizador ida iha asesu ba utilizador sira, sira bele asesu utilizador sira hotu iha sira nia ajensia." + explanation: Knaar ne'e bele asesu rejistu ne'ebe jere husi utilizador hotu-hotu iha sira nia ajensia. Se utilizador ida iha asesu ba utilizador sira, sira bele asesu utilizador sira hotu iha sira nia ajensia. label: Rejistu hotu-hotu ka utilizador sira iha hau-nia ajensia all: - explanation: "Knaar ne'e bele asesu rejistu hotu-hotu, utilizador sira, no grupu utilizador sira iha sistema, la depende ba grupu utilizador ida ne'ebe sira hola parte ba." + explanation: Knaar ne'e bele asesu rejistu hotu-hotu, utilizador sira, no grupu utilizador sira iha sistema, la depende ba grupu utilizador ida ne'ebe sira hola parte ba. label: Asesu Rejistu Hotu-Hotu ka utilizador group: explanation: Knaar ne'e bele asesu rejistu sira ne'ebe jere husi Utilizador sira hotu iha sira nia Grupu Utilizador sira. Sira bele de'it asesu Utilizador sira iha sira nia Grupu Utilizador sira. Sira so bele de'it asesu sira nia Grupu Utilizador sira. label: Asesu rejistu ka utilizador hotu-hotu iha ha'u-nia grupu self: - explanation: "Knaar ne'e bele asesu sira nia rejistu sira (Kazu sira, pedidu buka-tuir sira, ka insidente sira), no bele hadi'a sira nia konta utilizador." + explanation: Knaar ne'e bele asesu sira nia rejistu sira (Kazu sira, pedidu buka-tuir sira, ka insidente sira), no bele hadi'a sira nia konta utilizador. label: Asesu de'it ha'u nia rejistu ka utilizador - explanation: "Kontrola rejistu sira ne'ebe (Kazu sira, Pedidu BUka-Tuir sira, ka Insidente sira), knaar ne'e bele asesu. Se knaar ne'e iha asesu ba Utilizador sira no Grupu Utilizador sira, ida ne'e mos kontrola Utilizador sira no Grupu Utilizador sira ne'ebe sira bele asesu. Knaar ho asesu ba \"Laiha Rejistu\" so bele de'it asesu sistema konfigurasaun mak hanesan Formuláriu sira, Utilizador sira, no Relatoriu sira." - label: "Rejistu saida de'it mak knaar ne'e afeta?" + explanation: Kontrola rejistu sira ne'ebe (Kazu sira, Pedidu BUka-Tuir sira, ka Insidente sira), knaar ne'e bele asesu. Se knaar ne'e iha asesu ba Utilizador sira no Grupu Utilizador sira, ida ne'e mos kontrola Utilizador sira no Grupu Utilizador sira ne'ebe sira bele asesu. Knaar ho asesu ba "Laiha Rejistu" so bele de'it asesu sistema konfigurasaun mak hanesan Formuláriu sira, Utilizador sira, no Relatoriu sira. + label: Rejistu saida de'it mak knaar ne'e afeta? incident: actions: change_log: @@ -2778,10 +2676,10 @@ tet: explanation: Abilidade atu dezativa ka ativa Insidente ida. "Dezativadu" Insidente labele mosu tuir padraun iha lista Insidente ne'e. Utilizador sira be'e haree Insidente dezativadu sira iha lista Insidente tuir aplikasaun filtru ida. label: Ativa / Dezativa export_case_pdf: - explanation: "Utilizador bele halo arkivu PDF ida esporta husi lista insidente sira ka pajina sira hatudu insidente, ne'ebe kontein kampu sira hotu-hotu iha ne'ebe utilizador atual iha asesu, ba kazu ida, multiplu, ka kazu hotu-hotu iha ne'ebe utilizador iha asesu. Iha PDF arkivu esportasaun ne'e, informasaun sira alista dahuluk tuir kazu, no depois organiza tan tuir formulariu iha ne'ebe informasaun mosu ba." + explanation: Utilizador bele halo arkivu PDF ida esporta husi lista insidente sira ka pajina sira hatudu insidente, ne'ebe kontein kampu sira hotu-hotu iha ne'ebe utilizador atual iha asesu, ba kazu ida, multiplu, ka kazu hotu-hotu iha ne'ebe utilizador iha asesu. Iha PDF arkivu esportasaun ne'e, informasaun sira alista dahuluk tuir kazu, no depois organiza tan tuir formulariu iha ne'ebe informasaun mosu ba. label: Esporta PDF export_csv: - explanation: "Utilizador bele halo arkizu CSV ida esporta husi lista insidente ka pájina sira hatudu insidente, ne'ebé kontéin kampu hotu-hotu ne'ebé utilizador atual ne'e iha asesu, ba insidente ida, multiplu ka insidente hotu-hotu ne'ebé utilizador ne'e iha asesu." + explanation: Utilizador bele halo arkizu CSV ida esporta husi lista insidente ka pájina sira hatudu insidente, ne'ebé kontéin kampu hotu-hotu ne'ebé utilizador atual ne'e iha asesu, ba insidente ida, multiplu ka insidente hotu-hotu ne'ebé utilizador ne'e iha asesu. label: Esporta CSV export_custom: label: Esporta Personalizadu @@ -2792,47 +2690,44 @@ tet: explanation: Utilizador bele kria Excel espesializadu ida (arkivu XLS) esporta ba Violasaun MRM sira. Asaun ida ne'e disponivel iha pajina hatudu Insidente no lista Insidente. label: Esporta Violasaun MRM sira ba Excel (arkivu XLS) export_json: - explanation: "Utilizador bele kria arkivu JSON ida esporta husi lista insidente ka pajina sira hatudu insidente, ne'ebe kontein kampu sira hotu-hotu ne'ebe utilzador atual iha asesu, ba insidente ida, multiplu, ka insidente hotu-hotu ne'ebe utilizador iha asesu. Esporta ida ne'e prinsipalmente uza ba sira ne'ebe hakarak atu esporta insidente sira husi sistema Primero atual no depois importa insidente sira ne'e ba sistema Primero ida seluk, ka esporta ba jestaun sistema informasaun sira seluk. Formatu JSON ne'e lezivel husi makina no la pratikal ba maioria utilizador sira seluk." + explanation: Utilizador bele kria arkivu JSON ida esporta husi lista insidente ka pajina sira hatudu insidente, ne'ebe kontein kampu sira hotu-hotu ne'ebe utilzador atual iha asesu, ba insidente ida, multiplu, ka insidente hotu-hotu ne'ebe utilizador iha asesu. Esporta ida ne'e prinsipalmente uza ba sira ne'ebe hakarak atu esporta insidente sira husi sistema Primero atual no depois importa insidente sira ne'e ba sistema Primero ida seluk, ka esporta ba jestaun sistema informasaun sira seluk. Formatu JSON ne'e lezivel husi makina no la pratikal ba maioria utilizador sira seluk. label: Esporta JSON export_list_view_csv: explanation: Utilizador bele kria arkivu CSV ida husi pajina lista insidente ne'ebe kontein kampu sira ne'ebe hanesan ne'ebe mosu ba utilizador ida ne'eba iha lista insidente. Bele halo de'it husi pajina lista insidente. label: Esporta lista haree CSV export_pdf: - explanation: "Utilizador bele halo arkivu PDF ida esporta husi lista insidente sira ka pajina sira hatudu insidente, ne'ebe kontein kampu sira hotu-hotu iha ne'ebe utilizador atual iha asesu, ba kazu ida, multiplu, ka kazu hotu-hotu iha ne'ebe utilizador iha asesu. Iha PDF arkivu esportasaun ne'e, informasaun sira alista dahuluk tuir kazu, no depois organiza tan tuir formulariu iha ne'ebe informasaun mosu ba." + explanation: Utilizador bele halo arkivu PDF ida esporta husi lista insidente sira ka pajina sira hatudu insidente, ne'ebe kontein kampu sira hotu-hotu iha ne'ebe utilizador atual iha asesu, ba kazu ida, multiplu, ka kazu hotu-hotu iha ne'ebe utilizador iha asesu. Iha PDF arkivu esportasaun ne'e, informasaun sira alista dahuluk tuir kazu, no depois organiza tan tuir formulariu iha ne'ebe informasaun mosu ba. label: Esporta PDF export_xls: - explanation: "Utilizador bele halo arkizu XLS ida esporta husi lista insidente ka pájina sira hatudu insidente, ne'ebé kontéin formulariu ka kampu personalizadu, ba kazu ida, multiplu ka kazu hotu-hotu ne'ebé utilizador ne'e iha asesu. Iha esportasaun ida ne'e, formulariu ida-idak reprezenta ona iha sira nia tab rasik iha arkizu XLS nia laran. Utilizador bele hili formulariu ka kampu sira ne'ebe sira hakarak atu inklui iha esportasaun uza modal Esportasaun Personalizadu. Favo anota katak utilizador bele inklui dei't formulariu ka kampu sira iha esporta se sira iha ona abilidade atu haree formulariu ka kampu sira ne'e bainhira haree kazu ida iha aplikasaun." + explanation: Utilizador bele halo arkizu XLS ida esporta husi lista insidente ka pájina sira hatudu insidente, ne'ebé kontéin formulariu ka kampu personalizadu, ba kazu ida, multiplu ka kazu hotu-hotu ne'ebé utilizador ne'e iha asesu. Iha esportasaun ida ne'e, formulariu ida-idak reprezenta ona iha sira nia tab rasik iha arkizu XLS nia laran. Utilizador bele hili formulariu ka kampu sira ne'ebe sira hakarak atu inklui iha esportasaun uza modal Esportasaun Personalizadu. Favo anota katak utilizador bele inklui dei't formulariu ka kampu sira iha esporta se sira iha ona abilidade atu haree formulariu ka kampu sira ne'e bainhira haree kazu ida iha aplikasaun. label: Esporta Excel (Arkivu XLS) flag: explanation: Abilidade atu aumenta flag ida ba kazu ida. Utilizador sira ho permisaun ida ne'e bele mos hasa'i flag sira ne'ebe sira aumenta ona ba insidente ida. label: Flag import: - explanation: "Permiti utilizador ida atu kria insidente foun ida ka barak liu husi importa sira husi arkivu CSV, Excel ka JSON. Arkivu ne'ebe atu importa tenke iha formatu *very* espesifikamente ba informasuan atu importa ho apropriadu. Funsaun ida ne'e tenke disponivel de'it ba utilizador administrador sira ne'ebe mak iha konesimentu tekniku ne'ebe avansadu no iha konesimentu klean kona-ba oinsa halo formatu ba dadus iha Primero. Bele halo de'it husi pajina lista insidente." + explanation: Permiti utilizador ida atu kria insidente foun ida ka barak liu husi importa sira husi arkivu CSV, Excel ka JSON. Arkivu ne'ebe atu importa tenke iha formatu *very* espesifikamente ba informasuan atu importa ho apropriadu. Funsaun ida ne'e tenke disponivel de'it ba utilizador administrador sira ne'ebe mak iha konesimentu tekniku ne'ebe avansadu no iha konesimentu klean kona-ba oinsa halo formatu ba dadus iha Primero. Bele halo de'it husi pajina lista insidente. label: Importa remove_alert: - explanation: "" label: Elimina alerta husi insidente ida manage: - explanation: "Permiti utilizador ida atu halo asaun sira ne'ebé disponivel iha insidente sira. Permisaun \"Jere\" esensialmente signifika \"Buat hotu-hotu\". " + explanation: 'Permiti utilizador ida atu halo asaun sira ne''ebé disponivel iha insidente sira. Permisaun "Jere" esensialmente signifika "Buat hotu-hotu". ' label: Jere (Permisaun hotu-hotu ba tipu rekursu ida ne'e) read: explanation: Abilidade atu haree insidente ida. label: Haree sync_mobile: - explanation: "Permisaun ida ne'e jeralmente permiti utilizador ne'e atu uza aplikasaun iha telefone. Dahuluk, nia permiti utilizador ne'e atu haree asaun sira hanesan \"Marka ba Telefone\" no \"La-Marka ba Telefone\", ne'ebe mak mosu iha lista insidente no pájina hatudu insidente. Marka insidente ida ba telefone indika katak informasaun kona-ba insidente ne'e tenke sikroniza entre utilizador ne'e nia telefone no aplikasaun web, enkuantu la-marka insidente ida iha telefone hapara sikronizasaun ne'e atu akontese. Utilizador sira ne'ebe la iha permisaun ne'e mos labele sinkroniza sira nia telefone ho aplikasaun web en jerál, signifika katak sira labele uza app telefone atu jere insidente sira." + explanation: Permisaun ida ne'e jeralmente permiti utilizador ne'e atu uza aplikasaun iha telefone. Dahuluk, nia permiti utilizador ne'e atu haree asaun sira hanesan "Marka ba Telefone" no "La-Marka ba Telefone", ne'ebe mak mosu iha lista insidente no pájina hatudu insidente. Marka insidente ida ba telefone indika katak informasaun kona-ba insidente ne'e tenke sikroniza entre utilizador ne'e nia telefone no aplikasaun web, enkuantu la-marka insidente ida iha telefone hapara sikronizasaun ne'e atu akontese. Utilizador sira ne'ebe la iha permisaun ne'e mos labele sinkroniza sira nia telefone ho aplikasaun web en jerál, signifika katak sira labele uza app telefone atu jere insidente sira. label: Sinkroniza ho telefone write: - explanation: "Abilidade atu hanehan butaun \"Hadi'a\", atualiza informasaun kona-ba insidente, no hanehan \"Salva\". No mos permiti utilizador ne'e atu dezativa ka ativa insidente ida." + explanation: Abilidade atu hanehan butaun "Hadi'a", atualiza informasaun kona-ba insidente, no hanehan "Salva". No mos permiti utilizador ne'e atu dezativa ka ativa insidente ida. label: Hadi'a - explanation: "Reprezenta eventu ida ne'ebe akontese ona. Ne'e bai-bain insidente sira hanesan abuzu ka violensia, maske sira mos bele koresponde ba eventu sira mak hanesan hasoru ho ezekusan lei. Insidente sira ne'e bai-bain ligadu ho Kazu sira." + explanation: Reprezenta eventu ida ne'ebe akontese ona. Ne'e bai-bain insidente sira hanesan abuzu ka violensia, maske sira mos bele koresponde ba eventu sira mak hanesan hasoru ho ezekusan lei. Insidente sira ne'e bai-bain ligadu ho Kazu sira. label: Insidente is_manager: explanation: Aplika ba kualker knaar utilizador ne'ebe jeralmente superviziona utilizador sira seluk. Ida ne'e permiti utilizador ida atu haree painel sira no filtru sira ne'ebe ajuda utilizador ida jere ekipa ida. - label: "Jestor ne'e?" + label: Jestor ne'e? managed_report: actions: - managed_report_scope: - label: "" managed_report_scope_all: label: Hotu-Hotu managed_report_scope_group: @@ -2847,29 +2742,22 @@ tet: label: Nota Orizontal Global individual_children: label: Labarik Individual - workflow_report: - label: Workflow - explanation: Abilidade atu haree estatistíku iha Status Workflow. Permisaun ida ne'e mós permiti utilizador atu esporta dadus husi Insight ida. violence_type_report: - label: Tipu husi Violénsia explanation: Abilidade atu haree estatistíku iha Tipu husi Violénsia. Permisaun ida ne'e mós permiti utilizador atu esporta dadus husi Insight ida. - referrals_transfers_report: - label: Referál no Transferénsia - explanation: "" matching_configuration: actions: manage: - explanation: "Abilidade atu kontrola kampu sira ne'ebe kompara atu hetan korespondensia entre pedidu buka-tuir sira no kazu sira. Desde ida ne'e kontrola oinsa hala'o korespondensia iha sistema hotu-hotu, permisaun ida ne'e tenke disponivel de'it jeralmente ba sistema administrador." + explanation: Abilidade atu kontrola kampu sira ne'ebe kompara atu hetan korespondensia entre pedidu buka-tuir sira no kazu sira. Desde ida ne'e kontrola oinsa hala'o korespondensia iha sistema hotu-hotu, permisaun ida ne'e tenke disponivel de'it jeralmente ba sistema administrador. label: Jere (Permisaun hotu-hotu ba tipu rekursu ida ne'e) explanation: Kontrola kampu sira ne'ebe mak uza atu kompara Pedidu Buka-Tuir sira ho Kazu sira durante Buka-Tuir Familia no Reunifikasaun. label: Konfigurasaun Korespondente metadata: actions: manage: - explanation: "Abilidade atu kria, hadi'a, tradus, no hamoos formuláriu sira, formuláriu kampu sira, no peskiza sira. Favor anota katak utilizador ida ho permisaun ne'e so bele deit jere formuláriu sira ne'ebe sira iha asesu ba. Pur ezemplu, se administrador nasional ida iha deit abilidade atu haree formuláriu Rejistu Nain iha kazu sira, depois sira sei bele atualiza deit konfigurasaun ba formuláriu ida ne'e." + explanation: Abilidade atu kria, hadi'a, tradus, no hamoos formuláriu sira, formuláriu kampu sira, no peskiza sira. Favor anota katak utilizador ida ho permisaun ne'e so bele deit jere formuláriu sira ne'ebe sira iha asesu ba. Pur ezemplu, se administrador nasional ida iha deit abilidade atu haree formuláriu Rejistu Nain iha kazu sira, depois sira sei bele atualiza deit konfigurasaun ba formuláriu ida ne'e. label: Jere (Permisaun hotu-hotu ba tipu rekursu ida ne'e) - explanation: "Kontrola abilidade atu konfigura Formuláriu Primero no Kampu sira, nune'e mos opsaun Peskiza ne'ebe uza iha laran." - label: "Formuláriu sira, Peskiza sira" + explanation: Kontrola abilidade atu konfigura Formuláriu Primero no Kampu sira, nune'e mos opsaun Peskiza ne'ebe uza iha laran. + label: Formuláriu sira, Peskiza sira module: actions: cp: @@ -2892,20 +2780,20 @@ tet: explanation: Kontrola sira se utilizador ida buka hela korespondente buka-tuir bele haree fotografia sira ba Kazu ka Pedidu Buka-Tuir asosiadu ho Korespondente Potensial ida. label: Haree Fotografia manage: - explanation: "Permiti utilizador ida atu halo asaun sira ne'ebé disponivel iha Korespondente Potensial sira. Permisaun \"Jere\" esensialmente signifika \"Buat hotu-hotu\". " + explanation: 'Permiti utilizador ida atu halo asaun sira ne''ebé disponivel iha Korespondente Potensial sira. Permisaun "Jere" esensialmente signifika "Buat hotu-hotu". ' label: Jere label: Korespondente Potensial primero_configuration: actions: manage: - explanation: "Abilidade atu salva, aplika, no manda Konfigurasaun sira. Permisaun ida ne'e bai-bain rezerva ba sistema administrador." + explanation: Abilidade atu salva, aplika, no manda Konfigurasaun sira. Permisaun ida ne'e bai-bain rezerva ba sistema administrador. label: Jere (Permisaun hotu-hotu ba tipu rekursu ida ne'e) label: Konfigurasaun referral: actions: refer: - explanation: "Ida ne'e signifika knaar ne'e sei mosu hanesan opsaun ida ba \"Tipu Benefisiariu\" bainhira utilizador ne'e halo referál esternal ida. Se kuandu utilizador ne'e hili knaar ne'e hanesan tipu referál, Esportasaun ne'ebé Primero halo bainhira utilizador ne'e submete referál sei kontein deit informasaun ne'ebé hetan iha formuláriu knaar ne'e asesu ba. Nune'e, pur ezemplu, se kuandu utilizador ne'e hili \"Fornesedor Servisu Médiku\" hanesan tipu benefisiariu, no knaar Fornesedor Servisu Médiku iha deit asesu ba Identidade Báziku no formuláriu Prekupasaun ba Protesaun, arkivu esportasaun ne'ebé Primero esporta ba referál esternal sei kontein deit kampu sira ne'ebé iha formuláriu rua ne'e. " - label: "Bele utiliza knaar ne'e ba Referal esternal sira?" + explanation: 'Ida ne''e signifika knaar ne''e sei mosu hanesan opsaun ida ba "Tipu Benefisiariu" bainhira utilizador ne''e halo referál esternal ida. Se kuandu utilizador ne''e hili knaar ne''e hanesan tipu referál, Esportasaun ne''ebé Primero halo bainhira utilizador ne''e submete referál sei kontein deit informasaun ne''ebé hetan iha formuláriu knaar ne''e asesu ba. Nune''e, pur ezemplu, se kuandu utilizador ne''e hili "Fornesedor Servisu Médiku" hanesan tipu benefisiariu, no knaar Fornesedor Servisu Médiku iha deit asesu ba Identidade Báziku no formuláriu Prekupasaun ba Protesaun, arkivu esportasaun ne''ebé Primero esporta ba referál esternal sei kontein deit kampu sira ne''ebé iha formuláriu rua ne''e. ' + label: Bele utiliza knaar ne'e ba Referal esternal sira? label: Referál registry_record: actions: @@ -2922,7 +2810,7 @@ tet: explanation: 'Utilizador bele halo arkivu CSV ida esporta husi lista Rejistrasaun ka pájina sira hatudu Rejistrasaun, ne''ebé kontéin kampu hotu-hotu ne''ebé utilizador atual ne''e iha asesu, ba grava Rejistrasaun ida, multiplu ka grava Rejistrasaun hotu-hotu ne''ebé utilizador ne''e iha asesu. NOTA: Esportasaun CSV la lee karater non-Latina sira (e.g. Arabic, Bangla) iha formatu ne''ebé lezivel.' label: Esporta CSV export_json: - explanation: "Utilizador bele halo arkivu JSON ida esporta husi lista Rejistrasaun ka pájina sira hatudu Rejistrasaun, ne'ebé kontéin kampu hotu-hotu ne'ebé utilizador atual ne'e iha asesu. Formatu JSON hanesan makina lezivel no la pratikal ba maioria utilizador sira." + explanation: Utilizador bele halo arkivu JSON ida esporta husi lista Rejistrasaun ka pájina sira hatudu Rejistrasaun, ne'ebé kontéin kampu hotu-hotu ne'ebé utilizador atual ne'e iha asesu. Formatu JSON hanesan makina lezivel no la pratikal ba maioria utilizador sira. label: Esporta JSON export_xls: explanation: 'Utilizador bele halo arkivu XLS ida esporta husi lista Rejistrasaun ka pájina sira hatudu Rejistrasaun, ne''ebé kontéin kampu hotu-hotu ne''ebé utilizador atual ne''e iha asesu. NOTA: Formatu XLS la lee karater non-Latina sira (e.g. Arabic, Bangla) iha formatu ne''ebé lezivel, desde esportasaun CSV labele halo.' @@ -2931,85 +2819,66 @@ tet: explanation: Abilidade atu aumenta flag ida ba grava Rejistrasaun ida. Utilizador sira ho permisaun ida ne'e bele mos hasa'i flag sira ne'ebe sira aumenta ona ba grava Rejistrasaun ida. label: Flag manage: - explanation: "Permiti utilizador ida atu halo asaun sira ne'ebé disponivel iha grava Rejistrasaun sira. Permisaun \"Jere\" esensialmente signifika \"Buat hotu-hotu\". " + explanation: 'Permiti utilizador ida atu halo asaun sira ne''ebé disponivel iha grava Rejistrasaun sira. Permisaun "Jere" esensialmente signifika "Buat hotu-hotu". ' label: Jere (Permisaun hotu-hotu ba tipu rekursu ida ne'e) read: explanation: Abilidade atu haree grava Rejistrasaun sira. label: Haree write: - explanation: "Abilidade atu hanehan butaun \"Hadi'a\", atualiza informasaun kona-ba Grava Rejistrasaun, no hanehan \"Salva\"" + explanation: Abilidade atu hanehan butaun "Hadi'a", atualiza informasaun kona-ba Grava Rejistrasaun, no hanehan "Salva" label: Hadi'a sync_mobile: explanation: Permiti utilizador ne'e atu cache Grava Rejistrasaun sira ne'e ba utilizasaun durante offline. label: Marka ba Offline - explanation: "Ida ne'e bele reprezenta individual ka instituisaun ida ne'ebé presija atu ligadu ba rejistu sira seluk hanesan kazu ka insidente sira, mesak oi-oin deit, no atualiza repetidamente ho informasaun foun. Sira ne'e hanesan ho peskiza, maibe ho informasaun ne'ebé kompleksu liu ba entrada ida-idak." + explanation: Ida ne'e bele reprezenta individual ka instituisaun ida ne'ebé presija atu ligadu ba rejistu sira seluk hanesan kazu ka insidente sira, mesak oi-oin deit, no atualiza repetidamente ho informasaun foun. Sira ne'e hanesan ho peskiza, maibe ho informasaun ne'ebé kompleksu liu ba entrada ida-idak. label: Grava Rejistrasaun family: actions: - change_log: - explanation: "" - label: "" create: - explanation: "" label: Kria enable_disable_record: - explanation: "" label: Ativa / Dezativa export_csv: - explanation: '' label: Esporta CSV export_json: - explanation: "" label: Esporta JSON export_xls: - explanation: '' label: Esporta Excel (Arkivu XLS) export_list_view_csv: - explanation: "" label: Esporta lista haree CSV export_pdf: - explanation: "" label: Esporta PDF export_custom: label: Esporta Personalizadu flag: - explanation: "" label: Flag - manage: - explanation: "" - label: "" read: explanation: Abilidade atu haree família sira label: Haree write: - explanation: "" label: Hadi'a sync_mobile: - explanation: "" label: Marka ba Offline close: - explanation: "" label: Taka reopen: - explanation: "" label: Loke filafali case_from_family: - explanation: "" label: Kria Kazu label: Família report: actions: create: - explanation: "Abilidade atu kria relatóriu foun ida. Bainhira utilizador ida kria relatóriu ida, nia sei vizivel ba utilizador hotu-hotu ho asesu \"Lee\" ka \"Lee Grupu\" ba relatóriu sira." + explanation: Abilidade atu kria relatóriu foun ida. Bainhira utilizador ida kria relatóriu ida, nia sei vizivel ba utilizador hotu-hotu ho asesu "Lee" ka "Lee Grupu" ba relatóriu sira. label: Kria group_read: - explanation: "Abilidade atu haree relatóriu hotu-hotu. Númeru husi kada relatóriu sei refleta deit rejistu sira ne'ebé asesivel ba utilizador sira iha utilizador nia grupu utilizador atual sira. Permisaun ida ne'e uza bei-beik ba administrador lokal, rejional, ka ajénsia buka atu hetan insights ba sira nia ekipa ka organizasaun ninia dezempeño. Permisaun ida ne'e mós fó abilidade ba utilizador atu esporta dadus husi relatóriu ida." + explanation: Abilidade atu haree relatóriu hotu-hotu. Númeru husi kada relatóriu sei refleta deit rejistu sira ne'ebé asesivel ba utilizador sira iha utilizador nia grupu utilizador atual sira. Permisaun ida ne'e uza bei-beik ba administrador lokal, rejional, ka ajénsia buka atu hetan insights ba sira nia ekipa ka organizasaun ninia dezempeño. Permisaun ida ne'e mós fó abilidade ba utilizador atu esporta dadus husi relatóriu ida. label: Haree (dadus bazeia ba-grupu) manage: - explanation: "Permiti utilizador ida atu halo asaun sira ne'ebé disponivel iha Ajensia sira. Permisaun \"Jere\" esensialmente signifika \"Buat hotu-hotu\". " + explanation: 'Permiti utilizador ida atu halo asaun sira ne''ebé disponivel iha Ajensia sira. Permisaun "Jere" esensialmente signifika "Buat hotu-hotu". ' label: Jere (Permisaun hotu-hotu ba tipu rekursu ida ne'e) read: - explanation: "Abilidade atu haree relatóriu hotu-hotu. Númeru husi kada relatóriu sei refleta rejistu hotu-hotu iha sistema, la'os deit rejistu sira ne'ebé utilizador atual iha asesu. Permisaun ida ne'e mós fó abilidade ba utilizador atu esporta dadus husi relatóriu ida." + explanation: Abilidade atu haree relatóriu hotu-hotu. Númeru husi kada relatóriu sei refleta rejistu hotu-hotu iha sistema, la'os deit rejistu sira ne'ebé utilizador atual iha asesu. Permisaun ida ne'e mós fó abilidade ba utilizador atu esporta dadus husi relatóriu ida. label: Haree write: explanation: Abilidade atu hadi'a relatóriu hotu-hotu (inklui relatóriu sira ne'ebé kria husi utilizador sira seluk). @@ -3021,7 +2890,7 @@ tet: label: Relatóriu reporting_location_level: explanation: 'Ida ne''e sei kontrola nivel fatin saida deit maka mosu ba knaar ida ne''e iha painel sira, filtru sira, modal referál sira, no modal transferensia sira. Se kuandu ita husi kampu ne''e mamuk, Knaar ne''e sei haree nivel sistema nia padraun Fatin Relatóriu.' - label: "Tipu fatin ida ne'ebe maka tenke uza ba relatoriu ba knaar ida ne'e?" + label: Tipu fatin ida ne'ebe maka tenke uza ba relatoriu ba knaar ida ne'e? role: actions: assign: @@ -3040,20 +2909,20 @@ tet: explanation: 'Permiti utilizador ida atu halo asaun ba knaar sira ne''ebé disponivel. Permisaun "Jere" esensialmente signifika "Buat hotu-hotu". IMPORTANTE: Ida ne''e mos fó abilidade atu kria no hamoos knaar sira.' label: Jere (Permisaun hotu-hotu ba tipu rekursu ida ne'e) permitted_roles: - explanation: "Se kuandu knaar ida iha abilidade atu halo kualker asaun iha leten iha knaar ida, sira sei bele halo asaun sira ne'e iha asaun espesífiku sira iha lista ida ne'e. Nune'e, pur ezemplu, se kuandu knaar ida iha permisaun \"Lee\" no \"Atribui\" iha knaar sira ne'e, maibe so iha deit \"Servisu Nain Kazu CP\" no \"Jestor CP\" alista hanesan ninia \"Knaar Jere ona\", ne'e so bele haree deit knaar rua ne'e, no so bele atribui utilizador foun sira ba knaar rua ne'e. Se kuandu knaar ne'ebé hanesan laiha \"Knaar Jere Ona\" espesifikadu, ne'e bele haree knaar hotu-hotu no sei bele kria konta ba utilizador foun sira ho kualker knaar iha sistema ne'e." + explanation: Se kuandu knaar ida iha abilidade atu halo kualker asaun iha leten iha knaar ida, sira sei bele halo asaun sira ne'e iha asaun espesífiku sira iha lista ida ne'e. Nune'e, pur ezemplu, se kuandu knaar ida iha permisaun "Lee" no "Atribui" iha knaar sira ne'e, maibe so iha deit "Servisu Nain Kazu CP" no "Jestor CP" alista hanesan ninia "Knaar Jere ona", ne'e so bele haree deit knaar rua ne'e, no so bele atribui utilizador foun sira ba knaar rua ne'e. Se kuandu knaar ne'ebé hanesan laiha "Knaar Jere Ona" espesifikadu, ne'e bele haree knaar hotu-hotu no sei bele kria konta ba utilizador foun sira ho kualker knaar iha sistema ne'e. label: Kna'ar sira seluk ne'ebé jere husi kna'ar ida ne'e read: explanation: Abilidade atu haree kna'ar sira label: Haree write: - explanation: "Abilidade atu hanesan butaun \"Hadi'a\" iha pájina hatudu knaar, atualiza permisaun knaar ninian, no depois salva knaar ne'e." + explanation: Abilidade atu hanesan butaun "Hadi'a" iha pájina hatudu knaar, atualiza permisaun knaar ninian, no depois salva knaar ne'e. label: Hadi'a explanation: Determina asaun saida deit maka utilizador ida bele halo iha Primero. label: Knaar Sira system: actions: manage: - explanation: "Abilidade atu haree no atualiza informasaun iha sistema kontaktu informasaun, notifikasaun padraun no konfigurasaun benvindu email, no servidor sikronizadu sira. Permisaun ida ne'e bai-bain rezervadu ba sistema administrador" + explanation: Abilidade atu haree no atualiza informasaun iha sistema kontaktu informasaun, notifikasaun padraun no konfigurasaun benvindu email, no servidor sikronizadu sira. Permisaun ida ne'e bai-bain rezervadu ba sistema administrador label: Jere (Permisaun hotu-hotu ba tipu rekursu ida ne'e) explanation: Konfigurasaun Diversas ba sistema hotu-hotu. label: Sistema @@ -3069,22 +2938,22 @@ tet: explanation: Abilidade atu dezativa ka ativa Pedidu Buka-Tuir ida. "Dezativadu" Pedidu Buka-Tuir labele mosu tuir padraun iha lista Pedidu Buka-Tuir ne'e. Utilizador sira be'e haree Pedidu Buka-Tuir dezativadu sira iha lista Pedidu Buka-Tuir tuir aplikasaun filtru ida. label: Ativa / Dezativa export_case_pdf: - explanation: "Utilizador bele halo arkivu PDF ida esporta husi lista pedidu buka-tuir sira ka pajina sira hatudu pedidu buka-tuir, ne'ebe kontein kampu sira hotu-hotu iha ne'ebe utilizador atual iha asesu, ba rejistu ida, multiplu, ka rejistu hotu-hotu iha ne'ebe utilizador iha asesu. Iha PDF arkivu esportasaun ne'e, informasaun sira alista dahuluk tuir kazu, no depois organiza tan tuir formulariu iha ne'ebe informasaun mosu ba." + explanation: Utilizador bele halo arkivu PDF ida esporta husi lista pedidu buka-tuir sira ka pajina sira hatudu pedidu buka-tuir, ne'ebe kontein kampu sira hotu-hotu iha ne'ebe utilizador atual iha asesu, ba rejistu ida, multiplu, ka rejistu hotu-hotu iha ne'ebe utilizador iha asesu. Iha PDF arkivu esportasaun ne'e, informasaun sira alista dahuluk tuir kazu, no depois organiza tan tuir formulariu iha ne'ebe informasaun mosu ba. label: Esporta PDF export_csv: - explanation: "Utilizador bele halo arkizu CSV ida esporta husi lista pedidu buka-tuir ka pájina sira hatudu pedidu buka-tuir, ne'ebé kontéin kampu hotu-hotu ne'ebé utilizador atual ne'e iha asesu, ba pedidu buka-tuir ida, multiplu ka pedidu buka-tuir hotu-hotu ne'ebé utilizador ne'e iha asesu." + explanation: Utilizador bele halo arkizu CSV ida esporta husi lista pedidu buka-tuir ka pájina sira hatudu pedidu buka-tuir, ne'ebé kontéin kampu hotu-hotu ne'ebé utilizador atual ne'e iha asesu, ba pedidu buka-tuir ida, multiplu ka pedidu buka-tuir hotu-hotu ne'ebé utilizador ne'e iha asesu. label: Esporta CSV export_custom: - explanation: "Utilizador bele halo arkizu XLS ida esporta husi lista pedidu buka-tuir ka pájina sira hatudu pedidu buka-tuir, ne'ebé kontéin formulariu ka kampu personalizadu, ba pedidu buka-tuir ida, multiplu ka pedidu buka-tuir hotu-hotu ne'ebé utilizador ne'e iha asesu. Iha esportasaun ida ne'e, formulariu ida-idak reprezenta ona iha sira nia tab rasik iha arkizu XLS nia laran. Utilizador bele hili formulariu ka kampu sira ne'ebe sira hakarak atu inklui iha esportasaun uza modal Esportasaun Personalizadu. Favo anota katak utilizador bele inklui dei't formulariu ka kampu sira iha esporta se sira iha ona abilidade atu haree formulariu ka kampu sira ne'e bainhira haree pedidu buka-tuir ida iha aplikasaun." + explanation: Utilizador bele halo arkizu XLS ida esporta husi lista pedidu buka-tuir ka pájina sira hatudu pedidu buka-tuir, ne'ebé kontéin formulariu ka kampu personalizadu, ba pedidu buka-tuir ida, multiplu ka pedidu buka-tuir hotu-hotu ne'ebé utilizador ne'e iha asesu. Iha esportasaun ida ne'e, formulariu ida-idak reprezenta ona iha sira nia tab rasik iha arkizu XLS nia laran. Utilizador bele hili formulariu ka kampu sira ne'ebe sira hakarak atu inklui iha esportasaun uza modal Esportasaun Personalizadu. Favo anota katak utilizador bele inklui dei't formulariu ka kampu sira iha esporta se sira iha ona abilidade atu haree formulariu ka kampu sira ne'e bainhira haree pedidu buka-tuir ida iha aplikasaun. label: Esporta Personalizadu export_json: - explanation: "Utilizador bele kria arkivu JSON ida esporta husi lista pedidu buka-tuir ka pajina sira hatudu pedidu buka-tuir, ne'ebe kontein kampu sira hotu-hotu ne'ebe utilzador atual iha asesu, ba pedidu buka-tuir ida, multiplu, ka pedidu buka-tuir hotu-hotu ne'ebe utilizador iha asesu. Esporta ida ne'e prinsipalmente uza ba sira ne'ebe hakarak atu esporta insidente sira husi sistema Primero atual no depois importa insidente sira ne'e ba sistema Primero ida seluk, ka esporta ba jestaun sistema informasaun sira seluk. Formatu JSON ne'e lezivel husi makina no la pratikal ba maioria utilizador sira seluk." + explanation: Utilizador bele kria arkivu JSON ida esporta husi lista pedidu buka-tuir ka pajina sira hatudu pedidu buka-tuir, ne'ebe kontein kampu sira hotu-hotu ne'ebe utilzador atual iha asesu, ba pedidu buka-tuir ida, multiplu, ka pedidu buka-tuir hotu-hotu ne'ebe utilizador iha asesu. Esporta ida ne'e prinsipalmente uza ba sira ne'ebe hakarak atu esporta insidente sira husi sistema Primero atual no depois importa insidente sira ne'e ba sistema Primero ida seluk, ka esporta ba jestaun sistema informasaun sira seluk. Formatu JSON ne'e lezivel husi makina no la pratikal ba maioria utilizador sira seluk. label: Esporta JSON export_list_view_csv: explanation: Utilizador bele kria arkivu CSV ida husi pajina lista pedidu buka-tuir ne'ebe kontein kampu sira ne'ebe hanesan ne'ebe mosu ba utilizador ida ne'eba iha lista pedidu buka-tuir. Bele halo de'it husi pajina lista pedidu buka-tuir. label: Esporta lista haree CSV export_pdf: - explanation: "Utilizador bele halo arkivu PDF ida esporta husi lista pedidu buka-tuir sira ka pajina sira hatudu pedidu buka-tuir, ne'ebe kontein kampu sira hotu-hotu iha ne'ebe utilizador atual iha asesu, ba rejistu ida, multiplu, ka rejistu hotu-hotu iha ne'ebe utilizador iha asesu. Iha PDF arkivu esportasaun ne'e, informasaun sira alista dahuluk tuir kazu, no depois organiza tan tuir formulariu iha ne'ebe informasaun mosu ba." + explanation: Utilizador bele halo arkivu PDF ida esporta husi lista pedidu buka-tuir sira ka pajina sira hatudu pedidu buka-tuir, ne'ebe kontein kampu sira hotu-hotu iha ne'ebe utilizador atual iha asesu, ba rejistu ida, multiplu, ka rejistu hotu-hotu iha ne'ebe utilizador iha asesu. Iha PDF arkivu esportasaun ne'e, informasaun sira alista dahuluk tuir kazu, no depois organiza tan tuir formulariu iha ne'ebe informasaun mosu ba. label: Esporta PDF export_xls: explanation: 'Utilizador bele halo arkizu XLS ida esporta husi lista pedidu buka-tuir ka pájina sira hatudu pedidu buka-tuir, ne''ebé kontéin kampu hotu-hotu ne''ebé utilizador atual ne''e iha asesu, ba pedidu buka-tuir ida, multiplu ka pedidu buka-tuir hotu-hotu ne''ebé utilizador ne''e iha asesu. Iha esportasaun ida ne''e, formulariu ida-idak reprezenta ninia tab rasik iha arkivu XLS nia laran. NOTA: Formatu XLS la lee karater non-Latina sira (e.g. Arabic, Bangla) iha formatu ne''ebé lezivel, desde esportasaun CSV labele halo.' @@ -3093,29 +2962,29 @@ tet: explanation: Abilidade atu aumenta flag ida ba pedidu buka-tuir ida. Utilizador sira ho permisaun ida ne'e bele mos hasa'i flag sira ne'ebe sira aumenta ona ba pedidu buka-tuir ida. label: Flag import: - explanation: "Permiti utilizador ida atu kria kazu foun ida ka barak liu husi importa sira husi arkivu CSV, Excel ka JSON. Arkivu ne'ebe atu importa tenke iha formatu *very* espesifikamente ba informasuan atu importa ho apropriadu. Funsaun ida ne'e tenke disponivel de'it ba utilizador administrador sira ne'ebe mak iha konesimentu tekniku ne'ebe avansadu no iha konesimentu klean kona-ba oinsa halo formatu ba dadus iha Primero. Bele halo de'it husi pajina lista kazu." + explanation: Permiti utilizador ida atu kria kazu foun ida ka barak liu husi importa sira husi arkivu CSV, Excel ka JSON. Arkivu ne'ebe atu importa tenke iha formatu *very* espesifikamente ba informasuan atu importa ho apropriadu. Funsaun ida ne'e tenke disponivel de'it ba utilizador administrador sira ne'ebe mak iha konesimentu tekniku ne'ebe avansadu no iha konesimentu klean kona-ba oinsa halo formatu ba dadus iha Primero. Bele halo de'it husi pajina lista kazu. label: Importa manage: - explanation: "Permiti utilizador ida atu halo asaun sira ne'ebé disponivel iha pedidu buka-tuir sira. Permisaun \"Jere\" esensialmente signifika \"Buat hotu-hotu\". " + explanation: 'Permiti utilizador ida atu halo asaun sira ne''ebé disponivel iha pedidu buka-tuir sira. Permisaun "Jere" esensialmente signifika "Buat hotu-hotu". ' label: Jere (Permisaun hotu-hotu ba tipu rekursu ida ne'e) read: explanation: Abilidade atu haree pedidu buka-tuir ida. Knaar sira ho abilidade atu haree pedidu buka-tuir sira tenke iha mos abilidade atu haree tipu rejistu Korespondente Potensial. label: Haree write: - explanation: "Abilidade atu hanehan butaun \"Hadi'a\", atualiza informasaun kona-ba pedidu buka-tuir, no hanehan \"Salva\". No mos permiti utilizador ne'e atu dezativa ka ativa pedidu buka-tuir ida." + explanation: Abilidade atu hanehan butaun "Hadi'a", atualiza informasaun kona-ba pedidu buka-tuir, no hanehan "Salva". No mos permiti utilizador ne'e atu dezativa ka ativa pedidu buka-tuir ida. label: Hadi'a explanation: Reprezenta individual koko atu aloka no reunifika ho kazu ne'ebé laiha akompañamentu ka separadu. label: Pedidu Buka-Tuir transfer: actions: transfer: - explanation: "Ida ne'e signifika knaar ne'e sei mosu hanesan opsaun ida ba \"Tipu Benefisiariu\" bainhira utilizador ne'e halo referál esternal ida. Se kuandu utilizador ne'e hili knaar ne'e hanesan tipu referál, esportasaun ne'ebé Primero halo bainhira utilizador ne'e submete referál sei kontein deit informasaun ne'ebé hetan iha formuláriu knaar ne'e asesu ba. Nune'e, pur ezemplu, se kuandu utilizador ne'e hili \"Fornesedor Servisu Médiku\" hanesan tipu benefisiariu, no knaar Fornesedor Servisu Médiku iha deit asesu ba Identidade Báziku no formuláriu Prekupasaun ba Protesaun, arkivu esportasaun ne'ebé Primero esporta ba referál esternal sei kontein deit kampu sira ne'ebé iha formuláriu rua ne'e. " - label: "Bele utiliza knaar ne'e ba transferensia esternal sira?" + explanation: 'Ida ne''e signifika knaar ne''e sei mosu hanesan opsaun ida ba "Tipu Benefisiariu" bainhira utilizador ne''e halo referál esternal ida. Se kuandu utilizador ne''e hili knaar ne''e hanesan tipu referál, esportasaun ne''ebé Primero halo bainhira utilizador ne''e submete referál sei kontein deit informasaun ne''ebé hetan iha formuláriu knaar ne''e asesu ba. Nune''e, pur ezemplu, se kuandu utilizador ne''e hili "Fornesedor Servisu Médiku" hanesan tipu benefisiariu, no knaar Fornesedor Servisu Médiku iha deit asesu ba Identidade Báziku no formuláriu Prekupasaun ba Protesaun, arkivu esportasaun ne''ebé Primero esporta ba referál esternal sei kontein deit kampu sira ne''ebé iha formuláriu rua ne''e. ' + label: Bele utiliza knaar ne'e ba transferensia esternal sira? label: Transfere user: actions: agency_read: - explanation: "Abilidade atu haree deit konta utilizador sira ne'ebé iha utilizador ninia ajénsia atual. Ida ne'e mos afeta konta utilizador sira ne'ebé deit mak utilizador atual bele halo asaun seluk ba. Pur ezemplu, se kuandu utilizador atual iha permisaun \"Hareker\" iha utilizador sira, maibe mos iha permisaun Lee Ajénsia, sira sei bele deit hadi'a konta utilizador sira ne'ebé iha sira nia ajénsia rasik. Hanesan mos, se kuandu utilizador atual iha permisaun \"Jere\" iha utilizador sira, maibe iha mos permisaun \"Lee Ajénsia\", sira sei bele deit kria utilizador sira ba sira nia ajénsia rasik." + explanation: Abilidade atu haree deit konta utilizador sira ne'ebé iha utilizador ninia ajénsia atual. Ida ne'e mos afeta konta utilizador sira ne'ebé deit mak utilizador atual bele halo asaun seluk ba. Pur ezemplu, se kuandu utilizador atual iha permisaun "Hareker" iha utilizador sira, maibe mos iha permisaun Lee Ajénsia, sira sei bele deit hadi'a konta utilizador sira ne'ebé iha sira nia ajénsia rasik. Hanesan mos, se kuandu utilizador atual iha permisaun "Jere" iha utilizador sira, maibe iha mos permisaun "Lee Ajénsia", sira sei bele deit kria utilizador sira ba sira nia ajénsia rasik. label: Haree (Iha Ajénsia nia Laran) create: explanation: Abilidade atu kria konta utilizador ida. @@ -3124,17 +2993,17 @@ tet: explanation: 'Permiti utilizador ida atu halo asaun sira ne''ebé disponivel iha utilizador sira. Permisaun "Jere" esensialmente signifika "Buat hotu-hotu". IMPORTANTE: Ida ne''e mos fó abilidade atu kria konta utilizador foun.' label: Jere (Permisaun hotu-hotu ba tipu rekursu ida ne'e) read: - explanation: "Abilidade atu haree konta utilizador sira. Tuir padraun, kada utilizador iha abilidade atu haree no hadi'a informasaun kona-ba sira nia konta utilizador rasik (e.z. seña, email)." + explanation: Abilidade atu haree konta utilizador sira. Tuir padraun, kada utilizador iha abilidade atu haree no hadi'a informasaun kona-ba sira nia konta utilizador rasik (e.z. seña, email). label: Haree write: - explanation: "Abilidade atu hanehan butaun \"Hadi'a\" iha pájina hatudu utilizador, atualiza informasaun kona-ba utilizador ne'e, no depois salva. Favór anota katak permisaun ida ne'e fó abilidade atu dezativca konta utilizador sira." + explanation: Abilidade atu hanehan butaun "Hadi'a" iha pájina hatudu utilizador, atualiza informasaun kona-ba utilizador ne'e, no depois salva. Favór anota katak permisaun ida ne'e fó abilidade atu dezativca konta utilizador sira. label: Hadi'a explanation: Reprezenta konta Utilizador individual label: Utilizador sira user_group: actions: assign: - explanation: "Abilidade atu hili grupu utilizador sira bainhira kria ka hadi'a hela konta utilizador ida. Favór anota katak se kuandu utilizador atual iha nivel asesu \"rejistu deit ka utilizador sira iha ha'u-nia grupu\", sira so bele hili ida ka liu husi ida husi *sira nia* grupu utilizador sira ba konta utilizador ne'ebé sira kria ka hadi'a hela. Ida ne'e signifika katak jestor ida ho abilidade atu atribui grupu utilizador sira sei bele aumenta deit utilizador ida ba grupu utilizador sira ne'ebé jestor ne'e atualmente hola parte ba. Permisaun ida ne'e nesesáriu ba kualker knaar ne'ebé sei kria ka hadi'a konta utilizador sira." + explanation: Abilidade atu hili grupu utilizador sira bainhira kria ka hadi'a hela konta utilizador ida. Favór anota katak se kuandu utilizador atual iha nivel asesu "rejistu deit ka utilizador sira iha ha'u-nia grupu", sira so bele hili ida ka liu husi ida husi *sira nia* grupu utilizador sira ba konta utilizador ne'ebé sira kria ka hadi'a hela. Ida ne'e signifika katak jestor ida ho abilidade atu atribui grupu utilizador sira sei bele aumenta deit utilizador ida ba grupu utilizador sira ne'ebé jestor ne'e atualmente hola parte ba. Permisaun ida ne'e nesesáriu ba kualker knaar ne'ebé sei kria ka hadi'a konta utilizador sira. label: Atribui create: explanation: Abilidade atu kria grupu utilizador ida. @@ -3169,7 +3038,6 @@ tet: label: Hamoos manage: label: Jere (Permisaun hotu-hotu ba tipu rekursu ida ne'e) - explanation: activity_log: actions: transfer: @@ -3177,14 +3045,13 @@ tet: label: Transfere manage: label: Jere (Permisaun hotu-hotu ba tipu rekursu ida ne'e) - explanation: label: Rejistu Atividade potential_match: - case_id: "ID Kazu " + case_id: 'ID Kazu ' child_age: Tinan child_gender: Jéneru - child_id: "#id labarik" - inquirer_id: "#id inkiridor" + child_id: '#id labarik' + inquirer_id: '#id inkiridor' inquirer_tr_name: Pedidu Buka-Tuir inquiry_date: Data Inkéritu name: Naran @@ -3196,10 +3063,9 @@ tet: likelihood_likely: Provavel likelihood_possible: Posivel potential_matches: - display: "Hatudu hela korespondensia potensial ba %{type}%{id}" + display: Hatudu hela korespondensia potensial ba %{type} %{id} reassign: - multiple_error: "Erru ida akontese ona. Kazu %{select_records}seidauk atribui." - multiple_successfully: "" + multiple_error: Erru ida akontese ona. Kazu %{select_records} seidauk atribui. notes_label: Notas successfully: Atribui ona filafali ho susesu user_mandatory_label: Presiza benefisiariu @@ -3226,16 +3092,16 @@ tet: type_of_recipient: Tipu husi Benefisiáriu type_of_referral_required: Presiza Tipu Referal agency_label: Ajénsia - is_remote_label: "Ita halo hela refere ba sistema ida iha remota?" + is_remote_label: Ita halo hela refere ba sistema ida iha remota? location_label: Fatin notes_label: Notas notes_on_referral: Notas iha referál note_on_referral_from_provider: Notas iha referál husi fornesedor provided_consent_label: Konsentimentu la fornese iha Formuláriu sira. recipient_label: Benefisiáriu - refer_anyway_label: "Refere nafatin?" + refer_anyway_label: Refere nafatin? service_label: Servisu - success: '%{record_type}%{id} refere ona ho susesu' + success: '%{record_type} %{id} refere ona ho susesu' user_mandatory_label: Presiza benefisiariu date: Data rejected_reason: Razaun Rejeisaun @@ -3247,12 +3113,12 @@ tet: date: Loron month: Fulan quarter: Trimestre - quarter_abbr: "Q%{quarter}" + quarter_abbr: Q%{quarter} week: Semana year: Tinan description: Deskrisaun disabled: - explanation: "Se kuandu ita dezativca Relatóriu ne'e, nia sei la mosu iha relatóriu disponivel sira." + explanation: Se kuandu ita dezativca Relatóriu ne'e, nia sei la mosu iha relatóriu disponivel sira. label: Dezativadu exclude_empty_rows: Labele hatudu lina mamuk sira disaggregate_by: Grupu tuir koluna @@ -3261,7 +3127,7 @@ tet: label_new: Filtru relatóriu foun attribute: Filtru value: Ho - not_null: "La'os mamuk?" + not_null: La'os mamuk? less_than: Menus husi greater_than: Bo'ot liu husi equal_to: Hanesan ho @@ -3269,10 +3135,10 @@ tet: is: maka before: Molok after: Depois - delete_filter_message: "Ita iha serteza ita hakarak hamoos filtru ne'e?" + delete_filter_message: Ita iha serteza ita hakarak hamoos filtru ne'e? group_ages: Uza faixa tinan group_dates_by: Uza faixa data - is_graph: "Kria grafiku ida?" + is_graph: Kria grafiku ida? messages: delete_success: Relatóriu hamoos ona ho susesu. success: Relatóriu kria ona ho susesu. @@ -3289,7 +3155,7 @@ tet: incomplete_data: Dadus Inkompleta reports: delete_report: Hamoos Relatóriu - delete_report_message: "Ita iha serteza ita hakarak hamoos relatoriu ida ne'e? Hamoos ona sei labele asesu tan. Hanehan OK atu Hamoos relatoriu." + delete_report_message: Ita iha serteza ita hakarak hamoos relatoriu ida ne'e? Hamoos ona sei labele asesu tan. Hanehan OK atu Hamoos relatoriu. label: Relatóriu sira register_new_report: Kria Relatóriu translations: @@ -3310,20 +3176,20 @@ tet: description: Deskrisaun edit: Hadi'a Knaar error_in_updating: Erru bainhira atualiza hela detallu Knaar. - group_permission_label: "Rejistu saida de'it mak knaar ne'e afeta?" + group_permission_label: Rejistu saida de'it mak knaar ne'e afeta? label: Knaar manager: Jestor messages: - confirmation: "Ita iha serteza ita hakarak hamoos knaar ida ne'e? Hamoos ona sei labele asesu tan. Hanehan OK atu Hamoos knaar." + confirmation: Ita iha serteza ita hakarak hamoos knaar ida ne'e? Hamoos ona sei labele asesu tan. Hanehan OK atu Hamoos knaar. created: Knaar kria ona ho susesu. deleted: Knaar hamoos ona ho susesu. updated: Knaar atualiza ona ho susesu. name: Naran - referral_label: "Bele utiliza knaar ne'e ba Referal sira?" - reporting_location_level_label: "Tipu fatin ida ne'ebe maka tenke uza ba relatoriu ba knaar ida ne'e?" + referral_label: Bele utiliza knaar ne'e ba Referal sira? + reporting_location_level_label: Tipu fatin ida ne'ebe maka tenke uza ba relatoriu ba knaar ida ne'e? role_ids_label: Knaar sira seluk ne'ebé jere husi knaar ida ne'e successfully_updated: Detallu Knaar atualiza ona ho susesu. - transfer_label: "Bele utiliza knaar ne'e ba Transferensia sira?" + transfer_label: Bele utiliza knaar ne'e ba Transferensia sira? hide: Subar read: Hatudu read_write: Hatudu no Hadi'a @@ -3335,7 +3201,7 @@ tet: no_filters: Seidauk hili filtru ida save_success: Peskiza salva ona ho susesu saved_searches_tab: Salva Peskiza Sira - title_description: "Ita iha serteza ita hakarak hamoos peskiza sira ne'ebé salva ona?" + title_description: Ita iha serteza ita hakarak hamoos peskiza sira ne'ebé salva ona? title_modal: Hamoos peskiza sira ne'ebé salva ona saved_searches: no_save_searches: Ita laiha peskiza ne'ebé salva ona @@ -3358,7 +3224,7 @@ tet: label: Sistema Konfigurasaun task: due_date: Data Devidu - id: "#ID" + id: '#ID' name: Naran priorities: high_level: Aas @@ -3374,8 +3240,8 @@ tet: types: assessment: Avaliasaun case_plan: Planu Kazu - follow_up: "Follow Up - %{subtype}" - service: "Servisu - %{subtype}" + follow_up: Follow Up - %{subtype} + service: Servisu - %{subtype} tracing_request: label: Pedidu Buka-Tuir has_match: Iha Korespondensia @@ -3395,15 +3261,15 @@ tet: already_matched: Iha ona korespondensia ida iha sistema ho Inkiridor ida ne'ebé buka labarik ida ne'e. disabled: Pedidu Buka-Tuir Dezativadu nothing_found: La hetan buat ida - update_success: 'Pedidu Buka-Tuir %{record_id}atualiza ona ho susesu.' + update_success: 'Pedidu Buka-Tuir %{record_id} atualiza ona ho susesu.' creation_success: Grava Pedidu Buka-Tuir atualiza ona ho susesu. - update_success_queue: 'Pedidu Buka-Tuir %{record_id}atualiza ona ho susesu iha background.' + update_success_queue: 'Pedidu Buka-Tuir %{record_id} atualiza ona ho susesu iha background.' creation_success_queue: Grava Pedidu Buka-Tuir kria ona ho susesu iha background. - match_action: "Susesu ona koresponde Buka-Tuir %{trace_id}ho kazu %{record_id}." - unmatch_action: "Susesu ona la-koresponde Buka-Tuir %{trace_id}ho kazu %{record_id}." + match_action: Susesu ona koresponde Buka-Tuir %{trace_id} ho kazu %{record_id}. + unmatch_action: Susesu ona la-koresponde Buka-Tuir %{trace_id} ho kazu %{record_id}. registry_record: messages: - update_success: 'Grava Rejistrasaun %{record_id}atualiza ona ho susesu.' + update_success: 'Grava Rejistrasaun %{record_id} atualiza ona ho susesu.' creation_success: 'Grava Rejistrasaun kria ona ho susesu.' disabled: Grava Rejistrasaun dezativa ona tracing_requests: @@ -3460,7 +3326,7 @@ tet: export: Esporta mark_for_offline: title: Marka ba Offline - text: "Ita iha serteza ita hakarak marka rejistu rejistrasaun hirak-ne'e hodi uza bainhira ita offline?" + text: Ita iha serteza ita hakarak marka rejistu rejistrasaun hirak-ne'e hodi uza bainhira ita offline? success: Rejistu rejistrasaun marka ona ho susesu ba uza offline families: id: ID @@ -3474,13 +3340,9 @@ tet: register_new_family: Família Foun show_family: 'ID Família %{short_id}' disable_dialog_title: Dezativa Família - disable_dialog: "" - selected_records: '' - selected_all_records: '' mark_for_offline: title: Marka ba Offline - text: "Ita iha serteza ita hakarak marka rejistu família hirak-ne'e hodi uza bainhira ita offline?" - success: "" + text: Ita iha serteza ita hakarak marka rejistu família hirak-ne'e hodi uza bainhira ita offline? filter_by: by_date: Tuir Data status: Status @@ -3494,24 +3356,24 @@ tet: back_to_family_members: Filafali ba Membru Família create: Kria messages: - update_success: 'Família %{record_id}atualiza ona ho susesu.' + update_success: 'Família %{record_id} atualiza ona ho susesu.' creation_success: 'Família kria ona ho susesu.' disabled: Família dezativadu - confirm_create_case: "Ita hakarak atu kria kazu ida ba indivídu ida ne'e?" + confirm_create_case: Ita hakarak atu kria kazu ida ba indivídu ida ne'e? transfer: label: Transfere agency_label: Ajénsia - consent_from_individual_label: "Ita iha ona konsentimentu husi individual ne'e atu halo transferensia ka lae?" + consent_from_individual_label: Ita iha ona konsentimentu husi individual ne'e atu halo transferensia ka lae? consent_label: Rejistu sira seidauk fornese konsentimentu. - consent_override_label: "Ita hakarak atu ultrapasa konfigurasaun ida ne'e?" - is_remote_label: "Ita halo hela transferensia ba sistema ida iha remota?" + consent_override_label: Ita hakarak atu ultrapasa konfigurasaun ida ne'e? + is_remote_label: Ita halo hela transferensia ba sistema ida iha remota? location_label: Fatin notes_label: Notas provided_consent_label: Konsentimentu la fornese iha Formuláriu sira. recipient_label: Benefisiáriu select_label: Hili... success: Transfere ona ho susesu - transfer_label: "Transfere nafatin?" + transfer_label: Transfere nafatin? user_mandatory: Presiza benefisiariu rejected_reason: Razaun Rejeisaun transfer_assignment: @@ -3528,8 +3390,8 @@ tet: errors: consent: La fornese konsentimentu to_user_can_receive: Utilizador ida ne'e labele simu rejistu ida ne'e - individual_consent: "Servisu nain kazu iha ona konsentimentu husi individual ne'e atu halo transferensia ka lae?" - no_consent_share: "Konsentimetu atu fahe konfigurasaun substitui ona?" + individual_consent: Servisu nain kazu iha ona konsentimentu husi individual ne'e atu halo transferensia ka lae? + no_consent_share: Konsentimetu atu fahe konfigurasaun substitui ona? notes: Notas recipient: Benefisiáriu rejected: Razaun Rejeitadu @@ -3563,12 +3425,11 @@ tet: locale: Lokalidade location: Fatin messages: - records_update: "" - confirmation: "Ita iha serteza ita hakarak hamoos utilizador ida ne'e? Hamoos ona sei labele asesu tan. Hanehan OK atu Hamoos Utilizador." + confirmation: Ita iha serteza ita hakarak hamoos utilizador ida ne'e? Hamoos ona sei labele asesu tan. Hanehan OK atu Hamoos Utilizador. created: Utilizador kria ona ho susesu. - failure: "Akontese erru ida, favór kontaktu apoiu." - new_confirm_html: "Oras ne'e daudaun ita atu konvida utilzador %{username} husi %{identity} ho knaar %{role} atu uza Primero. Sei manda konfirmasaun husi email ba %{email}. Ita hakarak atu kontinua?" - new_confirm_non_identity_html: "Oras ne'e daudaun ita atu konvida utilzador %{username} ho knaar %{role} atu uza Primero. Sei manda konfirmasaun husi email ba %{email}. Ita hakarak atu kontinua?" + failure: Akontese erru ida, favór kontaktu apoiu. + new_confirm_html: Oras ne'e daudaun ita atu konvida utilzador %{username} husi %{identity} ho knaar %{role} atu uza Primero. Sei manda konfirmasaun husi email ba %{email}. Ita hakarak atu kontinua? + new_confirm_non_identity_html: Oras ne'e daudaun ita atu konvida utilzador %{username} ho knaar %{role} atu uza Primero. Sei manda konfirmasaun husi email ba %{email}. Ita hakarak atu kontinua? not_found: Utilizador ho id ne'e la eziste password_changed_successfully: Seña troka ona ho susesu passwords_do_not_match: La koresponde ho seña atual @@ -3576,14 +3437,14 @@ tet: updated: Utilizador atualiza ona ho susesu. organization: Organizasaun agency: Ajénsia - services_help_text: "se ita la espesifika servisu, Utilizador ida ne'e sei hetan servisu hanesan servisu ne'ebé ninia Ajénsia iha. " + services_help_text: 'se ita la espesifika servisu, Utilizador ida ne''e sei hetan servisu hanesan servisu ne''ebé ninia Ajénsia iha. ' password_setting: - label: "Oinsa mak Primero tenke estabelese utilizador nia seña?" + label: Oinsa mak Primero tenke estabelese utilizador nia seña? self: Ha'u sei estabele seña user: Utilizador sei estabelese seña uza email benvindu - help_text: "Favór hanoin katak se ita, nu'udar administrador, estabelese seña manualmente, ita sei presiza atu fahe seña ne'e ho utilizador ho maneira ne'ebé seguru." + help_text: Favór hanoin katak se ita, nu'udar administrador, estabelese seña manualmente, ita sei presiza atu fahe seña ne'e ho utilizador ho maneira ne'ebé seguru. password_reset_header: Manda seña reestabele email - password_reset_text: "Se ita hanehan 'Manda,' utilizador ida ne'e sei simu email ida ho link ida atu reestabelese sira nia seña" + password_reset_text: Se ita hanehan 'Manda,' utilizador ida ne'e sei simu email ida ho link ida atu reestabelese sira nia seña password_reset_request: Manda seña reestabele email password: Seña password_confirmation: Konfirmasaun Seña @@ -3591,18 +3452,14 @@ tet: position: Pozisaun provider_username_help: 'Ezemplu: my.username@%{domain}' role_id: Knaar - send_mail: "Simu notifikasaun husi email?" - receive_webpush: - label: "" - help_text: "" - tooltip: "" + send_mail: Simu notifikasaun husi email? user_group_unique_ids: Grupu Utilizador user_name: Naran Utilizador services: Servisu sira welcome_email: subject: 'Benvindu mai %{system}!' greeting: 'Benvindu mai %{system}!' - body_native: 'Aumenta ona ita hanesan %{role_name}. Favór kontaktu %{admin_full_name}(%{admin_email}) ba instrusaun tuir mai atu hahu servisu ho%{host}.' + body_native: 'Aumenta ona ita hanesan %{role_name}. Favór kontaktu %{admin_full_name}(%{admin_email}) ba instrusaun tuir mai atu hahu servisu ho %{host}.' sso: body: 'Aumenta ona ita hanesan %{role_name}.' step1: 'Ba iha %{host} no hanehan %{identity_provider}.' @@ -3616,13 +3473,13 @@ tet: step3: 'Login ho ita nia naran utilizador no seña temporaria %{otp}' step4: 'Wainhira fó-hanoin, reestabelese ita nia seña.' url_label: Primero - enabled_label: "Manda Email Benvindu?" + enabled_label: Manda Email Benvindu? text_label: Testu Email Benvindu password_reset: subject: 'Instrusaun sira ba reestabelese seña' email_greeting: "Karu %{full_name}," email_body1: "Ema ida halo ona pedidu atu estabelese ita nia seña ba %{host_href}. Hanehan url iha kraik atu hahu:" - email_body2: "Link ida ne'e sei espira iha oras %{hours}no sei bele uza de'it dala ida. Favór ignora email ida ne'e se ita lahalo pedidu ba reestabelese seña ka Utilizador Primero foun ida la'os rejistu ba ita. Se link iha leten ne'e espira, favór hanehan %{reset_request_href}atu submete filafali pedidu reestabelese seña." + email_body2: "Link ida ne'e sei espira iha oras %{hours} no sei bele uza de'it dala ida. Favór ignora email ida ne'e se ita lahalo pedidu ba reestabelese seña ka Utilizador Primero foun ida la'os rejistu ba ita. Se link iha leten ne'e espira, favór hanehan %{reset_request_href} atu submete filafali pedidu reestabelese seña." email_body_link: iha ne'e request_submitted: "Pedidu reestabelese seña submete ona" success: "Seña muda ona ho susesu" @@ -3640,7 +3497,7 @@ tet: associated_agencies: Ajénsia sira asosiadu ho Grupu Utilizador ida ne'e description: Deskrisaun disabled: - explanation: "Se ita dezativa Grupu Utilizador ida ne'e, ita sei labele ona atu atribui ne'e ba konta Utilizador sira." + explanation: Se ita dezativa Grupu Utilizador ida ne'e, ita sei labele ona atu atribui ne'e ba konta Utilizador sira. label: Dezativadu messages: created: Grupu Utilizador kria ona ho susesu. @@ -3658,19 +3515,13 @@ tet: devise: failure: already_authenticated: "Ita sign in ona" - invalid: "%{authentication_keys}ka seña inválidu " + invalid: "%{authentication_keys} ka seña inválidu " locked: "Ita nia konta blokeadu ona." last_attempt: "Ita iha tan tentativa ida molok ita nia konta blokeadu." admin: locations: selected_records: 'Hili ona fatin %{select_records}' - selected_all_records: "Hili hotu %{total_records}kazu sira ne'ebé koresponde ho pergunta ne'e." + selected_all_records: Hili hotu %{total_records} kazu sira ne'ebé koresponde ho pergunta ne'e. updated: 'Atualiza ona fatin %{updated_records}' push_notifications_dialog: title: Notifikasaun Instrumentu - body_blocked: - message: "" - android: "" - ios: "" - body: - other: '' diff --git a/config/locales/th.yml b/config/locales/th.yml index 88eeeae06d..2ef9fe3870 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -14,7 +14,6 @@ th: unavailable_offline: ไม่สามารถใช้ได้ในการทำงานแบบปิดการเชื่อมต่อ (โหมดออฟไลน์) online: การทำงานแบบเชื่อมต่อ (โหมดออนไลน์) yes_label: 'ใช่' - or_label: หรือ select_provider: เลือกผู้ให้บริการ select_language: เลือกภาษา log_in_primero_idp: เข้าสู่ระบบด้วยบัญชีชื่อ %{idp_name} @@ -1012,7 +1011,6 @@ th: english_text: ตัวอักษรภาษาอังกฤษ field_name: ชื่อช่องกรอกข้อมูล field_type: ประเภทของช่องกรอกข้อมูล - attachment_too_large: ไฟล์ไม่ควรมีขนาดใหญ่กว่า 10mb file_upload_box: add_document_label: เพิ่มเอกสาร add_new_document_button_text: เพิ่มเอกสารอื่น @@ -2047,7 +2045,6 @@ th: explanation: ผู้จัดการสามารถเห็นว่า ผู้ดูแลรายกรณีในทีมแต่ละท่านมีเคสที่เลยกำหนดเวลาที่ระบุไว้สำหรับการจัดบริการ จำนวนกี่เคส label: งานจัดบริการที่เลยเวลาที่กำหนด dash_case_incident_overview: - explanation: . label: ภาพรวม เคส/การแจ้งเหตุในการดูแลของฉัน dash_cases_by_social_worker: explanation: 'ตารางแสดงจํานวนเคสทั้งหมดที่อยู่ในสถานะเปิดและจํานวนเคสใหม่ที่อยู่ในความรับผิดชอบของผู้ปฏิบัติงานในทีมแต่ละท่าน แต่ละแถวจะแสดงรายชื่อผู้ปฏิบัติงาน ในขณะที่ข้อมูลในคอลัมน์จะแสดงจำนวนเคส "ทั้งหมด" และ เคส "ใหม่" ' @@ -2410,7 +2407,6 @@ th: display: แสดงการจับคู่ที่อาจตรงกันสำหรับ %{type}%{id} reassign: multiple_error: 'เกิดข้อผิดพลาด ยังไม่มีการมอบหมายเคส%{select_records} ' - multiple_successfully: 'ได้มอบหมายผู้ดูแลให้แก่เคสจำนวน %{select_records} เคสแล้ว' notes_label: บันทึกข้อความ successfully: มอบหมายงานสำเร็จแล้ว user_mandatory_label: ต้องมีการระบุผู้รับ diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 9d2a6b5306..abea2d105d 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -15,7 +15,6 @@ uk: unavailable_offline: Недоступно в автономному режимі online: Онлайн yes_label: 'Так' - or_label: або select_provider: Вибрати надавача select_language: Вибрати мову log_in_primero_idp: увійти під іменем %{idp_name} @@ -281,7 +280,7 @@ uk: text: Ви впевнені, що хочете позначити ці кейси для використання в автономному режимі? success: Кейси успішно позначені для використання поза мережею filter_by: - 3month_inactivity: На 3+ місяці + 3month_inactivity: Більше 3+ місяців action_plan: План дій age_0_5: 0 - 5 age_12_17: 12 - 17 @@ -330,7 +329,7 @@ uk: registration_date: Дата реєстрації risk_level: Рівень ризику sex: Стать - social_worker: Поле/кейс/соціальний працівник + social_worker: Сфера/кейс/соціальний працівник status: Статус transferred: Переслано type_of_risk: Тип ризику @@ -493,7 +492,7 @@ uk: phone: Телефон position: Позиція primero_version: Primero версія - support_forum: Форуи підтримки + support_forum: Форма підтримки system_version: Версія системи info_label: Контактна інформація updated: Контактна інформація була успішно оновлена. @@ -706,7 +705,7 @@ uk: number_of_violations: Кількість порушень number_of_violations_verified: Порушення підтверджені open: Відкрити - open_cases: Відкрити кейси + open_cases: Відкриті кейси open_incidents: Відкрити інциденти outstanding_transfers: Незакриті трансфери overdue_activities: Протерміновані заходи @@ -741,8 +740,8 @@ uk: shared_from_my_team_rejected_transfers: Відхилені трансфери shared_with_me_new_referrals: Нові направлення shared_with_me_total_referrals: Загальні направлення - shared_with_me_transfers_awaiting_acceptance: Трансфери, які очікують прийняття - shared_with_my_team_pending_transfers_overview: Трансфери, які очікують прийняття + shared_with_me_transfers_awaiting_acceptance: Переведення, які очікують прийняття + shared_with_my_team_pending_transfers_overview: Переведення, які очікують прийняття shared_with_my_team_pending_transfers: Очікують переведення shared_with_my_team_referrals: Направлення shared_with_others_pending_transfers: Очікують переведення @@ -754,7 +753,7 @@ uk: total_cases: Загальні кейси total_referred: Загальна кількість направлень tr_stats: Запити на відстеження - transers_awaiting_acceptance: Трансфери, які очікують прийняття + transers_awaiting_acceptance: Переведення, які очікують прийняття transfers_by_social_worker: Переведення соціального працівника users: Іконка налаштувань violence_type: Тип насильства @@ -1114,7 +1113,6 @@ uk: english_text: Текст англійською мовою field_name: Назва поля field_type: Тип Поля - attachment_too_large: Розмір файлу не повинен перевищувати 10 Мб file_upload_box: add_document_label: Додати документ add_new_document_button_text: Додати інший документ @@ -1298,7 +1296,6 @@ uk: dashboard: Панель en: English es: Español - es-GT: Español (Guatemala) fr: Français id: Bahasa km: ភាសាខ្មែរ @@ -1340,7 +1337,6 @@ uk: killing: Вбивство дітей maiming: Покалічення дітей recruitment: Вербування та/або використання дітей - sexual_violence: Зґвалтування та/або інші форми сексуального насильства abduction: Викрадення attack_on: Напади на школу(и) та/або лікарню(і) military_use: Військове використання школи(іл) та/або госпіталю(ів) @@ -1369,7 +1365,6 @@ uk: unknown: Невідомо verification_status: Статус підтвердження violence_type: Тип насильства - armed_force_group_name: Назва групи Збройних Сил armed_force_group_type: Тип групи Збройних Сил register_new_incident: Новий інцидент selectable_date_options: @@ -1799,9 +1794,7 @@ uk: killing: Вбивство дітей maiming: Покалічення дітей recruitment: Вербування та/або використання дітей - sexual_violence: Зґвалтування та/або інші форми сексуального насильства abduction: Викрадення - attack_on: Напади на школу(и) та/або лікарню(і) military_use: Військове використання школи(іл) та/або госпіталю(ів) denial_humanitarian_access: Відмова у гуманітарному доступі для дітей sub_reports: @@ -1821,22 +1814,7 @@ uk: date_of_first_report: Дата інтерв'ю incident_date: Дата інциденту reports: - incidents: Інциденти perpetrators: Зловмисники - sub_reports: - combined: Інциденти - total: Кількість зареєстрованих інцидентів ГЗН - gbv_sexual_violence: Кількість повідомлень про випадки сексуального насильства - gbv_previous_incidents: Кількість інцидентів, про які повідомили постраждалі з попередніми інцидентами ГЗН - gbv_sexual_violence_type: Тип інциденту - incident_timeofday: Час інциденту - elapsed_reporting_time: Час між датою інциденту та датою повідомлення - elapsed_reporting_time_rape: Випадки зґвалтування, час, що минув між інцидентом та датою повідомлення - incident_location_type: Місце події - number_of_perpetrators: Кількість основних винних - perpetrator_relationship: Відносини підозрюваного та постраждалого - perpetrator_age_group: Вікова група підозрюваного - perpetrator_occupation: Професія підозрюваного messages: alert_items: У вас є %{items} важливі речі. alerts_for: @@ -1861,7 +1839,7 @@ uk: column_header_tooltip: Сортувати за %{column} of: з no_match: На жаль, відповідних записів не знайдено - rows_per_page: Рядків на сторінку + rows_per_page: Рядків на сторінці sort: Сортувати navigation: bulk_exports: Експорти @@ -1880,6 +1858,7 @@ uk: code_of_conduct: Норми поведінки terms_of_use: Умови використання system_information: Системна інформація + resync: Неотправленные изменения в автономном режиме tasks: Задачі tracing_request: Запит на відстеження activity_log: Журнал активності @@ -2347,7 +2326,6 @@ uk: explanation: Дозволяє менеджеру побачити, скільки справ мають прострочені завдання з послуг для кожного з його співробітників. label: Прострочені завдання з послуг dash_case_incident_overview: - explanation: . label: Огляд - Мої кейси / інциденти dash_cases_by_social_worker: explanation: Таблиця, яка показує, як загальна кількість відкритих справ і кількість нових справ, якими керує кожен користувач у групах користувачів поточного користувача. Кожен рядок є користувачем у групах користувачів поточного користувача, тоді як "Усього" і "Новий" - це два стовпці. @@ -2594,6 +2572,10 @@ uk: label: Позначити для режиму поза мережею explanation: Це може представляти особу чи установу, яку необхідно пов’язати з іншими записами, як-от випадки чи інциденти, є дуже численними та постійно оновлюються новою інформацією. Вони схожі на пошукові запити, але мають більш складний набір інформації для кожного запису. label: Запис реєстру + family: + actions: + change_log: + label: Журнал змін report: actions: create: @@ -2791,7 +2773,6 @@ uk: display: Відображення потенційних збігів для %{type} %{id} reassign: multiple_error: Виникла помилка. %{select_records}кейс(и) не призначено. - multiple_successfully: '%{select_records} кейс(и) успішно призначено' notes_label: Нотатки successfully: Успішно перепризначено user_mandatory_label: Отримувач обов`язковий @@ -2805,7 +2786,7 @@ uk: module_id: Модуль owned_by: Код кейс-працівника owned_by_agency_id: Агенція - owned_by_text: Польови/кейс/соціальний працівник + owned_by_text: Сфера/кейс/соціальний працівник previously_owned_by: Попередній власник previously_owned_by_agency: Попередня агенція reassigned_tranferred_on: Перепризначено / передано @@ -3046,6 +3027,9 @@ uk: title: Позначити для режиму поза мережею text: Ви впевнені, що хочете позначити ці записи реєстру для використання в автономному режимі? success: Записи реєстру успішно позначено для використання поза мережею + family: + family_member: + save_and_return: Додати та повернутись transfer: label: Трансфер agency_label: Агенція @@ -3139,6 +3123,11 @@ uk: provider_username_help: 'Приклад: my.username@%{domain}' role_id: Роль send_mail: Отримувати сповіщення електронною поштою? + notification_preferences: + approval_request: 'Запит на ухвалення (супервізори)' + approval_response: 'Відповідь про ухвалення (кейс-працівники)' + transition_notification: 'Призначення, переведення та перенаправлення' + transfer_request: 'Запити на переведення' user_group_unique_ids: Групи Користувачів user_name: Ім'я користувача services: Послуги diff --git a/config/routes.rb b/config/routes.rb index 6d9f7749ed..1b73c4e2cb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -40,7 +40,9 @@ resources :primero, only: %i[index] resources :children, as: :cases, path: :cases do - resources :children_incidents, as: :incidents, path: :incidents, only: %i[index new] + resources :children_incidents, as: :incidents, path: :incidents, only: %i[index new] do + post '/', to: 'children_incidents#update_bulk', on: :collection + end resources :flags, only: %i[index create update] resources :alerts, only: %i[index destroy] resources :assigns, only: %i[index create] @@ -48,7 +50,7 @@ resources :transfers, only: %i[index create update] resources :transfer_requests, only: %i[index create update] resources :transitions, only: [:index] - resources :attachments, only: %i[create destroy] + resources :attachments, only: %i[create destroy update] resources :approvals, only: [:update] resources :potential_matches, only: [:index] resources :webhook_syncs, as: :sync, path: :sync, only: [:create] @@ -72,6 +74,7 @@ resources :transitions, only: [:index] post :flags, to: 'flags#create_bulk', on: :collection get :record_history, to: 'record_histories#index' + get :get_case_to_link, to: 'incidents#get_case_to_link', on: :collection collection do post :assigns, to: 'assigns#create_bulk' end diff --git a/config/version.rb b/config/version.rb index 4fb9b0031b..4a92118bf4 100644 --- a/config/version.rb +++ b/config/version.rb @@ -3,5 +3,5 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. class Primero::Application - VERSION = '2.10.0' + VERSION = '2.11.1' end diff --git a/db/configuration/lookups/lookups.rb b/db/configuration/lookups/lookups.rb index a26dd7860f..03afbfeff9 100644 --- a/db/configuration/lookups/lookups.rb +++ b/db/configuration/lookups/lookups.rb @@ -26,6 +26,12 @@ { id: 'sub-prefecture', display_text: 'Sub-Prefecture' }, { id: 'commune', display_text: 'Commune' }, { id: 'payam', display_text: 'Payam' }, + { id: 'departement_fr', display_text: 'Département' }, + { id: 'region_fr', display_text: 'Région' }, + { id: 'wilaya', display_text: 'Wilaya' }, + { id: 'division_fr', display_text: 'Division' }, + { id: 'moughataa', display_text: 'Moughataa' }, + { id: 'sub_division', display_text: 'Sub-division' }, { id: 'other', display_text: 'Other' } ].map(&:with_indifferent_access) ) diff --git a/db/data_migration/v2.11.1/README.md b/db/data_migration/v2.11.1/README.md new file mode 100644 index 0000000000..f4c66eb9d8 --- /dev/null +++ b/db/data_migration/v2.11.1/README.md @@ -0,0 +1,13 @@ +# Migrations in 2.11.1 + +This migration updates the configuration of GBV instances *only*. This migrates the fields that calculate average scores on subforms to new versions which support decimal places. + +# Verification of data to be updated + +These scripts will update the `Field` records where calculations exist. + +To validate which fields will be updated, run the following: + +```bash +rails r ./db/migrations/v2.11.1/update_calculated_avg_fields_gbv.rb +``` \ No newline at end of file diff --git a/db/data_migration/v2.11.1/update_calculated_avg_fields_gbv.rb b/db/data_migration/v2.11.1/update_calculated_avg_fields_gbv.rb new file mode 100644 index 0000000000..167c895dad --- /dev/null +++ b/db/data_migration/v2.11.1/update_calculated_avg_fields_gbv.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +save_records = ARGV[0] == 'true' + +def fields_with_old_avg_calculations + return unless PrimeroModule.exists? unique_id: PrimeroModule::GBV + + avg_fields = Field.where("calculation -> 'expression' ? 'avg'") + # The new type of calculated average field has the avg object as a hash, not an array. + avg_fields.filter { |f| f.calculation.dig('expression', 'avg').is_a?(Array) } +end + +def migrate_field(orig_field, save) + old_avg_data = orig_field.calculation.dig('expression', 'avg') + new_field = orig_field.dup + new_field.calculation = { type: 'number', expression: { avg: { data: old_avg_data, extra: { decimalPlaces: 2 } } } } + new_field.disabled = true + new_field.type = 'calculated' + if save + # We because the type of a field cannot be changed, we need to destroy and recreate + orig_field.destroy! + new_field.save! + puts "Updated field #{new_field.name}" + else + puts "Would update #{new_field.name} to the following" + puts new_field.inspect + end +end + +fields_with_old_avg_calculations.each { |f| migrate_field(f, save_records) } diff --git a/db/data_migration/v2.11/README.md b/db/data_migration/v2.11/README.md new file mode 100644 index 0000000000..e124684cd7 --- /dev/null +++ b/db/data_migration/v2.11/README.md @@ -0,0 +1,55 @@ + + +Migrations in v2.11 +======== + +## Introduction +In `v2.11` we are executing a script to store in PosgreSQL the fields that were used by Solr +to query for records and to update the location fields to a new naming convention. + +## Verification data to be updated +You can review the data that will updated with: + +```bash +rails r ./db/data_migration/v2.11/calculate_solr_fields.rb Child file/path.txt +``` + +returns reports which contain location fields that will be updated: +```bash +rails r ./db/data_migration/v2.11/migrate_location_fields.rb +``` + +returns the searchable identifiers to be generated: +```bash +rails r ./db/data_migration/v2.11/calculate_searchable_identifiers.rb Child false file/path.txt +``` + +returns information about the changes to be performed: +```bash +rails r ./db/data_migration/v2.11/calculate_incident_date_derived.rb false file/path.txt +``` + +## Executing scripts +Once you validate that the info is correct you can execute the script to modify the data using: + +```bash +rails r ./db/data_migration/v2.11/calculate_solr_fields.rb Child true file/path.txt +``` + +```bash +rails r ./db/data_migration/v2.11/migrate_location_fields.rb true +``` + +```bash +rails r ./db/data_migration/v2.11/calculate_searchable_identifiers.rb Child true file/path.txt +``` + +```bash +rails r ./db/data_migration/v2.11/calculate_incident_date_derived.rb false file/path.txt +``` + +Remove stale solr jobs. pass until what date you want to delete them. +```bash +rails r ./db/data_migration/v2.11/remove_solr_jobs.rb 2024-09-30 +``` + diff --git a/db/data_migration/v2.11/calculate_incident_date_derived.rb b/db/data_migration/v2.11/calculate_incident_date_derived.rb new file mode 100644 index 0000000000..b6e84fd33a --- /dev/null +++ b/db/data_migration/v2.11/calculate_incident_date_derived.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Example of usage: +# rails r bin/calculate_incident_date_derived.rb true file/path.txt + +def print_log(message) + message = "[#{DateTime.now.strftime('%m/%d/%Y %H:%M:%S')}]: #{message}" + puts message +end + +save_records = ARGV[0] == 'true' +file_path = ARGV[1] + +def print_record_data(model_class, records, batch) + print_log("===The following changes will be applied for #{model_class.name} records in batch ##{batch}===") + records.each do |record| + print_log("id= #{record.id}") + print_log("data= #{record.changes_to_save_for_record}") + end +end + +def records_to_process(model_class, ids_file_path) + return model_class unless ids_file_path.present? + + print_log("Loading record ids from #{ids_file_path}...") + ids_to_update = File.read(ids_file_path).split + model_class.where(id: ids_to_update) +end + +def update_records(model_class, record_hashes, batch) + model_class.transaction do + InsertAllService.insert_all(model_class, record_hashes, 'id') + print_log("Incident batch #{batch} completed.") + rescue StandardError => e + print_log("Error #{e.message} when updating the records for batch #{batch}") + end +end + +records_to_process(Incident, file_path).find_in_batches(batch_size: 1000).with_index do |records, batch| + print_log("Process Incident batch #{batch}...") + record_hashes = records.map do |record| + { + 'id' => record.id, + 'data' => record.data.merge('incident_date_derived' => record.calculate_incident_date_derived) + } + end + + if save_records + update_records(Incident, record_hashes, batch) + else + print_record_data(Incident, records, batch) + end +end diff --git a/db/data_migration/v2.11/calculate_searchable_identifiers.rb b/db/data_migration/v2.11/calculate_searchable_identifiers.rb new file mode 100644 index 0000000000..77196e4c10 --- /dev/null +++ b/db/data_migration/v2.11/calculate_searchable_identifiers.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Example of usage: +# rails r bin/calculate_solr_fields Child,Incident,TracingRequest true file/path.txt + +def print_log(message) + message = "[#{DateTime.now.strftime('%m/%d/%Y %H:%M:%S')}]: #{message}" + puts message +end + +models = (ARGV[0] || '').split(',') +save_records = ARGV[1] == 'true' +file_path = ARGV[2] + +return unless models.present? + +def records_to_process(model_class, ids_file_path) + return model_class unless ids_file_path.present? + + print_log("Loading record ids from #{ids_file_path}...") + ids_to_update = File.read(ids_file_path).split + model_class.where(id: ids_to_update) +end + +def update_records(model_class, record_hashes, _batch) + model_class.transaction do + InsertAllService.insert_all(model_class, record_hashes, 'id') + end +end + +def generate_searchable_identifiers(record) + record.generate_searchable_identifiers.map do |searchable_identifier| + searchable_identifier.merge(record_type: record.class.name, record_id: record.id) + end +end + +models.map(&:constantize).each do |model| + records_to_process(model, file_path).find_in_batches(batch_size: 1000).with_index do |records, batch| + print_log("Process #{model.name} batch #{batch}...") + searchable_identifiers_to_generate = [] + records.each do |record| + current_size = record.searchable_identifiers.size + searchable_identifiers = generate_searchable_identifiers(record) + generated_size = searchable_identifiers.size + total = generated_size - current_size + record_info = "record_type: #{model.name}, record_id: #{record.id}" + field_names = searchable_identifiers.map { |searchable_identifier| searchable_identifier[:field_name] } + identifiers_info = "Searchable Identifiers[#{field_names.join(', ')}]" + if total.positive? + searchable_identifiers_to_generate += searchable_identifiers + print_log("#{total} - #{identifiers_info} will be generated for #{record_info}") + else + print_log("No Searchable Identifiers will be generated for #{record_info}") + end + end + + if save_records && searchable_identifiers_to_generate.size.positive? + update_records(SearchableIdentifier, searchable_identifiers_to_generate, batch) + end + + print_log("#{model.name} batch #{batch} completed.") + rescue StandardError => e + print_log("Error #{e.message} when processing the records for batch #{batch}") + end +end diff --git a/db/data_migration/v2.11/calculate_solr_fields.rb b/db/data_migration/v2.11/calculate_solr_fields.rb new file mode 100644 index 0000000000..d0b2c2ab05 --- /dev/null +++ b/db/data_migration/v2.11/calculate_solr_fields.rb @@ -0,0 +1,168 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Example of usage: +# rails r bin/calculate_solr_fields Child,Incident,TracingRequest true file/path.txt + +def print_log(message) + message = "[#{DateTime.now.strftime('%m/%d/%Y %H:%M')}]: #{message}" + puts message +end + +models = (ARGV[0] || '').split(',') +save_records = ARGV[1] == 'true' +file_path = ARGV[2] + +return unless models.present? + +def print_record_data(model_class, records, batch) + print_log("===The following changes will be applied for #{model_class.name} records in batch ##{batch}===") + records.each do |record| + print_log("id= #{record.id}") + print_log("data= #{record.changes_to_save_for_record}") + print_log("phonetic_tokens= #{record.generate_tokens}") + end +end + +def update_records(model_class, record_hashes, batch) + model_class.transaction do + InsertAllService.insert_all(model_class, record_hashes, 'id') + print_log('===Done===') + rescue StandardError => e + print_log("Error #{e.message} when updating the records for batch #{batch}") + end +end + +def process_records(model_class, record_hashes, batch) + print_log("#{model_class.name} ids for batch ##{batch}:") + print_log(record_hashes.map { |data| data['id'] }) + update_records(model_class, record_hashes, batch) +end + +def records_to_process(model_class, ids_file_path) + model_class_and_relations = model_class.eager_loaded_class + model_class_and_relations = model_class_and_relations.includes(:transitions) if model_class.name == 'Child' + model_class_and_relations = model_class_and_relations.includes(:incidents) if model_class.name == 'Child' + + return model_class_and_relations unless ids_file_path.present? + + print_log("Loading record ids from #{ids_file_path}...") + ids_to_update = File.read(ids_file_path).split + model_class_and_relations.where(id: ids_to_update) +end + +# rubocop:disable Metrics/BlockLength +if models.include?('Child') + print_log('Recalculating solr fields for Child...') + records_to_process(Child, file_path).find_in_batches(batch_size: 1000).with_index do |records, batch| + record_hashes = records.map do |record| + { + 'id' => record.id, + 'data' => record.data.merge( + 'has_photo' => record.calculate_has_photo, + 'has_incidents' => record.calculate_has_incidents, + 'flagged' => record.calculate_flagged, + 'current_alert_types' => record.calculate_current_alert_types, + 'not_edited_by_owner' => record.calculate_not_edited_by_owner, + 'transferred_to_users' => record.calculate_transferred_to_users, + 'transferred_to_user_groups' => record.calculate_transferred_to_user_groups, + 'referred_users' => record.calculate_referred_users, + 'referred_users_present' => record.calculate_referred_users_present, + 'family_number' => record.family_number, + 'assessment_due_dates' => record.calculate_assessment_due_dates, + 'case_plan_due_dates' => record.calculate_case_plan_due_dates, + 'followup_due_dates' => record.calculate_followup_due_dates, + 'service_due_dates' => record.calculate_service_due_dates, + 'followup_dates' => record.calculate_followup_dates, + 'reunification_dates' => record.calculate_reunification_dates, + 'tracing_dates' => record.calculate_tracing_dates, + 'service_implemented_day_times' => record.calculate_service_implemented_day_times + ), + 'phonetic_data' => { 'tokens' => record.generate_tokens } + } + end + + if save_records + process_records(Child, record_hashes, batch) + else + print_record_data(Child, records, batch) + end + end +end +# rubocop:enable Metrics/BlockLength + +if models.include?('Incident') + print_log('Recalculating solr fields for Incident...') + records_to_process(Incident, file_path).find_in_batches(batch_size: 1000).with_index do |records, batch| + record_hashes = records.map do |record| + record.recalculate_association_fields + { + 'id' => record.id, + 'data' => record.data, + 'phonetic_data' => { 'tokens' => record.generate_tokens } + } + end + + if save_records + process_records(Incident, record_hashes, batch) + else + print_record_data(Incident, records, batch) + end + end +end + +if models.include?('TracingRequest') + print_log('Recalculating solr fields for TracingRequest...') + + records_to_process(TracingRequest, file_path).find_in_batches(batch_size: 1000).with_index do |records, batch| + record_hashes = records.map do |record| + { + 'id' => record.id, + 'data' => record.data.merge( + 'tracing_names' => record.calculate_tracing_names(record.traces), + 'tracing_nicknames' => record.calculate_tracing_nicknames(record.traces) + ), + 'phonetic_data' => { 'tokens' => record.generate_tokens } + } + end + + if save_records + process_records(TracingRequest, record_hashes, batch) + else + print_record_data(TracingRequest, records, batch) + end + end +end + +if models.include?('Family') + print_log('Recalculating solr fields for Family...') + + records_to_process(Family, file_path).find_in_batches(batch_size: 1000).with_index do |records, batch| + record_hashes = records.map do |record| + { 'id' => record.id, 'phonetic_data' => { 'tokens' => record.generate_tokens } } + end + + if save_records + process_records(Family, record_hashes, batch) + else + print_record_data(Family, records, batch) + end + end +end + +if models.include?('RegistryRecord') + print_log('Recalculating solr fields for RegistryRecord...') + + records_to_process(RegistryRecord, file_path).find_in_batches(batch_size: 1000).with_index do |records, batch| + record_hashes = records.map do |record| + { 'id' => record.id, 'phonetic_data' => { 'tokens' => record.generate_tokens } } + end + + if save_records + process_records(RegistryRecord, record_hashes, batch) + else + print_record_data(RegistryRecord, records, batch) + end + end +end \ No newline at end of file diff --git a/db/data_migration/v2.11/migrate_location_fields.rb b/db/data_migration/v2.11/migrate_location_fields.rb new file mode 100644 index 0000000000..b4f3e13e05 --- /dev/null +++ b/db/data_migration/v2.11/migrate_location_fields.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Example of usage: +# rails r bin/migrate_location_filters.rb true + +def print_log(message) + message = "[#{DateTime.now.strftime('%m/%d/%Y %H:%M')}]: #{message}" + puts message +end + +def deprecated_field_name?(field_name, matchers) + return false if field_name.starts_with?('loc:') + + matchers.any? { |matcher| matcher.match?(field_name) } +end + +def rename_field_names(field_names, matchers) + field_names.map do |field_name| + next(field_name) unless deprecated_field_name?(field_name, matchers) + + "loc:#{field_name}" + end +end + +save_records = ARGV[0] == 'true' + +location_field_names = Field.where( + type: Field::SELECT_BOX, + option_strings_source: %w[Location ReportingLocation] +).pluck(:name) + +matchers = location_field_names.map { |field_name| Regexp.new("#{field_name}([0-5]{1})?$") } + +Report.all.each do |report| + report.disaggregate_by = rename_field_names(report.disaggregate_by, matchers) + report.aggregate_by = rename_field_names(report.aggregate_by, matchers) + report.filters = report.filters.map do |filter| + next(filter) unless deprecated_field_name?(filter['attribute'], matchers) + + filter.merge('attribute' => "loc:#{filter['attribute']}") + end + + next unless report.changed? + + if save_records + report.save! + print_log("Report id: #{report.id} updated successfully.") + else + print_log("Report Id: #{report.id}") + print_log('Changes:') + report.changes.each { |change| print_log(change) } + end +rescue StandardError => e + print_log("Error #{e.message} when updating the report id: #{report.id}") +end diff --git a/db/data_migration/v2.11/remove_solr_jobs.rb b/db/data_migration/v2.11/remove_solr_jobs.rb new file mode 100644 index 0000000000..d6251d8834 --- /dev/null +++ b/db/data_migration/v2.11/remove_solr_jobs.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2024 UNICEF. All rights reserved. + +# Example of usage: +# rails r db/data_migration/v2.11/remove_solr_jobs.rb 2024-09-30 +created_at_date_limit = ARGV[0].to_date.end_of_day + +exit if Rails.application.config.solr_enabled + +optimize_solr = Delayed::Job.where('handler LIKE :job_class', job_class: '%job_class: OptimizeSolr%') +old_bulkexport_job = Delayed::Job.where('handler LIKE :job_class', + job_class: '%job_class: BulkExportJob%') + .where(created_at: ..created_at_date_limit) + +puts "Deleting OptimizeSolr #{optimize_solr.count}" +puts "Deleting BulkExportJob #{old_bulkexport_job.count}" + +optimize_solr.delete_all +old_bulkexport_job.delete_all diff --git a/db/migrate/20240306154915_add_settings_to_user.rb b/db/migrate/20240306154915_add_settings_to_user.rb new file mode 100644 index 0000000000..bd63059158 --- /dev/null +++ b/db/migrate/20240306154915_add_settings_to_user.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2024 UNICEF. All rights reserved. +class AddSettingsToUser < ActiveRecord::Migration[6.1] + def change + add_column :users, :settings, :jsonb + end +end diff --git a/db/migrate/20240708000000_add_phonetic_data.rb b/db/migrate/20240708000000_add_phonetic_data.rb new file mode 100644 index 0000000000..7eae33ea7e --- /dev/null +++ b/db/migrate/20240708000000_add_phonetic_data.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +class AddPhoneticData < ActiveRecord::Migration[6.1] + def change + add_column :cases, :phonetic_data, :jsonb + add_column :incidents, :phonetic_data, :jsonb + add_column :tracing_requests, :phonetic_data, :jsonb + add_column :families, :phonetic_data, :jsonb + add_column :registry_records, :phonetic_data, :jsonb + + add_index :cases, "(phonetic_data->'tokens')", using: :gin, name: 'cases_phonetic_tokens_idx' + add_index :incidents, "(phonetic_data->'tokens')", using: :gin, name: 'incidents_phonetic_tokens_idx' + add_index :tracing_requests, "(phonetic_data->'tokens')", using: :gin, name: 'tracing_requests_phonetic_tokens_idx' + add_index :families, "(phonetic_data->'tokens')", using: :gin, name: 'families_tokens_idx' + add_index :registry_records, "(phonetic_data->'tokens')", using: :gin, name: 'registry_records_phonetic_tokens_idx' + end +end diff --git a/db/migrate/20241009000000_create_searchable_identifiers.rb b/db/migrate/20241009000000_create_searchable_identifiers.rb new file mode 100644 index 0000000000..0ae453b062 --- /dev/null +++ b/db/migrate/20241009000000_create_searchable_identifiers.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +class CreateSearchableIdentifiers < ActiveRecord::Migration[6.1] + enable_extension 'pg_trgm' unless ENV['PRIMERO_PG_APP_ROLE'] || extension_enabled?('pg_trgm') + + def change + create_table :searchable_identifiers do |t| + t.references :record, polymorphic: true, type: :uuid + t.string 'field_name' + t.string 'value' + end + + add_index :searchable_identifiers, + :value, + using: :gin, + opclass: :gin_trgm_ops, + name: 'searchable_identifiers_value_idx' + end +end diff --git a/db/schema.rb b/db/schema.rb index 9ed7e1d88a..37413a0609 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,10 +10,11 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2023_11_21_151051) do +ActiveRecord::Schema.define(version: 2024_10_09_000000) do # These are extensions that must be enabled in order to support this database enable_extension "ltree" + enable_extension "pg_trgm" enable_extension "pgcrypto" enable_extension "plpgsql" @@ -140,7 +141,9 @@ t.uuid "duplicate_case_id" t.uuid "registry_record_id" t.uuid "family_id" + t.jsonb "phonetic_data" t.index "((data ->> 'case_id'::text))", name: "cases_case_id_unique_idx", unique: true + t.index "((phonetic_data -> 'tokens'::text))", name: "cases_phonetic_tokens_idx", using: :gin t.index ["data"], name: "index_cases_on_data", using: :gin t.index ["duplicate_case_id"], name: "index_cases_on_duplicate_case_id" t.index ["family_id"], name: "index_cases_on_family_id" @@ -197,6 +200,8 @@ create_table "families", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.jsonb "data", default: {} + t.jsonb "phonetic_data" + t.index "((phonetic_data -> 'tokens'::text))", name: "families_tokens_idx", using: :gin t.index ["data"], name: "index_families_on_data", using: :gin end @@ -342,7 +347,9 @@ create_table "incidents", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.jsonb "data", default: {} t.uuid "incident_case_id" + t.jsonb "phonetic_data" t.index "((data ->> 'incident_id'::text))", name: "incidents_incident_id_unique_idx", unique: true + t.index "((phonetic_data -> 'tokens'::text))", name: "incidents_phonetic_tokens_idx", using: :gin t.index ["data"], name: "index_incidents_on_data", using: :gin t.index ["incident_case_id"], name: "index_incidents_on_incident_case_id" end @@ -458,6 +465,8 @@ create_table "registry_records", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.jsonb "data", default: {} + t.jsonb "phonetic_data" + t.index "((phonetic_data -> 'tokens'::text))", name: "registry_records_phonetic_tokens_idx", using: :gin t.index ["data"], name: "index_registry_records_on_data", using: :gin end @@ -513,6 +522,15 @@ t.index ["user_id"], name: "index_saved_searches_on_user_id" end + create_table "searchable_identifiers", force: :cascade do |t| + t.string "record_type" + t.uuid "record_id" + t.string "field_name" + t.string "value" + t.index ["record_type", "record_id"], name: "index_searchable_identifiers_on_record" + t.index ["value"], name: "searchable_identifiers_value_idx", opclass: :gin_trgm_ops, using: :gin + end + create_table "sources", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.jsonb "data", default: {} t.index ["data"], name: "index_sources_on_data", using: :gin @@ -571,7 +589,9 @@ create_table "tracing_requests", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.jsonb "data", default: {} + t.jsonb "phonetic_data" t.index "((data ->> 'tracing_request_id'::text))", name: "tracing_requests_tracing_request_id_unique_idx", unique: true + t.index "((phonetic_data -> 'tokens'::text))", name: "tracing_requests_phonetic_tokens_idx", using: :gin t.index ["data"], name: "index_tracing_requests_on_data", using: :gin end @@ -657,6 +677,7 @@ t.datetime "code_of_conduct_accepted_on" t.bigint "code_of_conduct_id" t.boolean "receive_webpush" + t.jsonb "settings" t.index ["agency_id"], name: "index_users_on_agency_id" t.index ["code_of_conduct_id"], name: "index_users_on_code_of_conduct_id" t.index ["email"], name: "index_users_on_email", unique: true diff --git a/doc/api/activity_log/get.md b/doc/api/activity_log/get.md index 907f31b204..d533210afd 100644 --- a/doc/api/activity_log/get.md +++ b/doc/api/activity_log/get.md @@ -15,7 +15,7 @@ Shows a paginated list of activities that are accessible to this user. **Parameters** : * `page` Optional. Pagination. Defaults to 1 -* `per` Optional. Records per page. Defaults to 20 +* `per` Optional. Records per page. Defaults to 20. Maximum is 1000 * `order` Optional. Order activities. Defaults to desc * `types` Optional. An array of activities to be returned. Defaults to all available activities. Example: `types[]=transfer` diff --git a/doc/api/agencies/get.md b/doc/api/agencies/get.md index 8ac034a9a0..54f92200fd 100644 --- a/doc/api/agencies/get.md +++ b/doc/api/agencies/get.md @@ -15,7 +15,7 @@ Shows a paginated list of all agencies that are accessible to this user. **Parameters** : * `page` Optional. Pagination. Defaults to 1 -* `per` Optional. Records per page. Defaults to 20. +* `per` Optional. Records per page. Defaults to 20. Maximum is 1000 * `disabled` Optional. Get all the disabled or enabled agencies. Defaults get all the agencies ## Success Response diff --git a/doc/api/cases/get.md b/doc/api/cases/get.md index b4aeaa4ac0..9066834a54 100644 --- a/doc/api/cases/get.md +++ b/doc/api/cases/get.md @@ -2,7 +2,7 @@ # Query for cases -Show a paginated list of all cases that are accessible to this user. The user can filter the case list based on search criteria. +Show a paginated list of all cases that are accessible to this user. The user can filter the case list based on search criteria. **URL** : `/api/v2/cases` @@ -11,25 +11,25 @@ Show a paginated list of all cases that are accessible to this user. The user ca **Authentication** : YES **Authorization** : The user must be authorized to view cases in Primero. The full set of cases viewable by this user -depends on the user's authorization scope: just cases the user is assigned to, cases that are associated with all -users in this user's user groups, or all cases in the system. The fields that are shown for each case -are only fields that this user is permitted to view. +depends on the user's authorization scope: just cases the user is assigned to, cases that are associated with all +users in this user's user groups, or all cases in the system. The fields that are shown for each case +are only fields that this user is permitted to view. -**Parameters** : +**Parameters** : * `query` Optional. A text query over a special set of fields such as names and identifiers. -* Filter query over case fields of type select, numeric, date, booleans. +* Filter query over case fields of type select, numeric, date, booleans. Query values can be comma-separated lists and date and numeric ranges. Optional Example `sex=male&age=10..15&protection_concerns=unaccompanied,separated` -* `fields` Optional. A comma-separated list of fields that will be returned in the json data. +* `fields` Optional. A comma-separated list of fields that will be returned in the json data. If unspecified this displays all permitted fields. The special value `short` will return a condensed list of relevant permitted fields. * `page` Optional. Pagination. Defaults to 1 -* `per` Optional. Records per page. Defaults to 20. +* `per` Optional. Records per page. Defaults to 20. Maximum is 1000 ## Success Response -**Condition** : User can see one or more cases. +**Condition** : User can see one or more cases. **Code** : `200 OK` @@ -74,7 +74,7 @@ list of relevant permitted fields. ``` ## Error Response -**Condition** : User isn't authorized to query for cases. +**Condition** : User isn't authorized to query for cases. **Code** : `403 Forbidden` diff --git a/doc/api/cases/id/incidents/post.md b/doc/api/cases/id/incidents/post.md new file mode 100644 index 0000000000..db2936d6f6 --- /dev/null +++ b/doc/api/cases/id/incidents/post.md @@ -0,0 +1,78 @@ + + +# Query incidents for a case + +Show a list of all incidents associated with this user. + +**URL** : `/api/v2/cases/:id/incidents` + +**Method** : `POST` + +**Authentication** : YES + +**Authorization** : The user must be authorized to view this case in Primero and to link incidents. + +**Parameters** : + +* `data` A JSON representation of the transfer. +```json +{ + "data": { + "incident_ids": ["749e9c6e-60db-45ec-8f5a-69da7c223a79", "dcea6052-07d9-4cfa-9abf-9a36987cdd25"], + } +} +``` + +## Success Response + +**Condition** : User can see this case and can view incidents. + +**Code** : `200 OK` + +**Content** : + +```json +{ + "data": [ + { + "id": "11d8ef93-1b48-4469-9dce-ab173f6c90f2", + "enabled": true, + "age": 5, + "sex": "male", + "status": "open", + "created_at": "2020-08-05T16:06:37.696Z", + "description": "Test 1", + "incident_date": "2019-03-01" + }, + { + "id": "46255137-6e66-486d-b809-e1b825e840a8", + "enabled": true, + "age": 5, + "sex": "male", + "status": "open", + "created_at": "2020-08-05T16:06:37.717Z", + "description": "Test 2", + "incident_date": "2019-08-01" + } + ] +} +``` +## Error Response + +**Condition** : User isn't authorized to access this case or incidents. + +**Code** : `403 Forbidden` + +**Content** : + +```json +{ + "errors": [ + { + "code": 403, + "resource": "/api/v2/cases/:id/incidents", + "message": "Forbidden" + } + ] +} +``` diff --git a/doc/api/configurations/get.md b/doc/api/configurations/get.md index 9e816ce9bc..c11f5940df 100644 --- a/doc/api/configurations/get.md +++ b/doc/api/configurations/get.md @@ -15,7 +15,7 @@ Shows a paginated list of all configurations. **Parameters** : * `page` Optional. Pagination. Defaults to 1 -* `per` Optional. Records per page. Defaults to 20. +* `per` Optional. Records per page. Defaults to 20. Maximum is 1000 ## Success Response diff --git a/doc/api/exports/get.md b/doc/api/exports/get.md index 721c452a54..f14aa85e37 100644 --- a/doc/api/exports/get.md +++ b/doc/api/exports/get.md @@ -2,7 +2,7 @@ # Query for Exports -Show a paginated list of all exports that are accessible to this user. +Show a paginated list of all exports that are accessible to this user. This method can be used to poll for the status of ongoing export jobs. **URL** : `/api/v2/exports` @@ -14,13 +14,13 @@ This method can be used to poll for the status of ongoing export jobs. **Authorization** : The user must be authorized to perform at least one export action on a record. Only exports created by this user are viewable. -**Parameters** : +**Parameters** : -* `status` Optional. Query by status. Can be used to poll for ongoing jobs. +* `status` Optional. Query by status. Can be used to poll for ongoing jobs. * `record_type` Optional. The record for which the export is being performed. * `export_format` Optional. The type of export that is running. * `page` Optional. Pagination. Defaults to 1 -* `per` Optional. Records per page. Defaults to 20. +* `per` Optional. Records per page. Defaults to 20. Maximum is 1000 ## Success Response @@ -53,7 +53,7 @@ Only exports created by this user are viewable. ``` ## Error Response -**Condition** : User isn't authorized to perform exports. +**Condition** : User isn't authorized to perform exports. **Code** : `403 Forbidden` diff --git a/doc/api/families/get.md b/doc/api/families/get.md index 615b85451a..96efe2b85e 100644 --- a/doc/api/families/get.md +++ b/doc/api/families/get.md @@ -2,7 +2,7 @@ # Query for Families -Show a paginated list of all families that are accessible to this user. The user can filter the family list based on search criteria. +Show a paginated list of all families that are accessible to this user. The user can filter the family list based on search criteria. **URL** : `/api/v2/families` @@ -12,15 +12,15 @@ Show a paginated list of all families that are accessible to this user. The user **Authorization** : The user must be authorized to view families in Primero. -**Parameters** : +**Parameters** : * `family_number` Optional. * `page` Optional. Pagination. Defaults to 1 -* `per` Optional. Records per page. Defaults to 20. +* `per` Optional. Records per page. Defaults to 20. Maximum is 1000 ## Success Response -**Condition** : User can see one or more families. +**Condition** : User can see one or more families. **Code** : `200 OK` @@ -65,7 +65,7 @@ Show a paginated list of all families that are accessible to this user. The user ``` ## Error Response -**Condition** : User isn't authorized to query for families. +**Condition** : User isn't authorized to query for families. **Code** : `403 Forbidden` diff --git a/doc/api/lookups/get.md b/doc/api/lookups/get.md index 78c339c6ce..6be9474d7b 100644 --- a/doc/api/lookups/get.md +++ b/doc/api/lookups/get.md @@ -15,7 +15,7 @@ Shows a paginated list of all lookups that are accessible to this user. **Parameters** : * `page` Optional. Pagination. Defaults to 1 -* `per` Optional. Records per page. Defaults to 20. +* `per` Optional. Records per page. Defaults to 20. Maximum is 1000 ## Success Response diff --git a/doc/api/record_history/get.md b/doc/api/record_history/get.md index 9ac49fcd73..a3f969ed47 100644 --- a/doc/api/record_history/get.md +++ b/doc/api/record_history/get.md @@ -15,7 +15,7 @@ Shows a paginated list of all record histories that are accessible to this user. **Parameters** : * `page` Optional. Pagination. Defaults to 1 -* `per` Optional. Records per page. Defaults to 20. +* `per` Optional. Records per page. Defaults to 20. Maximum is 1000 ## Success Response diff --git a/doc/api/registry_records/get.md b/doc/api/registry_records/get.md index 9a7bc8afc6..35a51968ce 100644 --- a/doc/api/registry_records/get.md +++ b/doc/api/registry_records/get.md @@ -2,7 +2,7 @@ # Query for Registry Records -Show a paginated list of all cases that are accessible to this user. The user can filter the case list based on search criteria. +Show a paginated list of all cases that are accessible to this user. The user can filter the case list based on search criteria. **URL** : `/api/v2/registry_records` @@ -12,15 +12,15 @@ Show a paginated list of all cases that are accessible to this user. The user ca **Authorization** : The user must be authorized to view registry records in Primero. -**Parameters** : +**Parameters** : * `registry_type` Optional. * `page` Optional. Pagination. Defaults to 1 -* `per` Optional. Records per page. Defaults to 20. +* `per` Optional. Records per page. Defaults to 20. Maximum is 1000 ## Success Response -**Condition** : User can see one or more registry records. +**Condition** : User can see one or more registry records. **Code** : `200 OK` @@ -65,7 +65,7 @@ Show a paginated list of all cases that are accessible to this user. The user ca ``` ## Error Response -**Condition** : User isn't authorized to query for registry records. +**Condition** : User isn't authorized to query for registry records. **Code** : `403 Forbidden` diff --git a/doc/api/roles/get.md b/doc/api/roles/get.md index f04f8d5be0..8bd06465c1 100644 --- a/doc/api/roles/get.md +++ b/doc/api/roles/get.md @@ -15,7 +15,7 @@ Shows a paginated list of all roles that are accessible to this user. **Parameters** : * `page` Optional. Pagination. Defaults to 1 -* `per` Optional. Records per page. Defaults to 20. +* `per` Optional. Records per page. Defaults to 20. Maximum is 1000 ## Success Response diff --git a/doc/api/saved_searches/get.md b/doc/api/saved_searches/get.md index a0ff06b200..649626b4fa 100644 --- a/doc/api/saved_searches/get.md +++ b/doc/api/saved_searches/get.md @@ -15,7 +15,7 @@ Show a paginated list of all saved searches that are accessible to this user. **Parameters** : * `page` Optional. Pagination. Defaults to 1 -* `per` Optional. Records per page. Defaults to 20. +* `per` Optional. Records per page. Defaults to 20. Maximum is 1000 ## Success Response diff --git a/doc/api/user_groups/get.md b/doc/api/user_groups/get.md index 1b4109d797..8fb4bfc178 100644 --- a/doc/api/user_groups/get.md +++ b/doc/api/user_groups/get.md @@ -15,7 +15,7 @@ Shows a paginated list of all user_groups that are accessible to this user. **Parameters** : * `page` Optional. Pagination. Defaults to 1 -* `per` Optional. Records per page. Defaults to 20. +* `per` Optional. Records per page. Defaults to 20. Maximum is 1000 * `agency_unique_ids` Optional. Returns the users groups associated to the specified agencies. ## Success Response diff --git a/doc/dao/Managing Git & Formatting PRs.md b/doc/dao/Managing Git & Formatting PRs.md index e4346c69c5..066068e56b 100644 --- a/doc/dao/Managing Git & Formatting PRs.md +++ b/doc/dao/Managing Git & Formatting PRs.md @@ -22,6 +22,8 @@ git push --set-upstream fork my-branch-name Once you are ready to have your contribution reviewed by the core development team, you should open a Pull Request on the Primero repository. The development team will then review the contribution, and suggest changes. Once you implement those changes, the team will review the contribution again, and either the review process will continue, or the changes will be approved for merging. Once the changes are merged, and the contribution is concluded, you will be able to ask for payment from the DAO. +Please include the string "DAO" in the pull request title and a link to the proposal pitch from the [UNICEF DAO discussion forum](https://unicef.tomars.co/c/pp/) in the pull request description. We will not merge pull requests that have not been approved by the DAO voting members. This ensures that developers are fully compensated for the pull requests submitted through the DAO. + If your contribution is not ready, but you need a place to discuss the changes you are making, you can make a pull request, and mark it as a draft. Over time, as code is merged into Primero whilst your PR is pending, your PR will become stale. You should periodically merge in the most recent changes on the develop branch to ensure that there are no conflicts and that your code remains up-to-date. **You must always merge upstream changes, do not rebase.** diff --git a/doc/getting_started_development.md b/doc/getting_started_development.md index 604b512dfe..e1db7780f2 100644 --- a/doc/getting_started_development.md +++ b/doc/getting_started_development.md @@ -33,7 +33,7 @@ git checkout develop > [!NOTE] > Visual Studio Code is not required. -> +> > If you prefer another IDE or editor, such as RubyMine, Vim, or Emacs, these instructions don't apply to you, but you will still want to make sure that you have any Ruby and Rails language features enabled. If you do not already have Visual Studio Code, install it from . @@ -46,7 +46,7 @@ Click the *Open...* button in the middle of the window. Select the directory whe > [!NOTE] > This step is entirely optional. -> +> > How you use your editor is up to you! There are a number of extensions that help with ruby support in VSCode. You will want to install a few VSCode extensions to have the best experience editing Primero's code. @@ -80,10 +80,10 @@ If you want to use the debugging features of VSCode for Ruby, you can add the fo # Installing Dependencies ## Installing Ruby using `rbenv` -> [!NOTE] +> [!NOTE] > If you already have a solution that you like, such as rvm, asdf, or RTX, there is no reason to switch. You will just need to use them to install the correct runtimes. -> [!WARNING] +> [!WARNING] > The version of rbenv packaged with Ubuntu and Debian is out-of-date. You will need to install it according to the steps below, rather than use the version provided by apt. `rbenv` is a version manager and installer for ruby runtimes. It allows you to install the correct version of ruby for each project that you are working on. @@ -111,9 +111,9 @@ In the Primero top-level directory, there is a file `.ruby-version`, which conta ```bash cat .ruby-version -# This will print something like: ruby-3.2.2 +# This will print something like: ruby-3.3.5 # rbenv needs the version number, but not the ruby- prefix. -rbenv install 3.2.2 # replace 3.2.2 with whatever version is in .ruby-version +rbenv install 3.3.5 # replace 3.3.5 with whatever version is in .ruby-version ``` It will take several minutes to build and install ruby, depending on the speed of your machine. @@ -121,7 +121,7 @@ Once you have succeeded in installing ruby, it is worth checking that you are no ```bash ruby --version -# This should print something like: ruby 3.2.2 (or whatever the current version in the .ruby-version is) +# This should print something like: ruby 3.3.5 (or whatever the current version in the .ruby-version is) ``` ## Installing node using `nvm` @@ -145,14 +145,14 @@ nvm install --lts ``` ## Installing Docker and docker-compose -> [!NOTE] +> [!NOTE] > If you already have docker and docker-compose, skip this step. -> +> > Docker can be installed in a number of different ways. As we are primarily using docker as a convenient way of running a database locally, it doesn't matter how it is installed. -Install docker using apt: +Install docker using [apt](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository): ```bash -sudo apt install docker.io docker-compose +sudo apt install docker.io docker-compose-plugin ``` ## Building the Containers @@ -160,15 +160,33 @@ sudo apt install docker.io docker-compose cd ./docker sudo ./build.sh postgres solr ``` +## Configuration file + +Before running the containers, make sure to copy the sample environment file to create the necessary `local.env` file. This file is required when using `compose.local.sh up`. + +```bash +cp local.env.sample.development local.env +``` ## Running the Containers You should run this from inside the docker directory. ```bash sudo ./compose.local.sh up -d postgres +``` +If you want to use **SOLR**, you can enable it by setting the environment variable `SOLR_ENABLED=true` before running the containers. + +> **Note:** By default **SOLR** service is disabled, but it is still required to enable **FTR, GBV** and **KPI** features. + +```bash +export SOLR_ENABLED=true sudo ./compose.local.sh run solr make-primero-core.sh primero-test sudo ./compose.local.sh up -d solr ``` +## For more docker instructions + +For detailed Docker setup instructions, see the [Docker README](docker/README.md). + # Configuring Primero for Local Development Primero is partially configured with a number of yaml files. There are example versions of these files provided for local development. They need to be copied to the correct locations in order for Primero to function. @@ -178,10 +196,15 @@ Execute these from the root directory of the repository. You may want to review cp config/database.yml.development config/database.yml cp config/locales.yml.development config/locales.yml cp config/mailers.yml.development config/mailers.yml -cp config/sunspot.yml.development config/sunspot.yml mkdir log ``` +If you are using SOLR enabled, you must copy sunspot file + +```bash +cp config/sunspot.yml.development config/sunspot.yml +``` + You will also need to install some system-wide dependencies required to build and run Primero. ```bash @@ -222,7 +245,7 @@ The following bash command will generate a secure secret for each of these and a ```bash for v in PRIMERO_SECRET_KEY_BASE DEVISE_SECRET_KEY DEVISE_JWT_SECRET_KEY; -do echo "export ${v}=$(openssl rand -hex 16)" >> ~/.bashrc; +do echo "export ${v}=$(openssl rand -hex 16)" >> ~/.bashrc; done; ``` @@ -247,6 +270,8 @@ npm run dev In the other window, run the following command, which will run the rails server that hosts the Primero backend. +> **Note:** If `SOLR_ENABLED` variable is set to true, primero will use solr service. + ```bash rails s ``` @@ -258,7 +283,7 @@ Log in using the default credentials `primero/primer0!`. ![Logging into Primero](dao/Attachments/login.webp) -The version of Primero you will have configured by default is largely the same as CPIMS+. If you need a different configuration of Primero, for example, GBVIMS+, you will need to contact UNICEF and request access to the official configurations repository. +The version of Primero you will have configured by default is largely the same as CPIMS+. If you need a different configuration of Primero, for example, GBVIMS+, you will need to contact UNICEF and request access to the official configurations repository. # Running Linters - RuboCop & ESLint @@ -301,11 +326,12 @@ To use the push notification features of Primero, you must set some environment To generate a valid VAPID keypair, you can execute the following script to generate private and public keys for their respective environment variables. You will probably want to add the variables to your `~/.bashrc` file. ```bash -rails r ' -keypair = WebPush.generate_key -puts "Private Key: #{keypair.private_key}" -puts "Public Key: #{keypair.public_key}" -' + openssl ecparam -genkey -name prime256v1 -out private_key.pem + # generating public_vapid_key + openssl ec -in private_key.pem -pubout -outform DER|tail -c 65|base64|tr -d '\n'|tr -d '=' |tr '/+' '_-' + # generating private_vapid_key + openssl ec -in private_key.pem -outform DER|tail -c +8|head -c 32|base64|tr -d '\n'|tr -d '=' |tr '/+' '_-' + rm private_key.pem ``` ```bash diff --git a/doc/postgres_upgrade.md b/doc/postgres_upgrade.md index 4c6a697112..37acabd28c 100644 --- a/doc/postgres_upgrade.md +++ b/doc/postgres_upgrade.md @@ -3,29 +3,29 @@ Upgrading a Major PostgreSQL Version =========== -PostgreSQL data directories cannot be reused between major version upgrades. A data directory generated for PostgreSQL 10.x will not work with Postgres 11.x. When running Primero PostgreSQL with Docker, the data needs to be exported and reloaded, and the backing volume needs to be recreated. +PostgreSQL data directories cannot be reused between major version upgrades. A data directory generated for PostgreSQL 14.x will not work with Postgres 15.x. When running Primero PostgreSQL with Docker, the data needs to be exported and reloaded, and the backing volume needs to be recreated. In the instructions below, the **Primero Server** refers to the machine that runs a Dockerized Primero and the **Ansible Server** refers to the machine that is used to provision it with Ansible. 1. Create a back up of the database volume. This will not be used for the migration, but can be used to roll back the upgrade if something goes wrong. Look at the [Docker documentation](https://docs.docker.com/storage/volumes/#backup-restore-or-migrate-data-volumes) for more information about backing up and restoring volumes. On the **Primero Server**: $ mkdir postgres_backup && chmod 777 postgres_backup - $ docker run --rm --volumes-from primero_postgres_1 -v $(pwd)/postgres_backup:/backup busybox tar czvf /backup/primero-postgres-volume-backup.tar.gz /var/lib/postgresql/data + $ docker run --rm --volumes-from primero-postgres-1 -v $(pwd)/postgres_backup:/backup busybox tar czvf /backup/primero-postgres-volume-backup.tar.gz /var/lib/postgresql/data $ chmod 700 postgres_backup 2. Shut down all application containers. On the **Primero Server**: - $ docker stop primero_application_1 primero_worker_1 + $ docker stop primero-application-1 primero-worker-1 3. Create the migration data dump. On the **Primero Server**: $ mkdir migration_data - $ docker exec -t primero_postgres_1 pg_dumpall -c -U primero > migration_data/primero_migration_data.sql + $ docker exec -t primero-postgres-1 pg_dumpall -c -U primero > migration_data/primero_migration_data.sql 4. Delete the PostgreSQL data volume. On the **Primero Server**: - $ docker container stop primero_postgres_1 - $ docker container rm primero_postgres_1 + $ docker container stop primero-postgres-1 + $ docker container rm primero-postgres-1 $ docker volume rm primero_database @@ -37,12 +37,12 @@ In the instructions below, the **Primero Server** refers to the machine that run 6. Restore the migration dump file to the new database. On the **Primero Server**: - $ docker cp $(pwd)/migration_data/primero_migration_data.sql primero_postgres_1:/ - $ docker exec -t primero_postgres_1 psql -f /primero_migration_data.sql -U primero + $ docker cp $(pwd)/migration_data/primero_migration_data.sql primero-postgres-1:/ + $ docker exec -t primero-postgres-1 psql -f /primero_migration_data.sql -U primero 7. **(Necessary if upgrading from PostgreSQL 10.)** If the password encryption strategy is changing (MD5 to SCRAM), the `primero` role password will need to be reset. On the **Primero Server:** - $ docker exec -t primero_postgres_1 bash -c 'echo "ALTER ROLE primero PASSWORD '"'"'${POSTGRES_PASSWORD}'"'"';" | psql -U primero' + $ docker exec -t primero-postgres-1 bash -c 'echo "ALTER ROLE primero PASSWORD '"'"'${POSTGRES_PASSWORD}'"'"';" | psql -U primero' 8. Restart again, from the ***Ansible Server:** diff --git a/doc/transifex.md b/doc/transifex.md index b70721b939..a8e74a548f 100644 --- a/doc/transifex.md +++ b/doc/transifex.md @@ -22,10 +22,8 @@ tx --version Create a file `~/.transifexrc` and put the follow values ```text [https://www.transifex.com] -api_hostname = https://api.transifex.com -hostname = https://www.transifex.com -password = -username = api +rest_hostname = https://rest.api.transifex.com +token = API_TOKEN_HERE ``` Where is generate [here](https://www.transifex.com/user/settings/api/) @@ -62,3 +60,12 @@ There are some languages that are being reviewed after being translated, and eve ```bash tx pull -f -l ar --mode=onlyreviewed ``` + +## Verify translations: +To check for any incorrect interpolations in Transifex files, you can execute: + +```bash +./bin/check_transifex_interpolations.sh +``` + +If a list is displayed please fix it on Transifex and pull the translations again. diff --git a/doc/ui_testing.md b/doc/ui_testing.md index 1fc40a17fe..29c5e1f933 100644 --- a/doc/ui_testing.md +++ b/doc/ui_testing.md @@ -2,9 +2,6 @@ # Frontend Unit Testing -## Migration - -We are currently in the process of migrating React test from Enzyme. Going forward Enzyme is no longer supported with React 18+. ### Libraries @@ -12,7 +9,7 @@ We are currently in the process of migrating React test from Enzyme. Going forwa - [Jest](https://jestjs.io/docs/getting-started) ### Contributing -Temporarily pull request for migrated unit test should be made against +Temporarily pull request for migrated unit test should be made against the `develop_react_upgrade` branch in Github. #### Process for migrating a test file. @@ -23,8 +20,8 @@ the `develop_react_upgrade` branch in Github. #### Thing to know - Running unit test - - `npm run test:new` - Runs full test suite - - `npm run test:new -- $FILE_PATH` - Run individual test files. Example: `npm run test:new -- app/javascript/components/menu/component.spec.js` + - `npm run test:components` - Runs full test suite + - `npm run test:components -- $FILE_PATH` - Run individual test files. Example: `npm run test:components -- app/javascript/components/menu/component.spec.js` - There are some utility functions that we use to render test components in `/app/javascript/test-utils`. `mountedComponent` will be the most used for unit test. The function takes a component to test, desired store data, and other options. It will return a rendered component to use with your assertions. For an example see: `app/javascript/components/action-button/component.spec.js` - If there is a component without an unit test file please create one. In that file please place the following. ``` @@ -54,4 +51,3 @@ the `develop_react_upgrade` branch in Github. - RTL provides a few [queries](https://testing-library.com/docs/queries/about) to find elements in the rendered component. A require some kinda of attribute set on a component. For example: `byRole` requires a `data-role` WAI-ARIA attribute set on an element. You will need to make those small changes to the component file for finding elements for test assertions. `ByTestId` is to be only used if it is impossible to use the other provided queries. [List of WAI-ARIA Roles](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles) - diff --git a/doc/ui_ux.md b/doc/ui_ux.md index 3ae47a7325..3732a680e6 100644 --- a/doc/ui_ux.md +++ b/doc/ui_ux.md @@ -94,12 +94,9 @@ v2 ui can be found in the `app/javascript` directory. ```js // component.js -import styles from "./styles.css"; -import { makeStyles } from "@material-ui/styles"; +import css from "./styles.css"; const TODO = () => { - const css = makeStyles(styles)(); - return (
Hello Josh
) @@ -165,13 +162,12 @@ const testFunc = async options => { ### Libs - [chai](https://www.chaijs.com/) - [chai-immutable](https://github.com/astorije/chai-immutable) -- [enzyme](https://github.com/airbnb/enzyme) - [mocha](https://mochajs.org/) - [sinon](https://sinonjs.org/) - [require-hacker](https://github.com/catamphetamine/require-hacker) - [jsdom](https://github.com/jsdom/jsdom) - [react-test-renderer](https://reactjs.org/docs/test-renderer.html) -- [material-ui/testing](https://material-ui.com/guides/testing/#testing) : Material iu has testing helpers simular to enzyme's methods. +- [material-ui/testing](https://material-ui.com/guides/testing/#testing) There are also some helpers and setup in the `javascript/test` dir. The helpers in `javascript/test/unit-test-helpers.js` wrap components in the needed providers to mount components. Take a look at files with the name of *.unit.test.js for examples. Test should reside aside their component. diff --git a/docker/README.md b/docker/README.md index 800f5b9ad8..a4487f2171 100644 --- a/docker/README.md +++ b/docker/README.md @@ -26,7 +26,7 @@ cd docker Build your container images and tag with `latest`: ``` -./build all +./build.sh all ``` Create a `local.env` environment configuration file by @@ -118,9 +118,6 @@ To generate, can use the command `LC_ALL=C < /dev/urandom tr -dc '_A-Z-a-z-0-9' DEVISE_SECRET_KEY - Required. A secure random number. To generate, can use the command `LC_ALL=C < /dev/urandom tr -dc '_A-Z-a-z-0-9' | head -c"${1:-32}"` -DEVISE_JWT_SECRET_KEY - Required. A secure random number. -To generate, can use the command `LC_ALL=C < /dev/urandom tr -dc '_A-Z-a-z-0-9' | head -c"${1:-32}"` - PRIMERO_SECRET_KEY_BASE - Required. A secure random number. To generate, can use the command `LC_ALL=C < /dev/urandom tr -dc '_A-Z-a-z-0-9' | head -c"${1:-32}"` diff --git a/docker/application/Dockerfile b/docker/application/Dockerfile index 200a68ca51..86cee7a1a7 100644 --- a/docker/application/Dockerfile +++ b/docker/application/Dockerfile @@ -1,16 +1,17 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - # -------------------------------------------------------------------- BUILD STAGE +# -------------------------------------------------------------------- BUILD STAGE ARG BUILD_REGISTRY -FROM ${BUILD_REGISTRY}ruby:3.2.2-alpine3.18 AS build-env +ARG RUBY_VERSION=3.3.5 +FROM ${BUILD_REGISTRY}ruby:${RUBY_VERSION}-alpine3.20 AS build-env -ENV BUILD_PACKAGES bash curl wget curl-dev build-base git -ENV PYTHON_PACKAGES python3 py3-pip -ENV BUILD_DEP_PACKAGES postgresql-dev -ENV RUNTIME_PACKAGES libc6-compat nodejs gettext libintl npm imagemagick libsodium-dev -ENV DEV_PACKAGES busybox-extras tree cairo pixman pixman-dev -ENV RAILS_ENV production -ENV PYTHON /usr/bin/python +ENV BUILD_PACKAGES="bash curl wget curl-dev build-base git" +ENV PYTHON_PACKAGES="python3 py3-pip" +ENV BUILD_DEP_PACKAGES=postgresql-dev +ENV RUNTIME_PACKAGES="libc6-compat nodejs gettext libintl npm imagemagick libsodium-dev" +ENV DEV_PACKAGES="busybox-extras tree cairo pixman pixman-dev" +ENV RAILS_ENV=production +ENV PYTHON=/usr/bin/python # Grab our path from --build-arg and store it in an env ARG APP_ROOT @@ -52,16 +53,22 @@ COPY [ "Gemfile", "Gemfile.lock", "$APP_ROOT/" ] RUN set -euox pipefail \ ; if [ $RAILS_ENV == "production" ]; \ then \ - bundle install --without development test \ + export BUNDLER_WITHOUT="development test" \ ; else \ - bundle install \ - ; fi + export BUNDLER_WITHOUT="" \ + ; fi \ + && bundle install + +# Note: Deleting the Solr dev server is not strictly necessary since we don't run it +# but its java packages are riddled with vulnerabilities that set off static security scans. +# TODO: Get rid of this line when we get rid of Solr gems. +RUN rm -r /usr/local/bundle/gems/sunspot_solr-2.6.0/solr/server # Run npm ci COPY [ "package.json", "package-lock.json", "$APP_ROOT/" ] RUN set -euox pipefail \ - ; npm ci + ; npm config set legacy-peer-deps true; npm ci # Note: This has its build context set to the root dir so prepend 'docker' to # items that need to be copied from that directory @@ -94,10 +101,10 @@ RUN set -euox pipefail \ # -------------------------------------------------------------------- FINAL ARG BUILD_REGISTRY -FROM ${BUILD_REGISTRY}ruby:3.2.2-alpine3.18 +FROM ${BUILD_REGISTRY}ruby:${RUBY_VERSION}-alpine3.20 -ENV BUILD_PACKAGES bash -ENV RUNTIME_PACKAGES libpq gettext libintl imagemagick libsodium-dev p7zip curl tini +ENV BUILD_PACKAGES=bash +ENV RUNTIME_PACKAGES="libpq gettext libintl imagemagick libsodium-dev p7zip curl tini" ARG APP_UID ARG APP_GID @@ -106,8 +113,7 @@ ENV GROUP_ID=${APP_GID} ARG APP_ROOT ENV APP_ROOT=${APP_ROOT} -ENV RAILS_ENV production -ENV RAILS_PUBLIC_FILE_SERVER=${RAILS_PUBLIC_FILE_SERVER} +ENV RAILS_ENV=production # Install our packages RUN set -euox pipefail \ diff --git a/docker/application/root/entrypoint.sh b/docker/application/root/entrypoint.sh index b39e50990d..2a03e56de5 100755 --- a/docker/application/root/entrypoint.sh +++ b/docker/application/root/entrypoint.sh @@ -11,7 +11,7 @@ check_required_variables() { result=0 set +ux - required=( PRIMERO_HOST POSTGRES_USER POSTGRES_PASSWORD PRIMERO_SECRET_KEY_BASE DEVISE_SECRET_KEY DEVISE_JWT_SECRET_KEY PRIMERO_MESSAGE_SECRET ) + required=( PRIMERO_HOST POSTGRES_USER POSTGRES_PASSWORD PRIMERO_SECRET_KEY_BASE DEVISE_SECRET_KEY PRIMERO_MESSAGE_SECRET ) for var in "${required[@]}" do if [ -z "${!var}" ] diff --git a/docker/build.sh b/docker/build.sh index e526e925d8..00b5a3f56a 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -50,10 +50,8 @@ BUILD_NGINX="docker build -f nginx/Dockerfile . -t primero/nginx:${tag} -t ${rep BUILD_SOLR="docker build -f solr/Dockerfile ../ -t primero/solr:${tag} -t ${repository}/primero/solr:${tag} --build-arg BUILD_REGISTRY=${build_registry}" BUILD_APP="docker build -f application/Dockerfile ../ -t primero/application:${tag} -t ${repository}/primero/application:${tag} --build-arg APP_ROOT=${APP_ROOT} --build-arg RAILS_LOG_PATH=${RAILS_LOG_PATH} --build-arg APP_UID=${APP_UID} --build-arg APP_GID=${APP_GID} --build-arg BUILD_REGISTRY=${build_registry}" BUILD_MIGRATION="docker build -f migration/Dockerfile ../ -t primero/migration:${tag} -t ${repository}/primero/migration:${tag} --build-arg BUILD_REGISTRY=${build_registry} --build-arg PRIMERO_VERSION=${tag}" -BUILD_POSTGRES10="docker build -f postgres/Dockerfile . -t primero/postgres:${tag}-pg10 -t ${repository}/primero/postgres:${tag}-pg10 --build-arg BUILD_REGISTRY=${build_registry} --build-arg POSTGRES_VERSION=10.22" -BUILD_POSTGRES11="docker build -f postgres/Dockerfile . -t primero/postgres:${tag}-pg11 -t ${repository}/primero/postgres:${tag}-pg11 --build-arg BUILD_REGISTRY=${build_registry} --build-arg POSTGRES_VERSION=11.17" -BUILD_POSTGRES14="docker build -f postgres/Dockerfile . -t primero/postgres:${tag}-pg14 -t ${repository}/primero/postgres:${tag}-pg14 --build-arg BUILD_REGISTRY=${build_registry} --build-arg POSTGRES_VERSION=14.5" -BUILD_POSTGRES15="docker build -f postgres/Dockerfile . -t primero/postgres:${tag}-pg15 -t ${repository}/primero/postgres:${tag}-pg15 --build-arg BUILD_REGISTRY=${build_registry} --build-arg POSTGRES_VERSION=15.4" +BUILD_POSTGRES14="docker build -f postgres/Dockerfile . -t primero/postgres:${tag}-pg14 -t ${repository}/primero/postgres:${tag}-pg14 --build-arg BUILD_REGISTRY=${build_registry} --build-arg POSTGRES_VERSION=14.11 --build-arg ALPINE_VERSION=3.19" +BUILD_POSTGRES15="docker build -f postgres/Dockerfile . -t primero/postgres:${tag}-pg15 -t ${repository}/primero/postgres:${tag}-pg15 --build-arg BUILD_REGISTRY=${build_registry} --build-arg POSTGRES_VERSION=15.6 --build-arg ALPINE_VERSION=3.19" apply_tags () { local image=${1} @@ -87,8 +85,6 @@ case ${image} in eval "${BUILD_MIGRATION}" && apply_tags migration ;; postgres) - eval "${BUILD_POSTGRES10}" && apply_tags postgres pg10 - eval "${BUILD_POSTGRES11}" && apply_tags postgres pg11 eval "${BUILD_POSTGRES14}" && apply_tags postgres pg14 eval "${BUILD_POSTGRES15}" && apply_tags postgres pg15 ;; @@ -97,8 +93,6 @@ case ${image} in eval "${BUILD_MIGRATION}" && apply_tags migration eval "${BUILD_SOLR}" && apply_tags solr eval "${BUILD_NGINX}" && apply_tags nginx - eval "${BUILD_POSTGRES10}" && apply_tags postgres pg10 - eval "${BUILD_POSTGRES11}" && apply_tags postgres pg11 eval "${BUILD_POSTGRES14}" && apply_tags postgres pg14 eval "${BUILD_POSTGRES15}" && apply_tags postgres pg15 ;; diff --git a/docker/compose.configure.sh b/docker/compose.configure.sh index c12123fbe3..1d6da82aa4 100755 --- a/docker/compose.configure.sh +++ b/docker/compose.configure.sh @@ -17,4 +17,4 @@ then ENV_PRIMERO_CONFIGURATION_FILE="-e PRIMERO_CONFIGURATION_FILE=/primero-configuration/${PRIMERO_CONFIGURATION_FILE}" fi -./compose.prod.sh -f docker-compose.configure.yml run --rm ${CONFIGURATION_MOUNT} ${ENV_PRIMERO_CONFIGURATION_FILE} configure primero-bootstrap +./compose.prod.sh --profile configure -f docker-compose.configure.yml run --rm ${CONFIGURATION_MOUNT} ${ENV_PRIMERO_CONFIGURATION_FILE} configure primero-bootstrap diff --git a/docker/compose.local.sh b/docker/compose.local.sh index 37793e791d..040c95862f 100755 --- a/docker/compose.local.sh +++ b/docker/compose.local.sh @@ -1,5 +1,14 @@ #! /bin/sh # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. +: "${SOLR_ENABLED:=false}" + +SOLR_PROFILE="" + set -euox -exec "./compose.sh" -f "docker-compose.db.yml" -f "docker-compose.local.yml" "${@}" + +if [[ "${SOLR_ENABLED}" == 'true' ]] ; then + SOLR_PROFILE="--profile solr" +fi + +exec "./compose.sh" --profile db ${SOLR_PROFILE} -f "docker-compose.db.yml" -f "docker-compose.local.yml" "${@}" diff --git a/docker/compose.prod.sh b/docker/compose.prod.sh index 81d32794d9..b46ea97a43 100755 --- a/docker/compose.prod.sh +++ b/docker/compose.prod.sh @@ -2,11 +2,19 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. : "${PRIMERO_DEPLOY_NODB:=false}" +: "${SOLR_ENABLED:=false}" + +DB_PROFILE="" +SOLR_PROFILE="" set -euox if [[ "${PRIMERO_DEPLOY_NODB}" == 'false' ]] ; then - exec "./compose.sh" -f "docker-compose.prod.yml" -f "docker-compose.db.yml" "${@}" -else - exec "./compose.sh" -f "docker-compose.prod.yml" "${@}" + DB_PROFILE="--profile db" +fi + +if [[ "${SOLR_ENABLED}" == 'true' ]] ; then + SOLR_PROFILE="--profile solr" fi + +exec "./compose.sh" ${DB_PROFILE} ${SOLR_PROFILE} -f "docker-compose.prod.yml" -f "docker-compose.db.yml" "${@}" \ No newline at end of file diff --git a/docker/compose.sh b/docker/compose.sh index 428d79812b..8887c4df04 100755 --- a/docker/compose.sh +++ b/docker/compose.sh @@ -4,4 +4,4 @@ : "${PROJECT_NAME:=primero}" set -euox -exec docker-compose -p "${PROJECT_NAME}" --project-directory "../" -f "docker-compose.yml" "${@}" +exec docker compose -p "${PROJECT_NAME}" --project-directory "../" --profile app -f "docker-compose.yml" "${@}" diff --git a/docker/docker-compose.configure.yml b/docker/docker-compose.configure.yml index 64a0e6d57c..7e9867c993 100644 --- a/docker/docker-compose.configure.yml +++ b/docker/docker-compose.configure.yml @@ -1,7 +1,6 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. --- -version: '3' services: configure: image: '${PRIMERO_IMAGE_REPOSITORY:-primeroims}/application:${PRIMERO_TAG:-latest}' @@ -11,5 +10,9 @@ services: env_file: - docker/defaults.env - docker/local.env + profiles: + - configure depends_on: - - postgres + postgres: + condition: 'service_started' + required: false diff --git a/docker/docker-compose.db.yml b/docker/docker-compose.db.yml index 1fe4c6a522..5e7fb55f80 100644 --- a/docker/docker-compose.db.yml +++ b/docker/docker-compose.db.yml @@ -11,11 +11,25 @@ services: - docker/defaults.env - docker/local.env restart: always + profiles: + - db application: + profiles: + - app depends_on: - - solr - - postgres + solr: + condition: 'service_started' + required: false + postgres: + condition: 'service_started' + required: false worker: + profiles: + - app depends_on: - - solr - - postgres + solr: + condition: 'service_started' + required: false + postgres: + condition: 'service_started' + required: false diff --git a/docker/docker-compose.local.yml b/docker/docker-compose.local.yml index d94ca7e574..2f6f979688 100644 --- a/docker/docker-compose.local.yml +++ b/docker/docker-compose.local.yml @@ -30,6 +30,8 @@ services: - docker/local.env ports: - "8983:8983" + profiles: + - solr worker: env_file: - docker/defaults.env diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml index 37e11694fe..b43aefe16b 100644 --- a/docker/docker-compose.prod.yml +++ b/docker/docker-compose.prod.yml @@ -8,6 +8,8 @@ services: ports: - "80:80" - "443:443" + profiles: + - app volumes: - 'certbot_certificates:/etc/letsencrypt' - 'certbot_challenges:/usr/share/nginx/html/.well-known/acme-challenge' @@ -25,6 +27,8 @@ services: - docker/defaults.env - docker/local.env solr: + profiles: + - solr env_file: - docker/defaults.env - docker/local.env diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 247acaf2b1..ec6b7026ae 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -9,28 +9,38 @@ services: - docker/defaults.env volumes: - solr_cores:/var/solr + profiles: + - solr restart: always application: image: '${PRIMERO_IMAGE_REPOSITORY:-primeroims}/application:${PRIMERO_TAG:-latest}' depends_on: - - solr + solr: + condition: 'service_started' + required: false volumes: - public:/share/public - storage:/srv/primero/application/storage env_file: - docker/defaults.env + profiles: + - app stdin_open: true tty: true restart: always worker: image: '${PRIMERO_IMAGE_REPOSITORY:-primeroims}/application:${PRIMERO_TAG:-latest}' depends_on: - - solr + solr: + condition: 'service_started' + required: false volumes: - storage:/srv/primero/application/storage env_file: - docker/defaults.env command: ["primero-worker"] + profiles: + - app restart: always volumes: database: diff --git a/docker/local.env.sample.development b/docker/local.env.sample.development index 7814e25ab3..db1caed784 100644 --- a/docker/local.env.sample.development +++ b/docker/local.env.sample.development @@ -4,4 +4,3 @@ PRIMERO_SECRET_KEY_BASE=PRIMERO_SECRET_KEY_BASE POSTGRES_PASSWORD=primero POSTGRES_DB=primero_development DEVISE_SECRET_KEY=DEVISE_SECRET_KEY -DEVISE_JWT_SECRET_KEY=DEVISE_JWT_SECRET_KEY \ No newline at end of file diff --git a/docker/local.env.sample.production b/docker/local.env.sample.production index 1b4fd44824..ed4b1e5b97 100644 --- a/docker/local.env.sample.production +++ b/docker/local.env.sample.production @@ -22,7 +22,6 @@ POSTGRES_PASSWORD=mypassword PRIMERO_SECRET_KEY_BASE=xxxxx PRIMERO_MESSAGE_SECRET=xxxxx DEVISE_SECRET_KEY=xxxxx -DEVISE_JWT_SECRET_KEY=xxxxx # If you want to run a custom configuration script instead of the default seeds, # set PRIMERO_CONFIGURATION_FILE to the path on which the script is mounted on the container. diff --git a/docker/migration/Dockerfile b/docker/migration/Dockerfile index 3183a7388b..ac16c87bb6 100644 --- a/docker/migration/Dockerfile +++ b/docker/migration/Dockerfile @@ -1,10 +1,10 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - ARG BUILD_REGISTRY +ARG BUILD_REGISTRY ARG PRIMERO_VERSION FROM ${BUILD_REGISTRY}primero/application:${PRIMERO_VERSION} -ENV MIGRATION_PACKAGES postgresql-client openssh openssh-keygen rsync +ENV MIGRATION_PACKAGES="postgresql-client openssh openssh-keygen rsync" USER root RUN set -euox pipefail \ diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile index 32420e8772..dbe014a990 100644 --- a/docker/nginx/Dockerfile +++ b/docker/nginx/Dockerfile @@ -1,10 +1,13 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - ARG version=1.23.3 -ARG BUILD_REGISTRY +# ------------------------------------------------------------------ BUILD STAGE -FROM ${BUILD_REGISTRY}nginx:${version}-alpine AS builder +ARG BUILD_REGISTRY +ARG version=1.27.1 +# TODO: Although the rest of Primero uses Alpine 3.20 base images, Nginx doesn't have one. +ARG ALPINE_VERSION=3.20 +FROM ${BUILD_REGISTRY}nginx:${version}-alpine${ALPINE_VERSION} AS builder ARG version WORKDIR /root/ @@ -23,8 +26,12 @@ RUN apk add --update --no-cache build-base git pcre-dev openssl-dev zlib-dev lin --with-compat \ && make modules +# ------------------------------------------------------------------ FINAL STAGE + ARG BUILD_REGISTRY -FROM ${BUILD_REGISTRY}nginx:${version}-alpine +ARG version + +FROM ${BUILD_REGISTRY}nginx:${version}-alpine${ALPINE_VERSION} EXPOSE 80 443 ARG version @@ -32,6 +39,11 @@ ARG NGINX_UID ARG NGINX_GID ENV USER_ID=${NGINX_UID} ENV GROUP_ID=${NGINX_GID} +# TODO: +# If you are updating `version` or `ALPINE_VERSION`, +# run: `docker scout cves primero/nginx:my-tag` to verify whether the versions of the security packages +# listed in SECURITY_UPDATED_PACKAGES are still necessary. +ENV SECURITY_UPDATED_PACKAGES="libexpat>2.6.3-r0 curl>8.10" COPY [ "nginx/root/", "/" ] @@ -45,6 +57,7 @@ RUN set -ex \ ; chown -R docker-nginx:docker-nginx /certs \ ; apk update \ ; apk add openssl \ + ; apk add --no-cache $SECURITY_UPDATED_PACKAGES \ ; mkdir -p /etc/letsencrypt \ ; mkdir -p /etc/letsencrypt/accounts \ ; mkdir -p /etc/letsencrypt/archive \ diff --git a/docker/postgres/Dockerfile b/docker/postgres/Dockerfile index 33d05a9546..b7c735f26a 100644 --- a/docker/postgres/Dockerfile +++ b/docker/postgres/Dockerfile @@ -1,5 +1,18 @@ + # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - ARG BUILD_REGISTRY -ARG POSTGRES_VERSION=10.22 -FROM ${BUILD_REGISTRY}postgres:${POSTGRES_VERSION}-alpine +ARG BUILD_REGISTRY +ARG POSTGRES_VERSION=15.6 +ARG ALPINE_VERSION=3.19 +FROM ${BUILD_REGISTRY}postgres:${POSTGRES_VERSION}-alpine${ALPINE_VERSION} + +# TODO: +# If you are updating `POSTGRES_VERSION` or `ALPINE_VERSION`, +# run: `docker scout cves primero/postgres:my-tag` to verify whether the versions of the security packages +# listed in SECURITY_UPDATED_PACKAGES are still necessary. +ENV SECURITY_UPDATED_PACKAGES="openssl=3.1.7-r1 busybox=1.36.1-r19 libxml2=2.11.8-r0" + +RUN set -euox pipefail \ + ; apk update \ + ; apk add --no-cache $SECURITY_UPDATED_PACKAGES \ + ; rm -rf /var/cache/apk/* diff --git a/docker/solr/Dockerfile b/docker/solr/Dockerfile index 48feb0df6b..e0f3d865b6 100644 --- a/docker/solr/Dockerfile +++ b/docker/solr/Dockerfile @@ -1,7 +1,7 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - ARG BUILD_REGISTRY -FROM ${BUILD_REGISTRY}solr:8.11.2-slim +ARG BUILD_REGISTRY +FROM ${BUILD_REGISTRY}solr:8.11.3-slim ENV SOLR_PACKAGES gettext curl ENV SOLR_USER=solr diff --git a/jest.config.js b/jest.config.js index 8a58f65dcc..2e60d6207a 100644 --- a/jest.config.js +++ b/jest.config.js @@ -70,7 +70,7 @@ module.exports = { // globals: {}, // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. - // maxWorkers: "50%", + maxWorkers: 2, // An array of directory names to be searched recursively up from the requiring module's location moduleDirectories: ["node_modules", "./app/javascript/test-utils/index.js"], @@ -89,6 +89,8 @@ module.exports = { // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module moduleNameMapper: { + "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": + "/__mocks__/fileMock.js", ".+\\.(css|png|jpg|ttf|woff|woff2)$": "identity-obj-proxy" }, @@ -155,7 +157,9 @@ module.exports = { // testLocationInResults: false, // The glob patterns Jest uses to detect test files - testMatch: ["/components/**/*.spec.js"], + + // testMatch: ["/components/**/*.spec.js"], + testMatch: ["/components/**/*.spec.js", "/libs/**/*.spec.js"], // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped // testPathIgnorePatterns: ["/node_modules/"], diff --git a/lib/solr_utils.rb b/lib/solr_utils.rb index e8ed3f90ac..d00b2d650b 100644 --- a/lib/solr_utils.rb +++ b/lib/solr_utils.rb @@ -15,12 +15,8 @@ def self.sunspot_rsolr end # Retrieve the intenal Sunspot configuration for a model - def self.sunspot_setup(model) - clazz = model - unless clazz.is_a? Class - clazz = model == 'case' ? 'Child' : model.camelcase - clazz = Kernel.const_get(clazz) - end + def self.sunspot_setup(clazz) + clazz = PrimeroModelService.to_model(clazz.to_s) unless clazz.is_a? Class Sunspot::Setup.for(clazz) end diff --git a/lib/tasks/primero.rake b/lib/tasks/primero.rake index 720ddbcd98..3950e73d95 100644 --- a/lib/tasks/primero.rake +++ b/lib/tasks/primero.rake @@ -309,7 +309,7 @@ namespace :primero do task remove_config_data: :environment do # Adding in Field model because it is not included in CONFIGURABLE_MODELS but, you cannot delete FormSections # unless Fields are deleted first - config_data_models = [Field] + PrimeroConfiguration::CONFIGURABLE_MODELS.map { |m| Object.const_get(m) } + config_data_models = [Field] + PrimeroConfiguration::CONFIGURABLE_MODELS config_data_models.each do |m| puts "Deleting the database for #{m.name}" diff --git a/lib/tasks/sunspot.rake b/lib/tasks/sunspot.rake index 082f50b02b..2f715e318c 100644 --- a/lib/tasks/sunspot.rake +++ b/lib/tasks/sunspot.rake @@ -1,8 +1,9 @@ # frozen_string_literal: true +return if ActiveRecord::Type::Boolean.new.cast(ENV.fetch('SOLR_ENABLED', false)) == false + require 'sunspot/rails/tasks' require 'rsolr' - # Monekypatch: Use the same PID file for different rails envs # A single Solr instance has multiple cores (one each for every rails env) class Sunspot::Rails::Server @@ -14,6 +15,10 @@ end namespace :sunspot do desc 'Wait for solr to be started' task :wait, [:timeout] => :environment do |_, args| + unless Rails.configuration.solr_enabled + puts 'SolR not enabled' + next + end seconds = args[:timeout] ? args[:timeout].to_i : 30 puts "Waiting #{seconds} seconds for Solr to start..." @@ -25,6 +30,11 @@ namespace :sunspot do Rake::Task['sunspot:reindex'].clear desc 'Reindex all indexeable models' task reindex: :wait do + unless Rails.configuration.solr_enabled + puts 'Reindex not performed. SolR not enabled' + next + end + puts 'Reindexing Solr...' location_service = LocationService.new(true) [Child, Incident, TracingRequest, Trace, RegistryRecord, Family].each do |model| @@ -35,10 +45,13 @@ namespace :sunspot do desc 'Remove all records from Solr' task remove_all: :environment do + unless Rails.configuration.solr_enabled + puts 'SolR not enabled' + next + end + indexed_types = [ - Child, Incident, TracingRequest, - Flag, ReportableFollowUp, ReportableProtectionConcern, - ReportableService, Violation, Trace, RegistryRecord, Family + Child, Incident, TracingRequest, Trace, RegistryRecord, Family ] puts "Removing the following record types from the Solr index: #{indexed_types.join(', ')}" @@ -46,35 +59,13 @@ namespace :sunspot do end def batch_reindex(model, batch_size = 500, location_service = nil) + return unless Rails.configuration.solr_enabled + puts "Reindexing #{model.count} #{model.name} records in batches of #{batch_size}..." model.all.find_in_batches(batch_size:) do |records| records.each { |r| r.location_service = location_service } unless model == Trace Sunspot.index(records) - index_flags_for_records(model, records, batch_size) - index_nested_reportables_for_records(model, records, batch_size) - end - end - - def index_flags_for_records(model, records, batch_size) - return unless model.instance_methods.include?(:flags) - - flags = records.reduce([]) do |list, record| - list += record.flags if record.flags.present? - list - end - flags.each_slice(batch_size) { |batch| Sunspot.index(batch) } - end - - def index_nested_reportables_for_records(model, records, batch_size) - return unless model.instance_methods.include?(:nested_reportables_hash) - - nested_reportables = records.reduce([]) do |list, record| - record.nested_reportables_hash.each do |_, reportables| - list += reportables - end - list end - nested_reportables.each_slice(batch_size) { |batch| Sunspot.index(batch) } end end diff --git a/package-lock.json b/package-lock.json index 181b6f101d..f901a1c69a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,91 +1,92 @@ { "name": "primero", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "primero", "license": "AGPL-3.0", "dependencies": { + "@emotion/css": "^11.11.2", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "@mui/icons-material": "^5.15.20", + "@mui/lab": "^5.0.0-alpha.170", + "@mui/material": "^5.15.20", + "@mui/x-date-pickers": "^7.7.0", "@welldone-software/why-did-you-render": "^6.2.0", - "react-16-node-hanging-test-fix": "^1.0.0" + "formik-mui": "^5.0.0-alpha.0", + "stylis-plugin-rtl": "^2.1.1", + "tss-react": "^4.9.10" }, "devDependencies": { - "@azure/msal-browser": "^2.37.0", - "@babel/core": "~7.17.8", - "@babel/eslint-parser": "^7.17.0", + "@azure/msal-browser": "^3.17.0", + "@babel/core": "~7.24.7", + "@babel/eslint-parser": "^7.24.7", "@babel/plugin-proposal-class-properties": "~7.16.7", "@babel/plugin-proposal-object-rest-spread": "^7.17.3", "@babel/plugin-proposal-optional-chaining": "~7.16.7", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/plugin-syntax-dynamic-import": "~7.8.3", - "@babel/plugin-transform-destructuring": "~7.17.7", - "@babel/plugin-transform-regenerator": "~7.16.7", - "@babel/plugin-transform-runtime": "~7.17.0", - "@babel/preset-env": "^7.16.11", - "@babel/preset-react": "~7.16.7", - "@babel/register": "~7.17.7", + "@babel/plugin-transform-destructuring": "~7.24.7", + "@babel/plugin-transform-regenerator": "~7.24.7", + "@babel/plugin-transform-runtime": "~7.24.7", + "@babel/preset-env": "^7.24.7", + "@babel/preset-react": "~7.24.7", + "@babel/register": "~7.24.6", "@date-io/date-fns": "^1.3.13", - "@hookform/devtools": "^2.2.1", "@hookform/resolvers": "1.3.0", "@hot-loader/react-dom": "^17.0.2", - "@material-ui/core": "4.12.3", - "@material-ui/icons": "^4.11.2", - "@material-ui/lab": "^4.0.0-alpha.60", - "@material-ui/pickers": "^3.3.10", - "@material-ui/styles": "4.11.4", "@quoin/nepali-datepicker-reactjs": "^1.2.4", "@svgr/webpack": "^6.5.1", - "@swc/core": "^1.3.84", - "@swc/jest": "^0.2.29", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^12.1.4", - "@testing-library/react-hooks": "^7.0.0", - "@testing-library/user-event": "^14.4.3", - "@wojtekmaj/enzyme-adapter-react-17": "^0.4.1", + "@swc/core": "^1.5.29", + "@swc/jest": "^0.2.36", + "@testing-library/dom": "^10.1.0", + "@testing-library/jest-dom": "^6.4.6", + "@testing-library/react": "^16.0.0", + "@testing-library/react-hooks": "^8.0.1", + "@testing-library/user-event": "^14.5.2", "ad-bs-converter": "^0.5.0", "add": "^2.0.6", "babel-eslint": "^10.1.0", - "babel-jest": "^29.5.0", + "babel-jest": "^29.7.0", "babel-loader": "^8.2.3", "babel-plugin-dynamic-import-node": "^2.3.3", "babel-plugin-macros": "^3.1.0", - "babel-plugin-module-resolver": "^5.0.0", + "babel-plugin-module-resolver": "^5.0.2", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "babel-preset-react": "^6.24.1", "before-build-webpack": "^0.2.12", "bikram-sambat-js": "^1.0.1", - "blueimp-md5": "^2.13.0", + "blueimp-md5": "^2.19.0", "canvg": "^3.0.6", "chai": "^4.3.6", "chai-immutable": "^2.1.0", "chart.js": "^2.9.4", "clean-webpack-plugin": "^4.0.0", - "clsx": "^1.1.0", "compression-webpack-plugin": "^9.2.0", - "connected-react-router": "^6.8.0", - "core-js": "3.3.6", - "cross-env": "^7.0.3", + "connected-react-router": "^6.9.3", + "core-js": "3.37.1", "css-loader": "^6.7.1", - "date-fns": "2.1.0", - "deepmerge": "^4.0.0", + "date-fns": "^2.29.2", + "deepmerge": "^4.3.1", "dom-to-image-more": "2.8.0", - "dompurify": "^2.2.3", - "enzyme": "^3.11.0", + "dompurify": "^2.5.4", "eslint": "^8.11.0", "eslint-config-airbnb": "~19.0.4", "eslint-config-prettier": "~8.5.0", "eslint-import-resolver-alias": "^1.1.2", - "eslint-plugin-import": "~2.25.4", - "eslint-plugin-jest": "^27.2.1", - "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-import": "~2.29.1", + "eslint-plugin-jest": "^27.9.0", + "eslint-plugin-jsx-a11y": "^6.8.0", "eslint-plugin-prettier": "^4.0.0", - "eslint-plugin-react": "~7.29.4", - "eslint-plugin-react-hooks": "4.3.0", + "eslint-plugin-react": "~7.34.2", + "eslint-plugin-react-hooks": "4.6.2", "eslint-plugin-unused-imports": "^2.0.0", "fake-indexeddb": "^3.1.8", "file-loader": "^6.2.0", - "formik": "^2.2.9", - "formik-material-ui": "^3.0.1", + "formik": "^2.4.6", "fuzzysort": "^2.0.4", "history": "^4.9.0", "html2pdf-dom-to-image-more": "0.9.5", @@ -93,28 +94,25 @@ "idb": "^4.0.4", "identity-obj-proxy": "^3.0.0", "image-blob-reduce": "^1.0.4", - "immutable": "4.0.0-rc.12", + "immutable": "4.3.6", "jest": "^29.7.0", - "jest-environment-jsdom": "^29.5.0", + "jest-environment-jsdom": "^29.7.0", "jscpd": "^3.3.25", - "jsdom": "^16.4.0", + "jsdom": "^24.1.0", "jsdom-global": "^3.0.2", - "jspdf": "^2.3.1", - "jss": "10.8.2", - "jss-plugin-extend": "10.8.2", - "jss-rtl": "^0.3.0", + "jspdf": "^2.5.1", "keyevent": "^1.1.0", "lodash": "^4.17.21", - "mini-css-extract-plugin": "2.4.4", + "mini-css-extract-plugin": "2.9.0", "minimist-lite": "^2.2.1", "mocha": "^9.2.2", - "mui-datatables": "^3.8.5", - "mui-nepali-datepicker-reactjs": "^1.1.4", + "mui-datatables": "^4.3.0", + "mui-nepali-datepicker-reactjs": "^2.0.0", "mutationobserver-shim": "^0.3.5", "nock": "^10.0.6", - "normalizr": "^3.6.0", - "notistack": "^0.9.17", - "nyc": "^14.1.1", + "normalizr": "^3.6.2", + "notistack": "^2.0.8", + "nyc": "^17.1.0", "postcss-flexbugs-fixes": "^5.0.2", "postcss-import": "^14.0.2", "postcss-loader": "^6.2.1", @@ -122,21 +120,21 @@ "postcss-rtlcss": "^3.5.3", "prettier": "^2.6.0", "prettier-eslint": "~13.0.0", - "prop-types": "^15.7.2", + "prop-types": "^15.8.1", "proxy-memoize": "^2.0.3", - "qs": "^6.9.3", + "qs": "^6.12.1", "re-reselect": "^4.0.0", - "react": "^17.0.2", - "react-beautiful-dnd": "^13.0.0", - "react-dom": "^17.0.2", + "react": "^18.3.1", + "react-beautiful-dnd": "^13.1.1", + "react-dom": "^18.3.1", "react-hook-form": "6.15.1", - "react-idle-timer": "^5.6.2", + "react-idle-timer": "^5.7.2", "react-redux": "^7.2.4", "react-router-dom": "^5.0.1", - "react-router-navigation-prompt": "^1.8.11", + "react-router-navigation-prompt": "^1.9.6", "react-spaces": "^0.3.2", - "react-test-renderer": "^17.0.2", - "react-window": "^1.8.6", + "react-test-renderer": "^18.3.1", + "react-window": "^1.8.10", "reduce-reducers": "^1.0.4", "redux": "^4.1.0", "redux-immutable": "^4.0.0", @@ -147,12 +145,13 @@ "require-hacker": "^3.0.1", "reselect": "^4.0.0", "sinon": "^7.2.4", - "sinon-chai": "^3.5.0", + "sinon-chai": "^3.7.0", "style-loader": "^2.0.0", - "timezone-mock": "^1.0.18", + "stylis": "^4.2.0", + "timezone-mock": "^1.3.6", "uuid": "^8.3.2", - "webpack": "^5.76.0", - "webpack-assets-manifest": "^5.1.0", + "webpack": "^5.92.0", + "webpack-assets-manifest": "^5.2.1", "webpack-cli": "^4.9.2", "webpack-dev-server": "^4.7.4", "workbox-cacheable-response": "^5.1.4", @@ -164,20 +163,18 @@ "yup": "^0.32.9" }, "engines": { - "node": ">=18.13.0" + "node": ">=20.14.0" } }, "node_modules/@adobe/css-tools": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", - "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", - "dev": true + "version": "4.4.0", + "dev": true, + "license": "MIT" }, "node_modules/@ampproject/remapping": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -188,9 +185,8 @@ }, "node_modules/@ampproject/remapping/node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -200,69 +196,65 @@ } }, "node_modules/@azure/msal-browser": { - "version": "2.37.0", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-2.37.0.tgz", - "integrity": "sha512-YNGD/W/tw/5wDWlXOfmrVILaxVsorVLxYU2ovmL1PDvxkdudbQRyGk/76l4emqgDAl/kPQeqyivxjOU6w1YfvQ==", + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.17.0.tgz", + "integrity": "sha512-csccKXmW2z7EkZ0I3yAoW/offQt+JECdTIV/KrnRoZyM7wCSsQWODpwod8ZhYy7iOyamcHApR9uCh0oD1M+0/A==", "dev": true, "dependencies": { - "@azure/msal-common": "13.0.0" + "@azure/msal-common": "14.12.0" }, "engines": { "node": ">=0.8.0" } }, "node_modules/@azure/msal-common": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-13.0.0.tgz", - "integrity": "sha512-GqCOg5H5bouvLij9NFXFkh+asRRxsPBRwnTDsfK7o0KcxYHJbuidKw8/VXpycahGXNxgtuhqtK/n5he+5NhyEA==", + "version": "14.12.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.12.0.tgz", + "integrity": "sha512-IDDXmzfdwmDkv4SSmMEyAniJf6fDu3FJ7ncOjlxkDuT85uSnLEhZi3fGZpoR7T4XZpOMx9teM9GXBgrfJgyeBw==", "dev": true, "engines": { "node": ">=0.8.0" } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, + "version": "7.24.7", + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", - "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", + "version": "7.24.7", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.8.tgz", - "integrity": "sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.7", - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.8", - "@babel/parser": "^7.17.8", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", + "version": "7.24.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helpers": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -272,33 +264,35 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, "node_modules/@babel/eslint-parser": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.17.0.tgz", - "integrity": "sha512-PUEJ7ZBXbRkbq3qqM/jZ2nIuakUBqCYc7Qf52Lj7dlZ6zERnqisdHioL0l4wwQZnmskMeasqUNzLBFKs3nylXA==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "eslint-scope": "^5.1.1", + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || >=14.0.0" }, "peerDependencies": { - "@babel/core": ">=7.11.0", - "eslint": "^7.5.0 || ^8.0.0" + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, + "version": "7.24.7", + "license": "MIT", "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -306,78 +300,70 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", - "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.21.4", - "@babel/helper-validator-option": "^7.21.0", - "browserslist": "^4.21.3", + "@babel/compat-data": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.4.tgz", - "integrity": "sha512-46QrX2CQlaFRF4TkwfTt6nJD7IHq8539cCL7SDpqWSDeJKY1xylKKY5F/33mJhLZ3mFvKv2gGrVS6NkyF6qs+Q==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-member-expression-to-functions": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/helper-split-export-declaration": "^7.18.6" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -387,13 +373,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.4.tgz", - "integrity": "sha512-M00OuhU+0GyZ5iBBN9czjugzWrEq2vDpf/zCYHxxf93ul/Q5rv+a5h+/+0WnI1AebHNVtl5bFV0qsJoH23DbfA==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.3.1" + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -403,142 +389,119 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", - "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", + "version": "0.6.2", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" + "resolve": "^1.14.2" }, "peerDependencies": { - "@babel/core": "^7.4.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", - "dev": true, + "version": "7.24.7", + "license": "MIT", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, + "version": "7.24.7", + "license": "MIT", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, + "version": "7.24.7", + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz", - "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.21.0" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", - "dev": true, + "version": "7.24.7", + "license": "MIT", "dependencies": { - "@babel/types": "^7.21.4" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "version": "7.24.7", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", - "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-wrap-function": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -548,133 +511,119 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", - "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.20.7", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.20.2" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", - "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.20.0" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, + "version": "7.24.7", + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true, + "version": "7.24.7", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, + "version": "7.24.7", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "version": "7.24.7", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", - "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" + "@babel/helper-function-name": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, + "version": "7.24.7", + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true, + "version": "7.24.7", + "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -682,13 +631,13 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", - "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -697,63 +646,55 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz", - "integrity": "sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==", + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-proposal-optional-chaining": "^7.20.7" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.13.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.13.0" } }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", - "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, "node_modules/@babel/plugin-proposal-class-properties": { "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", - "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" @@ -765,124 +706,10 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", - "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", - "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-proposal-object-rest-spread": { "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.20.5", "@babel/helper-compilation-targets": "^7.20.7", @@ -897,27 +724,10 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-proposal-optional-chaining": { "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", - "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", @@ -932,9 +742,8 @@ }, "node_modules/@babel/plugin-proposal-private-methods": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -947,10 +756,9 @@ } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz", - "integrity": "sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==", + "version": "7.21.11", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-create-class-features-plugin": "^7.21.0", @@ -964,27 +772,10 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -994,9 +785,8 @@ }, "node_modules/@babel/plugin-syntax-bigint": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1006,9 +796,8 @@ }, "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -1018,9 +807,8 @@ }, "node_modules/@babel/plugin-syntax-class-static-block": { "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1033,9 +821,8 @@ }, "node_modules/@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1045,9 +832,8 @@ }, "node_modules/@babel/plugin-syntax-export-namespace-from": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -1056,12 +842,25 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz", - "integrity": "sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==", + "version": "7.24.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1072,9 +871,8 @@ }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -1084,9 +882,8 @@ }, "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1095,12 +892,11 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", - "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1111,9 +907,8 @@ }, "node_modules/@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -1123,9 +918,8 @@ }, "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1135,9 +929,8 @@ }, "node_modules/@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -1147,9 +940,8 @@ }, "node_modules/@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1159,9 +951,8 @@ }, "node_modules/@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1171,9 +962,8 @@ }, "node_modules/@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1183,9 +973,8 @@ }, "node_modules/@babel/plugin-syntax-private-property-in-object": { "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1198,9 +987,8 @@ }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1213,9 +1001,8 @@ }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz", - "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" }, @@ -1226,30 +1013,27 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", - "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", - "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1258,13 +1042,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", - "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7", + "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { "node": ">=6.9.0" @@ -1273,13 +1059,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", - "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1288,21 +1075,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz", - "integrity": "sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==", + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1311,14 +1089,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", - "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/template": "^7.20.7" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1327,13 +1103,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.7.tgz", - "integrity": "sha512-XVh0r5yq9sLR4vZ6eVZe8FKfIcSgaTBxVBRSYokRj2qksf6QerYnTxz9/GTuKTH/n/HwLP7t6gtlybHetJ/6hQ==", + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1342,29 +1118,35 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", - "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.12.0" } }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", - "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", + "node_modules/@babel/plugin-transform-classes": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" @@ -1373,14 +1155,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", - "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1389,13 +1170,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz", - "integrity": "sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==", + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1404,15 +1184,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", - "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1421,13 +1199,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", - "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1436,13 +1213,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", - "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -1451,14 +1228,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", - "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1467,15 +1243,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", - "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-simple-access": "^7.20.2" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -1484,16 +1258,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", - "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-identifier": "^7.19.1" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1502,14 +1273,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", - "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1518,29 +1289,27 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", - "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.20.5", - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", - "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", + "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1549,14 +1318,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", - "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { "node": ">=6.9.0" @@ -1565,13 +1333,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz", - "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==", + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1580,13 +1347,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", - "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1595,13 +1362,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.21.3.tgz", - "integrity": "sha512-4DVcFeWe/yDYBLp0kBmOGFJ6N2UYg7coGid1gdxb4co62dy/xISDMaYBXBVXEDhfgMk7qkbcYiGtwd5Q/hwDDQ==", + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1610,13 +1378,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", - "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1625,17 +1395,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.21.0.tgz", - "integrity": "sha512-6OAWljMvQrZjR2DaNhVfRz6dkCAVV+ymcLUmaf8bccGOHn2v5rHJK3tTpij0BuhdYWP4LLaqj5lwcdlpAAPuvg==", + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-jsx": "^7.18.6", - "@babel/types": "^7.21.0" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1644,29 +1410,27 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", - "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.18.6" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", - "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1675,13 +1439,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", - "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "regenerator-transform": "^0.14.2" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -1690,13 +1454,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", - "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { "node": ">=6.9.0" @@ -1705,18 +1469,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz", - "integrity": "sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A==", + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "babel-plugin-polyfill-corejs2": "^0.3.0", - "babel-plugin-polyfill-corejs3": "^0.5.0", - "babel-plugin-polyfill-regenerator": "^0.3.0", - "semver": "^6.3.0" + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1725,13 +1486,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", - "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1740,14 +1501,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", - "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -1756,13 +1516,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", - "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { "node": ">=6.9.0" @@ -1771,13 +1532,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", - "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1786,13 +1546,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", - "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1801,16 +1561,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.3.tgz", - "integrity": "sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==", + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-typescript": "^7.20.0" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { "node": ">=6.9.0" @@ -1819,13 +1578,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", - "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1834,14 +1592,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", - "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.21.3", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1850,87 +1606,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.21.4.tgz", - "integrity": "sha512-2W57zHs2yDLm6GD5ZpvNn71lZ0B/iypSdIeq25OurDKji6AdzV07qp4s3n1/x5BqtiGaTrPN3nerlSCaC5qNTw==", + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.21.0", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.20.7", - "@babel/plugin-proposal-async-generator-functions": "^7.20.7", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.21.0", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.20.7", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.20.7", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.21.0", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.21.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.20.0", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.20.7", - "@babel/plugin-transform-async-to-generator": "^7.20.7", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.21.0", - "@babel/plugin-transform-classes": "^7.21.0", - "@babel/plugin-transform-computed-properties": "^7.20.7", - "@babel/plugin-transform-destructuring": "^7.21.3", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.9", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.21.0", - "@babel/plugin-transform-function-name": "^7.18.9", - "@babel/plugin-transform-literals": "^7.18.9", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.20.11", - "@babel/plugin-transform-modules-commonjs": "^7.21.2", - "@babel/plugin-transform-modules-systemjs": "^7.20.11", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.20.5", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.21.3", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.20.5", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.20.7", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.9", - "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.21.4", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "core-js-compat": "^3.25.1", - "semver": "^6.3.0" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1939,14 +1620,16 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1955,15 +1638,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "@babel/plugin-transform-react-jsx": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1972,13 +1652,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/@babel/plugin-transform-destructuring": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz", - "integrity": "sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==", + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1987,14 +1667,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/@babel/plugin-transform-regenerator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", - "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "regenerator-transform": "^0.15.1" + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" }, "engines": { "node": ">=6.9.0" @@ -2003,68 +1682,45 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", - "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3", - "core-js-compat": "^3.25.1" + "@babel/helper-plugin-utils": "^7.24.7" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", - "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/regenerator-transform": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", - "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-react": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz", - "integrity": "sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==", + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-transform-react-display-name": "^7.16.7", - "@babel/plugin-transform-react-jsx": "^7.16.7", - "@babel/plugin-transform-react-jsx-development": "^7.16.7", - "@babel/plugin-transform-react-pure-annotations": "^7.16.7" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2073,17 +1729,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-typescript": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.21.4.tgz", - "integrity": "sha512-sMLNWY37TCdRH/bJ6ZeeOH1nPuanED7Ai9Y/vH31IPqalioJ6ZNFUWONsakhv4r4n+I6gm5lmoE0olkgib/j/A==", + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.21.0", - "@babel/plugin-syntax-jsx": "^7.21.4", - "@babel/plugin-transform-modules-commonjs": "^7.21.2", - "@babel/plugin-transform-typescript": "^7.21.3" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2092,17 +1744,12 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/register": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.17.7.tgz", - "integrity": "sha512-fg56SwvXRifootQEDQAu1mKdjh5uthPzdO0N6t358FktfL4XjAVXuH58ULoiW8mesxiOgNIrxiImqEwv0+hRRA==", + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "clone-deep": "^4.0.1", - "find-cache-dir": "^2.0.0", - "make-dir": "^2.1.0", - "pirates": "^4.0.5", - "source-map-support": "^0.5.16" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2111,143 +1758,409 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true - }, - "node_modules/@babel/runtime": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.8.tgz", - "integrity": "sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==", + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "regenerator-runtime": "^0.13.4" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/runtime-corejs3": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.8.tgz", - "integrity": "sha512-ZbYSUvoSF6dXZmMl/CYTMOvzIFnbGfv4W3SEHYgMvNsFTeLaF2gkGAF4K2ddmtSK4Emej+0aYcnSC6N5dPCXUQ==", + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "core-js-pure": "^3.20.2", - "regenerator-runtime": "^0.13.4" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.21.3", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-typescript": "^7.20.0" }, "engines": { "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@csstools/postcss-color-function": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.0.3.tgz", - "integrity": "sha512-J26I69pT2B3MYiLY/uzCGKVJyMYVg9TCpXkWsRlt+Yfq+nELUEm72QXIMYXs4xA9cJA4Oqs2EylrfokKl3mJEQ==", + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { - "node": "^12 || ^14 || >=16" + "node": ">=6.9.0" }, "peerDependencies": { - "postcss": "^8.4" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@csstools/postcss-font-format-keywords": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.0.tgz", - "integrity": "sha512-oO0cZt8do8FdVBX8INftvIA4lUrKUSCcWUf9IwH9IPWOgKT22oAZFXeHLoDK7nhB2SmkNycp5brxfNMRLIhd6Q==", + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "postcss-value-parser": "^4.2.0" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { - "node": "^12 || ^14 || >=16" + "node": ">=6.9.0" }, "peerDependencies": { - "postcss": "^8.3" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@csstools/postcss-hwb-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.0.tgz", - "integrity": "sha512-VSTd7hGjmde4rTj1rR30sokY3ONJph1reCBTUXqeW1fKwETPy1x4t/XIeaaqbMbC5Xg4SM/lyXZ2S8NELT2TaA==", + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.7", "dev": true, + "license": "MIT", "dependencies": { - "postcss-value-parser": "^4.2.0" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { - "node": "^12 || ^14 || >=16" + "node": ">=6.9.0" }, "peerDependencies": { - "postcss": "^8.3" + "@babel/core": "^7.0.0" } }, - "node_modules/@csstools/postcss-ic-unit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.0.tgz", - "integrity": "sha512-i4yps1mBp2ijrx7E96RXrQXQQHm6F4ym1TOD0D69/sjDjZvQ22tqiEvaNw7pFZTUO5b9vWRHzbHzP9+UKuw+bA==", - "dev": true, + "node_modules/@babel/preset-env": { + "version": "7.24.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.24.7", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.24.7", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.7", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.24.7", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.24.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-modules-systemjs": "^7.24.7", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.7", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.24.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.21.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-option": "^7.21.0", + "@babel/plugin-syntax-jsx": "^7.21.4", + "@babel/plugin-transform-modules-commonjs": "^7.21.2", + "@babel/plugin-transform-typescript": "^7.21.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.24.6", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/runtime": { + "version": "7.24.7", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.17.8", + "dev": true, + "license": "MIT", + "dependencies": { + "core-js-pure": "^3.20.2", + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.14.1", + "license": "MIT" + }, + "node_modules/@babel/template": { + "version": "7.24.7", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.7", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.24.7", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@csstools/postcss-color-function": { + "version": "1.0.3", + "dev": true, + "license": "CC0-1.0", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "1.0.0", + "dev": true, + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/@csstools/postcss-hwb-function": { + "version": "1.0.0", + "dev": true, + "license": "CC0-1.0", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/@csstools/postcss-ic-unit": { + "version": "1.0.0", + "dev": true, + "license": "CC0-1.0", "dependencies": { "@csstools/postcss-progressive-custom-properties": "^1.1.0", "postcss-value-parser": "^4.2.0" @@ -2261,9 +2174,8 @@ }, "node_modules/@csstools/postcss-is-pseudo-class": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.1.tgz", - "integrity": "sha512-Og5RrTzwFhrKoA79c3MLkfrIBYmwuf/X83s+JQtz/Dkk/MpsaKtqHV1OOzYkogQ+tj3oYp5Mq39XotBXNqVc3Q==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-selector-parser": "^6.0.9" }, @@ -2276,9 +2188,8 @@ }, "node_modules/@csstools/postcss-normalize-display-values": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.0.tgz", - "integrity": "sha512-bX+nx5V8XTJEmGtpWTO6kywdS725t71YSLlxWt78XoHUbELWgoCXeOFymRJmL3SU1TLlKSIi7v52EWqe60vJTQ==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -2291,9 +2202,8 @@ }, "node_modules/@csstools/postcss-oklab-function": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.0.2.tgz", - "integrity": "sha512-QwhWesEkMlp4narAwUi6pgc6kcooh8cC7zfxa9LSQNYXqzcdNUtNBzbGc5nuyAVreb7uf5Ox4qH1vYT3GA1wOg==", "dev": true, + "license": "CC0-1.0", "dependencies": { "@csstools/postcss-progressive-custom-properties": "^1.1.0", "postcss-value-parser": "^4.2.0" @@ -2307,9 +2217,8 @@ }, "node_modules/@csstools/postcss-progressive-custom-properties": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", - "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -2322,15 +2231,13 @@ }, "node_modules/@date-io/core": { "version": "1.3.13", - "resolved": "https://registry.npmjs.org/@date-io/core/-/core-1.3.13.tgz", - "integrity": "sha512-AlEKV7TxjeK+jxWVKcCFrfYAk8spX9aCyiToFIiLPtfQbsjmRGLIhb5VZgptQcJdHtLXo7+m0DuurwFgUToQuA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@date-io/date-fns": { "version": "1.3.13", - "resolved": "https://registry.npmjs.org/@date-io/date-fns/-/date-fns-1.3.13.tgz", - "integrity": "sha512-yXxGzcRUPcogiMj58wVgFjc9qUYrCnnU9eLcyNbsQCmae4jPuZCDoIBR21j8ZURsM7GRtU62VOw5yNd4dDHunA==", "dev": true, + "license": "MIT", "dependencies": { "@date-io/core": "^1.3.13" }, @@ -2340,152 +2247,298 @@ }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" } }, - "node_modules/@emotion/cache": { - "version": "10.0.29", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz", - "integrity": "sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==", - "dev": true, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "license": "MIT", "dependencies": { - "@emotion/sheet": "0.9.4", - "@emotion/stylis": "0.8.5", - "@emotion/utils": "0.11.3", - "@emotion/weak-memoize": "0.2.5" + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" } }, - "node_modules/@emotion/core": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/@emotion/core/-/core-10.3.1.tgz", - "integrity": "sha512-447aUEjPIm0MnE6QYIaFz9VQOHSXf4Iu6EWOIqq11EAPqinkSZmfymPTmlOE3QjLv846lH4JVZBUOtwGbuQoww==", - "dev": true, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/hash": { + "version": "0.9.1", + "license": "MIT" + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/memoize": { + "version": "0.8.1", + "license": "MIT" + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/serialize": { + "version": "1.1.4", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.5.5", - "@emotion/cache": "^10.0.27", - "@emotion/css": "^10.0.27", - "@emotion/serialize": "^0.11.15", - "@emotion/sheet": "0.9.4", - "@emotion/utils": "0.11.3" + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/unitless": { + "version": "0.8.1", + "license": "MIT" + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/utils": { + "version": "1.2.1", + "license": "MIT" + }, + "node_modules/@emotion/babel-plugin/node_modules/csstype": { + "version": "3.1.3", + "license": "MIT" + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=10" }, - "peerDependencies": { - "react": ">=16.3.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "dependencies": { + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" } }, + "node_modules/@emotion/cache/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/cache/node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, "node_modules/@emotion/css": { - "version": "10.0.27", - "resolved": "https://registry.npmjs.org/@emotion/css/-/css-10.0.27.tgz", - "integrity": "sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw==", - "dev": true, + "version": "11.11.2", + "license": "MIT", "dependencies": { - "@emotion/serialize": "^0.11.15", - "@emotion/utils": "0.11.3", - "babel-plugin-emotion": "^10.0.27" + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.2", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1" + } + }, + "node_modules/@emotion/css/node_modules/@emotion/hash": { + "version": "0.9.1", + "license": "MIT" + }, + "node_modules/@emotion/css/node_modules/@emotion/memoize": { + "version": "0.8.1", + "license": "MIT" + }, + "node_modules/@emotion/css/node_modules/@emotion/serialize": { + "version": "1.1.4", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" } }, + "node_modules/@emotion/css/node_modules/@emotion/unitless": { + "version": "0.8.1", + "license": "MIT" + }, + "node_modules/@emotion/css/node_modules/@emotion/utils": { + "version": "1.2.1", + "license": "MIT" + }, + "node_modules/@emotion/css/node_modules/csstype": { + "version": "3.1.3", + "license": "MIT" + }, "node_modules/@emotion/hash": { "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", - "dev": true + "license": "MIT" }, "node_modules/@emotion/is-prop-valid": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", - "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", - "dev": true, + "version": "1.2.2", + "license": "MIT", "dependencies": { - "@emotion/memoize": "0.7.4" + "@emotion/memoize": "^0.8.1" } }, + "node_modules/@emotion/is-prop-valid/node_modules/@emotion/memoize": { + "version": "0.8.1", + "license": "MIT" + }, "node_modules/@emotion/memoize": { "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", - "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", - "dev": true - }, - "node_modules/@emotion/serialize": { - "version": "0.11.16", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.11.16.tgz", - "integrity": "sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==", - "dev": true, - "dependencies": { - "@emotion/hash": "0.8.0", - "@emotion/memoize": "0.7.4", - "@emotion/unitless": "0.7.5", - "@emotion/utils": "0.11.3", - "csstype": "^2.5.7" - } + "license": "MIT" }, - "node_modules/@emotion/sheet": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-0.9.4.tgz", - "integrity": "sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==", - "dev": true - }, - "node_modules/@emotion/styled": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-10.3.0.tgz", - "integrity": "sha512-GgcUpXBBEU5ido+/p/mCT2/Xx+Oqmp9JzQRuC+a4lYM4i4LBBn/dWvc0rQ19N9ObA8/T4NWMrPNe79kMBDJqoQ==", - "dev": true, + "node_modules/@emotion/react": { + "version": "11.11.4", + "license": "MIT", "dependencies": { - "@emotion/styled-base": "^10.3.0", - "babel-plugin-emotion": "^10.0.27" + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" }, "peerDependencies": { - "@emotion/core": "^10.0.27", - "react": ">=16.3.0" + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@emotion/styled-base": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@emotion/styled-base/-/styled-base-10.3.0.tgz", - "integrity": "sha512-PBRqsVKR7QRNkmfH78hTSSwHWcwDpecH9W6heujWAcyp2wdz/64PP73s7fWS1dIPm8/Exc8JAzYS8dEWXjv60w==", - "dev": true, + "node_modules/@emotion/react/node_modules/@emotion/hash": { + "version": "0.9.1", + "license": "MIT" + }, + "node_modules/@emotion/react/node_modules/@emotion/memoize": { + "version": "0.8.1", + "license": "MIT" + }, + "node_modules/@emotion/react/node_modules/@emotion/serialize": { + "version": "1.1.4", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.5.5", - "@emotion/is-prop-valid": "0.8.8", - "@emotion/serialize": "^0.11.15", - "@emotion/utils": "0.11.3" + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/react/node_modules/@emotion/unitless": { + "version": "0.8.1", + "license": "MIT" + }, + "node_modules/@emotion/react/node_modules/@emotion/utils": { + "version": "1.2.1", + "license": "MIT" + }, + "node_modules/@emotion/react/node_modules/csstype": { + "version": "3.1.3", + "license": "MIT" + }, + "node_modules/@emotion/serialize": { + "version": "0.11.16", + "license": "MIT", + "dependencies": { + "@emotion/hash": "0.8.0", + "@emotion/memoize": "0.7.4", + "@emotion/unitless": "0.7.5", + "@emotion/utils": "0.11.3", + "csstype": "^2.5.7" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + }, + "node_modules/@emotion/styled": { + "version": "11.11.5", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/is-prop-valid": "^1.2.2", + "@emotion/serialize": "^1.1.4", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1" }, "peerDependencies": { - "@emotion/core": "^10.0.28", - "react": ">=16.3.0" + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@emotion/stylis": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", - "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==", - "dev": true + "node_modules/@emotion/styled/node_modules/@emotion/hash": { + "version": "0.9.1", + "license": "MIT" + }, + "node_modules/@emotion/styled/node_modules/@emotion/memoize": { + "version": "0.8.1", + "license": "MIT" + }, + "node_modules/@emotion/styled/node_modules/@emotion/serialize": { + "version": "1.1.4", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/styled/node_modules/@emotion/unitless": { + "version": "0.8.1", + "license": "MIT" + }, + "node_modules/@emotion/styled/node_modules/@emotion/utils": { + "version": "1.2.1", + "license": "MIT" + }, + "node_modules/@emotion/styled/node_modules/csstype": { + "version": "3.1.3", + "license": "MIT" }, "node_modules/@emotion/unitless": { "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", - "dev": true + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } }, "node_modules/@emotion/utils": { "version": "0.11.3", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.11.3.tgz", - "integrity": "sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==", - "dev": true + "license": "MIT" }, "node_modules/@emotion/weak-memoize": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", - "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==", - "dev": true + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -2498,9 +2551,8 @@ }, "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2510,9 +2562,8 @@ }, "node_modules/@eslint/eslintrc": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -2530,9 +2581,8 @@ }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -2545,9 +2595,8 @@ }, "node_modules/@eslint/eslintrc/node_modules/type-fest": { "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -2555,49 +2604,48 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@hookform/devtools": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@hookform/devtools/-/devtools-2.2.1.tgz", - "integrity": "sha512-VQh4kqwUOpz9LCDzIP0aJ4qnD/ob8Gp09L8gDy++9XtL66z6g8kbCynUvBrJm4qbCNdH0M7/Spm3AUjJqUuFlA==", - "dev": true, + "node_modules/@floating-ui/core": { + "version": "1.6.2", + "license": "MIT", "dependencies": { - "@emotion/core": "^10.0.28", - "@emotion/styled": "^10.0.27", - "@types/lodash": "^4.14.152", - "little-state-machine": "^3.0.1", - "lodash": "^4.17.15", - "react-simple-animate": "^3.3.8" + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.5", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" }, "peerDependencies": { "react": ">=16.8.0", - "react-dom": ">=16.8.0", - "react-hook-form": ">=6.5.0" + "react-dom": ">=16.8.0" } }, - "node_modules/@hookform/devtools/node_modules/little-state-machine": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/little-state-machine/-/little-state-machine-3.1.4.tgz", - "integrity": "sha512-gYlLCj6oUME0NG34/2O0Ljy52qYYyYDJ5yiAuq2ijbaRlBKIqtQQkKkEYn0KfjYXCE693j+bdY22EyZin25Bhw==", - "dev": true, - "peerDependencies": { - "react": "^16.8.0", - "react-dom": "^16.8.0" - } + "node_modules/@floating-ui/utils": { + "version": "0.2.2", + "license": "MIT" }, "node_modules/@hookform/resolvers": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-1.3.0.tgz", - "integrity": "sha512-NF+KJYDiFjnGAqhM92vG5kFJFCZFFjO5VxcByf06o6FrG7BEta5NDBhqVsIAMSfMNsn1kWfSKX1TkDT21xq9Hg==", "dev": true, + "license": "MIT", "peerDependencies": { "react-hook-form": ">=6.6.0" } }, "node_modules/@hot-loader/react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/@hot-loader/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-G2RZrFhsQClS+bdDh/Ojpk3SgocLPUGnvnJDTQYnmKSSwXtU+Yh+8QMs+Ia3zaAvBiOSpIIDSUxuN69cvKqrWg==", + "version": "17.0.2+4.13.0", "dev": true, + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -2609,9 +2657,8 @@ }, "node_modules/@humanwhocodes/config-array": { "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", @@ -2623,15 +2670,13 @@ }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -2645,40 +2690,24 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -2687,86 +2716,26 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@jest/console": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -2781,9 +2750,8 @@ }, "node_modules/@jest/console/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -2796,9 +2764,8 @@ }, "node_modules/@jest/console/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2812,9 +2779,8 @@ }, "node_modules/@jest/console/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -2824,18 +2790,16 @@ }, "node_modules/@jest/console/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@jest/console/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -2845,9 +2809,8 @@ }, "node_modules/@jest/core": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/reporters": "^29.7.0", @@ -2892,9 +2855,8 @@ }, "node_modules/@jest/core/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -2907,9 +2869,8 @@ }, "node_modules/@jest/core/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2923,9 +2884,8 @@ }, "node_modules/@jest/core/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -2935,18 +2895,16 @@ }, "node_modules/@jest/core/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@jest/core/node_modules/pretty-format": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -2958,9 +2916,8 @@ }, "node_modules/@jest/core/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2970,15 +2927,13 @@ }, "node_modules/@jest/core/node_modules/react-is": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jest/core/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -2987,111 +2942,20 @@ } }, "node_modules/@jest/create-cache-key-function": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-27.5.1.tgz", - "integrity": "sha512-dmH1yW+makpTSURTy8VzdUwFnfQh1G8R+DxO2Ho2FFmBbKFEVm+3jWdvFhE2VqB/LATCTokkP0dotjyQyw5/AQ==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/create-cache-key-function/node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/create-cache-key-function/node_modules/@types/yargs": { - "version": "16.0.5", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", - "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@jest/create-cache-key-function/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/create-cache-key-function/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/create-cache-key-function/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/create-cache-key-function/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/create-cache-key-function/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "29.7.0", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "@jest/types": "^29.6.3" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/environment": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", @@ -3104,9 +2968,8 @@ }, "node_modules/@jest/expect": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, + "license": "MIT", "dependencies": { "expect": "^29.7.0", "jest-snapshot": "^29.7.0" @@ -3117,9 +2980,8 @@ }, "node_modules/@jest/expect-utils": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, + "license": "MIT", "dependencies": { "jest-get-type": "^29.6.3" }, @@ -3129,9 +2991,8 @@ }, "node_modules/@jest/fake-timers": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", @@ -3146,9 +3007,8 @@ }, "node_modules/@jest/globals": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", @@ -3161,9 +3021,8 @@ }, "node_modules/@jest/reporters": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, + "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.7.0", @@ -3204,9 +3063,8 @@ }, "node_modules/@jest/reporters/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -3219,9 +3077,8 @@ }, "node_modules/@jest/reporters/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3235,9 +3092,8 @@ }, "node_modules/@jest/reporters/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -3247,99 +3103,30 @@ }, "node_modules/@jest/reporters/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/@jest/reporters/node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "node_modules/@jest/reporters/node_modules/jest-worker": { + "version": "29.7.0", "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", - "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@jest/reporters/node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@jest/reporters/node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@jest/reporters/node_modules/istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/reporters/node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters/node_modules/jest-worker/node_modules/supports-color": { "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -3350,50 +3137,10 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/@jest/reporters/node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@jest/reporters/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@jest/reporters/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@jest/reporters/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -3403,9 +3150,8 @@ }, "node_modules/@jest/schemas": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, + "license": "MIT", "dependencies": { "@sinclair/typebox": "^0.27.8" }, @@ -3415,9 +3161,8 @@ }, "node_modules/@jest/source-map": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", @@ -3429,9 +3174,8 @@ }, "node_modules/@jest/test-result": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/types": "^29.6.3", @@ -3444,9 +3188,8 @@ }, "node_modules/@jest/test-sequencer": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", @@ -3459,9 +3202,8 @@ }, "node_modules/@jest/transform": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -3485,9 +3227,8 @@ }, "node_modules/@jest/transform/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -3500,9 +3241,8 @@ }, "node_modules/@jest/transform/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3516,9 +3256,8 @@ }, "node_modules/@jest/transform/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -3528,24 +3267,21 @@ }, "node_modules/@jest/transform/node_modules/convert-source-map": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jest/transform/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@jest/transform/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -3555,9 +3291,8 @@ }, "node_modules/@jest/transform/node_modules/write-file-atomic": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" @@ -3568,9 +3303,8 @@ }, "node_modules/@jest/types": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", @@ -3585,9 +3319,8 @@ }, "node_modules/@jest/types/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -3600,9 +3333,8 @@ }, "node_modules/@jest/types/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3616,9 +3348,8 @@ }, "node_modules/@jest/types/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -3628,18 +3359,16 @@ }, "node_modules/@jest/types/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@jest/types/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -3648,14 +3377,12 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, + "version": "0.3.5", + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -3663,43 +3390,34 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, + "version": "1.2.1", + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.6", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", - "dev": true, + "version": "0.3.25", + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -3707,18 +3425,16 @@ }, "node_modules/@jscpd/core": { "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@jscpd/core/-/core-3.4.5.tgz", - "integrity": "sha512-02Ajnj07VykiwdWNoMKGdQDHT76kJGOvc1h9+aoicU0CeacWIEuoJW6Gy+N3j+UGUlc1ndWhZ91alIiQ8ERMGg==", "dev": true, + "license": "MIT", "dependencies": { "eventemitter3": "^4.0.4" } }, "node_modules/@jscpd/finder": { "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@jscpd/finder/-/finder-3.4.5.tgz", - "integrity": "sha512-Hz8s6UVbtETYmDP+MdjaTaKKgXsb+SR1dJcdwluBTm5ZNkE9cE/dnDVnrEcKGhE7N3Mg6HEo/fTIKqBsvbRZlw==", "dev": true, + "license": "MIT", "dependencies": { "@jscpd/core": "^3.4.5", "@jscpd/tokenizer": "^3.4.5", @@ -3734,9 +3450,8 @@ }, "node_modules/@jscpd/html-reporter": { "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@jscpd/html-reporter/-/html-reporter-3.4.5.tgz", - "integrity": "sha512-N1W97Xfz2xFDmi5UlYfplGOxz0oLNCvOVD5wYfe1v9WC7BYV1LrDNRWfJzadCefa1XGLsxvMDtLjnhIpFInpUg==", "dev": true, + "license": "MIT", "dependencies": { "colors": "1.4.0", "fs-extra": "^9.0.1" @@ -3744,9 +3459,8 @@ }, "node_modules/@jscpd/tokenizer": { "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@jscpd/tokenizer/-/tokenizer-3.4.5.tgz", - "integrity": "sha512-yPamcj9V1a6h1AGEzdlyfa8t9Lxsb3sZ6Wr7m+cZw2sWD2AlCAjSzbgUwdla7d6y5g1jaVU2XGHEVNUx4vZUqw==", "dev": true, + "license": "MIT", "dependencies": { "@jscpd/core": "^3.4.5", "reprism": "^0.0.11", @@ -3755,41 +3469,32 @@ }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true - }, - "node_modules/@material-ui/core": { - "version": "4.12.3", - "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz", - "integrity": "sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw==", - "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", "dev": true, + "license": "MIT" + }, + "node_modules/@mui/base": { + "version": "5.0.0-beta.40", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.4.4", - "@material-ui/styles": "^4.11.4", - "@material-ui/system": "^4.12.1", - "@material-ui/types": "5.1.0", - "@material-ui/utils": "^4.11.2", - "@types/react-transition-group": "^4.2.0", - "clsx": "^1.0.4", - "hoist-non-react-statics": "^3.3.2", - "popper.js": "1.16.1-lts", - "prop-types": "^15.7.2", - "react-is": "^16.8.0 || ^17.0.0", - "react-transition-group": "^4.4.0" + "@babel/runtime": "^7.23.9", + "@floating-ui/react-dom": "^2.0.8", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.0", + "prop-types": "^15.8.1" }, "engines": { - "node": ">=8.0.0" + "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/material-ui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -3797,23 +3502,38 @@ } } }, - "node_modules/@material-ui/icons": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.2.tgz", - "integrity": "sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ==", - "deprecated": "You can now upgrade to @mui/icons. See the guide: https://mui.com/guides/migration-v4/", - "dev": true, + "node_modules/@mui/base/node_modules/clsx": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@mui/core-downloads-tracker": { + "version": "5.15.20", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "5.15.20", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.4.4" + "@babel/runtime": "^7.23.9" }, "engines": { - "node": ">=8.0.0" + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@material-ui/core": "^4.0.0", - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -3821,121 +3541,128 @@ } } }, - "node_modules/@material-ui/lab": { - "version": "4.0.0-alpha.60", - "resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.60.tgz", - "integrity": "sha512-fadlYsPJF+0fx2lRuyqAuJj7hAS1tLDdIEEdov5jlrpb5pp4b+mRDUqQTUxi4inRZHS1bEXpU8QWUhO6xX88aA==", - "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", - "dev": true, + "node_modules/@mui/lab": { + "version": "5.0.0-alpha.170", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.4.4", - "@material-ui/utils": "^4.11.2", - "clsx": "^1.0.4", - "prop-types": "^15.7.2", - "react-is": "^16.8.0 || ^17.0.0" + "@babel/runtime": "^7.23.9", + "@mui/base": "5.0.0-beta.40", + "@mui/system": "^5.15.15", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "clsx": "^2.1.0", + "prop-types": "^15.8.1" }, "engines": { - "node": ">=8.0.0" + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@material-ui/core": "^4.12.1", - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material": ">=5.15.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, "@types/react": { "optional": true } } }, - "node_modules/@material-ui/pickers": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/@material-ui/pickers/-/pickers-3.3.10.tgz", - "integrity": "sha512-hS4pxwn1ZGXVkmgD4tpFpaumUaAg2ZzbTrxltfC5yPw4BJV+mGkfnQOB4VpWEYZw2jv65Z0wLwDE/piQiPPZ3w==", - "deprecated": "Material UI Pickers v3 doesn't receive active development since January 2020. See the guide https://mui.com/material-ui/guides/pickers-migration/ to upgrade.", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.6.0", - "@date-io/core": "1.x", - "@types/styled-jsx": "^2.2.8", - "clsx": "^1.0.2", - "react-transition-group": "^4.0.0", - "rifm": "^0.7.0" - }, - "peerDependencies": { - "@date-io/core": "^1.3.6", - "@material-ui/core": "^4.0.0", - "prop-types": "^15.6.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" + "node_modules/@mui/lab/node_modules/clsx": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=6" } }, - "node_modules/@material-ui/styles": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz", - "integrity": "sha512-KNTIZcnj/zprG5LW0Sao7zw+yG3O35pviHzejMdcSGCdWbiO8qzRgOYL8JAxAsWBKOKYwVZxXtHWaB5T2Kvxew==", - "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", - "dev": true, + "node_modules/@mui/material": { + "version": "5.15.20", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.4.4", - "@emotion/hash": "^0.8.0", - "@material-ui/types": "5.1.0", - "@material-ui/utils": "^4.11.2", - "clsx": "^1.0.4", - "csstype": "^2.5.2", - "hoist-non-react-statics": "^3.3.2", - "jss": "^10.5.1", - "jss-plugin-camel-case": "^10.5.1", - "jss-plugin-default-unit": "^10.5.1", - "jss-plugin-global": "^10.5.1", - "jss-plugin-nested": "^10.5.1", - "jss-plugin-props-sort": "^10.5.1", - "jss-plugin-rule-value-function": "^10.5.1", - "jss-plugin-vendor-prefixer": "^10.5.1", - "prop-types": "^15.7.2" + "@babel/runtime": "^7.23.9", + "@mui/base": "5.0.0-beta.40", + "@mui/core-downloads-tracker": "^5.15.20", + "@mui/system": "^5.15.20", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.20", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^18.2.0", + "react-transition-group": "^4.4.5" }, "engines": { - "node": ">=8.0.0" + "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/material-ui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, "@types/react": { "optional": true } } }, - "node_modules/@material-ui/system": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.1.tgz", - "integrity": "sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw==", - "deprecated": "You can now upgrade to @mui/system. See the guide: https://mui.com/guides/migration-v4/", - "dev": true, + "node_modules/@mui/material/node_modules/clsx": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@mui/material/node_modules/csstype": { + "version": "3.1.3", + "license": "MIT" + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "18.3.1", + "license": "MIT" + }, + "node_modules/@mui/private-theming": { + "version": "5.15.20", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.4.4", - "@material-ui/utils": "^4.11.2", - "csstype": "^2.5.2", - "prop-types": "^15.7.2" + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.15.20", + "prop-types": "^15.8.1" }, "engines": { - "node": ">=8.0.0" + "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/material-ui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -3943,78 +3670,254 @@ } } }, - "node_modules/@material-ui/types": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz", - "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==", - "dev": true, + "node_modules/@mui/styled-engine": { + "version": "5.15.14", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@emotion/cache": "^11.11.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, "peerDependencies": { - "@types/react": "*" + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { - "@types/react": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { "optional": true } } }, - "node_modules/@material-ui/utils": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz", - "integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.4.4", - "prop-types": "^15.7.2", - "react-is": "^16.8.0 || ^17.0.0" + "node_modules/@mui/styled-engine/node_modules/csstype": { + "version": "3.1.3", + "license": "MIT" + }, + "node_modules/@mui/system": { + "version": "5.15.20", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.15.20", + "@mui/styled-engine": "^5.15.14", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.20", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" }, "engines": { - "node": ">=8.0.0" + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, + "node_modules/@mui/system/node_modules/clsx": { + "version": "2.1.1", + "license": "MIT", "engines": { - "node": ">= 8" + "node": ">=6" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" + "node_modules/@mui/system/node_modules/csstype": { + "version": "3.1.3", + "license": "MIT" + }, + "node_modules/@mui/types": { + "version": "7.2.14", + "license": "MIT", + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, + "node_modules/@mui/utils": { + "version": "5.15.20", + "license": "MIT", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", + "@babel/runtime": "^7.23.9", + "@types/prop-types": "^15.7.11", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "18.3.1", + "license": "MIT" + }, + "node_modules/@mui/x-date-pickers": { + "version": "7.7.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@mui/base": "^5.0.0-beta.40", + "@mui/system": "^5.15.15", + "@mui/utils": "^5.15.14", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14", + "date-fns": "^2.25.0 || ^3.2.0", + "date-fns-jalali": "^2.13.0-0 || ^3.2.0-0", + "dayjs": "^1.10.7", + "luxon": "^3.0.2", + "moment": "^2.29.4", + "moment-hijri": "^2.1.2", + "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "date-fns": { + "optional": true + }, + "date-fns-jalali": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + }, + "moment-hijri": { + "optional": true + }, + "moment-jalaali": { + "optional": true + } + } + }, + "node_modules/@mui/x-date-pickers/node_modules/clsx": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" }, "engines": { "node": ">= 8" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@quoin/nepali-datepicker-reactjs": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@quoin/nepali-datepicker-reactjs/-/nepali-datepicker-reactjs-1.2.4.tgz", - "integrity": "sha512-xwcKdLsGF+vaFwM+CuqQukw9ZNhYbBXlJLJR42ZRe02s0pZV405cDyuiq6cKl/tRX90zGbSXWHUOxYAgQKGZkg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4024,27 +3927,23 @@ }, "node_modules/@react-dnd/asap": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-4.0.1.tgz", - "integrity": "sha512-kLy0PJDDwvwwTXxqTFNAAllPHD73AycE9ypWeln/IguoGBEbvFcPDbCV03G52bEcC5E+YgupBE0VzHGdC8SIXg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@react-dnd/invariant": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-2.0.0.tgz", - "integrity": "sha512-xL4RCQBCBDJ+GRwKTFhGUW8GXa4yoDfJrPbLblc3U09ciS+9ZJXJ3Qrcs/x2IODOdIE5kQxvMmE2UKyqUictUw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@react-dnd/shallowequal": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz", - "integrity": "sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", - "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.10.4", "@rollup/pluginutils": "^3.1.0" @@ -4065,9 +3964,8 @@ }, "node_modules/@rollup/plugin-node-resolve": { "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", - "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", "dev": true, + "license": "MIT", "dependencies": { "@rollup/pluginutils": "^3.1.0", "@types/resolve": "1.17.1", @@ -4085,9 +3983,8 @@ }, "node_modules/@rollup/plugin-replace": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", - "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", "dev": true, + "license": "MIT", "dependencies": { "@rollup/pluginutils": "^3.1.0", "magic-string": "^0.25.7" @@ -4098,9 +3995,8 @@ }, "node_modules/@rollup/pluginutils": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "0.0.39", "estree-walker": "^1.0.1", @@ -4115,48 +4011,42 @@ }, "node_modules/@rollup/pluginutils/node_modules/@types/estree": { "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@sinclair/typebox": { "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@sinonjs/commons": { "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^2.0.0" } }, "node_modules/@sinonjs/fake-timers/node_modules/@sinonjs/commons": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/formatio": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", - "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^1", "@sinonjs/samsam": "^3.1.0" @@ -4164,9 +4054,8 @@ }, "node_modules/@sinonjs/samsam": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", - "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^1.3.0", "array-from": "^2.1.1", @@ -4175,15 +4064,13 @@ }, "node_modules/@sinonjs/text-encoding": { "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true + "dev": true, + "license": "(Unlicense OR Apache-2.0)" }, "node_modules/@surma/rollup-plugin-off-main-thread": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", - "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "ejs": "^3.1.6", "json5": "^2.2.0", @@ -4193,9 +4080,8 @@ }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", - "integrity": "sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4209,9 +4095,8 @@ }, "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-7.0.0.tgz", - "integrity": "sha512-iiZaIvb3H/c7d3TH2HBeK91uI2rMhZNwnsIrvd7ZwGLkFw6mmunOCoVnjdYua662MqGFxlN9xTq4fv9hgR4VXQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" }, @@ -4225,9 +4110,8 @@ }, "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-7.0.0.tgz", - "integrity": "sha512-sQQmyo+qegBx8DfFc04PFmIO1FP1MHI1/QEpzcIcclo5OAISsOJPW76ZIs0bDyO/DBSJEa/tDa1W26pVtt0FRw==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" }, @@ -4241,9 +4125,8 @@ }, "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz", - "integrity": "sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4257,9 +4140,8 @@ }, "node_modules/@svgr/babel-plugin-svg-dynamic-title": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz", - "integrity": "sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4273,9 +4155,8 @@ }, "node_modules/@svgr/babel-plugin-svg-em-dimensions": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz", - "integrity": "sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4289,9 +4170,8 @@ }, "node_modules/@svgr/babel-plugin-transform-react-native-svg": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz", - "integrity": "sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4305,9 +4185,8 @@ }, "node_modules/@svgr/babel-plugin-transform-svg-component": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz", - "integrity": "sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -4321,9 +4200,8 @@ }, "node_modules/@svgr/babel-preset": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.5.1.tgz", - "integrity": "sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw==", "dev": true, + "license": "MIT", "dependencies": { "@svgr/babel-plugin-add-jsx-attribute": "^6.5.1", "@svgr/babel-plugin-remove-jsx-attribute": "*", @@ -4347,9 +4225,8 @@ }, "node_modules/@svgr/core": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.5.1.tgz", - "integrity": "sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.19.6", "@svgr/babel-preset": "^6.5.1", @@ -4365,41 +4242,10 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@svgr/core/node_modules/@babel/core": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", - "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.4", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.4", - "@babel/types": "^7.21.4", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, "node_modules/@svgr/hast-util-to-babel-ast": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz", - "integrity": "sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.20.0", "entities": "^4.4.0" @@ -4414,9 +4260,8 @@ }, "node_modules/@svgr/hast-util-to-babel-ast/node_modules/entities": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -4426,9 +4271,8 @@ }, "node_modules/@svgr/plugin-jsx": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz", - "integrity": "sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.19.6", "@svgr/babel-preset": "^6.5.1", @@ -4446,41 +4290,10 @@ "@svgr/core": "^6.0.0" } }, - "node_modules/@svgr/plugin-jsx/node_modules/@babel/core": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", - "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.4", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.4", - "@babel/types": "^7.21.4", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, "node_modules/@svgr/plugin-svgo": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz", - "integrity": "sha512-omvZKf8ixP9z6GWgwbtmP9qQMPX4ODXi+wzbVZgomNFsUIlHA1sf4fThdwTWSsZGgvGAG6yE+b/F5gWUkcZ/iQ==", "dev": true, + "license": "MIT", "dependencies": { "cosmiconfig": "^7.0.1", "deepmerge": "^4.2.2", @@ -4499,18 +4312,16 @@ }, "node_modules/@svgr/plugin-svgo/node_modules/commander": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10" } }, "node_modules/@svgr/plugin-svgo/node_modules/css-tree": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", "dev": true, + "license": "MIT", "dependencies": { "mdn-data": "2.0.14", "source-map": "^0.6.1" @@ -4521,24 +4332,21 @@ }, "node_modules/@svgr/plugin-svgo/node_modules/mdn-data": { "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true + "dev": true, + "license": "CC0-1.0" }, "node_modules/@svgr/plugin-svgo/node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/@svgr/plugin-svgo/node_modules/svgo": { "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", "dev": true, + "license": "MIT", "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", @@ -4557,9 +4365,8 @@ }, "node_modules/@svgr/webpack": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.5.1.tgz", - "integrity": "sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.19.6", "@babel/plugin-transform-react-constant-elements": "^7.18.12", @@ -4578,64 +4385,14 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@svgr/webpack/node_modules/@babel/core": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", - "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.4", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.4", - "@babel/types": "^7.21.4", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@svgr/webpack/node_modules/@babel/preset-react": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz", - "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-transform-react-display-name": "^7.18.6", - "@babel/plugin-transform-react-jsx": "^7.18.6", - "@babel/plugin-transform-react-jsx-development": "^7.18.6", - "@babel/plugin-transform-react-pure-annotations": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@swc/core": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.84.tgz", - "integrity": "sha512-UPKUiDwG7HOdPfOb1VFeEJ76JDgU2w80JLewzx6tb0fk9TIjhr9yxKBzPbzc/QpjGHDu5iaEuNeZcu27u4j63g==", + "version": "1.5.29", "dev": true, "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "@swc/types": "^0.1.4" + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.8" }, "engines": { "node": ">=10" @@ -4645,19 +4402,19 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.3.84", - "@swc/core-darwin-x64": "1.3.84", - "@swc/core-linux-arm-gnueabihf": "1.3.84", - "@swc/core-linux-arm64-gnu": "1.3.84", - "@swc/core-linux-arm64-musl": "1.3.84", - "@swc/core-linux-x64-gnu": "1.3.84", - "@swc/core-linux-x64-musl": "1.3.84", - "@swc/core-win32-arm64-msvc": "1.3.84", - "@swc/core-win32-ia32-msvc": "1.3.84", - "@swc/core-win32-x64-msvc": "1.3.84" + "@swc/core-darwin-arm64": "1.5.29", + "@swc/core-darwin-x64": "1.5.29", + "@swc/core-linux-arm-gnueabihf": "1.5.29", + "@swc/core-linux-arm64-gnu": "1.5.29", + "@swc/core-linux-arm64-musl": "1.5.29", + "@swc/core-linux-x64-gnu": "1.5.29", + "@swc/core-linux-x64-musl": "1.5.29", + "@swc/core-win32-arm64-msvc": "1.5.29", + "@swc/core-win32-ia32-msvc": "1.5.29", + "@swc/core-win32-x64-msvc": "1.5.29" }, "peerDependencies": { - "@swc/helpers": "^0.5.0" + "@swc/helpers": "*" }, "peerDependenciesMeta": { "@swc/helpers": { @@ -4666,13 +4423,12 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.84.tgz", - "integrity": "sha512-mqK0buOo+toF2HoJ/gWj2ApZbvbIiNq3mMwSTHCYJHlQFQfoTWnl9aaD5GSO4wfNFVYfEZ1R259o5uv5NlVtoA==", + "version": "1.5.29", "cpu": [ "arm64" ], "dev": true, + "license": "Apache-2.0 AND MIT", "optional": true, "os": [ "darwin" @@ -4681,291 +4437,105 @@ "node": ">=10" } }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.84.tgz", - "integrity": "sha512-cyuQZz62C43EDZqtnptUTlfDvAjgG3qu139m5zsfIK6ltXA5inKFbDWV3a/M5c18dFzA2Xh21Q46XZezmtQ9Tg==", - "cpu": [ - "x64" - ], + "node_modules/@swc/counter": { + "version": "0.1.3", "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } + "license": "Apache-2.0" }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.84.tgz", - "integrity": "sha512-dmt/ECQrp3ZPWnK27p4E4xRIRHOoJhgGvxC5t5YaWzN20KcxE9ykEY2oLGSoeceM/A+4D11aRYGwF/EM7yOkvA==", - "cpu": [ - "arm" - ], + "node_modules/@swc/jest": { + "version": "0.2.36", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", + "dependencies": { + "@jest/create-cache-key-function": "^29.7.0", + "@swc/counter": "^0.1.3", + "jsonc-parser": "^3.2.0" + }, "engines": { - "node": ">=10" + "npm": ">= 7.0.0" + }, + "peerDependencies": { + "@swc/core": "*" } }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.84.tgz", - "integrity": "sha512-PgVfrI3NVg2z/oeg3GWLb9rFLMqidbdPwVH5nRyHVP2RX/BWP6qfnYfG+gJv4qrKzIldb9TyCGH7y8VWctKLxw==", - "cpu": [ - "arm64" - ], + "node_modules/@swc/types": { + "version": "0.1.8", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3" } }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.84.tgz", - "integrity": "sha512-hcuEa8/vin4Ns0P+FpcDHQ4f3jmhgGKQhqw0w+TovPSVTIXr+nrFQ2AGhs9nAxS6tSQ77C53Eb5YRpK8ToFo1A==", - "cpu": [ - "arm64" - ], + "node_modules/@testing-library/dom": { + "version": "10.1.0", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.84.tgz", - "integrity": "sha512-IvyimSbwGdu21jBBEqR1Up8Jhvl8kIAf1k3e5Oy8oRfgojdUfmW1EIwgGdoUeyQ1VHlfquiWaRGfsnHQUKl35g==", - "cpu": [ - "x64" - ], + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "4.3.0", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.84.tgz", - "integrity": "sha512-hdgVU/O5ufDCe+p5RtCjU7PRNwd0WM+eWJS+GNY4QWL6O8y2VLM+i4+6YzwSUjeBk0xd+1YElMxbqz7r5tSZhw==", - "cpu": [ - "x64" - ], + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.84.tgz", - "integrity": "sha512-rzH6k2BF0BFOFhUTD+bh0oCiUCZjFfDfoZoYNN/CM0qbtjAcFH21hzMh/EH8ZaXq8k/iQmUNNa5MPNPZ4SOMNw==", - "cpu": [ - "arm64" - ], + "node_modules/@testing-library/dom/node_modules/color-convert": { + "version": "2.0.1", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.84.tgz", - "integrity": "sha512-Y+Dk7VLLVwwsAzoDmjkNW/sTmSPl9PGr4Mj1nhc5A2NNxZ+hz4SxFMclacDI03SC5ikK8Qh6WOoE/+nwUDa3uA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.84.tgz", - "integrity": "sha512-WmpaosqCWMX7DArLdU8AJcj96hy0PKlYh1DaMVikSrrDHbJm2dZ8rd27IK3qUB8DgPkrDYHmLAKNZ+z3gWXgRQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/jest": { - "version": "0.2.29", - "resolved": "https://registry.npmjs.org/@swc/jest/-/jest-0.2.29.tgz", - "integrity": "sha512-8reh5RvHBsSikDC3WGCd5ZTd2BXKkyOdK7QwynrCH58jk2cQFhhHhFBg/jvnWZehUQe/EoOImLENc9/DwbBFow==", - "dev": true, - "dependencies": { - "@jest/create-cache-key-function": "^27.4.2", - "jsonc-parser": "^3.2.0" - }, - "engines": { - "npm": ">= 7.0.0" - }, - "peerDependencies": { - "@swc/core": "*" - } - }, - "node_modules/@swc/types": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.4.tgz", - "integrity": "sha512-z/G02d+59gyyUb7KYhKi9jOhicek6QD2oMaotUyG+lUkybpXoV49dY9bj7Ah5Q+y7knK2jU67UTX9FyfGzaxQg==", - "dev": true - }, - "node_modules/@testing-library/dom": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz", - "integrity": "sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "^5.0.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.4.4", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@testing-library/dom/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@testing-library/dom/node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/@testing-library/dom/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@testing-library/dom/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@testing-library/dom/node_modules/deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=7.0.0" } }, "node_modules/@testing-library/dom/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/@testing-library/dom/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/@testing-library/dom/node_modules/pretty-format": { "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -4977,9 +4547,8 @@ }, "node_modules/@testing-library/dom/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4989,9 +4558,8 @@ }, "node_modules/@testing-library/dom/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -5000,32 +4568,53 @@ } }, "node_modules/@testing-library/jest-dom": { - "version": "5.16.5", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", - "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", + "version": "6.4.6", "dev": true, + "license": "MIT", "dependencies": { - "@adobe/css-tools": "^4.0.1", + "@adobe/css-tools": "^4.4.0", "@babel/runtime": "^7.9.2", - "@types/testing-library__jest-dom": "^5.9.1", "aria-query": "^5.0.0", "chalk": "^3.0.0", "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", "redent": "^3.0.0" }, "engines": { - "node": ">=8", + "node": ">=14", "npm": ">=6", "yarn": ">=1" + }, + "peerDependencies": { + "@jest/globals": ">= 28", + "@types/bun": "latest", + "@types/jest": ">= 28", + "jest": ">= 28", + "vitest": ">= 0.32" + }, + "peerDependenciesMeta": { + "@jest/globals": { + "optional": true + }, + "@types/bun": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "jest": { + "optional": true + }, + "vitest": { + "optional": true + } } }, "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -5036,20 +4625,10 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@testing-library/jest-dom/node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, "node_modules/@testing-library/jest-dom/node_modules/chalk": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -5060,9 +4639,8 @@ }, "node_modules/@testing-library/jest-dom/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -5070,54 +4648,23 @@ "node": ">=7.0.0" } }, - "node_modules/@testing-library/jest-dom/node_modules/deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, "node_modules/@testing-library/jest-dom/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/@testing-library/jest-dom/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/@testing-library/jest-dom/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -5126,44 +4673,52 @@ } }, "node_modules/@testing-library/react": { - "version": "12.1.5", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.5.tgz", - "integrity": "sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==", + "version": "16.0.0", "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^8.0.0", - "@types/react-dom": "<18.0.0" + "@babel/runtime": "^7.12.5" }, "engines": { - "node": ">=12" + "node": ">=18" }, "peerDependencies": { - "react": "<18.0.0", - "react-dom": "<18.0.0" + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, "node_modules/@testing-library/react-hooks": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-7.0.2.tgz", - "integrity": "sha512-dYxpz8u9m4q1TuzfcUApqi8iFfR6R0FaMbr2hjZJy1uC8z+bO/K4v8Gs9eogGKYQop7QsrBTFkv/BCF7MzD2Cg==", + "version": "8.0.1", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5", - "@types/react": ">=16.9.0", - "@types/react-dom": ">=16.9.0", - "@types/react-test-renderer": ">=16.9.0", "react-error-boundary": "^3.1.0" }, "engines": { "node": ">=12" }, "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0", - "react-test-renderer": ">=16.9.0" + "@types/react": "^16.9.0 || ^17.0.0", + "react": "^16.9.0 || ^17.0.0", + "react-dom": "^16.9.0 || ^17.0.0", + "react-test-renderer": "^16.9.0 || ^17.0.0" }, "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, "react-dom": { "optional": true }, @@ -5172,20 +4727,10 @@ } } }, - "node_modules/@testing-library/react/node_modules/@types/react-dom": { - "version": "17.0.19", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.19.tgz", - "integrity": "sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ==", - "dev": true, - "dependencies": { - "@types/react": "^17" - } - }, "node_modules/@testing-library/user-event": { - "version": "14.4.3", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.4.3.tgz", - "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==", + "version": "14.5.2", "dev": true, + "license": "MIT", "engines": { "node": ">=12", "npm": ">=6" @@ -5194,35 +4739,23 @@ "@testing-library/dom": ">=7.21.4" } }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/@trysound/sax": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10.13.0" } }, "node_modules/@types/aria-query": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", - "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==", - "dev": true + "version": "5.0.4", + "dev": true, + "license": "MIT" }, "node_modules/@types/babel__core": { "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -5233,18 +4766,16 @@ }, "node_modules/@types/babel__generator": { "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -5252,18 +4783,16 @@ }, "node_modules/@types/babel__traverse": { "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.3.0" } }, "node_modules/@types/body-parser": { "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", "dev": true, + "license": "MIT", "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -5271,69 +4800,44 @@ }, "node_modules/@types/bonjour": { "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", - "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect": { "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect-history-api-fallback": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", - "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", "dev": true, + "license": "MIT", "dependencies": { "@types/express-serve-static-core": "*", "@types/node": "*" } }, - "node_modules/@types/eslint": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", - "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/eslint-visitor-keys": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true }, "node_modules/@types/express": { "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", "dev": true, + "license": "MIT", "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.18", @@ -5343,9 +4847,8 @@ }, "node_modules/@types/express-serve-static-core": { "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -5354,9 +4857,8 @@ }, "node_modules/@types/glob": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", "dev": true, + "license": "MIT", "dependencies": { "@types/minimatch": "*", "@types/node": "*" @@ -5364,18 +4866,16 @@ }, "node_modules/@types/graceful-fs": { "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/hoist-non-react-statics": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", - "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", "dev": true, + "license": "MIT", "dependencies": { "@types/react": "*", "hoist-non-react-statics": "^3.3.0" @@ -5383,84 +4883,37 @@ }, "node_modules/@types/http-proxy": { "version": "1.17.8", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", - "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", "dev": true, + "license": "MIT", "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "dev": true, + "license": "MIT", "dependencies": { "@types/istanbul-lib-report": "*" } }, - "node_modules/@types/jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg==", - "dev": true, - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "node_modules/@types/jest/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@types/jest/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@types/jest/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/@types/jsdom": { "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "@types/tough-cookie": "*", @@ -5469,9 +4922,8 @@ }, "node_modules/@types/jsdom/node_modules/entities": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -5481,9 +4933,8 @@ }, "node_modules/@types/jsdom/node_modules/parse5": { "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", "dev": true, + "license": "MIT", "dependencies": { "entities": "^4.4.0" }, @@ -5493,104 +4944,78 @@ }, "node_modules/@types/json-schema": { "version": "7.0.10", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.10.tgz", - "integrity": "sha512-BLO9bBq59vW3fxCpD4o0N4U+DXsvwvIcl+jofw0frQo/GrBFC+/jRZj1E7kgp6dvTyNmA4y6JCV5Id/r3mNP5A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/json5": { "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/lodash": { "version": "4.14.180", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.180.tgz", - "integrity": "sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/mime": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/minimatch": { "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { "version": "17.0.23", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", - "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node-forge": { "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/parse-json": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true + "license": "MIT" }, "node_modules/@types/prop-types": { - "version": "15.7.4", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", - "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", - "dev": true + "version": "15.7.12", + "license": "MIT" }, "node_modules/@types/qs": { "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/raf": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.0.tgz", - "integrity": "sha512-taW5/WYqo36N7V39oYyHP9Ipfd5pNFvGTIQsNGj86xV88YQ7GnI30/yMfKDF7Zgin0m3e+ikX88FvImnK4RjGw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/range-parser": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/react": { "version": "17.0.42", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.42.tgz", - "integrity": "sha512-nuab3x3CpJ7VFeNA+3HTUuEkvClYHXqWtWd7Ud6AZYW7Z3NH9WKtgU+tFB0ZLcHq+niB/HnzLcaZPqMJ95+k5Q==", - "dev": true, + "license": "MIT", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", "csstype": "^3.0.2" } }, - "node_modules/@types/react-dom": { - "version": "18.0.11", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", - "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/react-redux": { "version": "7.1.23", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.23.tgz", - "integrity": "sha512-D02o3FPfqQlfu2WeEYwh3x2otYd2Dk1o8wAfsA0B1C2AJEFxE663Ozu7JzuWbznGgW248NaOF6wsqCGNq9d3qw==", "dev": true, + "license": "MIT", "dependencies": { "@types/hoist-non-react-statics": "^3.3.0", "@types/react": "*", @@ -5598,71 +5023,51 @@ "redux": "^4.0.0" } }, - "node_modules/@types/react-test-renderer": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-17.0.1.tgz", - "integrity": "sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/react-transition-group": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.4.tgz", - "integrity": "sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==", - "dev": true, + "version": "4.4.10", + "license": "MIT", "dependencies": { "@types/react": "*" } }, "node_modules/@types/react/node_modules/csstype": { "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true + "license": "MIT" }, "node_modules/@types/resolve": { "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/retry": { "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", - "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/scheduler": { "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", - "dev": true + "license": "MIT" }, "node_modules/@types/semver": { "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/serve-index": { "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", "dev": true, + "license": "MIT", "dependencies": { "@types/express": "*" } }, "node_modules/@types/serve-static": { "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -5670,78 +5075,52 @@ }, "node_modules/@types/sockjs": { "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/stack-utils": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "node_modules/@types/styled-jsx": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/@types/styled-jsx/-/styled-jsx-2.2.9.tgz", - "integrity": "sha512-W/iTlIkGEyTBGTEvZCey8EgQlQ5l0DwMqi3iOXlLs2kyBwYTXHKEiU6IZ5EwoRwngL8/dGYuzezSup89ttVHLw==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/testing-library__jest-dom": { - "version": "5.14.5", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz", - "integrity": "sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==", "dev": true, - "dependencies": { - "@types/jest": "*" - } + "license": "MIT" }, "node_modules/@types/tough-cookie": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/trusted-types": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", - "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/ws": { "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/yargs": { "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, + "license": "MIT", "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@typescript-eslint/experimental-utils": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz", - "integrity": "sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.3", "@typescript-eslint/types": "3.10.1", @@ -5762,9 +5141,8 @@ }, "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^1.1.0" }, @@ -5777,18 +5155,16 @@ }, "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-visitor-keys": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=4" } }, "node_modules/@typescript-eslint/parser": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz", - "integrity": "sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@types/eslint-visitor-keys": "^1.0.0", "@typescript-eslint/experimental-utils": "3.10.1", @@ -5814,18 +5190,16 @@ }, "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=4" } }, "node_modules/@typescript-eslint/scope-manager": { "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", - "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.59.0", "@typescript-eslint/visitor-keys": "5.59.0" @@ -5840,9 +5214,8 @@ }, "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", - "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -5853,9 +5226,8 @@ }, "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/visitor-keys": { "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", - "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.59.0", "eslint-visitor-keys": "^3.3.0" @@ -5870,9 +5242,8 @@ }, "node_modules/@typescript-eslint/scope-manager/node_modules/eslint-visitor-keys": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -5882,9 +5253,8 @@ }, "node_modules/@typescript-eslint/types": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.10.1.tgz", - "integrity": "sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==", "dev": true, + "license": "MIT", "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" }, @@ -5895,9 +5265,8 @@ }, "node_modules/@typescript-eslint/typescript-estree": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz", - "integrity": "sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "3.10.1", "@typescript-eslint/visitor-keys": "3.10.1", @@ -5923,9 +5292,8 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -5938,9 +5306,8 @@ }, "node_modules/@typescript-eslint/utils": { "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.0.tgz", - "integrity": "sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", @@ -5964,9 +5331,8 @@ }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", - "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -5977,9 +5343,8 @@ }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", - "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "5.59.0", "@typescript-eslint/visitor-keys": "5.59.0", @@ -6004,9 +5369,8 @@ }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", - "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.59.0", "eslint-visitor-keys": "^3.3.0" @@ -6021,18 +5385,16 @@ }, "node_modules/@typescript-eslint/utils/node_modules/array-union": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@typescript-eslint/utils/node_modules/eslint-visitor-keys": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -6042,9 +5404,8 @@ }, "node_modules/@typescript-eslint/utils/node_modules/globby": { "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -6062,9 +5423,8 @@ }, "node_modules/@typescript-eslint/utils/node_modules/semver": { "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -6077,9 +5437,8 @@ }, "node_modules/@typescript-eslint/visitor-keys": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz", - "integrity": "sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^1.1.0" }, @@ -6093,170 +5452,152 @@ }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=4" } }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "version": "1.12.1", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true + "version": "1.11.6", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true + "version": "1.11.6", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true + "version": "1.12.1", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "version": "1.11.6", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true + "version": "1.11.6", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "version": "1.12.1", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "version": "1.11.6", "dev": true, + "license": "MIT", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "version": "1.11.6", "dev": true, + "license": "Apache-2.0", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true + "version": "1.11.6", + "dev": true, + "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "version": "1.12.1", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "version": "1.12.1", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "version": "1.12.1", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "version": "1.12.1", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "version": "1.12.1", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, "node_modules/@webpack-cli/configtest": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz", - "integrity": "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==", "dev": true, + "license": "MIT", "peerDependencies": { "webpack": "4.x.x || 5.x.x", "webpack-cli": "4.x.x" @@ -6264,9 +5605,8 @@ }, "node_modules/@webpack-cli/info": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz", - "integrity": "sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA==", "dev": true, + "license": "MIT", "dependencies": { "envinfo": "^7.7.3" }, @@ -6276,9 +5616,8 @@ }, "node_modules/@webpack-cli/serve": { "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz", - "integrity": "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==", "dev": true, + "license": "MIT", "peerDependencies": { "webpack-cli": "4.x.x" }, @@ -6290,8 +5629,7 @@ }, "node_modules/@welldone-software/why-did-you-render": { "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@welldone-software/why-did-you-render/-/why-did-you-render-6.2.3.tgz", - "integrity": "sha512-FQgi90jvC9uw2aALlonJfqaWOvU5UUBBVvdAnS2iryXwCc4YJkKsPJY5Y/LzaND3OIyk8XGUn1vTRn6hcem28Q==", + "license": "MIT", "dependencies": { "lodash": "^4" }, @@ -6299,60 +5637,25 @@ "react": "^16 || ^17" } }, - "node_modules/@wojtekmaj/enzyme-adapter-react-17": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@wojtekmaj/enzyme-adapter-react-17/-/enzyme-adapter-react-17-0.4.1.tgz", - "integrity": "sha512-WZr8i4C6WVDV7Mb8sbm7GdlEPmk1f+xOMjUKThqrkWgwsfvu90zJyyX54wyAvsS91sjtKZ0JipGj2cJnEDaxPA==", - "dev": true, - "dependencies": { - "enzyme-adapter-utils": "^1.14.0", - "enzyme-shallow-equal": "^1.0.4", - "has": "^1.0.3", - "object.assign": "^4.1.0", - "object.values": "^1.1.1", - "prop-types": "^15.7.2", - "react-is": "^17.0.0", - "react-test-renderer": "^17.0.0", - "semver": "^5.7.0" - }, - "peerDependencies": { - "enzyme": "^3.0.0", - "react": "^17.0.0-0", - "react-dom": "^17.0.0-0" - } - }, - "node_modules/@wojtekmaj/enzyme-adapter-react-17/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@xtuc/long": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/abab": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/accepts": { "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -6363,9 +5666,8 @@ }, "node_modules/acorn": { "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -6373,60 +5675,26 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "node_modules/acorn-import-attributes": { + "version": "1.9.5", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^8" } }, "node_modules/acorn-jsx": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/ad-bs-converter": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/ad-bs-converter/-/ad-bs-converter-0.5.0.tgz", - "integrity": "sha1-hM2BwqME0DR3wwl7Iw66IaFPoZQ=", "dev": true, + "license": "ISC", "dependencies": { "get-nepali-number": "^0.1.0", "get-nepday-of-week": "^0.1.4" @@ -6434,15 +5702,13 @@ }, "node_modules/add": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/add/-/add-2.0.6.tgz", - "integrity": "sha1-JI8Kn25aUo7yKV2+7DBTITCuIjU=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/agent-base": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, + "license": "MIT", "dependencies": { "debug": "4" }, @@ -6450,11 +5716,23 @@ "node": ">= 6.0.0" } }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ajv": { "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6468,9 +5746,8 @@ }, "node_modules/ajv-formats": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^8.0.0" }, @@ -6485,9 +5762,8 @@ }, "node_modules/ajv-formats/node_modules/ajv": { "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -6501,33 +5777,29 @@ }, "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ajv-keywords": { "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, + "license": "MIT", "peerDependencies": { "ajv": "^6.9.1" } }, "node_modules/ansi-colors": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/ansi-escapes": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, @@ -6540,9 +5812,8 @@ }, "node_modules/ansi-escapes/node_modules/type-fest": { "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -6552,30 +5823,26 @@ }, "node_modules/ansi-html-community": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", "dev": true, "engines": [ "node >= 0.8.0" ], + "license": "Apache-2.0", "bin": { "ansi-html": "bin/ansi-html" } }, "node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -6585,9 +5852,8 @@ }, "node_modules/anymatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -6597,58 +5863,66 @@ } }, "node_modules/append-transform": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", - "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", "dev": true, "dependencies": { - "default-require-extensions": "^2.0.0" + "default-require-extensions": "^3.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true }, "node_modules/argparse": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "version": "5.3.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" }, "engines": { - "node": ">=6.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/array-from": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/array-includes": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", - "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "version": "3.1.8", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -6660,9 +5934,8 @@ }, "node_modules/array-union": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, + "license": "MIT", "dependencies": { "array-uniq": "^1.0.1" }, @@ -6672,24 +5945,23 @@ }, "node_modules/array-uniq": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/array.prototype.filter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.1.tgz", - "integrity": "sha512-Dk3Ty7N42Odk7PjU/Ci3zT4pLj20YvuVnneG/58ICM6bt4Ij5kZaJTVQ9TSaWaIECX2sFyz4KItkVZqHNnciqw==", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -6698,29 +5970,34 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.find": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.1.2.tgz", - "integrity": "sha512-00S1O4ewO95OmmJW7EesWfQlrCrLEL8kZ40w3+GkLX2yTt0m2ggcePPa2uHPJ9KUmJvwRq+lCV9bD8Yim23x/Q==", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/array.prototype.flat": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", - "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", + "version": "1.3.2", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -6730,14 +6007,61 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz", - "integrity": "sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==", + "version": "1.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -6748,60 +6072,52 @@ }, "node_modules/asap": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/assert-never": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.2.1.tgz", - "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/assertion-error": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", - "dev": true + "version": "0.0.8", + "dev": true, + "license": "MIT" }, "node_modules/astral-regex": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/at-least-node": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true, + "license": "ISC", "engines": { "node": ">= 4.0.0" } }, "node_modules/atob": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true, + "license": "(MIT OR Apache-2.0)", "bin": { "atob": "bin/atob.js" }, @@ -6811,8 +6127,6 @@ }, "node_modules/autoprefixer": { "version": "10.4.4", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.4.tgz", - "integrity": "sha512-Tm8JxsB286VweiZ5F0anmbyGiNI3v3wGv3mz9W+cxEDYB/6jbnj6GM9H9mK3wIL8ftgl+C07Lcwb8PG5PCCPzA==", "dev": true, "funding": [ { @@ -6824,6 +6138,7 @@ "url": "https://tidelift.com/funding/github/npm/autoprefixer" } ], + "license": "MIT", "dependencies": { "browserslist": "^4.20.2", "caniuse-lite": "^1.0.30001317", @@ -6843,10 +6158,12 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -6855,26 +6172,25 @@ } }, "node_modules/axe-core": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.1.tgz", - "integrity": "sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==", + "version": "4.7.0", "dev": true, + "license": "MPL-2.0", "engines": { "node": ">=4" } }, "node_modules/axobject-query": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", - "dev": true + "version": "3.2.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } }, "node_modules/babel-eslint": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", - "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", - "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "@babel/parser": "^7.7.0", @@ -6892,18 +6208,16 @@ }, "node_modules/babel-eslint/node_modules/eslint-visitor-keys": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=4" } }, "node_modules/babel-helper-builder-react-jsx": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", - "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", "dev": true, + "license": "MIT", "dependencies": { "babel-runtime": "^6.26.0", "babel-types": "^6.26.0", @@ -6912,9 +6226,8 @@ }, "node_modules/babel-jest": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", @@ -6933,9 +6246,8 @@ }, "node_modules/babel-jest/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -6948,9 +6260,8 @@ }, "node_modules/babel-jest/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -6964,9 +6275,8 @@ }, "node_modules/babel-jest/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -6976,18 +6286,16 @@ }, "node_modules/babel-jest/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/babel-jest/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -6997,9 +6305,8 @@ }, "node_modules/babel-loader": { "version": "8.2.4", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.4.tgz", - "integrity": "sha512-8dytA3gcvPPPv4Grjhnt8b5IIiTcq/zeXOPk4iTYI0SVXcsmuGg7JtBRDp8S9X+gJfhQ8ektjXZlDu1Bb33U8A==", "dev": true, + "license": "MIT", "dependencies": { "find-cache-dir": "^3.3.1", "loader-utils": "^2.0.0", @@ -7016,9 +6323,8 @@ }, "node_modules/babel-loader/node_modules/find-cache-dir": { "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, + "license": "MIT", "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", @@ -7031,24 +6337,10 @@ "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, - "node_modules/babel-loader/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/babel-loader/node_modules/loader-utils": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, + "license": "MIT", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -7058,23 +6350,10 @@ "node": ">=8.9.0" } }, - "node_modules/babel-loader/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/babel-loader/node_modules/make-dir": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^6.0.0" }, @@ -7085,122 +6364,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-loader/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/babel-loader/node_modules/pkg-dir": { + "version": "4.2.0", "dev": true, + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "find-up": "^4.0.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/babel-loader/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", "dev": true, + "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-loader/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/babel-loader/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-loader/node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "dependencies": { - "object.assign": "^4.1.0" - } - }, - "node_modules/babel-plugin-emotion": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.2.2.tgz", - "integrity": "sha512-SMSkGoqTbTyUTDeuVuPIWifPdUGkTk1Kf9BWRiXIOIcuyMfsdp2EjeiiFvOzX8NOBvEh/ypKYvUh2rkgAJMCLA==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.0.0", - "@emotion/hash": "0.8.0", - "@emotion/memoize": "0.7.4", - "@emotion/serialize": "^0.11.16", - "babel-plugin-macros": "^2.0.0", - "babel-plugin-syntax-jsx": "^6.18.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^1.0.5", - "find-root": "^1.1.0", - "source-map": "^0.5.7" - } - }, - "node_modules/babel-plugin-emotion/node_modules/babel-plugin-macros": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", - "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.7.2", - "cosmiconfig": "^6.0.0", - "resolve": "^1.12.0" - } - }, - "node_modules/babel-plugin-emotion/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" + "object.assign": "^4.1.0" } }, "node_modules/babel-plugin-istanbul": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -7212,20 +6398,10 @@ "node": ">=8" } }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -7237,25 +6413,10 @@ "node": ">=8" } }, - "node_modules/babel-plugin-istanbul/node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/babel-plugin-jest-hoist": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -7268,9 +6429,7 @@ }, "node_modules/babel-plugin-macros": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", @@ -7282,117 +6441,122 @@ } }, "node_modules/babel-plugin-module-resolver": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.0.tgz", - "integrity": "sha512-g0u+/ChLSJ5+PzYwLwP8Rp8Rcfowz58TJNCe+L/ui4rpzE/mg//JVX0EWBUYoxaextqnwuGHzfGp2hh0PPV25Q==", + "version": "5.0.2", "dev": true, + "license": "MIT", "dependencies": { - "find-babel-config": "^2.0.0", - "glob": "^8.0.3", + "find-babel-config": "^2.1.1", + "glob": "^9.3.3", "pkg-up": "^3.1.0", "reselect": "^4.1.7", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">= 16" + "resolve": "^1.22.8" } }, "node_modules/babel-plugin-module-resolver/node_modules/brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/babel-plugin-module-resolver/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "version": "9.3.5", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/babel-plugin-module-resolver/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "8.0.4", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/resolve": { + "version": "1.22.8", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", - "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", + "version": "0.4.11", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-define-polyfill-provider": "^0.3.3", - "semver": "^6.1.1" + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", - "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "version": "0.10.4", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1", - "core-js-compat": "^3.21.0" + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", - "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "version": "0.6.2", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.1" + "@babel/helper-define-polyfill-provider": "^0.6.2" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-syntax-flow": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/babel-plugin-syntax-jsx": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/babel-plugin-transform-flow-strip-types": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-syntax-flow": "^6.18.0", "babel-runtime": "^6.22.0" @@ -7400,18 +6564,16 @@ }, "node_modules/babel-plugin-transform-react-display-name": { "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", "dev": true, + "license": "MIT", "dependencies": { "babel-runtime": "^6.22.0" } }, "node_modules/babel-plugin-transform-react-jsx": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", "dev": true, + "license": "MIT", "dependencies": { "babel-helper-builder-react-jsx": "^6.24.1", "babel-plugin-syntax-jsx": "^6.8.0", @@ -7420,9 +6582,8 @@ }, "node_modules/babel-plugin-transform-react-jsx-self": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-syntax-jsx": "^6.8.0", "babel-runtime": "^6.22.0" @@ -7430,9 +6591,8 @@ }, "node_modules/babel-plugin-transform-react-jsx-source": { "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-syntax-jsx": "^6.8.0", "babel-runtime": "^6.22.0" @@ -7440,15 +6600,13 @@ }, "node_modules/babel-plugin-transform-react-remove-prop-types": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", - "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/babel-preset-current-node-syntax": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", @@ -7469,18 +6627,16 @@ }, "node_modules/babel-preset-flow": { "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", - "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-transform-flow-strip-types": "^6.22.0" } }, "node_modules/babel-preset-jest": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" @@ -7494,9 +6650,8 @@ }, "node_modules/babel-preset-react": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", - "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-syntax-jsx": "^6.3.13", "babel-plugin-transform-react-display-name": "^6.23.0", @@ -7508,9 +6663,8 @@ }, "node_modules/babel-runtime": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, + "license": "MIT", "dependencies": { "core-js": "^2.4.0", "regenerator-runtime": "^0.11.0" @@ -7518,23 +6672,19 @@ }, "node_modules/babel-runtime/node_modules/core-js": { "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", "dev": true, - "hasInstallScript": true + "hasInstallScript": true, + "license": "MIT" }, "node_modules/babel-runtime/node_modules/regenerator-runtime": { "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/babel-types": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, + "license": "MIT", "dependencies": { "babel-runtime": "^6.26.0", "esutils": "^2.0.2", @@ -7544,18 +6694,16 @@ }, "node_modules/babel-types/node_modules/to-fast-properties": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/babel-walk": { "version": "3.0.0-canary-5", - "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", - "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.9.6" }, @@ -7565,15 +6713,13 @@ }, "node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/base64-arraybuffer": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">= 0.6.0" @@ -7581,54 +6727,47 @@ }, "node_modules/base64-arraybuffer-es6": { "version": "0.7.0", - "resolved": "https://registry.npmjs.org/base64-arraybuffer-es6/-/base64-arraybuffer-es6-0.7.0.tgz", - "integrity": "sha512-ESyU/U1CFZDJUdr+neHRhNozeCv72Y7Vm0m1DCbjX3KBjT6eYocvAJlSk6+8+HkVwXlT1FNxhGW6q3UKAlCvvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/batch": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/before-build-webpack": { "version": "0.2.12", - "resolved": "https://registry.npmjs.org/before-build-webpack/-/before-build-webpack-0.2.12.tgz", - "integrity": "sha512-k91crmYKGUiKNRVa6sbP5jVD1m8c2Atjt9UIlVrjOla5kKPe96g1m45J98peZbImOtUCFZCSkT4fr5HNfK/Vew==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/big.js": { "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, "node_modules/bikram-sambat-js": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bikram-sambat-js/-/bikram-sambat-js-1.0.1.tgz", - "integrity": "sha512-d1hdHN0F2BdlJYzT866/FTHX7G+rsJ5AKggJlch4lU1kL7o6AVnbaeJ9JrEUusRwAM4vQhXmCEtPRRCrdnuPRA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/blamer": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/blamer/-/blamer-1.0.6.tgz", - "integrity": "sha512-fv7QToPS87oD1m1bDDTf29zC/bVKJxj2Nqh1r/v4NhMtbnzDIbWOHBYIfxCjlmkVGu3FGOjKgdNG3SFm7TkvBQ==", "dev": true, + "license": "MIT", "dependencies": { "execa": "^4.0.0", "which": "^2.0.2" @@ -7639,29 +6778,31 @@ }, "node_modules/blueimp-md5": { "version": "2.19.0", - "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", - "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dev": true, "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, "node_modules/body-parser/node_modules/debug": { @@ -7673,29 +6814,25 @@ "ms": "2.0.0" } }, - "node_modules/body-parser/node_modules/ms": { + "node_modules/body-parser/node_modules/depd": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.8" } }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "node_modules/bonjour-service": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", - "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" @@ -7703,48 +6840,36 @@ }, "node_modules/boolbase": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, "node_modules/browser-stdout": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.23.1", "dev": true, "funding": [ { @@ -7754,13 +6879,18 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001629", + "electron-to-chromium": "^1.4.796", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.16" }, "bin": { "browserslist": "cli.js" @@ -7771,18 +6901,16 @@ }, "node_modules/bser": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "node-int64": "^0.4.0" } }, "node_modules/btoa": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", - "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", "dev": true, + "license": "(MIT OR Apache-2.0)", "bin": { "btoa": "bin/btoa.js" }, @@ -7792,15 +6920,13 @@ }, "node_modules/buffer-from": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/builtin-modules": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", - "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -7810,36 +6936,55 @@ }, "node_modules/bytes": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/caching-transform": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", - "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, "dependencies": { - "hasha": "^3.0.0", - "make-dir": "^2.0.0", - "package-hash": "^3.0.0", - "write-file-atomic": "^2.4.2" + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" + } + }, + "node_modules/caching-transform/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7847,18 +6992,15 @@ }, "node_modules/callsites": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/camelcase": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -7867,9 +7009,7 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001474", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001474.tgz", - "integrity": "sha512-iaIZ8gVrWfemh5DG3T9/YqarVZoYf0r188IjaGwx68j4Pf0SGY6CQkmJUIE+NZHkkecQGohzXmBGEwWDr9aM3Q==", + "version": "1.0.30001632", "dev": true, "funding": [ { @@ -7884,13 +7024,13 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/canvg": { "version": "3.0.10", - "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", - "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5", "@types/raf": "^3.4.0", @@ -7905,23 +7045,10 @@ "node": ">=10.0.0" } }, - "node_modules/canvg/node_modules/core-js": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", - "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "dev": true, - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/chai": { "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", "dev": true, + "license": "MIT", "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", @@ -7937,9 +7064,8 @@ }, "node_modules/chai-immutable": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chai-immutable/-/chai-immutable-2.1.0.tgz", - "integrity": "sha512-IQrtwbwQYn2tkw/BOL+xYhJMcwuil1w0dzv9nZqi/w+jdQhdAn9rDyJb3qK+LvZkctJqdvy6opALGFZcdriW7A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -7950,9 +7076,7 @@ }, "node_modules/chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -7964,27 +7088,24 @@ }, "node_modules/char-regex": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/character-parser": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", - "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", "dev": true, + "license": "MIT", "dependencies": { "is-regex": "^1.0.3" } }, "node_modules/chart.js": { "version": "2.9.4", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz", - "integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==", "dev": true, + "license": "MIT", "dependencies": { "chartjs-color": "^2.1.0", "moment": "^2.10.2" @@ -7992,9 +7113,8 @@ }, "node_modules/chartjs-color": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", - "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", "dev": true, + "license": "MIT", "dependencies": { "chartjs-color-string": "^0.6.0", "color-convert": "^1.9.3" @@ -8002,63 +7122,22 @@ }, "node_modules/chartjs-color-string": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", - "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "^1.0.0" } }, "node_modules/check-error": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, - "node_modules/cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "dependencies": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/chokidar": { "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "funding": [ { @@ -8066,6 +7145,7 @@ "url": "https://paulmillr.com/funding/" } ], + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -8084,9 +7164,8 @@ }, "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -8096,17 +7175,14 @@ }, "node_modules/chrome-trace-event": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0" } }, "node_modules/ci-info": { "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true, "funding": [ { @@ -8114,21 +7190,29 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/cjs-module-lexer": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } }, "node_modules/clean-webpack-plugin": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-4.0.0.tgz", - "integrity": "sha512-WuWE1nyTNAyW5T7oNyys2EN0cfP2fdRxhxnIQWiAp0bMabPdHhoGxM8A6YL2GhqwgrPnnaemVE7nv5XJ2Fhh2w==", "dev": true, + "license": "MIT", "dependencies": { "del": "^4.1.1" }, @@ -8141,9 +7225,8 @@ }, "node_modules/cli-table3": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz", - "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==", "dev": true, + "license": "MIT", "dependencies": { "string-width": "^4.2.0" }, @@ -8156,9 +7239,8 @@ }, "node_modules/cliui": { "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -8167,9 +7249,8 @@ }, "node_modules/clone-deep": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", @@ -8181,18 +7262,16 @@ }, "node_modules/clsx": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", - "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/co": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, + "license": "MIT", "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" @@ -8200,51 +7279,42 @@ }, "node_modules/collect-v8-coverage": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/color-convert/node_modules/color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "license": "MIT" }, "node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/colorette": { "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/colors": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.1.90" } }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -8254,33 +7324,29 @@ }, "node_modules/commander": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/common-tags": { "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4.0.0" } }, "node_modules/commondir": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/compressible": { "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": ">= 1.43.0 < 2" }, @@ -8290,9 +7356,8 @@ }, "node_modules/compression": { "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", "dev": true, + "license": "MIT", "dependencies": { "accepts": "~1.3.5", "bytes": "3.0.0", @@ -8308,9 +7373,8 @@ }, "node_modules/compression-webpack-plugin": { "version": "9.2.0", - "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-9.2.0.tgz", - "integrity": "sha512-R/Oi+2+UHotGfu72fJiRoVpuRifZT0tTC6UqFD/DUo+mv8dbOow9rVOuTvDv5nPPm3GZhHL/fKkwxwIHnJ8Nyw==", "dev": true, + "license": "MIT", "dependencies": { "schema-utils": "^4.0.0", "serialize-javascript": "^6.0.0" @@ -8328,9 +7392,8 @@ }, "node_modules/compression-webpack-plugin/node_modules/ajv": { "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -8344,9 +7407,8 @@ }, "node_modules/compression-webpack-plugin/node_modules/ajv-keywords": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -8356,15 +7418,13 @@ }, "node_modules/compression-webpack-plugin/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/compression-webpack-plugin/node_modules/schema-utils": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.8.0", @@ -8381,54 +7441,47 @@ }, "node_modules/compression/node_modules/bytes": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/compression/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, "node_modules/compression/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/confusing-browser-globals": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/connect-history-api-fallback": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8" } }, "node_modules/connected-react-router": { - "version": "6.9.2", - "resolved": "https://registry.npmjs.org/connected-react-router/-/connected-react-router-6.9.2.tgz", - "integrity": "sha512-bE8kNBiZv9Mivp7pYn9JvLH5ItTjLl45kk1/Vha0rmAK9I/ETb5JPJrAm0h2KCG9qLfv7vqU3Jo4UUDo0oJnQg==", + "version": "6.9.3", "dev": true, + "license": "MIT", "dependencies": { "lodash.isequalwith": "^4.4.0", "prop-types": "^15.7.2" @@ -8445,18 +7498,10 @@ "redux": "^3.6.0 || ^4.0.0" } }, - "node_modules/connected-react-router/node_modules/immutable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", - "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", - "dev": true, - "optional": true - }, "node_modules/constantinople": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", - "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.6.0", "@babel/types": "^7.6.1" @@ -8464,9 +7509,8 @@ }, "node_modules/content-disposition": { "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -8476,8 +7520,6 @@ }, "node_modules/content-disposition/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -8492,12 +7534,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, "engines": { "node": ">= 0.6" @@ -8505,17 +7548,15 @@ }, "node_modules/convert-source-map": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.1" } }, "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "dev": true, "engines": { "node": ">= 0.6" @@ -8523,25 +7564,25 @@ }, "node_modules/cookie-signature": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/core-js": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.6.tgz", - "integrity": "sha512-u4oM8SHwmDuh5mWZdDg9UwNVq5s1uqq6ZDLLIs07VY+VJU91i3h4f3K/pgFvtUQPGdeStrZ+odKyfyt4EnKHfA==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "version": "3.37.1", "dev": true, - "hasInstallScript": true + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } }, "node_modules/core-js-compat": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.30.0.tgz", - "integrity": "sha512-P5A2h/9mRYZFIAP+5Ab8ns6083IyVpSclU74UNvbGVQ8VM7n3n3/g2yF3AkKQ9NXz2O+ioxLbEWKnDtgsFamhg==", + "version": "3.37.1", "dev": true, + "license": "MIT", "dependencies": { - "browserslist": "^4.21.5" + "browserslist": "^4.23.0" }, "funding": { "type": "opencollective", @@ -8550,11 +7591,9 @@ }, "node_modules/core-js-pure": { "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz", - "integrity": "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ==", - "deprecated": "core-js-pure@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js-pure.", "dev": true, "hasInstallScript": true, + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" @@ -8562,15 +7601,12 @@ }, "node_modules/core-util-is": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cosmiconfig": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, + "license": "MIT", "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -8582,27 +7618,10 @@ "node": ">=10" } }, - "node_modules/cp-file": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", - "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "make-dir": "^2.0.0", - "nested-error-stacks": "^2.0.0", - "pify": "^4.0.1", - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/create-jest": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", @@ -8621,9 +7640,8 @@ }, "node_modules/create-jest/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -8636,9 +7654,8 @@ }, "node_modules/create-jest/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -8652,9 +7669,8 @@ }, "node_modules/create-jest/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -8664,18 +7680,16 @@ }, "node_modules/create-jest/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/create-jest/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -8683,28 +7697,10 @@ "node": ">=8" } }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { "path-key": "^3.1.0", @@ -8717,18 +7713,16 @@ }, "node_modules/crypto-random-string": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/css-blank-pseudo": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", - "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-selector-parser": "^6.0.9" }, @@ -8744,24 +7738,21 @@ }, "node_modules/css-box-model": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", - "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", "dev": true, + "license": "MIT", "dependencies": { "tiny-invariant": "^1.0.6" } }, "node_modules/css-element-queries": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/css-element-queries/-/css-element-queries-1.2.3.tgz", - "integrity": "sha512-QK9uovYmKTsV2GXWQiMOByVNrLn2qz6m3P7vWpOR4IdD6I3iXoDw5qtgJEN3Xq7gIbdHVKvzHjdAtcl+4Arc4Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/css-has-pseudo": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", - "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-selector-parser": "^6.0.9" }, @@ -8777,9 +7768,8 @@ }, "node_modules/css-line-break": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", - "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "utrie": "^1.0.2" @@ -8787,9 +7777,8 @@ }, "node_modules/css-loader": { "version": "6.7.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", - "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", "dev": true, + "license": "MIT", "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.4.7", @@ -8813,9 +7802,8 @@ }, "node_modules/css-loader/node_modules/semver": { "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -8828,9 +7816,8 @@ }, "node_modules/css-prefers-color-scheme": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", - "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", "dev": true, + "license": "CC0-1.0", "bin": { "css-prefers-color-scheme": "dist/cli.cjs" }, @@ -8843,9 +7830,8 @@ }, "node_modules/css-select": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", - "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", "css-what": "^5.1.0", @@ -8857,21 +7843,10 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/css-vendor": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", - "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.3", - "is-in-browser": "^1.0.2" - } - }, "node_modules/css-what": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">= 6" }, @@ -8881,21 +7856,18 @@ }, "node_modules/css.escape": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cssdb": { "version": "6.5.0", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-6.5.0.tgz", - "integrity": "sha512-Rh7AAopF2ckPXe/VBcoUS9JrCZNSyc60+KpgE6X25vpVxA32TmiqvExjkfhwP4wGSb6Xe8Z/JIyGqwgx/zZYFA==", - "dev": true + "dev": true, + "license": "CC0-1.0" }, "node_modules/cssesc": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, + "license": "MIT", "bin": { "cssesc": "bin/cssesc" }, @@ -8903,11 +7875,18 @@ "node": ">=4" } }, + "node_modules/cssjanus": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cssjanus/-/cssjanus-2.1.0.tgz", + "integrity": "sha512-kAijbny3GmdOi9k+QT6DGIXqFvL96aksNlGr4Rhk9qXDZYWUojU4bRc3IHWxdaLNOqgEZHuXoe5Wl2l7dxLW5g==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/csso": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", "dev": true, + "license": "MIT", "dependencies": { "css-tree": "^1.1.2" }, @@ -8917,9 +7896,8 @@ }, "node_modules/csso/node_modules/css-tree": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", "dev": true, + "license": "MIT", "dependencies": { "mdn-data": "2.0.14", "source-map": "^0.6.1" @@ -8930,30 +7908,21 @@ }, "node_modules/csso/node_modules/mdn-data": { "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true + "dev": true, + "license": "CC0-1.0" }, "node_modules/csso/node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, "node_modules/cssstyle": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", "dev": true, + "license": "MIT", "dependencies": { "cssom": "~0.3.6" }, @@ -8963,47 +7932,124 @@ }, "node_modules/cssstyle/node_modules/cssom": { "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/csstype": { "version": "2.6.20", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", - "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==", - "dev": true + "license": "MIT" }, "node_modules/damerau-levenshtein": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "version": "5.0.0", "dev": true, + "license": "MIT", "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/tr46": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "7.0.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "14.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/date-fns": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.1.0.tgz", - "integrity": "sha512-eKeLk3sLCnxB/0PN4t1+zqDtSs4jb4mXRSTZ2okmx/myfWyDqeO4r5nnmA5LClJiCwpuTMeK2v5UQPuE4uMaxA==", - "dev": true + "version": "2.29.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } }, "node_modules/debug": { "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -9018,9 +8064,8 @@ }, "node_modules/decamelize": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -9030,15 +8075,13 @@ }, "node_modules/decimal.js": { "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/dedent": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", "dev": true, + "license": "MIT", "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, @@ -9050,15 +8093,13 @@ }, "node_modules/deep-diff": { "version": "0.3.8", - "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", - "integrity": "sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/deep-eql": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, + "license": "MIT", "dependencies": { "type-detect": "^4.0.0" }, @@ -9068,9 +8109,8 @@ }, "node_modules/deep-equal": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", "dev": true, + "license": "MIT", "dependencies": { "is-arguments": "^1.0.4", "is-date-object": "^1.0.1", @@ -9085,24 +8125,21 @@ }, "node_modules/deep-is": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "version": "4.3.1", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/default-gateway": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "execa": "^5.0.0" }, @@ -9112,9 +8149,8 @@ }, "node_modules/default-gateway/node_modules/execa": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -9135,9 +8171,8 @@ }, "node_modules/default-gateway/node_modules/get-stream": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -9147,40 +8182,66 @@ }, "node_modules/default-gateway/node_modules/human-signals": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } }, "node_modules/default-require-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", - "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", + "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", "dev": true, "dependencies": { - "strip-bom": "^3.0.0" + "strip-bom": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-require-extensions/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-lazy-prop": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", "dev": true, + "license": "MIT", "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -9193,9 +8254,8 @@ }, "node_modules/del": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/glob": "^7.1.1", "globby": "^6.1.0", @@ -9211,66 +8271,71 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/depd": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, + "node_modules/dequal": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } }, "node_modules/detect-newline": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/detect-node": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/diff": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/diff-sequences": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/dir-glob": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -9278,23 +8343,15 @@ "node": ">=8" } }, - "node_modules/discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=", - "dev": true - }, "node_modules/dlv": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/dnd-core": { "version": "11.1.3", - "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-11.1.3.tgz", - "integrity": "sha512-QugF55dNW+h+vzxVJ/LSJeTeUw9MCJ2cllhmVThVPEtF16ooBkxj0WBE5RB+AceFxMFo1rO6bJKXtqKl+JNnyA==", "dev": true, + "license": "MIT", "dependencies": { "@react-dnd/asap": "^4.0.0", "@react-dnd/invariant": "^2.0.0", @@ -9303,9 +8360,8 @@ }, "node_modules/dns-packet": { "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", "dev": true, + "license": "MIT", "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" }, @@ -9315,9 +8371,8 @@ }, "node_modules/doctrine": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -9327,21 +8382,17 @@ }, "node_modules/doctypes": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", - "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/dom-accessibility-api": { "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/dom-helpers": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" @@ -9349,15 +8400,12 @@ }, "node_modules/dom-helpers/node_modules/csstype": { "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true + "license": "MIT" }, "node_modules/dom-serializer": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", "dev": true, + "license": "MIT", "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", @@ -9369,48 +8417,24 @@ }, "node_modules/dom-to-image-more": { "version": "2.8.0", - "resolved": "https://registry.npmjs.org/dom-to-image-more/-/dom-to-image-more-2.8.0.tgz", - "integrity": "sha512-YqlHI1i+TMuaKwkFRO5oDPjC3eWf+6Hln9rHZcnFYvmoXwCrGZmZ7BYXBJOjw5utYg2Lp+QF9YO96F7CsDC4eQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/domelementtype": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/fb55" } - ] - }, - "node_modules/domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "dependencies": { - "webidl-conversions": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true, - "engines": { - "node": ">=8" - } + ], + "license": "BSD-2-Clause" }, "node_modules/domhandler": { "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.2.0" }, @@ -9422,16 +8446,15 @@ } }, "node_modules/dompurify": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.6.tgz", - "integrity": "sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.6.tgz", + "integrity": "sha512-zUTaUBO8pY4+iJMPE1B9XlO2tXVYIcEA4SNGtvDELzTSCQO7RzH+j7S180BmhmJId78lqGU2z19vgVx2Sxs/PQ==", "dev": true }, "node_modules/domutils": { "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", @@ -9444,14 +8467,13 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true }, "node_modules/ejs": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.7.tgz", - "integrity": "sha512-BIar7R6abbUxDA3bfXrO4DSgwo8I+fB5/1zgujl3HLLjwd6+9iOnrT+t3grn2qbk9vOgBubXOFwX2m9axoFaGw==", + "version": "3.1.10", "dev": true, + "license": "Apache-2.0", "dependencies": { "jake": "^10.8.5" }, @@ -9463,16 +8485,14 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.351", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.351.tgz", - "integrity": "sha512-W35n4jAsyj6OZGxeWe+gA6+2Md4jDO19fzfsRKEt3DBwIdlVTT8O9Uv8ojgUAoQeXASdgG9zMU+8n8Xg/W6dRQ==", - "dev": true + "version": "1.4.796", + "dev": true, + "license": "ISC" }, "node_modules/emittery": { "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -9482,23 +8502,21 @@ }, "node_modules/emoji-regex": { "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/emojis-list": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "engines": { "node": ">= 0.8" @@ -9506,17 +8524,16 @@ }, "node_modules/end-of-stream": { "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, + "license": "MIT", "dependencies": { "once": "^1.4.0" } }, "node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -9528,9 +8545,8 @@ }, "node_modules/enquirer": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-colors": "^4.1.1" }, @@ -9540,18 +8556,16 @@ }, "node_modules/entities": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", "dev": true, + "license": "BSD-2-Clause", "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/envinfo": { "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", "dev": true, + "license": "MIT", "bin": { "envinfo": "dist/cli.js" }, @@ -9559,197 +8573,156 @@ "node": ">=4" } }, - "node_modules/enzyme": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", - "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", - "dev": true, + "node_modules/error-ex": { + "version": "1.3.2", + "license": "MIT", "dependencies": { - "array.prototype.flat": "^1.2.3", - "cheerio": "^1.0.0-rc.3", - "enzyme-shallow-equal": "^1.0.1", - "function.prototype.name": "^1.1.2", - "has": "^1.0.3", - "html-element-map": "^1.2.0", - "is-boolean-object": "^1.0.1", - "is-callable": "^1.1.5", - "is-number-object": "^1.0.4", - "is-regex": "^1.0.5", - "is-string": "^1.0.5", - "is-subset": "^0.1.1", - "lodash.escape": "^4.0.1", - "lodash.isequal": "^4.5.0", - "object-inspect": "^1.7.0", - "object-is": "^1.0.2", - "object.assign": "^4.1.0", - "object.entries": "^1.1.1", - "object.values": "^1.1.1", - "raf": "^3.4.1", - "rst-selector-parser": "^2.2.3", - "string.prototype.trim": "^1.2.1" + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/enzyme-adapter-utils": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.14.0.tgz", - "integrity": "sha512-F/z/7SeLt+reKFcb7597IThpDp0bmzcH1E9Oabqv+o01cID2/YInlqHbFl7HzWBl4h3OdZYedtwNDOmSKkk0bg==", + "node_modules/es-define-property": { + "version": "1.0.0", "dev": true, + "license": "MIT", "dependencies": { - "airbnb-prop-types": "^2.16.0", - "function.prototype.name": "^1.1.3", - "has": "^1.0.3", - "object.assign": "^4.1.2", - "object.fromentries": "^2.0.3", - "prop-types": "^15.7.2", - "semver": "^5.7.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "get-intrinsic": "^1.2.4" }, - "peerDependencies": { - "react": "0.13.x || 0.14.x || ^15.0.0-0 || ^16.0.0-0" - } - }, - "node_modules/enzyme-adapter-utils/node_modules/airbnb-prop-types": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.16.0.tgz", - "integrity": "sha512-7WHOFolP/6cS96PhKNrslCLMYAI8yB1Pp6u6XmxozQOiZbsI5ycglZr5cHhBFfuRcQQjzCMith5ZPZdYiJCxUg==", - "dev": true, - "dependencies": { - "array.prototype.find": "^2.1.1", - "function.prototype.name": "^1.1.2", - "is-regex": "^1.1.0", - "object-is": "^1.1.2", - "object.assign": "^4.1.0", - "object.entries": "^1.1.2", - "prop-types": "^15.7.2", - "prop-types-exact": "^1.2.0", - "react-is": "^16.13.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - }, - "peerDependencies": { - "react": "^0.14 || ^15.0.0 || ^16.0.0-alpha" + "engines": { + "node": ">= 0.4" } }, - "node_modules/enzyme-adapter-utils/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "node_modules/enzyme-adapter-utils/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/es-errors": { + "version": "1.3.0", "dev": true, - "bin": { - "semver": "bin/semver" + "license": "MIT", + "engines": { + "node": ">= 0.4" } }, - "node_modules/enzyme-shallow-equal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.4.tgz", - "integrity": "sha512-MttIwB8kKxypwHvRynuC3ahyNc+cFbR8mjVIltnmzQ0uKGqmsfO4bfBuLxb0beLNPhjblUEYvEbsg+VSygvF1Q==", + "node_modules/es-iterator-helpers": { + "version": "1.0.19", "dev": true, + "license": "MIT", "dependencies": { - "has": "^1.0.3", - "object-is": "^1.1.2" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/es-module-lexer": { + "version": "1.2.1", "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } + "license": "MIT" }, - "node_modules/es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "node_modules/es-object-atoms": { + "version": "1.0.0", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", - "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "es-errors": "^1.3.0" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "node_modules/es-set-tostringtag": { + "version": "2.0.3", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" } }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/es-module-lexer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", - "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==", - "dev": true + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + } }, "node_modules/es-to-primitive": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -9770,39 +8743,33 @@ }, "node_modules/es6-promise": { "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-html": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/escodegen": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -9822,9 +8789,8 @@ }, "node_modules/escodegen/node_modules/levn": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -9835,9 +8801,8 @@ }, "node_modules/escodegen/node_modules/optionator": { "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", @@ -9852,8 +8817,6 @@ }, "node_modules/escodegen/node_modules/prelude-ls": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true, "engines": { "node": ">= 0.8.0" @@ -9861,9 +8824,8 @@ }, "node_modules/escodegen/node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "optional": true, "engines": { "node": ">=0.10.0" @@ -9871,9 +8833,8 @@ }, "node_modules/escodegen/node_modules/type-check": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "~1.1.2" }, @@ -9883,9 +8844,8 @@ }, "node_modules/eslint": { "version": "8.11.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", - "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint/eslintrc": "^1.2.1", "@humanwhocodes/config-array": "^0.9.2", @@ -9935,9 +8895,8 @@ }, "node_modules/eslint-config-airbnb": { "version": "19.0.4", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", - "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", "dev": true, + "license": "MIT", "dependencies": { "eslint-config-airbnb-base": "^15.0.0", "object.assign": "^4.1.2", @@ -9956,9 +8915,8 @@ }, "node_modules/eslint-config-airbnb-base": { "version": "15.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", - "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", "dev": true, + "license": "MIT", "dependencies": { "confusing-browser-globals": "^1.0.10", "object.assign": "^4.1.2", @@ -9975,9 +8933,8 @@ }, "node_modules/eslint-config-prettier": { "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", "dev": true, + "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -9987,9 +8944,8 @@ }, "node_modules/eslint-import-resolver-alias": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz", - "integrity": "sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" }, @@ -9998,65 +8954,85 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "version": "0.3.9", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7", - "resolve": "^1.20.0" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, + "node_modules/eslint-import-resolver-node/node_modules/resolve": { + "version": "1.22.8", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/eslint-module-utils": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", - "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", + "version": "2.8.1", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^3.2.7", - "find-up": "^2.1.0" + "debug": "^3.2.7" }, "engines": { "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, "node_modules/eslint-module-utils/node_modules/debug": { "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-plugin-import": { - "version": "2.25.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", - "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", + "version": "2.29.1", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.2", - "has": "^1.0.3", - "is-core-module": "^2.8.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.5", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.12.0" + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" @@ -10066,19 +9042,17 @@ } }, "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "node_modules/eslint-plugin-import/node_modules/doctrine": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -10086,17 +9060,10 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, "node_modules/eslint-plugin-jest": { - "version": "27.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz", - "integrity": "sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==", + "version": "27.9.0", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/utils": "^5.10.0" }, @@ -10104,8 +9071,9 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0", - "eslint": "^7.0.0 || ^8.0.0" + "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", + "eslint": "^7.0.0 || ^8.0.0", + "jest": "*" }, "peerDependenciesMeta": { "@typescript-eslint/eslint-plugin": { @@ -10117,23 +9085,26 @@ } }, "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz", - "integrity": "sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==", + "version": "6.8.0", "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.16.3", - "aria-query": "^4.2.2", - "array-includes": "^3.1.4", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.3.5", - "axobject-query": "^2.2.0", - "damerau-levenshtein": "^1.0.7", + "@babel/runtime": "^7.23.2", + "aria-query": "^5.3.0", + "array-includes": "^3.1.7", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "=4.7.0", + "axobject-query": "^3.2.1", + "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.2.1", - "language-tags": "^1.0.5", - "minimatch": "^3.0.4" + "es-iterator-helpers": "^1.0.15", + "hasown": "^2.0.0", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7" }, "engines": { "node": ">=4.0" @@ -10144,9 +9115,8 @@ }, "node_modules/eslint-plugin-prettier": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", "dev": true, + "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0" }, @@ -10164,25 +9134,28 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.29.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.29.4.tgz", - "integrity": "sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ==", + "version": "7.34.2", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flatmap": "^1.2.5", + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.3", "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", "estraverse": "^5.3.0", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.5", - "object.fromentries": "^2.0.5", - "object.hasown": "^1.1.0", - "object.values": "^1.1.5", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.hasown": "^1.1.4", + "object.values": "^1.2.0", "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.3", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.6" + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11" }, "engines": { "node": ">=4" @@ -10192,10 +9165,9 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz", - "integrity": "sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==", + "version": "4.6.2", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -10205,9 +9177,8 @@ }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -10216,13 +9187,16 @@ } }, "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.3", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz", - "integrity": "sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q==", + "version": "2.0.0-next.5", "dev": true, + "license": "MIT", "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10230,9 +9204,8 @@ }, "node_modules/eslint-plugin-unused-imports": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz", - "integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==", "dev": true, + "license": "MIT", "dependencies": { "eslint-rule-composer": "^0.3.0" }, @@ -10251,18 +9224,16 @@ }, "node_modules/eslint-rule-composer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", - "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", "dev": true, + "license": "MIT", "engines": { "node": ">=4.0.0" } }, "node_modules/eslint-scope": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -10273,18 +9244,16 @@ }, "node_modules/eslint-scope/node_modules/estraverse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/eslint-utils": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^2.0.0" }, @@ -10300,18 +9269,16 @@ }, "node_modules/eslint-visitor-keys": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10" } }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -10324,9 +9291,8 @@ }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -10340,9 +9306,8 @@ }, "node_modules/eslint/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -10352,9 +9317,8 @@ }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -10364,9 +9328,8 @@ }, "node_modules/eslint/node_modules/eslint-scope": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -10377,18 +9340,16 @@ }, "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/eslint/node_modules/globals": { "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -10401,18 +9362,16 @@ }, "node_modules/eslint/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -10422,9 +9381,8 @@ }, "node_modules/eslint/node_modules/type-fest": { "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -10434,9 +9392,8 @@ }, "node_modules/espree": { "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.7.0", "acorn-jsx": "^5.3.1", @@ -10448,18 +9405,16 @@ }, "node_modules/espree/node_modules/eslint-visitor-keys": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/esprima": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -10470,9 +9425,8 @@ }, "node_modules/esquery": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -10482,9 +9436,8 @@ }, "node_modules/esrecurse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -10494,24 +9447,21 @@ }, "node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/estree-walker": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/esutils": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -10519,7 +9469,7 @@ "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, "engines": { "node": ">= 0.6" @@ -10527,24 +9477,21 @@ }, "node_modules/eventemitter3": { "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/events": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.x" } }, "node_modules/execa": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", @@ -10565,8 +9512,6 @@ }, "node_modules/exit": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, "engines": { "node": ">= 0.8.0" @@ -10574,9 +9519,8 @@ }, "node_modules/expect": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/expect-utils": "^29.7.0", "jest-get-type": "^29.6.3", @@ -10589,89 +9533,85 @@ } }, "node_modules/express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.2", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", + "depd": "2.0.0", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.3.1", "fresh": "0.5.2", - "merge-descriptors": "1.0.1", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.9.7", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", - "statuses": "~1.5.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/array-flatten": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/express/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, + "node_modules/express/node_modules/depd": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/express/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "dev": true }, - "node_modules/express/node_modules/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", - "dev": true, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/express/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -10686,34 +9626,39 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" + }, + "node_modules/express/node_modules/statuses": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, "node_modules/fake-indexeddb": { "version": "3.1.8", - "resolved": "https://registry.npmjs.org/fake-indexeddb/-/fake-indexeddb-3.1.8.tgz", - "integrity": "sha512-7umIgcdnDfNcjw0ZaoD6yR2BflngKmPsyzZC+sV2fdttwz5bH6B6CCaNzzD+MURfRg8pvr/aL0trfNx65FLiDg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "realistic-structured-clone": "^2.0.1" } }, "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-diff": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/fast-glob": { "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -10727,9 +9672,8 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -10739,36 +9683,31 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastest-levenshtein": { "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastq": { "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, "node_modules/faye-websocket": { "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", "dev": true, + "license": "Apache-2.0", "dependencies": { "websocket-driver": ">=0.5.1" }, @@ -10778,24 +9717,21 @@ }, "node_modules/fb-watchman": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "bser": "2.1.1" } }, "node_modules/fflate": { "version": "0.4.8", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", - "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/file-entry-cache": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -10805,9 +9741,8 @@ }, "node_modules/file-loader": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", - "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", "dev": true, + "license": "MIT", "dependencies": { "loader-utils": "^2.0.0", "schema-utils": "^3.0.0" @@ -10825,9 +9760,8 @@ }, "node_modules/file-loader/node_modules/loader-utils": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, + "license": "MIT", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -10839,9 +9773,8 @@ }, "node_modules/file-loader/node_modules/schema-utils": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -10857,27 +9790,24 @@ }, "node_modules/filelist": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.3.tgz", - "integrity": "sha512-LwjCsruLWQULGYKy7TX0OPtrL9kLpojOFKc5VCTxdFTV7w5zbsgqVKfnkKG7Qgjtq50gKfO56hJv88OfcGb70Q==", "dev": true, + "license": "Apache-2.0", "dependencies": { "minimatch": "^5.0.1" } }, "node_modules/filelist/node_modules/brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/filelist/node_modules/minimatch": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -10886,10 +9816,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -10898,17 +9827,17 @@ } }, "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "engines": { @@ -10927,36 +9856,39 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/finalhandler/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/find-babel-config": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-2.0.0.tgz", - "integrity": "sha512-dOKT7jvF3hGzlW60Gc3ONox/0rRZ/tz7WCil0bqA1In/3I8f1BctpXahRnEKDySZqci7u+dqq93sZST9fOJpFw==", + "version": "2.1.1", "dev": true, + "license": "MIT", "dependencies": { - "json5": "^2.1.1", + "json5": "^2.2.3", "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" } }, "node_modules/find-babel-config/node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/find-cache-dir": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "dev": true, + "license": "MIT", "dependencies": { "commondir": "^1.0.1", "make-dir": "^2.0.0", @@ -10968,36 +9900,42 @@ }, "node_modules/find-root": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true + "license": "MIT" }, "node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { - "locate-path": "^2.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" + } + }, + "node_modules/find-up/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" } }, "node_modules/flat": { "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, + "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } }, "node_modules/flat-cache": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.1.0", "rimraf": "^3.0.2" @@ -11008,9 +9946,8 @@ }, "node_modules/flat-cache/node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -11023,14 +9960,11 @@ }, "node_modules/flatted": { "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", "dev": true, "funding": [ { @@ -11038,6 +9972,7 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -11049,79 +9984,55 @@ }, "node_modules/for-each": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.1.3" } }, "node_modules/foreground-child": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", - "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", - "dev": true, - "dependencies": { - "cross-spawn": "^4", - "signal-exit": "^3.0.0" - } - }, - "node_modules/foreground-child/node_modules/cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, "dependencies": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/form-data": { + "version": "4.0.0", "dev": true, + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/foreground-child/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" + "engines": { + "node": ">= 6" } }, "node_modules/formik": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/formik/-/formik-2.2.9.tgz", - "integrity": "sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==", + "version": "2.4.6", "dev": true, "funding": [ { @@ -11129,60 +10040,53 @@ "url": "https://opencollective.com/formik" } ], + "license": "Apache-2.0", "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", "deepmerge": "^2.1.1", "hoist-non-react-statics": "^3.3.0", "lodash": "^4.17.21", "lodash-es": "^4.17.21", "react-fast-compare": "^2.0.1", "tiny-warning": "^1.0.2", - "tslib": "^1.10.0" + "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, - "node_modules/formik-material-ui": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/formik-material-ui/-/formik-material-ui-3.0.1.tgz", - "integrity": "sha512-N8oxZIdhY70npRv86IfF6Zaaps9RL3a37XRdq02WDroB3XZC1mXs6lA/zQ09ZYFWYJp/UjI80SKVpVa/xJOJJA==", - "dev": true, + "node_modules/formik-mui": { + "version": "5.0.0-alpha.0", + "license": "MIT", "peerDependencies": { - "@material-ui/core": ">=4.0.0", - "formik": ">=2.0.0", - "react": ">=16.8.0", - "tiny-warning": ">=1.0.2" + "@emotion/react": ">=11.5.0", + "@emotion/styled": ">=11.3.0", + "@mui/material": ">=5.2.3", + "formik": ">=2.2.9", + "react": ">=17.0.2", + "tiny-warning": ">=1.0.3" } }, "node_modules/formik/node_modules/deepmerge": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/formik/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/forwarded": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/fraction.js": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", "dev": true, + "license": "MIT", "engines": { "node": "*" }, @@ -11194,35 +10098,36 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true, "engines": { "node": ">= 0.6" } }, - "node_modules/frontend-collective-react-dnd-scrollzone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/frontend-collective-react-dnd-scrollzone/-/frontend-collective-react-dnd-scrollzone-1.0.2.tgz", - "integrity": "sha512-me/D9PZJq9j/sjEjs/OPmm6V6nbaHbhgeQiwrWu0t35lhwAOKWc+QBzzKKcZQeboYTkgE8UvCD9el+5ANp+g5Q==", + "node_modules/fromentries": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", "dev": true, - "dependencies": { - "hoist-non-react-statics": "^3.1.0", - "lodash.throttle": "^4.0.1", - "prop-types": "^15.5.9", - "raf": "^3.2.0", - "react": "^16.3.0", - "react-display-name": "^0.2.0", - "react-dom": "^16.3.0" - }, - "peerDependencies": { - "react-dnd": "^7.3.0" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/fs-extra": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, + "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -11234,23 +10139,19 @@ } }, "node_modules/fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", - "dev": true + "version": "1.0.5", + "dev": true, + "license": "Unlicense" }, "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -11260,21 +10161,21 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "version": "1.1.6", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -11285,61 +10186,59 @@ }, "node_modules/functional-red-black-tree": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/functions-have-names": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.2.tgz", - "integrity": "sha512-bLgc3asbWdwPbx2mNk2S49kmJCuQeu0nfmaOgbs8WIyzzkw3r4htszdIi9Q9EMezDPTYuJx2wvjZ/EwgAthpnA==", + "version": "1.2.3", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/fuzzysort": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/fuzzysort/-/fuzzysort-2.0.4.tgz", - "integrity": "sha512-Api1mJL+Ad7W7vnDZnWq5pGaXJjyencT+iKGia2PlHUcSsSzWwIQ3S1isiMpwpavjYtGd2FzhUIhnnhOULZgDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-func-name": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.4", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11347,42 +10246,37 @@ }, "node_modules/get-nepali-number": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-nepali-number/-/get-nepali-number-0.1.0.tgz", - "integrity": "sha1-stNwsrDuPAn3q9aTw0ZDlZLd70E=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/get-nepday-of-week": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/get-nepday-of-week/-/get-nepday-of-week-0.1.4.tgz", - "integrity": "sha1-+MeFaHkKJBMYtO8IeUVKEFpGIt4=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/get-own-enumerable-property-symbols": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/get-package-type": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0.0" } }, "node_modules/get-stream": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, + "license": "MIT", "dependencies": { "pump": "^3.0.0" }, @@ -11394,13 +10288,13 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -11411,18 +10305,16 @@ }, "node_modules/gitignore-to-glob": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/gitignore-to-glob/-/gitignore-to-glob-0.3.0.tgz", - "integrity": "sha1-WfMqs9m2bOUCmcPtJMsO9CoJTOs=", "dev": true, + "license": "MIT", "engines": { "node": ">=4.4 <5 || >=6.9" } }, "node_modules/glob": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -11440,9 +10332,8 @@ }, "node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -11452,24 +10343,35 @@ }, "node_modules/glob-to-regexp": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/globals": { "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, + "node_modules/globalthis": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globby": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^1.0.1", "glob": "^7.0.3", @@ -11483,24 +10385,21 @@ }, "node_modules/globby/node_modules/pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/glur": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/glur/-/glur-1.1.2.tgz", - "integrity": "sha1-8g6jbbEDv8KSNDkh8fkeg8NGdok=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/gopd": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -11509,49 +10408,32 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true + "version": "4.2.11", + "dev": true, + "license": "ISC" }, "node_modules/growl": { "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4.x" } }, "node_modules/handle-thing": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/harmony-reflect": { "version": "1.6.2", - "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", - "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } + "license": "(Apache-2.0 OR MPL-1.1)" }, "node_modules/has-ansi": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, @@ -11560,30 +10442,37 @@ } }, "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "version": "1.0.2", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11591,9 +10480,8 @@ }, "node_modules/has-symbols": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -11602,12 +10490,11 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -11617,40 +10504,52 @@ } }, "node_modules/hasha": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", - "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, "dependencies": { - "is-stream": "^1.0.1" + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/hasha/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "node_modules/hasha/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/he": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, + "license": "MIT", "bin": { "he": "bin/he" } }, "node_modules/history": { "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.1.2", "loose-envify": "^1.2.0", @@ -11662,30 +10561,19 @@ }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dev": true, + "license": "BSD-3-Clause", "dependencies": { "react-is": "^16.7.0" } }, "node_modules/hoist-non-react-statics/node_modules/react-is": { "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "license": "MIT" }, "node_modules/hpack.js": { "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.1", "obuf": "^1.0.0", @@ -11695,15 +10583,13 @@ }, "node_modules/hpack.js/node_modules/isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/hpack.js/node_modules/readable-stream": { "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -11716,55 +10602,37 @@ }, "node_modules/hpack.js/node_modules/string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } }, - "node_modules/html-element-map": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.3.1.tgz", - "integrity": "sha512-6XMlxrAFX4UEEGxctfFnmrFaaZFNf9i5fNuV5wZ3WWQ4FVaNP1aX1LkX9j2mfEx1NpjeE/rL3nmgEn23GdFmrg==", - "dev": true, - "dependencies": { - "array.prototype.filter": "^1.0.0", - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "version": "4.0.0", "dev": true, + "license": "MIT", "dependencies": { - "whatwg-encoding": "^1.0.5" + "whatwg-encoding": "^3.1.1" }, "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/html-entities": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/html-escaper": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/html2canvas": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", - "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "css-line-break": "^2.1.0", @@ -11776,67 +10644,62 @@ }, "node_modules/html2pdf-dom-to-image-more": { "version": "0.9.5", - "resolved": "https://registry.npmjs.org/html2pdf-dom-to-image-more/-/html2pdf-dom-to-image-more-0.9.5.tgz", - "integrity": "sha512-YPs4dLXzJqJorngNpVGEI+XazPEu7MjcXJMRk4YSVumhB6L8fNZOFTRGvZHkgTUmjkHrJ+g0iNq3Y2vA+o89Dw==", "dev": true, + "license": "MIT", "dependencies": { "dom-to-image-more": "2.8.0", "es6-promise": "^4.2.8", "jspdf": "^2.5.1" } }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, "node_modules/http-deceiver": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "dependencies": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", + "statuses": "2.0.1", "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" } }, "node_modules/http-parser-js": { "version": "0.5.6", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", - "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/http-proxy": { "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, + "license": "MIT", "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", @@ -11847,23 +10710,32 @@ } }, "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "version": "7.0.2", "dev": true, + "license": "MIT", "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 6" + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" } }, "node_modules/http-proxy-middleware": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.4.tgz", - "integrity": "sha512-m/4FxX17SUvz4lJ5WPXOHDUuCwIqXLfLHs1s0uZ3oYjhoXlx9csYxaOa0ElDEJ+h8Q4iJ1s+lTMbiCa4EXIJqg==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", + "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", "dev": true, "dependencies": { "@types/http-proxy": "^1.17.8", @@ -11886,9 +10758,8 @@ }, "node_modules/https-proxy-agent": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" @@ -11899,24 +10770,16 @@ }, "node_modules/human-signals": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=8.12.0" } }, - "node_modules/hyphenate-style-name": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", - "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==", - "dev": true - }, "node_modules/i18n-js": { "version": "3.8.0", - "resolved": "https://registry.npmjs.org/i18n-js/-/i18n-js-3.8.0.tgz", - "integrity": "sha512-hDsGgPuvw/2P+lXSbOafAwspK8Ste8YrwuuUg17W3wEcO1JkQxBlPgsN1t2+852nTnz4YSYTjZc/1nAA2PC/nw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/iconv-lite": { "version": "0.4.24", @@ -11932,9 +10795,8 @@ }, "node_modules/icss-utils": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", "dev": true, + "license": "ISC", "engines": { "node": "^10 || ^12 || >= 14" }, @@ -11944,15 +10806,13 @@ }, "node_modules/idb": { "version": "4.0.5", - "resolved": "https://registry.npmjs.org/idb/-/idb-4.0.5.tgz", - "integrity": "sha512-P+Fk9HT2h1DhXoE1YNK183SY+CRh2GHNh28de94sGwhe0bUA75JJeVJWt3SenE5p0BXK7maflIq29dl6UZHrFw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/identity-obj-proxy": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", - "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", "dev": true, + "license": "MIT", "dependencies": { "harmony-reflect": "^1.4.6" }, @@ -11962,33 +10822,28 @@ }, "node_modules/ignore": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/image-blob-reduce": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/image-blob-reduce/-/image-blob-reduce-1.0.7.tgz", - "integrity": "sha512-sENh2BWeFjYv3mPutL/w6v/q5y6WLaobuzDMeXLB0X/XP4dLhyuBBlt3VXiM1pIp4E5z0qCAP26Va+XvCOHonA==", "dev": true, + "license": "MIT", "dependencies": { "pica": "^6.1.1" } }, "node_modules/immutable": { - "version": "4.0.0-rc.12", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz", - "integrity": "sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A==", - "dev": true + "version": "4.3.6", + "dev": true, + "license": "MIT" }, "node_modules/import-fresh": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -12002,9 +10857,8 @@ }, "node_modules/import-local": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, + "license": "MIT", "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -12019,111 +10873,37 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-local/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/import-local/node_modules/pkg-dir": { + "version": "4.2.0", "dev": true, + "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "find-up": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/import-local/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/imurmurhash": { + "version": "0.1.4", "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.8.19" } }, - "node_modules/import-local/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/indent-string": { + "version": "4.0.0", "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, + "license": "MIT", "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/import-local/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" + "node": ">=8" } }, "node_modules/inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -12131,18 +10911,16 @@ }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -12151,27 +10929,24 @@ }, "node_modules/interpret": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/ipaddr.js": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", - "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10" } }, "node_modules/is-arguments": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -12184,14 +10959,15 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12199,15 +10975,26 @@ }, "node_modules/is-arrayish": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/is-bigint": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, + "license": "MIT", "dependencies": { "has-bigints": "^1.0.1" }, @@ -12217,9 +11004,8 @@ }, "node_modules/is-binary-path": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -12229,9 +11015,8 @@ }, "node_modules/is-boolean-object": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -12244,10 +11029,9 @@ } }, "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "version": "1.2.7", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -12256,12 +11040,24 @@ } }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.13.1", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", "dev": true, + "license": "MIT", "dependencies": { - "has": "^1.0.3" + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12269,9 +11065,8 @@ }, "node_modules/is-date-object": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -12284,9 +11079,8 @@ }, "node_modules/is-docker": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, + "license": "MIT", "bin": { "is-docker": "cli.js" }, @@ -12299,9 +11093,8 @@ }, "node_modules/is-expression": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz", - "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==", "dev": true, + "license": "MIT", "dependencies": { "acorn": "^7.1.1", "object-assign": "^4.1.1" @@ -12309,9 +11102,8 @@ }, "node_modules/is-expression/node_modules/acorn": { "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -12321,36 +11113,57 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-generator-fn": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -12358,32 +11171,26 @@ "node": ">=0.10.0" } }, - "node_modules/is-in-browser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", - "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=", - "dev": true - }, "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "version": "2.0.3", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-module": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -12393,18 +11200,16 @@ }, "node_modules/is-number": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/is-number-object": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -12417,27 +11222,24 @@ }, "node_modules/is-obj": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-path-cwd": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/is-path-in-cwd": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", "dev": true, + "license": "MIT", "dependencies": { "is-path-inside": "^2.1.0" }, @@ -12447,9 +11249,8 @@ }, "node_modules/is-path-inside": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", "dev": true, + "license": "MIT", "dependencies": { "path-is-inside": "^1.0.2" }, @@ -12459,9 +11260,8 @@ }, "node_modules/is-plain-obj": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -12471,9 +11271,8 @@ }, "node_modules/is-plain-object": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, + "license": "MIT", "dependencies": { "isobject": "^3.0.1" }, @@ -12483,21 +11282,18 @@ }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-promise": { "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-regex": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -12511,29 +11307,32 @@ }, "node_modules/is-regexp": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "version": "2.0.3", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12541,9 +11340,8 @@ }, "node_modules/is-stream": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -12553,9 +11351,8 @@ }, "node_modules/is-string": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -12566,17 +11363,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", - "dev": true - }, "node_modules/is-symbol": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, + "license": "MIT", "dependencies": { "has-symbols": "^1.0.2" }, @@ -12588,16 +11378,11 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.13", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -12606,11 +11391,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, "node_modules/is-unicode-supported": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -12619,19 +11409,20 @@ } }, "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "version": "2.0.2", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-weakref": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2" }, @@ -12640,23 +11431,33 @@ } }, "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "version": "2.0.3", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-wsl": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, + "license": "MIT", "dependencies": { "is-docker": "^2.0.0" }, @@ -12666,171 +11467,266 @@ }, "node_modules/isarray": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/isobject": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/istanbul-lib-hook": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", - "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, "dependencies": { - "append-transform": "^1.0.0" + "append-transform": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/istanbul-lib-instrument": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", - "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, "dependencies": { - "@babel/generator": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", - "istanbul-lib-coverage": "^2.0.5", - "semver": "^6.0.0" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/istanbul-lib-report": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", - "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "supports-color": "^6.1.0" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "node_modules/istanbul-lib-processinfo": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", + "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "archy": "^1.0.0", + "cross-spawn": "^7.0.3", + "istanbul-lib-coverage": "^3.2.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^8.3.2" }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", - "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "node_modules/istanbul-lib-processinfo/node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "rimraf": "^2.6.3", - "source-map": "^0.6.1" + "aggregate-error": "^3.0.0" }, "engines": { - "node": ">=6" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/istanbul-reports": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", - "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", + "node_modules/istanbul-lib-processinfo/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { - "html-escaper": "^2.0.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">=6" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jake": { - "version": "10.8.5", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", - "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" - }, - "bin": { - "jake": "bin/cli.js" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" } }, - "node_modules/jake/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jake/node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", - "dev": true + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jake": { + "version": "10.8.5", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jake/node_modules/async": { + "version": "3.2.3", + "dev": true, + "license": "MIT" }, "node_modules/jake/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -12844,9 +11740,8 @@ }, "node_modules/jake/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -12856,18 +11751,16 @@ }, "node_modules/jake/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jake/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -12877,9 +11770,8 @@ }, "node_modules/jest": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -12903,9 +11795,8 @@ }, "node_modules/jest-changed-files": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, + "license": "MIT", "dependencies": { "execa": "^5.0.0", "jest-util": "^29.7.0", @@ -12917,9 +11808,8 @@ }, "node_modules/jest-changed-files/node_modules/execa": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -12940,9 +11830,8 @@ }, "node_modules/jest-changed-files/node_modules/get-stream": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -12952,18 +11841,16 @@ }, "node_modules/jest-changed-files/node_modules/human-signals": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } }, "node_modules/jest-changed-files/node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -12976,9 +11863,8 @@ }, "node_modules/jest-circus": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", @@ -13007,9 +11893,8 @@ }, "node_modules/jest-circus/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -13022,9 +11907,8 @@ }, "node_modules/jest-circus/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -13038,9 +11922,8 @@ }, "node_modules/jest-circus/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -13050,18 +11933,16 @@ }, "node_modules/jest-circus/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-circus/node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -13074,9 +11955,8 @@ }, "node_modules/jest-circus/node_modules/pretty-format": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -13088,9 +11968,8 @@ }, "node_modules/jest-circus/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -13100,15 +11979,13 @@ }, "node_modules/jest-circus/node_modules/react-is": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jest-circus/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -13118,9 +11995,8 @@ }, "node_modules/jest-cli": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/core": "^29.7.0", "@jest/test-result": "^29.7.0", @@ -13151,9 +12027,8 @@ }, "node_modules/jest-cli/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -13166,9 +12041,8 @@ }, "node_modules/jest-cli/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -13182,9 +12056,8 @@ }, "node_modules/jest-cli/node_modules/cliui": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -13196,9 +12069,8 @@ }, "node_modules/jest-cli/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -13208,18 +12080,16 @@ }, "node_modules/jest-cli/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-cli/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -13229,9 +12099,8 @@ }, "node_modules/jest-cli/node_modules/yargs": { "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -13247,18 +12116,16 @@ }, "node_modules/jest-cli/node_modules/yargs-parser": { "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/jest-config": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.7.0", @@ -13301,9 +12168,8 @@ }, "node_modules/jest-config/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -13316,9 +12182,8 @@ }, "node_modules/jest-config/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -13332,9 +12197,8 @@ }, "node_modules/jest-config/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -13344,18 +12208,16 @@ }, "node_modules/jest-config/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-config/node_modules/pretty-format": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -13367,9 +12229,8 @@ }, "node_modules/jest-config/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -13379,15 +12240,13 @@ }, "node_modules/jest-config/node_modules/react-is": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jest-config/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -13397,9 +12256,8 @@ }, "node_modules/jest-diff": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", @@ -13412,9 +12270,8 @@ }, "node_modules/jest-diff/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -13427,9 +12284,8 @@ }, "node_modules/jest-diff/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -13443,9 +12299,8 @@ }, "node_modules/jest-diff/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -13455,18 +12310,16 @@ }, "node_modules/jest-diff/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-diff/node_modules/pretty-format": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -13478,9 +12331,8 @@ }, "node_modules/jest-diff/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -13490,15 +12342,13 @@ }, "node_modules/jest-diff/node_modules/react-is": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jest-diff/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -13508,9 +12358,8 @@ }, "node_modules/jest-docblock": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, + "license": "MIT", "dependencies": { "detect-newline": "^3.0.0" }, @@ -13520,9 +12369,8 @@ }, "node_modules/jest-each": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", @@ -13536,9 +12384,8 @@ }, "node_modules/jest-each/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -13551,9 +12398,8 @@ }, "node_modules/jest-each/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -13567,9 +12413,8 @@ }, "node_modules/jest-each/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -13579,18 +12424,16 @@ }, "node_modules/jest-each/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-each/node_modules/pretty-format": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -13602,9 +12445,8 @@ }, "node_modules/jest-each/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -13614,15 +12456,13 @@ }, "node_modules/jest-each/node_modules/react-is": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jest-each/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -13631,18 +12471,17 @@ } }, "node_modules/jest-environment-jsdom": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.5.0.tgz", - "integrity": "sha512-/KG8yEK4aN8ak56yFVdqFDzKNHgF4BAymCx2LbPNPsUshUlfAl0eX402Xm1pt+eoG9SLZEUVifqXtX8SK74KCw==", + "version": "29.7.0", "dev": true, + "license": "MIT", "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/jsdom": "^20.0.0", "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0", "jsdom": "^20.0.0" }, "engines": { @@ -13659,18 +12498,16 @@ }, "node_modules/jest-environment-jsdom/node_modules/@tootallnate/once": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10" } }, "node_modules/jest-environment-jsdom/node_modules/acorn-globals": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", "dev": true, + "license": "MIT", "dependencies": { "acorn": "^8.1.0", "acorn-walk": "^8.0.2" @@ -13678,24 +12515,21 @@ }, "node_modules/jest-environment-jsdom/node_modules/acorn-walk": { "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/jest-environment-jsdom/node_modules/cssom": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jest-environment-jsdom/node_modules/data-urls": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", "dev": true, + "license": "MIT", "dependencies": { "abab": "^2.0.6", "whatwg-mimetype": "^3.0.0", @@ -13707,9 +12541,8 @@ }, "node_modules/jest-environment-jsdom/node_modules/domexception": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", "dev": true, + "license": "MIT", "dependencies": { "webidl-conversions": "^7.0.0" }, @@ -13719,9 +12552,8 @@ }, "node_modules/jest-environment-jsdom/node_modules/entities": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -13729,25 +12561,10 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/jest-environment-jsdom/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/jest-environment-jsdom/node_modules/html-encoding-sniffer": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", "dev": true, + "license": "MIT", "dependencies": { "whatwg-encoding": "^2.0.0" }, @@ -13757,9 +12574,8 @@ }, "node_modules/jest-environment-jsdom/node_modules/http-proxy-agent": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, + "license": "MIT", "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -13771,9 +12587,8 @@ }, "node_modules/jest-environment-jsdom/node_modules/iconv-lite": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -13783,9 +12598,8 @@ }, "node_modules/jest-environment-jsdom/node_modules/jsdom": { "version": "20.0.3", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", - "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", "dev": true, + "license": "MIT", "dependencies": { "abab": "^2.0.6", "acorn": "^8.8.1", @@ -13828,9 +12642,8 @@ }, "node_modules/jest-environment-jsdom/node_modules/parse5": { "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", "dev": true, + "license": "MIT", "dependencies": { "entities": "^4.4.0" }, @@ -13838,23 +12651,10 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/jest-environment-jsdom/node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, "node_modules/jest-environment-jsdom/node_modules/tr46": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", "dev": true, + "license": "MIT", "dependencies": { "punycode": "^2.1.1" }, @@ -13864,9 +12664,8 @@ }, "node_modules/jest-environment-jsdom/node_modules/w3c-xmlserializer": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", "dev": true, + "license": "MIT", "dependencies": { "xml-name-validator": "^4.0.0" }, @@ -13876,18 +12675,16 @@ }, "node_modules/jest-environment-jsdom/node_modules/webidl-conversions": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=12" } }, "node_modules/jest-environment-jsdom/node_modules/whatwg-encoding": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", "dev": true, + "license": "MIT", "dependencies": { "iconv-lite": "0.6.3" }, @@ -13897,18 +12694,16 @@ }, "node_modules/jest-environment-jsdom/node_modules/whatwg-mimetype": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" } }, "node_modules/jest-environment-jsdom/node_modules/whatwg-url": { "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "dev": true, + "license": "MIT", "dependencies": { "tr46": "^3.0.0", "webidl-conversions": "^7.0.0" @@ -13917,41 +12712,18 @@ "node": ">=12" } }, - "node_modules/jest-environment-jsdom/node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/jest-environment-jsdom/node_modules/xml-name-validator": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12" } }, "node_modules/jest-environment-node": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", @@ -13966,18 +12738,16 @@ }, "node_modules/jest-get-type": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -14000,18 +12770,16 @@ }, "node_modules/jest-haste-map/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-haste-map/node_modules/jest-worker": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", @@ -14024,9 +12792,8 @@ }, "node_modules/jest-haste-map/node_modules/supports-color": { "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -14039,9 +12806,8 @@ }, "node_modules/jest-leak-detector": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, + "license": "MIT", "dependencies": { "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" @@ -14052,9 +12818,8 @@ }, "node_modules/jest-leak-detector/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -14064,9 +12829,8 @@ }, "node_modules/jest-leak-detector/node_modules/pretty-format": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -14078,15 +12842,13 @@ }, "node_modules/jest-leak-detector/node_modules/react-is": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jest-matcher-utils": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.7.0", @@ -14099,9 +12861,8 @@ }, "node_modules/jest-matcher-utils/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -14114,9 +12875,8 @@ }, "node_modules/jest-matcher-utils/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14130,9 +12890,8 @@ }, "node_modules/jest-matcher-utils/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -14142,18 +12901,16 @@ }, "node_modules/jest-matcher-utils/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-matcher-utils/node_modules/pretty-format": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -14165,9 +12922,8 @@ }, "node_modules/jest-matcher-utils/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -14177,15 +12933,13 @@ }, "node_modules/jest-matcher-utils/node_modules/react-is": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jest-matcher-utils/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -14195,9 +12949,8 @@ }, "node_modules/jest-message-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.6.3", @@ -14215,9 +12968,8 @@ }, "node_modules/jest-message-util/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -14230,9 +12982,8 @@ }, "node_modules/jest-message-util/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14246,9 +12997,8 @@ }, "node_modules/jest-message-util/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -14258,18 +13008,16 @@ }, "node_modules/jest-message-util/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-message-util/node_modules/pretty-format": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -14281,9 +13029,8 @@ }, "node_modules/jest-message-util/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -14293,15 +13040,13 @@ }, "node_modules/jest-message-util/node_modules/react-is": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jest-message-util/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -14311,9 +13056,8 @@ }, "node_modules/jest-mock": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -14325,9 +13069,8 @@ }, "node_modules/jest-pnp-resolver": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -14342,18 +13085,16 @@ }, "node_modules/jest-regex-util": { "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", @@ -14371,9 +13112,8 @@ }, "node_modules/jest-resolve-dependencies": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, + "license": "MIT", "dependencies": { "jest-regex-util": "^29.6.3", "jest-snapshot": "^29.7.0" @@ -14384,9 +13124,8 @@ }, "node_modules/jest-resolve/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -14399,9 +13138,8 @@ }, "node_modules/jest-resolve/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14415,9 +13153,8 @@ }, "node_modules/jest-resolve/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -14427,18 +13164,16 @@ }, "node_modules/jest-resolve/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-resolve/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -14448,9 +13183,8 @@ }, "node_modules/jest-runner": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/environment": "^29.7.0", @@ -14480,9 +13214,8 @@ }, "node_modules/jest-runner/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -14495,9 +13228,8 @@ }, "node_modules/jest-runner/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14511,9 +13243,8 @@ }, "node_modules/jest-runner/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -14523,18 +13254,16 @@ }, "node_modules/jest-runner/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-runner/node_modules/jest-worker": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", @@ -14547,9 +13276,8 @@ }, "node_modules/jest-runner/node_modules/jest-worker/node_modules/supports-color": { "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -14562,9 +13290,8 @@ }, "node_modules/jest-runner/node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -14577,18 +13304,16 @@ }, "node_modules/jest-runner/node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/jest-runner/node_modules/source-map-support": { "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -14596,9 +13321,8 @@ }, "node_modules/jest-runner/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -14608,9 +13332,8 @@ }, "node_modules/jest-runtime": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", @@ -14641,9 +13364,8 @@ }, "node_modules/jest-runtime/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -14656,9 +13378,8 @@ }, "node_modules/jest-runtime/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14672,9 +13393,8 @@ }, "node_modules/jest-runtime/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -14684,27 +13404,24 @@ }, "node_modules/jest-runtime/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-runtime/node_modules/strip-bom": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-runtime/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -14714,9 +13431,8 @@ }, "node_modules/jest-snapshot": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", @@ -14745,9 +13461,8 @@ }, "node_modules/jest-snapshot/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -14760,9 +13475,8 @@ }, "node_modules/jest-snapshot/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14776,9 +13490,8 @@ }, "node_modules/jest-snapshot/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -14788,18 +13501,16 @@ }, "node_modules/jest-snapshot/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-snapshot/node_modules/pretty-format": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -14811,9 +13522,8 @@ }, "node_modules/jest-snapshot/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -14823,15 +13533,13 @@ }, "node_modules/jest-snapshot/node_modules/react-is": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jest-snapshot/node_modules/semver": { "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -14844,9 +13552,8 @@ }, "node_modules/jest-snapshot/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -14856,9 +13563,8 @@ }, "node_modules/jest-util": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -14873,9 +13579,8 @@ }, "node_modules/jest-util/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -14888,9 +13593,8 @@ }, "node_modules/jest-util/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14904,9 +13608,8 @@ }, "node_modules/jest-util/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -14916,18 +13619,16 @@ }, "node_modules/jest-util/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-util/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -14937,9 +13638,8 @@ }, "node_modules/jest-validate": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "camelcase": "^6.2.0", @@ -14954,9 +13654,8 @@ }, "node_modules/jest-validate/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -14969,9 +13668,8 @@ }, "node_modules/jest-validate/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -14985,9 +13683,8 @@ }, "node_modules/jest-validate/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -14997,18 +13694,16 @@ }, "node_modules/jest-validate/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-validate/node_modules/pretty-format": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -15020,9 +13715,8 @@ }, "node_modules/jest-validate/node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -15032,15 +13726,13 @@ }, "node_modules/jest-validate/node_modules/react-is": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jest-validate/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -15050,9 +13742,8 @@ }, "node_modules/jest-watcher": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, + "license": "MIT", "dependencies": { "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", @@ -15069,9 +13760,8 @@ }, "node_modules/jest-watcher/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -15084,9 +13774,8 @@ }, "node_modules/jest-watcher/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -15100,9 +13789,8 @@ }, "node_modules/jest-watcher/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -15112,18 +13800,16 @@ }, "node_modules/jest-watcher/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-watcher/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -15133,9 +13819,8 @@ }, "node_modules/jest-worker": { "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -15147,18 +13832,16 @@ }, "node_modules/jest-worker/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/jest-worker/node_modules/supports-color": { "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -15171,20 +13854,17 @@ }, "node_modules/js-stringify": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", - "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -15194,9 +13874,8 @@ }, "node_modules/jscpd": { "version": "3.4.5", - "resolved": "https://registry.npmjs.org/jscpd/-/jscpd-3.4.5.tgz", - "integrity": "sha512-2gAskcIpbnNTs0RgPZG72xBNa0eRR7mB121XApzbN7kkRUUue2ZT9ug7HMV1JZ01hIpJkrrchcDidMgnl6/DWA==", "dev": true, + "license": "MIT", "dependencies": { "@jscpd/core": "^3.4.5", "@jscpd/finder": "^3.4.5", @@ -15212,44 +13891,37 @@ } }, "node_modules/jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "version": "24.1.0", "dev": true, + "license": "MIT", "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", + "cssstyle": "^4.0.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.4", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", + "nwsapi": "^2.2.10", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.0", + "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" + "tough-cookie": "^4.1.4", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.17.0", + "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "peerDependencies": { - "canvas": "^2.5.0" + "canvas": "^2.11.2" }, "peerDependenciesMeta": { "canvas": { @@ -15259,18 +13931,112 @@ }, "node_modules/jsdom-global": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-3.0.2.tgz", - "integrity": "sha1-a9KZwTsMRiay2iwDk81DhdYGrLk=", "dev": true, + "license": "MIT", "peerDependencies": { "jsdom": ">=10.0.0" } }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "7.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/cssstyle": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "rrweb-cssom": "^0.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/cssstyle/node_modules/rrweb-cssom": { + "version": "0.6.0", + "dev": true, + "license": "MIT" + }, + "node_modules/jsdom/node_modules/entities": { + "version": "4.5.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "7.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/parse5": { + "version": "7.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/jsdom/node_modules/rrweb-cssom": { + "version": "0.7.0", + "dev": true, + "license": "MIT" + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "14.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/jsesc": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -15278,47 +14044,34 @@ "node": ">=4" } }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "license": "MIT" }, "node_modules/json-schema": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true + "dev": true, + "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stringify-safe": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/json5": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -15328,15 +14081,13 @@ }, "node_modules/jsonc-parser": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsonfile": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -15346,18 +14097,16 @@ }, "node_modules/jsonpointer": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz", - "integrity": "sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/jspdf": { "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz", - "integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.14.0", "atob": "^2.1.2", @@ -15371,593 +14120,234 @@ "html2canvas": "^1.0.0-rc.5" } }, - "node_modules/jspdf/node_modules/core-js": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", - "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "node_modules/jstransformer": { + "version": "1.0.0", "dev": true, - "hasInstallScript": true, - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" + "license": "MIT", + "dependencies": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" } }, - "node_modules/jss": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.8.2.tgz", - "integrity": "sha512-FkoUNxI329CKQ9OQC8L72MBF9KPf5q8mIupAJ5twU7G7XREW7ahb+7jFfrjZ4iy1qvhx1HwIWUIvkZBDnKkEdQ==", + "node_modules/jsx-ast-utils": { + "version": "3.3.5", "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/jss" + "engines": { + "node": ">=4.0" } }, - "node_modules/jss-plugin-camel-case": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.9.0.tgz", - "integrity": "sha512-UH6uPpnDk413/r/2Olmw4+y54yEF2lRIV8XIZyuYpgPYTITLlPOsq6XB9qeqv+75SQSg3KLocq5jUBXW8qWWww==", + "node_modules/just-extend": { + "version": "4.2.1", "dev": true, - "dependencies": { - "@babel/runtime": "^7.3.1", - "hyphenate-style-name": "^1.0.3", - "jss": "10.9.0" - } - }, - "node_modules/jss-plugin-camel-case/node_modules/csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true + "license": "MIT" }, - "node_modules/jss-plugin-camel-case/node_modules/jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", + "node_modules/keyevent": { + "version": "1.1.0", "dev": true, - "dependencies": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/jss" - } + "license": "MIT" }, - "node_modules/jss-plugin-default-unit": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.9.0.tgz", - "integrity": "sha512-7Ju4Q9wJ/MZPsxfu4T84mzdn7pLHWeqoGd/D8O3eDNNJ93Xc8PxnLmV8s8ZPNRYkLdxZqKtm1nPQ0BM4JRlq2w==", + "node_modules/kind-of": { + "version": "6.0.3", "dev": true, - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/jss-plugin-default-unit/node_modules/csstype": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==", - "dev": true - }, - "node_modules/jss-plugin-default-unit/node_modules/jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", + "node_modules/kleur": { + "version": "3.0.3", "dev": true, - "dependencies": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/jss" + "license": "MIT", + "engines": { + "node": ">=6" } }, - "node_modules/jss-plugin-extend": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/jss-plugin-extend/-/jss-plugin-extend-10.8.2.tgz", - "integrity": "sha512-NYu0cJ/Zb50ySPkegzbXQQfhXza0VpaRVXdXDex30yXqZpGcAdmhSg4HTv8vzHiL1v3uIOm641FYQX9WvLgSWw==", + "node_modules/klona": { + "version": "2.0.5", "dev": true, - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.8.2", - "tiny-warning": "^1.0.2" + "license": "MIT", + "engines": { + "node": ">= 8" } }, - "node_modules/jss-plugin-global": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.9.0.tgz", - "integrity": "sha512-4G8PHNJ0x6nwAFsEzcuVDiBlyMsj2y3VjmFAx/uHk/R/gzJV+yRHICjT4MKGGu1cJq2hfowFWCyrr/Gg37FbgQ==", + "node_modules/language-subtag-registry": { + "version": "0.3.23", "dev": true, - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0" - } - }, - "node_modules/jss-plugin-global/node_modules/csstype": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==", - "dev": true + "license": "CC0-1.0" }, - "node_modules/jss-plugin-global/node_modules/jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", + "node_modules/language-tags": { + "version": "1.0.9", "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" + "language-subtag-registry": "^0.3.20" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/jss" + "engines": { + "node": ">=0.10" } }, - "node_modules/jss-plugin-nested": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.9.0.tgz", - "integrity": "sha512-2UJnDrfCZpMYcpPYR16oZB7VAC6b/1QLsRiAutOt7wJaaqwCBvNsosLEu/fUyKNQNGdvg2PPJFDO5AX7dwxtoA==", + "node_modules/launch-editor": { + "version": "2.6.1", "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "tiny-warning": "^1.0.2" + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" } }, - "node_modules/jss-plugin-nested/node_modules/csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true + "node_modules/leven": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "node_modules/jss-plugin-nested/node_modules/jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", + "node_modules/levn": { + "version": "0.4.1", "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/jss" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/jss-plugin-props-sort": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.9.0.tgz", - "integrity": "sha512-7A76HI8bzwqrsMOJTWKx/uD5v+U8piLnp5bvru7g/3ZEQOu1+PjHvv7bFdNO3DwNPC9oM0a//KwIJsIcDCjDzw==", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "license": "MIT" + }, + "node_modules/loader-runner": { + "version": "4.2.0", "dev": true, - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0" + "license": "MIT", + "engines": { + "node": ">=6.11.5" } }, - "node_modules/jss-plugin-props-sort/node_modules/csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true - }, - "node_modules/jss-plugin-props-sort/node_modules/jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" + "p-locate": "^4.1.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/jss" + "engines": { + "node": ">=8" } }, - "node_modules/jss-plugin-rule-value-function": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.9.0.tgz", - "integrity": "sha512-IHJv6YrEf8pRzkY207cPmdbBstBaE+z8pazhPShfz0tZSDtRdQua5jjg6NMz3IbTasVx9FdnmptxPqSWL5tyJg==", + "node_modules/lockfile": { + "version": "1.0.4", "dev": true, + "license": "ISC", "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "tiny-warning": "^1.0.2" + "signal-exit": "^3.0.2" } }, - "node_modules/jss-plugin-rule-value-function/node_modules/csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true + "node_modules/lodash": { + "version": "4.17.21", + "license": "MIT" }, - "node_modules/jss-plugin-rule-value-function/node_modules/jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", + "node_modules/lodash-es": { + "version": "4.17.21", "dev": true, - "dependencies": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/jss" - } + "license": "MIT" }, - "node_modules/jss-plugin-vendor-prefixer": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.9.0.tgz", - "integrity": "sha512-MbvsaXP7iiVdYVSEoi+blrW+AYnTDvHTW6I6zqi7JcwXdc6I9Kbm234nEblayhF38EftoenbM+5218pidmC5gA==", + "node_modules/lodash.assignwith": { + "version": "4.2.0", "dev": true, - "dependencies": { - "@babel/runtime": "^7.3.1", - "css-vendor": "^2.0.8", - "jss": "10.9.0" - } - }, - "node_modules/jss-plugin-vendor-prefixer/node_modules/csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true + "license": "MIT" }, - "node_modules/jss-plugin-vendor-prefixer/node_modules/jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", + "node_modules/lodash.clonedeep": { + "version": "4.5.0", "dev": true, - "dependencies": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/jss" - } - }, - "node_modules/jss-rtl": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/jss-rtl/-/jss-rtl-0.3.0.tgz", - "integrity": "sha512-rg9jJmP1bAyhNOAp+BDZgOP/lMm4+oQ76qGueupDQ68Wq+G+6SGvCZvhIEg8OHSONRWOwFT6skCI+APGi8DgmA==", - "dev": true, - "dependencies": { - "rtl-css-js": "^1.13.1" - }, - "peerDependencies": { - "jss": "^10.0.0" - } - }, - "node_modules/jss/node_modules/csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true - }, - "node_modules/jstransformer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", - "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", - "dev": true, - "dependencies": { - "is-promise": "^2.0.0", - "promise": "^7.0.1" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz", - "integrity": "sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.3", - "object.assign": "^4.1.2" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "node_modules/keyevent": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/keyevent/-/keyevent-1.1.0.tgz", - "integrity": "sha1-nA4BGKIv2D1NI/ZxOhBwE5HKYGA=", - "dev": true - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/klona": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", - "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", - "integrity": "sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==", - "dev": true - }, - "node_modules/language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha1-0yHbxNowuovzAk4ED6XBRmH5GTo=", - "dev": true, - "dependencies": { - "language-subtag-registry": "~0.3.2" - } - }, - "node_modules/launch-editor": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", - "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", - "dev": true, - "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.8.1" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/lockfile": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz", - "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", - "dev": true, - "dependencies": { - "signal-exit": "^3.0.2" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", - "dev": true - }, - "node_modules/lodash.assignwith": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz", - "integrity": "sha512-ZznplvbvtjK2gMvnQ1BR/zqPFZmS6jbK4p+6Up4xcRYA7yMIwxHCfbTcrYxXKzzqLsQ05eJPVznEW3tuwV7k1g==", - "dev": true - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true + "license": "MIT" }, "node_modules/lodash.debounce": { "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true - }, - "node_modules/lodash.escape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.find": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", - "integrity": "sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", "dev": true }, "node_modules/lodash.get": { "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.has": { "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", - "integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.isequal": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.isequalwith": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.isequalwith/-/lodash.isequalwith-4.4.0.tgz", - "integrity": "sha1-Jmcm3dUo+FTyH06pigZWBuD7xrA=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.isplainobject": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.isundefined": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", - "integrity": "sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.memoize": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.sortby": { "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.throttle": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.truncate": { "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -15971,9 +14361,8 @@ }, "node_modules/log-symbols/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -15986,9 +14375,8 @@ }, "node_modules/log-symbols/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -16002,9 +14390,8 @@ }, "node_modules/log-symbols/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -16014,18 +14401,16 @@ }, "node_modules/log-symbols/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/log-symbols/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -16035,9 +14420,8 @@ }, "node_modules/loglevel": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", - "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6.0" }, @@ -16048,9 +14432,8 @@ }, "node_modules/loglevel-colored-level-prefix": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz", - "integrity": "sha1-akAhj9x64V/HbD0PPmdsRlOIYD4=", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^1.1.3", "loglevel": "^1.4.1" @@ -16058,18 +14441,16 @@ }, "node_modules/loglevel-colored-level-prefix/node_modules/ansi-styles": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/loglevel-colored-level-prefix/node_modules/chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", @@ -16083,9 +14464,8 @@ }, "node_modules/loglevel-colored-level-prefix/node_modules/strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, @@ -16095,23 +14475,20 @@ }, "node_modules/loglevel-colored-level-prefix/node_modules/supports-color": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/lolex": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", - "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/loose-envify": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -16121,17 +14498,16 @@ }, "node_modules/loupe": { "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", "dev": true, + "license": "MIT", "dependencies": { "get-func-name": "^2.0.0" } }, "node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -16141,27 +14517,24 @@ }, "node_modules/lz-string": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, + "license": "MIT", "bin": { "lz-string": "bin/bin.js" } }, "node_modules/magic-string": { "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", "dev": true, + "license": "MIT", "dependencies": { "sourcemap-codec": "^1.4.8" } }, "node_modules/make-dir": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, + "license": "MIT", "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -16172,27 +14545,24 @@ }, "node_modules/make-dir/node_modules/semver": { "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } }, "node_modules/makeerror": { "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "tmpl": "1.0.5" } }, "node_modules/markdown-table": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", - "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", "dev": true, + "license": "MIT", "dependencies": { "repeat-string": "^1.0.0" }, @@ -16204,19 +14574,18 @@ "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/memfs": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", - "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", + "version": "3.5.3", "dev": true, + "license": "Unlicense", "dependencies": { - "fs-monkey": "1.0.3" + "fs-monkey": "^1.0.4" }, "engines": { "node": ">= 4.0.0" @@ -16224,66 +14593,47 @@ }, "node_modules/memoize-one": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", - "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", - "dev": true - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "node_modules/merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } + "license": "MIT" }, - "node_modules/merge-source-map/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "dev": true, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/merge-stream": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/methods": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" @@ -16303,18 +14653,16 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -16324,28 +14672,24 @@ }, "node_modules/mimic-fn": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/min-indent": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/mini-create-react-context": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", - "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.1", "tiny-warning": "^1.0.3" @@ -16356,12 +14700,12 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.4.tgz", - "integrity": "sha512-UJ+aNuFQaQaECu7AamlWOBLj2cJ6XSGU4zNiqXeZ7lZLe5VD0DoSPWFbWArXueo+6FZVbgHzpX9lUIaBIDLuYg==", + "version": "2.9.0", "dev": true, + "license": "MIT", "dependencies": { - "schema-utils": "^3.1.0" + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" }, "engines": { "node": ">= 12.13.0" @@ -16374,62 +14718,96 @@ "webpack": "^5.0.0" } }, - "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "node_modules/mini-css-extract-plugin/node_modules/ajv": { + "version": "8.16.0", "dev": true, + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "fast-deep-equal": "^3.1.3" }, - "engines": { - "node": "*" + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, "node_modules/minimist": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/minimist-lite": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/minimist-lite/-/minimist-lite-2.2.1.tgz", - "integrity": "sha512-RSrWIRWGYoM2TDe102s7aIyeSipXMIXKb1fSHYx1tAbxAV0z4g2xR6ra3oPzkTqFb0EIUz1H3A/qvYYeDd+/qQ==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/minipass": { + "version": "4.2.8", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } }, "node_modules/mkdirp": { "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -16439,9 +14817,8 @@ }, "node_modules/mocha": { "version": "9.2.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", - "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, + "license": "MIT", "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", @@ -16482,9 +14859,8 @@ }, "node_modules/mocha/node_modules/debug": { "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -16499,15 +14875,13 @@ }, "node_modules/mocha/node_modules/debug/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/mocha/node_modules/escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -16517,9 +14891,8 @@ }, "node_modules/mocha/node_modules/find-up": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -16533,18 +14906,16 @@ }, "node_modules/mocha/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/mocha/node_modules/locate-path": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -16557,9 +14928,8 @@ }, "node_modules/mocha/node_modules/minimatch": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", - "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -16569,15 +14939,13 @@ }, "node_modules/mocha/node_modules/ms": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/mocha/node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -16590,9 +14958,8 @@ }, "node_modules/mocha/node_modules/p-locate": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -16605,18 +14972,16 @@ }, "node_modules/mocha/node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -16629,32 +14994,23 @@ }, "node_modules/moment": { "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, - "node_modules/moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==", - "dev": true - }, "node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "license": "MIT" }, "node_modules/mui-datatables": { - "version": "3.8.5", - "resolved": "https://registry.npmjs.org/mui-datatables/-/mui-datatables-3.8.5.tgz", - "integrity": "sha512-VS54Xkm5eXsPOUvzG3vXVjgSd2/nswwvhMK2D4PiHpV5MRJwfc6mdyuskh3s3jUi3NC8N+u7NsxX4pY14qaoKQ==", + "version": "4.3.0", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime-corejs3": "^7.12.1", + "@emotion/cache": "^11.7.1", "clsx": "^1.1.1", "lodash.assignwith": "^4.2.0", "lodash.clonedeep": "^4.5.0", @@ -16668,24 +15024,52 @@ "prop-types": "^15.7.2", "react-dnd": "^11.1.3", "react-dnd-html5-backend": "^11.1.3", - "react-sortable-tree": "^2.7.1", - "react-to-print": "^2.8.0" + "react-sortable-tree-patch-react-17": "^2.9.0", + "react-to-print": "^2.8.0", + "tss-react": "^3.6.0" + }, + "peerDependencies": { + "@emotion/react": "^11.10.5", + "@mui/icons-material": "^5.11.0", + "@mui/material": "^5.11.0", + "react": "^16.8.0 || ^17.0.2 || ^18.2.0", + "react-dom": "^16.8.0 || ^17.0.2 || ^18.2.0" + } + }, + "node_modules/mui-datatables/node_modules/@emotion/utils": { + "version": "1.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/mui-datatables/node_modules/tss-react": { + "version": "3.7.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@emotion/cache": "*", + "@emotion/serialize": "*", + "@emotion/utils": "*" }, "peerDependencies": { - "@material-ui/core": "^4.12.0", - "@material-ui/icons": "^4.11.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" + "@emotion/react": "^11.4.1", + "@emotion/server": "^11.4.0", + "react": "^16.8.0 || ^17.0.2 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/server": { + "optional": true + } } }, "node_modules/mui-nepali-datepicker-reactjs": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/mui-nepali-datepicker-reactjs/-/mui-nepali-datepicker-reactjs-1.1.4.tgz", - "integrity": "sha512-PWp+V2MfqK0OiuLqDP0tdpaTsJsahFcA/e6mNG7R049UNjVCrt/ZsiGRofBTr1sGYcPkBP+9Ai9MbFSqHSCeqA==", + "version": "2.0.0", "dev": true, + "license": "MIT", "dependencies": { - "@material-ui/core": "^4.12.3", - "@material-ui/icons": "^4.11.2", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "@mui/icons-material": "^5.15.20", + "@mui/material": "^5.15.20", "bikram-sambat-js": "^1.0.1", "nepali-number": "^1.0.3" }, @@ -16693,15 +15077,14 @@ "node": ">=10" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^18.3.1", + "react-dom": "^18.3.1" } }, "node_modules/multicast-dns": { "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", "dev": true, + "license": "MIT", "dependencies": { "dns-packet": "^5.2.2", "thunky": "^1.0.2" @@ -16712,9 +15095,8 @@ }, "node_modules/multimath": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/multimath/-/multimath-2.0.0.tgz", - "integrity": "sha512-toRx66cAMJ+Ccz7pMIg38xSIrtnbozk0dchXezwQDMgQmbGpfxjtv68H+L00iFL8hxDaVjrmwAFSb3I6bg8Q2g==", "dev": true, + "license": "MIT", "dependencies": { "glur": "^1.1.2", "object-assign": "^4.1.1" @@ -16722,21 +15104,18 @@ }, "node_modules/mutationobserver-shim": { "version": "0.3.7", - "resolved": "https://registry.npmjs.org/mutationobserver-shim/-/mutationobserver-shim-0.3.7.tgz", - "integrity": "sha512-oRIDTyZQU96nAiz2AQyngwx1e89iApl2hN5AOYwyxLUB47UYsU3Wv9lJWqH5y/QdiYkc5HQLi23ZNB3fELdHcQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nanoclone": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", - "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true, + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -16746,70 +15125,31 @@ }, "node_modules/natural-compare": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", "dev": true, - "dependencies": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "bin": { - "nearley-railroad": "bin/nearley-railroad.js", - "nearley-test": "bin/nearley-test.js", - "nearley-unparse": "bin/nearley-unparse.js", - "nearleyc": "bin/nearleyc.js" - }, - "funding": { - "type": "individual", - "url": "https://nearley.js.org/#give-to-nearley" - } - }, - "node_modules/nearley/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/neo-async": { "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nepali-number": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/nepali-number/-/nepali-number-1.0.3.tgz", - "integrity": "sha512-Vb6aMQM/xtE7KiiEhemgDcACxIMaDn18Ub/imWXB6JlhDwc2qVDnGW+sR0gDLPQmyiyk06bkKze1oK88FxWIjw==", - "dev": true - }, - "node_modules/nested-error-stacks": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", - "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nise": { "version": "1.5.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", - "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/formatio": "^3.2.1", "@sinonjs/text-encoding": "^0.7.1", @@ -16820,18 +15160,16 @@ }, "node_modules/nise/node_modules/lolex": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", - "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^1.7.0" } }, "node_modules/nock": { "version": "10.0.6", - "resolved": "https://registry.npmjs.org/nock/-/nock-10.0.6.tgz", - "integrity": "sha512-b47OWj1qf/LqSQYnmokNWM8D88KvUl2y7jT0567NB3ZBAZFz2bWp2PC81Xn7u8F2/vJxzkzNZybnemeFa7AZ2w==", "dev": true, + "license": "MIT", "dependencies": { "chai": "^4.1.2", "debug": "^4.1.0", @@ -16849,84 +15187,67 @@ }, "node_modules/nock/node_modules/semver": { "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } }, "node_modules/node-forge": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", "dev": true, + "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" } }, "node_modules/node-int64": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", - "dev": true + "dev": true, + "license": "MIT" }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "node_modules/node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "process-on-spawn": "^1.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/node-releases": { + "version": "2.0.14", "dev": true, - "bin": { - "semver": "bin/semver" - } + "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/normalize-range": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/normalizr": { "version": "3.6.2", - "resolved": "https://registry.npmjs.org/normalizr/-/normalizr-3.6.2.tgz", - "integrity": "sha512-30qCybsBaCBciotorvuOZTCGEg2AXrJfADMT2Kk/lvpIAcipHdK0zc33nNtwKzyfQAqIJXAcqET6YgflYUgsoQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/notistack": { - "version": "0.9.17", - "resolved": "https://registry.npmjs.org/notistack/-/notistack-0.9.17.tgz", - "integrity": "sha512-nypTN6sEe+q98wMaxF/UwatA1yAq948+bZOo9JKYR+tU65DW0ipWyx8DseJ3UJYvb6VDD+Fqo83qwayQ46bEEA==", + "version": "2.0.8", "dev": true, + "license": "MIT", "dependencies": { "clsx": "^1.1.0", "hoist-non-react-statics": "^3.3.0" @@ -16936,16 +15257,25 @@ "url": "https://opencollective.com/notistack" }, "peerDependencies": { - "@material-ui/core": "^4.0.0", - "react": "^16.8.0", - "react-dom": "^16.8.0" + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "@mui/material": "^5.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } } }, "node_modules/npm-run-path": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.0.0" }, @@ -16955,9 +15285,8 @@ }, "node_modules/nth-check": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0" }, @@ -16966,57 +15295,64 @@ } }, "node_modules/nwsapi": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.4.tgz", - "integrity": "sha512-NHj4rzRo0tQdijE9ZqAx6kYDcoRwYwSYzCA8MY3JzfxlrvEU0jhnhJT9BhqhJs7I/dKcrDm6TyulaRqZPIhN5g==", - "dev": true + "version": "2.2.10", + "dev": true, + "license": "MIT" }, "node_modules/nyc": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", - "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-17.1.0.tgz", + "integrity": "sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ==", "dev": true, "dependencies": { - "archy": "^1.0.0", - "caching-transform": "^3.0.2", - "convert-source-map": "^1.6.0", - "cp-file": "^6.2.0", - "find-cache-dir": "^2.1.0", - "find-up": "^3.0.0", - "foreground-child": "^1.5.6", - "glob": "^7.1.3", - "istanbul-lib-coverage": "^2.0.5", - "istanbul-lib-hook": "^2.0.7", - "istanbul-lib-instrument": "^3.3.0", - "istanbul-lib-report": "^2.0.8", - "istanbul-lib-source-maps": "^3.0.6", - "istanbul-reports": "^2.2.4", - "js-yaml": "^3.13.1", - "make-dir": "^2.1.0", - "merge-source-map": "^1.1.0", - "resolve-from": "^4.0.0", - "rimraf": "^2.6.3", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^3.3.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^6.0.2", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", "signal-exit": "^3.0.2", - "spawn-wrap": "^1.4.2", - "test-exclude": "^5.2.3", - "uuid": "^3.3.2", - "yargs": "^13.2.2", - "yargs-parser": "^13.0.0" + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" }, "bin": { "nyc": "bin/nyc.js" }, "engines": { - "node": ">=6" + "node": ">=18" } }, - "node_modules/nyc/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/nyc/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/nyc/node_modules/camelcase": { @@ -17029,152 +15365,130 @@ } }, "node_modules/nyc/node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/nyc/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, - "node_modules/nyc/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/nyc/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/nyc/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "locate-path": "^3.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=6" + "node": ">=7.0.0" } }, - "node_modules/nyc/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "node_modules/nyc/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, "engines": { - "node": ">=4" - } - }, - "node_modules/nyc/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "node": ">=0.10.0" } }, - "node_modules/nyc/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/nyc/node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" }, "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, - "node_modules/nyc/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/nyc/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "dependencies": { - "p-try": "^2.0.0" + "semver": "^6.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nyc/node_modules/p-locate": { + "node_modules/nyc/node_modules/p-map": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, "dependencies": { - "p-limit": "^2.0.0" + "aggregate-error": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/nyc/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/nyc/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/nyc/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/nyc/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/nyc/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "node_modules/nyc/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { - "ansi-regex": "^4.1.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">=6" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/nyc/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/nyc/node_modules/y18n": { @@ -17184,55 +15498,59 @@ "dev": true }, "node_modules/nyc/node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^3.0.0", + "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" } }, "node_modules/nyc/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" - } - }, + }, + "engines": { + "node": ">=6" + } + }, "node_modules/object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "version": "1.13.1", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object-is": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3" @@ -17246,21 +15564,19 @@ }, "node_modules/object-keys": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -17272,28 +15588,27 @@ } }, "node_modules/object.entries": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", - "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "version": "1.1.8", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", - "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", + "version": "2.0.8", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -17302,28 +15617,43 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.groupby": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/object.hasown": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz", - "integrity": "sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg==", + "version": "1.1.4", "dev": true, + "license": "MIT", "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "version": "1.2.0", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -17334,14 +15664,13 @@ }, "node_modules/obuf": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "dependencies": { "ee-first": "1.1.1" @@ -17352,27 +15681,24 @@ }, "node_modules/on-headers": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/onetime": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -17385,9 +15711,8 @@ }, "node_modules/open": { "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", "dev": true, + "license": "MIT", "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", @@ -17402,9 +15727,8 @@ }, "node_modules/optionator": { "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -17417,53 +15741,45 @@ "node": ">= 0.8.0" } }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "p-try": "^1.0.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "p-limit": "^1.1.0" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/p-map": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/p-retry": { "version": "4.6.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", - "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", "dev": true, + "license": "MIT", "dependencies": { "@types/retry": "^0.12.0", "retry": "^0.13.1" @@ -17473,34 +15789,32 @@ } }, "node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/package-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", - "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, "dependencies": { "graceful-fs": "^4.1.15", - "hasha": "^3.0.0", + "hasha": "^5.0.0", "lodash.flattendeep": "^4.4.0", "release-zalgo": "^1.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/parent-module": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -17510,9 +15824,7 @@ }, "node_modules/parse-json": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -17526,73 +15838,82 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "dependencies": { - "parse5": "^6.0.1" - } - }, "node_modules/parseurl": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/path-exists": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/path-is-inside": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true + "dev": true, + "license": "(WTFPL OR MIT)" }, "node_modules/path-key": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.2", + "dev": true, + "license": "ISC", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } }, "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", "dev": true, "dependencies": { "isarray": "0.0.1" @@ -17600,33 +15921,28 @@ }, "node_modules/path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/pathval": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, "node_modules/performance-now": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/pica": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/pica/-/pica-6.1.1.tgz", - "integrity": "sha512-dmjQheDGFOl+30rQhN3NM3MyDNjeOZvco6IL3ZVYgyVDmhgvcSCGOAsydRCIaZ36mcXO7ci0XFeD+h6unEcBvA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "multimath": "^2.0.0", @@ -17635,16 +15951,13 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.0.1", + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -17654,27 +15967,24 @@ }, "node_modules/pify": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/pinkie": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie-promise": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, + "license": "MIT", "dependencies": { "pinkie": "^2.0.0" }, @@ -17683,19 +15993,17 @@ } }, "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "version": "4.0.6", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/pkg-dir": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^3.0.0" }, @@ -17705,9 +16013,8 @@ }, "node_modules/pkg-dir/node_modules/find-up": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^3.0.0" }, @@ -17717,9 +16024,8 @@ }, "node_modules/pkg-dir/node_modules/locate-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -17728,26 +16034,10 @@ "node": ">=6" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/pkg-dir/node_modules/p-locate": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.0.0" }, @@ -17755,20 +16045,10 @@ "node": ">=6" } }, - "node_modules/pkg-dir/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/pkg-up": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^3.0.0" }, @@ -17778,9 +16058,8 @@ }, "node_modules/pkg-up/node_modules/find-up": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^3.0.0" }, @@ -17790,9 +16069,8 @@ }, "node_modules/pkg-up/node_modules/locate-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -17801,26 +16079,10 @@ "node": ">=6" } }, - "node_modules/pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/pkg-up/node_modules/p-locate": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.0.0" }, @@ -17828,25 +16090,16 @@ "node": ">=6" } }, - "node_modules/pkg-up/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/possible-typed-array-names": { + "version": "1.0.0", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/popper.js": { - "version": "1.16.1-lts", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", - "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==", - "dev": true - }, "node_modules/postcss": { "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, "funding": [ { @@ -17862,6 +16115,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", @@ -17873,9 +16127,8 @@ }, "node_modules/postcss-attribute-case-insensitive": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.0.tgz", - "integrity": "sha512-b4g9eagFGq9T5SWX4+USfVyjIb3liPnjhHHRMP7FMB2kFVpYyfEscV0wP3eaXhKlcHKUut8lt5BGoeylWA/dBQ==", "dev": true, + "license": "MIT", "dependencies": { "postcss-selector-parser": "^6.0.2" }, @@ -17885,9 +16138,8 @@ }, "node_modules/postcss-clamp": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", - "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -17900,9 +16152,8 @@ }, "node_modules/postcss-color-functional-notation": { "version": "4.2.2", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.2.tgz", - "integrity": "sha512-DXVtwUhIk4f49KK5EGuEdgx4Gnyj6+t2jBSEmxvpIK9QI40tWrpS2Pua8Q7iIZWBrki2QOaeUdEaLPPa91K0RQ==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -17915,9 +16166,8 @@ }, "node_modules/postcss-color-hex-alpha": { "version": "8.0.3", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.3.tgz", - "integrity": "sha512-fESawWJCrBV035DcbKRPAVmy21LpoyiXdPTuHUfWJ14ZRjY7Y7PA6P4g8z6LQGYhU1WAxkTxjIjurXzoe68Glw==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -17930,9 +16180,8 @@ }, "node_modules/postcss-color-rebeccapurple": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.0.2.tgz", - "integrity": "sha512-SFc3MaocHaQ6k3oZaFwH8io6MdypkUtEy/eXzXEB1vEQlO3S3oDc/FSZA8AsS04Z25RirQhlDlHLh3dn7XewWw==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -17945,9 +16194,8 @@ }, "node_modules/postcss-custom-media": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz", - "integrity": "sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -17957,9 +16205,8 @@ }, "node_modules/postcss-custom-properties": { "version": "12.1.5", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.5.tgz", - "integrity": "sha512-FHbbB/hRo/7cxLGkc2NS7cDRIDN1oFqQnUKBiyh4b/gwk8DD8udvmRDpUhEK836kB8ggUCieHVOvZDnF9XhI3g==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -17972,9 +16219,8 @@ }, "node_modules/postcss-custom-selectors": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.0.tgz", - "integrity": "sha512-/1iyBhz/W8jUepjGyu7V1OPcGbc636snN1yXEQCinb6Bwt7KxsiU7/bLQlp8GwAXzCh7cobBU5odNn/2zQWR8Q==", "dev": true, + "license": "MIT", "dependencies": { "postcss-selector-parser": "^6.0.4" }, @@ -17987,9 +16233,8 @@ }, "node_modules/postcss-dir-pseudo-class": { "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.4.tgz", - "integrity": "sha512-I8epwGy5ftdzNWEYok9VjW9whC4xnelAtbajGv4adql4FIF09rnrxnA9Y8xSHN47y7gqFIv10C5+ImsLeJpKBw==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-selector-parser": "^6.0.9" }, @@ -18002,9 +16247,8 @@ }, "node_modules/postcss-double-position-gradients": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.1.tgz", - "integrity": "sha512-jM+CGkTs4FcG53sMPjrrGE0rIvLDdCrqMzgDC5fLI7JHDO7o6QG8C5TQBtExb13hdBdoH9C2QVbG4jo2y9lErQ==", "dev": true, + "license": "CC0-1.0", "dependencies": { "@csstools/postcss-progressive-custom-properties": "^1.1.0", "postcss-value-parser": "^4.2.0" @@ -18018,9 +16262,8 @@ }, "node_modules/postcss-env-function": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", - "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -18033,18 +16276,16 @@ }, "node_modules/postcss-flexbugs-fixes": { "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", - "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", "dev": true, + "license": "MIT", "peerDependencies": { "postcss": "^8.1.4" } }, "node_modules/postcss-focus-visible": { "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", - "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-selector-parser": "^6.0.9" }, @@ -18057,9 +16298,8 @@ }, "node_modules/postcss-focus-within": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", - "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-selector-parser": "^6.0.9" }, @@ -18072,18 +16312,16 @@ }, "node_modules/postcss-font-variant": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", - "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", "dev": true, + "license": "MIT", "peerDependencies": { "postcss": "^8.1.0" } }, "node_modules/postcss-gap-properties": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.3.tgz", - "integrity": "sha512-rPPZRLPmEKgLk/KlXMqRaNkYTUpE7YC+bOIQFN5xcu1Vp11Y4faIXv6/Jpft6FMnl6YRxZqDZG0qQOW80stzxQ==", "dev": true, + "license": "CC0-1.0", "engines": { "node": "^12 || ^14 || >=16" }, @@ -18093,9 +16331,8 @@ }, "node_modules/postcss-image-set-function": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.6.tgz", - "integrity": "sha512-KfdC6vg53GC+vPd2+HYzsZ6obmPqOk6HY09kttU19+Gj1nC3S3XBVEXDHxkhxTohgZqzbUb94bKXvKDnYWBm/A==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -18108,9 +16345,8 @@ }, "node_modules/postcss-import": { "version": "14.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", - "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -18125,18 +16361,16 @@ }, "node_modules/postcss-initial": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", - "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", "dev": true, + "license": "MIT", "peerDependencies": { "postcss": "^8.0.0" } }, "node_modules/postcss-lab-function": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.1.2.tgz", - "integrity": "sha512-isudf5ldhg4fk16M8viAwAbg6Gv14lVO35N3Z/49NhbwPQ2xbiEoHgrRgpgQojosF4vF7jY653ktB6dDrUOR8Q==", "dev": true, + "license": "CC0-1.0", "dependencies": { "@csstools/postcss-progressive-custom-properties": "^1.1.0", "postcss-value-parser": "^4.2.0" @@ -18150,9 +16384,8 @@ }, "node_modules/postcss-loader": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", "dev": true, + "license": "MIT", "dependencies": { "cosmiconfig": "^7.0.0", "klona": "^2.0.5", @@ -18172,9 +16405,8 @@ }, "node_modules/postcss-loader/node_modules/semver": { "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -18187,9 +16419,8 @@ }, "node_modules/postcss-logical": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", - "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", "dev": true, + "license": "CC0-1.0", "engines": { "node": "^12 || ^14 || >=16" }, @@ -18199,9 +16430,8 @@ }, "node_modules/postcss-media-minmax": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", - "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -18211,9 +16441,8 @@ }, "node_modules/postcss-modules-extract-imports": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", "dev": true, + "license": "ISC", "engines": { "node": "^10 || ^12 || >= 14" }, @@ -18223,9 +16452,8 @@ }, "node_modules/postcss-modules-local-by-default": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", "dev": true, + "license": "MIT", "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^6.0.2", @@ -18240,9 +16468,8 @@ }, "node_modules/postcss-modules-scope": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", "dev": true, + "license": "ISC", "dependencies": { "postcss-selector-parser": "^6.0.4" }, @@ -18255,9 +16482,8 @@ }, "node_modules/postcss-modules-values": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, + "license": "ISC", "dependencies": { "icss-utils": "^5.0.0" }, @@ -18270,9 +16496,8 @@ }, "node_modules/postcss-nesting": { "version": "10.1.3", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.1.3.tgz", - "integrity": "sha512-wUC+/YCik4wH3StsbC5fBG1s2Z3ZV74vjGqBFYtmYKlVxoio5TYGM06AiaKkQPPlkXWn72HKfS7Cw5PYxnoXSw==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-selector-parser": "^6.0.9" }, @@ -18285,8 +16510,6 @@ }, "node_modules/postcss-opacity-percentage": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.2.tgz", - "integrity": "sha512-lyUfF7miG+yewZ8EAk9XUBIlrHyUE6fijnesuz+Mj5zrIHIEw6KcIZSOk/elVMqzLvREmXB83Zi/5QpNRYd47w==", "dev": true, "funding": [ { @@ -18298,15 +16521,15 @@ "url": "https://liberapay.com/mrcgrtz" } ], + "license": "MIT", "engines": { "node": "^12 || ^14 || >=16" } }, "node_modules/postcss-overflow-shorthand": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.3.tgz", - "integrity": "sha512-CxZwoWup9KXzQeeIxtgOciQ00tDtnylYIlJBBODqkgS/PU2jISuWOL/mYLHmZb9ZhZiCaNKsCRiLp22dZUtNsg==", "dev": true, + "license": "CC0-1.0", "engines": { "node": "^12 || ^14 || >=16" }, @@ -18316,18 +16539,16 @@ }, "node_modules/postcss-page-break": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", - "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", "dev": true, + "license": "MIT", "peerDependencies": { "postcss": "^8" } }, "node_modules/postcss-place": { "version": "7.0.4", - "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.4.tgz", - "integrity": "sha512-MrgKeiiu5OC/TETQO45kV3npRjOFxEHthsqGtkh3I1rPbZSbXGD/lZVi9j13cYh+NA8PIAPyk6sGjT9QbRyvSg==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -18340,9 +16561,8 @@ }, "node_modules/postcss-preset-env": { "version": "7.4.3", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.4.3.tgz", - "integrity": "sha512-dlPA65g9KuGv7YsmGyCKtFkZKCPLkoVMUE3omOl6yM+qrynVHxFvf0tMuippIrXB/sB/MyhL1FgTIbrO+qMERg==", "dev": true, + "license": "CC0-1.0", "dependencies": { "@csstools/postcss-color-function": "^1.0.3", "@csstools/postcss-font-format-keywords": "^1.0.0", @@ -18397,9 +16617,8 @@ }, "node_modules/postcss-pseudo-class-any-link": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.1.tgz", - "integrity": "sha512-JRoLFvPEX/1YTPxRxp1JO4WxBVXJYrSY7NHeak5LImwJ+VobFMwYDQHvfTXEpcn+7fYIeGkC29zYFhFWIZD8fg==", "dev": true, + "license": "CC0-1.0", "dependencies": { "postcss-selector-parser": "^6.0.9" }, @@ -18412,18 +16631,16 @@ }, "node_modules/postcss-replace-overflow-wrap": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", - "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", "dev": true, + "license": "MIT", "peerDependencies": { "postcss": "^8.0.3" } }, "node_modules/postcss-rtlcss": { "version": "3.5.3", - "resolved": "https://registry.npmjs.org/postcss-rtlcss/-/postcss-rtlcss-3.5.3.tgz", - "integrity": "sha512-QasqXUUBAqvHtDGJydyw5rJB88S4ZHRdxKsguqfes1PBDkBW97P9GiLCtcg6EuCXRvD+52giBQXKWNWg9gshow==", "dev": true, + "license": "Apache-2.0", "dependencies": { "rtlcss": "^3.5.0" }, @@ -18436,9 +16653,8 @@ }, "node_modules/postcss-selector-not": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-5.0.0.tgz", - "integrity": "sha512-/2K3A4TCP9orP4TNS7u3tGdRFVKqz/E6pX3aGnriPG0jU78of8wsUcqE4QAhWEU0d+WnMSF93Ah3F//vUtK+iQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" }, @@ -18448,9 +16664,8 @@ }, "node_modules/postcss-selector-parser": { "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", - "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", "dev": true, + "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -18461,14 +16676,11 @@ }, "node_modules/postcss-value-parser": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/postcss/node_modules/nanoid": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", "dev": true, "funding": [ { @@ -18476,6 +16688,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -18485,18 +16698,16 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { "version": "2.6.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.0.tgz", - "integrity": "sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin-prettier.js" }, @@ -18509,9 +16720,8 @@ }, "node_modules/prettier-eslint": { "version": "13.0.0", - "resolved": "https://registry.npmjs.org/prettier-eslint/-/prettier-eslint-13.0.0.tgz", - "integrity": "sha512-P5K31qWgUOQCtJL/3tpvEe28KfP49qbr6MTVEXC7I2k7ci55bP3YDr+glhyCdhIzxGCVp2f8eobfQ5so52RIIA==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/parser": "^3.0.0", "common-tags": "^1.4.0", @@ -18532,18 +16742,16 @@ }, "node_modules/prettier-eslint/node_modules/@babel/code-frame": { "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/highlight": "^7.10.4" } }, "node_modules/prettier-eslint/node_modules/@eslint/eslintrc": { "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.1.1", @@ -18561,9 +16769,8 @@ }, "node_modules/prettier-eslint/node_modules/@humanwhocodes/config-array": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@humanwhocodes/object-schema": "^1.2.0", "debug": "^4.1.1", @@ -18575,9 +16782,8 @@ }, "node_modules/prettier-eslint/node_modules/acorn": { "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -18587,9 +16793,8 @@ }, "node_modules/prettier-eslint/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -18602,18 +16807,16 @@ }, "node_modules/prettier-eslint/node_modules/argparse": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/prettier-eslint/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -18627,9 +16830,8 @@ }, "node_modules/prettier-eslint/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -18639,9 +16841,8 @@ }, "node_modules/prettier-eslint/node_modules/escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -18651,9 +16852,8 @@ }, "node_modules/prettier-eslint/node_modules/eslint": { "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.4.3", @@ -18708,9 +16908,8 @@ }, "node_modules/prettier-eslint/node_modules/eslint-utils": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^1.1.0" }, @@ -18723,18 +16922,16 @@ }, "node_modules/prettier-eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=4" } }, "node_modules/prettier-eslint/node_modules/espree": { "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^7.4.0", "acorn-jsx": "^5.3.1", @@ -18746,18 +16943,16 @@ }, "node_modules/prettier-eslint/node_modules/espree/node_modules/eslint-visitor-keys": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=4" } }, "node_modules/prettier-eslint/node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -18767,9 +16962,8 @@ }, "node_modules/prettier-eslint/node_modules/globals": { "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -18782,27 +16976,24 @@ }, "node_modules/prettier-eslint/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/prettier-eslint/node_modules/ignore": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/prettier-eslint/node_modules/js-yaml": { "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -18813,9 +17004,8 @@ }, "node_modules/prettier-eslint/node_modules/semver": { "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -18828,9 +17018,8 @@ }, "node_modules/prettier-eslint/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -18840,9 +17029,8 @@ }, "node_modules/prettier-eslint/node_modules/type-fest": { "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -18852,9 +17040,8 @@ }, "node_modules/prettier-linter-helpers": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, + "license": "MIT", "dependencies": { "fast-diff": "^1.1.2" }, @@ -18864,9 +17051,8 @@ }, "node_modules/pretty-bytes": { "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -18876,9 +17062,8 @@ }, "node_modules/pretty-format": { "version": "23.6.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", - "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^3.0.0", "ansi-styles": "^3.2.0" @@ -18886,33 +17071,41 @@ }, "node_modules/process-nextick-args": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/process-on-spawn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.1.0.tgz", + "integrity": "sha512-JOnOPQ/8TZgjs1JIH/m9ni7FfimjNa/PRx7y/Wb5qdItsnhO0jE4AT7fC0HjC28DUQWDr50dwSYZLdRMlqDq3Q==", + "dev": true, + "dependencies": { + "fromentries": "^1.2.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/progress": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/promise": { "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "dev": true, + "license": "MIT", "dependencies": { "asap": "~2.0.3" } }, "node_modules/prompts": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, + "license": "MIT", "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" @@ -18923,52 +17116,34 @@ }, "node_modules/prop-types": { "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, + "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, - "node_modules/prop-types-exact": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", - "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", - "dev": true, - "dependencies": { - "has": "^1.0.3", - "object.assign": "^4.1.0", - "reflect.ownkeys": "^0.2.0" - } - }, "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "license": "MIT" }, "node_modules/propagate": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-1.0.0.tgz", - "integrity": "sha1-AMLa7t2iDofjeCs0Stuhzd1q1wk=", "dev": true, "engines": [ "node >= 0.8.1" - ] + ], + "license": "MIT" }, "node_modules/property-expr": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", - "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/proxy-addr": { "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -18979,47 +17154,36 @@ }, "node_modules/proxy-addr/node_modules/ipaddr.js": { "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/proxy-compare": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.4.0.tgz", - "integrity": "sha512-FD8KmQUQD6Mfpd0hywCOzcon/dbkFP8XBd9F1ycbKtvVsfv6TsFUKJ2eC0Iz2y+KzlkdT1Z8SY6ZSgm07zOyqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/proxy-memoize": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/proxy-memoize/-/proxy-memoize-2.0.3.tgz", - "integrity": "sha512-PpZzfNsZbOI89phkaq2BP6OfG7/0RDKYKEwTSlIikcWZ5ODN/dRzrHfg1zPMtlZY6FJRmrHamJ1ol2gIc+bruQ==", "dev": true, + "license": "MIT", "dependencies": { "proxy-compare": "2.4.0" } }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, "node_modules/psl": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/pug": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.2.tgz", - "integrity": "sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==", + "version": "3.0.3", "dev": true, + "license": "MIT", "dependencies": { - "pug-code-gen": "^3.0.2", + "pug-code-gen": "^3.0.3", "pug-filters": "^4.0.0", "pug-lexer": "^5.0.1", "pug-linker": "^4.0.0", @@ -19031,9 +17195,8 @@ }, "node_modules/pug-attrs": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", - "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", "dev": true, + "license": "MIT", "dependencies": { "constantinople": "^4.0.1", "js-stringify": "^1.0.2", @@ -19041,32 +17204,29 @@ } }, "node_modules/pug-code-gen": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.2.tgz", - "integrity": "sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==", + "version": "3.0.3", "dev": true, + "license": "MIT", "dependencies": { "constantinople": "^4.0.1", "doctypes": "^1.1.0", "js-stringify": "^1.0.2", "pug-attrs": "^3.0.0", - "pug-error": "^2.0.0", - "pug-runtime": "^3.0.0", + "pug-error": "^2.1.0", + "pug-runtime": "^3.0.1", "void-elements": "^3.1.0", "with": "^7.0.0" } }, "node_modules/pug-error": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.0.0.tgz", - "integrity": "sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==", - "dev": true + "version": "2.1.0", + "dev": true, + "license": "MIT" }, "node_modules/pug-filters": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz", - "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==", "dev": true, + "license": "MIT", "dependencies": { "constantinople": "^4.0.1", "jstransformer": "1.0.0", @@ -19077,9 +17237,8 @@ }, "node_modules/pug-lexer": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz", - "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==", "dev": true, + "license": "MIT", "dependencies": { "character-parser": "^2.2.0", "is-expression": "^4.0.0", @@ -19088,9 +17247,8 @@ }, "node_modules/pug-linker": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz", - "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==", "dev": true, + "license": "MIT", "dependencies": { "pug-error": "^2.0.0", "pug-walk": "^2.0.0" @@ -19098,9 +17256,8 @@ }, "node_modules/pug-load": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz", - "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==", "dev": true, + "license": "MIT", "dependencies": { "object-assign": "^4.1.1", "pug-walk": "^2.0.0" @@ -19108,9 +17265,8 @@ }, "node_modules/pug-parser": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz", - "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==", "dev": true, + "license": "MIT", "dependencies": { "pug-error": "^2.0.0", "token-stream": "1.0.0" @@ -19118,48 +17274,41 @@ }, "node_modules/pug-runtime": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", - "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/pug-strip-comments": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz", - "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==", "dev": true, + "license": "MIT", "dependencies": { "pug-error": "^2.0.0" } }, "node_modules/pug-walk": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", - "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/pump": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.1", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/pure-rand": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", - "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", "dev": true, "funding": [ { @@ -19170,15 +17319,16 @@ "type": "opencollective", "url": "https://opencollective.com/fast-check" } - ] + ], + "license": "MIT" }, "node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -19189,14 +17339,11 @@ }, "node_modules/querystringify": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/queue-microtask": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { @@ -19211,68 +17358,46 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/raf": { "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", "dev": true, + "license": "MIT", "dependencies": { "performance-now": "^2.1.0" } }, "node_modules/raf-schd": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", - "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==", - "dev": true - }, - "node_modules/railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", - "dev": true - }, - "node_modules/randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", "dev": true, - "dependencies": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - }, - "engines": { - "node": ">=0.12" - } + "license": "MIT" }, "node_modules/randombytes": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/range-parser": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "dependencies": { "bytes": "3.1.2", - "http-errors": "1.8.1", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -19282,52 +17407,27 @@ }, "node_modules/re-reselect": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/re-reselect/-/re-reselect-4.0.0.tgz", - "integrity": "sha512-wuygyq8TXUlSdVXv2kigXxQNOgdb9m7LbIjwfTNGSpaY1riLd5e+VeQjlQMyUtrk0oiyhi1AqIVynworl3qxHA==", "dev": true, + "license": "MIT", "peerDependencies": { "reselect": ">1.0.0" } }, "node_modules/react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "version": "18.3.1", + "dev": true, + "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/react-16-node-hanging-test-fix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/react-16-node-hanging-test-fix/-/react-16-node-hanging-test-fix-1.0.0.tgz", - "integrity": "sha512-D22iNNa+0MuMPA49nZ5ILBHiJ7h9PTeUUuZee38pFSEWlHOYnHEWzUjOlYjEo6Ji+axHrRnT+y1QRIJOcIcj4w==", - "dependencies": { - "semver": "^7.3.4" - } - }, - "node_modules/react-16-node-hanging-test-fix/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/react-beautiful-dnd": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz", - "integrity": "sha512-aGvblPZTJowOWUNiwd6tNfEpgkX5OxmpqxHKNW/4VmvZTNTbeiq7bA3bn5T+QSF2uibXB0D1DmJsb1aC/+3cUA==", + "version": "13.1.1", "dev": true, + "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.9.2", "css-box-model": "^1.2.0", @@ -19338,21 +17438,19 @@ "use-memo-one": "^1.1.1" }, "peerDependencies": { - "react": "^16.8.5 || ^17.0.0", - "react-dom": "^16.8.5 || ^17.0.0" + "react": "^16.8.5 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" } }, "node_modules/react-display-name": { "version": "0.2.5", - "resolved": "https://registry.npmjs.org/react-display-name/-/react-display-name-0.2.5.tgz", - "integrity": "sha512-I+vcaK9t4+kypiSgaiVWAipqHRXYmZIuAiS8vzFvXHHXVigg/sMKwlRgLy6LH2i3rmP+0Vzfl5lFsFRwF1r3pg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/react-dnd": { "version": "11.1.3", - "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-11.1.3.tgz", - "integrity": "sha512-8rtzzT8iwHgdSC89VktwhqdKKtfXaAyC4wiqp0SywpHG12TTLvfOoL6xNEIUWXwIEWu+CFfDn4GZJyynCEuHIQ==", "dev": true, + "license": "MIT", "dependencies": { "@react-dnd/shallowequal": "^2.0.0", "@types/hoist-non-react-statics": "^3.3.1", @@ -19366,32 +17464,53 @@ }, "node_modules/react-dnd-html5-backend": { "version": "11.1.3", - "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-11.1.3.tgz", - "integrity": "sha512-/1FjNlJbW/ivkUxlxQd7o3trA5DE33QiRZgxent3zKme8DwF4Nbw3OFVhTRFGaYhHFNL1rZt6Rdj1D78BjnNLw==", "dev": true, + "license": "MIT", "dependencies": { "dnd-core": "^11.1.3" } }, - "node_modules/react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "node_modules/react-dnd-scrollzone-patch-react-17": { + "version": "1.0.2", "dev": true, + "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" + "hoist-non-react-statics": "^3.1.0", + "lodash.throttle": "^4.0.1", + "prop-types": "^15.5.9", + "raf": "^3.2.0", + "react-display-name": "^0.2.0" }, "peerDependencies": { - "react": "17.0.2" + "react": "^17.0.1", + "react-dnd": "^11.1.3", + "react-dom": "^17.0.1" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-dom/node_modules/scheduler": { + "version": "0.23.2", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" } }, "node_modules/react-error-boundary": { "version": "3.1.4", - "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz", - "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5" }, @@ -19405,24 +17524,21 @@ }, "node_modules/react-fast-compare": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", - "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/react-hook-form": { "version": "6.15.1", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-6.15.1.tgz", - "integrity": "sha512-bL0LQuQ3OlM3JYfbacKtBPLOHhmgYz8Lj6ivMrvu2M6e1wnt4sbGRtPEPYCc/8z3WDbjrMwfAfLX92OsB65pFA==", "dev": true, + "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17" } }, "node_modules/react-idle-timer": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/react-idle-timer/-/react-idle-timer-5.6.2.tgz", - "integrity": "sha512-X7zjDv7duCopQ4v3X2Gun8QunvYplPWkvW2y7suDSREu1vQRQ0mr1ESv325QoJuvSIE5QCSbLaJlrbbooNaUNg==", + "version": "5.7.2", "dev": true, + "license": "MIT", "peerDependencies": { "react": ">=16", "react-dom": ">=16" @@ -19430,21 +17546,18 @@ }, "node_modules/react-is": { "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/react-redux": { "version": "7.2.6", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz", - "integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.15.4", "@types/react-redux": "^7.1.20", @@ -19467,9 +17580,8 @@ }, "node_modules/react-router": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", - "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -19488,9 +17600,8 @@ }, "node_modules/react-router-dom": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz", - "integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -19506,9 +17617,8 @@ }, "node_modules/react-router-navigation-prompt": { "version": "1.9.6", - "resolved": "https://registry.npmjs.org/react-router-navigation-prompt/-/react-router-navigation-prompt-1.9.6.tgz", - "integrity": "sha512-l0sAtbroHK8i1/Eyy29XcrMpBEt0R08BaScgMUt8r5vWWbLz7G0ChOikayTCQm7QgDFsHw8gVnxDJb7TBZCAKg==", "dev": true, + "license": "MIT", "peerDependencies": { "react": ">=15", "react-router-dom": ">=4.x" @@ -19516,58 +17626,46 @@ }, "node_modules/react-router/node_modules/react-is": { "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/react-shallow-renderer": { - "version": "16.14.1", - "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.14.1.tgz", - "integrity": "sha512-rkIMcQi01/+kxiTE9D3fdS959U1g7gs+/rborw++42m1O9FAQiNI/UNRZExVUoAOprn4umcXf+pFRou8i4zuBg==", + "version": "16.15.0", "dev": true, + "license": "MIT", "dependencies": { "object-assign": "^4.1.1", - "react-is": "^16.12.0 || ^17.0.0" + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" }, "peerDependencies": { - "react": "^16.0.0 || ^17.0.0" - } - }, - "node_modules/react-simple-animate": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/react-simple-animate/-/react-simple-animate-3.3.12.tgz", - "integrity": "sha512-lFXjxD6ficcpOMsHfcDs1jqdkCve6jNlJnubOCzVOLswFDRANsaLN4KwpezDuliEFz8Q1zyj4J7Tmj3KMRnPcg==", - "dev": true, - "peerDependencies": { - "react": "^16.8.0 || ^17", - "react-dom": "^16.8.0 || ^17" + "react": "^16.0.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/react-sortable-tree": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/react-sortable-tree/-/react-sortable-tree-2.8.0.tgz", - "integrity": "sha512-gTjwxRNt7z0FC76KeNTnGqx1qUSlV3N78mMPRushBpSUXzZYhiFNsWHUIruyPnaAbw4SA7LgpItV7VieAuwDpw==", + "node_modules/react-sortable-tree-patch-react-17": { + "version": "2.9.0", "dev": true, + "license": "MIT", "dependencies": { - "frontend-collective-react-dnd-scrollzone": "^1.0.2", "lodash.isequal": "^4.5.0", "prop-types": "^15.6.1", + "react": "^17.0.0", "react-dnd": "^11.1.3", "react-dnd-html5-backend": "^11.1.3", + "react-dnd-scrollzone-patch-react-17": "^1.0.2", + "react-dom": "^17.0.0", "react-lifecycles-compat": "^3.0.4", "react-virtualized": "^9.21.2" }, "peerDependencies": { - "react": "^16.3.0", - "react-dnd": "^7.3.0", - "react-dom": "^16.3.0" + "react": "^17.0.0", + "react-dnd": "^11.1.3", + "react-dom": "^17.0.0" } }, "node_modules/react-spaces": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/react-spaces/-/react-spaces-0.3.2.tgz", - "integrity": "sha512-Yq3USb43jEt6k6CKe00z1sZfnOft+Tdv1IJQoVJBtKN5ut1v1m+0iIOJyxxWMRra/TsVBomSNV2LgwFvvRw9SA==", "dev": true, + "license": "MIT", "dependencies": { "css-element-queries": "^1.2.1", "prop-types": "^15.7.2" @@ -19578,25 +17676,35 @@ } }, "node_modules/react-test-renderer": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-17.0.2.tgz", - "integrity": "sha512-yaQ9cB89c17PUb0x6UfWRs7kQCorVdHlutU1boVPEsB8IDZH6n9tHxMacc3y0JoXOJUsZb/t/Mb8FUWMKaM7iQ==", + "version": "18.3.1", "dev": true, + "license": "MIT", "dependencies": { - "object-assign": "^4.1.1", - "react-is": "^17.0.2", - "react-shallow-renderer": "^16.13.1", - "scheduler": "^0.20.2" + "react-is": "^18.3.1", + "react-shallow-renderer": "^16.15.0", + "scheduler": "^0.23.2" }, "peerDependencies": { - "react": "17.0.2" + "react": "^18.3.1" + } + }, + "node_modules/react-test-renderer/node_modules/react-is": { + "version": "18.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/react-test-renderer/node_modules/scheduler": { + "version": "0.23.2", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" } }, "node_modules/react-to-print": { "version": "2.14.7", - "resolved": "https://registry.npmjs.org/react-to-print/-/react-to-print-2.14.7.tgz", - "integrity": "sha512-lWVVAs9Co25uyE0toxcWeFsmaZObwUozXrJD9WMpDPclpBgk+WIzxlt3Q3omL/BCBG/cpf0XNvhayUWa+99YGw==", "dev": true, + "license": "MIT", "dependencies": { "prop-types": "^15.8.1" }, @@ -19606,10 +17714,8 @@ } }, "node_modules/react-transition-group": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz", - "integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==", - "dev": true, + "version": "4.4.5", + "license": "BSD-3-Clause", "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", @@ -19622,10 +17728,9 @@ } }, "node_modules/react-virtualized": { - "version": "9.22.3", - "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.3.tgz", - "integrity": "sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw==", + "version": "9.22.5", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.2", "clsx": "^1.0.4", @@ -19635,15 +17740,14 @@ "react-lifecycles-compat": "^3.0.4" }, "peerDependencies": { - "react": "^15.3.0 || ^16.0.0-alpha", - "react-dom": "^15.3.0 || ^16.0.0-alpha" + "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0", + "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0" } }, "node_modules/react-window": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.6.tgz", - "integrity": "sha512-8VwEEYyjz6DCnGBsd+MgkD0KJ2/OXFULyDtorIiTz+QzwoP94tBoA7CnbtyXMm+cCeAUER5KJcPtWl9cpKbOBg==", + "version": "1.8.10", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.0.0", "memoize-one": ">=3.1.1 <6" @@ -19652,142 +17756,30 @@ "node": ">8.0.0" }, "peerDependencies": { - "react": "^15.0.0 || ^16.0.0 || ^17.0.0", - "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0" + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/read-cache": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", "dev": true, + "license": "MIT", "dependencies": { "pify": "^2.3.0" } }, "node_modules/read-cache/node_modules/pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", - "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/read-pkg-up/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/readable-stream": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -19799,9 +17791,8 @@ }, "node_modules/readdirp": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -19811,9 +17802,8 @@ }, "node_modules/realistic-structured-clone": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/realistic-structured-clone/-/realistic-structured-clone-2.0.4.tgz", - "integrity": "sha512-lItAdBIFHUSe6fgztHPtmmWqKUgs+qhcYLi3wTRUl4OTB3Vb8aBVSjGfQZUvkmJCKoX3K9Wf7kyLp/F/208+7A==", "dev": true, + "license": "Apache-2.0", "dependencies": { "core-js": "^3.4", "domexception": "^1.0.1", @@ -19821,38 +17811,23 @@ "typeson-registry": "^1.0.0-alpha.20" } }, - "node_modules/realistic-structured-clone/node_modules/core-js": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", - "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "dev": true, - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/realistic-structured-clone/node_modules/domexception": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", - "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", "dev": true, + "license": "MIT", "dependencies": { "webidl-conversions": "^4.0.2" } }, "node_modules/realistic-structured-clone/node_modules/webidl-conversions": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/rechoir": { "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", - "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", "dev": true, + "license": "MIT", "dependencies": { "resolve": "^1.9.0" }, @@ -19862,9 +17837,8 @@ }, "node_modules/redent": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, + "license": "MIT", "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" @@ -19875,72 +17849,78 @@ }, "node_modules/reduce-reducers": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reduce-reducers/-/reduce-reducers-1.0.4.tgz", - "integrity": "sha512-Mb2WZ2bJF597exiqX7owBzrqJ74DHLK3yOQjCyPAaNifRncE8OD0wFIuoMhXxTnHK07+8zZ2SJEKy/qtiyR7vw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/redux": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", - "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.9.2" } }, "node_modules/redux-immutable": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/redux-immutable/-/redux-immutable-4.0.0.tgz", - "integrity": "sha1-Ohoy32Y2ZGK2NpHw4dw15HK7yfM=", "dev": true, + "license": "BSD-3-Clause", "peerDependencies": { "immutable": "^3.8.1 || ^4.0.0-rc.1" } }, "node_modules/redux-logger": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-3.0.6.tgz", - "integrity": "sha1-91VZZvMJjzyIYExEnPC69XeCdL8=", "dev": true, + "license": "MIT", "dependencies": { "deep-diff": "^0.3.5" } }, "node_modules/redux-mock-store": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/redux-mock-store/-/redux-mock-store-1.5.4.tgz", - "integrity": "sha512-xmcA0O/tjCLXhh9Fuiq6pMrJCwFRaouA8436zcikdIpYWWCjU76CRk+i2bHx8EeiSiMGnB85/lZdU3wIJVXHTA==", "dev": true, + "license": "MIT", "dependencies": { "lodash.isplainobject": "^4.0.6" } }, "node_modules/redux-thunk": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", - "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", "dev": true, + "license": "MIT", "peerDependencies": { "redux": "^4" } }, - "node_modules/reflect.ownkeys": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", - "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=", - "dev": true + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/regenerate": { "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "version": "10.1.1", "dev": true, + "license": "MIT", "dependencies": { "regenerate": "^1.4.2" }, @@ -19950,28 +17930,26 @@ }, "node_modules/regenerator-runtime": { "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "version": "0.15.2", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.8.4" } }, "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.2", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -19982,9 +17960,8 @@ }, "node_modules/regexpp": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -19994,9 +17971,8 @@ }, "node_modules/regexpu-core": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", @@ -20011,9 +17987,8 @@ }, "node_modules/regjsparser": { "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "jsesc": "~0.5.0" }, @@ -20023,8 +17998,6 @@ }, "node_modules/regjsparser/node_modules/jsesc": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", "dev": true, "bin": { "jsesc": "bin/jsesc" @@ -20033,7 +18006,7 @@ "node_modules/release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", "dev": true, "dependencies": { "es6-error": "^4.0.1" @@ -20044,42 +18017,37 @@ }, "node_modules/repeat-string": { "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10" } }, "node_modules/reprism": { "version": "0.0.11", - "resolved": "https://registry.npmjs.org/reprism/-/reprism-0.0.11.tgz", - "integrity": "sha1-52C4XgriQXIgMsuJQqK8q5kqkIM=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/require-from-string": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/require-hacker": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/require-hacker/-/require-hacker-3.0.1.tgz", - "integrity": "sha1-CHm+Bn/PBnUwZlvM5MiayBqHBHc=", "dev": true, + "license": "MIT", "dependencies": { "babel-runtime": "^6.6.1", "colors": "^1.1.2" @@ -20093,27 +18061,22 @@ }, "node_modules/require-relative": { "version": "0.8.7", - "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", - "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/requires-port": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/reselect": { "version": "4.1.7", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz", - "integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/resolve": { "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -20128,9 +18091,8 @@ }, "node_modules/resolve-cwd": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, + "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, @@ -20140,60 +18102,44 @@ }, "node_modules/resolve-cwd/node_modules/resolve-from": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/resolve-pathname": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/resolve.exports": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, "node_modules/retry": { "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/reusify": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -20201,30 +18147,16 @@ }, "node_modules/rgbcolor": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", - "integrity": "sha1-1lBezbMEplldom+ktDMHMGd1lF0=", "dev": true, + "license": "MIT OR SEE LICENSE IN FEEL-FREE.md", "engines": { "node": ">= 0.8.15" } }, - "node_modules/rifm": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rifm/-/rifm-0.7.0.tgz", - "integrity": "sha512-DSOJTWHD67860I5ojetXdEQRIBvF6YcpNe53j0vn1vp9EUb9N80EiZTxgP+FkDKorWC8PZw052kTF4C1GOivCQ==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.3.1" - }, - "peerDependencies": { - "react": ">=16.8" - } - }, "node_modules/rimraf": { "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -20233,9 +18165,9 @@ } }, "node_modules/rollup": { - "version": "2.70.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.1.tgz", - "integrity": "sha512-CRYsI5EuzLbXdxC6RnYhOuRdtz4bhejPMSWjsFLfVM/7w/85n2szZv6yExqUXsBdz5KT8eoubeyDUDjhLHEslA==", + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -20249,10 +18181,8 @@ }, "node_modules/rollup-plugin-terser": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", - "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.10.4", "jest-worker": "^26.2.1", @@ -20265,18 +18195,16 @@ }, "node_modules/rollup-plugin-terser/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/rollup-plugin-terser/node_modules/jest-worker": { "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -20288,18 +18216,16 @@ }, "node_modules/rollup-plugin-terser/node_modules/serialize-javascript": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/rollup-plugin-terser/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -20307,30 +18233,10 @@ "node": ">=8" } }, - "node_modules/rst-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", - "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=", - "dev": true, - "dependencies": { - "lodash.flattendeep": "^4.4.0", - "nearley": "^2.7.10" - } - }, - "node_modules/rtl-css-js": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.15.0.tgz", - "integrity": "sha512-99Cu4wNNIhrI10xxUaABHsdDqzalrSRTie4GeCmbGVuehm4oj+fIy8fTzB+16pmKe8Bv9rl+hxIBez6KxExTew==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.1.2" - } - }, "node_modules/rtlcss": { "version": "3.5.0", - "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz", - "integrity": "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^5.0.0", "picocolors": "^1.0.0", @@ -20343,9 +18249,8 @@ }, "node_modules/rtlcss/node_modules/find-up": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -20359,9 +18264,8 @@ }, "node_modules/rtlcss/node_modules/locate-path": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -20374,9 +18278,8 @@ }, "node_modules/rtlcss/node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -20389,9 +18292,8 @@ }, "node_modules/rtlcss/node_modules/p-locate": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -20404,17 +18306,14 @@ }, "node_modules/rtlcss/node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/run-parallel": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -20430,39 +18329,73 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "dev": true, + "license": "MIT" + }, "node_modules/safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "version": "6.0.0", "dev": true, + "license": "ISC", "dependencies": { "xmlchars": "^2.2.0" }, "engines": { - "node": ">=10" + "node": ">=v12.22.7" } }, "node_modules/scheduler": { "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", "dev": true, + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -20470,9 +18403,8 @@ }, "node_modules/schema-utils": { "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.5", "ajv": "^6.12.4", @@ -20488,22 +18420,19 @@ }, "node_modules/seamless-immutable": { "version": "7.1.4", - "resolved": "https://registry.npmjs.org/seamless-immutable/-/seamless-immutable-7.1.4.tgz", - "integrity": "sha512-XiUO1QP4ki4E2PHegiGAlu6r82o5A+6tRh7IkGGTVg/h+UoeX4nFBeCGPOhb4CYjvkqsfm/TUtvOMYC1xmV30A==", "dev": true, + "license": "BSD-3-Clause", "optional": true }, "node_modules/select-hose": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/selfsigned": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, + "license": "MIT", "dependencies": { "@types/node-forge": "^1.3.0", "node-forge": "^1" @@ -20514,32 +18443,31 @@ }, "node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "dependencies": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.8.1", + "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "engines": { "node": ">= 0.8.0" @@ -20557,29 +18485,54 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/send/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/serialize-javascript": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/serve-index": { "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, + "license": "MIT", "dependencies": { "accepts": "~1.3.4", "batch": "0.6.1", @@ -20595,18 +18548,16 @@ }, "node_modules/serve-index/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, "node_modules/serve-index/node_modules/http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, + "license": "MIT", "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -20619,32 +18570,29 @@ }, "node_modules/serve-index/node_modules/inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/serve-index/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/serve-index/node_modules/setprototypeof": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.2" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" @@ -20653,9 +18601,39 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, + "node_modules/set-function-length": { + "version": "1.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -20664,9 +18642,8 @@ }, "node_modules/shallow-clone": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, + "license": "MIT", "dependencies": { "kind-of": "^6.0.2" }, @@ -20676,9 +18653,8 @@ }, "node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -20688,31 +18664,32 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shell-quote": { "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -20720,15 +18697,13 @@ }, "node_modules/signal-exit": { "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/sinon": { "version": "7.5.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", - "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^1.4.0", "@sinonjs/formatio": "^3.2.1", @@ -20741,9 +18716,8 @@ }, "node_modules/sinon-chai": { "version": "3.7.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", - "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", "dev": true, + "license": "(BSD-2-Clause OR WTFPL)", "peerDependencies": { "chai": "^4.0.0", "sinon": ">=4.0.0" @@ -20751,33 +18725,29 @@ }, "node_modules/sinon/node_modules/diff": { "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/sisteransi": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/slash": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/slice-ansi": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -20792,9 +18762,8 @@ }, "node_modules/slice-ansi/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -20807,9 +18776,8 @@ }, "node_modules/slice-ansi/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -20819,9 +18787,8 @@ }, "node_modules/sockjs": { "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", "dev": true, + "license": "MIT", "dependencies": { "faye-websocket": "^0.11.3", "uuid": "^8.3.2", @@ -20830,33 +18797,28 @@ }, "node_modules/source-list-map": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/source-map": { "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-js": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-support": { "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -20864,89 +18826,87 @@ }, "node_modules/source-map-support/node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/sourcemap-codec": { "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/spark-md5": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.2.tgz", - "integrity": "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw==", - "dev": true + "dev": true, + "license": "(WTFPL OR MIT)" }, "node_modules/spawn-wrap": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", - "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, "dependencies": { - "foreground-child": "^1.5.6", - "mkdirp": "^0.5.0", - "os-homedir": "^1.0.1", - "rimraf": "^2.6.2", + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", "signal-exit": "^3.0.2", - "which": "^1.3.0" + "which": "^2.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/spawn-wrap/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/spawn-wrap/node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", "dev": true, "dependencies": { - "isexe": "^2.0.0" + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" }, - "bin": { - "which": "bin/which" + "engines": { + "node": ">=8.0.0" } }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "node_modules/spawn-wrap/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/spawn-wrap/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true - }, "node_modules/spdy": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.0", "handle-thing": "^2.0.0", @@ -20960,9 +18920,8 @@ }, "node_modules/spdy-transport": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.0", "detect-node": "^2.0.4", @@ -20974,22 +18933,18 @@ }, "node_modules/sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/stable": { "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/stack-utils": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^2.0.0" }, @@ -20999,56 +18954,38 @@ }, "node_modules/stack-utils/node_modules/escape-string-regexp": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/stackblur-canvas": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.5.0.tgz", - "integrity": "sha512-EeNzTVfj+1In7aSLPKDD03F/ly4RxEuF/EX0YcOG0cKoPXs+SLZxDawQbexQDBzwROs4VKLWTOaZQlZkGBFEIQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.1.14" } }, "node_modules/statuses": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } }, "node_modules/string_decoder/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -21063,13 +19000,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/string-length": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, + "license": "MIT", "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -21080,9 +19017,8 @@ }, "node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -21094,38 +19030,43 @@ }, "node_modules/string-width/node_modules/emoji-regex": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/string.prototype.matchall": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", - "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "version": "4.0.11", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.1", - "side-channel": "^1.0.4" + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trim": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.5.tgz", - "integrity": "sha512-Lnh17webJVsD6ECeovpVN17RlAKjmz4rF9S+8Y45CkMc/ufVpTkU3vZIyIC7sllQ1FCvObZnnCdNs/HXTUOTlg==", + "version": "1.2.9", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -21135,26 +19076,29 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "version": "1.0.8", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "version": "1.0.8", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -21162,9 +19106,8 @@ }, "node_modules/stringify-object": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "get-own-enumerable-property-symbols": "^3.0.0", "is-obj": "^1.0.1", @@ -21176,9 +19119,8 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -21188,36 +19130,32 @@ }, "node_modules/strip-bom": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/strip-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", - "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/strip-final-newline": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/strip-indent": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, + "license": "MIT", "dependencies": { "min-indent": "^1.0.0" }, @@ -21227,9 +19165,8 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -21239,9 +19176,8 @@ }, "node_modules/style-loader": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", - "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", "dev": true, + "license": "MIT", "dependencies": { "loader-utils": "^2.0.0", "schema-utils": "^3.0.0" @@ -21259,9 +19195,8 @@ }, "node_modules/style-loader/node_modules/loader-utils": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, + "license": "MIT", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -21273,9 +19208,8 @@ }, "node_modules/style-loader/node_modules/schema-utils": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -21289,11 +19223,25 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/stylis-plugin-rtl": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/stylis-plugin-rtl/-/stylis-plugin-rtl-2.1.1.tgz", + "integrity": "sha512-q6xIkri6fBufIO/sV55md2CbgS5c6gg9EhSVATtHHCdOnbN/jcI0u3lYhNVeuI65c4lQPo67g8xmq5jrREvzlg==", + "dependencies": { + "cssjanus": "^2.0.1" + }, + "peerDependencies": { + "stylis": "4.x" + } + }, "node_modules/supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -21303,9 +19251,7 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -21315,30 +19261,26 @@ }, "node_modules/svg-parser": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/svg-pathdata": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", - "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.0.0" } }, "node_modules/symbol-tree": { "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/table": { "version": "6.8.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", - "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", @@ -21352,9 +19294,8 @@ }, "node_modules/table/node_modules/ajv": { "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -21368,33 +19309,29 @@ }, "node_modules/table/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/tapable": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/temp-dir": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/tempy": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", - "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", "dev": true, + "license": "MIT", "dependencies": { "is-stream": "^2.0.0", "temp-dir": "^2.0.0", @@ -21409,13 +19346,12 @@ } }, "node_modules/terser": { - "version": "5.16.9", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.9.tgz", - "integrity": "sha512-HPa/FdTB9XGI2H1/keLFZHxl6WNvAI4YalHGtDQTlMnJcoqSab1UwL4l1hGEhs6/GmLHBZIg/YgB++jcbzoOEg==", + "version": "5.31.1", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -21427,16 +19363,15 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", + "version": "5.3.10", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", + "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" + "terser": "^5.26.0" }, "engines": { "node": ">= 10.13.0" @@ -21461,10 +19396,9 @@ } }, "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -21479,40 +19413,36 @@ } }, "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "version": "6.0.2", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/test-exclude": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", - "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "dependencies": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/text-segmentation": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", - "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "utrie": "^1.0.2" @@ -21520,54 +19450,45 @@ }, "node_modules/text-table": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/thunky": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/timezone-mock": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/timezone-mock/-/timezone-mock-1.3.1.tgz", - "integrity": "sha512-kWK2liWUaYSLW/B2yJ6/oUbLc26cEbtIjM7BPrRxaX/3TSeqOOQfXQ6N4pNhy05ZBnUs9vywWAthiE9QYGZFwA==", - "dev": true + "version": "1.3.6", + "dev": true, + "license": "MIT" }, "node_modules/tiny-invariant": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", - "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/tiny-warning": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/tmpl": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -21586,21 +19507,18 @@ }, "node_modules/token-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", - "integrity": "sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/toposort": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "version": "4.1.4", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -21613,18 +19531,16 @@ }, "node_modules/tough-cookie/node_modules/universalify": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.0.0" } }, "node_modules/tr46": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", "dev": true, + "license": "MIT", "dependencies": { "punycode": "^2.1.1" }, @@ -21633,22 +19549,20 @@ } }, "node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "version": "3.15.0", "dev": true, + "license": "MIT", "dependencies": { "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "node_modules/tsconfig-paths/node_modules/json5": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -21657,16 +19571,37 @@ } }, "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true + "version": "2.6.3", + "dev": true, + "license": "0BSD" + }, + "node_modules/tss-react": { + "version": "4.9.10", + "license": "MIT", + "dependencies": { + "@emotion/cache": "*", + "@emotion/serialize": "*", + "@emotion/utils": "*" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/server": "^11.4.0", + "@mui/material": "^5.0.0", + "react": "^16.8.0 || ^17.0.2 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/server": { + "optional": true + }, + "@mui/material": { + "optional": true + } + } }, "node_modules/tsutils": { "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^1.8.1" }, @@ -21679,15 +19614,13 @@ }, "node_modules/tsutils/node_modules/tslib": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "dev": true, + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -21697,18 +19630,16 @@ }, "node_modules/type-detect": { "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/type-fest": { "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -21729,11 +19660,88 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, "node_modules/typescript": { "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -21744,18 +19752,16 @@ }, "node_modules/typeson": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/typeson/-/typeson-6.1.0.tgz", - "integrity": "sha512-6FTtyGr8ldU0pfbvW/eOZrEtEkczHRUtduBnA90Jh9kMPCiFNnXIon3vF41N0S4tV1HHQt4Hk1j4srpESziCaA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.1.14" } }, "node_modules/typeson-registry": { "version": "1.0.0-alpha.39", - "resolved": "https://registry.npmjs.org/typeson-registry/-/typeson-registry-1.0.0-alpha.39.tgz", - "integrity": "sha512-NeGDEquhw+yfwNhguLPcZ9Oj0fzbADiX4R0WxvoY8nGhy98IbzQy1sezjoEFWOywOboj/DWehI+/aUlRVrJnnw==", "dev": true, + "license": "MIT", "dependencies": { "base64-arraybuffer-es6": "^0.7.0", "typeson": "^6.0.0", @@ -21766,14 +19772,13 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" }, "funding": { @@ -21782,18 +19787,16 @@ }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/unicode-match-property-ecmascript": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, + "license": "MIT", "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -21804,27 +19807,24 @@ }, "node_modules/unicode-match-property-value-ecmascript": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/unicode-property-aliases-ecmascript": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/unique-string": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", "dev": true, + "license": "MIT", "dependencies": { "crypto-random-string": "^2.0.0" }, @@ -21834,9 +19834,8 @@ }, "node_modules/universalify": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -21844,7 +19843,7 @@ "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, "engines": { "node": ">= 0.8" @@ -21852,18 +19851,15 @@ }, "node_modules/upath": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true, + "license": "MIT", "engines": { "node": ">=4", "yarn": "*" } }, "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.0.16", "dev": true, "funding": [ { @@ -21873,14 +19869,19 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { - "browserslist-lint": "cli.js" + "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" @@ -21888,18 +19889,16 @@ }, "node_modules/uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, "node_modules/url-parse": { "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, + "license": "MIT", "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -21907,33 +19906,29 @@ }, "node_modules/use-memo-one": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz", - "integrity": "sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ==", "dev": true, + "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0" } }, "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4.0" } }, "node_modules/utrie": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", - "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { "base64-arraybuffer": "^1.0.2" @@ -21941,24 +19936,21 @@ }, "node_modules/uuid": { "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/v8-compile-cache": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/v8-to-istanbul": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, + "license": "ISC", "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -21968,45 +19960,31 @@ "node": ">=10.12.0" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "node_modules/value-equal": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", - "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/vary": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/void-elements": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", - "integrity": "sha1-YU9/v42AHwu18GYfWy9XhXUOTwk=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/vue-eslint-parser": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz", - "integrity": "sha512-8FdXi0gieEwh1IprIBafpiJWcApwrU+l2FEj8c1HtHFdNXMd0+2jUSjBVmcQYohf/E72irwAXEXLga6TQcB3FA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.1", "eslint-scope": "^5.0.0", @@ -22027,9 +20005,8 @@ }, "node_modules/vue-eslint-parser/node_modules/acorn": { "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -22039,18 +20016,16 @@ }, "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=4" } }, "node_modules/vue-eslint-parser/node_modules/espree": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^7.1.1", "acorn-jsx": "^5.2.0", @@ -22060,42 +20035,29 @@ "node": ">=6.0.0" } }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", - "dev": true, - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "version": "5.0.0", "dev": true, + "license": "MIT", "dependencies": { - "xml-name-validator": "^3.0.0" + "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/walker": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "makeerror": "1.0.12" } }, "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.4.1", "dev": true, + "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -22106,51 +20068,48 @@ }, "node_modules/wbuf": { "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "dev": true, + "license": "MIT", "dependencies": { "minimalistic-assert": "^1.0.0" } }, "node_modules/webidl-conversions": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=10.4" } }, "node_modules/webpack": { - "version": "5.79.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.79.0.tgz", - "integrity": "sha512-3mN4rR2Xq+INd6NnYuL9RC9GAmc1ROPKJoHhrZ4pAjdMFEkJJWrsPw8o2JjCIyQyTu7rTXYn4VG6OpyB3CobZg==", + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dev": true, "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", + "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { @@ -22170,18 +20129,17 @@ } }, "node_modules/webpack-assets-manifest": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/webpack-assets-manifest/-/webpack-assets-manifest-5.1.0.tgz", - "integrity": "sha512-kPuTMEjBrqZQVJ5M6yXNBCEdFbQQn7p+loNXt8NOeDFaAbsNFWqqwR0YL1mfG5LbwhK5FLXWXpuK3GuIIZ46rg==", + "version": "5.2.1", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.0", - "deepmerge": "^4.0", - "lockfile": "^1.0", - "lodash.get": "^4.0", - "lodash.has": "^4.0", - "schema-utils": "^3.0", - "tapable": "^2.0" + "chalk": "^4.1.2", + "deepmerge": "^4.3.1", + "lockfile": "^1.0.4", + "lodash.get": "^4.4.2", + "lodash.has": "^4.5.2", + "schema-utils": "^3.3.0", + "tapable": "^2.2.1" }, "engines": { "node": ">=10.13.0" @@ -22192,9 +20150,8 @@ }, "node_modules/webpack-assets-manifest/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -22207,9 +20164,8 @@ }, "node_modules/webpack-assets-manifest/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -22223,9 +20179,8 @@ }, "node_modules/webpack-assets-manifest/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -22235,18 +20190,16 @@ }, "node_modules/webpack-assets-manifest/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/webpack-assets-manifest/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -22262,9 +20215,8 @@ }, "node_modules/webpack-assets-manifest/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -22274,9 +20226,8 @@ }, "node_modules/webpack-cli": { "version": "4.9.2", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz", - "integrity": "sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ==", "dev": true, + "license": "MIT", "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^1.1.1", @@ -22317,18 +20268,16 @@ }, "node_modules/webpack-cli/node_modules/commander": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10" } }, "node_modules/webpack-cli/node_modules/execa": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -22349,9 +20298,8 @@ }, "node_modules/webpack-cli/node_modules/get-stream": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -22361,21 +20309,19 @@ }, "node_modules/webpack-cli/node_modules/human-signals": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } }, "node_modules/webpack-dev-middleware": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz", - "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==", + "version": "5.3.4", "dev": true, + "license": "MIT", "dependencies": { "colorette": "^2.0.10", - "memfs": "^3.4.1", + "memfs": "^3.4.3", "mime-types": "^2.1.31", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" @@ -22393,9 +20339,8 @@ }, "node_modules/webpack-dev-middleware/node_modules/ajv": { "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -22409,9 +20354,8 @@ }, "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -22421,15 +20365,13 @@ }, "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/webpack-dev-middleware/node_modules/schema-utils": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.8.0", @@ -22446,9 +20388,8 @@ }, "node_modules/webpack-dev-server": { "version": "4.15.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", - "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", "dev": true, + "license": "MIT", "dependencies": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", @@ -22505,9 +20446,8 @@ }, "node_modules/webpack-dev-server/node_modules/ajv": { "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -22521,9 +20461,8 @@ }, "node_modules/webpack-dev-server/node_modules/ajv-keywords": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -22533,15 +20472,13 @@ }, "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/webpack-dev-server/node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -22554,9 +20491,8 @@ }, "node_modules/webpack-dev-server/node_modules/schema-utils": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.8.0", @@ -22571,32 +20507,10 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/webpack-merge": { "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", "dev": true, + "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", "wildcard": "^2.0.0" @@ -22607,18 +20521,16 @@ }, "node_modules/webpack-sources": { "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.13.0" } }, "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -22634,9 +20546,8 @@ }, "node_modules/websocket-driver": { "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "http-parser-js": ">=0.5.1", "safe-buffer": ">=5.1.0", @@ -22648,39 +20559,51 @@ }, "node_modules/websocket-extensions": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=0.8.0" } }, "node_modules/webworkify": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/webworkify/-/webworkify-1.5.0.tgz", - "integrity": "sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "version": "3.1.1", "dev": true, + "license": "MIT", "dependencies": { - "iconv-lite": "0.4.24" + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/whatwg-url": { "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", "dev": true, + "license": "MIT", "dependencies": { "lodash": "^4.7.0", "tr46": "^2.1.0", @@ -22692,9 +20615,8 @@ }, "node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -22707,9 +20629,8 @@ }, "node_modules/which-boxed-primitive": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, + "license": "MIT", "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -22721,39 +20642,69 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "dev": true, + "license": "MIT" + }, "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "version": "1.0.2", "dev": true, + "license": "MIT", "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "dev": true }, "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.15", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -22764,15 +20715,13 @@ }, "node_modules/wildcard": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/with": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", - "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.9.6", "@babel/types": "^7.9.6", @@ -22785,18 +20734,16 @@ }, "node_modules/word-wrap": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/workbox-background-sync": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.5.3.tgz", - "integrity": "sha512-0DD/V05FAcek6tWv9XYj2w5T/plxhDSpclIcAGjA/b7t/6PdaRkQ7ZgtAX6Q/L7kV7wZ8uYRJUoH11VjNipMZw==", "dev": true, + "license": "MIT", "dependencies": { "idb": "^6.1.4", "workbox-core": "6.5.3" @@ -22804,36 +20751,31 @@ }, "node_modules/workbox-background-sync/node_modules/idb": { "version": "6.1.5", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", - "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/workbox-background-sync/node_modules/workbox-core": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/workbox-broadcast-update": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.3.tgz", - "integrity": "sha512-4AwCIA5DiDrYhlN+Miv/fp5T3/whNmSL+KqhTwRBTZIL6pvTgE4lVuRzAt1JltmqyMcQ3SEfCdfxczuI4kwFQg==", "dev": true, + "license": "MIT", "dependencies": { "workbox-core": "6.5.3" } }, "node_modules/workbox-broadcast-update/node_modules/workbox-core": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/workbox-build": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.3.tgz", - "integrity": "sha512-8JNHHS7u13nhwIYCDea9MNXBNPHXCs5KDZPKI/ZNTr3f4sMGoD7hgFGecbyjX1gw4z6e9bMpMsOEJNyH5htA/w==", "dev": true, + "license": "MIT", "dependencies": { "@apideck/better-ajv-errors": "^0.3.1", "@babel/core": "^7.11.1", @@ -22879,9 +20821,8 @@ }, "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.3.tgz", - "integrity": "sha512-9o+HO2MbJhJHjDYZaDxJmSDckvDpiuItEsrIShV0DXeCshXWRHhqYyU/PKHMkuClOmFnZhRd6wzv4vpDu/dRKg==", "dev": true, + "license": "MIT", "dependencies": { "json-schema": "^0.4.0", "jsonpointer": "^5.0.0", @@ -22896,9 +20837,8 @@ }, "node_modules/workbox-build/node_modules/ajv": { "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -22912,21 +20852,18 @@ }, "node_modules/workbox-build/node_modules/idb": { "version": "6.1.5", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", - "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/workbox-build/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/workbox-build/node_modules/source-map": { "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "whatwg-url": "^7.0.0" }, @@ -22936,24 +20873,21 @@ }, "node_modules/workbox-build/node_modules/tr46": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", "dev": true, + "license": "MIT", "dependencies": { "punycode": "^2.1.0" } }, "node_modules/workbox-build/node_modules/webidl-conversions": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/workbox-build/node_modules/whatwg-url": { "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", "dev": true, + "license": "MIT", "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", @@ -22962,24 +20896,21 @@ }, "node_modules/workbox-build/node_modules/workbox-cacheable-response": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.3.tgz", - "integrity": "sha512-6JE/Zm05hNasHzzAGKDkqqgYtZZL2H06ic2GxuRLStA4S/rHUfm2mnLFFXuHAaGR1XuuYyVCEey1M6H3PdZ7SQ==", "dev": true, + "license": "MIT", "dependencies": { "workbox-core": "6.5.3" } }, "node_modules/workbox-build/node_modules/workbox-core": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/workbox-build/node_modules/workbox-expiration": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.3.tgz", - "integrity": "sha512-jzYopYR1zD04ZMdlbn/R2Ik6ixiXbi15c9iX5H8CTi6RPDz7uhvMLZPKEndZTpfgmUk8mdmT9Vx/AhbuCl5Sqw==", "dev": true, + "license": "MIT", "dependencies": { "idb": "^6.1.4", "workbox-core": "6.5.3" @@ -22987,9 +20918,8 @@ }, "node_modules/workbox-build/node_modules/workbox-precaching": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.3.tgz", - "integrity": "sha512-sjNfgNLSsRX5zcc63H/ar/hCf+T19fRtTqvWh795gdpghWb5xsfEkecXEvZ8biEi1QD7X/ljtHphdaPvXDygMQ==", "dev": true, + "license": "MIT", "dependencies": { "workbox-core": "6.5.3", "workbox-routing": "6.5.3", @@ -22998,51 +20928,45 @@ }, "node_modules/workbox-build/node_modules/workbox-routing": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.3.tgz", - "integrity": "sha512-DFjxcuRAJjjt4T34RbMm3MCn+xnd36UT/2RfPRfa8VWJGItGJIn7tG+GwVTdHmvE54i/QmVTJepyAGWtoLPTmg==", "dev": true, + "license": "MIT", "dependencies": { "workbox-core": "6.5.3" } }, "node_modules/workbox-build/node_modules/workbox-strategies": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.3.tgz", - "integrity": "sha512-MgmGRrDVXs7rtSCcetZgkSZyMpRGw8HqL2aguszOc3nUmzGZsT238z/NN9ZouCxSzDu3PQ3ZSKmovAacaIhu1w==", "dev": true, + "license": "MIT", "dependencies": { "workbox-core": "6.5.3" } }, "node_modules/workbox-cacheable-response": { "version": "5.1.4", - "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-5.1.4.tgz", - "integrity": "sha512-0bfvMZs0Of1S5cdswfQK0BXt6ulU5kVD4lwer2CeI+03czHprXR3V4Y8lPTooamn7eHP8Iywi5QjyAMjw0qauA==", "dev": true, + "license": "MIT", "dependencies": { "workbox-core": "^5.1.4" } }, "node_modules/workbox-core": { "version": "5.1.4", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-5.1.4.tgz", - "integrity": "sha512-+4iRQan/1D8I81nR2L5vcbaaFskZC2CL17TLbvWVzQ4qiF/ytOGF6XeV54pVxAvKUtkLANhk8TyIUMtiMw2oDg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/workbox-expiration": { "version": "5.1.4", - "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-5.1.4.tgz", - "integrity": "sha512-oDO/5iC65h2Eq7jctAv858W2+CeRW5e0jZBMNRXpzp0ZPvuT6GblUiHnAsC5W5lANs1QS9atVOm4ifrBiYY7AQ==", "dev": true, + "license": "MIT", "dependencies": { "workbox-core": "^5.1.4" } }, "node_modules/workbox-google-analytics": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.3.tgz", - "integrity": "sha512-3GLCHotz5umoRSb4aNQeTbILETcrTVEozSfLhHSBaegHs1PnqCmN0zbIy2TjTpph2AGXiNwDrWGF0AN+UgDNTw==", "dev": true, + "license": "MIT", "dependencies": { "workbox-background-sync": "6.5.3", "workbox-core": "6.5.3", @@ -23052,18035 +20976,339 @@ }, "node_modules/workbox-google-analytics/node_modules/workbox-core": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/workbox-google-analytics/node_modules/workbox-routing": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.3.tgz", - "integrity": "sha512-DFjxcuRAJjjt4T34RbMm3MCn+xnd36UT/2RfPRfa8VWJGItGJIn7tG+GwVTdHmvE54i/QmVTJepyAGWtoLPTmg==", "dev": true, + "license": "MIT", "dependencies": { "workbox-core": "6.5.3" } }, "node_modules/workbox-google-analytics/node_modules/workbox-strategies": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.3.tgz", - "integrity": "sha512-MgmGRrDVXs7rtSCcetZgkSZyMpRGw8HqL2aguszOc3nUmzGZsT238z/NN9ZouCxSzDu3PQ3ZSKmovAacaIhu1w==", - "dev": true, - "dependencies": { - "workbox-core": "6.5.3" - } - }, - "node_modules/workbox-navigation-preload": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.3.tgz", - "integrity": "sha512-bK1gDFTc5iu6lH3UQ07QVo+0ovErhRNGvJJO/1ngknT0UQ702nmOUhoN9qE5mhuQSrnK+cqu7O7xeaJ+Rd9Tmg==", - "dev": true, - "dependencies": { - "workbox-core": "6.5.3" - } - }, - "node_modules/workbox-navigation-preload/node_modules/workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - }, - "node_modules/workbox-precaching": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-5.1.4.tgz", - "integrity": "sha512-gCIFrBXmVQLFwvAzuGLCmkUYGVhBb7D1k/IL7pUJUO5xacjLcFUaLnnsoVepBGAiKw34HU1y/YuqvTKim9qAZA==", - "dev": true, - "dependencies": { - "workbox-core": "^5.1.4" - } - }, - "node_modules/workbox-range-requests": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.5.3.tgz", - "integrity": "sha512-pGCP80Bpn/0Q0MQsfETSfmtXsQcu3M2QCJwSFuJ6cDp8s2XmbUXkzbuQhCUzKR86ZH2Vex/VUjb2UaZBGamijA==", - "dev": true, - "dependencies": { - "workbox-core": "6.5.3" - } - }, - "node_modules/workbox-range-requests/node_modules/workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - }, - "node_modules/workbox-recipes": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.3.tgz", - "integrity": "sha512-IcgiKYmbGiDvvf3PMSEtmwqxwfQ5zwI7OZPio3GWu4PfehA8jI8JHI3KZj+PCfRiUPZhjQHJ3v1HbNs+SiSkig==", - "dev": true, - "dependencies": { - "workbox-cacheable-response": "6.5.3", - "workbox-core": "6.5.3", - "workbox-expiration": "6.5.3", - "workbox-precaching": "6.5.3", - "workbox-routing": "6.5.3", - "workbox-strategies": "6.5.3" - } - }, - "node_modules/workbox-recipes/node_modules/idb": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", - "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==", - "dev": true - }, - "node_modules/workbox-recipes/node_modules/workbox-cacheable-response": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.3.tgz", - "integrity": "sha512-6JE/Zm05hNasHzzAGKDkqqgYtZZL2H06ic2GxuRLStA4S/rHUfm2mnLFFXuHAaGR1XuuYyVCEey1M6H3PdZ7SQ==", - "dev": true, - "dependencies": { - "workbox-core": "6.5.3" - } - }, - "node_modules/workbox-recipes/node_modules/workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - }, - "node_modules/workbox-recipes/node_modules/workbox-expiration": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.3.tgz", - "integrity": "sha512-jzYopYR1zD04ZMdlbn/R2Ik6ixiXbi15c9iX5H8CTi6RPDz7uhvMLZPKEndZTpfgmUk8mdmT9Vx/AhbuCl5Sqw==", - "dev": true, - "dependencies": { - "idb": "^6.1.4", - "workbox-core": "6.5.3" - } - }, - "node_modules/workbox-recipes/node_modules/workbox-precaching": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.3.tgz", - "integrity": "sha512-sjNfgNLSsRX5zcc63H/ar/hCf+T19fRtTqvWh795gdpghWb5xsfEkecXEvZ8biEi1QD7X/ljtHphdaPvXDygMQ==", - "dev": true, - "dependencies": { - "workbox-core": "6.5.3", - "workbox-routing": "6.5.3", - "workbox-strategies": "6.5.3" - } - }, - "node_modules/workbox-recipes/node_modules/workbox-routing": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.3.tgz", - "integrity": "sha512-DFjxcuRAJjjt4T34RbMm3MCn+xnd36UT/2RfPRfa8VWJGItGJIn7tG+GwVTdHmvE54i/QmVTJepyAGWtoLPTmg==", - "dev": true, - "dependencies": { - "workbox-core": "6.5.3" - } - }, - "node_modules/workbox-recipes/node_modules/workbox-strategies": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.3.tgz", - "integrity": "sha512-MgmGRrDVXs7rtSCcetZgkSZyMpRGw8HqL2aguszOc3nUmzGZsT238z/NN9ZouCxSzDu3PQ3ZSKmovAacaIhu1w==", - "dev": true, - "dependencies": { - "workbox-core": "6.5.3" - } - }, - "node_modules/workbox-routing": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-5.1.4.tgz", - "integrity": "sha512-8ljknRfqE1vEQtnMtzfksL+UXO822jJlHTIR7+BtJuxQ17+WPZfsHqvk1ynR/v0EHik4x2+826Hkwpgh4GKDCw==", - "dev": true, - "dependencies": { - "workbox-core": "^5.1.4" - } - }, - "node_modules/workbox-strategies": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-5.1.4.tgz", - "integrity": "sha512-VVS57LpaJTdjW3RgZvPwX0NlhNmscR7OQ9bP+N/34cYMDzXLyA6kqWffP6QKXSkca1OFo/v6v7hW7zrrguo6EA==", - "dev": true, - "dependencies": { - "workbox-core": "^5.1.4", - "workbox-routing": "^5.1.4" - } - }, - "node_modules/workbox-streams": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.3.tgz", - "integrity": "sha512-vN4Qi8o+b7zj1FDVNZ+PlmAcy1sBoV7SC956uhqYvZ9Sg1fViSbOpydULOssVJ4tOyKRifH/eoi6h99d+sJ33w==", - "dev": true, - "dependencies": { - "workbox-core": "6.5.3", - "workbox-routing": "6.5.3" - } - }, - "node_modules/workbox-streams/node_modules/workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - }, - "node_modules/workbox-streams/node_modules/workbox-routing": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.3.tgz", - "integrity": "sha512-DFjxcuRAJjjt4T34RbMm3MCn+xnd36UT/2RfPRfa8VWJGItGJIn7tG+GwVTdHmvE54i/QmVTJepyAGWtoLPTmg==", "dev": true, - "dependencies": { - "workbox-core": "6.5.3" - } - }, - "node_modules/workbox-sw": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.3.tgz", - "integrity": "sha512-BQBzm092w+NqdIEF2yhl32dERt9j9MDGUTa2Eaa+o3YKL4Qqw55W9yQC6f44FdAHdAJrJvp0t+HVrfh8AiGj8A==", - "dev": true - }, - "node_modules/workbox-webpack-plugin": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.5.3.tgz", - "integrity": "sha512-Es8Xr02Gi6Kc3zaUwR691ZLy61hz3vhhs5GztcklQ7kl5k2qAusPh0s6LF3wEtlpfs9ZDErnmy5SErwoll7jBA==", - "dev": true, - "dependencies": { - "fast-json-stable-stringify": "^2.1.0", - "pretty-bytes": "^5.4.1", - "upath": "^1.2.0", - "webpack-sources": "^1.4.3", - "workbox-build": "6.5.3" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "webpack": "^4.4.0 || ^5.9.0" - } - }, - "node_modules/workbox-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workbox-webpack-plugin/node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, - "node_modules/workbox-window": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.5.3.tgz", - "integrity": "sha512-GnJbx1kcKXDtoJBVZs/P7ddP0Yt52NNy4nocjBpYPiRhMqTpJCNrSL+fGHZ/i/oP6p/vhE8II0sA6AZGKGnssw==", - "dev": true, - "dependencies": { - "@types/trusted-types": "^2.0.2", - "workbox-core": "6.5.3" - } - }, - "node_modules/workbox-window/node_modules/workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - }, - "node_modules/workerpool": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", - "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "node_modules/ws": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yup": { - "version": "0.32.11", - "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", - "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.15.4", - "@types/lodash": "^4.14.175", - "lodash": "^4.17.21", - "lodash-es": "^4.17.21", - "nanoclone": "^0.2.1", - "property-expr": "^2.0.4", - "toposort": "^2.0.2" - }, - "engines": { - "node": ">=10" - } - } - }, - "dependencies": { - "@adobe/css-tools": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", - "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", - "dev": true - }, - "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - } - } - }, - "@azure/msal-browser": { - "version": "2.37.0", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-2.37.0.tgz", - "integrity": "sha512-YNGD/W/tw/5wDWlXOfmrVILaxVsorVLxYU2ovmL1PDvxkdudbQRyGk/76l4emqgDAl/kPQeqyivxjOU6w1YfvQ==", - "dev": true, - "requires": { - "@azure/msal-common": "13.0.0" - } - }, - "@azure/msal-common": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-13.0.0.tgz", - "integrity": "sha512-GqCOg5H5bouvLij9NFXFkh+asRRxsPBRwnTDsfK7o0KcxYHJbuidKw8/VXpycahGXNxgtuhqtK/n5he+5NhyEA==", - "dev": true - }, - "@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "requires": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - } - }, - "@babel/compat-data": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", - "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", - "dev": true - }, - "@babel/core": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.8.tgz", - "integrity": "sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.7", - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.8", - "@babel/parser": "^7.17.8", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" - } - }, - "@babel/eslint-parser": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.17.0.tgz", - "integrity": "sha512-PUEJ7ZBXbRkbq3qqM/jZ2nIuakUBqCYc7Qf52Lj7dlZ6zERnqisdHioL0l4wwQZnmskMeasqUNzLBFKs3nylXA==", - "dev": true, - "requires": { - "eslint-scope": "^5.1.1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.0" - } - }, - "@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, - "requires": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", - "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.21.4", - "@babel/helper-validator-option": "^7.21.0", - "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", - "semver": "^6.3.0" - }, - "dependencies": { - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - } - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.4.tgz", - "integrity": "sha512-46QrX2CQlaFRF4TkwfTt6nJD7IHq8539cCL7SDpqWSDeJKY1xylKKY5F/33mJhLZ3mFvKv2gGrVS6NkyF6qs+Q==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-member-expression-to-functions": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/helper-split-export-declaration": "^7.18.6" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.4.tgz", - "integrity": "sha512-M00OuhU+0GyZ5iBBN9czjugzWrEq2vDpf/zCYHxxf93ul/Q5rv+a5h+/+0WnI1AebHNVtl5bFV0qsJoH23DbfA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.3.1" - } - }, - "@babel/helper-define-polyfill-provider": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", - "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - } - }, - "@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz", - "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==", - "dev": true, - "requires": { - "@babel/types": "^7.21.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", - "dev": true, - "requires": { - "@babel/types": "^7.21.4" - } - }, - "@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", - "dev": true - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", - "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-replace-supers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", - "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.20.7", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" - } - }, - "@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", - "dev": true, - "requires": { - "@babel/types": "^7.20.2" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", - "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", - "dev": true, - "requires": { - "@babel/types": "^7.20.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", - "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" - } - }, - "@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", - "dev": true, - "requires": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" - } - }, - "@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true - }, - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", - "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz", - "integrity": "sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-proposal-optional-chaining": "^7.20.7" - }, - "dependencies": { - "@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - } - } - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", - "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", - "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-proposal-class-static-block": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", - "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", - "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", - "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz", - "integrity": "sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-import-assertions": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz", - "integrity": "sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.19.0" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", - "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz", - "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", - "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", - "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", - "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", - "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz", - "integrity": "sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", - "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/template": "^7.20.7" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.7.tgz", - "integrity": "sha512-XVh0r5yq9sLR4vZ6eVZe8FKfIcSgaTBxVBRSYokRj2qksf6QerYnTxz9/GTuKTH/n/HwLP7t6gtlybHetJ/6hQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", - "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", - "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", - "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz", - "integrity": "sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", - "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", - "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", - "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", - "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", - "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-simple-access": "^7.20.2" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", - "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-identifier": "^7.19.1" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", - "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", - "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.20.5", - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", - "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", - "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz", - "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", - "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-react-constant-elements": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.21.3.tgz", - "integrity": "sha512-4DVcFeWe/yDYBLp0kBmOGFJ6N2UYg7coGid1gdxb4co62dy/xISDMaYBXBVXEDhfgMk7qkbcYiGtwd5Q/hwDDQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-react-display-name": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", - "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-react-jsx": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.21.0.tgz", - "integrity": "sha512-6OAWljMvQrZjR2DaNhVfRz6dkCAVV+ymcLUmaf8bccGOHn2v5rHJK3tTpij0BuhdYWP4LLaqj5lwcdlpAAPuvg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-jsx": "^7.18.6", - "@babel/types": "^7.21.0" - } - }, - "@babel/plugin-transform-react-jsx-development": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", - "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", - "dev": true, - "requires": { - "@babel/plugin-transform-react-jsx": "^7.18.6" - } - }, - "@babel/plugin-transform-react-pure-annotations": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", - "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", - "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.2" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", - "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-runtime": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz", - "integrity": "sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-plugin-utils": "^7.16.7", - "babel-plugin-polyfill-corejs2": "^0.3.0", - "babel-plugin-polyfill-corejs3": "^0.5.0", - "babel-plugin-polyfill-regenerator": "^0.3.0", - "semver": "^6.3.0" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", - "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", - "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", - "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", - "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", - "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-typescript": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.3.tgz", - "integrity": "sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-typescript": "^7.20.0" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", - "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", - "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/preset-env": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.21.4.tgz", - "integrity": "sha512-2W57zHs2yDLm6GD5ZpvNn71lZ0B/iypSdIeq25OurDKji6AdzV07qp4s3n1/x5BqtiGaTrPN3nerlSCaC5qNTw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.21.0", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.20.7", - "@babel/plugin-proposal-async-generator-functions": "^7.20.7", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.21.0", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.20.7", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.20.7", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.21.0", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.21.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.20.0", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.20.7", - "@babel/plugin-transform-async-to-generator": "^7.20.7", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.21.0", - "@babel/plugin-transform-classes": "^7.21.0", - "@babel/plugin-transform-computed-properties": "^7.20.7", - "@babel/plugin-transform-destructuring": "^7.21.3", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.9", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.21.0", - "@babel/plugin-transform-function-name": "^7.18.9", - "@babel/plugin-transform-literals": "^7.18.9", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.20.11", - "@babel/plugin-transform-modules-commonjs": "^7.21.2", - "@babel/plugin-transform-modules-systemjs": "^7.20.11", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.20.5", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.21.3", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.20.5", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.20.7", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.9", - "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.21.4", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "core-js-compat": "^3.25.1", - "semver": "^6.3.0" - }, - "dependencies": { - "@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz", - "integrity": "sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", - "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "regenerator-transform": "^0.15.1" - } - }, - "babel-plugin-polyfill-corejs3": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", - "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.3", - "core-js-compat": "^3.25.1" - } - }, - "babel-plugin-polyfill-regenerator": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", - "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.3" - } - }, - "regenerator-transform": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", - "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4" - } - } - } - }, - "@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/preset-react": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz", - "integrity": "sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7", - "@babel/helper-validator-option": "^7.16.7", - "@babel/plugin-transform-react-display-name": "^7.16.7", - "@babel/plugin-transform-react-jsx": "^7.16.7", - "@babel/plugin-transform-react-jsx-development": "^7.16.7", - "@babel/plugin-transform-react-pure-annotations": "^7.16.7" - } - }, - "@babel/preset-typescript": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.21.4.tgz", - "integrity": "sha512-sMLNWY37TCdRH/bJ6ZeeOH1nPuanED7Ai9Y/vH31IPqalioJ6ZNFUWONsakhv4r4n+I6gm5lmoE0olkgib/j/A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.21.0", - "@babel/plugin-syntax-jsx": "^7.21.4", - "@babel/plugin-transform-modules-commonjs": "^7.21.2", - "@babel/plugin-transform-typescript": "^7.21.3" - } - }, - "@babel/register": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.17.7.tgz", - "integrity": "sha512-fg56SwvXRifootQEDQAu1mKdjh5uthPzdO0N6t358FktfL4XjAVXuH58ULoiW8mesxiOgNIrxiImqEwv0+hRRA==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "find-cache-dir": "^2.0.0", - "make-dir": "^2.1.0", - "pirates": "^4.0.5", - "source-map-support": "^0.5.16" - } - }, - "@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true - }, - "@babel/runtime": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.8.tgz", - "integrity": "sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/runtime-corejs3": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.8.tgz", - "integrity": "sha512-ZbYSUvoSF6dXZmMl/CYTMOvzIFnbGfv4W3SEHYgMvNsFTeLaF2gkGAF4K2ddmtSK4Emej+0aYcnSC6N5dPCXUQ==", - "dev": true, - "requires": { - "core-js-pure": "^3.20.2", - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - } - }, - "@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - } - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "@csstools/postcss-color-function": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.0.3.tgz", - "integrity": "sha512-J26I69pT2B3MYiLY/uzCGKVJyMYVg9TCpXkWsRlt+Yfq+nELUEm72QXIMYXs4xA9cJA4Oqs2EylrfokKl3mJEQ==", - "dev": true, - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-font-format-keywords": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.0.tgz", - "integrity": "sha512-oO0cZt8do8FdVBX8INftvIA4lUrKUSCcWUf9IwH9IPWOgKT22oAZFXeHLoDK7nhB2SmkNycp5brxfNMRLIhd6Q==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-hwb-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.0.tgz", - "integrity": "sha512-VSTd7hGjmde4rTj1rR30sokY3ONJph1reCBTUXqeW1fKwETPy1x4t/XIeaaqbMbC5Xg4SM/lyXZ2S8NELT2TaA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-ic-unit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.0.tgz", - "integrity": "sha512-i4yps1mBp2ijrx7E96RXrQXQQHm6F4ym1TOD0D69/sjDjZvQ22tqiEvaNw7pFZTUO5b9vWRHzbHzP9+UKuw+bA==", - "dev": true, - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-is-pseudo-class": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.1.tgz", - "integrity": "sha512-Og5RrTzwFhrKoA79c3MLkfrIBYmwuf/X83s+JQtz/Dkk/MpsaKtqHV1OOzYkogQ+tj3oYp5Mq39XotBXNqVc3Q==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "@csstools/postcss-normalize-display-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.0.tgz", - "integrity": "sha512-bX+nx5V8XTJEmGtpWTO6kywdS725t71YSLlxWt78XoHUbELWgoCXeOFymRJmL3SU1TLlKSIi7v52EWqe60vJTQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-oklab-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.0.2.tgz", - "integrity": "sha512-QwhWesEkMlp4narAwUi6pgc6kcooh8cC7zfxa9LSQNYXqzcdNUtNBzbGc5nuyAVreb7uf5Ox4qH1vYT3GA1wOg==", - "dev": true, - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-progressive-custom-properties": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", - "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@date-io/core": { - "version": "1.3.13", - "resolved": "https://registry.npmjs.org/@date-io/core/-/core-1.3.13.tgz", - "integrity": "sha512-AlEKV7TxjeK+jxWVKcCFrfYAk8spX9aCyiToFIiLPtfQbsjmRGLIhb5VZgptQcJdHtLXo7+m0DuurwFgUToQuA==", - "dev": true - }, - "@date-io/date-fns": { - "version": "1.3.13", - "resolved": "https://registry.npmjs.org/@date-io/date-fns/-/date-fns-1.3.13.tgz", - "integrity": "sha512-yXxGzcRUPcogiMj58wVgFjc9qUYrCnnU9eLcyNbsQCmae4jPuZCDoIBR21j8ZURsM7GRtU62VOw5yNd4dDHunA==", - "dev": true, - "requires": { - "@date-io/core": "^1.3.13" - } - }, - "@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true - }, - "@emotion/cache": { - "version": "10.0.29", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz", - "integrity": "sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==", - "dev": true, - "requires": { - "@emotion/sheet": "0.9.4", - "@emotion/stylis": "0.8.5", - "@emotion/utils": "0.11.3", - "@emotion/weak-memoize": "0.2.5" - } - }, - "@emotion/core": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/@emotion/core/-/core-10.3.1.tgz", - "integrity": "sha512-447aUEjPIm0MnE6QYIaFz9VQOHSXf4Iu6EWOIqq11EAPqinkSZmfymPTmlOE3QjLv846lH4JVZBUOtwGbuQoww==", - "dev": true, - "requires": { - "@babel/runtime": "^7.5.5", - "@emotion/cache": "^10.0.27", - "@emotion/css": "^10.0.27", - "@emotion/serialize": "^0.11.15", - "@emotion/sheet": "0.9.4", - "@emotion/utils": "0.11.3" - } - }, - "@emotion/css": { - "version": "10.0.27", - "resolved": "https://registry.npmjs.org/@emotion/css/-/css-10.0.27.tgz", - "integrity": "sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw==", - "dev": true, - "requires": { - "@emotion/serialize": "^0.11.15", - "@emotion/utils": "0.11.3", - "babel-plugin-emotion": "^10.0.27" - } - }, - "@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", - "dev": true - }, - "@emotion/is-prop-valid": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", - "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", - "dev": true, - "requires": { - "@emotion/memoize": "0.7.4" - } - }, - "@emotion/memoize": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", - "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", - "dev": true - }, - "@emotion/serialize": { - "version": "0.11.16", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.11.16.tgz", - "integrity": "sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==", - "dev": true, - "requires": { - "@emotion/hash": "0.8.0", - "@emotion/memoize": "0.7.4", - "@emotion/unitless": "0.7.5", - "@emotion/utils": "0.11.3", - "csstype": "^2.5.7" - } - }, - "@emotion/sheet": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-0.9.4.tgz", - "integrity": "sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==", - "dev": true - }, - "@emotion/styled": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-10.3.0.tgz", - "integrity": "sha512-GgcUpXBBEU5ido+/p/mCT2/Xx+Oqmp9JzQRuC+a4lYM4i4LBBn/dWvc0rQ19N9ObA8/T4NWMrPNe79kMBDJqoQ==", - "dev": true, - "requires": { - "@emotion/styled-base": "^10.3.0", - "babel-plugin-emotion": "^10.0.27" - } - }, - "@emotion/styled-base": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@emotion/styled-base/-/styled-base-10.3.0.tgz", - "integrity": "sha512-PBRqsVKR7QRNkmfH78hTSSwHWcwDpecH9W6heujWAcyp2wdz/64PP73s7fWS1dIPm8/Exc8JAzYS8dEWXjv60w==", - "dev": true, - "requires": { - "@babel/runtime": "^7.5.5", - "@emotion/is-prop-valid": "0.8.8", - "@emotion/serialize": "^0.11.15", - "@emotion/utils": "0.11.3" - } - }, - "@emotion/stylis": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", - "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==", - "dev": true - }, - "@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", - "dev": true - }, - "@emotion/utils": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.11.3.tgz", - "integrity": "sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==", - "dev": true - }, - "@emotion/weak-memoize": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", - "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==", - "dev": true - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", - "dev": true - } - } - }, - "@eslint/eslintrc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.1", - "globals": "^13.9.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "globals": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "@hookform/devtools": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@hookform/devtools/-/devtools-2.2.1.tgz", - "integrity": "sha512-VQh4kqwUOpz9LCDzIP0aJ4qnD/ob8Gp09L8gDy++9XtL66z6g8kbCynUvBrJm4qbCNdH0M7/Spm3AUjJqUuFlA==", - "dev": true, - "requires": { - "@emotion/core": "^10.0.28", - "@emotion/styled": "^10.0.27", - "@types/lodash": "^4.14.152", - "little-state-machine": "^3.0.1", - "lodash": "^4.17.15", - "react-simple-animate": "^3.3.8" - }, - "dependencies": { - "little-state-machine": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/little-state-machine/-/little-state-machine-3.1.4.tgz", - "integrity": "sha512-gYlLCj6oUME0NG34/2O0Ljy52qYYyYDJ5yiAuq2ijbaRlBKIqtQQkKkEYn0KfjYXCE693j+bdY22EyZin25Bhw==", - "dev": true, - "requires": {} - } - } - }, - "@hookform/resolvers": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-1.3.0.tgz", - "integrity": "sha512-NF+KJYDiFjnGAqhM92vG5kFJFCZFFjO5VxcByf06o6FrG7BEta5NDBhqVsIAMSfMNsn1kWfSKX1TkDT21xq9Hg==", - "dev": true, - "requires": {} - }, - "@hot-loader/react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/@hot-loader/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-G2RZrFhsQClS+bdDh/Ojpk3SgocLPUGnvnJDTQYnmKSSwXtU+Yh+8QMs+Ia3zaAvBiOSpIIDSUxuN69cvKqrWg==", - "dev": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" - } - }, - "@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, - "requires": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jest/create-cache-key-function": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-27.5.1.tgz", - "integrity": "sha512-dmH1yW+makpTSURTy8VzdUwFnfQh1G8R+DxO2Ho2FFmBbKFEVm+3jWdvFhE2VqB/LATCTokkP0dotjyQyw5/AQ==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1" - }, - "dependencies": { - "@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - } - }, - "@types/yargs": { - "version": "16.0.5", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", - "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "requires": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - } - }, - "@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "requires": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - } - }, - "@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "requires": { - "jest-get-type": "^29.6.3" - } - }, - "@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - } - }, - "@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", - "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - } - }, - "istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "requires": { - "semver": "^7.5.3" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, - "@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - } - }, - "@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, - "requires": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "requires": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - } - }, - "@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - } - } - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "@jscpd/core": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@jscpd/core/-/core-3.4.5.tgz", - "integrity": "sha512-02Ajnj07VykiwdWNoMKGdQDHT76kJGOvc1h9+aoicU0CeacWIEuoJW6Gy+N3j+UGUlc1ndWhZ91alIiQ8ERMGg==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.4" - } - }, - "@jscpd/finder": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@jscpd/finder/-/finder-3.4.5.tgz", - "integrity": "sha512-Hz8s6UVbtETYmDP+MdjaTaKKgXsb+SR1dJcdwluBTm5ZNkE9cE/dnDVnrEcKGhE7N3Mg6HEo/fTIKqBsvbRZlw==", - "dev": true, - "requires": { - "@jscpd/core": "^3.4.5", - "@jscpd/tokenizer": "^3.4.5", - "blamer": "^1.0.1", - "bytes": "^3.1.0", - "cli-table3": "^0.6.0", - "colors": "1.4.0", - "fast-glob": "^3.2.2", - "fs-extra": "^9.0.0", - "markdown-table": "^2.0.0", - "pug": "^3.0.1" - } - }, - "@jscpd/html-reporter": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@jscpd/html-reporter/-/html-reporter-3.4.5.tgz", - "integrity": "sha512-N1W97Xfz2xFDmi5UlYfplGOxz0oLNCvOVD5wYfe1v9WC7BYV1LrDNRWfJzadCefa1XGLsxvMDtLjnhIpFInpUg==", - "dev": true, - "requires": { - "colors": "1.4.0", - "fs-extra": "^9.0.1" - } - }, - "@jscpd/tokenizer": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@jscpd/tokenizer/-/tokenizer-3.4.5.tgz", - "integrity": "sha512-yPamcj9V1a6h1AGEzdlyfa8t9Lxsb3sZ6Wr7m+cZw2sWD2AlCAjSzbgUwdla7d6y5g1jaVU2XGHEVNUx4vZUqw==", - "dev": true, - "requires": { - "@jscpd/core": "^3.4.5", - "reprism": "^0.0.11", - "spark-md5": "^3.0.1" - } - }, - "@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true - }, - "@material-ui/core": { - "version": "4.12.3", - "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz", - "integrity": "sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.4.4", - "@material-ui/styles": "^4.11.4", - "@material-ui/system": "^4.12.1", - "@material-ui/types": "5.1.0", - "@material-ui/utils": "^4.11.2", - "@types/react-transition-group": "^4.2.0", - "clsx": "^1.0.4", - "hoist-non-react-statics": "^3.3.2", - "popper.js": "1.16.1-lts", - "prop-types": "^15.7.2", - "react-is": "^16.8.0 || ^17.0.0", - "react-transition-group": "^4.4.0" - } - }, - "@material-ui/icons": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.2.tgz", - "integrity": "sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.4.4" - } - }, - "@material-ui/lab": { - "version": "4.0.0-alpha.60", - "resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.60.tgz", - "integrity": "sha512-fadlYsPJF+0fx2lRuyqAuJj7hAS1tLDdIEEdov5jlrpb5pp4b+mRDUqQTUxi4inRZHS1bEXpU8QWUhO6xX88aA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.4.4", - "@material-ui/utils": "^4.11.2", - "clsx": "^1.0.4", - "prop-types": "^15.7.2", - "react-is": "^16.8.0 || ^17.0.0" - } - }, - "@material-ui/pickers": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/@material-ui/pickers/-/pickers-3.3.10.tgz", - "integrity": "sha512-hS4pxwn1ZGXVkmgD4tpFpaumUaAg2ZzbTrxltfC5yPw4BJV+mGkfnQOB4VpWEYZw2jv65Z0wLwDE/piQiPPZ3w==", - "dev": true, - "requires": { - "@babel/runtime": "^7.6.0", - "@date-io/core": "1.x", - "@types/styled-jsx": "^2.2.8", - "clsx": "^1.0.2", - "react-transition-group": "^4.0.0", - "rifm": "^0.7.0" - } - }, - "@material-ui/styles": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz", - "integrity": "sha512-KNTIZcnj/zprG5LW0Sao7zw+yG3O35pviHzejMdcSGCdWbiO8qzRgOYL8JAxAsWBKOKYwVZxXtHWaB5T2Kvxew==", - "dev": true, - "requires": { - "@babel/runtime": "^7.4.4", - "@emotion/hash": "^0.8.0", - "@material-ui/types": "5.1.0", - "@material-ui/utils": "^4.11.2", - "clsx": "^1.0.4", - "csstype": "^2.5.2", - "hoist-non-react-statics": "^3.3.2", - "jss": "^10.5.1", - "jss-plugin-camel-case": "^10.5.1", - "jss-plugin-default-unit": "^10.5.1", - "jss-plugin-global": "^10.5.1", - "jss-plugin-nested": "^10.5.1", - "jss-plugin-props-sort": "^10.5.1", - "jss-plugin-rule-value-function": "^10.5.1", - "jss-plugin-vendor-prefixer": "^10.5.1", - "prop-types": "^15.7.2" - } - }, - "@material-ui/system": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.1.tgz", - "integrity": "sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.4.4", - "@material-ui/utils": "^4.11.2", - "csstype": "^2.5.2", - "prop-types": "^15.7.2" - } - }, - "@material-ui/types": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz", - "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==", - "dev": true, - "requires": {} - }, - "@material-ui/utils": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz", - "integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.4.4", - "prop-types": "^15.7.2", - "react-is": "^16.8.0 || ^17.0.0" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@quoin/nepali-datepicker-reactjs": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@quoin/nepali-datepicker-reactjs/-/nepali-datepicker-reactjs-1.2.4.tgz", - "integrity": "sha512-xwcKdLsGF+vaFwM+CuqQukw9ZNhYbBXlJLJR42ZRe02s0pZV405cDyuiq6cKl/tRX90zGbSXWHUOxYAgQKGZkg==", - "dev": true, - "requires": {} - }, - "@react-dnd/asap": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-4.0.1.tgz", - "integrity": "sha512-kLy0PJDDwvwwTXxqTFNAAllPHD73AycE9ypWeln/IguoGBEbvFcPDbCV03G52bEcC5E+YgupBE0VzHGdC8SIXg==", - "dev": true - }, - "@react-dnd/invariant": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-2.0.0.tgz", - "integrity": "sha512-xL4RCQBCBDJ+GRwKTFhGUW8GXa4yoDfJrPbLblc3U09ciS+9ZJXJ3Qrcs/x2IODOdIE5kQxvMmE2UKyqUictUw==", - "dev": true - }, - "@react-dnd/shallowequal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz", - "integrity": "sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==", - "dev": true - }, - "@rollup/plugin-babel": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", - "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@rollup/pluginutils": "^3.1.0" - } - }, - "@rollup/plugin-node-resolve": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", - "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", - "builtin-modules": "^3.1.0", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.19.0" - } - }, - "@rollup/plugin-replace": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", - "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.1.0", - "magic-string": "^0.25.7" - } - }, - "@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", - "dev": true, - "requires": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - } - } - }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^2.0.0" - }, - "dependencies": { - "@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - } - } - }, - "@sinonjs/formatio": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", - "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" - } - }, - "@sinonjs/samsam": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", - "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.3.0", - "array-from": "^2.1.1", - "lodash": "^4.17.15" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "@surma/rollup-plugin-off-main-thread": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", - "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", - "dev": true, - "requires": { - "ejs": "^3.1.6", - "json5": "^2.2.0", - "magic-string": "^0.25.0", - "string.prototype.matchall": "^4.0.6" - } - }, - "@svgr/babel-plugin-add-jsx-attribute": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", - "integrity": "sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==", - "dev": true, - "requires": {} - }, - "@svgr/babel-plugin-remove-jsx-attribute": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-7.0.0.tgz", - "integrity": "sha512-iiZaIvb3H/c7d3TH2HBeK91uI2rMhZNwnsIrvd7ZwGLkFw6mmunOCoVnjdYua662MqGFxlN9xTq4fv9hgR4VXQ==", - "dev": true, - "requires": {} - }, - "@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-7.0.0.tgz", - "integrity": "sha512-sQQmyo+qegBx8DfFc04PFmIO1FP1MHI1/QEpzcIcclo5OAISsOJPW76ZIs0bDyO/DBSJEa/tDa1W26pVtt0FRw==", - "dev": true, - "requires": {} - }, - "@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz", - "integrity": "sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg==", - "dev": true, - "requires": {} - }, - "@svgr/babel-plugin-svg-dynamic-title": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz", - "integrity": "sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw==", - "dev": true, - "requires": {} - }, - "@svgr/babel-plugin-svg-em-dimensions": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz", - "integrity": "sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA==", - "dev": true, - "requires": {} - }, - "@svgr/babel-plugin-transform-react-native-svg": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz", - "integrity": "sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg==", - "dev": true, - "requires": {} - }, - "@svgr/babel-plugin-transform-svg-component": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz", - "integrity": "sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ==", - "dev": true, - "requires": {} - }, - "@svgr/babel-preset": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.5.1.tgz", - "integrity": "sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw==", - "dev": true, - "requires": { - "@svgr/babel-plugin-add-jsx-attribute": "^6.5.1", - "@svgr/babel-plugin-remove-jsx-attribute": "*", - "@svgr/babel-plugin-remove-jsx-empty-expression": "*", - "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.5.1", - "@svgr/babel-plugin-svg-dynamic-title": "^6.5.1", - "@svgr/babel-plugin-svg-em-dimensions": "^6.5.1", - "@svgr/babel-plugin-transform-react-native-svg": "^6.5.1", - "@svgr/babel-plugin-transform-svg-component": "^6.5.1" - } - }, - "@svgr/core": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.5.1.tgz", - "integrity": "sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==", - "dev": true, - "requires": { - "@babel/core": "^7.19.6", - "@svgr/babel-preset": "^6.5.1", - "@svgr/plugin-jsx": "^6.5.1", - "camelcase": "^6.2.0", - "cosmiconfig": "^7.0.1" - }, - "dependencies": { - "@babel/core": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", - "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.4", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.4", - "@babel/types": "^7.21.4", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - } - } - } - }, - "@svgr/hast-util-to-babel-ast": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz", - "integrity": "sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw==", - "dev": true, - "requires": { - "@babel/types": "^7.20.0", - "entities": "^4.4.0" - }, - "dependencies": { - "entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", - "dev": true - } - } - }, - "@svgr/plugin-jsx": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz", - "integrity": "sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw==", - "dev": true, - "requires": { - "@babel/core": "^7.19.6", - "@svgr/babel-preset": "^6.5.1", - "@svgr/hast-util-to-babel-ast": "^6.5.1", - "svg-parser": "^2.0.4" - }, - "dependencies": { - "@babel/core": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", - "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.4", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.4", - "@babel/types": "^7.21.4", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - } - } - } - }, - "@svgr/plugin-svgo": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz", - "integrity": "sha512-omvZKf8ixP9z6GWgwbtmP9qQMPX4ODXi+wzbVZgomNFsUIlHA1sf4fThdwTWSsZGgvGAG6yE+b/F5gWUkcZ/iQ==", - "dev": true, - "requires": { - "cosmiconfig": "^7.0.1", - "deepmerge": "^4.2.2", - "svgo": "^2.8.0" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "requires": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - } - }, - "mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "requires": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - } - } - } - }, - "@svgr/webpack": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.5.1.tgz", - "integrity": "sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA==", - "dev": true, - "requires": { - "@babel/core": "^7.19.6", - "@babel/plugin-transform-react-constant-elements": "^7.18.12", - "@babel/preset-env": "^7.19.4", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.18.6", - "@svgr/core": "^6.5.1", - "@svgr/plugin-jsx": "^6.5.1", - "@svgr/plugin-svgo": "^6.5.1" - }, - "dependencies": { - "@babel/core": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", - "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.4", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.4", - "@babel/types": "^7.21.4", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - } - }, - "@babel/preset-react": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz", - "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-transform-react-display-name": "^7.18.6", - "@babel/plugin-transform-react-jsx": "^7.18.6", - "@babel/plugin-transform-react-jsx-development": "^7.18.6", - "@babel/plugin-transform-react-pure-annotations": "^7.18.6" - } - } - } - }, - "@swc/core": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.84.tgz", - "integrity": "sha512-UPKUiDwG7HOdPfOb1VFeEJ76JDgU2w80JLewzx6tb0fk9TIjhr9yxKBzPbzc/QpjGHDu5iaEuNeZcu27u4j63g==", - "dev": true, - "requires": { - "@swc/core-darwin-arm64": "1.3.84", - "@swc/core-darwin-x64": "1.3.84", - "@swc/core-linux-arm-gnueabihf": "1.3.84", - "@swc/core-linux-arm64-gnu": "1.3.84", - "@swc/core-linux-arm64-musl": "1.3.84", - "@swc/core-linux-x64-gnu": "1.3.84", - "@swc/core-linux-x64-musl": "1.3.84", - "@swc/core-win32-arm64-msvc": "1.3.84", - "@swc/core-win32-ia32-msvc": "1.3.84", - "@swc/core-win32-x64-msvc": "1.3.84", - "@swc/types": "^0.1.4" - } - }, - "@swc/core-darwin-arm64": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.84.tgz", - "integrity": "sha512-mqK0buOo+toF2HoJ/gWj2ApZbvbIiNq3mMwSTHCYJHlQFQfoTWnl9aaD5GSO4wfNFVYfEZ1R259o5uv5NlVtoA==", - "dev": true, - "optional": true - }, - "@swc/core-darwin-x64": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.84.tgz", - "integrity": "sha512-cyuQZz62C43EDZqtnptUTlfDvAjgG3qu139m5zsfIK6ltXA5inKFbDWV3a/M5c18dFzA2Xh21Q46XZezmtQ9Tg==", - "dev": true, - "optional": true - }, - "@swc/core-linux-arm-gnueabihf": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.84.tgz", - "integrity": "sha512-dmt/ECQrp3ZPWnK27p4E4xRIRHOoJhgGvxC5t5YaWzN20KcxE9ykEY2oLGSoeceM/A+4D11aRYGwF/EM7yOkvA==", - "dev": true, - "optional": true - }, - "@swc/core-linux-arm64-gnu": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.84.tgz", - "integrity": "sha512-PgVfrI3NVg2z/oeg3GWLb9rFLMqidbdPwVH5nRyHVP2RX/BWP6qfnYfG+gJv4qrKzIldb9TyCGH7y8VWctKLxw==", - "dev": true, - "optional": true - }, - "@swc/core-linux-arm64-musl": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.84.tgz", - "integrity": "sha512-hcuEa8/vin4Ns0P+FpcDHQ4f3jmhgGKQhqw0w+TovPSVTIXr+nrFQ2AGhs9nAxS6tSQ77C53Eb5YRpK8ToFo1A==", - "dev": true, - "optional": true - }, - "@swc/core-linux-x64-gnu": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.84.tgz", - "integrity": "sha512-IvyimSbwGdu21jBBEqR1Up8Jhvl8kIAf1k3e5Oy8oRfgojdUfmW1EIwgGdoUeyQ1VHlfquiWaRGfsnHQUKl35g==", - "dev": true, - "optional": true - }, - "@swc/core-linux-x64-musl": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.84.tgz", - "integrity": "sha512-hdgVU/O5ufDCe+p5RtCjU7PRNwd0WM+eWJS+GNY4QWL6O8y2VLM+i4+6YzwSUjeBk0xd+1YElMxbqz7r5tSZhw==", - "dev": true, - "optional": true - }, - "@swc/core-win32-arm64-msvc": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.84.tgz", - "integrity": "sha512-rzH6k2BF0BFOFhUTD+bh0oCiUCZjFfDfoZoYNN/CM0qbtjAcFH21hzMh/EH8ZaXq8k/iQmUNNa5MPNPZ4SOMNw==", - "dev": true, - "optional": true - }, - "@swc/core-win32-ia32-msvc": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.84.tgz", - "integrity": "sha512-Y+Dk7VLLVwwsAzoDmjkNW/sTmSPl9PGr4Mj1nhc5A2NNxZ+hz4SxFMclacDI03SC5ikK8Qh6WOoE/+nwUDa3uA==", - "dev": true, - "optional": true - }, - "@swc/core-win32-x64-msvc": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.84.tgz", - "integrity": "sha512-WmpaosqCWMX7DArLdU8AJcj96hy0PKlYh1DaMVikSrrDHbJm2dZ8rd27IK3qUB8DgPkrDYHmLAKNZ+z3gWXgRQ==", - "dev": true, - "optional": true - }, - "@swc/jest": { - "version": "0.2.29", - "resolved": "https://registry.npmjs.org/@swc/jest/-/jest-0.2.29.tgz", - "integrity": "sha512-8reh5RvHBsSikDC3WGCd5ZTd2BXKkyOdK7QwynrCH58jk2cQFhhHhFBg/jvnWZehUQe/EoOImLENc9/DwbBFow==", - "dev": true, - "requires": { - "@jest/create-cache-key-function": "^27.4.2", - "jsonc-parser": "^3.2.0" - } - }, - "@swc/types": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.4.tgz", - "integrity": "sha512-z/G02d+59gyyUb7KYhKi9jOhicek6QD2oMaotUyG+lUkybpXoV49dY9bj7Ah5Q+y7knK2jU67UTX9FyfGzaxQg==", - "dev": true - }, - "@testing-library/dom": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz", - "integrity": "sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "^5.0.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.4.4", - "pretty-format": "^27.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, - "requires": { - "deep-equal": "^2.0.5" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "requires": { - "ansi-regex": "5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@testing-library/jest-dom": { - "version": "5.16.5", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", - "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", - "dev": true, - "requires": { - "@adobe/css-tools": "^4.0.1", - "@babel/runtime": "^7.9.2", - "@types/testing-library__jest-dom": "^5.9.1", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", - "redent": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, - "requires": { - "deep-equal": "^2.0.5" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@testing-library/react": { - "version": "12.1.5", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.5.tgz", - "integrity": "sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^8.0.0", - "@types/react-dom": "<18.0.0" - }, - "dependencies": { - "@types/react-dom": { - "version": "17.0.19", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.19.tgz", - "integrity": "sha512-PiYG40pnQRdPHnlf7tZnp0aQ6q9tspYr72vD61saO6zFCybLfMqwUCN0va1/P+86DXn18ZWeW30Bk7xlC5eEAQ==", - "dev": true, - "requires": { - "@types/react": "^17" - } - } - } - }, - "@testing-library/react-hooks": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-7.0.2.tgz", - "integrity": "sha512-dYxpz8u9m4q1TuzfcUApqi8iFfR6R0FaMbr2hjZJy1uC8z+bO/K4v8Gs9eogGKYQop7QsrBTFkv/BCF7MzD2Cg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.12.5", - "@types/react": ">=16.9.0", - "@types/react-dom": ">=16.9.0", - "@types/react-test-renderer": ">=16.9.0", - "react-error-boundary": "^3.1.0" - } - }, - "@testing-library/user-event": { - "version": "14.4.3", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.4.3.tgz", - "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==", - "dev": true, - "requires": {} - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true - }, - "@types/aria-query": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", - "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==", - "dev": true - }, - "@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", - "dev": true, - "requires": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", - "dev": true, - "requires": { - "@babel/types": "^7.3.0" - } - }, - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/bonjour": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", - "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect-history-api-fallback": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", - "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", - "dev": true, - "requires": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "@types/eslint": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", - "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", - "dev": true - }, - "@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true - }, - "@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/hoist-non-react-statics": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", - "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", - "dev": true, - "requires": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, - "@types/http-proxy": { - "version": "1.17.8", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", - "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg==", - "dev": true, - "requires": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "@types/jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" - }, - "dependencies": { - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true - }, - "parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "requires": { - "entities": "^4.4.0" - } - } - } - }, - "@types/json-schema": { - "version": "7.0.10", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.10.tgz", - "integrity": "sha512-BLO9bBq59vW3fxCpD4o0N4U+DXsvwvIcl+jofw0frQo/GrBFC+/jRZj1E7kgp6dvTyNmA4y6JCV5Id/r3mNP5A==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "@types/lodash": { - "version": "4.14.180", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.180.tgz", - "integrity": "sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g==", - "dev": true - }, - "@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "dev": true - }, - "@types/node": { - "version": "17.0.23", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", - "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", - "dev": true - }, - "@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "@types/prop-types": { - "version": "15.7.4", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", - "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", - "dev": true - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "@types/raf": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.0.tgz", - "integrity": "sha512-taW5/WYqo36N7V39oYyHP9Ipfd5pNFvGTIQsNGj86xV88YQ7GnI30/yMfKDF7Zgin0m3e+ikX88FvImnK4RjGw==", - "dev": true - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true - }, - "@types/react": { - "version": "17.0.42", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.42.tgz", - "integrity": "sha512-nuab3x3CpJ7VFeNA+3HTUuEkvClYHXqWtWd7Ud6AZYW7Z3NH9WKtgU+tFB0ZLcHq+niB/HnzLcaZPqMJ95+k5Q==", - "dev": true, - "requires": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - }, - "dependencies": { - "csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true - } - } - }, - "@types/react-dom": { - "version": "18.0.11", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", - "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, - "@types/react-redux": { - "version": "7.1.23", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.23.tgz", - "integrity": "sha512-D02o3FPfqQlfu2WeEYwh3x2otYd2Dk1o8wAfsA0B1C2AJEFxE663Ozu7JzuWbznGgW248NaOF6wsqCGNq9d3qw==", - "dev": true, - "requires": { - "@types/hoist-non-react-statics": "^3.3.0", - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0", - "redux": "^4.0.0" - } - }, - "@types/react-test-renderer": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-17.0.1.tgz", - "integrity": "sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, - "@types/react-transition-group": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.4.tgz", - "integrity": "sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, - "@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/retry": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", - "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", - "dev": true - }, - "@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", - "dev": true - }, - "@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true - }, - "@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", - "dev": true, - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "@types/styled-jsx": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/@types/styled-jsx/-/styled-jsx-2.2.9.tgz", - "integrity": "sha512-W/iTlIkGEyTBGTEvZCey8EgQlQ5l0DwMqi3iOXlLs2kyBwYTXHKEiU6IZ5EwoRwngL8/dGYuzezSup89ttVHLw==", - "dev": true, - "requires": { - "@types/react": "*" - } - }, - "@types/testing-library__jest-dom": { - "version": "5.14.5", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz", - "integrity": "sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==", - "dev": true, - "requires": { - "@types/jest": "*" - } - }, - "@types/tough-cookie": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", - "dev": true - }, - "@types/trusted-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", - "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==", - "dev": true - }, - "@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "@typescript-eslint/experimental-utils": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz", - "integrity": "sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/types": "3.10.1", - "@typescript-eslint/typescript-estree": "3.10.1", - "eslint-scope": "^5.0.0", - "eslint-utils": "^2.0.0" - }, - "dependencies": { - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "@typescript-eslint/parser": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz", - "integrity": "sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==", - "dev": true, - "requires": { - "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "3.10.1", - "@typescript-eslint/types": "3.10.1", - "@typescript-eslint/typescript-estree": "3.10.1", - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", - "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0" - }, - "dependencies": { - "@typescript-eslint/types": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", - "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", - "dev": true - }, - "@typescript-eslint/visitor-keys": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", - "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.59.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "eslint-visitor-keys": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", - "dev": true - } - } - }, - "@typescript-eslint/types": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.10.1.tgz", - "integrity": "sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz", - "integrity": "sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "3.10.1", - "@typescript-eslint/visitor-keys": "3.10.1", - "debug": "^4.1.1", - "glob": "^7.1.6", - "is-glob": "^4.0.1", - "lodash": "^4.17.15", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - }, - "dependencies": { - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/utils": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.0.tgz", - "integrity": "sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/typescript-estree": "5.59.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "dependencies": { - "@typescript-eslint/types": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", - "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", - "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", - "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.59.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", - "dev": true - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/visitor-keys": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz", - "integrity": "sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-cli/configtest": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz", - "integrity": "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==", - "dev": true, - "requires": {} - }, - "@webpack-cli/info": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz", - "integrity": "sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA==", - "dev": true, - "requires": { - "envinfo": "^7.7.3" - } - }, - "@webpack-cli/serve": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz", - "integrity": "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==", - "dev": true, - "requires": {} - }, - "@welldone-software/why-did-you-render": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@welldone-software/why-did-you-render/-/why-did-you-render-6.2.3.tgz", - "integrity": "sha512-FQgi90jvC9uw2aALlonJfqaWOvU5UUBBVvdAnS2iryXwCc4YJkKsPJY5Y/LzaND3OIyk8XGUn1vTRn6hcem28Q==", - "requires": { - "lodash": "^4" - } - }, - "@wojtekmaj/enzyme-adapter-react-17": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@wojtekmaj/enzyme-adapter-react-17/-/enzyme-adapter-react-17-0.4.1.tgz", - "integrity": "sha512-WZr8i4C6WVDV7Mb8sbm7GdlEPmk1f+xOMjUKThqrkWgwsfvu90zJyyX54wyAvsS91sjtKZ0JipGj2cJnEDaxPA==", - "dev": true, - "requires": { - "enzyme-adapter-utils": "^1.14.0", - "enzyme-shallow-equal": "^1.0.4", - "has": "^1.0.3", - "object.assign": "^4.1.0", - "object.values": "^1.1.1", - "prop-types": "^15.7.2", - "react-is": "^17.0.0", - "react-test-renderer": "^17.0.0", - "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true - }, - "acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - } - } - }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - }, - "ad-bs-converter": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/ad-bs-converter/-/ad-bs-converter-0.5.0.tgz", - "integrity": "sha1-hM2BwqME0DR3wwl7Iw66IaFPoZQ=", - "dev": true, - "requires": { - "get-nepali-number": "^0.1.0", - "get-nepday-of-week": "^0.1.4" - } - }, - "add": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/add/-/add-2.0.6.tgz", - "integrity": "sha1-JI8Kn25aUo7yKV2+7DBTITCuIjU=", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } - } - }, - "ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "append-transform": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", - "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", - "dev": true, - "requires": { - "default-require-extensions": "^2.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - } - }, - "array-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", - "dev": true - }, - "array-includes": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", - "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.7" - } - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array.prototype.filter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.1.tgz", - "integrity": "sha512-Dk3Ty7N42Odk7PjU/Ci3zT4pLj20YvuVnneG/58ICM6bt4Ij5kZaJTVQ9TSaWaIECX2sFyz4KItkVZqHNnciqw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - } - }, - "array.prototype.find": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.1.2.tgz", - "integrity": "sha512-00S1O4ewO95OmmJW7EesWfQlrCrLEL8kZ40w3+GkLX2yTt0m2ggcePPa2uHPJ9KUmJvwRq+lCV9bD8Yim23x/Q==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0" - } - }, - "array.prototype.flat": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", - "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0" - } - }, - "array.prototype.flatmap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz", - "integrity": "sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0" - } - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true - }, - "assert-never": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.2.1.tgz", - "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "autoprefixer": { - "version": "10.4.4", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.4.tgz", - "integrity": "sha512-Tm8JxsB286VweiZ5F0anmbyGiNI3v3wGv3mz9W+cxEDYB/6jbnj6GM9H9mK3wIL8ftgl+C07Lcwb8PG5PCCPzA==", - "dev": true, - "requires": { - "browserslist": "^4.20.2", - "caniuse-lite": "^1.0.30001317", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - } - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true - }, - "axe-core": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.1.tgz", - "integrity": "sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==", - "dev": true - }, - "axobject-query": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", - "dev": true - }, - "babel-eslint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", - "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0", - "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "babel-helper-builder-react-jsx": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", - "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "esutils": "^2.0.2" - } - }, - "babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "requires": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "babel-loader": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.4.tgz", - "integrity": "sha512-8dytA3gcvPPPv4Grjhnt8b5IIiTcq/zeXOPk4iTYI0SVXcsmuGg7JtBRDp8S9X+gJfhQ8ektjXZlDu1Bb33U8A==", - "dev": true, - "requires": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" - }, - "dependencies": { - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - } - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, - "babel-plugin-emotion": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.2.2.tgz", - "integrity": "sha512-SMSkGoqTbTyUTDeuVuPIWifPdUGkTk1Kf9BWRiXIOIcuyMfsdp2EjeiiFvOzX8NOBvEh/ypKYvUh2rkgAJMCLA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@emotion/hash": "0.8.0", - "@emotion/memoize": "0.7.4", - "@emotion/serialize": "^0.11.16", - "babel-plugin-macros": "^2.0.0", - "babel-plugin-syntax-jsx": "^6.18.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^1.0.5", - "find-root": "^1.1.0", - "source-map": "^0.5.7" - }, - "dependencies": { - "babel-plugin-macros": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", - "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "cosmiconfig": "^6.0.0", - "resolve": "^1.12.0" - } - }, - "cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - } - } - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "dependencies": { - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - } - } - }, - "babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" - } - }, - "babel-plugin-module-resolver": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.0.tgz", - "integrity": "sha512-g0u+/ChLSJ5+PzYwLwP8Rp8Rcfowz58TJNCe+L/ui4rpzE/mg//JVX0EWBUYoxaextqnwuGHzfGp2hh0PPV25Q==", - "dev": true, - "requires": { - "find-babel-config": "^2.0.0", - "glob": "^8.0.3", - "pkg-up": "^3.1.0", - "reselect": "^4.1.7", - "resolve": "^1.22.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "babel-plugin-polyfill-corejs2": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", - "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-define-polyfill-provider": "^0.3.3", - "semver": "^6.1.1" - } - }, - "babel-plugin-polyfill-corejs3": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", - "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.1", - "core-js-compat": "^3.21.0" - } - }, - "babel-plugin-polyfill-regenerator": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", - "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.1" - } - }, - "babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", - "dev": true - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true - }, - "babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true, - "requires": { - "babel-plugin-syntax-flow": "^6.18.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-display-name": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-jsx": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true, - "requires": { - "babel-helper-builder-react-jsx": "^6.24.1", - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-jsx-self": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-jsx-source": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-remove-prop-types": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", - "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==", - "dev": true - }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - } - }, - "babel-preset-flow": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", - "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true, - "requires": { - "babel-plugin-transform-flow-strip-types": "^6.22.0" - } - }, - "babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "babel-preset-react": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", - "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.3.13", - "babel-plugin-transform-react-display-name": "^6.23.0", - "babel-plugin-transform-react-jsx": "^6.24.1", - "babel-plugin-transform-react-jsx-self": "^6.22.0", - "babel-plugin-transform-react-jsx-source": "^6.22.0", - "babel-preset-flow": "^6.23.0" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - }, - "dependencies": { - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - } - } - }, - "babel-walk": { - "version": "3.0.0-canary-5", - "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", - "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", - "dev": true, - "requires": { - "@babel/types": "^7.9.6" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", - "dev": true, - "optional": true - }, - "base64-arraybuffer-es6": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/base64-arraybuffer-es6/-/base64-arraybuffer-es6-0.7.0.tgz", - "integrity": "sha512-ESyU/U1CFZDJUdr+neHRhNozeCv72Y7Vm0m1DCbjX3KBjT6eYocvAJlSk6+8+HkVwXlT1FNxhGW6q3UKAlCvvw==", - "dev": true - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true - }, - "before-build-webpack": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/before-build-webpack/-/before-build-webpack-0.2.12.tgz", - "integrity": "sha512-k91crmYKGUiKNRVa6sbP5jVD1m8c2Atjt9UIlVrjOla5kKPe96g1m45J98peZbImOtUCFZCSkT4fr5HNfK/Vew==", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "bikram-sambat-js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bikram-sambat-js/-/bikram-sambat-js-1.0.1.tgz", - "integrity": "sha512-d1hdHN0F2BdlJYzT866/FTHX7G+rsJ5AKggJlch4lU1kL7o6AVnbaeJ9JrEUusRwAM4vQhXmCEtPRRCrdnuPRA==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "blamer": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/blamer/-/blamer-1.0.6.tgz", - "integrity": "sha512-fv7QToPS87oD1m1bDDTf29zC/bVKJxj2Nqh1r/v4NhMtbnzDIbWOHBYIfxCjlmkVGu3FGOjKgdNG3SFm7TkvBQ==", - "dev": true, - "requires": { - "execa": "^4.0.0", - "which": "^2.0.2" - } - }, - "blueimp-md5": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", - "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", - "dev": true - }, - "body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", - "dev": true - } - } - }, - "bonjour-service": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", - "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "requires": { - "node-int64": "^0.4.0" - } - }, - "btoa": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", - "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", - "dev": true - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "builtin-modules": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", - "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", - "dev": true - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - }, - "caching-transform": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", - "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", - "dev": true, - "requires": { - "hasha": "^3.0.0", - "make-dir": "^2.0.0", - "package-hash": "^3.0.0", - "write-file-atomic": "^2.4.2" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001474", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001474.tgz", - "integrity": "sha512-iaIZ8gVrWfemh5DG3T9/YqarVZoYf0r188IjaGwx68j4Pf0SGY6CQkmJUIE+NZHkkecQGohzXmBGEwWDr9aM3Q==", - "dev": true - }, - "canvg": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", - "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", - "dev": true, - "requires": { - "@babel/runtime": "^7.12.5", - "@types/raf": "^3.4.0", - "core-js": "^3.8.3", - "raf": "^3.4.1", - "regenerator-runtime": "^0.13.7", - "rgbcolor": "^1.0.1", - "stackblur-canvas": "^2.0.0", - "svg-pathdata": "^6.0.3" - }, - "dependencies": { - "core-js": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", - "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==", - "dev": true - } - } - }, - "chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - } - }, - "chai-immutable": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chai-immutable/-/chai-immutable-2.1.0.tgz", - "integrity": "sha512-IQrtwbwQYn2tkw/BOL+xYhJMcwuil1w0dzv9nZqi/w+jdQhdAn9rDyJb3qK+LvZkctJqdvy6opALGFZcdriW7A==", - "dev": true, - "requires": {} - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "character-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", - "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", - "dev": true, - "requires": { - "is-regex": "^1.0.3" - } - }, - "chart.js": { - "version": "2.9.4", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz", - "integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==", - "dev": true, - "requires": { - "chartjs-color": "^2.1.0", - "moment": "^2.10.2" - } - }, - "chartjs-color": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", - "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", - "dev": true, - "requires": { - "chartjs-color-string": "^0.6.0", - "color-convert": "^1.9.3" - } - }, - "chartjs-color-string": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", - "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", - "dev": true, - "requires": { - "color-name": "^1.0.0" - } - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "requires": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - } - }, - "cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "requires": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true - }, - "ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true - }, - "cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true - }, - "clean-webpack-plugin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-4.0.0.tgz", - "integrity": "sha512-WuWE1nyTNAyW5T7oNyys2EN0cfP2fdRxhxnIQWiAp0bMabPdHhoGxM8A6YL2GhqwgrPnnaemVE7nv5XJ2Fhh2w==", - "dev": true, - "requires": { - "del": "^4.1.1" - } - }, - "cli-table3": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz", - "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==", - "dev": true, - "requires": { - "colors": "1.4.0", - "string-width": "^4.2.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "clsx": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", - "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", - "dev": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true - }, - "collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - }, - "dependencies": { - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - } - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "colorette": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", - "dev": true - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true - }, - "common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "compression-webpack-plugin": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-9.2.0.tgz", - "integrity": "sha512-R/Oi+2+UHotGfu72fJiRoVpuRifZT0tTC6UqFD/DUo+mv8dbOow9rVOuTvDv5nPPm3GZhHL/fKkwxwIHnJ8Nyw==", - "dev": true, - "requires": { - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", - "dev": true - }, - "connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true - }, - "connected-react-router": { - "version": "6.9.2", - "resolved": "https://registry.npmjs.org/connected-react-router/-/connected-react-router-6.9.2.tgz", - "integrity": "sha512-bE8kNBiZv9Mivp7pYn9JvLH5ItTjLl45kk1/Vha0rmAK9I/ETb5JPJrAm0h2KCG9qLfv7vqU3Jo4UUDo0oJnQg==", - "dev": true, - "requires": { - "immutable": "4.0.0-rc.12", - "lodash.isequalwith": "^4.4.0", - "prop-types": "^15.7.2", - "seamless-immutable": "^7.1.3" - }, - "dependencies": { - "immutable": { - "version": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", - "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", - "dev": true, - "optional": true - } - } - }, - "constantinople": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", - "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==", - "dev": true, - "requires": { - "@babel/parser": "^7.6.0", - "@babel/types": "^7.6.1" - } - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "requires": { - "safe-buffer": "5.2.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, - "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "core-js": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.6.tgz", - "integrity": "sha512-u4oM8SHwmDuh5mWZdDg9UwNVq5s1uqq6ZDLLIs07VY+VJU91i3h4f3K/pgFvtUQPGdeStrZ+odKyfyt4EnKHfA==", - "dev": true - }, - "core-js-compat": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.30.0.tgz", - "integrity": "sha512-P5A2h/9mRYZFIAP+5Ab8ns6083IyVpSclU74UNvbGVQ8VM7n3n3/g2yF3AkKQ9NXz2O+ioxLbEWKnDtgsFamhg==", - "dev": true, - "requires": { - "browserslist": "^4.21.5" - } - }, - "core-js-pure": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz", - "integrity": "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ==", - "dev": true - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - } - }, - "cp-file": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", - "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "make-dir": "^2.0.0", - "nested-error-stacks": "^2.0.0", - "pify": "^4.0.1", - "safe-buffer": "^5.0.1" - } - }, - "create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true - }, - "css-blank-pseudo": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", - "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "css-box-model": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", - "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", - "dev": true, - "requires": { - "tiny-invariant": "^1.0.6" - } - }, - "css-element-queries": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/css-element-queries/-/css-element-queries-1.2.3.tgz", - "integrity": "sha512-QK9uovYmKTsV2GXWQiMOByVNrLn2qz6m3P7vWpOR4IdD6I3iXoDw5qtgJEN3Xq7gIbdHVKvzHjdAtcl+4Arc4Q==", - "dev": true - }, - "css-has-pseudo": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", - "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "css-line-break": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", - "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", - "dev": true, - "optional": true, - "requires": { - "utrie": "^1.0.2" - } - }, - "css-loader": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", - "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", - "dev": true, - "requires": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.7", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.5" - }, - "dependencies": { - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "css-prefers-color-scheme": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", - "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", - "dev": true, - "requires": {} - }, - "css-select": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", - "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^5.1.0", - "domhandler": "^4.3.0", - "domutils": "^2.8.0", - "nth-check": "2.0.1" - } - }, - "css-vendor": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", - "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.3", - "is-in-browser": "^1.0.2" - } - }, - "css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", - "dev": true - }, - "css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", - "dev": true - }, - "cssdb": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-6.5.0.tgz", - "integrity": "sha512-Rh7AAopF2ckPXe/VBcoUS9JrCZNSyc60+KpgE6X25vpVxA32TmiqvExjkfhwP4wGSb6Xe8Z/JIyGqwgx/zZYFA==", - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "requires": { - "css-tree": "^1.1.2" - }, - "dependencies": { - "css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "requires": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - } - }, - "mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } - } - }, - "csstype": { - "version": "2.6.20", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", - "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==", - "dev": true - }, - "damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true - }, - "data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "requires": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - } - }, - "date-fns": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.1.0.tgz", - "integrity": "sha512-eKeLk3sLCnxB/0PN4t1+zqDtSs4jb4mXRSTZ2okmx/myfWyDqeO4r5nnmA5LClJiCwpuTMeK2v5UQPuE4uMaxA==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - }, - "decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true - }, - "dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "requires": {} - }, - "deep-diff": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", - "integrity": "sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ=", - "dev": true - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true - }, - "default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "requires": { - "execa": "^5.0.0" - }, - "dependencies": { - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - } - } - }, - "default-require-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", - "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", - "dev": true, - "requires": { - "strip-bom": "^3.0.0" - } - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true - }, - "define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dev": true, - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=", - "dev": true - }, - "dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "dnd-core": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-11.1.3.tgz", - "integrity": "sha512-QugF55dNW+h+vzxVJ/LSJeTeUw9MCJ2cllhmVThVPEtF16ooBkxj0WBE5RB+AceFxMFo1rO6bJKXtqKl+JNnyA==", - "dev": true, - "requires": { - "@react-dnd/asap": "^4.0.0", - "@react-dnd/invariant": "^2.0.0", - "redux": "^4.0.4" - } - }, - "dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, - "requires": { - "@leichtgewicht/ip-codec": "^2.0.1" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "doctypes": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", - "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=", - "dev": true - }, - "dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true - }, - "dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - }, - "dependencies": { - "csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true - } - } - }, - "dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "dom-to-image-more": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/dom-to-image-more/-/dom-to-image-more-2.8.0.tgz", - "integrity": "sha512-YqlHI1i+TMuaKwkFRO5oDPjC3eWf+6Hln9rHZcnFYvmoXwCrGZmZ7BYXBJOjw5utYg2Lp+QF9YO96F7CsDC4eQ==", - "dev": true - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, - "domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "requires": { - "webidl-conversions": "^5.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } - } - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "dompurify": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.6.tgz", - "integrity": "sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==", - "dev": true - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "ejs": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.7.tgz", - "integrity": "sha512-BIar7R6abbUxDA3bfXrO4DSgwo8I+fB5/1zgujl3HLLjwd6+9iOnrT+t3grn2qbk9vOgBubXOFwX2m9axoFaGw==", - "dev": true, - "requires": { - "jake": "^10.8.5" - } - }, - "electron-to-chromium": { - "version": "1.4.351", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.351.tgz", - "integrity": "sha512-W35n4jAsyj6OZGxeWe+gA6+2Md4jDO19fzfsRKEt3DBwIdlVTT8O9Uv8ojgUAoQeXASdgG9zMU+8n8Xg/W6dRQ==", - "dev": true - }, - "emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - }, - "envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", - "dev": true - }, - "enzyme": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", - "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", - "dev": true, - "requires": { - "array.prototype.flat": "^1.2.3", - "cheerio": "^1.0.0-rc.3", - "enzyme-shallow-equal": "^1.0.1", - "function.prototype.name": "^1.1.2", - "has": "^1.0.3", - "html-element-map": "^1.2.0", - "is-boolean-object": "^1.0.1", - "is-callable": "^1.1.5", - "is-number-object": "^1.0.4", - "is-regex": "^1.0.5", - "is-string": "^1.0.5", - "is-subset": "^0.1.1", - "lodash.escape": "^4.0.1", - "lodash.isequal": "^4.5.0", - "object-inspect": "^1.7.0", - "object-is": "^1.0.2", - "object.assign": "^4.1.0", - "object.entries": "^1.1.1", - "object.values": "^1.1.1", - "raf": "^3.4.1", - "rst-selector-parser": "^2.2.3", - "string.prototype.trim": "^1.2.1" - } - }, - "enzyme-adapter-utils": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.14.0.tgz", - "integrity": "sha512-F/z/7SeLt+reKFcb7597IThpDp0bmzcH1E9Oabqv+o01cID2/YInlqHbFl7HzWBl4h3OdZYedtwNDOmSKkk0bg==", - "dev": true, - "requires": { - "airbnb-prop-types": "^2.16.0", - "function.prototype.name": "^1.1.3", - "has": "^1.0.3", - "object.assign": "^4.1.2", - "object.fromentries": "^2.0.3", - "prop-types": "^15.7.2", - "semver": "^5.7.1" - }, - "dependencies": { - "airbnb-prop-types": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.16.0.tgz", - "integrity": "sha512-7WHOFolP/6cS96PhKNrslCLMYAI8yB1Pp6u6XmxozQOiZbsI5ycglZr5cHhBFfuRcQQjzCMith5ZPZdYiJCxUg==", - "dev": true, - "requires": { - "array.prototype.find": "^2.1.1", - "function.prototype.name": "^1.1.2", - "is-regex": "^1.1.0", - "object-is": "^1.1.2", - "object.assign": "^4.1.0", - "object.entries": "^1.1.2", - "prop-types": "^15.7.2", - "prop-types-exact": "^1.2.0", - "react-is": "^16.13.1" - } - }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "enzyme-shallow-equal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.4.tgz", - "integrity": "sha512-MttIwB8kKxypwHvRynuC3ahyNc+cFbR8mjVIltnmzQ0uKGqmsfO4bfBuLxb0beLNPhjblUEYvEbsg+VSygvF1Q==", - "dev": true, - "requires": { - "has": "^1.0.3", - "object-is": "^1.1.2" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", - "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - } - }, - "es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, - "es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - } - } - }, - "es-module-lexer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", - "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==", - "dev": true - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true - }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - } - } - }, - "eslint": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", - "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.2.1", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "globals": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "eslint-config-airbnb": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", - "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", - "dev": true, - "requires": { - "eslint-config-airbnb-base": "^15.0.0", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5" - } - }, - "eslint-config-airbnb-base": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", - "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", - "dev": true, - "requires": { - "confusing-browser-globals": "^1.0.10", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5", - "semver": "^6.3.0" - } - }, - "eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "requires": {} - }, - "eslint-import-resolver-alias": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz", - "integrity": "sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==", - "dev": true, - "requires": {} - }, - "eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", - "dev": true, - "requires": { - "debug": "^3.2.7", - "resolve": "^1.20.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-module-utils": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", - "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", - "dev": true, - "requires": { - "debug": "^3.2.7", - "find-up": "^2.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-plugin-import": { - "version": "2.25.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", - "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", - "dev": true, - "requires": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.2", - "has": "^1.0.3", - "is-core-module": "^2.8.0", - "is-glob": "^4.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.5", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.12.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-plugin-jest": { - "version": "27.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz", - "integrity": "sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==", - "dev": true, - "requires": { - "@typescript-eslint/utils": "^5.10.0" - } - }, - "eslint-plugin-jsx-a11y": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz", - "integrity": "sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==", - "dev": true, - "requires": { - "@babel/runtime": "^7.16.3", - "aria-query": "^4.2.2", - "array-includes": "^3.1.4", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.3.5", - "axobject-query": "^2.2.0", - "damerau-levenshtein": "^1.0.7", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.2.1", - "language-tags": "^1.0.5", - "minimatch": "^3.0.4" - } - }, - "eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-plugin-react": { - "version": "7.29.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.29.4.tgz", - "integrity": "sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ==", - "dev": true, - "requires": { - "array-includes": "^3.1.4", - "array.prototype.flatmap": "^1.2.5", - "doctrine": "^2.1.0", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.5", - "object.fromentries": "^2.0.5", - "object.hasown": "^1.1.0", - "object.values": "^1.1.5", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.3", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.6" - }, - "dependencies": { - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "resolve": { - "version": "2.0.0-next.3", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz", - "integrity": "sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q==", - "dev": true, - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - } - } - }, - "eslint-plugin-react-hooks": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz", - "integrity": "sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==", - "dev": true, - "requires": {} - }, - "eslint-plugin-unused-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz", - "integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==", - "dev": true, - "requires": { - "eslint-rule-composer": "^0.3.0" - } - }, - "eslint-rule-composer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", - "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", - "dev": true - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "dependencies": { - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - } - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - }, - "espree": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", - "dev": true, - "requires": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true - }, - "expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "requires": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", - "dev": true, - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.19.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.7", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", - "dev": true - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "fake-indexeddb": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/fake-indexeddb/-/fake-indexeddb-3.1.8.tgz", - "integrity": "sha512-7umIgcdnDfNcjw0ZaoD6yR2BflngKmPsyzZC+sV2fdttwz5bH6B6CCaNzzD+MURfRg8pvr/aL0trfNx65FLiDg==", - "dev": true, - "requires": { - "realistic-structured-clone": "^2.0.1" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "requires": { - "bser": "2.1.1" - } - }, - "fflate": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", - "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==", - "dev": true - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", - "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", - "dev": true, - "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "filelist": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.3.tgz", - "integrity": "sha512-LwjCsruLWQULGYKy7TX0OPtrL9kLpojOFKc5VCTxdFTV7w5zbsgqVKfnkKG7Qgjtq50gKfO56hJv88OfcGb70Q==", - "dev": true, - "requires": { - "minimatch": "^5.0.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "find-babel-config": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-2.0.0.tgz", - "integrity": "sha512-dOKT7jvF3hGzlW60Gc3ONox/0rRZ/tz7WCil0bqA1In/3I8f1BctpXahRnEKDySZqci7u+dqq93sZST9fOJpFw==", - "dev": true, - "requires": { - "json5": "^2.1.1", - "path-exists": "^4.0.0" - }, - "dependencies": { - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - } - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", - "dev": true - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "requires": { - "is-callable": "^1.1.3" - } - }, - "foreground-child": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", - "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", - "dev": true, - "requires": { - "cross-spawn": "^4", - "signal-exit": "^3.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - } - }, - "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "formik": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/formik/-/formik-2.2.9.tgz", - "integrity": "sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==", - "dev": true, - "requires": { - "deepmerge": "^2.1.1", - "hoist-non-react-statics": "^3.3.0", - "lodash": "^4.17.21", - "lodash-es": "^4.17.21", - "react-fast-compare": "^2.0.1", - "tiny-warning": "^1.0.2", - "tslib": "^1.10.0" - }, - "dependencies": { - "deepmerge": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "formik-material-ui": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/formik-material-ui/-/formik-material-ui-3.0.1.tgz", - "integrity": "sha512-N8oxZIdhY70npRv86IfF6Zaaps9RL3a37XRdq02WDroB3XZC1mXs6lA/zQ09ZYFWYJp/UjI80SKVpVa/xJOJJA==", - "dev": true, - "requires": {} - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true - }, - "fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "dev": true - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "frontend-collective-react-dnd-scrollzone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/frontend-collective-react-dnd-scrollzone/-/frontend-collective-react-dnd-scrollzone-1.0.2.tgz", - "integrity": "sha512-me/D9PZJq9j/sjEjs/OPmm6V6nbaHbhgeQiwrWu0t35lhwAOKWc+QBzzKKcZQeboYTkgE8UvCD9el+5ANp+g5Q==", - "dev": true, - "requires": { - "hoist-non-react-statics": "^3.1.0", - "lodash.throttle": "^4.0.1", - "prop-types": "^15.5.9", - "raf": "^3.2.0", - "react": "^17.0.2", - "react-display-name": "^0.2.0", - "react-dom": "^17.0.2" - } - }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - } - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "functions-have-names": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.2.tgz", - "integrity": "sha512-bLgc3asbWdwPbx2mNk2S49kmJCuQeu0nfmaOgbs8WIyzzkw3r4htszdIi9Q9EMezDPTYuJx2wvjZ/EwgAthpnA==", - "dev": true - }, - "fuzzysort": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/fuzzysort/-/fuzzysort-2.0.4.tgz", - "integrity": "sha512-Api1mJL+Ad7W7vnDZnWq5pGaXJjyencT+iKGia2PlHUcSsSzWwIQ3S1isiMpwpavjYtGd2FzhUIhnnhOULZgDw==", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true - }, - "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "get-nepali-number": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-nepali-number/-/get-nepali-number-0.1.0.tgz", - "integrity": "sha1-stNwsrDuPAn3q9aTw0ZDlZLd70E=", - "dev": true - }, - "get-nepday-of-week": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/get-nepday-of-week/-/get-nepday-of-week-0.1.4.tgz", - "integrity": "sha1-+MeFaHkKJBMYtO8IeUVKEFpGIt4=", - "dev": true - }, - "get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", - "dev": true - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "gitignore-to-glob": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/gitignore-to-glob/-/gitignore-to-glob-0.3.0.tgz", - "integrity": "sha1-WfMqs9m2bOUCmcPtJMsO9CoJTOs=", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "glur": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/glur/-/glur-1.1.2.tgz", - "integrity": "sha1-8g6jbbEDv8KSNDkh8fkeg8NGdok=", - "dev": true - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "harmony-reflect": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", - "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "5.0.1" - } - }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "hasha": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", - "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", - "dev": true, - "requires": { - "is-stream": "^1.0.1" - }, - "dependencies": { - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - } - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", - "dev": true, - "requires": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" - } - }, - "hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dev": true, - "requires": { - "react-is": "^16.7.0" - }, - "dependencies": { - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - } - } - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "html-element-map": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.3.1.tgz", - "integrity": "sha512-6XMlxrAFX4UEEGxctfFnmrFaaZFNf9i5fNuV5wZ3WWQ4FVaNP1aX1LkX9j2mfEx1NpjeE/rL3nmgEn23GdFmrg==", - "dev": true, - "requires": { - "array.prototype.filter": "^1.0.0", - "call-bind": "^1.0.2" - } - }, - "html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.5" - } - }, - "html-entities": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", - "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "html2canvas": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", - "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", - "dev": true, - "optional": true, - "requires": { - "css-line-break": "^2.1.0", - "text-segmentation": "^1.0.3" - } - }, - "html2pdf-dom-to-image-more": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/html2pdf-dom-to-image-more/-/html2pdf-dom-to-image-more-0.9.5.tgz", - "integrity": "sha512-YPs4dLXzJqJorngNpVGEI+XazPEu7MjcXJMRk4YSVumhB6L8fNZOFTRGvZHkgTUmjkHrJ+g0iNq3Y2vA+o89Dw==", - "dev": true, - "requires": { - "dom-to-image-more": "2.8.0", - "es6-promise": "^4.2.8", - "jspdf": "^2.5.1" - } - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true - }, - "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - } - }, - "http-parser-js": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", - "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==", - "dev": true - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "http-proxy-middleware": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.4.tgz", - "integrity": "sha512-m/4FxX17SUvz4lJ5WPXOHDUuCwIqXLfLHs1s0uZ3oYjhoXlx9csYxaOa0ElDEJ+h8Q4iJ1s+lTMbiCa4EXIJqg==", - "dev": true, - "requires": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true - }, - "hyphenate-style-name": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", - "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==", - "dev": true - }, - "i18n-js": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/i18n-js/-/i18n-js-3.8.0.tgz", - "integrity": "sha512-hDsGgPuvw/2P+lXSbOafAwspK8Ste8YrwuuUg17W3wEcO1JkQxBlPgsN1t2+852nTnz4YSYTjZc/1nAA2PC/nw==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} - }, - "idb": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/idb/-/idb-4.0.5.tgz", - "integrity": "sha512-P+Fk9HT2h1DhXoE1YNK183SY+CRh2GHNh28de94sGwhe0bUA75JJeVJWt3SenE5p0BXK7maflIq29dl6UZHrFw==", - "dev": true - }, - "identity-obj-proxy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", - "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", - "dev": true, - "requires": { - "harmony-reflect": "^1.4.6" - } - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "image-blob-reduce": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/image-blob-reduce/-/image-blob-reduce-1.0.7.tgz", - "integrity": "sha512-sENh2BWeFjYv3mPutL/w6v/q5y6WLaobuzDMeXLB0X/XP4dLhyuBBlt3VXiM1pIp4E5z0qCAP26Va+XvCOHonA==", - "dev": true, - "requires": { - "pica": "^6.1.1" - } - }, - "immutable": { - "version": "4.0.0-rc.12", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz", - "integrity": "sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true - }, - "ipaddr.js": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", - "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", - "dev": true - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "dev": true - }, - "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true - }, - "is-expression": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz", - "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "object-assign": "^4.1.1" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - } - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-in-browser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", - "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=", - "dev": true - }, - "is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true - }, - "is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, - "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } - }, - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", - "dev": true - }, - "is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", - "dev": true - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - } - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", - "dev": true - }, - "istanbul-lib-hook": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", - "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", - "dev": true, - "requires": { - "append-transform": "^1.0.0" - } - }, - "istanbul-lib-instrument": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", - "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", - "dev": true, - "requires": { - "@babel/generator": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", - "istanbul-lib-coverage": "^2.0.5", - "semver": "^6.0.0" - } - }, - "istanbul-lib-report": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", - "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "supports-color": "^6.1.0" - }, - "dependencies": { - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", - "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "rimraf": "^2.6.3", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "istanbul-reports": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", - "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0" - } - }, - "jake": { - "version": "10.8.5", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", - "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", - "dev": true, - "requires": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "requires": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - } - }, - "jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "dev": true, - "requires": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "dependencies": { - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - } - } - }, - "jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "dev": true, - "requires": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", - "dev": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-environment-jsdom": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.5.0.tgz", - "integrity": "sha512-/KG8yEK4aN8ak56yFVdqFDzKNHgF4BAymCx2LbPNPsUshUlfAl0eX402Xm1pt+eoG9SLZEUVifqXtX8SK74KCw==", - "dev": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/jsdom": "^20.0.0", - "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0", - "jsdom": "^20.0.0" - }, - "dependencies": { - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - }, - "acorn-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", - "dev": true, - "requires": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2" - } - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - }, - "cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true - }, - "data-urls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "dev": true, - "requires": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" - } - }, - "domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, - "requires": { - "webidl-conversions": "^7.0.0" - } - }, - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "requires": { - "whatwg-encoding": "^2.0.0" - } - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "jsdom": { - "version": "20.0.3", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", - "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", - "dev": true, - "requires": { - "abab": "^2.0.6", - "acorn": "^8.8.1", - "acorn-globals": "^7.0.0", - "cssom": "^0.5.0", - "cssstyle": "^2.3.0", - "data-urls": "^3.0.2", - "decimal.js": "^10.4.2", - "domexception": "^4.0.0", - "escodegen": "^2.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.2", - "parse5": "^7.1.1", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0", - "ws": "^8.11.0", - "xml-name-validator": "^4.0.0" - } - }, - "parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "requires": { - "entities": "^4.4.0" - } - }, - "saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", - "dev": true, - "requires": { - "xml-name-validator": "^4.0.0" - } - }, - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true - }, - "whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "requires": { - "iconv-lite": "0.6.3" - } - }, - "whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true - }, - "whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "requires": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - } - }, - "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, - "requires": {} - }, - "xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true - } - } - }, - "jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "dev": true, - "requires": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, - "jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - } - }, - "jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "requires": {} - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "dev": true, - "requires": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - } - }, - "jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "dev": true, - "requires": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", - "dev": true, - "requires": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-stringify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", - "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jscpd": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/jscpd/-/jscpd-3.4.5.tgz", - "integrity": "sha512-2gAskcIpbnNTs0RgPZG72xBNa0eRR7mB121XApzbN7kkRUUue2ZT9ug7HMV1JZ01hIpJkrrchcDidMgnl6/DWA==", - "dev": true, - "requires": { - "@jscpd/core": "^3.4.5", - "@jscpd/finder": "^3.4.5", - "@jscpd/html-reporter": "^3.4.5", - "@jscpd/tokenizer": "^3.4.5", - "colors": "1.4.0", - "commander": "^5.0.0", - "fs-extra": "^9.1.0", - "gitignore-to-glob": "^0.3.0" - } - }, - "jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "requires": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - } - }, - "jsdom-global": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-3.0.2.tgz", - "integrity": "sha1-a9KZwTsMRiay2iwDk81DhdYGrLk=", - "dev": true, - "requires": {} - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "jsonpointer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.0.tgz", - "integrity": "sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==", - "dev": true - }, - "jspdf": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz", - "integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.14.0", - "atob": "^2.1.2", - "btoa": "^1.2.1", - "canvg": "^3.0.6", - "core-js": "^3.6.0", - "dompurify": "^2.2.0", - "fflate": "^0.4.8", - "html2canvas": "^1.0.0-rc.5" - }, - "dependencies": { - "core-js": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", - "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==", - "dev": true, - "optional": true - } - } - }, - "jss": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.8.2.tgz", - "integrity": "sha512-FkoUNxI329CKQ9OQC8L72MBF9KPf5q8mIupAJ5twU7G7XREW7ahb+7jFfrjZ4iy1qvhx1HwIWUIvkZBDnKkEdQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - }, - "dependencies": { - "csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true - } - } - }, - "jss-plugin-camel-case": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.9.0.tgz", - "integrity": "sha512-UH6uPpnDk413/r/2Olmw4+y54yEF2lRIV8XIZyuYpgPYTITLlPOsq6XB9qeqv+75SQSg3KLocq5jUBXW8qWWww==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "hyphenate-style-name": "^1.0.3", - "jss": "10.9.0" - }, - "dependencies": { - "csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true - }, - "jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - } - } - } - }, - "jss-plugin-default-unit": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.9.0.tgz", - "integrity": "sha512-7Ju4Q9wJ/MZPsxfu4T84mzdn7pLHWeqoGd/D8O3eDNNJ93Xc8PxnLmV8s8ZPNRYkLdxZqKtm1nPQ0BM4JRlq2w==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0" - }, - "dependencies": { - "csstype": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==", - "dev": true - }, - "jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - } - } - } - }, - "jss-plugin-extend": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/jss-plugin-extend/-/jss-plugin-extend-10.8.2.tgz", - "integrity": "sha512-NYu0cJ/Zb50ySPkegzbXQQfhXza0VpaRVXdXDex30yXqZpGcAdmhSg4HTv8vzHiL1v3uIOm641FYQX9WvLgSWw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.8.2", - "tiny-warning": "^1.0.2" - } - }, - "jss-plugin-global": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.9.0.tgz", - "integrity": "sha512-4G8PHNJ0x6nwAFsEzcuVDiBlyMsj2y3VjmFAx/uHk/R/gzJV+yRHICjT4MKGGu1cJq2hfowFWCyrr/Gg37FbgQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0" - }, - "dependencies": { - "csstype": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==", - "dev": true - }, - "jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - } - } - } - }, - "jss-plugin-nested": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.9.0.tgz", - "integrity": "sha512-2UJnDrfCZpMYcpPYR16oZB7VAC6b/1QLsRiAutOt7wJaaqwCBvNsosLEu/fUyKNQNGdvg2PPJFDO5AX7dwxtoA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "tiny-warning": "^1.0.2" - }, - "dependencies": { - "csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true - }, - "jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - } - } - } - }, - "jss-plugin-props-sort": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.9.0.tgz", - "integrity": "sha512-7A76HI8bzwqrsMOJTWKx/uD5v+U8piLnp5bvru7g/3ZEQOu1+PjHvv7bFdNO3DwNPC9oM0a//KwIJsIcDCjDzw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0" - }, - "dependencies": { - "csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true - }, - "jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - } - } - } - }, - "jss-plugin-rule-value-function": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.9.0.tgz", - "integrity": "sha512-IHJv6YrEf8pRzkY207cPmdbBstBaE+z8pazhPShfz0tZSDtRdQua5jjg6NMz3IbTasVx9FdnmptxPqSWL5tyJg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "tiny-warning": "^1.0.2" - }, - "dependencies": { - "csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true - }, - "jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - } - } - } - }, - "jss-plugin-vendor-prefixer": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.9.0.tgz", - "integrity": "sha512-MbvsaXP7iiVdYVSEoi+blrW+AYnTDvHTW6I6zqi7JcwXdc6I9Kbm234nEblayhF38EftoenbM+5218pidmC5gA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "css-vendor": "^2.0.8", - "jss": "10.9.0" - }, - "dependencies": { - "csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true - }, - "jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.0.tgz", - "integrity": "sha512-YpzpreB6kUunQBbrlArlsMpXYyndt9JATbt95tajx0t4MTJJcCJdd4hdNpHmOIDiUJrF/oX5wtVFrS3uofWfGw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - } - } - } - }, - "jss-rtl": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/jss-rtl/-/jss-rtl-0.3.0.tgz", - "integrity": "sha512-rg9jJmP1bAyhNOAp+BDZgOP/lMm4+oQ76qGueupDQ68Wq+G+6SGvCZvhIEg8OHSONRWOwFT6skCI+APGi8DgmA==", - "dev": true, - "requires": { - "rtl-css-js": "^1.13.1" - } - }, - "jstransformer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", - "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", - "dev": true, - "requires": { - "is-promise": "^2.0.0", - "promise": "^7.0.1" - } - }, - "jsx-ast-utils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz", - "integrity": "sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA==", - "dev": true, - "requires": { - "array-includes": "^3.1.3", - "object.assign": "^4.1.2" - } - }, - "just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "keyevent": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/keyevent/-/keyevent-1.1.0.tgz", - "integrity": "sha1-nA4BGKIv2D1NI/ZxOhBwE5HKYGA=", - "dev": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - }, - "klona": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", - "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", - "dev": true - }, - "language-subtag-registry": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", - "integrity": "sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==", - "dev": true - }, - "language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha1-0yHbxNowuovzAk4ED6XBRmH5GTo=", - "dev": true, - "requires": { - "language-subtag-registry": "~0.3.2" - } - }, - "launch-editor": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", - "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", - "dev": true, - "requires": { - "picocolors": "^1.0.0", - "shell-quote": "^1.8.1" - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", - "dev": true - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "lockfile": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz", - "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", - "dev": true, - "requires": { - "signal-exit": "^3.0.2" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", - "dev": true - }, - "lodash.assignwith": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz", - "integrity": "sha512-ZznplvbvtjK2gMvnQ1BR/zqPFZmS6jbK4p+6Up4xcRYA7yMIwxHCfbTcrYxXKzzqLsQ05eJPVznEW3tuwV7k1g==", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true - }, - "lodash.escape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", - "dev": true - }, - "lodash.find": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", - "integrity": "sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg==", - "dev": true - }, - "lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "lodash.has": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", - "integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI=", - "dev": true - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, - "lodash.isequalwith": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.isequalwith/-/lodash.isequalwith-4.4.0.tgz", - "integrity": "sha1-Jmcm3dUo+FTyH06pigZWBuD7xrA=", - "dev": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.isundefined": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", - "integrity": "sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true - }, - "lodash.throttle": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", - "dev": true - }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "loglevel": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", - "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", - "dev": true - }, - "loglevel-colored-level-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz", - "integrity": "sha1-akAhj9x64V/HbD0PPmdsRlOIYD4=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "loglevel": "^1.4.1" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "requires": { - "ansi-regex": "5.0.1" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true - } - } - }, - "lolex": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", - "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", - "dev": true - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", - "dev": true, - "requires": { - "get-func-name": "^2.0.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "dev": true - }, - "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.8" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "requires": { - "tmpl": "1.0.5" - } - }, - "markdown-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", - "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", - "dev": true, - "requires": { - "repeat-string": "^1.0.0" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "memfs": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", - "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", - "dev": true, - "requires": { - "fs-monkey": "1.0.3" - } - }, - "memoize-one": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", - "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", - "dev": true - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, - "mini-create-react-context": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", - "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.12.1", - "tiny-warning": "^1.0.3" - } - }, - "mini-css-extract-plugin": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.4.tgz", - "integrity": "sha512-UJ+aNuFQaQaECu7AamlWOBLj2cJ6XSGU4zNiqXeZ7lZLe5VD0DoSPWFbWArXueo+6FZVbgHzpX9lUIaBIDLuYg==", - "dev": true, - "requires": { - "schema-utils": "^3.1.0" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true - }, - "minimist-lite": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/minimist-lite/-/minimist-lite-2.2.1.tgz", - "integrity": "sha512-RSrWIRWGYoM2TDe102s7aIyeSipXMIXKb1fSHYx1tAbxAV0z4g2xR6ra3oPzkTqFb0EIUz1H3A/qvYYeDd+/qQ==", - "dev": true - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "1.2.7" - } - }, - "mocha": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", - "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", - "dev": true, - "requires": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.3", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "4.2.1", - "ms": "2.1.3", - "nanoid": "3.3.1", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.2.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "minimatch": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", - "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "dev": true - }, - "moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "mui-datatables": { - "version": "3.8.5", - "resolved": "https://registry.npmjs.org/mui-datatables/-/mui-datatables-3.8.5.tgz", - "integrity": "sha512-VS54Xkm5eXsPOUvzG3vXVjgSd2/nswwvhMK2D4PiHpV5MRJwfc6mdyuskh3s3jUi3NC8N+u7NsxX4pY14qaoKQ==", - "dev": true, - "requires": { - "@babel/runtime-corejs3": "^7.12.1", - "clsx": "^1.1.1", - "lodash.assignwith": "^4.2.0", - "lodash.clonedeep": "^4.5.0", - "lodash.debounce": "^4.0.8", - "lodash.find": "^4.6.0", - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "lodash.isundefined": "^3.0.1", - "lodash.memoize": "^4.1.2", - "lodash.merge": "^4.6.2", - "prop-types": "^15.7.2", - "react-dnd": "^11.1.3", - "react-dnd-html5-backend": "^11.1.3", - "react-sortable-tree": "^2.7.1", - "react-to-print": "^2.8.0" - } - }, - "mui-nepali-datepicker-reactjs": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/mui-nepali-datepicker-reactjs/-/mui-nepali-datepicker-reactjs-1.1.4.tgz", - "integrity": "sha512-PWp+V2MfqK0OiuLqDP0tdpaTsJsahFcA/e6mNG7R049UNjVCrt/ZsiGRofBTr1sGYcPkBP+9Ai9MbFSqHSCeqA==", - "dev": true, - "requires": { - "@material-ui/core": "^4.12.3", - "@material-ui/icons": "^4.11.2", - "bikram-sambat-js": "^1.0.1", - "nepali-number": "^1.0.3" - } - }, - "multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "requires": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - } - }, - "multimath": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/multimath/-/multimath-2.0.0.tgz", - "integrity": "sha512-toRx66cAMJ+Ccz7pMIg38xSIrtnbozk0dchXezwQDMgQmbGpfxjtv68H+L00iFL8hxDaVjrmwAFSb3I6bg8Q2g==", - "dev": true, - "requires": { - "glur": "^1.1.2", - "object-assign": "^4.1.1" - } - }, - "mutationobserver-shim": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/mutationobserver-shim/-/mutationobserver-shim-0.3.7.tgz", - "integrity": "sha512-oRIDTyZQU96nAiz2AQyngwx1e89iApl2hN5AOYwyxLUB47UYsU3Wv9lJWqH5y/QdiYkc5HQLi23ZNB3fELdHcQ==", - "dev": true - }, - "nanoclone": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", - "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==", - "dev": true - }, - "nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } - } - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "nepali-number": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/nepali-number/-/nepali-number-1.0.3.tgz", - "integrity": "sha512-Vb6aMQM/xtE7KiiEhemgDcACxIMaDn18Ub/imWXB6JlhDwc2qVDnGW+sR0gDLPQmyiyk06bkKze1oK88FxWIjw==", - "dev": true - }, - "nested-error-stacks": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", - "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", - "dev": true - }, - "nise": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", - "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", - "dev": true, - "requires": { - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^5.0.1", - "path-to-regexp": "^1.7.0" - }, - "dependencies": { - "lolex": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", - "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - } - } - }, - "nock": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/nock/-/nock-10.0.6.tgz", - "integrity": "sha512-b47OWj1qf/LqSQYnmokNWM8D88KvUl2y7jT0567NB3ZBAZFz2bWp2PC81Xn7u8F2/vJxzkzNZybnemeFa7AZ2w==", - "dev": true, - "requires": { - "chai": "^4.1.2", - "debug": "^4.1.0", - "deep-equal": "^1.0.0", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.5", - "mkdirp": "^0.5.0", - "propagate": "^1.0.0", - "qs": "^6.5.1", - "semver": "^5.5.0" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "normalizr": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/normalizr/-/normalizr-3.6.2.tgz", - "integrity": "sha512-30qCybsBaCBciotorvuOZTCGEg2AXrJfADMT2Kk/lvpIAcipHdK0zc33nNtwKzyfQAqIJXAcqET6YgflYUgsoQ==", - "dev": true - }, - "notistack": { - "version": "0.9.17", - "resolved": "https://registry.npmjs.org/notistack/-/notistack-0.9.17.tgz", - "integrity": "sha512-nypTN6sEe+q98wMaxF/UwatA1yAq948+bZOo9JKYR+tU65DW0ipWyx8DseJ3UJYvb6VDD+Fqo83qwayQ46bEEA==", - "dev": true, - "requires": { - "clsx": "^1.1.0", - "hoist-non-react-statics": "^3.3.0" - } - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "nwsapi": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.4.tgz", - "integrity": "sha512-NHj4rzRo0tQdijE9ZqAx6kYDcoRwYwSYzCA8MY3JzfxlrvEU0jhnhJT9BhqhJs7I/dKcrDm6TyulaRqZPIhN5g==", - "dev": true - }, - "nyc": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", - "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", - "dev": true, - "requires": { - "archy": "^1.0.0", - "caching-transform": "^3.0.2", - "convert-source-map": "^1.6.0", - "cp-file": "^6.2.0", - "find-cache-dir": "^2.1.0", - "find-up": "^3.0.0", - "foreground-child": "^1.5.6", - "glob": "^7.1.3", - "istanbul-lib-coverage": "^2.0.5", - "istanbul-lib-hook": "^2.0.7", - "istanbul-lib-instrument": "^3.3.0", - "istanbul-lib-report": "^2.0.8", - "istanbul-lib-source-maps": "^3.0.6", - "istanbul-reports": "^2.2.4", - "js-yaml": "^3.13.1", - "make-dir": "^2.1.0", - "merge-source-map": "^1.1.0", - "resolve-from": "^4.0.0", - "rimraf": "^2.6.3", - "signal-exit": "^3.0.2", - "spawn-wrap": "^1.4.2", - "test-exclude": "^5.2.3", - "uuid": "^8.3.2", - "yargs": "^13.2.2", - "yargs-parser": "^13.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "5.0.1" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "dev": true - }, - "object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "object.entries": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", - "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "object.fromentries": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", - "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "object.hasown": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz", - "integrity": "sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", - "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - }, - "p-retry": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", - "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", - "dev": true, - "requires": { - "@types/retry": "^0.12.0", - "retry": "^0.13.1" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "package-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", - "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "hasha": "^3.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "requires": { - "parse5": "^6.0.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "pica": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/pica/-/pica-6.1.1.tgz", - "integrity": "sha512-dmjQheDGFOl+30rQhN3NM3MyDNjeOZvco6IL3ZVYgyVDmhgvcSCGOAsydRCIaZ36mcXO7ci0XFeD+h6unEcBvA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "multimath": "^2.0.0", - "object-assign": "^4.1.1", - "webworkify": "^1.5.0" - } - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - } - } - }, - "pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - } - } - }, - "popper.js": { - "version": "1.16.1-lts", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", - "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==", - "dev": true - }, - "postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "dev": true, - "requires": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "dependencies": { - "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "dev": true - } - } - }, - "postcss-attribute-case-insensitive": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.0.tgz", - "integrity": "sha512-b4g9eagFGq9T5SWX4+USfVyjIb3liPnjhHHRMP7FMB2kFVpYyfEscV0wP3eaXhKlcHKUut8lt5BGoeylWA/dBQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.2" - } - }, - "postcss-clamp": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", - "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-color-functional-notation": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.2.tgz", - "integrity": "sha512-DXVtwUhIk4f49KK5EGuEdgx4Gnyj6+t2jBSEmxvpIK9QI40tWrpS2Pua8Q7iIZWBrki2QOaeUdEaLPPa91K0RQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-color-hex-alpha": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.3.tgz", - "integrity": "sha512-fESawWJCrBV035DcbKRPAVmy21LpoyiXdPTuHUfWJ14ZRjY7Y7PA6P4g8z6LQGYhU1WAxkTxjIjurXzoe68Glw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-color-rebeccapurple": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.0.2.tgz", - "integrity": "sha512-SFc3MaocHaQ6k3oZaFwH8io6MdypkUtEy/eXzXEB1vEQlO3S3oDc/FSZA8AsS04Z25RirQhlDlHLh3dn7XewWw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-custom-media": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz", - "integrity": "sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g==", - "dev": true, - "requires": {} - }, - "postcss-custom-properties": { - "version": "12.1.5", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.5.tgz", - "integrity": "sha512-FHbbB/hRo/7cxLGkc2NS7cDRIDN1oFqQnUKBiyh4b/gwk8DD8udvmRDpUhEK836kB8ggUCieHVOvZDnF9XhI3g==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-custom-selectors": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.0.tgz", - "integrity": "sha512-/1iyBhz/W8jUepjGyu7V1OPcGbc636snN1yXEQCinb6Bwt7KxsiU7/bLQlp8GwAXzCh7cobBU5odNn/2zQWR8Q==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-dir-pseudo-class": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.4.tgz", - "integrity": "sha512-I8epwGy5ftdzNWEYok9VjW9whC4xnelAtbajGv4adql4FIF09rnrxnA9Y8xSHN47y7gqFIv10C5+ImsLeJpKBw==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "postcss-double-position-gradients": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.1.tgz", - "integrity": "sha512-jM+CGkTs4FcG53sMPjrrGE0rIvLDdCrqMzgDC5fLI7JHDO7o6QG8C5TQBtExb13hdBdoH9C2QVbG4jo2y9lErQ==", - "dev": true, - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-env-function": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", - "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-flexbugs-fixes": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", - "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", - "dev": true, - "requires": {} - }, - "postcss-focus-visible": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", - "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "postcss-focus-within": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", - "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "postcss-font-variant": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", - "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", - "dev": true, - "requires": {} - }, - "postcss-gap-properties": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.3.tgz", - "integrity": "sha512-rPPZRLPmEKgLk/KlXMqRaNkYTUpE7YC+bOIQFN5xcu1Vp11Y4faIXv6/Jpft6FMnl6YRxZqDZG0qQOW80stzxQ==", - "dev": true, - "requires": {} - }, - "postcss-image-set-function": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.6.tgz", - "integrity": "sha512-KfdC6vg53GC+vPd2+HYzsZ6obmPqOk6HY09kttU19+Gj1nC3S3XBVEXDHxkhxTohgZqzbUb94bKXvKDnYWBm/A==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-import": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", - "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - } - }, - "postcss-initial": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", - "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", - "dev": true, - "requires": {} - }, - "postcss-lab-function": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.1.2.tgz", - "integrity": "sha512-isudf5ldhg4fk16M8viAwAbg6Gv14lVO35N3Z/49NhbwPQ2xbiEoHgrRgpgQojosF4vF7jY653ktB6dDrUOR8Q==", - "dev": true, - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "dev": true, - "requires": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - }, - "dependencies": { - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "postcss-logical": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", - "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", - "dev": true, - "requires": {} - }, - "postcss-media-minmax": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", - "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", - "dev": true, - "requires": {} - }, - "postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} - }, - "postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0" - } - }, - "postcss-nesting": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.1.3.tgz", - "integrity": "sha512-wUC+/YCik4wH3StsbC5fBG1s2Z3ZV74vjGqBFYtmYKlVxoio5TYGM06AiaKkQPPlkXWn72HKfS7Cw5PYxnoXSw==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "postcss-opacity-percentage": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.2.tgz", - "integrity": "sha512-lyUfF7miG+yewZ8EAk9XUBIlrHyUE6fijnesuz+Mj5zrIHIEw6KcIZSOk/elVMqzLvREmXB83Zi/5QpNRYd47w==", - "dev": true - }, - "postcss-overflow-shorthand": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.3.tgz", - "integrity": "sha512-CxZwoWup9KXzQeeIxtgOciQ00tDtnylYIlJBBODqkgS/PU2jISuWOL/mYLHmZb9ZhZiCaNKsCRiLp22dZUtNsg==", - "dev": true, - "requires": {} - }, - "postcss-page-break": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", - "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", - "dev": true, - "requires": {} - }, - "postcss-place": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.4.tgz", - "integrity": "sha512-MrgKeiiu5OC/TETQO45kV3npRjOFxEHthsqGtkh3I1rPbZSbXGD/lZVi9j13cYh+NA8PIAPyk6sGjT9QbRyvSg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-preset-env": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.4.3.tgz", - "integrity": "sha512-dlPA65g9KuGv7YsmGyCKtFkZKCPLkoVMUE3omOl6yM+qrynVHxFvf0tMuippIrXB/sB/MyhL1FgTIbrO+qMERg==", - "dev": true, - "requires": { - "@csstools/postcss-color-function": "^1.0.3", - "@csstools/postcss-font-format-keywords": "^1.0.0", - "@csstools/postcss-hwb-function": "^1.0.0", - "@csstools/postcss-ic-unit": "^1.0.0", - "@csstools/postcss-is-pseudo-class": "^2.0.1", - "@csstools/postcss-normalize-display-values": "^1.0.0", - "@csstools/postcss-oklab-function": "^1.0.2", - "@csstools/postcss-progressive-custom-properties": "^1.3.0", - "autoprefixer": "^10.4.4", - "browserslist": "^4.20.2", - "css-blank-pseudo": "^3.0.3", - "css-has-pseudo": "^3.0.4", - "css-prefers-color-scheme": "^6.0.3", - "cssdb": "^6.5.0", - "postcss-attribute-case-insensitive": "^5.0.0", - "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^4.2.2", - "postcss-color-hex-alpha": "^8.0.3", - "postcss-color-rebeccapurple": "^7.0.2", - "postcss-custom-media": "^8.0.0", - "postcss-custom-properties": "^12.1.5", - "postcss-custom-selectors": "^6.0.0", - "postcss-dir-pseudo-class": "^6.0.4", - "postcss-double-position-gradients": "^3.1.1", - "postcss-env-function": "^4.0.6", - "postcss-focus-visible": "^6.0.4", - "postcss-focus-within": "^5.0.4", - "postcss-font-variant": "^5.0.0", - "postcss-gap-properties": "^3.0.3", - "postcss-image-set-function": "^4.0.6", - "postcss-initial": "^4.0.1", - "postcss-lab-function": "^4.1.2", - "postcss-logical": "^5.0.4", - "postcss-media-minmax": "^5.0.0", - "postcss-nesting": "^10.1.3", - "postcss-opacity-percentage": "^1.1.2", - "postcss-overflow-shorthand": "^3.0.3", - "postcss-page-break": "^3.0.4", - "postcss-place": "^7.0.4", - "postcss-pseudo-class-any-link": "^7.1.1", - "postcss-replace-overflow-wrap": "^4.0.0", - "postcss-selector-not": "^5.0.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-pseudo-class-any-link": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.1.tgz", - "integrity": "sha512-JRoLFvPEX/1YTPxRxp1JO4WxBVXJYrSY7NHeak5LImwJ+VobFMwYDQHvfTXEpcn+7fYIeGkC29zYFhFWIZD8fg==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "postcss-replace-overflow-wrap": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", - "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", - "dev": true, - "requires": {} - }, - "postcss-rtlcss": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/postcss-rtlcss/-/postcss-rtlcss-3.5.3.tgz", - "integrity": "sha512-QasqXUUBAqvHtDGJydyw5rJB88S4ZHRdxKsguqfes1PBDkBW97P9GiLCtcg6EuCXRvD+52giBQXKWNWg9gshow==", - "dev": true, - "requires": { - "rtlcss": "^3.5.0" - } - }, - "postcss-selector-not": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-5.0.0.tgz", - "integrity": "sha512-/2K3A4TCP9orP4TNS7u3tGdRFVKqz/E6pX3aGnriPG0jU78of8wsUcqE4QAhWEU0d+WnMSF93Ah3F//vUtK+iQ==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "postcss-selector-parser": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", - "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.0.tgz", - "integrity": "sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A==", - "dev": true - }, - "prettier-eslint": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/prettier-eslint/-/prettier-eslint-13.0.0.tgz", - "integrity": "sha512-P5K31qWgUOQCtJL/3tpvEe28KfP49qbr6MTVEXC7I2k7ci55bP3YDr+glhyCdhIzxGCVp2f8eobfQ5so52RIIA==", - "dev": true, - "requires": { - "@typescript-eslint/parser": "^3.0.0", - "common-tags": "^1.4.0", - "dlv": "^1.1.0", - "eslint": "^7.9.0", - "indent-string": "^4.0.0", - "lodash.merge": "^4.6.0", - "loglevel-colored-level-prefix": "^1.0.0", - "prettier": "^2.0.0", - "pretty-format": "^23.0.1", - "require-relative": "^0.8.7", - "typescript": "^3.9.3", - "vue-eslint-parser": "~7.1.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - } - }, - "@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true - }, - "pretty-format": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", - "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", - "dev": true, - "requires": { - "ansi-regex": "5.0.1", - "ansi-styles": "^3.2.0" - } - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "dev": true, - "requires": { - "asap": "~2.0.3" - } - }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - }, - "dependencies": { - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - } - } - }, - "prop-types-exact": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", - "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", - "dev": true, - "requires": { - "has": "^1.0.3", - "object.assign": "^4.1.0", - "reflect.ownkeys": "^0.2.0" - } - }, - "propagate": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-1.0.0.tgz", - "integrity": "sha1-AMLa7t2iDofjeCs0Stuhzd1q1wk=", - "dev": true - }, - "property-expr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", - "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==", - "dev": true - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "dependencies": { - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true - } - } - }, - "proxy-compare": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.4.0.tgz", - "integrity": "sha512-FD8KmQUQD6Mfpd0hywCOzcon/dbkFP8XBd9F1ycbKtvVsfv6TsFUKJ2eC0Iz2y+KzlkdT1Z8SY6ZSgm07zOyqg==", - "dev": true - }, - "proxy-memoize": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/proxy-memoize/-/proxy-memoize-2.0.3.tgz", - "integrity": "sha512-PpZzfNsZbOI89phkaq2BP6OfG7/0RDKYKEwTSlIikcWZ5ODN/dRzrHfg1zPMtlZY6FJRmrHamJ1ol2gIc+bruQ==", - "dev": true, - "requires": { - "proxy-compare": "2.4.0" - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "pug": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.2.tgz", - "integrity": "sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==", - "dev": true, - "requires": { - "pug-code-gen": "^3.0.2", - "pug-filters": "^4.0.0", - "pug-lexer": "^5.0.1", - "pug-linker": "^4.0.0", - "pug-load": "^3.0.0", - "pug-parser": "^6.0.0", - "pug-runtime": "^3.0.1", - "pug-strip-comments": "^2.0.0" - } - }, - "pug-attrs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", - "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", - "dev": true, - "requires": { - "constantinople": "^4.0.1", - "js-stringify": "^1.0.2", - "pug-runtime": "^3.0.0" - } - }, - "pug-code-gen": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.2.tgz", - "integrity": "sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==", - "dev": true, - "requires": { - "constantinople": "^4.0.1", - "doctypes": "^1.1.0", - "js-stringify": "^1.0.2", - "pug-attrs": "^3.0.0", - "pug-error": "^2.0.0", - "pug-runtime": "^3.0.0", - "void-elements": "^3.1.0", - "with": "^7.0.0" - } - }, - "pug-error": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.0.0.tgz", - "integrity": "sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==", - "dev": true - }, - "pug-filters": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz", - "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==", - "dev": true, - "requires": { - "constantinople": "^4.0.1", - "jstransformer": "1.0.0", - "pug-error": "^2.0.0", - "pug-walk": "^2.0.0", - "resolve": "^1.15.1" - } - }, - "pug-lexer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz", - "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==", - "dev": true, - "requires": { - "character-parser": "^2.2.0", - "is-expression": "^4.0.0", - "pug-error": "^2.0.0" - } - }, - "pug-linker": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz", - "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==", - "dev": true, - "requires": { - "pug-error": "^2.0.0", - "pug-walk": "^2.0.0" - } - }, - "pug-load": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz", - "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "pug-walk": "^2.0.0" - } - }, - "pug-parser": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz", - "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==", - "dev": true, - "requires": { - "pug-error": "^2.0.0", - "token-stream": "1.0.0" - } - }, - "pug-runtime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", - "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==", - "dev": true - }, - "pug-strip-comments": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz", - "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==", - "dev": true, - "requires": { - "pug-error": "^2.0.0" - } - }, - "pug-walk": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", - "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "pure-rand": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", - "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", - "dev": true - }, - "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "dev": true, - "requires": { - "performance-now": "^2.1.0" - } - }, - "raf-schd": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", - "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==", - "dev": true - }, - "railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", - "dev": true - }, - "randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dev": true, - "requires": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "re-reselect": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/re-reselect/-/re-reselect-4.0.0.tgz", - "integrity": "sha512-wuygyq8TXUlSdVXv2kigXxQNOgdb9m7LbIjwfTNGSpaY1riLd5e+VeQjlQMyUtrk0oiyhi1AqIVynworl3qxHA==", - "dev": true, - "requires": {} - }, - "react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "react-16-node-hanging-test-fix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/react-16-node-hanging-test-fix/-/react-16-node-hanging-test-fix-1.0.0.tgz", - "integrity": "sha512-D22iNNa+0MuMPA49nZ5ILBHiJ7h9PTeUUuZee38pFSEWlHOYnHEWzUjOlYjEo6Ji+axHrRnT+y1QRIJOcIcj4w==", - "requires": { - "semver": "^7.3.4" - }, - "dependencies": { - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "react-beautiful-dnd": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz", - "integrity": "sha512-aGvblPZTJowOWUNiwd6tNfEpgkX5OxmpqxHKNW/4VmvZTNTbeiq7bA3bn5T+QSF2uibXB0D1DmJsb1aC/+3cUA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.9.2", - "css-box-model": "^1.2.0", - "memoize-one": "^5.1.1", - "raf-schd": "^4.0.2", - "react-redux": "^7.2.0", - "redux": "^4.0.4", - "use-memo-one": "^1.1.1" - } - }, - "react-display-name": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/react-display-name/-/react-display-name-0.2.5.tgz", - "integrity": "sha512-I+vcaK9t4+kypiSgaiVWAipqHRXYmZIuAiS8vzFvXHHXVigg/sMKwlRgLy6LH2i3rmP+0Vzfl5lFsFRwF1r3pg==", - "dev": true - }, - "react-dnd": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-11.1.3.tgz", - "integrity": "sha512-8rtzzT8iwHgdSC89VktwhqdKKtfXaAyC4wiqp0SywpHG12TTLvfOoL6xNEIUWXwIEWu+CFfDn4GZJyynCEuHIQ==", - "dev": true, - "requires": { - "@react-dnd/shallowequal": "^2.0.0", - "@types/hoist-non-react-statics": "^3.3.1", - "dnd-core": "^11.1.3", - "hoist-non-react-statics": "^3.3.0" - } - }, - "react-dnd-html5-backend": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-11.1.3.tgz", - "integrity": "sha512-/1FjNlJbW/ivkUxlxQd7o3trA5DE33QiRZgxent3zKme8DwF4Nbw3OFVhTRFGaYhHFNL1rZt6Rdj1D78BjnNLw==", - "dev": true, - "requires": { - "dnd-core": "^11.1.3" - } - }, - "react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", - "dev": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" - } - }, - "react-error-boundary": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz", - "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.12.5" - } - }, - "react-fast-compare": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", - "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==", - "dev": true - }, - "react-hook-form": { - "version": "6.15.1", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-6.15.1.tgz", - "integrity": "sha512-bL0LQuQ3OlM3JYfbacKtBPLOHhmgYz8Lj6ivMrvu2M6e1wnt4sbGRtPEPYCc/8z3WDbjrMwfAfLX92OsB65pFA==", - "dev": true, - "requires": {} - }, - "react-idle-timer": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/react-idle-timer/-/react-idle-timer-5.6.2.tgz", - "integrity": "sha512-X7zjDv7duCopQ4v3X2Gun8QunvYplPWkvW2y7suDSREu1vQRQ0mr1ESv325QoJuvSIE5QCSbLaJlrbbooNaUNg==", - "dev": true, - "requires": {} - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "react-lifecycles-compat": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", - "dev": true - }, - "react-redux": { - "version": "7.2.6", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.6.tgz", - "integrity": "sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.15.4", - "@types/react-redux": "^7.1.20", - "hoist-non-react-statics": "^3.3.2", - "loose-envify": "^1.4.0", - "prop-types": "^15.7.2", - "react-is": "^17.0.2" - } - }, - "react-router": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", - "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.4.0", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" - }, - "dependencies": { - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - } - } - }, - "react-router-dom": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz", - "integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.2.1", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" - } - }, - "react-router-navigation-prompt": { - "version": "1.9.6", - "resolved": "https://registry.npmjs.org/react-router-navigation-prompt/-/react-router-navigation-prompt-1.9.6.tgz", - "integrity": "sha512-l0sAtbroHK8i1/Eyy29XcrMpBEt0R08BaScgMUt8r5vWWbLz7G0ChOikayTCQm7QgDFsHw8gVnxDJb7TBZCAKg==", - "dev": true, - "requires": {} - }, - "react-shallow-renderer": { - "version": "16.14.1", - "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.14.1.tgz", - "integrity": "sha512-rkIMcQi01/+kxiTE9D3fdS959U1g7gs+/rborw++42m1O9FAQiNI/UNRZExVUoAOprn4umcXf+pFRou8i4zuBg==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "react-is": "^16.12.0 || ^17.0.0" - } - }, - "react-simple-animate": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/react-simple-animate/-/react-simple-animate-3.3.12.tgz", - "integrity": "sha512-lFXjxD6ficcpOMsHfcDs1jqdkCve6jNlJnubOCzVOLswFDRANsaLN4KwpezDuliEFz8Q1zyj4J7Tmj3KMRnPcg==", - "dev": true, - "requires": {} - }, - "react-sortable-tree": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/react-sortable-tree/-/react-sortable-tree-2.8.0.tgz", - "integrity": "sha512-gTjwxRNt7z0FC76KeNTnGqx1qUSlV3N78mMPRushBpSUXzZYhiFNsWHUIruyPnaAbw4SA7LgpItV7VieAuwDpw==", - "dev": true, - "requires": { - "frontend-collective-react-dnd-scrollzone": "^1.0.2", - "lodash.isequal": "^4.5.0", - "prop-types": "^15.6.1", - "react-dnd": "^11.1.3", - "react-dnd-html5-backend": "^11.1.3", - "react-lifecycles-compat": "^3.0.4", - "react-virtualized": "^9.21.2" - } - }, - "react-spaces": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/react-spaces/-/react-spaces-0.3.2.tgz", - "integrity": "sha512-Yq3USb43jEt6k6CKe00z1sZfnOft+Tdv1IJQoVJBtKN5ut1v1m+0iIOJyxxWMRra/TsVBomSNV2LgwFvvRw9SA==", - "dev": true, - "requires": { - "css-element-queries": "^1.2.1", - "prop-types": "^15.7.2" - } - }, - "react-test-renderer": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-17.0.2.tgz", - "integrity": "sha512-yaQ9cB89c17PUb0x6UfWRs7kQCorVdHlutU1boVPEsB8IDZH6n9tHxMacc3y0JoXOJUsZb/t/Mb8FUWMKaM7iQ==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "react-is": "^17.0.2", - "react-shallow-renderer": "^16.13.1", - "scheduler": "^0.20.2" - } - }, - "react-to-print": { - "version": "2.14.7", - "resolved": "https://registry.npmjs.org/react-to-print/-/react-to-print-2.14.7.tgz", - "integrity": "sha512-lWVVAs9Co25uyE0toxcWeFsmaZObwUozXrJD9WMpDPclpBgk+WIzxlt3Q3omL/BCBG/cpf0XNvhayUWa+99YGw==", - "dev": true, - "requires": { - "prop-types": "^15.8.1" - } - }, - "react-transition-group": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz", - "integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - } - }, - "react-virtualized": { - "version": "9.22.3", - "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.3.tgz", - "integrity": "sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.7.2", - "clsx": "^1.0.4", - "dom-helpers": "^5.1.3", - "loose-envify": "^1.4.0", - "prop-types": "^15.7.2", - "react-lifecycles-compat": "^3.0.4" - } - }, - "react-window": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.6.tgz", - "integrity": "sha512-8VwEEYyjz6DCnGBsd+MgkD0KJ2/OXFULyDtorIiTz+QzwoP94tBoA7CnbtyXMm+cCeAUER5KJcPtWl9cpKbOBg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.0.0", - "memoize-one": ">=3.1.1 <6" - } - }, - "read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", - "dev": true, - "requires": { - "pify": "^2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "dependencies": { - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", - "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", - "dev": true, - "requires": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - } - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "realistic-structured-clone": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/realistic-structured-clone/-/realistic-structured-clone-2.0.4.tgz", - "integrity": "sha512-lItAdBIFHUSe6fgztHPtmmWqKUgs+qhcYLi3wTRUl4OTB3Vb8aBVSjGfQZUvkmJCKoX3K9Wf7kyLp/F/208+7A==", - "dev": true, - "requires": { - "core-js": "^3.4", - "domexception": "^1.0.1", - "typeson": "^6.1.0", - "typeson-registry": "^1.0.0-alpha.20" - }, - "dependencies": { - "core-js": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", - "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==", - "dev": true - }, - "domexception": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", - "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", - "dev": true, - "requires": { - "webidl-conversions": "^4.0.2" - } - }, - "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true - } - } - }, - "rechoir": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", - "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", - "dev": true, - "requires": { - "resolve": "^1.9.0" - } - }, - "redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "requires": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - } - }, - "reduce-reducers": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reduce-reducers/-/reduce-reducers-1.0.4.tgz", - "integrity": "sha512-Mb2WZ2bJF597exiqX7owBzrqJ74DHLK3yOQjCyPAaNifRncE8OD0wFIuoMhXxTnHK07+8zZ2SJEKy/qtiyR7vw==", - "dev": true - }, - "redux": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", - "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.9.2" - } - }, - "redux-immutable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/redux-immutable/-/redux-immutable-4.0.0.tgz", - "integrity": "sha1-Ohoy32Y2ZGK2NpHw4dw15HK7yfM=", - "dev": true, - "requires": {} - }, - "redux-logger": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-3.0.6.tgz", - "integrity": "sha1-91VZZvMJjzyIYExEnPC69XeCdL8=", - "dev": true, - "requires": { - "deep-diff": "^0.3.5" - } - }, - "redux-mock-store": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/redux-mock-store/-/redux-mock-store-1.5.4.tgz", - "integrity": "sha512-xmcA0O/tjCLXhh9Fuiq6pMrJCwFRaouA8436zcikdIpYWWCjU76CRk+i2bHx8EeiSiMGnB85/lZdU3wIJVXHTA==", - "dev": true, - "requires": { - "lodash.isplainobject": "^4.0.6" - } - }, - "redux-thunk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", - "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", - "dev": true, - "requires": {} - }, - "reflect.ownkeys": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", - "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=", - "dev": true - }, - "regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.2" - } - }, - "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true - }, - "regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dev": true, - "requires": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - } - }, - "regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true - } - } - }, - "release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", - "dev": true, - "requires": { - "es6-error": "^4.0.1" - } - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "reprism": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/reprism/-/reprism-0.0.11.tgz", - "integrity": "sha1-52C4XgriQXIgMsuJQqK8q5kqkIM=", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-hacker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/require-hacker/-/require-hacker-3.0.1.tgz", - "integrity": "sha1-CHm+Bn/PBnUwZlvM5MiayBqHBHc=", - "dev": true, - "requires": { - "babel-runtime": "^6.6.1", - "colors": "^1.1.2" - } - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "require-relative": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", - "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "reselect": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz", - "integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==", - "dev": true - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "resolve-pathname": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==", - "dev": true - }, - "resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rgbcolor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", - "integrity": "sha1-1lBezbMEplldom+ktDMHMGd1lF0=", - "dev": true - }, - "rifm": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rifm/-/rifm-0.7.0.tgz", - "integrity": "sha512-DSOJTWHD67860I5ojetXdEQRIBvF6YcpNe53j0vn1vp9EUb9N80EiZTxgP+FkDKorWC8PZw052kTF4C1GOivCQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.3.1" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rollup": { - "version": "2.70.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.1.tgz", - "integrity": "sha512-CRYsI5EuzLbXdxC6RnYhOuRdtz4bhejPMSWjsFLfVM/7w/85n2szZv6yExqUXsBdz5KT8eoubeyDUDjhLHEslA==", - "dev": true, - "requires": { - "fsevents": "~2.3.2" - } - }, - "rollup-plugin-terser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - } - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "rst-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", - "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=", - "dev": true, - "requires": { - "lodash.flattendeep": "^4.4.0", - "nearley": "^2.7.10" - } - }, - "rtl-css-js": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.15.0.tgz", - "integrity": "sha512-99Cu4wNNIhrI10xxUaABHsdDqzalrSRTie4GeCmbGVuehm4oj+fIy8fTzB+16pmKe8Bv9rl+hxIBez6KxExTew==", - "dev": true, - "requires": { - "@babel/runtime": "^7.1.2" - } - }, - "rtlcss": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz", - "integrity": "sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A==", - "dev": true, - "requires": { - "find-up": "^5.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.3.11", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - } - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", - "dev": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - } - }, - "seamless-immutable": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/seamless-immutable/-/seamless-immutable-7.1.4.tgz", - "integrity": "sha512-XiUO1QP4ki4E2PHegiGAlu6r82o5A+6tRh7IkGGTVg/h+UoeX4nFBeCGPOhb4CYjvkqsfm/TUtvOMYC1xmV30A==", - "dev": true, - "optional": true - }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true - }, - "selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, - "requires": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - }, - "send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "sinon": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", - "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.4.0", - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/samsam": "^3.3.3", - "diff": "^3.5.0", - "lolex": "^4.2.0", - "nise": "^1.5.2", - "supports-color": "^5.5.0" - }, - "dependencies": { - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - } - } - }, - "sinon-chai": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", - "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", - "dev": true, - "requires": {} - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - } - } - }, - "sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "requires": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "spark-md5": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.2.tgz", - "integrity": "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw==", - "dev": true - }, - "spawn-wrap": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", - "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", - "dev": true, - "requires": { - "foreground-child": "^1.5.6", - "mkdirp": "^0.5.0", - "os-homedir": "^1.0.1", - "rimraf": "^2.6.2", - "signal-exit": "^3.0.2", - "which": "^1.3.0" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true - }, - "spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, - "stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "requires": { - "escape-string-regexp": "^2.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } - } - }, - "stackblur-canvas": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.5.0.tgz", - "integrity": "sha512-EeNzTVfj+1In7aSLPKDD03F/ly4RxEuF/EX0YcOG0cKoPXs+SLZxDawQbexQDBzwROs4VKLWTOaZQlZkGBFEIQ==", - "dev": true - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "requires": { - "internal-slot": "^1.0.4" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - } - } - }, - "string.prototype.matchall": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", - "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.1", - "side-channel": "^1.0.4" - } - }, - "string.prototype.trim": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.5.tgz", - "integrity": "sha512-Lnh17webJVsD6ECeovpVN17RlAKjmz4rF9S+8Y45CkMc/ufVpTkU3vZIyIC7sllQ1FCvObZnnCdNs/HXTUOTlg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dev": true, - "requires": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "5.0.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", - "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "requires": { - "min-indent": "^1.0.0" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "style-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", - "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", - "dev": true, - "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "svg-parser": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", - "dev": true - }, - "svg-pathdata": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", - "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", - "dev": true - }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "table": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", - "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "dev": true - }, - "tempy": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", - "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", - "dev": true, - "requires": { - "is-stream": "^2.0.0", - "temp-dir": "^2.0.0", - "type-fest": "^0.16.0", - "unique-string": "^2.0.0" - } - }, - "terser": { - "version": "5.16.9", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.9.tgz", - "integrity": "sha512-HPa/FdTB9XGI2H1/keLFZHxl6WNvAI4YalHGtDQTlMnJcoqSab1UwL4l1hGEhs6/GmLHBZIg/YgB++jcbzoOEg==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - } - } - }, - "terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - } - } - }, - "test-exclude": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", - "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", - "dev": true, - "requires": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" - } - }, - "text-segmentation": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", - "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", - "dev": true, - "optional": true, - "requires": { - "utrie": "^1.0.2" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "timezone-mock": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/timezone-mock/-/timezone-mock-1.3.1.tgz", - "integrity": "sha512-kWK2liWUaYSLW/B2yJ6/oUbLc26cEbtIjM7BPrRxaX/3TSeqOOQfXQ6N4pNhy05ZBnUs9vywWAthiE9QYGZFwA==", - "dev": true - }, - "tiny-invariant": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", - "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==", - "dev": true - }, - "tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", - "dev": true - }, - "tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true - }, - "token-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", - "integrity": "sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ=", - "dev": true - }, - "toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=", - "dev": true - }, - "tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "dependencies": { - "universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true - } - } - }, - "tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "1.2.7", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "1.2.7" - } - } - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", - "dev": true - }, - "typeson": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/typeson/-/typeson-6.1.0.tgz", - "integrity": "sha512-6FTtyGr8ldU0pfbvW/eOZrEtEkczHRUtduBnA90Jh9kMPCiFNnXIon3vF41N0S4tV1HHQt4Hk1j4srpESziCaA==", - "dev": true - }, - "typeson-registry": { - "version": "1.0.0-alpha.39", - "resolved": "https://registry.npmjs.org/typeson-registry/-/typeson-registry-1.0.0-alpha.39.tgz", - "integrity": "sha512-NeGDEquhw+yfwNhguLPcZ9Oj0fzbADiX4R0WxvoY8nGhy98IbzQy1sezjoEFWOywOboj/DWehI+/aUlRVrJnnw==", - "dev": true, - "requires": { - "base64-arraybuffer-es6": "^0.7.0", - "typeson": "^6.0.0", - "whatwg-url": "^8.4.0" - } - }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, - "unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true - }, - "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "requires": { - "crypto-random-string": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "use-memo-one": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz", - "integrity": "sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ==", - "dev": true, - "requires": {} - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "utrie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", - "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", - "dev": true, - "optional": true, - "requires": { - "base64-arraybuffer": "^1.0.2" - } - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", - "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==", - "dev": true - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - }, - "void-elements": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", - "integrity": "sha1-YU9/v42AHwu18GYfWy9XhXUOTwk=", - "dev": true - }, - "vue-eslint-parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz", - "integrity": "sha512-8FdXi0gieEwh1IprIBafpiJWcApwrU+l2FEj8c1HtHFdNXMd0+2jUSjBVmcQYohf/E72irwAXEXLga6TQcB3FA==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "eslint-scope": "^5.0.0", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.2.1", - "esquery": "^1.0.1", - "lodash": "^4.17.15" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - }, - "espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" - } - } - } - }, - "w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "requires": { - "browser-process-hrtime": "^1.0.0" - } - }, - "w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "requires": { - "xml-name-validator": "^3.0.0" - } - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "requires": { - "makeerror": "1.0.12" - } - }, - "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true - }, - "webpack": { - "version": "5.79.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.79.0.tgz", - "integrity": "sha512-3mN4rR2Xq+INd6NnYuL9RC9GAmc1ROPKJoHhrZ4pAjdMFEkJJWrsPw8o2JjCIyQyTu7rTXYn4VG6OpyB3CobZg==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "webpack-assets-manifest": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/webpack-assets-manifest/-/webpack-assets-manifest-5.1.0.tgz", - "integrity": "sha512-kPuTMEjBrqZQVJ5M6yXNBCEdFbQQn7p+loNXt8NOeDFaAbsNFWqqwR0YL1mfG5LbwhK5FLXWXpuK3GuIIZ46rg==", - "dev": true, - "requires": { - "chalk": "^4.0", - "deepmerge": "^4.0", - "lockfile": "^1.0", - "lodash.get": "^4.0", - "lodash.has": "^4.0", - "schema-utils": "^3.0", - "tapable": "^2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "webpack-cli": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz", - "integrity": "sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ==", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.1.1", - "@webpack-cli/info": "^1.4.1", - "@webpack-cli/serve": "^1.6.1", - "colorette": "^2.0.14", - "commander": "^7.0.0", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "webpack-merge": "^5.7.3" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - } - } - }, - "webpack-dev-middleware": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz", - "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==", - "dev": true, - "requires": { - "colorette": "^2.0.10", - "memfs": "^3.4.1", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - } - } - }, - "webpack-dev-server": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", - "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", - "dev": true, - "requires": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.13.0" - }, - "dependencies": { - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - }, - "ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "requires": {} - } - } - }, - "webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true - }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true - }, - "webworkify": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/webworkify/-/webworkify-1.5.0.tgz", - "integrity": "sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g==", - "dev": true - }, - "whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "requires": { - "iconv-lite": "0.4.24" - } - }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, - "requires": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - } - }, - "wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "with": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", - "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", - "dev": true, - "requires": { - "@babel/parser": "^7.9.6", - "@babel/types": "^7.9.6", - "assert-never": "^1.2.1", - "babel-walk": "3.0.0-canary-5" - } - }, - "word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true - }, - "workbox-background-sync": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.5.3.tgz", - "integrity": "sha512-0DD/V05FAcek6tWv9XYj2w5T/plxhDSpclIcAGjA/b7t/6PdaRkQ7ZgtAX6Q/L7kV7wZ8uYRJUoH11VjNipMZw==", - "dev": true, - "requires": { - "idb": "^6.1.4", - "workbox-core": "6.5.3" - }, - "dependencies": { - "idb": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", - "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==", - "dev": true - }, - "workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - } - } - }, - "workbox-broadcast-update": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.3.tgz", - "integrity": "sha512-4AwCIA5DiDrYhlN+Miv/fp5T3/whNmSL+KqhTwRBTZIL6pvTgE4lVuRzAt1JltmqyMcQ3SEfCdfxczuI4kwFQg==", - "dev": true, - "requires": { - "workbox-core": "6.5.3" - }, - "dependencies": { - "workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - } - } - }, - "workbox-build": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.3.tgz", - "integrity": "sha512-8JNHHS7u13nhwIYCDea9MNXBNPHXCs5KDZPKI/ZNTr3f4sMGoD7hgFGecbyjX1gw4z6e9bMpMsOEJNyH5htA/w==", - "dev": true, - "requires": { - "@apideck/better-ajv-errors": "^0.3.1", - "@babel/core": "^7.11.1", - "@babel/preset-env": "^7.11.0", - "@babel/runtime": "^7.11.2", - "@rollup/plugin-babel": "^5.2.0", - "@rollup/plugin-node-resolve": "^11.2.1", - "@rollup/plugin-replace": "^2.4.1", - "@surma/rollup-plugin-off-main-thread": "^2.2.3", - "ajv": "^8.6.0", - "common-tags": "^1.8.0", - "fast-json-stable-stringify": "^2.1.0", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "lodash": "^4.17.20", - "pretty-bytes": "^5.3.0", - "rollup": "^2.43.1", - "rollup-plugin-terser": "^7.0.0", - "source-map": "^0.8.0-beta.0", - "stringify-object": "^3.3.0", - "strip-comments": "^2.0.1", - "tempy": "^0.6.0", - "upath": "^1.2.0", - "workbox-background-sync": "6.5.3", - "workbox-broadcast-update": "6.5.3", - "workbox-cacheable-response": "6.5.3", - "workbox-core": "6.5.3", - "workbox-expiration": "6.5.3", - "workbox-google-analytics": "6.5.3", - "workbox-navigation-preload": "6.5.3", - "workbox-precaching": "6.5.3", - "workbox-range-requests": "6.5.3", - "workbox-recipes": "6.5.3", - "workbox-routing": "6.5.3", - "workbox-strategies": "6.5.3", - "workbox-streams": "6.5.3", - "workbox-sw": "6.5.3", - "workbox-window": "6.5.3" - }, - "dependencies": { - "@apideck/better-ajv-errors": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.3.tgz", - "integrity": "sha512-9o+HO2MbJhJHjDYZaDxJmSDckvDpiuItEsrIShV0DXeCshXWRHhqYyU/PKHMkuClOmFnZhRd6wzv4vpDu/dRKg==", - "dev": true, - "requires": { - "json-schema": "^0.4.0", - "jsonpointer": "^5.0.0", - "leven": "^3.1.0" - } - }, - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "idb": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", - "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "dev": true, - "requires": { - "whatwg-url": "^7.0.0" - } - }, - "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true - }, - "whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "workbox-cacheable-response": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.3.tgz", - "integrity": "sha512-6JE/Zm05hNasHzzAGKDkqqgYtZZL2H06ic2GxuRLStA4S/rHUfm2mnLFFXuHAaGR1XuuYyVCEey1M6H3PdZ7SQ==", - "dev": true, - "requires": { - "workbox-core": "6.5.3" - } - }, - "workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - }, - "workbox-expiration": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.3.tgz", - "integrity": "sha512-jzYopYR1zD04ZMdlbn/R2Ik6ixiXbi15c9iX5H8CTi6RPDz7uhvMLZPKEndZTpfgmUk8mdmT9Vx/AhbuCl5Sqw==", - "dev": true, - "requires": { - "idb": "^6.1.4", - "workbox-core": "6.5.3" - } - }, - "workbox-precaching": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.3.tgz", - "integrity": "sha512-sjNfgNLSsRX5zcc63H/ar/hCf+T19fRtTqvWh795gdpghWb5xsfEkecXEvZ8biEi1QD7X/ljtHphdaPvXDygMQ==", - "dev": true, - "requires": { - "workbox-core": "6.5.3", - "workbox-routing": "6.5.3", - "workbox-strategies": "6.5.3" - } - }, - "workbox-routing": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.3.tgz", - "integrity": "sha512-DFjxcuRAJjjt4T34RbMm3MCn+xnd36UT/2RfPRfa8VWJGItGJIn7tG+GwVTdHmvE54i/QmVTJepyAGWtoLPTmg==", - "dev": true, - "requires": { - "workbox-core": "6.5.3" - } - }, - "workbox-strategies": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.3.tgz", - "integrity": "sha512-MgmGRrDVXs7rtSCcetZgkSZyMpRGw8HqL2aguszOc3nUmzGZsT238z/NN9ZouCxSzDu3PQ3ZSKmovAacaIhu1w==", - "dev": true, - "requires": { - "workbox-core": "6.5.3" - } - } + "license": "MIT", + "dependencies": { + "workbox-core": "6.5.3" } }, - "workbox-cacheable-response": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-5.1.4.tgz", - "integrity": "sha512-0bfvMZs0Of1S5cdswfQK0BXt6ulU5kVD4lwer2CeI+03czHprXR3V4Y8lPTooamn7eHP8Iywi5QjyAMjw0qauA==", + "node_modules/workbox-navigation-preload": { + "version": "6.5.3", "dev": true, - "requires": { - "workbox-core": "^5.1.4" + "license": "MIT", + "dependencies": { + "workbox-core": "6.5.3" } }, - "workbox-core": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-5.1.4.tgz", - "integrity": "sha512-+4iRQan/1D8I81nR2L5vcbaaFskZC2CL17TLbvWVzQ4qiF/ytOGF6XeV54pVxAvKUtkLANhk8TyIUMtiMw2oDg==", - "dev": true + "node_modules/workbox-navigation-preload/node_modules/workbox-core": { + "version": "6.5.3", + "dev": true, + "license": "MIT" }, - "workbox-expiration": { + "node_modules/workbox-precaching": { "version": "5.1.4", - "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-5.1.4.tgz", - "integrity": "sha512-oDO/5iC65h2Eq7jctAv858W2+CeRW5e0jZBMNRXpzp0ZPvuT6GblUiHnAsC5W5lANs1QS9atVOm4ifrBiYY7AQ==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "workbox-core": "^5.1.4" } }, - "workbox-google-analytics": { + "node_modules/workbox-range-requests": { + "version": "6.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "workbox-core": "6.5.3" + } + }, + "node_modules/workbox-range-requests/node_modules/workbox-core": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.3.tgz", - "integrity": "sha512-3GLCHotz5umoRSb4aNQeTbILETcrTVEozSfLhHSBaegHs1PnqCmN0zbIy2TjTpph2AGXiNwDrWGF0AN+UgDNTw==", "dev": true, - "requires": { - "workbox-background-sync": "6.5.3", + "license": "MIT" + }, + "node_modules/workbox-recipes": { + "version": "6.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "workbox-cacheable-response": "6.5.3", "workbox-core": "6.5.3", + "workbox-expiration": "6.5.3", + "workbox-precaching": "6.5.3", "workbox-routing": "6.5.3", "workbox-strategies": "6.5.3" - }, - "dependencies": { - "workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - }, - "workbox-routing": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.3.tgz", - "integrity": "sha512-DFjxcuRAJjjt4T34RbMm3MCn+xnd36UT/2RfPRfa8VWJGItGJIn7tG+GwVTdHmvE54i/QmVTJepyAGWtoLPTmg==", - "dev": true, - "requires": { - "workbox-core": "6.5.3" - } - }, - "workbox-strategies": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.3.tgz", - "integrity": "sha512-MgmGRrDVXs7rtSCcetZgkSZyMpRGw8HqL2aguszOc3nUmzGZsT238z/NN9ZouCxSzDu3PQ3ZSKmovAacaIhu1w==", - "dev": true, - "requires": { - "workbox-core": "6.5.3" - } - } } }, - "workbox-navigation-preload": { + "node_modules/workbox-recipes/node_modules/idb": { + "version": "6.1.5", + "dev": true, + "license": "ISC" + }, + "node_modules/workbox-recipes/node_modules/workbox-cacheable-response": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.3.tgz", - "integrity": "sha512-bK1gDFTc5iu6lH3UQ07QVo+0ovErhRNGvJJO/1ngknT0UQ702nmOUhoN9qE5mhuQSrnK+cqu7O7xeaJ+Rd9Tmg==", "dev": true, - "requires": { - "workbox-core": "6.5.3" - }, + "license": "MIT", "dependencies": { - "workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - } + "workbox-core": "6.5.3" } }, - "workbox-precaching": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-5.1.4.tgz", - "integrity": "sha512-gCIFrBXmVQLFwvAzuGLCmkUYGVhBb7D1k/IL7pUJUO5xacjLcFUaLnnsoVepBGAiKw34HU1y/YuqvTKim9qAZA==", + "node_modules/workbox-recipes/node_modules/workbox-core": { + "version": "6.5.3", "dev": true, - "requires": { - "workbox-core": "^5.1.4" - } + "license": "MIT" }, - "workbox-range-requests": { + "node_modules/workbox-recipes/node_modules/workbox-expiration": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.5.3.tgz", - "integrity": "sha512-pGCP80Bpn/0Q0MQsfETSfmtXsQcu3M2QCJwSFuJ6cDp8s2XmbUXkzbuQhCUzKR86ZH2Vex/VUjb2UaZBGamijA==", "dev": true, - "requires": { - "workbox-core": "6.5.3" - }, + "license": "MIT", "dependencies": { - "workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - } + "idb": "^6.1.4", + "workbox-core": "6.5.3" } }, - "workbox-recipes": { + "node_modules/workbox-recipes/node_modules/workbox-precaching": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.3.tgz", - "integrity": "sha512-IcgiKYmbGiDvvf3PMSEtmwqxwfQ5zwI7OZPio3GWu4PfehA8jI8JHI3KZj+PCfRiUPZhjQHJ3v1HbNs+SiSkig==", "dev": true, - "requires": { - "workbox-cacheable-response": "6.5.3", + "license": "MIT", + "dependencies": { "workbox-core": "6.5.3", - "workbox-expiration": "6.5.3", - "workbox-precaching": "6.5.3", "workbox-routing": "6.5.3", "workbox-strategies": "6.5.3" - }, + } + }, + "node_modules/workbox-recipes/node_modules/workbox-routing": { + "version": "6.5.3", + "dev": true, + "license": "MIT", "dependencies": { - "idb": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/idb/-/idb-6.1.5.tgz", - "integrity": "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==", - "dev": true - }, - "workbox-cacheable-response": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.3.tgz", - "integrity": "sha512-6JE/Zm05hNasHzzAGKDkqqgYtZZL2H06ic2GxuRLStA4S/rHUfm2mnLFFXuHAaGR1XuuYyVCEey1M6H3PdZ7SQ==", - "dev": true, - "requires": { - "workbox-core": "6.5.3" - } - }, - "workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - }, - "workbox-expiration": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.3.tgz", - "integrity": "sha512-jzYopYR1zD04ZMdlbn/R2Ik6ixiXbi15c9iX5H8CTi6RPDz7uhvMLZPKEndZTpfgmUk8mdmT9Vx/AhbuCl5Sqw==", - "dev": true, - "requires": { - "idb": "^6.1.4", - "workbox-core": "6.5.3" - } - }, - "workbox-precaching": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.3.tgz", - "integrity": "sha512-sjNfgNLSsRX5zcc63H/ar/hCf+T19fRtTqvWh795gdpghWb5xsfEkecXEvZ8biEi1QD7X/ljtHphdaPvXDygMQ==", - "dev": true, - "requires": { - "workbox-core": "6.5.3", - "workbox-routing": "6.5.3", - "workbox-strategies": "6.5.3" - } - }, - "workbox-routing": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.3.tgz", - "integrity": "sha512-DFjxcuRAJjjt4T34RbMm3MCn+xnd36UT/2RfPRfa8VWJGItGJIn7tG+GwVTdHmvE54i/QmVTJepyAGWtoLPTmg==", - "dev": true, - "requires": { - "workbox-core": "6.5.3" - } - }, - "workbox-strategies": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.3.tgz", - "integrity": "sha512-MgmGRrDVXs7rtSCcetZgkSZyMpRGw8HqL2aguszOc3nUmzGZsT238z/NN9ZouCxSzDu3PQ3ZSKmovAacaIhu1w==", - "dev": true, - "requires": { - "workbox-core": "6.5.3" - } - } + "workbox-core": "6.5.3" + } + }, + "node_modules/workbox-recipes/node_modules/workbox-strategies": { + "version": "6.5.3", + "dev": true, + "license": "MIT", + "dependencies": { + "workbox-core": "6.5.3" } }, - "workbox-routing": { + "node_modules/workbox-routing": { "version": "5.1.4", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-5.1.4.tgz", - "integrity": "sha512-8ljknRfqE1vEQtnMtzfksL+UXO822jJlHTIR7+BtJuxQ17+WPZfsHqvk1ynR/v0EHik4x2+826Hkwpgh4GKDCw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "workbox-core": "^5.1.4" } }, - "workbox-strategies": { + "node_modules/workbox-strategies": { "version": "5.1.4", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-5.1.4.tgz", - "integrity": "sha512-VVS57LpaJTdjW3RgZvPwX0NlhNmscR7OQ9bP+N/34cYMDzXLyA6kqWffP6QKXSkca1OFo/v6v7hW7zrrguo6EA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "workbox-core": "^5.1.4", "workbox-routing": "^5.1.4" } }, - "workbox-streams": { + "node_modules/workbox-streams": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.3.tgz", - "integrity": "sha512-vN4Qi8o+b7zj1FDVNZ+PlmAcy1sBoV7SC956uhqYvZ9Sg1fViSbOpydULOssVJ4tOyKRifH/eoi6h99d+sJ33w==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "workbox-core": "6.5.3", "workbox-routing": "6.5.3" - }, + } + }, + "node_modules/workbox-streams/node_modules/workbox-core": { + "version": "6.5.3", + "dev": true, + "license": "MIT" + }, + "node_modules/workbox-streams/node_modules/workbox-routing": { + "version": "6.5.3", + "dev": true, + "license": "MIT", "dependencies": { - "workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - }, - "workbox-routing": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.3.tgz", - "integrity": "sha512-DFjxcuRAJjjt4T34RbMm3MCn+xnd36UT/2RfPRfa8VWJGItGJIn7tG+GwVTdHmvE54i/QmVTJepyAGWtoLPTmg==", - "dev": true, - "requires": { - "workbox-core": "6.5.3" - } - } + "workbox-core": "6.5.3" } }, - "workbox-sw": { + "node_modules/workbox-sw": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.3.tgz", - "integrity": "sha512-BQBzm092w+NqdIEF2yhl32dERt9j9MDGUTa2Eaa+o3YKL4Qqw55W9yQC6f44FdAHdAJrJvp0t+HVrfh8AiGj8A==", - "dev": true + "dev": true, + "license": "MIT" }, - "workbox-webpack-plugin": { + "node_modules/workbox-webpack-plugin": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.5.3.tgz", - "integrity": "sha512-Es8Xr02Gi6Kc3zaUwR691ZLy61hz3vhhs5GztcklQ7kl5k2qAusPh0s6LF3wEtlpfs9ZDErnmy5SErwoll7jBA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "fast-json-stable-stringify": "^2.1.0", "pretty-bytes": "^5.4.1", "upath": "^1.2.0", "webpack-sources": "^1.4.3", "workbox-build": "6.5.3" }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "webpack": "^4.4.0 || ^5.9.0" + } + }, + "node_modules/workbox-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workbox-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "dev": true, + "license": "MIT", "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - } + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" } }, - "workbox-window": { + "node_modules/workbox-window": { "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.5.3.tgz", - "integrity": "sha512-GnJbx1kcKXDtoJBVZs/P7ddP0Yt52NNy4nocjBpYPiRhMqTpJCNrSL+fGHZ/i/oP6p/vhE8II0sA6AZGKGnssw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "@types/trusted-types": "^2.0.2", "workbox-core": "6.5.3" - }, - "dependencies": { - "workbox-core": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.3.tgz", - "integrity": "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==", - "dev": true - } } }, - "workerpool": { + "node_modules/workbox-window/node_modules/workbox-core": { + "version": "6.5.3", + "dev": true, + "license": "MIT" + }, + "node_modules/workerpool": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", - "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, - "wrap-ansi": { + "node_modules/wrap-ansi": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - } + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "wrappy": { + "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "dev": true, + "license": "ISC" }, - "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, - "requires": { - "graceful-fs": "^4.1.11", + "dependencies": { "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } }, - "ws": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "node_modules/ws": { + "version": "8.17.1", "dev": true, - "requires": {} + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true + "node_modules/xml-name-validator": { + "version": "5.0.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } }, - "xmlchars": { + "node_modules/xmlchars": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true + "dev": true, + "license": "MIT" }, - "y18n": { + "node_modules/y18n": { "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } }, - "yallist": { + "node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "dev": true, + "license": "ISC" }, - "yaml": { + "node_modules/yaml": { "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true + "license": "ISC", + "engines": { + "node": ">= 6" + } }, - "yargs": { + "node_modules/yargs": { "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", @@ -41088,46 +21316,57 @@ "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" } }, - "yargs-parser": { + "node_modules/yargs-parser": { "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } }, - "yargs-unparser": { + "node_modules/yargs-unparser": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" }, - "dependencies": { - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - } + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/is-plain-obj": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, - "yocto-queue": { + "node_modules/yocto-queue": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "yup": { + "node_modules/yup": { "version": "0.32.11", - "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", - "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "@babel/runtime": "^7.15.4", "@types/lodash": "^4.14.175", "lodash": "^4.17.21", @@ -41135,6 +21374,9 @@ "nanoclone": "^0.2.1", "property-expr": "^2.0.4", "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" } } } diff --git a/package.json b/package.json index 57cab780a8..243fdf384f 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "license": "AGPL-3.0", "repository": "https://github.com/primeroIMS/primero", "engines": { - "node": ">=18.13.0" + "node": ">=20.14.0" }, "scripts": { "build": "NODE_ENV=production webpack --config webpack/index.js", @@ -13,18 +13,13 @@ "dev:debug": "NODE_ENV=profile npm run dev", "test": "npm run test:run './app/javascript/**/*.unit.test.js'", "test:all": "npm test", - "test:batch": "npm run test:run \"./app/javascript/components/[$BATCH_RANGE]*/**/*.unit.test.js\"", - "test:batch:1": "cross-env BATCH_RANGE=a-f npm run test:batch", - "test:batch:2": "cross-env BATCH_RANGE=f-p npm run test:batch", - "test:batch:3": "cross-env BATCH_RANGE=q-r npm run test:batch", - "test:batch:4": "cross-env BATCH_RANGE=s-z npm run test:batch", - "test:batch:5": "npm run test:run './app/javascript/!(components)/**/*.unit.test.js'", "test:inspect": "NODE_ENV=test mocha -- --inspect-brk=0.0.0.0:9229", "test:coverage": "NODE_ENV=test nyc --nycrc-path './.nycrc.yml' npm run test:all", "test:run": "NODE_ENV=test mocha --timeout 8000 --check-leaks --parallel --reporter=dot --exit", "test:all-bb": "NODE_ENV=test mocha --timeout 8000 --check-leaks --reporter=dot './app/javascript/**/*.unit.test.js'", - "test:new": "NODE_ENV=test NODE_OPTIONS='--max-old-space-size=6144' jest", - "test:new:profile": "node --inspect-brk --expose-gc ./node_modules/.bin/jest --runInBand --logHeapUsage", + "test:components": "NODE_ENV=test NODE_OPTIONS='--max-old-space-size=6144' jest --no-compilation-cache --clearMocks --forceExit", + "test:components:profile": "NODE_ENV=test NODE_OPTIONS='--max-old-space-size=6144' node --no-compilation-cache --expose-gc ./node_modules/.bin/jest --runInBand --logHeapUsage --detectOpenHandles", + "test:components:debug": "npm run test:components:profile -- --inspect-brk", "jscpd": "npm run jscpd:run 'app/javascript/**'", "jscpd:run": "jscpd", "lint": "npm run lint:run -- --fix", @@ -39,84 +34,82 @@ "uuid": "$uuid", "dom-to-image-more": "2.8.0", "immutable": "$immutable", - "xml2js": "0.5.0" + "xml2js": "0.5.0", + "@emotion/cache": "11.11.0" + }, + "resolutions": { + "tss-react": "4.9.10", + "@emotion/react": "11.11.4", + "@emotion/styled": "11.11.4" }, "devDependencies": { - "@azure/msal-browser": "^2.37.0", - "@babel/core": "~7.17.8", - "@babel/eslint-parser": "^7.17.0", + "@azure/msal-browser": "^3.17.0", + "@babel/core": "~7.24.7", + "@babel/eslint-parser": "^7.24.7", "@babel/plugin-proposal-class-properties": "~7.16.7", "@babel/plugin-proposal-object-rest-spread": "^7.17.3", "@babel/plugin-proposal-optional-chaining": "~7.16.7", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/plugin-syntax-dynamic-import": "~7.8.3", - "@babel/plugin-transform-destructuring": "~7.17.7", - "@babel/plugin-transform-regenerator": "~7.16.7", - "@babel/plugin-transform-runtime": "~7.17.0", - "@babel/preset-env": "^7.16.11", - "@babel/preset-react": "~7.16.7", - "@babel/register": "~7.17.7", + "@babel/plugin-transform-destructuring": "~7.24.7", + "@babel/plugin-transform-regenerator": "~7.24.7", + "@babel/plugin-transform-runtime": "~7.24.7", + "@babel/preset-env": "^7.24.7", + "@babel/preset-react": "~7.24.7", + "@babel/register": "~7.24.6", "@date-io/date-fns": "^1.3.13", - "@hookform/devtools": "^2.2.1", "@hookform/resolvers": "1.3.0", "@hot-loader/react-dom": "^17.0.2", - "@material-ui/core": "4.12.3", - "@material-ui/icons": "^4.11.2", - "@material-ui/lab": "^4.0.0-alpha.60", - "@material-ui/pickers": "^3.3.10", - "@material-ui/styles": "4.11.4", "@quoin/nepali-datepicker-reactjs": "^1.2.4", "@svgr/webpack": "^6.5.1", - "@swc/core": "^1.3.84", - "@swc/jest": "^0.2.29", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^12.1.4", - "@testing-library/react-hooks": "^7.0.0", - "@testing-library/user-event": "^14.4.3", - "@wojtekmaj/enzyme-adapter-react-17": "^0.4.1", + "@swc/core": "^1.5.29", + "@swc/jest": "^0.2.36", + "@testing-library/dom": "^10.1.0", + "@testing-library/jest-dom": "^6.4.6", + "@testing-library/react": "^16.0.0", + "@testing-library/react-hooks": "^8.0.1", + "@testing-library/user-event": "^14.5.2", "ad-bs-converter": "^0.5.0", "add": "^2.0.6", "babel-eslint": "^10.1.0", - "babel-jest": "^29.5.0", + "babel-jest": "^29.7.0", "babel-loader": "^8.2.3", "babel-plugin-dynamic-import-node": "^2.3.3", "babel-plugin-macros": "^3.1.0", - "babel-plugin-module-resolver": "^5.0.0", + "babel-plugin-module-resolver": "^5.0.2", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "babel-preset-react": "^6.24.1", "before-build-webpack": "^0.2.12", "bikram-sambat-js": "^1.0.1", - "blueimp-md5": "^2.13.0", + "blueimp-md5": "^2.19.0", "canvg": "^3.0.6", "chai": "^4.3.6", "chai-immutable": "^2.1.0", "chart.js": "^2.9.4", "clean-webpack-plugin": "^4.0.0", - "clsx": "^1.1.0", "compression-webpack-plugin": "^9.2.0", - "connected-react-router": "^6.8.0", - "core-js": "3.3.6", - "cross-env": "^7.0.3", + "connected-react-router": "^6.9.3", + "core-js": "3.37.1", "css-loader": "^6.7.1", - "date-fns": "2.1.0", - "deepmerge": "^4.0.0", + "date-fns": "^2.29.2", + "deepmerge": "^4.3.1", "dom-to-image-more": "2.8.0", - "dompurify": "^2.2.3", - "enzyme": "^3.11.0", + "dompurify": "^2.5.4", "eslint": "^8.11.0", "eslint-config-airbnb": "~19.0.4", "eslint-config-prettier": "~8.5.0", "eslint-import-resolver-alias": "^1.1.2", - "eslint-plugin-import": "~2.25.4", - "eslint-plugin-jest": "^27.2.1", - "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-import": "~2.29.1", + "eslint-plugin-jest": "^27.9.0", + "eslint-plugin-jsx-a11y": "^6.8.0", "eslint-plugin-prettier": "^4.0.0", - "eslint-plugin-react": "~7.29.4", - "eslint-plugin-react-hooks": "4.3.0", + "eslint-plugin-react": "~7.34.2", + "eslint-plugin-react-hooks": "4.6.2", "eslint-plugin-unused-imports": "^2.0.0", "fake-indexeddb": "^3.1.8", "file-loader": "^6.2.0", - "formik": "^2.2.9", - "formik-material-ui": "^3.0.1", + "formik": "^2.4.6", "fuzzysort": "^2.0.4", "history": "^4.9.0", "html2pdf-dom-to-image-more": "0.9.5", @@ -124,28 +117,25 @@ "idb": "^4.0.4", "identity-obj-proxy": "^3.0.0", "image-blob-reduce": "^1.0.4", - "immutable": "4.0.0-rc.12", + "immutable": "4.3.6", "jest": "^29.7.0", - "jest-environment-jsdom": "^29.5.0", + "jest-environment-jsdom": "^29.7.0", "jscpd": "^3.3.25", - "jsdom": "^16.4.0", + "jsdom": "^24.1.0", "jsdom-global": "^3.0.2", - "jspdf": "^2.3.1", - "jss": "10.8.2", - "jss-plugin-extend": "10.8.2", - "jss-rtl": "^0.3.0", + "jspdf": "^2.5.1", "keyevent": "^1.1.0", "lodash": "^4.17.21", - "mini-css-extract-plugin": "2.4.4", + "mini-css-extract-plugin": "2.9.0", "minimist-lite": "^2.2.1", "mocha": "^9.2.2", - "mui-datatables": "^3.8.5", - "mui-nepali-datepicker-reactjs": "^1.1.4", + "mui-datatables": "^4.3.0", + "mui-nepali-datepicker-reactjs": "^2.0.0", "mutationobserver-shim": "^0.3.5", "nock": "^10.0.6", - "normalizr": "^3.6.0", - "notistack": "^0.9.17", - "nyc": "^14.1.1", + "normalizr": "^3.6.2", + "notistack": "^2.0.8", + "nyc": "^17.1.0", "postcss-flexbugs-fixes": "^5.0.2", "postcss-import": "^14.0.2", "postcss-loader": "^6.2.1", @@ -153,21 +143,21 @@ "postcss-rtlcss": "^3.5.3", "prettier": "^2.6.0", "prettier-eslint": "~13.0.0", - "prop-types": "^15.7.2", + "prop-types": "^15.8.1", "proxy-memoize": "^2.0.3", - "qs": "^6.9.3", + "qs": "^6.12.1", "re-reselect": "^4.0.0", - "react": "^17.0.2", - "react-beautiful-dnd": "^13.0.0", - "react-dom": "^17.0.2", + "react": "^18.3.1", + "react-beautiful-dnd": "^13.1.1", + "react-dom": "^18.3.1", "react-hook-form": "6.15.1", - "react-idle-timer": "^5.6.2", + "react-idle-timer": "^5.7.2", "react-redux": "^7.2.4", "react-router-dom": "^5.0.1", - "react-router-navigation-prompt": "^1.8.11", + "react-router-navigation-prompt": "^1.9.6", "react-spaces": "^0.3.2", - "react-test-renderer": "^17.0.2", - "react-window": "^1.8.6", + "react-test-renderer": "^18.3.1", + "react-window": "^1.8.10", "reduce-reducers": "^1.0.4", "redux": "^4.1.0", "redux-immutable": "^4.0.0", @@ -178,12 +168,13 @@ "require-hacker": "^3.0.1", "reselect": "^4.0.0", "sinon": "^7.2.4", - "sinon-chai": "^3.5.0", + "sinon-chai": "^3.7.0", "style-loader": "^2.0.0", - "timezone-mock": "^1.0.18", + "stylis": "^4.2.0", + "timezone-mock": "^1.3.6", "uuid": "^8.3.2", - "webpack": "^5.76.0", - "webpack-assets-manifest": "^5.1.0", + "webpack": "^5.92.0", + "webpack-assets-manifest": "^5.2.1", "webpack-cli": "^4.9.2", "webpack-dev-server": "^4.7.4", "workbox-cacheable-response": "^5.1.4", @@ -207,8 +198,8 @@ "require": [ "@babel/register", "./.mochaignore.js", - "./app/javascript/test/jsdom.setup.js", - "./app/javascript/test/test.setup.js" + "./app/javascript/test-utils/jsdom.setup.js", + "./app/javascript/test-utils/globals-mocha.js" ], "exclude": [ "**/node_modules/**" @@ -223,7 +214,16 @@ "printWidth": 120 }, "dependencies": { + "@emotion/css": "^11.11.2", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "@mui/icons-material": "^5.15.20", + "@mui/lab": "^5.0.0-alpha.170", + "@mui/material": "^5.15.20", + "@mui/x-date-pickers": "^7.7.0", "@welldone-software/why-did-you-render": "^6.2.0", - "react-16-node-hanging-test-fix": "^1.0.0" + "formik-mui": "^5.0.0-alpha.0", + "stylis-plugin-rtl": "^2.1.1", + "tss-react": "^4.9.10" } } diff --git a/postcss.config.js b/postcss.config.js index f22c8726ed..9959c2c900 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -14,6 +14,6 @@ module.exports = { "nesting-rules": true }, stage: 0 - }), + }) ] }; diff --git a/spec/factories/user.rb b/spec/factories/user.rb index a69a50f1a6..1a2c1d780f 100644 --- a/spec/factories/user.rb +++ b/spec/factories/user.rb @@ -15,6 +15,7 @@ association :role, factory: :role, strategy: :build user_group_ids { [FactoryBot.create(:user_group).id] } agency_office { 'Agency Office 1' } + settings { { notifications: {} } } end factory :user_group, traits: [:active_model] do diff --git a/spec/mailers/record_action_mailer_spec.rb b/spec/mailers/record_action_mailer_spec.rb index 4a6fad51a2..8161f8527a 100644 --- a/spec/mailers/record_action_mailer_spec.rb +++ b/spec/mailers/record_action_mailer_spec.rb @@ -28,27 +28,42 @@ ) end + let(:notification_settings) do + { + notifications: { + send_mail: { + Transition::NOTIFICATION_ACTION => true, Approval::NOTIFICATION_ACTIONS_REQUEST => true, + Approval::NOTIFICATION_ACTIONS_RESPONSE => true, Transfer::NOTIFICATION_ACTION => true + } + } + } + end + describe 'approvals' do before do - clean_data(Alert, User, Role, PrimeroModule, PrimeroProgram, Field, FormSection, Lookup, UserGroup, Agency, Referral) + clean_data(Alert, User, Role, PrimeroModule, PrimeroProgram, Field, FormSection, Lookup, UserGroup, Agency, + Referral) @lookup = Lookup.create!(id: 'lookup-approval-type', unique_id: 'lookup-approval-type', name: 'approval type', lookup_values_en: [{ 'id' => 'value1', 'display_text' => 'value1' }]) role = create(:role, is_manager: true) @manager1 = create(:user, role:, email: 'manager1@primero.dev', send_mail: false, user_name: 'manager1') - @manager2 = create(:user, role:, email: 'manager2@primero.dev', send_mail: true, user_name: 'manager2') + @manager2 = create(:user, role:, email: 'manager2@primero.dev', send_mail: true, user_name: 'manager2', + settings: notification_settings) @manager3 = create( - :user, role:, email: 'manager3@primero.dev', send_mail: true, user_name: 'manager3', locale: 'ar-LB' + :user, role:, email: 'manager3@primero.dev', send_mail: true, user_name: 'manager3', locale: 'ar-LB', + settings: notification_settings ) @manager4 = create( :user, role:, email: 'manager4@primero.dev', send_mail: true, user_name: 'manager4', disabled: true ) - @owner = create(:user, user_name: 'jnelson', full_name: 'Jordy Nelson', email: 'owner@primero.dev') + @owner = create(:user, user_name: 'jnelson', full_name: 'Jordy Nelson', email: 'owner@primero.dev', + settings: notification_settings) @disabled_user = create( :user, user_name: 'duser', full_name: 'Disabled User', email: 'duser@primero.dev', disabled: true ) @arabic_owner = create(:user, user_name: 'jdoe', full_name: 'Jhon Doe', email: 'arabic_owner@primero.dev', - locale: 'ar-LB') + locale: 'ar-LB', settings: notification_settings) @child = child_with_created_by(@owner.user_name, name: 'child1', module_id: PrimeroModule::CP, case_id_display: '12345') @arabic_child = child_with_created_by( @@ -178,7 +193,8 @@ end let(:user2) do - create(:user, user_name: 'user2', full_name: 'User random', email: 'user2@primero.dev', send_mail: true) + create(:user, user_name: 'user2', full_name: 'User random', email: 'user2@primero.dev', send_mail: true, + settings: notification_settings) end let(:assign1) do Assign.create!(transitioned_by: 'jnelson', transitioned_to_user: user2, record: @child) @@ -219,7 +235,8 @@ @user1 = User.new( user_name: 'user1', role: @role, user_groups: [@group1], email: 'uzer1@test.com', send_mail: true, - agency: + agency:, + settings: notification_settings ) @user1.save(validate: false) @group2 = UserGroup.create!(name: 'Group2') @@ -227,7 +244,8 @@ user_name: 'user2', role: @role, user_groups: [@group2], email: 'uzer_to@test.com', send_mail: true, - agency: + agency:, + settings: notification_settings ) @user2.save(validate: false) @user3 = User.new( @@ -235,7 +253,8 @@ user_groups: [@group2], email: 'ar_uzer_to@test.com', send_mail: true, agency:, - locale: 'ar-LB' + locale: 'ar-LB', + settings: notification_settings ) @user3.save(validate: false) @user4 = User.new( @@ -247,6 +266,21 @@ agency: ) @user4.save(validate: false) + @user5 = User.new( + user_name: 'user5', role: @role, + user_groups: [@group2], + email: 'user5@test.com', send_mail: true, + agency:, + locale: 'ar-LB', + settings: { + notifications: { + send_mail: { + Approval::NOTIFICATION_ACTIONS_REQUEST => true + } + } + } + ) + @user5.save(validate: false) @case = Child.create( data: { name: 'Test', owned_by: 'user1', @@ -387,7 +421,7 @@ end end - describe 'transition request with diferent locale' do + describe 'transition request with different locale' do before do @user1.locale = 'ar-LB' @user1.save(validate: false) @@ -403,7 +437,12 @@ it 'renders the body' do expect(mail.text_part.body.encoded) - .to match('مستخدم بريميرو user2 من مؤسسة Test Agency يطلب أن تنقل ملكية هذا السجل من نوع Case ومعرّف') + .to match( + %(مستخدم بريميرو user2 من الهيئة Test Agency يطلب أن تنقل ملكية هذا السجل من نوع Case ومعرّف + #{@case.short_id} + بحيث يتمكنون من تقديم خدمات إدارة للشخص في منطقتهم. إذا كان التحويل مقبولا من طرفك، يرجى النقر على رابط معرف نوع السجل + Case في هذا الايميل لفتح نوع السجل Case في بريميرو والبدء بعملية التحويل.).squish + ) end end diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index b215d9f3e4..10c6fed7c0 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -1174,19 +1174,21 @@ [ FormSection.create!( unique_id: 'form1', name: 'Form 1', parent_form: 'case', form_group_id: 'form1', fields: [ - Field.new(name: Attachable::PHOTOS_FIELD_NAME, display_name: 'Photos'), - Field.new(name: Attachable::AUDIOS_FIELD_NAME, display_name: 'Recorded Audio'), - Field.new(name: Attachable::DOCUMENTS_FIELD_NAME, display_name: 'Other Documents') + Field.new(name: Attachable::PHOTOS_FIELD_NAME, display_name: 'Photos', type: Field::PHOTO_UPLOAD_BOX), + Field.new(name: Attachable::AUDIOS_FIELD_NAME, display_name: 'Recorded Audio', + type: Field::AUDIO_UPLOAD_BOX), + Field.new(name: Attachable::DOCUMENTS_FIELD_NAME, display_name: 'Other Documents', + type: Field::DOCUMENT_UPLOAD_BOX) ] ), FormSection.create!( unique_id: 'form2', name: 'Form 2', parent_form: 'case', form_group_id: 'form2', fields: [ - Field.new(name: Attachable::PHOTOS_FIELD_NAME, display_name: 'Photos') + Field.new(name: Attachable::PHOTOS_FIELD_NAME, display_name: 'Photos', type: Field::PHOTO_UPLOAD_BOX) ] ), FormSection.create!( unique_id: 'form3', name: 'Form 3', parent_form: 'case', form_group_id: 'form3', fields: [ - Field.new(name: 'current_photos', display_name: 'Current Photos') + Field.new(name: 'current_photos', display_name: 'Current Photos', type: Field::PHOTO_UPLOAD_BOX) ] ) ] @@ -1197,11 +1199,18 @@ context 'when a user can access a record' do context 'and read access is permitted' do before do + clean_data(PrimeroModule) permission = Permission.new(resource: Permission::CASE, actions: [Permission::READ]) + primero_module = PrimeroModule.new( + unique_id: PrimeroModule::CP, name: 'Primero Module CP', associated_record_types: %w[case] + ) role = Role.new_with_properties( name: 'read_attachment', permissions: [permission], form_section_read_write: { form1: 'r' } ) role.save! + primero_module.form_sections = [form_sections.first] + primero_module.roles = [role] + primero_module.save! attachment_user.role = role attachment_user.save! end @@ -1223,11 +1232,18 @@ context 'and write access is permitted' do before do + clean_data(PrimeroModule) + primero_module = PrimeroModule.new( + unique_id: PrimeroModule::CP, name: 'Primero Module CP', associated_record_types: %w[case] + ) permission = Permission.new(resource: Permission::CASE, actions: [Permission::READ]) role = Role.new_with_properties( name: 'write_attachment', permissions: [permission], form_section_read_write: { form1: 'rw' } ) role.save! + primero_module.form_sections = [form_sections.first] + primero_module.roles = [role] + primero_module.save! attachment_user.role = role attachment_user.save! end @@ -1249,11 +1265,18 @@ context 'and can view audio for potential matches' do before do + clean_data(PrimeroModule) + primero_module = PrimeroModule.new( + unique_id: PrimeroModule::CP, name: 'Primero Module CP', associated_record_types: %w[case] + ) permission = Permission.new(resource: Permission::POTENTIAL_MATCH, actions: [Permission::VIEW_AUDIO]) role = Role.new_with_properties( name: 'read_audio_potential_match', permissions: [permission], form_section_read_write: {} ) role.save! + primero_module.form_sections = [form_sections.first] + primero_module.roles = [role] + primero_module.save! attachment_user.role = role attachment_user.save! end @@ -1310,11 +1333,18 @@ context 'and is a referred record' do context 'and the authorized role permits read access' do before do + clean_data(PrimeroModule) + primero_module = PrimeroModule.new( + unique_id: PrimeroModule::CP, name: 'Primero Module CP', associated_record_types: %w[case] + ) permission = Permission.new(resource: Permission::CASE, actions: [Permission::READ]) role = Role.new_with_properties( unique_id: 'referred_read_attachment', name: 'referred_read_attachment', permissions: [permission], form_section_read_write: { form1: 'r' } ) + primero_module.form_sections = [form_sections.first] + primero_module.roles = [role] + primero_module.save! role.save! Referral.create!( transitioned_by_user: attachment_user, transitioned_to_user: referred_user, record: child_with_attachment, @@ -1339,12 +1369,19 @@ context 'and the authorized role permits write access' do before do + clean_data(PrimeroModule) + primero_module = PrimeroModule.new( + unique_id: PrimeroModule::CP, name: 'Primero Module CP', associated_record_types: %w[case] + ) permission = Permission.new(resource: Permission::CASE, actions: [Permission::READ]) role = Role.new_with_properties( unique_id: 'referred_write_attachment', name: 'referred_write_attachment', permissions: [permission], form_section_read_write: { form1: 'rw' } ) role.save! + primero_module.form_sections = [form_sections.first] + primero_module.roles = [role] + primero_module.save! Referral.create!( transitioned_by_user: attachment_user, transitioned_to_user: referred_user, record: child_with_attachment, authorized_role_unique_id: 'referred_write_attachment' diff --git a/spec/models/approval_spec.rb b/spec/models/approval_spec.rb index c4bf0e16bb..9bd9779bd2 100644 --- a/spec/models/approval_spec.rb +++ b/spec/models/approval_spec.rb @@ -6,7 +6,7 @@ describe Approval do before :each do - clean_data(SystemSettings, User, Role, Agency, Incident, Child, Alert, PrimeroModule, PrimeroProgram, FormSection) + clean_data(SystemSettings, Alert, User, Role, Agency, Incident, Child, PrimeroModule, PrimeroProgram, FormSection) SystemSettings.create!( approval_forms_to_alert: { cp_bia_form: 'assessment', @@ -271,10 +271,9 @@ describe '.approve!' do context 'and record has many alerts' do before do - Alert.create(type: Approval::ACTION_PLAN, alert_for: 'approval', date: Date.today, record_id: @case.id, - record_type: @case.class) - Alert.create(type: Approval::GBV_CLOSURE, alert_for: 'approval', date: Date.today, record_id: @case.id, - record_type: @case.class) + @case.add_alert(type: Approval::ACTION_PLAN, alert_for: 'approval', date: Date.today) + @case.add_alert(type: Approval::GBV_CLOSURE, alert_for: 'approval', date: Date.today) + @case.save! @approval = Approval.get!( Approval::ACTION_PLAN, @case, @@ -286,6 +285,7 @@ it 'should delete one alert for the approval type' do expect(@case.alerts.count).to eq(2) @approval.approve! + @case.alerts.reload expect(@case.alerts.count).to eq(1) end end @@ -294,13 +294,7 @@ describe '.perform!' do context 'and record has alerts' do before do - Alert.create( - type: Approval::ACTION_PLAN, - alert_for: 'approval', - date: Date.today, - record_id: @case.id, - record_type: @case.class - ) + @case.add_alert(type: Approval::ACTION_PLAN, alert_for: 'approval', date: Date.today) @approval = Approval.get!( Approval::ACTION_PLAN, @case, @@ -308,10 +302,12 @@ approval_status: Approval::APPROVAL_STATUS_REQUESTED ) @case.update_properties(@user, { consent_for_services: true }) + @case.save! @approval.perform!(Approval::APPROVAL_STATUS_APPROVED) end it 'should delete one alert for the approval type' do + @case.alerts.reload expect(@case.alerts.count).to eq(0) end diff --git a/spec/models/attachements_spec.rb b/spec/models/attachements_spec.rb index cd37aacf72..ee0bc6baf1 100644 --- a/spec/models/attachements_spec.rb +++ b/spec/models/attachements_spec.rb @@ -24,7 +24,6 @@ @record_updated_on = child.last_updated_at child.reload attachment.attach! - Sunspot.commit end it 'attaches a base64 encoded file' do @@ -32,7 +31,11 @@ end it 'has_photo is true for the record' do - expect(Child.search { with(:has_photo, true) }.results.size).to eq(1) + expect( + PhoneticSearchService.search( + Child, { filters: [SearchFilters::Value.new(field_name: 'has_photo', value: true)] } + ).total + ).to eq(1) end xit 'updates the associated record' do @@ -49,7 +52,6 @@ attachment.attach! child.reload attachment.detach! - Sunspot.commit end it 'detaches the file and removes the attachment record' do @@ -58,7 +60,11 @@ end it 'has_photo is false for the record' do - expect(Child.search { with(:has_photo, true) }.results.size).to eq(0) + expect( + PhoneticSearchService.search( + Child, { filters: [SearchFilters::Value.new(field_name: 'has_photo', value: true)] } + ).total + ).to eq(0) end xit 'updates the associated record' do @@ -127,10 +133,53 @@ file_name: 'jorge.jpg', attachment: attachment_base64('jorge.jpg'), comments: 'not this one!' ) expect { attachment.attach! }.to raise_error(ActiveRecord::RecordInvalid) - expect(child.valid?).to be_falsey + expect(attachment.errors.full_messages).to eq ['errors.attachments.maximum'] expect(attachment.persisted?).to be_falsey end end + + context 'when maximum_attachments_per_record is set in SystemSettings' do + before :each do + clean_data(SystemSettings) + SystemSettings.create!( + system_options: { + maximum_attachments_per_record: 2 + } + ) + SystemSettings.stub(:current).and_return(SystemSettings.first) + SystemSettings.current.maximum_attachments_per_record.times.each do |i| + Attachment.new( + record: child, field_name: 'photos', attachment_type: Attachment::IMAGE, + file_name: 'jorge.jpg', attachment: attachment_base64('jorge.jpg'), comments: i.to_s + ).attach! + end + child.reload + end + + it 'disallows attaching more than 3 documents to a single record' do + attachment = Attachment.new( + record: child, field_name: 'photos', attachment_type: Attachment::IMAGE, + file_name: 'jorge.jpg', attachment: attachment_base64('jorge.jpg'), comments: 'not this one!' + ) + expect(child.attachments.count).to eq SystemSettings.current.maximum_attachments_per_record + expect { attachment.attach! }.to raise_error(ActiveRecord::RecordInvalid) + expect(attachment.errors.full_messages).to eq ['errors.attachments.maximum'] + expect(attachment.persisted?).to be_falsey + end + + it 'allows to perform updates on existing attachments' do + attachment = Attachment.first + attachment.comments = 'More comments' + attachment.save! + attachment.reload + + expect(attachment.comments).to eq('More comments') + end + + after :each do + clean_data(SystemSettings) + end + end end after(:each) do diff --git a/spec/models/bulk_export_spec.rb b/spec/models/bulk_export_spec.rb index 8340c49d86..72320efd54 100644 --- a/spec/models/bulk_export_spec.rb +++ b/spec/models/bulk_export_spec.rb @@ -3,10 +3,9 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. require 'rails_helper' -require 'sunspot' require 'roo' -describe BulkExport, search: true do +describe BulkExport, { search: true } do before :each do clean_data(BulkExport, Location, UserGroup, User, Agency, Role, Field, FormSection, Child, PrimeroModule, PrimeroProgram, SystemSettings, @@ -25,11 +24,13 @@ ] ) primero_module = create(:primero_module) - role = create(:role, form_sections: [@form_section], modules: [primero_module]) + role = create(:role, form_sections: [@form_section], modules: [primero_module], group_permission: Permission::SELF) @user = create(:user, role:) end describe 'custom bulk export' do + let(:child1) { Child.create!(data: { age: 5, owned_by: @user.user_name }) } + let(:child2) { Child.create!(data: { age: 10 }) } let(:bulk_export) do BulkExport.new( format: Exporters::SelectedFieldsExcelExporter.id, @@ -46,9 +47,20 @@ book.sheet(book.sheets.first) end + before do + child1 + child2 + end + it 'exports only the selected fields for cases' do expect(export_spreadsheet.row(1)).to eq %w[ID Age] end + + it 'exports only the record in the user scope' do + expect(export_spreadsheet.count).to eq(2) + expect(export_spreadsheet.row(1)).to eq %w[ID Age] + expect(export_spreadsheet.row(2)).to eq([child1.short_id, child1.age]) + end end after :each do diff --git a/spec/models/child_spec.rb b/spec/models/child_spec.rb index 0c4ec8ee80..d5b7dd10f9 100644 --- a/spec/models/child_spec.rb +++ b/spec/models/child_spec.rb @@ -3,12 +3,12 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. require 'rails_helper' -require 'sunspot' +require 'sunspot' if Rails.configuration.solr_enabled describe Child do - describe 'quicksearch', search: true do + describe 'quicksearch' do before do - clean_data(Child, Family) + clean_data(SearchableIdentifier, Child, Family) end it 'has a searchable case id, survivor number' do @@ -16,9 +16,9 @@ end it 'can find a child by survivor code' do - child = Child.create!(data: { name: 'Lonnie', survivor_code_no: 'ABC123XYZ' }) - child.index! - search_result = SearchService.search(Child, query: 'ABC123XYZ').results + Child.create!(data: { name: 'Lonnie', survivor_code_no: 'ABC123XYZ' }) + + search_result = PhoneticSearchService.search(Child, query: 'ABC123XYZ').records expect(search_result).to have(1).child expect(search_result.first.survivor_code_no).to eq('ABC123XYZ') end @@ -27,21 +27,26 @@ family = Family.create!( family_number: '4225', family_members: [ - { unique_id: '123', relation_name: 'Family Name',relation_age: 5, relation_sex: "male" } + { unique_id: '123', relation_name: 'Family Name', relation_age: 5, relation_sex: 'male' } ] ) + child = Child.create!(data: { name: 'Lonnie', survivor_code_no: 'ABC123XYZ' }) child.family = family child.save! - child.index! - search_result = SearchService.search(Child, query: '4225').results + filter = SearchFilters::TextValue.new(field_name: 'family_number', value: '4225') + search_result = PhoneticSearchService.search(Child, filters: [filter]).records expect(search_result).to have(1).child expect(search_result.first.family_number).to eq('4225') end end describe 'update_properties' do + before do + clean_data(SearchableIdentifier, Child) + end + it 'should replace old properties with updated ones' do child = Child.new(data: { 'name' => 'Dave', 'age' => 28, 'last_known_location' => 'London' }) new_properties = { 'name' => 'Dave', 'age' => 35 } @@ -74,6 +79,7 @@ let(:uuid) { SecureRandom.uuid } before do + clean_data(SearchableIdentifier, Child) data = case1.data.clone data['incident_details'] = [ { 'unique_id' => incident1.id, 'description' => 'incident1 - modified' }, @@ -114,7 +120,7 @@ describe 'registry_record' do before do - clean_data(Child, RegistryRecord) + clean_data(SearchableIdentifier, Child, RegistryRecord) end let(:registry_record1) { RegistryRecord.create!(registry_type: 'farmer') } @@ -128,13 +134,13 @@ end after do - clean_data(Child, RegistryRecord) + clean_data(SearchableIdentifier, Child, RegistryRecord) end end describe 'family record' do before do - clean_data(Child, Family) + clean_data(SearchableIdentifier, Child, Family) end let(:family1) do @@ -441,7 +447,8 @@ describe 'record ownership' do before do - clean_data(User, Agency, Incident, Child, Role, PrimeroModule, PrimeroProgram, UserGroup, FormSection) + clean_data(SearchableIdentifier, User, Agency, Incident, Child, Role, PrimeroModule, PrimeroProgram, UserGroup, + FormSection) @owner = create :user @previous_owner = create :user @@ -456,13 +463,15 @@ end after do - clean_data(User, Agency, Incident, Child, Role, PrimeroModule, PrimeroProgram, UserGroup, FormSection) + clean_data(SearchableIdentifier, User, Agency, Incident, Child, Role, PrimeroModule, PrimeroProgram, UserGroup, + FormSection) end end describe 'case id code' do before do - clean_data(User, Location, Role, Agency, PrimeroModule, PrimeroProgram, UserGroup, SystemSettings) + clean_data(SearchableIdentifier, User, Location, Role, Agency, PrimeroModule, PrimeroProgram, UserGroup, + SystemSettings) @permission_case ||= Permission.new( resource: Permission::CASE, @@ -622,13 +631,14 @@ end after do - clean_data(User, Location, Role, Agency, PrimeroModule, PrimeroProgram, UserGroup, SystemSettings) + clean_data(SearchableIdentifier, User, Location, Role, Agency, PrimeroModule, PrimeroProgram, UserGroup, + SystemSettings) end end describe 'syncing of protection concerns' do before do - clean_data(Child) + clean_data(SearchableIdentifier, Child) User.stub(:find_by_user_name).and_return(double(organization: double(unique_id: 'UNICEF'))) @protection_concerns = %w[Separated Unaccompanied] end @@ -665,13 +675,13 @@ end after do - clean_data(Child) + clean_data(SearchableIdentifier, Child) end end describe '.match_criteria' do before do - clean_data(Child) + clean_data(SearchableIdentifier, Child) end let(:case1) do @@ -729,13 +739,13 @@ end after do - clean_data(Child) + clean_data(SearchableIdentifier, Child) end end context 'testing service_implemented field' do before do - clean_data(Child) + clean_data(SearchableIdentifier, Child) end it 'not_implemented in service_implemented field' do @@ -764,13 +774,13 @@ end after do - clean_data(Child) + clean_data(SearchableIdentifier, Child) end end describe 'current care arrangements' do before do - clean_data(Child) + clean_data(SearchableIdentifier, Child) end context 'when all care arrangements have a start date' do @@ -913,7 +923,7 @@ end after :each do - clean_data(Child) + clean_data(SearchableIdentifier, Child) end let(:most_recent_care_arrangement) { case1.most_recent_care_arrangement } @@ -979,7 +989,7 @@ end after :each do - clean_data(Child) + clean_data(SearchableIdentifier, Child) end let(:most_recent_care_arrangement) { case1.most_recent_care_arrangement } @@ -1007,37 +1017,51 @@ end end after do - clean_data(Child) + clean_data(SearchableIdentifier, Child) end end describe 'urgent_protection_concern', search: true do it 'finds cases where the value is stored as string true' do child = Child.create!(data: { name: 'Lonnie', urgent_protection_concern: 'true' }) - child.index! - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Child, - filters: [SearchFilters::Value.new(field_name: 'urgent_protection_concern', value: true)] - ).results + filters: [SearchFilters::BooleanValue.new(field_name: 'urgent_protection_concern', value: true)] + ).records expect(search_result).to have(1).child expect(search_result.first.id).to eq(child.id) end it 'finds cases where the value is stored as string false' do child = Child.create!(data: { name: 'Lonnie', urgent_protection_concern: 'false' }) - child.index! - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Child, - filters: [SearchFilters::Value.new(field_name: 'urgent_protection_concern', value: false)] - ).results + filters: [SearchFilters::BooleanValue.new(field_name: 'urgent_protection_concern', value: false)] + ).records expect(search_result).to have(1).child expect(search_result.first.id).to eq(child.id) end + + context 'when fields store values string or boolean' do + let!(:record1) { Child.create!(data: { name: 'Foo', urgent_protection_concern: 'true' }) } + let!(:record2) { Child.create!(data: { name: 'Bar', urgent_protection_concern: true }) } + let!(:record3) { Child.create!(data: { name: 'Random', age: 2 }) } + + it 'finds cases where the value is stored as string or boolean' do + search_result = PhoneticSearchService.search( + Child, + filters: [SearchFilters::BooleanValue.new(field_name: 'urgent_protection_concern', value: true)] + ).records + + expect(search_result).to have(2).child + expect(search_result.map(&:id)).to match_array([record1.id, record2.id]) + end + end end describe 'calculate_has_case_plan' do before do - clean_data(Child) + clean_data(SearchableIdentifier, Child) end let(:child1) do @@ -1080,13 +1104,13 @@ end after do - clean_data(Child) + clean_data(SearchableIdentifier, Child) end end describe 'family_members' do before do - clean_data(Child) + clean_data(SearchableIdentifier, Child) end let(:member_unique_id1) { SecureRandom.uuid } @@ -1123,12 +1147,61 @@ end after do - clean_data(Child) + clean_data(SearchableIdentifier, Child) + end + end + + describe 'phonetic tokens' do + before do + clean_data(SearchableIdentifier, Child) + end + + it 'generates the phonetic tokens' do + child = Child.create!(data: { name: 'George', name_nickname: 'Wolf', name_other: 'Joe' }) + expect(child.tokens).to eq(%w[JRJ ALF J]) + end + end + + describe 'reunification_dates' do + before do + clean_data(SearchableIdentifier, Child) + end + + it 'stores the reunification_dates' do + child = Child.create!( + data: { + age: 2, sex: 'male', name: 'Random Name', reunification_details_section: [ + { 'unique_id' => '4b7c1011-a63e-422c-b6fb-a64cdcc2d472', 'date_reunification' => '2021-12-08' }, + { 'unique_id' => 'f732a61c-cdae-435c-9c0c-55a893321fed', 'date_reunification' => '2022-02-12' } + ] + } + ) + + expect(child.reunification_dates).to eq([Date.new(2021, 12, 8), Date.new(2022, 2, 12)]) + end + end + + describe 'tracing_dates' do + before do + clean_data(SearchableIdentifier, Child) + end + + it 'stores the tracing_dates' do + child = Child.create!( + data: { + age: 2, sex: 'male', name: 'Random Name', tracing_actions_section: [ + { 'unique_id' => '4b7c1011-a63e-422c-b6fb-a64cdcc2d472', 'date_tracing' => '2022-05-09' }, + { 'unique_id' => 'f732a61c-cdae-435c-9c0c-55a893321fed', 'date_tracing' => '2023-07-08' } + ] + } + ) + + expect(child.tracing_dates).to eq([Date.new(2022, 5, 9), Date.new(2023, 7, 8)]) end end after do - clean_data(Incident, Child, Field, FormSection, PrimeroModule) + clean_data(SearchableIdentifier, Incident, Child, Field, FormSection, PrimeroModule) end private diff --git a/spec/models/concerns/alertable_spec.rb b/spec/models/concerns/alertable_spec.rb index 46375ec692..8741422386 100644 --- a/spec/models/concerns/alertable_spec.rb +++ b/spec/models/concerns/alertable_spec.rb @@ -75,6 +75,7 @@ @group_a = UserGroup.create!(name: 'Group1') @group_b = UserGroup.create!(name: 'Group2') @group_c = UserGroup.create!(name: 'Group3') + @group_d = UserGroup.create!(name: 'Group4') @user_a = User.create!( full_name: 'Test User 1', user_name: 'test_user_1', @@ -103,7 +104,7 @@ email: 'test_user_3@localhost.com', agency_id: agency_b.id, role: role_group, - user_groups: [@group_a] + user_groups: [@group_a, @group_d] ) @user_d = User.create!( full_name: 'Test User 4', @@ -246,7 +247,9 @@ transitioned_by: 'test_user_2', transitioned_to: 'test_user_4', record: @test_class, type: Transfer.name, consent_overridden: true ) - child_tranferred = Child.create(name: 'bar', data: { owned_by: @user_c.user_name, module_id: 'primeromodule-cp' }) + child_tranferred = Child.create(name: 'bar', + data: { owned_by: @user_c.user_name, + module_id: 'primeromodule-cp' }) Transfer.create!( transitioned_by: 'test_user_3', transitioned_to: 'test_user_1', record: child_tranferred, type: Transfer.name, consent_overridden: true diff --git a/spec/models/concerns/family_linkable_spec.rb b/spec/models/concerns/family_linkable_spec.rb index 7349563785..517bb840ba 100644 --- a/spec/models/concerns/family_linkable_spec.rb +++ b/spec/models/concerns/family_linkable_spec.rb @@ -5,7 +5,7 @@ require 'rails_helper' describe FamilyLinkable do - before(:each) { clean_data(User, Child, Family) } + before(:each) { clean_data(SearchableIdentifier, User, Child, Family) } let(:user) do user = User.new(user_name: 'user_cp', full_name: 'Test User CP') diff --git a/spec/models/concerns/follow_upable_spec.rb b/spec/models/concerns/follow_upable_spec.rb index beb4ded94e..5e656294b8 100644 --- a/spec/models/concerns/follow_upable_spec.rb +++ b/spec/models/concerns/follow_upable_spec.rb @@ -78,6 +78,27 @@ end end + describe 'followup_dates' do + it 'stores the followup_dates' do + @child.followup_subform_section = [ + { + 'unique_id' => '4b7c1011-a63e-422c-b6fb-a64cdcc2d472', + 'followup_type' => 'visit1', + 'followup_child_labor' => 'in_child_labor', + 'followup_date' => '2022-10-04' + }, + { + 'unique_id' => 'f732a61c-cdae-435c-9c0c-55a893321fed', + 'followup_type' => 'visit2', + 'followup_child_labor' => 'in_child_labor', + 'followup_date' => '2022-12-04' + } + ] + @child.save! + expect(@child.reload.followup_dates).to eq([Date.new(2022, 10, 4), Date.new(2022, 12, 4)]) + end + end + after :each do clean_data(Child) end diff --git a/spec/models/concerns/historical_spec.rb b/spec/models/concerns/historical_spec.rb index b7c9d054a3..0d718dcd60 100644 --- a/spec/models/concerns/historical_spec.rb +++ b/spec/models/concerns/historical_spec.rb @@ -52,7 +52,7 @@ it 'should insert a creation history with correct record_changes' do # TODO: Not a very good test. What changes are expected? - expect(@inst.histories.first.record_changes.size).to eq(20) + expect(@inst.histories.first.record_changes.size).to eq(32) end # TODO: This is disabled for now. OK behavior, no? diff --git a/spec/models/concerns/monitoring_reporting_mechanism_spec.rb b/spec/models/concerns/monitoring_reporting_mechanism_spec.rb index 1e9c680370..5353dc010e 100644 --- a/spec/models/concerns/monitoring_reporting_mechanism_spec.rb +++ b/spec/models/concerns/monitoring_reporting_mechanism_spec.rb @@ -5,7 +5,7 @@ require 'rails_helper' describe MonitoringReportingMechanism, search: true do - let(:user_1) do + let(:user1) do primero_module = PrimeroModule.new(name: 'CP') role = Role.new(permissions: [], modules: [primero_module]) @@ -18,17 +18,18 @@ user end - let(:incident_1) do + let(:incident1) do incident1 = Incident.new_with_user( - user_1, + user1, { 'incident_date' => '2022-04-08', + 'module_id' => PrimeroModule::MRM, 'killing' => [ { 'unique_id' => 'b23b70de-9132-4c89-be8d-57e85a69ec68', 'ctfmr_verified' => 'verified', 'ctfmr_verified_date' => Date.today.beginning_of_quarter, - 'verified_ghn_reported' => ['2022-q2'], + 'verified_ghn_reported' => '2022-q2', 'type' => 'killing' } ], @@ -58,14 +59,15 @@ incident1 end - let(:incident_2) do + let(:incident2) do incident2 = Incident.new_with_user( - user_1, + user1, { + 'module_id' => PrimeroModule::MRM, 'killing' => [ { 'unique_id' => 'f37ccb6e-9f85-473e-890e-7037e8ece397', - 'verified_ghn_reported' => ['2022-q1'], + 'verified_ghn_reported' => '2022-q1', 'type' => 'killing', 'ctfmr_verified_date' => Date.today.end_of_quarter, 'weapon_type' => 'airstrike' @@ -108,10 +110,11 @@ incident2 end - let(:incident_3) do + let(:incident3) do incident3 = Incident.new_with_user( - user_1, + user1, { + 'module_id' => PrimeroModule::MRM, 'killing' => [ { 'type' => 'killing', 'ctfmr_verified' => 'not_mrm', 'ctfmr_verified_date' => Date.today.end_of_quarter } ], @@ -125,10 +128,11 @@ incident3 end - let(:incident_4) do + let(:incident4) do incident4 = Incident.new_with_user( - user_1, + user1, { + 'module_id' => PrimeroModule::MRM, 'military_use' => [ { 'type' => 'military_use', @@ -151,14 +155,15 @@ incident4 end - let(:incident_5) do + let(:incident5) do incident5 = Incident.new_with_user( - user_1, + user1, { + 'module_id' => PrimeroModule::MRM, 'attack_on_hospitals' => [ { 'type' => 'attack_on_hospitals', - 'facility_attack_type' => %w[attack_on_medical_personnel threat_of_attack_on_hospital_s], + 'facility_attack_type' => %w[attack_on_medical_personnel threat_of_attack_on_hospital], 'facility_impact' => 'serious_damage' } ], @@ -173,39 +178,37 @@ before do clean_data(User, UserGroup, Role, PrimeroModule, Incident, Violation, IndividualVictim) - incident_1 - incident_2 - incident_3 - incident_4 - incident_5 - Incident.reindex - Sunspot.commit + incident1 + incident2 + incident3 + incident4 + incident5 end it 'can find incidents where individual victims are linked to a violation type' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'individual_violations', value: 'maiming') + SearchFilters::TextValue.new(field_name: 'individual_violations', value: 'maiming') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_2.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident2.id) end it 'can find incidents where individual victims have an age' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'individual_age', value: '10') + SearchFilters::Value.new(field_name: 'individual_age', value: 10) ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_1.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident1.id) end it 'contains the violations with verification status' do - expect(incident_3.violation_with_verification_status).to match_array( + expect(incident3.violation_with_verification_status).to match_array( %w[ killing_not_mrm maiming_report_pending_verification ] @@ -213,276 +216,314 @@ end it 'can find an incident with a violation of type killing and verified' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'violation_with_verification_status', value: 'killing_verified') + SearchFilters::TextValue.new(field_name: 'violation_with_verification_status', value: 'killing_verified') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_1.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident1.id) end it 'can find incidents where individual victims have a sex' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'individual_sex', value: 'female') + SearchFilters::TextValue.new(field_name: 'individual_sex', value: 'female') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_2.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident2.id) end it 'can find incidents where individual victims have a victim_deprived_liberty_security_reasons' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'victim_deprived_liberty_security_reasons', value: 'unknown') + SearchFilters::TextValue.new(field_name: 'victim_deprived_liberty_security_reasons', value: 'unknown') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_2.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident2.id) end it 'can find incidents where individual victims have a reasons_deprivation_liberty' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'reasons_deprivation_liberty', value: 'reason_1') + SearchFilters::TextValue.new(field_name: 'reasons_deprivation_liberty', value: 'reason_1') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_1.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident1.id) end it 'can find incidents where individual victims have a facilty_victims_held' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'victim_facilty_victims_held', value: 'facility_2') + SearchFilters::TextValue.new(field_name: 'victim_facilty_victims_held', value: 'facility_2') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_2.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident2.id) end it 'can find incidents where individual victims have a torture_punishment_while_deprivated_liberty' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new( + SearchFilters::TextValue.new( field_name: 'torture_punishment_while_deprivated_liberty', value: 'no' ) ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_1.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident1.id) end it 'can find an incident with a violation of type maiming and report_pending_verification' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new( + SearchFilters::TextValue.new( field_name: 'violation_with_verification_status', value: 'maiming_report_pending_verification' ) ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_3.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident3.id) end it 'can find an incident by verification_status' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'verification_status', value: 'not_mrm') + SearchFilters::TextValue.new(field_name: 'verification_status', value: 'not_mrm') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_3.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident3.id) end it 'can find an incident by armed_force_group_party_names' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'armed_force_group_party_names', value: 'other') + SearchFilters::TextValue.new(field_name: 'armed_force_group_party_names', value: 'other') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_2.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident2.id) end it 'can find an incident by verified_ghn_reported' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::ValueList.new(field_name: 'verified_ghn_reported', values: %w[2022-q1 2022-q2]) + SearchFilters::TextList.new(field_name: 'verified_ghn_reported', values: %w[2022-q1 2022-q2]) ], - sort: { 'short_id': 'asc' } - ).results + sort: { 'short_id' => 'asc' } + ) - expect(search_result.size).to eq(2) - expect(search_result.map(&:id)).to match_array([incident_1.id, incident_2.id]) + expect(search_result.total).to eq(2) + expect(search_result.records.map(&:id)).to match_array([incident1.id, incident2.id]) end it 'can find an incident by violation_with_weapon_type' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'violation_with_weapon_type', value: 'killing_airstrike') + SearchFilters::TextValue.new(field_name: 'violation_with_weapon_type', value: 'killing_airstrike') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_2.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident2.id) end it 'can find an incident by violation_with_facility_impact' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'violation_with_facility_impact', value: 'military_use_total_destruction') + SearchFilters::TextValue.new( + field_name: 'violation_with_facility_impact', value: 'military_use_total_destruction' + ) ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_4.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident4.id) end it 'can find an incident by child_role' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'child_role', value: 'combatant') + SearchFilters::TextValue.new(field_name: 'child_role', value: 'combatant') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_4.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident4.id) end it 'can find an incident by abduction_purpose_single' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'abduction_purpose_single', value: 'extortion') + SearchFilters::TextValue.new(field_name: 'abduction_purpose_single', value: 'extortion') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_4.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident4.id) end it 'can find an incident by violation_with_facility_attack_type' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new( + SearchFilters::TextValue.new( field_name: 'violation_with_facility_attack_type', value: 'attack_on_hospitals_attack_on_medical_personnel' ) ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_5.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident5.id) end it 'can find an incident by military_use_type' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'military_use_type', value: 'military_use_of_school') + SearchFilters::TextValue.new(field_name: 'military_use_type', value: 'military_use_of_school') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_4.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident4.id) end it 'can find an incident by types_of_aid_disrupted_denial' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'types_of_aid_disrupted_denial', value: 'food') + SearchFilters::TextValue.new(field_name: 'types_of_aid_disrupted_denial', value: 'food') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_5.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident5.id) end it 'can find an incident by facility_attack_type' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new( + SearchFilters::TextValue.new( field_name: 'facility_attack_type', - value: 'threat_of_attack_on_hospital_s' + value: 'threat_of_attack_on_hospital' ) ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_5.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident5.id) end it 'can find an incident by facility_impact' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new( + SearchFilters::TextValue.new( field_name: 'facility_impact', value: 'serious_damage' ) ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_5.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident5.id) end it 'can find an incident by weapon_type' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::Value.new(field_name: 'weapon_type', value: 'baton') + SearchFilters::TextValue.new(field_name: 'weapon_type', value: 'baton') ] - ).results - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_4.id) + ) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident4.id) end it 'can find an incident with a late verified violation' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::ValueList.new(field_name: 'late_verified_violations', values: %w[killing]) + SearchFilters::TextList.new(field_name: 'late_verified_violations', values: %w[killing]) ], - sort: { 'short_id': 'asc' } - ).results + sort: { 'short_id' => 'asc' } + ) - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_1.id) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident1.id) end it 'can find an incident by type of perpetrator' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::ValueList.new(field_name: 'perpetrator_category', values: %w[crossfire]) + SearchFilters::TextList.new(field_name: 'perpetrator_category', values: %w[crossfire]) ], - sort: { 'short_id': 'asc' } - ).results + sort: { 'short_id' => 'asc' } + ) - expect(search_result.size).to eq(1) - expect(search_result.first.id).to eq(incident_1.id) + expect(search_result.total).to eq(1) + expect(search_result.records.first.id).to eq(incident1.id) end it 'can find an incident by ctfmr_verified_date' do - search_result = SearchService.search( + search_result = PhoneticSearchService.search( Incident, filters: [ - SearchFilters::ValueList.new(field_name: 'ctfmr_verified_date', values: [Date.today.end_of_quarter]) + SearchFilters::TextList.new(field_name: 'ctfmr_verified_date', values: [Date.today.end_of_quarter]) ], - sort: { 'short_id': 'asc' } - ).results + sort: { 'short_id' => 'asc' } + ) + + expect(search_result.total).to eq(2) + expect(search_result.records.map(&:id)).to match_array([incident2.id, incident3.id]) + end + + it 'the records has been stamped with fields from violations' do + expect(incident1.individual_violations).to match_array(%w[killing]) + expect(incident1.individual_sex).to match_array(%w[male]) + expect(incident1.victim_deprived_liberty_security_reasons).to match_array(%w[yes]) + expect(incident1.reasons_deprivation_liberty).to match_array(%w[reason_1]) + expect(incident1.victim_facilty_victims_held).to match_array(%w[facility_1]) + expect(incident1.torture_punishment_while_deprivated_liberty).to match_array(%w[no]) + expect(incident1.armed_force_group_party_names).to match_array(%w[armed_force_1]) + expect(incident1.perpetrator_category).to match_array(%w[crossfire]) + expect(incident1.violation_with_verification_status).to match_array(%w[killing_verified]) + expect(incident1.verified_ghn_reported).to match_array(%w[2022-q2]) + expect(incident1.ctfmr_verified_date).to match_array([Date.today.beginning_of_quarter]) + expect(incident5.facility_attack_type).to match_array(%w[attack_on_medical_personnel threat_of_attack_on_hospital]) + end + + it 'recalculates the stamped fields' do + incident1.update_properties( + user1, + 'perpetrators' => [ + { + 'unique_id' => 'a32b70de-9132-4c89-be8d-67e85a69ec68', + 'perpetrator_category' => 'category2' + }, + { + 'unique_id' => '23e9b1ba-2f25-11ef-8c62-18c04db5c362', + 'armed_force_group_party_name' => 'armed_force_2', + 'violations_ids' => ['b23b70de-9132-4c89-be8d-57e85a69ec68'] + } + ] + ) + incident1.save! - expect(search_result.size).to eq(2) - expect(search_result.map(&:id)).to match_array([incident_2.id, incident_3.id]) + expect(incident1.perpetrator_category).to match_array(%w[category2]) + expect(incident1.armed_force_group_party_names).to match_array(%w[armed_force_1 armed_force_2]) end end diff --git a/spec/models/concerns/phonetic_searchable_spec.rb b/spec/models/concerns/phonetic_searchable_spec.rb new file mode 100644 index 0000000000..2166b2152a --- /dev/null +++ b/spec/models/concerns/phonetic_searchable_spec.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +require 'rails_helper' + +describe PhoneticSearchable do + let(:child1) do + Child.create!( + data: { name_first: 'First 1', name_last: 'Last 1', unhcr_id_no: 'UNHCR/2024-001', national_id_no: 'NID-001' } + ) + end + + before do + clean_data(SearchableIdentifier, Child) + child1 + end + + describe 'recalculate_searchable_identifiers' do + it 'creates the searchable identifiers for the record' do + child = Child.create!( + data: { name_first: 'First 2', name_last: 'Last 2', unhcr_id_no: 'UNHCR/2024-002', national_id_no: 'NID-002' } + ) + searchable_identifiers = SearchableIdentifier.where(record_type: Child.name, record_id: child.id) + + expect(searchable_identifiers.size).to eq(6) + expect(searchable_identifiers.map(&:field_name)).to match_array( + %w[unhcr_id_no national_id_no unique_identifier short_id case_id case_id_display] + ) + expect(searchable_identifiers.map(&:value)).to match_array( + ['UNHCR/2024-002', 'NID-002', child.unique_identifier, child.short_id, child.case_id, child.case_id_display] + ) + end + + it 'creates the searchable identifiers without leading/trailing whitespaces' do + child = Child.create!( + data: { name_first: 'First 3', name_last: 'Last 3', unhcr_id_no: ' UNHCR/2024-003 ', national_id_no: ' NID-003' } + ) + searchable_identifiers = SearchableIdentifier.where(record_type: Child.name, record_id: child.id) + + expect(searchable_identifiers.size).to eq(6) + expect(searchable_identifiers.map(&:field_name)).to match_array( + %w[unhcr_id_no national_id_no unique_identifier short_id case_id case_id_display] + ) + expect(searchable_identifiers.map(&:value)).to match_array( + ['UNHCR/2024-003', 'NID-003', child.unique_identifier, child.short_id, child.case_id, child.case_id_display] + ) + end + + it 'updates the searchable identifiers for the record' do + child1.unhcr_id_no = 'UNHCR/2025-001' + child1.national_id_no = nil + child1.save! + + searchable_identifiers = SearchableIdentifier.where(record_type: Child.name, record_id: child1.id) + expect(searchable_identifiers.map(&:value)).to match_array( + ['UNHCR/2025-001', nil, child1.unique_identifier, child1.short_id, child1.case_id, child1.case_id_display] + ) + end + end +end diff --git a/spec/models/concerns/searchable_spec.rb b/spec/models/concerns/searchable_spec.rb deleted file mode 100644 index ec73594a07..0000000000 --- a/spec/models/concerns/searchable_spec.rb +++ /dev/null @@ -1,81 +0,0 @@ -# frozen_string_literal: true - -# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -require 'rails_helper' - -describe 'Searchable' do - before :each do - Sunspot.remove_all(Child) - end - - before :all do - form = FormSection.new(name: 'test_form', unique_id: 'test_form', parent_form: 'case') - form.fields << Field.new(name: 'text_field1', type: Field::TEXT_FIELD, display_name: 'Text Field 1') - form.fields << Field.new(name: 'tick_field1', type: Field::TICK_BOX, display_name: 'Tick Field 1') - form.fields << Field.new(name: 'tick_field2', type: Field::TICK_BOX, display_name: 'Tick Field 2') - form.fields << Field.new(name: 'date_field1', type: Field::DATE_FIELD, display_name: 'Date Field 1') - form.fields << Field.new(name: 'registration_date', type: Field::DATE_FIELD, display_name: 'Date Field 1', - date_include_time: true) - form.save! - end - - after :all do - Field.destroy_all - FormSection.destroy_all - end - - describe 'Text Query' do - xit 'should return empty array for no match' do - # TODO: pending "Write this test!" - end - - xit 'should return an exact match' do - # TODO: pending "Write this test!" - end - - xit 'should return a match that starts with the query' do - # TODO: pending "Write this test!" - end - - xit 'should return a fuzzy match' do - # TODO: pending "Fuzzy search isn't implemented yet" - end - - xit 'should search by exact match for short id' do - # TODO: pending "Write this test!" - end - - xit 'should match more than one word' do - # TODO: pending "Write this test!" - end - - xit 'should match more than one word with fuzzy search' do - # TODO: pending "Fuzzy search isn't implemented yet" - end - - xit 'should match more than one word with starts with' do - # TODO: pending "Are we even doing startswith searches for names?" - end - end - - describe 'Filtering' do - end - - describe 'Solr schema' do - it 'should build with date search fields' do - expect(Child.searchable_date_fields).to include('date_field1') - end - - it 'should build with date time search fields' do - expect(Child.searchable_date_time_fields).to include('registration_date') - end - - it 'should build with boolean search fields' do - expect(Child.searchable_boolean_fields).to include( - 'duplicate', 'flag', 'has_photo', 'record_state', - 'case_status_reopened', 'tick_field1', 'tick_field2' - ) - end - end -end diff --git a/spec/models/concerns/serviceable_spec.rb b/spec/models/concerns/serviceable_spec.rb index ca2297c08f..5594762223 100644 --- a/spec/models/concerns/serviceable_spec.rb +++ b/spec/models/concerns/serviceable_spec.rb @@ -87,4 +87,30 @@ end end end + + describe 'service_implemented_day_times' do + before do + clean_data(Child) + end + + it 'stores the service_implemented_day_times' do + child = Child.create!(data: { age: 2, sex: 'male', name: 'Random Name' }) + child.stub(:module).and_return(PrimeroModule.new(module_options: { use_workflow_service_implemented: true })) + child.services_section = [ + { + 'unique_id' => '4b7c1011-a63e-422c-b6fb-a64cdcc2d472', + 'service_implemented_day_time' => '2022-05-09T12:44:00.000Z' + }, + { + 'unique_id' => 'f732a61c-cdae-435c-9c0c-55a893321fed', + 'service_implemented_day_time' => '2023-07-08T08:10:00.000Z' + } + ] + child.save! + + expect(child.service_implemented_day_times).to eq( + [DateTime.new(2022, 5, 9, 12, 44, 0), DateTime.new(2023, 7, 8, 8, 10, 0)] + ) + end + end end diff --git a/spec/models/concerns/transitionable_spec.rb b/spec/models/concerns/transitionable_spec.rb index 3ed1977111..4fd8262f8e 100644 --- a/spec/models/concerns/transitionable_spec.rb +++ b/spec/models/concerns/transitionable_spec.rb @@ -112,6 +112,7 @@ @transfer3.status = Transition::STATUS_REJECTED @transfer4.status = Transition::STATUS_DONE [@transfer1, @transfer2, @transfer3, @transfer4].each(&:save!) + @case.save! end it 'should return the users with transfers' do @@ -125,14 +126,14 @@ @referral2 = Referral.create!(transitioned_by: 'user1', transitioned_to: 'user3', record: @case) @referral3 = Referral.create!(transitioned_by: 'user1', transitioned_to: 'user4', record: @case) @referral4 = Referral.create!(transitioned_by: 'user1', transitioned_to: 'user4', record: @case) - @referral1.status = Transition::STATUS_INPROGRESS - @referral2.status = Transition::STATUS_ACCEPTED - @referral3.status = Transition::STATUS_REJECTED - @referral4.status = Transition::STATUS_DONE + @referral2.accept! + @referral3.reject!(@user4) + @referral4.accept! + @referral4.done!(@user4) [@referral1, @referral2, @referral3, @referral4].each(&:save!) end - it 'should return the users with transfers' do + it 'should return the users with referrals' do expect(@case.referred_users).to match_array(%w[user2 user3]) end end diff --git a/spec/models/concerns/workflow_spec.rb b/spec/models/concerns/workflow_spec.rb index 16532cbefb..8363cc8f27 100644 --- a/spec/models/concerns/workflow_spec.rb +++ b/spec/models/concerns/workflow_spec.rb @@ -6,7 +6,8 @@ describe Workflow do before do - lookup = Lookup.new( + clean_data(FormSection, Lookup, PrimeroModule) + lookup = Lookup.create!( unique_id: 'lookup-service-response-type', name: 'Service Response Type', locked: true, @@ -91,6 +92,41 @@ include(include('id' => Workflow::WORKFLOW_ASSESSMENT)) ) end + it 'return assesment from app strings' do + assessment_status_text = Child.workflow_statuses(@modules)[:en] + &.find { |lkp| lkp['id'] == Workflow::WORKFLOW_ASSESSMENT } + &.dig('display_text') + expect(assessment_status_text).to eq('Assessment') + end + end + end + context 'when assessment value is present on workflow lookup' do + before do + clean_data(Lookup) + @modules = [@module_a, @module_b] + Lookup.create!( + unique_id: 'lookup-workflow', + name_i18n: { en: 'Workflow' }, + lookup_values_i18n: [ + { id: 'case_plan', display_text: { en: 'Case Plan LK' } }, + { id: 'assessment', display_text: { en: 'Assessment LK' } } + ] + ) + end + it 'return assesment from Lookup' do + assessment_status_text = Child.workflow_statuses(@modules)[:en] + &.find { |lkp| lkp['id'] == Workflow::WORKFLOW_ASSESSMENT } + &.dig('display_text') + expect(assessment_status_text).to eq('Assessment LK') + end + + it 'return status that include text from workflow lookup' do + workflow_status = Child.workflow_statuses(@modules)[:en].map { |lk| lk['display_text'] } + + expect(workflow_status).to match_array(['New', 'Reopened', 'Assessment LK', 'Case Plan LK', 'Closed']) + end + after do + clean_data(Lookup) end end end diff --git a/spec/models/duplicate_bulk_export_spec.rb b/spec/models/duplicate_bulk_export_spec.rb index 3d8cb19126..523a6c7ac0 100644 --- a/spec/models/duplicate_bulk_export_spec.rb +++ b/spec/models/duplicate_bulk_export_spec.rb @@ -3,9 +3,8 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. require 'rails_helper' -require 'sunspot' -describe DuplicateBulkExport, search: true do +describe DuplicateBulkExport do before :each do clean_data(BulkExport, User, Agency, Role, Location, UserGroup, Field, FormSection, Child, PrimeroModule, PrimeroProgram, SystemSettings, @@ -69,7 +68,6 @@ create(:child, age: 5, name: 'Test Child 6') @child1 = create(:child, national_id_no: 'test1', age: 5, name: 'Test Child 1') @child2 = create(:child, national_id_no: 'test1', age: 6, name: 'Test Child 2') - Sunspot.commit end it 'export cases with duplicate ids' do @@ -82,7 +80,6 @@ create(:child, national_id_no: 'test5', age: 3, name: 'Test Child 4') create(:child, national_id_no: 'test5', age: 3, name: 'Test Child 4') create(:child, national_id_no: 'test3', age: 3, name: 'Test Child 4') - Sunspot.commit expect(export_csv.count).to eq(7) ids_orderes = %w[test1 test3 test5] export_csv[1..].each_with_index do |row, index| @@ -96,7 +93,6 @@ before do @child1 = create(:child, national_id_no: 'test-1', age: 5, name: 'Test Child 1') @child2 = create(:child, national_id_no: 'test-1', age: 6, name: 'Test Child 2') - Sunspot.commit end it 'export cases with duplicate ids' do @@ -114,7 +110,6 @@ create(:child, national_id_no: 'test3', age: 3, name: 'Test Child 4') create(:child, age: 4, name: 'Test Child 5') create(:child, age: 5, name: 'Test Child 6') - Sunspot.commit end it 'exports no cases' do @@ -131,7 +126,6 @@ create(:child, age: 3, name: 'Test Child 4') create(:child, age: 4, name: 'Test Child 5') create(:child, age: 5, name: 'Test Child 6') - Sunspot.commit end it 'exports no cases' do diff --git a/spec/models/exporters/form_exporter_spec.rb b/spec/models/exporters/form_exporter_spec.rb index 103d7ab611..df7aa6000c 100644 --- a/spec/models/exporters/form_exporter_spec.rb +++ b/spec/models/exporters/form_exporter_spec.rb @@ -284,6 +284,43 @@ module Exporters end end + context 'when fields has special option_strings_source' do + before do + clean_data(Field, FormSection, PrimeroModule) + form1 = FormSection.new( + name: 'Form1', parent_form: 'case', visible: true, + order_form_group: 2, order: 0, order_subform: 0, form_group_id: 'form_group1', + unique_id: 'basic_identity' + ) + form1.fields << Field.new( + name: 'service_incident', + type: Field::SELECT_BOX, + display_name: 'Incident action addresses', + option_strings_source: 'LinkedIncidents' + ) + form1.fields << Field.new( + name: 'service_delivery_location', + type: Field::SELECT_BOX, + display_name: 'Service delivery location', + option_strings_source: 'ReportingLocation' + ) + form1.save! + + create(:primero_module, unique_id: 'primeromodule-cp', name: 'CP', form_sections: [form1]) + + exporter = Exporters::FormExporter.new + exporter.export + @book = Roo::Spreadsheet.open(exporter.file_name) + + @test_xlsx_files << exporter.file_name + end + + it 'export fields options' do + expected_values = [nil, 'Options', 'Linked Incidents', 'Reporting Locations'] + expect(@book.sheet('Form1').column(9)).to match_array(expected_values) + end + end + after do clean_data(Field, FormSection, PrimeroModule, PrimeroProgram, Lookup) diff --git a/spec/models/exporters/incident_recorder_exporter_spec.rb b/spec/models/exporters/incident_recorder_exporter_spec.rb index a1d1f1e0cc..b387d3a340 100644 --- a/spec/models/exporters/incident_recorder_exporter_spec.rb +++ b/spec/models/exporters/incident_recorder_exporter_spec.rb @@ -13,7 +13,7 @@ module Exporters User, Agency, Role, UserGroup, PrimeroModule, PrimeroProgram, Field, FormSection, Incident, Location, Lookup ) subform = FormSection.new( - name: 'cases_test_subform_2', parent_form: 'case', 'visible' => false, 'is_nested' => true, + name: 'cases_test_subform_2', parent_form: 'incident', 'visible' => false, 'is_nested' => true, order_form_group: 0, order: 0, order_subform: 0, form_group_id: 'cases_test_subform_2', unique_id: 'cases_test_subform_2' ) @@ -21,7 +21,7 @@ module Exporters subform.fields << Field.new(name: 'field_4', type: Field::TEXT_FIELD, display_name: 'field_4') subform.save! form1 = FormSection.new( - name: 'cases_test_form_3', parent_form: 'case', 'visible' => true, order_form_group: 0, + name: 'cases_test_form_3', parent_form: 'incident', 'visible' => true, order_form_group: 0, order: 0, order_subform: 0, form_group_id: 'cases_test_form_3', unique_id: 'cases_test_form_3' ) form1.fields << Field.new( @@ -29,7 +29,7 @@ module Exporters ) form1.save! form2 = FormSection.new( - :name => 'cases_test_form_2', parent_form: 'case', 'visible' => true, order_form_group: 0, + :name => 'cases_test_form_2', parent_form: 'incident', 'visible' => true, order_form_group: 0, order: 0, order_subform: 0, form_group_id: 'cases_test_form_2', unique_id: 'cases_test_form_2' ) form2.fields << Field.new(name: 'relationship', type: Field::TEXT_FIELD, display_name: 'relationship') @@ -41,14 +41,14 @@ module Exporters ) form2.save! subform = FormSection.new( - name: 'cases_test_subform_1', parent_form: 'case', 'visible' => false, 'is_nested' => true, order_form_group: 0, + name: 'cases_test_subform_1', parent_form: 'incident', 'visible' => false, 'is_nested' => true, order_form_group: 0, order: 0, order_subform: 0, form_group_id: 'cases_test_subform_1', unique_id: 'cases_test_subform_1' ) subform.fields << Field.new(name: 'field_1', type: Field::TEXT_FIELD, display_name: 'field_1') subform.fields << Field.new(name: 'field_2', type: Field::TEXT_FIELD, display_name: 'field_2') subform.save! form3 = FormSection.new( - name: 'cases_test_form_1', parent_form: 'case', 'visible' => true, order_form_group: 0, + name: 'cases_test_form_1', parent_form: 'incident', 'visible' => true, order_form_group: 0, order: 0, order_subform: 0, form_group_id: 'cases_test_form_1', unique_id: 'cases_test_form_1' ) form3.fields << Field.new(name: 'first_name', type: Field::TEXT_FIELD, display_name: 'first_name') @@ -56,27 +56,33 @@ module Exporters form3.fields << Field.new( name: 'subform_field_1', type: Field::SUBFORM, display_name: 'subform field', 'subform_section_id' => subform.id ) + form3.fields << Field.new(name: 'ethnicity', display_name: 'ethnicity', type: Field::SELECT_BOX, + option_strings_source: 'lookup lookup-ethnicity') + form3.fields << Field.new(name: 'displacement_incident', type: Field::SELECT_BOX, + display_name: 'Stage of displacement at time of incident', + option_strings_text_i18n: [ + { 'id' => 'during_flight', 'display_text' => { 'en' => 'During Flight' } }, + { 'id' => 'during_refuge', 'display_text' => { 'en' => 'During Refuge' } } + ]) + form3.fields << Field.new(name: 'perpetrator_occupation', type: Field::SELECT_BOX, display_name: 'perpetrator_occupation', + multi_select: true, option_strings_text: [ + { id: 'occupation_1', display_text: 'Occupation 1' }, + { id: 'occupation_2', display_text: 'Occupation 2' } + ].map(&:with_indifferent_access)) form3.save! @primero_module = create( - :primero_module, name: 'CP', description: 'Child Protection', associated_record_types: %w[case] + :primero_module, unique_id: 'primeromodule-gbv', name: 'GBV', description: 'Child Protection', + associated_record_types: %w[incident], form_sections: [form1, form2, form3] ) - @role = create(:role, modules: [@primero_module], form_sections: [form1, form2, form3]) + @role = create(:role, modules: [@primero_module]) @user = create(:user, user_name: 'fakeadmin', role: @role, code: 'test01') - Field.create!(name: 'ethnicity', display_name: 'ethnicity', type: Field::SELECT_BOX, - option_strings_source: 'lookup lookup-ethnicity') - Field.create!(name: 'displacement_incident', type: Field::SELECT_BOX, - display_name: 'Stage of displacement at time of incident', - option_strings_text_i18n: [ - { 'id': 'during_flight', 'display_text': { 'en': 'During Flight' } }, - { 'id': 'during_refuge', 'display_text': { 'en': 'During Refuge' } } - ]) - Lookup.create!(unique_id: 'lookup-ethnicity', name_i18n: { 'en': 'Ethnicity' }, + Lookup.create!(unique_id: 'lookup-ethnicity', name_i18n: { 'en' => 'Ethnicity' }, lookup_values_i18n: [ - { 'id': 'ethnicity1', 'display_text': { 'en': 'Ethnicity1' } }, - { 'id': 'ethnicity2', 'display_text': { 'en': 'Ethnicity2' } }, - { 'id': 'ethnicity3', 'display_text': { 'en': 'Ethnicity3' } }, - { 'id': 'ethnicity4', 'display_text': { 'en': 'Ethnicity4' } } + { 'id' => 'ethnicity1', 'display_text' => { 'en' => 'Ethnicity1' } }, + { 'id' => 'ethnicity2', 'display_text' => { 'en' => 'Ethnicity2' } }, + { 'id' => 'ethnicity3', 'display_text' => { 'en' => 'Ethnicity3' } }, + { 'id' => 'ethnicity4', 'display_text' => { 'en' => 'Ethnicity4' } } ]) incident_a = Incident.create!( @@ -362,13 +368,14 @@ module Exporters workbook = Roo::Spreadsheet.open(StringIO.new(data).set_encoding('ASCII-8BIT'), extension: :xlsx) expect(workbook.sheets.size).to eq(2) model = @record_with_all_fields.first + expect(workbook.sheet(0).row(2)).to eq( [ '111-22-ir', '111-222', 'test01', I18n.l(model.date_of_first_report), I18n.l(model.incident_date), I18n.l(model.data['date_of_birth']), 'F', 'Ethnicity3', 'andorra', 'divorced_separated', 'refugee', 'mental_disability', 'separated_child', 'During Flight', 'afternoon', 'garden', 'Guinea', 'Kindia', 'town', 'sexual_assault', 'type_of_practice_1', 'false', 'forced_conscription', 'non-gbvims-org', 'true', 2, - 'M and F', 'Yes', 'Age 18 - 25', 'supervisor_employer', 'occupation_2', 'police_other_service', + 'M and F', 'Yes', 'Age 18 - 25', 'supervisor_employer', 'Occupation 2', 'police_other_service', 'services_already_received_from_another_agency', 'service_provided_by_your_agency', 'service_not_applicable', 'No', 'service_not_applicable', 'referral_declined_by_survivor', 'service_not_applicable', 'services_already_received_from_another_agency', @@ -387,7 +394,7 @@ module Exporters it 'Get age_type form perpetrators' do form_perpetrator = FormSection.new( - name: 'alleged_perpetrator', parent_form: 'case', 'visible' => true, order_form_group: 0, + name: 'alleged_perpetrator', parent_form: 'incident', 'visible' => true, order_form_group: 0, order: 0, order_subform: 0, form_group_id: 'cases_test_subform_2', unique_id: 'alleged_perpetrator' ) form_perpetrator.fields << Field.new(name: 'age_type', type: Field::TEXT_FIELD, display_name: 'age_type') @@ -401,20 +408,6 @@ module Exporters end it 'Get select field value from primary perpetrators' do - form_perpetrator = FormSection.new( - name: 'alleged_perpetrator', parent_form: 'case', 'visible' => true, order_form_group: 0, - order: 0, order_subform: 0, form_group_id: 'cases_test_subform_2', unique_id: 'alleged_perpetrator' - ) - fields = [ - Field.new(name: 'perpetrator_occupation', type: Field::SELECT_BOX, display_name: 'perpetrator_occupation', - multi_select: true, option_strings_text: [ - { id: 'occupation_1', display_text: 'Occupation 1' }, - { id: 'occupation_2', display_text: 'Occupation ' } - ].map(&:with_indifferent_access)) - ] - form_perpetrator.fields = fields - form_perpetrator.save! - data = IncidentRecorderExporter.export(@records, nil, { user: @user }, {}) workbook = Roo::Spreadsheet.open(StringIO.new(data).set_encoding('ASCII-8BIT'), extension: :xlsx) expect(workbook.sheet(0).last_row).to eq(3) diff --git a/spec/models/exporters/managed_report_exporter_spec.rb b/spec/models/exporters/managed_report_exporter_spec.rb index eacdd2d759..a561728038 100644 --- a/spec/models/exporters/managed_report_exporter_spec.rb +++ b/spec/models/exporters/managed_report_exporter_spec.rb @@ -200,7 +200,7 @@ gbv_previous_incidents: true, incident_timeofday: 'afternoon', incident_location_type: 'school', - age: 5, + age: 2, health_medical_referral_subform_section: [{ unique_id: '001', service_medical_referral: 'referred' }], alleged_perpetrator: [ { @@ -248,12 +248,12 @@ end it 'should export the excel' do - expect(workbook.sheets.size).to eq(4) + expect(workbook.sheets.size).to eq(1) end - describe 'Incidents subreport' do + describe 'GBV Statistics subreport' do it 'prints subreport headers' do - expect(workbook.sheet(0).row(1)).to eq(['Incidents', nil]) + expect(workbook.sheet(0).row(1)).to eq(['GBV Statistics', nil]) end it 'prints report params' do @@ -266,95 +266,164 @@ end it 'prints indicator tables' do - expect(workbook.sheet(0).row(5)).to eq(['Incidents', nil]) + expect(workbook.sheet(0).row(5)).to eq(['General Statistics', nil]) expect(workbook.sheet(0).row(6)).to eq([nil, 'Total']) - expect(workbook.sheet(0).row(7)).to eq(['Number of GBV Incidents Reported', 3]) - expect(workbook.sheet(0).row(8)).to eq(['Number of Incidents of Sexual Violence Reported', 3]) - expect(workbook.sheet(0).row(9)).to eq( - ['Number of Incidents Reported by Survivors with Prior GBV Incidents', 1] + expect(workbook.sheet(0).row(7)).to eq(['1. New GBV Incidents Reported', 3]) + expect(workbook.sheet(0).row(8)).to eq(['2. New Incidents of Sexual Violence Reported', 1]) + expect(workbook.sheet(0).row(11)).to eq(['Survivor Statistics - 3. Sex of survivors', nil]) + expect(workbook.sheet(0).row(12)).to eq([nil, 'Total']) + + expect(workbook.sheet(0).row(38)).to eq(['Survivor Statistics - 4. Age of survivors', nil]) + expect(workbook.sheet(0).row(39)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(40)).to eq([AgeRange.new(0, 4).to_s, 2]) + expect(workbook.sheet(0).row(41)).to eq([AgeRange.new(5, 11).to_s, 1]) + + expect(workbook.sheet(0).row(67)).to eq(['Survivor Statistics - 5. Marital Status of Survivors', nil]) + expect(workbook.sheet(0).row(68)).to eq([nil, 'Total']) + + expect(workbook.sheet(0).row(94)).to eq( + ['Survivor Statistics - 6. Displacement Status at Time of Report', nil] ) + expect(workbook.sheet(0).row(95)).to eq([nil, 'Total']) - expect(workbook.sheet(0).row(12)).to eq(['Incident Type', nil]) - expect(workbook.sheet(0).row(13)).to eq([nil, 'Total']) - expect(workbook.sheet(0).row(14)).to eq(['Rape', 1]) - expect(workbook.sheet(0).row(15)).to eq(['Sexual Assault', 1]) - expect(workbook.sheet(0).row(16)).to eq(['Forced Marriage', 1]) + expect(workbook.sheet(0).row(121)).to eq( + ['Survivor Statistics - 7. Stage of Displacement at Time of Incident', nil] + ) + expect(workbook.sheet(0).row(122)).to eq([nil, 'Total']) - expect(workbook.sheet(0).row(42)).to eq(['Incident Time of Day', nil]) - expect(workbook.sheet(0).row(43)).to eq([nil, 'Total']) - expect(workbook.sheet(0).row(44)).to eq(['Morning (sunrise to noon)', 1]) - expect(workbook.sheet(0).row(45)).to eq(['Afternoon (noon to sunset)', 1]) - expect(workbook.sheet(0).row(46)).to eq(['Evening/Night (sunset to sunrise)', 1]) + expect(workbook.sheet(0).row(148)).to eq( + ['Survivor Statistics - 8. Vulnerable Populations', nil] + ) + expect(workbook.sheet(0).row(149)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(150)).to eq(['With Disabilities', 0]) - expect(workbook.sheet(0).row(72)).to eq(['Time Between Incident and Report Date', nil]) - expect(workbook.sheet(0).row(73)).to eq([nil, 'Total']) - expect(workbook.sheet(0).row(74)).to eq(['0-3 Days', 3]) + expect(workbook.sheet(0).row(176)).to eq( + ['Survivor Statistics - 9. Number of Incidents of Sexual Violence Reported', nil] + ) + expect(workbook.sheet(0).row(177)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(178)).to eq(['Incidents', 3]) - expect(workbook.sheet(0).row(100)).to eq( - ['Incidents of Rape, Time Elapsed between Incident and Report Date', nil] + expect(workbook.sheet(0).row(204)).to eq( + ['Incident Statistics - 10. Type of GBV', nil] ) - expect(workbook.sheet(0).row(101)).to eq([nil, 'Total']) - expect(workbook.sheet(0).row(102)).to eq(['0-3 Days', 1]) + expect(workbook.sheet(0).row(205)).to eq([nil, 'Total']) + + expect(workbook.sheet(0).row(206)).to eq(['Rape', 1]) + expect(workbook.sheet(0).row(207)).to eq(['Sexual Assault', 1]) + expect(workbook.sheet(0).row(208)).to eq(['Forced Marriage', 1]) - expect(workbook.sheet(0).row(128)).to eq( - ['Incidents of Rape, Time Elapsed between Incident and Report Date (Health Service or Referral)', nil] + expect(workbook.sheet(0).row(234)).to eq( + ['Incident Statistics - 11. Incident Time of Day', nil] ) - expect(workbook.sheet(0).row(129)).to eq([nil, 'Total']) - expect(workbook.sheet(0).row(130)).to eq(['0-3 Days', 1]) - - expect(workbook.sheet(0).row(156)).to eq(['Incident Location', nil]) - expect(workbook.sheet(0).row(157)).to eq([nil, 'Total']) - expect(workbook.sheet(0).row(158)).to eq(['Bush/Forest', 1]) - expect(workbook.sheet(0).row(159)).to eq(['Garden/Cultivated Field', 1]) - expect(workbook.sheet(0).row(160)).to eq(['School', 1]) - - expect(workbook.sheet(0).row(186)).to eq(['Case Context', nil]) - expect(workbook.sheet(0).row(187)).to eq([nil, 'Total']) - expect(workbook.sheet(0).row(188)).to eq(['Child Sexual Abuse', 2]) - expect(workbook.sheet(0).row(189)).to eq(['Early Marriage', 1]) - expect(workbook.sheet(0).row(190)).to eq(['Possible Sexual Exploitation', 1]) - end - end + expect(workbook.sheet(0).row(235)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(236)).to eq(['Morning (sunrise to noon)', 1]) + expect(workbook.sheet(0).row(237)).to eq(['Afternoon (noon to sunset)', 1]) + expect(workbook.sheet(0).row(238)).to eq(['Evening/Night (sunset to sunrise)', 1]) - describe 'Perpetrators subreport' do - it 'prints subreport headers' do - expect(workbook.sheet(1).row(1)).to eq(['Perpetrators', nil]) - end + expect(workbook.sheet(0).row(264)).to eq( + ['Incident Statistics - 12. Case Context', nil] + ) + expect(workbook.sheet(0).row(265)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(266)).to eq(['Child Sexual Abuse', 2]) + expect(workbook.sheet(0).row(267)).to eq(['Early Marriage', 1]) + expect(workbook.sheet(0).row(268)).to eq(['Possible Sexual Exploitation', 1]) - it 'prints report params' do - expect(workbook.sheet(1).row(2)).to eq( + expect(workbook.sheet(0).row(294)).to eq( + ['Incident Statistics - 13. Time Between Incident and Report Date', nil] + ) + expect(workbook.sheet(0).row(295)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(296)).to eq(['0-3 Days', 3]) + + expect(workbook.sheet(0).row(322)).to eq( + ['Incident Statistics - 14. Incidents of Rape, Time Elapsed between Incident and Report Date', nil] + ) + expect(workbook.sheet(0).row(323)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(324)).to eq(['0-3 Days', 1]) + + expect(workbook.sheet(0).row(350)).to eq( + ['Incident Statistics - 15. Incidents of Rape, Time Elapsed (Health Service or Referral)', nil] + ) + expect(workbook.sheet(0).row(351)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(352)).to eq(['0-3 Days', 1]) + + expect(workbook.sheet(0).row(378)).to eq( + ['Incident Statistics - 16. Incident Location', nil] + ) + + expect(workbook.sheet(0).row(379)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(380)).to eq(['Bush/Forest', 1]) + expect(workbook.sheet(0).row(381)).to eq(['Garden/Cultivated Field', 1]) + expect(workbook.sheet(0).row(382)).to eq(['School', 1]) + + expect(workbook.sheet(0).row(408)).to eq(['Perpetrator Statistics - 17. Number of Primary Perpetrators', nil]) + expect(workbook.sheet(0).row(409)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(410)).to eq([1, 1]) + expect(workbook.sheet(0).row(411)).to eq([2, 1]) + expect(workbook.sheet(0).row(412)).to eq([3, 1]) + + expect(workbook.sheet(0).row(438)).to eq( + ['Perpetrator Statistics - 18. Alleged Perpetrator - Survivor Relationship', nil] + ) + expect(workbook.sheet(0).row(439)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(440)).to eq(['Primary Caregiver', 3]) + expect(workbook.sheet(0).row(441)).to eq(['Other', 1]) + expect(workbook.sheet(0).row(442)).to eq(['No relation', 2]) + + expect(workbook.sheet(0).row(468)).to eq( + ['Perpetrator Statistics - 19. Alleged Primary Perpetrators Age Group', nil] + ) + expect(workbook.sheet(0).row(469)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(470)).to eq(['0-11', 3]) + expect(workbook.sheet(0).row(471)).to eq(['12-17', 2]) + expect(workbook.sheet(0).row(472)).to eq(['18-25', 1]) + + expect(workbook.sheet(0).row(498)).to eq( + ['Perpetrator Statistics - 20. Alleged Primary Perpetrator Occupation', nil] + ) + expect(workbook.sheet(0).row(499)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(500)).to eq(['Occupation 1', 2]) + expect(workbook.sheet(0).row(501)).to eq(['Occupation 2', 2]) + expect(workbook.sheet(0).row(502)).to eq(['Unknown', 1]) + expect(workbook.sheet(0).row(503)).to eq(['Incomplete Data', 1]) + + expect(workbook.sheet(0).row(529)).to eq( [ - 'Date Range: This Quarter / Date: Date of Incident / ', + 'Referral Statistics - 21. Number of incidents for which your organisation is the first point of contact', nil ] ) - end + expect(workbook.sheet(0).row(530)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(531)).to eq(['Incidents', 0]) - it 'prints indicator tables' do - expect(workbook.sheet(1).row(5)).to eq(['Number of Perpetrators', nil]) - expect(workbook.sheet(1).row(6)).to eq([nil, 'Total']) - expect(workbook.sheet(1).row(7)).to eq([1, 1]) - expect(workbook.sheet(1).row(8)).to eq([2, 1]) - expect(workbook.sheet(1).row(9)).to eq([3, 1]) - - expect(workbook.sheet(1).row(35)).to eq(["Alleged Primary Perpetrator's Relationship to Survivor", nil]) - expect(workbook.sheet(1).row(36)).to eq([nil, 'Total']) - expect(workbook.sheet(1).row(37)).to eq(['Primary Caregiver', 3]) - expect(workbook.sheet(1).row(38)).to eq(['Other', 1]) - expect(workbook.sheet(1).row(39)).to eq(['No relation', 2]) - - expect(workbook.sheet(1).row(65)).to eq(['Alleged Primary Perpetrators Age Group', nil]) - expect(workbook.sheet(1).row(66)).to eq([nil, 'Total']) - expect(workbook.sheet(1).row(67)).to eq(['0-11', 3]) - expect(workbook.sheet(1).row(68)).to eq(['12-17', 2]) - expect(workbook.sheet(1).row(69)).to eq(['18-25', 1]) - - expect(workbook.sheet(1).row(95)).to eq(['Alleged Primary Perpetrator Occupation', nil]) - expect(workbook.sheet(1).row(96)).to eq([nil, 'Total']) - expect(workbook.sheet(1).row(97)).to eq(['Occupation 1', 2]) - expect(workbook.sheet(1).row(98)).to eq(['Occupation 2', 2]) - expect(workbook.sheet(1).row(99)).to eq(['Unknown', 1]) - expect(workbook.sheet(1).row(100)).to eq(['Incomplete Data', 1]) + expect(workbook.sheet(0).row(557)).to eq( + ['Referral Statistics - 22. Incidents Referred From Other Service Providers', nil] + ) + expect(workbook.sheet(0).row(558)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(559)).to eq(['Incidents', 1]) + + expect(workbook.sheet(0).row(585)).to eq( + ['Referral Statistics - 23. Number of Services Provided for Incidents', nil] + ) + expect(workbook.sheet(0).row(586)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(587)).to eq(['Legal Assistance Services', 0]) + expect(workbook.sheet(0).row(588)).to eq(['Livelihoods Services', 0]) + expect(workbook.sheet(0).row(589)).to eq(['Health/Medical Referral', 0]) + expect(workbook.sheet(0).row(590)).to eq(['Police or Other Type of Security Services', 0]) + expect(workbook.sheet(0).row(591)).to eq(['Child Protection Services', 0]) + expect(workbook.sheet(0).row(592)).to eq(['Psychosocial/Counseling Services', 0]) + expect(workbook.sheet(0).row(593)).to eq(['Safe House/Safe Shelter Referral', 0]) + + expect(workbook.sheet(0).row(619)).to eq( + ['Referral Statistics - 24. New Incident Referrals to Other Service Providers', nil] + ) + expect(workbook.sheet(0).row(620)).to eq([nil, 'Total']) + expect(workbook.sheet(0).row(621)).to eq(['Legal Assistance Services', 0]) + expect(workbook.sheet(0).row(622)).to eq(['Livelihoods Services', 0]) + expect(workbook.sheet(0).row(623)).to eq(['Health/Medical Referral', 1]) + expect(workbook.sheet(0).row(624)).to eq(['Police or Other Type of Security Services', 0]) + expect(workbook.sheet(0).row(625)).to eq(['Child Protection Services', 0]) + expect(workbook.sheet(0).row(626)).to eq(['Psychosocial/Counseling Services', 0]) + expect(workbook.sheet(0).row(627)).to eq(['Safe House/Safe Shelter Referral', 0]) end end end @@ -389,105 +458,184 @@ ] end - context 'Incidents subreport' do + context 'GBV Statistics subreport' do it 'prints subreport headers' do - expect(workbook_grouped.sheet(0).row(1)).to match_array(['Incidents', nil, nil, nil, nil, nil]) + expect(workbook_grouped.sheet(0).row(1)).to match_array(['GBV Statistics', nil, nil, nil, nil, nil]) end it 'prints report params' do - result = 'View By: Month / Date Range: Custom / '\ - "From: #{(Date.today - 2.month).strftime('%Y-%m-%d')} / "\ - "To: #{(Date.today + 2.month).strftime('%Y-%m-%d')} / Date: Date of Incident / " + result = + 'View By: Month / Date Range: Custom / ' \ + "From: #{(Date.today - 2.month).strftime('%Y-%m-%d')} / " \ + "To: #{(Date.today + 2.month).strftime('%Y-%m-%d')} / Date: Date of Incident / " expect(workbook_grouped.sheet(0).row(2)).to match_array([result, nil, nil, nil, nil, nil]) end it 'prints indicator tables' do expect(workbook_grouped.sheet(0).row(5)).to match_array( - ['Incidents', nil, nil, nil, nil, nil] + ['General Statistics', nil, nil, nil, nil, nil] ) expect(workbook_grouped.sheet(0).row(6)).to match_array(year_range) expect(workbook_grouped.sheet(0).row(7)).to match_array( - ['Number of GBV Incidents Reported', 0, 0, 3, 0, 0] + ['1. New GBV Incidents Reported', 0, 0, 3, 0, 0] ) expect(workbook_grouped.sheet(0).row(8)).to match_array( - ['Number of Incidents Reported by Survivors with Prior GBV Incidents', 0, 0, 1, 0, 0] + ['2. New Incidents of Sexual Violence Reported', 0, 0, 1, 0, 0] + ) + expect(workbook_grouped.sheet(0).row(11)).to match_array( + ['Survivor Statistics - 3. Sex of survivors', nil, nil, nil, nil, nil] + ) + expect(workbook_grouped.sheet(0).row(13)).to match_array( + ['Survivor Statistics - 4. Age of survivors', nil, nil, nil, nil, nil] ) - expect(workbook_grouped.sheet(0).row(9)).to match_array( - ['Number of Incidents of Sexual Violence Reported', 0, 0, 3, 0, 0] + + expect(workbook_grouped.sheet(0).row(14)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(15)).to match_array([AgeRange.new(0, 4).to_s, 0, 0, 2, 0, 0]) + expect(workbook_grouped.sheet(0).row(16)).to match_array([AgeRange.new(5, 11).to_s, 0, 0, 1, 0, 0]) + + expect(workbook_grouped.sheet(0).row(41)).to eq( + ['Survivor Statistics - 5. Marital Status of Survivors', nil, nil, nil, nil, nil] + ) + expect(workbook_grouped.sheet(0).row(43)).to eq( + ['Survivor Statistics - 6. Displacement Status at Time of Report', nil, nil, nil, nil, nil] + ) + expect(workbook_grouped.sheet(0).row(45)).to eq( + ['Survivor Statistics - 7. Stage of Displacement at Time of Incident', nil, nil, nil, nil, nil] + ) + expect(workbook_grouped.sheet(0).row(47)).to eq( + ['Survivor Statistics - 8. Vulnerable Populations', nil, nil, nil, nil, nil] ) - expect(workbook_grouped.sheet(0).row(12)).to match_array( - ['Incident Type', nil, nil, nil, nil, nil] + expect(workbook_grouped.sheet(0).row(49)).to eq( + ['Survivor Statistics - 9. Number of Incidents of Sexual Violence Reported', nil, nil, nil, nil, nil] ) - expect(workbook_grouped.sheet(0).row(13)).to match_array(year_range) - expect(workbook_grouped.sheet(0).row(14)).to match_array(['Rape', 0, 0, 1, 0, 0]) - expect(workbook_grouped.sheet(0).row(15)).to match_array( + expect(workbook_grouped.sheet(0).row(50)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(51)).to match_array( + ['Incidents', 0, 0, 3, 0, 0] + ) + + expect(workbook_grouped.sheet(0).row(76)).to eq( + ['Incident Statistics - 10. Type of GBV', nil, nil, nil, nil, nil] + ) + expect(workbook_grouped.sheet(0).row(77)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(78)).to match_array( + ['Rape', 0, 0, 1, 0, 0] + ) + expect(workbook_grouped.sheet(0).row(79)).to match_array( ['Sexual Assault', 0, 0, 1, 0, 0] ) - expect(workbook_grouped.sheet(0).row(16)).to match_array( + expect(workbook_grouped.sheet(0).row(80)).to match_array( ['Forced Marriage', 0, 0, 1, 0, 0] ) - expect(workbook_grouped.sheet(0).row(41)).to match_array( - ['Incident Time of Day', nil, nil, nil, nil, nil] - ) - expect(workbook_grouped.sheet(0).row(42)).to match_array(year_range) - expect(workbook_grouped.sheet(0).row(43)).to match_array( - ['Morning (sunrise to noon)', 0, 0, 1, 0, 0] + expect(workbook_grouped.sheet(0).row(105)).to eq( + ['Incident Statistics - 11. Incident Time of Day', nil, nil, nil, nil, nil] ) - expect(workbook_grouped.sheet(0).row(44)).to match_array( - ['Afternoon (noon to sunset)', 0, 0, 1, 0, 0] - ) - expect(workbook_grouped.sheet(0).row(45)).to match_array( - ['Evening/Night (sunset to sunrise)', 0, 0, 1, 0, 0] + expect(workbook_grouped.sheet(0).row(106)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(107)).to eq(['Morning (sunrise to noon)', 0, 0, 1, 0, 0]) + expect(workbook_grouped.sheet(0).row(108)).to eq(['Afternoon (noon to sunset)', 0, 0, 1, 0, 0]) + expect(workbook_grouped.sheet(0).row(109)).to eq(['Evening/Night (sunset to sunrise)', 0, 0, 1, 0, 0]) + + expect(workbook_grouped.sheet(0).row(134)).to eq( + ['Incident Statistics - 12. Case Context', nil, nil, nil, nil, nil] ) + expect(workbook_grouped.sheet(0).row(135)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(136)).to eq(['Child Sexual Abuse', 0, 0, 2, 0, 0]) + expect(workbook_grouped.sheet(0).row(137)).to eq(['Early Marriage', 0, 0, 1, 0, 0]) + expect(workbook_grouped.sheet(0).row(138)).to eq(['Possible Sexual Exploitation', 0, 0, 1, 0, 0]) - expect(workbook_grouped.sheet(0).row(70)).to match_array( - ['Time Between Incident and Report Date', nil, nil, nil, nil, nil] + expect(workbook_grouped.sheet(0).row(163)).to eq( + ['Incident Statistics - 13. Time Between Incident and Report Date', nil, nil, nil, nil, nil] ) - expect(workbook_grouped.sheet(0).row(71)).to match_array(year_range) - expect(workbook_grouped.sheet(0).row(72)).to match_array(['0-3 Days', 0, 0, 3, 0, 0]) + expect(workbook_grouped.sheet(0).row(164)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(165)).to eq(['0-3 Days', 0, 0, 3, 0, 0]) - expect(workbook_grouped.sheet(0).row(97)).to match_array( + expect(workbook_grouped.sheet(0).row(190)).to eq( [ - 'Incidents of Rape, Time Elapsed between Incident and Report Date', + 'Incident Statistics - 14. Incidents of Rape, Time Elapsed between Incident and Report Date', nil, nil, nil, nil, nil ] ) - expect(workbook_grouped.sheet(0).row(98)).to match_array(year_range) - expect(workbook_grouped.sheet(0).row(99)).to match_array(['0-3 Days', 0, 0, 1, 0, 0]) + expect(workbook_grouped.sheet(0).row(191)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(192)).to eq(['0-3 Days', 0, 0, 1, 0, 0]) - expect(workbook_grouped.sheet(0).row(124)).to match_array( + expect(workbook_grouped.sheet(0).row(217)).to match_array( [ - 'Incidents of Rape, Time Elapsed between Incident and Report Date (Health Service or Referral)', + 'Incident Statistics - 15. Incidents of Rape, Time Elapsed (Health Service or Referral)', nil, nil, nil, nil, nil ] ) - expect(workbook_grouped.sheet(0).row(125)).to match_array(year_range) - expect(workbook_grouped.sheet(0).row(126)).to match_array(['0-3 Days', 0, 0, 1, 0, 0]) + expect(workbook_grouped.sheet(0).row(218)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(219)).to match_array(['0-3 Days', 0, 0, 1, 0, 0]) - expect(workbook_grouped.sheet(0).row(151)).to match_array( - ['Incident Location', nil, nil, nil, nil, nil] + expect(workbook_grouped.sheet(0).row(244)).to match_array( + ['Incident Statistics - 16. Incident Location', nil, nil, nil, nil, nil] ) - expect(workbook_grouped.sheet(0).row(152)).to match_array(year_range) - expect(workbook_grouped.sheet(0).row(153)).to match_array(['Bush/Forest', 0, 0, 1, 0, 0]) - expect(workbook_grouped.sheet(0).row(154)).to match_array( - ['Garden/Cultivated Field', 0, 0, 1, 0, 0] + expect(workbook_grouped.sheet(0).row(245)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(246)).to match_array(['Bush/Forest', 0, 0, 1, 0, 0]) + expect(workbook_grouped.sheet(0).row(247)).to match_array(['Garden/Cultivated Field', 0, 0, 1, 0, 0]) + expect(workbook_grouped.sheet(0).row(248)).to match_array(['School', 0, 0, 1, 0, 0]) + + expect(workbook_grouped.sheet(0).row(273)).to match_array( + ['Perpetrator Statistics - 17. Number of Primary Perpetrators', nil, nil, nil, nil, nil] ) - expect(workbook_grouped.sheet(0).row(155)).to match_array(['School', 0, 0, 1, 0, 0]) - end + expect(workbook_grouped.sheet(0).row(274)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(275)).to match_array([1, 0, 0, 1, 0, 0]) + expect(workbook_grouped.sheet(0).row(276)).to match_array([2, 0, 0, 1, 0, 0]) + expect(workbook_grouped.sheet(0).row(277)).to match_array([3, 0, 0, 1, 0, 0]) + + expect(workbook_grouped.sheet(0).row(302)).to match_array( + ['Perpetrator Statistics - 18. Alleged Perpetrator - Survivor Relationship', nil, nil, nil, nil, nil] + ) + expect(workbook_grouped.sheet(0).row(303)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(304)).to match_array(['Primary Caregiver', 0, 0, 3, 0, 0]) + expect(workbook_grouped.sheet(0).row(305)).to match_array(['Other', 0, 0, 1, 0, 0]) + expect(workbook_grouped.sheet(0).row(306)).to match_array(['No relation', 0, 0, 2, 0, 0]) + + expect(workbook_grouped.sheet(0).row(331)).to match_array( + ['Perpetrator Statistics - 19. Alleged Primary Perpetrators Age Group', nil, nil, nil, nil, nil] + ) + expect(workbook_grouped.sheet(0).row(332)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(333)).to match_array(['0-11', 0, 0, 3, 0, 0]) + expect(workbook_grouped.sheet(0).row(334)).to match_array(['12-17', 0, 0, 2, 0, 0]) + expect(workbook_grouped.sheet(0).row(335)).to match_array(['18-25', 0, 0, 1, 0, 0]) + + expect(workbook_grouped.sheet(0).row(360)).to match_array( + ['Perpetrator Statistics - 20. Alleged Primary Perpetrator Occupation', nil, nil, nil, nil, nil] + ) + expect(workbook_grouped.sheet(0).row(361)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(362)).to match_array(['Occupation 1', 0, 0, 2, 0, 0]) + expect(workbook_grouped.sheet(0).row(363)).to match_array(['Occupation 2', 0, 0, 2, 0, 0]) + expect(workbook_grouped.sheet(0).row(364)).to match_array(['Unknown', 0, 0, 1, 0, 0]) + expect(workbook_grouped.sheet(0).row(365)).to match_array(['Incomplete Data', 0, 0, 1, 0, 0]) - it 'prints the referrals subreport' do - expect(workbook_grouped.sheet(3).row(1)).to match_array( - ['Referrals', nil, nil, nil, nil, nil] + expect(workbook_grouped.sheet(0).row(390)).to match_array( + [ + 'Referral Statistics - ' \ + '21. Number of incidents for which your organisation is the first point of contact', + nil, nil, nil, nil, nil + ] + ) + expect(workbook_grouped.sheet(0).row(392)).to match_array( + ['Referral Statistics - 22. Incidents Referred From Other Service Providers', nil, nil, nil, nil, nil] + ) + expect(workbook_grouped.sheet(0).row(393)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(394)).to match_array( + ['Incidents', 0, 0, 1, 0, 0] ) - expect(workbook_grouped.sheet(3).row(7)).to match_array( - ['Incidents Referred from Other Service Providers', nil, nil, nil, nil, nil] + expect(workbook_grouped.sheet(0).row(419)).to match_array( + [ + 'Referral Statistics - 23. Number of Services Provided for Incidents', + nil, nil, nil, nil, nil + ] ) - expect(workbook_grouped.sheet(3).row(8)).to match_array(year_range) - expect(workbook_grouped.sheet(3).row(9)).to match_array( - ['Incidents Referred from Other Service Providers', 0, 0, 1, 0, 0] + expect(workbook_grouped.sheet(0).row(421)).to match_array( + ['Referral Statistics - 24. New Incident Referrals to Other Service Providers', nil, nil, nil, nil, nil] + ) + expect(workbook_grouped.sheet(0).row(422)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(423)).to match_array( + ['Health/Medical Referral', 0, 0, 1, 0, 0] ) end end @@ -514,15 +662,16 @@ Roo::Spreadsheet.open(StringIO.new(data), extension: :xlsx) end - context 'Incidents subreport' do + context 'GBV Statistics subreport' do it 'prints subreport headers' do - expect(workbook_grouped.sheet(0).row(1)).to match_array(['Incidents', nil, nil]) + expect(workbook_grouped.sheet(0).row(1)).to match_array(['GBV Statistics', nil, nil]) end it 'prints report params' do - result = 'View By: Year / Date Range: Custom / '\ - "From: #{(Date.today - 1.year).strftime('%Y-%m-%d')} / "\ - "To: #{Date.today.end_of_year.strftime('%Y-%m-%d')} / Date: Date of Incident / " + result = + 'View By: Year / Date Range: Custom / ' \ + "From: #{(Date.today - 1.year).strftime('%Y-%m-%d')} / " \ + "To: #{Date.today.end_of_year.strftime('%Y-%m-%d')} / Date: Date of Incident / " expect(workbook_grouped.sheet(0).row(2)).to match_array([result, nil, nil]) end @@ -533,79 +682,169 @@ ] expect(workbook_grouped.sheet(0).row(5)).to match_array( - ['Incidents', nil, nil] + ['General Statistics', nil, nil] ) expect(workbook_grouped.sheet(0).row(6)).to match_array(year_range) expect(workbook_grouped.sheet(0).row(7)).to match_array( - ['Number of GBV Incidents Reported', 0, 3] + ['1. New GBV Incidents Reported', 0, 3] ) expect(workbook_grouped.sheet(0).row(8)).to match_array( - ['Number of Incidents Reported by Survivors with Prior GBV Incidents', 0, 1] + ['2. New Incidents of Sexual Violence Reported', 0, 1] ) - expect(workbook_grouped.sheet(0).row(9)).to match_array( - ['Number of Incidents of Sexual Violence Reported', 0, 3] + expect(workbook_grouped.sheet(0).row(11)).to match_array( + ['Survivor Statistics - 3. Sex of survivors', nil, nil] ) + expect(workbook_grouped.sheet(0).row(13)).to match_array( + ['Survivor Statistics - 4. Age of survivors', nil, nil] + ) + expect(workbook_grouped.sheet(0).row(14)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(15)).to match_array([AgeRange.new(0, 4).to_s, 0, 2]) + expect(workbook_grouped.sheet(0).row(16)).to match_array([AgeRange.new(5, 11).to_s, 0, 1]) - expect(workbook_grouped.sheet(0).row(12)).to match_array( - ['Incident Type', nil, nil] + expect(workbook_grouped.sheet(0).row(41)).to eq( + ['Survivor Statistics - 5. Marital Status of Survivors', nil, nil] ) - expect(workbook_grouped.sheet(0).row(13)).to match_array(year_range) - expect(workbook_grouped.sheet(0).row(14)).to match_array(['Rape', 0, 1]) - expect(workbook_grouped.sheet(0).row(15)).to match_array( - ['Sexual Assault', 0, 1] + expect(workbook_grouped.sheet(0).row(43)).to eq( + ['Survivor Statistics - 6. Displacement Status at Time of Report', nil, nil] ) - expect(workbook_grouped.sheet(0).row(16)).to match_array( - ['Forced Marriage', 0, 1] + expect(workbook_grouped.sheet(0).row(45)).to eq( + ['Survivor Statistics - 7. Stage of Displacement at Time of Incident', nil, nil] + ) + expect(workbook_grouped.sheet(0).row(47)).to eq( + ['Survivor Statistics - 8. Vulnerable Populations', nil, nil] + ) + + expect(workbook_grouped.sheet(0).row(49)).to eq( + ['Survivor Statistics - 9. Number of Incidents of Sexual Violence Reported', nil, nil] + ) + expect(workbook_grouped.sheet(0).row(50)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(51)).to match_array( + ['Incidents', 0, 3] ) - expect(workbook_grouped.sheet(0).row(41)).to match_array( - ['Incident Time of Day', nil, nil] + expect(workbook_grouped.sheet(0).row(76)).to eq( + ['Incident Statistics - 10. Type of GBV', nil, nil] + ) + expect(workbook_grouped.sheet(0).row(77)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(78)).to match_array( + ['Rape', 0, 1] + ) + expect(workbook_grouped.sheet(0).row(79)).to match_array( + ['Sexual Assault', 0, 1] ) - expect(workbook_grouped.sheet(0).row(42)).to match_array(year_range) - expect(workbook_grouped.sheet(0).row(43)).to match_array( - ['Morning (sunrise to noon)', 0, 1] + expect(workbook_grouped.sheet(0).row(80)).to match_array( + ['Forced Marriage', 0, 1] ) - expect(workbook_grouped.sheet(0).row(44)).to match_array( - ['Afternoon (noon to sunset)', 0, 1] + + expect(workbook_grouped.sheet(0).row(105)).to eq( + ['Incident Statistics - 11. Incident Time of Day', nil, nil] ) - expect(workbook_grouped.sheet(0).row(45)).to match_array( - ['Evening/Night (sunset to sunrise)', 0, 1] + expect(workbook_grouped.sheet(0).row(106)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(107)).to eq(['Morning (sunrise to noon)', 0, 1]) + expect(workbook_grouped.sheet(0).row(108)).to eq(['Afternoon (noon to sunset)', 0, 1]) + expect(workbook_grouped.sheet(0).row(109)).to eq(['Evening/Night (sunset to sunrise)', 0, 1]) + + expect(workbook_grouped.sheet(0).row(134)).to eq( + ['Incident Statistics - 12. Case Context', nil, nil] ) + expect(workbook_grouped.sheet(0).row(135)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(136)).to eq(['Child Sexual Abuse', 0, 2]) + expect(workbook_grouped.sheet(0).row(137)).to eq(['Early Marriage', 0, 1]) + expect(workbook_grouped.sheet(0).row(138)).to eq(['Possible Sexual Exploitation', 0, 1]) - expect(workbook_grouped.sheet(0).row(70)).to match_array( - ['Time Between Incident and Report Date', nil, nil] + expect(workbook_grouped.sheet(0).row(163)).to eq( + ['Incident Statistics - 13. Time Between Incident and Report Date', nil, nil] ) - expect(workbook_grouped.sheet(0).row(71)).to match_array(year_range) - expect(workbook_grouped.sheet(0).row(72)).to match_array(['0-3 Days', 0, 3]) + expect(workbook_grouped.sheet(0).row(164)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(165)).to eq(['0-3 Days', 0, 3]) - expect(workbook_grouped.sheet(0).row(97)).to match_array( + expect(workbook_grouped.sheet(0).row(190)).to eq( [ - 'Incidents of Rape, Time Elapsed between Incident and Report Date', + 'Incident Statistics - 14. Incidents of Rape, Time Elapsed between Incident and Report Date', nil, nil ] ) - expect(workbook_grouped.sheet(0).row(98)).to match_array(year_range) - expect(workbook_grouped.sheet(0).row(99)).to match_array(['0-3 Days', 0, 1]) + expect(workbook_grouped.sheet(0).row(191)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(192)).to eq(['0-3 Days', 0, 1]) - expect(workbook_grouped.sheet(0).row(124)).to match_array( + expect(workbook_grouped.sheet(0).row(217)).to match_array( [ - 'Incidents of Rape, Time Elapsed between Incident and Report Date (Health Service or Referral)', + 'Incident Statistics - 15. Incidents of Rape, Time Elapsed (Health Service or Referral)', nil, nil ] ) - expect(workbook_grouped.sheet(0).row(125)).to match_array(year_range) - expect(workbook_grouped.sheet(0).row(126)).to match_array(['0-3 Days', 0, 1]) + expect(workbook_grouped.sheet(0).row(218)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(219)).to match_array(['0-3 Days', 0, 1]) + + expect(workbook_grouped.sheet(0).row(244)).to match_array( + ['Incident Statistics - 16. Incident Location', nil, nil] + ) + expect(workbook_grouped.sheet(0).row(245)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(246)).to match_array(['Bush/Forest', 0, 1]) + expect(workbook_grouped.sheet(0).row(247)).to match_array(['Garden/Cultivated Field', 0, 1]) + expect(workbook_grouped.sheet(0).row(248)).to match_array(['School', 0, 1]) + + expect(workbook_grouped.sheet(0).row(273)).to match_array( + ['Perpetrator Statistics - 17. Number of Primary Perpetrators', nil, nil] + ) + expect(workbook_grouped.sheet(0).row(274)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(275)).to match_array([1, 0, 1]) + expect(workbook_grouped.sheet(0).row(276)).to match_array([2, 0, 1]) + expect(workbook_grouped.sheet(0).row(277)).to match_array([3, 0, 1]) + + expect(workbook_grouped.sheet(0).row(302)).to match_array( + ['Perpetrator Statistics - 18. Alleged Perpetrator - Survivor Relationship', nil, nil] + ) + expect(workbook_grouped.sheet(0).row(303)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(304)).to match_array(['Primary Caregiver', 0, 3]) + expect(workbook_grouped.sheet(0).row(305)).to match_array(['Other', 0, 1]) + expect(workbook_grouped.sheet(0).row(306)).to match_array(['No relation', 0, 2]) + + expect(workbook_grouped.sheet(0).row(331)).to match_array( + ['Perpetrator Statistics - 19. Alleged Primary Perpetrators Age Group', nil, nil] + ) + expect(workbook_grouped.sheet(0).row(332)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(333)).to match_array(['0-11', 0, 3]) + expect(workbook_grouped.sheet(0).row(334)).to match_array(['12-17', 0, 2]) + expect(workbook_grouped.sheet(0).row(335)).to match_array(['18-25', 0, 1]) + + expect(workbook_grouped.sheet(0).row(360)).to match_array( + ['Perpetrator Statistics - 20. Alleged Primary Perpetrator Occupation', nil, nil] + ) + expect(workbook_grouped.sheet(0).row(361)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(362)).to match_array(['Occupation 1', 0, 2]) + expect(workbook_grouped.sheet(0).row(363)).to match_array(['Occupation 2', 0, 2]) + expect(workbook_grouped.sheet(0).row(364)).to match_array(['Unknown', 0, 1]) + expect(workbook_grouped.sheet(0).row(365)).to match_array(['Incomplete Data', 0, 1]) - expect(workbook_grouped.sheet(0).row(151)).to match_array( - ['Incident Location', nil, nil] + expect(workbook_grouped.sheet(0).row(390)).to match_array( + [ + 'Referral Statistics - ' \ + '21. Number of incidents for which your organisation is the first point of contact', + nil, nil + ] + ) + expect(workbook_grouped.sheet(0).row(392)).to match_array( + ['Referral Statistics - 22. Incidents Referred From Other Service Providers', nil, nil] + ) + expect(workbook_grouped.sheet(0).row(393)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(394)).to match_array( + ['Incidents', 0, 1] + ) + expect(workbook_grouped.sheet(0).row(419)).to match_array( + [ + 'Referral Statistics - 23. Number of Services Provided for Incidents', + nil, nil + ] + ) + expect(workbook_grouped.sheet(0).row(421)).to match_array( + ['Referral Statistics - 24. New Incident Referrals to Other Service Providers', nil, nil] ) - expect(workbook_grouped.sheet(0).row(152)).to match_array(year_range) - expect(workbook_grouped.sheet(0).row(153)).to match_array(['Bush/Forest', 0, 1]) - expect(workbook_grouped.sheet(0).row(154)).to match_array( - ['Garden/Cultivated Field', 0, 1] + expect(workbook_grouped.sheet(0).row(422)).to match_array(year_range) + expect(workbook_grouped.sheet(0).row(423)).to match_array( + ['Health/Medical Referral', 0, 1] ) - expect(workbook_grouped.sheet(0).row(155)).to match_array(['School', 0, 1]) end end end @@ -633,12 +872,12 @@ context 'Incidents subreport' do it 'prints subreport headers' do - expect(workbook_grouped.sheet(0).row(1)).to match_array(['Incidents', nil]) + expect(workbook_grouped.sheet(0).row(1)).to match_array(['GBV Statistics', nil]) end it 'prints report params' do - result = 'View By: Quarter / Date Range: This Quarter / '\ - 'Date: Date of Incident / ' + result = 'View By: Quarter / Date Range: This Quarter / ' \ + 'Date: Date of Incident / ' expect(workbook_grouped.sheet(0).row(2)).to match_array([result, nil]) end @@ -647,79 +886,169 @@ quarter_range = [nil, "#{Date.today.year}-Q#{(Date.today.month / 3.0).ceil}"] expect(workbook_grouped.sheet(0).row(5)).to match_array( - ['Incidents', nil] + ['General Statistics', nil] ) expect(workbook_grouped.sheet(0).row(6)).to match_array(quarter_range) expect(workbook_grouped.sheet(0).row(7)).to match_array( - ['Number of GBV Incidents Reported', 3] + ['1. New GBV Incidents Reported', 3] ) expect(workbook_grouped.sheet(0).row(8)).to match_array( - ['Number of Incidents Reported by Survivors with Prior GBV Incidents', 1] + ['2. New Incidents of Sexual Violence Reported', 1] ) - expect(workbook_grouped.sheet(0).row(9)).to match_array( - ['Number of Incidents of Sexual Violence Reported', 3] + expect(workbook_grouped.sheet(0).row(11)).to match_array( + ['Survivor Statistics - 3. Sex of survivors', nil] ) + expect(workbook_grouped.sheet(0).row(13)).to match_array( + ['Survivor Statistics - 4. Age of survivors', nil] + ) + expect(workbook_grouped.sheet(0).row(14)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(15)).to match_array([AgeRange.new(0, 4).to_s, 2]) + expect(workbook_grouped.sheet(0).row(16)).to match_array([AgeRange.new(5, 11).to_s, 1]) - expect(workbook_grouped.sheet(0).row(12)).to match_array( - ['Incident Type', nil] + expect(workbook_grouped.sheet(0).row(41)).to eq( + ['Survivor Statistics - 5. Marital Status of Survivors', nil] ) - expect(workbook_grouped.sheet(0).row(13)).to match_array(quarter_range) - expect(workbook_grouped.sheet(0).row(14)).to match_array(['Rape', 1]) - expect(workbook_grouped.sheet(0).row(15)).to match_array( - ['Sexual Assault', 1] + expect(workbook_grouped.sheet(0).row(43)).to eq( + ['Survivor Statistics - 6. Displacement Status at Time of Report', nil] ) - expect(workbook_grouped.sheet(0).row(16)).to match_array( - ['Forced Marriage', 1] + expect(workbook_grouped.sheet(0).row(45)).to eq( + ['Survivor Statistics - 7. Stage of Displacement at Time of Incident', nil] + ) + expect(workbook_grouped.sheet(0).row(47)).to eq( + ['Survivor Statistics - 8. Vulnerable Populations', nil] + ) + + expect(workbook_grouped.sheet(0).row(49)).to eq( + ['Survivor Statistics - 9. Number of Incidents of Sexual Violence Reported', nil] + ) + expect(workbook_grouped.sheet(0).row(50)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(51)).to match_array( + ['Incidents', 3] ) - expect(workbook_grouped.sheet(0).row(41)).to match_array( - ['Incident Time of Day', nil] + expect(workbook_grouped.sheet(0).row(76)).to eq( + ['Incident Statistics - 10. Type of GBV', nil] ) - expect(workbook_grouped.sheet(0).row(42)).to match_array(quarter_range) - expect(workbook_grouped.sheet(0).row(43)).to match_array( - ['Morning (sunrise to noon)', 1] + expect(workbook_grouped.sheet(0).row(77)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(78)).to match_array( + ['Rape', 1] ) - expect(workbook_grouped.sheet(0).row(44)).to match_array( - ['Afternoon (noon to sunset)', 1] + expect(workbook_grouped.sheet(0).row(79)).to match_array( + ['Sexual Assault', 1] + ) + expect(workbook_grouped.sheet(0).row(80)).to match_array( + ['Forced Marriage', 1] + ) + + expect(workbook_grouped.sheet(0).row(105)).to eq( + ['Incident Statistics - 11. Incident Time of Day', nil] ) - expect(workbook_grouped.sheet(0).row(45)).to match_array( - ['Evening/Night (sunset to sunrise)', 1] + expect(workbook_grouped.sheet(0).row(106)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(107)).to eq(['Morning (sunrise to noon)', 1]) + expect(workbook_grouped.sheet(0).row(108)).to eq(['Afternoon (noon to sunset)', 1]) + expect(workbook_grouped.sheet(0).row(109)).to eq(['Evening/Night (sunset to sunrise)', 1]) + + expect(workbook_grouped.sheet(0).row(134)).to eq( + ['Incident Statistics - 12. Case Context', nil] ) + expect(workbook_grouped.sheet(0).row(135)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(136)).to eq(['Child Sexual Abuse', 2]) + expect(workbook_grouped.sheet(0).row(137)).to eq(['Early Marriage', 1]) + expect(workbook_grouped.sheet(0).row(138)).to eq(['Possible Sexual Exploitation', 1]) - expect(workbook_grouped.sheet(0).row(70)).to match_array( - ['Time Between Incident and Report Date', nil] + expect(workbook_grouped.sheet(0).row(163)).to eq( + ['Incident Statistics - 13. Time Between Incident and Report Date', nil] ) - expect(workbook_grouped.sheet(0).row(71)).to match_array(quarter_range) - expect(workbook_grouped.sheet(0).row(72)).to match_array(['0-3 Days', 3]) + expect(workbook_grouped.sheet(0).row(164)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(165)).to eq(['0-3 Days', 3]) - expect(workbook_grouped.sheet(0).row(97)).to match_array( + expect(workbook_grouped.sheet(0).row(190)).to eq( [ - 'Incidents of Rape, Time Elapsed between Incident and Report Date', + 'Incident Statistics - 14. Incidents of Rape, Time Elapsed between Incident and Report Date', nil ] ) - expect(workbook_grouped.sheet(0).row(98)).to match_array(quarter_range) - expect(workbook_grouped.sheet(0).row(99)).to match_array(['0-3 Days', 1]) + expect(workbook_grouped.sheet(0).row(191)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(192)).to eq(['0-3 Days', 1]) - expect(workbook_grouped.sheet(0).row(124)).to match_array( + expect(workbook_grouped.sheet(0).row(217)).to match_array( [ - 'Incidents of Rape, Time Elapsed between Incident and Report Date (Health Service or Referral)', + 'Incident Statistics - 15. Incidents of Rape, Time Elapsed (Health Service or Referral)', nil ] ) - expect(workbook_grouped.sheet(0).row(125)).to match_array(quarter_range) - expect(workbook_grouped.sheet(0).row(126)).to match_array(['0-3 Days', 1]) + expect(workbook_grouped.sheet(0).row(218)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(219)).to match_array(['0-3 Days', 1]) + + expect(workbook_grouped.sheet(0).row(244)).to match_array( + ['Incident Statistics - 16. Incident Location', nil] + ) + expect(workbook_grouped.sheet(0).row(245)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(246)).to match_array(['Bush/Forest', 1]) + expect(workbook_grouped.sheet(0).row(247)).to match_array(['Garden/Cultivated Field', 1]) + expect(workbook_grouped.sheet(0).row(248)).to match_array(['School', 1]) + + expect(workbook_grouped.sheet(0).row(273)).to match_array( + ['Perpetrator Statistics - 17. Number of Primary Perpetrators', nil] + ) + expect(workbook_grouped.sheet(0).row(274)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(275)).to match_array([1, 1]) + expect(workbook_grouped.sheet(0).row(276)).to match_array([2, 1]) + expect(workbook_grouped.sheet(0).row(277)).to match_array([3, 1]) - expect(workbook_grouped.sheet(0).row(151)).to match_array( - ['Incident Location', nil] + expect(workbook_grouped.sheet(0).row(302)).to match_array( + ['Perpetrator Statistics - 18. Alleged Perpetrator - Survivor Relationship', nil] ) - expect(workbook_grouped.sheet(0).row(152)).to match_array(quarter_range) - expect(workbook_grouped.sheet(0).row(153)).to match_array(['Bush/Forest', 1]) - expect(workbook_grouped.sheet(0).row(154)).to match_array( - ['Garden/Cultivated Field', 1] + expect(workbook_grouped.sheet(0).row(303)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(304)).to match_array(['Primary Caregiver', 3]) + expect(workbook_grouped.sheet(0).row(305)).to match_array(['Other', 1]) + expect(workbook_grouped.sheet(0).row(306)).to match_array(['No relation', 2]) + + expect(workbook_grouped.sheet(0).row(331)).to match_array( + ['Perpetrator Statistics - 19. Alleged Primary Perpetrators Age Group', nil] + ) + expect(workbook_grouped.sheet(0).row(332)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(333)).to match_array(['0-11', 3]) + expect(workbook_grouped.sheet(0).row(334)).to match_array(['12-17', 2]) + expect(workbook_grouped.sheet(0).row(335)).to match_array(['18-25', 1]) + + expect(workbook_grouped.sheet(0).row(360)).to match_array( + ['Perpetrator Statistics - 20. Alleged Primary Perpetrator Occupation', nil] + ) + expect(workbook_grouped.sheet(0).row(361)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(362)).to match_array(['Occupation 1', 2]) + expect(workbook_grouped.sheet(0).row(363)).to match_array(['Occupation 2', 2]) + expect(workbook_grouped.sheet(0).row(364)).to match_array(['Unknown', 1]) + expect(workbook_grouped.sheet(0).row(365)).to match_array(['Incomplete Data', 1]) + + expect(workbook_grouped.sheet(0).row(390)).to match_array( + [ + 'Referral Statistics - ' \ + '21. Number of incidents for which your organisation is the first point of contact', + nil + ] + ) + expect(workbook_grouped.sheet(0).row(392)).to match_array( + ['Referral Statistics - 22. Incidents Referred From Other Service Providers', nil] + ) + expect(workbook_grouped.sheet(0).row(393)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(394)).to match_array( + ['Incidents', 1] + ) + expect(workbook_grouped.sheet(0).row(419)).to match_array( + [ + 'Referral Statistics - 23. Number of Services Provided for Incidents', + nil + ] + ) + expect(workbook_grouped.sheet(0).row(421)).to match_array( + ['Referral Statistics - 24. New Incident Referrals to Other Service Providers', nil] + ) + expect(workbook_grouped.sheet(0).row(422)).to match_array(quarter_range) + expect(workbook_grouped.sheet(0).row(423)).to match_array( + ['Health/Medical Referral', 1] ) - expect(workbook_grouped.sheet(0).row(155)).to match_array(['School', 1]) end end end @@ -778,7 +1107,7 @@ data: { type: 'killing', attack_type: 'arson', ctfmr_verified_date: Date.new(2022, 5, 8), - violation_tally: { 'boys': 1, 'girls': 1, 'unknown': 1, 'total': 3 } + violation_tally: { boys: 1, girls: 1, unknown: 1, total: 3 } }, incident_id: incident1.id ) @@ -787,7 +1116,7 @@ data: { type: 'killing', attack_type: 'aerial_attack', ctfmr_verified_date: Date.new(2022, 2, 8), - violation_tally: { 'boys': 1, 'girls': 1, 'unknown': 1, 'total': 3 } + violation_tally: { boys: 1, girls: 1, unknown: 1, total: 3 } }, incident_id: incident2.id ) @@ -796,7 +1125,7 @@ data: { type: 'killing', attack_type: 'aerial_attack', ctfmr_verified_date: Date.new(2022, 3, 18), - violation_tally: { 'boys': 1, 'girls': 1, 'unknown': 4, 'total': 6 } + violation_tally: { boys: 1, girls: 1, unknown: 4, total: 6 } }, incident_id: incident3.id ) @@ -805,7 +1134,7 @@ data: { type: 'killing', attack_type: 'suicide_attack', ctfmr_verified_date: Date.new(2022, 4, 28), - violation_tally: { 'boys': 3, 'girls': 1, 'unknown': 1, 'total': 5 } + violation_tally: { boys: 3, girls: 1, unknown: 1, total: 5 } }, incident_id: incident4.id ) @@ -910,19 +1239,16 @@ end it 'should export all the sheets' do - expect(workbook_all.sheets.size).to eq(4) + expect(workbook_all.sheets.size).to eq(1) end it 'should export the excel' do - expect(workbook_all.sheets.size).to eq(4) - expect(workbook_all.sheets).to match_array(%w[Incidents Perpetrators Survivors Referrals]) + expect(workbook_all.sheets.size).to eq(1) + expect(workbook_all.sheets).to match_array(['GBV Statistics']) end it 'prints subreports headers' do - expect(workbook_all.sheet(0).row(1)).to match_array(['Incidents', nil, nil]) - expect(workbook_all.sheet(1).row(1)).to match_array(['Perpetrators', nil, nil]) - expect(workbook_all.sheet(2).row(1)).to match_array(['Survivors', nil, nil]) - expect(workbook_all.sheet(3).row(1)).to match_array(['Referrals', nil, nil]) + expect(workbook_all.sheet(0).row(1)).to match_array(['GBV Statistics', nil, nil]) end end @@ -943,22 +1269,55 @@ end it 'should export indicators in the correct order' do - expect(workbook.sheet(0).row(5).at(0)).to eq('Incidents') - expect(workbook.sheet(0).row(7).at(0)).to eq('Number of GBV Incidents Reported') - expect(workbook.sheet(0).row(8).at(0)).to eq('Number of Incidents of Sexual Violence Reported') - expect(workbook.sheet(0).row(9).at(0)).to eq( - 'Number of Incidents Reported by Survivors with Prior GBV Incidents' + expect(workbook.sheet(0).row(5).at(0)).to eq('General Statistics') + expect(workbook.sheet(0).row(7).at(0)).to eq('1. New GBV Incidents Reported') + expect(workbook.sheet(0).row(8).at(0)).to eq('2. New Incidents of Sexual Violence Reported') + expect(workbook.sheet(0).row(11).at(0)).to eq('Survivor Statistics - 3. Sex of survivors') + expect(workbook.sheet(0).row(38).at(0)).to eq('Survivor Statistics - 4. Age of survivors') + expect(workbook.sheet(0).row(67).at(0)).to eq('Survivor Statistics - 5. Marital Status of Survivors') + expect(workbook.sheet(0).row(94).at(0)).to eq('Survivor Statistics - 6. Displacement Status at Time of Report') + expect(workbook.sheet(0).row(121).at(0)).to eq( + 'Survivor Statistics - 7. Stage of Displacement at Time of Incident' + ) + expect(workbook.sheet(0).row(148).at(0)).to eq('Survivor Statistics - 8. Vulnerable Populations') + expect(workbook.sheet(0).row(176).at(0)).to eq( + 'Survivor Statistics - 9. Number of Incidents of Sexual Violence Reported' + ) + expect(workbook.sheet(0).row(204).at(0)).to eq('Incident Statistics - 10. Type of GBV') + expect(workbook.sheet(0).row(234).at(0)).to eq('Incident Statistics - 11. Incident Time of Day') + expect(workbook.sheet(0).row(264).at(0)).to eq('Incident Statistics - 12. Case Context') + expect(workbook.sheet(0).row(294).at(0)).to eq( + 'Incident Statistics - 13. Time Between Incident and Report Date' + ) + expect(workbook.sheet(0).row(322).at(0)).to eq( + 'Incident Statistics - 14. Incidents of Rape, Time Elapsed between Incident and Report Date' + ) + expect(workbook.sheet(0).row(350).at(0)).to eq( + 'Incident Statistics - 15. Incidents of Rape, Time Elapsed (Health Service or Referral)' ) - expect(workbook.sheet(0).row(12).at(0)).to eq('Incident Type') - expect(workbook.sheet(0).row(42).at(0)).to eq('Incident Time of Day') - expect(workbook.sheet(0).row(72).at(0)).to eq('Time Between Incident and Report Date') - expect(workbook.sheet(0).row(100).at(0)).to eq( - 'Incidents of Rape, Time Elapsed between Incident and Report Date' + expect(workbook.sheet(0).row(378).at(0)).to eq('Incident Statistics - 16. Incident Location') + expect(workbook.sheet(0).row(408).at(0)).to eq('Perpetrator Statistics - 17. Number of Primary Perpetrators') + expect(workbook.sheet(0).row(438).at(0)).to eq( + 'Perpetrator Statistics - 18. Alleged Perpetrator - Survivor Relationship' ) - expect(workbook.sheet(0).row(128).at(0)).to eq( - 'Incidents of Rape, Time Elapsed between Incident and Report Date (Health Service or Referral)' + expect(workbook.sheet(0).row(468).at(0)).to eq( + 'Perpetrator Statistics - 19. Alleged Primary Perpetrators Age Group' + ) + expect(workbook.sheet(0).row(498).at(0)).to eq( + 'Perpetrator Statistics - 20. Alleged Primary Perpetrator Occupation' + ) + expect(workbook.sheet(0).row(529).at(0)).to eq( + 'Referral Statistics - 21. Number of incidents for which your organisation is the first point of contact' + ) + expect(workbook.sheet(0).row(557).at(0)).to eq( + 'Referral Statistics - 22. Incidents Referred From Other Service Providers' + ) + expect(workbook.sheet(0).row(585).at(0)).to eq( + 'Referral Statistics - 23. Number of Services Provided for Incidents' + ) + expect(workbook.sheet(0).row(619).at(0)).to eq( + 'Referral Statistics - 24. New Incident Referrals to Other Service Providers' ) - expect(workbook.sheet(0).row(156).at(0)).to eq('Incident Location') end end @@ -985,49 +1344,74 @@ context 'should render report' do it 'prints subreport headers' do - expect(workbook_no_data.sheet(0).row(1)).to match_array(['Incidents']) + expect(workbook_no_data.sheet(0).row(1)).to match_array(['GBV Statistics']) end it 'prints report params' do - result = 'View By: Month / Date Range: Custom / '\ - "From: #{(Date.today + 1.month).strftime('%Y-%m-%d')} / "\ - "To: #{(Date.today + 2.month).strftime('%Y-%m-%d')} / Date: Date of Incident / " + result = + 'View By: Month / Date Range: Custom / ' \ + "From: #{(Date.today + 1.month).strftime('%Y-%m-%d')} / " \ + "To: #{(Date.today + 2.month).strftime('%Y-%m-%d')} / Date: Date of Incident / " expect(workbook_no_data.sheet(0).row(2)).to match_array([result]) end it 'prints indicator tables' do expect(workbook_no_data.sheet(0).row(7)).to match_array( - ['Number of GBV Incidents Reported'] + ['1. New GBV Incidents Reported'] ) expect(workbook_no_data.sheet(0).row(8)).to match_array( - ['Number of Incidents Reported by Survivors with Prior GBV Incidents'] + ['2. New Incidents of Sexual Violence Reported'] ) - expect(workbook_no_data.sheet(0).row(9)).to match_array( - ['Number of Incidents of Sexual Violence Reported'] + expect(workbook_no_data.sheet(0).row(13).at(0)).to eq('Survivor Statistics - 4. Age of survivors') + expect(workbook_no_data.sheet(0).row(15).at(0)).to eq('Survivor Statistics - 5. Marital Status of Survivors') + expect(workbook_no_data.sheet(0).row(17).at(0)).to eq( + 'Survivor Statistics - 6. Displacement Status at Time of Report' ) - - expect(workbook_no_data.sheet(0).row(12)).to match_array( - ['Incident Type'] + expect(workbook_no_data.sheet(0).row(19).at(0)).to eq( + 'Survivor Statistics - 7. Stage of Displacement at Time of Incident' ) - - expect(workbook_no_data.sheet(0).row(14)).to match_array( - ['Incident Time of Day'] + expect(workbook_no_data.sheet(0).row(21).at(0)).to eq('Survivor Statistics - 8. Vulnerable Populations') + expect(workbook_no_data.sheet(0).row(23).at(0)).to eq( + 'Survivor Statistics - 9. Number of Incidents of Sexual Violence Reported' ) - - expect(workbook_no_data.sheet(0).row(16)).to match_array( - ['Time Between Incident and Report Date'] + expect(workbook_no_data.sheet(0).row(25).at(0)).to eq('Incident Statistics - 10. Type of GBV') + expect(workbook_no_data.sheet(0).row(27).at(0)).to eq('Incident Statistics - 11. Incident Time of Day') + expect(workbook_no_data.sheet(0).row(29).at(0)).to eq('Incident Statistics - 12. Case Context') + expect(workbook_no_data.sheet(0).row(31).at(0)).to eq( + 'Incident Statistics - 13. Time Between Incident and Report Date' ) - expect(workbook_no_data.sheet(0).row(18)).to match_array( - ['Incidents of Rape, Time Elapsed between Incident and Report Date'] + expect(workbook_no_data.sheet(0).row(33).at(0)).to eq( + 'Incident Statistics - 14. Incidents of Rape, Time Elapsed between Incident and Report Date' ) - expect(workbook_no_data.sheet(0).row(20)).to match_array( - [ - 'Incidents of Rape, Time Elapsed between Incident and Report Date (Health Service or Referral)' - ] + expect(workbook_no_data.sheet(0).row(35).at(0)).to eq( + 'Incident Statistics - 15. Incidents of Rape, Time Elapsed (Health Service or Referral)' + ) + expect(workbook_no_data.sheet(0).row(37).at(0)).to eq('Incident Statistics - 16. Incident Location') + expect(workbook_no_data.sheet(0).row(39).at(0)).to eq( + 'Perpetrator Statistics - 17. Number of Primary Perpetrators' + ) + expect(workbook_no_data.sheet(0).row(41).at(0)).to eq( + 'Perpetrator Statistics - 18. Alleged Perpetrator - Survivor Relationship' + ) + expect(workbook_no_data.sheet(0).row(43).at(0)).to eq( + 'Perpetrator Statistics - 19. Alleged Primary Perpetrators Age Group' + ) + expect(workbook_no_data.sheet(0).row(45).at(0)).to eq( + 'Perpetrator Statistics - 20. Alleged Primary Perpetrator Occupation' + ) + expect(workbook_no_data.sheet(0).row(47).at(0)).to eq( + 'Referral Statistics - 21. Number of incidents for which your organisation is the first point of contact' + ) + expect(workbook_no_data.sheet(0).row(49).at(0)).to eq( + 'Referral Statistics - 22. Incidents Referred From Other Service Providers' + ) + expect(workbook_no_data.sheet(0).row(51).at(0)).to eq( + 'Referral Statistics - 23. Number of Services Provided for Incidents' + ) + expect(workbook_no_data.sheet(0).row(53).at(0)).to eq( + 'Referral Statistics - 24. New Incident Referrals to Other Service Providers' ) - - expect(workbook_no_data.sheet(0).row(22)).to match_array(['Incident Location']) end end end @@ -1074,7 +1458,7 @@ type: 'killing', ctfmr_verified: 'verified', ctfmr_verified_date: Date.new(2022, 4, 23), - violation_tally: { 'boys': 2, 'girls': 0, 'unknown': 2, 'total': 4 } + violation_tally: { boys: 2, girls: 0, unknown: 2, total: 4 } }, incident_id: incident0.id ) @@ -1082,7 +1466,7 @@ violation2 = Violation.create!( data: { type: 'abduction', ctfmr_verified: 'verified', ctfmr_verified_date: Date.new(2022, 6, 4), - violation_tally: { 'boys': 1, 'girls': 2, 'unknown': 5, 'total': 8 } }, + violation_tally: { boys: 1, girls: 2, unknown: 5, total: 8 } }, incident_id: incident1.id ) @@ -1090,21 +1474,21 @@ data: { type: 'maiming', ctfmr_verified: 'report_pending_verification', - violation_tally: { 'boys': 2, 'girls': 3, 'unknown': 2, 'total': 7 } + violation_tally: { boys: 2, girls: 3, unknown: 2, total: 7 } }, incident_id: incident0.id ) Violation.create!( data: { type: 'attack_on_schools', ctfmr_verified: 'report_pending_verification', - violation_tally: { 'boys': 3, 'girls': 4, 'unknown': 5, 'total': 12 } }, + violation_tally: { boys: 3, girls: 4, unknown: 5, total: 12 } }, incident_id: incident0.id ) Violation.create!( data: { type: 'attack_on_schools', ctfmr_verified: 'verified', ctfmr_verified_date: Date.new(2022, 4, 23), - violation_tally: { 'boys': 3, 'girls': 4, 'unknown': 5, 'total': 12 } }, + violation_tally: { boys: 3, girls: 4, unknown: 5, total: 12 } }, incident_id: incident0.id ) @@ -1425,7 +1809,8 @@ it 'prints report params' do expect(workbook.sheet(0).row(2)).to eq( [ - 'View By: Week / Date Range: Custom / From: 2023-04-30 / To: 2023-05-13 / '\ + 'View By: Week / Date Range: Custom / ' \ + 'From: 2023-04-30 / To: 2023-05-13 / ' \ 'Date: Registration Date / Status: Open,Closed / Type of Violence: Forced Marriage / ' \ 'By: User Groups of record owner / User Group: Group 1', nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil @@ -1434,7 +1819,8 @@ expect(workbook.sheet(1).row(2)).to eq( [ - 'View By: Week / Date Range: Custom / From: 2023-04-30 / To: 2023-05-13 / '\ + 'View By: Week / Date Range: Custom / ' \ + 'From: 2023-04-30 / To: 2023-05-13 / ' \ 'Date: Registration Date / Status: Open,Closed / Type of Violence: Forced Marriage / ' \ 'By: User Groups of record owner / User Group: Group 1', nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil diff --git a/spec/models/exporters/mrm_violation_exporter_spec.rb b/spec/models/exporters/mrm_violation_exporter_spec.rb index 246e4966de..dfde6a9293 100644 --- a/spec/models/exporters/mrm_violation_exporter_spec.rb +++ b/spec/models/exporters/mrm_violation_exporter_spec.rb @@ -216,6 +216,10 @@ def generate_forms(form_unique_ids) expect(workbook.sheets.size).to eq(6) end + it 'create worksheets with correct nams' do + expect(workbook.sheets).to match_array(Violation::MRM_ASSOCIATIONS_KEYS + %w[Violations]) + end + it 'prints the id headers' do expect(workbook.sheet(0).row(2)[0]).to eq('ID#') expect(workbook.sheet(0).row(3)[0..3]).to eq( diff --git a/spec/models/family_spec.rb b/spec/models/family_spec.rb index 06fb7691bb..380415c8d9 100644 --- a/spec/models/family_spec.rb +++ b/spec/models/family_spec.rb @@ -16,20 +16,25 @@ end describe 'quicksearch', search: true do - it 'has a searchable case id, survivor number' do - expected = %w[short_id family_id family_name family_number] - expect(Family.quicksearch_fields).to match_array(expected) - end - it 'can find a Family by Family Number' do - family = Family.create!(data: { family_name: 'Family One', family_number: 'ABC123XYZ' }) - family.index! - search_result = SearchService.search(Family, query: 'ABC123XYZ').results + Family.create!(data: { family_name: 'Family One', family_number: 'ABC123XYZ' }) + search_result = PhoneticSearchService.search(Family, query: 'ABC123XYZ').records expect(search_result).to have(1).family expect(search_result.first.family_number).to eq('ABC123XYZ') end end + describe 'phonetic tokens' do + before do + clean_data(Family) + end + + it 'generates the phonetic tokens' do + registry_record = Family.create!(data: { family_name: 'Miller' }) + expect(registry_record.tokens).to eq(%w[MLR]) + end + end + after do clean_data(Family) end diff --git a/spec/models/field_spec.rb b/spec/models/field_spec.rb index 03b7f8af4d..1c8295727f 100644 --- a/spec/models/field_spec.rb +++ b/spec/models/field_spec.rb @@ -858,7 +858,7 @@ end end - describe 'aggregate or disaggregate with number at the end should be able to match with a field' do + describe 'aggregate or disaggregate with number at the end should be able to match with a location field' do before do clean_data(FormSection) @@ -886,7 +886,7 @@ end it 'should return a field' do - expect(Field.find_by_name('field_name1')[0]['name']).to eq('field_name') + expect(Field.find_by_name('loc:field_name')[0]['name']).to eq('field_name') end end diff --git a/spec/models/filter_spec.rb b/spec/models/filter_spec.rb index 127006f035..d0143e2433 100644 --- a/spec/models/filter_spec.rb +++ b/spec/models/filter_spec.rb @@ -165,14 +165,14 @@ it 'has current location filter' do expect(@filters_cp[0]['cases']).to include(have_attributes(name: 'cases.filter_by.current_location', - field_name: 'location_current', + field_name: 'loc:location_current', type: 'multi_select')) end # TODO: test with different reporting location levels it 'has reporting location filter' do expect(@filters_cp[0]['cases']).to include(have_attributes(name: 'location.base_types.district', - field_name: 'owned_by_location2', + field_name: 'loc:owned_by_location2', type: 'multi_select')) end @@ -250,6 +250,10 @@ { id: 'assessment_requested_on', display_name: 'Date of Assessment' }, { id: 'date_case_plan', display_name: 'Date of Case Plan' }, { id: 'date_closure', display_name: 'Date of Case Closure ' }, + { id: 'followup_dates', display_name: 'Date of Follow Up' }, + { id: 'reunification_dates', display_name: 'Date of Reunification' }, + { id: 'tracing_dates', display_name: 'Date of Tracing' }, + { id: 'service_implemented_day_times', display_name: 'Date Service Completed' }, { id: 'created_at', display_name: 'Case Open Date' } ] expect( diff --git a/spec/models/incident_spec.rb b/spec/models/incident_spec.rb index 0e5f090dec..8449506607 100644 --- a/spec/models/incident_spec.rb +++ b/spec/models/incident_spec.rb @@ -8,8 +8,8 @@ describe Incident do before do clean_data( - User, Agency, Role, Incident, Child, PrimeroModule, PrimeroProgram, UserGroup, FormSection, Field, - Violation, Response, IndividualVictim, Source, Perpetrator, GroupVictim + SearchableIdentifier, User, Agency, Role, Incident, Child, PrimeroModule, PrimeroProgram, UserGroup, FormSection, + Field, Violation, Response, IndividualVictim, Source, Perpetrator, GroupVictim ) create(:agency) @@ -69,12 +69,13 @@ let(:incident_data) do { 'unique_id' => '790f958d-ac8e-414b-af64-e75831e3353a', + 'module_id' => PrimeroModule::MRM, 'incident_code' => '0123456', 'description' => 'this is a test', 'recruitment' => [ { 'unique_id' => '8dccaf74-e9aa-452a-9b58-dc365b1062a2', - 'violation_tally': { 'boys': 3, 'girls': 1, 'unknown': 0, 'total': 4 }, + 'violation_tally' => { 'boys' => 3, 'girls' => 1, 'unknown' => 0, 'total' => 4 }, 'name' => 'violation1' } ], @@ -116,7 +117,8 @@ } end before :each do - clean_data(Incident, Violation, Response, IndividualVictim, Source, Perpetrator, GroupVictim) + clean_data(SearchableIdentifier, Incident, Violation, Response, IndividualVictim, Source, Perpetrator, + GroupVictim) incident_record = Incident.new_with_user(fake_user, incident_data) incident_record.save! end @@ -174,7 +176,7 @@ 'incident_location' => 'IQG08Q02N02', 'incident_description' => 'none', 'incident_total_tally' => { 'boys' => 1, 'total' => 1 }, - 'incident_code': '9f88531', + incident_code: '9f88531', 'individual_victims' => [{ 'violations_ids' => ['222d97fb-b49d-401a-aff5-55dbe81a6fbf'], 'individual_multiple_violations' => false, @@ -218,7 +220,8 @@ 'module_id' => 'primeromodule-mrm' } end before :each do - clean_data(Incident, Violation, Response, IndividualVictim, Source, Perpetrator, GroupVictim) + clean_data(SearchableIdentifier, Incident, Violation, Response, IndividualVictim, Source, Perpetrator, + GroupVictim) incident_record = Incident.new_with_user(fake_user, data) incident_record.save! end @@ -308,7 +311,7 @@ describe '.copy_from_case' do before(:each) do - clean_data(Incident, Child, PrimeroModule, User) && module_cp + clean_data(SearchableIdentifier, Incident, Child, PrimeroModule, User) && module_cp module_cp = PrimeroModule.new( unique_id: 'primeromodule-cp', field_map: { @@ -408,7 +411,7 @@ end before :each do - clean_data(Incident, Violation) + clean_data(SearchableIdentifier, Incident, Violation) incident_record = Incident.new_with_user(fake_user, incident_data) incident_record.save! end @@ -441,7 +444,9 @@ describe 'add_alert_on_case' do before(:each) do - clean_data(Agency, SystemSettings, User, Incident, Child, PrimeroModule, Violation) && module_cp + clean_data( + SearchableIdentifier, Agency, SystemSettings, User, Incident, Child, PrimeroModule, Violation + ) && module_cp Agency.create!(unique_id: 'agency-1', agency_code: 'a1', name: 'Agency') @@ -463,24 +468,33 @@ case_cp end - it 'should add an alert for the case if the incident creator is not the case owner' do - incident = Incident.new_with_user( - User.new(user_name: 'incident_user', agency_id: Agency.last.id), - survivor_code: 'abc123', module_id: 'primeromodule-cp' - ) - incident.case = case_cp - incident.save! + let(:incident_user) { User.new(user_name: 'incident_user', agency_id: Agency.last.id) } - case_cp.reload + context 'when incident creator is not the case owner' do + before do + incident = Incident.new_with_user( + incident_user, + survivor_code: 'abc123', + module_id: 'primeromodule-cp' + ) + incident.case = case_cp + incident.save! + + case_cp.reload + end - expect(case_cp.alerts.size).to eq(1) + it 'should add an alert for the case' do + expect(case_cp.alerts.size).to eq(1) + expect(case_cp.alerts.first.type).to eq('incident_from_case') + expect(case_cp.alerts.first.form_sidebar_id).to eq('incident_from_case') + end end it 'should add a record history in the case after incident is created' do last_updated_at = case_cp.last_updated_at incident = Incident.new_with_user( - User.new(user_name: 'incident_user', agency_id: Agency.last.id), + incident_user, survivor_code: 'abc123', module_id: 'primeromodule-cp' ) incident.case = case_cp @@ -496,14 +510,18 @@ end describe '#update_properties' do - let(:incident) { Incident.create!(unique_id: '1a2b3c', incident_code: '0123456', description: 'this is a test') } + let(:incident) do + Incident.create!( + unique_id: '1a2b3c', incident_code: '0123456', description: 'this is a test', module_id: PrimeroModule::MRM + ) + end before do data = incident.data.clone data['recruitment'] = [ { 'unique_id' => '8dccaf74-e9aa-452a-9b58-dc365b1062a2', - 'violation_tally': { 'boys': 3, 'girls': 1, 'unknown': 0, 'total': 4 }, + 'violation_tally' => { 'boys' => 3, 'girls' => 1, 'unknown' => 0, 'total' => 4 }, 'name' => 'violation1' } ] @@ -584,21 +602,28 @@ end describe '#associations_as_data' do - let(:incident) { Incident.create!(unique_id: '1a2b3c', incident_code: '987654', description: 'this is a test') } + let(:incident) do + Incident.create!( + unique_id: '1a2b3c', incident_code: '987654', description: 'this is a test', module_id: PrimeroModule::MRM + ) + end + let(:incident2) do Incident.create!( unique_id: '15e65cf1-6980-4c7c-a591-94f900f5d721', - incident_code: '6980', description: 'this is a second test' + incident_code: '6980', + description: 'this is a second test', + module_id: PrimeroModule::MRM ) end before(:each) do - clean_data(Incident, Violation, IndividualVictim) + clean_data(SearchableIdentifier, Incident, Violation, IndividualVictim) data = incident.data.clone data['recruitment'] = [ { 'unique_id' => '8dccaf74-e9aa-452a-9b58-dc365b1062a2', - 'violation_tally': { 'boys': 3, 'girls': 1, 'unknown': 0, 'total': 4 }, + 'violation_tally' => { 'boys' => 3, 'girls' => 1, 'unknown' => 0, 'total' => 4 }, 'name' => 'violation1' } ] @@ -716,10 +741,10 @@ { 'id_number' => '1', 'violations_ids' => ['8dccaf74-e9aa-452a-9b58-dc365b1062a2'], - "source_interview_date": '2023-02-01', - "source_category": 'secondary', - "source_type": 'photograph', - "unique_id": 'ba604357-5dce-4861-b740-af5d40398ef7' + 'source_interview_date' => '2023-02-01', + 'source_category' => 'secondary', + 'source_type' => 'photograph', + 'unique_id' => 'ba604357-5dce-4861-b740-af5d40398ef7' } ] } @@ -818,6 +843,30 @@ end end + describe 'phonetic tokens' do + before do + clean_data(SearchableIdentifier, Incident) + end + + it 'generates the phonetic tokens' do + incident = Incident.create!(data: { super_incident_name: 'George', incident_description: 'New Incident' }) + expect(incident.tokens).to eq(%w[JRJ N ANST]) + end + end + + describe '#calculate_incident_date_derived' do + before do + clean_data(Incident) + end + + it 'sets the incident_date_derived field' do + incident = Incident.create!(data: { super_incident_name: 'George', incident_description: 'New Incident', + incident_date: '2024-10-08' }) + + expect(incident.incident_date_derived).to eq(Date.new(2024, 10, 8)) + end + end + private def create_incident_with_created_by(created_by, options = {}) @@ -827,8 +876,8 @@ def create_incident_with_created_by(created_by, options = {}) after do clean_data( - User, Agency, Role, Incident, Child, PrimeroModule, PrimeroProgram, UserGroup, FormSection, Field, - Violation, Response, IndividualVictim, Source, Perpetrator, GroupVictim + SearchableIdentifier, User, Agency, Role, Incident, Child, PrimeroModule, PrimeroProgram, UserGroup, FormSection, + Field, Violation, Response, IndividualVictim, Source, Perpetrator, GroupVictim ) end end diff --git a/spec/models/kpi/assessment_status_spec.rb b/spec/models/kpi/assessment_status_spec.rb index 91f5531dc8..bc9d9ddc52 100644 --- a/spec/models/kpi/assessment_status_spec.rb +++ b/spec/models/kpi/assessment_status_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::AssessmentStatus, search: true do +describe Kpi::AssessmentStatus, { search: true, skip_when_solr_disabled: true } do include FormAndFieldHelper include SunspotHelper diff --git a/spec/models/kpi/average_followup_meetings_per_case_spec.rb b/spec/models/kpi/average_followup_meetings_per_case_spec.rb index a4bde72919..b9e66c0ab1 100644 --- a/spec/models/kpi/average_followup_meetings_per_case_spec.rb +++ b/spec/models/kpi/average_followup_meetings_per_case_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::AverageFollowupMeetingsPerCase, search: true do +describe Kpi::AverageFollowupMeetingsPerCase, { search: true, skip_when_solr_disabled: true } do include FormAndFieldHelper include SunspotHelper diff --git a/spec/models/kpi/average_referrals_spec.rb b/spec/models/kpi/average_referrals_spec.rb index 1b1d51ad63..820163d620 100644 --- a/spec/models/kpi/average_referrals_spec.rb +++ b/spec/models/kpi/average_referrals_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::AverageReferrals, search: true do +describe Kpi::AverageReferrals, { search: true, skip_when_solr_disabled: true } do include FormAndFieldHelper include SunspotHelper diff --git a/spec/models/kpi/case_closure_rate_spec.rb b/spec/models/kpi/case_closure_rate_spec.rb index 4dbbeae745..f4a0159527 100644 --- a/spec/models/kpi/case_closure_rate_spec.rb +++ b/spec/models/kpi/case_closure_rate_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::CaseClosureRate, search: true do +describe Kpi::CaseClosureRate, { search: true, skip_when_solr_disabled: true } do include FormAndFieldHelper include SunspotHelper diff --git a/spec/models/kpi/case_load_spec.rb b/spec/models/kpi/case_load_spec.rb index 46f60c6682..006b8e7d72 100644 --- a/spec/models/kpi/case_load_spec.rb +++ b/spec/models/kpi/case_load_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::CaseLoad, search: true do +describe Kpi::CaseLoad, { search: true, skip_when_solr_disabled: true } do include FormAndFieldHelper include SunspotHelper diff --git a/spec/models/kpi/client_satification_rate_spec.rb b/spec/models/kpi/client_satification_rate_spec.rb index c7aabc02fa..0e0263fbc0 100644 --- a/spec/models/kpi/client_satification_rate_spec.rb +++ b/spec/models/kpi/client_satification_rate_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::ClientSatisfactionRate, search: true do +describe Kpi::ClientSatisfactionRate, { search: true, skip_when_solr_disabled: true } do include FormAndFieldHelper include SunspotHelper diff --git a/spec/models/kpi/completed_action_plans_approved_by_superviror_spec.rb b/spec/models/kpi/completed_action_plans_approved_by_superviror_spec.rb index ef6aeba9f1..f52f80f200 100644 --- a/spec/models/kpi/completed_action_plans_approved_by_superviror_spec.rb +++ b/spec/models/kpi/completed_action_plans_approved_by_superviror_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::CompletedSupervisorApprovedCaseActionPlans, search: true do +describe Kpi::CompletedSupervisorApprovedCaseActionPlans, { search: true, skip_when_solr_disabled: true } do include FormAndFieldHelper include SunspotHelper diff --git a/spec/models/kpi/completed_action_plans_spec.rb b/spec/models/kpi/completed_action_plans_spec.rb index ad6dde35af..5ee37eae68 100644 --- a/spec/models/kpi/completed_action_plans_spec.rb +++ b/spec/models/kpi/completed_action_plans_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::CompletedCaseActionPlans, search: true do +describe Kpi::CompletedCaseActionPlans, { search: true, skip_when_solr_disabled: true } do include FormAndFieldHelper include SunspotHelper diff --git a/spec/models/kpi/completed_safety_plans_spec.rb b/spec/models/kpi/completed_safety_plans_spec.rb index 4f4cb095fc..a14e54ddd3 100644 --- a/spec/models/kpi/completed_safety_plans_spec.rb +++ b/spec/models/kpi/completed_safety_plans_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::CompletedCaseSafetyPlans, search: true do +describe Kpi::CompletedCaseSafetyPlans, { search: true, skip_when_solr_disabled: true } do include FormAndFieldHelper include SunspotHelper diff --git a/spec/models/kpi/number_of_cases_spec.rb b/spec/models/kpi/number_of_cases_spec.rb index 61a4e22337..ff9b2b2558 100644 --- a/spec/models/kpi/number_of_cases_spec.rb +++ b/spec/models/kpi/number_of_cases_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::NumberOfCases, search: true do +describe Kpi::NumberOfCases, { search: true, skip_when_solr_disabled: true } do include SunspotHelper let(:from) { indexed_field(DateTime.parse('2020/09/01')) } diff --git a/spec/models/kpi/number_of_incidents_spec.rb b/spec/models/kpi/number_of_incidents_spec.rb index 85564e8898..17dd16078b 100644 --- a/spec/models/kpi/number_of_incidents_spec.rb +++ b/spec/models/kpi/number_of_incidents_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::NumberOfIncidents, search: true do +describe Kpi::NumberOfIncidents, { search: true, skip_when_solr_disabled: true } do include SunspotHelper let(:from) { indexed_field(DateTime.parse('2020/09/01')) } diff --git a/spec/models/kpi/reporting_delay_spec.rb b/spec/models/kpi/reporting_delay_spec.rb index 8e3b41c640..caa829f4c6 100644 --- a/spec/models/kpi/reporting_delay_spec.rb +++ b/spec/models/kpi/reporting_delay_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::ReportingDelay, search: true do +describe Kpi::ReportingDelay, { search: true, skip_when_solr_disabled: true } do include SunspotHelper let(:from) { indexed_field(DateTime.parse('2020/09/01')) } diff --git a/spec/models/kpi/services_provided_spec.rb b/spec/models/kpi/services_provided_spec.rb index 7825074a9e..7145d75ba1 100644 --- a/spec/models/kpi/services_provided_spec.rb +++ b/spec/models/kpi/services_provided_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::ServicesProvided, search: true do +describe Kpi::ServicesProvided, { search: true, skip_when_solr_disabled: true } do include FormAndFieldHelper include SunspotHelper diff --git a/spec/models/kpi/time_from_case_open_to_case_close_spec.rb b/spec/models/kpi/time_from_case_open_to_case_close_spec.rb index 2ef9f77569..cd33ac6d91 100644 --- a/spec/models/kpi/time_from_case_open_to_case_close_spec.rb +++ b/spec/models/kpi/time_from_case_open_to_case_close_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe Kpi::TimeFromCaseOpenToClose, search: true do +describe Kpi::TimeFromCaseOpenToClose, { search: true, skip_when_solr_disabled: true } do include FormAndFieldHelper include SunspotHelper diff --git a/spec/models/managed_report_spec.rb b/spec/models/managed_report_spec.rb index 7de23e059d..233c86086f 100644 --- a/spec/models/managed_report_spec.rb +++ b/spec/models/managed_report_spec.rb @@ -14,20 +14,26 @@ it 'return a Hash of ManagedReport' do expect(managed_reports).to be_an_instance_of(Hash) - expect(managed_reports.size).to eq(7) + expect(managed_reports.size).to eq(12) end it 'should have gbv_statistics and violation keys' do expect(managed_reports.keys).to match_array([Permission::GBV_STATISTICS_REPORT, Permission::VIOLATION_REPORT, Permission::GHN_REPORT, - Permission::INDIVIDUAL_CHILDREN, Permission::WORKFLOW_REPORT, + Permission::INDIVIDUAL_CHILDREN, + Permission::PROTECTION_CONCERNS_REPORT, + Permission::REPORTING_LOCATIONS_REPORT, + Permission::FOLLOWUPS_REPORT, + Permission::SERVICES_REPORT, + Permission::CASES_WORKFLOW_REPORT, + Permission::WORKFLOW_REPORT, Permission::VIOLENCE_TYPE_REPORT, Permission::REFERRALS_TRANSFERS_REPORT]) end it 'should return subreports of gbv_statistics' do expect(managed_reports[Permission::GBV_STATISTICS_REPORT].subreports).to match_array( - %w[incidents perpetrators survivors referrals] + %w[incidents] ) end diff --git a/spec/models/managed_reports/indicators/incident_attack_on_spec.rb b/spec/models/managed_reports/indicators/incident_attack_on_spec.rb index bb01a5fea3..10e379f67e 100644 --- a/spec/models/managed_reports/indicators/incident_attack_on_spec.rb +++ b/spec/models/managed_reports/indicators/incident_attack_on_spec.rb @@ -45,7 +45,7 @@ ) Violation.create!( - data: { type: 'maiming', violation_tally: { 'boys': 2, 'girls': 3, 'unknown': 2, 'total': 7 } }, + data: { type: 'maiming', violation_tally: { 'boys' => 2, 'girls' => 3, 'unknown' => 2, 'total' => 7 } }, incident_id: incident5.id ) end @@ -56,7 +56,7 @@ { 'type' => SearchFilters::Value.new(field_name: 'type', value: 'attack_on_schools') } ).data - expect(denial_type_data[0][:total]).to eq(5) + expect(denial_type_data[0]['total']).to eq(5) end describe 'grouped by' do @@ -79,19 +79,15 @@ [ { group_id: 2020, - data: [ - { id: 'violation', total: 1 } - ] + data: [{ 'id' => 'violation', 'total' => 1 }] }, { group_id: 2021, - data: [{ id: 'violation', total: 2 }] + data: [{ 'id' => 'violation', 'total' => 2 }] }, { group_id: 2022, - data: [ - { id: 'violation', total: 2 } - ] + data: [{ 'id' => 'violation', 'total' => 2 }] } ] ) @@ -115,16 +111,16 @@ expect(data).to match_array( [ - { group_id: '2020-08', data: [{ id: 'violation', total: 1 }] }, + { group_id: '2020-08', data: [{ 'id' => 'violation', 'total' => 1 }] }, { group_id: '2020-09', data: [] }, { group_id: '2020-10', data: [] }, { group_id: '2020-11', data: [] }, { group_id: '2020-12', data: [] }, { group_id: '2021-01', data: [] }, { group_id: '2021-02', data: [] }, { group_id: '2021-03', data: [] }, { group_id: '2021-04', data: [] }, { group_id: '2021-05', data: [] }, { group_id: '2021-06', data: [] }, { group_id: '2021-07', data: [] }, - { group_id: '2021-08', data: [{ id: 'violation', total: 2 }] }, + { group_id: '2021-08', data: [{ 'id' => 'violation', 'total' => 2 }] }, { group_id: '2021-09', data: [] }, { group_id: '2021-10', data: [] }, { group_id: '2021-11', data: [] }, { group_id: '2021-12', data: [] }, - { group_id: '2022-01', data: [{ id: 'violation', total: 1 }] }, - { group_id: '2022-02', data: [{ id: 'violation', total: 1 }] } + { group_id: '2022-01', data: [{ 'id' => 'violation', 'total' => 1 }] }, + { group_id: '2022-02', data: [{ 'id' => 'violation', 'total' => 1 }] } ] ) end @@ -147,12 +143,12 @@ expect(data).to match_array( [ - { group_id: '2020-Q3', data: [{ id: 'violation', total: 1 }] }, + { group_id: '2020-Q3', data: [{ 'id' => 'violation', 'total' => 1 }] }, { group_id: '2020-Q4', data: [] }, { group_id: '2021-Q1', data: [] }, { group_id: '2021-Q2', data: [] }, - { group_id: '2021-Q3', data: [{ id: 'violation', total: 2 }] }, + { group_id: '2021-Q3', data: [{ 'id' => 'violation', 'total' => 2 }] }, { group_id: '2021-Q4', data: [] }, - { group_id: '2022-Q1', data: [{ id: 'violation', total: 2 }] } + { group_id: '2022-Q1', data: [{ 'id' => 'violation', 'total' => 2 }] } ] ) end diff --git a/spec/models/managed_reports/indicators/incident_denials_spec.rb b/spec/models/managed_reports/indicators/incident_denials_spec.rb index 64c4b38061..cbaf5034d5 100644 --- a/spec/models/managed_reports/indicators/incident_denials_spec.rb +++ b/spec/models/managed_reports/indicators/incident_denials_spec.rb @@ -56,7 +56,7 @@ { 'type' => SearchFilters::Value.new(field_name: 'type', value: 'denial_humanitarian_access') } ).data - expect(denial_type_data[0][:total]).to eq(5) + expect(denial_type_data[0]['total']).to eq(5) end describe 'grouped by' do @@ -77,22 +77,9 @@ expect(data).to match_array( [ - { - group_id: 2020, - data: [ - { id: 'denial_humanitarian_access', total: 1 } - ] - }, - { - group_id: 2021, - data: [{ id: 'denial_humanitarian_access', total: 2 }] - }, - { - group_id: 2022, - data: [ - { id: 'denial_humanitarian_access', total: 2 } - ] - } + { group_id: 2020, data: [{ 'id' => 'denial_humanitarian_access', 'total' => 1 }] }, + { group_id: 2021, data: [{ 'id' => 'denial_humanitarian_access', 'total' => 2 }] }, + { group_id: 2022, data: [{ 'id' => 'denial_humanitarian_access', 'total' => 2 }] } ] ) end @@ -115,7 +102,7 @@ expect(data).to match_array( [ - { group_id: '2020-08', data: [{ id: 'denial_humanitarian_access', total: 1 }] }, + { group_id: '2020-08', data: [{ 'id' => 'denial_humanitarian_access', 'total' => 1 }] }, { group_id: '2020-09', data: [] }, { group_id: '2020-10', data: [] }, { group_id: '2020-11', data: [] }, @@ -127,13 +114,13 @@ { group_id: '2021-05', data: [] }, { group_id: '2021-06', data: [] }, { group_id: '2021-07', data: [] }, - { group_id: '2021-08', data: [{ id: 'denial_humanitarian_access', total: 2 }] }, + { group_id: '2021-08', data: [{ 'id' => 'denial_humanitarian_access', 'total' => 2 }] }, { group_id: '2021-09', data: [] }, { group_id: '2021-10', data: [] }, { group_id: '2021-11', data: [] }, { group_id: '2021-12', data: [] }, - { group_id: '2022-01', data: [{ id: 'denial_humanitarian_access', total: 1 }] }, - { group_id: '2022-02', data: [{ id: 'denial_humanitarian_access', total: 1 }] } + { group_id: '2022-01', data: [{ 'id' => 'denial_humanitarian_access', 'total' => 1 }] }, + { group_id: '2022-02', data: [{ 'id' => 'denial_humanitarian_access', 'total' => 1 }] } ] ) end @@ -156,13 +143,13 @@ expect(data).to match_array( [ - { group_id: '2020-Q3', data: [{ id: 'denial_humanitarian_access', total: 1 }] }, + { group_id: '2020-Q3', data: [{ 'id' => 'denial_humanitarian_access', 'total' => 1 }] }, { group_id: '2020-Q4', data: [] }, { group_id: '2021-Q1', data: [] }, { group_id: '2021-Q2', data: [] }, - { group_id: '2021-Q3', data: [{ id: 'denial_humanitarian_access', total: 2 }] }, + { group_id: '2021-Q3', data: [{ 'id' => 'denial_humanitarian_access', 'total' => 2 }] }, { group_id: '2021-Q4', data: [] }, - { group_id: '2022-Q1', data: [{ id: 'denial_humanitarian_access', total: 2 }] } + { group_id: '2022-Q1', data: [{ 'id' => 'denial_humanitarian_access', 'total' => 2 }] } ] ) end diff --git a/spec/models/managed_reports/indicators/incidents_first_point_of_contact_spec.rb b/spec/models/managed_reports/indicators/incidents_first_point_of_contact_spec.rb index 7aa60e9d70..d38115024e 100644 --- a/spec/models/managed_reports/indicators/incidents_first_point_of_contact_spec.rb +++ b/spec/models/managed_reports/indicators/incidents_first_point_of_contact_spec.rb @@ -122,32 +122,32 @@ it 'returns the total number of incidents where the organization is the first point of contact' do total = ManagedReports::Indicators::IncidentsFirstPointOfContact.build.data - expect(total).to eq([{ 'id' => 'incidents_first_point_of_contact', 'total' => 3 }]) + expect(total).to eq([{ 'id' => 'incidents', 'total' => 3 }]) end describe 'records in scope' do it 'returns owned records for a self scope' do total = ManagedReports::Indicators::IncidentsFirstPointOfContact.build(@self_user).data - expect(total).to eq([{ 'id' => 'incidents_first_point_of_contact', 'total' => 1 }]) + expect(total).to eq([{ 'id' => 'incidents', 'total' => 1 }]) end it 'returns group records for a group scope' do total = ManagedReports::Indicators::IncidentsFirstPointOfContact.build(@group_user).data - expect(total).to eq([{ 'id' => 'incidents_first_point_of_contact', 'total' => 2 }]) + expect(total).to eq([{ 'id' => 'incidents', 'total' => 2 }]) end it 'returns agency records for an agency scope' do total = ManagedReports::Indicators::IncidentsFirstPointOfContact.build(@agency_user).data - expect(total).to eq([{ 'id' => 'incidents_first_point_of_contact', 'total' => 2 }]) + expect(total).to eq([{ 'id' => 'incidents', 'total' => 2 }]) end it 'returns all records for an all scope' do total = ManagedReports::Indicators::IncidentsFirstPointOfContact.build(@all_user).data - expect(total).to eq([{ 'id' => 'incidents_first_point_of_contact', 'total' => 3 }]) + expect(total).to eq([{ 'id' => 'incidents', 'total' => 3 }]) end end @@ -168,8 +168,8 @@ expect(data).to match_array( [ - { group_id: 2020, data: [{ 'id' => 'incidents_first_point_of_contact', 'total' => 1 }] }, - { group_id: 2021, data: [{ 'id' => 'incidents_first_point_of_contact', 'total' => 2 }] } + { group_id: 2020, data: [{ 'id' => 'incidents', 'total' => 1 }] }, + { group_id: 2021, data: [{ 'id' => 'incidents', 'total' => 2 }] } ] ) end @@ -192,14 +192,14 @@ expect(data).to match_array( [ { group_id: '2020-09', data: [] }, - { group_id: '2020-10', data: [{ 'id' => 'incidents_first_point_of_contact', 'total' => 1 }] }, + { group_id: '2020-10', data: [{ 'id' => 'incidents', 'total' => 1 }] }, { group_id: '2020-11', data: [] }, { group_id: '2020-12', data: [] }, { group_id: '2021-01', data: [] }, { group_id: '2021-02', data: [] }, { group_id: '2021-03', data: [] }, { group_id: '2021-04', data: [] }, { group_id: '2021-05', data: [] }, { group_id: '2021-06', data: [] }, { group_id: '2021-07', data: [] }, - { group_id: '2021-08', data: [{ 'id' => 'incidents_first_point_of_contact', 'total' => 1 }] }, - { group_id: '2021-09', data: [{ 'id' => 'incidents_first_point_of_contact', 'total' => 1 }] }, + { group_id: '2021-08', data: [{ 'id' => 'incidents', 'total' => 1 }] }, + { group_id: '2021-09', data: [{ 'id' => 'incidents', 'total' => 1 }] }, { group_id: '2021-10', data: [] } ] ) @@ -223,9 +223,9 @@ expect(data).to match_array( [ { group_id: '2020-Q3', data: [] }, - { group_id: '2020-Q4', data: [{ 'id' => 'incidents_first_point_of_contact', 'total' => 1 }] }, + { group_id: '2020-Q4', data: [{ 'id' => 'incidents', 'total' => 1 }] }, { group_id: '2021-Q1', data: [] }, { group_id: '2021-Q2', data: [] }, - { group_id: '2021-Q3', data: [{ 'id' => 'incidents_first_point_of_contact', 'total' => 2 }] }, + { group_id: '2021-Q3', data: [{ 'id' => 'incidents', 'total' => 2 }] }, { group_id: '2021-Q4', data: [] } ] ) diff --git a/spec/models/managed_reports/indicators/incidents_from_other_service_provider_spec.rb b/spec/models/managed_reports/indicators/incidents_from_other_service_provider_spec.rb index be2abbc2fb..2ea164b30b 100644 --- a/spec/models/managed_reports/indicators/incidents_from_other_service_provider_spec.rb +++ b/spec/models/managed_reports/indicators/incidents_from_other_service_provider_spec.rb @@ -122,32 +122,32 @@ it 'returns the total number of incident referrals to other service providers' do total_incidents = ManagedReports::Indicators::IncidentsFromOtherServiceProvider.build.data - expect(total_incidents).to eq([{ 'id' => 'incidents_from_other_service_provider', 'total' => 3 }]) + expect(total_incidents).to eq([{ 'id' => 'incidents', 'total' => 3 }]) end describe 'records in scope' do it 'returns owned records for a self scope' do total_incidents = ManagedReports::Indicators::IncidentsFromOtherServiceProvider.build(@self_user).data - expect(total_incidents).to eq([{ 'id' => 'incidents_from_other_service_provider', 'total' => 1 }]) + expect(total_incidents).to eq([{ 'id' => 'incidents', 'total' => 1 }]) end it 'returns group records for a group scope' do total_incidents = ManagedReports::Indicators::IncidentsFromOtherServiceProvider.build(@group_user).data - expect(total_incidents).to eq([{ 'id' => 'incidents_from_other_service_provider', 'total' => 2 }]) + expect(total_incidents).to eq([{ 'id' => 'incidents', 'total' => 2 }]) end it 'returns agency records for an agency scope' do total_incidents = ManagedReports::Indicators::IncidentsFromOtherServiceProvider.build(@agency_user).data - expect(total_incidents).to eq([{ 'id' => 'incidents_from_other_service_provider', 'total' => 2 }]) + expect(total_incidents).to eq([{ 'id' => 'incidents', 'total' => 2 }]) end it 'returns all records for an all scope' do total_incidents = ManagedReports::Indicators::IncidentsFromOtherServiceProvider.build(@all_user).data - expect(total_incidents).to eq([{ 'id' => 'incidents_from_other_service_provider', 'total' => 3 }]) + expect(total_incidents).to eq([{ 'id' => 'incidents', 'total' => 3 }]) end end @@ -168,8 +168,8 @@ expect(data).to match_array( [ - { group_id: 2020, data: [{ 'id' => 'incidents_from_other_service_provider', 'total' => 1 }] }, - { group_id: 2021, data: [{ 'id' => 'incidents_from_other_service_provider', 'total' => 2 }] } + { group_id: 2020, data: [{ 'id' => 'incidents', 'total' => 1 }] }, + { group_id: 2021, data: [{ 'id' => 'incidents', 'total' => 2 }] } ] ) end @@ -192,14 +192,14 @@ expect(data).to match_array( [ { group_id: '2020-09', data: [] }, - { group_id: '2020-10', data: [{ 'id' => 'incidents_from_other_service_provider', 'total' => 1 }] }, + { group_id: '2020-10', data: [{ 'id' => 'incidents', 'total' => 1 }] }, { group_id: '2020-11', data: [] }, { group_id: '2020-12', data: [] }, { group_id: '2021-01', data: [] }, { group_id: '2021-02', data: [] }, { group_id: '2021-03', data: [] }, { group_id: '2021-04', data: [] }, { group_id: '2021-05', data: [] }, { group_id: '2021-06', data: [] }, { group_id: '2021-07', data: [] }, - { group_id: '2021-08', data: [{ 'id' => 'incidents_from_other_service_provider', 'total' => 1 }] }, - { group_id: '2021-09', data: [{ 'id' => 'incidents_from_other_service_provider', 'total' => 1 }] }, + { group_id: '2021-08', data: [{ 'id' => 'incidents', 'total' => 1 }] }, + { group_id: '2021-09', data: [{ 'id' => 'incidents', 'total' => 1 }] }, { group_id: '2021-10', data: [] } ] ) @@ -223,9 +223,9 @@ expect(data).to match_array( [ { group_id: '2020-Q3', data: [] }, - { group_id: '2020-Q4', data: [{ 'id' => 'incidents_from_other_service_provider', 'total' => 1 }] }, + { group_id: '2020-Q4', data: [{ 'id' => 'incidents', 'total' => 1 }] }, { group_id: '2021-Q1', data: [] }, { group_id: '2021-Q2', data: [] }, - { group_id: '2021-Q3', data: [{ 'id' => 'incidents_from_other_service_provider', 'total' => 2 }] }, + { group_id: '2021-Q3', data: [{ 'id' => 'incidents', 'total' => 2 }] }, { group_id: '2021-Q4', data: [] } ] ) diff --git a/spec/models/managed_reports/indicators/individual_perpetrator_spec.rb b/spec/models/managed_reports/indicators/individual_perpetrator_spec.rb index 5b41a8e421..6dc7d79ff8 100644 --- a/spec/models/managed_reports/indicators/individual_perpetrator_spec.rb +++ b/spec/models/managed_reports/indicators/individual_perpetrator_spec.rb @@ -136,4 +136,18 @@ ) end end + + describe 'when is filtered by violation_type' do + it 'return data for individual age indicator' do + data = ManagedReports::Indicators::IndividualViolationType.build( + nil, + { + 'grouped_by' => SearchFilters::Value.new(field_name: 'grouped_by', value: 'quarter'), + 'violation_type' => SearchFilters::TextList.new(field_name: 'violation_type', values: %w[attack_on_schools]) + } + ).data + + expect(data).to match_array([{ id: 'attack_on_schools', total: 1 }]) + end + end end diff --git a/spec/models/managed_reports/indicators/individual_region_spec.rb b/spec/models/managed_reports/indicators/individual_region_spec.rb index 0688cf30d7..681f90a2ca 100644 --- a/spec/models/managed_reports/indicators/individual_region_spec.rb +++ b/spec/models/managed_reports/indicators/individual_region_spec.rb @@ -129,4 +129,18 @@ ) end end + + describe 'when is filtered by violation_type' do + it 'return data for individual age indicator' do + data = ManagedReports::Indicators::IndividualViolationType.build( + nil, + { + 'grouped_by' => SearchFilters::Value.new(field_name: 'grouped_by', value: 'quarter'), + 'violation_type' => SearchFilters::TextList.new(field_name: 'violation_type', values: %w[attack_on_schools]) + } + ).data + + expect(data).to match_array([{ id: 'attack_on_schools', total: 3 }]) + end + end end diff --git a/spec/models/managed_reports/indicators/individual_violation_type_spec.rb b/spec/models/managed_reports/indicators/individual_violation_type_spec.rb index 31146c9028..761c3290af 100644 --- a/spec/models/managed_reports/indicators/individual_violation_type_spec.rb +++ b/spec/models/managed_reports/indicators/individual_violation_type_spec.rb @@ -117,4 +117,18 @@ ) end end + + describe 'when is filtered by violation_type' do + it 'return data for individual age indicator' do + data = ManagedReports::Indicators::IndividualViolationType.build( + nil, + { + 'grouped_by' => SearchFilters::Value.new(field_name: 'grouped_by', value: 'quarter'), + 'violation_type' => SearchFilters::TextList.new(field_name: 'violation_type', values: %w[killing]) + } + ).data + + expect(data).to match_array([{id: 'killing', total: 2}]) + end + end end diff --git a/spec/models/managed_reports/indicators/late_verification_spec.rb b/spec/models/managed_reports/indicators/late_verification_spec.rb index 2d63073fac..d2e00a1908 100644 --- a/spec/models/managed_reports/indicators/late_verification_spec.rb +++ b/spec/models/managed_reports/indicators/late_verification_spec.rb @@ -15,25 +15,25 @@ incident2 = Incident.create!(data: { incident_date: Date.new(2021, 10, 21), status: 'open' }) Violation.create!( - data: { type: 'killing', violation_tally: { 'boys': 2, 'girls': 0, 'unknown': 2, 'total': 4 }, + data: { type: 'killing', violation_tally: { 'boys' => 2, 'girls' => 0, 'unknown' => 2, 'total' => 4 }, ctfmr_verified: 'verified' }, incident_id: incident.id ) Violation.create!( data: { type: 'denial_humanitarian_access', ctfmr_verified: 'report_pending_verification', - violation_tally: { 'boys': 1, 'girls': 2, 'unknown': 5, 'total': 8 } }, + violation_tally: { 'boys' => 1, 'girls' => 2, 'unknown' => 5, 'total' => 8 } }, incident_id: incident1.id ) Violation.create!( - data: { type: 'maiming', violation_tally: { 'boys': 2, 'girls': 3, 'unknown': 2, 'total': 7 }, + data: { type: 'maiming', violation_tally: { 'boys' => 2, 'girls' => 3, 'unknown' => 2, 'total' => 7 }, ctfmr_verified: 'verified', ctfmr_verified_date: Date.new(2022, 7, 1) }, incident_id: incident.id ) Violation.create!( - data: { type: 'maiming', violation_tally: { 'boys': 1, 'girls': 2, 'unknown': 0, 'total': 3 }, + data: { type: 'maiming', violation_tally: { 'boys' => 1, 'girls' => 2, 'unknown' => 0, 'total' => 3 }, ctfmr_verified: 'verified', ctfmr_verified_date: Date.new(2022, 1, 1) }, incident_id: incident2.id ) diff --git a/spec/models/managed_reports/indicators/multiple_violations_spec.rb b/spec/models/managed_reports/indicators/multiple_violations_spec.rb index 9c2f6dddbe..d11819c551 100644 --- a/spec/models/managed_reports/indicators/multiple_violations_spec.rb +++ b/spec/models/managed_reports/indicators/multiple_violations_spec.rb @@ -141,6 +141,10 @@ field_name: 'ghn_date_filter', from: '2021-04-01', to: '2022-06-10' + ), + 'type' => SearchFilters::Value.new( + field_name: 'type', + value: 'ghn_report' ) } ).data diff --git a/spec/models/managed_reports/indicators/sexual_violance_type_spec.rb b/spec/models/managed_reports/indicators/sexual_violance_type_spec.rb index 9b221cb005..2bff0458c1 100644 --- a/spec/models/managed_reports/indicators/sexual_violance_type_spec.rb +++ b/spec/models/managed_reports/indicators/sexual_violance_type_spec.rb @@ -101,41 +101,26 @@ role: all_role ) - incident1 = Incident.new_with_user( - @self_user, - { incident_date: Date.new(2020, 8, 8), status: 'open' } - ) + incident1 = Incident.new_with_user(@self_user, { incident_date: Date.new(2020, 8, 8), status: 'open' }) incident1.save! - incident2 = Incident.new_with_user( - @group_user, - { incident_date: Date.new(2021, 5, 8), status: 'open' } - ) + incident2 = Incident.new_with_user(@group_user, { incident_date: Date.new(2021, 5, 8), status: 'open' }) incident2.save! - incident3 = Incident.new_with_user( - @agency_user, - { incident_date: Date.new(2022, 2, 18), status: 'open' } - ) + incident3 = Incident.new_with_user(@agency_user, { incident_date: Date.new(2022, 2, 18), status: 'open' }) incident3.save! - incident4 = Incident.new_with_user( - @all_user, - { incident_date: Date.new(2022, 3, 28), status: 'open' } - ) + incident4 = Incident.new_with_user(@all_user, { incident_date: Date.new(2022, 3, 28), status: 'open' }) incident4.save! Violation.create!( data: { type: 'sexual_violence', sexual_violence_type: %w[rape], - violation_tally: { 'boys': 1, 'girls': 2, 'unknown': 3, 'total': 6 } + violation_tally: { 'boys' => 1, 'girls' => 2, 'unknown' => 3, 'total' => 6 } }, incident_id: incident1.id ) Violation.create!( data: { - type: 'sexual_violence', sexual_violence_type: %w[ - forced_abortion - forced_marriage - ], - violation_tally: { 'boys': 1, 'girls': 1, 'unknown': 1, 'total': 3 } + type: 'sexual_violence', sexual_violence_type: %w[forced_abortion forced_marriage], + violation_tally: { 'boys' => 1, 'girls' => 1, 'unknown' => 1, 'total' => 3 } }, incident_id: incident2.id ) @@ -144,26 +129,21 @@ type: 'sexual_violence', sexual_violence_type: [ 'rape' ], - violation_tally: { 'boys': 2, 'girls': 1, 'unknown': 2, 'total': 5 } + violation_tally: { 'boys' => 2, 'girls' => 1, 'unknown' => 2, 'total' => 5 } }, incident_id: incident3.id ) Violation.create!( data: { - type: 'sexual_violence', sexual_violence_type: %w[ - forced_abortion - rape - ], - violation_tally: { 'boys': 2, 'girls': 3, 'unknown': 2, 'total': 7 } + type: 'sexual_violence', sexual_violence_type: %w[forced_abortion rape], + violation_tally: { 'boys' => 2, 'girls' => 3, 'unknown' => 2, 'total' => 7 } }, incident_id: incident4.id ) Violation.create!( data: { - type: 'killing', sexual_violence_type: [ - 'forced_abortion' - ], - violation_tally: { 'boys': 2, 'girls': 4, 'unknown': 3, 'total': 9 } + type: 'killing', sexual_violence_type: %w[forced_abortion], + violation_tally: { 'boys' => 2, 'girls' => 4, 'unknown' => 3, 'total' => 9 } }, incident_id: incident4.id ) @@ -177,9 +157,9 @@ expect(sexual_violence_type).to match_array( [ - { 'total' => 18, 'unknown' => 7, 'boys' => 5, 'girls' => 6, :id => 'rape' }, - { 'boys' => 3, 'girls' => 4, 'unknown' => 3, 'total' => 10, :id => 'forced_abortion' }, - { 'total' => 3, 'girls' => 1, 'unknown' => 1, 'boys' => 1, :id => 'forced_marriage' } + { 'total' => 18, 'unknown' => 7, 'boys' => 5, 'girls' => 6, 'id' => 'rape' }, + { 'boys' => 3, 'girls' => 4, 'unknown' => 3, 'total' => 10, 'id' => 'forced_abortion' }, + { 'total' => 3, 'girls' => 1, 'unknown' => 1, 'boys' => 1, 'id' => 'forced_marriage' } ] ) end @@ -193,7 +173,7 @@ expect(sexual_violence_type).to match_array( [ - { 'total' => 6, 'unknown' => 3, 'boys' => 1, 'girls' => 2, :id => 'rape' } + { 'total' => 6, 'unknown' => 3, 'boys' => 1, 'girls' => 2, 'id' => 'rape' } ] ) end @@ -206,9 +186,9 @@ expect(sexual_violence_type).to match_array( [ - { 'boys' => 4, 'girls' => 4, 'unknown' => 4, 'total' => 12, :id => 'rape' }, - { 'boys' => 3, 'girls' => 4, 'unknown' => 3, 'total' => 10, :id => 'forced_abortion' }, - { 'boys' => 1, 'girls' => 1, 'unknown' => 1, 'total' => 3, :id => 'forced_marriage' } + { 'boys' => 4, 'girls' => 4, 'unknown' => 4, 'total' => 12, 'id' => 'rape' }, + { 'boys' => 3, 'girls' => 4, 'unknown' => 3, 'total' => 10, 'id' => 'forced_abortion' }, + { 'boys' => 1, 'girls' => 1, 'unknown' => 1, 'total' => 3, 'id' => 'forced_marriage' } ] ) end @@ -221,9 +201,9 @@ expect(sexual_violence_type).to match_array( [ - { 'total' => 5, 'boys' => 2, 'girls' => 1, 'unknown' => 2, :id => 'rape' }, - { 'total' => 3, 'boys' => 1, 'girls' => 1, 'unknown' => 1, :id => 'forced_abortion' }, - { 'total' => 3, 'boys' => 1, 'girls' => 1, 'unknown' => 1, :id => 'forced_marriage' } + { 'total' => 5, 'boys' => 2, 'girls' => 1, 'unknown' => 2, 'id' => 'rape' }, + { 'total' => 3, 'boys' => 1, 'girls' => 1, 'unknown' => 1, 'id' => 'forced_abortion' }, + { 'total' => 3, 'boys' => 1, 'girls' => 1, 'unknown' => 1, 'id' => 'forced_marriage' } ] ) end @@ -236,9 +216,9 @@ expect(sexual_violence_type).to match_array( [ - { 'total' => 18, 'unknown' => 7, 'boys' => 5, 'girls' => 6, :id => 'rape' }, - { 'boys' => 3, 'girls' => 4, 'unknown' => 3, 'total' => 10, :id => 'forced_abortion' }, - { 'total' => 3, 'girls' => 1, 'unknown' => 1, 'boys' => 1, :id => 'forced_marriage' } + { 'total' => 18, 'unknown' => 7, 'boys' => 5, 'girls' => 6, 'id' => 'rape' }, + { 'boys' => 3, 'girls' => 4, 'unknown' => 3, 'total' => 10, 'id' => 'forced_abortion' }, + { 'total' => 3, 'girls' => 1, 'unknown' => 1, 'boys' => 1, 'id' => 'forced_marriage' } ] ) end @@ -262,19 +242,19 @@ expect(data).to match_array( [ - { group_id: 2020, data: [{ 'unknown' => 3, 'girls' => 2, 'boys' => 1, 'total' => 6, :id => 'rape' }] }, + { group_id: 2020, data: [{ 'unknown' => 3, 'girls' => 2, 'boys' => 1, 'total' => 6, 'id' => 'rape' }] }, { group_id: 2021, data: [ - { 'total' => 3, 'boys' => 1, 'girls' => 1, 'unknown' => 1, :id => 'forced_abortion' }, - { 'total' => 3, 'girls' => 1, 'boys' => 1, 'unknown' => 1, :id => 'forced_marriage' } + { 'total' => 3, 'boys' => 1, 'girls' => 1, 'unknown' => 1, 'id' => 'forced_abortion' }, + { 'total' => 3, 'girls' => 1, 'boys' => 1, 'unknown' => 1, 'id' => 'forced_marriage' } ] }, { group_id: 2022, data: [ - { 'total' => 7, 'unknown' => 2, 'girls' => 3, 'boys' => 2, :id => 'forced_abortion' }, - { 'boys' => 4, 'girls' => 4, 'total' => 12, 'unknown' => 4, :id => 'rape' } + { 'total' => 7, 'unknown' => 2, 'girls' => 3, 'boys' => 2, 'id' => 'forced_abortion' }, + { 'boys' => 4, 'girls' => 4, 'total' => 12, 'unknown' => 4, 'id' => 'rape' } ] } ] @@ -301,7 +281,7 @@ [ { group_id: '2020-08', - data: [{ 'boys' => 1, 'girls' => 2, 'unknown' => 3, 'total' => 6, :id => 'rape' }] + data: [{ 'boys' => 1, 'girls' => 2, 'unknown' => 3, 'total' => 6, 'id' => 'rape' }] }, { group_id: '2020-09', data: [] }, { group_id: '2020-10', data: [] }, { group_id: '2020-11', data: [] }, { group_id: '2020-12', data: [] }, { group_id: '2021-01', data: [] }, { group_id: '2021-02', data: [] }, @@ -309,8 +289,8 @@ { group_id: '2021-05', data: [ - { 'unknown' => 1, 'total' => 3, 'girls' => 1, 'boys' => 1, :id => 'forced_abortion' }, - { 'boys' => 1, 'girls' => 1, 'total' => 3, 'unknown' => 1, :id => 'forced_marriage' } + { 'unknown' => 1, 'total' => 3, 'girls' => 1, 'boys' => 1, 'id' => 'forced_abortion' }, + { 'boys' => 1, 'girls' => 1, 'total' => 3, 'unknown' => 1, 'id' => 'forced_marriage' } ] }, { group_id: '2021-06', data: [] }, { group_id: '2021-07', data: [] }, { group_id: '2021-08', data: [] }, @@ -318,13 +298,13 @@ { group_id: '2021-12', data: [] }, { group_id: '2022-01', data: [] }, { group_id: '2022-02', data: [ - { 'unknown' => 2, 'girls' => 1, 'total' => 5, 'boys' => 2, :id => 'rape' } + { 'unknown' => 2, 'girls' => 1, 'total' => 5, 'boys' => 2, 'id' => 'rape' } ] }, { group_id: '2022-03', data: [ - { 'unknown' => 2, 'girls' => 3, 'boys' => 2, 'total' => 7, :id => 'forced_abortion' }, - { 'boys' => 2, 'total' => 7, 'unknown' => 2, 'girls' => 3, :id => 'rape' } + { 'unknown' => 2, 'girls' => 3, 'boys' => 2, 'total' => 7, 'id' => 'forced_abortion' }, + { 'boys' => 2, 'total' => 7, 'unknown' => 2, 'girls' => 3, 'id' => 'rape' } ] } ] @@ -349,21 +329,21 @@ expect(data).to match_array( [ - { group_id: '2020-Q3', data: [{ 'boys' => 1, 'total' => 6, 'unknown' => 3, 'girls' => 2, :id => 'rape' }] }, + { group_id: '2020-Q3', data: [{ 'boys' => 1, 'total' => 6, 'unknown' => 3, 'girls' => 2, 'id' => 'rape' }] }, { group_id: '2020-Q4', data: [] }, { group_id: '2021-Q1', data: [] }, { group_id: '2021-Q2', data: [ - { 'boys' => 1, 'total' => 3, 'unknown' => 1, 'girls' => 1, :id => 'forced_abortion' }, - { 'boys' => 1, 'total' => 3, 'girls' => 1, 'unknown' => 1, :id => 'forced_marriage' } + { 'boys' => 1, 'total' => 3, 'unknown' => 1, 'girls' => 1, 'id' => 'forced_abortion' }, + { 'boys' => 1, 'total' => 3, 'girls' => 1, 'unknown' => 1, 'id' => 'forced_marriage' } ] }, { group_id: '2021-Q3', data: [] }, { group_id: '2021-Q4', data: [] }, { group_id: '2022-Q1', data: [ - { 'boys' => 2, 'unknown' => 2, 'total' => 7, 'girls' => 3, :id => 'forced_abortion' }, - { 'unknown' => 4, 'girls' => 4, 'boys' => 4, 'total' => 12, :id => 'rape' } + { 'boys' => 2, 'unknown' => 2, 'total' => 7, 'girls' => 3, 'id' => 'forced_abortion' }, + { 'unknown' => 4, 'girls' => 4, 'boys' => 4, 'total' => 12, 'id' => 'rape' } ] } ] diff --git a/spec/models/managed_reports/indicators/total_gbv_sexual_violence_spec.rb b/spec/models/managed_reports/indicators/total_gbv_sexual_violence_spec.rb index e3064f41bb..ee31b0f49c 100644 --- a/spec/models/managed_reports/indicators/total_gbv_sexual_violence_spec.rb +++ b/spec/models/managed_reports/indicators/total_gbv_sexual_violence_spec.rb @@ -126,32 +126,32 @@ it 'returns the total number of incidents with a gbv_sexual_violence_type' do total_incidents = ManagedReports::Indicators::TotalGBVSexualViolence.build.data - expect(total_incidents).to eq([{ 'id' => 'gbv_sexual_violence_type', 'total' => 3 }]) + expect(total_incidents).to eq([{ 'id' => 'incidents', 'total' => 3 }]) end describe 'records in scope' do it 'returns owned records for a self scope' do total_incidents = ManagedReports::Indicators::TotalGBVSexualViolence.build(@self_user).data - expect(total_incidents).to eq([{ 'id' => 'gbv_sexual_violence_type', 'total' => 1 }]) + expect(total_incidents).to eq([{ 'id' => 'incidents', 'total' => 1 }]) end it 'returns group records for a group scope' do total_incidents = ManagedReports::Indicators::TotalGBVSexualViolence.build(@group_user).data - expect(total_incidents).to eq([{ 'id' => 'gbv_sexual_violence_type', 'total' => 2 }]) + expect(total_incidents).to eq([{ 'id' => 'incidents', 'total' => 2 }]) end it 'returns agency records for an agency scope' do total_incidents = ManagedReports::Indicators::TotalGBVSexualViolence.build(@agency_user).data - expect(total_incidents).to eq([{ 'id' => 'gbv_sexual_violence_type', 'total' => 2 }]) + expect(total_incidents).to eq([{ 'id' => 'incidents', 'total' => 2 }]) end it 'returns all records for an all scope' do total_incidents = ManagedReports::Indicators::TotalGBVSexualViolence.build(@all_user).data - expect(total_incidents).to eq([{ 'id' => 'gbv_sexual_violence_type', 'total' => 3 }]) + expect(total_incidents).to eq([{ 'id' => 'incidents', 'total' => 3 }]) end end @@ -172,8 +172,8 @@ expect(data).to match_array( [ - { group_id: 2020, data: [{ 'id' => 'gbv_sexual_violence_type', 'total' => 1 }] }, - { group_id: 2021, data: [{ 'id' => 'gbv_sexual_violence_type', 'total' => 2 }] } + { group_id: 2020, data: [{ 'id' => 'incidents', 'total' => 1 }] }, + { group_id: 2021, data: [{ 'id' => 'incidents', 'total' => 2 }] } ] ) end @@ -196,14 +196,14 @@ expect(data).to match_array( [ { group_id: '2020-09', data: [] }, - { group_id: '2020-10', data: [{ 'id' => 'gbv_sexual_violence_type', 'total' => 1 }] }, + { group_id: '2020-10', data: [{ 'id' => 'incidents', 'total' => 1 }] }, { group_id: '2020-11', data: [] }, { group_id: '2020-12', data: [] }, { group_id: '2021-01', data: [] }, { group_id: '2021-02', data: [] }, { group_id: '2021-03', data: [] }, { group_id: '2021-04', data: [] }, { group_id: '2021-05', data: [] }, { group_id: '2021-06', data: [] }, { group_id: '2021-07', data: [] }, - { group_id: '2021-08', data: [{ 'id' => 'gbv_sexual_violence_type', 'total' => 1 }] }, - { group_id: '2021-09', data: [{ 'id' => 'gbv_sexual_violence_type', 'total' => 1 }] } + { group_id: '2021-08', data: [{ 'id' => 'incidents', 'total' => 1 }] }, + { group_id: '2021-09', data: [{ 'id' => 'incidents', 'total' => 1 }] } ] ) end @@ -226,9 +226,9 @@ expect(data).to match_array( [ { group_id: '2020-Q3', data: [] }, - { group_id: '2020-Q4', data: [{ 'id' => 'gbv_sexual_violence_type', 'total' => 1 }] }, + { group_id: '2020-Q4', data: [{ 'id' => 'incidents', 'total' => 1 }] }, { group_id: '2021-Q1', data: [] }, { group_id: '2021-Q2', data: [] }, - { group_id: '2021-Q3', data: [{ 'id' => 'gbv_sexual_violence_type', 'total' => 2 }] } + { group_id: '2021-Q3', data: [{ 'id' => 'incidents', 'total' => 2 }] } ] ) end diff --git a/spec/models/managed_reports/indicators/total_referrals_by_user_groups_spec.rb b/spec/models/managed_reports/indicators/total_referrals_by_user_groups_spec.rb index dacf43d65a..ec9e561f4b 100644 --- a/spec/models/managed_reports/indicators/total_referrals_by_user_groups_spec.rb +++ b/spec/models/managed_reports/indicators/total_referrals_by_user_groups_spec.rb @@ -17,15 +17,15 @@ Referral.new( transitioned_to_user: group_user, transitioned_by_user: self_user, record: child1, consent_overridden: true, - created_at: Date.new(2021, 8, 12) + created_at: DateTime.new(2021, 8, 12, 10, 15, 13) ).save(validate: false) Referral.new( transitioned_to_user: group_user, transitioned_by_user: agency_user, record: child2, consent_overridden: true, - created_at: Date.new(2021, 9, 8) + created_at: DateTime.new(2021, 9, 8, 21, 12, 10) ).save(validate: false) Referral.new( transitioned_to_user: group_user, transitioned_by_user: all_user, record: child3, consent_overridden: true, - created_at: Date.new(2020, 10, 10) + created_at: DateTime.new(2020, 10, 10, 5, 10, 21) ).save(validate: false) end @@ -204,11 +204,7 @@ nil, { 'grouped_by' => SearchFilters::Value.new(field_name: 'grouped_by', value: 'year'), - 'created_at' => SearchFilters::DateRange.new( - field_name: 'created_at', - from: '2020-01-01', - to: '2021-12-10' - ) + 'created_at' => SearchFilters::DateRange.new(field_name: 'created_at', from: '2020-01-01', to: '2021-09-08') } ).data @@ -241,11 +237,7 @@ nil, { 'grouped_by' => SearchFilters::Value.new(field_name: 'grouped_by', value: 'month'), - 'created_at' => SearchFilters::DateRange.new( - field_name: 'created_at', - from: '2021-08-01', - to: '2021-09-30' - ) + 'created_at' => SearchFilters::DateRange.new(field_name: 'created_at', from: '2021-08-01', to: '2021-09-08') } ).data @@ -276,11 +268,7 @@ nil, { 'grouped_by' => SearchFilters::Value.new(field_name: 'grouped_by', value: 'quarter'), - 'created_at' => SearchFilters::DateRange.new( - field_name: 'created_at', - from: '2021-08-01', - to: '2021-09-30' - ) + 'created_at' => SearchFilters::DateRange.new(field_name: 'created_at', from: '2021-08-01', to: '2021-09-08') } ).data @@ -305,11 +293,7 @@ nil, { 'grouped_by' => SearchFilters::Value.new(field_name: 'grouped_by', value: 'week'), - 'created_at' => SearchFilters::DateRange.new( - field_name: 'created_at', - from: '2021-08-08', - to: '2021-08-13' - ) + 'created_at' => SearchFilters::DateRange.new(field_name: 'created_at', from: '2021-08-08', to: '2021-08-12') } ).data diff --git a/spec/models/managed_reports/indicators/total_transfers_by_user_groups_spec.rb b/spec/models/managed_reports/indicators/total_transfers_by_user_groups_spec.rb index 6635813cea..a4dfc802b4 100644 --- a/spec/models/managed_reports/indicators/total_transfers_by_user_groups_spec.rb +++ b/spec/models/managed_reports/indicators/total_transfers_by_user_groups_spec.rb @@ -17,15 +17,15 @@ Transfer.new( transitioned_to_user: group_user, transitioned_by_user: self_user, record: child1, consent_overridden: true, - created_at: Date.new(2021, 8, 12) + created_at: DateTime.new(2021, 8, 12, 10, 15, 13) ).save(validate: false) Transfer.new( transitioned_to_user: group_user, transitioned_by_user: agency_user, record: child2, consent_overridden: true, - created_at: Date.new(2021, 9, 8) + created_at: DateTime.new(2021, 9, 8, 21, 12, 10) ).save(validate: false) Transfer.new( transitioned_to_user: group_user, transitioned_by_user: all_user, record: child3, consent_overridden: true, - created_at: Date.new(2020, 10, 10) + created_at: DateTime.new(2020, 10, 10, 5, 10, 21) ).save(validate: false) end @@ -208,11 +208,7 @@ nil, { 'grouped_by' => SearchFilters::Value.new(field_name: 'grouped_by', value: 'year'), - 'created_at' => SearchFilters::DateRange.new( - field_name: 'created_at', - from: '2020-01-01', - to: '2021-12-10' - ) + 'created_at' => SearchFilters::DateRange.new(field_name: 'created_at', from: '2020-01-01', to: '2021-09-08') } ).data @@ -245,11 +241,7 @@ nil, { 'grouped_by' => SearchFilters::Value.new(field_name: 'grouped_by', value: 'month'), - 'created_at' => SearchFilters::DateRange.new( - field_name: 'created_at', - from: '2021-08-01', - to: '2021-09-30' - ) + 'created_at' => SearchFilters::DateRange.new(field_name: 'created_at', from: '2021-08-01', to: '2021-09-08') } ).data @@ -280,11 +272,7 @@ nil, { 'grouped_by' => SearchFilters::Value.new(field_name: 'grouped_by', value: 'quarter'), - 'created_at' => SearchFilters::DateRange.new( - field_name: 'created_at', - from: '2021-08-01', - to: '2021-09-30' - ) + 'created_at' => SearchFilters::DateRange.new(field_name: 'created_at', from: '2021-08-01', to: '2021-09-08') } ).data @@ -309,11 +297,7 @@ nil, { 'grouped_by' => SearchFilters::Value.new(field_name: 'grouped_by', value: 'week'), - 'created_at' => SearchFilters::DateRange.new( - field_name: 'created_at', - from: '2021-08-08', - to: '2021-08-13' - ) + 'created_at' => SearchFilters::DateRange.new(field_name: 'created_at', from: '2021-08-08', to: '2021-08-12') } ).data diff --git a/spec/models/matching_configuration_spec.rb b/spec/models/matching_configuration_spec.rb index 6c2300b16f..e3bc0844cb 100644 --- a/spec/models/matching_configuration_spec.rb +++ b/spec/models/matching_configuration_spec.rb @@ -3,7 +3,7 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. require 'rails_helper' -require 'sunspot' +require 'sunspot' if Rails.configuration.solr_enabled describe MatchingConfiguration do before :all do diff --git a/spec/models/potential_match_spec.rb b/spec/models/potential_match_spec.rb index 308cf35708..92bd125bb8 100644 --- a/spec/models/potential_match_spec.rb +++ b/spec/models/potential_match_spec.rb @@ -3,7 +3,7 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. require 'rails_helper' -require 'sunspot' +require 'sunspot' if Rails.configuration.solr_enabled describe PotentialMatch do before do diff --git a/spec/models/record_spec.rb b/spec/models/record_spec.rb index 161c92d3ea..d1151cd96d 100644 --- a/spec/models/record_spec.rb +++ b/spec/models/record_spec.rb @@ -25,8 +25,8 @@ it "should keep unique_identifier, short_id and #{record_id_name} if they are provided" do unique_identifier = '123456789' - short_id = '1234567', - record_id = '987654320' + short_id = '1234567' + record_id = '987654320' record = model_class.new(:unique_identifier => unique_identifier, :short_id => short_id, record_id_name.to_s => record_id) @@ -47,8 +47,8 @@ it "should not change unique_identifier, short_id and #{record_id_name} on saving operations" do date_value = Date.new(1990, 7, 21) unique_identifier = '123456789' - short_id = '1234567', - record_id = '987654321' + short_id = '1234567' + record_id = '987654321' record = model_class.new(:unique_identifier => unique_identifier, :short_id => short_id, record_id_name.to_s => record_id) record.save diff --git a/spec/models/referral_spec.rb b/spec/models/referral_spec.rb index 750207bc63..ab811a61cf 100644 --- a/spec/models/referral_spec.rb +++ b/spec/models/referral_spec.rb @@ -73,6 +73,8 @@ referral = Referral.create!(transitioned_by: 'user1', transitioned_to: 'user2', record: @case) expect(referral.status).to eq(Referral::STATUS_INPROGRESS) expect(@case.assigned_user_names).to include(referral.transitioned_to) + expect(@case.referred_users).to include(referral.transitioned_to) + expect(@case.referred_users_present).to eq(true) end it 'does not perform the referral if the receiving user is not allowed to receive referrals' do @@ -107,6 +109,8 @@ expect(@revoke_referral.status).to eq(Referral::STATUS_REVOKED) expect(@case.assigned_user_names).not_to include(@revoke_referral.transitioned_to) expect(service_object['service_implemented']).to be_nil + expect(@case.referred_users).not_to include(@revoke_referral.transitioned_to) + expect(@case.referred_users_present).to eq(false) end it 'it save a record history when referral is rejected' do @@ -132,6 +136,8 @@ expect(@done_referral.status).to eq(Transition::STATUS_DONE) expect(@case.assigned_user_names).not_to include('user2') + expect(@case.referred_users).not_to include(@done_referral.transitioned_to) + expect(@case.referred_users_present).to eq(false) end it 'mark the service object as implemented' do @@ -273,47 +279,50 @@ end it 'does not remove the transitioned_to from assigned_user_names if the referral is in progress' do - @referral.status = Transition::STATUS_INPROGRESS - @referral.save! - @done_referral.done!(@user1) @done_referral.reload expect(@done_referral.status).to eq(Transition::STATUS_DONE) expect(@case.assigned_user_names).to include('user2') + expect(@case.referred_users).to include('user2') + expect(@case.referred_users_present).to eq(true) end it 'does not remove the transitioned_to from assigned_user_names if the referral is accepted' do - @referral.status = Transition::STATUS_ACCEPTED - @referral.save! + @referral.accept! @done_referral.done!(@user1) @done_referral.reload expect(@done_referral.status).to eq(Transition::STATUS_DONE) expect(@case.assigned_user_names).to include('user2') + expect(@case.referred_users).to include('user2') + expect(@case.referred_users_present).to eq(true) end it 'removes the transitioned_to from assigned_user_names if the referral is rejected' do - @referral.status = Transition::STATUS_REJECTED - @referral.save! + @referral.reject!(@user2) @done_referral.done!(@user1) @done_referral.reload expect(@done_referral.status).to eq(Transition::STATUS_DONE) expect(@case.assigned_user_names).not_to include('user2') + expect(@case.referred_users).not_to include('user2') + expect(@case.referred_users_present).to eq(false) end it 'removes the transitioned_to from assigned_user_names if the referral is done' do - @referral.status = Transition::STATUS_DONE - @referral.save! + @referral.accept! + @referral.done!(@user2) @done_referral.done!(@user1) @done_referral.reload expect(@done_referral.status).to eq(Transition::STATUS_DONE) expect(@case.assigned_user_names).not_to include('user2') + expect(@case.referred_users).not_to include('user2') + expect(@case.referred_users_present).to eq(false) end end @@ -341,6 +350,8 @@ expect(referral.status).to eq(Transition::STATUS_ACCEPTED) expect(referral.responded_at).to eq(now) expect(@case.assigned_user_names).to include('user2') + expect(@case.referred_users).to include(referral.transitioned_to) + expect(@case.referred_users_present).to eq(true) end end @@ -360,6 +371,8 @@ expect(@rejected_referral.rejected_reason).to eq(@rejected_reason) expect(@rejected_referral.responded_at).to eq(@now) expect(@case.assigned_user_names).not_to include('user2') + expect(@case.referred_users).not_to include(@rejected_referral.transitioned_to) + expect(@case.referred_users_present).to eq(false) end context 'when the user has a referral in progress for another case' do @@ -373,6 +386,8 @@ expect(@rejected_referral.status).to eq(Transition::STATUS_REJECTED) expect(@case.assigned_user_names).not_to include('user2') + expect(@case.referred_users).not_to include(@rejected_referral.transitioned_to) + expect(@case.referred_users_present).to eq(false) end end @@ -405,11 +420,12 @@ expect(@rejected_referral.rejected_reason).to eq(@rejected_reason) expect(@rejected_referral.responded_at).to eq(@now) expect(@case.assigned_user_names).to include('user2') + expect(@case.referred_users).not_to include(@rejected_referral.transitioned_to) + expect(@case.referred_users_present).to eq(false) end it 'removes the transitioned_to from assigned_user_names if the transfer is accepted' do - @transfer.status = Transition::STATUS_ACCEPTED - @transfer.save! + @transfer.accept!(@user2) @rejected_referral.reject!(@user1, @rejected_reason) @rejected_referral.reload @@ -418,24 +434,12 @@ expect(@rejected_referral.rejected_reason).to eq(@rejected_reason) expect(@rejected_referral.responded_at).to eq(@now) expect(@case.assigned_user_names).not_to include('user2') + expect(@case.referred_users).not_to include(@rejected_referral.transitioned_to) + expect(@case.referred_users_present).to eq(false) end it 'removes the transitioned_to from assigned_user_names if the transfer is rejected' do - @transfer.status = Transition::STATUS_REJECTED - @transfer.save! - - @rejected_referral.reject!(@user1, @rejected_reason) - @rejected_referral.reload - - expect(@rejected_referral.status).to eq(Transition::STATUS_REJECTED) - expect(@rejected_referral.rejected_reason).to eq(@rejected_reason) - expect(@rejected_referral.responded_at).to eq(@now) - expect(@case.assigned_user_names).not_to include('user2') - end - - it 'removes the transitioned_to from assigned_user_names if the transfer is done' do - @transfer.status = Transition::STATUS_DONE - @transfer.save! + @transfer.reject!(@user2) @rejected_referral.reject!(@user1, @rejected_reason) @rejected_referral.reload @@ -444,6 +448,8 @@ expect(@rejected_referral.rejected_reason).to eq(@rejected_reason) expect(@rejected_referral.responded_at).to eq(@now) expect(@case.assigned_user_names).not_to include('user2') + expect(@case.referred_users).not_to include(@rejected_referral.transitioned_to) + expect(@case.referred_users_present).to eq(false) end end @@ -463,11 +469,12 @@ expect(@rejected_referral.rejected_reason).to eq(@rejected_reason) expect(@rejected_referral.responded_at).to eq(@now) expect(@case.assigned_user_names).to include('user2') + expect(@case.referred_users).to include(@referral.transitioned_to) + expect(@case.referred_users_present).to eq(true) end it 'does not remove the transitioned_to from assigned_user_names if the referral is accepted' do - @referral.status = Transition::STATUS_ACCEPTED - @referral.save! + @referral.accept! @rejected_referral.reject!(@user1, @rejected_reason) @rejected_referral.reload @@ -476,11 +483,12 @@ expect(@rejected_referral.rejected_reason).to eq(@rejected_reason) expect(@rejected_referral.responded_at).to eq(@now) expect(@case.assigned_user_names).to include('user2') + expect(@case.referred_users).to include(@referral.transitioned_to) + expect(@case.referred_users_present).to eq(true) end it 'removes the transitioned_to from assigned_user_names if the referral is rejected' do - @referral.status = Transition::STATUS_REJECTED - @referral.save! + @referral.reject!(@user2) @rejected_referral.reject!(@user1, @rejected_reason) @rejected_referral.reload @@ -489,11 +497,13 @@ expect(@rejected_referral.rejected_reason).to eq(@rejected_reason) expect(@rejected_referral.responded_at).to eq(@now) expect(@case.assigned_user_names).not_to include('user2') + expect(@case.referred_users).not_to include(@referral.transitioned_to) + expect(@case.referred_users_present).to eq(false) end it 'removes the transitioned_to from assigned_user_names if the referral is done' do - @referral.status = Transition::STATUS_DONE - @referral.save! + @referral.accept! + @referral.done!(@user2) @rejected_referral.reject!(@user1, @rejected_reason) @rejected_referral.reload @@ -502,6 +512,8 @@ expect(@rejected_referral.rejected_reason).to eq(@rejected_reason) expect(@rejected_referral.responded_at).to eq(@now) expect(@case.assigned_user_names).not_to include('user2') + expect(@case.referred_users).not_to include(@referral.transitioned_to) + expect(@case.referred_users_present).to eq(false) end it 'saves a record history when referral is rejected' do diff --git a/spec/models/registry_record_spec.rb b/spec/models/registry_record_spec.rb index 9f5355a98e..5f589c11ea 100644 --- a/spec/models/registry_record_spec.rb +++ b/spec/models/registry_record_spec.rb @@ -64,21 +64,26 @@ end describe 'quicksearch', search: true do - it 'has a searchable case id, survivor number' do - expected = %w[registry_id short_id registry_no registry_type name] - expect(RegistryRecord.quicksearch_fields).to match_array(expected) - end - it 'can find a Registry Record by Registry Number' do - registry = RegistryRecord.create!(registry_type: 'farmer', - data: { name: 'Registry One', registry_no: 'ABC123XYZ' }) - registry.index! - search_result = SearchService.search(RegistryRecord, query: 'ABC123XYZ').results + RegistryRecord.create!(registry_type: 'farmer', + data: { name: 'Registry One', registry_no: 'ABC123XYZ' }) + search_result = PhoneticSearchService.search(RegistryRecord, query: 'ABC123XYZ').records expect(search_result).to have(1).registryRecord expect(search_result.first.registry_no).to eq('ABC123XYZ') end end + describe 'phonetic tokens' do + before do + clean_data(RegistryRecord) + end + + it 'generates the phonetic tokens' do + registry_record = RegistryRecord.create!(data: { name: 'Miller' }) + expect(registry_record.tokens).to eq(%w[MLR]) + end + end + after do clean_data(RegistryRecord) end diff --git a/spec/models/report_spec.rb b/spec/models/report_spec.rb index 5b8ab94124..a19af6bfe7 100644 --- a/spec/models/report_spec.rb +++ b/spec/models/report_spec.rb @@ -45,17 +45,7 @@ expect(r.valid?).to be_falsey end - it 'lists reportable record types' do - expect(Report.reportable_record_types).to include('case', 'incident', 'tracing_request', 'violation') - end - describe 'nested reports' do - it 'lists reportsable nested record types' do - expect(Report.reportable_record_types).to include( - 'reportable_follow_up', 'reportable_protection_concern', 'reportable_service' - ) - end - it 'has default follow up filters' do r = Report.new(record_type: 'reportable_follow_up', add_default_filters: true) r.apply_default_filters @@ -85,7 +75,7 @@ end end - describe 'modules_present' do + describe 'validate_modules_present' do it 'will reject the empty module_id list' do r = Report.new record_type: 'case', aggregate_by: %w[a b], module_id: '' expect(r.valid?).to be_falsey @@ -100,7 +90,7 @@ it 'will accept the valid module_id list' do r = Report.new record_type: 'case', aggregate_by: %w[a b], module_id: 'primeromodule-cp' - expect(r.modules_present).to be_nil + expect(r.validate_modules_present).to be_nil end end @@ -744,7 +734,7 @@ name: 'Report by Custom Location and Sex', record_type: 'case', module_id: @module.unique_id, - aggregate_by: ['custom_abc4x5a11'], + aggregate_by: ['loc:custom_abc4x5a11'], disaggregate_by: ['sex'] ) end @@ -757,9 +747,7 @@ aggregate_by: ['sex'], disaggregate_by: ['created_at'], group_dates_by: Report::DAY, - filters: [ - { 'value': '2022-10-10', 'attribute': 'created_at', 'constraint': '>' } - ] + filters: [{ 'value' => '2022-10-10', 'attribute' => 'created_at', 'constraint' => '>' }] ) end diff --git a/spec/models/search_filters/boolean_list_spec.rb b/spec/models/search_filters/boolean_list_spec.rb new file mode 100644 index 0000000000..162c1bb03a --- /dev/null +++ b/spec/models/search_filters/boolean_list_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +require 'rails_helper' + +describe SearchFilters::BooleanList do + let(:record1) { Child.create!(data: { name: 'Record 1', sex: 'female', age: 12, record_state: true }) } + let(:record2) { Child.create!(data: { name: 'Record 2', sex: 'female', age: 12, record_state: 'true' }) } + let(:record3) { Child.create!(data: { name: 'Record 3', sex: 'female', age: 12, record_state: 'false' }) } + let(:record4) { Child.create!(data: { name: 'Record 4', sex: 'female', age: 12, record_state: false }) } + + before(:each) do + clean_data(Child) + record1 + record2 + record3 + record4 + end + + it 'matches the true filter' do + filter = SearchFilters::BooleanList.new(field_name: 'record_state', values: [true]) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(2) + expect(search.records.map(&:id)).to match_array([record1.id, record2.id]) + end + + it 'matches the false filter' do + filter = SearchFilters::BooleanList.new(field_name: 'record_state', values: [false]) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(2) + expect(search.records.map(&:id)).to match_array([record3.id, record4.id]) + end +end diff --git a/spec/models/search_filters/date_range_spec.rb b/spec/models/search_filters/date_range_spec.rb index e316ad75dc..be22f7b686 100644 --- a/spec/models/search_filters/date_range_spec.rb +++ b/spec/models/search_filters/date_range_spec.rb @@ -6,27 +6,21 @@ describe SearchFilters::DateRange do describe '.query_scope', search: true do - before :example do - @correct_match = Child.create!(data: { name: 'Correct Match', registration_date: Date.new(2019, 1, 1) }) - @incorrect_match = Child.create!(data: { name: 'Incorrect Match', registration_date: Date.new(2018, 1, 1) }) - Sunspot.commit - end + let!(:correct_match) { Child.create!(data: { name: 'Correct Match', registration_date: Date.new(2019, 1, 1) }) } + let!(:incorrect_match) { Child.create!(data: { name: 'Incorrect Match', registration_date: Date.new(2018, 1, 1) }) } it 'matches on string values' do filter = SearchFilters::DateRange.new( field_name: 'registration_date', from: Date.new(2018, 6, 1), to: Date.new(2019, 3, 1) ) - search = Child.search do - filter.query_scope(self) - end + search = PhoneticSearchService.search(Child, filters: [filter]) expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@correct_match.name) + expect(search.records.first.name).to eq(correct_match.name) end - after :example do - @correct_match.destroy - @incorrect_match.destroy + after do + clean_data(Child) end end end diff --git a/spec/models/search_filters/id_filter_spec.rb b/spec/models/search_filters/id_filter_spec.rb new file mode 100644 index 0000000000..3cd2eb5754 --- /dev/null +++ b/spec/models/search_filters/id_filter_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +require 'rails_helper' + +describe SearchFilters::IdFilter do + describe 'filter', search: true do + let!(:record1) { Child.create!(data: { name: 'Record 1', sex: 'female', age: 12, record_state: true }) } + let!(:record2) { Child.create!(data: { name: 'Record 2', sex: 'male', age: 8, record_state: false }) } + + it 'matches the record id' do + filter = SearchFilters::IdFilter.new(field_name: 'id', value: record1.id) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record1.name) + end + + after(:each) do + clean_data(Child) + end + end +end diff --git a/spec/models/search_filters/id_list_filter_spec.rb b/spec/models/search_filters/id_list_filter_spec.rb new file mode 100644 index 0000000000..fc4d7c457c --- /dev/null +++ b/spec/models/search_filters/id_list_filter_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +require 'rails_helper' + +describe SearchFilters::IdListFilter do + describe 'filter', search: true do + let!(:record1) { Child.create!(data: { name: 'Record 1', sex: 'female', age: 12, record_state: true }) } + let!(:record2) { Child.create!(data: { name: 'Record 2', sex: 'male', age: 8, record_state: false }) } + + it 'matches the record id' do + filter = SearchFilters::IdListFilter.new(field_name: 'id', values: [record2.id]) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record2.name) + end + + after(:each) do + clean_data(Child) + end + end +end diff --git a/spec/models/search_filters/not_null_spec.rb b/spec/models/search_filters/not_null_spec.rb new file mode 100644 index 0000000000..bbb486a7fd --- /dev/null +++ b/spec/models/search_filters/not_null_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +require 'rails_helper' + +describe SearchFilters::BooleanList do + let(:record1) { Child.create!(data: { name: 'Record 1', sex: nil, age: 12, record_state: true }) } + let(:record2) { Child.create!(data: { name: 'Record 2', sex: nil, age: 12, record_state: 'true' }) } + let(:record3) { Child.create!(data: { name: 'Record 3', sex: nil, age: 12, record_state: 'false' }) } + let(:record4) { Child.create!(data: { name: 'Record 4', sex: 'female', age: 12, record_state: false }) } + + before(:each) do + clean_data(Child) + record1 + record2 + record3 + record4 + end + + it 'matches the not_null filter' do + filter = SearchFilters::NotNull.new(field_name: 'sex') + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(1) + expect(search.records.map(&:id)).to match_array([record4.id]) + end +end diff --git a/spec/models/search_filters/not_value_spec.rb b/spec/models/search_filters/not_value_spec.rb deleted file mode 100644 index 47a9b6eaf0..0000000000 --- a/spec/models/search_filters/not_value_spec.rb +++ /dev/null @@ -1,54 +0,0 @@ -# frozen_string_literal: true - -# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -require 'rails_helper' - -describe SearchFilters::NotValue do - describe '.query_scope', search: true do - before :example do - clean_data(Child) - @correct_match = Child.create!(data: { name: 'Correct Match', sex: 'female', age: 12, record_state: true }) - Child.create!(data: { name: 'Incorrect Match 1', sex: 'male', age: 8, record_state: false }) - Child.create!(data: { name: 'Incorrect Match 2', sex: 'male', age: 10, record_state: false }) - Sunspot.commit - end - - it 'matches on string values' do - filter = SearchFilters::NotValue.new(field_name: 'sex', values: 'male') - - search = Child.search do - filter.query_scope(self) - end - - expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@correct_match.name) - end - - it 'matches on boolean value' do - filter = SearchFilters::NotValue.new(field_name: 'record_state', values: false) - - search = Child.search do - filter.query_scope(self) - end - - expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@correct_match.name) - end - - it 'matches by two values' do - filter = SearchFilters::NotValue.new(field_name: 'age', values: [8, 10]) - - search = Child.search do - filter.query_scope(self) - end - - expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@correct_match.name) - end - - after :example do - clean_data(Child) - end - end -end diff --git a/spec/models/search_filters/numeric_range_spec.rb b/spec/models/search_filters/numeric_range_spec.rb index ff231b73e4..86ad6a6037 100644 --- a/spec/models/search_filters/numeric_range_spec.rb +++ b/spec/models/search_filters/numeric_range_spec.rb @@ -5,28 +5,26 @@ require 'rails_helper' describe SearchFilters::NumericRange do - describe '.query_scope', search: true do - before :example do - @correct_match = Child.create!(data: { name: 'Correct Match', age: 12 }) - @incorrect_match = Child.create!(data: { name: 'Incorrect Match', age: 8 }) - Sunspot.commit + describe 'filter', search: true do + before(:each) do + clean_data(Child) end + let!(:correct_match) { Child.create!(data: { name: 'Correct Match', age: 12 }) } + let!(:incorrect_match) { Child.create!(data: { name: 'Incorrect Match', sex: 'male', age: 8 }) } + it 'matches on a numeric range' do filter = SearchFilters::NumericRange.new( field_name: 'age', from: 11, to: 15 ) - search = Child.search do - filter.query_scope(self) - end + search = PhoneticSearchService.search(Child, filters: [filter]) expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@correct_match.name) + expect(search.records.first.name).to eq(correct_match.name) end - after :example do - @correct_match.destroy - @incorrect_match.destroy + after(:each) do + clean_data(Child) end end end diff --git a/spec/models/search_filters/or_spec.rb b/spec/models/search_filters/or_spec.rb index a103dd1e7f..2408db7d80 100644 --- a/spec/models/search_filters/or_spec.rb +++ b/spec/models/search_filters/or_spec.rb @@ -5,36 +5,35 @@ require 'rails_helper' describe SearchFilters::Or do - describe '.query_scope', search: true do - before :example do - @correct_match1 = Child.create!(data: { name: 'Correct Match1', sex: 'female', - protection_concerns: %w[trafficking] }) - @correct_match2 = Child.create!(data: { name: 'Correct Match2', sex: 'male', - protection_concerns: %w[statelessness] }) - @incorrect_match = Child.create!(data: { name: 'Incorrect Match', sex: 'male', - protection_concerns: %w[trafficking] }) - Sunspot.commit + describe '.filter', search: true do + before(:each) do + clean_data(Incident, Child) end + let!(:correct_match1) { + Child.create!(data: { name: 'Correct Match1', sex: 'female', protection_concerns: %w[trafficking] }) + } + let!(:correct_match2) { + Child.create!(data: { name: 'Correct Match2', sex: 'male', protection_concerns: %w[statelessness] }) + } + let!(:incorrect_match) { + Child.create!(data: { name: 'Incorrect Match', sex: 'male', protection_concerns: %w[trafficking] }) + } + it 'matches on values for either or the given fields' do filter = SearchFilters::Or.new(filters: [ - SearchFilters::Value.new(field_name: 'sex', value: 'female'), - SearchFilters::Value.new(field_name: 'protection_concerns', - value: 'statelessness') + SearchFilters::TextValue.new(field_name: 'sex', value: 'female'), + SearchFilters::TextValue.new(field_name: 'protection_concerns', + value: 'statelessness') ]) - - search = Child.search do - filter.query_scope(self) - end + search = PhoneticSearchService.search(Child, filters: [filter]) expect(search.total).to eq(2) - expect(search.results.map(&:name)).to include(@correct_match1.name, @correct_match2.name) + expect(search.records.map(&:name)).to include(correct_match1.name, correct_match2.name) end - after :example do - @correct_match1.destroy - @correct_match2.destroy - @incorrect_match.destroy + after(:each) do + clean_data(Incident, Child) end end end diff --git a/spec/models/search_filters/value_list_spec.rb b/spec/models/search_filters/value_list_spec.rb index 9586d3e907..a394150089 100644 --- a/spec/models/search_filters/value_list_spec.rb +++ b/spec/models/search_filters/value_list_spec.rb @@ -5,41 +5,11 @@ require 'rails_helper' describe SearchFilters::ValueList do - describe '.query_scope', search: true do - before :example do - @correct_match1 = Child.create!(data: { name: 'Correct Match', protection_concerns: %w[statelessness] }) - @correct_match2 = Child.create!(data: { name: 'Correct Match', protection_concerns: %w[trafficked] }) - @incorrect_match = Child.create!(data: { name: 'Incorrect Match', protection_concerns: %w[labor] }) - @age_match = Child.create!(data: { name: 'Incorrect Match', age: 5 }) - Sunspot.commit - end - - it 'matches on a list of values' do - filter = SearchFilters::ValueList.new(field_name: 'protection_concerns', values: %w[statelessness trafficked]) - - search = Child.search do - filter.query_scope(self) - end - - expect(search.total).to eq(2) - expect(search.results.map(&:name)).to include(@correct_match1.name, @correct_match2.name) - end - - it 'matches on a list of range values' do - filter = SearchFilters::ValueList.new(field_name: 'age', values: [{ 'from' => 0, 'to' => 5 }]) - - search = Child.search do - filter.query_scope(self) - end - - expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@age_match.name) - end + describe 'to_s' do + it 'generates a query param' do + filter = SearchFilters::ValueList.new(field_name: 'age', values: [4, 5, 12]) - after :example do - @correct_match1.destroy - @correct_match2.destroy - @incorrect_match.destroy + expect(filter.to_s).to eq('age=4,5,12') end end end diff --git a/spec/models/search_filters/value_spec.rb b/spec/models/search_filters/value_spec.rb index 6a2aacec67..d33512cd26 100644 --- a/spec/models/search_filters/value_spec.rb +++ b/spec/models/search_filters/value_spec.rb @@ -5,38 +5,20 @@ require 'rails_helper' describe SearchFilters::Value do - describe '.query_scope', search: true do - before :example do - @correct_match = Child.create!(data: { name: 'Correct Match', sex: 'female', age: 12, record_state: true }) - @incorrect_match = Child.create!(data: { name: 'Incorrect Match', sex: 'male', age: 8, record_state: false }) - Sunspot.commit - end - - it 'matches on string values' do - filter = SearchFilters::Value.new(field_name: 'sex', value: 'female') - - search = Child.search do - filter.query_scope(self) - end - - expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@correct_match.name) - end - - it 'matches on boolean value' do - filter = SearchFilters::Value.new(field_name: 'record_state', value: true) + describe 'filter', search: true do + let!(:correct_match) { Child.create!(data: { name: 'Correct Match', sex: 'female', age: 12, record_state: true }) } + let!(:incorrect_match) { Child.create!(data: { name: 'Incorrect Match', sex: 'male', age: 8, record_state: false }) } - search = Child.search do - filter.query_scope(self) - end + it 'matches on number values' do + filter = SearchFilters::Value.new(field_name: 'age', value: 12) + search = PhoneticSearchService.search(Child, filters: [filter]) expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@correct_match.name) + expect(search.records.first.name).to eq(correct_match.name) end - after :example do - @correct_match.destroy - @incorrect_match.destroy + after(:each) do + clean_data(Child) end end end diff --git a/spec/models/system_settings_spec.rb b/spec/models/system_settings_spec.rb index 8b59c8180d..7349a7ae87 100644 --- a/spec/models/system_settings_spec.rb +++ b/spec/models/system_settings_spec.rb @@ -73,5 +73,33 @@ expect(@system_settings).to be_valid end end + + context '#maximum_attachments_per_record' do + it 'when is not defined return default value' do + expect(@system_settings.maximum_attachments_per_record).to eq(Attachment::DEFAULT_MAX_ATTACHMENTS) + end + end + + describe '#primero_promote_config' do + context 'when primero_promote_config is not defined ' do + it 'return default value' do + expect(@system_settings.primero_promote_config).to match_array([]) + end + end + + context 'when primero_promote_config is defined ' do + it 'return value' do + @system_settings.primero_promote_config = [ + { + tls: 'true', host: 'foo.bar', port: '443', basic_auth_secret: 'PRIMERO_PROMOTE_CONFIG_PROD_BASIC_AUTH' + }.with_indifferent_access + ] + @system_settings.save! + + expect(@system_settings.primero_promote_config.length).to eq(1) + expect(@system_settings.primero_promote_config.first['host']).to eq('foo.bar') + end + end + end end end diff --git a/spec/models/tracing_request_spec.rb b/spec/models/tracing_request_spec.rb index d2b9632bed..1ebb0ff7bc 100644 --- a/spec/models/tracing_request_spec.rb +++ b/spec/models/tracing_request_spec.rb @@ -3,7 +3,7 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. require 'rails_helper' -require 'sunspot' +require 'sunspot' if Rails.configuration.solr_enabled require 'will_paginate' describe TracingRequest do @@ -182,6 +182,25 @@ end end + describe 'phonetic tokens' do + before do + clean_data(TracingRequest) + end + + it 'generates the phonetic tokens' do + child = TracingRequest.create!( + data: { + relation_name: 'George', + relation_nickname: 'Wolf', + relation_other_family: 'Miller', + tracing_names: %w[John Jean], + tracing_nicknames: %w[Fox Lion] + } + ) + expect(child.tokens).to eq(%w[JRJ ALF MLR JN FKS LN]) + end + end + private def create_tracing_request(name, options = {}) diff --git a/spec/models/transfer_spec.rb b/spec/models/transfer_spec.rb index 55373c10dd..905ace530e 100644 --- a/spec/models/transfer_spec.rb +++ b/spec/models/transfer_spec.rb @@ -90,6 +90,11 @@ expect(case1.assigned_user_names).to include(@transfer.transitioned_to) end + it 'updates the transferred_to fields' do + expect(case1.transferred_to_users).to include(@transfer.transitioned_to) + expect(case1.transferred_to_user_groups).to include(@group2.unique_id) + end + it 'does not change ownership of the record' do expect(case1.owned_by).to eq('user1') expect(case1.owned_by_full_name).to eq('Test User One') @@ -142,6 +147,8 @@ expect(@transfer.responded_at).to eq(@now) expect(case1.transfer_status).to eq(Transition::STATUS_ACCEPTED) expect(case1.status).to eq(Record::STATUS_OPEN) + expect(case1.transferred_to_users).not_to include(@transfer.transitioned_to) + expect(case1.transferred_to_user_groups).not_to include(@group2.unique_id) end it 'should have a entry in record histories' do @@ -286,6 +293,8 @@ expect(@case.assigned_user_names.present?).to be_falsey expect(@case.transfer_status).to eq(Transition::STATUS_REJECTED) expect(@case.status).to eq(Record::STATUS_OPEN) + expect(@case.transferred_to_users).not_to include(@rejected_transfer.transitioned_to) + expect(@case.transferred_to_user_groups).not_to include(@group2.unique_id) end it 'does not change ownership of the record' do @@ -395,6 +404,8 @@ expect(@rejected_transfer.status).to eq(Transition::STATUS_REJECTED) expect(@rejected_transfer.responded_at).to eq(@now) expect(@case.assigned_user_names).to include('user2') + expect(@case.transferred_to_users).to include(@rejected_transfer.transitioned_to) + expect(@case.transferred_to_user_groups).to include(@group2.unique_id) end it 'removes the transitioned_to from assigned_user_names if the transfer is accepted' do @@ -407,6 +418,8 @@ expect(@rejected_transfer.status).to eq(Transition::STATUS_REJECTED) expect(@rejected_transfer.responded_at).to eq(@now) expect(@case.assigned_user_names).not_to include('user2') + expect(@case.transferred_to_users).not_to include(@rejected_transfer.transitioned_to) + expect(@case.transferred_to_user_groups).not_to include(@group2.unique_id) end it 'removes the transitioned_to from assigned_user_names if the transfer is rejected' do @@ -419,6 +432,8 @@ expect(@rejected_transfer.status).to eq(Transition::STATUS_REJECTED) expect(@rejected_transfer.responded_at).to eq(@now) expect(@case.assigned_user_names).not_to include('user2') + expect(@case.transferred_to_users).not_to include(@rejected_transfer.transitioned_to) + expect(@case.transferred_to_user_groups).not_to include(@group2.unique_id) end it 'removes the transitioned_to from assigned_user_names if the transfer is done' do @@ -431,6 +446,8 @@ expect(@rejected_transfer.status).to eq(Transition::STATUS_REJECTED) expect(@rejected_transfer.responded_at).to eq(@now) expect(@case.assigned_user_names).not_to include('user2') + expect(@case.transferred_to_users).not_to include(@rejected_transfer.transitioned_to) + expect(@case.transferred_to_user_groups).not_to include(@group2.unique_id) end it 'should have a entry in record histories' do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 006ad55a14..0d68de420d 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -791,8 +791,7 @@ def build_and_save_user(options = {}) password_confirmation: 'a12345678', email: 'user_admin@localhost.com', agency_id: @agency1.id, role: @role1, user_groups: [@group1]) @child1 = Child.new_with_user(@current_user, name: 'Child 3') - [@child1].each(&:save!) - Sunspot.commit + @child1.save! end it 'return the scope of the user' do @@ -1057,6 +1056,35 @@ def build_and_save_user(options = {}) end end + describe '.permitted_api_params' do + before do + clean_data(User, Role, PrimeroModule, PrimeroProgram, FormSection, Agency, UserGroup, Child) + @module_cp = PrimeroModule.new(name: 'CP') + @module_cp.save(validate: false) + + permission_case = Permission.new( + resource: Permission::CASE, + actions: [Permission::READ, Permission::WRITE, Permission::CREATE] + ) + @role = Role.new(permissions: [permission_case], modules: [@module_cp]) + @role.save(validate: false) + @group1 = UserGroup.create!(name: 'Group1') + @user1 = User.new(user_name: 'user1', role: @role, user_groups: [@group1]) + @user1.save(validate: false) + end + context 'when user is not admin' do + it 'should not returm that are not allowed' do + expect(User.permitted_api_params(@user1, @user1)).not_to include( + *User.self_hidden_attributes + ) + end + end + + after do + clean_data(User, Role, PrimeroModule, PrimeroProgram, FormSection, Agency, UserGroup, Child) + end + end + after do clean_data(Alert, User, Agency, Role, FormSection, Field) end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 8955f99e45..74ac647db3 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -9,12 +9,14 @@ SimpleCov.coverage_dir 'coverage/rspec' end +ENV['PRIMERO_USE_CSRF_PROTECTION'] = 'false' + ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../config/environment', __dir__) require 'rspec/rails' require 'csv' require 'active_support/inflector' -require 'sunspot_test/rspec' +require 'sunspot_test/rspec' if Rails.configuration.solr_enabled # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. @@ -107,6 +109,8 @@ def reset(object) # --seed 1234 config.order = 'random' + config.filter_run_excluding skip_when_solr_disabled: true unless Rails.configuration.solr_enabled + # Recreate db if needed. config.before(:suite) do FactoryBot.find_definitions @@ -140,7 +144,7 @@ def stub_env(new_env) def clean_data(*models) models.each(&:destroy_all) SystemSettings.reset if models.include?(SystemSettings) - Sunspot.commit if self.class.metadata&.dig(:search) + Sunspot.commit if Rails.configuration.solr_enabled && self.class.metadata&.dig(:search) end def reloaded_model(model) diff --git a/spec/requests/active_storage_auth_spec.rb b/spec/requests/active_storage_auth_spec.rb index 75942993cb..c8232ba41a 100644 --- a/spec/requests/active_storage_auth_spec.rb +++ b/spec/requests/active_storage_auth_spec.rb @@ -103,6 +103,10 @@ end describe 'Record attachments' do + let(:primero_module) do + PrimeroModule.new(unique_id: PrimeroModule::CP, name: 'Primero Module CP', associated_record_types: %w[case]) + end + let(:photo_form) do photo_form = FormSection.new( unique_id: 'photo_form', @@ -127,6 +131,9 @@ role.save(validate: false) FormPermission.create!(form_section: photo_form, role:) + primero_module.roles = [role] + primero_module.form_sections = [photo_form] + primero_module.save(validate: false) role end @@ -182,7 +189,7 @@ let(:case_with_photo) do child = Child.create( - data: { name: 'Test', owned_by: 'user1' } + data: { name: 'Test', owned_by: 'user1', module_id: PrimeroModule::CP } ) Attachment.new( record: child, field_name: 'photos', attachment_type: Attachment::IMAGE, @@ -192,7 +199,7 @@ let(:case_with_document) do child = Child.create( - data: { name: 'Test2', owned_by: 'user1' } + data: { name: 'Test2', owned_by: 'user1', module_id: PrimeroModule::CP } ) Attachment.new( record: child, field_name: Attachable::DOCUMENTS_FIELD_NAME, file_name: 'dummy.pdf', @@ -254,11 +261,15 @@ end after(:each) do - clean_data(Attachment, Child, User, FormPermission, Role, FormSection) + clean_data(Attachment, Child, User, PrimeroModule, FormPermission, Role, FormSection) end end describe 'Export files' do + let(:primero_module) do + PrimeroModule.new(unique_id: PrimeroModule::CP, name: 'Primero Module CP', associated_record_types: %w[case]) + end + let(:role) do permissions = Permission.new( resource: Permission::CASE, diff --git a/spec/requests/api/v2/alerts_controller_spec.rb b/spec/requests/api/v2/alerts_controller_spec.rb index 1adb8e6d5f..4ee0b89e65 100644 --- a/spec/requests/api/v2/alerts_controller_spec.rb +++ b/spec/requests/api/v2/alerts_controller_spec.rb @@ -200,7 +200,7 @@ end describe 'DELETE /api/v2//alerts/' do - it 'deletes an alert from a child' do + it 'deletes an alert from a child and updates the current_alert_types' do alert = @test_child.alerts.first login_for_test( permissions: [ @@ -212,11 +212,14 @@ ) delete "/api/v2/cases/#{@test_child.id}/alerts/#{alert.unique_id}" + expect(response).to have_http_status(204) expect(@test_child.alerts.count).to eq(2) + @test_child.reload + expect(@test_child.current_alert_types).to match_array(%w[new_form]) end - it 'deletes an alert from a incident' do + it 'deletes an alert from a incident and updates the current_alert_types' do alert = @test_incident.alerts.first login_for_test( permissions: [ @@ -229,6 +232,8 @@ delete "/api/v2/incidents/#{@test_incident.id}/alerts/#{alert.unique_id}" expect(response).to have_http_status(204) expect(@test_incident.alerts.count).to eq(2) + @test_child.reload + expect(@test_incident.current_alert_types).to match_array(%w[transfer_request]) end it 'does not delete an alert from a incident if the user does not have remove_alert permission' do alert = @test_incident.alerts.first diff --git a/spec/requests/api/v2/assigns_controller_spec.rb b/spec/requests/api/v2/assigns_controller_spec.rb index add695d7e2..a3b56eab95 100644 --- a/spec/requests/api/v2/assigns_controller_spec.rb +++ b/spec/requests/api/v2/assigns_controller_spec.rb @@ -96,7 +96,6 @@ } ) end - Sunspot.commit context 'bulk assign with valid permissions' do it 'assigns multiple records to the target user' do @@ -133,7 +132,7 @@ it 'raises Errors::ForbiddenOperation' do sign_in(@user1) - filters = { short_id: %w[fbd6839 4c7084f 2d4bc3d] } + filters = { id: Array.new(3) { SecureRandom.uuid } } params = { data: { transitioned_to: 'user2', notes: 'Test Notes', filters: } } post('/api/v2/cases/assigns', params:) @@ -141,6 +140,27 @@ expect(response).to have_http_status(403) end end + + context 'when invalid filters are send' do + it 'returns a 422 error when the filters param is not specified' do + sign_in(@user1) + params = { data: { transitioned_to: 'user2', notes: 'Test Notes' } } + post('/api/v2/cases/assigns', params:) + + expect(response).to have_http_status(422) + expect(json['errors'][0]['resource']).to eq('/api/v2/cases/assigns') + end + + it 'returns a 200 when the filters param is sent' do + sign_in(@user1) + filters = { status: ['open'], record_state: ['true'], age: ['6..11'] } + params = { data: { transitioned_to: 'user2', notes: 'Test Notes', filters: } } + post('/api/v2/cases/assigns', params:) + + expect(response).to have_http_status(200) + expect(json['errors']).to be_nil + end + end end after do diff --git a/spec/requests/api/v2/attachments_controller_spec.rb b/spec/requests/api/v2/attachments_controller_spec.rb index 533124f763..80dabcbf4b 100644 --- a/spec/requests/api/v2/attachments_controller_spec.rb +++ b/spec/requests/api/v2/attachments_controller_spec.rb @@ -8,15 +8,18 @@ include ActiveJob::TestHelper before :each do @case = Child.create(data: { name: 'Test', owned_by: 'faketest' }) - Sunspot.commit end let(:json) { JSON.parse(response.body) } let(:audit_params) { enqueued_jobs.find { |job| job[:job] == AuditLogJob }[:args].first } - let(:records_with_photo) { Child.search { with(:has_photo, true) }.results } + let(:records_with_photo) do + PhoneticSearchService.search( + Child, filters: [SearchFilters::BooleanValue.new(field_name: 'has_photo', value: true)] + ).records + end describe 'POST /api/v2/:record/:id/attachments', search: true do - it 'attaches a file to an existing record' do + it 'attaches a file to an existing record and sets has_photo to true' do login_for_test({ permitted_field_names: [Attachable::PHOTOS_FIELD_NAME] }) params = { @@ -31,7 +34,8 @@ expect(json['data']['record']['id']).to eq(@case.id) expect(records_with_photo.size).to eq(1) expect(records_with_photo.first.id).to eq(@case.id) - + @case.reload + expect(@case.has_photo).to eq(true) expect(audit_params['action']).to eq('attach') end @@ -84,6 +88,50 @@ end end + describe 'PATCH /api/v2/:record/:id/attachments', search: true do + let(:attachment) do + Attachment.new( + record: @case, field_name: Attachable::DOCUMENTS_FIELD_NAME, attachment_type: Attachment::DOCUMENT, + file_name: 'dummy.pdf', attachment: attachment_base64('dummy.pdf'), description: 'Document Description', + is_current: true, date: '2020-02-15', comments: 'Some comments' + ) + end + + before { attachment.attach! } + + it 'updates the metadata fields for a document' do + login_for_test({ permitted_field_names: [Attachable::DOCUMENTS_FIELD_NAME] }) + + params = { + data: { description: 'New Description', is_current: false, date: '2020-02-16', comments: 'Other comments' } + } + + patch("/api/v2/cases/#{@case.id}/attachments/#{attachment.id}", params:) + + expect(response).to have_http_status(200) + expect(json['data']['description']).to eq('New Description') + expect(json['data']['is_current']).to eq(false) + expect(json['data']['date']).to eq('2020-02-16') + expect(json['data']['comments']).to eq('Other comments') + end + + it 'refuses to update the attached document' do + login_for_test({ permitted_field_names: [Attachable::DOCUMENTS_FIELD_NAME] }) + + params = { + data: { attachment: attachment_base64('hxl_location_sample.csv') } + } + + patch("/api/v2/cases/#{@case.id}/attachments/#{attachment.id}", params:) + + expect(response).to have_http_status(422) + expect(json['errors'][0]['status']).to eq(422) + expect(json['errors'][0]['detail']).to eq(%w[attachment]) + expect(json['errors'][0]['resource']).to eq("/api/v2/cases/#{@case.id}/attachments/#{attachment.id}") + expect(json['errors'][0]['message']).to eq('Invalid Attachment JSON') + end + end + describe 'DELETE /api/v2/:record/:id/attachment/:attachment-id' do let(:attachment) do attachment = Attachment.new( @@ -94,14 +142,17 @@ attachment end - it 'removes an attached record' do + before { attachment } + + it 'removes an attached record and updates the has_photo field' do login_for_test({ permitted_field_names: [Attachable::PHOTOS_FIELD_NAME] }) delete "/api/v2/cases/#{@case.id}/attachments/#{attachment.id}" expect(response).to have_http_status(204) expect(@case.attachments.count).to eq(0) - + @case.reload + expect(@case.has_photo).to eq(false) expect(audit_params['action']).to eq('detach') end diff --git a/spec/requests/api/v2/bulk_exports_controller_spec.rb b/spec/requests/api/v2/bulk_exports_controller_spec.rb index 8a227aeadd..eb9f402323 100644 --- a/spec/requests/api/v2/bulk_exports_controller_spec.rb +++ b/spec/requests/api/v2/bulk_exports_controller_spec.rb @@ -47,6 +47,10 @@ expect(json['metadata']['page']).to eq(1) end + it_behaves_like 'a paginated resource' do + let(:action) { { resource: 'exports', login_params: { permissions: [@export_permission] } } } + end + it 'lists only csv permitted exports and accompanying metadata' do login_for_test(permissions: [@export_permission]) diff --git a/spec/requests/api/v2/children_controller_spec.rb b/spec/requests/api/v2/children_controller_spec.rb index 02d3413b6f..361b3b2401 100644 --- a/spec/requests/api/v2/children_controller_spec.rb +++ b/spec/requests/api/v2/children_controller_spec.rb @@ -9,8 +9,8 @@ before :each do clean_data( - Alert, Flag, Attachment, Incident, Child, User, Agency, Role, Lookup, PrimeroModule, RegistryRecord, Family, - Field, FormSection + Alert, Flag, Attachment, Trace, Incident, Child, User, Agency, Role, Lookup, PrimeroModule, RegistryRecord, + Family, Field, FormSection, Location ) @agency = Agency.create!(name: 'Test Agency', agency_code: 'TA', services: ['Test type']) @@ -21,6 +21,7 @@ Field.create!(name: 'field_a', display_name: 'Field A', type: Field::TEXT_FIELD) ] ) + role_self = Role.create!( name: 'Test Role 3', unique_id: 'test-role-3', @@ -80,6 +81,11 @@ form_section_read_write: { @form_a.unique_id => 'rw' } ) @role_restricted.save! + + @cp.form_sections = [@form_a] + @cp.roles = [@role_restricted] + @cp.save! + @role1 = Role.create!(name: 'Role self permission', unique_id: 'role_self_permission', modules: [@cp], referral: true, transfer: true, group_permission: 'self', permissions: [Permission.new(resource: Permission::CASE, actions: [Permission::MANAGE])]) @@ -114,6 +120,9 @@ user_group_ids: [@group1.id], role: @role1 ) + Location.create!(placename: 'Country', type: 'country', location_code: 'LOC') + Location.create!(placename: 'State', type: 'state', location_code: 'LOC01', hierarchy_path: 'LOC.LOC01') + Location.create!(placename: 'City', type: 'city', location_code: 'LOC0102', hierarchy_path: 'LOC.LOC01.LOC0102') Lookup.create!( unique_id: 'lookup-service-type', @@ -126,7 +135,7 @@ registry_type: 'farmer', name: 'Jones', registry_no: 'GH123.ABC123' ) @case1 = Child.create!( - data: { name: 'Test1', age: 5, sex: 'male', urgent_protection_concern: false }, + data: { name: 'Test1', age: 5, sex: 'male', urgent_protection_concern: false, location_current: 'LOC0102' }, registry_record: @registry_record1 ) Attachment.new( @@ -134,7 +143,7 @@ file_name: 'jorge.jpg', attachment: attachment_base64('jorge.jpg') ).attach! @case2 = Child.create!( - data: { name: 'Test2', age: 10, sex: 'female', urgent_protection_concern: true }, + data: { name: 'Test2', age: 10, sex: 'female', urgent_protection_concern: true, location_current: 'LOC0102' }, alerts: [ Alert.create(type: 'transfer_request', alert_for: 'transfer_request'), Alert.create(type: 'transfer_request', alert_for: 'transfer_request') @@ -145,7 +154,7 @@ @unique_id_uncle = SecureRandom.uuid @case3 = Child.create!( data: { - name: 'Test3', age: 6, sex: 'male', + name: 'Test3', age: 6, sex: 'male', location_current: 'LOC0101', family_details_section: [ { unique_id: @unique_id_mother, relation_type: 'mother', relation_age: 33 }, { unique_id: @unique_id_father, relation_type: 'father', relation_age: 32 } @@ -247,10 +256,6 @@ transitioned_by: 'user_cp', transitioned_to: 'user_referral', record: @case11, authorized_role_unique_id: 'role-restricted' ) - # This is legitimate. The cases are implicitly reloaded in the attachments & flagging api - reloaded_cases = [@case1, @case2, @case3, @case4, @case5, @case6, @case7, @case8].map(&:reload) - Sunspot.index(*reloaded_cases) - Sunspot.commit end let(:json) { JSON.parse(response.body) } @@ -276,6 +281,10 @@ expect(case4_data['alert_count']).to eq(0) end + it_behaves_like 'a paginated resource' do + let(:action) { { resource: 'cases' } } + end + it 'shows relevant fields' do login_for_test(permitted_field_names: %w[age sex]) get '/api/v2/cases' @@ -325,16 +334,15 @@ end it 'Search flagged children' do - @case1.add_flag('This is a flag', Date.today, 'faketest') - Sunspot.index(@case1.reload) - Sunspot.commit + @case_flagged = Child.create!(data: { name: 'Case Flagged', age: 5, sex: 'male' }) + @case_flagged.add_flag!('This is a flag', Date.today, 'faketest') login_for_test(permissions: permission_flag_record) get '/api/v2/cases?flagged=true' expect(response).to have_http_status(200) expect(json['data'][0]['flag_count']).to eq(1) - expect(json['data'][0]['id']).to eq(@case1.id) + expect(json['data'][0]['id']).to eq(@case_flagged.id) end it 'Search through photo' do @@ -368,6 +376,17 @@ expect(response).to have_http_status(200) end + it 'returns an empty response for an invalid filter and logs the error' do + allow(Rails.logger).to receive(:error).and_return(nil) + login_for_test + + get '/api/v2/cases?associated_user_names=List["user1"]' + expect(response).to have_http_status(200) + expect(json['metadata']['total']).to eq(0) + expect(json['data']).to be_empty + expect(Rails.logger).to have_received(:error) + end + context 'when a user can only see his own records but has search_owned_by_others' do it 'lists only those cases a user has permission to see' do sign_in(@user_owned_others) @@ -395,6 +414,13 @@ expect(json['data'].map { |rr| rr['age'] }).to eq([2, 5, 5, 6, 9, 10, 10, 12, 16, 17, 18]) end + it 'return records by location_current' do + login_for_test + get '/api/v2/cases?fields=short&loc:location_current[0]=LOC0102' + expect(json['data'].count).to eq(2) + expect(json['data'].map { |c| c['id'] }).to match_array([@case1.id, @case2.id]) + end + context 'when a gbv case has in the associated_user_names a cp user' do it 'should be part of the response' do login_for_test( @@ -555,7 +581,7 @@ user_id: fake_user_id, # This is technically wrong, but an artifact of the way we do tests resource_url: request.url, metadata: { user_name: fake_user_name, remote_ip: '127.0.0.1', agency_id: nil, role_id: nil, - http_method: 'GET' }) + http_method: 'GET', record_ids: [@case1.id] }) end it 'obfuscates the case name when hidden' do @@ -748,6 +774,19 @@ expect(json['data']['id']).to eq(@case1.id) end + it 'ignores unauthorized attributes' do + login_for_test + params = { data: { name: 'TesterTester', unauthorized_field: '0001' } } + + patch "/api/v2/cases/#{@case1.id}", params:, as: :json + + expect(response).to have_http_status(200) + expect(json['data']['name']).to eq('TesterTester') + + case1 = Child.find_by(id: @case1.id) + expect(case1.data['unauthorized_field']).to be_nil + end + it 'filters sensitive information from logs' do allow(Rails.logger).to receive(:debug).and_return(nil) login_for_test @@ -863,6 +902,7 @@ describe 'when a user adds a service subform' do it 'updates the subforms if cannot update the record' do login_for_test( + permitted_fields: [], group_permission: Permission::SELF, permissions: [ Permission.new( @@ -888,6 +928,7 @@ it 'updates the subforms if cannot read/write cases' do login_for_test( + permitted_fields: [], group_permission: Permission::SELF, permissions: [ Permission.new( @@ -1262,20 +1303,6 @@ expect(json['data']['field_a']).to eq('new value for field_a') expect(json['data']['permitted_forms']).to eq({ 'form_a' => 'rw' }) end - - it 'returns 422 error if the updated field is not authorized' do - sign_in(@user_referral) - - params = { data: { national_id_no: '0001' } } - - patch "/api/v2/cases/#{@case11.id}", params:, as: :json - - expect(response).to have_http_status(422) - expect(json['errors'][0]['status']).to eq(422) - expect(json['errors'][0]['resource']).to eq("/api/v2/cases/#{@case11.id}") - expect(json['errors'][0]['detail']).to match_array(['/national_id_no']) - expect(json['errors'][0]['message']).to eq('Invalid Record JSON') - end end end end @@ -1424,7 +1451,7 @@ after :each do clean_data( Trace, Alert, Flag, Attachment, Incident, Child, User, Agency, Role, Lookup, PrimeroModule, RegistryRecord, - Field, FormSection + Field, FormSection, Location ) clear_performed_jobs clear_enqueued_jobs diff --git a/spec/requests/api/v2/children_incidents_controller_spec.rb b/spec/requests/api/v2/children_incidents_controller_spec.rb index 915f005ce2..62f6e10a57 100644 --- a/spec/requests/api/v2/children_incidents_controller_spec.rb +++ b/spec/requests/api/v2/children_incidents_controller_spec.rb @@ -64,4 +64,28 @@ expect(json['data']['sex']).to eq('male') end end + + describe 'POST /api/v2/cases/:id/incidents' do + it 'links a case to a incident' do + login_for_test( + permissions: [ + Permission.new(resource: Permission::INCIDENT, actions: [Permission::LINK_INCIDENT_TO_CASE]) + ] + ) + params = { data: { incident_ids: [@incident1.id] } } + post("/api/v2/cases/#{@case1.id}/incidents", params:) + + expect(response).to have_http_status(204) + end + + it 'fetches the data of a new incident created from a case' do + login_for_test(permissions: []) + params = { data: { incident_ids: [@incident1.id] } } + post("/api/v2/cases/#{@case1.id}/incidents", params:) + + expect(response).to have_http_status(403) + expect(json['errors'].size).to eq(1) + expect(json['errors'][0]['resource']).to eq("/api/v2/cases/#{@case1.id}/incidents") + end + end end diff --git a/spec/requests/api/v2/dashboards_controller_spec.rb b/spec/requests/api/v2/dashboards_controller_spec.rb index d2ca8447c4..d91a725ee5 100644 --- a/spec/requests/api/v2/dashboards_controller_spec.rb +++ b/spec/requests/api/v2/dashboards_controller_spec.rb @@ -5,7 +5,7 @@ require 'rails_helper' describe Api::V2::DashboardsController, type: :request do - before :each do + before do clean_data( Alert, User, UserGroup, Role, Incident, Child, Location, SystemSettings, Field, FormSection, Lookup, PrimeroModule ) @@ -67,9 +67,8 @@ Child.create!( data: { record_state: true, status: 'open', owned_by: 'foo', workflow: 'new', created_at: last_week, - protection_concerns: ['refugee'], followup_subform_section: [ - { followup_needed_by_date: [Time.zone.now] } - ], assessment_due_date: Time.zone.now, case_plan_due_date: Time.zone.now, services_section: [ + protection_concerns: ['refugee'], followup_subform_section: [{ followup_needed_by_date: Time.zone.now }], + assessment_due_date: Time.zone.now, case_plan_due_date: Time.zone.now, services_section: [ { service_type: 'health_medical_service', service_referral: 'referred', service_implemented: 'not_implemented', service_response_type: 'care_plan', @@ -82,17 +81,21 @@ child = Child.create!( data: { record_state: true, status: 'open', owned_by: 'foo', last_updated_by: 'bar', workflow: 'assessment', - protection_concerns: ['refugee'], followup_subform_section: [ - { followup_needed_by_date: [Time.zone.now] } - ], assessment_due_date: Time.zone.now, case_plan_due_date: Time.zone.now + protection_concerns: ['refugee'], followup_subform_section: [{ followup_needed_by_date: Time.zone.now }], + assessment_due_date: Time.zone.now, case_plan_due_date: Time.zone.now } ) - child.alerts = [Alert.new(record: child, type: Alertable::INCIDENT_FROM_CASE, alert_for: Alertable::FIELD_CHANGE)] + # TODO: This alert shouldn't be necessary once alerts on incidents get fixed. + child.add_alert(type: Alertable::INCIDENT_FROM_CASE, alert_for: Alertable::FIELD_CHANGE) - incident = Incident.create!(data: { incident_date: Date.new(2019, 3, 1), description: 'Test 1' }) - incident.incident_case_id = child.id - incident.save + Incident.create!( + data: { incident_date: Date.new(2019, 3, 1), description: 'Test 1' }, incident_case_id: child.id + ) + + child.reload + child.update_properties(@bar, name_first: 'Updated Name') + child.save! Child.create!(data: { record_state: false, status: 'open', owned_by: 'foo', workflow: 'new' }) Child.create!(data: { @@ -109,14 +112,12 @@ }) Child.create!(data: { record_state: true, status: 'open', owned_by: 'bar', workflow: 'new' }) Child.create!(data: { record_state: true, status: 'open', owned_by: 'bar' }) - - Sunspot.commit end let(:json) { JSON.parse(response.body) } describe 'GET /api/v2/dashboards', search: true do - it 'lists statistics for permitted dashboards' do + it 'lists all the permitted dashboards' do login_for_test( user_name: 'foo', group_permission: Permission::SELF, @@ -127,6 +128,18 @@ expect(response).to have_http_status(200) expect(json['data'].size).to eq(13) + end + + it 'lists statistics for the case overview dashboard' do + login_for_test( + user_name: 'foo', + group_permission: Permission::SELF, + permissions: [@permission_case, @permission_dashboard] + ) + + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) case_overview_dashboard = json['data'].find { |d| d['name'] == 'dashboard.case_overview' } expect(case_overview_dashboard['indicators']['total']['count']).to eq(2) @@ -137,46 +150,153 @@ expect(case_overview_dashboard['indicators']['new_or_updated']['query']).to match_array( %w[record_state=true status=open not_edited_by_owner=true] ) + end + + it 'lists statistics for the workflow dashboards' do + login_for_test( + user_name: 'foo', + group_permission: Permission::SELF, + permissions: [@permission_case, @permission_dashboard] + ) + + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) workflow_dashboard = json['data'].find { |d| d['name'] == 'dashboard.workflow' } expect(workflow_dashboard['indicators']['workflow']['assessment']['count']).to eq(1) expect(workflow_dashboard['indicators']['workflow']['assessment']['query']).to match_array( %w[owned_by=foo record_state=true status=open,closed workflow=assessment] ) + end - reporting_location_dashboard = json['data'].find { |d| d['name'] == 'dashboard.reporting_location' } + it 'lists statistics for the reporting location dashboards' do + login_for_test( + user_name: 'foo', + group_permission: Permission::SELF, + permissions: [@permission_case, @permission_dashboard] + ) + + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) + reporting_location_dashboard = json['data'].find { |d| d['name'] == 'dashboard.reporting_location' } expect(reporting_location_dashboard['indicators']['reporting_location_open']['cty']['count']).to eq(2) expect(reporting_location_dashboard['indicators']['reporting_location_open_this_week']['cty']['count']).to eq(1) expect(reporting_location_dashboard['indicators']['reporting_location_open_last_week']['cty']['count']).to eq(1) expect(reporting_location_dashboard['indicators']['reporting_location_closed_this_week']['cty']['count']).to eq(2) expect(reporting_location_dashboard['indicators']['reporting_location_closed_last_week']['cty']['count']).to eq(1) + end + + it 'lists statistics for the protection concerns dashboards' do + login_for_test( + user_name: 'foo', + group_permission: Permission::SELF, + permissions: [@permission_case, @permission_dashboard] + ) + + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) protection_concerns = json['data'].find { |d| d['name'] == 'dashboard.dash_protection_concerns' }['indicators'] expect(protection_concerns['protection_concerns_open_cases']['refugee']['count']).to eq(2) expect(protection_concerns['protection_concerns_new_this_week']['refugee']['count']).to eq(1) expect(protection_concerns['protection_concerns_all_cases']['refugee']['count']).to eq(4) expect(protection_concerns['protection_concerns_closed_this_week']['refugee']['count']).to eq(1) + end + + it 'lists statistics for the group overview dashboards' do + login_for_test( + user_name: 'foo', + group_permission: Permission::SELF, + permissions: [@permission_case, @permission_dashboard] + ) + + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) group_overview_dashboard = json['data'].find { |d| d['name'] == 'dashboard.dash_group_overview' } expect(group_overview_dashboard['indicators']['group_overview_open']['count']).to eq(2) expect(group_overview_dashboard['indicators']['group_overview_closed']['count']).to eq(3) + end + + it 'lists statistics for the task overdue assessment plan dashboards' do + login_for_test( + user_name: 'foo', + group_permission: Permission::SELF, + permissions: [@permission_case, @permission_dashboard] + ) + + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) tasks_overdue_assessment = json['data'].find { |d| d['name'] == 'dashboard.cases_by_task_overdue_assessment' } expect(tasks_overdue_assessment['indicators']['tasks_overdue_assessment']['foo']['count']).to eq(2) expect(tasks_overdue_assessment['indicators']['tasks_overdue_assessment'].count).to eq(1) + end + + it 'lists statistics for the task overdue case plan dashboards' do + login_for_test( + user_name: 'foo', + group_permission: Permission::SELF, + permissions: [@permission_case, @permission_dashboard] + ) + + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) tasks_overdue_case_plan = json['data'].find { |d| d['name'] == 'dashboard.cases_by_task_overdue_case_plan' } expect(tasks_overdue_case_plan['indicators']['tasks_overdue_case_plan']['foo']['count']).to eq(2) expect(tasks_overdue_case_plan['indicators']['tasks_overdue_case_plan'].count).to eq(1) + end + + it 'lists statistics for the task overdue followups dashboards' do + login_for_test( + user_name: 'foo', + group_permission: Permission::SELF, + permissions: [@permission_case, @permission_dashboard] + ) + + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) tasks_overdue_followups = json['data'].find { |d| d['name'] == 'dashboard.cases_by_task_overdue_followups' } expect(tasks_overdue_followups['indicators']['tasks_overdue_followups']['foo']['count']).to eq(2) expect(tasks_overdue_followups['indicators']['tasks_overdue_followups'].count).to eq(1) + end + + it 'lists statistics for the task overdue services dashboards' do + login_for_test( + user_name: 'foo', + group_permission: Permission::SELF, + permissions: [@permission_case, @permission_dashboard] + ) + + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) tasks_overdue_services = json['data'].find { |d| d['name'] == 'dashboard.cases_by_task_overdue_services' } expect(tasks_overdue_services['indicators']['tasks_overdue_services']['foo']['count']).to eq(1) expect(tasks_overdue_services['indicators']['tasks_overdue_services'].count).to eq(1) + end + + it 'lists statistics for the case incident overview dashboards' do + login_for_test( + user_name: 'foo', + group_permission: Permission::SELF, + permissions: [@permission_case, @permission_dashboard] + ) + + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) case_incident_overview = json['data'].find { |d| d['name'] == 'dashboard.dash_case_incident_overview' } expect(case_incident_overview['indicators'].count).to eq(5) @@ -185,6 +305,19 @@ expect(case_incident_overview['indicators']['with_incidents']['count']).to eq(1) expect(case_incident_overview['indicators']['with_new_incidents']['count']).to eq(1) expect(case_incident_overview['indicators']['without_incidents']['count']).to eq(1) + end + + it 'lists statistics for the cases by social worker dashboards' do + login_for_test( + user_name: 'foo', + user_group_unique_ids: @foo.user_group_unique_ids, + group_permission: Permission::SELF, + permissions: [@permission_case, @permission_dashboard] + ) + + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) cases_by_social_worker = json['data'].find { |d| d['name'] == 'dashboard.dash_cases_by_social_worker' } expect(cases_by_social_worker['indicators'].count).to eq(2) @@ -192,6 +325,18 @@ cases_by_social_worker_new_or_updated]) expect(cases_by_social_worker['indicators']['cases_by_social_worker_total']['foo']['count']).to eq(2) expect(cases_by_social_worker['indicators']['cases_by_social_worker_new_or_updated']['foo']['count']).to eq(1) + end + + it 'lists statistics for the national admin summary dashboards' do + login_for_test( + user_name: 'foo', + group_permission: Permission::SELF, + permissions: [@permission_case, @permission_dashboard] + ) + + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) national_admin_summary = json['data'].find { |d| d['name'] == 'dashboard.dash_national_admin_summary' } expect(national_admin_summary['indicators'].count).to eq(5) @@ -229,7 +374,7 @@ @role = Role.new(permissions: [ @permission_refer_case, @permission_dashboard_shared_from_my_team - ], modules: [@primero_module]) + ], modules: [@primero_module], group_permission: Permission::GROUP) @role2 = Role.new(permissions: [ @permission_refer_case, @permission_dashboard_shared_with_my_team_overview @@ -280,7 +425,7 @@ Transfer.create!(transitioned_by: 'user1', transitioned_to: 'user2', record: @case_a) Transfer.create!(transitioned_by: 'user1', transitioned_to: 'user2', record: @case_b) @case_b.update(transfer_status: Transition::STATUS_REJECTED) - Sunspot.commit + @case_a.save! end it 'lists statistics for permitted shared with me dashboards' do @@ -290,6 +435,7 @@ permissions: [@permission_case, @permission_dashboard_shared_with_me] ) get '/api/v2/dashboards' + expect(response).to have_http_status(200) shared_with_me_dashboard = json['data'][0]['indicators'] @@ -337,19 +483,46 @@ expect(dash['shared_from_my_team_rejected_transfers'].count).to eq(1) end - it 'lists statistics for permitted shared with my team dashboard dashboards' do - login_for_test( - user_name: 'user1', - user_group_ids: [@group_a.id], - group_permission: Permission::GROUP, - permissions: [@permission_case, @permission_dashboard_shared_with_me_team] - ) - get '/api/v2/dashboards' - - expect(response).to have_http_status(200) - indicators = json['data'][0]['indicators'] - expect(indicators['shared_with_my_team_referrals'][@user2.user_name]['count']).to eq(1) - expect(indicators['shared_with_my_team_pending_transfers'][@user2.user_name]['count']).to eq(2) + describe 'shared with my team dashboard' do + it 'list statistics for a user with admin permissions' do + login_for_test( + group_permission: Permission::ALL, + permissions: [@permission_case, @permission_dashboard_shared_with_me_team] + ) + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) + indicators = json['data'][0]['indicators'] + expect(indicators['shared_with_my_team_referrals'][@user2.user_name]['count']).to eq(1) + expect(indicators['shared_with_my_team_pending_transfers'][@user2.user_name]['count']).to eq(2) + end + + it 'lists statistics for a user with group permissions' do + login_for_test( + user_name: 'user1', + user_group_unique_ids: [@group_a.unique_id], + permissions: [@permission_case, @permission_dashboard_shared_with_me_team] + ) + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) + indicators = json['data'][0]['indicators'] + expect(indicators['shared_with_my_team_referrals'][@user2.user_name]['count']).to eq(1) + expect(indicators['shared_with_my_team_pending_transfers'][@user2.user_name]['count']).to eq(2) + end + + it 'do not list statistics if values are not in the scope of the user' do + login_for_test( + group_permission: Permission::SELF, + permissions: [@permission_case, @permission_dashboard_shared_with_me_team] + ) + get '/api/v2/dashboards' + + expect(response).to have_http_status(200) + indicators = json['data'][0]['indicators'] + expect(indicators['shared_with_my_team_referrals']).to be_empty + expect(indicators['shared_with_my_team_pending_transfers']).to be_empty + end end it 'lists statistics for permitted shared with my team (overview) dashboards' do @@ -363,7 +536,6 @@ after :each do clean_data(Alert, User, UserGroup, Role, Incident, Child, Location, SystemSettings, Lookup) - Sunspot.commit end end end @@ -380,6 +552,5 @@ clean_data( Alert, User, UserGroup, Role, Incident, Child, Location, SystemSettings, Field, FormSection, Lookup, PrimeroModule ) - Sunspot.commit end end diff --git a/spec/requests/api/v2/families_controller_spec.rb b/spec/requests/api/v2/families_controller_spec.rb index 1057880021..6948c7d2f5 100644 --- a/spec/requests/api/v2/families_controller_spec.rb +++ b/spec/requests/api/v2/families_controller_spec.rb @@ -11,7 +11,6 @@ family2 family3 family4 - Sunspot.commit end let(:family1) do @@ -77,6 +76,13 @@ expect(json['metadata']['per']).to eq(20) expect(json['metadata']['page']).to eq(1) end + + it_behaves_like 'a paginated resource' do + let(:action) do + { resource: 'families', login_params: { permissions: [Permission.new(resource: Permission::FAMILY, actions: [Permission::READ])], + group_permission: Permission::GROUP } } + end + end end context 'when user is unauthorized' do diff --git a/spec/requests/api/v2/flags_controller_spec.rb b/spec/requests/api/v2/flags_controller_spec.rb index e6f1ef1298..3b4e68ac32 100644 --- a/spec/requests/api/v2/flags_controller_spec.rb +++ b/spec/requests/api/v2/flags_controller_spec.rb @@ -84,7 +84,7 @@ end describe 'POST /api/v2/:recordType/:recordId/flags' do - it 'creates a new flag to a case' do + it 'creates a new flag to a case and sets the flagged property to true' do login_for_test(permissions: permission_flag_record) params = { data: { date: Date.today.to_s, message: 'This is another flag' } } post("/api/v2/cases/#{@case1.id}/flags", params:) @@ -95,11 +95,12 @@ expect(json['data']['message']).to eq('This is another flag') expect(json['data']['removed']).to be_falsey expect(json['data']['record_id']).to eq(json['data']['record']['id']) - + @case1.reload + expect(@case1.flagged).to eq(true) expect(audit_params['action']).to eq('flag') end - it 'creates a new flag to a tracing_request' do + it 'creates a new flag to a tracing_request and sets the flagged property to true' do login_for_test(permissions: permission_flag_record) params = { data: { date: Date.today.to_s, message: 'This is another flag TR' } } post("/api/v2/tracing_requests/#{@tracing_request1.id}/flags", params:) @@ -110,9 +111,11 @@ expect(json['data']['message']).to eq('This is another flag TR') expect(json['data']['removed']).to be_falsey expect(json['data']['record_id']).to eq(json['data']['record']['id']) + @tracing_request1.reload + expect(@tracing_request1.flagged).to eq(true) end - it 'creates a new flag to an incident' do + it 'creates a new flag to an incident and sets the flagged property to true' do login_for_test(permissions: permission_flag_record) params = { data: { date: Date.today.to_s, message: 'This is another flag IN' } } post("/api/v2/incidents/#{@incident1.id}/flags", params:) @@ -123,6 +126,8 @@ expect(json['data']['message']).to eq('This is another flag IN') expect(json['data']['removed']).to be_falsey expect(json['data']['record_id']).to eq(json['data']['record']['id']) + @incident1.reload + expect(@incident1.flagged).to eq(true) end it "get a forbidden message if the user doesn't have flag permission" do @@ -148,12 +153,12 @@ user_id: fake_user_id, # This is technically wrong, but an artifact of the way we do tests resource_url: request.url, metadata: { user_name: fake_user_name, remote_ip: '127.0.0.1', agency_id: nil, role_id: nil, - http_method: 'POST' }) + http_method: 'POST', record_ids: [] }) end end describe 'PATCH /api/v2/:recordType/:recordId/flags/:id' do - it 'unflags a case' do + it 'unflags a case and sets the flagged property to false' do login_for_test(permissions: permission_flag_record) params = { data: { unflag_message: 'This is unflag message' } } patch("/api/v2/cases/#{@case1.id}/flags/#{@case1.flags.first.id}", params:) @@ -164,11 +169,12 @@ expect(json['data']['unflagged_date']).to eq(Date.today.to_s) expect(json['data']['unflagged_by']).to eq('faketest') expect(json['data']['record_id']).to eq(json['data']['record']['id']) - + @case1.reload + expect(@case1.flagged).to eq(false) expect(audit_params['action']).to eq('unflag') end - it 'unflags a tracing_request' do + it 'unflags a tracing_request and sets the flagged property to false' do login_for_test(permissions: permission_flag_record) params = { data: { unflag_message: 'This is unflag message TR' } } patch("/api/v2/tracing_requests/#{@tracing_request1.id}/flags/#{@tracing_request1.flags.first.id}", params:) @@ -179,9 +185,11 @@ expect(json['data']['unflagged_date']).to eq(Date.today.to_s) expect(json['data']['unflagged_by']).to eq('faketest') expect(json['data']['record_id']).to eq(json['data']['record']['id']) + @tracing_request1.reload + expect(@tracing_request1.flagged).to eq(false) end - it 'unflags an incident' do + it 'unflags an incident and sets the flagged property to false' do login_for_test(permissions: permission_flag_record) params = { data: { unflag_message: 'This is unflag message IN' } } patch("/api/v2/incidents/#{@incident1.id}/flags/#{@incident1.flags.first.id}", params:) @@ -192,6 +200,8 @@ expect(json['data']['unflagged_date']).to eq(Date.today.to_s) expect(json['data']['unflagged_by']).to eq('faketest') expect(json['data']['record_id']).to eq(json['data']['record']['id']) + @incident1.reload + expect(@incident1.flagged).to eq(false) end it "get a forbidden message if the user doesn't have flag permission" do diff --git a/spec/requests/api/v2/flags_owners_controller_spec.rb b/spec/requests/api/v2/flags_owners_controller_spec.rb index 89d8a3bddd..9d095eb125 100644 --- a/spec/requests/api/v2/flags_owners_controller_spec.rb +++ b/spec/requests/api/v2/flags_owners_controller_spec.rb @@ -52,8 +52,8 @@ owned_by: 'user2' }) @case1.add_flag('This is a flag', Date.today, 'faketest') - @case3.add_flag('This is a flag', Date.today, 'faketest') - @flag_to_remove = @case1.add_flag('This is test flag 3', Date.today, 'faketest') + @case3.add_flag('This is a flag', Date.today - 1.days, 'faketest') + @flag_to_remove = @case1.add_flag('This is test flag 3', Date.today - 2.days, 'faketest') @case1.remove_flag(@flag_to_remove.id, 'faketest', 'Resolved Flag') @tracing_request1.add_flag('This is a flag TR', Date.today, 'faketest') @incident1.add_flag('This is a flag IN', Date.today, 'faketest') @@ -198,6 +198,16 @@ expect(flag_data['removed']).to be_falsey expect(flag_data['short_id']).to eq(@case1.short_id) end + + it 'lists flags sorted by date for a record_type' do + get '/api/v2/flags?record_type=cases' + + expect(response).to have_http_status(200) + expect(json['data'].size).to eq(3) + expect(json['data'].map { |flag| flag['date'] }).to eq( + 3.times.map { |index| (Date.today - index.days).as_json } + ) + end end context 'and user has Agency permissions' do diff --git a/spec/requests/api/v2/incidents_controller_spec.rb b/spec/requests/api/v2/incidents_controller_spec.rb index 4743703b57..920f57c40a 100644 --- a/spec/requests/api/v2/incidents_controller_spec.rb +++ b/spec/requests/api/v2/incidents_controller_spec.rb @@ -75,14 +75,92 @@ def mrm_fields ].freeze end before :each do + clean_data(Location, PrimeroModule, Incident, Child, Alert, User, Agency, Role, SystemSettings) + + SystemSettings.create!( + incident_reporting_location_config: { admin_level: 2, field_key: 'incident_location' } + ) + + @country = create( + :location, placename_all: 'MyCountry', type: 'country', location_code: 'MC01' + ) + @province1 = create( + :location, hierarchy_path: "#{@country.location_code}.PR01", + type: 'province', location_code: 'PR01', + placename_i18n: { en: 'Province 1', fr: 'La Province 1' } + ) + @town1 = create( + :location, hierarchy_path: "#{@country.location_code}.#{@province1.location_code}.TW01", + placename_all: 'Town 1', type: 'city', location_code: 'TW01' + ) + + @mrm_module = PrimeroModule.create!( + primero_program: PrimeroProgram.first, + name: 'MRM Module', + unique_id: PrimeroModule::MRM, + associated_record_types: ['incident'] + ) + @mrm_role = Role.new_with_properties( + name: 'MRM Role', + unique_id: 'mrm-role', + group_permission: Permission::SELF, + permissions: [ + Permission.new( + resource: Permission::INCIDENT, + actions: [Permission::READ, Permission::CREATE, Permission::WRITE] + ) + ], + modules: [@mrm_module] + ) + @mrm_agency = Agency.create!(name: 'Test Agency', agency_code: 'TA', services: ['Test type']) + @mrm_user = User.create!( + full_name: 'MRM User', + user_name: 'mrm_user', + password: 'a12345632', + password_confirmation: 'a12345632', + email: 'mrm_user@localhost.com', + agency_id: @mrm_agency.id, + role: @mrm_role + ) @case1 = Child.create!(data: { name: 'Test1', age: 5, sex: 'male', urgent_protection_concern: false }) - @incident1 = Incident.create!(data: { incident_date: Date.new(2019, 3, 1), description: 'Test 1' }) + @case2 = Child.create!(data: { name: 'Test2', age: 6, sex: 'male' }) + @incident1 = Incident.create!( + data: { incident_date: Date.new(2019, 3, 1), description: 'Test 1', module_id: PrimeroModule::MRM } + ) @incident2 = Incident.create!(data: { incident_date: Date.new(2018, 3, 1), description: 'Test 2' }) @incident3 = Incident.create!( data: { incident_date: Date.new(2018, 3, 1), description: 'Test 3' }, incident_case_id: @case1.id ) - Sunspot.commit + @incident4 = Incident.new_with_user( + @mrm_user, + { + incident_date: Date.new(2022, 8, 10), + description: 'Test 4', + violation_category: ['killing'], + module_id: PrimeroModule::MRM, + killing: [ + { + unique_id: '0fff1c74-7626-11ef-998a-18c04db5c362', + type: 'killing', + verified: 'verified', + ctfmr_verified_date: Date.new(2023, 5, 12), + is_late_verification: true + } + ] + }.with_indifferent_access + ) + @incident4.save! + @incident5 = Incident.new_with_user( + @mrm_user, + { + incident_date: Date.new(2022, 8, 10), + description: 'Test 5', + incident_location: 'TW01', + module_id: PrimeroModule::MRM + } + ) + @incident5.save! end let(:json) { JSON.parse(response.body) } @@ -93,15 +171,19 @@ def mrm_fields get '/api/v2/incidents' expect(response).to have_http_status(200) - expect(json['data'].size).to eq(3) + expect(json['data'].size).to eq(5) expect(json['data'].map { |c| c['description'] }).to include( - @incident1.description, @incident2.description, @incident3.description + @incident1.description, @incident2.description, @incident3.description, @incident4.description ) - expect(json['metadata']['total']).to eq(3) + expect(json['metadata']['total']).to eq(5) expect(json['metadata']['per']).to eq(20) expect(json['metadata']['page']).to eq(1) end + it_behaves_like 'a paginated resource' do + let(:action) { { resource: 'incidents' } } + end + it 'returns flag_count for the short form ' do @incident1.add_flag('This is a flag IN', Date.today, 'faketest') @@ -112,6 +194,24 @@ def mrm_fields incident_data = json['data'].find { |i| i['id'] == @incident1.id } expect(incident_data['flag_count']).to eq(1) end + + it 'returns the incidents with late_verified_violations' do + sign_in(@mrm_user) + get '/api/v2/incidents?has_late_verified_violations=true' + + expect(response).to have_http_status(200) + expect(json['data'].size).to eq(1) + expect(json['data'].map { |data| data['id'] }).to match_array([@incident4.id]) + end + + it 'returns the incidents for the reporting location' do + sign_in(@mrm_user) + get '/api/v2/incidents?loc:incident_location2=TW01' + + expect(response).to have_http_status(200) + expect(json['data'].size).to eq(1) + expect(json['data'].map { |data| data['id'] }).to match_array([@incident5.id]) + end end describe 'GET /api/v2/incidents/:id' do @@ -252,6 +352,30 @@ def mrm_fields expect(Incident.find_by(id: json['data']['id'])).not_to be_nil end end + + context 'when an incident is created for a case' do + it 'creates a new record and updates the has_incidents property on the case' do + login_for_test + + params = { + data: { + incident_date: '2024-01-10', + age: 7, + cp_sex: @case2.sex, + case_id_display: @case2.case_id_display, + incident_case_id: @case2.id + } + } + + post '/api/v2/incidents', params:, as: :json + + expect(response).to have_http_status(200) + expect(json['data']['id']).not_to be_empty + expect(json['data']['age']).to eq(7) + @case2.reload + expect(@case2.has_incidents).to eq(true) + end + end end describe 'PATCH /api/v2/incidents/:id' do @@ -285,7 +409,7 @@ def mrm_fields data['recruitment'] = [ { 'unique_id' => '8dccaf74-e9aa-452a-9b58-dc365b1062a2', - 'violation_tally': { 'boys': 3, 'girls': 1, 'unknown': 0, 'total': 4 }, + violation_tally: { boys: 3, girls: 1, unknown: 0, total: 4 }, 'name' => 'violation1' } ] diff --git a/spec/requests/api/v2/key_performance_indicators_controller_spec.rb b/spec/requests/api/v2/key_performance_indicators_controller_spec.rb index 9745241c35..0e53cea496 100644 --- a/spec/requests/api/v2/key_performance_indicators_controller_spec.rb +++ b/spec/requests/api/v2/key_performance_indicators_controller_spec.rb @@ -5,7 +5,7 @@ require 'rails_helper' # Most of the tests after the HTTP status should be moved into unit tests. -describe Api::V2::KeyPerformanceIndicatorsController, type: :request do +describe Api::V2::KeyPerformanceIndicatorsController, { type: :request, skip_when_solr_disabled: true } do def form(id, fields) FormSection.create_or_update!( unique_id: id, @@ -24,7 +24,7 @@ def field(id, config = {}) end before(:each) do - clean_data(Lookup, Location, Agency, Role, UserGroup, User, Incident, Child, FormSection) + clean_data(User, Lookup, Location, Agency, Role, UserGroup, Incident, Child, FormSection) @uk = Location.create!( location_code: 'GBR', diff --git a/spec/requests/api/v2/password_reset_controller_spec.rb b/spec/requests/api/v2/password_reset_controller_spec.rb index 58846278fe..264adf8038 100644 --- a/spec/requests/api/v2/password_reset_controller_spec.rb +++ b/spec/requests/api/v2/password_reset_controller_spec.rb @@ -88,8 +88,6 @@ describe 'POST /api/v2/users/password-reset' do let(:reset_password_token) { user.send(:set_reset_password_token) } - let(:authorization_token) { response.headers['Authorization'].split(' ')[1] } - let(:token_cookie) { response.cookies['primero_token'] } let(:json) { JSON.parse(response.body) } context 'with valid token' do @@ -109,11 +107,8 @@ end it 'logs the user in' do - expect(authorization_token).to be_present - expect(token_cookie).to be_present expect(json['id']).to eq(user.id) expect(json['user_name']).to eq(user.user_name) - expect(json['token']).to eq(token_cookie) end end diff --git a/spec/requests/api/v2/potential_matches_controller_spec.rb b/spec/requests/api/v2/potential_matches_controller_spec.rb index 04c9825e7e..374b2076ad 100644 --- a/spec/requests/api/v2/potential_matches_controller_spec.rb +++ b/spec/requests/api/v2/potential_matches_controller_spec.rb @@ -5,8 +5,8 @@ require 'rails_helper' describe Api::V2::PotentialMatchesController, type: :request do - before(:each) { clean_data(Attachment, Trace, Child) } - after(:each) { clean_data(Attachment, Trace, Child) } + before(:each) { clean_data(Attachment, Trace, Incident, Child) } + after(:each) { clean_data(Attachment, Trace, Incident, Child) } let(:case1) do Child.create!( diff --git a/spec/requests/api/v2/primero_configurations_controller_spec.rb b/spec/requests/api/v2/primero_configurations_controller_spec.rb index cf10c5ae42..295899943b 100644 --- a/spec/requests/api/v2/primero_configurations_controller_spec.rb +++ b/spec/requests/api/v2/primero_configurations_controller_spec.rb @@ -55,6 +55,10 @@ expect(json['metadata']['page']).to eq(1) end + it_behaves_like 'a paginated resource' do + let(:action) { { resource: 'configurations', login_params: { permissions: correct_permissions } } } + end + it 'returns 403 if user is not authorized to access' do login_for_test get '/api/v2/configurations' diff --git a/spec/requests/api/v2/record_histories_controller_spec.rb b/spec/requests/api/v2/record_histories_controller_spec.rb index d31232da08..59b2f0c959 100644 --- a/spec/requests/api/v2/record_histories_controller_spec.rb +++ b/spec/requests/api/v2/record_histories_controller_spec.rb @@ -6,7 +6,7 @@ describe Api::V2::RecordHistoriesController, type: :request do before :each do - clean_data(User, Role, Agency, Child, TracingRequest, Incident, RecordHistory) + clean_data(User, Role, Agency, Incident, TracingRequest, Child, RecordHistory) agency_a = Agency.create!( unique_id: 'agency_1', @@ -81,8 +81,10 @@ user_name: 'faketest', action: 'create', record_changes: [ { 'status' => { 'from' => nil, 'to' => 'open' } }, + { 'flagged' => { 'from' => nil, 'to' => false } }, { 'owned_by' => { 'from' => nil, 'to' => 'faketest' } }, { 'short_id' => { 'from' => nil, 'to' => TracingRequest.first.short_id } }, + { 'has_photo' => { 'from' => nil, 'to' => false } }, { 'posted_at' => { 'from' => nil, 'to' => TracingRequest.first.posted_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ') } }, { 'created_at' => { 'from' => nil, @@ -95,6 +97,8 @@ { 'created_by_groups' => { 'from' => nil, 'to' => [] } }, { 'unique_identifier' => { 'from' => nil, 'to' => TracingRequest.first.unique_identifier } }, { 'tracing_request_id' => { 'from' => nil, 'to' => TracingRequest.first.tracing_request_id } }, + { 'current_alert_types' => { 'from' => nil, 'to' => [] } }, + { 'not_edited_by_owner' => { 'from' => nil, 'to' => false } }, { 'associated_user_names' => { 'from' => nil, 'to' => ['faketest'] } }, { 'associated_user_groups' => { 'from' => nil, 'to' => [] } }, { 'associated_user_agencies' => { 'from' => nil, 'to' => [] } } @@ -136,7 +140,8 @@ record_changes: [ { unique_id: { from: nil, to: Incident.first.id } }, { description: { from: 'Test', to: 'Tester' } }, - { incident_date: { from: '2019-04-01', to: '2019-02-01' } } + { incident_date: { from: '2019-04-01', to: '2019-02-01' } }, + { incident_date_derived: { from: '2019-04-01', to: '2019-02-01' } } ] } @@ -148,8 +153,10 @@ action: 'create', record_changes: [ { 'status' => { 'from' => nil, 'to' => 'open' } }, + { 'flagged' => { 'from' => nil, 'to' => false } }, { 'owned_by' => { 'from' => nil, 'to' => 'faketest' } }, { 'short_id' => { 'from' => nil, 'to' => Incident.first.short_id } }, + { 'has_photo' => { 'from' => nil, 'to' => false } }, { 'posted_at' => { 'from' => nil, 'to' => Incident.first.posted_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ') } }, { 'created_at' => { 'from' => nil, 'to' => Incident.first.created_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ') } }, { 'created_by' => { 'from' => nil, 'to' => 'faketest' } }, @@ -158,15 +165,22 @@ { 'record_state' => { 'from' => nil, 'to' => true } }, { 'incident_code' => { 'from' => nil, 'to' => Incident.first.incident_code } }, { 'incident_date' => { 'from' => nil, 'to' => '2019-04-01' } }, + { 'referred_users' => { 'from' => nil, 'to' => [] } }, { 'owned_by_groups' => { 'from' => nil, 'to' => [] } }, { 'gbv_case_context' => { 'from' => nil, 'to' => [] } }, { 'created_by_groups' => { 'from' => nil, 'to' => [] } }, { 'unique_identifier' => { 'from' => nil, 'to' => Incident.first.incident_id } }, + { 'current_alert_types' => { 'from' => nil, 'to' => [] } }, + { 'not_edited_by_owner' => { 'from' => nil, 'to' => false } }, { 'date_of_first_report' => { 'from' => nil, 'to' => Incident.first.date_of_first_report.iso8601 } }, + { 'transferred_to_users' => { 'from' => nil, 'to' => [] } }, { 'associated_user_names' => { 'from' => nil, 'to' => ['faketest'] } }, + { 'incident_date_derived' => { 'from' => nil, 'to' => '2019-04-01' } }, { 'associated_user_groups' => { 'from' => nil, 'to' => [] } }, { 'elapsed_reporting_time' => { 'from' => nil, 'to' => 'over_1_month' } }, - { 'associated_user_agencies' => { 'from' => nil, 'to' => [] } } + { 'referred_users_present' => { 'from' => nil, 'to' => false } }, + { 'associated_user_agencies' => { 'from' => nil, 'to' => [] } }, + { 'transferred_to_user_groups' => { 'from' => nil, 'to' => [] } } ] } @@ -219,26 +233,38 @@ { 'name' => { 'from' => nil, 'to' => 'Test' } }, { 'status' => { 'from' => nil, 'to' => 'open' } }, { 'case_id' => { 'from' => nil, 'to' => Child.first.case_id } }, + { 'flagged' => { 'from' => nil, 'to' => false } }, { 'owned_by' => { 'from' => nil, 'to' => 'faketest' } }, { 'short_id' => { 'from' => nil, 'to' => Child.first.short_id } }, { 'workflow' => { 'from' => nil, 'to' => 'new' } }, + { 'has_photo' => { 'from' => nil, 'to' => false } }, { 'posted_at' => { 'from' => nil, 'to' => Child.first.posted_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ') } }, { 'created_at' => { 'from' => nil, 'to' => Child.first.created_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ') } }, { 'created_by' => { 'from' => nil, 'to' => 'faketest' } }, { 'record_state' => { 'from' => nil, 'to' => true } }, { 'has_case_plan' => { 'from' => nil, 'to' => false } }, + { 'has_incidents' => { 'from' => nil, 'to' => false } }, { 'notes_section' => { 'from' => nil, 'to' => [] } }, { 'reopened_logs' => { 'from' => nil, 'to' => [] } }, + { 'referred_users' => { 'from' => nil, 'to' => [] } }, { 'case_id_display' => { 'from' => nil, 'to' => Child.first.case_id_display } }, { 'followup_status' => { 'from' => nil, 'to' => 'follow_ups_not_planned' } }, { 'owned_by_groups' => { 'from' => nil, 'to' => [] } }, { 'created_by_groups' => { 'from' => nil, 'to' => [] } }, { 'registration_date' => { 'from' => nil, 'to' => Child.first.registration_date.iso8601 } }, { 'unique_identifier' => { 'from' => nil, 'to' => Child.first.unique_identifier } }, + { 'followup_due_dates' => { 'from' => nil, 'to' => [] } }, + { 'case_plan_due_dates' => { 'from' => nil, 'to' => [] } }, + { 'current_alert_types' => { 'from' => nil, 'to' => [] } }, + { 'not_edited_by_owner' => { 'from' => nil, 'to' => false } }, { 'protection_concerns' => { 'from' => nil, 'to' => [] } }, + { 'assessment_due_dates' => { 'from' => nil, 'to' => [] } }, + { 'transferred_to_users' => { 'from' => nil, 'to' => [] } }, { 'associated_user_names' => { 'from' => nil, 'to' => ['faketest'] } }, { 'associated_user_groups' => { 'from' => nil, 'to' => [] } }, - { 'associated_user_agencies' => { 'from' => nil, 'to' => [] } } + { 'referred_users_present' => { 'from' => nil, 'to' => false } }, + { 'associated_user_agencies' => { 'from' => nil, 'to' => [] } }, + { 'transferred_to_user_groups' => { 'from' => nil, 'to' => [] } } ] } diff --git a/spec/requests/api/v2/referrals_controller_spec.rb b/spec/requests/api/v2/referrals_controller_spec.rb index 6b9a946553..5ac3fa1c4d 100644 --- a/spec/requests/api/v2/referrals_controller_spec.rb +++ b/spec/requests/api/v2/referrals_controller_spec.rb @@ -158,6 +158,7 @@ service_record_id: @case_b.data['services_section'][0]['unique_id'] } } + post("/api/v2/cases/#{@case_b.id}/referrals", params:) expect(response).to have_http_status(200) diff --git a/spec/requests/api/v2/registry_records_controller_spec.rb b/spec/requests/api/v2/registry_records_controller_spec.rb index 5a4b95a603..3e79ecda51 100644 --- a/spec/requests/api/v2/registry_records_controller_spec.rb +++ b/spec/requests/api/v2/registry_records_controller_spec.rb @@ -11,7 +11,6 @@ @registry2 = RegistryRecord.create!(registry_type: RegistryRecord::REGISTRY_TYPE_INDIVIDUAL) @registry3 = RegistryRecord.create!(registry_type: RegistryRecord::REGISTRY_TYPE_INDIVIDUAL) @registry4 = RegistryRecord.create!(registry_type: RegistryRecord::REGISTRY_TYPE_FOSTER_CARE) - Sunspot.commit end let(:json) { JSON.parse(response.body) } @@ -31,6 +30,10 @@ expect(json['metadata']['page']).to eq(1) end + it_behaves_like 'a paginated resource' do + let(:action) { { resource: 'registry_records' } } + end + context 'when a registry_type is passed in' do it 'lists registries only for that registry_type' do expected_registry_types = [RegistryRecord::REGISTRY_TYPE_INDIVIDUAL, RegistryRecord::REGISTRY_TYPE_INDIVIDUAL] diff --git a/spec/requests/api/v2/reports_controller_spec.rb b/spec/requests/api/v2/reports_controller_spec.rb index 1ec417ef4b..d4059aa9e9 100644 --- a/spec/requests/api/v2/reports_controller_spec.rb +++ b/spec/requests/api/v2/reports_controller_spec.rb @@ -80,7 +80,7 @@ associated_record_types: %w[case tracing_request incident], primero_program: @program, form_sections: [FormSection.create!(name: 'form_1')]) @report1 = Report.create(name_en: 'Protection Concerns By Location', description_en: '', - module_id: PrimeroModule::CP, record_type: 'case', aggregate_by: ['owned_by_location0'], + module_id: PrimeroModule::CP, record_type: 'case', aggregate_by: ['loc:owned_by_location'], disaggregate_by: ['protection_concerns'], filters: [{ 'attribute' => 'status', 'value' => [Record::STATUS_OPEN] }, { 'attribute' => 'record_state', 'value' => ['true'] }], @@ -131,8 +131,6 @@ } ]) @child_concerns2.save! - - Sunspot.commit end let(:json) { JSON.parse(response.body) } @@ -546,7 +544,7 @@ graph: true, disabled: false, editable: true, - aggregate_by: %w[owned_by_location], + aggregate_by: %w[loc:owned_by_location], fields: [ { name: 'owned_by_location', diff --git a/spec/requests/api/v2/saved_searches_controller_spec.rb b/spec/requests/api/v2/saved_searches_controller_spec.rb index 7d9ee6d71a..b9de52ed64 100644 --- a/spec/requests/api/v2/saved_searches_controller_spec.rb +++ b/spec/requests/api/v2/saved_searches_controller_spec.rb @@ -73,6 +73,10 @@ expect(json['metadata']['per']).to eq(20) expect(json['metadata']['page']).to eq(1) end + + it_behaves_like 'a paginated resource' do + let(:action) { { resource: 'saved_searches' } } + end end describe 'POST /api/v2/saved_searches' do diff --git a/spec/requests/api/v2/system_settings_controller_spec.rb b/spec/requests/api/v2/system_settings_controller_spec.rb index a707f9b3a8..54fcd3e628 100644 --- a/spec/requests/api/v2/system_settings_controller_spec.rb +++ b/spec/requests/api/v2/system_settings_controller_spec.rb @@ -85,6 +85,9 @@ expect(json['data']['rtl_locales']).to contain_exactly('ar') expect(json['data']['primero_version']).to eq(@system_settings.primero_version) expect(json['data']['system_options']['maximum_users']).to eq(@system_settings.maximum_users) + expect( + json['data']['system_options']['maximum_attachments_per_record'] + ).to eq(@system_settings.maximum_attachments_per_record) end it 'lists system_settings and all agencies and all modules when the param *extended* is true on the request' do diff --git a/spec/requests/api/v2/tokens_controller_spec.rb b/spec/requests/api/v2/tokens_controller_spec.rb index e9613b30da..5fb0294784 100644 --- a/spec/requests/api/v2/tokens_controller_spec.rb +++ b/spec/requests/api/v2/tokens_controller_spec.rb @@ -3,7 +3,6 @@ # Copyright (c) 2014 - 2023 UNICEF. All rights reserved. require 'rails_helper' -require 'devise/jwt/test_helpers' describe Api::V2::TokensController, type: :request do include ActiveJob::TestHelper @@ -17,29 +16,14 @@ end describe 'POST /api/v2/tokens' do - let(:authorization_token) { response.headers['Authorization'].split(' ')[1] } let(:json) { JSON.parse(response.body) } - let(:jwt_header) { decode_jwt(authorization_token) } - let(:token_cookie) { response.cookies['primero_token'] } - it 'generates a new JWT token for valid credentials' do + it 'returns users with valid credentials' do post '/api/v2/tokens', params: @params expect(response).to have_http_status(200) - expect(authorization_token).to be_present expect(json['id']).to be_present expect(json['user_name']).to be_present - expect(json['token']).to be_present - expect(json['token']).to eq(authorization_token) - expect(jwt_header['sub']).to be_present - end - - it 'sets the JWT token as an HTTP-only, domain bound cookie' do - post '/api/v2/tokens', params: @params - - expect(response).to have_http_status(200) - expect(token_cookie).to be_present - expect(token_cookie).to eq(json['token']) end it 'returns nothing for invalid credentials' do @@ -49,7 +33,8 @@ it 'enqueues an audit log job that records the login attempt' do metadata = { - user_name: @user.user_name, remote_ip: '127.0.0.1', agency_id: nil, role_id: nil, http_method: 'POST' + user_name: @user.user_name, remote_ip: '127.0.0.1', agency_id: nil, role_id: nil, http_method: 'POST', + record_ids: [] } post '/api/v2/tokens', params: @params expect(AuditLogJob).to have_been_enqueued @@ -93,9 +78,9 @@ it 'returns a 401 when got JWT exception' do headers = { - 'HTTP_AUTHORIZATION' => 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.'\ - 'eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.'\ - 'SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c' + 'HTTP_AUTHORIZATION' => 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.' \ + 'eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.' \ + 'SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c' } post('/api/v2/tokens', headers:) @@ -137,11 +122,8 @@ end describe 'DELETE /api/v2/tokens' do - it 'revokes the current token' do - headers = { 'Accept' => 'application/json', 'Content-Type' => 'application/json' } - auth_headers = Devise::JWT::TestHelpers.auth_headers(headers, @user) - - delete '/api/v2/tokens', headers: auth_headers + it 'revokes the user session' do + delete '/api/v2/tokens' # delete url expect(response).to have_http_status(200) diff --git a/spec/requests/api/v2/tracing_requests_controller_spec.rb b/spec/requests/api/v2/tracing_requests_controller_spec.rb index c34c337852..1d81cfd47f 100644 --- a/spec/requests/api/v2/tracing_requests_controller_spec.rb +++ b/spec/requests/api/v2/tracing_requests_controller_spec.rb @@ -17,7 +17,6 @@ data: { name: 'Trace Test 2' }, tracing_request: @tracing_request2 ) - Sunspot.commit end let(:json) { JSON.parse(response.body) } @@ -38,6 +37,10 @@ expect(json['metadata']['page']).to eq(1) end + it_behaves_like 'a paginated resource' do + let(:action) { { resource: 'tracing_requests' } } + end + it 'returns flag_count for the short form ' do @tracing_request1.add_flag('This is a flag IN', Date.today, 'faketest') diff --git a/spec/requests/api/v2/users_controller_spec.rb b/spec/requests/api/v2/users_controller_spec.rb index 262849189e..6358286fc9 100644 --- a/spec/requests/api/v2/users_controller_spec.rb +++ b/spec/requests/api/v2/users_controller_spec.rb @@ -158,6 +158,9 @@ agency_id: @agency_a.id, role: @role, identity_provider_id: @identity_provider_a.id, + agency_office: 'my office 1', + locale: 'en', + services: ['service1'], user_groups: [@user_group_a] ) @@ -646,7 +649,9 @@ data: { full_name: 'Updated User 1', user_group_unique_ids: ['user-group-1'], - identity_provider_unique_id: @identity_provider_b.unique_id + identity_provider_unique_id: @identity_provider_b.unique_id, + agency_office: nil, + services: %w[service1 service2] } } @@ -657,9 +662,41 @@ user1 = User.find_by(id: @user_a.id) expect(user1.full_name).to eq('Updated User 1') expect(user1.user_groups.map(&:unique_id)).to eq(params[:data][:user_group_unique_ids]) + expect(user1.agency_office).to be_nil + expect(user1.services).to eq(%w[service1 service2]) expect(user1.identity_provider.unique_id).to eq(@identity_provider_b.unique_id) end + it 'keeps user signed in when password changed' do + sign_in(@user_d) + params = { + data: { + password: 'primer0!', + password_confirmation: 'primer0!' + } + } + patch("/api/v2/users/#{@user_d.id}", params:) + expect(response).to have_http_status(200) + get('/api/v2/roles') + expect(response).to have_http_status(200) + expect(controller.current_user).to eq(@user_d) + end + + it 'does not change logged in user session when password changed on another user' do + sign_in(@super_user) + params = { + data: { + password: 'primer0!', + password_confirmation: 'primer0!' + } + } + patch("/api/v2/users/#{@user_c.id}", params:) + expect(response).to have_http_status(200) + get('/api/v2/roles') + expect(response).to have_http_status(200) + expect(controller.current_user).to eq(@super_user) + end + it "returns 403 if user isn't authorized to update users" do login_for_test params = { @@ -726,6 +763,7 @@ data: { role_unique_id: 'test-role-1', identity_provider_unique_id: 'primeroims_2', + agency_id: @agency_a.id, user_name: } } @@ -737,6 +775,7 @@ expect(response).to have_http_status(200) expect(json['data']['id']).to eq(@user_d.id) expect(@user_d.role.unique_id).to eq(@role_manage_user.unique_id) + expect(@user_d.agency.unique_id).to eq(@agency_b.unique_id) expect(@user_d.user_name).not_to eq(user_name) expect(@user_d.identity_provider.unique_id).to eq(@identity_provider_a.unique_id) end diff --git a/spec/requests/api/v2/webpush_config_controller_spec.rb b/spec/requests/api/v2/webpush_config_controller_spec.rb index 490ef31d20..0138eb1e4e 100644 --- a/spec/requests/api/v2/webpush_config_controller_spec.rb +++ b/spec/requests/api/v2/webpush_config_controller_spec.rb @@ -9,6 +9,11 @@ describe 'GET /api/v2/webpush/config' do context 'when webpush is not enabled' do + before(:each) do + Rails.configuration.x.webpush.enabled = false + Rails.configuration.x.webpush.vapid_public = nil + end + it 'return enable false and vapid_public key nil' do login_for_test get '/api/v2/webpush/config' diff --git a/spec/requests/health_controller_spec.rb b/spec/requests/health_controller_spec.rb index e830291a7d..4d749eb00e 100644 --- a/spec/requests/health_controller_spec.rb +++ b/spec/requests/health_controller_spec.rb @@ -21,7 +21,7 @@ expect(response).to have_http_status(204) end - it 'returns 204 when testing just solr' do + it 'returns 204 when testing just solr', skip_when_solr_disabled: true do get '/health/solr' expect(response).to have_http_status(204) end diff --git a/spec/schedules/recalculate_age_spec.rb b/spec/schedules/recalculate_age_spec.rb index 792ed2f359..0e58c1d3d3 100644 --- a/spec/schedules/recalculate_age_spec.rb +++ b/spec/schedules/recalculate_age_spec.rb @@ -20,7 +20,6 @@ @case9 = Child.create(data: { name: 'case9', date_of_birth: Date.new(2015, 3, 1) }) @case10 = Child.create(data: { name: 'case10', date_of_birth: Date.new(2014, 10, 10) }) @case11 = Child.create(data: { name: 'case11', date_of_birth: Date.new(2010, 2, 28) }) # leap year - Sunspot.commit allow(Date).to receive(:current).and_return(today) end @@ -161,7 +160,7 @@ end @case31 = Child.create(data: { name: "case21'", date_of_birth: Date.current - 5.days }) @case32 = Child.create(data: { name: "case22'", date_of_birth: Date.current - 5.months }) - Sunspot.commit + Sunspot.commit if Rails.configuration.solr_enabled end it 'should return total pages and total_count' do diff --git a/spec/services/api_connector/primero_configuration_connector_spec.rb b/spec/services/api_connector/primero_configuration_connector_spec.rb index 81b584f606..eabfa1eb90 100644 --- a/spec/services/api_connector/primero_configuration_connector_spec.rb +++ b/spec/services/api_connector/primero_configuration_connector_spec.rb @@ -65,4 +65,60 @@ end end end + + describe 'When SystemSettings.primero_promote_config is present and ENV are set' do + before do + system_settings = instance_double( + 'SystemSettings', primero_promote_config: [ + { tls: 'true', host: 'foo.bar', port: '443', + basic_auth_secret: 'PRIMERO_PROMOTE_CONFIG_PROD_BASIC_AUTH' }.with_indifferent_access, + { tls: 'true', host: 'some.url', port: '443', basic_auth_secret: 'RANDOM_ENV' }.with_indifferent_access + ] + ) + allow(SystemSettings).to receive(:current).and_return(system_settings) + stub_const('ENV', + ENV.to_hash.merge( + { + 'PRIMERO_PROMOTE_CONFIG_PROD_BASIC_AUTH' => 'random:passwd', + 'PRIMERO_PROMOTE_CONFIG_PROD_HOST' => 'local.net', + 'PRIMERO_PROMOTE_CONFIG_PROD_PORT' => '443', + 'PRIMERO_PROMOTE_CONFIG_PROD_TLS' => 'true' + } + )) + end + + describe '.build_connectors' do + it 'return an array of PrimeroConfigurationConnector' do + result = ApiConnector::PrimeroConfigurationConnector.build_connectors(prefix: 'PRIMERO_PROMOTE_CONFIG_PROD_') + expect(result.map(&:class)).to match_array([ApiConnector::PrimeroConfigurationConnector, + ApiConnector::PrimeroConfigurationConnector]) + end + end + + describe '.config_connectors' do + it 'array should include only valid config' do + result = ApiConnector::PrimeroConfigurationConnector.config_connectors(prefix: 'PRIMERO_PROMOTE_CONFIG_PROD_') + expect(result.map { |hash| hash['host'] }).not_to include('some.url') + expect(result.map { |hash| hash['basic_auth'] }).to match_array(['random:passwd', 'random:passwd']) + end + end + + describe '.hosts_config' do + it 'return only host with basic_auth' do + result = ApiConnector::PrimeroConfigurationConnector.hosts_config(prefix: 'PRIMERO_PROMOTE_CONFIG_PROD_') + expect(result.map { |hash| hash['host'] }).to match_array(['foo.bar', 'local.net', 'some.url']) + end + end + + describe '.config_connector_from_env' do + it 'return a hash from ENV' do + result = ApiConnector::PrimeroConfigurationConnector.config_connector_from_env( + prefix: 'PRIMERO_PROMOTE_CONFIG_PROD_' + ) + expected_hash = { 'host' => 'local.net', 'tls' => 'true', 'basic_auth' => 'random:passwd', 'port' => '443' } + + expect(result).to contain_exactly(expected_hash) + end + end + end end diff --git a/spec/services/api_connector/webhook_connector_spec.rb b/spec/services/api_connector/webhook_connector_spec.rb index 4802ebf4d5..8c041a0efa 100644 --- a/spec/services/api_connector/webhook_connector_spec.rb +++ b/spec/services/api_connector/webhook_connector_spec.rb @@ -5,7 +5,22 @@ require 'rails_helper' describe ApiConnector::WebhookConnector do - before(:each) { clean_data(Role, Field, FormSection, PrimeroModule, AuditLog) } + before(:each) do + clean_data(Role, Field, FormSection, PrimeroModule, AuditLog) + + primero_module + end + + let(:primero_module) do + PrimeroModule.create!( + unique_id: PrimeroModule::CP, + name: 'Primero Module CP', + associated_record_types: %w[case], + roles: [role], + form_sections: [form] + ) + end + let(:form) do FormSection.create!( unique_id: 'test_form_abc', parent_form: 'case', name_en: 'Basic Identity', @@ -16,6 +31,7 @@ ] ) end + let(:role) do Role.create!( name: 'Test Role 1', @@ -34,7 +50,11 @@ 'webhook_url' => url ) end - let(:record) { Child.new(data: { name: 'Test', age: 12, sex: 'female', protection_concerns: %w[a b c] }) } + let(:record) do + Child.new( + data: { name: 'Test', age: 12, sex: 'female', protection_concerns: %w[a b c], module_id: 'primeromodule-cp' } + ) + end # test creation/initializer parsing the webhook url correctly, setting role ,etc describe 'initialization' do diff --git a/spec/services/associated_records_service_spec.rb b/spec/services/associated_records_service_spec.rb index aa4b446a40..a6259871e9 100644 --- a/spec/services/associated_records_service_spec.rb +++ b/spec/services/associated_records_service_spec.rb @@ -29,7 +29,6 @@ @child3 = Child.new_with_user(@current_user, name: 'Child 3') @incident1 = Incident.new_with_user(@current_user, short_id: 'a1b2c3', assigned_user_names: [@associated_user.user_name]) [@child1, @child2, @child3, @incident1].each(&:save!) - Sunspot.commit end it 'should update the associated_user_groups of the records' do @@ -72,7 +71,6 @@ @child2 = Child.new_with_user(@current_user, name: 'Child 2', assigned_user_names: [@associated_user.user_name]) @child3 = Child.new_with_user(@current_user, name: 'Child 3') [@child1, @child2, @child3].each(&:save!) - Sunspot.commit end it 'should update the associated_user_agencies of the records' do diff --git a/spec/models/concerns/auto_populatable_spec.rb b/spec/services/auto_populate_service_spec.rb similarity index 71% rename from spec/models/concerns/auto_populatable_spec.rb rename to spec/services/auto_populate_service_spec.rb index ea71e71b50..e93841b430 100644 --- a/spec/models/concerns/auto_populatable_spec.rb +++ b/spec/services/auto_populate_service_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe AutoPopulatable do +describe AutoPopulateService do context 'when auto_populate_list is present' do before do SystemSettings.all.each(&:destroy) @@ -36,19 +36,19 @@ context 'and SystemSettings is passed in' do context 'and separator is populated with a space' do it 'generates the auto populate field' do - expect(@t1.auto_populate('name', @system_settings)).to eq('Jim Bob Smith') + expect(AutoPopulateService.auto_populate(@t1, 'name', @system_settings)).to eq('Jim Bob Smith') end end context 'and separator is populated with a dash' do it 'generates the auto populate field' do - expect(@t1.auto_populate('id_code', @system_settings)).to eq('Smith-Abc-Def-Ghi') + expect(AutoPopulateService.auto_populate(@t1, 'id_code', @system_settings)).to eq('Smith-Abc-Def-Ghi') end end context 'and separator is not populated' do it 'generates the auto populate field' do - expect(@t1.auto_populate('no_separator', @system_settings)).to eq('JimBobSmithAbc') + expect(AutoPopulateService.auto_populate(@t1, 'no_separator', @system_settings)).to eq('JimBobSmithAbc') end end end @@ -56,19 +56,19 @@ context 'and SystemSettings is not passed in' do context 'and separator is populated with a space' do it 'generates the auto populate field' do - expect(@t1.auto_populate('name')).to eq('Jim Bob Smith') + expect(AutoPopulateService.auto_populate(@t1, 'name')).to eq('Jim Bob Smith') end end context 'and separator is populated with a dash' do it 'generates the auto populate field' do - expect(@t1.auto_populate('id_code')).to eq('Smith-Abc-Def-Ghi') + expect(AutoPopulateService.auto_populate(@t1, 'id_code')).to eq('Smith-Abc-Def-Ghi') end end context 'and separator is not populated' do it 'generates the auto populate field' do - expect(@t1.auto_populate('no_separator')).to eq('JimBobSmithAbc') + expect(AutoPopulateService.auto_populate(@t1, 'no_separator')).to eq('JimBobSmithAbc') end end end @@ -83,19 +83,19 @@ context 'and SystemSettings is passed in' do context 'and separator is populated with a space' do it 'generates the auto populate field' do - expect(@t1.auto_populate('name', @system_settings)).to eq('Jim Smith') + expect(AutoPopulateService.auto_populate(@t1, 'name', @system_settings)).to eq('Jim Smith') end end context 'and separator is populated with a dash' do it 'generates the auto populate field' do - expect(@t1.auto_populate('id_code', @system_settings)).to eq('Smith-Abc-Ghi') + expect(AutoPopulateService.auto_populate(@t1, 'id_code', @system_settings)).to eq('Smith-Abc-Ghi') end end context 'and separator is not populated' do it 'generates the auto populate field' do - expect(@t1.auto_populate('no_separator', @system_settings)).to eq('JimSmithAbc') + expect(AutoPopulateService.auto_populate(@t1, 'no_separator', @system_settings)).to eq('JimSmithAbc') end end end @@ -103,19 +103,19 @@ context 'and SystemSettings is not passed in' do context 'and separator is populated with a space' do it 'generates the auto populate field' do - expect(@t1.auto_populate('name')).to eq('Jim Smith') + expect(AutoPopulateService.auto_populate(@t1, 'name')).to eq('Jim Smith') end end context 'and separator is populated with a dash' do it 'generates the auto populate field' do - expect(@t1.auto_populate('id_code')).to eq('Smith-Abc-Ghi') + expect(AutoPopulateService.auto_populate(@t1, 'id_code')).to eq('Smith-Abc-Ghi') end end context 'and separator is not populated' do it 'generates the auto populate field' do - expect(@t1.auto_populate('no_separator')).to eq('JimSmithAbc') + expect(AutoPopulateService.auto_populate(@t1, 'no_separator')).to eq('JimSmithAbc') end end end @@ -129,19 +129,19 @@ context 'and SystemSettings is passed in' do context 'and separator is populated with a space' do it 'generates the auto populate field' do - expect(@t1.auto_populate('name', @system_settings)).to eq('Smith') + expect(AutoPopulateService.auto_populate(@t1, 'name', @system_settings)).to eq('Smith') end end context 'and separator is populated with a dash' do it 'generates the auto populate field' do - expect(@t1.auto_populate('id_code', @system_settings)).to eq('Smith') + expect(AutoPopulateService.auto_populate(@t1, 'id_code', @system_settings)).to eq('Smith') end end context 'and separator is not populated' do it 'generates the auto populate field' do - expect(@t1.auto_populate('no_separator', @system_settings)).to eq('Smith') + expect(AutoPopulateService.auto_populate(@t1, 'no_separator', @system_settings)).to eq('Smith') end end end @@ -149,19 +149,19 @@ context 'and SystemSettings is not passed in' do context 'and separator is populated with a space' do it 'generates the auto populate field' do - expect(@t1.auto_populate('name')).to eq('Smith') + expect(AutoPopulateService.auto_populate(@t1, 'name')).to eq('Smith') end end context 'and separator is populated with a dash' do it 'generates the auto populate field' do - expect(@t1.auto_populate('id_code')).to eq('Smith') + expect(AutoPopulateService.auto_populate(@t1, 'id_code')).to eq('Smith') end end context 'and separator is not populated' do it 'generates the auto populate field' do - expect(@t1.auto_populate('no_separator')).to eq('Smith') + expect(AutoPopulateService.auto_populate(@t1, 'no_separator')).to eq('Smith') end end end @@ -175,19 +175,19 @@ context 'and SystemSettings is passed in' do context 'and separator is populated with a space' do it 'generates the auto populate field' do - expect(@t1.auto_populate('name', @system_settings)).to eq('') + expect(AutoPopulateService.auto_populate(@t1, 'name', @system_settings)).to eq('') end end context 'and separator is populated with a dash' do it 'generates the auto populate field' do - expect(@t1.auto_populate('id_code', @system_settings)).to eq('') + expect(AutoPopulateService.auto_populate(@t1, 'id_code', @system_settings)).to eq('') end end context 'and separator is not populated' do it 'generates the auto populate field' do - expect(@t1.auto_populate('no_separator', @system_settings)).to eq('') + expect(AutoPopulateService.auto_populate(@t1, 'no_separator', @system_settings)).to eq('') end end end @@ -195,19 +195,19 @@ context 'and SystemSettings is not passed in' do context 'and separator is populated with a space' do it 'generates the auto populate field' do - expect(@t1.auto_populate('name')).to eq('') + expect(AutoPopulateService.auto_populate(@t1, 'name')).to eq('') end end context 'and separator is populated with a dash' do it 'generates the auto populate field' do - expect(@t1.auto_populate('id_code')).to eq('') + expect(AutoPopulateService.auto_populate(@t1, 'id_code')).to eq('') end end context 'and separator is not populated' do it 'generates the auto populate field' do - expect(@t1.auto_populate('no_separator')).to eq('') + expect(AutoPopulateService.auto_populate(@t1, 'no_separator')).to eq('') end end end @@ -222,13 +222,13 @@ context 'and SystemSettings is passed in' do it 'returns nil' do - expect(@t1.auto_populate('no_code', @system_settings)).to be_nil + expect(AutoPopulateService.auto_populate(@t1, 'no_code', @system_settings)).to be_nil end end context 'and SystemSettings is not passed in' do it 'returns nil' do - expect(@t1.auto_populate('no_code')).to be_nil + expect(AutoPopulateService.auto_populate(@t1, 'no_code')).to be_nil end end end @@ -239,10 +239,10 @@ end context 'when auto_populate_list is nil' do - before do - SystemSettings.all.each(&:destroy) + let(:empty_system_settings) { SystemSettings.create(default_locale: 'en') } - @system_settings = SystemSettings.create(default_locale: 'en') + before :each do + SystemSettings.destroy_all @t1 = Child.new(data: { name_first: 'Jim', name_middle: 'Bob', name_last: 'Smith', code_1: 'Abc', code_2: 'Def', code_3: 'Ghi' }) @@ -250,13 +250,13 @@ context 'and SystemSettings is passed in' do it 'returns nil' do - expect(@t1.auto_populate('name', @system_settings)).to be_nil + expect(AutoPopulateService.auto_populate(@t1, 'name', empty_system_settings)).to be_nil end end context 'and SystemSettings is not passed in' do it 'returns nil' do - expect(@t1.auto_populate('name')).to be_nil + expect(AutoPopulateService.auto_populate(@t1, 'name')).to be_nil end end end diff --git a/spec/services/bulk_assign_service_spec.rb b/spec/services/bulk_assign_service_spec.rb index a1800fc968..3bb1abd8ec 100644 --- a/spec/services/bulk_assign_service_spec.rb +++ b/spec/services/bulk_assign_service_spec.rb @@ -28,17 +28,17 @@ end let!(:child) do - create(:child, name: 'Test', owned_by: user.user_name, consent_for_services: true, + create(:child, name: 'Test', sex: 'female', owned_by: user.user_name, consent_for_services: true, disclosure_other_orgs: true, module_id: PrimeroModule::CP) end let!(:child2) do - create(:child, name: 'Test2', owned_by: user.user_name, consent_for_services: true, + create(:child, name: 'Test2', sex: 'male', owned_by: user.user_name, consent_for_services: true, disclosure_other_orgs: true, module_id: PrimeroModule::CP) end let!(:child3) do - create(:child, name: 'Test2', owned_by: user.user_name, consent_for_services: true, + create(:child, name: 'Test2', sex: 'female', owned_by: user.user_name, consent_for_services: true, disclosure_other_orgs: true, module_id: PrimeroModule::CP) end @@ -69,36 +69,51 @@ end context 'when model_class is Child' do - let(:bulk_assign_params) do - { - filters: { short_id: [child.short_id, child2.short_id, child3.short_id] } - }.merge(bulk_assign_shared_params) - end - before :each do - BulkAssignService.any_instance.stub(:search_results_ids).and_return([child.id, child2.id, child3.id]) - end + context 'when filter by id' do + let(:bulk_assign_params) do + { + filters: { 'id' => [child.id, child2.id, child3.id] } + }.merge(bulk_assign_shared_params) + end - it 'creates an Transition record' do - BulkAssignService.new(Child, user, **bulk_assign_params).assign_records! - expect(Assign.count).to eq(3) - assigns = Transition.all - expect(assigns.pluck(:type).uniq).to eq(['Assign']) - expect(assigns.pluck(:record_id)).to match_array([child.id, child2.id, child3.id]) - end + it 'creates an Transition record' do + BulkAssignService.new(Child, user, **bulk_assign_params).assign_records! + expect(Assign.count).to eq(3) + assigns = Transition.all + expect(assigns.pluck(:type).uniq).to eq(['Assign']) + expect(assigns.pluck(:record_id)).to match_array([child.id, child2.id, child3.id]) + end + + context 'when there is a problem at least one of the record' do + it 'inserts records and handles failures' do + expect(Assign).to receive(:create!).with({ record: child }.merge(bulk_assign_shared_params)) + + expect(Assign).to receive(:create!).with( + { record: child2 }.merge(bulk_assign_shared_params) + ).and_raise(StandardError) - context 'when there is a problem at least one of the record' do - it 'inserts records and handles failures' do - expect(Assign).to receive(:create!).with({ record: child }.merge(bulk_assign_shared_params)) + expect(Assign).to receive(:create!).with({ record: child3 }.merge(bulk_assign_shared_params)) - expect(Assign).to receive(:create!).with( - { record: child2 }.merge(bulk_assign_shared_params) - ).and_raise(StandardError) + expect(Rails.logger).to receive(:error).with(/StandardError/).once - expect(Assign).to receive(:create!).with({ record: child3 }.merge(bulk_assign_shared_params)) + BulkAssignService.new(Child, user, **bulk_assign_params).assign_records! + end + end + end - expect(Rails.logger).to receive(:error).with(/StandardError/).once + context 'when filter by sex' do + let(:bulk_assign_params) do + { + filters: { 'sex' => 'female' } + }.merge(bulk_assign_shared_params) + end + it 'creates an Transition record' do BulkAssignService.new(Child, user, **bulk_assign_params).assign_records! + expect(Assign.count).to eq(2) + assigns = Transition.all + expect(assigns.pluck(:type).uniq).to eq(['Assign']) + expect(assigns.pluck(:record_id)).to match_array([child.id, child3.id]) end end end @@ -106,12 +121,9 @@ context 'when model_class is Incident' do let(:bulk_assign_params) do { - filters: { short_id: [incident.short_id, incident2.short_id, incident3.short_id] } + filters: { 'id' => [incident.id, incident2.id, incident3.id] } }.merge(bulk_assign_shared_params) end - before :each do - BulkAssignService.any_instance.stub(:search_results_ids).and_return([incident.id, incident2.id, incident3.id]) - end it 'creates an Transition record' do BulkAssignService.new(Incident, user, **bulk_assign_params).assign_records! diff --git a/spec/services/data_removal_service_spec.rb b/spec/services/data_removal_service_spec.rb index bf253b5627..a00fdc4b56 100644 --- a/spec/services/data_removal_service_spec.rb +++ b/spec/services/data_removal_service_spec.rb @@ -70,6 +70,7 @@ expect(Alert.all).to be_empty expect(Transition.all).to be_empty expect(Attachment.all).to be_empty + expect(SearchableIdentifier.all).to be_empty expect( ActiveRecord::Base.connection.exec_query('SELECT id FROM active_storage_attachments').to_a ).to be_empty @@ -93,6 +94,7 @@ expect(Alert.all).to be_empty expect(Transition.all).to be_empty expect(Attachment.all.size).to eq(1) + expect(SearchableIdentifier.all.size).to eq(7) end it 'removes records Incidents that meet the filters without deleting the associated cases' do diff --git a/spec/services/duplicated_field_alert_service_spec.rb b/spec/services/duplicated_field_alert_service_spec.rb index 2a2fc80f55..c304c485c8 100644 --- a/spec/services/duplicated_field_alert_service_spec.rb +++ b/spec/services/duplicated_field_alert_service_spec.rb @@ -6,7 +6,7 @@ describe DuplicatedFieldAlertService do before :each do - clean_data(Alert, Child) + clean_data(Alert, Incident, Child) @child1 = Child.create!(data: { id_field: '0001' }) @child2 = Child.create!(data: { id_field: '0001' }) diff --git a/spec/services/family_linkage_service_spec.rb b/spec/services/family_linkage_service_spec.rb index e37a9268a4..5ddf7a2572 100644 --- a/spec/services/family_linkage_service_spec.rb +++ b/spec/services/family_linkage_service_spec.rb @@ -5,7 +5,7 @@ require 'rails_helper' describe FamilyLinkageService do - before(:each) { clean_data(User, Child, Family) } + before(:each) { clean_data(User, Incident, Child, Family) } let(:user) do user = User.new(user_name: 'user_cp', full_name: 'Test User CP') diff --git a/spec/services/health_check_service_spec.rb b/spec/services/health_check_service_spec.rb index 36f07f1b0c..97771fb150 100644 --- a/spec/services/health_check_service_spec.rb +++ b/spec/services/health_check_service_spec.rb @@ -17,7 +17,7 @@ end end - describe '.solr_accessible?', search: true do + describe '.solr_accessible?', { search: true, skip_when_solr_disabled: true } do it 'returns true if Solr is connected' do expect(HealthCheckService.solr_accessible?).to be_truthy end diff --git a/spec/services/indicator_query_service_spec.rb b/spec/services/indicator_query_service_spec.rb index 7819b1e611..a33211669f 100644 --- a/spec/services/indicator_query_service_spec.rb +++ b/spec/services/indicator_query_service_spec.rb @@ -27,10 +27,11 @@ @baz = User.new(user_name: 'baz', role: role_self, user_groups: [group2]) @baz.save(validate: false) + # TODO: Add back indicators once the pivoted/faceted indicators are migrated to SQL @indicators = - Dashboard::CASE_OVERVIEW.indicators + - Dashboard::WORKFLOW.indicators + - Dashboard::WORKFLOW_TEAM.indicators + Dashboard::CASE_OVERVIEW.indicators # + + # Dashboard::WORKFLOW.indicators + + # Dashboard::WORKFLOW_TEAM.indicators Child.create!( data: { @@ -66,8 +67,6 @@ ) Child.create!(data: { record_state: true, status: 'open', owned_by: 'baz', workflow: 'new' }) Child.create!(data: { record_state: true, status: 'closed', owned_by: 'baz', workflow: 'closed' }) - - Sunspot.commit end describe 'individual user scope' do @@ -93,13 +92,13 @@ expect(stats['case']['new_or_updated']['new_or_updated']['query']).to match_array(expected_query) end - it 'shows the workflows breakdown' do + xit 'shows the workflows breakdown' do expect(stats['case']['workflow']['new']['count']).to eq(1) expect(stats['case']['workflow']['assessment']['count']).to eq(1) expect(stats['case']['workflow']['closed']['count']).to eq(3) end - it 'shows the string queries to get the workflow breakdown' do + xit 'shows the string queries to get the workflow breakdown' do expected_query_new = %w[record_state=true status=open,closed owned_by=foo workflow=new] expect(stats['case']['workflow']['new']['query']).to match_array(expected_query_new) expected_query_assessment = %w[record_state=true status=open,closed owned_by=foo workflow=assessment] @@ -107,7 +106,7 @@ end end - describe 'team user scope' do + xdescribe 'team user scope' do let(:stats) do IndicatorQueryService.query(@indicators, @bar) end @@ -171,6 +170,5 @@ after :each do clean_data(User, UserGroup, Role, Child, SystemSettings) - Sunspot.commit end end diff --git a/spec/services/json_validator_service_spec.rb b/spec/services/json_validator_service_spec.rb index 865ae859f9..4221b15de7 100644 --- a/spec/services/json_validator_service_spec.rb +++ b/spec/services/json_validator_service_spec.rb @@ -28,4 +28,47 @@ end.to raise_error(Errors::InvalidRecordJson, 'Invalid Record JSON') end end + + describe '.strong_params' do + let(:schema) do + { + 'type' => 'object', + 'properties' => { + 'id' => { 'type' => 'string', 'format' => 'regex', 'pattern' => '\\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\z' }, + "status"=>{"type"=>["string", "null"]}, + "name"=>{"type"=>["string", "null"]}, + "age"=>{"type"=>["integer", "null"], "minimum"=>-2147483648, "maximum"=>2147483647}, + "sex"=>{"type"=>["string", "null"]}, + "protection_concerns"=>{"type"=>["array", "null"], "items"=>{"type"=>"string"}}, + "registration_date"=>{"type"=>["date", "string", "null"], "format"=>"date"}, + "family_details_section" => { + 'type' => ['array', 'null'], + 'items' => { + 'type' => 'object', + 'properties' => { + "relation_name"=>{"type"=>["string", "null"]}, + "relation"=>{"type"=>["string", "null"]}, + "relation_type"=>{"type"=>["string", "null"]}, + "relation_age"=>{"type"=>["integer", "null"], "minimum"=>-2147483648, "maximum"=>2147483647}, + "relation_is_caregiver"=>{"type"=>["boolean"]}, + "_destroy"=>{"type"=>["boolean", "null"]}, + "unique_id"=>{"type"=>"string", "format"=>"regex", "pattern"=>"\\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\z"} + }, + "additionalProperties"=>false} + } + }, + 'additionalProperties' => false + } + end + let(:service) { RecordJsonValidatorService.new(schema:) } + let(:strong_params) { service.strong_params } + + it 'converts the json schema into a string parameters hash' do + expect(strong_params).to include(:id, :status, :name, :age, :sex, :registration_date) + expect(strong_params).to include({ protection_concerns: [] }) + expect(strong_params).to include( + { family_details_section: [:relation_name, :relation, :relation_type, :relation_age, :relation_is_caregiver, :_destroy, :unique_id] } + ) + end + end end diff --git a/spec/services/language_service_spec.rb b/spec/services/language_service_spec.rb new file mode 100644 index 0000000000..79dc1567c0 --- /dev/null +++ b/spec/services/language_service_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +require 'rails_helper' + +describe LanguageService do + describe 'strip_arabic_vowels' do + it 'strips the vowels in arabic strings' do + expect( + ['فَتَحَ', 'أصلاً', 'عُنف', 'طفلٌ', 'مِلف', 'راح إلى محطةٍ', 'احْمد', 'محمّد'].map do |elem| + LanguageService.strip_arabic_vowels(elem) + end + ).to eq(['فتح', 'أصلا', 'عنف', 'طفل', 'ملف', 'راح إلى محطة', 'احمد', 'محمد']) + end + end + + describe 'when values include an integer' do + it 'should skip integer values' do + expect( + [0, 1, 'sample'].map do |elem| + LanguageService.tokenize(elem).uniq + end + ).to match_array([[], [], ['SMPL']]) + end + end +end diff --git a/spec/services/matching_service_spec.rb b/spec/services/matching_service_spec.rb index 859e4b853a..a9c2118443 100644 --- a/spec/services/matching_service_spec.rb +++ b/spec/services/matching_service_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' -describe MatchingService, search: true do +describe MatchingService, { search: true, skip_when_solr_disabled: true } do before(:each) { clean_data(Trace, TracingRequest, Child) } let(:tracing_request1) do diff --git a/spec/services/permitted_attachment_service_spec.rb b/spec/services/permitted_attachment_service_spec.rb index 72c7cdb64c..0c0bde626b 100644 --- a/spec/services/permitted_attachment_service_spec.rb +++ b/spec/services/permitted_attachment_service_spec.rb @@ -5,11 +5,21 @@ require 'rails_helper' describe PermittedAttachmentService, search: true do + let(:primero_module) do + PrimeroModule.create!( + unique_id: PrimeroModule::CP, + name: 'Primero Module CP', + associated_record_types: %w[case], + roles: [role_with_write_form_permission, role_with_read_form_permission], + form_sections: + ) + end + let(:form_sections) do [ FormSection.create!( unique_id: 'form1', name: 'Form 1', parent_form: 'case', form_group_id: 'form1', fields: [ - Field.new(name: Attachable::PHOTOS_FIELD_NAME, display_name: 'Photos') + Field.new(name: Attachable::PHOTOS_FIELD_NAME, display_name: 'Photos', type: Field::PHOTO_UPLOAD_BOX) ] ) ] @@ -19,24 +29,20 @@ let(:role_with_write_form_permission) do role = Role.new_with_properties( - name: 'write_attachment', permissions: [permission], form_section_read_write: { form1: 'rw' } + name: 'write_attachment', permissions: [permission], form_section_read_write: { form_sections.first.unique_id => 'rw' } ) - role.save! - role + role.save! && role end let(:role_with_read_form_permission) do role = Role.new_with_properties( - name: 'read_attachment', permissions: [permission], form_section_read_write: { form1: 'r' } + name: 'read_attachment', permissions: [permission], form_section_read_write: { form_sections.first.unique_id => 'r' } ) - role.save! - role + role.save! && role end let(:role_without_form_permissions) do - role = Role.new_with_properties(name: 'no_attachment', permissions: [permission]) - role.save! - role + Role.new_with_properties(name: 'no_attachment', permissions: [permission]) end let(:user) do @@ -46,13 +52,13 @@ end let(:record_with_access) do - child = Child.new_with_user(user, { name: 'Child 1', age: 5, sex: 'male' }) + child = Child.new_with_user(user, { name: 'Child 1', age: 5, sex: 'male', module_id: PrimeroModule::CP }) child.save! child end let(:record_without_access) do - Child.create!(data: { name: 'Child 2', age: 8, sex: 'female' }) + Child.create!(data: { name: 'Child 2', age: 8, sex: 'female', module_id: PrimeroModule::CP }) end let(:attachment_with_access) do @@ -97,11 +103,8 @@ end before do - clean_data( - User, Role, PrimeroModule, PrimeroProgram, - Child, Field, FormSection, Agency, UserGroup - ) - form_sections + clean_data(PrimeroModule, User, Agency, Role, FormSection, Field, Child) + primero_module end describe '#permitted_to_read?' do @@ -326,9 +329,6 @@ end after do - clean_data( - User, Role, PrimeroModule, PrimeroProgram, - Child, Field, FormSection, Agency, UserGroup - ) + clean_data(PrimeroModule, User, Agency, Role, FormSection, Field, Child) end end diff --git a/spec/services/permitted_field_service_spec.rb b/spec/services/permitted_field_service_spec.rb index 033fb037c1..8b9787de84 100644 --- a/spec/services/permitted_field_service_spec.rb +++ b/spec/services/permitted_field_service_spec.rb @@ -5,6 +5,15 @@ require 'rails_helper' describe PermittedFieldService, search: true do + let(:cp_module) do + PrimeroModule.create!( + primero_program: PrimeroProgram.first, + name: 'CP Module', + unique_id: PrimeroModule::CP, + associated_record_types: %w[case], + form_sections: [form] + ) + end let(:form) { FormSection.create!(unique_id: 'A', name: 'A', parent_form: 'case', form_group_id: 'm') } let(:field) { Field.create!(name: 'test', display_name: 'test', type: Field::TEXT_FIELD, form_section_id: form.id) } let(:role) do @@ -57,6 +66,40 @@ form_section_read_write: { form.unique_id => 'rw' } ) end + + let(:case_risk_dashboard_role) do + Role.new_with_properties( + name: 'Test Role 1', + unique_id: 'test-role-1', + group_permission: Permission::SELF, + permissions: [ + Permission.new(resource: Permission::DASHBOARD, actions: [Permission::DASH_CASE_RISK]) + ] + ) + end + + let(:shared_with_other_dashboard_role) do + Role.new_with_properties( + name: 'Test Role 2', + unique_id: 'test-role-2', + group_permission: Permission::SELF, + permissions: [ + Permission.new(resource: Permission::DASHBOARD, actions: [Permission::DASH_SHARED_WITH_OTHERS]) + ] + ) + end + + let(:shared_from_my_team_dashboard_role) do + Role.new_with_properties( + name: 'Test Role 3', + unique_id: 'test-role-3', + group_permission: Permission::SELF, + permissions: [ + Permission.new(resource: Permission::DASHBOARD, actions: [Permission::DASH_SHARED_FROM_MY_TEAM]) + ] + ) + end + let(:agency) do Agency.create!( name: 'Test Agency', @@ -64,6 +107,7 @@ services: ['Test type'] ) end + let(:user) do User.create!( full_name: 'Test User 1', @@ -103,6 +147,45 @@ ) end + let(:user_with_risk_level) do + User.create!( + full_name: 'User With Risk Level', + user_name: 'user_with_risk_level', + password: 'a12345632', + password_confirmation: 'a12345632', + email: 'test_user_3@localhost.com', + agency_id: agency.id, + role: case_risk_dashboard_role, + services: ['Test type'] + ) + end + + let(:user_with_shared_with_others) do + User.create!( + full_name: 'User With Shared With Others', + user_name: 'user_with_shared_with_others', + password: 'a12345632', + password_confirmation: 'a12345632', + email: 'user_with_shared_with_others@localhost.com', + agency_id: agency.id, + role: shared_with_other_dashboard_role, + services: ['Test type'] + ) + end + + let(:user_with_shared_from_my_team) do + User.create!( + full_name: 'User With Shared From My Team', + user_name: 'user_with_shared_from_my_team', + password: 'a12345632', + password_confirmation: 'a12345632', + email: 'user_with_shared_from_my_team@localhost.com', + agency_id: agency.id, + role: shared_from_my_team_dashboard_role, + services: ['Test type'] + ) + end + let(:system_settings) do SystemSettings.create( default_locale: 'en', @@ -119,9 +202,9 @@ end before(:each) do - clean_data(PrimeroProgram, User, Agency, Role, FormSection, Field, SystemSettings) + clean_data(PrimeroModule, PrimeroProgram, User, Agency, Role, FormSection, Field, SystemSettings) system_settings - form + cp_module field role.save! agency @@ -135,7 +218,7 @@ end it 'returns the formsection permitted' do - permitted_field_names = PermittedFieldService.new(user, Child).permitted_field_names + permitted_field_names = PermittedFieldService.new(user, Child).permitted_field_names('primeromodule-cp') expect(permitted_field_names.include?(field.name)).to be true end @@ -147,7 +230,9 @@ end it 'returns the permitted fields for id_search = true' do - permitted_field_names = PermittedFieldService.new(user, Child, nil, true).permitted_field_names + permitted_field_names = PermittedFieldService.new( + user, Child, nil, { action_name: nil, id_search: true } + ).permitted_field_names expect((PermittedFieldService::ID_SEARCH_FIELDS - permitted_field_names).empty?).to be true end @@ -167,7 +252,7 @@ end it 'does not return id when is an update' do - permitted_field_names = PermittedFieldService.new(user, Child).permitted_field_names(false, true) + permitted_field_names = PermittedFieldService.new(user, Child).permitted_field_names(PrimeroModule::CP, false, true) expect(permitted_field_names.include?('id')).to be false end @@ -178,9 +263,7 @@ permitted_reporting_location_field = PermittedFieldService.new(user, Child).permitted_reporting_location_field.first reporting_location_config = system_settings.reporting_location_config - expect(permitted_reporting_location_field).to eq( - "#{reporting_location_config.field_key}#{reporting_location_config.admin_level}" - ) + expect(permitted_reporting_location_field).to eq(reporting_location_config.field_key) end it 'returns the reporting_location field permitted for a role with a reporting_location_level set' do @@ -205,32 +288,51 @@ agency_id: agency.id, role: role_with_reporting_location ) - permitted_reporting_location_field = PermittedFieldService.new(user_with_reporting_location, Child) - .permitted_reporting_location_field.first + permitted_reporting_location_field = PermittedFieldService.new( + user_with_reporting_location, Child + ).permitted_reporting_location_field.first reporting_location_config = system_settings.reporting_location_config - expect(permitted_reporting_location_field).to eq( - "#{reporting_location_config.field_key}#{role_with_reporting_location.reporting_location_level}" - ) + expect(permitted_reporting_location_field).to eq(reporting_location_config.field_key) + end + + it 'return the risk_level field permitted for a role with a case_risk permission in dashboard' do + permitted_field_names = PermittedFieldService.new(user_with_risk_level, Child).permitted_field_names + + expect(permitted_field_names).to include('risk_level') + end + + it 'returns the transfer_status field permitted for a role with a shared_with_other permission in dashboard' do + permitted_field_names = PermittedFieldService.new(user_with_shared_with_others, Child).permitted_field_names + + expect(permitted_field_names).to include('transfer_status') + end + + it 'returns the transfer_status field permitted for a role with a shared_from_my_team permission in dashboard' do + permitted_field_names = PermittedFieldService.new(user_with_shared_from_my_team, Child).permitted_field_names + + expect(permitted_field_names).to include('transfer_status') end describe 'MRM - Vioaltions forms and fields' do - let(:mrm_form) { FormSection.create!(unique_id: 'A', name: 'A', parent_form: 'incident', form_group_id: 'm') } + let(:mrm_form) do + FormSection.create!(unique_id: 'A', name: 'A', parent_form: 'incident', form_group_id: 'm', fields: [mrm_field]) + end let(:mrm_module) do PrimeroModule.create!( primero_program: PrimeroProgram.first, name: 'MRM Module', unique_id: PrimeroModule::MRM, associated_record_types: ['incident'], - form_sections: [mrm_form] + form_sections: [mrm_form], + roles: [mrm_role] ) end let(:mrm_field) do Field.create!( name: 'mrm_field', display_name: 'mrm field', - type: Field::TALLY_FIELD, - form_section_id: mrm_form.id + type: Field::TALLY_FIELD ) end let(:mrm_role) do @@ -238,7 +340,6 @@ name: 'Test Role 1', unique_id: 'test-role-1', group_permission: Permission::SELF, - modules: [mrm_module], permissions: [ Permission.new( resource: Permission::INCIDENT, @@ -268,21 +369,15 @@ end before(:each) do clean_data(PrimeroModule, User, Agency, Role, FormSection, Field, SystemSettings) - mrm_module mrm_form - mrm_field mrm_role.save! + mrm_module mrm_user end it 'returns Violations fields if user has permission' do - permitted_field_names = PermittedFieldService.new(mrm_user, Incident).permitted_field_names + permitted_field_names = PermittedFieldService.new(mrm_user, Incident).permitted_field_names(PrimeroModule::MRM) expect(permitted_field_names.include?('mrm_field')).to be true end - - it 'return a field schema for tally fields' do - permitted_fields_schema = PermittedFieldService.new(mrm_user, Incident).permitted_fields_schema - expect((Violation::TYPES + Violation::MRM_ASSOCIATIONS_KEYS) - permitted_fields_schema.keys).to be_empty - end end describe 'Permitted Fields for Multiple Roles' do @@ -364,7 +459,7 @@ it 'returns the permitted fields for the roles' do permitted_field_names = PermittedFieldService.new(test_user, Child).permitted_field_names( - false, false, [role_a, role_b] + PrimeroModule::CP, false, false, [role_a, role_b] ) expect(permitted_field_names).to include('field_a', 'field_b') diff --git a/spec/services/permitted_form_fields_service_spec.rb b/spec/services/permitted_form_fields_service_spec.rb index 7924908d9c..2679fa92d3 100644 --- a/spec/services/permitted_form_fields_service_spec.rb +++ b/spec/services/permitted_form_fields_service_spec.rb @@ -10,7 +10,14 @@ end let!(:form_section1) do - FormSection.create( + family_details = FormSection.create!( + unique_id: 'family_details', parent_form: 'case', name_en: 'family_details', is_nested: true, + fields: [ + Field.new(name: 'relation_name', type: Field::TEXT_FIELD, display_name_en: 'A'), + Field.new(name: 'relation_type', type: Field::SELECT_BOX, display_name_en: 'A') + ] + ) + FormSection.create!( unique_id: 'form_section1', parent_form: 'case', name_en: 'form_section1', fields: [ Field.new(name: 'name', type: Field::TEXT_FIELD, display_name_en: 'A'), @@ -28,20 +35,15 @@ name: 'family_details', display_name_en: 'A', type: Field::SUBFORM, - subform: FormSection.new( - fields: [ - Field.new(name: 'relation_name', type: Field::TEXT_FIELD), - Field.new(name: 'relation_type', type: Field::SELECT_BOX) - ] - ) + subform: family_details ) ] ) end let!(:form_section2) do - FormSection.create( - unique_id: 'form_section2', parent_form: 'case', name_en: 'form_section2', + FormSection.create!( + unique_id: 'form_section2', parent_form: 'case', name_en: 'form_section2', is_nested: true, fields: [ Field.new(name: 'interview_date', type: Field::DATE_FIELD, display_name_en: 'A'), Field.new(name: 'consent_for_referral', type: Field::TICK_BOX, display_name_en: 'A') @@ -50,7 +52,7 @@ end let!(:form_section3) do - FormSection.create( + FormSection.create!( unique_id: 'form_section3', parent_form: 'case', name_en: 'form_section3', fields: [ Field.new(name: 'interview_date3', type: Field::DATE_FIELD, display_name_en: 'A'), @@ -59,6 +61,174 @@ ) end + let!(:form_section4) do + notes_section = FormSection.create!( + unique_id: 'notes_section', parent_form: 'case', name_en: 'notes_section', is_nested: true, + fields: [ + Field.new(name: 'note_field', type: Field::TEXT_FIELD, display_name_en: 'A'), + Field.new(name: 'separator2', type: Field::SEPARATOR, display_name_en: 'A') + ] + ) + FormSection.create!( + unique_id: 'form_section4', parent_form: 'case', name_en: 'form_section4', + fields: [ + Field.new( + name: 'notes_section', + display_name_en: 'A', + type: Field::SUBFORM, + subform: notes_section + ) + ] + ) + end + + let!(:form_section5) do + services_section = FormSection.create!( + unique_id: 'services_section', parent_form: 'case', name_en: 'services_section', is_nested: true, + fields: [ + Field.new(name: 'service_description', type: Field::TEXT_FIELD, display_name_en: 'A'), + Field.new(name: 'separator3', type: Field::SEPARATOR, display_name_en: 'A') + ] + ) + FormSection.create( + unique_id: 'form_section5', parent_form: 'case', name_en: 'form_section5', + fields: [ + Field.new( + name: 'services_section', + display_name_en: 'A', + type: Field::SUBFORM, + subform: services_section + ) + ] + ) + end + + let!(:form_section_mrm) do + killing_form = FormSection.create!( + unique_id: 'killing', parent_form: 'incident', name_en: 'family_details', is_nested: true, + fields: [ + Field.new(name: 'description_text', type: Field::TEXT_FIELD, display_name_en: 'B'), + Field.new(name: 'violation_tally', type: Field::SELECT_BOX, display_name_en: 'C', + tally_en: [ + { 'id' => 'boys', 'display_text' => 'Boys' }, + { 'id' => 'girls', 'display_text' => 'Girls' }, + { 'id' => 'unknown', 'display_text' => 'Unknown' } + ]) + ] + ) + FormSection.create!( + unique_id: 'form_section6', parent_form: 'incident', name_en: 'form_section1', + fields: [ + Field.new(name: 'another_field', type: Field::TEXT_FIELD, display_name_en: 'A'), + Field.new( + name: 'killing', + display_name_en: 'killing_form', + type: Field::SUBFORM, + subform: killing_form + ) + ] + ) + end + + let!(:form_section7) do + notes_section = FormSection.create!( + unique_id: 'form_7_notes_section', parent_form: 'incident', name_en: 'notes_section', is_nested: true, + fields: [ + Field.new(name: 'note_field', type: Field::TEXT_FIELD, display_name_en: 'A'), + Field.new(name: 'separator2', type: Field::SEPARATOR, display_name_en: 'A') + ] + ) + FormSection.create!( + unique_id: 'form_section7', parent_form: 'incident', name_en: 'form_section7', + fields: [ + Field.new( + name: 'notes_section', + display_name_en: 'A', + type: Field::SUBFORM, + subform: notes_section + ) + ] + ) + end + + let!(:notes_section_cp) do + notes_section_subform = FormSection.create!( + unique_id: 'notes_section_subform_cp', parent_form: 'case', name_en: 'notes_section', is_nested: true, + fields: [ + Field.new(name: 'name', type: Field::TEXT_FIELD, display_name_en: 'Name'), + Field.new(name: 'comment', type: Field::TEXT_FIELD, display_name_en: 'Comment') + ] + ) + FormSection.create( + unique_id: 'notes_section_cp', parent_form: 'case', name_en: 'notes_section', + fields: [ + Field.new( + name: 'notes_section', + display_name_en: 'Pets Section Field', + type: Field::SUBFORM, + subform: notes_section_subform + ) + ] + ) + end + + let!(:notes_section_gbv) do + notes_section_subform = FormSection.create!( + unique_id: 'notes_section_subform_gbv', parent_form: 'case', name_en: 'notes_section', is_nested: true, + fields: [ + Field.new(name: 'name', type: Field::TEXT_FIELD, display_name_en: 'Name'), + Field.new(name: 'age', type: Field::NUMERIC_FIELD, display_name_en: 'Age') + ] + ) + FormSection.create( + unique_id: 'notes_section_gbv', parent_form: 'case', name_en: 'notes_section_gbv', + fields: [ + Field.new( + name: 'notes_section', + display_name_en: 'Notes Section Field', + type: Field::SUBFORM, + subform: notes_section_subform + ) + ] + ) + end + + let!(:primero_module) do + PrimeroModule.create!( + unique_id: 'primeromodule-cpa', name: 'CPA', description: 'Child Protection A', + associated_record_types: %w[case tracing_request incident], + primero_program: PrimeroProgram.new(name: 'program'), + form_sections: [form_section1, form_section2, form_section3, form_section4, form_section5, form_section7] + ) + end + + let!(:primero_module_mrm) do + PrimeroModule.create!( + unique_id: 'primeromodule-mrm', name: 'MRM', description: 'MRM', + associated_record_types: %w[incident], + primero_program: PrimeroProgram.new(name: 'program'), + form_sections: [form_section_mrm] + ) + end + + let!(:primero_module_cp) do + PrimeroModule.create!( + unique_id: 'primeromodule-cp', name: 'CP', description: 'Child Protection', + associated_record_types: %w[case], + primero_program: PrimeroProgram.new(name: 'program'), + form_sections: [notes_section_cp] + ) + end + + let!(:primero_module_gbv) do + PrimeroModule.create!( + unique_id: 'primeromodule-gbv', name: 'GBV', description: 'Gender Violence', + associated_record_types: %w[case], + primero_program: PrimeroProgram.new(name: 'program'), + form_sections: [notes_section_gbv] + ) + end + let!(:role) do Role.create( unique_id: 'role_test_01', @@ -66,52 +236,192 @@ description: 'description_test_01', group_permission: 'all', permissions: [ - Permission.new(resource: Permission::USER, actions: [Permission::READ, Permission::WRITE, Permission::CREATE]) + Permission.new(resource: Permission::CASE, actions: [Permission::READ, Permission::WRITE, Permission::CREATE]) ], form_permissions: [ FormPermission.new(form_section: form_section1, permission: FormPermission::PERMISSIONS[:read_write]), FormPermission.new(form_section: form_section2, permission: FormPermission::PERMISSIONS[:read]) ], - modules: [ - PrimeroModule.new( - unique_id: 'primeromodule-cp-a', name: 'CPA', description: 'Child Protection A', - associated_record_types: %w[case tracing_request incident], - primero_program: PrimeroProgram.new(name: 'program'), - form_sections: [form_section1, form_section2] + modules: [primero_module] + ) + end + + let!(:role_with_notes) do + Role.create( + unique_id: 'role_test_01', + name: 'name_test_01', + description: 'description_test_01', + group_permission: 'all', + permissions: [ + Permission.new( + resource: Permission::CASE, + actions: [Permission::READ, Permission::WRITE, Permission::CREATE, Permission::ADD_NOTE] + ) + ], + form_permissions: [ + FormPermission.new(form_section: form_section7, permission: FormPermission::PERMISSIONS[:read_write]) + ], + modules: [primero_module] + ) + end + + let!(:role_with_actions) do + Role.create( + unique_id: 'role_test_02', + name: 'name_test_02', + description: 'description_test_02', + group_permission: 'all', + permissions: [ + Permission.new( + resource: Permission::CASE, + actions: [ + Permission::READ, Permission::WRITE, Permission::CREATE, Permission::ADD_NOTE, + Permission::SERVICES_SECTION_FROM_CASE + ] ) - ] + ], + form_permissions: [ + FormPermission.new(form_section: form_section1, permission: FormPermission::PERMISSIONS[:read_write]), + FormPermission.new(form_section: form_section2, permission: FormPermission::PERMISSIONS[:read]) + ], + modules: [primero_module] + ) + end + + let!(:role_mrm) do + Role.create( + unique_id: 'role_test_03', + name: 'name_test_03', + description: 'description_test_03', + group_permission: 'all', + permissions: [ + Permission.new( + resource: Permission::INCIDENT, + actions: [ + Permission::READ, Permission::WRITE, Permission::CREATE + ] + ) + ], + form_permissions: [ + FormPermission.new(form_section: form_section_mrm, permission: FormPermission::PERMISSIONS[:read_write]) + ], + modules: [primero_module_mrm] ) end let(:service) { PermittedFormFieldsService.new } + let(:role_cp) do + Role.create( + unique_id: 'role_test_cp', + name: 'name_test_cp', + description: 'description_test_cp', + group_permission: 'all', + permissions: [ + Permission.new( + resource: Permission::CASE, + actions: [ + Permission::READ, Permission::WRITE, Permission::CREATE, Permission::ADD_NOTE + ] + ) + ], + form_permissions: [ + FormPermission.new(form_section: notes_section_cp, permission: FormPermission::PERMISSIONS[:read_write]) + ], + modules: [primero_module_cp] + ) + end + + let!(:role_gbv) do + Role.create( + unique_id: 'role_test_gbv', + name: 'name_test_gbv', + description: 'description_test_gbv', + group_permission: 'all', + permissions: [ + Permission.new( + resource: Permission::CASE, + actions: [ + Permission::READ, Permission::WRITE, Permission::CREATE, Permission::ADD_NOTE + ] + ) + ], + form_permissions: [ + FormPermission.new(form_section: notes_section_gbv, permission: FormPermission::PERMISSIONS[:read_write]) + ], + modules: [primero_module_gbv] + ) + end + describe '#permitted_fields' do it 'lists all writeable fields' do - permitted_fields = service.permitted_fields(role, 'case', true) - expect(permitted_fields.size).to eq(12) + permitted_fields = service.permitted_fields(role, 'case', 'primeromodule-cpa', true) + expect(permitted_fields.size).to eq(11) expect(permitted_fields.map(&:name)).to match_array( %w[name age sex national_id_no consent_for_services current_address protection_concerns - registration_date created_on separator1 other_documents family_details] + registration_date created_on family_details other_documents] ) end it 'lists all readable fields' do - permitted_fields = service.permitted_fields(role, 'case', false) + permitted_fields = service.permitted_fields(role, 'case', 'primeromodule-cpa', false) expect(permitted_fields.size).to eq(14) expect(permitted_fields.map(&:name)).to match_array( %w[name age sex national_id_no consent_for_services current_address protection_concerns registration_date created_on separator1 other_documents family_details interview_date consent_for_referral] ) end + + it 'includes action subforms when writeable for the module' do + permitted_fields = service.permitted_fields(role_with_actions, 'case', 'primeromodule-cpa', true) + expect(permitted_fields.size).to eq(13) + expect(permitted_fields.map(&:name)).to match_array( + %w[name age sex national_id_no consent_for_services current_address protection_concerns other_documents + registration_date created_on family_details notes_section services_section] + ) + end + + it 'excludes action subforms when readable' do + permitted_fields = service.permitted_fields(role_with_actions, 'case', 'primeromodule-cpa', false) + expect(permitted_fields.size).to eq(14) + expect(permitted_fields.map(&:name)).to_not include(:notes_section, :services_section) + end + + it 'includes mrm subforms when writeable' do + permitted_fields = service.permitted_fields(role_mrm, 'incident', PrimeroModule::MRM, true) + expect(permitted_fields.size).to eq(2) + expect(permitted_fields.map(&:name)).to match_array(%w[another_field killing]) + end + + context 'when a user has access to the notes_section field and can add notes' do + it 'returns fields for the specified parent_form and module' do + permitted_fields = service.permitted_fields(role_with_notes, 'case', 'primeromodule-cpa', true) + expect(permitted_fields.size).to eq(1) + expect(permitted_fields.map { |field| field.form_section.parent_form }).to match_array(%w[case]) + expect(permitted_fields.map(&:name)).to match_array(%w[notes_section]) + end + + it 'returns the notes_section fields for the cp module' do + permitted_fields = service.permitted_fields(role_cp, 'case', PrimeroModule::CP, true) + expect(permitted_fields.size).to eq(1) + expect(permitted_fields.first.subform.fields.map(&:name)).to match_array(%w[name comment]) + end + + it 'returns the notes_section fields for the gbv module' do + permitted_fields = service.permitted_fields(role_gbv, 'case', PrimeroModule::GBV, true) + expect(permitted_fields.size).to eq(1) + expect(permitted_fields.first.subform.fields.map(&:name)).to match_array(%w[name age]) + end + end end describe '#permitted_field_names' do it 'lists all writeable field names' do - permitted_field_names = service.permitted_field_names(role, 'case', true) - expect(permitted_field_names.size).to eq(12) + permitted_field_names = service.permitted_field_names(role, 'case', 'primeromodule-cpa', true) + expect(permitted_field_names.size).to eq(11) expect(permitted_field_names).to match_array( %w[name age sex national_id_no consent_for_services current_address protection_concerns - registration_date created_on separator1 other_documents family_details] + registration_date created_on family_details other_documents] ) end end diff --git a/spec/services/phonetic_search_service_spec.rb b/spec/services/phonetic_search_service_spec.rb new file mode 100644 index 0000000000..2938c30238 --- /dev/null +++ b/spec/services/phonetic_search_service_spec.rb @@ -0,0 +1,657 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +require 'rails_helper' + +describe PhoneticSearchService, search: true do + describe 'Filter search' do + describe 'search with text filters' do + let(:record1) { Child.create!(data: { name: 'Record 1', sex: 'female' }) } + let(:record2) { Child.create!(data: { name: 'Record 2', sex: 'male' }) } + let(:record3) { Child.create!(data: { name: 'Record 3' }) } + let(:record4) { Child.create!(data: { name: 'Record 3', sex: nil }) } + + before do + clean_data(SearchableIdentifier, Child) + record1 + record2 + record3 + record4 + end + + it 'matches the filter' do + filter = SearchFilters::TextValue.new(field_name: 'sex', value: 'female') + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record1.name) + end + + it 'matches the list filter' do + filter = SearchFilters::TextList.new(field_name: 'sex', values: %w[male]) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record2.name) + end + + it 'matches the not filter' do + filter = SearchFilters::TextValue.new(field_name: 'sex', value: 'male', not_filter: true) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(3) + expect(search.records.map(&:name)).to match_array([record1.name, record3.name, record4.name]) + end + + it 'matches the not filter for a list' do + filter = SearchFilters::TextList.new(field_name: 'sex', values: %w[male], not_filter: true) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(3) + expect(search.records.map(&:name)).to match_array([record1.name, record3.name, record4.name]) + end + end + + describe 'searches with boolean filters' do + let(:record1) { Child.create!(data: { name: 'Record 1', urgent_protection_concern: true }) } + let(:record2) { Child.create!(data: { name: 'Record 2', urgent_protection_concern: false }) } + let(:record3) { Child.create!(data: { name: 'Record 3' }) } + let(:record4) { Child.create!(data: { name: 'Record 4', urgent_protection_concern: nil }) } + + before do + clean_data(SearchableIdentifier, Child) + record1 + record2 + record3 + record4 + end + + it 'matches the filter' do + filter = SearchFilters::BooleanValue.new(field_name: 'urgent_protection_concern', value: true) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record1.name) + end + + it 'matches the list filter' do + filter = SearchFilters::BooleanList.new(field_name: 'urgent_protection_concern', values: [false]) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(3) + expect(search.records.map(&:name)).to match_array([record2.name, record3.name, record4.name]) + end + + it 'matches the not filter for a list of values' do + filter = SearchFilters::BooleanList.new( + field_name: 'urgent_protection_concern', values: [true], not_filter: true + ) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(3) + expect(search.records.map(&:name)).to match_array([record2.name, record3.name, record4.name]) + end + + it 'matches the not filter for false value' do + filter = SearchFilters::BooleanValue.new( + field_name: 'urgent_protection_concern', value: false, not_filter: true + ) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record1.name) + end + + it 'matches the not filter for true value' do + filter = SearchFilters::BooleanValue.new( + field_name: 'urgent_protection_concern', value: true, not_filter: true + ) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(3) + expect(search.records.map(&:name)).to match_array([record2.name, record3.name, record4.name]) + end + end + + describe 'searches with integer filters' do + let(:record1) { Child.create!(data: { name: 'Record 1', age: 5 }) } + let(:record2) { Child.create!(data: { name: 'Record 2', age: 2 }) } + let(:record3) { Child.create!(data: { name: 'Record 3' }) } + let(:record4) { Child.create!(data: { name: 'Record 4', age: nil }) } + + before do + clean_data(SearchableIdentifier, Child) + record1 + record2 + record3 + record4 + end + + it 'matches the filter' do + filter = SearchFilters::Value.new(field_name: 'age', value: 5) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record1.name) + end + + it 'matches the list filter' do + filter = SearchFilters::ValueList.new(field_name: 'age', values: [5, 2]) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(2) + expect(search.records.map(&:name)).to match_array([record1.name, record2.name]) + end + + it 'matches the numeric range filter' do + filter = SearchFilters::NumericRange.new(field_name: 'age', from: 0, to: 2) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record2.name) + end + + it 'matches the numeric range list' do + filter = SearchFilters::RangeList.new( + field_name: 'age', values: [{ 'from' => 0, 'to' => 2 }], range_type: SearchFilters::NumericRange + ) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record2.name) + end + + it 'matches the not filter' do + filter = SearchFilters::Value.new(field_name: 'age', value: 2, not_filter: true) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(3) + expect(search.records.map(&:name)).to match_array([record1.name, record3.name, record4.name]) + end + + it 'matches the not filter for a list' do + filter = SearchFilters::ValueList.new(field_name: 'age', values: [2], not_filter: true) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(3) + expect(search.records.map(&:name)).to match_array([record1.name, record3.name, record4.name]) + end + + it 'matches the not filter for a numeric range' do + filter = SearchFilters::NumericRange.new(field_name: 'age', from: 0, to: 2, not_filter: true) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(3) + expect(search.records.map(&:name)).to match_array([record1.name, record3.name, record4.name]) + end + end + + describe 'searches with date filters' do + let(:record1) { Child.create!(data: { name: 'Record 1', date_of_birth: '2020-08-09' }) } + let(:record2) { Child.create!(data: { name: 'Record 2', date_of_birth: '2022-04-25' }) } + let(:record3) { Child.create!(data: { name: 'Record 3' }) } + let(:record4) { Child.create!(data: { name: 'Record 4', date_of_birth: nil }) } + + before do + clean_data(SearchableIdentifier, Child) + record1 + record2 + record3 + record4 + end + + it 'matches the filter' do + filter = SearchFilters::DateValue.new(field_name: 'date_of_birth', value: Date.new(2022, 4, 25)) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record2.name) + end + + it 'matches the date range filter' do + filter = SearchFilters::DateRange.new( + field_name: 'date_of_birth', from: Date.new(2020, 8, 1), to: Date.new(2022, 4, 30) + ) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(2) + expect(search.records.map(&:name)).to match_array([record1.name, record2.name]) + end + + it 'matches the date range list' do + filter = SearchFilters::RangeList.new( + field_name: 'date_of_birth', values: [{ 'from' => Date.new(2020, 8, 1), 'to' => Date.new(2022, 4, 30) }], + range_type: SearchFilters::DateRange + ) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(2) + expect(search.records.map(&:name)).to match_array([record1.name, record2.name]) + end + + it 'matches the filter' do + filter = SearchFilters::DateValue.new(field_name: 'date_of_birth', value: Date.new(2022, 4, 25)) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record2.name) + end + end + + describe 'searches with id fields' do + let(:record1) { Child.create!(data: { name: 'Record 1', sex: 'female' }) } + let(:record2) { Child.create!(data: { name: 'Record 2', sex: 'male' }) } + + before do + clean_data(SearchableIdentifier, Child) + record1 + record2 + end + + it 'searches with id filters' do + filter = SearchFilters::TextValue.new(field_name: 'case_id', value: record1.case_id) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(1) + expect(search.records).to contain_exactly(record1) + end + + it 'searches a list of id filters' do + filter = SearchFilters::TextList.new(field_name: 'case_id', values: [record1.case_id, record2.case_id]) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(2) + expect(search.records).to contain_exactly(record1, record2) + end + end + end + + describe 'Text search' do + let(:record1) do + Child.create!( + id: '2f10eef2-4ad0-11ef-9559-18c04db5c362', + data: { + name: 'Augustina Link', + sex: 'female', + unique_identifier: '074b2516-4acd-11ef-858e-18c04db5c362', + national_id_no: 'ER/054/8/56/test-1', + case_id: '043854d4-4acd-11ef-a0cb-18c04db5c362', + short_id: '548561' + } + ) + end + let(:record2) do + Child.create!( + id: '39531c32-4ad0-11ef-b0ed-18c04db5c362', + data: { + name: 'Ahmad MacPherson', + sex: 'male', + unique_identifier: '08149eaa-4acd-11ef-b594-18c04db5c362', + national_id_no: 'ER/054/8/56/test-2', + case_id: '08db9eec-4acd-11ef-91f0-18c04db5c362', + short_id: '548562' + } + ) + end + let(:record3) do + Child.create!( + id: '4974e866-4ad0-11ef-918a-18c04db5c362', + data: { + name: 'Numeric 0001', + sex: 'male', + unique_identifier: '67529840-4acd-11ef-9384-18c04db5c362', + case_id: '67ea4c58-4acd-11ef-a3ee-18c04db5c362', + short_id: '0001' + } + ) + end + let(:record4) do + Child.create!( + id: '4eed3c6c-4ad0-11ef-92b0-18c04db5c362', + data: { + name: 'Numeric 1234', + sex: 'male', + unique_identifier: '9c33e154-4acd-11ef-997f-18c04db5c362', + case_id: '9cd59602-4acd-11ef-821c-18c04db5c362', + short_id: '1234' + } + ) + end + let(:record5) do + Child.create!( + id: '5516770c-4ad0-11ef-8c9b-18c04db5c362', + data: { + name: 'Numeric 01', + sex: 'male', + unique_identifier: 'b5c4b9b8-4acd-11ef-8037-18c04db5c362', + case_id: 'b6561c14-4acd-11ef-b83f-18c04db5c362', + short_id: '01' + } + ) + end + + before do + clean_data(SearchableIdentifier, Child) + record1 + record2 + record3 + record4 + record5 + end + + it 'searches with plain text when is a phonetic query' do + search = PhoneticSearchService.search(Child, query: 'Augustina', phonetic: 'true') + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record1.name) + end + + it 'finds the exact identifier with mixed characters' do + search = PhoneticSearchService.search(Child, query: 'ER/054/8/56/test-1') + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record1.name) + end + + it 'finds a numeric short_id=0001' do + search = PhoneticSearchService.search(Child, query: '0001') + + expect(search.total).to eq(1) + expect(search.records.first.short_id).to eq('0001') + expect(search.records.first.name).to eq(record3.name) + end + + it 'finds a numeric short_id=01' do + search = PhoneticSearchService.search(Child, query: '01') + + expect(search.total).to eq(2) + expect(search.records.first.short_id).to eq('01') + expect(search.records.first.name).to eq(record5.name) + end + + it 'finds a numeric short_id using a few zeros in the query' do + search = PhoneticSearchService.search(Child, query: '00') + + expect(search.total).to eq(1) + expect(search.records.first.short_id).to eq('0001') + expect(search.records.first.name).to eq(record3.name) + end + + it 'finds a numeric short_id with different numbers' do + search = PhoneticSearchService.search(Child, query: '1234') + + expect(search.total).to eq(1) + expect(search.records.first.short_id).to eq('1234') + expect(search.records.first.name).to eq(record4.name) + end + + it 'finds a numeric short_id with leading/trailing whitespaces' do + search = PhoneticSearchService.search(Child, query: ' 1234 ') + + expect(search.total).to eq(1) + expect(search.records.first.short_id).to eq('1234') + expect(search.records.first.name).to eq(record4.name) + end + end + + describe 'Sorting search' do + let(:record1) { Child.create!(data: { name: 'Augustina Link', national_id_no: '001', sex: 'female' }) } + let(:record2) { Child.create!(data: { name: 'Augustina MacPherson', national_id_no: '011', sex: 'male' }) } + let(:record3) { Child.create!(data: { name: 'Augustina Applebee', national_id_no: '100', sex: 'male' }) } + + before do + clean_data(SearchableIdentifier, Child) + record1 + record2 + record3 + end + + it 'sorts a phonetic search by similarity' do + search = PhoneticSearchService.search(Child, query: 'Augustina Link', phonetic: 'true') + expect(search.records.map(&:name)).to eq([record1, record3, record2].map(&:name)) + end + end + + describe 'Authorization' do + let(:user_group1) { UserGroup.new(id: 1, unique_id: 'user_group_1') } + let(:user_group2) { UserGroup.new(id: 2, unique_id: 'user_group_2') } + let(:agency) do + agency = Agency.new(id: 1, unique_id: 'agency_1', agency_code: 'agency_1') + agency.save(validate: false) + agency + end + let(:user1) do + user1 = User.new(user_name: 'test1', agency:, user_groups: [user_group1]) + user1.save(validate: false) + user1 + end + let(:user2) do + user2 = User.new(user_name: 'test2', user_groups: [user_group2]) + user2.save(validate: false) + user2 + end + let(:user3) do + user3 = User.new(user_name: 'test3', agency:, user_groups: [user_group2]) + user3.save(validate: false) + user3 + end + let(:record1) { Child.create!(data: { name: 'Record 1', owned_by: user1.user_name }) } + let(:record2) { Child.create!(data: { name: 'Record 2', owned_by: user2.user_name }) } + let(:record3) do + Child.create!(data: { name: 'Case3', owned_by: user2.user_name, assigned_user_names: [user3.user_name] }) + end + + before do + clean_data(User, UserGroup, Agency, SearchableIdentifier, Child) + user1 + user2 + user3 + record1 + record2 + record3 + end + + it 'limits access for currently associated users if user scope is provided' do + search = PhoneticSearchService.search(Child, scope: { user: { 'user' => user1.user_name } }) + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record1.name) + end + + it 'limits access by user group if group scope is provided' do + search = PhoneticSearchService.search( + Child, scope: { user: { 'group' => [user_group1.unique_id, user_group2.unique_id] } } + ) + + expect(search.total).to eq(3) + expect(search.records.map(&:name)).to include(record2.name, record3.name) + end + + it 'limits access by agency if agency scope is provided' do + search = PhoneticSearchService.search(Child, scope: { user: { 'agency' => agency.unique_id } }) + expect(search.total).to eq(2) + expect(search.records.map(&:name)).to include(record1.name, record3.name) + end + + it "doesn't limit access if no user scope is provided" do + search = PhoneticSearchService.search(Child) + + expect(search.total).to eq(3) + expect(search.records.map(&:name)).to include(record1.name, record2.name, record3.name) + end + end + + describe 'Filter search locations' do + let(:record1) { Child.create!(data: { name: 'Record 1', location_current: 'MC01' }) } + let(:record2) { Child.create!(data: { name: 'Record 2', location_current: 'TW01' }) } + let(:record3) { Child.create!(data: { name: 'Record 3', location_current: 'TW02' }) } + let(:record4) { Child.create!(data: { name: 'Record 4', location_current: 'PR02' }) } + let(:record5) { Child.create!(data: { name: 'Record 5', location_current: 'TW03' }) } + let(:record6) { Child.create!(data: { name: 'Record 6', location_current: '1234' }) } + let(:country) { create(:location, placename_all: 'MyCountry', type: 'country', location_code: 'MC01') } + let(:province1) do + create(:location, hierarchy_path: "#{country.location_code}.PR01", type: 'state', location_code: 'PR01') + end + let(:province2) do + create(:location, hierarchy_path: "#{country.location_code}.PR02", type: 'province', location_code: 'PR02') + end + let(:town1) do + create( + :location, + hierarchy_path: "#{country.location_code}.#{province1.location_code}.TW01", + type: 'city', + location_code: 'TW01' + ) + end + let(:town2) do + create( + :location, + hierarchy_path: "#{country.location_code}.#{province1.location_code}.TW02", + type: 'city', + disabled: false, + location_code: 'TW02' + ) + end + let(:town3) do + create( + :location, + hierarchy_path: "#{country.location_code}.#{province2.location_code}.TW03", + type: 'city', + disabled: false, + location_code: 'TW03' + ) + end + let(:town4) do + create( + :location, + hierarchy_path: "#{country.location_code}.#{province2.location_code}.1234", + type: 'city', + disabled: false, + location_code: '1234' + ) + end + + before do + clean_data(Location, FormSection, Field, User, UserGroup, Agency, SearchableIdentifier, Child) + + create( + :form_section, + unique_id: 'form_section_1', + fields: [ + create(:field, name: 'location_current', type: Field::SELECT_BOX, option_strings_source: 'Location') + ] + ) + country + province1 + province2 + town1 + town2 + town3 + town4 + record1 + record2 + record3 + record4 + record5 + record6 + end + + it 'searches with location filter' do + filter = SearchFilters::LocationValue.new(field_name: 'loc:location_current', value: 'PR02') + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(3) + expect(search.records).to contain_exactly(record4, record5, record6) + end + + it 'searches with location list filters' do + filter = SearchFilters::LocationList.new(field_name: 'loc:location_current', values: %w[PR01 TW03]) + search = PhoneticSearchService.search(Child, filters: [filter]) + + expect(search.total).to eq(3) + expect(search.records).to contain_exactly(record2, record3, record5) + end + end + + describe 'Module scope' do + let(:record1) { Child.create!(data: { name: 'Record 1', module_id: 'primeromodule-cp' }) } + let(:record2) { Child.create!(data: { name: 'Record 2', module_id: 'primeromodule-gbv' }) } + + before do + clean_data(User, UserGroup, Agency, SearchableIdentifier, Child) + record1 + record2 + end + + it 'limits search results by module' do + search = PhoneticSearchService.search(Child, scope: { module: ['primeromodule-cp'] }) + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record1.name) + end + end + + describe 'Filter search' do + let(:record1) { Child.create!(data: { name: 'Record 1', oscar_number: 'RXJA12819JIKA2893' }) } + let(:record2) { Child.create!(data: { name: 'Record 2', oscar_number: 'RT128N1281O084' }) } + + before do + clean_data(User, UserGroup, Agency, Child) + record1 + record2 + end + + it 'searches with filters' do + search = PhoneticSearchService.search(Child, query: 'RXJA12819JIKA2893') + + expect(search.total).to eq(1) + expect(search.records.first.name).to eq(record1.name) + end + end + + describe 'Violation Search' do + let(:record1) do + Incident.create!( + data: { + violation_category: %w[killing attack_on_hospitals], + created_at: 1.months.ago, + incident_id: '04274225-8c68-4ce1-b10b-be18b9f88531' + } + ) + end + let(:record2) do + Incident.create!( + data: { + violation_category: %w[maiming], + created_at: 1.months.ago, + incident_id: '9448d2fa-5d81-4c0b-9522-bb2617adaa52' + } + ) + end + let(:record3) do + Incident.create!( + data: { + violation_category: %w[recruitment], + created_at: DateTime.current, + incident_id: '7d93d75e-588b-449f-b94e-a28d301c6594' + } + ) + end + before do + clean_data(SearchableIdentifier, Incident) + record1 + record2 + record3 + end + + it 'search with filters' do + filter = SearchFilters::TextList.new(field_name: 'violation_category', values: %w[killing maiming]) + search = PhoneticSearchService.search(Incident, filters: [filter], sort: { 'created_at' => 'desc' }) + + expect(search.total).to eq(2) + expect(search.records.map(&:incident_id)).to match_array( + [record1.incident_id, record2.incident_id] + ) + end + end +end diff --git a/spec/services/primero_model_service_spec.rb b/spec/services/primero_model_service_spec.rb new file mode 100644 index 0000000000..72d9c608b0 --- /dev/null +++ b/spec/services/primero_model_service_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +require 'rails_helper' + +describe PrimeroModelService do + describe 'to_model' do + it 'converts a valid string to a class' do + expect(PrimeroModelService.to_model('incident')).to eq(Incident) + end + + it 'converts the string "case" to a Child object' do + expect(PrimeroModelService.to_model('case')).to eq(Child) + end + + it 'will not convert unsafe strings to an object' do + expect(PrimeroModelService.to_model('Kernel')).to be_nil + end + end + + describe 'to_name' do + it 'changes a class name to a simple type name' do + expect(PrimeroModelService.to_name('Incident')).to eq('incident') + end + + it 'changes the string "Child" to "case"' do + expect(PrimeroModelService.to_name('Child')).to eq('case') + end + end +end diff --git a/spec/services/record_data_service_spec.rb b/spec/services/record_data_service_spec.rb index 27afb031ad..e97e036221 100644 --- a/spec/services/record_data_service_spec.rb +++ b/spec/services/record_data_service_spec.rb @@ -15,6 +15,7 @@ @user = User.new(user_name: 'user1', role: @role) @record = Child.new_with_user(@user, name: 'Test', hidden_name: true, field1: 'value1', field2: nil) @incident = Incident.new_with_user(@user, incident_date: Date.today, violation_category: %w[foo bar]) + @incident.save! allow(@record).to receive(:flag_count).and_return(2) end diff --git a/spec/services/record_json_validator_service_spec.rb b/spec/services/record_json_validator_service_spec.rb index 77365ef151..a9b242a8d2 100644 --- a/spec/services/record_json_validator_service_spec.rb +++ b/spec/services/record_json_validator_service_spec.rb @@ -230,7 +230,7 @@ end it 'accepts array values' do - expect(service.valid?('calculated' => [])).to be_truthy + expect(service.valid?('calculated' => [])).to be_falsey end it 'rejects very big numeric values' do diff --git a/spec/services/search_filter_service_spec.rb b/spec/services/search_filter_service_spec.rb index 6f2f7b9d31..371b1da162 100644 --- a/spec/services/search_filter_service_spec.rb +++ b/spec/services/search_filter_service_spec.rb @@ -21,57 +21,69 @@ describe 'filter construction' do it 'builds a value filter from numeric values' do - filter = service.build_filters('age' => 10).first + filter = service.build_filters({ 'age' => 10 }).first expect(filter).to be_instance_of(SearchFilters::Value) expect(filter.field_name).to eq('age') expect(filter.value).to eq(10) end it 'builds a value filter from string values' do - filter = service.build_filters('sex' => 'male').first - expect(filter).to be_instance_of(SearchFilters::Value) + filter = service.build_filters({ 'sex' => 'male' }).first + expect(filter).to be_instance_of(SearchFilters::TextValue) expect(filter.field_name).to eq('sex') expect(filter.value).to eq('male') end it 'builds a value filter from boolean values' do - filter = service.build_filters('valid' => true).first - expect(filter).to be_instance_of(SearchFilters::Value) + filter = service.build_filters({ 'valid' => true }).first + expect(filter).to be_instance_of(SearchFilters::BooleanValue) expect(filter.field_name).to eq('valid') expect(filter.value).to be true end - it 'builds a not value filter from numeric values' do - filter = service.build_filters('not' => { 'age' => 10 }).first - expect(filter).to be_instance_of(SearchFilters::NotValue) + it 'builds a not filter from numeric values' do + filter = service.build_filters({ 'not' => { 'age' => 10 } }).first + expect(filter).to be_instance_of(SearchFilters::Value) expect(filter.field_name).to eq('age') - expect(filter.values).to eq(10) + expect(filter.value).to eq(10) + expect(filter.not_filter).to eq(true) end - it 'builds a not value filter from string values' do - filter = service.build_filters('not' => { 'sex' => 'male' }).first - expect(filter).to be_instance_of(SearchFilters::NotValue) + it 'builds a not filter from string values' do + filter = service.build_filters({ 'not' => { 'sex' => 'male' } }).first + expect(filter).to be_instance_of(SearchFilters::TextValue) expect(filter.field_name).to eq('sex') - expect(filter.values).to eq('male') + expect(filter.value).to eq('male') + expect(filter.not_filter).to eq(true) end - it 'builds a not value filter from boolean values' do - filter = service.build_filters('not' => { 'valid' => true }).first - expect(filter).to be_instance_of(SearchFilters::NotValue) + it 'builds a not filter from boolean values' do + filter = service.build_filters({ 'not' => { 'valid' => true } }).first + expect(filter).to be_instance_of(SearchFilters::BooleanValue) expect(filter.field_name).to eq('valid') - expect(filter.values).to eq(true) + expect(filter.value).to eq(true) + expect(filter.not_filter).to eq(true) end - it 'builds a not value filter with two values' do - filter = service.build_filters('not' => { 'age' => [10, 8] }).first - expect(filter).to be_instance_of(SearchFilters::NotValue) + it 'builds a not filter with two values' do + filter = service.build_filters({ 'not' => { 'age' => [10, 8] } }).first + expect(filter).to be_instance_of(SearchFilters::ValueList) expect(filter.field_name).to eq('age') expect(filter.values).to eq([10, 8]) + expect(filter.not_filter).to eq(true) + end + + it 'builds a not filter with two values' do + filter = service.build_filters({ 'not' => { 'age' => [10, 8] } }).first + expect(filter).to be_instance_of(SearchFilters::ValueList) + expect(filter.field_name).to eq('age') + expect(filter.values).to eq([10, 8]) + expect(filter.not_filter).to eq(true) end it 'builds a date range filter from date range values' do filter = service.build_filters( - 'registration_date' => { 'from' => Date.new(2018, 1, 1), 'to' => Date.new(2019, 1, 1) } + { 'registration_date' => { 'from' => Date.new(2018, 1, 1), 'to' => Date.new(2019, 1, 1) } } ).first expect(filter).to be_instance_of(SearchFilters::DateRange) expect(filter.field_name).to eq('registration_date') @@ -80,7 +92,7 @@ end it 'builds a numeric range filter from numeric range values' do - filter = service.build_filters('age' => { 'from' => 0, 'to' => 5 }).first + filter = service.build_filters({ 'age' => { 'from' => 0, 'to' => 5 } }).first expect(filter).to be_instance_of(SearchFilters::NumericRange) expect(filter.field_name).to eq('age') expect(filter.from).to eq(0) @@ -88,8 +100,8 @@ end it 'builds a value list filter from a value list' do - filter = service.build_filters('sex' => %w[male female]).first - expect(filter).to be_instance_of(SearchFilters::ValueList) + filter = service.build_filters({ 'sex' => %w[male female] }).first + expect(filter).to be_instance_of(SearchFilters::TextList) expect(filter.field_name).to eq('sex') expect(filter.values).to eq(%w[male female]) end @@ -106,12 +118,13 @@ expect(filter.filters[0].field_name).to eq('age') expect(filter.filters[0].from).to eq(0) expect(filter.filters[0].to).to eq(5) - expect(filter.filters[1]).to be_instance_of(SearchFilters::Value) + expect(filter.filters[1]).to be_instance_of(SearchFilters::TextValue) expect(filter.filters[1].field_name).to eq('sex') expect(filter.filters[1].value).to eq('female') - expect(filter.filters[2]).to be_instance_of(SearchFilters::NotValue) + expect(filter.filters[2]).to be_instance_of(SearchFilters::TextValue) expect(filter.filters[2].field_name).to eq('sex') - expect(filter.filters[2].values).to eq('female') + expect(filter.filters[2].value).to eq('female') + expect(filter.filters[2].not_filter).to eq(true) end it 'builds an or filter from or values if they are specified as a hash' do @@ -126,12 +139,33 @@ expect(filter.filters[0].field_name).to eq('age') expect(filter.filters[0].from).to eq(0) expect(filter.filters[0].to).to eq(5) - expect(filter.filters[1]).to be_instance_of(SearchFilters::Value) + expect(filter.filters[1]).to be_instance_of(SearchFilters::TextValue) expect(filter.filters[1].field_name).to eq('sex') expect(filter.filters[1].value).to eq('female') - expect(filter.filters[2]).to be_instance_of(SearchFilters::NotValue) + expect(filter.filters[2]).to be_instance_of(SearchFilters::TextValue) expect(filter.filters[2].field_name).to eq('sex') - expect(filter.filters[2].values).to eq('female') + expect(filter.filters[2].value).to eq('female') + expect(filter.filters[2].not_filter).to eq(true) + end + + it 'does not build a filter for an invalid hash' do + params = { 'age' => { 'display_name' => 'Age' } } + + expect(service.build_filters(params)).to be_empty + end + + it 'builds a location filter' do + filter = service.build_filters({ 'loc:location_current' => 'city1' }).first + expect(filter).to be_instance_of(SearchFilters::LocationValue) + expect(filter.field_name).to eq('loc:location_current') + expect(filter.value).to eq('city1') + end + + it 'builds a location list filter' do + filter = service.build_filters({ 'loc:location_current' => ['city1'] }).first + expect(filter).to be_instance_of(SearchFilters::LocationList) + expect(filter.field_name).to eq('loc:location_current') + expect(filter.values).to eq(['city1']) end end diff --git a/spec/services/search_service_spec.rb b/spec/services/search_service_spec.rb deleted file mode 100644 index 9e00ed16f1..0000000000 --- a/spec/services/search_service_spec.rb +++ /dev/null @@ -1,286 +0,0 @@ -# frozen_string_literal: true - -# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. - -require 'rails_helper' - -describe SearchService, search: true do - describe 'Filter search' do - before :example do - @correct_match = Child.create!(data: { name: 'Correct Match1', sex: 'female' }) - @incorrect_match = Child.create!(data: { name: 'Incorrect Match', sex: 'male' }) - Sunspot.commit - end - - it 'searches with filters' do - filter = SearchFilters::Value.new(field_name: 'sex', value: 'female') - search = SearchService.search(Child, filters: [filter]) - - expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@correct_match.name) - end - - it 'searches with filters not value' do - filter = SearchFilters::NotValue.new(field_name: 'sex', values: 'male') - search = SearchService.search(Child, filters: [filter]) - - expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@correct_match.name) - end - end - - describe 'Filter search locations' do - before :example do - clean_data(Location, FormSection, Field) - - create(:form_section, unique_id: 'form_section_1', fields: [ - create(:field, name: 'location_current', type: Field::SELECT_BOX, option_strings_source: 'Location') - ]) - - @country = create( - :location, placename_all: 'MyCountry', type: 'country', location_code: 'MC01' - ) - @province1 = create( - :location, hierarchy_path: "#{@country.location_code}.PR01", type: 'state', location_code: 'PR01' - ) - @province2 = create( - :location, hierarchy_path: "#{@country.location_code}.PR02", type: 'province', location_code: 'PR02' - ) - @town1 = create( - :location, hierarchy_path: "#{@country.location_code}.#{@province1.location_code}.TW01", - type: 'city', location_code: 'TW01' - ) - @town2 = create( - :location, hierarchy_path: "#{@country.location_code}.#{@province1.location_code}.TW02", - type: 'city', disabled: false, location_code: 'TW02' - ) - @town3 = create( - :location, hierarchy_path: "#{@country.location_code}.#{@province2.location_code}.TW03", - type: 'city', disabled: false, location_code: 'TW03' - ) - @town4 = create( - :location, hierarchy_path: "#{@country.location_code}.#{@province2.location_code}.1234", - type: 'city', disabled: false, location_code: '1234' - ) - - @child_location1 = Child.create!(data: { location_current: 'MC01' }) - @child_location2 = Child.create!(data: { location_current: 'TW01' }) - @child_location3 = Child.create!(data: { location_current: 'TW02' }) - @child_location4 = Child.create!(data: { location_current: 'PR02' }) - @child_location5 = Child.create!(data: { location_current: 'TW03' }) - @child_location6 = Child.create!(data: { location_current: '1234' }) - - Sunspot.commit - end - - it 'searches with location filters' do - filter = SearchFilters::ValueList.new(field_name: 'location_current', values: %w[PR01 TW03]) - search = SearchService.search(Child, filters: [filter]) - - expect(search.total).to eq(3) - expect(search.results).to contain_exactly(@child_location2, @child_location3, @child_location5) - end - - it 'searches with location filters and numeric location code' do - filter = SearchFilters::ValueList.new(field_name: 'location_current', values: [1234]) - location_field_name = filter.as_location_filter(Child).filters.last.field_name - - expect(location_field_name).to eq("location_current#{@town4.admin_level}") - end - end - - describe 'Filter search id fields' do - before :example do - @case1 = Child.create!(data: { name: 'Case 1', sex: 'female' }) - @case2 = Child.create!(data: { name: 'Case 2', sex: 'male' }) - Sunspot.commit - end - - it 'searches with id filters' do - filter = SearchFilters::Value.new(field_name: 'case_id', value: @case1.case_id) - search = SearchService.search(Child, filters: [filter]) - - expect(search.total).to eq(1) - expect(search.results).to contain_exactly(@case1) - end - - it 'searches a list of id filters' do - filter = SearchFilters::ValueList.new(field_name: 'case_id', values: [@case1.case_id, @case2.case_id]) - search = SearchService.search(Child, filters: [filter]) - - expect(search.total).to eq(2) - expect(search.results).to contain_exactly(@case1, @case2) - end - end - - describe 'Text search' do - before :example do - @correct_match = Child.create!( - data: { name: 'Augustina Link', sex: 'female', national_id_no: 'ER/054/8/56/test-1' } - ) - @incorrect_match = Child.create!( - data: { name: 'Ahmad MacPherson', sex: 'male', national_id_no: 'ER/054/8/56/test-2' } - ) - Sunspot.commit - end - - it 'searches with plain text' do - search = SearchService.search(Child, query: 'Augustina') - - expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@correct_match.name) - end - - it 'finds the exact identifier with mixed characters' do - search = SearchService.search(Child, query: 'ER/054/8/56/test-1') - - expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@correct_match.name) - end - end - - describe 'Sorting search' do - before :example do - @child1 = Child.create!(data: { name: 'Augustina Link', sex: 'female' }) - @child2 = Child.create!(data: { name: 'Augustina MacPherson', sex: 'male' }) - @child3 = Child.create!(data: { name: 'Augustina Applebee', sex: 'male' }) - - Sunspot.commit - end - - it 'sorts sortable fields' do - search = SearchService.search(Child, query: 'Augustina', sort: { name: :asc }) - expect(search.results.map(&:name)).to eq([@child3, @child1, @child2].map(&:name)) - end - - it 'sorts fields' do - search = SearchService.search(Child, query: 'Augustina', sort: { sex: :desc }) - expect(search.results.map(&:sex)).to eq([@child2, @child3, @child1].map(&:sex)) - end - end - - describe 'Authorization' do - before :example do - @user_group = UserGroup.new(id: 1, unique_id: 'user_group_1') - @user_group_b = UserGroup.new(id: 2, unique_id: 'user_group_2') - @agency = Agency.new(id: 1, unique_id: 'agency_1', agency_code: 'agency_1') - @agency.save(validate: false) - @user = User.new(user_name: 'test1', agency: @agency, user_groups: [@user_group]) - @user.save(validate: false) - @user2 = User.new(user_name: 'test2', user_groups: [@user_group_b]) - @user2.save(validate: false) - @user3 = User.new(user_name: 'test3', agency: @agency, user_groups: [@user_group_b]) - @user3.save(validate: false) - - @case1 = Child.create!(data: { name: 'Case1', owned_by: @user.user_name }) - @case2 = Child.create!(data: { name: 'Case2', owned_by: @user2.user_name }) - @case3 = Child.create!(data: { - name: 'Case3', owned_by: @user2.user_name, assigned_user_names: [@user3.user_name] - }) - Sunspot.commit - end - - it 'limits access for currently associated users if user scope is provided' do - search = SearchService.search(Child, query_scope: { user: { 'user' => @user.user_name } }) - - expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@case1.name) - end - - it 'limits access by user group if group scope is provided' do - search = SearchService.search( - Child, - query_scope: { user: { Permission::GROUP => [@user_group.unique_id, @user_group_b.unique_id] } } - ) - - expect(search.total).to eq(3) - expect(search.results.map(&:name)).to include(@case2.name, @case3.name) - end - - it 'limits access by agency if agency scope is provided' do - search = SearchService.search(Child, query_scope: { user: { Permission::AGENCY => @agency.unique_id } }) - expect(search.total).to eq(2) - expect(search.results.map(&:name)).to include(@case1.name, @case3.name) - end - - it "doesn't limit access if no user scope is provided" do - search = SearchService.search(Child) - - expect(search.total).to eq(3) - expect(search.results.map(&:name)).to include(@case1.name, @case2.name, @case3.name) - end - end - - describe 'Module scope' do - before :each do - @case1 = Child.create!(data: { name: 'Case1', module_id: 'primeromodule-cp' }) - @case2 = Child.create!(data: { name: 'Case2', module_id: 'primeromodule-gbv' }) - Sunspot.commit - end - - it 'limits search results by module' do - search = SearchService.search(Child, query_scope: { module: ['primeromodule-cp'] }) - expect(search.total).to eq(1) - expect(search.results[0].name).to eq(@case1.name) - end - end - - after :example do - clean_data(User, Agency, UserGroup, Child) - end - - describe 'Filter search' do - before :example do - @correct_match = Child.create!(data: { name: 'Correct Match1', oscar_number: 'RXJA12819JIKA2893' }) - @incorrect_match = Child.create!(data: { name: 'Incorrect Match', oscar_number: 'RT128N1281O084' }) - Sunspot.commit - end - - it 'searches with filters' do - search = SearchService.search(Child, query: 'RXJA12819JIKA2893') - - expect(search.total).to eq(1) - expect(search.results.first.name).to eq(@correct_match.name) - end - end - - describe 'Violation Search' do - before :example do - Sunspot.setup(Incident) do - string('violation_category', multiple: true) - end - @correct_match_a = Incident.create!( - data: { - violation_category: %w[killing attack_on_hospitals], - created_at: 1.months.ago, - incident_id: '04274225-8c68-4ce1-b10b-be18b9f88531' - } - ) - @correct_match_b = Incident.create!( - data: { - violation_category: %w[maiming], - created_at: 1.months.ago, - incident_id: '9448d2fa-5d81-4c0b-9522-bb2617adaa52' - } - ) - @incorrect_match = Incident.create!( - data: { - violation_category: %w[recruitment], - created_at: DateTime.current, - incident_id: '7d93d75e-588b-449f-b94e-a28d301c6594' - } - ) - Sunspot.commit - end - - it 'search with filters' do - filter = SearchFilters::Value.new(field_name: 'violation_category', value: %w[killing maiming]) - search = SearchService.search(Incident, filters: [filter], sort: { 'created_at' => 'desc' }) - - expect(search.total).to eq(2) - expect(search.results.map(&:incident_id)).to match_array( - [@correct_match_a.incident_id, @correct_match_b.incident_id] - ) - end - end -end diff --git a/spec/support/fake_devise_login.rb b/spec/support/fake_devise_login.rb index cdeca51ce0..6d5df208dd 100644 --- a/spec/support/fake_devise_login.rb +++ b/spec/support/fake_devise_login.rb @@ -50,6 +50,21 @@ module FakeDeviseLogin Field.new(name: 'family_size', type: Field::NUMERIC_FIELD, display_name_en: 'Family Size') ].freeze + SERVICE_FIELDS = [ + Field.new( + name: 'services_section', + display_name_en: 'A', + type: Field::SUBFORM, + subform: FormSection.new( + unique_id: 'services_section', parent_form: 'case', name_en: 'services_section', is_nested: true, + fields: [ + Field.new(name: 'service_type', type: Field::TEXT_FIELD, display_name_en: 'A'), + Field.new(name: 'separator3', type: Field::SEPARATOR, display_name_en: 'A'), + ] + ) + ) + ].freeze + def permission_case @permission_case ||= Permission.new( resource: Permission::CASE, @@ -136,18 +151,30 @@ def fake_user(opts = {}) agency_id = opts[:agency_id] user_group_ids = opts[:user_group_ids] || [] user = User.new(user_name:, user_group_ids:, agency_id:) + stub_role(user, opts) + stub_user_group_unique_ids(user, opts) + user.id = opts[:id] + user + end + + def stub_role(user, opts = {}) if opts[:role].present? user.role = opts[:role] else user.stub(:role).and_return(fake_role(opts)) end - user.id = opts[:id] - user end - def permit_fields(opts = {}) + def stub_user_group_unique_ids(user, opts = {}) + return unless opts[:user_group_unique_ids].present? + + user.stub(:user_group_unique_ids).and_return(opts[:user_group_unique_ids]) + end + + def permit_fields(user, opts = {}) permitted_fields = opts[:permitted_fields] || COMMON_PERMITTED_FIELDS - permitted_field_names = opts[:permitted_field_names] || common_permitted_field_names + permitted_fields += SERVICE_FIELDS if user&.role&.permits?('case', Permission::SERVICES_SECTION_FROM_CASE) + permitted_field_names = opts[:permitted_field_names] || permitted_fields.map(&:name) allow_any_instance_of(PermittedFormFieldsService).to( receive(:permitted_field_names).and_return(permitted_field_names) ) @@ -157,7 +184,8 @@ def permit_fields(opts = {}) end def login_for_test(opts = {}) - permit_fields(opts) - sign_in(fake_user(opts)) + user = fake_user(opts) + permit_fields(user, opts) + sign_in(user) end end diff --git a/spec/support/request_helper.rb b/spec/support/request_helper.rb new file mode 100644 index 0000000000..172b6b992a --- /dev/null +++ b/spec/support/request_helper.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +# Copyright (c) 2014 - 2023 UNICEF. All rights reserved. + +# Helpers for request specs. + +shared_examples 'a paginated resource' do + before(:each) do + login_for_test(action[:login_params] || {}) + end + + it 'limits pagination per page to 1000' do + get "/api/v2/#{action[:resource]}?per=3000" + + expect(json['metadata']['per']).to eq(1000) + end + + it 'defaults pagination per page to 20' do + get "/api/v2/#{action[:resource]}" + + expect(json['metadata']['per']).to eq(20) + end + + it 'return pagination per page when less than 1000' do + get "/api/v2/#{action[:resource]}?per=999" + + expect(json['metadata']['per']).to eq(999) + end +end diff --git a/spec/support/sunspot_helper.rb b/spec/support/sunspot_helper.rb index 8635835898..49cbdb9cf1 100644 --- a/spec/support/sunspot_helper.rb +++ b/spec/support/sunspot_helper.rb @@ -4,6 +4,8 @@ module SunspotHelper def indexed_field(value, klass = nil) + return unless Rails.configuration.solr_enabled + Sunspot::Type.for_class(klass || value.class).to_indexed(value) end end diff --git a/spec/webpush_notifiers/record_action_webpush_notifier_spec.rb b/spec/webpush_notifiers/record_action_webpush_notifier_spec.rb index 2ad55f4373..efaea01b2c 100644 --- a/spec/webpush_notifiers/record_action_webpush_notifier_spec.rb +++ b/spec/webpush_notifiers/record_action_webpush_notifier_spec.rb @@ -27,6 +27,17 @@ ) end + let(:notification_settings) do + { + notifications: { + receive_webpush: { + Transition::NOTIFICATION_ACTION => true, Approval::NOTIFICATION_ACTIONS_REQUEST => true, + Approval::NOTIFICATION_ACTIONS_RESPONSE => true, Transfer::NOTIFICATION_ACTION => true + } + } + } + end + let(:primero_module) do create(:primero_module, name: 'CP') end @@ -40,12 +51,15 @@ end let(:user) do - create(:user, user_name: 'user', full_name: 'Test User 1', email: 'owner@primero.dev', receive_webpush: true, role:) + create( + :user, user_name: 'user', full_name: 'Test User 1', email: 'owner@primero.dev', + receive_webpush: true, role:, settings: notification_settings + ) end let(:user2) do create(:user, user_name: 'user2', role: role2, full_name: 'Test User 2', - email: 'user2@primero.dev', receive_webpush: true) + email: 'user2@primero.dev', receive_webpush: true, settings: notification_settings) end let(:manager1) do @@ -60,7 +74,8 @@ send_mail: true, user_name: 'manager2', receive_webpush: true, - locale: 'en' + locale: 'en', + settings: notification_settings ) end diff --git a/webpack/config.common.js b/webpack/config.common.js index e70c1092f8..691e2ee250 100644 --- a/webpack/config.common.js +++ b/webpack/config.common.js @@ -16,7 +16,9 @@ const plugins = require("./plugins"); const resolve = { extensions: ["*", ".jsx", ".js"], alias: { - "@material-ui/styles": path.resolve("node_modules", "@material-ui/styles"), + "@mui/material/styles": path.resolve("node_modules", "@mui/material/styles"), + "@mui/cache": path.resolve("node_modules", "@mui/styled-engine/node_modules/@emotion/cache"), + "tss-react": path.resolve("node_modules", "tss-react"), window: "self" } };