diff --git a/app/components/dossiers/export_component/export_component.html.haml b/app/components/dossiers/export_component/export_component.html.haml deleted file mode 100644 index e4e2be3e2..000000000 --- a/app/components/dossiers/export_component/export_component.html.haml +++ /dev/null @@ -1,29 +0,0 @@ -= render Dropdown::MenuComponent.new(wrapper: :span, button_options: { class: ['fr-btn--sm', @class_btn.present? ? @class_btn : 'fr-btn--secondary']}, menu_options: { id: @count.nil? ? "download_menu" : "download_all_menu", class: ['dropdown-export'] }) do |menu| - - menu.with_menu_header_html do - %p.menu-component-header.fr-px-2w.fr-pt-2w.fr-mb-0 - %span.fr-icon-info-line{ aria: { hidden: true } } - Des macros ? Lisez la - = link_to('doc', t('.macros_doc.url'), - title: t('.macros_doc.title'), - **external_link_attributes) - - - menu.with_button_inner_html do - = @count.nil? ? t(".download_all") : t(".download", count: @count) - - exports.each do |item| - - export = item[:export] - - - if export.nil? - - menu.with_item do - = link_to download_export_path(export_format: item[:format]), role: 'menuitem', data: { turbo_method: :post, turbo: true } do - = t(".everything_#{item[:format]}_html") - - elsif export.available? - - menu.with_item do - %div - = link_to ready_link_label(export), export.file.url, target: "_blank", rel: "noopener", role: 'menuitem' - - if export.old? - = button_to download_export_path(export_format: export.format, force_export: true), refresh_button_options(export).merge(role: 'menuitem') do - .icon.retry - - else - - menu.with_item(aria: {disabled:"true"}, class: 'selected') do - %span{ data: poll_controller_options(export) } - = pending_label(export) diff --git a/app/components/dossiers/export_dropdown_component.rb b/app/components/dossiers/export_dropdown_component.rb new file mode 100644 index 000000000..82a78db45 --- /dev/null +++ b/app/components/dossiers/export_dropdown_component.rb @@ -0,0 +1,44 @@ +class Dossiers::ExportDropdownComponent < ApplicationComponent + include ApplicationHelper + + def initialize(procedure:, exports:, statut: nil, count: nil, class_btn: nil, export_url: nil) + @procedure = procedure + @exports = exports + @statut = statut + @count = count + @class_btn = class_btn + @export_url = export_url + end + + def exports + 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) + @export_url.call(@procedure, + export_format: export_format, + statut: @statut, + force_export: force_export, + no_progress_notification: no_progress_notification) + end +end diff --git a/app/components/dossiers/export_component/export_component.en.yml b/app/components/dossiers/export_dropdown_component/export_dropdown_component.en.yml similarity index 76% rename from app/components/dossiers/export_component/export_component.en.yml rename to app/components/dossiers/export_dropdown_component/export_dropdown_component.en.yml index ecc660050..d48aa0879 100644 --- a/app/components/dossiers/export_component/export_component.en.yml +++ b/app/components/dossiers/export_dropdown_component/export_dropdown_component.en.yml @@ -6,8 +6,6 @@ en: 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_dropdown_component/export_dropdown_component.fr.yml b/app/components/dossiers/export_dropdown_component/export_dropdown_component.fr.yml new file mode 100644 index 000000000..d5646ce34 --- /dev/null +++ b/app/components/dossiers/export_dropdown_component/export_dropdown_component.fr.yml @@ -0,0 +1,15 @@ +--- +fr: + everything_csv_html: Demander un export au format .csv
(uniquement les dossiers, sans les champs répétables) + 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} + download_all: Télécharger tous les dossiers + download: + one: Télécharger un dossier + other: Télécharger %{count} dossiers + macros_doc: + title: "documentation sur les macros" + url: "https://doc.demarches-simplifiees.fr/pour-aller-plus-loin/exports-et-macros" diff --git a/app/components/dossiers/export_dropdown_component/export_dropdown_component.html.haml b/app/components/dossiers/export_dropdown_component/export_dropdown_component.html.haml new file mode 100644 index 000000000..346d12bc9 --- /dev/null +++ b/app/components/dossiers/export_dropdown_component/export_dropdown_component.html.haml @@ -0,0 +1,18 @@ += render Dropdown::MenuComponent.new(wrapper: :span, button_options: { class: ['fr-btn--sm', @class_btn.present? ? @class_btn : 'fr-btn--secondary']}, menu_options: { id: @count.nil? ? "download_menu" : "download_all_menu", class: ['dropdown-export'] }) do |menu| + - menu.with_menu_header_html do + %p.menu-component-header.fr-px-2w.fr-pt-2w.fr-mb-0 + %span.fr-icon-info-line{ aria: { hidden: true } } + Des macros ? Lisez la + = link_to('doc', t('.macros_doc.url'), + title: t('.macros_doc.title'), + **external_link_attributes) + + - menu.with_button_inner_html do + = @count.nil? ? t(".download_all") : t(".download", count: @count) + + - exports.each do |item| + - export = item[:export] + + - menu.with_item do + = link_to download_export_path(export_format: item[:format]), role: 'menuitem', data: { turbo_method: :post, turbo: true } do + = t(".everything_#{item[:format]}_html") diff --git a/app/components/dossiers/export_component.rb b/app/components/dossiers/export_link_component.rb similarity index 63% rename from app/components/dossiers/export_component.rb rename to app/components/dossiers/export_link_component.rb index bb955c21e..95f0b04a9 100644 --- a/app/components/dossiers/export_component.rb +++ b/app/components/dossiers/export_link_component.rb @@ -1,4 +1,4 @@ -class Dossiers::ExportComponent < ApplicationComponent +class Dossiers::ExportLinkComponent < ApplicationComponent include ApplicationHelper def initialize(procedure:, exports:, statut: nil, count: nil, class_btn: nil, export_url: nil) @@ -10,26 +10,6 @@ class Dossiers::ExportComponent < ApplicationComponent @export_url = export_url end - def exports - 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 @@ -44,24 +24,33 @@ class Dossiers::ExportComponent < ApplicationComponent def refresh_button_options(export) { - title: t(".everything_short", export_format: ".#{export.format}"), - class: "button small", - style: "padding-right: 2px" + title: t(".refresh_old_export", export_format: ".#{export.format}"), + class: "fr-btn fr-btn--sm fr-icon-refresh-line fr-btn--icon-left fr-btn--tertiary fr-mt-1w" } end def ready_link_label(export) - t(".everything_ready_html", - export_time: helpers.time_ago_in_words(export.updated_at), + t(".everything_ready", export_format: ".#{export.format}") end + def ready_link_label_extra_infos(export) + t(".ready_link_label_extra_infos", + export_time: helpers.time_ago_in_words(export.updated_at), + export_tabs: export.statut.to_s) + end + def pending_label(export) t(".everything_pending_html", export_time: time_ago_in_words(export.created_at), export_format: ".#{export.format}") end + def failed_label(export) + t(".failed_label", + export_format: ".#{export.format}") + end + def poll_controller_options(export) { controller: 'turbo-poll', diff --git a/app/components/dossiers/export_link_component/export_link_component.en.yml b/app/components/dossiers/export_link_component/export_link_component.en.yml new file mode 100644 index 000000000..aebacc6c5 --- /dev/null +++ b/app/components/dossiers/export_link_component/export_link_component.en.yml @@ -0,0 +1,20 @@ +--- +en: + 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 + refresh_old_export: Recreate this export + everything_pending_html: An export in %{export_format} format is being generated
(ask %{export_time} ago) + everything_ready: Download the export in %{export_format} format + failed_label: The export in %{export_format} format has failed + ready_link_label_extra_infos: generated %{export_time} ago, for files "%{export_tabs}" + download_all: Download all files + download: + one: Download a file + other: Download %{count} files + macros_doc: + title: "Macros documentation" + url: "https://doc.demarches-simplifiees.fr/pour-aller-plus-loin/exports-et-macros" diff --git a/app/components/dossiers/export_component/export_component.fr.yml b/app/components/dossiers/export_link_component/export_link_component.fr.yml similarity index 75% rename from app/components/dossiers/export_component/export_component.fr.yml rename to app/components/dossiers/export_link_component/export_link_component.fr.yml index c89310c89..b1f98ba98 100644 --- a/app/components/dossiers/export_component/export_component.fr.yml +++ b/app/components/dossiers/export_link_component/export_link_component.fr.yml @@ -6,8 +6,11 @@ fr: 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} + refresh_old_export: Recréer cet export 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}) + everything_ready: Télécharger l’export au format %{export_format} + failed_label: L’export au format %{export_format}, n'a pas fonctionné + ready_link_label_extra_infos: généré il y a %{export_time} pour les dossiers "%{export_tabs}" download_all: Télécharger tous les dossiers download: one: Télécharger un dossier diff --git a/app/components/dossiers/export_link_component/export_link_component.html.haml b/app/components/dossiers/export_link_component/export_link_component.html.haml new file mode 100644 index 000000000..eddcc9298 --- /dev/null +++ b/app/components/dossiers/export_link_component/export_link_component.html.haml @@ -0,0 +1,16 @@ +%ul + - @exports.each do |export| + - if export.available? + %li.fr-mb-2w + = link_to ready_link_label(export), export.file.url, target: "_blank", rel: "noopener", role: 'menuitem' + %span= ready_link_label_extra_infos(export) + - if export.old? + = button_to refresh_button_options(export)[:title], download_export_path(export_format: export.format, force_export: true), refresh_button_options(export).merge(role: 'menuitem') + - elsif export.failed? + %li.fr-mb-2w + = failed_label(export) + = button_to refresh_button_options(export)[:title], download_export_path(export_format: export.format, force_export: true), refresh_button_options(export).merge(role: 'menuitem') + - else + %li.fr-mb-2w + %span{ data: poll_controller_options(export) } + = pending_label(export) diff --git a/app/controllers/instructeurs/procedures_controller.rb b/app/controllers/instructeurs/procedures_controller.rb index 2ba73e1ad..880c000a9 100644 --- a/app/controllers/instructeurs/procedures_controller.rb +++ b/app/controllers/instructeurs/procedures_controller.rb @@ -226,6 +226,11 @@ module Instructeurs @usual_traitement_time_by_month = @procedure.stats_usual_traitement_time_by_month_in_days end + def exports + @procedure = procedure + @exports = Export.find_all_exports_for_groupe_instructeurs(groupe_instructeur_ids) + end + def email_usagers @procedure = procedure @bulk_messages = BulkMessage.includes(:groupe_instructeurs).where(groupe_instructeurs: { procedure: procedure }) diff --git a/app/models/export.rb b/app/models/export.rb index f5fcab31c..e49c7f281 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -88,6 +88,10 @@ class Export < ApplicationRecord end end + def self.find_all_exports_for_groupe_instructeurs(groupe_instructeurs_ids) + joins(:groupe_instructeurs).where(groupe_instructeurs: groupe_instructeurs_ids) + end + def self.find_for_groupe_instructeurs(groupe_instructeurs_ids, procedure_presentation) exports = if procedure_presentation.present? where(key: generate_cache_key(groupe_instructeurs_ids, procedure_presentation)) diff --git a/app/views/administrateurs/archives/index.html.haml b/app/views/administrateurs/archives/index.html.haml index b98f6f1f8..c66fb3358 100644 --- a/app/views/administrateurs/archives/index.html.haml +++ b/app/views/administrateurs/archives/index.html.haml @@ -8,7 +8,7 @@ %h1.mb-2 Archives -# index not renderable as administrateur flagged as manager, so render it anyway - = render Dossiers::ExportComponent.new(procedure: @procedure, exports: @exports, export_url: method(:download_admin_procedure_exports_path)) + = render Dossiers::ExportDropdownComponent.new(procedure: @procedure, exports: @exports, export_url: method(:download_admin_procedure_exports_path)) = render partial: "shared/archives/notice" = render partial: "shared/archives/table", locals: {count_dossiers_termines_by_month: @count_dossiers_termines_by_month, archives: @archives, average_dossier_weight: @average_dossier_weight, procedure: @procedure } diff --git a/app/views/administrateurs/exports/download.turbo_stream.haml b/app/views/administrateurs/exports/download.turbo_stream.haml index 4f160d415..9847d4718 100644 --- a/app/views/administrateurs/exports/download.turbo_stream.haml +++ b/app/views/administrateurs/exports/download.turbo_stream.haml @@ -1,4 +1,4 @@ -# not renderable as administrateur flagged as manager, so render it anyway - if @can_download_dossiers = turbo_stream.update_all '.procedure-actions' do - = render Dossiers::ExportComponent.new(procedure: @procedure, exports: @exports, count: @dossiers_count, export_url: method(:admin_procedure_exports_path)) + = render Dossiers::ExportDropdownComponent.new(procedure: @procedure, exports: @exports, count: @dossiers_count, export_url: method(:admin_procedure_exports_path)) diff --git a/app/views/instructeurs/procedures/_header.html.haml b/app/views/instructeurs/procedures/_header.html.haml index 6a9a87f54..f4c81264f 100644 --- a/app/views/instructeurs/procedures/_header.html.haml +++ b/app/views/instructeurs/procedures/_header.html.haml @@ -22,3 +22,5 @@ | = link_to t('instructeurs.dossiers.header.banner.administrators_list'), administrateurs_instructeur_procedure_path(procedure), class: 'header-link' + | + = link_to t('instructeurs.dossiers.header.banner.exports_list'), exports_instructeur_procedure_path(procedure), class: 'header-link' diff --git a/app/views/instructeurs/procedures/deleted_dossiers.html.haml b/app/views/instructeurs/procedures/deleted_dossiers.html.haml index 05c209457..5ae0ed543 100644 --- a/app/views/instructeurs/procedures/deleted_dossiers.html.haml +++ b/app/views/instructeurs/procedures/deleted_dossiers.html.haml @@ -11,7 +11,7 @@ .procedure-actions - if @can_download_dossiers - = render Dossiers::ExportComponent.new(procedure: @procedure, exports: @exports, export_url: method(:download_export_instructeur_procedure_path)) + = render Dossiers::ExportDropdownComponent.new(procedure: @procedure, exports: @exports, export_url: method(:download_export_instructeur_procedure_path)) .fr-container.flex= render partial: "tabs", locals: { procedure: @procedure, statut: @statut, diff --git a/app/views/instructeurs/procedures/download_export.turbo_stream.haml b/app/views/instructeurs/procedures/download_export.turbo_stream.haml index f124bd379..0da0725fa 100644 --- a/app/views/instructeurs/procedures/download_export.turbo_stream.haml +++ b/app/views/instructeurs/procedures/download_export.turbo_stream.haml @@ -2,7 +2,7 @@ - if @can_download_dossiers - if @statut.nil? = turbo_stream.update_all '.procedure-actions' do - = render Dossiers::ExportComponent.new(procedure: @procedure, exports: @exports, export_url: method(:download_export_instructeur_procedure_path)) + = render Dossiers::ExportDropdownComponent.new(procedure: @procedure, exports: @exports, export_url: method(:download_export_instructeur_procedure_path)) - else = turbo_stream.update_all '.dossiers-export' do - = render Dossiers::ExportComponent.new(procedure: @procedure, exports: @exports, statut: @statut, count: @dossiers_count, export_url: method(:download_export_instructeur_procedure_path)) + = render Dossiers::ExportDropdownComponent.new(procedure: @procedure, exports: @exports, statut: @statut, count: @dossiers_count, export_url: method(:download_export_instructeur_procedure_path)) diff --git a/app/views/instructeurs/procedures/exports.html.haml b/app/views/instructeurs/procedures/exports.html.haml new file mode 100644 index 000000000..ff86e94d0 --- /dev/null +++ b/app/views/instructeurs/procedures/exports.html.haml @@ -0,0 +1,14 @@ +- title = "Exports · #{@procedure.libelle}" +- content_for(:title, title) + += render partial: 'administrateurs/breadcrumbs', + locals: { steps: [[@procedure.libelle.truncate_words(10), instructeur_procedure_path(@procedure)], + [t('.title')]] } + +.fr-container + %h1= title + - if @exports.present? + = render Dossiers::ExportLinkComponent.new(procedure: @procedure, exports: @exports, statut: @statut, count: @dossiers_count, class_btn: 'fr-btn--tertiary', export_url: method(:download_export_instructeur_procedure_path)) + + - else + = t('.no_export_html', expiration_time: Export::MAX_DUREE_CONSERVATION_EXPORT.in_hours.to_i ) diff --git a/app/views/instructeurs/procedures/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index 19228faaa..8c256b9bb 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -11,7 +11,7 @@ .procedure-actions - if @can_download_dossiers - = render Dossiers::ExportComponent.new(procedure: @procedure, exports: @exports, export_url: method(:download_export_instructeur_procedure_path)) + = render Dossiers::ExportDropdownComponent.new(procedure: @procedure, exports: @exports, export_url: method(:download_export_instructeur_procedure_path)) .fr-container.flex= render partial: "tabs", locals: { procedure: @procedure, statut: @statut, @@ -72,7 +72,7 @@ - if @dossiers_count > 0 %span.dossiers-export - = render Dossiers::ExportComponent.new(procedure: @procedure, exports: @exports, statut: @statut, count: @dossiers_count, class_btn: 'fr-btn--tertiary', export_url: method(:download_export_instructeur_procedure_path)) + = render Dossiers::ExportDropdownComponent.new(procedure: @procedure, exports: @exports, statut: @statut, count: @dossiers_count, class_btn: 'fr-btn--tertiary', export_url: method(:download_export_instructeur_procedure_path)) - if @filtered_sorted_paginated_ids.present? || @current_filters.count > 0 = render partial: "dossiers_filter_tags", locals: { procedure: @procedure, procedure_presentation: @procedure_presentation, current_filters: @current_filters, statut: @statut } diff --git a/app/views/layouts/application.turbo_stream.haml b/app/views/layouts/application.turbo_stream.haml index accaad848..c359b707a 100644 --- a/app/views/layouts/application.turbo_stream.haml +++ b/app/views/layouts/application.turbo_stream.haml @@ -1,5 +1,6 @@ - if flash.any? = turbo_stream.replace 'flash_messages', partial: 'layouts/flash_messages' + = turbo_stream.show 'flash_messages' = turbo_stream.hide 'flash_messages', delay: 30000 - flash.clear diff --git a/config/locales/views/instructeurs/header/en.yml b/config/locales/views/instructeurs/header/en.yml index 48999fbce..dd9c5a960 100644 --- a/config/locales/views/instructeurs/header/en.yml +++ b/config/locales/views/instructeurs/header/en.yml @@ -12,6 +12,7 @@ en: button_delay_expiration: "Keep for one more month" notification_management: notification management administrators_list: administrators list + exports_list: exports list statistics: statistics instructeurs: instructors contact_users: contact users (draft) diff --git a/config/locales/views/instructeurs/header/fr.yml b/config/locales/views/instructeurs/header/fr.yml index f8396928a..d7fbf0df4 100644 --- a/config/locales/views/instructeurs/header/fr.yml +++ b/config/locales/views/instructeurs/header/fr.yml @@ -12,6 +12,7 @@ fr: button_delay_expiration: "Conserver un mois de plus" notification_management: gestion des notifications administrators_list: voir les administrateurs + exports_list: voir les exports statistics: statistiques instructeurs: instructeurs contact_users: contacter les usagers (brouillon) diff --git a/config/locales/views/instructeurs/procedures/en.yml b/config/locales/views/instructeurs/procedures/en.yml index 987287ab2..84a1a8c1f 100644 --- a/config/locales/views/instructeurs/procedures/en.yml +++ b/config/locales/views/instructeurs/procedures/en.yml @@ -23,3 +23,5 @@ en: title: "%{procedure_libelle} - n°%{procedure_id} - administrators" stats: title: Statistics + exports: + title: Exports diff --git a/config/locales/views/instructeurs/procedures/exports/en.yml b/config/locales/views/instructeurs/procedures/exports/en.yml new file mode 100644 index 000000000..3a825a784 --- /dev/null +++ b/config/locales/views/instructeurs/procedures/exports/en.yml @@ -0,0 +1,5 @@ +en: + instructeurs: + procedures: + exports: + no_export_html: You have no export at the moment.
Can't find an export? It may have expired, exports are deleted after %{expiration_time} hours. diff --git a/config/locales/views/instructeurs/procedures/exports/fr.yml b/config/locales/views/instructeurs/procedures/exports/fr.yml new file mode 100644 index 000000000..d5eb75d6e --- /dev/null +++ b/config/locales/views/instructeurs/procedures/exports/fr.yml @@ -0,0 +1,5 @@ +fr: + instructeurs: + procedures: + exports: + no_export_html: Vous n'avez pas d'export pour le moment.
Vous ne trouvez pas un export ? Il a peut-être expiré, les exports sont supprimés au bout de %{expiration_time} heures. diff --git a/config/locales/views/instructeurs/procedures/fr.yml b/config/locales/views/instructeurs/procedures/fr.yml index b2e035019..633954027 100644 --- a/config/locales/views/instructeurs/procedures/fr.yml +++ b/config/locales/views/instructeurs/procedures/fr.yml @@ -23,3 +23,5 @@ fr: title: "%{procedure_libelle} - n°%{procedure_id} - administrateurs" stats: title: Statistiques + exports: + title: Exports diff --git a/config/routes.rb b/config/routes.rb index 090f27d27..c6f1af9a6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -415,6 +415,7 @@ Rails.application.routes.draw do get 'download_export' post 'download_export' get 'stats' + get 'exports' get 'email_notifications' get 'administrateurs' patch 'update_email_notifications'