commit
a28806ddbb
32 changed files with 1997 additions and 1372 deletions
|
@ -1,5 +1,6 @@
|
||||||
require:
|
require:
|
||||||
- rubocop/rspec/focused
|
- rubocop/rspec/focused
|
||||||
|
- ./lib/cops/unscoped.rb
|
||||||
|
|
||||||
AllCops:
|
AllCops:
|
||||||
Exclude:
|
Exclude:
|
||||||
|
|
|
@ -12,7 +12,7 @@ module Manager
|
||||||
Procedure
|
Procedure
|
||||||
else
|
else
|
||||||
# … but allow them to be searched and displayed.
|
# … but allow them to be searched and displayed.
|
||||||
Procedure.unscope(:where)
|
Procedure.with_hidden
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ module Users
|
||||||
def show
|
def show
|
||||||
if dossier.brouillon?
|
if dossier.brouillon?
|
||||||
redirect_to brouillon_dossier_path(dossier)
|
redirect_to brouillon_dossier_path(dossier)
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@dossier = dossier
|
@dossier = dossier
|
||||||
|
|
|
@ -18,6 +18,12 @@ type Avis {
|
||||||
reponse: String
|
reponse: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Represents non-fractional signed whole numeric values. Since the value may
|
||||||
|
exceed the size of a 32-bit integer, it's encoded as a string.
|
||||||
|
"""
|
||||||
|
scalar BigInt
|
||||||
|
|
||||||
type CarteChamp implements Champ {
|
type CarteChamp implements Champ {
|
||||||
geoAreas: [GeoArea!]!
|
geoAreas: [GeoArea!]!
|
||||||
id: ID!
|
id: ID!
|
||||||
|
@ -648,7 +654,7 @@ enum DossierState {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Entreprise {
|
type Entreprise {
|
||||||
capitalSocial: Int!
|
capitalSocial: BigInt!
|
||||||
codeEffectifEntreprise: String!
|
codeEffectifEntreprise: String!
|
||||||
dateCreation: ISO8601Date!
|
dateCreation: ISO8601Date!
|
||||||
formeJuridique: String!
|
formeJuridique: String!
|
||||||
|
@ -730,7 +736,7 @@ type IntegerNumberChamp implements Champ {
|
||||||
La valeur du champ sous forme texte.
|
La valeur du champ sous forme texte.
|
||||||
"""
|
"""
|
||||||
stringValue: String
|
stringValue: String
|
||||||
value: Int
|
value: BigInt
|
||||||
}
|
}
|
||||||
|
|
||||||
type LinkedDropDownListChamp implements Champ {
|
type LinkedDropDownListChamp implements Champ {
|
||||||
|
|
|
@ -2,7 +2,7 @@ module Types::Champs
|
||||||
class IntegerNumberChampType < Types::BaseObject
|
class IntegerNumberChampType < Types::BaseObject
|
||||||
implements Types::ChampType
|
implements Types::ChampType
|
||||||
|
|
||||||
field :value, Int, null: true
|
field :value, GraphQL::Types::BigInt, null: true
|
||||||
|
|
||||||
def value
|
def value
|
||||||
if object.value.present?
|
if object.value.present?
|
||||||
|
|
|
@ -2,7 +2,7 @@ module Types
|
||||||
class PersonneMoraleType < Types::BaseObject
|
class PersonneMoraleType < Types::BaseObject
|
||||||
class EntrepriseType < Types::BaseObject
|
class EntrepriseType < Types::BaseObject
|
||||||
field :siren, String, null: false
|
field :siren, String, null: false
|
||||||
field :capital_social, Int, null: false
|
field :capital_social, GraphQL::Types::BigInt, null: false
|
||||||
field :numero_tva_intracommunautaire, String, null: false
|
field :numero_tva_intracommunautaire, String, null: false
|
||||||
field :forme_juridique, String, null: false
|
field :forme_juridique, String, null: false
|
||||||
field :forme_juridique_code, String, null: false
|
field :forme_juridique_code, String, null: false
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core';
|
import { library } from '@fortawesome/fontawesome-svg-core';
|
||||||
import {
|
|
||||||
faArrowCircleDown,
|
import { faArrowCircleDown } from '@fortawesome/free-solid-svg-icons/faArrowCircleDown';
|
||||||
faArrowDown,
|
import { faArrowDown } from '@fortawesome/free-solid-svg-icons/faArrowDown';
|
||||||
faArrowsAltV,
|
import { faArrowsAltV } from '@fortawesome/free-solid-svg-icons/faArrowsAltV';
|
||||||
faArrowUp,
|
import { faArrowUp } from '@fortawesome/free-solid-svg-icons/faArrowUp';
|
||||||
faPlus,
|
import { faPlus } from '@fortawesome/free-solid-svg-icons/faPlus';
|
||||||
faTrash
|
import { faTrash } from '@fortawesome/free-solid-svg-icons/faTrash';
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
|
||||||
|
|
||||||
import Flash from './Flash';
|
import Flash from './Flash';
|
||||||
import OperationsQueue from './OperationsQueue';
|
import OperationsQueue from './OperationsQueue';
|
||||||
|
|
|
@ -1,47 +1,38 @@
|
||||||
import { initMap, drawPolygons, addFreeDrawEvents } from '../../shared/carte';
|
|
||||||
|
|
||||||
async function initialize() {
|
async function initialize() {
|
||||||
const elements = document.querySelectorAll('.carte');
|
const elements = document.querySelectorAll('.carte');
|
||||||
|
|
||||||
if (elements.length) {
|
if (elements.length) {
|
||||||
const editable = [...elements].find(element =>
|
|
||||||
element.classList.contains('edit')
|
|
||||||
);
|
|
||||||
await loadLeaflet(editable);
|
|
||||||
|
|
||||||
for (let element of elements) {
|
for (let element of elements) {
|
||||||
diplayMap(element, null, true);
|
loadAndDrawMap(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We load leaflet dynamically, ramda and freedraw and assign them to globals.
|
async function loadAndDrawMap(element) {
|
||||||
// Latest freedraw version build needs globals.
|
const data = JSON.parse(element.dataset.geo);
|
||||||
async function loadLeaflet(editable) {
|
const editable = element.classList.contains('edit');
|
||||||
window.L = await import('leaflet').then(({ default: L }) => L);
|
|
||||||
|
|
||||||
if (editable) {
|
if (editable) {
|
||||||
window.R = await import('ramda').then(({ default: R }) => R);
|
const { drawEditableMap } = await import('../../shared/carte-editor');
|
||||||
await import('leaflet-freedraw/dist/leaflet-freedraw.web.js');
|
|
||||||
|
drawEditableMap(element, data);
|
||||||
|
} else {
|
||||||
|
const { drawMap } = await import('../../shared/carte');
|
||||||
|
|
||||||
|
drawMap(element, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function diplayMap(element, data, initial = false) {
|
async function loadAndRedrawMap(element, data) {
|
||||||
data = data || JSON.parse(element.dataset.geo);
|
const { redrawMap } = await import('../../shared/carte-editor');
|
||||||
const editable = element.classList.contains('edit');
|
|
||||||
const map = initMap(element, data.position, editable);
|
|
||||||
|
|
||||||
drawPolygons(map, data, { initial, editable });
|
redrawMap(element, data);
|
||||||
|
|
||||||
if (initial && editable) {
|
|
||||||
const input = element.parentElement.querySelector('input[data-remote]');
|
|
||||||
addFreeDrawEvents(map, input);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addEventListener('turbolinks:load', initialize);
|
addEventListener('turbolinks:load', initialize);
|
||||||
|
|
||||||
addEventListener('carte:update', ({ detail: { selector, data } }) => {
|
addEventListener('carte:update', ({ detail: { selector, data } }) => {
|
||||||
const element = document.querySelector(selector);
|
const element = document.querySelector(selector);
|
||||||
diplayMap(element, data);
|
|
||||||
|
loadAndRedrawMap(element, data);
|
||||||
});
|
});
|
||||||
|
|
214
app/javascript/shared/carte-editor.js
Normal file
214
app/javascript/shared/carte-editor.js
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
import L from 'leaflet';
|
||||||
|
import FreeDraw from 'leaflet-freedraw';
|
||||||
|
import { fire, delegate } from '@utils';
|
||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
import polygonArea from './polygon_area';
|
||||||
|
|
||||||
|
const MAPS = new WeakMap();
|
||||||
|
|
||||||
|
export function drawEditableMap(element, data) {
|
||||||
|
const map = initMap(element, data);
|
||||||
|
|
||||||
|
drawCadastre(map, data);
|
||||||
|
drawQuartiersPrioritaires(map, data);
|
||||||
|
drawParcellesAgricoles(map, data);
|
||||||
|
|
||||||
|
drawUserSelectionEditor(map, data);
|
||||||
|
|
||||||
|
const input = element.parentElement.querySelector('input[data-remote]');
|
||||||
|
addFreeDrawEvents(map, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function redrawMap(element, data) {
|
||||||
|
const map = initMap(element, data);
|
||||||
|
|
||||||
|
clearLayers(map);
|
||||||
|
|
||||||
|
drawCadastre(map, data);
|
||||||
|
drawQuartiersPrioritaires(map, data);
|
||||||
|
drawParcellesAgricoles(map, data);
|
||||||
|
|
||||||
|
bringToFrontUserSelection(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initMap(element, { position }) {
|
||||||
|
if (MAPS.has(element)) {
|
||||||
|
return MAPS.get(element);
|
||||||
|
} else {
|
||||||
|
const map = L.map(element, {
|
||||||
|
scrollWheelZoom: false
|
||||||
|
}).setView([position.lat, position.lon], 18);
|
||||||
|
|
||||||
|
const loadTilesLayer = process.env.RAILS_ENV != 'test';
|
||||||
|
if (loadTilesLayer) {
|
||||||
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
|
attribution:
|
||||||
|
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||||
|
}).addTo(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
const freeDraw = new FreeDraw({
|
||||||
|
mode: FreeDraw.NONE,
|
||||||
|
smoothFactor: 4,
|
||||||
|
mergePolygons: false
|
||||||
|
});
|
||||||
|
map.addLayer(freeDraw);
|
||||||
|
map.freeDraw = freeDraw;
|
||||||
|
|
||||||
|
MAPS.set(element, map);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toLatLngs({ coordinates }) {
|
||||||
|
return coordinates.map(polygon =>
|
||||||
|
polygon[0].map(point => L.GeoJSON.coordsToLatLng(point))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawUserSelectionEditor(map, { selection }) {
|
||||||
|
if (selection) {
|
||||||
|
const geoJSON = L.geoJSON(selection);
|
||||||
|
|
||||||
|
for (let polygon of toLatLngs(selection)) {
|
||||||
|
map.freeDraw.create(polygon);
|
||||||
|
}
|
||||||
|
|
||||||
|
map.fitBounds(geoJSON.getBounds());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addFreeDrawEvents(map, selector) {
|
||||||
|
const input = findInput(selector);
|
||||||
|
map.freeDraw.on('markers', ({ latLngs }) => {
|
||||||
|
if (latLngs.length === 0) {
|
||||||
|
input.value = EMPTY_GEO_JSON;
|
||||||
|
} else if (polygonArea(latLngs) < 300000) {
|
||||||
|
input.value = JSON.stringify(latLngs);
|
||||||
|
} else {
|
||||||
|
input.value = ERROR_GEO_JSON;
|
||||||
|
}
|
||||||
|
|
||||||
|
fire(input, 'change');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawCadastre(map, { cadastres }) {
|
||||||
|
drawLayer(map, cadastres, CADASTRE_POLYGON_STYLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawQuartiersPrioritaires(map, { quartiersPrioritaires }) {
|
||||||
|
drawLayer(map, quartiersPrioritaires, QP_POLYGON_STYLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawParcellesAgricoles(map, { parcellesAgricoles }) {
|
||||||
|
drawLayer(map, parcellesAgricoles, RPG_POLYGON_STYLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentMap(element) {
|
||||||
|
if (!element.matches('.carte')) {
|
||||||
|
const closestCarteElement = element.closest('.carte');
|
||||||
|
const closestToolbarElement = element.closest('.toolbar');
|
||||||
|
|
||||||
|
element = closestCarteElement
|
||||||
|
? closestCarteElement
|
||||||
|
: closestToolbarElement.parentElement.querySelector('.carte');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MAPS.has(element)) {
|
||||||
|
return MAPS.get(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const EMPTY_GEO_JSON = '[]';
|
||||||
|
const ERROR_GEO_JSON = '';
|
||||||
|
|
||||||
|
function findInput(selector) {
|
||||||
|
return typeof selector === 'string'
|
||||||
|
? document.querySelector(selector)
|
||||||
|
: selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearLayers(map) {
|
||||||
|
map.eachLayer(layer => {
|
||||||
|
if (layer instanceof L.GeoJSON) {
|
||||||
|
map.removeLayer(layer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function bringToFrontUserSelection(map) {
|
||||||
|
for (let layer of map.freeDraw.all()) {
|
||||||
|
layer.bringToFront();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawLayer(map, data, style) {
|
||||||
|
if (Array.isArray(data) && data.length > 0) {
|
||||||
|
const layer = new L.GeoJSON(undefined, {
|
||||||
|
interactive: false,
|
||||||
|
style
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let { geometry } of data) {
|
||||||
|
layer.addData(geometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
layer.addTo(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const POLYGON_STYLE = {
|
||||||
|
weight: 2,
|
||||||
|
opacity: 0.3,
|
||||||
|
color: 'white',
|
||||||
|
dashArray: '3',
|
||||||
|
fillOpacity: 0.7
|
||||||
|
};
|
||||||
|
|
||||||
|
const CADASTRE_POLYGON_STYLE = Object.assign({}, POLYGON_STYLE, {
|
||||||
|
fillColor: '#8a6d3b'
|
||||||
|
});
|
||||||
|
|
||||||
|
const QP_POLYGON_STYLE = Object.assign({}, POLYGON_STYLE, {
|
||||||
|
fillColor: '#31708f'
|
||||||
|
});
|
||||||
|
|
||||||
|
const RPG_POLYGON_STYLE = Object.assign({}, POLYGON_STYLE, {
|
||||||
|
fillColor: '#31708f'
|
||||||
|
});
|
||||||
|
|
||||||
|
delegate('click', '.carte.edit', event => {
|
||||||
|
const map = getCurrentMap(event.target);
|
||||||
|
|
||||||
|
if (map) {
|
||||||
|
const isPath = event.target.matches('.leaflet-container g path');
|
||||||
|
if (isPath) {
|
||||||
|
setTimeout(() => {
|
||||||
|
map.freeDraw.mode(FreeDraw.EDIT | FreeDraw.DELETE);
|
||||||
|
}, 50);
|
||||||
|
} else {
|
||||||
|
map.freeDraw.mode(FreeDraw.NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
delegate('click', '.toolbar .new-area', event => {
|
||||||
|
event.preventDefault();
|
||||||
|
const map = getCurrentMap(event.target);
|
||||||
|
|
||||||
|
if (map) {
|
||||||
|
map.freeDraw.mode(FreeDraw.CREATE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('select2:select', 'select[data-address]', event => {
|
||||||
|
const map = getCurrentMap(event.target);
|
||||||
|
const { geometry } = event.params.data;
|
||||||
|
|
||||||
|
if (map && geometry && geometry.type === 'Point') {
|
||||||
|
const [lon, lat] = geometry.coordinates;
|
||||||
|
map.setView(new L.LatLng(lat, lon), 14);
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,18 +1,23 @@
|
||||||
/* globals FreeDraw L */
|
import L from 'leaflet';
|
||||||
import { fire, delegate } from '@utils';
|
|
||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
import polygonArea from './polygon_area';
|
|
||||||
|
|
||||||
const MAPS = new WeakMap();
|
const MAPS = new WeakMap();
|
||||||
|
|
||||||
export function initMap(element, position, editable = false) {
|
export function drawMap(element, data) {
|
||||||
|
const map = initMap(element, data);
|
||||||
|
|
||||||
|
drawCadastre(map, data);
|
||||||
|
drawQuartiersPrioritaires(map, data);
|
||||||
|
drawParcellesAgricoles(map, data);
|
||||||
|
drawUserSelection(map, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initMap(element, { position }) {
|
||||||
if (MAPS.has(element)) {
|
if (MAPS.has(element)) {
|
||||||
return MAPS.get(element);
|
return MAPS.get(element);
|
||||||
} else {
|
} else {
|
||||||
const map = L.map(element, {
|
const map = L.map(element, {
|
||||||
scrollWheelZoom: false
|
scrollWheelZoom: false
|
||||||
}).setView([position.lat, position.lon], editable ? 18 : position.zoom);
|
}).setView([position.lat, position.lon], position.zoom);
|
||||||
|
|
||||||
const loadTilesLayer = process.env.RAILS_ENV != 'test';
|
const loadTilesLayer = process.env.RAILS_ENV != 'test';
|
||||||
if (loadTilesLayer) {
|
if (loadTilesLayer) {
|
||||||
|
@ -22,168 +27,47 @@ export function initMap(element, position, editable = false) {
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editable) {
|
|
||||||
const freeDraw = new FreeDraw({
|
|
||||||
mode: FreeDraw.NONE,
|
|
||||||
smoothFactor: 4,
|
|
||||||
mergePolygons: false
|
|
||||||
});
|
|
||||||
map.addLayer(freeDraw);
|
|
||||||
map.freeDraw = freeDraw;
|
|
||||||
}
|
|
||||||
|
|
||||||
MAPS.set(element, map);
|
MAPS.set(element, map);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function drawPolygons(map, data, { editable, initial }) {
|
function drawUserSelection(map, { selection }) {
|
||||||
if (initial) {
|
|
||||||
drawUserSelection(map, data, editable);
|
|
||||||
}
|
|
||||||
clearLayers(map);
|
|
||||||
drawCadastre(map, data, editable);
|
|
||||||
drawQuartiersPrioritaires(map, data, editable);
|
|
||||||
drawParcellesAgricoles(map, data, editable);
|
|
||||||
bringToFrontUserSelection(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function drawUserSelection(map, { selection }, editable = false) {
|
|
||||||
if (selection) {
|
if (selection) {
|
||||||
const coordinates = toLatLngs(selection);
|
const layer = L.geoJSON(selection, {
|
||||||
let polygon;
|
style: USER_SELECTION_POLYGON_STYLE
|
||||||
|
|
||||||
if (editable) {
|
|
||||||
coordinates.forEach(polygon => map.freeDraw.create(polygon));
|
|
||||||
[polygon] = markFreeDrawLayers(map);
|
|
||||||
} else {
|
|
||||||
polygon = L.polygon(coordinates, {
|
|
||||||
color: 'red',
|
|
||||||
zIndex: 3
|
|
||||||
});
|
});
|
||||||
polygon.addTo(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (polygon) {
|
|
||||||
map.fitBounds(polygon.getBounds());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function addFreeDrawEvents(map, selector) {
|
|
||||||
const input = findInput(selector);
|
|
||||||
map.freeDraw.on('markers', ({ latLngs }) => {
|
|
||||||
if (latLngs.length === 0) {
|
|
||||||
input.value = EMPTY_GEO_JSON;
|
|
||||||
} else if (polygonArea(latLngs) < 300000) {
|
|
||||||
input.value = JSON.stringify(latLngs);
|
|
||||||
} else {
|
|
||||||
input.value = ERROR_GEO_JSON;
|
|
||||||
}
|
|
||||||
|
|
||||||
markFreeDrawLayers(map);
|
|
||||||
fire(input, 'change');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawCadastre(map, { cadastres }, editable = false) {
|
|
||||||
drawLayer(
|
|
||||||
map,
|
|
||||||
cadastres,
|
|
||||||
editable ? CADASTRE_POLYGON_STYLE : noEditStyle(CADASTRE_POLYGON_STYLE)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawQuartiersPrioritaires(
|
|
||||||
map,
|
|
||||||
{ quartiersPrioritaires },
|
|
||||||
editable = false
|
|
||||||
) {
|
|
||||||
drawLayer(
|
|
||||||
map,
|
|
||||||
quartiersPrioritaires,
|
|
||||||
editable ? QP_POLYGON_STYLE : noEditStyle(QP_POLYGON_STYLE)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawParcellesAgricoles(map, { parcellesAgricoles }, editable = false) {
|
|
||||||
drawLayer(
|
|
||||||
map,
|
|
||||||
parcellesAgricoles,
|
|
||||||
editable ? RPG_POLYGON_STYLE : noEditStyle(RPG_POLYGON_STYLE)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCurrentMap(element) {
|
|
||||||
if (!element.matches('.carte')) {
|
|
||||||
const closestCarteElement = element.closest('.carte');
|
|
||||||
const closestToolbarElement = element.closest('.toolbar');
|
|
||||||
|
|
||||||
element = closestCarteElement
|
|
||||||
? closestCarteElement
|
|
||||||
: closestToolbarElement.parentElement.querySelector('.carte');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MAPS.has(element)) {
|
|
||||||
return MAPS.get(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const EMPTY_GEO_JSON = '[]';
|
|
||||||
const ERROR_GEO_JSON = '';
|
|
||||||
|
|
||||||
function toLatLngs({ coordinates }) {
|
|
||||||
return coordinates.map(polygon =>
|
|
||||||
polygon[0].map(point => ({ lng: point[0], lat: point[1] }))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function findInput(selector) {
|
|
||||||
return typeof selector === 'string'
|
|
||||||
? document.querySelector(selector)
|
|
||||||
: selector;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createLayer(map) {
|
|
||||||
const layer = new L.GeoJSON(undefined, {
|
|
||||||
interactive: false
|
|
||||||
});
|
|
||||||
layer.addTo(map);
|
layer.addTo(map);
|
||||||
return layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearLayers(map) {
|
map.fitBounds(layer.getBounds());
|
||||||
map.eachLayer(layer => {
|
|
||||||
if (layer instanceof L.GeoJSON) {
|
|
||||||
map.removeLayer(layer);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function bringToFrontUserSelection(map) {
|
function drawCadastre(map, { cadastres }) {
|
||||||
map.eachLayer(layer => {
|
drawLayer(map, cadastres, noEditStyle(CADASTRE_POLYGON_STYLE));
|
||||||
if (layer.isFreeDraw) {
|
|
||||||
layer.bringToFront();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function markFreeDrawLayers(map) {
|
function drawQuartiersPrioritaires(map, { quartiersPrioritaires }) {
|
||||||
return map.freeDraw.all().map(layer => {
|
drawLayer(map, quartiersPrioritaires, noEditStyle(QP_POLYGON_STYLE));
|
||||||
layer.isFreeDraw = true;
|
}
|
||||||
return layer;
|
|
||||||
});
|
function drawParcellesAgricoles(map, { parcellesAgricoles }) {
|
||||||
|
drawLayer(map, parcellesAgricoles, noEditStyle(RPG_POLYGON_STYLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawLayer(map, data, style) {
|
function drawLayer(map, data, style) {
|
||||||
if (Array.isArray(data) && data.length > 0) {
|
if (Array.isArray(data) && data.length > 0) {
|
||||||
const layer = createLayer(map);
|
const layer = new L.GeoJSON(undefined, {
|
||||||
|
interactive: false,
|
||||||
data.forEach(function(item) {
|
style
|
||||||
layer.addData(item.geometry);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
layer.setStyle(style).addTo(map);
|
for (let { geometry } of data) {
|
||||||
|
layer.addData(geometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
layer.addTo(map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,36 +99,6 @@ const RPG_POLYGON_STYLE = Object.assign({}, POLYGON_STYLE, {
|
||||||
fillColor: '#31708f'
|
fillColor: '#31708f'
|
||||||
});
|
});
|
||||||
|
|
||||||
delegate('click', '.carte.edit', event => {
|
const USER_SELECTION_POLYGON_STYLE = {
|
||||||
const map = getCurrentMap(event.target);
|
color: 'red'
|
||||||
|
};
|
||||||
if (map) {
|
|
||||||
const isPath = event.target.matches('.leaflet-container g path');
|
|
||||||
if (isPath) {
|
|
||||||
setTimeout(() => {
|
|
||||||
map.freeDraw.mode(FreeDraw.EDIT | FreeDraw.DELETE);
|
|
||||||
}, 50);
|
|
||||||
} else {
|
|
||||||
map.freeDraw.mode(FreeDraw.NONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
delegate('click', '.toolbar .new-area', event => {
|
|
||||||
event.preventDefault();
|
|
||||||
const map = getCurrentMap(event.target);
|
|
||||||
|
|
||||||
if (map) {
|
|
||||||
map.freeDraw.mode(FreeDraw.CREATE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on('select2:select', 'select[data-address]', event => {
|
|
||||||
const map = getCurrentMap(event.target);
|
|
||||||
const { geometry } = event.params.data;
|
|
||||||
|
|
||||||
if (map && geometry && geometry.type === 'Point') {
|
|
||||||
const [lon, lat] = geometry.coordinates;
|
|
||||||
map.setView(new L.LatLng(lat, lon), 14);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
@ -36,7 +36,8 @@ class Champs::RepetitionChamp < Champ
|
||||||
# We have to truncate the label here as spreadsheets have a (30 char) limit on length.
|
# We have to truncate the label here as spreadsheets have a (30 char) limit on length.
|
||||||
def libelle_for_export
|
def libelle_for_export
|
||||||
str = "(#{type_de_champ.stable_id}) #{libelle}"
|
str = "(#{type_de_champ.stable_id}) #{libelle}"
|
||||||
ActiveStorage::Filename.new(str).sanitized.truncate(30)
|
# /\*?[] are invalid Excel worksheet characters
|
||||||
|
ActiveStorage::Filename.new(str.delete('[]*?')).sanitized.truncate(30)
|
||||||
end
|
end
|
||||||
|
|
||||||
class Row < Hashie::Dash
|
class Row < Hashie::Dash
|
||||||
|
|
|
@ -95,6 +95,8 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
default_scope { where(hidden_at: nil) }
|
default_scope { where(hidden_at: nil) }
|
||||||
|
scope :hidden, -> { unscope(where: :hidden_at).where.not(hidden_at: nil) }
|
||||||
|
scope :with_hidden, -> { unscope(where: :hidden_at) }
|
||||||
scope :state_brouillon, -> { where(state: states.fetch(:brouillon)) }
|
scope :state_brouillon, -> { where(state: states.fetch(:brouillon)) }
|
||||||
scope :state_not_brouillon, -> { where.not(state: states.fetch(:brouillon)) }
|
scope :state_not_brouillon, -> { where.not(state: states.fetch(:brouillon)) }
|
||||||
scope :state_en_construction, -> { where(state: states.fetch(:en_construction)) }
|
scope :state_en_construction, -> { where(state: states.fetch(:en_construction)) }
|
||||||
|
|
|
@ -45,6 +45,8 @@ class Procedure < ApplicationRecord
|
||||||
accepts_nested_attributes_for :types_de_champ_private, reject_if: proc { |attributes| attributes['libelle'].blank? }, allow_destroy: true
|
accepts_nested_attributes_for :types_de_champ_private, reject_if: proc { |attributes| attributes['libelle'].blank? }, allow_destroy: true
|
||||||
|
|
||||||
default_scope { where(hidden_at: nil) }
|
default_scope { where(hidden_at: nil) }
|
||||||
|
scope :hidden, -> { unscope(where: :hidden_at).where.not(hidden_at: nil) }
|
||||||
|
scope :with_hidden, -> { unscope(where: :hidden_at) }
|
||||||
scope :brouillons, -> { where(aasm_state: :brouillon) }
|
scope :brouillons, -> { where(aasm_state: :brouillon) }
|
||||||
scope :publiees, -> { where(aasm_state: :publiee) }
|
scope :publiees, -> { where(aasm_state: :publiee) }
|
||||||
scope :closes, -> { where(aasm_state: [:close, :depubliee]) }
|
scope :closes, -> { where(aasm_state: [:close, :depubliee]) }
|
||||||
|
|
|
@ -9,4 +9,9 @@ const resolve = {
|
||||||
|
|
||||||
environment.splitChunks();
|
environment.splitChunks();
|
||||||
environment.config.merge({ resolve });
|
environment.config.merge({ resolve });
|
||||||
|
|
||||||
|
// Uncoment next lines to run webpack-bundle-analyzer
|
||||||
|
// const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
||||||
|
// environment.plugins.append('BundleAnalyzer', new BundleAnalyzerPlugin());
|
||||||
|
|
||||||
module.exports = environment;
|
module.exports = environment;
|
||||||
|
|
18
lib/cops/unscoped.rb
Normal file
18
lib/cops/unscoped.rb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module DS
|
||||||
|
class Unscoped < Cop
|
||||||
|
MSG = "Avoid using `unscoped`. Instead unscope specific clauses by using `unscope(where: :attribute)`."
|
||||||
|
|
||||||
|
def_node_matcher :unscoped?, <<-END
|
||||||
|
(send _ :unscoped)
|
||||||
|
END
|
||||||
|
|
||||||
|
def on_send(node)
|
||||||
|
return unless unscoped?(node)
|
||||||
|
add_offense(node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,5 @@
|
||||||
namespace :'2017_09_19_set_confidentialite_to_old_avis' do
|
namespace :'2017_09_19_set_confidentialite_to_old_avis' do
|
||||||
task set: :environment do
|
task set: :environment do
|
||||||
Avis.unscoped.update_all(confidentiel: true)
|
Avis.unscope(:joins).update_all(confidentiel: true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
namespace :'2017_09_22_set_dossier_updated_replied_to_initiated' do
|
namespace :'2017_09_22_set_dossier_updated_replied_to_initiated' do
|
||||||
task set: :environment do
|
task set: :environment do
|
||||||
Dossier.unscoped.where(state: [:updated, :replied]).update_all(state: :initiated)
|
Dossier.with_hidden.where(state: [:updated, :replied]).update_all(state: :initiated)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,8 +12,8 @@ namespace :'2017_10_18_regenerate_attestation' do
|
||||||
end
|
end
|
||||||
|
|
||||||
def regenerate_attestations(attestation)
|
def regenerate_attestations(attestation)
|
||||||
Procedure.unscoped do
|
Procedure.with_hidden do
|
||||||
Dossier.unscoped do
|
Dossier.with_hidden do
|
||||||
dossier = attestation.dossier
|
dossier = attestation.dossier
|
||||||
procedure = dossier.procedure
|
procedure = dossier.procedure
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,37 @@
|
||||||
namespace :'2017_12_04_translate_dossier_state_to_french' do
|
namespace :'2017_12_04_translate_dossier_state_to_french' do
|
||||||
task brouillon: :environment do
|
task brouillon: :environment do
|
||||||
Dossier.unscoped.where(state: 'draft').update_all(state: 'brouillon')
|
Dossier.with_hidden.where(state: 'draft').update_all(state: 'brouillon')
|
||||||
end
|
end
|
||||||
|
|
||||||
task en_construction: :environment do
|
task en_construction: :environment do
|
||||||
Dossier.unscoped.where(state: 'initiated').update_all(state: 'en_construction')
|
Dossier.with_hidden.where(state: 'initiated').update_all(state: 'en_construction')
|
||||||
end
|
end
|
||||||
|
|
||||||
task en_instruction: :environment do
|
task en_instruction: :environment do
|
||||||
Dossier.unscoped.where(state: 'received').update_all(state: 'en_instruction')
|
Dossier.with_hidden.where(state: 'received').update_all(state: 'en_instruction')
|
||||||
end
|
end
|
||||||
|
|
||||||
task accepte: :environment do
|
task accepte: :environment do
|
||||||
Dossier.unscoped.where(state: 'closed').update_all(state: 'accepte')
|
Dossier.with_hidden.where(state: 'closed').update_all(state: 'accepte')
|
||||||
end
|
end
|
||||||
|
|
||||||
task refuse: :environment do
|
task refuse: :environment do
|
||||||
Dossier.unscoped.where(state: 'refused').update_all(state: 'refuse')
|
Dossier.with_hidden.where(state: 'refused').update_all(state: 'refuse')
|
||||||
end
|
end
|
||||||
|
|
||||||
task sans_suite: :environment do
|
task sans_suite: :environment do
|
||||||
Dossier.unscoped.where(state: 'without_continuation').update_all(state: 'sans_suite')
|
Dossier.with_hidden.where(state: 'without_continuation').update_all(state: 'sans_suite')
|
||||||
end
|
end
|
||||||
|
|
||||||
task all: [:brouillon, :en_construction, :en_instruction, :accepte, :refuse, :sans_suite] do
|
task all: [:brouillon, :en_construction, :en_instruction, :accepte, :refuse, :sans_suite] do
|
||||||
end
|
end
|
||||||
|
|
||||||
task revert: :environment do
|
task revert: :environment do
|
||||||
Dossier.unscoped.where(state: 'brouillon').update_all(state: 'draft')
|
Dossier.with_hidden.where(state: 'brouillon').update_all(state: 'draft')
|
||||||
Dossier.unscoped.where(state: 'en_construction').update_all(state: 'initiated')
|
Dossier.with_hidden.where(state: 'en_construction').update_all(state: 'initiated')
|
||||||
Dossier.unscoped.where(state: 'en_instruction').update_all(state: 'received')
|
Dossier.with_hidden.where(state: 'en_instruction').update_all(state: 'received')
|
||||||
Dossier.unscoped.where(state: 'accepte').update_all(state: 'closed')
|
Dossier.with_hidden.where(state: 'accepte').update_all(state: 'closed')
|
||||||
Dossier.unscoped.where(state: 'refuse').update_all(state: 'refused')
|
Dossier.with_hidden.where(state: 'refuse').update_all(state: 'refused')
|
||||||
Dossier.unscoped.where(state: 'sans_suite').update_all(state: 'without_continuation')
|
Dossier.with_hidden.where(state: 'sans_suite').update_all(state: 'without_continuation')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace :'2018_04_04_fetch_etablissement_with_no_entreprise' do
|
||||||
task fetch: :environment do
|
task fetch: :environment do
|
||||||
dossiers = Entreprise.joins('LEFT JOIN etablissements et ON entreprises.id = et.entreprise_id')
|
dossiers = Entreprise.joins('LEFT JOIN etablissements et ON entreprises.id = et.entreprise_id')
|
||||||
.where('et.id IS NULL')
|
.where('et.id IS NULL')
|
||||||
.map(&:dossier_id).map { |id| Dossier.unscoped.find_by(id: id) }.compact
|
.map(&:dossier_id).map { |id| Dossier.with_hidden.find_by(id: id) }.compact
|
||||||
|
|
||||||
dossiers.each do |dossier|
|
dossiers.each do |dossier|
|
||||||
siret = dossier.entreprise.siret_siege_social
|
siret = dossier.entreprise.siret_siege_social
|
||||||
|
|
|
@ -3,6 +3,6 @@ namespace :'2018_05_15_add_aasm_state_to_procedure' do
|
||||||
Procedure.archivees.update_all(aasm_state: :archivee)
|
Procedure.archivees.update_all(aasm_state: :archivee)
|
||||||
Procedure.publiees.update_all(aasm_state: :publiee)
|
Procedure.publiees.update_all(aasm_state: :publiee)
|
||||||
Procedure.brouillons.update_all(aasm_state: :brouillon)
|
Procedure.brouillons.update_all(aasm_state: :brouillon)
|
||||||
Procedure.unscoped.where.not(hidden_at: nil).update_all(aasm_state: :hidden)
|
Procedure.hidden.update_all(aasm_state: :hidden)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace :'2018_06_13_unhide_dossiers' do
|
namespace :'2018_06_13_unhide_dossiers' do
|
||||||
task run: :environment do
|
task run: :environment do
|
||||||
Dossier.unscoped.where.not(hidden_at: nil).state_instruction_commencee.each do |d|
|
Dossier.hidden.state_instruction_commencee.each do |d|
|
||||||
if !d.procedure.nil? # ensure the procedure was not deleted by administrateur for testing
|
if !d.procedure.nil? # ensure the procedure was not deleted by administrateur for testing
|
||||||
d.update(hidden_at: nil)
|
d.update(hidden_at: nil)
|
||||||
DeletedDossier.find_by(dossier_id: d.id)&.destroy
|
DeletedDossier.find_by(dossier_id: d.id)&.destroy
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace :fix_timestamps_of_migrated_dossiers do
|
||||||
desc 'Fix the timestamps of dossiers affected by the faulty PJ migration'
|
desc 'Fix the timestamps of dossiers affected by the faulty PJ migration'
|
||||||
task run: :environment do
|
task run: :environment do
|
||||||
affected_time_range = Time.utc(2019, 6, 4, 8, 0)..Time.utc(2019, 6, 4, 18, 0)
|
affected_time_range = Time.utc(2019, 6, 4, 8, 0)..Time.utc(2019, 6, 4, 18, 0)
|
||||||
dossiers = Dossier.unscoped.includes(:groupe_instructeur).where(groupe_instructeurs: { procedure_id: 0..1000 }).where(updated_at: affected_time_range)
|
dossiers = Dossier.with_hidden.includes(:groupe_instructeur).where(groupe_instructeurs: { procedure_id: 0..1000 }).where(updated_at: affected_time_range)
|
||||||
|
|
||||||
progress = ProgressReport.new(dossiers.count)
|
progress = ProgressReport.new(dossiers.count)
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@ namespace :after_party do
|
||||||
task create_dummy_paths_for_archived_and_hidden_procedures: :environment do
|
task create_dummy_paths_for_archived_and_hidden_procedures: :environment do
|
||||||
rake_puts "Running deploy task 'create_dummy_paths_for_archived_procedures'"
|
rake_puts "Running deploy task 'create_dummy_paths_for_archived_procedures'"
|
||||||
|
|
||||||
Procedure.unscoped.archivees.where(path: nil).each do |p|
|
Procedure.with_hidden.archivees.where(path: nil).each do |p|
|
||||||
p.update_column(:path, SecureRandom.uuid)
|
p.update_column(:path, SecureRandom.uuid)
|
||||||
end
|
end
|
||||||
|
|
||||||
Procedure.unscoped.hidden.where(path: nil).each do |p|
|
Procedure.hidden.where(path: nil).each do |p|
|
||||||
p.update_column(:path, SecureRandom.uuid)
|
p.update_column(:path, SecureRandom.uuid)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ namespace :after_party do
|
||||||
desc 'Deployment task: create_default_groupe_instructeur'
|
desc 'Deployment task: create_default_groupe_instructeur'
|
||||||
task create_default_groupe_instructeur: :environment do
|
task create_default_groupe_instructeur: :environment do
|
||||||
Procedure
|
Procedure
|
||||||
.unscoped
|
.with_hidden
|
||||||
.left_outer_joins(:groupe_instructeurs)
|
.left_outer_joins(:groupe_instructeurs)
|
||||||
.where('groupe_instructeurs.id is null')
|
.where('groupe_instructeurs.id is null')
|
||||||
.find_each do |procedure|
|
.find_each do |procedure|
|
||||||
|
|
59
package.json
59
package.json
|
@ -1,55 +1,56 @@
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/preset-react": "^7.6.3",
|
"@babel/preset-react": "^7.8.3",
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.25",
|
"@fortawesome/fontawesome-svg-core": "^1.2.26",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.11.2",
|
"@fortawesome/free-solid-svg-icons": "^5.12.0",
|
||||||
"@fortawesome/react-fontawesome": "^0.1.7",
|
"@fortawesome/react-fontawesome": "^0.1.8",
|
||||||
"@rails/actiontext": "^6.0.0",
|
"@rails/actiontext": "^6.0.2-1",
|
||||||
"@rails/activestorage": "^6.0.0",
|
"@rails/activestorage": "^6.0.2-1",
|
||||||
"@rails/ujs": "^6.0.0",
|
"@rails/ujs": "^6.0.2-1",
|
||||||
"@rails/webpacker": "4.0.7",
|
"@rails/webpacker": "4.2.2",
|
||||||
"@sentry/browser": "^5.7.1",
|
"@sentry/browser": "^5.11.1",
|
||||||
"@turf/area": "^6.0.1",
|
"@turf/area": "^6.0.1",
|
||||||
"babel-plugin-macros": "^2.6.1",
|
"babel-plugin-macros": "^2.8.0",
|
||||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
||||||
"chartkick": "^3.1.3",
|
"chartkick": "^3.2.0",
|
||||||
"core-js": "^2.0.0",
|
"core-js": "^2.0.0",
|
||||||
"debounce": "^1.2.0",
|
"debounce": "^1.2.0",
|
||||||
"dom4": "^2.1.5",
|
"dom4": "^2.1.5",
|
||||||
"email-butler": "^1.0.12",
|
"email-butler": "^1.0.13",
|
||||||
"highcharts": "^6.1.2",
|
"highcharts": "^6.1.2",
|
||||||
"intersection-observer": "^0.7.0",
|
"intersection-observer": "^0.7.0",
|
||||||
"jquery": "^3.4.1",
|
"jquery": "^3.4.1",
|
||||||
"leaflet": "^1.4.0",
|
"leaflet": "^1.6.0",
|
||||||
"leaflet-freedraw": "^2.10.0",
|
"leaflet-freedraw": "^2.12.0",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"ramda": "=0.24.1",
|
"react": "^16.12.0",
|
||||||
"react": "^16.11.0",
|
"react-dom": "^16.12.0",
|
||||||
"react-dom": "^16.11.0",
|
"react-intersection-observer": "^8.25.2",
|
||||||
"react-intersection-observer": "^8.25.1",
|
|
||||||
"react-loadable": "^5.5.0",
|
"react-loadable": "^5.5.0",
|
||||||
"react-scroll-to-component": "^1.0.2",
|
"react-scroll-to-component": "^1.0.2",
|
||||||
"react-sortable-hoc": "^1.10.1",
|
"react-sortable-hoc": "^1.10.1",
|
||||||
"react_ujs": "^2.6.0",
|
"react_ujs": "^2.6.1",
|
||||||
"select2": "^4.0.11",
|
"select2": "^4.0.13",
|
||||||
"trix": "^1.2.1",
|
"trix": "^1.2.2",
|
||||||
"turbolinks": "^5.2.0",
|
"turbolinks": "^5.2.0",
|
||||||
"whatwg-fetch": "^3.0.0"
|
"whatwg-fetch": "^3.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-eslint": "^10.0.3",
|
"babel-eslint": "^10.0.3",
|
||||||
"eclint": "^2.8.1",
|
"eclint": "^2.8.1",
|
||||||
"eslint": "^6.6.0",
|
"eslint": "^6.7.2",
|
||||||
"eslint-config-prettier": "^6.5.0",
|
"eslint-config-prettier": "^6.10.0",
|
||||||
"eslint-plugin-prettier": "^3.1.1",
|
"eslint-plugin-prettier": "^3.1.2",
|
||||||
"eslint-plugin-react": "^7.16.0",
|
"eslint-plugin-react": "^7.18.0",
|
||||||
"eslint-plugin-react-hooks": "^2.2.0",
|
"eslint-plugin-react-hooks": "^2.3.0",
|
||||||
"prettier": "^1.18.2",
|
"prettier": "^1.19.1",
|
||||||
"webpack-dev-server": "^3.9.0"
|
"webpack-bundle-analyzer": "^3.6.0",
|
||||||
|
"webpack-dev-server": "^3.10.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint:ec": "eclint check $({ git ls-files | grep -v app/graphql/schema.graphql ; find vendor -type f ; echo 'db/schema.rb' ; } | sort | uniq -u)",
|
"lint:ec": "eclint check $({ git ls-files | grep -v app/graphql/schema.graphql ; find vendor -type f ; echo 'db/schema.rb' ; } | sort | uniq -u)",
|
||||||
"lint:js": "eslint ./app/javascript ./app/assets/javascripts ./config/webpack"
|
"lint:js": "eslint ./app/javascript ./app/assets/javascripts ./config/webpack",
|
||||||
|
"webpack:build": "NODE_ENV=production bin/webpack"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "8.* || >= 10.*"
|
"node": "8.* || >= 10.*"
|
||||||
|
|
|
@ -308,6 +308,7 @@ describe API::V2::GraphqlController do
|
||||||
entreprise {
|
entreprise {
|
||||||
siren
|
siren
|
||||||
dateCreation
|
dateCreation
|
||||||
|
capitalSocial
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,7 +331,8 @@ describe API::V2::GraphqlController do
|
||||||
siegeSocial: dossier.etablissement.siege_social,
|
siegeSocial: dossier.etablissement.siege_social,
|
||||||
entreprise: {
|
entreprise: {
|
||||||
siren: dossier.etablissement.entreprise_siren,
|
siren: dossier.etablissement.entreprise_siren,
|
||||||
dateCreation: dossier.etablissement.entreprise_date_creation.iso8601
|
dateCreation: dossier.etablissement.entreprise_date_creation.iso8601,
|
||||||
|
capitalSocial: dossier.etablissement.entreprise_capital_social.to_s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -757,13 +757,19 @@ describe Users::DossiersController, type: :controller do
|
||||||
procedure: procedure,
|
procedure: procedure,
|
||||||
user: user)
|
user: user)
|
||||||
}
|
}
|
||||||
|
|
||||||
subject! { get(:show, params: { id: dossier.id, format: :pdf }) }
|
subject! { get(:show, params: { id: dossier.id, format: :pdf }) }
|
||||||
|
|
||||||
|
context 'when the dossier is a brouillon' do
|
||||||
|
let(:dossier) { create(:dossier, user: user) }
|
||||||
|
it { is_expected.to redirect_to(brouillon_dossier_path(dossier)) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the dossier has been submitted' do
|
||||||
it { expect(assigns(:include_infos_administration)).to eq(false) }
|
it { expect(assigns(:include_infos_administration)).to eq(false) }
|
||||||
it { expect(response).to render_template 'dossiers/show' }
|
it { expect(response).to render_template 'dossiers/show' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#formulaire' do
|
describe '#formulaire' do
|
||||||
let(:dossier) { create(:dossier, :en_construction, user: user) }
|
let(:dossier) { create(:dossier, :en_construction, user: user) }
|
||||||
|
|
|
@ -5,6 +5,42 @@ describe Dossier do
|
||||||
|
|
||||||
let(:user) { create(:user) }
|
let(:user) { create(:user) }
|
||||||
|
|
||||||
|
describe 'scopes' do
|
||||||
|
describe '.default_scope' do
|
||||||
|
let!(:dossier) { create(:dossier) }
|
||||||
|
let!(:hidden_dossier) { create(:dossier, :hidden) }
|
||||||
|
|
||||||
|
subject { Dossier.all }
|
||||||
|
|
||||||
|
it { is_expected.to match_array([dossier]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.hidden' do
|
||||||
|
let!(:dossier) { create(:dossier) }
|
||||||
|
let!(:hidden_dossier) { create(:dossier, :hidden) }
|
||||||
|
|
||||||
|
subject { Dossier.all.hidden }
|
||||||
|
|
||||||
|
it { is_expected.to match_array([hidden_dossier]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.with_hidden' do
|
||||||
|
let!(:dossier) { create(:dossier) }
|
||||||
|
let!(:hidden_dossier) { create(:dossier, :hidden) }
|
||||||
|
|
||||||
|
subject { Dossier.all.with_hidden }
|
||||||
|
|
||||||
|
it { is_expected.to match_array([dossier, hidden_dossier]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.without_followers' do
|
||||||
|
let!(:dossier_with_follower) { create(:dossier, :followed, :with_entreprise, user: user) }
|
||||||
|
let!(:dossier_without_follower) { create(:dossier, :with_entreprise, user: user) }
|
||||||
|
|
||||||
|
it { expect(Dossier.without_followers.to_a).to eq([dossier_without_follower]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'validations' do
|
describe 'validations' do
|
||||||
let(:procedure) { create(:procedure, :for_individual) }
|
let(:procedure) { create(:procedure, :for_individual) }
|
||||||
subject(:dossier) { create(:dossier, procedure: procedure) }
|
subject(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
@ -12,13 +48,6 @@ describe Dossier do
|
||||||
it { is_expected.to validate_presence_of(:individual) }
|
it { is_expected.to validate_presence_of(:individual) }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "without_followers scope" do
|
|
||||||
let!(:dossier) { create(:dossier, :followed, :with_entreprise, user: user) }
|
|
||||||
let!(:dossier2) { create(:dossier, :with_entreprise, user: user) }
|
|
||||||
|
|
||||||
it { expect(Dossier.without_followers.to_a).to eq([dossier2]) }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'with_champs' do
|
describe 'with_champs' do
|
||||||
let(:procedure) { create(:procedure) }
|
let(:procedure) { create(:procedure) }
|
||||||
let(:dossier) { Dossier.create(user: create(:user), groupe_instructeur: procedure.defaut_groupe_instructeur) }
|
let(:dossier) { Dossier.create(user: create(:user), groupe_instructeur: procedure.defaut_groupe_instructeur) }
|
||||||
|
@ -522,23 +551,6 @@ describe Dossier do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe ".default_scope" do
|
|
||||||
let!(:dossier) { create(:dossier, hidden_at: hidden_at) }
|
|
||||||
|
|
||||||
context "when dossier is not hidden" do
|
|
||||||
let(:hidden_at) { nil }
|
|
||||||
|
|
||||||
it { expect(Dossier.count).to eq(1) }
|
|
||||||
it { expect(Dossier.all).to include(dossier) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context "when dossier is hidden" do
|
|
||||||
let(:hidden_at) { 1.day.ago }
|
|
||||||
|
|
||||||
it { expect(Dossier.count).to eq(0) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'updated_at' do
|
describe 'updated_at' do
|
||||||
let!(:dossier) { create(:dossier) }
|
let!(:dossier) { create(:dossier) }
|
||||||
let(:modif_date) { Time.zone.parse('01/01/2100') }
|
let(:modif_date) { Time.zone.parse('01/01/2100') }
|
||||||
|
|
|
@ -151,6 +151,26 @@ describe Procedure do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'scopes' do
|
||||||
|
let!(:procedure) { create(:procedure) }
|
||||||
|
let!(:hidden_procedure) { create(:procedure, :hidden) }
|
||||||
|
|
||||||
|
describe 'default_scope' do
|
||||||
|
subject { Procedure.all }
|
||||||
|
it { is_expected.to match_array([procedure]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.hidden' do
|
||||||
|
subject { Procedure.all.hidden }
|
||||||
|
it { is_expected.to match_array([hidden_procedure]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.with_hidden' do
|
||||||
|
subject { Procedure.all.with_hidden }
|
||||||
|
it { is_expected.to match_array([procedure, hidden_procedure]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'validation' do
|
describe 'validation' do
|
||||||
context 'libelle' do
|
context 'libelle' do
|
||||||
it { is_expected.not_to allow_value(nil).for(:libelle) }
|
it { is_expected.not_to allow_value(nil).for(:libelle) }
|
||||||
|
|
|
@ -334,7 +334,7 @@ describe ProcedureExportService do
|
||||||
|
|
||||||
context 'with invalid characters' do
|
context 'with invalid characters' do
|
||||||
before do
|
before do
|
||||||
champ_repetition.type_de_champ.update(libelle: 'A / B \ C')
|
champ_repetition.type_de_champ.update(libelle: 'A / B \ C *[]?')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should have valid sheet name' do
|
it 'should have valid sheet name' do
|
||||||
|
|
Loading…
Reference in a new issue