commit
ace5ac36c3
7 changed files with 1316 additions and 1870 deletions
|
@ -1,13 +1,14 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { library } from '@fortawesome/fontawesome-svg-core';
|
||||
|
||||
import { faArrowCircleDown } from '@fortawesome/free-solid-svg-icons/faArrowCircleDown';
|
||||
import { faArrowDown } from '@fortawesome/free-solid-svg-icons/faArrowDown';
|
||||
import { faArrowsAltV } from '@fortawesome/free-solid-svg-icons/faArrowsAltV';
|
||||
import { faArrowUp } from '@fortawesome/free-solid-svg-icons/faArrowUp';
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons/faPlus';
|
||||
import { faTrash } from '@fortawesome/free-solid-svg-icons/faTrash';
|
||||
import {
|
||||
faArrowCircleDown,
|
||||
faArrowDown,
|
||||
faArrowsAltV,
|
||||
faArrowUp,
|
||||
faPlus,
|
||||
faTrash
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
import Flash from './Flash';
|
||||
import OperationsQueue from './OperationsQueue';
|
||||
|
|
|
@ -1,38 +1,47 @@
|
|||
import { initMap, drawPolygons, addFreeDrawEvents } from '../../shared/carte';
|
||||
|
||||
async function initialize() {
|
||||
const elements = document.querySelectorAll('.carte');
|
||||
|
||||
if (elements.length) {
|
||||
const editable = [...elements].find(element =>
|
||||
element.classList.contains('edit')
|
||||
);
|
||||
await loadLeaflet(editable);
|
||||
|
||||
for (let element of elements) {
|
||||
loadAndDrawMap(element);
|
||||
diplayMap(element, null, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function loadAndDrawMap(element) {
|
||||
const data = JSON.parse(element.dataset.geo);
|
||||
const editable = element.classList.contains('edit');
|
||||
// We load leaflet dynamically, ramda and freedraw and assign them to globals.
|
||||
// Latest freedraw version build needs globals.
|
||||
async function loadLeaflet(editable) {
|
||||
window.L = await import('leaflet').then(({ default: L }) => L);
|
||||
|
||||
if (editable) {
|
||||
const { drawEditableMap } = await import('../../shared/carte-editor');
|
||||
|
||||
drawEditableMap(element, data);
|
||||
} else {
|
||||
const { drawMap } = await import('../../shared/carte');
|
||||
|
||||
drawMap(element, data);
|
||||
window.R = await import('ramda').then(({ default: R }) => R);
|
||||
await import('leaflet-freedraw/dist/leaflet-freedraw.web.js');
|
||||
}
|
||||
}
|
||||
|
||||
async function loadAndRedrawMap(element, data) {
|
||||
const { redrawMap } = await import('../../shared/carte-editor');
|
||||
function diplayMap(element, data, initial = false) {
|
||||
data = data || JSON.parse(element.dataset.geo);
|
||||
const editable = element.classList.contains('edit');
|
||||
const map = initMap(element, data.position, editable);
|
||||
|
||||
redrawMap(element, data);
|
||||
drawPolygons(map, data, { initial, editable });
|
||||
|
||||
if (initial && editable) {
|
||||
const input = element.parentElement.querySelector('input[data-remote]');
|
||||
addFreeDrawEvents(map, input);
|
||||
}
|
||||
}
|
||||
|
||||
addEventListener('turbolinks:load', initialize);
|
||||
|
||||
addEventListener('carte:update', ({ detail: { selector, data } }) => {
|
||||
const element = document.querySelector(selector);
|
||||
|
||||
loadAndRedrawMap(element, data);
|
||||
diplayMap(element, data);
|
||||
});
|
||||
|
|
|
@ -1,214 +0,0 @@
|
|||
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,23 +1,18 @@
|
|||
import L from 'leaflet';
|
||||
/* globals FreeDraw L */
|
||||
import { fire, delegate } from '@utils';
|
||||
import $ from 'jquery';
|
||||
|
||||
import polygonArea from './polygon_area';
|
||||
|
||||
const MAPS = new WeakMap();
|
||||
|
||||
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 }) {
|
||||
export function initMap(element, position, editable = false) {
|
||||
if (MAPS.has(element)) {
|
||||
return MAPS.get(element);
|
||||
} else {
|
||||
const map = L.map(element, {
|
||||
scrollWheelZoom: false
|
||||
}).setView([position.lat, position.lon], position.zoom);
|
||||
}).setView([position.lat, position.lon], editable ? 18 : position.zoom);
|
||||
|
||||
const loadTilesLayer = process.env.RAILS_ENV != 'test';
|
||||
if (loadTilesLayer) {
|
||||
|
@ -27,47 +22,168 @@ function initMap(element, { position }) {
|
|||
}).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);
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
function drawUserSelection(map, { selection }) {
|
||||
export function drawPolygons(map, data, { editable, initial }) {
|
||||
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) {
|
||||
const layer = L.geoJSON(selection, {
|
||||
style: USER_SELECTION_POLYGON_STYLE
|
||||
const coordinates = toLatLngs(selection);
|
||||
let polygon;
|
||||
|
||||
if (editable) {
|
||||
coordinates.forEach(polygon => map.freeDraw.create(polygon));
|
||||
[polygon] = markFreeDrawLayers(map);
|
||||
} else {
|
||||
polygon = L.polygon(coordinates, {
|
||||
color: 'red',
|
||||
zIndex: 3
|
||||
});
|
||||
polygon.addTo(map);
|
||||
}
|
||||
|
||||
layer.addTo(map);
|
||||
|
||||
map.fitBounds(layer.getBounds());
|
||||
if (polygon) {
|
||||
map.fitBounds(polygon.getBounds());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawCadastre(map, { cadastres }) {
|
||||
drawLayer(map, cadastres, noEditStyle(CADASTRE_POLYGON_STYLE));
|
||||
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 drawQuartiersPrioritaires(map, { quartiersPrioritaires }) {
|
||||
drawLayer(map, quartiersPrioritaires, noEditStyle(QP_POLYGON_STYLE));
|
||||
function drawCadastre(map, { cadastres }, editable = false) {
|
||||
drawLayer(
|
||||
map,
|
||||
cadastres,
|
||||
editable ? CADASTRE_POLYGON_STYLE : noEditStyle(CADASTRE_POLYGON_STYLE)
|
||||
);
|
||||
}
|
||||
|
||||
function drawParcellesAgricoles(map, { parcellesAgricoles }) {
|
||||
drawLayer(map, parcellesAgricoles, noEditStyle(RPG_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);
|
||||
return layer;
|
||||
}
|
||||
|
||||
function clearLayers(map) {
|
||||
map.eachLayer(layer => {
|
||||
if (layer instanceof L.GeoJSON) {
|
||||
map.removeLayer(layer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function bringToFrontUserSelection(map) {
|
||||
map.eachLayer(layer => {
|
||||
if (layer.isFreeDraw) {
|
||||
layer.bringToFront();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function markFreeDrawLayers(map) {
|
||||
return map.freeDraw.all().map(layer => {
|
||||
layer.isFreeDraw = true;
|
||||
return layer;
|
||||
});
|
||||
}
|
||||
|
||||
function drawLayer(map, data, style) {
|
||||
if (Array.isArray(data) && data.length > 0) {
|
||||
const layer = new L.GeoJSON(undefined, {
|
||||
interactive: false,
|
||||
style
|
||||
const layer = createLayer(map);
|
||||
|
||||
data.forEach(function(item) {
|
||||
layer.addData(item.geometry);
|
||||
});
|
||||
|
||||
for (let { geometry } of data) {
|
||||
layer.addData(geometry);
|
||||
}
|
||||
|
||||
layer.addTo(map);
|
||||
layer.setStyle(style).addTo(map);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,6 +215,36 @@ const RPG_POLYGON_STYLE = Object.assign({}, POLYGON_STYLE, {
|
|||
fillColor: '#31708f'
|
||||
});
|
||||
|
||||
const USER_SELECTION_POLYGON_STYLE = {
|
||||
color: 'red'
|
||||
};
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -9,9 +9,4 @@ const resolve = {
|
|||
|
||||
environment.splitChunks();
|
||||
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;
|
||||
|
|
59
package.json
59
package.json
|
@ -1,56 +1,55 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"@babel/preset-react": "^7.8.3",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.26",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.12.0",
|
||||
"@fortawesome/react-fontawesome": "^0.1.8",
|
||||
"@rails/actiontext": "^6.0.2-1",
|
||||
"@rails/activestorage": "^6.0.2-1",
|
||||
"@rails/ujs": "^6.0.2-1",
|
||||
"@rails/webpacker": "4.2.2",
|
||||
"@sentry/browser": "^5.11.1",
|
||||
"@babel/preset-react": "^7.6.3",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.25",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.11.2",
|
||||
"@fortawesome/react-fontawesome": "^0.1.7",
|
||||
"@rails/actiontext": "^6.0.0",
|
||||
"@rails/activestorage": "^6.0.0",
|
||||
"@rails/ujs": "^6.0.0",
|
||||
"@rails/webpacker": "4.0.7",
|
||||
"@sentry/browser": "^5.7.1",
|
||||
"@turf/area": "^6.0.1",
|
||||
"babel-plugin-macros": "^2.8.0",
|
||||
"babel-plugin-macros": "^2.6.1",
|
||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
||||
"chartkick": "^3.2.0",
|
||||
"chartkick": "^3.1.3",
|
||||
"core-js": "^2.0.0",
|
||||
"debounce": "^1.2.0",
|
||||
"dom4": "^2.1.5",
|
||||
"email-butler": "^1.0.13",
|
||||
"email-butler": "^1.0.12",
|
||||
"highcharts": "^6.1.2",
|
||||
"intersection-observer": "^0.7.0",
|
||||
"jquery": "^3.4.1",
|
||||
"leaflet": "^1.6.0",
|
||||
"leaflet-freedraw": "^2.12.0",
|
||||
"leaflet": "^1.4.0",
|
||||
"leaflet-freedraw": "^2.10.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-intersection-observer": "^8.25.2",
|
||||
"ramda": "=0.24.1",
|
||||
"react": "^16.11.0",
|
||||
"react-dom": "^16.11.0",
|
||||
"react-intersection-observer": "^8.25.1",
|
||||
"react-loadable": "^5.5.0",
|
||||
"react-scroll-to-component": "^1.0.2",
|
||||
"react-sortable-hoc": "^1.10.1",
|
||||
"react_ujs": "^2.6.1",
|
||||
"select2": "^4.0.13",
|
||||
"trix": "^1.2.2",
|
||||
"react_ujs": "^2.6.0",
|
||||
"select2": "^4.0.11",
|
||||
"trix": "^1.2.1",
|
||||
"turbolinks": "^5.2.0",
|
||||
"whatwg-fetch": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^10.0.3",
|
||||
"eclint": "^2.8.1",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-config-prettier": "^6.10.0",
|
||||
"eslint-plugin-prettier": "^3.1.2",
|
||||
"eslint-plugin-react": "^7.18.0",
|
||||
"eslint-plugin-react-hooks": "^2.3.0",
|
||||
"prettier": "^1.19.1",
|
||||
"webpack-bundle-analyzer": "^3.6.0",
|
||||
"webpack-dev-server": "^3.10.0"
|
||||
"eslint": "^6.6.0",
|
||||
"eslint-config-prettier": "^6.5.0",
|
||||
"eslint-plugin-prettier": "^3.1.1",
|
||||
"eslint-plugin-react": "^7.16.0",
|
||||
"eslint-plugin-react-hooks": "^2.2.0",
|
||||
"prettier": "^1.18.2",
|
||||
"webpack-dev-server": "^3.9.0"
|
||||
},
|
||||
"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:js": "eslint ./app/javascript ./app/assets/javascripts ./config/webpack",
|
||||
"webpack:build": "NODE_ENV=production bin/webpack"
|
||||
"lint:js": "eslint ./app/javascript ./app/assets/javascripts ./config/webpack"
|
||||
},
|
||||
"engines": {
|
||||
"node": "8.* || >= 10.*"
|
||||
|
|
Loading…
Reference in a new issue