commit
a105a090bf
10 changed files with 109 additions and 37 deletions
|
@ -1089,7 +1089,7 @@ type Entreprise {
|
|||
"""
|
||||
capital social de l’entreprise. -1 si inconnu.
|
||||
"""
|
||||
capitalSocial: BigInt!
|
||||
capitalSocial: BigInt
|
||||
codeEffectifEntreprise: String
|
||||
dateCreation: ISO8601Date!
|
||||
|
||||
|
@ -1107,7 +1107,7 @@ type Entreprise {
|
|||
inlineAdresse: String!
|
||||
nom: String
|
||||
nomCommercial: String!
|
||||
numeroTvaIntracommunautaire: String!
|
||||
numeroTvaIntracommunautaire: String
|
||||
prenom: String
|
||||
raisonSociale: String!
|
||||
siren: String!
|
||||
|
|
|
@ -7,8 +7,8 @@ module Types
|
|||
end
|
||||
|
||||
field :siren, String, null: false
|
||||
field :capital_social, GraphQL::Types::BigInt, null: false, description: "capital social de l’entreprise. -1 si inconnu."
|
||||
field :numero_tva_intracommunautaire, String, null: false
|
||||
field :capital_social, GraphQL::Types::BigInt, null: true, description: "capital social de l’entreprise. -1 si inconnu."
|
||||
field :numero_tva_intracommunautaire, String, null: true
|
||||
field :forme_juridique, String, null: true
|
||||
field :forme_juridique_code, String, null: true
|
||||
field :nom_commercial, String, null: false
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import React, { useState, useCallback, useRef, useMemo } from 'react';
|
||||
import React, {
|
||||
useState,
|
||||
useCallback,
|
||||
useRef,
|
||||
useMemo,
|
||||
useEffect
|
||||
} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import mapboxgl from 'mapbox-gl';
|
||||
import { GeoJSONLayer, ZoomControl } from 'react-mapbox-gl';
|
||||
|
@ -10,6 +16,7 @@ import { getJSON, ajax, fire } from '@utils';
|
|||
import Mapbox from '../shared/mapbox/Mapbox';
|
||||
import { getMapStyle } from '../shared/mapbox/styles';
|
||||
import SwitchMapStyle from '../shared/mapbox/SwitchMapStyle';
|
||||
import { FlashMessage } from '../shared/FlashMessage';
|
||||
|
||||
import ComboAdresseSearch from '../ComboAdresseSearch';
|
||||
import {
|
||||
|
@ -30,6 +37,7 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
|||
const drawControl = useRef(null);
|
||||
const [currentMap, setCurrentMap] = useState(null);
|
||||
|
||||
const [errorMessage, setErrorMessage] = useState();
|
||||
const [style, setStyle] = useState('ortho');
|
||||
const [coords, setCoords] = useState([1.7, 46.9]);
|
||||
const [zoom, setZoom] = useState([5]);
|
||||
|
@ -44,6 +52,11 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
|||
]);
|
||||
const hasCadastres = useMemo(() => options.layers.includes('cadastres'));
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setErrorMessage(null), 5000);
|
||||
return () => clearTimeout(timer);
|
||||
}, [errorMessage]);
|
||||
|
||||
const translations = [
|
||||
['.mapbox-gl-draw_line', 'Tracer une ligne'],
|
||||
['.mapbox-gl-draw_polygon', 'Dessiner un polygone'],
|
||||
|
@ -118,21 +131,34 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
|||
}
|
||||
|
||||
async function onDrawCreate({ features }) {
|
||||
for (const feature of features) {
|
||||
const data = await getJSON(url, { feature }, 'post');
|
||||
setFeatureId(feature.id, data.feature);
|
||||
}
|
||||
try {
|
||||
for (const feature of features) {
|
||||
const data = await getJSON(url, { feature }, 'post');
|
||||
setFeatureId(feature.id, data.feature);
|
||||
}
|
||||
|
||||
updateFeaturesList(features);
|
||||
updateFeaturesList(features);
|
||||
} catch {
|
||||
setErrorMessage('Le polygone dessiné n’est pas valide.');
|
||||
}
|
||||
}
|
||||
|
||||
async function onDrawUpdate({ features }) {
|
||||
for (const feature of features) {
|
||||
let { id } = feature.properties;
|
||||
await getJSON(`${url}/${id}`, { feature }, 'patch');
|
||||
}
|
||||
try {
|
||||
for (const feature of features) {
|
||||
const { id } = feature.properties;
|
||||
if (id) {
|
||||
await getJSON(`${url}/${id}`, { feature }, 'patch');
|
||||
} else {
|
||||
const data = await getJSON(url, { feature }, 'post');
|
||||
setFeatureId(feature.id, data.feature);
|
||||
}
|
||||
}
|
||||
|
||||
updateFeaturesList(features);
|
||||
updateFeaturesList(features);
|
||||
} catch {
|
||||
setErrorMessage('Le polygone dessiné n’est pas valide.');
|
||||
}
|
||||
}
|
||||
|
||||
async function onDrawDelete({ features }) {
|
||||
|
@ -152,8 +178,9 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
|||
);
|
||||
}
|
||||
|
||||
const onFileImport = (e, inputId) => {
|
||||
readGeoFile(e.target.files[0]).then(async (featureCollection) => {
|
||||
const onFileImport = async (e, inputId) => {
|
||||
try {
|
||||
const featureCollection = await readGeoFile(e.target.files[0]);
|
||||
const resultFeatureCollection = await getJSON(
|
||||
`${url}/import`,
|
||||
featureCollection,
|
||||
|
@ -188,7 +215,9 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
|||
updateFeaturesList(resultFeatureCollection.features);
|
||||
setImportInputs(setInputs);
|
||||
setBbox(resultFeatureCollection.bbox);
|
||||
});
|
||||
} catch {
|
||||
setErrorMessage('Le fichier importé contient des polygones invalides.');
|
||||
}
|
||||
};
|
||||
|
||||
const addInputFile = (e) => {
|
||||
|
@ -233,6 +262,9 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
|||
|
||||
return (
|
||||
<>
|
||||
{errorMessage && (
|
||||
<FlashMessage message={errorMessage} level="alert" fixed={true} />
|
||||
)}
|
||||
<div>
|
||||
<p style={{ marginBottom: '20px' }}>
|
||||
Besoin d'aide ?
|
||||
|
|
24
app/javascript/components/shared/FlashMessage.jsx
Normal file
24
app/javascript/components/shared/FlashMessage.jsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
import React from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
export function FlashMessage({ message, level, sticky, fixed }) {
|
||||
return createPortal(
|
||||
<div className="flash_message center">
|
||||
<div className={flashClassName(level, sticky, fixed)}>{message}</div>
|
||||
</div>,
|
||||
document.getElementById('flash_messages')
|
||||
);
|
||||
}
|
||||
|
||||
function flashClassName(level, sticky = false, fixed = false) {
|
||||
const className =
|
||||
level == 'notice' ? ['alert', 'alert-success'] : ['alert', 'alert-danger'];
|
||||
|
||||
if (sticky) {
|
||||
className.push('sticky');
|
||||
}
|
||||
if (fixed) {
|
||||
className.push('alert-fixed');
|
||||
}
|
||||
return className.join(' ');
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
class AnnuaireEducationUpdateJob < ApplicationJob
|
||||
def perform(champ)
|
||||
external_id = champ.external_id
|
||||
|
||||
if external_id.present?
|
||||
data = APIEducation::AnnuaireEducationAdapter.new(external_id).to_params
|
||||
|
||||
if data.present?
|
||||
champ.data = data
|
||||
else
|
||||
champ.external_id = nil
|
||||
end
|
||||
champ.save!
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
class ChampFetchExternalDataJob < ApplicationJob
|
||||
def perform(champ)
|
||||
if champ.external_id.present?
|
||||
def perform(champ, external_id)
|
||||
if champ.external_id == external_id && champ.data.nil?
|
||||
data = champ.fetch_external_data
|
||||
|
||||
if data.present?
|
||||
|
|
|
@ -171,7 +171,7 @@ class Champ < ApplicationRecord
|
|||
|
||||
def fetch_external_data_later
|
||||
if fetch_external_data? && external_id.present? && data.nil?
|
||||
ChampFetchExternalDataJob.perform_later(self)
|
||||
ChampFetchExternalDataJob.perform_later(self, external_id)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ class GeoArea < ApplicationRecord
|
|||
scope :selections_utilisateur, -> { where(source: sources.fetch(:selection_utilisateur)) }
|
||||
scope :cadastres, -> { where(source: sources.fetch(:cadastre)) }
|
||||
|
||||
validates :geometry, geo_json: true, allow_blank: false
|
||||
|
||||
def to_feature
|
||||
{
|
||||
type: 'Feature',
|
||||
|
|
9
app/validators/geo_json_validator.rb
Normal file
9
app/validators/geo_json_validator.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
class GeoJSONValidator < ActiveModel::EachValidator
|
||||
def validate_each(record, attribute, value)
|
||||
begin
|
||||
RGeo::GeoJSON.decode(value.to_json, geo_factory: RGeo::Geographic.simple_mercator_factory)
|
||||
rescue RGeo::Error::InvalidGeometry
|
||||
record.errors[attribute] << (options[:message] || "n'est pas un GeoJSON valide")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
namespace :after_party do
|
||||
desc 'Deployment task: remove_invalid_geometries'
|
||||
task remove_invalid_geometries: :environment do
|
||||
puts "Running deploy task 'remove_invalid_geometries'"
|
||||
|
||||
geo_areas = GeoArea.where(source: :selection_utilisateur)
|
||||
progress = ProgressReport.new(geo_areas.count)
|
||||
geo_areas.find_each do |geo_area|
|
||||
if !geo_area.valid?
|
||||
geo_area.destroy
|
||||
end
|
||||
progress.inc
|
||||
end
|
||||
progress.finish
|
||||
|
||||
# Update task as completed. If you remove the line below, the task will
|
||||
# run with every deploy (or every time you call after_party:run).
|
||||
AfterParty::TaskRecord
|
||||
.create version: AfterParty::TaskRecorder.new(__FILE__).timestamp
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue