Add filtering to the dossiers table
This commit is contained in:
parent
801318b053
commit
0705efde30
8 changed files with 164 additions and 12 deletions
1
app/assets/images/close.svg
Normal file
1
app/assets/images/close.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><g stroke="#FFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.749 1L1 12.75M12.749 12.75L1 1"/></g><path d="M-5-5h24v24H-5z"/></g></svg>
|
After Width: | Height: | Size: 286 B |
|
@ -104,6 +104,11 @@
|
||||||
cursor: default;
|
cursor: default;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
|
||||||
|
&.left-aligned {
|
||||||
|
left: 0;
|
||||||
|
right: unset;
|
||||||
|
}
|
||||||
|
|
||||||
&.terminated {
|
&.terminated {
|
||||||
width: 600px;
|
width: 600px;
|
||||||
color: $black;
|
color: $black;
|
||||||
|
@ -186,6 +191,22 @@
|
||||||
border: 1px solid $border-grey;
|
border: 1px solid $border-grey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.large {
|
||||||
|
width: 340px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
width: 100px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 2 * $default-spacer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
select {
|
||||||
|
width: 200px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.select2-dropdown {
|
.select2-dropdown {
|
||||||
|
|
|
@ -26,4 +26,22 @@
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter {
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
background-color: $light-blue;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
height: 36px;
|
||||||
|
line-height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-icon {
|
||||||
|
vertical-align: top;
|
||||||
|
margin-top: 12px;
|
||||||
|
margin-left: 6px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ module NewGestionnaire
|
||||||
def show
|
def show
|
||||||
@procedure = procedure
|
@procedure = procedure
|
||||||
|
|
||||||
|
@current_filters = current_filters
|
||||||
|
@available_fields_to_filters = available_fields_to_filters
|
||||||
@displayed_fields = procedure_presentation.displayed_fields
|
@displayed_fields = procedure_presentation.displayed_fields
|
||||||
@displayed_fields_values = displayed_fields_values
|
@displayed_fields_values = displayed_fields_values
|
||||||
|
|
||||||
|
@ -69,20 +71,27 @@ module NewGestionnaire
|
||||||
|
|
||||||
sorted_ids = sorted_ids(@dossiers)
|
sorted_ids = sorted_ids(@dossiers)
|
||||||
|
|
||||||
|
if @current_filters.count > 0
|
||||||
|
filtered_ids = filtered_ids(@dossiers)
|
||||||
|
filtered_sorted_ids = sorted_ids.select { |id| filtered_ids.include?(id) }
|
||||||
|
else
|
||||||
|
filtered_sorted_ids = sorted_ids
|
||||||
|
end
|
||||||
|
|
||||||
page = params[:page].present? ? params[:page] : 1
|
page = params[:page].present? ? params[:page] : 1
|
||||||
|
|
||||||
sorted_paginated_ids = Kaminari
|
filtered_sorted_paginated_ids = Kaminari
|
||||||
.paginate_array(sorted_ids)
|
.paginate_array(filtered_sorted_ids)
|
||||||
.page(page)
|
.page(page)
|
||||||
.per(ITEMS_PER_PAGE)
|
.per(ITEMS_PER_PAGE)
|
||||||
|
|
||||||
@dossiers = @dossiers.where(id: sorted_paginated_ids)
|
@dossiers = @dossiers.where(id: filtered_sorted_paginated_ids)
|
||||||
|
|
||||||
eager_load_displayed_fields
|
eager_load_displayed_fields
|
||||||
|
|
||||||
@dossiers = @dossiers.sort_by { |d| sorted_paginated_ids.index(d.id) }
|
@dossiers = @dossiers.sort_by { |d| filtered_sorted_paginated_ids.index(d.id) }
|
||||||
|
|
||||||
kaminarize(page, sorted_ids.count)
|
kaminarize(page, filtered_sorted_ids.count)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_displayed_fields
|
def update_displayed_fields
|
||||||
|
@ -134,6 +143,36 @@ module NewGestionnaire
|
||||||
redirect_back(fallback_location: procedure_url(procedure))
|
redirect_back(fallback_location: procedure_url(procedure))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_filter
|
||||||
|
filters = procedure_presentation.filters
|
||||||
|
table, column = params[:field].split('/')
|
||||||
|
label = procedure.fields.find { |c| c['table'] == table && c['column'] == column }['label']
|
||||||
|
|
||||||
|
filters[statut] << {
|
||||||
|
'label' => label,
|
||||||
|
'table' => table,
|
||||||
|
'column' => column,
|
||||||
|
'value' => params[:value]
|
||||||
|
}
|
||||||
|
|
||||||
|
procedure_presentation.update_attributes(filters: filters.to_json)
|
||||||
|
|
||||||
|
redirect_back(fallback_location: procedure_url(procedure))
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_filter
|
||||||
|
filters = procedure_presentation.filters
|
||||||
|
filter_to_remove = current_filters.find do |filter|
|
||||||
|
filter['table'] == params[:table] && filter['column'] == params[:column]
|
||||||
|
end
|
||||||
|
|
||||||
|
filters[statut] = filters[statut] - [filter_to_remove]
|
||||||
|
|
||||||
|
procedure_presentation.update_attributes(filters: filters.to_json)
|
||||||
|
|
||||||
|
redirect_back(fallback_location: procedure_url(procedure))
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def statut
|
def statut
|
||||||
|
@ -167,6 +206,33 @@ module NewGestionnaire
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def filtered_ids(dossiers)
|
||||||
|
current_filters.map do |filter|
|
||||||
|
case filter['table']
|
||||||
|
when 'self'
|
||||||
|
dossiers.where("? LIKE ?", filter['column'], "%#{filter['value']}%")
|
||||||
|
|
||||||
|
when 'france_connect_information'
|
||||||
|
dossiers
|
||||||
|
.includes(user: :france_connect_information)
|
||||||
|
.where("? LIKE ?", "france_connect_informations.#{filter['column']}", "%#{filter['value']}%")
|
||||||
|
|
||||||
|
when 'type_de_champ', 'type_de_champ_private'
|
||||||
|
relation = filter['table'] == 'type_de_champ' ? :champs : :champs_private
|
||||||
|
dossiers
|
||||||
|
.includes(relation)
|
||||||
|
.where("champs.type_de_champ_id = ?", filter['column'].to_i)
|
||||||
|
.where("champs.value LIKE ?", "%#{filter['value']}%")
|
||||||
|
|
||||||
|
when 'user', 'etablissement', 'entreprise'
|
||||||
|
dossiers
|
||||||
|
.includes(filter['table'])
|
||||||
|
.where("#{filter['table'].pluralize}.#{filter['column']} LIKE ?", "%#{filter['value']}%")
|
||||||
|
|
||||||
|
end.pluck(:id)
|
||||||
|
end.reduce(:&)
|
||||||
|
end
|
||||||
|
|
||||||
def sorted_ids(dossiers)
|
def sorted_ids(dossiers)
|
||||||
table = procedure_presentation.sort['table']
|
table = procedure_presentation.sort['table']
|
||||||
column = procedure_presentation.sort['column']
|
column = procedure_presentation.sort['column']
|
||||||
|
@ -192,6 +258,20 @@ module NewGestionnaire
|
||||||
dossiers.includes(includes).where(where).order(Dossier.sanitize_for_order(order)).pluck(:id)
|
dossiers.includes(includes).where(where).order(Dossier.sanitize_for_order(order)).pluck(:id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def current_filters
|
||||||
|
@current_filters ||= procedure_presentation.filters[statut]
|
||||||
|
end
|
||||||
|
|
||||||
|
def available_fields_to_filters
|
||||||
|
current_filters_fields_ids = current_filters.map do |field|
|
||||||
|
"#{field['table']}/#{field['column']}"
|
||||||
|
end
|
||||||
|
|
||||||
|
procedure.fields_for_select.reject do |field|
|
||||||
|
current_filters_fields_ids.include?(field[1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def eager_load_displayed_fields
|
def eager_load_displayed_fields
|
||||||
@displayed_fields
|
@displayed_fields
|
||||||
.reject { |field| field['table'] == 'self' }
|
.reject { |field| field['table'] == 'self' }
|
||||||
|
|
|
@ -10,4 +10,8 @@ class ProcedurePresentation < ActiveRecord::Base
|
||||||
def sort
|
def sort
|
||||||
JSON.parse(read_attribute(:sort))
|
JSON.parse(read_attribute(:sort))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def filters
|
||||||
|
JSON.parse(read_attribute(:filters))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -51,7 +51,26 @@
|
||||||
= link_to "Au format .ods", backoffice_download_dossiers_tps_path(format: :ods, procedure_id: @procedure.id), target: "_blank"
|
= link_to "Au format .ods", backoffice_download_dossiers_tps_path(format: :ods, procedure_id: @procedure.id), target: "_blank"
|
||||||
|
|
||||||
.container
|
.container
|
||||||
- if @dossiers.present?
|
- if @dossiers.present? || @current_filters.count > 0
|
||||||
|
%span.button.dropdown
|
||||||
|
Filtrer
|
||||||
|
.dropdown-content.left-aligned.fade-in-down
|
||||||
|
= form_tag add_filter_procedure_path(@procedure), method: :post, class: 'dropdown-form large' do
|
||||||
|
= label_tag :field, "Colonne"
|
||||||
|
= select_tag :field, options_for_select(@available_fields_to_filters)
|
||||||
|
%br
|
||||||
|
= label_tag :value, "Valeur"
|
||||||
|
= text_field_tag :value
|
||||||
|
= hidden_field_tag :statut, @statut
|
||||||
|
%br
|
||||||
|
= submit_tag "Ajouter le filtre", class: 'button'
|
||||||
|
|
||||||
|
- @current_filters.each do |filter|
|
||||||
|
%span.filter
|
||||||
|
= "#{filter['label']} : #{filter['value']}"
|
||||||
|
= link_to remove_filter_procedure_path(@procedure, statut: @statut, table: filter['table'], column: filter['column']) do
|
||||||
|
%img.close-icon{ src: image_url("close.svg") }
|
||||||
|
|
||||||
%table.table.dossiers-table.hoverable
|
%table.table.dossiers-table.hoverable
|
||||||
%thead
|
%thead
|
||||||
%tr
|
%tr
|
||||||
|
|
|
@ -239,6 +239,8 @@ Rails.application.routes.draw do
|
||||||
member do
|
member do
|
||||||
patch 'update_displayed_fields'
|
patch 'update_displayed_fields'
|
||||||
get 'update_sort/:table/:column' => 'procedures#update_sort', as: 'update_sort'
|
get 'update_sort/:table/:column' => 'procedures#update_sort', as: 'update_sort'
|
||||||
|
post 'add_filter'
|
||||||
|
get 'remove_filter/:statut/:table/:column' => 'procedures#remove_filter', as: 'remove_filter'
|
||||||
|
|
||||||
resources :dossiers, only: [:show], param: :dossier_id do
|
resources :dossiers, only: [:show], param: :dossier_id do
|
||||||
member do
|
member do
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe ProcedurePresentation do
|
describe ProcedurePresentation do
|
||||||
let (:procedure_presentation_id) { ProcedurePresentation.create(
|
let (:procedure_presentation_id) {
|
||||||
displayed_fields: [
|
ProcedurePresentation.create(
|
||||||
{ "label" => "test1", "table" => "user" }.to_json,
|
displayed_fields: [
|
||||||
{ "label" => "test2", "table" => "champs" }.to_json],
|
{ "label" => "test1", "table" => "user" }.to_json,
|
||||||
sort: { "table" => "user","column" => "email","order" => "asc" }.to_json
|
{ "label" => "test2", "table" => "champs" }.to_json],
|
||||||
).id }
|
sort: { "table" => "user","column" => "email","order" => "asc" }.to_json,
|
||||||
|
filters: { "a-suivre" => [], "suivis" => [{ "label" => "label1", "table" => "table1", "column" => "column1" }] }.to_json
|
||||||
|
).id
|
||||||
|
}
|
||||||
let (:procedure_presentation) { ProcedurePresentation.find(procedure_presentation_id) }
|
let (:procedure_presentation) { ProcedurePresentation.find(procedure_presentation_id) }
|
||||||
|
|
||||||
describe "#displayed_fields" do
|
describe "#displayed_fields" do
|
||||||
|
@ -16,4 +19,8 @@ describe ProcedurePresentation do
|
||||||
describe "#sort" do
|
describe "#sort" do
|
||||||
it { expect(procedure_presentation.sort).to eq({ "table" => "user","column" => "email","order" => "asc" }) }
|
it { expect(procedure_presentation.sort).to eq({ "table" => "user","column" => "email","order" => "asc" }) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#filters" do
|
||||||
|
it { expect(procedure_presentation.filters).to eq({ "a-suivre" => [], "suivis" => [{ "label" => "label1", "table" => "table1", "column" => "column1" }] }) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue