Merge branch 'new_design' into dev

This commit is contained in:
Mathieu Magnin 2017-09-06 11:14:52 +02:00
commit 4266407709
176 changed files with 3648 additions and 318 deletions

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path d="M0 0h24v24H0z"/><path stroke="#35D49E" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 1C5.928 1 1 5.928 1 12s4.928 11 11 11 11-4.928 11-11S18.072 1 12 1z"/><path stroke="#35D49E" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 12.093L10.182 16 18 8"/></g></svg>

After

Width:  |  Height:  |  Size: 434 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><g stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M20.54 4.23l-1.391-1.68A1.447 1.447 0 0 0 18 2H6c-.471 0-.88.21-1.16.55L3.46 4.23C3.17 4.57 3 5.02 3 5.5V18c0 1.1.899 2 2 2h14c1.1 0 2-.9 2-2V5.5c0-.48-.17-.93-.46-1.27z"/><path d="M12.088 7.333h3.438c0-2 2.562-2 2.562-2h2l.842-.38a1.933 1.933 0 0 0-.385-.723l-1.39-1.68a1.448 1.448 0 0 0-1.15-.55h-12c-.47 0-.88.21-1.16.55l-1.38 1.68a1.913 1.913 0 0 0-.395.763l.018.34h3s2.562 0 2.562 2h3.438M9 13.868l3 3 3-3M12 16v-5"/></g><path d="M0 0h24v24H0z"/></g></svg>

After

Width:  |  Height:  |  Size: 672 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path d="M0 0h24v24H0z"/><path stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8.999A2.989 2.989 0 0 0 14.995 6c0-1.66-1.332-3-2.995-3a2.998 2.998 0 1 0 0 5.999zm0 4c-2.33 0-7 1.17-7 3.5v3.834h14v-3.834c0-2.33-4.67-3.5-7-3.5z"/></g></svg>

After

Width:  |  Height:  |  Size: 396 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" stroke="#CCC" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6.754 19.498l-.007-.006A9 9 0 1 0 11.73 3c-4.97 0-8.999 4.031-8.999 9a8.964 8.964 0 0 0 1.23 4.535S4.1 19.201 2 20.6c0 0 2.309.796 4.754-1.102z"/></svg>

After

Width:  |  Height:  |  Size: 335 B

View file

@ -0,0 +1 @@
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1683 808l-742 741q-19 19-45 19t-45-19L109 808q-19-19-19-45.5t19-45.5l166-165q19-19 45-19t45 19l531 531 531-531q19-19 45-19t45 19l166 165q19 19 19 45.5t-19 45.5z"/></svg>

After

Width:  |  Height:  |  Size: 270 B

View file

@ -0,0 +1 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>ic_close_circle_white</title><defs><path id="a" d="M0 0h992v412H0z"/><filter x="-8.1%" y="-4.6%" width="116.2%" height="110.9%" filterUnits="objectBoundingBox" id="b"><feOffset dy="4" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation="8" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" in="shadowBlurOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter><path id="c" d="M0 0h320v479H0z"/></defs><g fill="none" fill-rule="evenodd"><g transform="translate(-557 -325)"><use fill="#FFF" xlink:href="#a"/><path stroke="#CCC" d="M.5.5h991v411H.5z"/></g><g filter="url(#b)" transform="translate(-16 -399)"><use fill="#FFF" xlink:href="#c"/><path stroke="#CCC" d="M.5.5h319v478H.5z"/><g><path d="M16 399h24v24H16z"/><path d="M28 400c-6.072 0-11 4.928-11 11s4.928 11 11 11 11-4.928 11-11-4.928-11-11-11zM31.833 407L24 414.833M31.833 414.833L24 407" stroke="#FF5D60" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><g stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M11.999 7.104l-2.2-2.25h-6.6c-1.21 0-2.189 1.014-2.189 2.25l-.011 13.5c0 1.238.99 2.25 2.2 2.25h17.6c1.21 0 2.2-1.012 2.2-2.25V9.355c0-1.237-.99-2.25-2.2-2.25"/><path d="M20.877 6.871l1.829-1.829a.994.994 0 0 0 0-1.41l-2.339-2.34a.996.996 0 0 0-1.41 0l-1.83 1.83-1.069 1.07L4.999 15.25V19h3.75L19.807 7.941l1.07-1.07zm-3.608-3.662l3.396 3.542"/></g><path d="M0 0h24v24H0z"/></g></svg>

After

Width:  |  Height:  |  Size: 595 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2z"/><path d="M0 0h24v24H0z"/></g></svg>

After

Width:  |  Height:  |  Size: 337 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="18" viewBox="0 0 22 18"><g fill="none" fill-rule="evenodd"><path stroke="#35D49E" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 3h-8L9 1H3c-1.1 0-1.99.9-1.99 2L1 15c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/><path d="M14 10H6.533M11 7l4 3-4 3" stroke="#35D49E" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/><path d="M-1-3h24v24H-1z"/></g></svg>

After

Width:  |  Height:  |  Size: 456 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.5 21h18M18.878 8.871l1.829-1.829a.994.994 0 0 0 0-1.41l-2.339-2.34a.996.996 0 0 0-1.41 0l-1.83 1.83-1.069 1.07L3 17.25V21h3.75L17.808 9.941l1.07-1.07zm-3.609-3.662l3.396 3.542"/><path d="M0 0h24v24H0z"/></g></svg>

After

Width:  |  Height:  |  Size: 424 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><g stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2z"/><path d="M2.292 5.033l9.667 6.675 9.666-6.75"/></g><path d="M0 0h24v24H0z"/></g></svg>

After

Width:  |  Height:  |  Size: 383 B

View file

@ -0,0 +1 @@
<svg width="25" height="25" viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg"><title>Shape</title><path d="M20.37.5H4.946L.7 6.19l12 18.31 12-18.31L20.37.5zm2.355 5.69l-2.98 4.541c0-.006-.005-.011-.005-.011-.39-.975-.853-2.648-4.215-3.026 0 0-5.351.321-6.377-.563-1.025-.885-2.917-3.132 1.417-4.58 2.635-.885 5.716.377 5.998 3.887h3.488V2.213l2.674 3.977zM8.253 14.49a.148.148 0 0 0-.021.034L5.84 10.877l.005-.01s.912.732 4.232.884c3.32.146 6.25.146 7.158 1.087.912.94-.769 2.704-4.791 2.462-.005 0-2.257-3.606-4.19-.811zM18.311 2.19s.21 1.578-.756 1.972c0 0-.084-.355-1.207-1.972h1.963zm-12.735 0h2.45c-.454.192-3.657 1.989-3.417 6.8v.023L2.759 6.19l2.817-4zm4.073 14.496c.004 0 4.85.715 6.212-.186.059-.04.117-.079.18-.13l-3.299 5.031-3.093-4.715z" fill-rule="nonzero" fill="#4393F3"/></svg>

After

Width:  |  Height:  |  Size: 798 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path d="M0 0h24v24H0z"/><g stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M23 12c0 6.076-4.924 11-11 11-6.074 0-11-4.924-11-11S5.926 1 12 1c6.076 0 11 4.924 11 11zM12 8v10"/><path d="M16 11l-4-4-4 4"/></g></g></svg>

After

