Merge pull request #6628 from betagouv/feat/6536
ETQ usager, je veux pouvoir supprimer les dossiers terminés
This commit is contained in:
commit
783b0ed9f0
16 changed files with 135 additions and 51 deletions
|
@ -83,3 +83,11 @@
|
|||
width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
.file-hidden-by-user {
|
||||
background-color: rgba(242, 137, 0, 0.6);
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(242, 137, 0, 0.6) !important;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@ module Users
|
|||
before_action :store_user_location!, only: :new
|
||||
|
||||
def index
|
||||
@user_dossiers = current_user.dossiers.includes(:procedure).order_by_updated_at.page(page)
|
||||
@user_dossiers = current_user.dossiers.includes(:procedure).not_termine.order_by_updated_at.page(page)
|
||||
@dossiers_traites = current_user.dossiers.includes(:procedure).termine.not_hidden_by_user.order_by_updated_at.page(page)
|
||||
@dossiers_invites = current_user.dossiers_invites.includes(:procedure).order_by_updated_at.page(page)
|
||||
@dossiers_supprimes = current_user.deleted_dossiers.order_by_updated_at.page(page)
|
||||
@dossier_transfers = DossierTransfer
|
||||
|
@ -25,7 +26,7 @@ module Users
|
|||
.where(email: current_user.email)
|
||||
.page(page)
|
||||
@dossiers_close_to_expiration = current_user.dossiers.close_to_expiration.page(page)
|
||||
@statut = statut(@user_dossiers, @dossiers_invites, @dossiers_supprimes, @dossier_transfers, @dossiers_close_to_expiration, params[:statut])
|
||||
@statut = statut(@user_dossiers, @dossiers_traites, @dossiers_invites, @dossiers_supprimes, @dossier_transfers, @dossiers_close_to_expiration, params[:statut])
|
||||
end
|
||||
|
||||
def show
|
||||
|
@ -287,14 +288,22 @@ module Users
|
|||
@transfer = DossierTransfer.new(dossiers: current_user.dossiers)
|
||||
end
|
||||
|
||||
def hide_dossier
|
||||
dossier = current_user.dossiers.includes(:user, procedure: :administrateurs).find(params[:id])
|
||||
dossier.update(hidden_by_user_at: Time.zone.now)
|
||||
flash.notice = t('users.dossiers.ask_deletion.deleted_dossier')
|
||||
redirect_to dossiers_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# if the status tab is filled, then this tab
|
||||
# else first filled tab
|
||||
# else mes-dossiers
|
||||
def statut(mes_dossiers, dossiers_invites, dossiers_supprimes, dossier_transfers, dossiers_close_to_expiration, params_statut)
|
||||
# else en-cours
|
||||
def statut(mes_dossiers, dossiers_traites, dossiers_invites, dossiers_supprimes, dossier_transfers, dossiers_close_to_expiration, params_statut)
|
||||
tabs = {
|
||||
'mes-dossiers' => mes_dossiers.present?,
|
||||
'en-cours' => mes_dossiers.present?,
|
||||
'traites' => dossiers_traites.present?,
|
||||
'dossiers-invites' => dossiers_invites.present?,
|
||||
'dossiers-supprimes' => dossiers_supprimes.present?,
|
||||
'dossiers-transferes' => dossier_transfers.present?,
|
||||
|
@ -306,7 +315,7 @@ module Users
|
|||
tabs
|
||||
.filter { |_tab, filled| filled }
|
||||
.map { |tab, _| tab }
|
||||
.first || 'mes-dossiers'
|
||||
.first || 'en-cours'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
# en_instruction_at :datetime
|
||||
# groupe_instructeur_updated_at :datetime
|
||||
# hidden_at :datetime
|
||||
# hidden_by_user_at :datetime
|
||||
# identity_updated_at :datetime
|
||||
# last_avis_updated_at :datetime
|
||||
# last_champ_private_updated_at :datetime
|
||||
|
@ -206,9 +207,11 @@ class Dossier < ApplicationRecord
|
|||
scope :state_en_construction_ou_instruction, -> { where(state: EN_CONSTRUCTION_OU_INSTRUCTION) }
|
||||
scope :state_instruction_commencee, -> { where(state: INSTRUCTION_COMMENCEE) }
|
||||
scope :state_termine, -> { where(state: TERMINE) }
|
||||
scope :state_not_termine, -> { where.not(state: TERMINE) }
|
||||
|
||||
scope :archived, -> { where(archived: true) }
|
||||
scope :not_archived, -> { where(archived: false) }
|
||||
scope :not_hidden_by_user, -> { where(hidden_by_user_at: nil) }
|
||||
|
||||
scope :order_by_updated_at, -> (order = :desc) { order(updated_at: order) }
|
||||
scope :order_by_created_at, -> (order = :asc) { order(en_construction_at: order, created_at: order, id: order) }
|
||||
|
@ -229,6 +232,7 @@ class Dossier < ApplicationRecord
|
|||
scope :en_construction, -> { not_archived.state_en_construction }
|
||||
scope :en_instruction, -> { not_archived.state_en_instruction }
|
||||
scope :termine, -> { not_archived.state_termine }
|
||||
scope :not_termine, -> { state_not_termine }
|
||||
scope :processed_in_month, -> (month) do
|
||||
state_termine
|
||||
.joins(:traitements)
|
||||
|
@ -1091,6 +1095,10 @@ class Dossier < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def hidden_by_user?
|
||||
self.hidden_by_user_at.present?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_missing_traitemets
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class DossierProjectionService
|
||||
class DossierProjection < Struct.new(:dossier_id, :state, :archived, :columns)
|
||||
class DossierProjection < Struct.new(:dossier_id, :state, :archived, :hidden_by_user_at, :columns)
|
||||
end
|
||||
|
||||
TABLE = 'table'
|
||||
|
@ -20,8 +20,9 @@ class DossierProjectionService
|
|||
def self.project(dossiers_ids, fields)
|
||||
state_field = { TABLE => 'self', COLUMN => 'state' }
|
||||
archived_field = { TABLE => 'self', COLUMN => 'archived' }
|
||||
hidden_by_user_at_field = { TABLE => 'self', COLUMN => 'hidden_by_user_at' }
|
||||
|
||||
([state_field, archived_field] + fields) # the view needs state and archived dossier attributes
|
||||
([state_field, archived_field, hidden_by_user_at_field] + fields) # the view needs state and archived dossier attributes
|
||||
.each { |f| f[:id_value_h] = {} }
|
||||
.group_by { |f| f[TABLE] } # one query per table
|
||||
.each do |table, fields|
|
||||
|
@ -45,7 +46,7 @@ class DossierProjectionService
|
|||
.pluck(:id, *fields.map { |f| f[COLUMN].to_sym })
|
||||
.each do |id, *columns|
|
||||
fields.zip(columns).each do |field, value|
|
||||
if [state_field, archived_field].include?(field)
|
||||
if [state_field, archived_field, hidden_by_user_at_field].include?(field)
|
||||
field[:id_value_h][id] = value
|
||||
else
|
||||
field[:id_value_h][id] = value&.strftime('%d/%m/%Y') # other fields are datetime
|
||||
|
@ -98,6 +99,7 @@ class DossierProjectionService
|
|||
dossier_id,
|
||||
state_field[:id_value_h][dossier_id],
|
||||
archived_field[:id_value_h][dossier_id],
|
||||
hidden_by_user_at_field[:id_value_h][dossier_id],
|
||||
fields.map { |f| f[:id_value_h][dossier_id] }
|
||||
)
|
||||
end
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
= link_to t('views.shared.account.already_user'), commencer_sign_in_path(path: @procedure.path), class: ['button large expand']
|
||||
|
||||
- else
|
||||
- dossiers = current_user.dossiers.where(revision: @revision.draft? ? @revision : @procedure.revisions.where.not(id: @procedure.draft_revision_id))
|
||||
- dossiers = current_user.dossiers.where(hidden_by_user_at: nil, revision: @revision.draft? ? @revision : @procedure.revisions.where.not(id: @procedure.draft_revision_id))
|
||||
- drafts = dossiers.merge(Dossier.state_brouillon)
|
||||
- not_drafts = dossiers.merge(Dossier.state_not_brouillon)
|
||||
|
||||
|
|
|
@ -100,8 +100,7 @@
|
|||
%tbody
|
||||
- @projected_dossiers.each do |p|
|
||||
- path = instructeur_dossier_path(@procedure, p.dossier_id)
|
||||
|
||||
%tr
|
||||
%tr{ class: [p.hidden_by_user_at.present? && "file-hidden-by-user"] }
|
||||
%td.folder-col
|
||||
%a.cell-link{ href: path }
|
||||
%span.icon.folder
|
||||
|
@ -113,7 +112,9 @@
|
|||
|
||||
- p.columns.each do |column|
|
||||
%td
|
||||
%a.cell-link{ href: path }= column
|
||||
%a.cell-link{ href: path }
|
||||
= column
|
||||
= "- #{t('views.instructeurs.dossiers.deleted_by_user')}" if p.hidden_by_user_at.present?
|
||||
|
||||
%td.status-col
|
||||
%a.cell-link{ href: path }= status_badge(p.state)
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
- has_delete_action = dossier.can_be_deleted_by_user?
|
||||
- has_new_dossier_action = dossier.procedure.accepts_new_dossiers?
|
||||
- has_transfer_action = dossier.user == current_user
|
||||
- has_actions = has_edit_action || has_delete_action || has_new_dossier_action || has_transfer_action
|
||||
- has_hide_action = dossier.termine? && dossier.hidden_by_user_at.nil?
|
||||
- has_actions = has_edit_action || has_delete_action || has_new_dossier_action || has_transfer_action || has_hide_action
|
||||
|
||||
- if has_actions
|
||||
.dropdown.user-dossier-actions
|
||||
|
@ -44,3 +45,10 @@
|
|||
%span.icon.delete
|
||||
.dropdown-description
|
||||
= t('views.users.dossiers.dossier_action.delete_dossier')
|
||||
- if has_hide_action
|
||||
%li
|
||||
= link_to hide_dossier_dossier_path(dossier), method: :patch do
|
||||
%span.icon.delete
|
||||
.dropdown-description
|
||||
= t('views.users.dossiers.dossier_action.hide_dossier')
|
||||
|
||||
|
|
|
@ -15,25 +15,31 @@
|
|||
- else
|
||||
%h1.page-title= t('views.users.dossiers.index.dossiers')
|
||||
%ul.tabs
|
||||
- if @user_dossiers.count > 0
|
||||
= tab_item(t('pluralize.mes_dossiers', count: @user_dossiers.count),
|
||||
dossiers_path(statut: 'mes-dossiers'),
|
||||
active: @statut == 'mes-dossiers',
|
||||
- if @user_dossiers.present?
|
||||
= tab_item(t('pluralize.en_cours', count: @user_dossiers.count),
|
||||
dossiers_path(statut: 'en-cours'),
|
||||
active: @statut == 'en-cours',
|
||||
badge: number_with_html_delimiter(@user_dossiers.count))
|
||||
|
||||
- if @dossiers_invites.count > 0
|
||||
- if @dossiers_traites.present?
|
||||
= tab_item(t('pluralize.traites', count: @dossiers_traites.count),
|
||||
dossiers_path(statut: 'traites'),
|
||||
active: @statut == 'traites',
|
||||
badge: number_with_html_delimiter(@dossiers_traites.count))
|
||||
|
||||
- if @dossiers_invites.present?
|
||||
= tab_item(t('pluralize.dossiers_invites', count: @dossiers_invites.count),
|
||||
dossiers_path(statut: 'dossiers-invites'),
|
||||
active: @statut == 'dossiers-invites',
|
||||
badge: number_with_html_delimiter(@dossiers_invites.count))
|
||||
|
||||
- if @dossiers_supprimes.count > 0
|
||||
- if @dossiers_supprimes.present?
|
||||
= tab_item(t('pluralize.dossiers_supprimes', count: @dossiers_supprimes.count),
|
||||
dossiers_path(statut: 'dossiers-supprimes'),
|
||||
active: @statut == 'dossiers-supprimes',
|
||||
badge: number_with_html_delimiter(@dossiers_supprimes.count))
|
||||
|
||||
- if @dossier_transfers.count > 0
|
||||
- if @dossier_transfers.present?
|
||||
= tab_item(t('pluralize.dossiers_transferes', count: @dossier_transfers.count),
|
||||
dossiers_path(statut: 'dossiers-transferes'),
|
||||
active: @statut == 'dossiers-transferes',
|
||||
|
@ -46,9 +52,12 @@
|
|||
badge: number_with_html_delimiter(@dossiers_close_to_expiration.count))
|
||||
|
||||
.container
|
||||
- if @statut == "mes-dossiers"
|
||||
- if @statut == "en-cours"
|
||||
= render partial: "dossiers_list", locals: { dossiers: @user_dossiers }
|
||||
|
||||
- if @statut == "traites"
|
||||
= render partial: "dossiers_list", locals: { dossiers: @dossiers_traites }
|
||||
|
||||
- if @statut == "dossiers-invites"
|
||||
= render partial: "dossiers_list", locals: { dossiers: @dossiers_invites }
|
||||
|
||||
|
|
|
@ -132,6 +132,9 @@ en:
|
|||
form: "Form"
|
||||
edit_siret: "Edit SIRET"
|
||||
edit_identity: "Edit identity data"
|
||||
instructeurs:
|
||||
dossiers:
|
||||
deleted_by_user: "File deleted by user"
|
||||
users:
|
||||
dossiers:
|
||||
autosave:
|
||||
|
@ -191,6 +194,7 @@ en:
|
|||
edit_dossier: "Edit the file"
|
||||
start_other_dossier: "Start an other file"
|
||||
delete_dossier: "Delete the file"
|
||||
hide_dossier: "Delete from your screen"
|
||||
transfer_dossier: "Transfer the file"
|
||||
edit_draft: "Edit the draft"
|
||||
actions: "Actions"
|
||||
|
@ -326,10 +330,14 @@ en:
|
|||
zero: archived
|
||||
one: archived
|
||||
other: archived
|
||||
mes_dossiers:
|
||||
zero: my file
|
||||
one: my file
|
||||
other: my files
|
||||
en_cours:
|
||||
zero: in progress
|
||||
one: in progress
|
||||
other: in progress
|
||||
traites:
|
||||
zero: finished
|
||||
one: finished
|
||||
other: finished
|
||||
dossiers_invites:
|
||||
zero: guest file
|
||||
one: guest file
|
||||
|
|
|
@ -128,6 +128,9 @@ fr:
|
|||
form: "Formulaire"
|
||||
edit_siret: "Modifier le SIRET"
|
||||
edit_identity: "Modifier l’identité"
|
||||
instructeurs:
|
||||
dossiers:
|
||||
deleted_by_user: "Dossier supprimé par l'usager"
|
||||
users:
|
||||
dossiers:
|
||||
autosave:
|
||||
|
@ -187,6 +190,7 @@ fr:
|
|||
edit_dossier: "Modifier le dossier"
|
||||
start_other_dossier: "Commencer un autre dossier"
|
||||
delete_dossier: "Supprimer le dossier"
|
||||
hide_dossier: "Supprimer de votre interface"
|
||||
transfer_dossier: "Transferer le dossier"
|
||||
edit_draft: "Modifier le brouillon"
|
||||
actions: "Actions"
|
||||
|
@ -334,10 +338,14 @@ fr:
|
|||
zero: archivé
|
||||
one: archivé
|
||||
other: archivés
|
||||
mes_dossiers:
|
||||
zero: mon dossier
|
||||
one: mon dossier
|
||||
other: mes dossiers
|
||||
en_cours:
|
||||
zero: en cours
|
||||
one: en cours
|
||||
other: en cours
|
||||
traites:
|
||||
zero: traité
|
||||
one: traité
|
||||
other: traités
|
||||
dossiers_invites:
|
||||
zero: dossier invité
|
||||
one: dossier invité
|
||||
|
|
|
@ -268,6 +268,7 @@ Rails.application.routes.draw do
|
|||
get 'messagerie'
|
||||
post 'commentaire' => 'dossiers#create_commentaire'
|
||||
post 'ask_deletion'
|
||||
patch 'hide_dossier'
|
||||
get 'attestation'
|
||||
get 'transferer', to: 'dossiers#transferer'
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class AddHideByUserAtOnDossiers < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
add_column :dossiers, :hidden_by_user_at, :datetime
|
||||
end
|
||||
end
|
|
@ -324,6 +324,7 @@ ActiveRecord::Schema.define(version: 2021_11_24_111429) do
|
|||
t.bigint "dossier_transfer_id"
|
||||
t.datetime "identity_updated_at"
|
||||
t.datetime "depose_at"
|
||||
t.datetime "hidden_by_user_at"
|
||||
t.index ["archived"], name: "index_dossiers_on_archived"
|
||||
t.index ["dossier_transfer_id"], name: "index_dossiers_on_dossier_transfer_id"
|
||||
t.index ["groupe_instructeur_id"], name: "index_dossiers_on_groupe_instructeur_id"
|
||||
|
|
|
@ -793,14 +793,14 @@ describe Users::DossiersController, type: :controller do
|
|||
context 'when the user does not have any dossiers' do
|
||||
before { get(:index) }
|
||||
|
||||
it { expect(assigns(:statut)).to eq('mes-dossiers') }
|
||||
it { expect(assigns(:statut)).to eq('en-cours') }
|
||||
end
|
||||
|
||||
context 'when the user only have its own dossiers' do
|
||||
let!(:own_dossier) { create(:dossier, user: user) }
|
||||
|
||||
before { get(:index) }
|
||||
it { expect(assigns(:statut)).to eq('mes-dossiers') }
|
||||
it { expect(assigns(:statut)).to eq('en-cours') }
|
||||
it { expect(assigns(:user_dossiers)).to match([own_dossier]) }
|
||||
end
|
||||
|
||||
|
@ -813,14 +813,16 @@ describe Users::DossiersController, type: :controller do
|
|||
it { expect(assigns(:dossiers_invites)).to match([invite.dossier]) }
|
||||
end
|
||||
|
||||
context 'when the user has both' do
|
||||
context 'when the user has dossiers invites, own and traites' do
|
||||
let!(:procedure) { create(:procedure, :published) }
|
||||
let!(:own_dossier) { create(:dossier, user: user) }
|
||||
let!(:own_dossier2) { create(:dossier, user: user, state: "accepte", procedure: procedure) }
|
||||
let!(:invite) { create(:invite, dossier: create(:dossier), user: user) }
|
||||
|
||||
context 'and there is no statut param' do
|
||||
before { get(:index) }
|
||||
|
||||
it { expect(assigns(:statut)).to eq('mes-dossiers') }
|
||||
it { expect(assigns(:statut)).to eq('en-cours') }
|
||||
end
|
||||
|
||||
context 'and there is "dossiers-invites" param' do
|
||||
|
@ -829,10 +831,24 @@ describe Users::DossiersController, type: :controller do
|
|||
it { expect(assigns(:statut)).to eq('dossiers-invites') }
|
||||
end
|
||||
|
||||
context 'and there is "mes-dossiers" param' do
|
||||
before { get(:index, params: { statut: 'mes-dossiers' }) }
|
||||
context 'and there is "en-cours" param' do
|
||||
before { get(:index, params: { statut: 'en-cours' }) }
|
||||
|
||||
it { expect(assigns(:statut)).to eq('mes-dossiers') }
|
||||
it { expect(assigns(:statut)).to eq('en-cours') }
|
||||
end
|
||||
|
||||
context 'and there is "traites" param' do
|
||||
before { get(:index, params: { statut: 'traites' }) }
|
||||
|
||||
it { expect(assigns(:statut)).to eq('traites') }
|
||||
end
|
||||
|
||||
context 'and the traité dossier has been hidden by user' do
|
||||
before do
|
||||
own_dossier2.update!(hidden_by_user_at: Time.zone.now)
|
||||
get(:index, params: { statut: 'traites' })
|
||||
end
|
||||
it { expect(assigns(:statut)).to eq('en-cours') }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -18,14 +18,4 @@ describe 'users/dossiers/dossier_actions.html.haml', type: :view do
|
|||
let(:procedure) { create(:procedure, :closed) }
|
||||
it { is_expected.not_to have_link('Commencer un autre dossier') }
|
||||
end
|
||||
|
||||
context 'when there are no actions to display' do
|
||||
let(:procedure) { create(:procedure, :closed) }
|
||||
let(:dossier) { create(:dossier, :accepte, procedure: procedure) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it 'doesn’t render the menu at all' do
|
||||
expect(subject).not_to have_selector('.dropdown')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,9 +2,10 @@ describe 'users/dossiers/index.html.haml', type: :view do
|
|||
let(:user) { create(:user) }
|
||||
let(:dossier_brouillon) { create(:dossier, state: Dossier.states.fetch(:brouillon), user: user) }
|
||||
let(:dossier_en_construction) { create(:dossier, state: Dossier.states.fetch(:en_construction), user: user) }
|
||||
let(:user_dossiers) { [dossier_brouillon, dossier_en_construction] }
|
||||
let(:dossier_termine) { create(:dossier, state: Dossier.states.fetch(:accepte), user: user) }
|
||||
let(:user_dossiers) { [dossier_brouillon, dossier_en_construction, dossier_termine] }
|
||||
let(:dossiers_invites) { [] }
|
||||
let(:statut) { 'mes-dossiers' }
|
||||
let(:statut) { 'en-cours' }
|
||||
|
||||
before do
|
||||
allow(view).to receive(:new_demarche_url).and_return('#')
|
||||
|
@ -12,6 +13,7 @@ describe 'users/dossiers/index.html.haml', type: :view do
|
|||
assign(:user_dossiers, Kaminari.paginate_array(user_dossiers).page(1))
|
||||
assign(:dossiers_invites, Kaminari.paginate_array(dossiers_invites).page(1))
|
||||
assign(:dossiers_supprimes, Kaminari.paginate_array(user_dossiers).page(1))
|
||||
assign(:dossiers_traites, Kaminari.paginate_array(user_dossiers).page(1))
|
||||
assign(:dossier_transfers, Kaminari.paginate_array([]).page(1))
|
||||
assign(:dossiers_close_to_expiration, Kaminari.paginate_array([]).page(1))
|
||||
assign(:statut, statut)
|
||||
|
@ -19,7 +21,7 @@ describe 'users/dossiers/index.html.haml', type: :view do
|
|||
end
|
||||
|
||||
it 'affiche la liste des dossiers' do
|
||||
expect(rendered).to have_selector('.dossiers-table tbody tr', count: 2)
|
||||
expect(rendered).to have_selector('.dossiers-table tbody tr', count: 3)
|
||||
end
|
||||
|
||||
it 'affiche les informations des dossiers' do
|
||||
|
@ -67,8 +69,16 @@ describe 'users/dossiers/index.html.haml', type: :view do
|
|||
|
||||
it 'affiche la barre d’onglets' do
|
||||
expect(rendered).to have_selector('ul.tabs')
|
||||
expect(rendered).to have_selector('ul.tabs li', count: 3)
|
||||
expect(rendered).to have_selector('ul.tabs li', count: 4)
|
||||
expect(rendered).to have_selector('ul.tabs li.active', count: 1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'where there is a traite dossier' do
|
||||
let(:dossiers_traites) { create_list(:dossier, 1) }
|
||||
|
||||
it "displays the hide by user at button" do
|
||||
expect(rendered).to have_text("Supprimer le dossier")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue