diff --git a/app/assets/stylesheets/01_common.scss b/app/assets/stylesheets/01_common.scss
index 7ed530f6c..de740e9de 100644
--- a/app/assets/stylesheets/01_common.scss
+++ b/app/assets/stylesheets/01_common.scss
@@ -1,7 +1,8 @@
@import "placeholders";
-turbo-events {
- display: none;
+html,
+body {
+ min-height: 100vh;
}
.page-wrapper {
diff --git a/app/components/dossiers/export_component.rb b/app/components/dossiers/export_component.rb
index 2780f668d..6853b83ad 100644
--- a/app/components/dossiers/export_component.rb
+++ b/app/components/dossiers/export_component.rb
@@ -8,7 +8,27 @@ class Dossiers::ExportComponent < ApplicationComponent
end
def exports
- helpers.exports_list(@exports, @statut)
+ if @statut
+ Export::FORMATS.filter(&method(:allowed_format?)).map do |item|
+ export = @exports
+ .fetch(item.fetch(:format))
+ .fetch(:statut)
+ .fetch(@statut, nil)
+ item.merge(export: export)
+ end
+ else
+ Export::FORMATS_WITH_TIME_SPAN.map do |item|
+ export = @exports
+ .fetch(item.fetch(:format))
+ .fetch(:time_span_type)
+ .fetch(item.fetch(:time_span_type), nil)
+ item.merge(export: export)
+ end
+ end
+ end
+
+ def allowed_format?(item)
+ item.fetch(:format) != :json || @procedure.active_revision.carte?
end
def download_export_path(export_format:, force_export: false, no_progress_notification: nil)
diff --git a/app/components/dossiers/export_component/export_component.en.yml b/app/components/dossiers/export_component/export_component.en.yml
index 0da205bd2..67b504324 100644
--- a/app/components/dossiers/export_component/export_component.en.yml
+++ b/app/components/dossiers/export_component/export_component.en.yml
@@ -1,12 +1,13 @@
---
en:
- everything_csv_html: Ask an export in format .csv
(only folders, without repeatable fields)
- everything_xlsx_html: Ask an export in format .xlsx
- everything_ods_html: Ask an export in format .ods
- everything_zip_html: Ask an export in format .zip
(does not contains timestamp nor operation logs )
- everything_short: Ask an export in format%{export_format}
- everything_pending_html: Ask an export in format %{export_format} is being generated
(ask %{export_time} ago)
- everything_ready_html: Download the export in format %{export_format}
(generated %{export_time} ago)
+ everything_csv_html: Request an export in .csv format
(only files, without repeatable fields)
+ everything_xlsx_html: Request an export in .xlsx format
+ everything_ods_html: Request an export in .ods format
+ everything_zip_html: Request an export in .zip format
(does not contains timestamp nor operation logs)
+ everything_json_html: Request an export in .json format (GeoJSON)
+ everything_short: Request an export in %{export_format} format
+ everything_pending_html: An export in %{export_format} format is being generated
(ask %{export_time} ago)
+ everything_ready_html: Download the export in %{export_format} format
(generated %{export_time} ago)
download_all: Download all files
download:
one: Download a file
diff --git a/app/components/dossiers/export_component/export_component.fr.yml b/app/components/dossiers/export_component/export_component.fr.yml
index 930d1598a..7895c00f3 100644
--- a/app/components/dossiers/export_component/export_component.fr.yml
+++ b/app/components/dossiers/export_component/export_component.fr.yml
@@ -4,6 +4,7 @@ fr:
everything_xlsx_html: Demander un export au format .xlsx
everything_ods_html: Demander un export au format .ods
everything_zip_html: Demander un export au format .zip
(ne contient pas l'horodatage ni le journal de log)
+ everything_json_html: Demander un export au format .json (GeoJSON)
everything_short: Demander un export au format %{export_format}
everything_pending_html: Un export au format %{export_format} est en train d’être généré
(demandé il y a %{export_time})
everything_ready_html: Télécharger l’export au format %{export_format}
(généré il y a %{export_time})
diff --git a/app/helpers/dossier_helper.rb b/app/helpers/dossier_helper.rb
index fc18c15d2..c51f4b5f8 100644
--- a/app/helpers/dossier_helper.rb
+++ b/app/helpers/dossier_helper.rb
@@ -96,26 +96,6 @@ module DossierHelper
"#{base_url}/rechercher?terme=#{siren_or_siret}"
end
- def exports_list(exports, statut = nil)
- if statut
- Export::FORMATS.map do |item|
- export = exports
- .fetch(item.fetch(:format))
- .fetch(:statut)
- .fetch(statut, nil)
- item.merge(export: export)
- end
- else
- Export::FORMATS_WITH_TIME_SPAN.map do |item|
- export = exports
- .fetch(item.fetch(:format))
- .fetch(:time_span_type)
- .fetch(item.fetch(:time_span_type), nil)
- item.merge(export: export)
- end
- end
- end
-
def france_connect_informations(user_information)
if user_information.full_name.empty?
t("shared.dossiers.france_connect_informations.details_no_name")
diff --git a/app/models/champ.rb b/app/models/champ.rb
index 7db57ccb9..3fc3b2bb4 100644
--- a/app/models/champ.rb
+++ b/app/models/champ.rb
@@ -61,6 +61,7 @@ class Champ < ApplicationRecord
:mesri?,
:rna?,
:siret?,
+ :carte?,
:stable_id,
:mandatory?,
to: :type_de_champ
diff --git a/app/models/dossier.rb b/app/models/dossier.rb
index 7599582e4..fea101a0f 100644
--- a/app/models/dossier.rb
+++ b/app/models/dossier.rb
@@ -1144,6 +1144,13 @@ class Dossier < ApplicationRecord
}
end
+ def self.to_feature_collection
+ {
+ type: 'FeatureCollection',
+ features: GeoArea.joins(:champ).where(champ: { dossier: ids }).map(&:to_feature)
+ }
+ end
+
def log_api_entreprise_job_exception(exception)
exceptions = self.api_entreprise_job_exceptions ||= []
exceptions << exception.inspect
diff --git a/app/models/export.rb b/app/models/export.rb
index 80fccbe1b..4f21b176d 100644
--- a/app/models/export.rb
+++ b/app/models/export.rb
@@ -23,7 +23,8 @@ class Export < ApplicationRecord
csv: 'csv',
ods: 'ods',
xlsx: 'xlsx',
- zip: 'zip'
+ zip: 'zip',
+ json: 'json'
}, _prefix: true
enum time_span_type: {
@@ -53,7 +54,7 @@ class Export < ApplicationRecord
FORMATS_WITH_TIME_SPAN = [:xlsx, :ods, :csv].flat_map do |format|
[{ format: format, time_span_type: 'everything' }]
end
- FORMATS = [:xlsx, :ods, :csv, :zip].map do |format|
+ FORMATS = [:xlsx, :ods, :csv, :zip, :json].map do |format|
{ format: format }
end
@@ -127,6 +128,10 @@ class Export < ApplicationRecord
zip: {
time_span_type: {},
statut: filtered.filter(&:format_zip?).index_by(&:statut)
+ },
+ json: {
+ time_span_type: {},
+ statut: filtered.filter(&:format_json?).index_by(&:statut)
}
}
end
@@ -195,6 +200,8 @@ class Export < ApplicationRecord
service.to_ods
when :zip
service.to_zip
+ when :json
+ service.to_geo_json
end
end
diff --git a/app/models/geo_area.rb b/app/models/geo_area.rb
index bb94da325..99e163400 100644
--- a/app/models/geo_area.rb
+++ b/app/models/geo_area.rb
@@ -64,7 +64,10 @@ class GeoArea < ApplicationRecord
description: description,
filename: filename,
id: id,
+ champ_label: champ.libelle,
champ_id: champ.stable_id,
+ champ_row: champ.row,
+ champ_private: champ.private?,
dossier_id: champ.dossier_id
).compact
}
diff --git a/app/models/procedure_revision.rb b/app/models/procedure_revision.rb
index aea71e8d4..8c550594b 100644
--- a/app/models/procedure_revision.rb
+++ b/app/models/procedure_revision.rb
@@ -200,6 +200,10 @@ class ProcedureRevision < ApplicationRecord
revision_types_de_champ.find_by!(type_de_champ: tdc)
end
+ def carte?
+ types_de_champ_public.any?(&:carte?)
+ end
+
private
def compute_estimated_fill_duration
diff --git a/app/services/procedure_export_service.rb b/app/services/procedure_export_service.rb
index 68a35a16c..def935f06 100644
--- a/app/services/procedure_export_service.rb
+++ b/app/services/procedure_export_service.rb
@@ -42,6 +42,11 @@ class ProcedureExportService
end
end
+ def to_geo_json
+ io = StringIO.new(dossiers.to_feature_collection.to_json)
+ create_blob(io, :json)
+ end
+
private
def create_blob(io, format)
@@ -77,6 +82,8 @@ class ProcedureExportService
'application/vnd.oasis.opendocument.spreadsheet'
when :zip
'application/zip'
+ when :json
+ 'application/json'
end
end
diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb
index 68f5739d8..956add7a1 100644
--- a/spec/models/dossier_spec.rb
+++ b/spec/models/dossier_spec.rb
@@ -1444,7 +1444,9 @@ describe Dossier do
},
properties: {
area: 103.6,
+ champ_label: champ_carte.libelle,
champ_id: champ_carte.stable_id,
+ champ_private: false,
dossier_id: dossier.id,
id: geo_area.id,
source: 'selection_utilisateur'
diff --git a/spec/models/export_spec.rb b/spec/models/export_spec.rb
index fb7f0831a..37a0508c8 100644
--- a/spec/models/export_spec.rb
+++ b/spec/models/export_spec.rb
@@ -61,9 +61,9 @@ RSpec.describe Export, type: :model do
context 'when an export is made for one groupe instructeur' do
let!(:export) { create(:export, groupe_instructeurs: [gi_1, gi_2]) }
- it { expect(Export.find_for_groupe_instructeurs([gi_1.id], nil)).to eq({ csv: { statut: {}, time_span_type: {} }, xlsx: { statut: {}, time_span_type: {} }, ods: { statut: {}, time_span_type: {} }, zip: { statut: {}, time_span_type: {} } }) }
- it { expect(Export.find_for_groupe_instructeurs([gi_2.id, gi_1.id], nil)).to eq({ csv: { statut: {}, time_span_type: { 'everything' => export } }, xlsx: { statut: {}, time_span_type: {} }, ods: { statut: {}, time_span_type: {} }, zip: { statut: {}, time_span_type: {} } }) }
- it { expect(Export.find_for_groupe_instructeurs([gi_1.id, gi_2.id, gi_3.id], nil)).to eq({ csv: { statut: {}, time_span_type: {} }, xlsx: { statut: {}, time_span_type: {} }, ods: { statut: {}, time_span_type: {} }, zip: { statut: {}, time_span_type: {} } }) }
+ it { expect(Export.find_for_groupe_instructeurs([gi_1.id], nil)).to eq({ csv: { statut: {}, time_span_type: {} }, xlsx: { statut: {}, time_span_type: {} }, ods: { statut: {}, time_span_type: {} }, zip: { statut: {}, time_span_type: {} }, json: { statut: {}, time_span_type: {} } }) }
+ it { expect(Export.find_for_groupe_instructeurs([gi_2.id, gi_1.id], nil)).to eq({ csv: { statut: {}, time_span_type: { 'everything' => export } }, xlsx: { statut: {}, time_span_type: {} }, ods: { statut: {}, time_span_type: {} }, zip: { statut: {}, time_span_type: {} }, json: { statut: {}, time_span_type: {} } }) }
+ it { expect(Export.find_for_groupe_instructeurs([gi_1.id, gi_2.id, gi_3.id], nil)).to eq({ csv: { statut: {}, time_span_type: {} }, xlsx: { statut: {}, time_span_type: {} }, ods: { statut: {}, time_span_type: {} }, zip: { statut: {}, time_span_type: {} }, json: { statut: {}, time_span_type: {} } }) }
end
end
@@ -78,7 +78,8 @@ RSpec.describe Export, type: :model do
csv: { statut: { Export.statuts.fetch(:suivis) => export_with_filter }, time_span_type: { 'everything' => export_global } },
xlsx: { statut: {}, time_span_type: {} },
ods: { statut: {}, time_span_type: {} },
- zip: { statut: {}, time_span_type: {} }
+ zip: { statut: {}, time_span_type: {} },
+ json: { statut: {}, time_span_type: {} }
})
end
end
diff --git a/spec/services/procedure_export_service_spec.rb b/spec/services/procedure_export_service_spec.rb
index 040a7f84e..a084e3410 100644
--- a/spec/services/procedure_export_service_spec.rb
+++ b/spec/services/procedure_export_service_spec.rb
@@ -467,4 +467,27 @@ describe ProcedureExportService do
end
end
end
+
+ describe 'to_geo_json' do
+ subject do
+ service
+ .to_geo_json
+ .open { |f| JSON.parse(f.read) }
+ end
+
+ let(:dossier) { create(:dossier, :en_instruction, :with_populated_champs, :with_individual, procedure: procedure) }
+ let(:champ_carte) { dossier.champs_public.find(&:carte?) }
+ let(:properties) { subject['features'].first['properties'] }
+
+ before do
+ create(:geo_area, :polygon, champ: champ_carte)
+ end
+
+ it 'should have features' do
+ expect(subject['features'].size).to eq(1)
+ expect(properties['dossier_id']).to eq(dossier.id)
+ expect(properties['champ_id']).to eq(champ_carte.stable_id)
+ expect(properties['champ_label']).to eq(champ_carte.libelle)
+ end
+ end
end