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 highcharts
//= require chartkick
//= require_tree .
//= require_tree ./old_design
//= require bootstrap-sprockets
//= require bootstrap-datepicker/core
//= 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
// about supported directives.
//
//= require ./init
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require leaflet.1.1.0
//= require highcharts
//= require chartkick
//= require select2
//= require typeahead.bundle
//= 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 () {
$(".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;
$light-red: #EBCCD1;
$lighter-red: #F2DEDE;
$green: #35D49E;
$orange: #F59415;

View file

@ -1,3 +1,7 @@
$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 "mixins";
%horizontal-list {
list-style-type: none;
@ -14,12 +13,6 @@
display: inline-block;
}
%page-width-container {
@include horizontal-padding($default-padding);
max-width: $page-width + 2 * $default-padding;
margin: 0 auto;
}
%animation {
animation-fill-mode: forwards;
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 {
font-size: 14px;
.reset-password {
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 "constants";
.button {
display: inline-block;
@ -6,15 +7,22 @@
border-radius: 30px;
border: 1px solid $border-grey;
font-size: 14px;
line-height: 20px;
background-color: #FFFFFF;
color: $black;
cursor: pointer;
-webkit-appearance: none;
&:hover {
background: $light-grey;
text-decoration: none;
}
&:active,
&:focus {
outline: none;
}
&.primary {
color: #FFFFFF;
border-color: $blue;
@ -38,12 +46,99 @@
&.large {
font-size: 18px;
line-height: 26px;
padding: 15px 32px;
}
&.expand {
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 {

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";
body {
body,
input,
textarea,
select {
@extend %new-type;
font-size: 16px;
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 {
font-size: 36px;
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";
.form {
@ -6,32 +7,175 @@
margin-bottom: 20px;
}
label,
input {
font-size: 14px;
}
label,
input[type=submit] {
margin-top: 24px;
}
label {
margin-bottom: 8px;
display: inline-block;
margin-bottom: $default-padding;
display: block;
.mandatory {
color: $dark-red;
}
.notice {
font-size: 14px;
display: block;
margin-top: $default-spacer;
color: $grey;
}
}
input[type=text],
input[type=text]:not([data-address='true']),
input[type=email],
input[type=password] {
input[type=password],
input[type=date],
input[type=number],
input[type=tel],
textarea,
select {
display: block;
width: 100%;
border-radius: 4px;
border: solid 1px $border-grey;
padding: 16px;
margin-bottom: 2 * $default-padding;
padding: $default-padding;
&:disabled {
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);
}
.landing-panel-inner-content {
@extend %page-width-container;
}
$landing-breakpoint: 1040px;
.hero-wrapper {

View file

@ -1,6 +1,6 @@
@import "colors";
@import "common";
@import "constants";
@import "placeholders";
.two-columns {
$column-padding: 60px;
@ -9,7 +9,7 @@
background: linear-gradient(to right, #FFFFFF 0%, #FFFFFF 50%, $light-grey 50%, $light-grey 100%);
.columns-container {
@extend %page-width-container;
@extend .container;
display: flex;
flex-direction: row;
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 ./utils
// = require ./fonts
// = require leaflet.1.1.0
// = require select2
// = require typeahead
// = require_tree .

View file

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

View file

@ -1,7 +1,7 @@
@import "constants";
@import "colors";
@import "common";
@import "constants";
@import "mixins";
@import "placeholders";
// FIXME: Rename when the header is generalized
.new-header {
@ -14,10 +14,37 @@
}
.header-inner-content {
@extend %page-width-container;
@extend .container;
display: flex;
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 {
@ -41,10 +68,11 @@
padding-right: 42px;
float: right;
width: 300px;
margin: 0;
}
button {
padding: 6px 9px;
padding: 9px;
border: none;
background: none;
cursor: pointer;
@ -80,6 +108,7 @@
border: 1px solid $border-grey;
min-width: 270px;
max-width: 340px;
z-index: 10;
&.open {
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";
.patron {
.patron-container {
@extend %page-width-container;
}
p {
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 {
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 {
margin: 15px 10px 0 10px;
height: 30px;
}
#search-button {

View file

@ -98,9 +98,10 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
dossier = Dossier.find(params[:dossier_id])
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
def process_dossier
@ -142,16 +143,7 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
NotificationMailer.send_notification(dossier, template, attestation_pdf).deliver_now!
redirect_to backoffice_dossier_path(id: dossier.id)
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
redirect_to_dossier(dossier)
end
def reload_smartlisting
@ -188,13 +180,21 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
create_dossier_facade params[:dossier_id]
@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
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)
if dossier&.attestation&.emailable? == false
human_size = number_to_human_size(dossier.attestation.pdf.size)

View file

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

View file

@ -4,10 +4,93 @@ module NewGestionnaire
send_data(dossier.attestation.pdf.read, filename: 'attestation.pdf', type: 'application/pdf')
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
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

View file

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

View file

@ -1,6 +1,68 @@
module NewGestionnaire
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

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
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

View file

@ -6,6 +6,12 @@ class ChampDecorator < Draper::Decorator
Date.parse(object.value).strftime("%d/%m/%Y")
elsif type_champ == 'checkbox'
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?
JSON.parse(object.value).join(', ')
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
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? }
def mandatory?
@ -65,9 +68,35 @@ class Champ < ActiveRecord::Base
self.value = date
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
unless dossier.state == 'draft'
NotificationService.new('champs', self.dossier.id, self.libelle).notify
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

View file

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

View file

@ -17,6 +17,7 @@ class Dossier < ActiveRecord::Base
WAITING_FOR_USER = %w(replied)
EN_CONSTRUCTION = %w(initiated updated replied)
EN_INSTRUCTION = %w(received)
EN_CONSTRUCTION_OU_INSTRUCTION = EN_CONSTRUCTION + EN_INSTRUCTION
A_INSTRUIRE = %w(received)
TERMINE = %w(closed refused without_continuation)
@ -42,31 +43,38 @@ class Dossier < ActiveRecord::Base
belongs_to :procedure
belongs_to :user
accepts_nested_attributes_for :champs
accepts_nested_attributes_for :champs_private
default_scope { where(hidden_at: nil) }
scope :state_brouillon, -> { where(state: BROUILLON) }
scope :state_not_brouillon, -> { where.not(state: BROUILLON) }
scope :state_nouveaux, -> { where(state: NOUVEAUX) }
scope :state_ouvert, -> { where(state: OUVERT) }
scope :state_waiting_for_gestionnaire, -> { where(state: WAITING_FOR_GESTIONNAIRE) }
scope :state_waiting_for_user, -> { where(state: WAITING_FOR_USER) }
scope :state_en_construction, -> { where(state: EN_CONSTRUCTION) }
scope :state_en_instruction, -> { where(state: EN_INSTRUCTION) }
scope :state_a_instruire, -> { where(state: A_INSTRUIRE) }
scope :state_termine, -> { where(state: TERMINE) }
scope :state_brouillon, -> { where(state: BROUILLON) }
scope :state_not_brouillon, -> { where.not(state: BROUILLON) }
scope :state_nouveaux, -> { where(state: NOUVEAUX) }
scope :state_ouvert, -> { where(state: OUVERT) }
scope :state_waiting_for_gestionnaire, -> { where(state: WAITING_FOR_GESTIONNAIRE) }
scope :state_waiting_for_user, -> { where(state: WAITING_FOR_USER) }
scope :state_en_construction, -> { where(state: EN_CONSTRUCTION) }
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_termine, -> { where(state: TERMINE) }
scope :archived, -> { where(archived: true) }
scope :not_archived, -> { where(archived: false) }
scope :order_by_updated_at, -> (order = :desc) { order(updated_at: order) }
scope :all_state, -> { not_archived.state_not_brouillon.order_by_updated_at(:asc) }
scope :nouveaux, -> { not_archived.state_nouveaux.order_by_updated_at(:asc) }
scope :ouvert, -> { not_archived.state_ouvert.order_by_updated_at(:asc) }
scope :waiting_for_gestionnaire, -> { not_archived.state_waiting_for_gestionnaire.order_by_updated_at(:asc) }
scope :waiting_for_user, -> { not_archived.state_waiting_for_user.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 :downloadable, -> { state_not_brouillon.order_by_updated_at(:asc) }
scope :all_state, -> { not_archived.state_not_brouillon.order_by_updated_at(:asc) }
scope :nouveaux, -> { not_archived.state_nouveaux.order_by_updated_at(:asc) }
scope :ouvert, -> { not_archived.state_ouvert.order_by_updated_at(:asc) }
scope :waiting_for_gestionnaire, -> { not_archived.state_waiting_for_gestionnaire.order_by_updated_at(:asc) }
scope :waiting_for_user, -> { not_archived.state_waiting_for_user.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 :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
@ -96,6 +104,16 @@ class Dossier < ActiveRecord::Base
pieces_justificatives.where(type_de_piece_justificative_id: type_id).count > 0
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)
pieces_justificatives.where(type_de_piece_justificative_id: type).last
end
@ -213,6 +231,22 @@ class Dossier < ActiveRecord::Base
BROUILLON.include?(state)
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?
procedure.cerfa_flag? && cerfa.size != 0
end

View file

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

View file

@ -7,7 +7,7 @@ class Gestionnaire < ActiveRecord::Base
has_one :preference_smart_listing_page, 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 :followed_dossiers, through: :follows, source: :dossier
has_many :follows
@ -34,21 +34,14 @@ class Gestionnaire < ActiveRecord::Base
dossiers.where(id: dossier_id).any?
end
def toggle_follow_dossier dossier_id
dossier = dossier_id
dossier = Dossier.find(dossier_id) unless dossier_id.class == Dossier
def follow(dossier)
return if follow?(dossier)
Follow.create!(dossier: dossier, gestionnaire: self)
rescue ActiveRecord::RecordInvalid
Follow.where(dossier: dossier, gestionnaire: self).delete_all
rescue ActiveRecord::RecordNotFound
nil
followed_dossiers << dossier
end
def follow? dossier_id
dossier_id = dossier_id.id if dossier_id.class == Dossier
Follow.where(gestionnaire_id: id, dossier_id: dossier_id).any?
def follow?(dossier)
followed_dossiers.include?(dossier)
end
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
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
notifications.pluck(:dossier_id).uniq.count
end

View file

@ -8,7 +8,27 @@ class Notification < ActiveRecord::Base
avis: 'avis'
}
DEMANDE = %w(cerfa piece_justificative champs submitted)
INSTRUCTION = %w(avis)
MESSAGERIE = %w(commentaire)
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

View file

@ -52,10 +52,10 @@
= value
%td.center
- if current_gestionnaire.follow?(dossier.id)
= link_to('Quitter', backoffice_dossier_follow_path(dossier_id: dossier.id), 'data-method' => :put, class: 'btn-sm btn-danger', id: "suivre_dossier_#{dossier.id}")
- if current_gestionnaire.follow?(dossier)
= link_to('Quitter', unfollow_dossier_path(dossier.procedure, dossier), method: :patch, class: 'btn-sm btn-danger', id: "suivre_dossier_#{dossier.id}")
- 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' : ''}" }
= dossier.total_follow

View file

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

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