Merge pull request #7089 from betagouv/main

2022-03-29-02
This commit is contained in:
Pierre de La Morinerie 2022-03-29 15:13:34 +02:00 committed by GitHub
commit 613d0a90f8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 193 additions and 28 deletions

View file

@ -53,6 +53,12 @@
} }
} }
&.no-list {
ul {
list-style: none !important;
}
}
ul { ul {
list-style-type: disc; list-style-type: disc;
list-style-position: inside; list-style-position: inside;

View file

@ -7,7 +7,7 @@
# encrypted_token :string # encrypted_token :string
# created_at :datetime # created_at :datetime
# updated_at :datetime # updated_at :datetime
# user_id :bigint # user_id :bigint not null
# #
class Administrateur < ApplicationRecord class Administrateur < ApplicationRecord
include ActiveRecord::SecureToken include ActiveRecord::SecureToken

View file

@ -504,7 +504,7 @@ class Dossier < ApplicationRecord
end end
def read_only? def read_only?
en_instruction? || accepte? || refuse? || sans_suite? en_instruction? || accepte? || refuse? || sans_suite? || procedure.discarded? || procedure.close? && brouillon?
end end
def can_transition_to_en_construction? def can_transition_to_en_construction?

View file

@ -5,7 +5,7 @@
# id :bigint not null, primary key # id :bigint not null, primary key
# created_at :datetime not null # created_at :datetime not null
# updated_at :datetime not null # updated_at :datetime not null
# user_id :bigint # user_id :bigint not null
# #
class Expert < ApplicationRecord class Expert < ApplicationRecord
belongs_to :user belongs_to :user

View file

@ -9,7 +9,7 @@
# created_at :datetime # created_at :datetime
# updated_at :datetime # updated_at :datetime
# agent_connect_id :string # agent_connect_id :string
# user_id :bigint # user_id :bigint not null
# #
class Instructeur < ApplicationRecord class Instructeur < ApplicationRecord
has_and_belongs_to_many :administrateurs has_and_belongs_to_many :administrateurs

View file

@ -8,7 +8,8 @@
= render(partial: 'users/dossiers/expiration_banner', locals: {dossier: dossier}) = render(partial: 'users/dossiers/expiration_banner', locals: {dossier: dossier})
.header-actions - if current_user.owns?(dossier) && !dossier.procedure.discarded? && !dossier.procedure.close?
- if current_user.owns?(dossier) .header-actions
= render partial: 'invites/dropdown', locals: { dossier: dossier } = render partial: 'invites/dropdown', locals: { dossier: dossier }
- else
= render(partial: 'users/dossiers/procedure_removed_banner', locals: { dossier: dossier })

View file

@ -0,0 +1,22 @@
.card.warning.mb-3.no-list
- if dossier.procedure.discarded?
.flex.justify-between
.card-title= t('users.dossiers.header.banner.procedure_deleted_title')
= render(partial: 'users/dossiers/show/print_dossier', locals: { dossier: dossier}) if !dossier.brouillon?
- if dossier.termine?
%p
= t('users.dossiers.header.banner.procedure_deleted_dossier_termine_content')
- elsif dossier.brouillon?
%p
= t('users.dossiers.header.banner.procedure_close_content')
- else
%p
= t('users.dossiers.header.banner.procedure_deleted_dossier_en_cours_content')
- else
.flex.justify-between
.card-title= t('users.dossiers.header.banner.procedure_close_title')
= render(partial: 'users/dossiers/show/print_dossier', locals: { dossier: dossier }) if !dossier.brouillon?
%p
= t('users.dossiers.header.banner.procedure_close_content')

View file

@ -12,19 +12,15 @@
= render(partial: 'users/dossiers/expiration_banner', locals: {dossier: dossier}) = render(partial: 'users/dossiers/expiration_banner', locals: {dossier: dossier})
- if (current_user.owns?(dossier) && !dossier.procedure.discarded?) || (!dossier.procedure.discarded? && !dossier.procedure.close? && !dossier.en_construction?)
- if current_user.owns?(dossier)
.header-actions .header-actions
= render partial: 'invites/dropdown', locals: { dossier: dossier } = render partial: 'invites/dropdown', locals: { dossier: dossier }
- if dossier.can_be_updated_by_user? && !current_page?(modifier_dossier_path(dossier)) - if dossier.can_be_updated_by_user? && !current_page?(modifier_dossier_path(dossier))
= link_to t('views.users.dossiers.show.header.edit_dossier'), modifier_dossier_path(dossier), class: 'button accepted edit-form', 'title'=> "Vous pouvez modifier votre dossier tant qu'il n'est passé en instruction" = link_to t('views.users.dossiers.show.header.edit_dossier'), modifier_dossier_path(dossier), class: 'button accepted edit-form', 'title'=> "Vous pouvez modifier votre dossier tant qu'il n'est passé en instruction"
%span.dropdown.print-menu-opener = render(partial: 'users/dossiers/show/print_dossier', locals: { dossier: dossier })
%button.button.dropdown-button.icon-only{ title: t('views.users.dossiers.show.header.print'), 'aria-label': 'imprimer', 'aria-expanded' => 'false', 'aria-controls' => 'print-menu' }
%span.icon.printer
%ul#print-menu.print-menu.dropdown-content
%li
= link_to t('views.users.dossiers.show.header.print_dossier'), dossier_path(dossier, format: :pdf), target: "_blank", rel: "noopener", class: "menu-item menu-link"
- else
= render(partial: 'users/dossiers/procedure_removed_banner', locals: { dossier: dossier })
%nav.tabs %nav.tabs
%ul %ul

View file

@ -0,0 +1,6 @@
%span.dropdown.print-menu-opener
%button.button.dropdown-button.icon-only{ title: t('views.users.dossiers.show.header.print'), 'aria-label': 'imprimer', 'aria-expanded' => 'false', 'aria-controls' => 'print-menu' }
%span.icon.printer
%ul#print-menu.print-menu.dropdown-content
%li
= link_to t('views.users.dossiers.show.header.print_dossier'), dossier_path(dossier, format: :pdf), target: "_blank", rel: "noopener", class: "menu-item menu-link"

View file

@ -3,6 +3,11 @@ fr:
dossiers: dossiers:
header: header:
banner: banner:
procedure_deleted_title: "La démarche liée à votre dossier est supprimée"
procedure_close_title: "La démarche liée à votre dossier est close"
procedure_deleted_dossier_en_cours_content: "Vous pouvez toujours consulter votre dossier, mais il nest plus possible de le modifier."
procedure_deleted_dossier_termine_content: "Votre dossier a été traité par l'administration, aucune action n'est possible"
procedure_close_content: "Vous pouvez toujours consulter votre dossier, mais il ne sera pas traité par l'administration"
title: Votre dossier va expirer title: Votre dossier va expirer
states: states:
brouillon: Votre dossier est en brouillon, mais va bientôt expirer. Cela signifie quil va bientôt être supprimé sans avoir été déposé. Si vous souhaitez le conserver afin de poursuivre la démarche, vous pouvez le conserver un mois de plus en cliquant sur le bouton ci-dessous. brouillon: Votre dossier est en brouillon, mais va bientôt expirer. Cela signifie quil va bientôt être supprimé sans avoir été déposé. Si vous souhaitez le conserver afin de poursuivre la démarche, vous pouvez le conserver un mois de plus en cliquant sur le bouton ci-dessous.

View file

@ -0,0 +1,18 @@
class AddNotNullConstraintsToRoleTables < ActiveRecord::Migration[6.1]
include Database::MigrationHelpers
def change
# If this migration fails, that means you need to run the matching data migration task first.
# Please run:
# bin/rake after_party:copy_user_association_to_user_related_models
# bin/rake after_party:delete_roles_without_users
#
# (We ignore strong_migrations safety warnings, because those tables are relatively small, and the null check
# will be very fast.)
safety_assured do
change_column_null :administrateurs, :user_id, false
change_column_null :instructeurs, :user_id, false
change_column_null :experts, :user_id, false
end
end
end

View file

@ -0,0 +1,10 @@
class AddForeignKeysToRoleTables < ActiveRecord::Migration[6.1]
def change
# Add foreign keys constraints to role tables.
#
# (We don't validate foreign keys right now, to avoid blocking writes to these tables for too long.)
add_foreign_key :administrateurs, :users, validate: false
add_foreign_key :instructeurs, :users, validate: false
add_foreign_key :experts, :users, validate: false
end
end

View file

@ -0,0 +1,10 @@
class ValidateForeignKeysToRoleTables < ActiveRecord::Migration[6.1]
disable_ddl_transaction!
def change
# Now that the foreign keys are added, we can validate them safely without blocking writes.
validate_foreign_key :administrateurs, :users
validate_foreign_key :instructeurs, :users
validate_foreign_key :experts, :users
end
end

View file

@ -0,0 +1,9 @@
class AddIndexToRoleTables < ActiveRecord::Migration[6.1]
disable_ddl_transaction!
def change
add_index :administrateurs, :user_id, algorithm: :concurrently
add_index :instructeurs, :user_id, algorithm: :concurrently
add_index :experts, :user_id, algorithm: :concurrently
end
end

View file

@ -0,0 +1,10 @@
class RemoveRoleColumnsOnUser < ActiveRecord::Migration[6.1]
def change
# (The safety_assured block validates that the columns to remove are ignored in the model, which is the case.)
safety_assured do
remove_column :users, :administrateur_id
remove_column :users, :instructeur_id
remove_column :users, :expert_id
end
end
end

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2022_03_22_110900) do ActiveRecord::Schema.define(version: 2022_03_23_120846) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -60,7 +60,8 @@ ActiveRecord::Schema.define(version: 2022_03_22_110900) do
t.datetime "created_at" t.datetime "created_at"
t.string "encrypted_token" t.string "encrypted_token"
t.datetime "updated_at" t.datetime "updated_at"
t.bigint "user_id" t.bigint "user_id", null: false
t.index ["user_id"], name: "index_administrateurs_on_user_id"
end end
create_table "administrateurs_instructeurs", id: false, force: :cascade do |t| create_table "administrateurs_instructeurs", id: false, force: :cascade do |t|
@ -410,7 +411,8 @@ ActiveRecord::Schema.define(version: 2022_03_22_110900) do
create_table "experts", force: :cascade do |t| create_table "experts", force: :cascade do |t|
t.datetime "created_at", precision: 6, null: false t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false
t.bigint "user_id" t.bigint "user_id", null: false
t.index ["user_id"], name: "index_experts_on_user_id"
end end
create_table "experts_procedures", force: :cascade do |t| create_table "experts_procedures", force: :cascade do |t|
@ -539,8 +541,9 @@ ActiveRecord::Schema.define(version: 2022_03_22_110900) do
t.text "encrypted_login_token" t.text "encrypted_login_token"
t.datetime "login_token_created_at" t.datetime "login_token_created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.bigint "user_id" t.bigint "user_id", null: false
t.index ["agent_connect_id"], name: "index_instructeurs_on_agent_connect_id", unique: true t.index ["agent_connect_id"], name: "index_instructeurs_on_agent_connect_id", unique: true
t.index ["user_id"], name: "index_instructeurs_on_user_id"
end end
create_table "invites", id: :serial, force: :cascade do |t| create_table "invites", id: :serial, force: :cascade do |t|
@ -788,7 +791,6 @@ ActiveRecord::Schema.define(version: 2022_03_22_110900) do
end end
create_table "users", id: :serial, force: :cascade do |t| create_table "users", id: :serial, force: :cascade do |t|
t.bigint "administrateur_id"
t.datetime "confirmation_sent_at" t.datetime "confirmation_sent_at"
t.string "confirmation_token" t.string "confirmation_token"
t.datetime "confirmed_at" t.datetime "confirmed_at"
@ -797,9 +799,7 @@ ActiveRecord::Schema.define(version: 2022_03_22_110900) do
t.string "current_sign_in_ip" t.string "current_sign_in_ip"
t.string "email", default: "", null: false t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false t.string "encrypted_password", default: "", null: false
t.bigint "expert_id"
t.integer "failed_attempts", default: 0, null: false t.integer "failed_attempts", default: 0, null: false
t.bigint "instructeur_id"
t.datetime "last_sign_in_at" t.datetime "last_sign_in_at"
t.string "last_sign_in_ip" t.string "last_sign_in_ip"
t.string "locale" t.string "locale"
@ -814,11 +814,8 @@ ActiveRecord::Schema.define(version: 2022_03_22_110900) do
t.text "unconfirmed_email" t.text "unconfirmed_email"
t.string "unlock_token" t.string "unlock_token"
t.datetime "updated_at" t.datetime "updated_at"
t.index ["administrateur_id"], name: "index_users_on_administrateur_id"
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
t.index ["email"], name: "index_users_on_email", unique: true t.index ["email"], name: "index_users_on_email", unique: true
t.index ["expert_id"], name: "index_users_on_expert_id"
t.index ["instructeur_id"], name: "index_users_on_instructeur_id"
t.index ["requested_merge_into_id"], name: "index_users_on_requested_merge_into_id" t.index ["requested_merge_into_id"], name: "index_users_on_requested_merge_into_id"
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true
@ -852,6 +849,7 @@ ActiveRecord::Schema.define(version: 2022_03_22_110900) do
end end
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "administrateurs", "users"
add_foreign_key "administrateurs_instructeurs", "administrateurs" add_foreign_key "administrateurs_instructeurs", "administrateurs"
add_foreign_key "administrateurs_instructeurs", "instructeurs" add_foreign_key "administrateurs_instructeurs", "instructeurs"
add_foreign_key "administrateurs_procedures", "administrateurs" add_foreign_key "administrateurs_procedures", "administrateurs"
@ -876,12 +874,14 @@ ActiveRecord::Schema.define(version: 2022_03_22_110900) do
add_foreign_key "dossiers", "groupe_instructeurs" add_foreign_key "dossiers", "groupe_instructeurs"
add_foreign_key "dossiers", "procedure_revisions", column: "revision_id" add_foreign_key "dossiers", "procedure_revisions", column: "revision_id"
add_foreign_key "dossiers", "users" add_foreign_key "dossiers", "users"
add_foreign_key "experts", "users"
add_foreign_key "experts_procedures", "experts" add_foreign_key "experts_procedures", "experts"
add_foreign_key "experts_procedures", "procedures" add_foreign_key "experts_procedures", "procedures"
add_foreign_key "france_connect_informations", "users" add_foreign_key "france_connect_informations", "users"
add_foreign_key "geo_areas", "champs" add_foreign_key "geo_areas", "champs"
add_foreign_key "groupe_instructeurs", "procedures" add_foreign_key "groupe_instructeurs", "procedures"
add_foreign_key "initiated_mails", "procedures" add_foreign_key "initiated_mails", "procedures"
add_foreign_key "instructeurs", "users"
add_foreign_key "merge_logs", "users" add_foreign_key "merge_logs", "users"
add_foreign_key "procedure_presentations", "assign_tos" add_foreign_key "procedure_presentations", "assign_tos"
add_foreign_key "procedure_revision_types_de_champ", "procedure_revision_types_de_champ", column: "parent_id" add_foreign_key "procedure_revision_types_de_champ", "procedure_revision_types_de_champ", column: "parent_id"
@ -901,9 +901,6 @@ ActiveRecord::Schema.define(version: 2022_03_22_110900) do
add_foreign_key "trusted_device_tokens", "instructeurs" add_foreign_key "trusted_device_tokens", "instructeurs"
add_foreign_key "types_de_champ", "procedure_revisions", column: "revision_id" add_foreign_key "types_de_champ", "procedure_revisions", column: "revision_id"
add_foreign_key "types_de_champ", "types_de_champ", column: "parent_id" add_foreign_key "types_de_champ", "types_de_champ", column: "parent_id"
add_foreign_key "users", "administrateurs"
add_foreign_key "users", "experts"
add_foreign_key "users", "instructeurs"
add_foreign_key "users", "users", column: "requested_merge_into_id" add_foreign_key "users", "users", column: "requested_merge_into_id"
add_foreign_key "without_continuation_mails", "procedures" add_foreign_key "without_continuation_mails", "procedures"
end end

View file

@ -0,0 +1,34 @@
describe 'dossiers/show/header.html.haml', type: :view do
let(:procedure) { create(:procedure, :discarded) }
let(:dossier) { create(:dossier, state: "brouillon", procedure: procedure) }
before do
sign_in dossier.user
end
subject! { render 'shared/dossiers/header.html.haml', dossier: dossier }
context "when the procedure is discarded with a dossier en brouillon" do
it 'affiche que la démarche est supprimée' do
expect(rendered).to have_text("La démarche liée à votre dossier est supprimée")
expect(rendered).to have_text("Vous pouvez toujours consulter votre dossier, mais il ne sera pas traité par l'administration")
end
it 'cannot download the dossier' do
expect(rendered).not_to have_text("Tout le dossier")
end
end
context "when the procedure is closed with a dossier en brouillon" do
let(:procedure) { create(:procedure, :closed) }
it 'affiche que la démarche est close' do
expect(rendered).to have_text("La démarche liée à votre dossier est close")
expect(rendered).to have_text("Vous pouvez toujours consulter votre dossier, mais il ne sera pas traité par l'administration")
end
it 'cannot download the dossier' do
expect(rendered).not_to have_text("Tout le dossier")
end
end
end

View file

@ -16,4 +16,45 @@ describe 'users/dossiers/show/header.html.haml', type: :view do
expect(rendered).to have_link("Résumé", href: dossier_path(dossier)) expect(rendered).to have_link("Résumé", href: dossier_path(dossier))
expect(rendered).to have_link("Demande", href: demande_dossier_path(dossier)) expect(rendered).to have_link("Demande", href: demande_dossier_path(dossier))
end end
context "when the procedure is closed with a dossier en construction" do
let(:procedure) { create(:procedure, :closed) }
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
it "n'affiche pas de banner" do
expect(rendered).not_to have_text("La démarche liée à votre dossier est close")
end
it 'can download the dossier' do
expect(rendered).to have_text("Tout le dossier")
end
end
context "when the procedure is discarded with a dossier en construction" do
let(:procedure) { create(:procedure, :discarded) }
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
it 'affiche que la démarche est supprimée' do
expect(rendered).to have_text("La démarche liée à votre dossier est supprimée")
expect(rendered).to have_text("Vous pouvez toujours consulter votre dossier, mais il nest plus possible de le modifier")
end
it 'can download the dossier' do
expect(rendered).to have_text("Tout le dossier")
end
end
context "when the procedure is discarded with a dossier terminé" do
let(:procedure) { create(:procedure, :discarded) }
let(:dossier) { create(:dossier, state: "accepte", procedure: procedure) }
it 'affiche que la démarche est supprimée' do
expect(rendered).to have_text("La démarche liée à votre dossier est supprimée")
expect(rendered).to have_text("Votre dossier a été traité par l'administration, aucune action n'est possible")
end
it 'can download the dossier' do
expect(rendered).to have_text("Tout le dossier")
end
end
end end