Add ordering feature on piece justificative view

This commit is contained in:
Guillaume Lazzara 2016-06-08 16:45:18 +02:00
parent 35a07aec87
commit 1551b7ce21
17 changed files with 343 additions and 23 deletions

View file

@ -22,6 +22,23 @@ class Admin::PiecesJustificativesController < AdminController
def update_params def update_params
params params
.require(:procedure) .require(:procedure)
.permit(types_de_piece_justificative_attributes: [:libelle, :description, :id]) .permit(types_de_piece_justificative_attributes: [:libelle, :description, :id, :order_place])
end
def move_up
index = params[:index].to_i - 1
if @procedure.switch_types_de_piece_justificative index
render 'show', format: :js
else
render json: {}, status: 400
end
end
def move_down
if @procedure.switch_types_de_piece_justificative params[:index].to_i
render 'show', format: :js
else
render json: {}, status: 400
end
end end
end end

View file

@ -1,7 +1,7 @@
class Admin::TypesDeChampController < AdminController class Admin::TypesDeChampController < AdminController
before_action :retrieve_procedure before_action :retrieve_procedure
before_action :procedure_locked? before_action :procedure_locked?
def destroy def destroy
@procedure.types_de_champ.destroy(params[:id]) @procedure.types_de_champ.destroy(params[:id])
render 'show', format: :js render 'show', format: :js
@ -19,7 +19,9 @@ class Admin::TypesDeChampController < AdminController
end end
def update_params def update_params
params.require(:procedure).permit(types_de_champ_attributes: [:libelle, :description, :order_place, :type_champ, :id, :mandatory]) params
.require(:procedure)
.permit(types_de_champ_attributes: [:libelle, :description, :order_place, :type_champ, :id, :mandatory])
end end
def move_up def move_up

View file

@ -0,0 +1,37 @@
class TypeDePieceJustificativeDecorator < Draper::Decorator
delegate_all
def button_up params
h.link_to '', params[:url], class: up_classes, id: "btn_up_#{params[:index]}", remote: true, method: :post if display_up_button?(params[:index])
end
def button_down params
h.link_to '', params[:url], class: down_classes, id: "btn_down_#{params[:index]}", remote: true, method: :post if display_down_button?(params[:index])
end
private
def up_classes
base_classes << 'fa-chevron-up'
end
def down_classes
base_classes << 'fa-chevron-down'
end
def base_classes
%w(btn btn-default form-control fa)
end
def display_up_button?(index)
!(index == 0 || count_type_de_piece_justificative < 2)
end
def display_down_button?(index)
(index + 1) < count_type_de_piece_justificative
end
def count_type_de_piece_justificative
@count_type_de_piece_justificative ||= procedure.types_de_piece_justificative.count
end
end

View file

@ -5,7 +5,7 @@ class PieceJustificative < ActiveRecord::Base
belongs_to :user belongs_to :user
delegate :api_entreprise, :libelle, to: :type_de_piece_justificative delegate :api_entreprise, :libelle, :order_place, to: :type_de_piece_justificative
alias_attribute :type, :type_de_piece_justificative_id alias_attribute :type, :type_de_piece_justificative_id

View file

@ -25,18 +25,28 @@ class Procedure < ActiveRecord::Base
types_de_champ.order(:order_place) types_de_champ.order(:order_place)
end end
def types_de_piece_justificative_ordered
types_de_piece_justificative.order(:order_place)
end
def self.not_archived id def self.not_archived id
Procedure.where(archived: false).find(id) Procedure.where(archived: false).find(id)
end end
def switch_types_de_champ index_of_first_element def switch_types_de_champ index_of_first_element
switch_list_order(types_de_champ_ordered, index_of_first_element)
end
def switch_types_de_piece_justificative index_of_first_element
switch_list_order(types_de_piece_justificative_ordered, index_of_first_element)
end
def switch_list_order(list, index_of_first_element)
return false if index_of_first_element < 0 return false if index_of_first_element < 0
types_de_champ_tmp = types_de_champ_ordered return false if index_of_first_element == list.count - 1
nb_types_de_champ = types_de_champ_tmp.count return false if list.count < 1
return false if index_of_first_element == nb_types_de_champ - 1 list[index_of_first_element].update_attributes(order_place: index_of_first_element + 1)
return false if types_de_champ_ordered.count < 1 list[index_of_first_element + 1].update_attributes(order_place: index_of_first_element)
types_de_champ_tmp[index_of_first_element].update_attributes(order_place: index_of_first_element + 1)
types_de_champ_tmp[index_of_first_element + 1].update_attributes(order_place: index_of_first_element)
true true
end end

