diff options
| -rw-r--r-- | app/assets/stylesheets/base/_config.sass | 1 | ||||
| -rw-r--r-- | app/assets/stylesheets/components/_forms.sass | 7 | ||||
| -rw-r--r-- | app/helpers/table_builder_helper.rb | 147 | ||||
| -rw-r--r-- | app/views/workbenches/show.html.slim | 2 | ||||
| -rw-r--r-- | spec/helpers/table_builder_helper_spec.rb | 81 | ||||
| -rw-r--r-- | spec/support/integration_spec_helper.rb | 47 | ||||
| -rw-r--r-- | spec/views/offer_workbenches/show.html.erb_spec.rb | 55 | ||||
| -rw-r--r-- | spec/views/stop_areas/index.html.slim_spec.rb | 27 |
8 files changed, 269 insertions, 98 deletions
diff --git a/app/assets/stylesheets/base/_config.sass b/app/assets/stylesheets/base/_config.sass index 65444479f..ec1c43e7f 100644 --- a/app/assets/stylesheets/base/_config.sass +++ b/app/assets/stylesheets/base/_config.sass @@ -16,6 +16,7 @@ $blue: #007fbb $darkgrey: #4b4b4b $grey: #a4a4a4 +$lightgrey: rgba($grey, 0.15) $green: #70b12b $red: #da2f36 diff --git a/app/assets/stylesheets/components/_forms.sass b/app/assets/stylesheets/components/_forms.sass index 9a363ab97..47faf19b1 100644 --- a/app/assets/stylesheets/components/_forms.sass +++ b/app/assets/stylesheets/components/_forms.sass @@ -229,6 +229,13 @@ $cbx-size-xs: 15px &[type='checkbox']:checked + label:before background-color: $blue + &[type='checkbox']:disabled + label + &:before + border-color: $grey + background-color: $lightgrey + cursor: not-allowed + &:after + display: none // Table adjustments table, .table .td, td, .th, th diff --git a/app/helpers/table_builder_helper.rb b/app/helpers/table_builder_helper.rb index 64bec6bae..de78e903d 100644 --- a/app/helpers/table_builder_helper.rb +++ b/app/helpers/table_builder_helper.rb @@ -95,6 +95,18 @@ module TableBuilderHelper class: cls end + def self.item_row_class_name collection + if collection.respond_to?(:model) + model_name = collection.model.name + elsif collection.respond_to?(:first) + model_name = collection.first.class.name + else + model_name = "item" + end + + model_name.split("::").last.parameterize + end + private def thead(collection, columns, sortable, selectable, has_links, overhead, model ) @@ -187,92 +199,92 @@ module TableBuilderHelper end end - def tbody(collection, columns, selectable, links, overhead) - if collection.respond_to?(:model) - model_name = collection.model.name.split("::").last - else - model_name = "item" - end - - content_tag :tbody do - collection.map do |item| - klass = "#{model_name.parameterize}-#{item.id}" - content_tag :tr, class: klass do - bcont = [] - - if selectable - bcont << content_tag( - :td, - checkbox(id_name: item.try(:id), value: item.try(:id)) - ) - end - - columns.each do |column| - value = column.value(item) - - if column.linkable? - path = column.link_to(item) - link = link_to(value, path) + def tr item, columns, selectable, links, overhead, model_name + klass = "#{model_name}-#{item.id}" + content_tag :tr, class: klass do + bcont = [] + if selectable + disabled = selectable.respond_to?(:call) && !selectable.call(item) + bcont << content_tag( + :td, + checkbox(id_name: item.try(:id), value: item.try(:id), disabled: disabled) + ) + end - if overhead.empty? - bcont << content_tag(:td, link, title: 'Voir') + columns.each do |column| + value = column.value(item) - else - i = columns.index(column) + if column.linkable? + path = column.link_to(item) + link = link_to(value, path) - if overhead[i].blank? - if (i > 0) && (overhead[i - 1][:width] > 1) - clsArrayAlt = overhead[i - 1][:cls].split + if overhead.empty? + bcont << content_tag(:td, link, title: 'Voir') - bcont << content_tag(:td, link, title: 'Voir', class: td_cls(clsArrayAlt)) + else + i = columns.index(column) - else - bcont << content_tag(:td, link, title: 'Voir') - end + if overhead[i].blank? + if (i > 0) && (overhead[i - 1][:width] > 1) + clsArrayAlt = overhead[i - 1][:cls].split - else - clsArray = overhead[columns.index(column)][:cls].split + bcont << content_tag(:td, link, title: 'Voir', class: td_cls(clsArrayAlt)) - bcont << content_tag(:td, link, title: 'Voir', class: td_cls(clsArray)) - end + else + bcont << content_tag(:td, link, title: 'Voir') end else - if overhead.empty? - bcont << content_tag(:td, value) + clsArray = overhead[columns.index(column)][:cls].split - else - i = columns.index(column) + bcont << content_tag(:td, link, title: 'Voir', class: td_cls(clsArray)) + end + end - if overhead[i].blank? - if (i > 0) && (overhead[i - 1][:width] > 1) - clsArrayAlt = overhead[i - 1][:cls].split + else + if overhead.empty? + bcont << content_tag(:td, value) - bcont << content_tag(:td, value, class: td_cls(clsArrayAlt)) + else + i = columns.index(column) - else - bcont << content_tag(:td, value) - end + if overhead[i].blank? + if (i > 0) && (overhead[i - 1][:width] > 1) + clsArrayAlt = overhead[i - 1][:cls].split - else - clsArray = overhead[i][:cls].split + bcont << content_tag(:td, value, class: td_cls(clsArrayAlt)) - bcont << content_tag(:td, value, class: td_cls(clsArray)) - end + else + bcont << content_tag(:td, value) end + + else + clsArray = overhead[i][:cls].split + + bcont << content_tag(:td, value, class: td_cls(clsArray)) end end + end + end - if links.any? || item.try(:action_links).try(:any?) - bcont << content_tag( - :td, - build_links(item, links), - class: 'actions' - ) - end + if links.any? || item.try(:action_links).try(:any?) + bcont << content_tag( + :td, + build_links(item, links), + class: 'actions' + ) + end - bcont.join.html_safe - end + bcont.join.html_safe + end + end + + def tbody(collection, columns, selectable, links, overhead) + model_name = TableBuilderHelper.item_row_class_name collection + + content_tag :tbody do + collection.map do |item| + tr item, columns, selectable, links, overhead, model_name end.join.html_safe end end @@ -347,13 +359,14 @@ module TableBuilderHelper end end - def checkbox(id_name:, value:) + def checkbox(id_name:, value:, disabled: false) content_tag :div, '', class: 'checkbox' do - check_box_tag(id_name, value).concat( + check_box_tag(id_name, value, nil, disabled: disabled).concat( content_tag(:label, '', for: id_name) ) end end + def gear_menu_link(link) content_tag( :li, diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim index af312fc08..1c82c34b7 100644 --- a/app/views/workbenches/show.html.slim +++ b/app/views/workbenches/show.html.slim @@ -57,7 +57,7 @@ attribute: '' \ ) \ ], - selectable: true, + selectable: ->(ref){ @workbench.referentials.include?(ref) }, links: [:show, :edit], cls: 'table has-filter has-search' diff --git a/spec/helpers/table_builder_helper_spec.rb b/spec/helpers/table_builder_helper_spec.rb index 3b3504c60..83b746d4b 100644 --- a/spec/helpers/table_builder_helper_spec.rb +++ b/spec/helpers/table_builder_helper_spec.rb @@ -381,5 +381,86 @@ describe TableBuilderHelper, type: :helper do expect(beautified_html).to eq(expected.chomp) end + + context "on a single row" do + let(:referential){ build_stubbed :referential } + let(:other_referential){ build_stubbed :referential } + let(:user_context){ + UserContext.new( + build_stubbed( + :user, + organisation: referential.organisation, + permissions: [ + 'referentials.create', + 'referentials.update', + 'referentials.destroy', + ] + ), + referential: referential + ) + } + let(:columns){ + [ + TableBuilderHelper::Column.new( + key: :name, + attribute: 'name' + ), + ] + } + let(:item){ referential.decorate } + let(:other_item){ other_referential.decorate } + let(:selectable){ false } + let(:links){ [:show] } + let(:overhead){ [] } + let(:model_name){ "referential" } + let(:other_tr){ helper.send(:tr, other_item, columns, selectable, links, overhead, model_name) } + let(:items){ [item, other_item] } + + before(:each){ + allow(helper).to receive(:current_user).and_return(user_context) + } + + context "with all rows non-selectable" do + let(:selectable){ false } + it "sets all rows as non selectable" do + items.each do |i| + tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name) + klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}" + selector = "tr.#{klass} [type=checkbox]" + expect(tr).to_not have_selector selector + end + end + end + + context "with all rows selectable" do + let(:selectable){ true } + it "adds a checkbox in all rows" do + items.each do |i| + tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name) + klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}" + selector = "tr.#{klass} [type=checkbox]" + expect(tr).to have_selector selector + end + end + end + + context "with THIS row non selectable" do + let(:selectable){ ->(i){ i.id != item.id } } + it "adds a checkbox in all rows" do + items.each do |i| + tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name) + klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}" + selector = "tr.#{klass} [type=checkbox]" + expect(tr).to have_selector selector + end + end + it "disables this rows checkbox" do + tr = helper.send(:tr, item, columns, selectable, links, overhead, model_name) + klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{item.id}" + selector = "tr.#{klass} [type=checkbox][disabled]" + expect(tr).to have_selector selector + end + end + end end end diff --git a/spec/support/integration_spec_helper.rb b/spec/support/integration_spec_helper.rb index 182cadf24..78efb9027 100644 --- a/spec/support/integration_spec_helper.rb +++ b/spec/support/integration_spec_helper.rb @@ -1,12 +1,49 @@ module IntegrationSpecHelper - def with_permission permission, &block - context "with permission #{permission}" do - let(:permissions){ [permission] } - context('', &block) if block_given? + + def paginate_collection klass, decorator, page=1 + ModelDecorator.decorate( klass.page(page), with: decorator ) + end + + def build_paginated_collection factory, decorator, opts={} + count = opts.delete(:count) || 2 + page = opts.delete(:page) || 1 + klass = nil + count.times { klass ||= create(factory, opts).class } + paginate_collection klass, decorator, page + end + + module Methods + def with_permission permission, &block + context "with permission #{permission}" do + let(:permissions){ [permission] } + context('', &block) if block_given? + end end end + + def self.included into + into.extend Methods + end end RSpec.configure do |config| - config.extend IntegrationSpecHelper, type: :view + config.include IntegrationSpecHelper, type: :view +end + +RSpec::Matchers.define :have_link_for_each_item do |collection, name, href| + match do |actual| + collection.each do |item| + expect(rendered).to have_selector("tr.#{TableBuilderHelper.item_row_class_name(collection)}-#{item.id} .actions a[href='#{href.call(item)}']", count: 1) + end + end + description { "have #{name} link for each item" } +end + +RSpec::Matchers.define :have_the_right_number_of_links do |collection, count| + match do |actual| + collection.each do |item| + expect(rendered).to have_selector("tr.#{TableBuilderHelper.item_row_class_name(collection)}-#{item.id} .actions a", count: count) + end + end + description { "have #{count} links for each item" } end diff --git a/spec/views/offer_workbenches/show.html.erb_spec.rb b/spec/views/offer_workbenches/show.html.erb_spec.rb index 40b09268a..138a1560d 100644 --- a/spec/views/offer_workbenches/show.html.erb_spec.rb +++ b/spec/views/offer_workbenches/show.html.erb_spec.rb @@ -1,5 +1,56 @@ -require 'rails_helper' +require 'spec_helper' -RSpec.describe "workbenches/show.html.erb", :type => :view do +RSpec::Matchers.define :have_box_for_item do |item, disabled| + match do |actual| + klass = "#{TableBuilderHelper.item_row_class_name([item])}-#{item.id}" + if disabled + selector = "tr.#{klass} [type=checkbox][disabled][value='#{item.id}']" + else + selector = "tr.#{klass} [type=checkbox][value='#{item.id}']:not([disabled])" + end + expect(actual).to have_selector(selector, count: 1) + end + description { "have a #{disabled ? "disabled ": ""}box for the item ##{item.id}" } +end + +describe "workbenches/show", :type => :view do + let!(:ids) { ['STIF:CODIFLIGNE:Line:C00840', 'STIF:CODIFLIGNE:Line:C00086'] } + let!(:lines) { + ids.map do |id| + create :line, objectid: id, line_referential: workbench.line_referential + end + } + let!(:workbench){ assign :workbench, create(:workbench) } + let!(:same_organisation_referential){ create :workbench_referential, workbench: workbench, metadatas: [create(:referential_metadata, lines: lines)] } + let!(:different_organisation_referential){ create :workbench_referential, metadatas: [create(:referential_metadata, lines: lines)] } + let!(:referentials){ + same_organisation_referential && different_organisation_referential + assign :wbench_refs, paginate_collection(Referential, ReferentialDecorator) + } + let!(:q) { assign :q_for_form, Ransack::Search.new(Referential) } + before :each do + lines + controller.request.path_parameters[:id] = workbench.id + expect(workbench.referentials).to include same_organisation_referential + expect(workbench.referentials).to_not include different_organisation_referential + expect(workbench.all_referentials).to include same_organisation_referential + expect(workbench.all_referentials).to include different_organisation_referential + render + end + + it { should have_link_for_each_item(referentials, "show", -> (referential){ view.referential_path(referential) }) } + + context "without permission" do + it "should disable all the checkboxes" do + expect(rendered).to have_box_for_item same_organisation_referential, false + expect(rendered).to have_box_for_item different_organisation_referential, true + end + end + with_permission "referentials.destroy" do + it "should enable the checkbox for the referential which belongs to the same organisation and disable the other one" do + expect(rendered).to have_box_for_item same_organisation_referential, false + expect(rendered).to have_box_for_item different_organisation_referential, true + end + end end diff --git a/spec/views/stop_areas/index.html.slim_spec.rb b/spec/views/stop_areas/index.html.slim_spec.rb index 64c958879..294acfe1a 100644 --- a/spec/views/stop_areas/index.html.slim_spec.rb +++ b/spec/views/stop_areas/index.html.slim_spec.rb @@ -1,29 +1,10 @@ require 'spec_helper' -RSpec::Matchers.define :have_link_for_each_stop_area do |stop_areas, name, href| - match do |actual| - stop_areas.each do |stop_area| - expect(rendered).to have_selector("tr.stoparea-#{stop_area.id} .actions a[href='#{href.call(stop_area)}']", count: 1) - end - end - description { "have #{name} link for each stop area" } -end - -RSpec::Matchers.define :have_the_right_number_of_links do |stop_areas, count| - match do |actual| - stop_areas.each do |stop_area| - expect(rendered).to have_selector("tr.stoparea-#{stop_area.id} .actions a", count: count) - end - end - description { "have #{count} links for each stop area" } -end - describe "/stop_areas/index", :type => :view do let!(:stop_area_referential) { assign :stop_area_referential, create(:stop_area_referential) } let!(:stop_areas) do - 2.times { create(:stop_area, stop_area_referential: stop_area_referential) } - assign :stop_areas, ModelDecorator.decorate( Chouette::StopArea.page(1), with: StopAreaDecorator ) + assign :stop_areas, build_paginated_collection(:stop_area, StopAreaDecorator, stop_area_referential: stop_area_referential) end let!(:q) { assign :q, Ransack::Search.new(Chouette::StopArea) } @@ -35,7 +16,7 @@ describe "/stop_areas/index", :type => :view do render end - it { should have_link_for_each_stop_area(stop_areas, "show", -> (stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) } + it { should have_link_for_each_item(stop_areas, "show", -> (stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) } it { should have_the_right_number_of_links(stop_areas, 1) } with_permission "stop_areas.create" do @@ -45,8 +26,8 @@ describe "/stop_areas/index", :type => :view do end with_permission "stop_areas.update" do - it { should have_link_for_each_stop_area(stop_areas, "show", -> (stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) } - it { should have_link_for_each_stop_area(stop_areas, "edit", -> (stop_area){ view.edit_stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) } + it { should have_link_for_each_item(stop_areas, "show", -> (stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) } + it { should have_link_for_each_item(stop_areas, "edit", -> (stop_area){ view.edit_stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) } it { should have_the_right_number_of_links(stop_areas, 2) } end |