Width:  |  Height:  |  Size: 377 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2 16.112v1.862C2 19.088 2.907 20 4.017 20h16.132c1.11 0 2.018-.912 2.018-2.026V7.85a2.028 2.028 0 0 0-2.018-2.025h-8.066L10.066 3.8h-6.05A2.02 2.02 0 0 0 2.01 5.825L2 8.015M3 12h7.467"/><path stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 9l-4 3 4 3"/><path d="M0 0h24v24H0z"/></g></svg>

After

Width:  |  Height:  |  Size: 536 B

View file

@ -0,0 +1 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>sans-suite</title><defs><path id="a" d="M0 0h992v412H0z"/><filter x="-8.1%" y="-4.6%" width="116.2%" height="110.9%" filterUnits="objectBoundingBox" id="b"><feOffset dy="4" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation="8" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" in="shadowBlurOuter1" result="shadowMatrixOuter1"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="SourceGraphic"/></feMerge></filter><path id="c" d="M0 0h320v479H0z"/></defs><g fill="none" fill-rule="evenodd"><g transform="translate(-557 -229)"><use fill="#FFF" xlink:href="#a"/><path stroke="#CCC" d="M.5.5h991v411H.5z"/></g><g filter="url(#b)" transform="translate(-16 -303)"><use fill="#FFF" xlink:href="#c"/><path stroke="#CCC" d="M.5.5h319v478H.5z"/><g><path d="M16 303h24v24H16z"/><path d="M28 304c-6.072 0-11 4.928-11 11s4.928 11 11 11 11-4.928 11-11-4.928-11-11-11z" stroke="#333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><g fill="#333" transform="translate(16 303)"><circle cx="8" cy="12" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="16" cy="12" r="1"/></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -15,7 +15,7 @@
//= require turbolinks //= require turbolinks
//= require highcharts //= require highcharts
//= require chartkick //= require chartkick
//= require_tree . //= require_tree ./old_design
//= require bootstrap-sprockets //= require bootstrap-sprockets
//= require bootstrap-datepicker/core //= require bootstrap-datepicker/core
//= require bootstrap-datepicker/locales/bootstrap-datepicker.fr.js //= require bootstrap-datepicker/locales/bootstrap-datepicker.fr.js

View file

@ -10,9 +10,13 @@
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives. // about supported directives.
// //
//= require ./init
//= require jquery //= require jquery
//= require jquery_ujs //= require jquery_ujs
//= require turbolinks //= require turbolinks
//= require leaflet.1.1.0
//= require highcharts //= require highcharts
//= require chartkick //= require chartkick
//= require select2
//= require typeahead.bundle
//= require_tree . //= require_tree .

View file

@ -0,0 +1,11 @@
$(document).on("click", "body", function () {
$(".button.dropdown").removeClass("open");
});
$(document).on("click", ".button.dropdown", function(event) {
event.stopPropagation();
var $target = $(event.target);
if($target.hasClass("button", "dropdown")){
$target.toggleClass("open");
}
});

View file

@ -0,0 +1,10 @@
function drawCadastre (map) {
drawLayerWithItems(map, dossierCadastres, {
fillColor: '#8A6D3B',
weight: 2,
opacity: 0.7,
color: '#8A6D3B',
dashArray: '3',
fillOpacity: 0.5
});
}

View file

@ -0,0 +1,61 @@
function initCarto() {
if ($("#map").length > 0) {
var position = getPosition() || defaultGestionnairePosition();
var map = L.map('map', {
scrollWheelZoom: false
}).setView([position.lat, position.lon], position.zoom);
L.tileLayer('http://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// draw external polygons
drawCadastre(map);
drawQuartiersPrioritaires(map);
// draw user polygon
drawUserSelection(map);
}
}
$(document).on('turbolinks:load', initCarto);
function drawUserSelection(map) {
if (dossierJsonLatLngs.length > 0) {
var polygon = L.polygon(dossierJsonLatLngs, { color: 'red', zIndex: 3 }).addTo(map);
map.fitBounds(polygon.getBounds());
}
}
function defaultGestionnairePosition() {
var LON = '2.428462';
var LAT = '46.538192';
return { lon: LON, lat: LAT, zoom: 5 }
}
function getPosition() {
var position;
$.ajax({
url: getPositionUrl,
dataType: 'json',
async: false
}).done(function (data) {
position = data
});
return position;
}
function drawLayerWithItems(map, items, style) {
if (Array.isArray(items) && items.length > 0) {
var layer = new L.GeoJSON();
items.forEach(function (item) {
layer.addData(item.geometry);
});
layer.setStyle(style).addTo(map);
}
}

View file

@ -0,0 +1,10 @@
function drawQuartiersPrioritaires (map) {
drawLayerWithItems(map, dossierQuartiersPrioritaires, {
fillColor: '#31708F',
weight: 2,
opacity: 0.7,
color: '#31708F',
dashArray: '3',
fillOpacity: 0.5
});
}

View file

@ -0,0 +1,27 @@
(function () {
var display = 'label';
var bloodhound = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace(display),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/ban/search?request=%QUERY',
wildcard: '%QUERY'
}
});
bloodhound.initialize();
var bindTypeahead = function() {
$("input[data-address='true']").typeahead({
minLength: 1
}, {
display: display,
source: bloodhound,
limit: 5
});
};
document.addEventListener('turbolinks:load', bindTypeahead);
})();

View file

@ -0,0 +1,3 @@
document.addEventListener('turbolinks:load', function() {
$('select.select2').select2();
});

View file

@ -0,0 +1,8 @@
$(document).on('blur keydown', 'input, textarea', function() {
$(this).addClass('touched');
});
$(document).on('click', 'input[type="submit"]:not([formnovalidate])', function() {
var $form = $(this).closest('form');
$('input, textarea', $form).addClass('touched');
});

View file

@ -1,5 +1,3 @@
window.TPS = window.TPS || {};
$(document).on("click", "body", function () { $(document).on("click", "body", function () {
$(".header-menu").removeClass("open fade-in-down"); $(".header-menu").removeClass("open fade-in-down");
}); });

View file

@ -0,0 +1,2 @@
// namespace
window.TPS = window.TPS || {};

View file

@ -0,0 +1,9 @@
TPS.acceptDossier = function () {
$(".motivation").show();
$(".dropdown-items").hide();
}
TPS.motivationCancel = function () {
$(".motivation").hide();
$(".dropdown-items").show();
}

View file

@ -0,0 +1,36 @@
(function() {
var showNotFound = function() {
$('.dossier-link .text-info').hide();
$('.dossier-link .text-warning').show();
};
var showData = function(data) {
$('.dossier-link .dossier-text-summary').text(data.textSummary);
$('.dossier-link .text-info').show();
$('.dossier-link .text-warning').hide();
};
var hideEverything = function() {
$('.dossier-link .text-info').hide();
$('.dossier-link .text-warning').hide();
};
var fetchProcedureLibelle = function(e) {
var dossierId = $(e.target).val();
if(dossierId) {
$.get('/users/dossiers/' + dossierId + '/text_summary')
.done(showData)
.fail(showNotFound);
} else {
hideEverything();
}
};
var timeOut = null;
var debounceFetchProcedureLibelle = function(e) {
if(timeOut){ clearTimeout(timeOut); }
timeOut = setTimeout(function() { fetchProcedureLibelle(e); }, 300);
};
$(document).on('input', '[data-type=dossier-link]', debounceFetchProcedureLibelle);
})();

View file

@ -7,3 +7,5 @@ $border-grey: #CCCCCC;
$dark-red: #A94442; $dark-red: #A94442;
$light-red: #EBCCD1; $light-red: #EBCCD1;
$lighter-red: #F2DEDE; $lighter-red: #F2DEDE;
$green: #35D49E;
$orange: #F59415;

View file

@ -1,3 +1,7 @@
$page-width: 1040px; $page-width: 1040px;
$default-padding: 15px; $default-spacer: 8px;
$default-padding: 2 * $default-spacer;
$footer-height: 267px;
$footer-height-mobile: 531px;

View file

@ -1,5 +1,4 @@
@import "constants"; @import "constants";
@import "mixins";
%horizontal-list { %horizontal-list {
list-style-type: none; list-style-type: none;
@ -14,12 +13,6 @@
display: inline-block; display: inline-block;
} }
%page-width-container {
@include horizontal-padding($default-padding);
max-width: $page-width + 2 * $default-padding;
margin: 0 auto;
}
%animation { %animation {
animation-fill-mode: forwards; animation-fill-mode: forwards;
animation-duration: 0.3s; animation-duration: 0.3s;

View file

@ -0,0 +1,61 @@
@import "colors";
@import "mixins";
.tabs {
li {
display: inline-block;
line-height: 36px;
position: relative;
text-align: center;
font-size: 14px;
border-radius: 3px 3px 0 0;
border: 1px solid transparent;
a {
display: block;
padding-left: 20px;
padding-right: 20px;
color: $black;
}
&.active {
background-color: #FFFFFF;
border-top: 1px solid $border-grey;
border-left: 1px solid $border-grey;
border-right: 1px solid $border-grey;
a {
color: $blue;
}
.badge {
color: $blue;
}
}
&:hover {
a {
color: $blue;
}
.badge {
color: $blue;
}
}
.badge {
background-color: rgba(0, 0, 0, 0.08);
padding-left: 5px;
padding-right: 5px;
border-radius: 100px;
font-weight: bold;
color: rgba(0, 0, 0, 0.6);
font-size: 14px;
}
.notifications {
top: 3px;
right: 3px;
}
}
}

View file

@ -59,8 +59,6 @@ $auth-breakpoint: 820px;
} }
.auth-form { .auth-form {
font-size: 14px;
.reset-password { .reset-password {
margin-top: 8px; margin-top: 8px;
} }

View file

@ -0,0 +1,20 @@
@import "colors";
@import "constants";
.backoffice-title {
font-size: 30px;
font-weight: normal;
margin-top: 3 * $default-spacer;
margin-bottom: 3 * $default-spacer;
}
.backoffice-header {
background-color: $light-grey;
padding-top: $default-padding;
margin-bottom: 2 * $default-spacer;
border-bottom: 1px solid $border-grey;
.container {
margin-bottom: -1px;
}
}

View file

@ -0,0 +1,28 @@
@import "colors";
@import "constants";
.breadcrumbs {
margin: $default-spacer 0;
li {
display: inline-block;
font-weight: bold;
font-size: 14px;
a {
color: $black;
}
&::after {
content: " > ";
}
&:last-child {
color: $blue;
&::after {
content: none;
}
}
}
}

View file

@ -1,4 +1,5 @@
@import "colors"; @import "colors";
@import "constants";
.button { .button {
display: inline-block; display: inline-block;
@ -6,15 +7,22 @@
border-radius: 30px; border-radius: 30px;
border: 1px solid $border-grey; border: 1px solid $border-grey;
font-size: 14px; font-size: 14px;
line-height: 20px;
background-color: #FFFFFF; background-color: #FFFFFF;
color: $black; color: $black;
cursor: pointer; cursor: pointer;
-webkit-appearance: none;
&:hover { &:hover {
background: $light-grey; background: $light-grey;
text-decoration: none; text-decoration: none;
} }
&:active,
&:focus {
outline: none;
}
&.primary { &.primary {
color: #FFFFFF; color: #FFFFFF;
border-color: $blue; border-color: $blue;
@ -38,12 +46,99 @@
&.large { &.large {
font-size: 18px; font-size: 18px;
line-height: 26px;
padding: 15px 32px; padding: 15px 32px;
} }
&.expand { &.expand {
width: 100%; width: 100%;
} }
> i {
width: 18px;
height: 18px;
background-size: 18px 18px;
vertical-align: middle;
margin-right: $default-spacer;
}
&.dropdown {
position: relative;
&::after {
content: "";
margin-left: $default-spacer;
font-weight: bold;
}
.dropdown-content {
display: none;
}
&.open {
.dropdown-content {
display: block;
}
}
}
}
.dropdown-content {
border: 1px solid $border-grey;
background: #FFFFFF;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
position: absolute;
right: 0;
top: 5 * $default-spacer;
cursor: default;
}
.dropdown-items {
li {
display: flex;
padding: 2 * $default-spacer;
color: $grey;
border-bottom: 1px solid $border-grey;
font-size: 12px;
min-width: 300px;
cursor: pointer;
&.selected {
cursor: default;
h4 {
color: $blue;
}
}
&.selected,
&:hover {
background: $light-grey;
}
&:last-child {
border-bottom: none;
}
a {
display: flex;
color: $grey;
}
i {
flex-shrink: 0;
}
div {
padding-left: $default-spacer;
}
}
h4 {
font-size: 14px;
color: $black;
margin-bottom: $default-spacer;
}
} }
.link { .link {

View file

@ -0,0 +1,22 @@
@import "colors";
@import "constants";
.card {
padding: ($default-spacer * 3) ($default-spacer * 2);
border: 1px solid $border-grey;
margin-bottom: $default-spacer * 2;
&.featured {
border-top: 8px solid $blue;
.card-title {
color: $blue;
}
}
.card-title {
font-weight: bold;
font-size: 20px;
margin-bottom: $default-spacer * 2;
}
}

View file

@ -1,12 +1,39 @@
@import "colors";
@import "constants";
@import "mixins";
@import "placeholders";
@import "typography"; @import "typography";
body { body,
input,
textarea,
select {
@extend %new-type; @extend %new-type;
font-size: 16px; font-size: 16px;
line-height: 1.42857143; line-height: 1.42857143;
} }
.page-wrapper {
position: relative;
padding-bottom: $footer-height;
min-height: 100%;
@media (max-width: 1000px) {
padding-bottom: $footer-height-mobile;
}
}
h1 { h1 {
font-size: 36px; font-size: 36px;
font-weight: bold; font-weight: bold;
} }
a {
color: $blue;
}
.container {
@include horizontal-padding($default-padding);
max-width: $page-width + 2 * $default-padding;
margin: 0 auto;
}

View file

@ -0,0 +1,17 @@
@import "constants";
@import "colors";
.dossier-link {
.help-block > p {
margin-top: - $default-padding;
margin-bottom: 2 * $default-padding;
}
.text-info {
color: $blue;
}
.text-warning {
color: $dark-red;
}
}

View file

@ -0,0 +1,71 @@
@import "colors";
@import "common";
@import "constants";
#dossier-instruction {
h1 {
font-size: 18px;
font-weight: bold;
margin-bottom: $default-padding;
}
.avis-notice {
font-size: 12px;
color: $grey;
margin-bottom: 2 * $default-padding;
}
input[type=email] {
max-width: 500px;
}
.avis {
.title {
margin-bottom: $default-padding;
.count {
display: inline-block;
width: 20px;
height: 20px;
border-radius: 10px;
border: 1px solid $grey;
text-align: center;
font-size: 12px;
font-weight: normal;
margin-left: 8px;
}
}
.one-avis {
border-top: 1px solid $grey;
padding: $default-padding 0;
h2 {
font-weight: bold;
margin-bottom: $default-spacer;
span {
font-weight: normal;
}
}
.answer {
margin-top: $default-padding;
}
.avis-icon {
margin-right: $default-spacer;
}
}
.date,
.waiting {
font-size: 12px;
color: $grey;
}
.date {
float: right;
}
}
}

View file

@ -0,0 +1,33 @@
@import "colors";
@import "common";
@import "constants";
#dossier-messagerie {
li {
display: flex;
align-items: flex-start;
margin-bottom: 2 * $default-padding;
}
.person-icon {
margin-right: $default-spacer;
}
h2 {
margin-bottom: $default-spacer;
}
.mail {
font-weight: bold;
}
.guest,
.date {
font-size: 12px;
color: $grey;
}
.date {
float: right;
}
}

View file

@ -0,0 +1,39 @@
@import "colors";
@import "constants";
.table.dossiers-table {
td {
padding: 0;
}
.cell-link {
color: $black;
padding: (3 * $default-spacer) 2px;
display: block;
}
i.folder {
margin-right: $default-spacer;
position: relative;
.notifications {
top: 0px;
right: -10px;
}
}
.number-col,
.status-col {
width: 130px;
}
.status-col span {
width: 110px;
text-align: center;
}
.follow-col {
width: 200px;
text-align: center;
}
}

View file

@ -0,0 +1,15 @@
.flex {
display: flex;
&.align-center {
align-items: center;
}
&.align-start {
align-items: flex-start;
}
&.justify-between {
justify-content: space-between;
}
}

View file

@ -1,3 +1,4 @@
@import "constants";
@import "colors"; @import "colors";
.form { .form {
@ -6,32 +7,175 @@
margin-bottom: 20px; margin-bottom: 20px;
} }
label,
input {
font-size: 14px;
}
label,
input[type=submit] {
margin-top: 24px;
}
label { label {
margin-bottom: 8px; margin-bottom: $default-padding;
display: inline-block; display: block;
.mandatory {
color: $dark-red;
} }
input[type=text], .notice {
input[type=email], font-size: 14px;
input[type=password] { display: block;
margin-top: $default-spacer;
color: $grey;
}
}
input[type=text]:not([data-address='true']),
input[type=email],
input[type=password],
input[type=date],
input[type=number],
input[type=tel],
textarea,
select {
display: block; display: block;
width: 100%;
border-radius: 4px; border-radius: 4px;
border: solid 1px $border-grey; border: solid 1px $border-grey;
padding: 16px; margin-bottom: 2 * $default-padding;
padding: $default-padding;
&:disabled { &:disabled {
background-color: $border-grey; background-color: $border-grey;
} }
} }
input[type=text],
input[type=email],
input[type=password],
input[type=date],
input[type=number],
input[type=tel],
textarea {
width: 100%;
}
input[type=email],
input[type=number],
input[type=tel], {
max-width: 500px;
}
input[type=checkbox],
input[type=radio] {
margin-bottom: 2 * $default-padding;
}
input[type=date] {
max-width: 180px;
}
input:invalid,
textarea:invalid {
box-shadow: none;
}
input.touched:invalid,
textarea.touched:invalid {
border-color: $dark-red;
box-shadow: 0px 0px 5px $dark-red;
}
select,
.select2-selection {
// hack found here: https://stackoverflow.com/questions/1895476/how-to-style-a-select-dropdown-with-css-only-without-javascript
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: image-url("icons/chevron-down.svg") no-repeat;
background-size: 14px;
background-position: right 10px center;
padding-right: 3 * $default-spacer;
// CAUTION: IE hackery ahead
&::-ms-expand {
display: none; // remove default arrow in IE 10 and 11 */
}
// target Internet Explorer 9 to undo the custom arrow */
@media screen and (min-width:0\0) {
select {
background: none\9;
}
}
}
.select2 {
min-width: 50%;
}
.select2-container {
display: block;
margin-bottom: 2 * $default-padding;
&.select2-container--focus {
.select2-selection {
border-color: $border-grey;
}
}
// scss-lint:disable SelectorFormat
.select2-selection__rendered {
padding: $default-padding;
}
.select2-selection__choice {
background-color: #FFFFFF;
}
// scss-lint:enable
}
.twitter-typeahead {
margin-bottom: 2 * $default-padding;
}
input.tt-input,
input.tt-hint {
border-radius: 4px;
border: solid 1px $border-grey;
padding: $default-padding;
}
input.tt-hint {
color: $grey;
}
.datetime {
input[type=date] {
display: inline-block;
}
select {
display: inline-block;
}
}
.header-section {
color: #4393F3;
font-weight: bold;
font-size: 20px;
margin-bottom: 2 * $default-padding;
}
.explication-libelle {
font-weight: bold;
font-size: 20px;
margin-bottom: $default-padding;
}
.explication {
background-color: $light-grey;
padding: $default-padding;
margin-bottom: 2 * $default-padding;
}
.send-wrapper {
text-align: right;
.send {
margin-bottom: $default-padding;
}
}
} }

View file

@ -0,0 +1,47 @@
i {
display: inline-block;
width: 24px;
height: 24px;
background-size: 24px 24px;
vertical-align: bottom;
&.follow {
background-image: image-url("icons/follow-folder.svg");
}
&.unfollow {
background-image: image-url("icons/unfollow-folder.svg");
}
&.archive {
background-image: image-url("icons/archive.svg");
}
&.unarchive {
background-image: image-url("icons/unarchive.svg");
}
&.folder {
background-image: image-url("icons/folder.svg");
}
&.accept {
background-image: image-url("icons/accept.svg");
}
&.close {
background-image: image-url("icons/close.svg");
}
&.without-continuation {
background-image: image-url("icons/without-continuation.svg");
}
&.edit {
background-image: image-url("icons/edit-folder-blue.svg");
}
&.in-progress {
background-image: image-url("icons/in-progress-blue.svg");
}
}

View file

@ -0,0 +1,36 @@
@import "colors";
@import "constants";
.label {
display: inline-block;
padding: 4px $default-spacer;
background: $grey;
border: 1px solid transparent;
color: #FFFFFF;
border-radius: 4px;
font-size: 12px;
&.instruction {
background-color: #FFFFFF;
color: $blue;
border: 1px solid $blue;
}
&.construction {
background-color: #FFFFFF;
color: $black;
border: 1px solid $black;
}
&.closed {
background-color: $green;
}
&.refused {
background-color: $dark-red;
}
&.without-continuation {
background-color: $black;
}
}

View file

@ -11,10 +11,6 @@
@include vertical-padding(60px); @include vertical-padding(60px);
} }
.landing-panel-inner-content {
@extend %page-width-container;
}
$landing-breakpoint: 1040px; $landing-breakpoint: 1040px;
.hero-wrapper { .hero-wrapper {

View file

@ -1,6 +1,6 @@
@import "colors"; @import "colors";
@import "common";
@import "constants"; @import "constants";
@import "placeholders";
.two-columns { .two-columns {
$column-padding: 60px; $column-padding: 60px;
@ -9,7 +9,7 @@
background: linear-gradient(to right, #FFFFFF 0%, #FFFFFF 50%, $light-grey 50%, $light-grey 100%); background: linear-gradient(to right, #FFFFFF 0%, #FFFFFF 50%, $light-grey 50%, $light-grey 100%);
.columns-container { .columns-container {
@extend %page-width-container; @extend .container;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;

View file

@ -0,0 +1,4 @@
#map {
height: 400px;
margin-bottom: 16px;
}

View file

@ -0,0 +1,29 @@
@import "colors";
@import "constants";
.motivation {
display: none;
padding: $default-padding;
color: $black;
width: 450px;
h3 {
font-size: 22px;
margin-bottom: $default-spacer * 2;
i {
vertical-align: sub;
margin-right: $default-spacer;
}
}
textarea {
margin-bottom: $default-spacer;
}
.help {
color: $grey;
font-size: 11px;
margin-bottom: $default-spacer * 2;
}
}

View file

@ -3,4 +3,7 @@
// = require ./common // = require ./common
// = require ./utils // = require ./utils
// = require ./fonts // = require ./fonts
// = require leaflet.1.1.0
// = require select2
// = require typeahead
// = require_tree . // = require_tree .

View file

@ -3,14 +3,18 @@
@import "mixins"; @import "mixins";
@import "placeholders"; @import "placeholders";
.footer { footer {
@include vertical-padding(72px); @include vertical-padding(72px);
background-color: $light-grey; background-color: $light-grey;
border-top: 1px solid $border-grey; border-top: 1px solid $border-grey;
} position: absolute;
bottom: 0;
width: 100%;
height: $footer-height;
.footer-inner-content { @media (max-width: 1000px) {
@extend %page-width-container; height: $footer-height-mobile;
}
} }
.footer-columns { .footer-columns {

View file

@ -1,7 +1,7 @@
@import "constants";
@import "colors"; @import "colors";
@import "common";
@import "constants";
@import "mixins"; @import "mixins";
@import "placeholders";
// FIXME: Rename when the header is generalized // FIXME: Rename when the header is generalized
.new-header { .new-header {
@ -14,10 +14,37 @@
} }
.header-inner-content { .header-inner-content {
@extend %page-width-container; @extend .container;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding-top: 17px; height: 100%;
}
.header-logo {
display: inline-block;
margin-right: 4 * $default-spacer;
}
.header-tabs {
li {
display: inline-block;
padding: $default-padding;
}
a {
@include vertical-padding(23px);
font-size: 18px;
color: $black;
&.active {
color: $blue;
border-bottom: 2px solid $blue;
}
&:not(.active):hover {
background-color: $light-grey;
}
}
} }
.header-right-content { .header-right-content {
@ -41,10 +68,11 @@
padding-right: 42px; padding-right: 42px;
float: right; float: right;
width: 300px; width: 300px;
margin: 0;
} }
button { button {
padding: 6px 9px; padding: 9px;
border: none; border: none;
background: none; background: none;
cursor: pointer; cursor: pointer;
@ -80,6 +108,7 @@
border: 1px solid $border-grey; border: 1px solid $border-grey;
min-width: 270px; min-width: 270px;
max-width: 340px; max-width: 340px;
z-index: 10;
&.open { &.open {
display: block; display: block;

View file

@ -0,0 +1,9 @@
@import "colors";
span.notifications {
position: absolute;
width: 8px;
height: 8px;
border-radius: 4px;
background-color: $orange;
}

View file

@ -1,10 +1,6 @@
@import "placeholders"; @import "placeholders";
.patron { .patron {
.patron-container {
@extend %page-width-container;
}
p { p {
margin-bottom: 20px; margin-bottom: 20px;
} }

View file

@ -0,0 +1,77 @@
@import "colors";
@import "constants";
@import "mixins";
.procedure-list {
.procedure-item {
border-bottom: 1px solid $border-grey;
&:last-child {
border-bottom: none;
}
a {
@include vertical-padding(24px);
color: $black;
width: 100%;
&:hover {
background-color: $light-grey;
.procedure-title {
text-decoration: underline;
}
}
}
}
.procedure-logo {
margin-right: 16px;
width: 40px;
border-bottom: 1px solid $border-grey;
}
.procedure-title {
min-height: 40px;
font-size: 20px;
margin-bottom: 16px;
padding-left: $default-spacer;
}
.procedure-status {
margin-left: auto;
}
.procedure-stats {
li {
min-height: 36px;
border-left: 1px solid $border-grey;
width: 90px;
position: relative;
&:last-child {
border-right: 1px solid $border-grey;
}
.stats-number,
.stats-legend {
text-align: center;
}
.stats-number {
font-size: 14px;
font-weight: bold;
}
.stats-legend {
font-size: 12px;
color: $grey;
}
}
.notifications {
top: 3px;
right: 18px;
}
}
}

View file

@ -0,0 +1,26 @@
@import "colors";
@import "common";
@import "constants";
#procedure-show {
.procedure-logo {
margin-right: $default-padding;
}
h1 {
color: $black;
font-size: 22px;
margin-bottom: 2 * $default-padding;
}
.dossiers-table {
margin: (3 * $default-spacer) auto;
}
h2 {
font-size: 20px;
font-weight: bold;
text-align: center;
margin: 60px 0;
}
}

View file

@ -0,0 +1,52 @@
@import "colors";
@import "constants";
@import "mixins";
.table { // TODO : tester de remplacer par l'élément table uniquement
width: 100%;
tbody tr {
border-top: 1px solid $border-grey;
}
td {
@include vertical-padding($default-spacer);
vertical-align: middle;
}
th {
text-align: left;
font-weight: bold;
padding: (3 * $default-spacer) 2px;
}
&.hoverable {
tbody tr:hover {
background: $light-grey;
}
}
&.vertical {
font-size: 14px;
line-height: 22px;
tr {
border-top: none;
}
th {
@include vertical-padding($default-spacer);
font-weight: normal;
&.header-section {
color: $blue;
font-weight: bold;
font-size: 20px;
}
}
td {
font-weight: bold;
}
}
}

View file

@ -21,3 +21,7 @@
.hidden { .hidden {
display: none; display: none;
} }
.width-100 {
width: 100%;
}

View file

@ -1,6 +1,21 @@
.new-design-button {
color: #FFFFFF;
display: block;
font-size: 20px;
margin: 16px 0;
padding: 8px;
text-align: center;
border: 1px solid #FFFFFF;
border-radius: 15px;
&:hover {
background-color: #668ABD;
color: #FFFFFF;
}
}
#search-block { #search-block {
margin: 15px 10px 0 10px; margin: 15px 10px 0 10px;
height: 30px;
} }
#search-button { #search-button {

View file

@ -98,9 +98,10 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
dossier = Dossier.find(params[:dossier_id]) dossier = Dossier.find(params[:dossier_id])
dossier.received! dossier.received!
flash.notice = 'Dossier considéré comme reçu.' current_gestionnaire.follow(dossier)
flash.notice = 'Dossier passé en instruction.'
redirect_to backoffice_dossier_path(id: dossier.id) redirect_to_dossier(dossier)
end end
def process_dossier def process_dossier
@ -142,16 +143,7 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
NotificationMailer.send_notification(dossier, template, attestation_pdf).deliver_now! NotificationMailer.send_notification(dossier, template, attestation_pdf).deliver_now!
redirect_to backoffice_dossier_path(id: dossier.id) redirect_to_dossier(dossier)
end
def follow
follow = current_gestionnaire.toggle_follow_dossier params[:dossier_id]
current_gestionnaire.dossiers.find(params[:dossier_id]).next_step! 'gestionnaire', 'follow'
flash.notice = (follow.class == Follow ? 'Dossier suivi' : 'Dossier relaché')
redirect_to request.referer
end end
def reload_smartlisting def reload_smartlisting
@ -188,13 +180,21 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
create_dossier_facade params[:dossier_id] create_dossier_facade params[:dossier_id]
@facade.dossier.replied! @facade.dossier.replied!
flash.notice = 'Dossier réouvert.' flash.notice = 'Dossier repassé en construction.'
redirect_to backoffice_dossiers_path redirect_to_dossier(@facade.dossier)
end end
private private
def redirect_to_dossier(dossier)
if URI(request.referer).path == dossier_path(dossier.procedure, dossier)
redirect_to dossier_path(dossier.procedure, dossier)
else
redirect_to backoffice_dossier_path(id: dossier.id)
end
end
def check_attestation_emailable(dossier) def check_attestation_emailable(dossier)
if dossier&.attestation&.emailable? == false if dossier&.attestation&.emailable? == false
human_size = number_to_human_size(dossier.attestation.pdf.size) human_size = number_to_human_size(dossier.attestation.pdf.size)

View file

@ -44,9 +44,7 @@ class CommentairesController < ApplicationController
end end
if is_gestionnaire? if is_gestionnaire?
unless current_gestionnaire.follow? @commentaire.dossier current_gestionnaire.follow(@commentaire.dossier)
current_gestionnaire.toggle_follow_dossier @commentaire.dossier
end
redirect_to url_for(controller: 'backoffice/dossiers', action: :show, id: params['dossier_id']) redirect_to url_for(controller: 'backoffice/dossiers', action: :show, id: params['dossier_id'])
else else

View file

@ -4,10 +4,93 @@ module NewGestionnaire
send_data(dossier.attestation.pdf.read, filename: 'attestation.pdf', type: 'application/pdf') send_data(dossier.attestation.pdf.read, filename: 'attestation.pdf', type: 'application/pdf')
end end
def show
@dossier = dossier
dossier.notifications.demande.mark_as_read
end
def messagerie
@dossier = dossier
dossier.notifications.messagerie.mark_as_read
end
def instruction
@dossier = dossier
dossier.notifications.instruction.mark_as_read
end
def follow
current_gestionnaire.follow(dossier)
dossier.next_step!('gestionnaire', 'follow')
flash.notice = 'Dossier suivi'
redirect_back(fallback_location: procedures_url)
end
def unfollow
current_gestionnaire.followed_dossiers.delete(dossier)
flash.notice = "Vous ne suivez plus le dossier nº #{dossier.id}"
redirect_back(fallback_location: procedures_url)
end
def archive
dossier.update_attributes(archived: true)
redirect_back(fallback_location: procedures_url)
end
def unarchive
dossier.update_attributes(archived: false)
redirect_back(fallback_location: procedures_url)
end
def create_commentaire
Commentaire.create(commentaire_params.merge(email: current_gestionnaire.email, dossier: dossier))
redirect_to messagerie_dossier_path(dossier.procedure, dossier)
end
def position
etablissement = dossier.etablissement
point = Carto::Geocodeur.convert_adresse_to_point(etablissement.geo_adresse) unless etablissement.nil?
lon = "2.428462"
lat = "46.538192"
zoom = "13"
unless point.nil?
lon = point.x.to_s
lat = point.y.to_s
end
render json: { lon: lon, lat: lat, zoom: zoom, dossier_id: params[:dossier_id] }
end
def create_avis
Avis.create(avis_params.merge(claimant: current_gestionnaire, dossier: dossier))
redirect_to instruction_dossier_path(dossier.procedure, dossier)
end
def update_annotations
dossier = current_gestionnaire.dossiers.includes(champs_private: :type_de_champ).find(params[:dossier_id])
dossier.update_attributes(champs_private_params)
redirect_to instruction_dossier_path(dossier.procedure, dossier)
end
private private
def dossier def dossier
Dossier.find(params[:dossier_id]) current_gestionnaire.dossiers.find(params[:dossier_id])
end
def commentaire_params
params.require(:commentaire).permit(:body)
end
def avis_params
params.require(:avis).permit(:email, :introduction)
end
def champs_private_params
params.require(:dossier).permit(champs_private_attributes: [:id, :value, value: []])
end end
end end
end end

View file

@ -1,5 +1,7 @@
module NewGestionnaire module NewGestionnaire
class GestionnaireController < ApplicationController class GestionnaireController < ApplicationController
layout "new_application"
before_action :authenticate_gestionnaire! before_action :authenticate_gestionnaire!
end end
end end

View file

@ -1,6 +1,68 @@
module NewGestionnaire module NewGestionnaire
class ProceduresController < GestionnaireController class ProceduresController < GestionnaireController
before_action :ensure_ownership! before_action :ensure_ownership!, except: [:index]
def index
@procedures = current_gestionnaire.procedures.order(archived_at: :desc, published_at: :desc)
dossiers = current_gestionnaire.dossiers
@dossiers_count_per_procedure = dossiers.all_state.group(:procedure_id).reorder(nil).count
@dossiers_a_suivre_count_per_procedure = dossiers.without_followers.en_cours.group(:procedure_id).reorder(nil).count
@dossiers_archived_count_per_procedure = dossiers.archived.group(:procedure_id).count
@dossiers_termines_count_per_procedure = dossiers.termine.group(:procedure_id).reorder(nil).count
@followed_dossiers_count_per_procedure = current_gestionnaire
.followed_dossiers
.en_cours
.where(procedure: @procedures)
.group(:procedure_id)
.reorder(nil)
.count
@notifications_count_per_procedure = current_gestionnaire.notifications_count_per_procedure
end
def show
@procedure = procedure
@a_suivre_dossiers = procedure
.dossiers
.includes(:user)
.without_followers
.en_cours
@followed_dossiers = current_gestionnaire
.followed_dossiers
.includes(:user, :notifications)
.where(procedure: @procedure)
.en_cours
@followed_dossiers_id = current_gestionnaire
.followed_dossiers
.where(procedure: @procedure)
.pluck(:id)
@termines_dossiers = procedure.dossiers.includes(:user).termine
@all_state_dossiers = procedure.dossiers.includes(:user).all_state
@archived_dossiers = procedure.dossiers.includes(:user).archived
@statut = params[:statut].present? ? params[:statut] : 'a-suivre'
@dossiers = case @statut
when 'a-suivre'
@a_suivre_dossiers
when 'suivis'
@followed_dossiers
when 'traites'
@termines_dossiers
when 'tous'
@all_state_dossiers
when 'archives'
@archived_dossiers
end
end
private private

View file

@ -0,0 +1,23 @@
module NewGestionnaire
class RecherchesController < GestionnaireController
def index
@search_terms = params[:q]
# exact id match?
if @search_terms.to_i != 0
@dossiers = current_gestionnaire.dossiers.where(id: @search_terms.to_i)
end
@dossiers = Dossier.none if @dossiers.nil?
# full text search
if @dossiers.empty?
@dossiers = Search.new(
gestionnaire: current_gestionnaire,
query: @search_terms,
page: params[:page]
).results
end
end
end
end

View file

@ -32,5 +32,45 @@ class RootController < ApplicationController
end end
def patron def patron
description = 'a not so long description'
all_champs = TypeDeChamp.type_champs
.map { |name, _| TypeDeChamp.new(type_champ: name, libelle: name, description: description, mandatory: true) }
.map { |type_de_champ| ChampPublic.new(type_de_champ: type_de_champ) }
.map.with_index do |champ, i|
champ.id = i
champ
end
all_champs
.select { |champ| champ.type_champ == 'header_section' }
.each { |champ| champ.type_de_champ.libelle = 'un super titre de section' }
all_champs
.select { |champ| %w(drop_down_list multiple_drop_down_list).include?(champ.type_champ) }
.each do |champ|
champ.type_de_champ.drop_down_list = DropDownList.new(type_de_champ: champ.type_de_champ)
champ.drop_down_list.value =
"option A
option B
-- avant l'option C --
option C"
champ.value = '["option B", "option C"]'
end
type_champ_values = {
'date': '2016-07-26',
'datetime': '26/07/2016 07:35',
'textarea': 'Une description de mon projet',
'explication': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In erat mauris, faucibus quis pharetra sit amet, pretium ac libero. Etiam vehicula eleifend bibendum. Morbi gravida metus ut sapien condimentum sodales mollis augue sodales. Vestibulum quis quam at sem placerat aliquet',
}
type_champ_values.each do |(type_champ, value)|
all_champs
.select { |champ| champ.type_champ == type_champ.to_s }
.each { |champ| champ.value = value }
end
@dossier = Dossier.new(champs: all_champs)
end end
end end

View file

@ -6,6 +6,12 @@ class ChampDecorator < Draper::Decorator
Date.parse(object.value).strftime("%d/%m/%Y") Date.parse(object.value).strftime("%d/%m/%Y")
elsif type_champ == 'checkbox' elsif type_champ == 'checkbox'
object.value == 'on' ? 'Oui' : 'Non' object.value == 'on' ? 'Oui' : 'Non'
elsif type_champ == 'yes_no'
if object.value == 'true'
'Oui'
elsif object.value == 'false'
'Non'
end
elsif type_champ == 'multiple_drop_down_list' && object.value.present? elsif type_champ == 'multiple_drop_down_list' && object.value.present?
JSON.parse(object.value).join(', ') JSON.parse(object.value).join(', ')
else else

View file

@ -6,6 +6,9 @@ class Champ < ActiveRecord::Base
delegate :libelle, :type_champ, :order_place, :mandatory, :description, :drop_down_list, to: :type_de_champ delegate :libelle, :type_champ, :order_place, :mandatory, :description, :drop_down_list, to: :type_de_champ
before_save :format_date_to_iso, if: Proc.new { type_champ == 'date' } before_save :format_date_to_iso, if: Proc.new { type_champ == 'date' }
before_save :serialize_datetime_if_needed, if: Proc.new { type_champ == 'datetime' }
before_save :multiple_select_to_string, if: Proc.new { type_champ == 'multiple_drop_down_list' }
after_save :internal_notification, if: Proc.new { !dossier.nil? } after_save :internal_notification, if: Proc.new { !dossier.nil? }
def mandatory? def mandatory?
@ -65,9 +68,35 @@ class Champ < ActiveRecord::Base
self.value = date self.value = date
end end
def serialize_datetime_if_needed
if (value =~ /=>/).present?
date = begin
hash_date = YAML.safe_load(value.gsub('=>', ': '))
year, month, day, hour, minute = hash_date.values_at(1,2,3,4,5)
DateTime.new(year, month, day, hour, minute).strftime("%d/%m/%Y %H:%M")
rescue
nil
end
self.value = date
end
end
def internal_notification def internal_notification
unless dossier.state == 'draft' unless dossier.state == 'draft'
NotificationService.new('champs', self.dossier.id, self.libelle).notify NotificationService.new('champs', self.dossier.id, self.libelle).notify
end end
end end
def multiple_select_to_string
if value.present?
json = JSON.parse(value)
if json == ['']
self.value = nil
else
json = json - ['']
self.value = json.to_s
end
end
end
end end

View file

@ -4,6 +4,8 @@ class Commentaire < ActiveRecord::Base
belongs_to :piece_justificative belongs_to :piece_justificative
scope :ordered, -> { order(created_at: :asc) }
after_create :notify after_create :notify
def header def header

View file

@ -17,6 +17,7 @@ class Dossier < ActiveRecord::Base
WAITING_FOR_USER = %w(replied) WAITING_FOR_USER = %w(replied)
EN_CONSTRUCTION = %w(initiated updated replied) EN_CONSTRUCTION = %w(initiated updated replied)
EN_INSTRUCTION = %w(received) EN_INSTRUCTION = %w(received)
EN_CONSTRUCTION_OU_INSTRUCTION = EN_CONSTRUCTION + EN_INSTRUCTION
A_INSTRUIRE = %w(received) A_INSTRUIRE = %w(received)
TERMINE = %w(closed refused without_continuation) TERMINE = %w(closed refused without_continuation)
@ -42,6 +43,9 @@ class Dossier < ActiveRecord::Base
belongs_to :procedure belongs_to :procedure
belongs_to :user belongs_to :user
accepts_nested_attributes_for :champs
accepts_nested_attributes_for :champs_private
default_scope { where(hidden_at: nil) } default_scope { where(hidden_at: nil) }
scope :state_brouillon, -> { where(state: BROUILLON) } scope :state_brouillon, -> { where(state: BROUILLON) }
scope :state_not_brouillon, -> { where.not(state: BROUILLON) } scope :state_not_brouillon, -> { where.not(state: BROUILLON) }
@ -51,6 +55,7 @@ class Dossier < ActiveRecord::Base
scope :state_waiting_for_user, -> { where(state: WAITING_FOR_USER) } scope :state_waiting_for_user, -> { where(state: WAITING_FOR_USER) }
scope :state_en_construction, -> { where(state: EN_CONSTRUCTION) } scope :state_en_construction, -> { where(state: EN_CONSTRUCTION) }
scope :state_en_instruction, -> { where(state: EN_INSTRUCTION) } scope :state_en_instruction, -> { where(state: EN_INSTRUCTION) }
scope :state_en_construction_ou_instruction, -> { where(state: EN_CONSTRUCTION_OU_INSTRUCTION) }
scope :state_a_instruire, -> { where(state: A_INSTRUIRE) } scope :state_a_instruire, -> { where(state: A_INSTRUIRE) }
scope :state_termine, -> { where(state: TERMINE) } scope :state_termine, -> { where(state: TERMINE) }
@ -67,6 +72,9 @@ class Dossier < ActiveRecord::Base
scope :a_instruire, -> { not_archived.state_a_instruire.order_by_updated_at(:asc) } scope :a_instruire, -> { not_archived.state_a_instruire.order_by_updated_at(:asc) }
scope :termine, -> { not_archived.state_termine.order_by_updated_at(:asc) } scope :termine, -> { not_archived.state_termine.order_by_updated_at(:asc) }
scope :downloadable, -> { state_not_brouillon.order_by_updated_at(:asc) } scope :downloadable, -> { state_not_brouillon.order_by_updated_at(:asc) }
scope :en_cours, -> { not_archived.state_en_construction_ou_instruction.order_by_updated_at(:asc) }
scope :without_followers, -> { includes(:follows).where(follows: { id: nil }) }
scope :with_unread_notifications, -> { where(notifications: { already_read: false }) }
accepts_nested_attributes_for :individual accepts_nested_attributes_for :individual
@ -96,6 +104,16 @@ class Dossier < ActiveRecord::Base
pieces_justificatives.where(type_de_piece_justificative_id: type_id).count > 0 pieces_justificatives.where(type_de_piece_justificative_id: type_id).count > 0
end end
def notifications_summary
unread_notifications = notifications.unread
{
demande: unread_notifications.select(&:demande?).present?,
instruction: unread_notifications.select(&:instruction?).present?,
messagerie: unread_notifications.select(&:messagerie?).present?
}
end
def retrieve_last_piece_justificative_by_type(type) def retrieve_last_piece_justificative_by_type(type)
pieces_justificatives.where(type_de_piece_justificative_id: type).last pieces_justificatives.where(type_de_piece_justificative_id: type).last
end end
@ -213,6 +231,22 @@ class Dossier < ActiveRecord::Base
BROUILLON.include?(state) BROUILLON.include?(state)
end end
def en_construction?
EN_CONSTRUCTION.include?(state)
end
def en_instruction?
EN_INSTRUCTION.include?(state)
end
def en_construction_ou_instruction?
EN_CONSTRUCTION_OU_INSTRUCTION.include?(state)
end
def termine?
TERMINE.include?(state)
end
def cerfa_available? def cerfa_available?
procedure.cerfa_flag? && cerfa.size != 0 procedure.cerfa_flag? && cerfa.size != 0
end end

View file

@ -14,6 +14,10 @@ class DropDownList < ActiveRecord::Base
champ.object.value.blank? ? [] : multiple ? JSON.parse(champ.object.value) : [champ.object.value] champ.object.value.blank? ? [] : multiple ? JSON.parse(champ.object.value) : [champ.object.value]
end end
def selected_options_without_decorator(champ)
champ.value.blank? ? [] : multiple ? JSON.parse(champ.value) : [champ.value]
end
def multiple def multiple
type_de_champ.type_champ == 'multiple_drop_down_list' type_de_champ.type_champ == 'multiple_drop_down_list'
end end

View file

@ -7,7 +7,7 @@ class Gestionnaire < ActiveRecord::Base
has_one :preference_smart_listing_page, dependent: :destroy has_one :preference_smart_listing_page, dependent: :destroy
has_many :assign_to, dependent: :destroy has_many :assign_to, dependent: :destroy
has_many :procedures, through: :assign_to has_many :procedures, -> { publiees_ou_archivees }, through: :assign_to
has_many :dossiers, -> { state_not_brouillon }, through: :procedures has_many :dossiers, -> { state_not_brouillon }, through: :procedures
has_many :followed_dossiers, through: :follows, source: :dossier has_many :followed_dossiers, through: :follows, source: :dossier
has_many :follows has_many :follows
@ -34,21 +34,14 @@ class Gestionnaire < ActiveRecord::Base
dossiers.where(id: dossier_id).any? dossiers.where(id: dossier_id).any?
end end
def toggle_follow_dossier dossier_id def follow(dossier)
dossier = dossier_id return if follow?(dossier)
dossier = Dossier.find(dossier_id) unless dossier_id.class == Dossier
Follow.create!(dossier: dossier, gestionnaire: self) followed_dossiers << dossier
rescue ActiveRecord::RecordInvalid
Follow.where(dossier: dossier, gestionnaire: self).delete_all
rescue ActiveRecord::RecordNotFound
nil
end end
def follow? dossier_id def follow?(dossier)
dossier_id = dossier_id.id if dossier_id.class == Dossier followed_dossiers.include?(dossier)
Follow.where(gestionnaire_id: id, dossier_id: dossier_id).any?
end end
def assigned_on_procedure?(procedure_id) def assigned_on_procedure?(procedure_id)
@ -100,6 +93,14 @@ class Gestionnaire < ActiveRecord::Base
Notification.unread.where(dossier_id: followed_dossiers_id).select(:dossier_id).distinct(:dossier_id).count Notification.unread.where(dossier_id: followed_dossiers_id).select(:dossier_id).distinct(:dossier_id).count
end end
def notifications_count_per_procedure
followed_dossiers
.joins(:notifications)
.where(notifications: { already_read: false })
.group('procedure_id')
.count
end
def dossiers_with_notifications_count def dossiers_with_notifications_count
notifications.pluck(:dossier_id).uniq.count notifications.pluck(:dossier_id).uniq.count
end end

View file

@ -8,7 +8,27 @@ class Notification < ActiveRecord::Base
avis: 'avis' avis: 'avis'
} }
DEMANDE = %w(cerfa piece_justificative champs submitted)
INSTRUCTION = %w(avis)
MESSAGERIE = %w(commentaire)
belongs_to :dossier belongs_to :dossier
scope :unread, -> { where(already_read: false) } scope :unread, -> { where(already_read: false) }
scope :demande, -> { where(type_notif: DEMANDE) }
scope :instruction, -> { where(type_notif: INSTRUCTION) }
scope :messagerie, -> { where(type_notif: MESSAGERIE) }
scope :mark_as_read, -> { update_all(already_read: true) }
def demande?
Notification::DEMANDE.include?(type_notif)
end
def instruction?
Notification::INSTRUCTION.include?(type_notif)
end
def messagerie?
Notification::MESSAGERIE.include?(type_notif)
end
end end

View file

@ -52,10 +52,10 @@
= value = value
%td.center %td.center
- if current_gestionnaire.follow?(dossier.id) - if current_gestionnaire.follow?(dossier)
= link_to('Quitter', backoffice_dossier_follow_path(dossier_id: dossier.id), 'data-method' => :put, class: 'btn-sm btn-danger', id: "suivre_dossier_#{dossier.id}") = link_to('Quitter', unfollow_dossier_path(dossier.procedure, dossier), method: :patch, class: 'btn-sm btn-danger', id: "suivre_dossier_#{dossier.id}")
- else - else
= link_to('Suivre', backoffice_dossier_follow_path(dossier_id: dossier.id), 'data-method' => :put, class: 'btn-sm btn-primary', id: "suivre_dossier_#{dossier.id}") = link_to('Suivre', follow_dossier_path(dossier.procedure, dossier), method: :patch, class: 'btn-sm btn-primary', id: "suivre_dossier_#{dossier.id}")
%td.center{ style: "color: #{dossier.total_follow == 0 ? 'red' : ''}" } %td.center{ style: "color: #{dossier.total_follow == 0 ? 'red' : ''}" }
= dossier.total_follow = dossier.total_follow

View file

@ -46,11 +46,6 @@
= dossier.text_summary = dossier.text_summary
- else - else
Pas de dossier associé Pas de dossier associé
- elsif champ.type_champ == 'yes_no'
- if champ.decorate.value == 'true'
Oui
- elsif champ.decorate.value == 'false'
Non
- else - else
= sanitize(champ.decorate.value) = sanitize(champ.decorate.value)

Some files were not shown because too many files have changed in this diff Show more