View file

@ -1,6 +1,6 @@
class TypeDePieceJustificativeSerializer < ActiveModel::Serializer class TypeDePieceJustificativeSerializer < ActiveModel::Serializer
attributes :id, attributes :id,
:libelle, :libelle,
:description :description,
:order_place
end end

View file

@ -1,14 +1,21 @@
= f.fields_for :types_de_piece_justificative, types_de_piece_justificative, remote: true do |ff|
= f.fields_for :types_de_piece_justificative, types_de_piece_justificative do |ff|
.form-inline .form-inline
.form-group .form-group
%h4 Libellé %h4 Libellé
=ff.text_field :libelle, class: 'form-control libelle', placeholder: 'Libellé' =ff.text_field :libelle, class: 'form-control libelle', placeholder: 'Libellé'
.form-group .form-group
%h4 Description %h4 Description
=ff.text_area :description, class: 'form-control description', placeholder: 'Description' =ff.text_area :description, class: 'form-control description', placeholder: 'Description'
.form-group
= ff.hidden_field :order_place, value: ff.index
= ff.hidden_field :id
- unless ff.object.id.nil?
.form-group
%br &nbsp;
= ff.object.button_up(index: ff.index, url: move_up_admin_procedure_pieces_justificatives_path(@procedure, ff.index))
= ff.object.button_down(index: ff.index, url: move_down_admin_procedure_pieces_justificatives_path(@procedure, ff.index))
.form-group .form-group
%br &nbsp; %br &nbsp;

View file

@ -1,8 +1,7 @@
= form_for [:admin, @procedure], url: admin_procedure_pieces_justificatives_path(@procedure) , remote: true do |f| = form_for [:admin, @procedure], url: admin_procedure_pieces_justificatives_path(@procedure) , remote: true do |f|
#liste_piece_justificative #liste_piece_justificative
= render partial: 'fields', locals:{ types_de_piece_justificative: @procedure.types_de_piece_justificative, f: f } = render partial: 'fields', locals:{ types_de_piece_justificative: @procedure.types_de_piece_justificative_ordered.decorate, f: f }
= f.submit "Enregistrer", class: 'btn btn-success', id: :save = f.submit "Enregistrer", class: 'btn btn-success', id: :save
%hr %hr
#new_type_de_piece_justificative #new_type_de_piece_justificative
= render partial: 'fields', locals:{ types_de_piece_justificative: TypeDePieceJustificative.new, f: f } = render partial: 'fields', locals:{ types_de_piece_justificative: TypeDePieceJustificative.new.decorate, f: f }

View file

@ -1,4 +1,4 @@
<% flash.each do |type, message| %> <% flash.each do |type, message| %>
$("#flash_message").html("<div class=\"alert alert-success move_up\" style=\"display: block:\"> <%= message.html_safe %></div>").children().fadeOut(5000) $("#flash_message").html("<div class=\"alert alert-success move_up\" style=\"display: block:\"> <%= message.html_safe %></div>").children().fadeOut(5000)
<% end %> <% end %>
$('#piece_justificative_form').html("<%= escape_javascript(render partial: 'form', locals: { procedure: @procedure } ) %>"); $('#piece_justificative_form').html("<%= escape_javascript(render partial: 'form', locals: { procedure: @procedure } ) %>");

View file

@ -89,6 +89,10 @@ Rails.application.routes.draw do
post '/:index/move_up' => 'types_de_champ#move_up', as: :move_up post '/:index/move_up' => 'types_de_champ#move_up', as: :move_up
post '/:index/move_down' => 'types_de_champ#move_down', as: :move_down post '/:index/move_down' => 'types_de_champ#move_down', as: :move_down
end end
resource :pieces_justificatives, only: [:show, :update] do
post '/:index/move_up' => 'pieces_justificatives#move_up', as: :move_up
post '/:index/move_down' => 'pieces_justificatives#move_down', as: :move_down
end
put 'archive' => 'procedures#archive', as: :archive put 'archive' => 'procedures#archive', as: :archive

View file

@ -0,0 +1,9 @@
class AddOrderPlaceInTypeDePieceJustificative < ActiveRecord::Migration
def up
add_column :types_de_piece_justificative, :order_place, :integer
end
def down
remove_column :types_de_piece_justificative, :order_place
end
end

View file

@ -11,7 +11,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: 20160524093540) do ActiveRecord::Schema.define(version: 20160607150440) 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"
@ -278,6 +278,7 @@ ActiveRecord::Schema.define(version: 20160524093540) do
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.integer "procedure_id" t.integer "procedure_id"
t.integer "order_place"
end end
create_table "users", force: :cascade do |t| create_table "users", force: :cascade do |t|

View file

@ -2,12 +2,12 @@ require 'spec_helper'
describe Admin::PiecesJustificativesController, type: :controller do describe Admin::PiecesJustificativesController, type: :controller do
let(:admin) { create(:administrateur) } let(:admin) { create(:administrateur) }
let(:procedure) { create(:procedure, administrateur: admin) }
before do before do
sign_in admin sign_in admin
end end
describe 'GET #show' do describe 'GET #show' do
let(:procedure) { create(:procedure, administrateur: admin) }
let(:procedure_id) { procedure.id } let(:procedure_id) { procedure.id }
subject { get :show, procedure_id: procedure_id } subject { get :show, procedure_id: procedure_id }
@ -30,7 +30,6 @@ describe Admin::PiecesJustificativesController, type: :controller do
end end
describe 'PUT #update' do describe 'PUT #update' do
let(:procedure) { create(:procedure, administrateur: admin) }
let(:procedure_id) { procedure.id } let(:procedure_id) { procedure.id }
let(:libelle) { 'RIB' } let(:libelle) { 'RIB' }
let(:description) { "relevé d'identité bancaire" } let(:description) { "relevé d'identité bancaire" }
@ -72,7 +71,6 @@ describe Admin::PiecesJustificativesController, type: :controller do
end end
describe 'DELETE #destroy' do describe 'DELETE #destroy' do
let(:procedure) { create(:procedure, administrateur: admin) }
let!(:pj) { create(:type_de_piece_justificative, procedure: procedure) } let!(:pj) { create(:type_de_piece_justificative, procedure: procedure) }
let(:procedure_id) { procedure.id } let(:procedure_id) { procedure.id }
let(:pj_id) { pj.id } let(:pj_id) { pj.id }
@ -97,4 +95,76 @@ describe Admin::PiecesJustificativesController, type: :controller do
it { expect{ subject }.to change(TypeDePieceJustificative, :count).by(-1) } it { expect{ subject }.to change(TypeDePieceJustificative, :count).by(-1) }
end end
end end
describe 'POST #move_up' do
subject { post :move_up, procedure_id: procedure.id, index: index, format: :js }
context 'when procedure have no type de champ' do
let(:index) { 0 }
it { expect(subject.status).to eq(400) }
end
context 'when procedure have only one type de champ' do
let(:index) { 1 }
let!(:type_de_piece_justificative) { create(:type_de_piece_justificative, procedure: procedure) }
it { expect(subject.status).to eq(400) }
end
context 'when procedure have tow type de champs' do
context 'when index == 0' do
let(:index) { 0 }
let!(:type_de_piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure) }
let!(:type_de_piece_justificative_2) { create(:type_de_piece_justificative, procedure: procedure) }
it { expect(subject.status).to eq(400) }
end
context 'when index > 0' do
let(:index) { 1 }
let!(:type_de_piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure, order_place: 0) }
let!(:type_de_piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure, order_place: 1) }
it { expect(subject.status).to eq(200) }
it { expect(subject).to render_template('show') }
it 'changes order places' do
post :move_up, procedure_id: procedure.id, index: index, format: :js
type_de_piece_justificative_0.reload
type_de_piece_justificative_1.reload
expect(type_de_piece_justificative_0.order_place).to eq(1)
expect(type_de_piece_justificative_1.order_place).to eq(0)
end
end
end
end
describe 'POST #move_down' do
let(:request) { post :move_down, procedure_id: procedure.id, index: index, format: :js }
let(:index) { 0 }
subject { request }
context 'when procedure have no type de champ' do
it { expect(subject.status).to eq(400) }
end
context 'when procedure have only one type de champ' do
let!(:type_de_piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure) }
it { expect(subject.status).to eq(400) }
end
context 'when procedure have 2 type de champ' do
let!(:type_de_piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure, order_place: 0) }
let!(:type_de_piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure, order_place: 1) }
context 'when index represent last type_de_piece_justificative' do
let(:index) { 1 }
it { expect(subject.status).to eq(400) }
end
context 'when index does not represent last type_de_piece_justificative' do
let(:index) { 0 }
it { expect(subject.status).to eq(200) }
it { expect(subject).to render_template('show') }
it 'changes order place' do
request
type_de_piece_justificative_0.reload
type_de_piece_justificative_1.reload
expect(type_de_piece_justificative_0.order_place).to eq(1)
expect(type_de_piece_justificative_1.order_place).to eq(0)
end
end
end
end
end end

