Merge pull request #7809 from mfo/US/new-notified-button
feat(instructeur/procedure#show): enhance sort by notifications as planned by UX
This commit is contained in:
commit
5370f45a7c
13 changed files with 137 additions and 10 deletions
|
@ -103,6 +103,11 @@
|
|||
border-color: $blue-france-500;
|
||||
}
|
||||
}
|
||||
|
||||
// fix/dsfr
|
||||
.fr-checkbox-group.fix-dsfr-notified-toggle-component {
|
||||
margin-top: -7px;
|
||||
}
|
||||
}
|
||||
|
||||
ul.revision-changes {
|
||||
|
|
|
@ -18,6 +18,18 @@
|
|||
display: inline;
|
||||
}
|
||||
|
||||
.visually-hidden {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: none;
|
||||
}
|
||||
|
||||
// text
|
||||
.text-center,
|
||||
.center {
|
||||
|
|
41
app/components/dossiers/notified_toggle_component.rb
Normal file
41
app/components/dossiers/notified_toggle_component.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
class Dossiers::NotifiedToggleComponent < ApplicationComponent
|
||||
def initialize(procedure:, procedure_presentation:)
|
||||
@procedure = procedure
|
||||
@procedure_presentation = procedure_presentation
|
||||
@current_sort = procedure_presentation.sort
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def opposite_order
|
||||
@procedure_presentation.opposite_order_for(current_table, current_column)
|
||||
end
|
||||
|
||||
def active?
|
||||
sorted_by_notifications? && order_asc?
|
||||
end
|
||||
|
||||
def icon_class_name
|
||||
active? ? 'fr-fi-checkbox' : 'fr-fi-checkbox-blank'
|
||||
end
|
||||
|
||||
def order_asc?
|
||||
current_order == 'asc'
|
||||
end
|
||||
|
||||
def current_order
|
||||
@current_sort['order']
|
||||
end
|
||||
|
||||
def current_table
|
||||
@current_sort['table']
|
||||
end
|
||||
|
||||
def current_column
|
||||
@current_sort['column']
|
||||
end
|
||||
|
||||
def sorted_by_notifications?
|
||||
current_table == 'notifications' && current_column == 'notifications'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
en:
|
||||
show_notified_first: Show files with notification first
|
|
@ -0,0 +1,2 @@
|
|||
fr:
|
||||
show_notified_first: Remonter les dossiers avec une notification
|
|
@ -0,0 +1,7 @@
|
|||
= form_tag update_sort_instructeur_procedure_path(procedure_id: @procedure.id, table: 'notifications', column: 'notifications', order: opposite_order), method: 'GET', data: {controller: 'checkbox'} do
|
||||
.fr-form-group
|
||||
.fr-fieldset__content
|
||||
.fr-checkbox-group.fix-dsfr-notified-toggle-component
|
||||
= check_box_tag :order, opposite_order, active?, data: {action: 'change->checkbox#onChange'}
|
||||
= label_tag :order, t('.show_notified_first'), class: 'fr-label'
|
||||
= submit_tag t('.show_notified_first'), data: {"checkbox-target": 'submit' }, class: 'visually-hidden'
|
|
@ -121,7 +121,7 @@ module Instructeurs
|
|||
end
|
||||
|
||||
def update_sort
|
||||
procedure_presentation.update_sort(params[:table], params[:column])
|
||||
procedure_presentation.update_sort(params[:table], params[:column], params[:order])
|
||||
|
||||
redirect_back(fallback_location: instructeur_procedure_url(procedure))
|
||||
end
|
||||
|
|
8
app/javascript/controllers/checkbox_controller.ts
Normal file
8
app/javascript/controllers/checkbox_controller.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { ApplicationController } from './application_controller';
|
||||
|
||||
export class CheckboxController extends ApplicationController {
|
||||
onChange() {
|
||||
const form = this.element as HTMLFormElement;
|
||||
form.requestSubmit();
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
@import '@gouvfr/dsfr/dist/component/connect/connect.css';
|
||||
@import '@gouvfr/dsfr/dist/component/highlight/highlight.css';
|
||||
@import '@gouvfr/dsfr/dist/component/input/input.css';
|
||||
@import '@gouvfr/dsfr/dist/component/checkbox/checkbox.css';
|
||||
@import '@gouvfr/dsfr/dist/component/logo/logo.css';
|
||||
@import '@gouvfr/dsfr/dist/component/modal/modal.css';
|
||||
@import '@gouvfr/dsfr/dist/component/navigation/navigation.css';
|
||||
|
|
|
@ -18,6 +18,8 @@ class ProcedurePresentation < ApplicationRecord
|
|||
|
||||
TABLE = 'table'
|
||||
COLUMN = 'column'
|
||||
ORDER = 'order'
|
||||
|
||||
SLASH = '/'
|
||||
TYPE_DE_CHAMP = 'type_de_champ'
|
||||
TYPE_DE_CHAMP_PRIVATE = 'type_de_champ_private'
|
||||
|
@ -286,18 +288,20 @@ class ProcedurePresentation < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def update_sort(table, column)
|
||||
order = if sort.values_at(TABLE, COLUMN) == [table, column]
|
||||
def update_sort(table, column, order)
|
||||
update!(sort: {
|
||||
TABLE => table,
|
||||
COLUMN => column,
|
||||
ORDER => opposite_order_for(table, column)
|
||||
})
|
||||
end
|
||||
|
||||
def opposite_order_for(table, column)
|
||||
if sort.values_at(TABLE, COLUMN) == [table, column]
|
||||
sort['order'] == 'asc' ? 'desc' : 'asc'
|
||||
else
|
||||
'asc'
|
||||
end
|
||||
|
||||
update!(sort: {
|
||||
TABLE => table,
|
||||
COLUMN => column,
|
||||
'order' => order
|
||||
})
|
||||
end
|
||||
|
||||
def snapshot
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%th{ class: classname }
|
||||
= link_to update_sort_instructeur_procedure_path(@procedure, table: field['table'], column: field['column']) do
|
||||
= link_to update_sort_instructeur_procedure_path(@procedure, table: field['table'], column: field['column'], order: @procedure_presentation.opposite_order_for(field['table'], field['column'])) do
|
||||
- if @procedure_presentation.sort['table'] == field['table'] && @procedure_presentation.sort['column'] == field['column']
|
||||
- if @procedure_presentation.sort['order'] == 'asc'
|
||||
#{field['label']} ↑
|
||||
|
|
|
@ -63,6 +63,8 @@
|
|||
.flex
|
||||
.flex-grow
|
||||
= render partial: "dossiers_filter", locals: { procedure: @procedure, procedure_presentation: @procedure_presentation, current_filters: @current_filters, statut: @statut, filterable_fields_for_select: @filterable_fields_for_select }
|
||||
.flex-grow
|
||||
= render Dossiers::NotifiedToggleComponent.new(procedure: @procedure, procedure_presentation: @procedure_presentation)
|
||||
- if @dossiers_count > 0
|
||||
.dossiers-export
|
||||
= render Dossiers::ExportComponent.new(procedure: @procedure, exports: @exports, statut: @statut, count: @dossiers_count, export_url: method(:download_export_instructeur_procedure_path))
|
||||
|
|
43
spec/system/instructeurs/procedure_sort_spec.rb
Normal file
43
spec/system/instructeurs/procedure_sort_spec.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
describe "procedure sort" do
|
||||
let(:instructeur) { create(:instructeur) }
|
||||
let(:procedure) { create(:procedure, :published, :with_type_de_champ, instructeurs: [instructeur]) }
|
||||
let!(:new_unfollow_dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction)) }
|
||||
let!(:followed_dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction)) }
|
||||
let!(:new_unfollow_dossier_2) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction)) }
|
||||
|
||||
before do
|
||||
instructeur.follow(followed_dossier)
|
||||
followed_dossier.champs.first.update(value: '123')
|
||||
|
||||
login_as(instructeur.user, scope: :user)
|
||||
visit instructeur_procedure_path(procedure)
|
||||
end
|
||||
|
||||
scenario "should be able to sort with header" do
|
||||
all(".dossiers-table tbody tr:nth-child(1) .number-col a", text: new_unfollow_dossier_2.id)
|
||||
all(".dossiers-table tbody tr:nth-child(2) .number-col a", text: followed_dossier.id)
|
||||
all(".dossiers-table tbody tr:nth-child(3) .number-col a", text: new_unfollow_dossier.id)
|
||||
|
||||
find("thead .number-col a").click # reverse id filter
|
||||
|
||||
all(".dossiers-table tbody tr:nth-child(1) .number-col a", text: new_unfollow_dossier.id)
|
||||
all(".dossiers-table tbody tr:nth-child(2) .number-col a", text: followed_dossier.id)
|
||||
all(".dossiers-table tbody tr:nth-child(3) .number-col a", text: new_unfollow_dossier_2.id)
|
||||
end
|
||||
|
||||
scenario "should be able to sort with direct link to notificaiton filter" do
|
||||
# dossier sorted by id
|
||||
check "Remonter les dossiers avec une notification"
|
||||
|
||||
# sort by notification
|
||||
all(".dossiers-table tbody tr:nth-child(1) .number-col a", text: followed_dossier.id)
|
||||
all(".dossiers-table tbody tr:nth-child(2) .number-col a", text: new_unfollow_dossier.id)
|
||||
all(".dossiers-table tbody tr:nth-child(3) .number-col a", text: new_unfollow_dossier_2.id)
|
||||
|
||||
uncheck "Remonter les dossiers avec une notification"
|
||||
|
||||
all(".dossiers-table tbody tr:nth-child(1) .number-col a", text: new_unfollow_dossier_2.id)
|
||||
all(".dossiers-table tbody tr:nth-child(2) .number-col a", text: followed_dossier.id)
|
||||
all(".dossiers-table tbody tr:nth-child(3) .number-col a", text: new_unfollow_dossier.id)
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue