commit
917f3cadf7
50 changed files with 649 additions and 161 deletions
|
@ -90,20 +90,8 @@ jobs:
|
|||
- *yarn_restore_cache
|
||||
- *yarn_install
|
||||
- run:
|
||||
name: Run eslint
|
||||
command: yarn lint:js
|
||||
- run:
|
||||
name: Run rubocop
|
||||
command: bundle exec rubocop
|
||||
- run:
|
||||
name: Run brakeman
|
||||
command: bundle exec brakeman
|
||||
- run:
|
||||
name: Run haml-lint
|
||||
command: bundle exec haml-lint app/views/
|
||||
- run:
|
||||
name: Run scss-lint
|
||||
command: bundle exec scss-lint app/assets/stylesheets/
|
||||
name: Run linters
|
||||
command: bundle exec rake lint
|
||||
deploy:
|
||||
<<: *defaults
|
||||
steps:
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -70,6 +70,8 @@ gem 'leaflet-draw-rails'
|
|||
gem 'chartkick'
|
||||
|
||||
gem 'logstasher'
|
||||
gem 'lograge'
|
||||
gem 'logstash-event'
|
||||
|
||||
gem 'font-awesome-rails'
|
||||
|
||||
|
|
|
@ -457,6 +457,11 @@ GEM
|
|||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
ruby_dep (~> 1.2)
|
||||
lograge (0.10.0)
|
||||
actionpack (>= 4)
|
||||
activesupport (>= 4)
|
||||
railties (>= 4)
|
||||
request_store (~> 1.0)
|
||||
logstash-event (1.2.02)
|
||||
logstasher (1.2.2)
|
||||
activesupport (>= 4.0)
|
||||
|
@ -845,6 +850,8 @@ DEPENDENCIES
|
|||
leaflet-draw-rails
|
||||
leaflet-markercluster-rails (~> 0.7.0)
|
||||
leaflet-rails
|
||||
lograge
|
||||
logstash-event
|
||||
logstasher
|
||||
mailjet
|
||||
maruku
|
||||
|
|
|
@ -108,11 +108,9 @@ Une fois `overmind` lancé, et un breakpoint `byebug` inséré dans le code, il
|
|||
|
||||
## Linting
|
||||
|
||||
- Faire tourner RuboCop : `bundle exec rubocop`
|
||||
- Faire tourner Brakeman : `bundle exec brakeman`
|
||||
- Linter les fichiers HAML : `bundle exec haml-lint app/views/`
|
||||
- Linter les fichiers SCSS : `bundle exec scss-lint app/assets/stylesheets/`
|
||||
- Linter les fichiers JavaScript : `yarn lint:js` (`yarn lint:js --fix`)
|
||||
Le projet utilise plusieurs linters pour vérifier la lisibilité et la qualité code.
|
||||
|
||||
- Faire tourner tous les linters : `bin/rake lint`
|
||||
- [AccessLint](http://accesslint.com/) tourne automatiquement sur les PRs
|
||||
|
||||
## Déploiement
|
||||
|
|
8
Rakefile
8
Rakefile
|
@ -5,6 +5,14 @@ require File.expand_path('config/application', __dir__)
|
|||
|
||||
Rails.application.load_tasks
|
||||
|
||||
task :lint do
|
||||
sh "bundle exec rubocop"
|
||||
sh "bundle exec haml-lint app/views/"
|
||||
sh "bundle exec scss-lint app/assets/stylesheets/"
|
||||
sh "bundle exec brakeman --no-pager"
|
||||
sh "yarn lint:js"
|
||||
end
|
||||
|
||||
task :deploy do
|
||||
domains = %w(37.187.249.111 149.202.72.152 149.202.198.6)
|
||||
domains.each do |domain|
|
||||
|
|
|
@ -1,34 +1,30 @@
|
|||
$(document).on('turbolinks:load', init_admin);
|
||||
|
||||
function init_admin(){
|
||||
destroy_action();
|
||||
on_change_type_de_champ_select();
|
||||
}
|
||||
|
||||
function destroy_action(){
|
||||
$(".delete").on('click', function(){
|
||||
$(document).on('click', '.delete', function() {
|
||||
$(this).hide();
|
||||
$(this).closest('td').find(".confirm").show();
|
||||
$(this)
|
||||
.closest('td')
|
||||
.find('.confirm')
|
||||
.show();
|
||||
});
|
||||
|
||||
$(".cancel").on('click', function(){
|
||||
$(this).closest('td').find(".delete").show();
|
||||
$(this).closest('td').find(".confirm").hide();
|
||||
$(document).on('click', '.cancel', function() {
|
||||
$(this)
|
||||
.closest('td')
|
||||
.find('.delete')
|
||||
.show();
|
||||
$(this)
|
||||
.closest('td')
|
||||
.find('.confirm')
|
||||
.hide();
|
||||
});
|
||||
|
||||
$("#liste-gestionnaire #libelle").on('click', function(){
|
||||
setTimeout(destroy_action, 500);
|
||||
});
|
||||
}
|
||||
|
||||
function on_change_type_de_champ_select (){
|
||||
$("select.form-control.type-champ").on('change', function(e){
|
||||
|
||||
parent = $(this).parent().parent();
|
||||
$(document).on('change', 'select.form-control.type-champ', function() {
|
||||
var parent = $(this)
|
||||
.parent()
|
||||
.parent();
|
||||
|
||||
parent.removeClass('header-section');
|
||||
parent.children(".drop-down-list").removeClass('show-inline');
|
||||
parent.children(".pj-template").removeClass('show-inline');
|
||||
parent.children('.drop-down-list').removeClass('show-inline');
|
||||
parent.children('.pj-template').removeClass('show-inline');
|
||||
|
||||
$('.mandatory', parent).show();
|
||||
|
||||
|
@ -39,14 +35,13 @@ function on_change_type_de_champ_select (){
|
|||
case 'drop_down_list':
|
||||
case 'multiple_drop_down_list':
|
||||
case 'linked_drop_down_list':
|
||||
parent.children(".drop-down-list").addClass('show-inline');
|
||||
parent.children('.drop-down-list').addClass('show-inline');
|
||||
break;
|
||||
case 'piece_justificative':
|
||||
parent.children(".pj-template").addClass('show-inline');
|
||||
parent.children('.pj-template').addClass('show-inline');
|
||||
break;
|
||||
case 'explication':
|
||||
$('.mandatory', parent).hide();
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
$(document).on('turbolinks:load', link_init);
|
||||
|
||||
function link_init() {
|
||||
$('#dossiers-list tr').on('click', function(event) {
|
||||
$(document).on('click', '#dossiers-list tr', function(event) {
|
||||
var href = $(this).data('href');
|
||||
if (href && event.target.tagName !== 'A') {
|
||||
location.href = href;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -178,7 +178,8 @@ div.pagination {
|
|||
}
|
||||
|
||||
.alert.alert-success.move-up,
|
||||
.alert.alert-danger.siret {
|
||||
.alert.alert-danger.siret,
|
||||
.alert.sticky {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
.icon {
|
||||
padding: 10px 5px;
|
||||
margin: 10px 10px;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
|
|
33
app/assets/stylesheets/new_design/dossier_show.scss
Normal file
33
app/assets/stylesheets/new_design/dossier_show.scss
Normal file
|
@ -0,0 +1,33 @@
|
|||
@import "colors";
|
||||
@import "constants";
|
||||
|
||||
#dossier-show {
|
||||
.sub-header {
|
||||
.label {
|
||||
float: right;
|
||||
margin-left: $default-spacer;
|
||||
}
|
||||
|
||||
.title-container {
|
||||
margin-bottom: $default-padding * 2;
|
||||
padding-left: 32px;
|
||||
|
||||
.icon.folder {
|
||||
float: left;
|
||||
margin-left: -32px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: $black;
|
||||
font-size: 22px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: $grey;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
82
app/assets/stylesheets/new_design/status_progress.scss
Normal file
82
app/assets/stylesheets/new_design/status_progress.scss
Normal file
|
@ -0,0 +1,82 @@
|
|||
@import "colors";
|
||||
@import "constants";
|
||||
|
||||
.status-progress {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.status-timeline {
|
||||
display: inline-block;
|
||||
margin-top: $default-padding * 2;
|
||||
margin-bottom: $default-padding * 2;
|
||||
border: 1px solid #808080;
|
||||
border-radius: 3px;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
padding-top: $default-spacer;
|
||||
padding-bottom: $default-spacer;
|
||||
|
||||
&:first-child {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&.active ~ li {
|
||||
color: $grey;
|
||||
}
|
||||
|
||||
// Arrows
|
||||
&:not(:last-child)::after {
|
||||
content: "▸";
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.status-explanation {
|
||||
text-align: left;
|
||||
|
||||
&.brouillon,
|
||||
&.en-construction,
|
||||
&.en-instruction {
|
||||
max-width: 600px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
margin-bottom: $default-spacer;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: $default-padding;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
quotes: "« " " »" "‘" "’";
|
||||
}
|
||||
|
||||
blockquote::before {
|
||||
content: open-quote;
|
||||
}
|
||||
|
||||
blockquote::after {
|
||||
content: close-quote;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: $default-spacer;
|
||||
}
|
||||
}
|
|
@ -97,15 +97,18 @@ class ApplicationController < ActionController::Base
|
|||
Raven.user_context(context)
|
||||
end
|
||||
|
||||
def session_info_payload
|
||||
def append_info_to_payload(payload)
|
||||
super
|
||||
user = logged_user
|
||||
|
||||
payload = {
|
||||
payload[:xhr] = !!request.xhr?
|
||||
|
||||
payload.merge!({
|
||||
user_agent: request.user_agent,
|
||||
current_user_id: user&.id,
|
||||
current_user_email: user&.email,
|
||||
current_user_roles: logged_user_roles
|
||||
}.compact
|
||||
user_id: user&.id,
|
||||
user_email: user&.email,
|
||||
user_roles: logged_user_roles
|
||||
}.compact)
|
||||
|
||||
if browser.known?
|
||||
payload.merge!({
|
||||
|
|
|
@ -7,13 +7,43 @@ module ApplicationHelper
|
|||
end
|
||||
end
|
||||
|
||||
def flash_class(level)
|
||||
def flash_class(level, sticky = false)
|
||||
case level
|
||||
when "notice" then "alert-success"
|
||||
when "alert" then "alert-danger"
|
||||
when "notice" then "alert-success#{sticky ? ' sticky' : ''}"
|
||||
when "alert" then "alert-danger#{sticky ? ' sticky' : ''}"
|
||||
end
|
||||
end
|
||||
|
||||
def render_to_element(selector, partial:, outer: false, locals: {})
|
||||
method = outer ? 'outerHTML' : 'innerHTML'
|
||||
html = escape_javascript(render partial: partial, locals: locals)
|
||||
# rubocop:disable Rails/OutputSafety
|
||||
raw("document.querySelector('#{selector}').#{method} = \"#{html}\";")
|
||||
# rubocop:enable Rails/OutputSafety
|
||||
end
|
||||
|
||||
def render_flash(timeout: false, sticky: false)
|
||||
if flash.any?
|
||||
html = render_to_element('#flash_messages', partial: 'layouts/flash_messages', locals: { sticky: sticky }, outer: true)
|
||||
flash.clear
|
||||
if timeout
|
||||
html += remove_element('#flash_messages', timeout: timeout, inner: true)
|
||||
end
|
||||
html
|
||||
end
|
||||
end
|
||||
|
||||
def remove_element(selector, timeout: 0, inner: false)
|
||||
script = "(function() {";
|
||||
script << "var el = document.querySelector('#{selector}');"
|
||||
method = (inner ? "el.innerHTML = ''" : "el.parentNode.removeChild(el)")
|
||||
script << "setTimeout(function() { #{method}; }, #{timeout});";
|
||||
script << "})();"
|
||||
# rubocop:disable Rails/OutputSafety
|
||||
raw(script);
|
||||
# rubocop:enable Rails/OutputSafety
|
||||
end
|
||||
|
||||
def current_email
|
||||
current_user&.email ||
|
||||
current_gestionnaire&.email ||
|
||||
|
@ -37,4 +67,17 @@ module ApplicationHelper
|
|||
Raven.capture_exception(e)
|
||||
{}
|
||||
end
|
||||
|
||||
def sentry_config
|
||||
sentry = Rails.application.secrets.sentry
|
||||
if sentry
|
||||
{
|
||||
dsn: sentry[:browser],
|
||||
id: current_user&.id,
|
||||
email: current_email
|
||||
}.to_json
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,6 +13,7 @@ import 'babel-polyfill';
|
|||
|
||||
import 'typeahead.js';
|
||||
|
||||
import '../shared/sentry';
|
||||
import '../shared/rails-ujs-fix';
|
||||
|
||||
// Start Rails helpers
|
||||
|
|
|
@ -13,6 +13,7 @@ import 'babel-polyfill';
|
|||
import 'select2';
|
||||
import 'typeahead.js';
|
||||
|
||||
import '../shared/sentry';
|
||||
import '../shared/rails-ujs-fix';
|
||||
|
||||
import '../new_design/buttons';
|
||||
|
|
14
app/javascript/shared/sentry.js
Normal file
14
app/javascript/shared/sentry.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { init, configureScope } from '@sentry/browser';
|
||||
import { getData } from './data';
|
||||
|
||||
const { dsn, email, id } = getData('sentry');
|
||||
|
||||
if (dsn) {
|
||||
init({ dsn });
|
||||
|
||||
if (email) {
|
||||
configureScope(scope => {
|
||||
scope.setUser({ id, email });
|
||||
});
|
||||
}
|
||||
}
|
|
@ -4,4 +4,8 @@ class Champs::CheckboxChamp < Champ
|
|||
[ libelle ]
|
||||
end
|
||||
end
|
||||
|
||||
def to_s
|
||||
value == 'on' ? 'oui' : 'non'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
<% flash.each do |type, message| %>
|
||||
$("#flash_message").html("<div class=\"alert alert-success move-up\" style=\"display: block:\"> <%= sanitize(message) %></div>").children().fadeOut(5000)
|
||||
<% end %>
|
||||
$('#piece_justificative_form').html("<%= escape_javascript(render partial: 'form', locals: { procedure: @procedure } ) %>");
|
||||
<%= render_flash(timeout: 3000, sticky: true) %>
|
||||
<%= render_to_element('#piece_justificative_form', partial: 'admin/pieces_justificatives/form', locals: { procedure: @procedure }) %>
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
<%= smart_listing_update :procedures %>
|
||||
link_init();
|
|
@ -1,9 +1,7 @@
|
|||
<%- if response.status == 404 %>
|
||||
transfer_errors_message(true);
|
||||
<%- else %>
|
||||
$("#main-container").prepend("<div class='row'><div id='flash_message'></div></div>");
|
||||
$("#flash_message").prepend("<div class=\"alert alert-success\"> <%= sanitize(flash.notice) %></div>");
|
||||
<% flash.clear %>
|
||||
<%= render_flash %>
|
||||
|
||||
transfer_errors_message(false);
|
||||
$("#email_admin").val('');
|
||||
|
|
|
@ -1,5 +1,2 @@
|
|||
<% flash.each do |type, message| %>
|
||||
$("#flash_message").html("<div class=\"alert alert-success move-up\" style=\"display: block:\"> <%= sanitize(message) %></div>").children().fadeOut(5000)
|
||||
<% end %>
|
||||
$('#liste-champ').html("<%= escape_javascript(render partial: 'admin/types_de_champ/form', locals: { procedure: @procedure, types_de_champ: @types_de_champ } ) %>");
|
||||
on_change_type_de_champ_select ();
|
||||
<%= render_flash(timeout: 3000, sticky: true) %>
|
||||
<%= render_to_element('#liste-champ', partial: 'admin/types_de_champ/form', locals: { procedure: @procedure, types_de_champ: @types_de_champ }) %>
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
(function() {
|
||||
<% if @blank || @error %>
|
||||
var html = "<%= escape_javascript(render partial: 'shared/champs/siret/delete_etablissement', locals: { message: @error, position: @champ.order_place, etablissement: @etablissement }) %>";
|
||||
<%= render_to_element("#etablissement-for-#{@champ.id}", partial: 'shared/champs/siret/delete_etablissement', locals: { message: @error, position: @champ.order_place, etablissement: @etablissement }) %>
|
||||
<% else %>
|
||||
var html = "<%= escape_javascript(render partial: 'shared/champs/siret/etablissement', locals: { position: @champ.order_place, etablissement: @etablissement }) %>";
|
||||
<%= render_to_element("#etablissement-for-#{@champ.id}", partial: 'shared/champs/siret/etablissement', locals: { position: @champ.order_place, etablissement: @etablissement }) %>
|
||||
<% end %>
|
||||
document.querySelector("#etablissement-for-<%= @champ.id %>").innerHTML = html;
|
||||
})();
|
||||
|
|
|
@ -1,6 +1,2 @@
|
|||
var formView = "<%= escape_javascript(render partial: 'invites/form', locals: { dossier: @dossier }) %>";
|
||||
document.querySelector("#invites-form").outerHTML = formView;
|
||||
|
||||
var flashMessagesView = "<%= escape_javascript(render partial: 'layouts/flash_messages') %>";
|
||||
document.querySelector("#flash_messages").outerHTML = flashMessagesView;
|
||||
<% flash.clear %>
|
||||
<%= render_to_element('#invites-form', partial: 'invites/form', locals: { dossier: @dossier }, outer: true) %>
|
||||
<%= render_flash %>
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
- if flash.any?
|
||||
#flash_message.center
|
||||
- flash.each do |key, value|
|
||||
- sticky = defined?(sticky) ? sticky : false
|
||||
- if value.class == Array
|
||||
.alert{ class: flash_class(key) }
|
||||
.alert{ class: flash_class(key, sticky) }
|
||||
- value.each do |message|
|
||||
= sanitize(message)
|
||||
%br
|
||||
- else
|
||||
.alert{ class: flash_class(key) }
|
||||
.alert{ class: flash_class(key, sticky) }
|
||||
= sanitize(value)
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
= csrf_meta_tags
|
||||
|
||||
:javascript
|
||||
DATA = [];
|
||||
DATA = [{
|
||||
sentry: #{raw(sentry_config)}
|
||||
}];
|
||||
%body
|
||||
= render partial: 'layouts/support_navigator_banner'
|
||||
= render partial: 'layouts/pre_maintenance'
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
= stylesheet_link_tag :xray
|
||||
|
||||
:javascript
|
||||
DATA = [];
|
||||
DATA = [{
|
||||
sentry: #{raw(sentry_config)}
|
||||
}];
|
||||
%body
|
||||
.page-wrapper
|
||||
= render partial: "layouts/support_navigator_banner"
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
%span.icon.without-continuation
|
||||
.description
|
||||
%h4 Classer sans suite
|
||||
L'usager ne recevra aucune notification
|
||||
L'usager sera notifié que son dossier a été classé sans suite
|
||||
%li{ onclick: "DS.showMotivation('refuse');" }
|
||||
%span.icon.refuse
|
||||
.description
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#{popup_title}
|
||||
|
||||
= form_tag(terminer_gestionnaire_dossier_path(dossier.procedure, dossier), method: :post, class: 'form') do
|
||||
= text_area :dossier, :motivation, class: 'motivation-text-area', placeholder: 'Rédigez votre motivation ici (facultative)'
|
||||
- if title == 'Accepter'
|
||||
= text_area :dossier, :motivation, class: 'motivation-text-area', placeholder: 'Rédigez votre motivation ici (facultative)', required: false
|
||||
%p.help
|
||||
L'acceptation du dossier envoie automatiquement une attestation à l'usager.
|
||||
|
||||
|
@ -26,7 +26,8 @@
|
|||
%ul
|
||||
- unspecified_annotations_privees.each do |unspecified_annotations_privee|
|
||||
%li= unspecified_annotations_privee.libelle
|
||||
|
||||
- else
|
||||
= text_area :dossier, :motivation, class: 'motivation-text-area', placeholder: 'Rédigez votre motivation ici (obligatoire)', required: true
|
||||
.text-right
|
||||
%span.button{ onclick: 'DS.motivationCancel();' } Annuler
|
||||
= button_tag 'Valider la décision', name: :process_action, value: process_action, class: 'button primary', title: title, data: { confirm: confirm }
|
||||
|
|
|
@ -15,17 +15,6 @@
|
|||
= link_to(dossiers_path(current_tab: 'dossiers-invites')) do
|
||||
dossiers invités
|
||||
|
||||
- if current_user.feedbacks.empty?
|
||||
.container#user-satisfaction
|
||||
%h3 Que pensez-vous de ce service ?
|
||||
.icons
|
||||
= link_to feedback_path(mark: 0), data: { remote: true, method: :post } do
|
||||
%span.icon.frown
|
||||
= link_to feedback_path(mark: 1), data: { remote: true, method: :post } do
|
||||
%span.icon.meh
|
||||
= link_to feedback_path(mark: 2), data: { remote: true, method: :post } do
|
||||
%span.icon.smile
|
||||
|
||||
.container
|
||||
- if @dossiers.present?
|
||||
- if @dossiers.total_pages >= 2
|
||||
|
@ -64,6 +53,17 @@
|
|||
= dossier.updated_at.localtime.strftime("%d/%m/%Y")
|
||||
= paginate(@dossiers)
|
||||
|
||||
- if current_user.feedbacks.empty?
|
||||
#user-satisfaction
|
||||
%h3 Que pensez-vous de ce service ?
|
||||
.icons
|
||||
= link_to feedback_path(mark: 0), data: { remote: true, method: :post } do
|
||||
%span.icon.frown
|
||||
= link_to feedback_path(mark: 1), data: { remote: true, method: :post } do
|
||||
%span.icon.meh
|
||||
= link_to feedback_path(mark: 2), data: { remote: true, method: :post } do
|
||||
%span.icon.smile
|
||||
|
||||
- else
|
||||
.dossiers-table-empty
|
||||
%h2.empty-text Aucun dossier.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
%h1
|
||||
Dossier
|
||||
= @dossier.id
|
||||
#dossier-show
|
||||
= render partial: 'new_user/dossiers/show/header', locals: { dossier: @dossier }
|
||||
|
||||
= render partial: 'new_user/dossiers/show/resume', locals: { dossier: @dossier }
|
||||
|
|
12
app/views/new_user/dossiers/show/_header.html.haml
Normal file
12
app/views/new_user/dossiers/show/_header.html.haml
Normal file
|
@ -0,0 +1,12 @@
|
|||
.sub-header
|
||||
.container
|
||||
= render partial: 'shared/dossiers/status', locals: { dossier: dossier }
|
||||
|
||||
.title-container
|
||||
%span.icon.folder
|
||||
%h1= dossier.procedure.libelle
|
||||
%h2 Dossier nº #{dossier.id}
|
||||
|
||||
%ul.tabs
|
||||
%li.active
|
||||
= link_to "Résumé", dossier_path(dossier)
|
2
app/views/new_user/dossiers/show/_resume.html.haml
Normal file
2
app/views/new_user/dossiers/show/_resume.html.haml
Normal file
|
@ -0,0 +1,2 @@
|
|||
.container
|
||||
= render partial: 'new_user/dossiers/show/status_progress', locals: { dossier: dossier }
|
63
app/views/new_user/dossiers/show/_status_progress.html.haml
Normal file
63
app/views/new_user/dossiers/show/_status_progress.html.haml
Normal file
|
@ -0,0 +1,63 @@
|
|||
.status-progress
|
||||
- if !dossier.termine?
|
||||
%ul.status-timeline
|
||||
%li.brouillon{ class: dossier.brouillon? ? 'active' : nil }
|
||||
brouillon
|
||||
%li.en-construction{ class: dossier.en_construction? ? 'active' : nil }
|
||||
en construction
|
||||
%li.en-instruction{ class: dossier.en_instruction? ? 'active' : nil }
|
||||
en instruction
|
||||
%li.termine{ class: dossier.termine? ? 'active' : nil }
|
||||
terminé
|
||||
|
||||
.status-explanation
|
||||
- if dossier.brouillon?
|
||||
.brouillon
|
||||
%p Vous pouvez remplir votre dossier tranquillement : il n’est pas encore visible par l’administration.
|
||||
%p Quand vous aurez terminé, soumettez votre dossier pour qu’il soit examiné.
|
||||
|
||||
- elsif dossier.en_construction?
|
||||
.en-construction
|
||||
%p Un accompagnant de l’administration est en train de vérifier que votre dossier est bien complet.
|
||||
%p Si des modifications sont nécessaires, vous recevrez un email avec les modifications à effectuer. Et sinon, dès que votre dossier sera complet, il passera automatiquement en instruction.
|
||||
|
||||
- elsif dossier.en_instruction?
|
||||
.en-instruction
|
||||
%p Votre dossier est complet. Il est en cours d’examen par les agent·e·s de l’administration.
|
||||
%p Dès que l’administration aura statué sur votre dossier, vous recevrez un email avec le résultat.
|
||||
|
||||
- elsif dossier.accepte?
|
||||
.accepte
|
||||
%p
|
||||
%span.icon.accept
|
||||
Votre dossier a été
|
||||
= succeed '.' do
|
||||
%strong accepté
|
||||
|
||||
- if dossier.motivation.present?
|
||||
%h3 Motif de l’acceptation
|
||||
%blockquote= dossier.motivation
|
||||
|
||||
- elsif dossier.refuse?
|
||||
.refuse
|
||||
%p
|
||||
%span.icon.refuse
|
||||
Nous sommes désolés, votre dossier a malheureusement été
|
||||
= succeed '.' do
|
||||
%strong refusé
|
||||
|
||||
- if dossier.motivation.present?
|
||||
%h3 Motif du refus
|
||||
%blockquote= dossier.motivation
|
||||
|
||||
- elsif dossier.sans_suite?
|
||||
.sans-suite
|
||||
%p
|
||||
%span.icon.without-continuation
|
||||
Votre dossier a été classé
|
||||
= succeed '.' do
|
||||
%strong sans suite
|
||||
|
||||
- if dossier.motivation.present?
|
||||
%h3 Motif du classement sans suite
|
||||
%blockquote= dossier.motivation
|
|
@ -1,4 +1,2 @@
|
|||
document.querySelector('#user-satisfaction').innerHTML = '';
|
||||
var flashMessagesView = "<%= escape_javascript(render partial: 'layouts/flash_messages') %>";
|
||||
document.querySelector("#flash_messages").outerHTML = flashMessagesView;
|
||||
<% flash.clear %>
|
||||
<%= remove_element('#user-satisfaction') %>
|
||||
<%= render_flash %>
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
%p
|
||||
Votre dossier nº --numéro du dossier-- a été refusé le --date de décision--.
|
||||
|
||||
%p
|
||||
Le motif de refus est le suivant : --motivation--
|
||||
|
||||
%p
|
||||
Pour en savoir plus sur le motif du refus, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier--
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
%p
|
||||
Votre dossier nº --numéro du dossier-- a été classé sans suite le --date de décision--.
|
||||
|
||||
%p
|
||||
Le motif est le suivant : --motivation--
|
||||
|
||||
%p
|
||||
Pour en savoir plus sur les raisons de ce classement sans suite, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier--
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
- if dossier.brouillon?
|
||||
%span.label.brouillon brouillon
|
||||
- if dossier.en_instruction?
|
||||
%span.label.instruction en instruction
|
||||
- elsif dossier.en_construction?
|
||||
%span.label.construction en construction
|
||||
- if dossier.en_instruction?
|
||||
%span.label.instruction en instruction
|
||||
- elsif dossier.accepte?
|
||||
%span.label.accepted accepté
|
||||
- elsif dossier.refuse?
|
||||
|
|
30
config/initializers/lograge.rb
Normal file
30
config/initializers/lograge.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
Rails.application.configure do
|
||||
config.lograge.formatter = Lograge::Formatters::Logstash.new
|
||||
config.lograge.base_controller_class = ['ActionController::Base', 'Manager::ApplicationController']
|
||||
|
||||
# This will allow to override custom options from environement file
|
||||
# injected by ansible.
|
||||
if !config.lograge.custom_options
|
||||
config.lograge.custom_options = lambda do |event|
|
||||
{
|
||||
type: 'tps',
|
||||
user_id: event.payload[:user_id],
|
||||
user_email: event.payload[:user_email],
|
||||
user_roles: event.payload[:user_roles],
|
||||
user_agent: event.payload[:user_agent],
|
||||
browser: event.payload[:browser],
|
||||
browser_version: event.payload[:browser_version],
|
||||
platform: event.payload[:platform]
|
||||
}.compact
|
||||
end
|
||||
|
||||
config.lograge.custom_payload do |controller|
|
||||
{
|
||||
xhr: !!controller.request.xhr?
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
config.lograge.keep_original_rails_log = true
|
||||
config.lograge.logger = ActiveSupport::Logger.new Rails.root.join('log', "logstash_#{Rails.env}.log")
|
||||
end
|
|
@ -1,11 +0,0 @@
|
|||
backtrace: true
|
||||
suppress_app_log: false
|
||||
log_controller_parameters: false
|
||||
development:
|
||||
enabled: false
|
||||
test:
|
||||
enabled: false
|
||||
staging:
|
||||
enabled: false
|
||||
production:
|
||||
enabled: true
|
|
@ -2,4 +2,8 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'production'
|
|||
|
||||
const environment = require('./environment')
|
||||
|
||||
// https://github.com/rails/webpacker/issues/1235
|
||||
environment.config.optimization.minimizer[0].options.uglifyOptions.ecma = 5; // for IE 11 support
|
||||
environment.config.optimization.minimizer[0].options.uglifyOptions.safari10 = true;
|
||||
|
||||
module.exports = environment.toWebpackConfig()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"@rails/webpacker": "4.0.0-pre.2",
|
||||
"@sentry/browser": "^4.0.0-beta.12",
|
||||
"activestorage": "^5.2.0",
|
||||
"bloodhound-js": "^1.2.2",
|
||||
"chartkick": "^2.3.6",
|
||||
|
|
|
@ -17,7 +17,7 @@ describe ApplicationController, type: :controller do
|
|||
let(:current_gestionnaire) { nil }
|
||||
let(:current_administrateur) { nil }
|
||||
let(:current_administration) { nil }
|
||||
let(:payload) { @controller.send(:session_info_payload) }
|
||||
let(:payload) { {} }
|
||||
|
||||
before do
|
||||
expect(@controller).to receive(:current_user).and_return(current_user)
|
||||
|
@ -27,6 +27,7 @@ describe ApplicationController, type: :controller do
|
|||
allow(Raven).to receive(:user_context)
|
||||
|
||||
@controller.send(:set_raven_context)
|
||||
@controller.send(:append_info_to_payload, payload)
|
||||
end
|
||||
|
||||
context 'when no one is logged in' do
|
||||
|
@ -35,7 +36,16 @@ describe ApplicationController, type: :controller do
|
|||
.with({ ip_address: '0.0.0.0', roles: 'Guest' })
|
||||
end
|
||||
|
||||
it { expect(payload).to eq({ user_agent: 'Rails Testing', current_user_roles: 'Guest' }) }
|
||||
it do
|
||||
[:db_runtime, :view_runtime, :variant, :rendered_format].each do |key|
|
||||
payload.delete(key)
|
||||
end
|
||||
expect(payload).to eq({
|
||||
user_agent: 'Rails Testing',
|
||||
user_roles: 'Guest',
|
||||
xhr: false
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a user is logged in' do
|
||||
|
@ -47,11 +57,15 @@ describe ApplicationController, type: :controller do
|
|||
end
|
||||
|
||||
it do
|
||||
[:db_runtime, :view_runtime, :variant, :rendered_format].each do |key|
|
||||
payload.delete(key)
|
||||
end
|
||||
expect(payload).to eq({
|
||||
user_agent: 'Rails Testing',
|
||||
current_user_id: current_user.id,
|
||||
current_user_email: current_user.email,
|
||||
current_user_roles: 'User'
|
||||
user_id: current_user.id,
|
||||
user_email: current_user.email,
|
||||
user_roles: 'User',
|
||||
xhr: false
|
||||
})
|
||||
end
|
||||
end
|
||||
|
@ -68,11 +82,15 @@ describe ApplicationController, type: :controller do
|
|||
end
|
||||
|
||||
it do
|
||||
[:db_runtime, :view_runtime, :variant, :rendered_format].each do |key|
|
||||
payload.delete(key)
|
||||
end
|
||||
expect(payload).to eq({
|
||||
user_agent: 'Rails Testing',
|
||||
current_user_id: current_user.id,
|
||||
current_user_email: current_user.email,
|
||||
current_user_roles: 'User, Gestionnaire, Administrateur, Administration'
|
||||
user_id: current_user.id,
|
||||
user_email: current_user.email,
|
||||
user_roles: 'User, Gestionnaire, Administrateur, Administration',
|
||||
xhr: false
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -87,5 +87,48 @@ FactoryBot.define do
|
|||
dossier.save!
|
||||
end
|
||||
end
|
||||
|
||||
trait :accepte do
|
||||
after(:create) do |dossier, _evaluator|
|
||||
dossier.state = 'accepte'
|
||||
dossier.processed_at = dossier.created_at + 1.minute
|
||||
dossier.en_construction_at = dossier.created_at + 2.minutes
|
||||
dossier.created_at = dossier.created_at + 3.minutes
|
||||
dossier.save!
|
||||
end
|
||||
end
|
||||
|
||||
trait :refuse do
|
||||
after(:create) do |dossier, _evaluator|
|
||||
dossier.state = 'refuse'
|
||||
dossier.processed_at = dossier.created_at + 1.minute
|
||||
dossier.en_construction_at = dossier.created_at + 2.minutes
|
||||
dossier.created_at = dossier.created_at + 3.minutes
|
||||
dossier.save!
|
||||
end
|
||||
end
|
||||
|
||||
trait :sans_suite do
|
||||
after(:create) do |dossier, _evaluator|
|
||||
dossier.state = 'sans_suite'
|
||||
dossier.processed_at = dossier.created_at + 1.minute
|
||||
dossier.en_construction_at = dossier.created_at + 2.minutes
|
||||
dossier.created_at = dossier.created_at + 3.minutes
|
||||
dossier.save!
|
||||
end
|
||||
end
|
||||
|
||||
trait :with_motivation do
|
||||
after(:create) do |dossier, _evaluator|
|
||||
dossier.motivation = case dossier.state
|
||||
when 'refuse'
|
||||
'L’entreprise concernée n’est pas agréée.'
|
||||
when 'sans_suite'
|
||||
'Le département n’est pas éligible. Veuillez remplir un nouveau dossier auprès de la DDT du 93.'
|
||||
else
|
||||
'Vous avez validé les conditions.'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,11 +6,12 @@ describe 'Dossier details:' do
|
|||
Flipflop::FeatureSet.current.test!.switch!(:new_dossier_details, true)
|
||||
end
|
||||
|
||||
scenario 'the user can see the details of their dossier' do
|
||||
scenario 'the user can see the summary of the dossier status' do
|
||||
visit_dossier dossier
|
||||
|
||||
expect(page).to have_current_path(dossier_path(dossier))
|
||||
expect(page).to have_content(dossier.id)
|
||||
expect(page).to have_selector('.status-explanation')
|
||||
end
|
||||
|
||||
private
|
||||
|
|
21
spec/models/champs/checkbox_champ_spec.rb
Normal file
21
spec/models/champs/checkbox_champ_spec.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Champs::CheckboxChamp do
|
||||
let(:checkbox) { Champs::CheckboxChamp.new(value: value) }
|
||||
|
||||
describe '#to_s' do
|
||||
subject { checkbox.to_s }
|
||||
|
||||
context 'when the value is on' do
|
||||
let(:value) { 'on' }
|
||||
|
||||
it { is_expected.to eq('oui') }
|
||||
end
|
||||
|
||||
context 'when the value is off' do
|
||||
let(:value) { 'off' }
|
||||
|
||||
it { is_expected.to eq('non') }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -11,6 +11,7 @@ describe 'new_user/dossiers/show.html.haml', type: :view do
|
|||
subject! { render }
|
||||
|
||||
it 'affiche les informations du dossier' do
|
||||
expect(rendered).to have_text("Dossier #{dossier.id}")
|
||||
expect(rendered).to have_text(dossier.procedure.libelle)
|
||||
expect(rendered).to have_text("Dossier nº #{dossier.id}")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
describe 'new_user/dossiers/show/_status_progress.html.haml', type: :view do
|
||||
subject! { render 'new_user/dossiers/show/status_progress.html.haml', dossier: dossier }
|
||||
|
||||
matcher :have_timeline_item do |selector|
|
||||
match do |rendered|
|
||||
expect(rendered).to have_selector(item_selector(selector))
|
||||
end
|
||||
|
||||
chain :active do
|
||||
@active = true
|
||||
end
|
||||
|
||||
chain :inactive do
|
||||
@active = false
|
||||
end
|
||||
|
||||
def item_selector(selector)
|
||||
item_selector = ".status-timeline #{selector}"
|
||||
item_selector += '.active' if @active == true
|
||||
item_selector += ':not(.active)' if @active == false
|
||||
item_selector
|
||||
end
|
||||
end
|
||||
|
||||
context 'when brouillon' do
|
||||
let(:dossier) { create :dossier }
|
||||
|
||||
it 'renders the timeline (without the final states)' do
|
||||
expect(rendered).to have_timeline_item('.brouillon').active
|
||||
expect(rendered).to have_timeline_item('.en-construction').inactive
|
||||
expect(rendered).to have_timeline_item('.en-instruction').inactive
|
||||
expect(rendered).to have_timeline_item('.termine').inactive
|
||||
end
|
||||
|
||||
it { is_expected.to have_selector('.status-explanation .brouillon') }
|
||||
end
|
||||
|
||||
context 'when en construction' do
|
||||
let(:dossier) { create :dossier, :en_construction }
|
||||
|
||||
it 'renders the timeline (without the final states)' do
|
||||
expect(rendered).to have_timeline_item('.brouillon').inactive
|
||||
expect(rendered).to have_timeline_item('.en-construction').active
|
||||
expect(rendered).to have_timeline_item('.en-instruction').inactive
|
||||
expect(rendered).to have_timeline_item('.termine').inactive
|
||||
end
|
||||
|
||||
it { is_expected.to have_selector('.status-explanation .en-construction') }
|
||||
end
|
||||
|
||||
context 'when en instruction' do
|
||||
let(:dossier) { create :dossier, :en_instruction }
|
||||
|
||||
it 'renders the timeline (without the final states)' do
|
||||
expect(rendered).to have_timeline_item('.brouillon').inactive
|
||||
expect(rendered).to have_timeline_item('.en-construction').inactive
|
||||
expect(rendered).to have_timeline_item('.en-instruction').active
|
||||
expect(rendered).to have_timeline_item('.termine').inactive
|
||||
end
|
||||
|
||||
it { is_expected.to have_selector('.status-explanation .en-instruction') }
|
||||
end
|
||||
|
||||
context 'when accepté' do
|
||||
let(:dossier) { create :dossier, :accepte, :with_motivation }
|
||||
|
||||
it { is_expected.not_to have_selector('.status-timeline') }
|
||||
it { is_expected.to have_selector('.status-explanation .accepte') }
|
||||
it { is_expected.to have_text(dossier.motivation) }
|
||||
end
|
||||
|
||||
context 'when refusé' do
|
||||
let(:dossier) { create :dossier, :refuse, :with_motivation }
|
||||
|
||||
it { is_expected.not_to have_selector('.status-timeline') }
|
||||
it { is_expected.to have_selector('.status-explanation .refuse') }
|
||||
it { is_expected.to have_text(dossier.motivation) }
|
||||
end
|
||||
|
||||
context 'when classé sans suite' do
|
||||
let(:dossier) { create :dossier, :sans_suite, :with_motivation }
|
||||
|
||||
it { is_expected.not_to have_selector('.status-timeline') }
|
||||
it { is_expected.to have_selector('.status-explanation .sans-suite') }
|
||||
it { is_expected.to have_text(dossier.motivation) }
|
||||
end
|
||||
end
|
43
yarn.lock
43
yarn.lock
|
@ -49,6 +49,49 @@
|
|||
dependencies:
|
||||
any-observable "^0.3.0"
|
||||
|
||||
"@sentry/browser@^4.0.0-beta.12":
|
||||
version "4.0.0-beta.12"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-4.0.0-beta.12.tgz#dff44c7a3732577057844b1643e0ba38c644138b"
|
||||
dependencies:
|
||||
"@sentry/core" "4.0.0-beta.12"
|
||||
"@sentry/hub" "4.0.0-beta.12"
|
||||
"@sentry/minimal" "4.0.0-beta.12"
|
||||
"@sentry/types" "4.0.0-beta.12"
|
||||
"@sentry/utils" "4.0.0-beta.12"
|
||||
|
||||
"@sentry/core@4.0.0-beta.12":
|
||||
version "4.0.0-beta.12"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-4.0.0-beta.12.tgz#c821e41b02c1d66e48fbef16da744f0173575558"
|
||||
dependencies:
|
||||
"@sentry/hub" "4.0.0-beta.12"
|
||||
"@sentry/minimal" "4.0.0-beta.12"
|
||||
"@sentry/types" "4.0.0-beta.12"
|
||||
"@sentry/utils" "4.0.0-beta.12"
|
||||
|
||||
"@sentry/hub@4.0.0-beta.12":
|
||||
version "4.0.0-beta.12"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-4.0.0-beta.12.tgz#85267cec47c0bbf1094a537f7d14d19495c77234"
|
||||
dependencies:
|
||||
"@sentry/types" "4.0.0-beta.12"
|
||||
"@sentry/utils" "4.0.0-beta.12"
|
||||
|
||||
"@sentry/minimal@4.0.0-beta.12":
|
||||
version "4.0.0-beta.12"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-4.0.0-beta.12.tgz#534e8edd065646e0e5f8d71443a63f6ce7187573"
|
||||
dependencies:
|
||||
"@sentry/hub" "4.0.0-beta.12"
|
||||
"@sentry/types" "4.0.0-beta.12"
|
||||
|
||||
"@sentry/types@4.0.0-beta.12":
|
||||
version "4.0.0-beta.12"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-4.0.0-beta.12.tgz#0abd303692e48c0fc11afbfea8cbad87e625357a"
|
||||
|
||||
"@sentry/utils@4.0.0-beta.12":
|
||||
version "4.0.0-beta.12"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-4.0.0-beta.12.tgz#9d51e88634843232b6c6f0edb6df3d3fba83071e"
|
||||
dependencies:
|
||||
"@sentry/types" "4.0.0-beta.12"
|
||||
|
||||
"@sindresorhus/is@^0.7.0":
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd"
|
||||
|
|
Loading…
Reference in a new issue