View file

@ -0,0 +1,55 @@
require 'spec_helper'
describe TypeDeChampDecorator do
let(:procedure) { create(:procedure) }
let(:url) { 'http://localhost' }
let(:params) { { url: url, index: index } }
let!(:type_de_champ_0) { create(:type_de_champ, procedure: procedure, order_place: 0) }
let!(:type_de_champ_1) { create(:type_de_champ, procedure: procedure, order_place: 1) }
let!(:type_de_champ_2) { create(:type_de_champ, procedure: procedure, order_place: 2) }
describe '#button_up' do
describe 'with first piece justificative' do
let(:index) { 0 }
subject { type_de_champ_0.decorate }
let(:button_up) { type_de_champ_.decorate }
it 'returns a button up' do
expect(subject.button_up(params)).to be(nil)
end
it 'returns a button down' do
expect(subject.button_down(params)).to match(/fa-chevron-down/)
end
end
describe 'with second out of three piece justificative' do
let(:index) { 1 }
subject { type_de_champ_1.decorate }
let(:button_up) { type_de_champ_1.decorate }
it 'returns a button up' do
expect(subject.button_up(params)).to match(/fa-chevron-up/)
end
it 'returns a button down' do
expect(subject.button_down(params)).to match(/fa-chevron-down/)
end
end
describe 'with last piece justificative' do
let(:index) { 2 }
subject { type_de_champ_2.decorate }
let(:button_up) { type_de_champ_1.decorate }
it 'returns a button up' do
expect(subject.button_up(params)).to match(/fa-chevron-up/)
end
it 'returns a button down' do
expect(subject.button_down(params)).to be(nil)
end
end
end
end

View file

@ -0,0 +1,54 @@
require 'spec_helper'
describe TypeDePieceJustificativeDecorator do
let(:procedure) { create(:procedure) }
let(:url) { 'http://localhost' }
let(:params) { { url: url, index: index } }
let!(:type_de_piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure, order_place: 0) }
let!(:type_de_piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure, order_place: 1) }
let!(:type_de_piece_justificative_2) { create(:type_de_piece_justificative, procedure: procedure, order_place: 2) }
describe '#button_up' do
describe 'with first piece justificative' do
let(:index) { 0 }
subject { type_de_piece_justificative_0.decorate }
let(:button_up) { type_de_piece_justificative_.decorate }
it 'returns a button up' do
expect(subject.button_up(params)).to be(nil)
end
it 'returns a button down' do
expect(subject.button_down(params)).to match(/fa-chevron-down/)
end
end
describe 'with second out of three piece justificative' do
let(:index) { 1 }
subject { type_de_piece_justificative_1.decorate }
let(:button_up) { type_de_piece_justificative_1.decorate }
it 'returns a button up' do
expect(subject.button_up(params)).to match(/fa-chevron-up/)
end
it 'returns a button down' do
expect(subject.button_down(params)).to match(/fa-chevron-down/)
end
end
describe 'with last piece justificative' do
let(:index) { 2 }
subject { type_de_piece_justificative_2.decorate }
let(:button_up) { type_de_piece_justificative_1.decorate }
it 'returns a button up' do
expect(subject.button_up(params)).to match(/fa-chevron-up/)
end
it 'returns a button down' do
expect(subject.button_down(params)).to be(nil)
end
end
end
end

View file

@ -9,6 +9,7 @@ describe TypeDePieceJustificative do
it { is_expected.to have_db_column(:api_entreprise) } it { is_expected.to have_db_column(:api_entreprise) }
it { is_expected.to have_db_column(:created_at) } it { is_expected.to have_db_column(:created_at) }
it { is_expected.to have_db_column(:updated_at) } it { is_expected.to have_db_column(:updated_at) }
it { is_expected.to have_db_column(:order_place) }
end end
describe 'associations' do describe 'associations' do
@ -22,5 +23,11 @@ describe TypeDePieceJustificative do
it { is_expected.not_to allow_value('').for(:libelle) } it { is_expected.not_to allow_value('').for(:libelle) }
it { is_expected.to allow_value('RIB').for(:libelle) } it { is_expected.to allow_value('RIB').for(:libelle) }
end end
context 'order_place' do
# it { is_expected.not_to allow_value(nil).for(:order_place) }
# it { is_expected.not_to allow_value('').for(:order_place) }
it { is_expected.to allow_value(1).for(:order_place) }
end
end end
end end

View file

@ -0,0 +1,48 @@
require 'spec_helper'
describe 'admin/pieces_justificatives/show.html.haml', type: :view do
let(:procedure) { create(:procedure) }
describe 'fields sorted' do
let(:first_libelle) { 'salut la compagnie' }
let(:last_libelle) { 'je suis bien sur la page' }
let!(:type_de_piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure, order_place: 1, libelle: last_libelle) }
let!(:type_de_piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure, order_place: 0, libelle: first_libelle) }
before do
procedure.reload
assign(:procedure, procedure)
render
end
it 'sorts by order place' do
expect(rendered).to match(/#{first_libelle}.*#{last_libelle}/m)
end
end
describe 'arrow button' do
subject do
procedure.reload
assign(:procedure, procedure)
render
rendered
end
context 'when there is no field in database' do
it { expect(subject).not_to have_css('.fa-chevron-down') }
it { expect(subject).not_to have_css('.fa-chevron-up') }
end
context 'when there is only one field in database' do
let!(:type_de_piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure, order_place: 0) }
it { expect(subject).not_to have_css('#btn_down_0') }
it { expect(subject).not_to have_css('#btn_up_0') }
it { expect(subject).not_to have_css('#btn_up_1') }
it { expect(subject).not_to have_css('#btn_down_1') }
end
context 'when there are 2 fields in database' do
let!(:type_de_piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure, order_place: 0) }
let!(:type_de_piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure, order_place: 1) }
it { expect(subject).to have_css('#btn_down_0') }
it { expect(subject).not_to have_css('#btn_up_0') }
it { expect(subject).to have_css('#btn_up_1') }
it { expect(subject).not_to have_css('#btn_down_1') }
end
end
end