Merge branch 'dev'
This commit is contained in:
commit
9a4c1360ab
108 changed files with 9038 additions and 549 deletions
18
.babelrc
Normal file
18
.babelrc
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"presets": [
|
||||
["env", {
|
||||
"modules": false,
|
||||
"targets": {
|
||||
"browsers": "> 1%",
|
||||
"uglify": true
|
||||
},
|
||||
"useBuiltIns": true
|
||||
}]
|
||||
],
|
||||
|
||||
"plugins": [
|
||||
"syntax-dynamic-import",
|
||||
"transform-object-rest-spread",
|
||||
["transform-class-properties", { "spec": true }]
|
||||
]
|
||||
}
|
|
@ -25,6 +25,21 @@ bundle_install: &bundle_install
|
|||
name: Install Ruby Dependencies
|
||||
command: bundle install --path ~/vendor/bundle
|
||||
|
||||
yarn_restore_cache: &yarn_restore_cache
|
||||
restore_cache:
|
||||
key: yarn-install-v8-{{ arch }}-{{ checksum "yarn.lock" }}
|
||||
|
||||
yarn_save_cache: &yarn_save_cache
|
||||
save_cache:
|
||||
key: yarn-install-v8-{{ arch }}-{{ checksum "yarn.lock" }}
|
||||
paths:
|
||||
- ~/node_modules
|
||||
|
||||
yarn_install: &yarn_install
|
||||
run:
|
||||
name: Install JS Dependencies
|
||||
command: yarn install --non-interactive
|
||||
|
||||
jobs:
|
||||
build:
|
||||
<<: *defaults
|
||||
|
@ -33,6 +48,9 @@ jobs:
|
|||
- *bundle_restore_cache
|
||||
- *bundle_install
|
||||
- *bundle_save_cache
|
||||
- *yarn_restore_cache
|
||||
- *yarn_save_cache
|
||||
- *yarn_install
|
||||
test:
|
||||
<<: *defaults
|
||||
parallelism: 3
|
||||
|
@ -40,6 +58,8 @@ jobs:
|
|||
- checkout
|
||||
- *bundle_restore_cache
|
||||
- *bundle_install
|
||||
- *yarn_restore_cache
|
||||
- *yarn_install
|
||||
- run:
|
||||
environment:
|
||||
DATABASE_URL: "postgres://tps_test@localhost:5432/tps_test"
|
||||
|
@ -63,6 +83,11 @@ jobs:
|
|||
- checkout
|
||||
- *bundle_restore_cache
|
||||
- *bundle_install
|
||||
- *yarn_restore_cache
|
||||
- *yarn_install
|
||||
- run:
|
||||
name: Run eslint
|
||||
command: yarn lint:js
|
||||
- run:
|
||||
name: Run rubocop
|
||||
command: bundle exec rubocop
|
||||
|
|
19
.eslintrc.js
Normal file
19
.eslintrc.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2017,
|
||||
sourceType: 'module'
|
||||
},
|
||||
globals: {
|
||||
'$': true,
|
||||
'process': true
|
||||
},
|
||||
plugins: ['prettier'],
|
||||
extends: ['eslint:recommended', 'prettier'],
|
||||
env: {
|
||||
browser: true
|
||||
},
|
||||
rules: {
|
||||
'prettier/prettier': 'error'
|
||||
}
|
||||
};
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -37,3 +37,8 @@ coverage/**/*
|
|||
.env
|
||||
Procfile.dev
|
||||
storage/
|
||||
/public/packs
|
||||
/public/packs-test
|
||||
/node_modules
|
||||
yarn-debug.log*
|
||||
.yarn-integrity
|
||||
|
|
3
.postcssrc.yml
Normal file
3
.postcssrc.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
plugins:
|
||||
postcss-import: {}
|
||||
postcss-cssnext: {}
|
3
.prettierrc.js
Normal file
3
.prettierrc.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
singleQuote: true
|
||||
};
|
|
@ -5,6 +5,7 @@ AllCops:
|
|||
Exclude:
|
||||
- "db/schema.rb"
|
||||
- "bin/*"
|
||||
- "node_modules/**/*"
|
||||
|
||||
Bundler/DuplicatedGem:
|
||||
Enabled: true
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -105,6 +105,8 @@ gem 'flipflop'
|
|||
|
||||
gem 'aasm'
|
||||
|
||||
gem 'webpacker', '>= 4.0.x'
|
||||
|
||||
# Cron jobs
|
||||
gem 'delayed_job_active_record'
|
||||
gem "daemons"
|
||||
|
|
19
Gemfile.lock
19
Gemfile.lock
|
@ -19,7 +19,7 @@ GEM
|
|||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (2.3.6)
|
||||
aasm (4.12.3)
|
||||
aasm (5.0.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
actioncable (5.2.0)
|
||||
actionpack (= 5.2.0)
|
||||
|
@ -88,7 +88,7 @@ GEM
|
|||
sass-rails (~> 5.0)
|
||||
selectize-rails (~> 0.6)
|
||||
aes_key_wrap (1.0.1)
|
||||
apipie-rails (0.5.9)
|
||||
apipie-rails (0.5.10)
|
||||
rails (>= 4.1)
|
||||
arel (9.0.0)
|
||||
ast (2.4.0)
|
||||
|
@ -565,7 +565,9 @@ GEM
|
|||
rack
|
||||
rack-protection (2.0.3)
|
||||
rack
|
||||
rack-test (1.0.0)
|
||||
rack-proxy (0.6.4)
|
||||
rack
|
||||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rails (5.2.0)
|
||||
actioncable (= 5.2.0)
|
||||
|
@ -653,7 +655,7 @@ GEM
|
|||
rspec-support (3.7.1)
|
||||
rspec_junit_formatter (0.4.1)
|
||||
rspec-core (>= 2, < 4, != 2.12.0)
|
||||
rubocop (0.58.1)
|
||||
rubocop (0.58.2)
|
||||
jaro_winkler (~> 1.5.1)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.5, != 2.5.1.1)
|
||||
|
@ -752,13 +754,13 @@ GEM
|
|||
ethon (>= 0.9.0)
|
||||
tzinfo (1.2.5)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (4.1.15)
|
||||
uglifier (4.1.17)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.5)
|
||||
unicode-display_width (1.4.0)
|
||||
unicorn (5.4.0)
|
||||
unicorn (5.4.1)
|
||||
kgio (~> 2.6)
|
||||
raindrops (~> 0.7)
|
||||
validate_email (0.1.6)
|
||||
|
@ -780,6 +782,10 @@ GEM
|
|||
addressable (>= 2.3.6)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff
|
||||
webpacker (4.0.0.pre.pre.2)
|
||||
activesupport (>= 4.2)
|
||||
rack-proxy (>= 0.6.1)
|
||||
railties (>= 4.2)
|
||||
websocket-driver (0.7.0)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.3)
|
||||
|
@ -885,6 +891,7 @@ DEPENDENCIES
|
|||
warden!
|
||||
web-console
|
||||
webmock
|
||||
webpacker (>= 4.0.x)
|
||||
xray-rails
|
||||
|
||||
BUNDLED WITH
|
||||
|
|
|
@ -17,6 +17,7 @@ demarches-simplifiees.fr est un site web conçu afin de répondre au besoin urge
|
|||
- Overmind :
|
||||
* Mac : `brew install overmind`
|
||||
* Linux : voir https://github.com/DarthSim/overmind#installation
|
||||
- Yarn : voir https://yarnpkg.com/en/docs/install
|
||||
|
||||
### Tests
|
||||
|
||||
|
@ -31,6 +32,7 @@ demarches-simplifiees.fr est un site web conçu afin de répondre au besoin urge
|
|||
Afin d'initialiser l'environnement de développement, exécutez la commande suivante :
|
||||
|
||||
bundle install
|
||||
yarn install
|
||||
|
||||
|
||||
## Création de la base de données
|
||||
|
@ -111,6 +113,7 @@ Une fois `overmind` lancé, et un breakpoint `byebug` inséré dans le code, il
|
|||
- Faire tourner Brakeman : `bundle exec brakeman`
|
||||
- Linter les fichiers HAML : `bundle exec haml-lint app/views/`
|
||||
- Linter les fichiers SCSS : `bundle exec scss-lint app/assets/stylesheets/`
|
||||
- Linter les fichiers JavaScript : `yarn lint:js` (`yarn lint:js --fix`)
|
||||
- [AccessLint](http://accesslint.com/) tourne automatiquement sur les PRs
|
||||
|
||||
## Déploiement
|
||||
|
|
|
@ -10,12 +10,6 @@
|
|||
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
||||
// about supported directives.
|
||||
//
|
||||
//= require activestorage
|
||||
//= require jquery
|
||||
//= require jquery_ujs
|
||||
//= require turbolinks
|
||||
//= require highcharts
|
||||
//= require chartkick
|
||||
//= require_tree ./old_design
|
||||
//= require bootstrap-sprockets
|
||||
|
||||
|
@ -31,12 +25,9 @@
|
|||
//= require bootstrap-wysihtml5
|
||||
//= require bootstrap-wysihtml5/locales/fr-FR
|
||||
//= require handlebars
|
||||
//= require typeahead.bundle
|
||||
//= require select2
|
||||
|
||||
$(document).on('turbolinks:load', application_init);
|
||||
|
||||
|
||||
function application_init(){
|
||||
tooltip_init();
|
||||
scroll_to();
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
||||
// listed below.
|
||||
//
|
||||
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
||||
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
||||
//
|
||||
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
||||
// compiled file.
|
||||
//
|
||||
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
||||
// about supported directives.
|
||||
//
|
||||
//= require ./init
|
||||
//= require activestorage
|
||||
//= require jquery
|
||||
//= require jquery_ujs
|
||||
//= require turbolinks
|
||||
//= require leaflet.1.1.0
|
||||
//= require highcharts
|
||||
//= require chartkick
|
||||
//= require select2
|
||||
//= require select2_locale_fr
|
||||
//= require typeahead.bundle
|
||||
//= require_tree .
|
|
@ -1,3 +0,0 @@
|
|||
DS.toggleCondidentielExplanation = function(event) {
|
||||
$(".confidentiel-explanation").toggle();
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
$(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");
|
||||
}
|
||||
});
|
|
@ -1,10 +0,0 @@
|
|||
function drawCadastre (map) {
|
||||
drawLayerWithItems(map, dossierCadastres, {
|
||||
fillColor: '#8A6D3B',
|
||||
weight: 2,
|
||||
opacity: 0.7,
|
||||
color: '#8A6D3B',
|
||||
dashArray: '3',
|
||||
fillOpacity: 0.5
|
||||
});
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
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.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© <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);
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
function drawQuartiersPrioritaires (map) {
|
||||
drawLayerWithItems(map, dossierQuartiersPrioritaires, {
|
||||
fillColor: '#31708F',
|
||||
weight: 2,
|
||||
opacity: 0.7,
|
||||
color: '#31708F',
|
||||
dashArray: '3',
|
||||
fillOpacity: 0.5
|
||||
});
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
(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);
|
||||
})();
|
|
@ -1,36 +0,0 @@
|
|||
(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);
|
||||
})();
|
|
@ -1,30 +0,0 @@
|
|||
document.addEventListener('turbolinks:load', function() {
|
||||
var primaries, i;
|
||||
|
||||
primaries = document.querySelectorAll('select[data-secondary-options]');
|
||||
for (i = 0; i < primaries.length; i++) {
|
||||
primaries[i].addEventListener('change', function(e) {
|
||||
var option, options, element, primary, secondary, secondaryOptions;
|
||||
|
||||
primary = e.target;
|
||||
secondary = document.querySelector('select[data-secondary-id="' + primary.dataset.primaryId + '"]');
|
||||
secondaryOptions = JSON.parse(primary.dataset.secondaryOptions);
|
||||
|
||||
while ((option = secondary.firstChild)) {
|
||||
secondary.removeChild(option);
|
||||
}
|
||||
|
||||
options = secondaryOptions[e.target.value];
|
||||
|
||||
for (i = 0; i < options.length; i++) {
|
||||
option = options[i];
|
||||
element = document.createElement("option");
|
||||
element.textContent = option;
|
||||
element.value = option;
|
||||
secondary.appendChild(element);
|
||||
}
|
||||
|
||||
secondary.selectedIndex = 0;
|
||||
});
|
||||
}
|
||||
});
|
|
@ -1,13 +0,0 @@
|
|||
document.addEventListener('turbolinks:load', function() {
|
||||
$('select.select2').select2({
|
||||
'language': 'fr',
|
||||
'width': '100%'
|
||||
});
|
||||
|
||||
$('select.select2-limited').select2({
|
||||
'language': 'fr',
|
||||
'placeholder': 'Sélectionnez des colonnes',
|
||||
'maximumSelectionLength': '5',
|
||||
'width': '300px'
|
||||
});
|
||||
});
|
|
@ -1,30 +0,0 @@
|
|||
document.addEventListener('turbolinks:load', function() {
|
||||
$('[data-siret]').on('input', function(evt) {
|
||||
var input = $(evt.target);
|
||||
var value = input.val();
|
||||
var url = input.attr('data-siret');
|
||||
switch (value.length) {
|
||||
case 0:
|
||||
$.get(url+'?siret=blank');
|
||||
break;
|
||||
case 14:
|
||||
input.attr('disabled', 'disabled');
|
||||
$('.spinner').show();
|
||||
$.get(url+'?siret='+value).then(function() {
|
||||
input.removeAttr('data-invalid');
|
||||
input.removeAttr('disabled');
|
||||
$('.spinner').hide();
|
||||
}, function() {
|
||||
input.removeAttr('disabled');
|
||||
input.attr('data-invalid', true);
|
||||
$('.spinner').hide();
|
||||
});
|
||||
break;
|
||||
default:
|
||||
if (!input.attr('data-invalid')) {
|
||||
input.attr('data-invalid', true);
|
||||
$.get(url+'?siret=invalid');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,69 +0,0 @@
|
|||
addEventListener("direct-upload:initialize", function (event) {
|
||||
var target = event.target,
|
||||
detail = event.detail,
|
||||
id = detail.id,
|
||||
file = detail.file;
|
||||
|
||||
target.insertAdjacentHTML("beforebegin", "\n<div id=\"direct-upload-" +
|
||||
id +
|
||||
"\" class=\"direct-upload direct-upload--pending\">\n<div id=\"direct-upload-progress-" +
|
||||
id + "\" class=\"direct-upload__progress\" style=\"width: 0%\"></div>\n<span class=\"direct-upload__filename\">" +
|
||||
file.name +
|
||||
"</span>\n</div>\n");
|
||||
});
|
||||
|
||||
addEventListener("direct-upload:start", function (event) {
|
||||
var id = event.detail.id,
|
||||
element = document.getElementById("direct-upload-" + id);
|
||||
|
||||
element.classList.remove("direct-upload--pending");
|
||||
});
|
||||
|
||||
addEventListener("direct-upload:progress", function (event) {
|
||||
var id = event.detail.id,
|
||||
progress = event.detail.progress,
|
||||
progressElement = document.getElementById("direct-upload-progress-" + id);
|
||||
|
||||
progressElement.style.width = progress + "%";
|
||||
});
|
||||
|
||||
addEventListener("direct-upload:error", function (event) {
|
||||
event.preventDefault();
|
||||
var id = event.detail.id,
|
||||
error = event.detail.error,
|
||||
element = document.getElementById("direct-upload-" + id);
|
||||
|
||||
element.classList.add("direct-upload--error");
|
||||
element.setAttribute("title", error);
|
||||
});
|
||||
|
||||
addEventListener("direct-upload:end", function (event) {
|
||||
var id = event.detail.id,
|
||||
element = document.getElementById("direct-upload-" + id);
|
||||
|
||||
element.classList.add("direct-upload--complete");
|
||||
});
|
||||
|
||||
addEventListener('turbolinks:load', function() {
|
||||
var submitButtons = document.querySelectorAll('form button[type=submit][data-action]');
|
||||
var hiddenInput = document.querySelector('form input[type=hidden][name=submit_action]');
|
||||
submitButtons = [].slice.call(submitButtons);
|
||||
|
||||
submitButtons.forEach(function(button) {
|
||||
button.addEventListener('click', function() {
|
||||
// Active Storage will intercept the form.submit event to upload
|
||||
// the attached files, and then fire the submit action again – but forgetting
|
||||
// which button was clicked. So we manually set the type of action that trigerred
|
||||
// the form submission.
|
||||
var action = button.getAttribute('data-action');
|
||||
hiddenInput.value = action;
|
||||
// Some form fields are marked as mandatory, but when saving a draft we don't want them
|
||||
// to be enforced by the browser.
|
||||
if (action === 'submit') {
|
||||
button.form.removeAttribute('novalidate');
|
||||
} else {
|
||||
button.form.setAttribute('novalidate', 'novalidate');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,8 +0,0 @@
|
|||
$(document).on("click", "body", function () {
|
||||
$(".print-menu").removeClass("open fade-in-down");
|
||||
});
|
||||
|
||||
DS.togglePrintMenu = function(event) {
|
||||
event.stopPropagation();
|
||||
$(".print-menu").toggleClass("open fade-in-down");
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
$(document).on("click", "body", function () {
|
||||
$(".header-menu").removeClass("open fade-in-down");
|
||||
});
|
||||
|
||||
DS.toggleHeaderMenu = function(event) {
|
||||
event.stopPropagation();
|
||||
$(".header-menu").toggleClass("open fade-in-down");
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
// namespace
|
||||
window.DS = window.DS || {};
|
|
@ -1,24 +0,0 @@
|
|||
DS.scrollMessagerie = function () {
|
||||
var scrollTo = function ($container, $scrollTo) {
|
||||
$container.scrollTop(
|
||||
$scrollTo.offset().top - $container.offset().top + $container.scrollTop()
|
||||
);
|
||||
}
|
||||
|
||||
var scrollToBottom = function ($container) {
|
||||
$container.scrollTop($container.prop('scrollHeight'));
|
||||
}
|
||||
|
||||
var $ul = $(".messagerie ul").first();
|
||||
if($ul.length) {
|
||||
var $elementToScroll = $('.date.highlighted').first();
|
||||
|
||||
if ($elementToScroll.length != 0) {
|
||||
scrollTo($ul, $elementToScroll);
|
||||
} else {
|
||||
scrollToBottom($ul);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("turbolinks:load", DS.scrollMessagerie);
|
|
@ -1,9 +0,0 @@
|
|||
DS.showMotivation = function (state) {
|
||||
$(".motivation." + state).show();
|
||||
$(".dropdown-items").hide();
|
||||
};
|
||||
|
||||
DS.motivationCancel = function () {
|
||||
$(".motivation").hide();
|
||||
$(".dropdown-items").show();
|
||||
};
|
|
@ -1,18 +0,0 @@
|
|||
DS.toggleChart = function(event, chartClass) {
|
||||
var nextSelectorItem = $(event.target),
|
||||
nextChart = $(chartClass),
|
||||
nextChartId = nextChart.children().first().attr("id"),
|
||||
currentSelectorItem = nextSelectorItem.parent().find(".segmented-control-item-active"),
|
||||
currentChart = nextSelectorItem.parent().parent().find(".chart:not(.hidden)");
|
||||
|
||||
// Change the current selector and the next selector states
|
||||
currentSelectorItem.toggleClass("segmented-control-item-active");
|
||||
nextSelectorItem.toggleClass("segmented-control-item-active");
|
||||
|
||||
// Hide the currently shown chart and show the new one
|
||||
currentChart.toggleClass("hidden");
|
||||
nextChart.toggleClass("hidden");
|
||||
|
||||
// Reflow needed, see https://github.com/highcharts/highcharts/issues/1979
|
||||
Chartkick.charts[nextChartId].getChartObject().reflow();
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
addEventListener("direct-upload:initialize", function (event) {
|
||||
var target = event.target,
|
||||
detail = event.detail,
|
||||
id = detail.id,
|
||||
file = detail.file;
|
||||
|
||||
target.insertAdjacentHTML("beforebegin", "\n<div id=\"direct-upload-" +
|
||||
id +
|
||||
"\" class=\"direct-upload direct-upload--pending\">\n<div id=\"direct-upload-progress-" +
|
||||
id + "\" class=\"direct-upload__progress\" style=\"width: 0%\"></div>\n<span class=\"direct-upload__filename\">" +
|
||||
file.name +
|
||||
"</span>\n</div>\n");
|
||||
});
|
||||
|
||||
addEventListener("direct-upload:start", function (event) {
|
||||
var id = event.detail.id,
|
||||
element = document.getElementById("direct-upload-" + id);
|
||||
|
||||
element.classList.remove("direct-upload--pending");
|
||||
});
|
||||
|
||||
addEventListener("direct-upload:progress", function (event) {
|
||||
var id = event.detail.id,
|
||||
progress = event.detail.progress,
|
||||
progressElement = document.getElementById("direct-upload-progress-" + id);
|
||||
|
||||
progressElement.style.width = progress + "%";
|
||||
});
|
||||
|
||||
addEventListener("direct-upload:error", function (event) {
|
||||
event.preventDefault();
|
||||
var id = event.detail.id,
|
||||
error = event.detail.error,
|
||||
element = document.getElementById("direct-upload-" + id);
|
||||
|
||||
element.classList.add("direct-upload--error");
|
||||
element.setAttribute("title", error);
|
||||
});
|
||||
|
||||
addEventListener("direct-upload:end", function (event) {
|
||||
var id = event.detail.id,
|
||||
element = document.getElementById("direct-upload-" + id);
|
||||
|
||||
element.classList.add("direct-upload--complete");
|
||||
});
|
||||
|
||||
addEventListener('load', function() {
|
||||
var submitButtons = document.querySelectorAll('form button[type=submit][data-action]');
|
||||
var hiddenInput = document.querySelector('form input[type=hidden][name=submit_action]');
|
||||
submitButtons = [].slice.call(submitButtons);
|
||||
|
||||
submitButtons.forEach(function(button) {
|
||||
button.addEventListener('click', function() {
|
||||
hiddenInput.value = button.getAttribute('data-action');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -5,7 +5,7 @@ $(document)
|
|||
function the_terms() {
|
||||
var the_terms = $("#dossier_autorisation_donnees");
|
||||
|
||||
if (the_terms.size() == 0)
|
||||
if (the_terms.length == 0)
|
||||
return;
|
||||
|
||||
check_value(the_terms);
|
||||
|
|
|
@ -150,6 +150,7 @@
|
|||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
|
||||
position: absolute;
|
||||
right: 0;
|
||||
text-align: left;
|
||||
top: 5 * $default-spacer;
|
||||
cursor: default;
|
||||
z-index: 10;
|
||||
|
|
|
@ -64,10 +64,6 @@
|
|||
visibility: visible;
|
||||
}
|
||||
|
||||
.etablissement-titre {
|
||||
margin-bottom: 2 * $default-padding;
|
||||
}
|
||||
|
||||
// Align checkboxes on the top-left side of the label
|
||||
&.editable-champ-checkbox,
|
||||
&.editable-champ-engagement {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
.right-spinner {
|
||||
display: none;
|
||||
position: absolute;
|
||||
bottom: 1.3em;
|
||||
top: 3.7em;
|
||||
right: 1.2em;
|
||||
transform: scale(0.3);
|
||||
}
|
||||
|
|
|
@ -12,14 +12,16 @@ class Champs::SiretController < ApplicationController
|
|||
if @etablissement
|
||||
@etablissement.mark_for_destruction
|
||||
end
|
||||
@error = "SIRET invalide"
|
||||
@error = "Le numéro de SIRET doit comporter exactement 14 chiffres."
|
||||
else
|
||||
etablissement_attributes = ApiEntrepriseService.get_etablissement_params_for_siret(siret, @champ.dossier.procedure_id)
|
||||
if etablissement_attributes.present?
|
||||
@etablissement = @champ.build_etablissement(etablissement_attributes)
|
||||
@etablissement.champ = @champ
|
||||
else
|
||||
@error = "SIRET invalide"
|
||||
message = ['Nous n’avons pas trouvé d’établissement correspondant à ce numéro de SIRET.']
|
||||
message << helpers.link_to('Plus d’informations', "https://faq.demarches-simplifiees.fr/article/4-erreur-siret", target: '_blank')
|
||||
@error = helpers.safe_join(message, ' ')
|
||||
end
|
||||
end
|
||||
respond_to do |format|
|
||||
|
|
|
@ -101,8 +101,10 @@ module NewGestionnaire
|
|||
NotificationMailer.send_without_continuation_notification(dossier).deliver_later
|
||||
when "accepter"
|
||||
dossier.accepte!
|
||||
dossier.attestation = dossier.build_attestation
|
||||
dossier.save
|
||||
if dossier.attestation.nil?
|
||||
dossier.attestation = dossier.build_attestation
|
||||
dossier.save
|
||||
end
|
||||
flash.notice = "Dossier traité avec succès."
|
||||
NotificationMailer.send_closed_notification(dossier).deliver_later
|
||||
end
|
||||
|
|
19
app/javascript/manager/fields/features.js
Normal file
19
app/javascript/manager/fields/features.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Administrate injects its own copy of jQuery, and it is the one
|
||||
// configured by rails to send csrf-token
|
||||
const $ = window.$;
|
||||
|
||||
$(document).on('change', '#features input[type=checkbox]', ({ target }) => {
|
||||
target = $(target);
|
||||
const url = target.data('url');
|
||||
const key = target.data('key');
|
||||
const value = target.prop('checked');
|
||||
|
||||
$.ajax(url, {
|
||||
method: 'put',
|
||||
contentType: 'application/json',
|
||||
dataType: 'json',
|
||||
data: JSON.stringify({
|
||||
features: { [key]: value }
|
||||
})
|
||||
});
|
||||
});
|
3
app/javascript/new_design/avis.js
Normal file
3
app/javascript/new_design/avis.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
export function toggleCondidentielExplanation() {
|
||||
$('.confidentiel-explanation').toggle();
|
||||
}
|
11
app/javascript/new_design/buttons.js
Normal file
11
app/javascript/new_design/buttons.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
$(document).on('click', 'body', () => {
|
||||
$('.button.dropdown').removeClass('open');
|
||||
});
|
||||
|
||||
$(document).on('click', '.button.dropdown', event => {
|
||||
event.stopPropagation();
|
||||
const $target = $(event.target);
|
||||
if ($target.hasClass('button', 'dropdown')) {
|
||||
$target.toggleClass('open');
|
||||
}
|
||||
});
|
44
app/javascript/new_design/carto.js
Normal file
44
app/javascript/new_design/carto.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
import L from 'leaflet';
|
||||
|
||||
import { getData } from '../shared/data';
|
||||
|
||||
import {
|
||||
drawCadastre,
|
||||
drawQuartiersPrioritaires,
|
||||
drawUserSelection
|
||||
} from './carto/draw';
|
||||
|
||||
const LON = '2.428462';
|
||||
const LAT = '46.538192';
|
||||
const DEFAULT_POSITION = { lon: LON, lat: LAT, zoom: 5 };
|
||||
|
||||
function initialize() {
|
||||
if ($('#map').length > 0) {
|
||||
$.getJSON(getData('carto').getPositionUrl).then(
|
||||
position => initializeWithPosition(position),
|
||||
() => initializeWithPosition(DEFAULT_POSITION)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
addEventListener('turbolinks:load', initialize);
|
||||
|
||||
function initializeWithPosition(position) {
|
||||
const map = L.map('map', {
|
||||
scrollWheelZoom: false
|
||||
}).setView([position.lat, position.lon], position.zoom);
|
||||
|
||||
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution:
|
||||
'© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
}).addTo(map);
|
||||
|
||||
const data = getData('carto');
|
||||
|
||||
// draw external polygons
|
||||
drawCadastre(map, data);
|
||||
drawQuartiersPrioritaires(map, data);
|
||||
|
||||
// draw user polygon
|
||||
drawUserSelection(map, data);
|
||||
}
|
48
app/javascript/new_design/carto/draw.js
Normal file
48
app/javascript/new_design/carto/draw.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
import L from 'leaflet';
|
||||
|
||||
function drawLayerWithItems(map, items, style) {
|
||||
if (Array.isArray(items) && items.length > 0) {
|
||||
const layer = new L.GeoJSON();
|
||||
|
||||
items.forEach(function(item) {
|
||||
layer.addData(item.geometry);
|
||||
});
|
||||
|
||||
layer.setStyle(style).addTo(map);
|
||||
}
|
||||
}
|
||||
|
||||
export function drawCadastre(map, { dossierCadastres }) {
|
||||
drawLayerWithItems(map, dossierCadastres, {
|
||||
fillColor: '#8A6D3B',
|
||||
weight: 2,
|
||||
opacity: 0.7,
|
||||
color: '#8A6D3B',
|
||||
dashArray: '3',
|
||||
fillOpacity: 0.5
|
||||
});
|
||||
}
|
||||
|
||||
export function drawQuartiersPrioritaires(
|
||||
map,
|
||||
{ dossierQuartiersPrioritaires }
|
||||
) {
|
||||
drawLayerWithItems(map, dossierQuartiersPrioritaires, {
|
||||
fillColor: '#31708F',
|
||||
weight: 2,
|
||||
opacity: 0.7,
|
||||
color: '#31708F',
|
||||
dashArray: '3',
|
||||
fillOpacity: 0.5
|
||||
});
|
||||
}
|
||||
|
||||
export function drawUserSelection(map, { dossierJsonLatLngs }) {
|
||||
if (dossierJsonLatLngs.length > 0) {
|
||||
const polygon = L.polygon(dossierJsonLatLngs, {
|
||||
color: 'red',
|
||||
zIndex: 3
|
||||
}).addTo(map);
|
||||
map.fitBounds(polygon.getBounds());
|
||||
}
|
||||
}
|
30
app/javascript/new_design/champs/address.js
Normal file
30
app/javascript/new_design/champs/address.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
import Bloodhound from 'bloodhound-js';
|
||||
|
||||
const display = 'label';
|
||||
|
||||
const bloodhound = new Bloodhound({
|
||||
datumTokenizer: Bloodhound.tokenizers.obj.whitespace(display),
|
||||
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
||||
|
||||
remote: {
|
||||
url: '/ban/search?request=%QUERY',
|
||||
wildcard: '%QUERY'
|
||||
}
|
||||
});
|
||||
|
||||
bloodhound.initialize();
|
||||
|
||||
function bindTypeahead() {
|
||||
$('input[data-address="true"]').typeahead(
|
||||
{
|
||||
minLength: 1
|
||||
},
|
||||
{
|
||||
display: display,
|
||||
source: bloodhound,
|
||||
limit: 5
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
addEventListener('turbolinks:load', bindTypeahead);
|
40
app/javascript/new_design/champs/dossier-link.js
Normal file
40
app/javascript/new_design/champs/dossier-link.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
function showNotFound() {
|
||||
$('.dossier-link .text-info').hide();
|
||||
$('.dossier-link .text-warning').show();
|
||||
}
|
||||
|
||||
function showData(data) {
|
||||
$('.dossier-link .dossier-text-summary').text(data.textSummary);
|
||||
$('.dossier-link .text-info').show();
|
||||
$('.dossier-link .text-warning').hide();
|
||||
}
|
||||
|
||||
function hideEverything() {
|
||||
$('.dossier-link .text-info').hide();
|
||||
$('.dossier-link .text-warning').hide();
|
||||
}
|
||||
|
||||
function fetchProcedureLibelle(e) {
|
||||
const dossierId = $(e.target).val();
|
||||
if (dossierId) {
|
||||
$.get(`/users/dossiers/${dossierId}/text_summary`)
|
||||
.done(showData)
|
||||
.fail(showNotFound);
|
||||
} else {
|
||||
hideEverything();
|
||||
}
|
||||
}
|
||||
|
||||
let timeOut;
|
||||
function debounceFetchProcedureLibelle(e) {
|
||||
if (timeOut) {
|
||||
clearTimeout(timeOut);
|
||||
}
|
||||
timeOut = setTimeout(() => fetchProcedureLibelle(e), 300);
|
||||
}
|
||||
|
||||
$(document).on(
|
||||
'input',
|
||||
'[data-type=dossier-link]',
|
||||
debounceFetchProcedureLibelle
|
||||
);
|
29
app/javascript/new_design/champs/linked-drop-down-list.js
Normal file
29
app/javascript/new_design/champs/linked-drop-down-list.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
addEventListener('turbolinks:load', () => {
|
||||
const primaries = document.querySelectorAll('select[data-secondary-options]');
|
||||
|
||||
for (let primary of primaries) {
|
||||
let secondary = document.querySelector(
|
||||
`select[data-secondary-id="${primary.dataset.primaryId}"]`
|
||||
);
|
||||
let secondaryOptions = JSON.parse(primary.dataset.secondaryOptions);
|
||||
|
||||
primary.addEventListener('change', e => {
|
||||
let option, options, element;
|
||||
|
||||
while ((option = secondary.firstChild)) {
|
||||
secondary.removeChild(option);
|
||||
}
|
||||
|
||||
options = secondaryOptions[e.target.value];
|
||||
|
||||
for (let option of options) {
|
||||
element = document.createElement('option');
|
||||
element.textContent = option;
|
||||
element.value = option;
|
||||
secondary.appendChild(element);
|
||||
}
|
||||
|
||||
secondary.selectedIndex = 0;
|
||||
});
|
||||
}
|
||||
});
|
13
app/javascript/new_design/champs/multiple-drop-down-list.js
Normal file
13
app/javascript/new_design/champs/multiple-drop-down-list.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
addEventListener('turbolinks:load', () => {
|
||||
$('select.select2').select2({
|
||||
language: 'fr',
|
||||
width: '100%'
|
||||
});
|
||||
|
||||
$('select.select2-limited').select2({
|
||||
language: 'fr',
|
||||
placeholder: 'Sélectionnez des colonnes',
|
||||
maximumSelectionLength: '5',
|
||||
width: '300px'
|
||||
});
|
||||
});
|
35
app/javascript/new_design/champs/siret.js
Normal file
35
app/javascript/new_design/champs/siret.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
addEventListener('turbolinks:load', () => {
|
||||
$('[data-siret]').on('input', evt => {
|
||||
const input = $(evt.target);
|
||||
const value = input.val();
|
||||
const url = input.attr('data-siret');
|
||||
|
||||
switch (value.length) {
|
||||
case 0:
|
||||
input.removeAttr('data-invalid');
|
||||
$.get(`${url}?siret=blank`);
|
||||
break;
|
||||
case 14:
|
||||
input.attr('disabled', 'disabled');
|
||||
$('.spinner').show();
|
||||
$.get(`${url}?siret=${value}`).then(
|
||||
() => {
|
||||
input.removeAttr('data-invalid');
|
||||
input.removeAttr('disabled');
|
||||
$('.spinner').hide();
|
||||
},
|
||||
() => {
|
||||
input.removeAttr('disabled');
|
||||
input.attr('data-invalid', true);
|
||||
$('.spinner').hide();
|
||||
}
|
||||
);
|
||||
break;
|
||||
default:
|
||||
if (!input.attr('data-invalid')) {
|
||||
input.attr('data-invalid', true);
|
||||
$.get(`${url}?siret=invalid`);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
8
app/javascript/new_design/dossier.js
Normal file
8
app/javascript/new_design/dossier.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
$(document).on('click', 'body', () => {
|
||||
$('.print-menu').removeClass('open fade-in-down');
|
||||
});
|
||||
|
||||
export function togglePrintMenu(event) {
|
||||
event.stopPropagation();
|
||||
$('.print-menu').toggleClass('open fade-in-down');
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
$(document).on('blur keydown', 'input, textarea', function() {
|
||||
$(document).on('blur keydown', 'input, textarea', () => {
|
||||
$(this).addClass('touched');
|
||||
});
|
||||
|
||||
$(document).on('click', 'input[type="submit"]:not([formnovalidate])', function() {
|
||||
var $form = $(this).closest('form');
|
||||
$(document).on('click', 'input[type="submit"]:not([formnovalidate])', () => {
|
||||
const $form = $(this).closest('form');
|
||||
$('input, textarea', $form).addClass('touched');
|
||||
});
|
8
app/javascript/new_design/header.js
Normal file
8
app/javascript/new_design/header.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
$(document).on('click', 'body', () => {
|
||||
$('.header-menu').removeClass('open fade-in-down');
|
||||
});
|
||||
|
||||
export function toggleHeaderMenu(event) {
|
||||
event.stopPropagation();
|
||||
$('.header-menu').toggleClass('open fade-in-down');
|
||||
}
|
25
app/javascript/new_design/messagerie.js
Normal file
25
app/javascript/new_design/messagerie.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
export function scrollMessagerie() {
|
||||
const $ul = $('.messagerie ul').first();
|
||||
|
||||
if ($ul.length) {
|
||||
const $elementToScroll = $('.date.highlighted').first();
|
||||
|
||||
if ($elementToScroll.length != 0) {
|
||||
scrollTo($ul, $elementToScroll);
|
||||
} else {
|
||||
scrollToBottom($ul);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function scrollTo($container, $scrollTo) {
|
||||
$container.scrollTop(
|
||||
$scrollTo.offset().top - $container.offset().top + $container.scrollTop()
|
||||
);
|
||||
}
|
||||
|
||||
function scrollToBottom($container) {
|
||||
$container.scrollTop($container.prop('scrollHeight'));
|
||||
}
|
||||
|
||||
addEventListener('turbolinks:load', scrollMessagerie);
|
9
app/javascript/new_design/state-button.js
Normal file
9
app/javascript/new_design/state-button.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
export function showMotivation(state) {
|
||||
$(`.motivation.${state}`).show();
|
||||
$('.dropdown-items').hide();
|
||||
}
|
||||
|
||||
export function motivationCancel() {
|
||||
$('.motivation').hide();
|
||||
$('.dropdown-items').show();
|
||||
}
|
28
app/javascript/new_design/toggle-chart.js
Normal file
28
app/javascript/new_design/toggle-chart.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
import Chartkick from 'chartkick';
|
||||
|
||||
export function toggleChart(event, chartClass) {
|
||||
const nextSelectorItem = $(event.target),
|
||||
nextChart = $(chartClass),
|
||||
nextChartId = nextChart
|
||||
.children()
|
||||
.first()
|
||||
.attr('id'),
|
||||
currentSelectorItem = nextSelectorItem
|
||||
.parent()
|
||||
.find('.segmented-control-item-active'),
|
||||
currentChart = nextSelectorItem
|
||||
.parent()
|
||||
.parent()
|
||||
.find('.chart:not(.hidden)');
|
||||
|
||||
// Change the current selector and the next selector states
|
||||
currentSelectorItem.toggleClass('segmented-control-item-active');
|
||||
nextSelectorItem.toggleClass('segmented-control-item-active');
|
||||
|
||||
// Hide the currently shown chart and show the new one
|
||||
currentChart.toggleClass('hidden');
|
||||
nextChart.toggleClass('hidden');
|
||||
|
||||
// Reflow needed, see https://github.com/highcharts/highcharts/issues/1979
|
||||
Chartkick.charts[nextChartId].getChartObject().reflow();
|
||||
}
|
31
app/javascript/packs/application-old.js
Normal file
31
app/javascript/packs/application-old.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
import Turbolinks from 'turbolinks';
|
||||
import Rails from 'rails-ujs';
|
||||
import * as ActiveStorage from 'activestorage';
|
||||
import Chartkick from 'chartkick';
|
||||
import Highcharts from 'highcharts';
|
||||
import Bloodhound from 'bloodhound-js';
|
||||
import jQuery from 'jquery';
|
||||
|
||||
import 'select2';
|
||||
import 'typeahead.js';
|
||||
|
||||
import '../shared/rails-ujs-fix';
|
||||
import '../shared/direct-uploads';
|
||||
|
||||
// Start Rails helpers
|
||||
Chartkick.addAdapter(Highcharts);
|
||||
Rails.start();
|
||||
Turbolinks.start();
|
||||
ActiveStorage.start();
|
||||
|
||||
// Disable jQuery-driven animations during tests
|
||||
if (process.env['RAILS_ENV'] === 'test') {
|
||||
jQuery.fx.off = true;
|
||||
}
|
||||
|
||||
// Expose globals
|
||||
window.Bloodhound = Bloodhound;
|
||||
window.Chartkick = Chartkick;
|
||||
// Export jQuery globally for legacy Javascript files used in the old design
|
||||
window.$ = jQuery;
|
||||
window.jQuery = jQuery;
|
56
app/javascript/packs/application.js
Normal file
56
app/javascript/packs/application.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
import Turbolinks from 'turbolinks';
|
||||
import Rails from 'rails-ujs';
|
||||
import * as ActiveStorage from 'activestorage';
|
||||
|
||||
import Chartkick from 'chartkick';
|
||||
import Highcharts from 'highcharts';
|
||||
import jQuery from 'jquery';
|
||||
|
||||
import 'select2';
|
||||
import 'typeahead.js';
|
||||
|
||||
import '../shared/rails-ujs-fix';
|
||||
import '../shared/direct-uploads';
|
||||
|
||||
import '../new_design/buttons';
|
||||
import '../new_design/form-validation';
|
||||
import '../new_design/carto';
|
||||
|
||||
import '../new_design/champs/address';
|
||||
import '../new_design/champs/dossier-link';
|
||||
import '../new_design/champs/linked-drop-down-list';
|
||||
import '../new_design/champs/multiple-drop-down-list';
|
||||
import '../new_design/champs/siret';
|
||||
|
||||
import { toggleCondidentielExplanation } from '../new_design/avis';
|
||||
import { togglePrintMenu } from '../new_design/dossier';
|
||||
import { toggleHeaderMenu } from '../new_design/header';
|
||||
import { scrollMessagerie } from '../new_design/messagerie';
|
||||
import { showMotivation, motivationCancel } from '../new_design/state-button';
|
||||
import { toggleChart } from '../new_design/toggle-chart';
|
||||
|
||||
// This is the global application namespace where we expose helpers used from rails views
|
||||
const DS = {
|
||||
toggleCondidentielExplanation,
|
||||
togglePrintMenu,
|
||||
toggleHeaderMenu,
|
||||
scrollMessagerie,
|
||||
showMotivation,
|
||||
motivationCancel,
|
||||
toggleChart
|
||||
};
|
||||
|
||||
// Start Rails helpers
|
||||
Chartkick.addAdapter(Highcharts);
|
||||
Rails.start();
|
||||
Turbolinks.start();
|
||||
ActiveStorage.start();
|
||||
|
||||
// Disable jQuery-driven animations during tests
|
||||
if (process.env['RAILS_ENV'] === 'test') {
|
||||
jQuery.fx.off = true;
|
||||
}
|
||||
|
||||
// Expose globals
|
||||
window.DS = window.DS || DS;
|
||||
window.Chartkick = Chartkick;
|
1
app/javascript/packs/manager.js
Normal file
1
app/javascript/packs/manager.js
Normal file
|
@ -0,0 +1 @@
|
|||
import '../manager/fields/features';
|
13
app/javascript/shared/data.js
Normal file
13
app/javascript/shared/data.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
const _DATA = {};
|
||||
|
||||
function setupData() {
|
||||
if (window.DATA.length) {
|
||||
Object.assign(_DATA, ...window.DATA);
|
||||
window.DATA.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
export function getData(namespace) {
|
||||
setupData();
|
||||
return namespace ? _DATA[namespace] : _DATA;
|
||||
}
|
76
app/javascript/shared/direct-uploads.js
Normal file
76
app/javascript/shared/direct-uploads.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
addEventListener('direct-upload:initialize', event => {
|
||||
const target = event.target,
|
||||
detail = event.detail,
|
||||
id = detail.id,
|
||||
file = detail.file;
|
||||
|
||||
target.insertAdjacentHTML(
|
||||
'beforebegin',
|
||||
'\n<div id="direct-upload-' +
|
||||
id +
|
||||
'" class="direct-upload direct-upload--pending">\n<div id="direct-upload-progress-' +
|
||||
id +
|
||||
'" class="direct-upload__progress" style="width: 0%"></div>\n<span class="direct-upload__filename">' +
|
||||
file.name +
|
||||
'</span>\n</div>\n'
|
||||
);
|
||||
});
|
||||
|
||||
addEventListener('direct-upload:start', event => {
|
||||
const id = event.detail.id,
|
||||
element = document.getElementById('direct-upload-' + id);
|
||||
|
||||
element.classList.remove('direct-upload--pending');
|
||||
});
|
||||
|
||||
addEventListener('direct-upload:progress', event => {
|
||||
const id = event.detail.id,
|
||||
progress = event.detail.progress,
|
||||
progressElement = document.getElementById('direct-upload-progress-' + id);
|
||||
|
||||
progressElement.style.width = `${progress} %`;
|
||||
});
|
||||
|
||||
addEventListener('direct-upload:error', event => {
|
||||
event.preventDefault();
|
||||
const id = event.detail.id,
|
||||
error = event.detail.error,
|
||||
element = document.getElementById('direct-upload-' + id);
|
||||
|
||||
element.classList.add('direct-upload--error');
|
||||
element.setAttribute('title', error);
|
||||
});
|
||||
|
||||
addEventListener('direct-upload:end', event => {
|
||||
const id = event.detail.id,
|
||||
element = document.getElementById('direct-upload-' + id);
|
||||
|
||||
element.classList.add('direct-upload--complete');
|
||||
});
|
||||
|
||||
addEventListener('turbolinks:load', () => {
|
||||
const submitButtons = document.querySelectorAll(
|
||||
'form button[type=submit][data-action]'
|
||||
);
|
||||
const hiddenInput = document.querySelector(
|
||||
'form input[type=hidden][name=submit_action]'
|
||||
);
|
||||
|
||||
for (let button of submitButtons) {
|
||||
button.addEventListener('click', () => {
|
||||
// Active Storage will intercept the form.submit event to upload
|
||||
// the attached files, and then fire the submit action again – but forgetting
|
||||
// which button was clicked. So we manually set the type of action that trigerred
|
||||
// the form submission.
|
||||
const action = button.getAttribute('data-action');
|
||||
hiddenInput.value = action;
|
||||
// Some form fields are marked as mandatory, but when saving a draft we don't want them
|
||||
// to be enforced by the browser.
|
||||
if (action === 'submit') {
|
||||
button.form.removeAttribute('novalidate');
|
||||
} else {
|
||||
button.form.setAttribute('novalidate', 'novalidate');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
26
app/javascript/shared/rails-ujs-fix.js
Normal file
26
app/javascript/shared/rails-ujs-fix.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import Rails from 'rails-ujs';
|
||||
import jQuery from 'jquery';
|
||||
|
||||
// We use `jQuery.active` in our capybara suit to wait for ajax requests.
|
||||
// Newer jQuery-less version of rails-ujs is breaking it.
|
||||
// We have to set `ajax:complete` listener on the same element as the one
|
||||
// we catch ajax:send on as by the end of the request
|
||||
// the old element may be removed from DOM.
|
||||
Rails.delegate(document, '[data-remote]', 'ajax:send', ({ target }) => {
|
||||
let callback = () => {
|
||||
jQuery.active--;
|
||||
target.removeEventListener('ajax:complete', callback);
|
||||
};
|
||||
target.addEventListener('ajax:complete', callback);
|
||||
jQuery.active++;
|
||||
});
|
||||
|
||||
// `smart_listing` gem is overriding `$.rails.href` method. When using newer
|
||||
// jQuery-less version of rails-ujs it breaks.
|
||||
// https://github.com/Sology/smart_listing/blob/master/app/assets/javascripts/smart_listing.coffee.erb#L9
|
||||
addEventListener('load', () => {
|
||||
const { href } = $.rails;
|
||||
$.rails.href = function(element) {
|
||||
return element.href || href(element);
|
||||
};
|
||||
});
|
|
@ -20,6 +20,10 @@ class Champ < ApplicationRecord
|
|||
mandatory? && value.blank?
|
||||
end
|
||||
|
||||
def search_terms
|
||||
[ to_s ]
|
||||
end
|
||||
|
||||
def to_s
|
||||
if value.present?
|
||||
string_value
|
||||
|
|
|
@ -1,2 +1,7 @@
|
|||
class Champs::CheckboxChamp < Champ
|
||||
def search_terms
|
||||
if value == 'on'
|
||||
[ libelle ]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
class Champs::DateChamp < Champ
|
||||
before_save :format_before_save
|
||||
|
||||
def search_terms
|
||||
# Text search is pretty useless for dates so we’re not including these champs
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def format_before_save
|
||||
|
|
|
@ -9,6 +9,10 @@ class Champs::DatetimeChamp < Champ
|
|||
same_date?(num, '%M')
|
||||
end
|
||||
|
||||
def search_terms
|
||||
# Text search is pretty useless for datetimes so we’re not including these champs
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def same_date?(num, compare)
|
||||
|
|
|
@ -1,2 +1,7 @@
|
|||
class Champs::EngagementChamp < Champs::CheckboxChamp
|
||||
def search_terms
|
||||
if value == 'on'
|
||||
[ libelle ]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
class Champs::ExplicationChamp < Champs::TextChamp
|
||||
def search_terms
|
||||
# The user cannot enter any information here so it doesn’t make much sense to search
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
class Champs::HeaderSectionChamp < Champ
|
||||
def search_terms
|
||||
# The user cannot enter any information here so it doesn’t make much sense to search
|
||||
end
|
||||
end
|
||||
|
|
|
@ -37,6 +37,10 @@ class Champs::LinkedDropDownListChamp < Champ
|
|||
mandatory? && (primary_value.blank? || secondary_value.blank?)
|
||||
end
|
||||
|
||||
def search_terms
|
||||
[ primary_value, secondary_value ]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def string_value
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
class Champs::MultipleDropDownListChamp < Champ
|
||||
before_save :format_before_save
|
||||
|
||||
def search_terms
|
||||
drop_down_list.selected_options_without_decorator(self)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def format_before_save
|
||||
|
|
|
@ -18,6 +18,10 @@ class Champs::PieceJustificativeChamp < Champ
|
|||
"image/jpeg"
|
||||
]
|
||||
|
||||
def search_terms
|
||||
# We don’t know how to search inside documents yet
|
||||
end
|
||||
|
||||
def mandatory_and_blank?
|
||||
mandatory? && !piece_justificative_file.attached?
|
||||
end
|
||||
|
|
|
@ -39,4 +39,8 @@ class Champs::SiretChamp < Champ
|
|||
|
||||
belongs_to :etablissement, dependent: :destroy
|
||||
accepts_nested_attributes_for :etablissement, allow_destroy: true, update_only: true
|
||||
|
||||
def search_terms
|
||||
etablissement.present? ? etablissement.search_terms : [ value ]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
class Champs::YesNoChamp < Champs::CheckboxChamp
|
||||
def search_terms
|
||||
if value == 'true'
|
||||
[ libelle ]
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def value_for_export
|
||||
|
|
|
@ -14,7 +14,13 @@ class Commentaire < ApplicationRecord
|
|||
after_create :notify
|
||||
|
||||
def header
|
||||
"#{email}, #{I18n.l(created_at.localtime, format: '%d %b %Y %H:%M')}"
|
||||
"#{sender}, #{I18n.l(created_at.localtime, format: '%d %b %Y %H:%M')}"
|
||||
end
|
||||
|
||||
def sender
|
||||
if email.present?
|
||||
email.split('@').first
|
||||
end
|
||||
end
|
||||
|
||||
def file_url
|
||||
|
|
|
@ -69,6 +69,7 @@ class Dossier < ApplicationRecord
|
|||
delegate :france_connect_information, to: :user
|
||||
|
||||
before_validation :update_state_dates, if: -> { state_changed? }
|
||||
before_save :update_search_terms
|
||||
|
||||
after_save :build_default_champs, if: Proc.new { saved_change_to_procedure_id? }
|
||||
after_save :build_default_individual, if: Proc.new { procedure.for_individual? }
|
||||
|
@ -78,6 +79,19 @@ class Dossier < ApplicationRecord
|
|||
|
||||
validates :user, presence: true
|
||||
|
||||
def update_search_terms
|
||||
self.search_terms = [
|
||||
user&.email,
|
||||
france_connect_information&.given_name,
|
||||
france_connect_information&.family_name,
|
||||
*ordered_champs.flat_map(&:search_terms),
|
||||
*etablissement&.search_terms,
|
||||
individual&.nom,
|
||||
individual&.prenom
|
||||
].compact.join(' ')
|
||||
self.private_search_terms = ordered_champs_private.flat_map(&:search_terms).compact.join(' ')
|
||||
end
|
||||
|
||||
def was_piece_justificative_uploaded_for_type_id?(type_id)
|
||||
pieces_justificatives.where(type_de_piece_justificative_id: type_id).count > 0
|
||||
end
|
||||
|
|
|
@ -11,6 +11,30 @@ class Etablissement < ApplicationRecord
|
|||
|
||||
validate :validate_signature
|
||||
|
||||
def search_terms
|
||||
[
|
||||
entreprise_siren,
|
||||
entreprise_numero_tva_intracommunautaire,
|
||||
entreprise_forme_juridique,
|
||||
entreprise_forme_juridique_code,
|
||||
entreprise_nom_commercial,
|
||||
entreprise_raison_sociale,
|
||||
entreprise_siret_siege_social,
|
||||
entreprise_nom,
|
||||
entreprise_prenom,
|
||||
association_rna,
|
||||
association_titre,
|
||||
association_objet,
|
||||
siret,
|
||||
naf,
|
||||
libelle_naf,
|
||||
adresse,
|
||||
code_postal,
|
||||
localite,
|
||||
code_insee_localite
|
||||
]
|
||||
end
|
||||
|
||||
def siren
|
||||
entreprise_siren
|
||||
end
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
<% else %>
|
||||
var html = "<%= escape_javascript(render partial: 'shared/champs/siret/etablissement', locals: { position: @champ.order_place, etablissement: @etablissement }) %>";
|
||||
<% end %>
|
||||
$("#etablissement-for-<%= @champ.id %>").html(html);
|
||||
document.querySelector("#etablissement-for-<%= @champ.id %>").innerHTML = html;
|
||||
})();
|
||||
|
|
|
@ -5,22 +5,3 @@
|
|||
%td= feature.title
|
||||
%td
|
||||
= check_box_tag "enable-feature", "enable", field.data[feature.name], data: { url: enable_feature_manager_administrateur_path(field.resource.id), key: feature.key }
|
||||
|
||||
:javascript
|
||||
window.onload = function() {
|
||||
$('#features input[type=checkbox]').on('change', function(evt) {
|
||||
let url = $(evt.target).data('url');
|
||||
let key = $(evt.target).data('key');
|
||||
let features = {};
|
||||
features[key] = $(evt.target).prop('checked');
|
||||
$.ajax(url, {
|
||||
method: 'put',
|
||||
contentType: 'application/json',
|
||||
dataType: 'json',
|
||||
data: JSON.stringify({
|
||||
features: features
|
||||
})
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -10,11 +10,14 @@
|
|||
= favicon_link_tag(image_url("favicons/32x32.png"), type: "image/png", sizes: "32x32")
|
||||
= favicon_link_tag(image_url("favicons/96x96.png"), type: "image/png", sizes: "96x96")
|
||||
|
||||
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => "reload"
|
||||
= stylesheet_link_tag 'print', media: 'print', 'data-turbolinks-track' => "reload"
|
||||
= javascript_include_tag 'application', 'data-turbolinks-track' => true
|
||||
|
||||
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': "reload"
|
||||
= stylesheet_link_tag 'print', media: 'print', 'data-turbolinks-track': "reload"
|
||||
= javascript_pack_tag 'application-old', defer: true, 'data-turbolinks-track': 'reload'
|
||||
= javascript_include_tag 'application', defer: true, 'data-turbolinks-track': 'reload'
|
||||
= csrf_meta_tags
|
||||
|
||||
:javascript
|
||||
DATA = [];
|
||||
%body
|
||||
= render partial: 'layouts/support_navigator_banner'
|
||||
= render partial: 'layouts/pre_maintenance'
|
||||
|
@ -22,14 +25,8 @@
|
|||
#beta
|
||||
Env Test
|
||||
|
||||
- if Rails.env == 'test'
|
||||
%script{ type: 'text/javascript' }
|
||||
(typeof jQuery !== 'undefined') && (jQuery.fx.off = true);
|
||||
|
||||
|
||||
= render partial: 'layouts/ie_lt_10'
|
||||
|
||||
|
||||
#wrap
|
||||
.row
|
||||
#header.navbar
|
||||
|
|
|
@ -10,13 +10,6 @@
|
|||
.badge.progress-bar-info
|
||||
= @facade.dossier.invites.count
|
||||
.dropdown-menu.dropdown-menu-right.dropdown-pannel
|
||||
%h4= t('dynamics.dossiers.followers.title')
|
||||
%ul
|
||||
- if @facade.followers.present?
|
||||
- @facade.followers.each do |follower|
|
||||
%li= follower.email
|
||||
- else
|
||||
= t('dynamics.dossiers.followers.empty')
|
||||
%h4= t('dynamics.dossiers.invites.title')
|
||||
%ul
|
||||
- if @facade.invites.present?
|
||||
|
|
|
@ -14,12 +14,15 @@
|
|||
= favicon_link_tag(image_url("favicons/32x32.png"), type: "image/png", sizes: "32x32")
|
||||
= favicon_link_tag(image_url("favicons/96x96.png"), type: "image/png", sizes: "96x96")
|
||||
|
||||
= stylesheet_link_tag "new_design/new_application", media: "all", "data-turbolinks-track": "reload"
|
||||
= stylesheet_link_tag "new_design/print", media: "print", "data-turbolinks-track": true
|
||||
= javascript_pack_tag 'application', defer: true, 'data-turbolinks-track': 'reload'
|
||||
= stylesheet_link_tag 'new_design/new_application', media: 'all', 'data-turbolinks-track': 'reload'
|
||||
= stylesheet_link_tag 'new_design/print', media: 'print', 'data-turbolinks-track': 'reload'
|
||||
|
||||
- if Rails.env.development?
|
||||
= stylesheet_link_tag :xray
|
||||
|
||||
:javascript
|
||||
DATA = [];
|
||||
%body
|
||||
.page-wrapper
|
||||
= render partial: "layouts/support_navigator_banner"
|
||||
|
@ -37,12 +40,7 @@
|
|||
= content_for(:footer)
|
||||
= render partial: "layouts/mailjet_newsletter"
|
||||
|
||||
= javascript_include_tag "new_design/application", "data-turbolinks-eval": false
|
||||
|
||||
- if Rails.env.development?
|
||||
= javascript_include_tag :xray
|
||||
|
||||
= yield :charts_js
|
||||
- if Rails.env == "test"
|
||||
%script{ type: "text/javascript" }
|
||||
(typeof jQuery !== "undefined") && (jQuery.fx.off = true);
|
||||
|
|
23
app/views/manager/application/_javascript.html.erb
Normal file
23
app/views/manager/application/_javascript.html.erb
Normal file
|
@ -0,0 +1,23 @@
|
|||
<%#
|
||||
# Javascript Partial
|
||||
|
||||
This partial imports the necessary javascript on each page.
|
||||
By default, it includes the application JS,
|
||||
but each page can define additional JS sources
|
||||
by providing a `content_for(:javascript)` block.
|
||||
%>
|
||||
|
||||
<% Administrate::Engine.javascripts.each do |js_path| %>
|
||||
<%= javascript_include_tag js_path %>
|
||||
<% end %>
|
||||
|
||||
<%= javascript_pack_tag 'manager' %>
|
||||
|
||||
<%= yield :javascript %>
|
||||
|
||||
<% if Rails.env.test? %>
|
||||
<%= javascript_tag do %>
|
||||
$.fx.off = true;
|
||||
$.ajaxSetup({ async: false });
|
||||
<% end %>
|
||||
<% end %>
|
|
@ -17,7 +17,11 @@
|
|||
= "Parcelle n° #{p.numero} - Feuille #{p.code_arr} #{p.section} #{p.feuille}"
|
||||
|
||||
:javascript
|
||||
var getPositionUrl = "#{position_gestionnaire_dossier_path(dossier.procedure, dossier)}";
|
||||
var dossierJsonLatLngs = #{raw(ensure_safe_json(dossier.json_latlngs))};
|
||||
var dossierCadastres = #{raw(ensure_safe_json(dossier.cadastres.to_json))};
|
||||
var dossierQuartiersPrioritaires = #{raw(ensure_safe_json(dossier.quartier_prioritaires.to_json))};
|
||||
DATA.push({
|
||||
carto: {
|
||||
getPositionUrl: "#{position_gestionnaire_dossier_path(dossier.procedure, dossier)}",
|
||||
dossierJsonLatLngs: #{raw(ensure_safe_json(dossier.json_latlngs))},
|
||||
dossierCadastres: #{raw(ensure_safe_json(dossier.cadastres.to_json))},
|
||||
dossierQuartiersPrioritaires: #{raw(ensure_safe_json(dossier.quartier_prioritaires.to_json))}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
= message
|
||||
.mandatory= message
|
||||
- if etablissement.present?
|
||||
- champ_attributes = etablissement.champ.private? ? 'champs_private_attributes' : 'champs_attributes'
|
||||
= fields_for "dossier[#{champ_attributes}][#{position}][etablissement_attributes]", etablissement do |form|
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.etablissement-titre
|
||||
.explication
|
||||
= raison_sociale_or_name(etablissement)
|
||||
= etablissement.entreprise_forme_juridique
|
||||
- if etablissement.entreprise_capital_social.present?
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
%script{ type: 'text/javascript' }
|
||||
= "var dossier_id =#{dossier.id}"
|
||||
$(document).on('turbolinks:load', initCarto);
|
||||
:javascript
|
||||
var dossier_id = #{dossier.id};
|
||||
addEventListener('turbolinks:load', function() {
|
||||
initCarto();
|
||||
});
|
||||
|
|
15
bin/webpack
Executable file
15
bin/webpack
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
|
||||
ENV["NODE_ENV"] ||= ENV["NODE_ENV"] || "development"
|
||||
|
||||
require "pathname"
|
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require "rubygems"
|
||||
require "bundler/setup"
|
||||
|
||||
require "webpacker"
|
||||
require "webpacker/webpack_runner"
|
||||
Webpacker::WebpackRunner.run(ARGV)
|
15
bin/webpack-dev-server
Executable file
15
bin/webpack-dev-server
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
|
||||
ENV["NODE_ENV"] ||= ENV["NODE_ENV"] || "development"
|
||||
|
||||
require "pathname"
|
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require "rubygems"
|
||||
require "bundler/setup"
|
||||
|
||||
require "webpacker"
|
||||
require "webpacker/dev_server_runner"
|
||||
Webpacker::DevServerRunner.run(ARGV)
|
|
@ -46,7 +46,6 @@ set :rails_env, ENV["to"]
|
|||
# They will be linked in the 'deploy:link_shared_paths' step.
|
||||
set :shared_paths, [
|
||||
'log',
|
||||
'bin',
|
||||
'uploads',
|
||||
'tmp/pids',
|
||||
'tmp/cache',
|
||||
|
@ -123,6 +122,16 @@ task :setup => :environment do
|
|||
queue %[echo "-----> Be sure to edit 'shared/environments/staging.rb'."]
|
||||
end
|
||||
|
||||
namespace :yarn do
|
||||
desc "Install package dependencies using yarn."
|
||||
task :install do
|
||||
queue %{
|
||||
echo "-----> Installing package dependencies using yarn"
|
||||
#{echo_cmd %[yarn install --non-interactive]}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
desc "Deploys the current version to the server."
|
||||
task :deploy => :environment do
|
||||
queue 'export PATH=$PATH:/usr/local/rbenv/bin:/usr/local/rbenv/shims'
|
||||
|
@ -133,6 +142,7 @@ task :deploy => :environment do
|
|||
invoke :'git:clone'
|
||||
invoke :'deploy:link_shared_paths'
|
||||
invoke :'bundle:install'
|
||||
invoke :'yarn:install'
|
||||
invoke :'rails:db_migrate'
|
||||
invoke :'rails:assets_precompile:force'
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# Verifies that versions and hashed value of the package contents in the project's package.json
|
||||
config.webpacker.check_yarn_integrity = true
|
||||
|
||||
# In the development environment your application's code is reloaded on
|
||||
# every request. This slows down response time but is perfect for development
|
||||
# since you don't have to restart the web server when you make code changes.
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# Verifies that versions and hashed value of the package contents in the project's package.json
|
||||
config.webpacker.check_yarn_integrity = false
|
||||
|
||||
# Code is not reloaded between requests.
|
||||
config.cache_classes = true
|
||||
|
||||
|
|
|
@ -7,9 +7,6 @@ fr:
|
|||
dossiers:
|
||||
depositaite: "Dépositaire"
|
||||
numéro: 'Dossier nº '
|
||||
followers:
|
||||
title: "Personnes suivant l'activité de ce dossier"
|
||||
empty: "Aucune personne ne suit ce dossier"
|
||||
invites:
|
||||
title: "Personnes invitées à voir ce dossier"
|
||||
empty: "Aucune personne invitée"
|
||||
|
|
5
config/webpack/development.js
Normal file
5
config/webpack/development.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
|
||||
|
||||
const environment = require('./environment')
|
||||
|
||||
module.exports = environment.toWebpackConfig()
|
9
config/webpack/environment.js
Normal file
9
config/webpack/environment.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
const { environment } = require('@rails/webpacker')
|
||||
|
||||
const webpack = require('webpack');
|
||||
environment.plugins.append('Provide', new webpack.ProvidePlugin({
|
||||
$: 'jquery',
|
||||
jQuery: 'jquery'
|
||||
}));
|
||||
|
||||
module.exports = environment
|
5
config/webpack/production.js
Normal file
5
config/webpack/production.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
process.env.NODE_ENV = process.env.NODE_ENV || 'production'
|
||||
|
||||
const environment = require('./environment')
|
||||
|
||||
module.exports = environment.toWebpackConfig()
|
5
config/webpack/test.js
Normal file
5
config/webpack/test.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
|
||||
|
||||
const environment = require('./environment')
|
||||
|
||||
module.exports = environment.toWebpackConfig()
|
77
config/webpacker.yml
Normal file
77
config/webpacker.yml
Normal file
|
@ -0,0 +1,77 @@
|
|||
# Note: You must restart bin/webpack-dev-server for changes to take effect
|
||||
|
||||
default: &default
|
||||
source_path: app/javascript
|
||||
source_entry_path: packs
|
||||
public_output_path: packs
|
||||
cache_path: tmp/cache/webpacker
|
||||
|
||||
# Additional paths webpack should lookup modules
|
||||
# ['app/assets', 'engine/foo/app/assets']
|
||||
resolved_paths: []
|
||||
|
||||
# Reload manifest.json on all requests so we reload latest compiled packs
|
||||
cache_manifest: false
|
||||
|
||||
extensions:
|
||||
- .js
|
||||
- .sass
|
||||
- .scss
|
||||
- .css
|
||||
- .module.sass
|
||||
- .module.scss
|
||||
- .module.css
|
||||
- .png
|
||||
- .svg
|
||||
- .gif
|
||||
- .jpeg
|
||||
- .jpg
|
||||
|
||||
development:
|
||||
<<: *default
|
||||
compile: true
|
||||
|
||||
# Reference: https://webpack.js.org/configuration/dev-server/
|
||||
dev_server:
|
||||
https: false
|
||||
host: localhost
|
||||
port: 3035
|
||||
public: localhost:3035
|
||||
hmr: false
|
||||
# Inline should be set to true if using HMR
|
||||
inline: true
|
||||
overlay: true
|
||||
compress: true
|
||||
disable_host_check: true
|
||||
use_local_ip: false
|
||||
quiet: false
|
||||
headers:
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
watch_options:
|
||||
ignored: /node_modules/
|
||||
|
||||
|
||||
test:
|
||||
<<: *default
|
||||
compile: true
|
||||
|
||||
# Compile test packs to a separate directory
|
||||
public_output_path: packs-test
|
||||
|
||||
staging:
|
||||
<<: *default
|
||||
|
||||
# Production depends on precompilation of packs prior to booting for performance.
|
||||
compile: false
|
||||
|
||||
# Cache manifest.json for performance
|
||||
cache_manifest: true
|
||||
|
||||
production:
|
||||
<<: *default
|
||||
|
||||
# Production depends on precompilation of packs prior to booting for performance.
|
||||
compile: false
|
||||
|
||||
# Cache manifest.json for performance
|
||||
cache_manifest: true
|
|
@ -0,0 +1,8 @@
|
|||
class AddSearchTermsToDossiers < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :dossiers, :search_terms, :text
|
||||
add_column :dossiers, :private_search_terms, :text
|
||||
add_index :dossiers, "to_tsvector('french', search_terms)", using: :gin, name: 'index_dossiers_on_search_terms'
|
||||
add_index :dossiers, "to_tsvector('french', search_terms || private_search_terms)", using: :gin, name: 'index_dossiers_on_search_terms_private_search_terms'
|
||||
end
|
||||
end
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2018_07_19_125038) do
|
||||
ActiveRecord::Schema.define(version: 2018_07_24_153247) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -244,6 +244,10 @@ ActiveRecord::Schema.define(version: 2018_07_19_125038) do
|
|||
t.datetime "processed_at"
|
||||
t.text "motivation"
|
||||
t.datetime "hidden_at"
|
||||
t.text "search_terms"
|
||||
t.text "private_search_terms"
|
||||
t.index "to_tsvector('french'::regconfig, (search_terms || private_search_terms))", name: "index_dossiers_on_search_terms_private_search_terms", using: :gin
|
||||
t.index "to_tsvector('french'::regconfig, search_terms)", name: "index_dossiers_on_search_terms", using: :gin
|
||||
t.index ["hidden_at"], name: "index_dossiers_on_hidden_at"
|
||||
t.index ["procedure_id"], name: "index_dossiers_on_procedure_id"
|
||||
t.index ["user_id"], name: "index_dossiers_on_user_id"
|
||||
|
|
17
lib/tasks/2018_07_24_refresh_search_terms.rake
Normal file
17
lib/tasks/2018_07_24_refresh_search_terms.rake
Normal file
|
@ -0,0 +1,17 @@
|
|||
require Rails.root.join("lib", "tasks", "task_helper")
|
||||
|
||||
namespace :'2018_07_24_refresh_search_terms' do
|
||||
task run: :environment do
|
||||
# For dossiers belonging to an archived procedure, the check for the `build_default_individual` `after_save` callback fails.
|
||||
# So, we filter those out by joining with `procedure`, whose default scope excludes archived procedures.
|
||||
ds = Dossier.joins(:procedure)
|
||||
total_count = ds.count
|
||||
one_percent = total_count / 100
|
||||
Dossier.joins(:procedure).find_each(batch_size: 100).with_index do |d, i|
|
||||
if i % one_percent == 0
|
||||
rake_puts("#{i}/#{total_count} (#{i / one_percent}%)")
|
||||
end
|
||||
d.save(touch: false)
|
||||
end
|
||||
end
|
||||
end
|
28
package.json
Normal file
28
package.json
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"@rails/webpacker": "4.0.0-pre.2",
|
||||
"activestorage": "^5.2.0",
|
||||
"bloodhound-js": "^1.2.2",
|
||||
"chartkick": "^2.3.6",
|
||||
"highcharts": "^6.1.1",
|
||||
"jquery": "^3.3.1",
|
||||
"leaflet": "^1.3.1",
|
||||
"rails-ujs": "^5.2.0",
|
||||
"select2": "^4.0.6-rc.1",
|
||||
"turbolinks": "^5.1.1",
|
||||
"typeahead.js": "^0.11.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^5.2.0",
|
||||
"eslint-config-prettier": "^2.9.0",
|
||||
"eslint-plugin-prettier": "^2.6.2",
|
||||
"prettier": "^1.13.7",
|
||||
"webpack-dev-server": "^3.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
"lint:js": "eslint ./app/javascript"
|
||||
},
|
||||
"engines": {
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
}
|
|
@ -227,6 +227,14 @@ describe NewGestionnaire::DossiersController, type: :controller do
|
|||
|
||||
is_expected.to redirect_to redirect_to gestionnaire_dossier_path(procedure, dossier)
|
||||
end
|
||||
|
||||
context 'and the dossier has already an attestation' do
|
||||
it 'should not crash' do
|
||||
dossier.attestation = Attestation.new
|
||||
dossier.save
|
||||
expect(subject).to redirect_to redirect_to gestionnaire_dossier_path(procedure, dossier)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the attestation template uses the motivation field' do
|
||||
|
|
|
@ -66,7 +66,7 @@ feature 'As a User I wanna create a dossier' do
|
|||
login_as user, scope: :user
|
||||
visit commencer_path(procedure_path: procedure_with_siret.path)
|
||||
expect(page).to have_current_path(users_dossier_path(procedure_with_siret.dossiers.last.id.to_s))
|
||||
fill_in 'dossier-siret', with: siret
|
||||
|
||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*token=/)
|
||||
.to_return(status: 200, body: File.read('spec/support/files/etablissement.json'))
|
||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=/)
|
||||
|
@ -75,8 +75,11 @@ feature 'As a User I wanna create a dossier' do
|
|||
.to_return(status: 200, body: File.read('spec/support/files/exercices.json'))
|
||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\/#{siret}?.*token=/)
|
||||
.to_return(status: 404, body: '')
|
||||
|
||||
page.find_by_id('dossier-siret').set siret
|
||||
page.find_by_id('submit-siret').click
|
||||
wait_for_ajax
|
||||
|
||||
expect(page).to have_css('#recap-info-entreprise')
|
||||
find(:css, "#dossier_autorisation_donnees[value='1']").set(true)
|
||||
page.find_by_id('etape_suivante').click
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue