commit
7cdf71f1c5
88 changed files with 1855 additions and 1000 deletions
2
.github/workflows/sentry-release.yml
vendored
2
.github/workflows/sentry-release.yml
vendored
|
@ -9,7 +9,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Sentry Release
|
- name: Sentry Release
|
||||||
uses: getsentry/action-release@v1.0.0
|
uses: getsentry/action-release@v1
|
||||||
env:
|
env:
|
||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||||
|
|
|
@ -1320,6 +1320,8 @@ Rails/ActiveRecordCallbacksOrder:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
Rails/AfterCommitOverride:
|
Rails/AfterCommitOverride:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
Rails/AttributeDefaultBlockValue:
|
||||||
|
Enabled: true
|
||||||
Rails/FindById:
|
Rails/FindById:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
Rails/Inquiry:
|
Rails/Inquiry:
|
||||||
|
@ -1342,6 +1344,8 @@ Rails/ShortI18n:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
Rails/SquishedSQLHeredocs:
|
Rails/SquishedSQLHeredocs:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
Rails/WhereEquals:
|
||||||
|
Enabled: true
|
||||||
Rails/WhereExists:
|
Rails/WhereExists:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
Rails/WhereNot:
|
Rails/WhereNot:
|
||||||
|
|
376
Gemfile.lock
376
Gemfile.lock
|
@ -22,38 +22,38 @@ GEM
|
||||||
specs:
|
specs:
|
||||||
aasm (5.1.1)
|
aasm (5.1.1)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
actioncable (6.0.3.4)
|
actioncable (6.0.3.5)
|
||||||
actionpack (= 6.0.3.4)
|
actionpack (= 6.0.3.5)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
actionmailbox (6.0.3.4)
|
actionmailbox (6.0.3.5)
|
||||||
actionpack (= 6.0.3.4)
|
actionpack (= 6.0.3.5)
|
||||||
activejob (= 6.0.3.4)
|
activejob (= 6.0.3.5)
|
||||||
activerecord (= 6.0.3.4)
|
activerecord (= 6.0.3.5)
|
||||||
activestorage (= 6.0.3.4)
|
activestorage (= 6.0.3.5)
|
||||||
activesupport (= 6.0.3.4)
|
activesupport (= 6.0.3.5)
|
||||||
mail (>= 2.7.1)
|
mail (>= 2.7.1)
|
||||||
actionmailer (6.0.3.4)
|
actionmailer (6.0.3.5)
|
||||||
actionpack (= 6.0.3.4)
|
actionpack (= 6.0.3.5)
|
||||||
actionview (= 6.0.3.4)
|
actionview (= 6.0.3.5)
|
||||||
activejob (= 6.0.3.4)
|
activejob (= 6.0.3.5)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
actionpack (6.0.3.4)
|
actionpack (6.0.3.5)
|
||||||
actionview (= 6.0.3.4)
|
actionview (= 6.0.3.5)
|
||||||
activesupport (= 6.0.3.4)
|
activesupport (= 6.0.3.5)
|
||||||
rack (~> 2.0, >= 2.0.8)
|
rack (~> 2.0, >= 2.0.8)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||||
actiontext (6.0.3.4)
|
actiontext (6.0.3.5)
|
||||||
actionpack (= 6.0.3.4)
|
actionpack (= 6.0.3.5)
|
||||||
activerecord (= 6.0.3.4)
|
activerecord (= 6.0.3.5)
|
||||||
activestorage (= 6.0.3.4)
|
activestorage (= 6.0.3.5)
|
||||||
activesupport (= 6.0.3.4)
|
activesupport (= 6.0.3.5)
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
actionview (6.0.3.4)
|
actionview (6.0.3.5)
|
||||||
activesupport (= 6.0.3.4)
|
activesupport (= 6.0.3.5)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.4)
|
erubi (~> 1.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
|
@ -61,32 +61,31 @@ GEM
|
||||||
active_link_to (1.0.5)
|
active_link_to (1.0.5)
|
||||||
actionpack
|
actionpack
|
||||||
addressable
|
addressable
|
||||||
active_model_serializers (0.10.10)
|
active_model_serializers (0.10.12)
|
||||||
actionpack (>= 4.1, < 6.1)
|
actionpack (>= 4.1, < 6.2)
|
||||||
activemodel (>= 4.1, < 6.1)
|
activemodel (>= 4.1, < 6.2)
|
||||||
case_transform (>= 0.2)
|
case_transform (>= 0.2)
|
||||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
||||||
active_storage_validations (0.9.0)
|
active_storage_validations (0.9.2)
|
||||||
rails (>= 5.2.0)
|
rails (>= 5.2.0)
|
||||||
activejob (6.0.3.4)
|
activejob (6.0.3.5)
|
||||||
activesupport (= 6.0.3.4)
|
activesupport (= 6.0.3.5)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (6.0.3.4)
|
activemodel (6.0.3.5)
|
||||||
activesupport (= 6.0.3.4)
|
activesupport (= 6.0.3.5)
|
||||||
activerecord (6.0.3.4)
|
activerecord (6.0.3.5)
|
||||||
activemodel (= 6.0.3.4)
|
activemodel (= 6.0.3.5)
|
||||||
activesupport (= 6.0.3.4)
|
activesupport (= 6.0.3.5)
|
||||||
activestorage (6.0.3.4)
|
activestorage (6.0.3.5)
|
||||||
actionpack (= 6.0.3.4)
|
actionpack (= 6.0.3.5)
|
||||||
activejob (= 6.0.3.4)
|
activejob (= 6.0.3.5)
|
||||||
activerecord (= 6.0.3.4)
|
activerecord (= 6.0.3.5)
|
||||||
marcel (~> 0.3.1)
|
marcel (~> 0.3.1)
|
||||||
activestorage-openstack (1.4.1)
|
activestorage-openstack (1.5.1)
|
||||||
fog-openstack (~> 1.0)
|
fog-openstack (~> 1.0)
|
||||||
marcel
|
marcel
|
||||||
mime-types
|
|
||||||
rails (>= 5.2.2)
|
rails (>= 5.2.2)
|
||||||
activesupport (6.0.3.4)
|
activesupport (6.0.3.5)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
minitest (~> 5.1)
|
minitest (~> 5.1)
|
||||||
|
@ -111,11 +110,11 @@ GEM
|
||||||
annotate (3.1.1)
|
annotate (3.1.1)
|
||||||
activerecord (>= 3.2, < 7.0)
|
activerecord (>= 3.2, < 7.0)
|
||||||
rake (>= 10.4, < 14.0)
|
rake (>= 10.4, < 14.0)
|
||||||
ast (2.4.1)
|
ast (2.4.2)
|
||||||
attr_encrypted (3.1.0)
|
attr_encrypted (3.1.0)
|
||||||
encryptor (~> 3.0.0)
|
encryptor (~> 3.0.0)
|
||||||
attr_required (1.0.1)
|
attr_required (1.0.1)
|
||||||
autoprefixer-rails (10.0.1.0)
|
autoprefixer-rails (10.2.4.0)
|
||||||
execjs
|
execjs
|
||||||
axe-matchers (2.6.1)
|
axe-matchers (2.6.1)
|
||||||
dumb_delegator (~> 0.8)
|
dumb_delegator (~> 0.8)
|
||||||
|
@ -124,7 +123,7 @@ GEM
|
||||||
descendants_tracker (~> 0.0.4)
|
descendants_tracker (~> 0.0.4)
|
||||||
ice_nine (~> 0.11.0)
|
ice_nine (~> 0.11.0)
|
||||||
thread_safe (~> 0.3, >= 0.3.1)
|
thread_safe (~> 0.3, >= 0.3.1)
|
||||||
axlsx_styler (1.0.0)
|
axlsx_styler (1.1.0)
|
||||||
activesupport (>= 3.1)
|
activesupport (>= 3.1)
|
||||||
caxlsx (>= 2.0.2)
|
caxlsx (>= 2.0.2)
|
||||||
babel-source (5.8.35)
|
babel-source (5.8.35)
|
||||||
|
@ -134,22 +133,22 @@ GEM
|
||||||
bcrypt (3.1.16)
|
bcrypt (3.1.16)
|
||||||
bindata (2.4.8)
|
bindata (2.4.8)
|
||||||
bindex (0.8.1)
|
bindex (0.8.1)
|
||||||
brakeman (4.9.1)
|
brakeman (5.0.0)
|
||||||
browser (5.0.0)
|
browser (5.3.0)
|
||||||
builder (3.2.4)
|
builder (3.2.4)
|
||||||
byebug (11.1.3)
|
byebug (11.1.3)
|
||||||
capybara (3.33.0)
|
capybara (3.35.3)
|
||||||
addressable
|
addressable
|
||||||
mini_mime (>= 0.1.3)
|
mini_mime (>= 0.1.3)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
rack (>= 1.6.0)
|
rack (>= 1.6.0)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
regexp_parser (~> 1.5)
|
regexp_parser (>= 1.5, < 3.0)
|
||||||
xpath (~> 3.2)
|
xpath (~> 3.2)
|
||||||
capybara-email (3.0.2)
|
capybara-email (3.0.2)
|
||||||
capybara (>= 2.4, < 4.0)
|
capybara (>= 2.4, < 4.0)
|
||||||
mail
|
mail
|
||||||
capybara-screenshot (1.0.24)
|
capybara-screenshot (1.0.25)
|
||||||
capybara (>= 1.0, < 4)
|
capybara (>= 1.0, < 4)
|
||||||
launchy
|
launchy
|
||||||
capybara-selenium (0.0.6)
|
capybara-selenium (0.0.6)
|
||||||
|
@ -157,15 +156,15 @@ GEM
|
||||||
selenium-webdriver
|
selenium-webdriver
|
||||||
case_transform (0.2)
|
case_transform (0.2)
|
||||||
activesupport
|
activesupport
|
||||||
caxlsx (3.0.2)
|
caxlsx (3.0.4)
|
||||||
htmlentities (~> 4.3, >= 4.3.4)
|
htmlentities (~> 4.3, >= 4.3.4)
|
||||||
mimemagic (~> 0.3)
|
mimemagic (~> 0.3)
|
||||||
nokogiri (~> 1.10, >= 1.10.4)
|
nokogiri (~> 1.10, >= 1.10.4)
|
||||||
rubyzip (>= 1.3.0, < 3)
|
rubyzip (>= 1.3.0, < 3)
|
||||||
chartkick (3.4.0)
|
chartkick (3.4.2)
|
||||||
childprocess (3.0.0)
|
childprocess (3.0.0)
|
||||||
choice (0.2.0)
|
choice (0.2.0)
|
||||||
chunky_png (1.3.11)
|
chunky_png (1.4.0)
|
||||||
clamav-client (3.2.0)
|
clamav-client (3.2.0)
|
||||||
coderay (1.1.3)
|
coderay (1.1.3)
|
||||||
coercible (1.0.0)
|
coercible (1.0.0)
|
||||||
|
@ -179,22 +178,28 @@ GEM
|
||||||
coffee-script-source (1.12.2)
|
coffee-script-source (1.12.2)
|
||||||
concurrent-ruby (1.1.8)
|
concurrent-ruby (1.1.8)
|
||||||
connection_pool (2.2.3)
|
connection_pool (2.2.3)
|
||||||
crack (0.4.4)
|
crack (0.4.5)
|
||||||
|
rexml
|
||||||
crass (1.0.6)
|
crass (1.0.6)
|
||||||
css_parser (1.7.1)
|
css_parser (1.9.0)
|
||||||
addressable
|
addressable
|
||||||
daemons (1.3.1)
|
daemons (1.3.1)
|
||||||
database_cleaner (1.8.5)
|
database_cleaner (2.0.1)
|
||||||
|
database_cleaner-active_record (~> 2.0.0)
|
||||||
|
database_cleaner-active_record (2.0.0)
|
||||||
|
activerecord (>= 5.a)
|
||||||
|
database_cleaner-core (~> 2.0.0)
|
||||||
|
database_cleaner-core (2.0.1)
|
||||||
datetime_picker_rails (0.0.7)
|
datetime_picker_rails (0.0.7)
|
||||||
momentjs-rails (>= 2.8.1)
|
momentjs-rails (>= 2.8.1)
|
||||||
deep_cloneable (3.0.0)
|
deep_cloneable (3.0.0)
|
||||||
activerecord (>= 3.1.0, < 7)
|
activerecord (>= 3.1.0, < 7)
|
||||||
delayed_cron_job (0.7.3)
|
delayed_cron_job (0.7.4)
|
||||||
delayed_job (>= 4.1)
|
delayed_job (>= 4.1)
|
||||||
delayed_job (4.1.8)
|
delayed_job (4.1.9)
|
||||||
activesupport (>= 3.0, < 6.1)
|
activesupport (>= 3.0, < 6.2)
|
||||||
delayed_job_active_record (4.1.4)
|
delayed_job_active_record (4.1.5)
|
||||||
activerecord (>= 3.0, < 6.1)
|
activerecord (>= 3.0, < 6.2)
|
||||||
delayed_job (>= 3.0, < 5)
|
delayed_job (>= 3.0, < 5)
|
||||||
delayed_job_web (1.4.3)
|
delayed_job_web (1.4.3)
|
||||||
activerecord (> 3.0.0)
|
activerecord (> 3.0.0)
|
||||||
|
@ -225,9 +230,9 @@ GEM
|
||||||
railties (>= 3.2)
|
railties (>= 3.2)
|
||||||
dry-inflector (0.2.0)
|
dry-inflector (0.2.0)
|
||||||
dumb_delegator (0.8.1)
|
dumb_delegator (0.8.1)
|
||||||
ecma-re-validator (0.2.1)
|
ecma-re-validator (0.3.0)
|
||||||
regexp_parser (~> 1.2)
|
regexp_parser (~> 2.0)
|
||||||
em-websocket (0.5.1)
|
em-websocket (0.5.2)
|
||||||
eventmachine (>= 0.12.9)
|
eventmachine (>= 0.12.9)
|
||||||
http_parser.rb (~> 0.6.0)
|
http_parser.rb (~> 0.6.0)
|
||||||
encryptor (3.0.0)
|
encryptor (3.0.0)
|
||||||
|
@ -239,28 +244,28 @@ GEM
|
||||||
ethon (0.12.0)
|
ethon (0.12.0)
|
||||||
ffi (>= 1.3.0)
|
ffi (>= 1.3.0)
|
||||||
eventmachine (1.2.7)
|
eventmachine (1.2.7)
|
||||||
excon (0.76.0)
|
excon (0.79.0)
|
||||||
execjs (2.7.0)
|
execjs (2.7.0)
|
||||||
factory_bot (5.1.2)
|
factory_bot (6.1.0)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 5.0.0)
|
||||||
faraday (1.3.0)
|
faraday (1.3.0)
|
||||||
faraday-net_http (~> 1.0)
|
faraday-net_http (~> 1.0)
|
||||||
multipart-post (>= 1.2, < 3)
|
multipart-post (>= 1.2, < 3)
|
||||||
ruby2_keywords
|
ruby2_keywords
|
||||||
faraday-net_http (1.0.1)
|
faraday-net_http (1.0.1)
|
||||||
ffi (1.13.1)
|
ffi (1.14.2)
|
||||||
ffi-geos (2.1.0)
|
ffi-geos (2.1.0)
|
||||||
ffi (>= 1.0.0)
|
ffi (>= 1.0.0)
|
||||||
flipper (0.19.0)
|
flipper (0.20.3)
|
||||||
flipper-active_record (0.19.0)
|
flipper-active_record (0.20.3)
|
||||||
activerecord (>= 5.0, < 7)
|
activerecord (>= 5.0, < 7)
|
||||||
flipper (~> 0.19.0)
|
flipper (~> 0.20.3)
|
||||||
flipper-ui (0.19.0)
|
flipper-ui (0.20.3)
|
||||||
erubi (>= 1.0.0, < 2.0.0)
|
erubi (>= 1.0.0, < 2.0.0)
|
||||||
flipper (~> 0.19.0)
|
flipper (~> 0.20.3)
|
||||||
rack (>= 1.4, < 3)
|
rack (>= 1.4, < 3)
|
||||||
rack-protection (>= 1.5.3, < 2.1.0)
|
rack-protection (>= 1.5.3, < 2.2.0)
|
||||||
fog-core (2.2.0)
|
fog-core (2.2.3)
|
||||||
builder
|
builder
|
||||||
excon (~> 0.71)
|
excon (~> 0.71)
|
||||||
formatador (~> 0.2)
|
formatador (~> 0.2)
|
||||||
|
@ -268,16 +273,16 @@ GEM
|
||||||
fog-json (1.2.0)
|
fog-json (1.2.0)
|
||||||
fog-core
|
fog-core
|
||||||
multi_json (~> 1.10)
|
multi_json (~> 1.10)
|
||||||
fog-openstack (1.0.10)
|
fog-openstack (1.0.11)
|
||||||
fog-core (~> 2.1)
|
fog-core (~> 2.1)
|
||||||
fog-json (>= 1.0)
|
fog-json (>= 1.0)
|
||||||
ipaddress (>= 0.8)
|
ipaddress (>= 0.8)
|
||||||
formatador (0.2.5)
|
formatador (0.2.5)
|
||||||
fugit (1.3.4)
|
fugit (1.4.2)
|
||||||
et-orbi (~> 1.1, >= 1.1.8)
|
et-orbi (~> 1.1, >= 1.1.8)
|
||||||
raabro (~> 1.1)
|
raabro (~> 1.4)
|
||||||
geo_coord (0.1.0)
|
geo_coord (0.2.0)
|
||||||
geocoder (1.6.3)
|
geocoder (1.6.5)
|
||||||
globalid (0.4.2)
|
globalid (0.4.2)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
gon (6.4.0)
|
gon (6.4.0)
|
||||||
|
@ -285,11 +290,11 @@ GEM
|
||||||
i18n (>= 0.7)
|
i18n (>= 0.7)
|
||||||
multi_json
|
multi_json
|
||||||
request_store (>= 1.0)
|
request_store (>= 1.0)
|
||||||
graphql (1.10.9)
|
graphql (1.12.4)
|
||||||
graphql-batch (0.4.3)
|
graphql-batch (0.4.3)
|
||||||
graphql (>= 1.3, < 2)
|
graphql (>= 1.3, < 2)
|
||||||
promise.rb (~> 0.7.2)
|
promise.rb (~> 0.7.2)
|
||||||
graphql-rails_logger (1.2.2)
|
graphql-rails_logger (1.2.3)
|
||||||
actionpack (> 5.0)
|
actionpack (> 5.0)
|
||||||
activesupport (> 5.0)
|
activesupport (> 5.0)
|
||||||
railties (> 5.0)
|
railties (> 5.0)
|
||||||
|
@ -300,7 +305,7 @@ GEM
|
||||||
thor (>= 0.19, < 2.0)
|
thor (>= 0.19, < 2.0)
|
||||||
graphql_playground-rails (2.1.0)
|
graphql_playground-rails (2.1.0)
|
||||||
rails (>= 5.1.0)
|
rails (>= 5.1.0)
|
||||||
groupdate (5.2.1)
|
groupdate (5.2.2)
|
||||||
activesupport (>= 5)
|
activesupport (>= 5)
|
||||||
guard (2.16.2)
|
guard (2.16.2)
|
||||||
formatador (>= 0.2.4)
|
formatador (>= 0.2.4)
|
||||||
|
@ -321,7 +326,7 @@ GEM
|
||||||
guard (~> 2.1)
|
guard (~> 2.1)
|
||||||
guard-compat (~> 1.1)
|
guard-compat (~> 1.1)
|
||||||
rspec (>= 2.99.0, < 4.0)
|
rspec (>= 2.99.0, < 4.0)
|
||||||
haml (5.1.2)
|
haml (5.2.1)
|
||||||
temple (>= 0.8.0)
|
temple (>= 0.8.0)
|
||||||
tilt
|
tilt
|
||||||
haml-lint (0.999.999)
|
haml-lint (0.999.999)
|
||||||
|
@ -332,8 +337,9 @@ GEM
|
||||||
haml (>= 4.0.6, < 6.0)
|
haml (>= 4.0.6, < 6.0)
|
||||||
html2haml (>= 1.0.1)
|
html2haml (>= 1.0.1)
|
||||||
railties (>= 5.1)
|
railties (>= 5.1)
|
||||||
haml_lint (0.35.0)
|
haml_lint (0.37.0)
|
||||||
haml (>= 4.0, < 5.2)
|
haml (>= 4.0, < 5.3)
|
||||||
|
parallel (~> 1.10)
|
||||||
rainbow
|
rainbow
|
||||||
rubocop (>= 0.50.0)
|
rubocop (>= 0.50.0)
|
||||||
sysexits (~> 1.1)
|
sysexits (~> 1.1)
|
||||||
|
@ -353,7 +359,7 @@ GEM
|
||||||
http_accept_language (2.1.1)
|
http_accept_language (2.1.1)
|
||||||
http_parser.rb (0.6.0)
|
http_parser.rb (0.6.0)
|
||||||
httpclient (2.8.3)
|
httpclient (2.8.3)
|
||||||
i18n (1.8.7)
|
i18n (1.8.9)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
i18n-tasks (0.9.33)
|
i18n-tasks (0.9.33)
|
||||||
activesupport (>= 4.0.2)
|
activesupport (>= 4.0.2)
|
||||||
|
@ -375,15 +381,15 @@ GEM
|
||||||
rails-dom-testing (>= 1, < 3)
|
rails-dom-testing (>= 1, < 3)
|
||||||
railties (>= 4.2.0)
|
railties (>= 4.2.0)
|
||||||
thor (>= 0.14, < 2.0)
|
thor (>= 0.14, < 2.0)
|
||||||
json (2.3.1)
|
json (2.5.1)
|
||||||
json-jwt (1.13.0)
|
json-jwt (1.13.0)
|
||||||
activesupport (>= 4.2)
|
activesupport (>= 4.2)
|
||||||
aes_key_wrap
|
aes_key_wrap
|
||||||
bindata
|
bindata
|
||||||
json_schemer (0.2.16)
|
json_schemer (0.2.17)
|
||||||
ecma-re-validator (~> 0.2)
|
ecma-re-validator (~> 0.3)
|
||||||
hana (~> 1.3)
|
hana (~> 1.3)
|
||||||
regexp_parser (~> 1.5)
|
regexp_parser (~> 2.0)
|
||||||
uri_template (~> 0.7)
|
uri_template (~> 0.7)
|
||||||
jsonapi-renderer (0.2.2)
|
jsonapi-renderer (0.2.2)
|
||||||
jwt (2.2.2)
|
jwt (2.2.2)
|
||||||
|
@ -407,7 +413,7 @@ GEM
|
||||||
actionmailer (>= 3.2)
|
actionmailer (>= 3.2)
|
||||||
letter_opener (~> 1.0)
|
letter_opener (~> 1.0)
|
||||||
railties (>= 3.2)
|
railties (>= 3.2)
|
||||||
listen (3.2.1)
|
listen (3.4.1)
|
||||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||||
rb-inotify (~> 0.9, >= 0.9.10)
|
rb-inotify (~> 0.9, >= 0.9.10)
|
||||||
lograge (0.11.2)
|
lograge (0.11.2)
|
||||||
|
@ -419,19 +425,19 @@ GEM
|
||||||
loofah (2.9.0)
|
loofah (2.9.0)
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.5.9)
|
nokogiri (>= 1.5.9)
|
||||||
lumberjack (1.2.4)
|
lumberjack (1.2.8)
|
||||||
mail (2.7.1)
|
mail (2.7.1)
|
||||||
mini_mime (>= 0.1.1)
|
mini_mime (>= 0.1.1)
|
||||||
mailjet (1.5.4)
|
mailjet (1.6.0)
|
||||||
activesupport (>= 3.1.0)
|
activesupport (>= 3.1.0)
|
||||||
rack (>= 1.4.0)
|
rack (>= 1.4.0)
|
||||||
rest-client
|
rest-client (>= 2.0.0)
|
||||||
marcel (0.3.3)
|
marcel (0.3.3)
|
||||||
mimemagic (~> 0.3.2)
|
mimemagic (~> 0.3.2)
|
||||||
method_source (1.0.0)
|
method_source (1.0.0)
|
||||||
mime-types (3.3.1)
|
mime-types (3.3.1)
|
||||||
mime-types-data (~> 3.2015)
|
mime-types-data (~> 3.2015)
|
||||||
mime-types-data (3.2020.0512)
|
mime-types-data (3.2021.0212)
|
||||||
mimemagic (0.3.5)
|
mimemagic (0.3.5)
|
||||||
mini_magick (4.11.0)
|
mini_magick (4.11.0)
|
||||||
mini_mime (1.0.2)
|
mini_mime (1.0.2)
|
||||||
|
@ -445,7 +451,7 @@ GEM
|
||||||
ruby2_keywords (~> 0.0.1)
|
ruby2_keywords (~> 0.0.1)
|
||||||
nenv (0.3.0)
|
nenv (0.3.0)
|
||||||
netrc (0.11.0)
|
netrc (0.11.0)
|
||||||
nio4r (2.5.4)
|
nio4r (2.5.5)
|
||||||
nokogiri (1.11.1)
|
nokogiri (1.11.1)
|
||||||
mini_portile2 (~> 2.5.0)
|
mini_portile2 (~> 2.5.0)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
|
@ -453,7 +459,7 @@ GEM
|
||||||
nenv (~> 0.1)
|
nenv (~> 0.1)
|
||||||
shellany (~> 0.0)
|
shellany (~> 0.0)
|
||||||
open4 (1.3.4)
|
open4 (1.3.4)
|
||||||
openid_connect (1.1.8)
|
openid_connect (1.2.0)
|
||||||
activemodel
|
activemodel
|
||||||
attr_required (>= 1.0.0)
|
attr_required (>= 1.0.0)
|
||||||
json-jwt (>= 1.5.0)
|
json-jwt (>= 1.5.0)
|
||||||
|
@ -464,25 +470,25 @@ GEM
|
||||||
validate_url
|
validate_url
|
||||||
webfinger (>= 1.0.1)
|
webfinger (>= 1.0.1)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
parallel (1.19.2)
|
parallel (1.20.1)
|
||||||
parser (2.7.1.5)
|
parser (3.0.0.0)
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
pdf-core (0.7.0)
|
pdf-core (0.9.0)
|
||||||
pg (1.2.3)
|
pg (1.2.3)
|
||||||
phonelib (0.6.45)
|
phonelib (0.6.48)
|
||||||
prawn (2.2.2)
|
prawn (2.4.0)
|
||||||
pdf-core (~> 0.7.0)
|
pdf-core (~> 0.9.0)
|
||||||
ttfunk (~> 1.5)
|
ttfunk (~> 1.7)
|
||||||
prawn-rails (1.3.0)
|
prawn-rails (1.3.0)
|
||||||
prawn
|
prawn
|
||||||
prawn-table
|
prawn-table
|
||||||
rails (>= 3.1.0)
|
rails (>= 3.1.0)
|
||||||
prawn-svg (0.30.0)
|
prawn-svg (0.31.0)
|
||||||
css_parser (~> 1.6)
|
css_parser (~> 1.6)
|
||||||
prawn (>= 0.11.1, < 3)
|
prawn (>= 0.11.1, < 3)
|
||||||
prawn-table (0.2.2)
|
prawn-table (0.2.2)
|
||||||
prawn (>= 1.3.0, < 3.0.0)
|
prawn (>= 1.3.0, < 3.0.0)
|
||||||
premailer (1.14.1)
|
premailer (1.14.2)
|
||||||
addressable
|
addressable
|
||||||
css_parser (>= 1.6.0)
|
css_parser (>= 1.6.0)
|
||||||
htmlentities (>= 4.0.0)
|
htmlentities (>= 4.0.0)
|
||||||
|
@ -497,43 +503,43 @@ GEM
|
||||||
byebug (~> 11.0)
|
byebug (~> 11.0)
|
||||||
pry (~> 0.13.0)
|
pry (~> 0.13.0)
|
||||||
public_suffix (4.0.6)
|
public_suffix (4.0.6)
|
||||||
puma (5.0.2)
|
puma (5.2.1)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
pundit (2.1.0)
|
pundit (2.1.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
raabro (1.1.6)
|
raabro (1.4.0)
|
||||||
racc (1.5.2)
|
racc (1.5.2)
|
||||||
rack (2.2.3)
|
rack (2.2.3)
|
||||||
rack-attack (6.3.1)
|
rack-attack (6.5.0)
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 1.0, < 3)
|
||||||
rack-mini-profiler (2.1.0)
|
rack-mini-profiler (2.3.1)
|
||||||
rack (>= 1.2.0)
|
rack (>= 1.2.0)
|
||||||
rack-oauth2 (1.15.0)
|
rack-oauth2 (1.16.0)
|
||||||
activesupport
|
activesupport
|
||||||
attr_required
|
attr_required
|
||||||
httpclient
|
httpclient
|
||||||
json-jwt (>= 1.11.0)
|
json-jwt (>= 1.11.0)
|
||||||
rack (>= 2.1.0)
|
rack (>= 2.1.0)
|
||||||
rack-protection (2.0.8.1)
|
rack-protection (2.1.0)
|
||||||
rack
|
rack
|
||||||
rack-proxy (0.6.5)
|
rack-proxy (0.6.5)
|
||||||
rack
|
rack
|
||||||
rack-test (1.1.0)
|
rack-test (1.1.0)
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 1.0, < 3)
|
||||||
rails (6.0.3.4)
|
rails (6.0.3.5)
|
||||||
actioncable (= 6.0.3.4)
|
actioncable (= 6.0.3.5)
|
||||||
actionmailbox (= 6.0.3.4)
|
actionmailbox (= 6.0.3.5)
|
||||||
actionmailer (= 6.0.3.4)
|
actionmailer (= 6.0.3.5)
|
||||||
actionpack (= 6.0.3.4)
|
actionpack (= 6.0.3.5)
|
||||||
actiontext (= 6.0.3.4)
|
actiontext (= 6.0.3.5)
|
||||||
actionview (= 6.0.3.4)
|
actionview (= 6.0.3.5)
|
||||||
activejob (= 6.0.3.4)
|
activejob (= 6.0.3.5)
|
||||||
activemodel (= 6.0.3.4)
|
activemodel (= 6.0.3.5)
|
||||||
activerecord (= 6.0.3.4)
|
activerecord (= 6.0.3.5)
|
||||||
activestorage (= 6.0.3.4)
|
activestorage (= 6.0.3.5)
|
||||||
activesupport (= 6.0.3.4)
|
activesupport (= 6.0.3.5)
|
||||||
bundler (>= 1.3.0)
|
bundler (>= 1.3.0)
|
||||||
railties (= 6.0.3.4)
|
railties (= 6.0.3.5)
|
||||||
sprockets-rails (>= 2.0.0)
|
sprockets-rails (>= 2.0.0)
|
||||||
rails-controller-testing (1.0.5)
|
rails-controller-testing (1.0.5)
|
||||||
actionpack (>= 5.0.1.rc1)
|
actionpack (>= 5.0.1.rc1)
|
||||||
|
@ -552,9 +558,9 @@ GEM
|
||||||
rails-i18n (6.0.0)
|
rails-i18n (6.0.0)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
railties (>= 6.0.0, < 7)
|
railties (>= 6.0.0, < 7)
|
||||||
railties (6.0.3.4)
|
railties (6.0.3.5)
|
||||||
actionpack (= 6.0.3.4)
|
actionpack (= 6.0.3.5)
|
||||||
activesupport (= 6.0.3.4)
|
activesupport (= 6.0.3.5)
|
||||||
method_source
|
method_source
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
thor (>= 0.20.3, < 2.0)
|
thor (>= 0.20.3, < 2.0)
|
||||||
|
@ -570,7 +576,7 @@ GEM
|
||||||
execjs
|
execjs
|
||||||
railties (>= 3.2)
|
railties (>= 3.2)
|
||||||
tilt
|
tilt
|
||||||
regexp_parser (1.8.0)
|
regexp_parser (2.0.3)
|
||||||
request_store (1.5.0)
|
request_store (1.5.0)
|
||||||
rack (>= 1.4)
|
rack (>= 1.4)
|
||||||
responders (3.0.1)
|
responders (3.0.1)
|
||||||
|
@ -582,7 +588,7 @@ GEM
|
||||||
mime-types (>= 1.16, < 4.0)
|
mime-types (>= 1.16, < 4.0)
|
||||||
netrc (~> 0.8)
|
netrc (~> 0.8)
|
||||||
rexml (3.2.4)
|
rexml (3.2.4)
|
||||||
rgeo (2.1.1)
|
rgeo (2.2.0)
|
||||||
rgeo-geojson (2.1.1)
|
rgeo-geojson (2.1.1)
|
||||||
rgeo (>= 1.0.0)
|
rgeo (>= 1.0.0)
|
||||||
rodf (1.1.1)
|
rodf (1.1.1)
|
||||||
|
@ -591,56 +597,59 @@ GEM
|
||||||
rubyzip (>= 1.0)
|
rubyzip (>= 1.0)
|
||||||
rotp (4.1.0)
|
rotp (4.1.0)
|
||||||
addressable (~> 2.5)
|
addressable (~> 2.5)
|
||||||
rouge (3.17.0)
|
rouge (3.26.0)
|
||||||
rqrcode (1.1.2)
|
rqrcode (1.2.0)
|
||||||
chunky_png (~> 1.0)
|
chunky_png (~> 1.0)
|
||||||
rqrcode_core (~> 0.1)
|
rqrcode_core (~> 0.2)
|
||||||
rqrcode_core (0.1.2)
|
rqrcode_core (0.2.0)
|
||||||
rspec (3.9.0)
|
rspec (3.10.0)
|
||||||
rspec-core (~> 3.9.0)
|
rspec-core (~> 3.10.0)
|
||||||
rspec-expectations (~> 3.9.0)
|
rspec-expectations (~> 3.10.0)
|
||||||
rspec-mocks (~> 3.9.0)
|
rspec-mocks (~> 3.10.0)
|
||||||
rspec-core (3.9.2)
|
rspec-core (3.10.1)
|
||||||
rspec-support (~> 3.9.3)
|
rspec-support (~> 3.10.0)
|
||||||
rspec-expectations (3.9.2)
|
rspec-expectations (3.10.1)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.9.0)
|
rspec-support (~> 3.10.0)
|
||||||
rspec-mocks (3.9.1)
|
rspec-mocks (3.10.2)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.9.0)
|
rspec-support (~> 3.10.0)
|
||||||
rspec-rails (4.0.1)
|
rspec-rails (4.0.2)
|
||||||
actionpack (>= 4.2)
|
actionpack (>= 4.2)
|
||||||
activesupport (>= 4.2)
|
activesupport (>= 4.2)
|
||||||
railties (>= 4.2)
|
railties (>= 4.2)
|
||||||
rspec-core (~> 3.9)
|
rspec-core (~> 3.10)
|
||||||
rspec-expectations (~> 3.9)
|
rspec-expectations (~> 3.10)
|
||||||
rspec-mocks (~> 3.9)
|
rspec-mocks (~> 3.10)
|
||||||
rspec-support (~> 3.9)
|
rspec-support (~> 3.10)
|
||||||
rspec-support (3.9.3)
|
rspec-support (3.10.2)
|
||||||
rspec_junit_formatter (0.4.1)
|
rspec_junit_formatter (0.4.1)
|
||||||
rspec-core (>= 2, < 4, != 2.12.0)
|
rspec-core (>= 2, < 4, != 2.12.0)
|
||||||
rubocop (0.92.0)
|
rubocop (1.10.0)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
parser (>= 2.7.1.5)
|
parser (>= 3.0.0.0)
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
regexp_parser (>= 1.7)
|
regexp_parser (>= 1.8, < 3.0)
|
||||||
rexml
|
rexml
|
||||||
rubocop-ast (>= 0.5.0)
|
rubocop-ast (>= 1.2.0, < 2.0)
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 1.4.0, < 2.0)
|
unicode-display_width (>= 1.4.0, < 3.0)
|
||||||
rubocop-ast (0.7.0)
|
rubocop-ast (1.4.1)
|
||||||
parser (>= 2.7.1.5)
|
parser (>= 2.7.1.5)
|
||||||
strscan (>= 1.0.0)
|
rubocop-packaging (0.5.1)
|
||||||
rubocop-performance (1.8.1)
|
rubocop (>= 0.89, < 2.0)
|
||||||
rubocop (>= 0.87.0)
|
rubocop-performance (1.9.2)
|
||||||
|
rubocop (>= 0.90.0, < 2.0)
|
||||||
rubocop-ast (>= 0.4.0)
|
rubocop-ast (>= 0.4.0)
|
||||||
rubocop-rails (2.8.1)
|
rubocop-rails (2.9.1)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
rack (>= 1.1)
|
rack (>= 1.1)
|
||||||
rubocop (>= 0.87.0)
|
rubocop (>= 0.90.0, < 2.0)
|
||||||
rubocop-rails_config (0.12.6)
|
rubocop-rails_config (1.3.0)
|
||||||
railties (>= 5.0)
|
railties (>= 5.0)
|
||||||
rubocop (~> 0.82)
|
rubocop (>= 1.8)
|
||||||
|
rubocop-ast (>= 1.0.1)
|
||||||
|
rubocop-packaging (~> 0.5)
|
||||||
rubocop-performance (~> 1.3)
|
rubocop-performance (~> 1.3)
|
||||||
rubocop-rails (~> 2.0)
|
rubocop-rails (~> 2.0)
|
||||||
rubocop-rspec-focused (1.0.0)
|
rubocop-rspec-focused (1.0.0)
|
||||||
|
@ -649,12 +658,12 @@ GEM
|
||||||
rake (>= 0.8.1)
|
rake (>= 0.8.1)
|
||||||
ruby-graphviz (1.2.5)
|
ruby-graphviz (1.2.5)
|
||||||
rexml
|
rexml
|
||||||
ruby-progressbar (1.10.1)
|
ruby-progressbar (1.11.0)
|
||||||
ruby-saml-idp (0.3.5)
|
ruby-saml-idp (0.3.5)
|
||||||
ruby-vips (2.0.17)
|
ruby-vips (2.0.17)
|
||||||
ffi (~> 1.9)
|
ffi (~> 1.9)
|
||||||
ruby2_keywords (0.0.4)
|
ruby2_keywords (0.0.4)
|
||||||
ruby_parser (3.15.0)
|
ruby_parser (3.15.1)
|
||||||
sexp_processor (~> 4.9)
|
sexp_processor (~> 4.9)
|
||||||
rubyzip (2.3.0)
|
rubyzip (2.3.0)
|
||||||
sanitize-url (0.1.4)
|
sanitize-url (0.1.4)
|
||||||
|
@ -677,7 +686,7 @@ GEM
|
||||||
selenium-webdriver (3.142.7)
|
selenium-webdriver (3.142.7)
|
||||||
childprocess (>= 0.5, < 4.0)
|
childprocess (>= 0.5, < 4.0)
|
||||||
rubyzip (>= 1.2.2)
|
rubyzip (>= 1.2.2)
|
||||||
semantic_range (2.3.0)
|
semantic_range (2.3.1)
|
||||||
sentry-delayed_job (4.2.0)
|
sentry-delayed_job (4.2.0)
|
||||||
sentry-ruby-core (~> 4.2.0)
|
sentry-ruby-core (~> 4.2.0)
|
||||||
sentry-rails (4.2.1)
|
sentry-rails (4.2.1)
|
||||||
|
@ -690,31 +699,31 @@ GEM
|
||||||
sentry-ruby-core (4.2.1)
|
sentry-ruby-core (4.2.1)
|
||||||
concurrent-ruby
|
concurrent-ruby
|
||||||
faraday
|
faraday
|
||||||
sexp_processor (4.15.1)
|
sexp_processor (4.15.2)
|
||||||
shellany (0.0.1)
|
shellany (0.0.1)
|
||||||
shoulda-matchers (4.4.1)
|
shoulda-matchers (4.5.1)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
sib-api-v3-sdk (7.0.0)
|
sib-api-v3-sdk (7.4.0)
|
||||||
json (~> 2.1, >= 2.1.0)
|
json (~> 2.1, >= 2.1.0)
|
||||||
typhoeus (~> 1.0, >= 1.0.1)
|
typhoeus (~> 1.0, >= 1.0.1)
|
||||||
simple_xlsx_reader (1.0.4)
|
simple_xlsx_reader (1.0.4)
|
||||||
nokogiri
|
nokogiri
|
||||||
rubyzip
|
rubyzip
|
||||||
sinatra (2.0.8.1)
|
sinatra (2.1.0)
|
||||||
mustermann (~> 1.0)
|
mustermann (~> 1.0)
|
||||||
rack (~> 2.0)
|
rack (~> 2.2)
|
||||||
rack-protection (= 2.0.8.1)
|
rack-protection (= 2.1.0)
|
||||||
tilt (~> 2.0)
|
tilt (~> 2.0)
|
||||||
skylight (4.3.1)
|
skylight (4.3.2)
|
||||||
skylight-core (= 4.3.1)
|
skylight-core (= 4.3.2)
|
||||||
skylight-core (4.3.1)
|
skylight-core (4.3.2)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
smart_listing (1.2.3)
|
smart_listing (1.2.3)
|
||||||
coffee-rails
|
coffee-rails
|
||||||
jquery-rails
|
jquery-rails
|
||||||
kaminari (>= 0.17)
|
kaminari (>= 0.17)
|
||||||
rails (>= 3.2)
|
rails (>= 3.2)
|
||||||
spreadsheet_architect (4.0.0)
|
spreadsheet_architect (4.1.0)
|
||||||
axlsx_styler (>= 1.0.0, < 2)
|
axlsx_styler (>= 1.0.0, < 2)
|
||||||
caxlsx (>= 2.0.2, < 4)
|
caxlsx (>= 2.0.2, < 4)
|
||||||
rodf (>= 1.0.0, < 2)
|
rodf (>= 1.0.0, < 2)
|
||||||
|
@ -728,8 +737,7 @@ GEM
|
||||||
actionpack (>= 4.0)
|
actionpack (>= 4.0)
|
||||||
activesupport (>= 4.0)
|
activesupport (>= 4.0)
|
||||||
sprockets (>= 3.0.0)
|
sprockets (>= 3.0.0)
|
||||||
strscan (1.0.3)
|
swd (1.2.0)
|
||||||
swd (1.1.2)
|
|
||||||
activesupport (>= 3)
|
activesupport (>= 3)
|
||||||
attr_required (>= 0.0.5)
|
attr_required (>= 0.0.5)
|
||||||
httpclient (>= 2.4)
|
httpclient (>= 2.4)
|
||||||
|
@ -740,8 +748,8 @@ GEM
|
||||||
thor (1.1.0)
|
thor (1.1.0)
|
||||||
thread_safe (0.3.6)
|
thread_safe (0.3.6)
|
||||||
tilt (2.0.10)
|
tilt (2.0.10)
|
||||||
timecop (0.9.1)
|
timecop (0.9.4)
|
||||||
ttfunk (1.6.2.1)
|
ttfunk (1.7.0)
|
||||||
typhoeus (1.4.0)
|
typhoeus (1.4.0)
|
||||||
ethon (>= 0.9.0)
|
ethon (>= 0.9.0)
|
||||||
tzinfo (1.2.9)
|
tzinfo (1.2.9)
|
||||||
|
@ -754,7 +762,7 @@ GEM
|
||||||
validate_email (0.1.6)
|
validate_email (0.1.6)
|
||||||
activemodel (>= 3.0)
|
activemodel (>= 3.0)
|
||||||
mail (>= 2.2.5)
|
mail (>= 2.2.5)
|
||||||
validate_url (1.0.11)
|
validate_url (1.0.13)
|
||||||
activemodel (>= 3.0.0)
|
activemodel (>= 3.0.0)
|
||||||
public_suffix
|
public_suffix
|
||||||
vcr (6.0.0)
|
vcr (6.0.0)
|
||||||
|
@ -765,19 +773,19 @@ GEM
|
||||||
equalizer (~> 0.0, >= 0.0.9)
|
equalizer (~> 0.0, >= 0.0.9)
|
||||||
warden (1.2.9)
|
warden (1.2.9)
|
||||||
rack (>= 2.0.9)
|
rack (>= 2.0.9)
|
||||||
web-console (4.0.4)
|
web-console (4.1.0)
|
||||||
actionview (>= 6.0.0)
|
actionview (>= 6.0.0)
|
||||||
activemodel (>= 6.0.0)
|
activemodel (>= 6.0.0)
|
||||||
bindex (>= 0.4.0)
|
bindex (>= 0.4.0)
|
||||||
railties (>= 6.0.0)
|
railties (>= 6.0.0)
|
||||||
webdrivers (4.4.1)
|
webdrivers (4.5.0)
|
||||||
nokogiri (~> 1.6)
|
nokogiri (~> 1.6)
|
||||||
rubyzip (>= 1.3.0)
|
rubyzip (>= 1.3.0)
|
||||||
selenium-webdriver (>= 3.0, < 4.0)
|
selenium-webdriver (>= 3.0, < 4.0)
|
||||||
webfinger (1.1.0)
|
webfinger (1.1.0)
|
||||||
activesupport
|
activesupport
|
||||||
httpclient (>= 2.4)
|
httpclient (>= 2.4)
|
||||||
webmock (3.9.1)
|
webmock (3.11.2)
|
||||||
addressable (>= 2.3.6)
|
addressable (>= 2.3.6)
|
||||||
crack (>= 0.3.2)
|
crack (>= 0.3.2)
|
||||||
hashdiff (>= 0.4.0, < 2.0.0)
|
hashdiff (>= 0.4.0, < 2.0.0)
|
||||||
|
@ -798,7 +806,7 @@ GEM
|
||||||
zipline (1.3.0)
|
zipline (1.3.0)
|
||||||
actionpack (>= 3.2.1, < 7.0)
|
actionpack (>= 3.2.1, < 7.0)
|
||||||
zip_tricks (>= 4.2.1, < 6.0)
|
zip_tricks (>= 4.2.1, < 6.0)
|
||||||
zxcvbn-ruby (1.1.0)
|
zxcvbn-ruby (1.2.0)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|
10
README.md
10
README.md
|
@ -128,8 +128,14 @@ Le projet utilise plusieurs linters pour vérifier la lisibilité et la qualité
|
||||||
|
|
||||||
## Déploiement
|
## Déploiement
|
||||||
|
|
||||||
- Tout nouveau commit ajouté à la branche `dev` est automatiquement déployé [en intégration](https://dev.demarches-simplifiees.fr/)
|
Dans le cas d’un déploiement sur plusieurs serveurs, l’application peut être déployée avec la tâche :
|
||||||
- Tout nouveau commit ajouté à la branche `master` est automatiquement déployé [en production](https://www.demarches-simplifiees.fr/)
|
|
||||||
|
```
|
||||||
|
DOMAINS="web1 web2" BRANCH="main" bin/rake deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
En interne, cette tâche utilise [mina](https://github.com/mina-deploy/mina) pour lancer les commandes
|
||||||
|
de déploiement sur tous les serveurs spécifiés.
|
||||||
|
|
||||||
## Tâches courantes
|
## Tâches courantes
|
||||||
|
|
||||||
|
|
|
@ -5,34 +5,4 @@
|
||||||
.select-instructeurs {
|
.select-instructeurs {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select2-container--default {
|
|
||||||
.select2-selection--multiple {
|
|
||||||
border: solid 1px $border-grey;
|
|
||||||
|
|
||||||
.select2-selection__choice, // scss-lint:disable SelectorFormat
|
|
||||||
.select2-search--inline {
|
|
||||||
padding: $default-spacer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.select2-container--focus {
|
|
||||||
.select2-selection--multiple {
|
|
||||||
border: 1px solid $blue;
|
|
||||||
box-shadow: 0px 0px 2px 1px $blue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.select2-results__option { // scss-lint:disable SelectorFormat
|
|
||||||
padding: $default-spacer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-select2-option {
|
|
||||||
.icon {
|
|
||||||
margin-right: $default-spacer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,5 @@
|
||||||
// = require ./utils
|
// = require ./utils
|
||||||
// = require ./fonts
|
// = require ./fonts
|
||||||
// = require leaflet
|
// = require leaflet
|
||||||
// = require select2
|
|
||||||
// = require_tree .
|
// = require_tree .
|
||||||
// = stub ./print.scss
|
// = stub ./print.scss
|
||||||
|
|
|
@ -281,18 +281,6 @@
|
||||||
.dropdown-form {
|
.dropdown-form {
|
||||||
padding: 2 * $default-spacer;
|
padding: 2 * $default-spacer;
|
||||||
|
|
||||||
.select2-container {
|
|
||||||
margin-bottom: 2 * $default-spacer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.select2-selection {
|
|
||||||
border: 1px solid $border-grey;
|
|
||||||
|
|
||||||
&.select2-selection--multiple {
|
|
||||||
border: 1px solid $border-grey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.large {
|
&.large {
|
||||||
width: 340px;
|
width: 340px;
|
||||||
}
|
}
|
||||||
|
@ -310,10 +298,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.select2-dropdown {
|
|
||||||
border: 1px solid $border-grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
.link {
|
||||||
color: $blue;
|
color: $blue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,8 +260,7 @@
|
||||||
max-width: 180px;
|
max-width: 180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
select,
|
select {
|
||||||
.select2-selection {
|
|
||||||
// hack found here: https://stackoverflow.com/questions/1895476/how-to-style-a-select-dropdown-with-css-only-without-javascript
|
// hack found here: https://stackoverflow.com/questions/1895476/how-to-style-a-select-dropdown-with-css-only-without-javascript
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
|
@ -305,39 +304,26 @@
|
||||||
border-color: $blue;
|
border-color: $blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select2 {
|
[data-reach-combobox-token-list] {
|
||||||
min-width: 50%;
|
padding: $default-padding;
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select2-container {
|
[data-reach-combobox-token] {
|
||||||
display: block;
|
border: solid 1px $border-grey;
|
||||||
margin-bottom: $default-fields-spacer;
|
color: $black;
|
||||||
|
margin-top: $default-padding;
|
||||||
|
margin-bottom: $default-padding;
|
||||||
|
margin-right: 0.5 * $default-padding;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: $default-padding;
|
||||||
|
cursor: pointer;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
&.select2-container--focus {
|
[data-reach-combobox-token]:focus {
|
||||||
.select2-selection {
|
background-color: $black;
|
||||||
border-color: $border-grey;
|
color: $white;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.select2-selection--single {
|
|
||||||
min-height: 62px;
|
|
||||||
|
|
||||||
// scss-lint:disable SelectorFormat
|
|
||||||
.select2-selection__arrow {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
// scss-lint:enable
|
|
||||||
}
|
|
||||||
|
|
||||||
// scss-lint:disable SelectorFormat
|
|
||||||
.select2-selection__rendered {
|
|
||||||
padding: $default-padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.select2-selection__choice {
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
}
|
|
||||||
// scss-lint:enable
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.editable-champ {
|
.editable-champ {
|
||||||
|
@ -481,11 +467,55 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-react-class="ComboMultipleDropdownList"] {
|
||||||
|
margin-bottom: $default-fields-spacer;
|
||||||
|
|
||||||
|
[data-reach-combobox-input] {
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
flex-grow: 1;
|
||||||
|
margin: 0.25rem;
|
||||||
|
background-image: image-url("icons/chevron-down");
|
||||||
|
background-size: 14px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: right 10px center;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-reach-combobox-input]:focus {
|
||||||
|
outline: solid;
|
||||||
|
outline-color: $light-blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-combobox-token-label] {
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
[data-reach-combobox-option] {
|
[data-reach-combobox-option] {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-reach-combobox-option][aria-selected="true"] {
|
[data-reach-combobox-option][aria-selected="true"] {
|
||||||
background: $light-blue !important;
|
background: $light-blue !important;
|
||||||
color: $white;
|
color: $white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-combobox-separator] {
|
||||||
|
font-size: 16px;
|
||||||
|
color: $dark-grey;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-combobox-remove-token] {
|
||||||
|
color: $dark-grey;
|
||||||
|
padding-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[data-reach-combobox-input]:focus {
|
||||||
|
outline-color: $light-blue;
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,50 @@
|
||||||
|
@import "constants";
|
||||||
|
@import "colors";
|
||||||
|
|
||||||
.personnes-impliquees {
|
.personnes-impliquees {
|
||||||
padding-bottom: 50px;
|
padding-bottom: 50px;
|
||||||
|
|
||||||
ul {
|
ul.tab-list {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
margin-left: 16px;
|
margin-left: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// scss-lint:disable SelectorFormat
|
[data-react-class="ComboMultipleDropdownList"] {
|
||||||
.form .select2-container .select2-selection__rendered {
|
margin-bottom: $default-fields-spacer;
|
||||||
padding: 12px;
|
|
||||||
|
[data-reach-combobox-token-list] {
|
||||||
|
padding: 0.5 * $default-padding;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-reach-combobox-token] {
|
||||||
|
border: solid 1px $border-grey;
|
||||||
|
color: $black;
|
||||||
|
margin-top: 0.5 * $default-padding;
|
||||||
|
margin-bottom: 0.5 * $default-padding;
|
||||||
|
margin-right: 0.5 * $default-padding;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.5 * $default-padding;
|
||||||
|
cursor: pointer;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-reach-combobox-token]:focus {
|
||||||
|
background-color: $black;
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[data-reach-combobox-input] {
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
flex-grow: 1;
|
||||||
|
margin: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-reach-combobox-input]:focus {
|
||||||
|
outline: solid;
|
||||||
|
outline-color: $light-blue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// scss-lint:enable
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
flex: 10;
|
flex: 10;
|
||||||
padding: 0 $default-padding;
|
padding: 0 $default-padding;
|
||||||
background-color: $light-grey;
|
background-color: $light-grey;
|
||||||
|
|
||||||
|
&.no-background {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.procedure-form__column--preview {
|
.procedure-form__column--preview {
|
||||||
|
|
|
@ -61,4 +61,42 @@
|
||||||
margin-bottom: 3 * $default-spacer;
|
margin-bottom: 3 * $default-spacer;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-react-class="ComboMultipleDropdownList"] {
|
||||||
|
margin-bottom: $default-fields-spacer;
|
||||||
|
|
||||||
|
[data-reach-combobox-token-list] {
|
||||||
|
padding: 0.25 * $default-padding;
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-reach-combobox-token] {
|
||||||
|
border: solid 1px $border-grey;
|
||||||
|
color: $black;
|
||||||
|
margin: 0.25 * $default-padding;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0.25 * $default-padding;
|
||||||
|
cursor: pointer;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-reach-combobox-token]:focus {
|
||||||
|
background-color: $black;
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[data-reach-combobox-input] {
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
flex-grow: 1;
|
||||||
|
margin: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-reach-combobox-input]:focus {
|
||||||
|
outline: solid;
|
||||||
|
outline-color: $light-blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,10 @@ class API::V2::GraphqlController < API::V2::BaseController
|
||||||
|
|
||||||
render json: result
|
render json: result
|
||||||
rescue => exception
|
rescue => exception
|
||||||
if Rails.env.development?
|
if Rails.env.production?
|
||||||
handle_error_in_development(exception)
|
|
||||||
else
|
|
||||||
handle_error_in_production(exception)
|
handle_error_in_production(exception)
|
||||||
|
else
|
||||||
|
handle_error_in_development(exception)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ module Instructeurs
|
||||||
end
|
end
|
||||||
|
|
||||||
def send_to_instructeurs
|
def send_to_instructeurs
|
||||||
recipients = Instructeur.find(params[:recipients])
|
recipients = Instructeur.find(JSON.parse(params[:recipients]))
|
||||||
|
|
||||||
recipients.each do |recipient|
|
recipients.each do |recipient|
|
||||||
recipient.follow(dossier)
|
recipient.follow(dossier)
|
||||||
|
|
|
@ -138,7 +138,7 @@ module Instructeurs
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_displayed_fields
|
def update_displayed_fields
|
||||||
procedure_presentation.update_displayed_fields(params[:values])
|
procedure_presentation.update_displayed_fields(JSON.parse(params[:values]))
|
||||||
|
|
||||||
redirect_back(fallback_location: instructeur_procedure_url(procedure))
|
redirect_back(fallback_location: instructeur_procedure_url(procedure))
|
||||||
end
|
end
|
||||||
|
|
|
@ -60,7 +60,7 @@ module NewAdministrateur
|
||||||
|
|
||||||
def uninterlaced_png(uploaded_file)
|
def uninterlaced_png(uploaded_file)
|
||||||
if uploaded_file&.content_type == 'image/png'
|
if uploaded_file&.content_type == 'image/png'
|
||||||
chunky_img = ChunkyPNG::Image.from_io(uploaded_file)
|
chunky_img = ChunkyPNG::Image.from_io(uploaded_file.to_io)
|
||||||
chunky_img.save(uploaded_file.tempfile.to_path, interlace: false)
|
chunky_img.save(uploaded_file.tempfile.to_path, interlace: false)
|
||||||
uploaded_file.tempfile.reopen(uploaded_file.tempfile.to_path, 'rb')
|
uploaded_file.tempfile.reopen(uploaded_file.tempfile.to_path, 'rb')
|
||||||
end
|
end
|
||||||
|
|
|
@ -80,8 +80,8 @@ module NewAdministrateur
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_instructeur
|
def add_instructeur
|
||||||
emails = params['emails'].presence || []
|
emails = params['emails'].presence || [].to_json
|
||||||
emails = emails.map(&:strip).map(&:downcase)
|
emails = JSON.parse(emails).map(&:strip).map(&:downcase)
|
||||||
|
|
||||||
correct_emails, bad_emails = emails
|
correct_emails, bad_emails = emails
|
||||||
.partition { |email| URI::MailTo::EMAIL_REGEXP.match?(email) }
|
.partition { |email| URI::MailTo::EMAIL_REGEXP.match?(email) }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module NewAdministrateur
|
module NewAdministrateur
|
||||||
class ProceduresController < AdministrateurController
|
class ProceduresController < AdministrateurController
|
||||||
before_action :retrieve_procedure, only: [:champs, :annotations, :edit, :monavis, :update_monavis, :jeton, :update_jeton, :publication, :publish, :transfert, :allow_expert_review, :invited_expert_list]
|
before_action :retrieve_procedure, only: [:champs, :annotations, :edit, :monavis, :update_monavis, :jeton, :update_jeton, :publication, :publish, :transfert, :allow_expert_review, :invited_expert_list, :update_allow_decision_access]
|
||||||
before_action :procedure_locked?, only: [:champs, :annotations]
|
before_action :procedure_locked?, only: [:champs, :annotations]
|
||||||
|
|
||||||
ITEMS_PER_PAGE = 25
|
ITEMS_PER_PAGE = 25
|
||||||
|
@ -186,7 +186,14 @@ module NewAdministrateur
|
||||||
end
|
end
|
||||||
|
|
||||||
def invited_expert_list
|
def invited_expert_list
|
||||||
@invited_expert_emails = ExpertsProcedure.invited_expert_emails(@procedure)
|
@experts_procedure = @procedure.experts_procedures.sort_by { |expert_procedure| expert_procedure.expert.email }
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_allow_decision_access
|
||||||
|
@procedure
|
||||||
|
.experts_procedures
|
||||||
|
.find(params[:expert_procedure])
|
||||||
|
.update!(allow_decision_access_params)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -215,5 +222,9 @@ module NewAdministrateur
|
||||||
def publish_params
|
def publish_params
|
||||||
params.permit(:path, :lien_site_web)
|
params.permit(:path, :lien_site_web)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def allow_decision_access_params
|
||||||
|
params.require(:experts_procedure).permit(:allow_decision_access)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
66
app/graphql/mutations/dossier_modifier_annotation.rb
Normal file
66
app/graphql/mutations/dossier_modifier_annotation.rb
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
module Mutations
|
||||||
|
class DossierModifierAnnotation < Mutations::BaseMutation
|
||||||
|
argument :dossier_id, ID, "Dossier ID", required: true, loads: Types::DossierType
|
||||||
|
argument :instructeur_id, ID, "Instructeur qui demande la modification.", required: true, loads: Types::ProfileType
|
||||||
|
argument :annotation_id, ID, "Annotation ID", required: true
|
||||||
|
|
||||||
|
field :annotation, Types::ChampType, null: true
|
||||||
|
field :errors, [Types::ValidationErrorType], null: true
|
||||||
|
|
||||||
|
def resolve_with_type(type, dossier, annotation_id, instructeur, value)
|
||||||
|
annotation = find_annotation(dossier, type, annotation_id)
|
||||||
|
|
||||||
|
if block_given?
|
||||||
|
annotation.value = yield annotation.type_champ, value
|
||||||
|
else
|
||||||
|
annotation.value = value
|
||||||
|
end
|
||||||
|
|
||||||
|
if annotation.save
|
||||||
|
dossier.log_modifier_annotation!(annotation, instructeur)
|
||||||
|
|
||||||
|
{ annotation: annotation }
|
||||||
|
else
|
||||||
|
{ errors: annotation.errors.full_messages }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorized?(dossier:, instructeur:, **args)
|
||||||
|
dossier_authorized_for?(dossier, instructeur)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def find_annotation(dossier, type, annotation_id)
|
||||||
|
_, stable_id = GraphQL::Schema::UniqueWithinType.decode(annotation_id)
|
||||||
|
dossier.champs_private
|
||||||
|
.joins(:type_de_champ)
|
||||||
|
.find_by!(types_de_champ: {
|
||||||
|
type_champ: annotation_type_champ(type),
|
||||||
|
stable_id: stable_id
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
def annotation_type_champ(type)
|
||||||
|
case type
|
||||||
|
when :text
|
||||||
|
[
|
||||||
|
TypeDeChamp.type_champs.fetch(:text),
|
||||||
|
TypeDeChamp.type_champs.fetch(:textarea)
|
||||||
|
]
|
||||||
|
when :checkbox
|
||||||
|
[
|
||||||
|
TypeDeChamp.type_champs.fetch(:checkbox),
|
||||||
|
TypeDeChamp.type_champs.fetch(:yes_no),
|
||||||
|
TypeDeChamp.type_champs.fetch(:engagement)
|
||||||
|
]
|
||||||
|
when :date
|
||||||
|
TypeDeChamp.type_champs.fetch(:date)
|
||||||
|
when :datetime
|
||||||
|
TypeDeChamp.type_champs.fetch(:datetime)
|
||||||
|
when :integer_number
|
||||||
|
TypeDeChamp.type_champs.fetch(:integer_number)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,23 @@
|
||||||
|
module Mutations
|
||||||
|
class DossierModifierAnnotationCheckbox < Mutations::DossierModifierAnnotation
|
||||||
|
description "Modifier l’annotation au format oui/non."
|
||||||
|
|
||||||
|
argument :value, Boolean, required: true
|
||||||
|
|
||||||
|
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
||||||
|
resolve_with_type(
|
||||||
|
:checkbox,
|
||||||
|
dossier,
|
||||||
|
annotation_id,
|
||||||
|
instructeur,
|
||||||
|
value
|
||||||
|
) do |type_champ, value|
|
||||||
|
if type_champ == TypeDeChamp.type_champs.fetch(:yes_no)
|
||||||
|
value ? 'true' : 'false'
|
||||||
|
else
|
||||||
|
value ? 'on' : 'off'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
17
app/graphql/mutations/dossier_modifier_annotation_date.rb
Normal file
17
app/graphql/mutations/dossier_modifier_annotation_date.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
module Mutations
|
||||||
|
class DossierModifierAnnotationDate < Mutations::DossierModifierAnnotation
|
||||||
|
description "Modifier l’annotation au format date."
|
||||||
|
|
||||||
|
argument :value, GraphQL::Types::ISO8601Date, required: true
|
||||||
|
|
||||||
|
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
||||||
|
resolve_with_type(
|
||||||
|
:date,
|
||||||
|
dossier,
|
||||||
|
annotation_id,
|
||||||
|
instructeur,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,17 @@
|
||||||
|
module Mutations
|
||||||
|
class DossierModifierAnnotationDatetime < Mutations::DossierModifierAnnotation
|
||||||
|
description "Modifier l’annotation au format date et heure."
|
||||||
|
|
||||||
|
argument :value, GraphQL::Types::ISO8601DateTime, required: true
|
||||||
|
|
||||||
|
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
||||||
|
resolve_with_type(
|
||||||
|
:datetime,
|
||||||
|
dossier,
|
||||||
|
annotation_id,
|
||||||
|
instructeur,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,17 @@
|
||||||
|
module Mutations
|
||||||
|
class DossierModifierAnnotationIntegerNumber < Mutations::DossierModifierAnnotation
|
||||||
|
description "Modifier l’annotation au format nombre entier."
|
||||||
|
|
||||||
|
argument :value, Int, required: true
|
||||||
|
|
||||||
|
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
||||||
|
resolve_with_type(
|
||||||
|
:integer_number,
|
||||||
|
dossier,
|
||||||
|
annotation_id,
|
||||||
|
instructeur,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
17
app/graphql/mutations/dossier_modifier_annotation_text.rb
Normal file
17
app/graphql/mutations/dossier_modifier_annotation_text.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
module Mutations
|
||||||
|
class DossierModifierAnnotationText < Mutations::DossierModifierAnnotation
|
||||||
|
description "Modifier l’annotation au format text."
|
||||||
|
|
||||||
|
argument :value, String, required: true
|
||||||
|
|
||||||
|
def resolve(dossier:, annotation_id:, instructeur:, value:)
|
||||||
|
resolve_with_type(
|
||||||
|
:text,
|
||||||
|
dossier,
|
||||||
|
annotation_id,
|
||||||
|
instructeur,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -685,6 +685,201 @@ type DossierLinkChamp implements Champ {
|
||||||
stringValue: String
|
stringValue: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated input type of DossierModifierAnnotationCheckbox
|
||||||
|
"""
|
||||||
|
input DossierModifierAnnotationCheckboxInput {
|
||||||
|
"""
|
||||||
|
Annotation ID
|
||||||
|
"""
|
||||||
|
annotationId: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Dossier ID
|
||||||
|
"""
|
||||||
|
dossierId: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
Instructeur qui demande la modification.
|
||||||
|
"""
|
||||||
|
instructeurId: ID!
|
||||||
|
value: Boolean!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated return type of DossierModifierAnnotationCheckbox
|
||||||
|
"""
|
||||||
|
type DossierModifierAnnotationCheckboxPayload {
|
||||||
|
annotation: Champ
|
||||||
|
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
errors: [ValidationError!]
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated input type of DossierModifierAnnotationDate
|
||||||
|
"""
|
||||||
|
input DossierModifierAnnotationDateInput {
|
||||||
|
"""
|
||||||
|
Annotation ID
|
||||||
|
"""
|
||||||
|
annotationId: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Dossier ID
|
||||||
|
"""
|
||||||
|
dossierId: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
Instructeur qui demande la modification.
|
||||||
|
"""
|
||||||
|
instructeurId: ID!
|
||||||
|
value: ISO8601Date!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated return type of DossierModifierAnnotationDate
|
||||||
|
"""
|
||||||
|
type DossierModifierAnnotationDatePayload {
|
||||||
|
annotation: Champ
|
||||||
|
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
errors: [ValidationError!]
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated input type of DossierModifierAnnotationDatetime
|
||||||
|
"""
|
||||||
|
input DossierModifierAnnotationDatetimeInput {
|
||||||
|
"""
|
||||||
|
Annotation ID
|
||||||
|
"""
|
||||||
|
annotationId: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Dossier ID
|
||||||
|
"""
|
||||||
|
dossierId: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
Instructeur qui demande la modification.
|
||||||
|
"""
|
||||||
|
instructeurId: ID!
|
||||||
|
value: ISO8601DateTime!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated return type of DossierModifierAnnotationDatetime
|
||||||
|
"""
|
||||||
|
type DossierModifierAnnotationDatetimePayload {
|
||||||
|
annotation: Champ
|
||||||
|
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
errors: [ValidationError!]
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated input type of DossierModifierAnnotationIntegerNumber
|
||||||
|
"""
|
||||||
|
input DossierModifierAnnotationIntegerNumberInput {
|
||||||
|
"""
|
||||||
|
Annotation ID
|
||||||
|
"""
|
||||||
|
annotationId: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Dossier ID
|
||||||
|
"""
|
||||||
|
dossierId: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
Instructeur qui demande la modification.
|
||||||
|
"""
|
||||||
|
instructeurId: ID!
|
||||||
|
value: Int!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated return type of DossierModifierAnnotationIntegerNumber
|
||||||
|
"""
|
||||||
|
type DossierModifierAnnotationIntegerNumberPayload {
|
||||||
|
annotation: Champ
|
||||||
|
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
errors: [ValidationError!]
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated input type of DossierModifierAnnotationText
|
||||||
|
"""
|
||||||
|
input DossierModifierAnnotationTextInput {
|
||||||
|
"""
|
||||||
|
Annotation ID
|
||||||
|
"""
|
||||||
|
annotationId: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Dossier ID
|
||||||
|
"""
|
||||||
|
dossierId: ID!
|
||||||
|
|
||||||
|
"""
|
||||||
|
Instructeur qui demande la modification.
|
||||||
|
"""
|
||||||
|
instructeurId: ID!
|
||||||
|
value: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Autogenerated return type of DossierModifierAnnotationText
|
||||||
|
"""
|
||||||
|
type DossierModifierAnnotationTextPayload {
|
||||||
|
annotation: Champ
|
||||||
|
|
||||||
|
"""
|
||||||
|
A unique identifier for the client performing the mutation.
|
||||||
|
"""
|
||||||
|
clientMutationId: String
|
||||||
|
errors: [ValidationError!]
|
||||||
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Autogenerated input type of DossierPasserEnInstruction
|
Autogenerated input type of DossierPasserEnInstruction
|
||||||
"""
|
"""
|
||||||
|
@ -986,42 +1181,132 @@ type Mutation {
|
||||||
"""
|
"""
|
||||||
File information required to prepare a direct upload
|
File information required to prepare a direct upload
|
||||||
"""
|
"""
|
||||||
createDirectUpload(input: CreateDirectUploadInput!): CreateDirectUploadPayload
|
createDirectUpload(
|
||||||
|
"""
|
||||||
|
Parameters for CreateDirectUpload
|
||||||
|
"""
|
||||||
|
input: CreateDirectUploadInput!
|
||||||
|
): CreateDirectUploadPayload
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Accepter le dossier.
|
Accepter le dossier.
|
||||||
"""
|
"""
|
||||||
dossierAccepter(input: DossierAccepterInput!): DossierAccepterPayload
|
dossierAccepter(
|
||||||
|
"""
|
||||||
|
Parameters for DossierAccepter
|
||||||
|
"""
|
||||||
|
input: DossierAccepterInput!
|
||||||
|
): DossierAccepterPayload
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Archiver le dossier.
|
Archiver le dossier.
|
||||||
"""
|
"""
|
||||||
dossierArchiver(input: DossierArchiverInput!): DossierArchiverPayload
|
dossierArchiver(
|
||||||
|
"""
|
||||||
|
Parameters for DossierArchiver
|
||||||
|
"""
|
||||||
|
input: DossierArchiverInput!
|
||||||
|
): DossierArchiverPayload
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Changer le grope instructeur du dossier.
|
Changer le grope instructeur du dossier.
|
||||||
"""
|
"""
|
||||||
dossierChangerGroupeInstructeur(input: DossierChangerGroupeInstructeurInput!): DossierChangerGroupeInstructeurPayload
|
dossierChangerGroupeInstructeur(
|
||||||
|
"""
|
||||||
|
Parameters for DossierChangerGroupeInstructeur
|
||||||
|
"""
|
||||||
|
input: DossierChangerGroupeInstructeurInput!
|
||||||
|
): DossierChangerGroupeInstructeurPayload
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Classer le dossier sans suite.
|
Classer le dossier sans suite.
|
||||||
"""
|
"""
|
||||||
dossierClasserSansSuite(input: DossierClasserSansSuiteInput!): DossierClasserSansSuitePayload
|
dossierClasserSansSuite(
|
||||||
|
"""
|
||||||
|
Parameters for DossierClasserSansSuite
|
||||||
|
"""
|
||||||
|
input: DossierClasserSansSuiteInput!
|
||||||
|
): DossierClasserSansSuitePayload
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Envoyer un message à l'usager du dossier.
|
Envoyer un message à l'usager du dossier.
|
||||||
"""
|
"""
|
||||||
dossierEnvoyerMessage(input: DossierEnvoyerMessageInput!): DossierEnvoyerMessagePayload
|
dossierEnvoyerMessage(
|
||||||
|
"""
|
||||||
|
Parameters for DossierEnvoyerMessage
|
||||||
|
"""
|
||||||
|
input: DossierEnvoyerMessageInput!
|
||||||
|
): DossierEnvoyerMessagePayload
|
||||||
|
|
||||||
|
"""
|
||||||
|
Modifier l’annotation au format oui/non.
|
||||||
|
"""
|
||||||
|
dossierModifierAnnotationCheckbox(
|
||||||
|
"""
|
||||||
|
Parameters for DossierModifierAnnotationCheckbox
|
||||||
|
"""
|
||||||
|
input: DossierModifierAnnotationCheckboxInput!
|
||||||
|
): DossierModifierAnnotationCheckboxPayload
|
||||||
|
|
||||||
|
"""
|
||||||
|
Modifier l’annotation au format date.
|
||||||
|
"""
|
||||||
|
dossierModifierAnnotationDate(
|
||||||
|
"""
|
||||||
|
Parameters for DossierModifierAnnotationDate
|
||||||
|
"""
|
||||||
|
input: DossierModifierAnnotationDateInput!
|
||||||
|
): DossierModifierAnnotationDatePayload
|
||||||
|
|
||||||
|
"""
|
||||||
|
Modifier l’annotation au format date et heure.
|
||||||
|
"""
|
||||||
|
dossierModifierAnnotationDatetime(
|
||||||
|
"""
|
||||||
|
Parameters for DossierModifierAnnotationDatetime
|
||||||
|
"""
|
||||||
|
input: DossierModifierAnnotationDatetimeInput!
|
||||||
|
): DossierModifierAnnotationDatetimePayload
|
||||||
|
|
||||||
|
"""
|
||||||
|
Modifier l’annotation au format nombre entier.
|
||||||
|
"""
|
||||||
|
dossierModifierAnnotationIntegerNumber(
|
||||||
|
"""
|
||||||
|
Parameters for DossierModifierAnnotationIntegerNumber
|
||||||
|
"""
|
||||||
|
input: DossierModifierAnnotationIntegerNumberInput!
|
||||||
|
): DossierModifierAnnotationIntegerNumberPayload
|
||||||
|
|
||||||
|
"""
|
||||||
|
Modifier l’annotation au format text.
|
||||||
|
"""
|
||||||
|
dossierModifierAnnotationText(
|
||||||
|
"""
|
||||||
|
Parameters for DossierModifierAnnotationText
|
||||||
|
"""
|
||||||
|
input: DossierModifierAnnotationTextInput!
|
||||||
|
): DossierModifierAnnotationTextPayload
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Passer le dossier en instruction.
|
Passer le dossier en instruction.
|
||||||
"""
|
"""
|
||||||
dossierPasserEnInstruction(input: DossierPasserEnInstructionInput!): DossierPasserEnInstructionPayload
|
dossierPasserEnInstruction(
|
||||||
|
"""
|
||||||
|
Parameters for DossierPasserEnInstruction
|
||||||
|
"""
|
||||||
|
input: DossierPasserEnInstructionInput!
|
||||||
|
): DossierPasserEnInstructionPayload
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Refuser le dossier.
|
Refuser le dossier.
|
||||||
"""
|
"""
|
||||||
dossierRefuser(input: DossierRefuserInput!): DossierRefuserPayload
|
dossierRefuser(
|
||||||
|
"""
|
||||||
|
Parameters for DossierRefuser
|
||||||
|
"""
|
||||||
|
input: DossierRefuserInput!
|
||||||
|
): DossierRefuserPayload
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Order {
|
enum Order {
|
||||||
|
|
|
@ -9,5 +9,11 @@ module Types
|
||||||
field :dossier_accepter, mutation: Mutations::DossierAccepter
|
field :dossier_accepter, mutation: Mutations::DossierAccepter
|
||||||
field :dossier_archiver, mutation: Mutations::DossierArchiver
|
field :dossier_archiver, mutation: Mutations::DossierArchiver
|
||||||
field :dossier_changer_groupe_instructeur, mutation: Mutations::DossierChangerGroupeInstructeur
|
field :dossier_changer_groupe_instructeur, mutation: Mutations::DossierChangerGroupeInstructeur
|
||||||
|
|
||||||
|
field :dossier_modifier_annotation_text, mutation: Mutations::DossierModifierAnnotationText
|
||||||
|
field :dossier_modifier_annotation_checkbox, mutation: Mutations::DossierModifierAnnotationCheckbox
|
||||||
|
field :dossier_modifier_annotation_date, mutation: Mutations::DossierModifierAnnotationDate
|
||||||
|
field :dossier_modifier_annotation_datetime, mutation: Mutations::DossierModifierAnnotationDatetime
|
||||||
|
field :dossier_modifier_annotation_integer_number, mutation: Mutations::DossierModifierAnnotationIntegerNumber
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { ReactQueryCacheProvider } from 'react-query';
|
import { QueryClientProvider } from 'react-query';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import ComboSearch from './ComboSearch';
|
import ComboSearch from './ComboSearch';
|
||||||
import { queryCache } from './shared/queryCache';
|
import { queryClient } from './shared/queryClient';
|
||||||
|
|
||||||
function ComboAdresseSearch({
|
function ComboAdresseSearch({
|
||||||
mandatory,
|
mandatory,
|
||||||
|
@ -16,7 +16,7 @@ function ComboAdresseSearch({
|
||||||
const transformResults = useCallback((_, { features }) => features);
|
const transformResults = useCallback((_, { features }) => features);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactQueryCacheProvider queryCache={queryCache}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<ComboSearch
|
<ComboSearch
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
required={mandatory}
|
required={mandatory}
|
||||||
|
@ -28,7 +28,7 @@ function ComboAdresseSearch({
|
||||||
transformResult={transformResult}
|
transformResult={transformResult}
|
||||||
transformResults={transformResults}
|
transformResults={transformResults}
|
||||||
/>
|
/>
|
||||||
</ReactQueryCacheProvider>
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ReactQueryCacheProvider } from 'react-query';
|
import { QueryClientProvider } from 'react-query';
|
||||||
|
|
||||||
import ComboSearch from './ComboSearch';
|
import ComboSearch from './ComboSearch';
|
||||||
import { queryCache } from './shared/queryCache';
|
import { queryClient } from './shared/queryClient';
|
||||||
|
|
||||||
function ComboAnnuaireEducationSearch(params) {
|
function ComboAnnuaireEducationSearch(params) {
|
||||||
return (
|
return (
|
||||||
<ReactQueryCacheProvider queryCache={queryCache}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<ComboSearch
|
<ComboSearch
|
||||||
required={params.mandatory}
|
required={params.mandatory}
|
||||||
hiddenFieldId={params.hiddenFieldId}
|
hiddenFieldId={params.hiddenFieldId}
|
||||||
|
@ -21,7 +21,7 @@ function ComboAnnuaireEducationSearch(params) {
|
||||||
}
|
}
|
||||||
}) => [id, `${nom_etablissement}, ${nom_commune} (${id})`]}
|
}) => [id, `${nom_etablissement}, ${nom_commune} (${id})`]}
|
||||||
/>
|
/>
|
||||||
</ReactQueryCacheProvider>
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ReactQueryCacheProvider } from 'react-query';
|
import { QueryClientProvider } from 'react-query';
|
||||||
|
|
||||||
import ComboSearch from './ComboSearch';
|
import ComboSearch from './ComboSearch';
|
||||||
import { queryCache } from './shared/queryCache';
|
import { queryClient } from './shared/queryClient';
|
||||||
|
|
||||||
function ComboCommunesSearch(params) {
|
function ComboCommunesSearch(params) {
|
||||||
return (
|
return (
|
||||||
<ReactQueryCacheProvider queryCache={queryCache}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<ComboSearch
|
<ComboSearch
|
||||||
required={params.mandatory}
|
required={params.mandatory}
|
||||||
hiddenFieldId={params.hiddenFieldId}
|
hiddenFieldId={params.hiddenFieldId}
|
||||||
|
@ -17,7 +17,7 @@ function ComboCommunesSearch(params) {
|
||||||
`${nom} (${codesPostaux[0]})`
|
`${nom} (${codesPostaux[0]})`
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</ReactQueryCacheProvider>
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { ReactQueryCacheProvider } from 'react-query';
|
import { QueryClientProvider } from 'react-query';
|
||||||
import matchSorter from 'match-sorter';
|
import { matchSorter } from 'match-sorter';
|
||||||
|
|
||||||
import ComboSearch from './ComboSearch';
|
import ComboSearch from './ComboSearch';
|
||||||
import { queryCache } from './shared/queryCache';
|
import { queryClient } from './shared/queryClient';
|
||||||
|
|
||||||
const extraTerms = [{ code: '99', nom: 'Etranger' }];
|
const extraTerms = [{ code: '99', nom: 'Etranger' }];
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ function ComboDepartementsSearch(params) {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactQueryCacheProvider queryCache={queryCache}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<ComboSearch
|
<ComboSearch
|
||||||
required={params.mandatory}
|
required={params.mandatory}
|
||||||
hiddenFieldId={params.hiddenFieldId}
|
hiddenFieldId={params.hiddenFieldId}
|
||||||
|
@ -25,7 +25,7 @@ function ComboDepartementsSearch(params) {
|
||||||
transformResult={({ code, nom }) => [code, `${code} - ${nom}`]}
|
transformResult={({ code, nom }) => [code, `${code} - ${nom}`]}
|
||||||
transformResults={transformResults}
|
transformResults={transformResults}
|
||||||
/>
|
/>
|
||||||
</ReactQueryCacheProvider>
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
250
app/javascript/components/ComboMultipleDropdownList.jsx
Normal file
250
app/javascript/components/ComboMultipleDropdownList.jsx
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
import React, {
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
useRef,
|
||||||
|
useContext,
|
||||||
|
createContext,
|
||||||
|
useEffect,
|
||||||
|
useLayoutEffect
|
||||||
|
} from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
Combobox,
|
||||||
|
ComboboxInput,
|
||||||
|
ComboboxList,
|
||||||
|
ComboboxOption,
|
||||||
|
ComboboxPopover
|
||||||
|
} from '@reach/combobox';
|
||||||
|
import '@reach/combobox/styles.css';
|
||||||
|
import { matchSorter } from 'match-sorter';
|
||||||
|
import { fire } from '@utils';
|
||||||
|
|
||||||
|
const Context = createContext();
|
||||||
|
|
||||||
|
function ComboMultipleDropdownList({
|
||||||
|
options,
|
||||||
|
hiddenFieldId,
|
||||||
|
selected,
|
||||||
|
label,
|
||||||
|
acceptNewValues = false
|
||||||
|
}) {
|
||||||
|
if (label == undefined) {
|
||||||
|
label = 'Choisir une option';
|
||||||
|
}
|
||||||
|
if (Array.isArray(options[0]) == false) {
|
||||||
|
options = options.map((o) => [o, o]);
|
||||||
|
}
|
||||||
|
const inputRef = useRef();
|
||||||
|
const [term, setTerm] = useState('');
|
||||||
|
const [selections, setSelections] = useState(selected);
|
||||||
|
const [newValues, setNewValues] = useState([]);
|
||||||
|
const results = useMemo(
|
||||||
|
() =>
|
||||||
|
(term
|
||||||
|
? matchSorter(
|
||||||
|
options.filter((o) => !o[0].startsWith('--')),
|
||||||
|
term
|
||||||
|
)
|
||||||
|
: options
|
||||||
|
).filter((o) => o[0] && !selections.includes(o[1])),
|
||||||
|
[term, selections.join(',')]
|
||||||
|
);
|
||||||
|
const hiddenField = useMemo(
|
||||||
|
() => document.querySelector(`input[data-uuid="${hiddenFieldId}"]`),
|
||||||
|
[hiddenFieldId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleChange = (event) => {
|
||||||
|
setTerm(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onKeyDown = (event) => {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
if (term && options.map((o) => o[0]).includes(term)) {
|
||||||
|
event.preventDefault();
|
||||||
|
return onSelect(term);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
acceptNewValues &&
|
||||||
|
term &&
|
||||||
|
matchSorter(
|
||||||
|
options.map((o) => o[0]),
|
||||||
|
term
|
||||||
|
).length == 0 // ignore when was pressed for selecting popover option
|
||||||
|
) {
|
||||||
|
event.preventDefault();
|
||||||
|
setNewValues([...newValues, term]);
|
||||||
|
saveSelection([...selections, term]);
|
||||||
|
setTerm('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveSelection = (selections) => {
|
||||||
|
setSelections(selections);
|
||||||
|
if (hiddenField) {
|
||||||
|
hiddenField.setAttribute('value', JSON.stringify(selections));
|
||||||
|
fire(hiddenField, 'autosave:trigger');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSelect = (value) => {
|
||||||
|
let sel = options.find((o) => o[0] == value)[1];
|
||||||
|
saveSelection([...selections, sel]);
|
||||||
|
setTerm('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const onRemove = (value) => {
|
||||||
|
saveSelection(
|
||||||
|
selections.filter((s) =>
|
||||||
|
newValues.includes(value)
|
||||||
|
? s != value
|
||||||
|
: s !== options.find((o) => o[0] == value)[1]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
inputRef.current.focus();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Combobox openOnFocus={true} onSelect={onSelect} aria-label={label}>
|
||||||
|
<ComboboxTokenLabel onRemove={onRemove}>
|
||||||
|
<ul
|
||||||
|
aria-live="polite"
|
||||||
|
aria-atomic={true}
|
||||||
|
data-reach-combobox-token-list
|
||||||
|
>
|
||||||
|
{selections.map((selection) => (
|
||||||
|
<ComboboxToken
|
||||||
|
key={selection}
|
||||||
|
value={
|
||||||
|
newValues.find((newValue) => newValue == selection) ||
|
||||||
|
options.find((o) => o[1] == selection)[0]
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<ComboboxInput
|
||||||
|
ref={inputRef}
|
||||||
|
value={term}
|
||||||
|
onChange={handleChange}
|
||||||
|
onKeyDown={onKeyDown}
|
||||||
|
autocomplete={false}
|
||||||
|
/>
|
||||||
|
</ComboboxTokenLabel>
|
||||||
|
{results && (
|
||||||
|
<ComboboxPopover portal={false}>
|
||||||
|
{results.length === 0 && (
|
||||||
|
<p>
|
||||||
|
Aucun résultat{' '}
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setTerm('');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Effacer
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<ComboboxList>
|
||||||
|
{results.map((value, index) => {
|
||||||
|
if (value[0].startsWith('--')) {
|
||||||
|
return <ComboboxSeparator key={index} value={value[0]} />;
|
||||||
|
}
|
||||||
|
return <ComboboxOption key={index} value={value[0]} />;
|
||||||
|
})}
|
||||||
|
</ComboboxList>
|
||||||
|
</ComboboxPopover>
|
||||||
|
)}
|
||||||
|
</Combobox>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxTokenLabel({ onRemove, ...props }) {
|
||||||
|
const selectionsRef = useRef([]);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
selectionsRef.current = [];
|
||||||
|
return () => (selectionsRef.current = []);
|
||||||
|
});
|
||||||
|
|
||||||
|
const context = {
|
||||||
|
onRemove,
|
||||||
|
selectionsRef
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Context.Provider value={context}>
|
||||||
|
<div data-combobox-token-label {...props} />
|
||||||
|
</Context.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboboxTokenLabel.propTypes = {
|
||||||
|
onRemove: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
function ComboboxSeparator({ value }) {
|
||||||
|
return (
|
||||||
|
<li aria-disabled="true" role="option" data-combobox-separator>
|
||||||
|
{value.slice(2, -2)}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboboxSeparator.propTypes = {
|
||||||
|
value: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
function ComboboxToken({ value, ...props }) {
|
||||||
|
const { selectionsRef, onRemove } = useContext(Context);
|
||||||
|
useEffect(() => {
|
||||||
|
selectionsRef.current.push(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
data-reach-combobox-token
|
||||||
|
tabIndex="0"
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
if (event.key === 'Backspace') {
|
||||||
|
onRemove(value);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
role="presentation"
|
||||||
|
data-combobox-remove-token
|
||||||
|
onClick={() => {
|
||||||
|
onRemove(value);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
x
|
||||||
|
</span>
|
||||||
|
{value}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboboxToken.propTypes = {
|
||||||
|
value: PropTypes.string,
|
||||||
|
label: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
ComboMultipleDropdownList.propTypes = {
|
||||||
|
options: PropTypes.oneOfType([
|
||||||
|
PropTypes.arrayOf(PropTypes.string),
|
||||||
|
PropTypes.arrayOf(
|
||||||
|
PropTypes.arrayOf(
|
||||||
|
PropTypes.oneOfType([PropTypes.string, PropTypes.number])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
hiddenFieldId: PropTypes.string,
|
||||||
|
selected: PropTypes.arrayOf(PropTypes.string),
|
||||||
|
arraySelected: PropTypes.arrayOf(PropTypes.array),
|
||||||
|
label: PropTypes.string,
|
||||||
|
acceptNewValues: PropTypes.bool
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ComboMultipleDropdownList;
|
|
@ -1,12 +1,12 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ReactQueryCacheProvider } from 'react-query';
|
import { QueryClientProvider } from 'react-query';
|
||||||
|
|
||||||
import ComboSearch from './ComboSearch';
|
import ComboSearch from './ComboSearch';
|
||||||
import { queryCache } from './shared/queryCache';
|
import { queryClient } from './shared/queryClient';
|
||||||
|
|
||||||
function ComboPaysSearch(params) {
|
function ComboPaysSearch(params) {
|
||||||
return (
|
return (
|
||||||
<ReactQueryCacheProvider queryCache={queryCache}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<ComboSearch
|
<ComboSearch
|
||||||
required={params.mandatory}
|
required={params.mandatory}
|
||||||
hiddenFieldId={params.hiddenFieldId}
|
hiddenFieldId={params.hiddenFieldId}
|
||||||
|
@ -14,7 +14,7 @@ function ComboPaysSearch(params) {
|
||||||
minimumInputLength={0}
|
minimumInputLength={0}
|
||||||
transformResult={({ nom }) => [nom, nom]}
|
transformResult={({ nom }) => [nom, nom]}
|
||||||
/>
|
/>
|
||||||
</ReactQueryCacheProvider>
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ReactQueryCacheProvider } from 'react-query';
|
import { QueryClientProvider } from 'react-query';
|
||||||
|
|
||||||
import ComboSearch from './ComboSearch';
|
import ComboSearch from './ComboSearch';
|
||||||
import { queryCache } from './shared/queryCache';
|
import { queryClient } from './shared/queryClient';
|
||||||
|
|
||||||
function ComboRegionsSearch(params) {
|
function ComboRegionsSearch(params) {
|
||||||
return (
|
return (
|
||||||
<ReactQueryCacheProvider queryCache={queryCache}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<ComboSearch
|
<ComboSearch
|
||||||
required={params.mandatory}
|
required={params.mandatory}
|
||||||
hiddenFieldId={params.hiddenFieldId}
|
hiddenFieldId={params.hiddenFieldId}
|
||||||
|
@ -14,7 +14,7 @@ function ComboRegionsSearch(params) {
|
||||||
minimumInputLength={0}
|
minimumInputLength={0}
|
||||||
transformResult={({ code, nom }) => [code, nom]}
|
transformResult={({ code, nom }) => [code, nom]}
|
||||||
/>
|
/>
|
||||||
</ReactQueryCacheProvider>
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useState, useMemo, useCallback, useRef } from 'react';
|
import React, { useState, useMemo, useCallback, useRef } from 'react';
|
||||||
import { useDebounce } from 'react-use';
|
import { useDebounce } from 'use-debounce';
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {
|
import {
|
||||||
|
@ -41,7 +41,7 @@ function ComboSearch({
|
||||||
);
|
);
|
||||||
const initialValue = hiddenValueField && hiddenValueField.value;
|
const initialValue = hiddenValueField && hiddenValueField.value;
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
|
const [debouncedSearchTerm] = useDebounce(searchTerm, 300);
|
||||||
const [value, setValue] = useState(initialValue);
|
const [value, setValue] = useState(initialValue);
|
||||||
const resultsMap = useRef({});
|
const resultsMap = useRef({});
|
||||||
const setExternalValue = useCallback((value) => {
|
const setExternalValue = useCallback((value) => {
|
||||||
|
@ -64,14 +64,6 @@ function ComboSearch({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
useDebounce(
|
|
||||||
() => {
|
|
||||||
setDebouncedSearchTerm(searchTerm);
|
|
||||||
},
|
|
||||||
300,
|
|
||||||
[searchTerm]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleOnChange = useCallback(
|
const handleOnChange = useCallback(
|
||||||
({ target: { value } }) => {
|
({ target: { value } }) => {
|
||||||
setValue(value);
|
setValue(value);
|
|
@ -1,4 +1,3 @@
|
||||||
import scrollToComponent from 'react-scroll-to-component';
|
|
||||||
import { debounce } from '@utils';
|
import { debounce } from '@utils';
|
||||||
import {
|
import {
|
||||||
createTypeDeChampOperation,
|
createTypeDeChampOperation,
|
||||||
|
@ -53,8 +52,10 @@ function addTypeDeChamp(state, typeDeChamps, insertAfter, done) {
|
||||||
state.flash.success();
|
state.flash.success();
|
||||||
done();
|
done();
|
||||||
if (insertAfter) {
|
if (insertAfter) {
|
||||||
scrollToComponent(insertAfter.target.nextElementSibling, {
|
insertAfter.target.nextElementSibling.scrollIntoView({
|
||||||
duration: 300
|
behavior: 'smooth',
|
||||||
|
block: 'start',
|
||||||
|
inline: 'nearest'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { QueryCache } from 'react-query';
|
import { QueryClient } from 'react-query';
|
||||||
import { isNumeric } from '@utils';
|
import { isNumeric } from '@utils';
|
||||||
import matchSorter from 'match-sorter';
|
import { matchSorter } from 'match-sorter';
|
||||||
|
|
||||||
const { api_geo_url, api_adresse_url, api_education_url } =
|
const { api_geo_url, api_adresse_url, api_education_url } =
|
||||||
gon.autocomplete || {};
|
gon.autocomplete || {};
|
||||||
|
|
||||||
export const queryCache = new QueryCache({
|
export const queryClient = new QueryClient({
|
||||||
defaultConfig: {
|
defaultOptions: {
|
||||||
queries: {
|
queries: {
|
||||||
queryFn: defaultQueryFn
|
queryFn: defaultQueryFn
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ function buildOptions() {
|
||||||
return [{}, null];
|
return [{}, null];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function defaultQueryFn(scope, term) {
|
async function defaultQueryFn({ queryKey: [scope, term] }) {
|
||||||
if (scope == 'pays') {
|
if (scope == 'pays') {
|
||||||
return matchSorter(await getPays(), term, { keys: ['nom'] });
|
return matchSorter(await getPays(), term, { keys: ['nom'] });
|
||||||
}
|
}
|
5
app/javascript/loaders/ComboMultipleDropdownList.js
Normal file
5
app/javascript/loaders/ComboMultipleDropdownList.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import Loadable from '../components/Loadable';
|
||||||
|
|
||||||
|
export default Loadable(() =>
|
||||||
|
import('../components/ComboMultipleDropdownList')
|
||||||
|
);
|
|
@ -1,80 +0,0 @@
|
||||||
import $ from 'jquery';
|
|
||||||
import 'select2';
|
|
||||||
|
|
||||||
const language = {
|
|
||||||
errorLoading: function () {
|
|
||||||
return 'Les résultats ne peuvent pas être chargés.';
|
|
||||||
},
|
|
||||||
inputTooLong: function (args) {
|
|
||||||
var overChars = args.input.length - args.maximum;
|
|
||||||
|
|
||||||
return 'Supprimez ' + overChars + ' caractère' + (overChars > 1 ? 's' : '');
|
|
||||||
},
|
|
||||||
inputTooShort: function (args) {
|
|
||||||
var remainingChars = args.minimum - args.input.length;
|
|
||||||
|
|
||||||
return (
|
|
||||||
'Saisissez au moins ' +
|
|
||||||
remainingChars +
|
|
||||||
' caractère' +
|
|
||||||
(remainingChars > 1 ? 's' : '')
|
|
||||||
);
|
|
||||||
},
|
|
||||||
loadingMore: function () {
|
|
||||||
return 'Chargement de résultats supplémentaires…';
|
|
||||||
},
|
|
||||||
maximumSelected: function (args) {
|
|
||||||
return (
|
|
||||||
'Vous pouvez seulement sélectionner ' +
|
|
||||||
args.maximum +
|
|
||||||
' élément' +
|
|
||||||
(args.maximum > 1 ? 's' : '')
|
|
||||||
);
|
|
||||||
},
|
|
||||||
noResults: function () {
|
|
||||||
return 'Aucun résultat trouvé';
|
|
||||||
},
|
|
||||||
searching: function () {
|
|
||||||
return 'Recherche en cours…';
|
|
||||||
},
|
|
||||||
removeAllItems: function () {
|
|
||||||
return 'Supprimer tous les éléments';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const baseOptions = {
|
|
||||||
language,
|
|
||||||
width: '100%'
|
|
||||||
};
|
|
||||||
|
|
||||||
const templateOption = ({ text }) =>
|
|
||||||
$(
|
|
||||||
`<span class="custom-select2-option"><span class="icon person"></span>${text}</span>`
|
|
||||||
);
|
|
||||||
|
|
||||||
addEventListener('ds:page:update', () => {
|
|
||||||
$('select.select2').select2(baseOptions);
|
|
||||||
|
|
||||||
$('.columns-form select.select2-limited').select2({
|
|
||||||
width: '300px',
|
|
||||||
placeholder: 'Sélectionnez des colonnes',
|
|
||||||
maximumSelectionLength: '5'
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.recipients-form select.select2-limited').select2({
|
|
||||||
language,
|
|
||||||
width: '300px',
|
|
||||||
placeholder: 'Sélectionnez des instructeurs',
|
|
||||||
maximumSelectionLength: '30'
|
|
||||||
});
|
|
||||||
|
|
||||||
$('select.select2-limited.select-instructeurs').select2({
|
|
||||||
language,
|
|
||||||
dropdownParent: $('.instructeur-wrapper'),
|
|
||||||
placeholder: 'Saisir l’adresse email de l’instructeur',
|
|
||||||
tags: true,
|
|
||||||
tokenSeparators: [',', ' '],
|
|
||||||
templateResult: templateOption,
|
|
||||||
templateSelection: templateOption
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -17,7 +17,6 @@ import '../new_design/dropdown';
|
||||||
import '../new_design/form-validation';
|
import '../new_design/form-validation';
|
||||||
import '../new_design/procedure-context';
|
import '../new_design/procedure-context';
|
||||||
import '../new_design/procedure-form';
|
import '../new_design/procedure-form';
|
||||||
import '../new_design/select2';
|
|
||||||
import '../new_design/spinner';
|
import '../new_design/spinner';
|
||||||
import '../new_design/support';
|
import '../new_design/support';
|
||||||
import '../new_design/dossiers/auto-save';
|
import '../new_design/dossiers/auto-save';
|
||||||
|
|
|
@ -679,6 +679,10 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def log_modifier_annotation!(champ, instructeur)
|
||||||
|
log_dossier_operation(instructeur, :modifier_annotation, champ)
|
||||||
|
end
|
||||||
|
|
||||||
def demander_un_avis!(avis)
|
def demander_un_avis!(avis)
|
||||||
log_dossier_operation(avis.claimant, :demander_un_avis, avis)
|
log_dossier_operation(avis.claimant, :demander_un_avis, avis)
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,15 +14,4 @@ class ExpertsProcedure < ApplicationRecord
|
||||||
belongs_to :procedure
|
belongs_to :procedure
|
||||||
|
|
||||||
has_many :avis, dependent: :destroy
|
has_many :avis, dependent: :destroy
|
||||||
|
|
||||||
def email_to_display
|
|
||||||
expert&.email
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.invited_expert_emails(procedure)
|
|
||||||
joins(:expert)
|
|
||||||
.where(procedure: procedure)
|
|
||||||
.map(&:email_to_display)
|
|
||||||
.sort
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -62,7 +62,7 @@ class DossierSearchService
|
||||||
|
|
||||||
def self.to_tsquery(search_terms)
|
def self.to_tsquery(search_terms)
|
||||||
(search_terms || "")
|
(search_terms || "")
|
||||||
.gsub(/['?\\:&|!<>\(\)]/, "") # drop disallowed characters
|
.gsub(/['?\\:&|!<>()]/, "") # drop disallowed characters
|
||||||
.strip
|
.strip
|
||||||
.split(/\s+/) # split words
|
.split(/\s+/) # split words
|
||||||
.map { |x| "#{x}:*" } # enable prefix matching
|
.map { |x| "#{x}:*" } # enable prefix matching
|
||||||
|
|
|
@ -8,9 +8,8 @@
|
||||||
Le destinataire suivra automatiquement le dossier
|
Le destinataire suivra automatiquement le dossier
|
||||||
= form_for dossier, url: send_to_instructeurs_instructeur_dossier_path(dossier.procedure, dossier), method: :post, html: { class: 'form recipients-form' } do |f|
|
= form_for dossier, url: send_to_instructeurs_instructeur_dossier_path(dossier.procedure, dossier), method: :post, html: { class: 'form recipients-form' } do |f|
|
||||||
.flex.justify-start.align-start
|
.flex.justify-start.align-start
|
||||||
= select_tag(:recipients,
|
- hidden_field_id = SecureRandom.uuid
|
||||||
options_from_collection_for_select(potential_recipients, :id, :email),
|
= hidden_field_tag :recipients, nil, data: { uuid: hidden_field_id }
|
||||||
multiple: true,
|
= react_component("ComboMultipleDropdownList", options: potential_recipients.map{|r| [r.email, r.id]}, selected: [], disabled: [], hiddenFieldId: hidden_field_id, label: "email instructeur")
|
||||||
class: 'select2-limited',
|
|
||||||
placeholder: '')
|
|
||||||
= f.submit "Envoyer", class: "button large send gap-left"
|
= f.submit "Envoyer", class: "button large send gap-left"
|
||||||
|
|
|
@ -122,10 +122,10 @@
|
||||||
Personnaliser
|
Personnaliser
|
||||||
#custom-menu.dropdown-content.fade-in-down
|
#custom-menu.dropdown-content.fade-in-down
|
||||||
= form_tag update_displayed_fields_instructeur_procedure_path(@procedure), method: :patch, class: 'dropdown-form columns-form' do
|
= form_tag update_displayed_fields_instructeur_procedure_path(@procedure), method: :patch, class: 'dropdown-form columns-form' do
|
||||||
= select_tag :values,
|
- hidden_field_id = SecureRandom.uuid
|
||||||
options_for_select(@displayed_fields_options, selected: @displayed_fields_selected),
|
= hidden_field_tag :values, nil, data: { uuid: hidden_field_id }
|
||||||
multiple: true,
|
= react_component("ComboMultipleDropdownList", options: @displayed_fields_options, selected: @displayed_fields_selected, disabled: [], hiddenFieldId: hidden_field_id, label: 'colonne')
|
||||||
class: 'select2-limited'
|
|
||||||
= submit_tag "Enregistrer", class: 'button'
|
= submit_tag "Enregistrer", class: 'button'
|
||||||
|
|
||||||
%tbody
|
%tbody
|
||||||
|
|
|
@ -25,12 +25,15 @@
|
||||||
.instructeur-wrapper
|
.instructeur-wrapper
|
||||||
- if !@procedure.routee?
|
- if !@procedure.routee?
|
||||||
%p.notice Entrez les adresses email des instructeurs que vous souhaitez affecter à cette démarche
|
%p.notice Entrez les adresses email des instructeurs que vous souhaitez affecter à cette démarche
|
||||||
= select_tag :emails,
|
- hidden_field_id = SecureRandom.uuid
|
||||||
options_for_select(@available_instructeur_emails),
|
= hidden_field_tag :emails, nil, data: { uuid: hidden_field_id }
|
||||||
multiple: true,
|
= react_component("ComboMultipleDropdownList",
|
||||||
class: 'select-instructeurs select2-limited'
|
options: @available_instructeur_emails, selected: [], disabled: [],
|
||||||
|
hiddenFieldId: hidden_field_id,
|
||||||
|
label: 'email instructeur',
|
||||||
|
acceptNewValues: true)
|
||||||
|
|
||||||
= f.submit 'Affecter', class: 'button primary send'
|
= f.submit 'Affecter', class: 'button primary send'
|
||||||
|
|
||||||
%table.table.mt-2
|
%table.table.mt-2
|
||||||
%thead
|
%thead
|
||||||
|
|
|
@ -1,16 +1,36 @@
|
||||||
|
= render partial: 'new_administrateur/breadcrumbs',
|
||||||
|
locals: { steps: [link_to('Démarches', admin_procedures_path),
|
||||||
|
link_to(@procedure.libelle, admin_procedure_path(@procedure)),
|
||||||
|
'Liste des experts'] }
|
||||||
|
|
||||||
.container
|
.container
|
||||||
%h1.mt-2 Experts invités sur #{@procedure.libelle}
|
%h1.page-title.mt-2 Experts invités sur #{@procedure.libelle}
|
||||||
- if @invited_expert_emails.present?
|
- if @experts_procedure.present?
|
||||||
%table.table.mt-2
|
%table.table.mt-2
|
||||||
%thead
|
%thead
|
||||||
%tr
|
%tr
|
||||||
%th Liste des experts
|
%th Liste des experts
|
||||||
|
- if feature_enabled_for?(:make_experts_notifiable, @procedure)
|
||||||
|
%th Notifier des décisions sur les dossiers
|
||||||
%tbody
|
%tbody
|
||||||
- @invited_expert_emails.each do |expert|
|
- @experts_procedure.each do |expert_procedure|
|
||||||
%tr
|
%tr
|
||||||
%td
|
%td
|
||||||
%span.icon.person
|
%span.icon.person
|
||||||
= expert
|
= expert_procedure.expert.email
|
||||||
|
- if feature_enabled_for?(:make_experts_notifiable, @procedure)
|
||||||
|
%td
|
||||||
|
= form_for expert_procedure,
|
||||||
|
url: admin_procedure_update_allow_decision_access_path(expert_procedure: expert_procedure),
|
||||||
|
remote: true,
|
||||||
|
method: :put,
|
||||||
|
authenticity_token: true,
|
||||||
|
html: { class: 'form procedure-form__column--form no-background' } do |f|
|
||||||
|
%label.toggle-switch
|
||||||
|
= f.check_box :allow_decision_access, class: 'toggle-switch-checkbox', onchange: 'this.form.submit()'
|
||||||
|
%span.toggle-switch-control.round
|
||||||
|
%span.toggle-switch-label.on
|
||||||
|
%span.toggle-switch-label.off
|
||||||
- else
|
- else
|
||||||
.blank-tab
|
.blank-tab
|
||||||
%h2.empty-text Aucun expert invité pour le moment.
|
%h2.empty-text Aucun expert invité pour le moment.
|
||||||
|
|
|
@ -167,7 +167,7 @@
|
||||||
%p.card-admin-subtitle Liste des experts invités par les instructeurs
|
%p.card-admin-subtitle Liste des experts invités par les instructeurs
|
||||||
|
|
||||||
.card-admin-action
|
.card-admin-action
|
||||||
= link_to "Voir", invited_expert_list_admin_procedure_path(@procedure), class: 'button'
|
= link_to "Voir", admin_procedure_invited_expert_list_path(@procedure), class: 'button'
|
||||||
|
|
||||||
|
|
||||||
.card-admin
|
.card-admin
|
||||||
|
|
|
@ -7,10 +7,7 @@
|
||||||
= b.text
|
= b.text
|
||||||
|
|
||||||
- else
|
- else
|
||||||
= form.select :value,
|
- hidden_field_id = SecureRandom.uuid
|
||||||
champ.options,
|
= form.hidden_field :value, { data: { uuid: hidden_field_id } }
|
||||||
{ selected: champ.selected_options,
|
= react_component("ComboMultipleDropdownList", options: champ.options, selected: champ.selected_options, disabled: champ.disabled_options, hiddenFieldId: hidden_field_id, label: champ.libelle)
|
||||||
disabled: champ.disabled_options },
|
|
||||||
multiple: true,
|
|
||||||
class: 'select2'
|
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ Rails.application.configure do
|
||||||
# test suite. You never need to work with it otherwise. Remember that
|
# test suite. You never need to work with it otherwise. Remember that
|
||||||
# your test database is "scratch space" for the test suite and is wiped
|
# your test database is "scratch space" for the test suite and is wiped
|
||||||
# and recreated between test runs. Don't rely on the data there!
|
# and recreated between test runs. Don't rely on the data there!
|
||||||
config.cache_classes = true
|
config.cache_classes = false
|
||||||
|
|
||||||
# Do not eager load code on boot. This avoids loading your whole application
|
# Do not eager load code on boot. This avoids loading your whole application
|
||||||
# just for the purpose of running a single test. If you are using a tool that
|
# just for the purpose of running a single test. If you are using a tool that
|
||||||
|
|
|
@ -5,11 +5,10 @@ Rails.application.config.assets.version = '1.0'
|
||||||
|
|
||||||
# Add additional assets to the asset load path
|
# Add additional assets to the asset load path
|
||||||
Rails.application.config.assets.paths << Rails.root.join('node_modules', 'trix', 'dist')
|
Rails.application.config.assets.paths << Rails.root.join('node_modules', 'trix', 'dist')
|
||||||
Rails.application.config.assets.paths << Rails.root.join('node_modules', 'select2', 'dist', 'css')
|
|
||||||
Rails.application.config.assets.paths << Rails.root.join('node_modules', 'mapbox-gl', 'dist')
|
Rails.application.config.assets.paths << Rails.root.join('node_modules', 'mapbox-gl', 'dist')
|
||||||
Rails.application.config.assets.paths << Rails.root.join('node_modules', '@reach', 'combobox')
|
Rails.application.config.assets.paths << Rails.root.join('node_modules', '@reach', 'combobox')
|
||||||
Rails.application.config.assets.paths << Rails.root.join('node_modules', '@mapbox', 'mapbox-gl-draw', 'dist')
|
Rails.application.config.assets.paths << Rails.root.join('node_modules', '@mapbox', 'mapbox-gl-draw', 'dist')
|
||||||
|
|
||||||
# Precompile additional assets.
|
# Precompile additional assets.
|
||||||
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
|
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
|
||||||
Rails.application.config.assets.precompile += ['print.css', 'new_design/new_application.css', 'new_design/print.css', 'new_design/application.js', 'new_design/manager.css']
|
Rails.application.config.assets.precompile += ['print.css']
|
||||||
|
|
|
@ -3,5 +3,5 @@ Sentry.init do |config|
|
||||||
config.send_default_pii = false
|
config.send_default_pii = false
|
||||||
config.enabled_environments = ['production']
|
config.enabled_environments = ['production']
|
||||||
config.breadcrumbs_logger = [:active_support_logger]
|
config.breadcrumbs_logger = [:active_support_logger]
|
||||||
config.traces_sample_rate = 0.01
|
config.traces_sample_rate = 0.001
|
||||||
end
|
end
|
||||||
|
|
|
@ -379,13 +379,14 @@ Rails.application.routes.draw do
|
||||||
get 'jeton'
|
get 'jeton'
|
||||||
patch 'update_jeton'
|
patch 'update_jeton'
|
||||||
put :allow_expert_review
|
put :allow_expert_review
|
||||||
get 'invited_expert_list'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
get 'publication' => 'procedures#publication', as: :publication
|
get 'publication' => 'procedures#publication', as: :publication
|
||||||
put 'publish' => 'procedures#publish', as: :publish
|
put 'publish' => 'procedures#publish', as: :publish
|
||||||
get 'transfert' => 'procedures#transfert', as: :transfert
|
get 'transfert' => 'procedures#transfert', as: :transfert
|
||||||
post 'transfer' => 'procedures#transfer', as: :transfer
|
post 'transfer' => 'procedures#transfer', as: :transfer
|
||||||
|
get 'invited_expert_list'
|
||||||
|
put 'update_allow_decision_access' => 'procedures#update_allow_decision_access', as: :update_allow_decision_access
|
||||||
|
|
||||||
resources :mail_templates, only: [:edit, :update]
|
resources :mail_templates, only: [:edit, :update]
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ default: &default
|
||||||
extensions:
|
extensions:
|
||||||
- .mjs
|
- .mjs
|
||||||
- .js
|
- .js
|
||||||
|
- .jsx
|
||||||
- .sass
|
- .sass
|
||||||
- .scss
|
- .scss
|
||||||
- .css
|
- .css
|
||||||
|
|
33
package.json
33
package.json
|
@ -1,15 +1,15 @@
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/preset-react": "^7.10.4",
|
"@babel/preset-react": "^7.12.13",
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.28",
|
"@fortawesome/fontawesome-svg-core": "^1.2.34",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.13.0",
|
"@fortawesome/free-solid-svg-icons": "^5.15.2",
|
||||||
"@fortawesome/react-fontawesome": "^0.1.9",
|
"@fortawesome/react-fontawesome": "^0.1.14",
|
||||||
"@mapbox/mapbox-gl-draw": "^1.2.0",
|
"@mapbox/mapbox-gl-draw": "^1.2.0",
|
||||||
"@rails/actiontext": "^6.0.3",
|
"@rails/actiontext": "^6.0.3",
|
||||||
"@rails/activestorage": "^6.0.3",
|
"@rails/activestorage": "^6.0.3",
|
||||||
"@rails/ujs": "^6.0.3",
|
"@rails/ujs": "^6.0.3",
|
||||||
"@rails/webpacker": "5.1.1",
|
"@rails/webpacker": "5.1.1",
|
||||||
"@reach/combobox": "^0.10.2",
|
"@reach/combobox": "^0.13.0",
|
||||||
"@sentry/browser": "^5.15.5",
|
"@sentry/browser": "^5.15.5",
|
||||||
"@tmcw/togeojson": "^4.0.0",
|
"@tmcw/togeojson": "^4.0.0",
|
||||||
"babel-plugin-macros": "^2.8.0",
|
"babel-plugin-macros": "^2.8.0",
|
||||||
|
@ -20,23 +20,20 @@
|
||||||
"dom4": "^2.1.5",
|
"dom4": "^2.1.5",
|
||||||
"email-butler": "^1.0.13",
|
"email-butler": "^1.0.13",
|
||||||
"highcharts": "^8.1.1",
|
"highcharts": "^8.1.1",
|
||||||
"intersection-observer": "^0.10.0",
|
"intersection-observer": "^0.12.0",
|
||||||
"jquery": "^3.5.1",
|
|
||||||
"mapbox-gl": "^1.11.1",
|
"mapbox-gl": "^1.11.1",
|
||||||
"match-sorter": "^4.2.1",
|
"match-sorter": "^6.2.0",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"react": "^16.13.1",
|
"react": "^17.0.1",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^17.0.1",
|
||||||
"react-intersection-observer": "^8.26.2",
|
"react-intersection-observer": "^8.31.0",
|
||||||
"react-mapbox-gl": "^4.8.6",
|
"react-mapbox-gl": "^4.8.6",
|
||||||
"react-mapbox-gl-draw": "^2.0.4",
|
"react-mapbox-gl-draw": "^2.0.4",
|
||||||
"react-query": "^2.23.1",
|
"react-query": "^3.9.7",
|
||||||
"react-scroll-to-component": "^1.0.2",
|
|
||||||
"react-sortable-hoc": "^1.11.0",
|
"react-sortable-hoc": "^1.11.0",
|
||||||
"react-use": "^15.3.4",
|
|
||||||
"react_ujs": "^2.6.1",
|
"react_ujs": "^2.6.1",
|
||||||
"select2": "^4.0.13",
|
|
||||||
"trix": "^1.2.3",
|
"trix": "^1.2.3",
|
||||||
|
"use-debounce": "^5.2.0",
|
||||||
"whatwg-fetch": "^3.0.0"
|
"whatwg-fetch": "^3.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -45,15 +42,15 @@
|
||||||
"eslint": "^7.0.0",
|
"eslint": "^7.0.0",
|
||||||
"eslint-config-prettier": "^6.11.0",
|
"eslint-config-prettier": "^6.11.0",
|
||||||
"eslint-plugin-prettier": "^3.1.3",
|
"eslint-plugin-prettier": "^3.1.3",
|
||||||
"eslint-plugin-react": "^7.20.0",
|
"eslint-plugin-react": "^7.22.0",
|
||||||
"eslint-plugin-react-hooks": "^4.0.2",
|
"eslint-plugin-react-hooks": "^4.2.0",
|
||||||
"netlify-cli": "^2.61.2",
|
"netlify-cli": "^2.61.2",
|
||||||
"prettier": "^2.0.5",
|
"prettier": "^2.0.5",
|
||||||
"webpack-bundle-analyzer": "^3.7.0",
|
"webpack-bundle-analyzer": "^3.7.0",
|
||||||
"webpack-dev-server": "^3.11.0"
|
"webpack-dev-server": "^3.11.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint:js": "eslint ./app/javascript ./config/webpack",
|
"lint:js": "eslint --ext .js,.jsx,.ts,.tsx ./app/javascript ./config/webpack",
|
||||||
"webpack:build": "NODE_ENV=production bin/webpack",
|
"webpack:build": "NODE_ENV=production bin/webpack",
|
||||||
"graphql:docs:build": "graphdoc --force",
|
"graphql:docs:build": "graphdoc --force",
|
||||||
"graphql:docs:deploy": "netlify deploy -d ./docs/graphql --prod",
|
"graphql:docs:deploy": "netlify deploy -d ./docs/graphql --prod",
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
describe API::V2::GraphqlController do
|
describe API::V2::GraphqlController do
|
||||||
let(:admin) { create(:administrateur) }
|
let(:admin) { create(:administrateur) }
|
||||||
let(:token) { admin.renew_api_token }
|
let(:token) { admin.renew_api_token }
|
||||||
let(:procedure) { create(:procedure, :published, :for_individual, :with_service, :with_all_champs, administrateurs: [admin]) }
|
let(:procedure) { create(:procedure, :published, :for_individual, :with_service, :with_all_champs, :with_all_annotations, administrateurs: [admin]) }
|
||||||
let(:dossier) do
|
let(:dossier) do
|
||||||
dossier = create(:dossier,
|
dossier = create(:dossier,
|
||||||
:en_construction,
|
:en_construction,
|
||||||
:with_all_champs,
|
:with_all_champs,
|
||||||
|
:with_all_annotations,
|
||||||
:with_individual,
|
:with_individual,
|
||||||
procedure: procedure)
|
procedure: procedure)
|
||||||
create(:commentaire, :with_file, dossier: dossier, email: 'test@test.com')
|
create(:commentaire, :with_file, dossier: dossier, email: 'test@test.com')
|
||||||
|
@ -1117,6 +1118,240 @@ describe API::V2::GraphqlController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'dossierModifierAnnotation' do
|
||||||
|
describe 'text' do
|
||||||
|
let(:query) do
|
||||||
|
"mutation {
|
||||||
|
dossierModifierAnnotationText(input: {
|
||||||
|
dossierId: \"#{dossier.to_typed_id}\",
|
||||||
|
annotationId: \"#{dossier.champs_private.first.to_typed_id}\",
|
||||||
|
instructeurId: \"#{instructeur.to_typed_id}\",
|
||||||
|
value: \"hello\"
|
||||||
|
}) {
|
||||||
|
annotation {
|
||||||
|
stringValue
|
||||||
|
}
|
||||||
|
errors {
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
end
|
||||||
|
|
||||||
|
context "success" do
|
||||||
|
it 'should be a success' do
|
||||||
|
expect(gql_errors).to eq(nil)
|
||||||
|
|
||||||
|
expect(gql_data).to eq(dossierModifierAnnotationText: {
|
||||||
|
annotation: {
|
||||||
|
stringValue: 'hello'
|
||||||
|
},
|
||||||
|
errors: nil
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'checkbox' do
|
||||||
|
let(:value) { 'true' }
|
||||||
|
|
||||||
|
let(:query) do
|
||||||
|
"mutation {
|
||||||
|
dossierModifierAnnotationCheckbox(input: {
|
||||||
|
dossierId: \"#{dossier.to_typed_id}\",
|
||||||
|
annotationId: \"#{dossier.champs_private.find { |c| c.type_champ == 'checkbox' }.to_typed_id}\",
|
||||||
|
instructeurId: \"#{instructeur.to_typed_id}\",
|
||||||
|
value: #{value}
|
||||||
|
}) {
|
||||||
|
annotation {
|
||||||
|
stringValue
|
||||||
|
}
|
||||||
|
errors {
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
end
|
||||||
|
|
||||||
|
context "success when true" do
|
||||||
|
it 'should be a success' do
|
||||||
|
expect(gql_errors).to eq(nil)
|
||||||
|
|
||||||
|
expect(gql_data).to eq(dossierModifierAnnotationCheckbox: {
|
||||||
|
annotation: {
|
||||||
|
stringValue: 'true'
|
||||||
|
},
|
||||||
|
errors: nil
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "success when false" do
|
||||||
|
let(:value) { 'false' }
|
||||||
|
|
||||||
|
it 'should be a success' do
|
||||||
|
expect(gql_errors).to eq(nil)
|
||||||
|
|
||||||
|
expect(gql_data).to eq(dossierModifierAnnotationCheckbox: {
|
||||||
|
annotation: {
|
||||||
|
stringValue: 'false'
|
||||||
|
},
|
||||||
|
errors: nil
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'yes_no' do
|
||||||
|
let(:value) { 'true' }
|
||||||
|
|
||||||
|
let(:query) do
|
||||||
|
"mutation {
|
||||||
|
dossierModifierAnnotationCheckbox(input: {
|
||||||
|
dossierId: \"#{dossier.to_typed_id}\",
|
||||||
|
annotationId: \"#{dossier.champs_private.find { |c| c.type_champ == 'yes_no' }.to_typed_id}\",
|
||||||
|
instructeurId: \"#{instructeur.to_typed_id}\",
|
||||||
|
value: #{value}
|
||||||
|
}) {
|
||||||
|
annotation {
|
||||||
|
stringValue
|
||||||
|
}
|
||||||
|
errors {
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
end
|
||||||
|
|
||||||
|
context "success when true" do
|
||||||
|
it 'should be a success' do
|
||||||
|
expect(gql_errors).to eq(nil)
|
||||||
|
|
||||||
|
expect(gql_data).to eq(dossierModifierAnnotationCheckbox: {
|
||||||
|
annotation: {
|
||||||
|
stringValue: 'true'
|
||||||
|
},
|
||||||
|
errors: nil
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "success when false" do
|
||||||
|
let(:value) { 'false' }
|
||||||
|
|
||||||
|
it 'should be a success' do
|
||||||
|
expect(gql_errors).to eq(nil)
|
||||||
|
|
||||||
|
expect(gql_data).to eq(dossierModifierAnnotationCheckbox: {
|
||||||
|
annotation: {
|
||||||
|
stringValue: 'false'
|
||||||
|
},
|
||||||
|
errors: nil
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'date' do
|
||||||
|
let(:query) do
|
||||||
|
"mutation {
|
||||||
|
dossierModifierAnnotationDate(input: {
|
||||||
|
dossierId: \"#{dossier.to_typed_id}\",
|
||||||
|
annotationId: \"#{dossier.champs_private.find { |c| c.type_champ == 'date' }.to_typed_id}\",
|
||||||
|
instructeurId: \"#{instructeur.to_typed_id}\",
|
||||||
|
value: \"#{1.day.from_now.to_date.iso8601}\"
|
||||||
|
}) {
|
||||||
|
annotation {
|
||||||
|
stringValue
|
||||||
|
}
|
||||||
|
errors {
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
end
|
||||||
|
|
||||||
|
context "success" do
|
||||||
|
it 'should be a success' do
|
||||||
|
expect(gql_errors).to eq(nil)
|
||||||
|
|
||||||
|
expect(gql_data).to eq(dossierModifierAnnotationDate: {
|
||||||
|
annotation: {
|
||||||
|
stringValue: dossier.reload.champs_private.find { |c| c.type_champ == 'date' }.to_s
|
||||||
|
},
|
||||||
|
errors: nil
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'datetime' do
|
||||||
|
let(:query) do
|
||||||
|
"mutation {
|
||||||
|
dossierModifierAnnotationDatetime(input: {
|
||||||
|
dossierId: \"#{dossier.to_typed_id}\",
|
||||||
|
annotationId: \"#{dossier.champs_private.find { |c| c.type_champ == 'datetime' }.to_typed_id}\",
|
||||||
|
instructeurId: \"#{instructeur.to_typed_id}\",
|
||||||
|
value: \"#{1.day.from_now.iso8601}\"
|
||||||
|
}) {
|
||||||
|
annotation {
|
||||||
|
stringValue
|
||||||
|
}
|
||||||
|
errors {
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
end
|
||||||
|
|
||||||
|
context "success" do
|
||||||
|
it 'should be a success' do
|
||||||
|
expect(gql_errors).to eq(nil)
|
||||||
|
|
||||||
|
expect(gql_data).to eq(dossierModifierAnnotationDatetime: {
|
||||||
|
annotation: {
|
||||||
|
stringValue: dossier.reload.champs_private.find { |c| c.type_champ == 'datetime' }.to_s
|
||||||
|
},
|
||||||
|
errors: nil
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'integer_number' do
|
||||||
|
let(:query) do
|
||||||
|
"mutation {
|
||||||
|
dossierModifierAnnotationIntegerNumber(input: {
|
||||||
|
dossierId: \"#{dossier.to_typed_id}\",
|
||||||
|
annotationId: \"#{dossier.champs_private.find { |c| c.type_champ == 'integer_number' }.to_typed_id}\",
|
||||||
|
instructeurId: \"#{instructeur.to_typed_id}\",
|
||||||
|
value: 42
|
||||||
|
}) {
|
||||||
|
annotation {
|
||||||
|
stringValue
|
||||||
|
}
|
||||||
|
errors {
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
end
|
||||||
|
|
||||||
|
context "success" do
|
||||||
|
it 'should be a success' do
|
||||||
|
expect(gql_errors).to eq(nil)
|
||||||
|
|
||||||
|
expect(gql_data).to eq(dossierModifierAnnotationIntegerNumber: {
|
||||||
|
annotation: {
|
||||||
|
stringValue: '42'
|
||||||
|
},
|
||||||
|
errors: nil
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ describe Instructeurs::DossiersController, type: :controller do
|
||||||
post(
|
post(
|
||||||
:send_to_instructeurs,
|
:send_to_instructeurs,
|
||||||
params: {
|
params: {
|
||||||
recipients: [recipient],
|
recipients: [recipient.id].to_json,
|
||||||
procedure_id: procedure.id,
|
procedure_id: procedure.id,
|
||||||
dossier_id: dossier.id
|
dossier_id: dossier.id
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,11 +207,11 @@ describe NewAdministrateur::GroupeInstructeursController, type: :controller do
|
||||||
|
|
||||||
describe '#add_instructeur_procedure_non_routee' do
|
describe '#add_instructeur_procedure_non_routee' do
|
||||||
let(:procedure) { create :procedure, administrateur: admin }
|
let(:procedure) { create :procedure, administrateur: admin }
|
||||||
let(:emails) { ['instructeur_3@ministere_a.gouv.fr', 'instructeur_4@ministere_b.gouv.fr'] }
|
let(:emails) { ['instructeur_3@ministere_a.gouv.fr', 'instructeur_4@ministere_b.gouv.fr'].to_json }
|
||||||
subject { post :add_instructeur, params: { emails: emails, procedure_id: procedure.id, id: gi_1_1.id } }
|
subject { post :add_instructeur, params: { emails: emails, procedure_id: procedure.id, id: gi_1_1.id } }
|
||||||
|
|
||||||
context 'when all emails are valid' do
|
context 'when all emails are valid' do
|
||||||
let(:emails) { ['test@b.gouv.fr', 'test2@b.gouv.fr'] }
|
let(:emails) { ['test@b.gouv.fr', 'test2@b.gouv.fr'].to_json }
|
||||||
it { expect(response.status).to eq(200) }
|
it { expect(response.status).to eq(200) }
|
||||||
it { expect(subject.request.flash[:alert]).to be_nil }
|
it { expect(subject.request.flash[:alert]).to be_nil }
|
||||||
it { expect(subject.request.flash[:notice]).to be_present }
|
it { expect(subject.request.flash[:notice]).to be_present }
|
||||||
|
@ -219,7 +219,7 @@ describe NewAdministrateur::GroupeInstructeursController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when there is at least one bad email' do
|
context 'when there is at least one bad email' do
|
||||||
let(:emails) { ['badmail', 'instructeur2@gmail.com'] }
|
let(:emails) { ['badmail', 'instructeur2@gmail.com'].to_json }
|
||||||
it { expect(response.status).to eq(200) }
|
it { expect(response.status).to eq(200) }
|
||||||
it { expect(subject.request.flash[:alert]).to be_present }
|
it { expect(subject.request.flash[:alert]).to be_present }
|
||||||
it { expect(subject.request.flash[:notice]).to be_present }
|
it { expect(subject.request.flash[:notice]).to be_present }
|
||||||
|
@ -227,7 +227,7 @@ describe NewAdministrateur::GroupeInstructeursController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the admin wants to assign an instructor who is already assigned on this procedure' do
|
context 'when the admin wants to assign an instructor who is already assigned on this procedure' do
|
||||||
let(:emails) { ['instructeur_1@ministere_a.gouv.fr'] }
|
let(:emails) { ['instructeur_1@ministere_a.gouv.fr'].to_json }
|
||||||
it { expect(subject.request.flash[:alert]).to be_present }
|
it { expect(subject.request.flash[:alert]).to be_present }
|
||||||
it { expect(subject).to redirect_to admin_procedure_groupe_instructeur_path(procedure, procedure.defaut_groupe_instructeur) }
|
it { expect(subject).to redirect_to admin_procedure_groupe_instructeur_path(procedure, procedure.defaut_groupe_instructeur) }
|
||||||
end
|
end
|
||||||
|
@ -247,7 +247,7 @@ describe NewAdministrateur::GroupeInstructeursController, type: :controller do
|
||||||
params: {
|
params: {
|
||||||
procedure_id: procedure.id,
|
procedure_id: procedure.id,
|
||||||
id: gi_1_2.id,
|
id: gi_1_2.id,
|
||||||
emails: new_instructeur_emails
|
emails: new_instructeur_emails.to_json
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -281,7 +281,7 @@ describe NewAdministrateur::GroupeInstructeursController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'of an empty string' do
|
context 'of an empty string' do
|
||||||
let(:new_instructeur_emails) { '' }
|
let(:new_instructeur_emails) { [''] }
|
||||||
|
|
||||||
it { expect(response).to redirect_to(admin_procedure_groupe_instructeur_path(procedure, gi_1_2)) }
|
it { expect(response).to redirect_to(admin_procedure_groupe_instructeur_path(procedure, gi_1_2)) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -532,4 +532,34 @@ describe NewAdministrateur::ProceduresController, type: :controller do
|
||||||
it { expect(procedure.allow_expert_review).to be_truthy }
|
it { expect(procedure.allow_expert_review).to be_truthy }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'PUT #update_allow_decision_access' do
|
||||||
|
let!(:procedure) { create :procedure, :with_service, administrateur: admin }
|
||||||
|
let(:expert) { create(:expert) }
|
||||||
|
let(:expert_procedure) { ExpertsProcedure.create(procedure: procedure, expert: expert) }
|
||||||
|
|
||||||
|
subject do
|
||||||
|
put :update_allow_decision_access, params: { procedure_id: procedure.id, experts_procedure: { allow_decision_access: !expert_procedure.allow_decision_access }, expert_procedure: expert_procedure }, format: :js
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the experts_procedure is true' do
|
||||||
|
let(:expert_procedure) { ExpertsProcedure.create(procedure: procedure, expert: expert, allow_decision_access: true) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
subject
|
||||||
|
expert_procedure.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(expert_procedure.allow_decision_access).to be_falsy }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the experts_procedure is false' do
|
||||||
|
before do
|
||||||
|
subject
|
||||||
|
expert_procedure.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(expert_procedure.allow_decision_access).to be_truthy }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -216,8 +216,8 @@ FactoryBot.define do
|
||||||
|
|
||||||
trait :with_all_annotations do
|
trait :with_all_annotations do
|
||||||
after(:create) do |dossier, _evaluator|
|
after(:create) do |dossier, _evaluator|
|
||||||
dossier.champs = dossier.types_de_champ.map do |type_de_champ|
|
dossier.champs_private = dossier.types_de_champ_private.map do |type_de_champ|
|
||||||
build(:"champ_#{type_de_champ.type_champ}", dossier: dossier, type_de_champ: type_de_champ)
|
build(:"champ_#{type_de_champ.type_champ}", private: true, dossier: dossier, type_de_champ: type_de_champ)
|
||||||
end
|
end
|
||||||
dossier.save!
|
dossier.save!
|
||||||
end
|
end
|
||||||
|
|
|
@ -128,10 +128,8 @@ feature 'Instructing a dossier:' do
|
||||||
|
|
||||||
click_on 'Personnes impliquées'
|
click_on 'Personnes impliquées'
|
||||||
|
|
||||||
first('.select2-container', minimum: 1).click
|
select_multi('email instructeur', instructeur_2.email)
|
||||||
find('li.select2-results__option[role="option"]', text: instructeur_2.email).click
|
select_multi('email instructeur', instructeur_3.email)
|
||||||
first('.select2-container', minimum: 1).click
|
|
||||||
find('li.select2-results__option[role="option"]', text: instructeur_3.email).click
|
|
||||||
|
|
||||||
click_on 'Envoyer'
|
click_on 'Envoyer'
|
||||||
|
|
||||||
|
|
|
@ -125,15 +125,13 @@ feature "procedure filters" do
|
||||||
|
|
||||||
def add_column(column_name)
|
def add_column(column_name)
|
||||||
click_on 'Personnaliser'
|
click_on 'Personnaliser'
|
||||||
find("span.select2-container").click
|
select_multi('colonne', column_name)
|
||||||
find(:xpath, "//li[text()='#{column_name}']").click
|
|
||||||
click_button "Enregistrer"
|
click_button "Enregistrer"
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_column(column_name)
|
def remove_column(column_name)
|
||||||
click_on 'Personnaliser'
|
click_on 'Personnaliser'
|
||||||
find(:xpath, "//li[contains(@title, '#{column_name}')]/span[contains(text(), '×')]").click
|
find(:xpath, "//li[contains(text(), '#{column_name}')]/span[contains(text(), 'x')]").click
|
||||||
find(:xpath, "//form[contains(@class, 'columns-form')]//span[contains(@class, 'select2-container')]").click
|
|
||||||
click_button "Enregistrer"
|
click_button "Enregistrer"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,14 +30,14 @@ feature 'The routing', js: true do
|
||||||
expect(page).to have_field('Nom du groupe', with: 'littéraire')
|
expect(page).to have_field('Nom du groupe', with: 'littéraire')
|
||||||
|
|
||||||
# add victor to littéraire groupe
|
# add victor to littéraire groupe
|
||||||
find('input.select2-search__field').send_keys('victor@inst.com', :enter)
|
find("input[aria-label='email instructeur'").send_keys('victor@inst.com', :enter)
|
||||||
perform_enqueued_jobs { click_on 'Affecter' }
|
perform_enqueued_jobs { click_on 'Affecter' }
|
||||||
expect(page).to have_text("Les instructeurs ont bien été affectés à la démarche")
|
expect(page).to have_text("Les instructeurs ont bien été affectés à la démarche")
|
||||||
|
|
||||||
victor = User.find_by(email: 'victor@inst.com').instructeur
|
victor = User.find_by(email: 'victor@inst.com').instructeur
|
||||||
|
|
||||||
# add superwoman to littéraire groupe
|
# add superwoman to littéraire groupe
|
||||||
find('input.select2-search__field').send_keys('superwoman@inst.com', :enter)
|
find("input[aria-label='email instructeur'").send_keys('superwoman@inst.com', :enter)
|
||||||
perform_enqueued_jobs { click_on 'Affecter' }
|
perform_enqueued_jobs { click_on 'Affecter' }
|
||||||
expect(page).to have_text("Les instructeurs ont bien été affectés à la démarche")
|
expect(page).to have_text("Les instructeurs ont bien été affectés à la démarche")
|
||||||
|
|
||||||
|
@ -50,14 +50,14 @@ feature 'The routing', js: true do
|
||||||
expect(page).to have_text('Le groupe d’instructeurs « scientifique » a été créé.')
|
expect(page).to have_text('Le groupe d’instructeurs « scientifique » a été créé.')
|
||||||
|
|
||||||
# add marie to scientifique groupe
|
# add marie to scientifique groupe
|
||||||
find('input.select2-search__field').send_keys('marie@inst.com', :enter)
|
find("input[aria-label='email instructeur'").send_keys('marie@inst.com', :enter)
|
||||||
perform_enqueued_jobs { click_on 'Affecter' }
|
perform_enqueued_jobs { click_on 'Affecter' }
|
||||||
expect(page).to have_text("L’instructeur marie@inst.com a été affecté")
|
expect(page).to have_text("L’instructeur marie@inst.com a été affecté")
|
||||||
|
|
||||||
marie = User.find_by(email: 'marie@inst.com').instructeur
|
marie = User.find_by(email: 'marie@inst.com').instructeur
|
||||||
|
|
||||||
# add superwoman to scientifique groupe
|
# add superwoman to scientifique groupe
|
||||||
find('input.select2-search__field').send_keys('superwoman@inst.com', :enter)
|
find("input[aria-label='email instructeur'").send_keys('superwoman@inst.com', :enter)
|
||||||
perform_enqueued_jobs { click_on 'Affecter' }
|
perform_enqueued_jobs { click_on 'Affecter' }
|
||||||
expect(page).to have_text("L’instructeur superwoman@inst.com a été affecté")
|
expect(page).to have_text("L’instructeur superwoman@inst.com a été affecté")
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,9 @@ feature 'The user' do
|
||||||
check('val1')
|
check('val1')
|
||||||
check('val3')
|
check('val3')
|
||||||
select('bravo', from: form_id_for('simple_choice_drop_down_list_long'))
|
select('bravo', from: form_id_for('simple_choice_drop_down_list_long'))
|
||||||
select('alpha', from: form_id_for('multiple_choice_drop_down_list_long'))
|
select_multi('multiple_choice_drop_down_list_long', 'alpha')
|
||||||
select('charly', from: form_id_for('multiple_choice_drop_down_list_long'))
|
select_multi('multiple_choice_drop_down_list_long', 'charly')
|
||||||
|
|
||||||
select_champ_geo('pays', 'aust', 'AUSTRALIE')
|
select_champ_geo('pays', 'aust', 'AUSTRALIE')
|
||||||
|
|
||||||
select_champ_geo('regions', 'Ma', 'Martinique')
|
select_champ_geo('regions', 'Ma', 'Martinique')
|
||||||
|
@ -83,7 +84,7 @@ feature 'The user' do
|
||||||
expect(page).to have_checked_field('val1')
|
expect(page).to have_checked_field('val1')
|
||||||
expect(page).to have_checked_field('val3')
|
expect(page).to have_checked_field('val3')
|
||||||
expect(page).to have_selected_value('simple_choice_drop_down_list_long', selected: 'bravo')
|
expect(page).to have_selected_value('simple_choice_drop_down_list_long', selected: 'bravo')
|
||||||
expect(page).to have_selected_value('multiple_choice_drop_down_list_long', selected: ['alpha', 'charly'])
|
check_selected_values('multiple_choice_drop_down_list_long', ['alpha', 'charly'])
|
||||||
expect(page).to have_hidden_field('pays', with: 'AUSTRALIE')
|
expect(page).to have_hidden_field('pays', with: 'AUSTRALIE')
|
||||||
expect(page).to have_hidden_field('regions', with: 'Martinique')
|
expect(page).to have_hidden_field('regions', with: 'Martinique')
|
||||||
expect(page).to have_hidden_field('departements', with: '02 - Aisne')
|
expect(page).to have_hidden_field('departements', with: '02 - Aisne')
|
||||||
|
|
|
@ -7,7 +7,7 @@ RSpec.describe ExpertsProcedure, type: :model do
|
||||||
let(:experts_procedure) { ExpertsProcedure.create(expert: expert, procedure: procedure) }
|
let(:experts_procedure) { ExpertsProcedure.create(expert: expert, procedure: procedure) }
|
||||||
let(:experts_procedure2) { ExpertsProcedure.create(expert: expert2, procedure: procedure) }
|
let(:experts_procedure2) { ExpertsProcedure.create(expert: expert2, procedure: procedure) }
|
||||||
let(:experts_procedure3) { ExpertsProcedure.create(expert: expert3, procedure: procedure) }
|
let(:experts_procedure3) { ExpertsProcedure.create(expert: expert3, procedure: procedure) }
|
||||||
subject { ExpertsProcedure.invited_expert_emails(procedure) }
|
subject { procedure.experts_procedures }
|
||||||
|
|
||||||
context 'when there is one dossier' do
|
context 'when there is one dossier' do
|
||||||
let!(:dossier) { create(:dossier, procedure: procedure) }
|
let!(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
@ -15,14 +15,18 @@ RSpec.describe ExpertsProcedure, type: :model do
|
||||||
context 'when a procedure has one avis and known instructeur' do
|
context 'when a procedure has one avis and known instructeur' do
|
||||||
let!(:avis) { create(:avis, dossier: dossier, instructeur: create(:instructeur, email: expert.email), experts_procedure: experts_procedure) }
|
let!(:avis) { create(:avis, dossier: dossier, instructeur: create(:instructeur, email: expert.email), experts_procedure: experts_procedure) }
|
||||||
|
|
||||||
it { is_expected.to eq([expert.email]) }
|
it { is_expected.to eq([experts_procedure]) }
|
||||||
|
it { expect(procedure.experts.count).to eq(1) }
|
||||||
|
it { expect(procedure.experts.first.email).to eq(expert.email) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when a dossier has 2 avis from the same expert' do
|
context 'when a dossier has 2 avis from the same expert' do
|
||||||
let!(:avis) { create(:avis, dossier: dossier, experts_procedure: experts_procedure) }
|
let!(:avis) { create(:avis, dossier: dossier, experts_procedure: experts_procedure) }
|
||||||
let!(:avis2) { create(:avis, dossier: dossier, experts_procedure: experts_procedure) }
|
let!(:avis2) { create(:avis, dossier: dossier, experts_procedure: experts_procedure) }
|
||||||
|
|
||||||
it { is_expected.to eq([expert.email]) }
|
it { is_expected.to eq([experts_procedure]) }
|
||||||
|
it { expect(procedure.experts.count).to eq(1) }
|
||||||
|
it { expect(procedure.experts.first).to eq(expert) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -35,7 +39,9 @@ RSpec.describe ExpertsProcedure, type: :model do
|
||||||
let!(:avis2) { create(:avis, dossier: dossier2, experts_procedure: experts_procedure2) }
|
let!(:avis2) { create(:avis, dossier: dossier2, experts_procedure: experts_procedure2) }
|
||||||
let!(:avis3) { create(:avis, dossier: dossier2, experts_procedure: experts_procedure3) }
|
let!(:avis3) { create(:avis, dossier: dossier2, experts_procedure: experts_procedure3) }
|
||||||
|
|
||||||
it { is_expected.to eq([expert.email, expert2.email, expert3.email].sort) }
|
it { is_expected.to match_array([experts_procedure, experts_procedure2, experts_procedure3]) }
|
||||||
|
it { expect(procedure.experts.count).to eq(3) }
|
||||||
|
it { expect(procedure.experts).to match_array([expert, expert2, expert3]) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -914,9 +914,11 @@ describe ProcedurePresentation do
|
||||||
it 'should downcase and transform value' do
|
it 'should downcase and transform value' do
|
||||||
procedure_presentation.add_filter("suivis", "type_de_champ/#{first_type_de_champ_id}", "Oui")
|
procedure_presentation.add_filter("suivis", "type_de_champ/#{first_type_de_champ_id}", "Oui")
|
||||||
|
|
||||||
expect(procedure_presentation.filters).to eq({ "suivis" => [
|
expect(procedure_presentation.filters).to eq({
|
||||||
{ "label" => first_type_de_champ.libelle, "table" => "type_de_champ", "column" => first_type_de_champ_id, "value" => "true" }
|
"suivis" =>
|
||||||
]
|
[
|
||||||
|
{ "label" => first_type_de_champ.libelle, "table" => "type_de_champ", "column" => first_type_de_champ_id, "value" => "true" }
|
||||||
|
]
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -927,9 +929,10 @@ describe ProcedurePresentation do
|
||||||
it 'should passthrough value' do
|
it 'should passthrough value' do
|
||||||
procedure_presentation.add_filter("suivis", "type_de_champ/#{first_type_de_champ_id}", "Oui")
|
procedure_presentation.add_filter("suivis", "type_de_champ/#{first_type_de_champ_id}", "Oui")
|
||||||
|
|
||||||
expect(procedure_presentation.filters).to eq({ "suivis" => [
|
expect(procedure_presentation.filters).to eq({
|
||||||
{ "label" => first_type_de_champ.libelle, "table" => "type_de_champ", "column" => first_type_de_champ_id, "value" => "Oui" }
|
"suivis" => [
|
||||||
]
|
{ "label" => first_type_de_champ.libelle, "table" => "type_de_champ", "column" => first_type_de_champ_id, "value" => "Oui" }
|
||||||
|
]
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,8 +27,8 @@ module FeatureHelpers
|
||||||
if sign_in_by_link
|
if sign_in_by_link
|
||||||
mail = ActionMailer::Base.deliveries.last
|
mail = ActionMailer::Base.deliveries.last
|
||||||
message = mail.html_part.body.raw_source
|
message = mail.html_part.body.raw_source
|
||||||
instructeur_id = message[/\".+\/connexion-par-jeton\/(.+)\?jeton=(.*)\"/, 1]
|
instructeur_id = message[/".+\/connexion-par-jeton\/(.+)\?jeton=(.*)"/, 1]
|
||||||
jeton = message[/\".+\/connexion-par-jeton\/(.+)\?jeton=(.*)\"/, 2]
|
jeton = message[/".+\/connexion-par-jeton\/(.+)\?jeton=(.*)"/, 2]
|
||||||
|
|
||||||
visit sign_in_by_link_path(instructeur_id, jeton: jeton)
|
visit sign_in_by_link_path(instructeur_id, jeton: jeton)
|
||||||
end
|
end
|
||||||
|
@ -103,6 +103,25 @@ module FeatureHelpers
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def select_multi(champ, with)
|
||||||
|
input = find("input[aria-label='#{champ}'")
|
||||||
|
input.click
|
||||||
|
|
||||||
|
# hack because for unknown reason, the click on input doesn't show combobox-popover with selenium driver
|
||||||
|
script = "document.evaluate(\"//input[@aria-label='#{champ}']//ancestor::div[@data-reach-combobox]/div[@data-reach-combobox-popover]\", document, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null).iterateNext().removeAttribute(\"hidden\")"
|
||||||
|
execute_script(script)
|
||||||
|
|
||||||
|
element = find(:xpath, "//input[@aria-label='#{champ}']/ancestor::div[@data-reach-combobox]//div[@data-reach-combobox-popover]//li/span[normalize-space(text())='#{with}']")
|
||||||
|
element.click
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_selected_values(champ, values)
|
||||||
|
combobox = find(:xpath, "//input[@aria-label='#{champ}']/ancestor::div[@data-react-class='ComboMultipleDropdownList']")
|
||||||
|
hiddenFieldId = JSON.parse(combobox["data-react-props"])["hiddenFieldId"]
|
||||||
|
hiddenField = find("input[data-uuid='#{hiddenFieldId}']")
|
||||||
|
expect(values.sort).to eq(JSON.parse(hiddenField.value).sort)
|
||||||
|
end
|
||||||
|
|
||||||
# Keep the brower window open after a test success of failure, to
|
# Keep the brower window open after a test success of failure, to
|
||||||
# allow inspecting the page or the console.
|
# allow inspecting the page or the console.
|
||||||
#
|
#
|
||||||
|
|
|
@ -13,7 +13,7 @@ describe 'instructeurs/dossiers/envoyer_dossier_block.html.haml', type: :view do
|
||||||
let(:instructeur) { create(:instructeur, email: 'yop@totomail.fr') }
|
let(:instructeur) { create(:instructeur, email: 'yop@totomail.fr') }
|
||||||
let(:potential_recipients) { [instructeur] }
|
let(:potential_recipients) { [instructeur] }
|
||||||
|
|
||||||
it { is_expected.to have_css("select > option[value='#{instructeur.id}']") }
|
it { is_expected.to match(/data-react-props.*#{instructeur.email}/) }
|
||||||
it { is_expected.to have_css(".button.send") }
|
it { is_expected.to have_css(".button.send") }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -12,13 +12,13 @@ describe 'new_administrateur/procedures/invited_expert_list.html.haml', type: :v
|
||||||
context 'when the procedure has 0 avis' do
|
context 'when the procedure has 0 avis' do
|
||||||
let!(:dossier) { create(:dossier, procedure: procedure) }
|
let!(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
before do
|
before do
|
||||||
@invited_expert_emails = ExpertsProcedure.invited_expert_emails(procedure)
|
@invited_experts = procedure.experts_procedures
|
||||||
subject
|
subject
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'has 0 experts into the page' do
|
it 'has 0 experts into the page' do
|
||||||
expect(@invited_expert_emails.count).to eq(0)
|
expect(@invited_experts.count).to eq(0)
|
||||||
expect(@invited_expert_emails).to eq([])
|
expect(@invited_experts).to eq([])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -32,13 +32,13 @@ describe 'new_administrateur/procedures/invited_expert_list.html.haml', type: :v
|
||||||
let!(:avis2) { create(:avis, dossier: dossier, experts_procedure: experts_procedure2) }
|
let!(:avis2) { create(:avis, dossier: dossier, experts_procedure: experts_procedure2) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@invited_expert_emails = ExpertsProcedure.invited_expert_emails(procedure)
|
@invited_experts = procedure.experts_procedures
|
||||||
subject
|
subject
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'has 2 experts and match array' do
|
it 'has 2 experts and match array' do
|
||||||
expect(@invited_expert_emails.count).to eq(2)
|
expect(@invited_experts.count).to eq(2)
|
||||||
expect(@invited_expert_emails).to eq([expert.email, expert2.email].sort)
|
expect(@invited_experts).to match_array([experts_procedure, experts_procedure2])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -82,7 +82,7 @@ describe 'shared/dossiers/edit.html.haml', type: :view do
|
||||||
let(:type_de_champ) { create(:type_de_champ_multiple_drop_down_list, :long, procedure: dossier.procedure) }
|
let(:type_de_champ) { create(:type_de_champ_multiple_drop_down_list, :long, procedure: dossier.procedure) }
|
||||||
|
|
||||||
it 'renders the list as a multiple-selection dropdown' do
|
it 'renders the list as a multiple-selection dropdown' do
|
||||||
expect(subject).to have_selector('select.select2')
|
expect(subject).to have_selector('[data-react-class="ComboMultipleDropdownList"]')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue