aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/assets/stylesheets/components/_buttons.sass7
-rw-r--r--app/controllers/lines_controller.rb8
-rw-r--r--app/decorators/line_decorator.rb20
-rw-r--r--app/decorators/referential_line_decorator.rb9
-rw-r--r--app/helpers/links_helper.rb15
-rw-r--r--app/helpers/table_builder_helper.rb6
-rw-r--r--app/models/chouette/line.rb11
-rw-r--r--app/policies/line_policy.rb8
-rw-r--r--config/locales/actions.en.yml2
-rw-r--r--config/locales/actions.fr.yml2
-rw-r--r--config/locales/lines.en.yml8
-rw-r--r--config/locales/lines.fr.yml4
-rw-r--r--config/routes.rb5
-rw-r--r--lib/link.rb5
-rw-r--r--spec/controllers/lines_controller_spec.rb38
-rw-r--r--spec/controllers/stop_area_referentials_controller_spec.rb2
-rw-r--r--spec/support/integration_spec_helper.rb34
-rw-r--r--spec/views/lines/index.html.erb_spec.rb27
-rw-r--r--spec/views/lines/index.html.slim_spec.rb71
19 files changed, 228 insertions, 54 deletions
diff --git a/app/assets/stylesheets/components/_buttons.sass b/app/assets/stylesheets/components/_buttons.sass
index a59699383..a649a07ef 100644
--- a/app/assets/stylesheets/components/_buttons.sass
+++ b/app/assets/stylesheets/components/_buttons.sass
@@ -165,6 +165,13 @@ table, .table
.fa:first-child
margin-right: 0.5em
+ & + li.delete-action
+ > a, > button
+ margin-top: 0
+ &:before
+ display: none
+
+
&.table-2entries .t2e-item
> .th
position: relative
diff --git a/app/controllers/lines_controller.rb b/app/controllers/lines_controller.rb
index 571c73f4a..676581076 100644
--- a/app/controllers/lines_controller.rb
+++ b/app/controllers/lines_controller.rb
@@ -50,6 +50,14 @@ class LinesController < ChouetteController
super
end
+ %w(activate deactivate).each do |action|
+ define_method action do
+ authorize resource, "#{action}?"
+ resource.send "#{action}!"
+ redirect_to request.referer || [resource.line_referential, resource]
+ end
+ end
+
# overwrite inherited resources to use delete instead of destroy
# foreign keys will propagate deletion)
def destroy_resource(object)
diff --git a/app/decorators/line_decorator.rb b/app/decorators/line_decorator.rb
index ede670cbd..fe0750b05 100644
--- a/app/decorators/line_decorator.rb
+++ b/app/decorators/line_decorator.rb
@@ -41,6 +41,26 @@ class LineDecorator < Draper::Decorator
)
end
+ if h.policy(object).deactivate?
+ links << Link.new(
+ content: h.deactivate_link_content('lines.actions.deactivate'),
+ href: h.deactivate_line_referential_line_path(context[:line_referential], object),
+ method: :put,
+ data: {confirm: h.t('lines.actions.deactivate_confirm')},
+ extra_class: "delete-action"
+ )
+ end
+
+ if h.policy(object).activate?
+ links << Link.new(
+ content: h.activate_link_content('lines.actions.activate'),
+ href: h.activate_line_referential_line_path(context[:line_referential], object),
+ method: :put,
+ data: {confirm: h.t('lines.actions.activate_confirm')},
+ extra_class: "delete-action"
+ )
+ end
+
if h.policy(object).destroy?
links << Link.new(
content: h.destroy_link_content('lines.actions.destroy'),
diff --git a/app/decorators/referential_line_decorator.rb b/app/decorators/referential_line_decorator.rb
index 654f68bf5..dceb3e2a9 100644
--- a/app/decorators/referential_line_decorator.rb
+++ b/app/decorators/referential_line_decorator.rb
@@ -24,15 +24,6 @@ class ReferentialLineDecorator < Draper::Decorator
)
)
- if h.policy(object).destroy?
- links << Link.new(
- content: h.destroy_link_content('actions.destroy'),
- href: h.referential_line_path(context[:referential], object),
- method: :delete,
- data: { confirm: t('lines.actions.destroy_confirm') }
- )
- end
-
if !object.hub_restricted? ||
(object.hub_restricted? && object.routes.size < 2)
if h.policy(Chouette::Route).create? &&
diff --git a/app/helpers/links_helper.rb b/app/helpers/links_helper.rb
index 4fb7a797d..088415dc3 100644
--- a/app/helpers/links_helper.rb
+++ b/app/helpers/links_helper.rb
@@ -1,5 +1,18 @@
module LinksHelper
+ def custom_link_content(translation_key, klass, extra_class: nil)
+ klass = ["fa", "fa-#{klass}", "mr-xs", extra_class].compact.join(" ")
+ content_tag(:span, nil, class: klass) + t(translation_key)
+ end
+
def destroy_link_content(translation_key = 'actions.destroy')
- content_tag(:span, nil, class: 'fa fa-trash mr-xs') + t(translation_key)
+ custom_link_content translation_key, 'trash'
+ end
+
+ def deactivate_link_content(translation_key = 'actions.deactivate')
+ custom_link_content translation_key, 'power-off', extra_class: "text-danger"
+ end
+
+ def activate_link_content(translation_key = 'actions.activate')
+ custom_link_content translation_key, 'power-off', extra_class: "text-success"
end
end
diff --git a/app/helpers/table_builder_helper.rb b/app/helpers/table_builder_helper.rb
index de78e903d..96b2889da 100644
--- a/app/helpers/table_builder_helper.rb
+++ b/app/helpers/table_builder_helper.rb
@@ -368,6 +368,10 @@ module TableBuilderHelper
end
def gear_menu_link(link)
+ klass = [link.extra_class]
+ klass << 'delete-action' if link.method == :delete
+ klass = klass.compact.join(' ')
+ klass = nil unless klass.present?
content_tag(
:li,
link_to(
@@ -377,7 +381,7 @@ module TableBuilderHelper
) do
link.content
end,
- class: ('delete-action' if link.method == :delete)
+ class: klass
)
end
diff --git a/app/models/chouette/line.rb b/app/models/chouette/line.rb
index 93d4f5e8b..2d776e94b 100644
--- a/app/models/chouette/line.rb
+++ b/app/models/chouette/line.rb
@@ -79,5 +79,16 @@ module Chouette
line_referential.companies.where(id: ([company_id] + Array(secondary_company_ids)).compact)
end
+ def deactivate!
+ update_attribute :deactivated, true
+ end
+
+ def activate!
+ update_attribute :deactivated, false
+ end
+
+ def activated?
+ !deactivated
+ end
end
end
diff --git a/app/policies/line_policy.rb b/app/policies/line_policy.rb
index 67ea0b611..e5674fbe2 100644
--- a/app/policies/line_policy.rb
+++ b/app/policies/line_policy.rb
@@ -14,6 +14,14 @@ class LinePolicy < ApplicationPolicy
user.has_permission?('lines.destroy')
end
+ def deactivate?
+ !record.deactivated? && user.has_permission?('lines.change_status')
+ end
+
+ def activate?
+ record.deactivated? && user.has_permission?('lines.change_status')
+ end
+
def update?
user.has_permission?('lines.update')
end
diff --git a/config/locales/actions.en.yml b/config/locales/actions.en.yml
index 2706ba69d..f5f48db22 100644
--- a/config/locales/actions.en.yml
+++ b/config/locales/actions.en.yml
@@ -1,6 +1,8 @@
en:
actions:
edit: "Edit"
+ activate: 'Activate'
+ deactivate: 'Deactivate'
destroy: "Destroy"
delete: "Delete"
search: "Search"
diff --git a/config/locales/actions.fr.yml b/config/locales/actions.fr.yml
index e796017c7..4b3ac6901 100644
--- a/config/locales/actions.fr.yml
+++ b/config/locales/actions.fr.yml
@@ -1,6 +1,8 @@
fr:
actions:
edit: 'Editer'
+ activate: 'Activer'
+ deactivate: 'Désactiver'
destroy: 'Supprimer'
delete: 'Supprimer'
search: "Chercher"
diff --git a/config/locales/lines.en.yml b/config/locales/lines.en.yml
index 78d5c36be..0bbe1b30d 100644
--- a/config/locales/lines.en.yml
+++ b/config/locales/lines.en.yml
@@ -6,8 +6,12 @@ en:
edit: "Edit this line"
edit_footnotes: "Edit line footnotes"
destroy: "Remove this line"
- destroy_confirm: "Are you sure you want destroy this line?"
- destroy_selection_confirm: "Are you sure you want destroy those lines?"
+ activate: "Activate this line"
+ deactivate: "Deactivate this line"
+ activate_confirm: "Are you sure you want to activate this line ?"
+ deactivate_confirm: "Are you sure you want tode activate this line ?"
+ destroy_confirm: "Are you sure you want to destroy this line ?"
+ destroy_selection_confirm: "Are you sure you want to destroy those lines ?"
import: "Import lines"
export_kml: "Export KML line"
export_kml_all: "Export KML lines"
diff --git a/config/locales/lines.fr.yml b/config/locales/lines.fr.yml
index 36254d754..9397f6989 100644
--- a/config/locales/lines.fr.yml
+++ b/config/locales/lines.fr.yml
@@ -6,6 +6,10 @@ fr:
edit: "Editer cette ligne"
edit_footnotes: "Editer notes en bas de page"
destroy: "Supprimer cette ligne"
+ activate: "Activer cette ligne"
+ deactivate: "Désactiver cette ligne"
+ activate_confirm: "Etes vous sûr d'activer cette ligne ?"
+ deactivate_confirm: "Etes vous sûr de désactiver cette ligne ?"
destroy_confirm: "Etes vous sûr de supprimer cette ligne ?"
destroy_selection_confirm: "Etes vous sûr de supprimer cette sélection de lignes ?"
import: "Importer des lignes"
diff --git a/config/routes.rb b/config/routes.rb
index d097d2d71..a36ecc36e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -93,7 +93,10 @@ ChouetteIhm::Application.routes.draw do
resources :line_referentials, :only => [:show, :edit, :update] do
post :sync, on: :member
- resources :lines
+ resources :lines do
+ put :deactivate, on: :member
+ put :activate, on: :member
+ end
resources :group_of_lines
resources :companies
resources :networks
diff --git a/lib/link.rb b/lib/link.rb
index 7683a808f..d34c5c59a 100644
--- a/lib/link.rb
+++ b/lib/link.rb
@@ -1,10 +1,11 @@
class Link
- attr_reader :content, :href, :method, :data
+ attr_reader :content, :href, :method, :data, :extra_class
- def initialize(content: nil, href:, method: nil, data: nil)
+ def initialize(content: nil, href:, method: nil, data: nil, extra_class: nil)
@content = content
@href = href
@method = method
@data = data
+ @extra_class = extra_class
end
end
diff --git a/spec/controllers/lines_controller_spec.rb b/spec/controllers/lines_controller_spec.rb
new file mode 100644
index 000000000..ce5adbbdd
--- /dev/null
+++ b/spec/controllers/lines_controller_spec.rb
@@ -0,0 +1,38 @@
+RSpec.describe LinesController, :type => :controller do
+ login_user
+
+ let(:line_referential) { create :line_referential }
+ let(:line) { create :line, line_referential: line_referential }
+
+ describe 'PUT deactivate' do
+ let(:request){ put :deactivate, id: line.id, line_referential_id: line_referential.id }
+
+ it 'should redirect to 403' do
+ expect(request).to redirect_to "/403"
+ end
+
+ with_permission "lines.change_status" do
+ it 'returns HTTP success' do
+ expect(request).to redirect_to [line_referential, line]
+ expect(line.reload).to be_deactivated
+ end
+ end
+ end
+
+ describe 'PUT activate' do
+ let(:request){ put :activate, id: line.id, line_referential_id: line_referential.id }
+ before(:each){
+ line.deactivate!
+ }
+ it 'should redirect to 403' do
+ expect(request).to redirect_to "/403"
+ end
+
+ with_permission "lines.change_status" do
+ it 'returns HTTP success' do
+ expect(request).to redirect_to [line_referential, line]
+ expect(line.reload).to be_activated
+ end
+ end
+ end
+end
diff --git a/spec/controllers/stop_area_referentials_controller_spec.rb b/spec/controllers/stop_area_referentials_controller_spec.rb
index c8d7e1736..384323334 100644
--- a/spec/controllers/stop_area_referentials_controller_spec.rb
+++ b/spec/controllers/stop_area_referentials_controller_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe StopAreaReferentialsController, :type => :controller do
describe 'PUT sync' do
let(:request){ put :sync, id: stop_area_referential.id }
- it { request.should redirect_to "/403" }
+ it { expect(request).to redirect_to "/403" }
with_permission "stop_area_referentials.synchronize" do
it 'returns HTTP success' do
diff --git a/spec/support/integration_spec_helper.rb b/spec/support/integration_spec_helper.rb
index 1bf211fe1..36306559d 100644
--- a/spec/support/integration_spec_helper.rb
+++ b/spec/support/integration_spec_helper.rb
@@ -1,19 +1,20 @@
module IntegrationSpecHelper
- def paginate_collection klass, decorator, page=1
- coll = klass.page(page)
+ def paginate_collection klass, decorator, page=1, context={}
+ collection = klass.page(page)
if decorator
- coll = ModelDecorator.decorate( coll, with: decorator )
+ collection = ModelDecorator.decorate(collection, with: decorator, context: context)
end
- coll
+ collection
end
def build_paginated_collection factory, decorator, opts={}
+ context = opts.delete(:context) || {}
count = opts.delete(:count) || 2
page = opts.delete(:page) || 1
klass = nil
- count.times { klass ||= create(factory, opts).class }
- paginate_collection klass, decorator, page
+ count.times { klass = create(factory, opts).class }
+ paginate_collection klass, decorator, page, context
end
module Methods
@@ -34,20 +35,33 @@ RSpec.configure do |config|
config.include IntegrationSpecHelper, type: :view
end
-RSpec::Matchers.define :have_link_for_each_item do |collection, name, href|
+RSpec::Matchers.define :have_link_for_each_item do |collection, name, opts|
+ opts = {href: opts} unless opts.is_a? Hash
+ href = opts[:href]
+ method = opts[:method]
+ method_selector = method.present? ? "[data-method='#{method.downcase}']": ""
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)
+ @selector = "tr.#{TableBuilderHelper.item_row_class_name(collection)}-#{item.id} .actions a[href='#{href.call(item)}']#{method_selector}"
+ expect(rendered).to have_selector(@selector, count: 1)
end
end
description { "have #{name} link for each item" }
+ failure_message do
+ "expected view to have #{name} link for each item, failed with selector: \"#{@selector}\""
+ end
end
RSpec::Matchers.define :have_the_right_number_of_links do |collection, count|
- match do |actual|
+ match do
collection.each do |item|
- expect(rendered).to have_selector("tr.#{TableBuilderHelper.item_row_class_name(collection)}-#{item.id} .actions a", count: count)
+ @selector = "tr.#{TableBuilderHelper.item_row_class_name(collection)}-#{item.id} .actions a"
+ expect(rendered).to have_selector(@selector, count: count)
end
end
description { "have #{count} links for each item" }
+ failure_message do
+ actual = Capybara::Node::Simple.new(rendered).all(@selector).count
+ "expected #{count} links for each item, got #{actual} for \"#{@selector}\""
+ end
end
diff --git a/spec/views/lines/index.html.erb_spec.rb b/spec/views/lines/index.html.erb_spec.rb
deleted file mode 100644
index dbc3cbdb7..000000000
--- a/spec/views/lines/index.html.erb_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-require 'spec_helper'
-
-describe "/lines/index", :type => :view do
-
- let!(:line_referential) { assign :line_referential, create(:line_referential) }
- let!(:network) { create :network }
- let!(:company) { create :company }
- let!(:lines) { assign :lines, Array.new(2) { create(:line, line_referential: line_referential, network: network, company: company) }.paginate }
- let!(:q) { assign :q, Ransack::Search.new(Chouette::Line) }
-
- before :each do
- allow(view).to receive(:link_with_search).and_return("#")
- end
-
- # it "should render a show link for each group" do
- # render
- # lines.each do |line|
- # expect(rendered).to have_selector(".line a[href='#{view.line_referential_line_path(line_referential, line)}']", :text => line.name)
- # end
- # end
- #
- # it "should render a link to create a new group" do
- # render
- # expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{new_line_referential_line_path(line_referential)}']")
- # end
-
-end
diff --git a/spec/views/lines/index.html.slim_spec.rb b/spec/views/lines/index.html.slim_spec.rb
new file mode 100644
index 000000000..498784912
--- /dev/null
+++ b/spec/views/lines/index.html.slim_spec.rb
@@ -0,0 +1,71 @@
+require 'spec_helper'
+
+describe "/lines/index", :type => :view do
+ let(:deactivated_line){ nil }
+ let(:line_referential) { assign :line_referential, create(:line_referential) }
+ let(:current_organisation) { current_user.organisation }
+ let(:context) {
+ {
+ current_organisation: current_organisation,
+ line_referential: line_referential
+ }
+ }
+ let(:lines) do
+ assign :lines, build_paginated_collection(:line, LineDecorator, line_referential: line_referential, context: context)
+ end
+ let!(:q) { assign :q, Ransack::Search.new(Chouette::Line) }
+
+ before :each do
+ deactivated_line
+ allow(view).to receive(:collection).and_return(lines)
+ allow(view).to receive(:current_referential).and_return(line_referential)
+ controller.request.path_parameters[:line_referential_id] = line_referential.id
+ render
+ end
+
+ common_items = ->{
+ it { should have_link_for_each_item(lines, "show", -> (line){ view.line_referential_line_path(line_referential, line) }) }
+ it { should have_link_for_each_item(lines, "network", -> (line){ view.line_referential_network_path(line_referential, line.network) }) }
+ it { should have_link_for_each_item(lines, "company", -> (line){ view.line_referential_company_path(line_referential, line.company) }) }
+ }
+
+ common_items.call()
+ it { should have_the_right_number_of_links(lines, 3) }
+
+ with_permission "lines.change_status" do
+ common_items.call()
+ it { should have_link_for_each_item(lines, "deactivate", -> (line){ view.deactivate_line_referential_line_path(line_referential, line) }) }
+ it { should have_the_right_number_of_links(lines, 4) }
+ end
+
+ with_permission "lines.destroy" do
+ common_items.call()
+ it {
+ should have_link_for_each_item(lines, "destroy", {
+ href: ->(line){ view.line_referential_line_path(line_referential, line)},
+ method: :delete
+ })
+ }
+ it { should have_the_right_number_of_links(lines, 4) }
+ end
+
+ context "with a deactivated item" do
+ with_permission "lines.change_status" do
+ let(:deactivated_line){ create :line, deactivated: true }
+
+ common_items.call()
+ it "should display an activate link for the deactivated one" do
+ lines.each do |line|
+ if line == deactivated_line
+ href = view.activate_line_referential_line_path(line_referential, line)
+ else
+ href = view.deactivate_line_referential_line_path(line_referential, line)
+ end
+ selector = "tr.#{TableBuilderHelper.item_row_class_name(lines)}-#{line.id} .actions a[href='#{href}']"
+ expect(rendered).to have_selector(selector, count: 1)
+ end
+ end
+ it { should have_the_right_number_of_links(lines, 4) }
+ end
+ end
+end