aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--INSTALL.md179
-rw-r--r--README.md162
-rw-r--r--app/assets/javascripts/main_menu.coffee1
-rw-r--r--app/assets/stylesheets/components/_breadcrumb.sass5
-rw-r--r--app/assets/stylesheets/components/_buttons.sass7
-rw-r--r--app/assets/stylesheets/components/_main_nav.sass16
-rw-r--r--app/controllers/concerns/activatable.rb11
-rw-r--r--app/controllers/lines_controller.rb2
-rw-r--r--app/controllers/purchase_windows_controller.rb29
-rw-r--r--app/controllers/referential_companies_controller.rb3
-rw-r--r--app/controllers/stop_areas_controller.rb3
-rw-r--r--app/decorators/line_decorator.rb23
-rw-r--r--app/decorators/referential_decorator.rb7
-rw-r--r--app/decorators/referential_line_decorator.rb9
-rw-r--r--app/decorators/stop_area_decorator.rb38
-rw-r--r--app/decorators/stop_point_decorator.rb2
-rw-r--r--app/helpers/links_helper.rb15
-rw-r--r--app/helpers/table_builder_helper.rb7
-rw-r--r--app/javascript/vehicle_journeys/components/Tools.js4
-rw-r--r--app/models/chouette/line.rb11
-rw-r--r--app/models/chouette/purchase_window.rb4
-rw-r--r--app/models/chouette/stop_area.rb15
-rw-r--r--app/policies/line_policy.rb8
-rw-r--r--app/policies/stop_area_policy.rb8
-rw-r--r--app/views/dashboards/_dashboard.html.slim41
-rw-r--r--app/views/lines/_form.html.slim3
-rw-r--r--app/views/lines/index.html.slim2
-rw-r--r--app/views/lines/show.html.slim2
-rw-r--r--app/views/purchase_windows/_filters.html.slim2
-rw-r--r--app/views/purchase_windows/_form.html.slim10
-rw-r--r--app/views/purchase_windows/index.html.slim3
-rw-r--r--app/views/referentials/show.html.slim2
-rw-r--r--app/views/vehicle_journeys/index.html.slim6
-rw-r--r--config/deploy.rb6
-rw-r--r--config/locales/actions.en.yml2
-rw-r--r--config/locales/actions.fr.yml2
-rw-r--r--config/locales/calendars.fr.yml2
-rw-r--r--config/locales/lines.en.yml9
-rw-r--r--config/locales/lines.fr.yml5
-rw-r--r--config/locales/purchase_windows.en.yml2
-rw-r--r--config/locales/purchase_windows.fr.yml4
-rw-r--r--config/locales/routes.en.yml1
-rw-r--r--config/locales/routes.fr.yml1
-rw-r--r--config/locales/stop_areas.en.yml4
-rw-r--r--config/locales/stop_areas.fr.yml4
-rw-r--r--config/routes.rb9
-rw-r--r--lib/link.rb6
-rw-r--r--spec/controllers/lines_controller_spec.rb38
-rw-r--r--spec/controllers/stop_area_referentials_controller_spec.rb2
-rw-r--r--spec/controllers/stop_areas_controller_spec.rb38
-rw-r--r--spec/factories/chouette_routes.rb7
-rw-r--r--spec/factories/chouette_stop_areas.rb4
-rw-r--r--spec/features/purchase_windows_permission_spec.rb4
-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
-rw-r--r--spec/views/stop_areas/index.html.slim_spec.rb54
-rw-r--r--spec/views/vehicle_journeys/index.html.slim_spec.rb30
58 files changed, 649 insertions, 357 deletions
diff --git a/INSTALL.md b/INSTALL.md
index 6e497b580..28ffdeb4d 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -1,31 +1,40 @@
# Installation Guide
-This guide is based on mac/OS with [Homebrew](https://brew.sh/) and [RVM](https://rvm.io/)
-
## Ruby
-Get a correct `.ruby-version` (Can we remove it from `.gitignore`?)
-and install that version.
+Example with [rvm](https://rvm.io/) (other solutions : rbenv, packages..):
-Example with [rvm](https://rvm.io/):
+```sh
+rvm install 2.3.1
+```
- rvm install 2.3.1
+## Node and Yarn
-Add the bundler gem
+Yarn needs node. If you use Node Version Manager [NVM](https://github.com/creationix/nvm) you can rely on the content of `.nvmrc`. Otherwise please make sure to use a compatible version, still best to use the same as indicated by `.nvrmc`.
- gem install bundler
+* Install node
-Go into your local repro and install the gems
+```sh
+nvm install 6.12.0
+```
- bundle
+* Install [yarn](https://yarnpkg.com/lang/en/docs/install/)
-## Node and Yarn
+```sh
+// On macOS
+brew install yarn
-Yarn needs a node version ≥ 6, if you use Node Version Manager [NVM](https://github.com/creationix/nvm) you can rely on the content of `.nvmrc`.
+// On Debian/ubuntu
+curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
+echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
+sudo apt-get update && sudo apt-get install yarn
+```
-Otherwise please make sure to use a compatible version, still best to use the same as indicated by `.nvrmc`.
+* Install nodes packages
-Then install yarn (`brew install yarn` does nicely on macOS).
+```sh
+yarn install
+```
### Installation Caveats
@@ -33,14 +42,16 @@ Then install yarn (`brew install yarn` does nicely on macOS).
`libv8` might cause you troubles, depending on your local configuration. If you have `libv8` installed (probably because of `node.js`) you might need to tell bundler/Rubygems to use the system version.
-
- bundle config build.libv8 --with-system-v8
- bundle
-
+```sh
+bundle config build.libv8 --with-system-v8
+bundle
+```
or
- gem install libv8 -v '<version>' -- --with-system-v8
- bundle
+```sh
+gem install libv8 -v '<version>' -- --with-system-v8
+bundle
+```
You will get the correct value of `<version>` from bundler's error message.
@@ -50,35 +61,18 @@ Even after `libv8` installation working, the gem `therubyracer` might not like t
In that case however we can let the gem make its own choice:
- gem uninstall libv8
- gem install therubyracer -v '<version>'
+```sh
+gem uninstall libv8
+gem install therubyracer -v '<version>'
+```
The version to be installed is indicated in the error message bundler gave us in the first place.
This will install an appropriate `libv8` version and we can continue with `bundle`.
-## Rails
-
-### Dependencies
-
-As documented [here](https://github.com/dryade/georuby-ext/issues/2) we need some more libs before we can start the `rake` setup tasks. On mac/OS the easiest way is just to install `postgis` now with `homebrew` as this will
-install all needed libraries.
-
-Also if on Linux you might discover a problem as late as when launching `rake`.
-In case of a stacktrace similar to this one
-
-```
-$ bundle exec rake --trace -T
-rake aborted!
-LoadError: library names list must not be empty
-```
-
-you need to install `libproj4-dev` on your system.
-
-
-### Postgres
+## Postgres
-#### Create user
+### Create user
createuser -s -U $USER -P chouette
^ ^ ^
@@ -88,85 +82,110 @@ you need to install `libproj4-dev` on your system.
When promted for the password enter the highly secure string `chouette`.
+## Rails
-#### Create database
+### Dependencies
- bundle exec rake db:create
- bundle exec rake db:migrate
+As documented [here](https://github.com/dryade/georuby-ext/issues/2) we need some more libs before we can start the `rake` setup tasks.
- RAILS_ENV=test bundle exec rake db:create
- RAILS_ENV=test bundle exec rake db:migrate
-#### Install node.js packages
+On mac/OS :
- bundle exec rake npm:install
+```sh
+brew install postgis
+```
-#### Check installation
+On debian/ubuntu system :
-* Run tests
+```sh
+sudo apt-get install libproj-dev postgis
+```
- bundle exec rake spec
- bundle exec rake teaspoon
+### Install gems
-* Start local server
+Add the bundler gem
- bundle exec rails server
+```sh
+gem install bundler
+```
-### Authentication
+Go into your local repository and install the gems
-See `config.chouette_authentication_settings`.
+```sh
+bundle install
+```
-Use the database authentication or get an invitation to [STIF Portail](http://stif-portail-dev.af83.priv/).
+#### Nokogiri on macOS
-### Run seed
+http://www.nokogiri.org/tutorials/installing_nokogiri.html tells us that `xz` can cause troubles, here is what to do
+```
+brew unlink xz
+gem install nokogiri # or bundle install
+brew link xz
+```
-#### Basic Database Content
+### Database
- bundle exec rake db:seed
+#### Create database
+```sh
+bundle exec rake db:create db:migrate
+RAILS_ENV=test bundle exec rake db:create db:migrate
+```
-Two users are created : stif-boiv@af83.com/secret and stif-boiv+transporteur@af83.com/secret
+#### Load seed datas
-#### Synchronize With STIF
+```sh
+bundle exec rake db:seed
+```
-If you have access to STIF CodifLigne and Reflex :
+#### Synchronise datas with lines and stop areas referentials
* Launch Sidekiq
- bundle exec sidekiq
+```sh
+bundle exec sidekiq
+```
* Execute the Synchronization Tasks
- bundle exec rake codifligne:sync
- bundle exec rake reflex:sync
+```sh
+bundle exec rake codifligne:sync
+bundle exec rake reflex:sync
+```
**N.B.** These are asynchronious tasks, you can observe the launched jobs in your [Sidekiq Console](http://localhost:3000/sidekiq)
#### Data in various Apartments (Referentials)
-To create `Referential` objects with some data (`Route`, `JourneyPattern`, `VehicleJourney`, etc) :
+To create `Referential` objects with some data (`Route`, `JourneyPattern`, `VehicleJourney`, etc), you need to wait codifligne and reflex jobs finished. And then you can launch :
- bundle exec rake referential:create
+```sh
+bundle exec rake referential:create
+```
-# Troubleshooting
+### Check installation
-## Postgres
+#### Run tests
-If Postgres complains about illegal type `hstore` in your tests that is probably because the shared extension is not installed, here is what to do:
+```sh
+bundle exec rake spec
+bundle exec rake teaspoon
+```
+
+If Postgres complains about illegal type `hstore` or `unaccent` in your tests that is probably because the shared extension is not installed, here is what to do:
bundle exec rake db:test:purge
Thanks to `lib/tasks/extensions.rake`.
-## macOS
-### Nokogiri
-http://www.nokogiri.org/tutorials/installing_nokogiri.html tells us that `xz` can cause troubles, here is what to do
+#### Start local server
+```sh
+bin/webpack-dev-server // Launch webpack server to compile assets on the fly
+bundle exec rails server // Launch rails server
```
-brew unlink xz
-gem install nokogiri # or bundle install
-brew link xz
-```
+You need to have an account on [STIF Portail](http://stif-portail-dev.af83.priv/) to connect to the Rails application.
diff --git a/README.md b/README.md
index c7dd6d333..83ede1b13 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,15 @@
# Chouette2 [![Build Status](https://travis-ci.org/afimb/chouette2.svg?branch=master)](https://travis-ci.org/afimb/chouette2) [![Dependency Status](https://gemnasium.com/afimb/chouette2.png)](https://gemnasium.com/afimb/chouette2) [![Code Climate](https://codeclimate.com/github/afimb/chouette2.png)](https://codeclimate.com/github/afimb/chouette2)
Chouette2 is an open source web project in Ruby/Rails to edit and view transport offer data. It is designed as an [SaaS](http://en.wikipedia.org/wiki/Software_as_a_service) platform and can :
-* Exchange transport data : [Neptune](http://www.normes-donnees-tc.org/format-dechange/donnees-theoriques/neptune/), [GTFS](https://developers.google.com/transit/gtfs/reference?hl=fr), [NeTEx](http://www.normes-donnees-tc.org/format-dechange/donnees-theoriques/netex/), CSV
+* Exchange transport data
+ * [Neptune](http://www.normes-donnees-tc.org/format-dechange/donnees-theoriques/neptune/),
+ * [GTFS](https://developers.google.com/transit/gtfs/reference?hl=fr),
+ * [NeTEx](http://www.normes-donnees-tc.org/format-dechange/donnees-theoriques/netex/)
* Edit transport data
* Be requested via a read-only [Restful API](https://en.wikipedia.org/wiki/Representational_state_transfer)
* [Import, Export and Validate transport data asynchronously](http://github.com/afimb/chouette)
* Use a [multi-tenancy database](http://en.wikipedia.org/wiki/Multitenancy)
-Chouette2 uses Rest Web Service API from [chouette](http://github.com/afimb/chouette) (another git project) to import, export and validate various transport data.
-
-Feel free to test and access to the free SaaS web site at [http://appli.chouette.mobi](http://appli.chouette.mobi/chouette2/users/sign_in). Two types of access are granted :
-* A demo organisation with an existing Public Transport dataset
- * login : demo@chouette.mobi
- * password : chouette
-* Create your own organisation : follow the link "Sign up" ("S'inscrire")
-
Release Notes
-------------
@@ -23,162 +18,28 @@ The release notes (in French) can be found in the [CHANGELOG](./CHANGELOG.md) fi
Requirements
------------
-* [Chouette IEV 3.X Web Service](https://github.com/afimb/chouette) (requires Postgresql and Java)
-* Ruby 1.9.3 or 2.1.6
-* Bundler 1.10.3
-* Proj 4.8.0
-
-External Deps
--------------
-
-Install Chouette IEV 3.X Web Service [see how to](https://github.com/afimb/chouette/readme.md)
-Next steps assumes that :
-* a Chouette IEV Web Service is running (on localhost, port 8080)
-* a Postgres database exists (chouette2 on localhost, port 5432) with a postgres user (chouette, with password chouette)
-
-On Debian/Ubuntu/Kubuntu OS : assumes that the depot contains the correct version
-```sh
-sudo apt-get install libpq-dev
-sudo apt-get install git
-sudo apt-get install unzip
-sudo apt-get install proj-bin
-sudo apt-get install libproj-dev
-sudo apt-get install make
-sudo apt-get install libmagic-dev
-```
-
-If Linux distribution doesn't publish an RVM package,
-install [RVM from sources](./doc/install/rvm.md)
-
-Install ruby 2.1.6
-```sh
-rvm install ruby-2.1.6
-rvm --default use 2.1.6
-```
-
-Install bundler 1.10.3
-```sh
-gem install bundler -v 1.10.3
-```
-
-Installation
-------------
-
-On Debian, chouette can also be installed as a package : see [debian packages](http://packages.chouette.cityway.fr/debian/chouette)
-
-Install web application
-
-Get git source code :
-```sh
-cd
-git clone -b V3_1 git://github.com/afimb/chouette2
-cd chouette2
-```
-Download gem librairies
-```sh
-bundle install
-```
-Update database schema
-```sh
-RAILS_ENV=production bundle exec rake db:migrate
-```
-Prepare static resources (assets)
-```sh
-RAILS_ENV=production bundle exec rake assets:clobber assets:precompile
-```
-
-Configuration
--------------
-
-Configure for Generating URLs in Action Mailer Views.
-* Edit [production.rb](./config/environments/production.rb) and change ```config.action_mailer.default_url_options```
-* see [Action Mailer Configuration documentation](http://guides.rubyonrails.org/action_mailer_basics.html)
-
-Configure assets access (Must be true if you use Webrick, or false if you use Apache or Nginx).
-* Edit [production.rb](./config/environments/production.rb) and change ```config.serve_static_files```
-
-Configure SMTP settings.
-* Edit [production.rb](./config/environments/production.rb) and change ```ActionMailer::Base.smtp_settings```
-* see [Action Mailer Configuration documentation](http://guides.rubyonrails.org/action_mailer_basics.html)
-
-Configure e-mail send address visible on the e-mail sent when a user registers, re-initialises its password, ...
-* Edit [production.rb](./config/environments/production.rb) and change ```config.mailer_sender```
-
-Configure Rails secret key.
-* Edit [secrets.yml](./config/secrets.yml) and uncomment and set```secret_key_base```
-* see [Rails documentation](http://guides.rubyonrails.org/4_1_release_notes.html#config-secrets-yml)
-
-Configure address of the Chouette IEV Web Service.
-* Edit [secrets.yml](./config/secrets.yml) and uncomment and set```api_endpoint```
-
-Configure Google Analytics Key.
-* Edit [secrets.yml](./config/secrets.yml) and change```google_analytic_tracker```
-* see [Google Analytics](https://www.google.fr/intl/fr/analytics/)
+* [Import, Export and Validation Operations](https://github.com/af83/stif-boiv-iev) are in another project in Java
-Configure IGN Géoportail Key.
-* Edit [secrets.yml](./config/secrets.yml) and uncomment and set```geoportail_api_key```
-* see [API Géoportail documentation](http://api.ign.fr/accueil)
-
-Configure the way that Chouette2 sends e-mail.
-* Edit [devise_async.rb](./config/initializer/devise_async.rb) and uncomment and set```Devise::Async.enabled``` ( true if you want to use asynchronously and false otherwise )
-* see [Devise Async specification](https://github.com/mhfs/devise-async)
-
-Configure OSRM Backend URL
-* Edit [secrets.yml](./config/secrets.yml) and change```osrm_endpoint```
-* see [Project-OSRM](https://github.com/Project-OSRM/osrm-backend/wiki/Api-usage-policy)
-
-Run
----
-
-Launch the task if you want to send mail asynchronously (See previous chapter to desactivate it)
-```sh
-RAILS_ENV=production bundle exec rake jobs:work
-```
-This task may be added in system start-up configuration
-
-Launch rails server with [WEBrick](http://guides.rubyonrails.org/command_line.html#server-with-different-backends) ( default RoR web server, note: webrick runs on default port 3000)
-```sh
-RAILS_ENV=production bundle exec rails server
-```
-
-This task may be added in system start-up configuration.
-Instead of using WEBrick, Rails application may be deployed on [Phusion Passenger](https://www.phusionpassenger.com/) with an [Apache](http://httpd.apache.org/) or [NGinx](http://nginx.com/) front-end, to make server faster and more robust.
-
-Apache like NGinx can serve static resources,
-so change parameter ```serve_static_files``` to false in [production.rb](./config/environments/production.rb)
-
-Test
-----
+Install
+-------
-```sh
-bundle exec rake db:create
-bundle exec rake db:migrate
-bundle exec rake spec
-```
+See [installation manual](./INSTALL.md)
More Information
----------------
-Complete docs (in French) can be found on the [project website](http://www.chouette.mobi/developpeurs).
Some technical articles are available [on the wiki](../../wiki) too.
API Documentation
-----------------
-The description (in French) of the read-only restful API is described in :
-* [User manual file](./doc/interfaces/Chouette_API_REST_v1.2.pdf)
-* [XSD file](./doc/interfaces/api_rest_v1.xsd)
+TODO
License
-------
This project is licensed under the CeCILL-B license, a copy of which can be found in the [LICENSE](./LICENSE.md) file.
-Project-OSRM Licence
--------------------------
-
-Project-OSRM is licensed under the [ODbL](http://opendatacommons.org/licenses/odbl/) licence.
-
Release Notes
-------------
@@ -188,8 +49,3 @@ Support
-------
Users looking for support should file an issue on the GitHub [issue tracking page](../../issues), or file a [pull request](../../pulls) if you have a fix available.
-
-Credits
--------
-
-Thanks to Ingolf for his [photo](https://www.flickr.com/photos/ingolfbln/7663851694) under CC BY-SA 2.0 license
diff --git a/app/assets/javascripts/main_menu.coffee b/app/assets/javascripts/main_menu.coffee
index a12c47576..1c39be736 100644
--- a/app/assets/javascripts/main_menu.coffee
+++ b/app/assets/javascripts/main_menu.coffee
@@ -24,6 +24,7 @@ $ ->
limit = 51
if $(window).scrollTop() >= limit
+ data = ""
if ($('.page-action .small').length > 0)
data = $('.page-action .small')[0].innerHTML
diff --git a/app/assets/stylesheets/components/_breadcrumb.sass b/app/assets/stylesheets/components/_breadcrumb.sass
index 62f167eb4..1b30ca42b 100644
--- a/app/assets/stylesheets/components/_breadcrumb.sass
+++ b/app/assets/stylesheets/components/_breadcrumb.sass
@@ -1,3 +1,6 @@
.breadcrumbs
+ white-space: nowrap
+ text-overflow: ellipsis
+ overflow: hidden
a
- color: white \ No newline at end of file
+ color: white
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/assets/stylesheets/components/_main_nav.sass b/app/assets/stylesheets/components/_main_nav.sass
index 9f7a8e244..f102c4617 100644
--- a/app/assets/stylesheets/components/_main_nav.sass
+++ b/app/assets/stylesheets/components/_main_nav.sass
@@ -243,6 +243,9 @@ $menuW: 300px
left: 0
top: 13px
+ & > .menu-item
+ max-width: 75%
+
.menu-item
padding: 0 10px
@@ -324,8 +327,11 @@ $menuW: 300px
height: $menuH * 2
transition: 0.1s
- #menu_top > .menu-content > .menu-item-group
- display: none
+ #menu_top > .menu-content
+ & > .menu-item
+ max-width: 90%
+ & > .menu-item-group
+ display: none
.sticky-content
height: $menuH
@@ -345,16 +351,16 @@ $menuW: 300px
white-space: nowrap
max-height: 1.1em
margin: 0 -1.4em 0 0
- padding: 0 1.4em 0 0
+ padding: 0 1.4em 5px 0
overflow: hidden
&:before
content: '[...]'
font-size: 0.65em
position: absolute
- z-index: 5
+ z-index: 6
right: 0
- bottom: 4px
+ bottom: 9px
&:after
content: ''
diff --git a/app/controllers/concerns/activatable.rb b/app/controllers/concerns/activatable.rb
new file mode 100644
index 000000000..1a34551a9
--- /dev/null
+++ b/app/controllers/concerns/activatable.rb
@@ -0,0 +1,11 @@
+module Activatable
+ extend ActiveSupport::Concern
+
+ %w(activate deactivate).each do |action|
+ define_method action do
+ authorize resource, "#{action}?"
+ resource.send "#{action}!"
+ redirect_to request.referer || [current_referential, resource]
+ end
+ end
+end
diff --git a/app/controllers/lines_controller.rb b/app/controllers/lines_controller.rb
index 571c73f4a..f446e1d37 100644
--- a/app/controllers/lines_controller.rb
+++ b/app/controllers/lines_controller.rb
@@ -1,6 +1,8 @@
class LinesController < ChouetteController
include ApplicationHelper
+ include Activatable
include PolicyChecker
+
defaults :resource_class => Chouette::Line
respond_to :html
respond_to :xml
diff --git a/app/controllers/purchase_windows_controller.rb b/app/controllers/purchase_windows_controller.rb
index a70535150..04b5736bb 100644
--- a/app/controllers/purchase_windows_controller.rb
+++ b/app/controllers/purchase_windows_controller.rb
@@ -6,11 +6,11 @@ class PurchaseWindowsController < ChouetteController
defaults :resource_class => Chouette::PurchaseWindow, collection_name: 'purchase_windows', instance_name: 'purchase_window'
belongs_to :referential
+ requires_feature :purchase_windows
+
def index
index! do
- scope = self.ransack_period_range(scope: @purchase_windows, error_message: t('compliance_check_sets.filters.error_period_filter'), query: :overlapping)
- @q = scope.ransack(params[:q])
- @purchase_windows = decorate_purchase_windows(@q.result.paginate(page: params[:page], per_page: 30))
+ @purchase_windows = decorate_purchase_windows(@purchase_windows)
end
end
@@ -45,14 +45,31 @@ class PurchaseWindowsController < ChouetteController
)
end
+ def sort_column
+ Chouette::PurchaseWindow.column_names.include?(params[:sort]) ? params[:sort] : 'name'
+ end
+
+ def sort_direction
+ %w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc'
+ end
+
+ def collection
+ return @purchase_windows if @purchase_windows
+ @q = Chouette::PurchaseWindow.ransack(params[:q])
+
+ purchase_windows = @q.result
+ purchase_windows = purchase_windows.order(sort_column + ' ' + sort_direction) if sort_column && sort_direction
+ @purchase_windows = purchase_windows.paginate(page: params[:page])
+ end
+
def ransack_contains_date
date =[]
- if params[:q] && !params[:q]['date_ranges(1i)'].empty?
- ['date_ranges(1i)', 'date_ranges(2i)', 'date_ranges(3i)'].each do |key|
+ if params[:q] && params[:q]['contains_date(1i)'].present?
+ ['contains_date(1i)', 'contains_date(2i)', 'contains_date(3i)'].each do |key|
date << params[:q][key].to_i
params[:q].delete(key)
end
- params[:q]['date_ranges'] = Date.new(*date) rescue nil
+ params[:q]['contains_date'] = @date = Date.new(*date) rescue nil
end
end
end
diff --git a/app/controllers/referential_companies_controller.rb b/app/controllers/referential_companies_controller.rb
index ca1ff67db..7e65a72cf 100644
--- a/app/controllers/referential_companies_controller.rb
+++ b/app/controllers/referential_companies_controller.rb
@@ -35,7 +35,8 @@ class ReferentialCompaniesController < ChouetteController
def collection
scope = referential.line_referential.companies
if params[:line_id]
- scope = referential.line_referential.lines.find(params[:line_id]).companies
+ line_scope = referential.line_referential.lines.find(params[:line_id]).companies
+ scope = line_scope if line_scope.exists?
end
@q = scope.search(params[:q])
diff --git a/app/controllers/stop_areas_controller.rb b/app/controllers/stop_areas_controller.rb
index 498493f1e..b478d38fa 100644
--- a/app/controllers/stop_areas_controller.rb
+++ b/app/controllers/stop_areas_controller.rb
@@ -1,6 +1,7 @@
class StopAreasController < ChouetteController
include ApplicationHelper
-
+ include Activatable
+
defaults :resource_class => Chouette::StopArea
belongs_to :stop_area_referential
diff --git a/app/decorators/line_decorator.rb b/app/decorators/line_decorator.rb
index ede670cbd..9c0cf7292 100644
--- a/app/decorators/line_decorator.rb
+++ b/app/decorators/line_decorator.rb
@@ -18,7 +18,8 @@ class LineDecorator < Draper::Decorator
links << Link.new(
content: h.t('lines.actions.show_company'),
- href: [context[:line_referential], object.company]
+ href: [context[:line_referential], object.company],
+ disabled: object.company.nil?
)
if h.policy(Chouette::Line).create? &&
@@ -41,6 +42,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_decorator.rb b/app/decorators/referential_decorator.rb
index 0863b7f4b..d75ad1050 100644
--- a/app/decorators/referential_decorator.rb
+++ b/app/decorators/referential_decorator.rb
@@ -12,6 +12,13 @@ class ReferentialDecorator < Draper::Decorator
)
end
+ if has_feature?(:purchase_windows)
+ links << Link.new(
+ content: h.t('purchase_windows.index.title'),
+ href: h.referential_purchase_windows_path(object)
+ )
+ end
+
links << Link.new(
content: h.t('time_tables.index.title'),
href: h.referential_time_tables_path(object)
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/decorators/stop_area_decorator.rb b/app/decorators/stop_area_decorator.rb
index cf3612f79..32f6e1d2b 100644
--- a/app/decorators/stop_area_decorator.rb
+++ b/app/decorators/stop_area_decorator.rb
@@ -3,12 +3,12 @@ class StopAreaDecorator < Draper::Decorator
delegate_all
- def action_links(stop_area = nil)
- links = []
+ def common_action_links(stop_area = nil)
+ top_links, bottom_links = [], []
stop_area ||= object
if h.policy(stop_area).update?
- links << Link.new(
+ top_links << Link.new(
content: h.t('stop_areas.actions.edit'),
href: h.edit_stop_area_referential_stop_area_path(
stop_area.stop_area_referential,
@@ -18,7 +18,7 @@ class StopAreaDecorator < Draper::Decorator
end
if h.policy(stop_area).destroy?
- links << Link.new(
+ bottom_links << Link.new(
content: h.destroy_link_content('stop_areas.actions.destroy'),
href: h.stop_area_referential_stop_area_path(
stop_area.stop_area_referential,
@@ -29,7 +29,35 @@ class StopAreaDecorator < Draper::Decorator
)
end
- links
+ [top_links, bottom_links]
+ end
+
+ def action_links(stop_area = nil)
+ stop_area ||= object
+ top_links, bottom_links = common_action_links(stop_area)
+ links = []
+
+ if h.policy(object).deactivate?
+ links << Link.new(
+ content: h.deactivate_link_content('stop_areas.actions.deactivate'),
+ href: h.deactivate_stop_area_referential_stop_area_path(stop_area.stop_area_referential, object),
+ method: :put,
+ data: {confirm: h.t('stop_areas.actions.deactivate_confirm')},
+ extra_class: "delete-action"
+ )
+ end
+
+ if h.policy(object).activate?
+ links << Link.new(
+ content: h.activate_link_content('stop_areas.actions.activate'),
+ href: h.activate_stop_area_referential_stop_area_path(stop_area.stop_area_referential, object),
+ method: :put,
+ data: {confirm: h.t('stop_areas.actions.activate_confirm')},
+ extra_class: "delete-action"
+ )
+ end
+
+ top_links + links + bottom_links
end
def waiting_time_text
diff --git a/app/decorators/stop_point_decorator.rb b/app/decorators/stop_point_decorator.rb
index 196d6d490..27e1a7058 100644
--- a/app/decorators/stop_point_decorator.rb
+++ b/app/decorators/stop_point_decorator.rb
@@ -4,6 +4,6 @@ class StopPointDecorator < StopAreaDecorator
delegate_all
def action_links
- super(object.stop_area)
+ common_action_links(object.stop_area).flatten
end
end
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..dede51920 100644
--- a/app/helpers/table_builder_helper.rb
+++ b/app/helpers/table_builder_helper.rb
@@ -368,6 +368,11 @@ module TableBuilderHelper
end
def gear_menu_link(link)
+ klass = []
+ klass << link.extra_class if link.extra_class
+ klass << 'delete-action' if link.method == :delete
+ klass << 'disabled' if link.disabled
+
content_tag(
:li,
link_to(
@@ -377,7 +382,7 @@ module TableBuilderHelper
) do
link.content
end,
- class: ('delete-action' if link.method == :delete)
+ class: (klass.join(' ') if klass.present?)
)
end
diff --git a/app/javascript/vehicle_journeys/components/Tools.js b/app/javascript/vehicle_journeys/components/Tools.js
index 7621dfc10..1ef576529 100644
--- a/app/javascript/vehicle_journeys/components/Tools.js
+++ b/app/javascript/vehicle_journeys/components/Tools.js
@@ -17,7 +17,7 @@ export default class Tools extends Component {
hasPolicy(key) {
// Check if the user has the policy to disable or not the action
- return this.props.filters.policy[`vehicle_journeys.${key}`]
+ return this.props.filters.policy[`vehicle_journeys.${key}`]
}
render() {
@@ -45,4 +45,4 @@ Tools.propTypes = {
vehicleJourneys : PropTypes.array.isRequired,
onCancelSelection: PropTypes.func.isRequired,
filters: PropTypes.object.isRequired
-} \ No newline at end of file
+}
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/models/chouette/purchase_window.rb b/app/models/chouette/purchase_window.rb
index 8786c7252..5368d790a 100644
--- a/app/models/chouette/purchase_window.rb
+++ b/app/models/chouette/purchase_window.rb
@@ -16,6 +16,10 @@ module Chouette
scope :contains_date, ->(date) { where('date ? <@ any (date_ranges)', date) }
+ def self.ransackable_scopes(auth_object = nil)
+ [:contains_date]
+ end
+
def local_id
"IBOO-#{self.referential.id}-#{self.id}"
end
diff --git a/app/models/chouette/stop_area.rb b/app/models/chouette/stop_area.rb
index 3a9b44d59..2f8d7c096 100644
--- a/app/models/chouette/stop_area.rb
+++ b/app/models/chouette/stop_area.rb
@@ -328,5 +328,20 @@ module Chouette
end
end
+ def activated?
+ deleted_at.nil?
+ end
+
+ def deactivated?
+ !activated?
+ end
+
+ def activate!
+ update_attribute :deleted_at, nil
+ end
+
+ def deactivate!
+ update_attribute :deleted_at, Time.now
+ 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/app/policies/stop_area_policy.rb b/app/policies/stop_area_policy.rb
index faeebbc2a..e5921ef61 100644
--- a/app/policies/stop_area_policy.rb
+++ b/app/policies/stop_area_policy.rb
@@ -16,4 +16,12 @@ class StopAreaPolicy < ApplicationPolicy
def update?
user.has_permission?('stop_areas.update')
end
+
+ def deactivate?
+ !record.deactivated? && user.has_permission?('stop_areas.change_status')
+ end
+
+ def activate?
+ record.deactivated? && user.has_permission?('stop_areas.change_status')
+ end
end
diff --git a/app/views/dashboards/_dashboard.html.slim b/app/views/dashboards/_dashboard.html.slim
index b468fed27..075b94ddc 100644
--- a/app/views/dashboards/_dashboard.html.slim
+++ b/app/views/dashboards/_dashboard.html.slim
@@ -34,34 +34,21 @@
em.small.text-muted
= t('dasboard.calendars.none')
- .panel.panel-default
- .panel-heading
- h3.panel-title.with_actions
- = t('dasboard.purchase_windows.title')
- div
- = link_to '', purchase_windows_path, class: ' fa fa-chevron-right pull-right'
- - if @dashboard.current_organisation.purchase_windows.present?
- .list-group
- - @dashboard.current_organisation.purchase_windows.order("updated_at desc").limit(5).each do |purchase_window|
- = link_to purchase_window.name, referential_purchase_window_path(purchase_window.referential, purchase_window), class: 'list-group-item'
- - else
- .panel-body
- em.small.text-muted
- = t('dasboard.purchase_windows.none')
-
.col-lg-6.col-md-6.col-sm-6.col-xs-12
.panel.panel-default
- .panel-heading
- h3.panel-title
- = t('dashboard.stop_area_referentials.title')
- .list-group
- - @dashboard.current_organisation.stop_area_referentials.each do |referential|
- = link_to referential.name, stop_area_referential_stop_areas_path(referential), class: 'list-group-item'
+ - @dashboard.current_organisation.stop_area_referentials.each do |referential|
+ .panel-heading
+ h3.panel-title
+ = referential.name
+ .list-group
+ = link_to Chouette::StopArea.model_name.human.pluralize.capitalize, stop_area_referential_stop_areas_path(referential), class: 'list-group-item'
.panel.panel-default
- .panel-heading
- h3.panel-title
- = t('dashboard.line_referentials.title')
- .list-group
- - @dashboard.current_organisation.line_referentials.all.each do |referential|
- = link_to referential.name, line_referential_lines_path(referential), class: 'list-group-item'
+ - @dashboard.current_organisation.line_referentials.all.each do |referential|
+ .panel-heading
+ h3.panel-title
+ = referential.name
+ .list-group
+ = link_to Chouette::Line.model_name.human.pluralize.capitalize, line_referential_lines_path(referential), class: 'list-group-item'
+ = link_to Chouette::Company.model_name.human.pluralize.capitalize, line_referential_companies_path(referential), class: 'list-group-item'
+ = link_to "Réseaux", line_referential_networks_path(referential), class: 'list-group-item'
diff --git a/app/views/lines/_form.html.slim b/app/views/lines/_form.html.slim
index de0308289..909d6512e 100644
--- a/app/views/lines/_form.html.slim
+++ b/app/views/lines/_form.html.slim
@@ -3,7 +3,7 @@
.col-lg-12
= f.input :name
= f.input :network_id, as: :select, :collection => @line_referential.networks, include_blank: false
- = f.input :company_id, as: :select, :collection => @line_referential.companies, include_blank: false
+ = f.input :company_id, as: :select, :collection => @line_referential.companies, include_blank: true
= f.input :secondary_company_ids, :collection => @line_referential.companies, include_blank: false, input_html: { multiple: true, 'data-select2ed': true }, label: t('activerecord.attributes.line.secondary_company')
= f.input :published_name
= f.input :registration_number
@@ -20,4 +20,3 @@
.separator
= f.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'lines_form'
-
diff --git a/app/views/lines/index.html.slim b/app/views/lines/index.html.slim
index 8b035b477..e94837ed5 100644
--- a/app/views/lines/index.html.slim
+++ b/app/views/lines/index.html.slim
@@ -41,7 +41,7 @@
), \
TableBuilderHelper::Column.new( \
key: 'companies.name', \
- attribute: Proc.new { |n| n.try(:company).try(:name) } \
+ attribute: Proc.new { |n| n&.company&.name || "-" } \
), \
TableBuilderHelper::Column.new( \
key: :transport_mode, \
diff --git a/app/views/lines/show.html.slim b/app/views/lines/show.html.slim
index d62fe30d6..83244f739 100644
--- a/app/views/lines/show.html.slim
+++ b/app/views/lines/show.html.slim
@@ -6,7 +6,7 @@
= link_to link.href,
method: link.method,
data: link.data,
- class: 'btn btn-primary' do
+ class: "btn btn-primary #{link.disabled ? "disabled" : ""}" do
= link.content
- page_header_content_for @line
diff --git a/app/views/purchase_windows/_filters.html.slim b/app/views/purchase_windows/_filters.html.slim
index 9c83d20db..4d7c8ce26 100644
--- a/app/views/purchase_windows/_filters.html.slim
+++ b/app/views/purchase_windows/_filters.html.slim
@@ -8,7 +8,7 @@
.form-group
= f.label Chouette::PurchaseWindow.human_attribute_name(:date), class: 'control-label'
- = f.input :date_ranges, as: :date, label: false, wrapper_html: { class: 'date smart_date' }, class: 'form-control', include_blank: true
+ = f.input :contains_date, as: :date, label: false, wrapper_html: { class: 'date smart_date' }, class: 'form-control', default: @date, include_blank: @date ? false : true
.actions
= link_to t('actions.erase'), referential_purchase_windows_path, class: 'btn btn-link'
diff --git a/app/views/purchase_windows/_form.html.slim b/app/views/purchase_windows/_form.html.slim
index 8f3ba769d..8821ecc8a 100644
--- a/app/views/purchase_windows/_form.html.slim
+++ b/app/views/purchase_windows/_form.html.slim
@@ -2,7 +2,15 @@
.row
.col-lg-12
= f.input :name
- = f.input :color, as: :select, boolean_style: :inline, collection: Chouette::PurchaseWindow.color.values, input_html: {class: 'color_selector'}
+ // = f.input :color, as: :select, boolean_style: :inline, collection: Chouette::PurchaseWindow.color.values, input_html: {class: 'color_selector '}
+ div
+ .form-group
+ label.select.optional.col-sm-4.col-xs-5.control-label
+ = @purchase_window.class.human_attribute_name :color
+ div.col-sm-8.col-xs-7
+ span.fa.fa-circle style="color:#7F551B"
+
+ = f.input :color, as: :hidden, input_html: { value: '#7F551B' }
.separator
diff --git a/app/views/purchase_windows/index.html.slim b/app/views/purchase_windows/index.html.slim
index 38954b5dc..04f9fb0a8 100644
--- a/app/views/purchase_windows/index.html.slim
+++ b/app/views/purchase_windows/index.html.slim
@@ -28,7 +28,8 @@
), \
TableBuilderHelper::Column.new( \
key: :bounding_dates, \
- attribute: Proc.new {|w| w.bounding_dates.nil? ? '-' : t('validity_range', debut: l(w.bounding_dates.begin, format: :short), end: l(w.bounding_dates.end, format: :short))} \
+ attribute: Proc.new {|w| w.bounding_dates.nil? ? '-' : t('validity_range', debut: l(w.bounding_dates.begin, format: :short), end: l(w.bounding_dates.end, format: :short))}, \
+ sortable: false \
) \
],
links: [:show],
diff --git a/app/views/referentials/show.html.slim b/app/views/referentials/show.html.slim
index 9852fb0a3..96755359c 100644
--- a/app/views/referentials/show.html.slim
+++ b/app/views/referentials/show.html.slim
@@ -68,7 +68,7 @@
), \
TableBuilderHelper::Column.new( \
key: 'companies.name', \
- attribute: Proc.new { |n| n.try(:company).try(:name) } \
+ attribute: Proc.new { |n| n&.company&.name || "-" } \
) \
],
links: [:show],
diff --git a/app/views/vehicle_journeys/index.html.slim b/app/views/vehicle_journeys/index.html.slim
index 52c1a9728..4ad9d524d 100644
--- a/app/views/vehicle_journeys/index.html.slim
+++ b/app/views/vehicle_journeys/index.html.slim
@@ -1,5 +1,11 @@
- breadcrumb :vehicle_journeys, @referential, @route
- content_for :page_header_title, t('vehicle_journeys.index.title', route: @route.name)
+- if @route.opposite_route.present?
+ - content_for :page_header_content do
+ .row.mb-sm
+ .col-lg-12.text-right
+ = link_to(t('routes.actions.opposite_route_timetable'), [@referential, @route.line, @route.opposite_route, :vehicle_journeys], class: 'btn btn-primary')
+
.page_content
.container-fluid
diff --git a/config/deploy.rb b/config/deploy.rb
index 33771507f..d541f2581 100644
--- a/config/deploy.rb
+++ b/config/deploy.rb
@@ -9,8 +9,8 @@ set :deploy_to, "/var/www/stif-boiv"
set :use_sudo, false
default_run_options[:pty] = true
set :group_writable, true
-set :bundle_cmd, "/var/lib/gems/2.2.0/bin/bundle"
-set :rake, "#{bundle_cmd} exec /var/lib/gems/2.2.0/bin/rake"
+set :bundle_cmd, "/var/lib/gems/2.3.0/bin/bundle"
+set :rake, "#{bundle_cmd} exec rake"
set :keep_releases, -> { fetch(:kept_releases, 5) }
after "deploy:restart", "deploy:cleanup"
@@ -29,7 +29,7 @@ require 'whenever/capistrano'
#after 'deploy:finalize_update', 'npm:install'
# Whenever
-set :whenever_variables, ->{ "'environment=#{fetch :whenever_environment}&bundle_command=bin/bundle exec&additionnal_path=/var/lib/gems/2.2.0/bin'" } # invoke bin/bundle to use 'correct' ruby environment
+set :whenever_variables, ->{ "'environment=#{fetch :whenever_environment}&bundle_command=bin/bundle exec&additionnal_path=/var/lib/gems/2.3.0/bin'" } # invoke bin/bundle to use 'correct' ruby environment
set :whenever_command, "sudo /usr/local/sbin/whenever-sudo" # use sudo to change www-data crontab
set :whenever_user, "www-data" # use www-data crontab
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/calendars.fr.yml b/config/locales/calendars.fr.yml
index bd3051730..88cb275ff 100644
--- a/config/locales/calendars.fr.yml
+++ b/config/locales/calendars.fr.yml
@@ -31,7 +31,7 @@ fr:
destroy_confirm: Etes vous sûr de supprimer cet calendrier ?
errors:
overlapped_periods: Une autre période chevauche cette période
- short_period: Une période doit être d'un duréé de deux jours minimum
+ short_period: "Une période doit être d'une durée de deux jours minimum"
index:
title: Calendriers
all: Tous
diff --git a/config/locales/lines.en.yml b/config/locales/lines.en.yml
index 78d5c36be..49a629557 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"
@@ -66,6 +70,7 @@ en:
networks:
name: "Network"
company_id: "Company"
+ company: "Company"
secondary_company: "Secondary company"
companies:
name: "Company"
diff --git a/config/locales/lines.fr.yml b/config/locales/lines.fr.yml
index 36254d754..8fd409f1e 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"
@@ -67,6 +71,7 @@ fr:
networks:
name: "Réseau"
company_id: "Transporteur principal"
+ company: "Transporteur principal"
secondary_company: "Transporteurs secondaires"
companies:
name: "Transporteur principal"
diff --git a/config/locales/purchase_windows.en.yml b/config/locales/purchase_windows.en.yml
index 59d00673a..c0f402bf4 100644
--- a/config/locales/purchase_windows.en.yml
+++ b/config/locales/purchase_windows.en.yml
@@ -66,7 +66,7 @@ en:
name: Name
date_ranges: Date ranges
referential: Referential
- color: Color
+ color: Associated Color
bounding_dates: Bounding Dates
errors:
models:
diff --git a/config/locales/purchase_windows.fr.yml b/config/locales/purchase_windows.fr.yml
index 01476cd92..589546c32 100644
--- a/config/locales/purchase_windows.fr.yml
+++ b/config/locales/purchase_windows.fr.yml
@@ -29,7 +29,7 @@ fr:
destroy_confirm: Etes vous sûr de supprimer cet calendrier commercial ?
errors:
overlapped_periods: Une autre période chevauche cette période
- short_period: Une période doit être d'un duréé de deux jours minimum
+ short_period: "Une période doit être d'une durée de deux jours minimum"
index:
title: Calendriers commerciaux
all: Tous
@@ -67,7 +67,7 @@ fr:
short_name: Nom court
date_ranges: Intervalles de dates
referential: Jeu de données
- color: Couleur
+ color: Couleur associée
bounding_dates: Période englobante
errors:
models:
diff --git a/config/locales/routes.en.yml b/config/locales/routes.en.yml
index d82ba98dd..7b82e788b 100644
--- a/config/locales/routes.en.yml
+++ b/config/locales/routes.en.yml
@@ -13,6 +13,7 @@ en:
export_hub_all: "Export HUB routes"
add_stop_point: "Add stop point"
new_stop_point: "Create new stop"
+ opposite_route_timetable: "Timetable back"
new:
title: "Add a new route"
edit:
diff --git a/config/locales/routes.fr.yml b/config/locales/routes.fr.yml
index 457345ae8..1d151e60b 100644
--- a/config/locales/routes.fr.yml
+++ b/config/locales/routes.fr.yml
@@ -13,6 +13,7 @@ fr:
export_hub_all: "Export HUB des itinéraires"
add_stop_point: "Ajouter un arrêt"
new_stop_point: "Créer un arrêt pour l'ajouter"
+ opposite_route_timetable: "Horaires retour"
new:
title: "Ajouter un itinéraire"
edit:
diff --git a/config/locales/stop_areas.en.yml b/config/locales/stop_areas.en.yml
index 3ef3835e2..4d84d1191 100644
--- a/config/locales/stop_areas.en.yml
+++ b/config/locales/stop_areas.en.yml
@@ -17,6 +17,10 @@ en:
new: "Add a new stop"
edit: "Edit this stop"
destroy: "Remove"
+ activate: "Activate this stop"
+ deactivate: "Deactivate this stop"
+ activate_confirm: "Are you sure you want to activate this stop ?"
+ deactivate_confirm: "Are you sure you want tode activate this stop ?"
deleted_at: "Activated"
destroy_confirm: "Are you sure you want destroy this stop and all of his children ?"
select_parent: "Create or modify the relation child -> parent"
diff --git a/config/locales/stop_areas.fr.yml b/config/locales/stop_areas.fr.yml
index 69e3ba71e..eda1e4e3d 100644
--- a/config/locales/stop_areas.fr.yml
+++ b/config/locales/stop_areas.fr.yml
@@ -17,6 +17,10 @@ fr:
new: "Ajouter un arrêt"
edit: "Editer cet arrêt"
destroy: "Supprimer"
+ activate: "Activer cet arrêt"
+ deactivate: "Désactiver cet arrêt"
+ activate_confirm: "Etes vous sûr d'activer cet arrêt ?"
+ deactivate_confirm: "Etes vous sûr de désactiver cet arrêt ?"
deleted_at: "Activé"
destroy_confirm: "Etes vous sûr de supprimer cet arrêt ainsi que tous ses fils?"
select_parent: "Créer ou éditer la relation enfant -> parent"
diff --git a/config/routes.rb b/config/routes.rb
index d097d2d71..e05f5d365 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -86,14 +86,19 @@ ChouetteIhm::Application.routes.draw do
resources :compliance_control_blocks, :except => [:show, :index]
end
+ deactivable = Proc.new do
+ put :deactivate, on: :member
+ put :activate, on: :member
+ end
+
resources :stop_area_referentials, :only => [:show] do
post :sync, on: :member
- resources :stop_areas
+ resources :stop_areas, &deactivable
end
resources :line_referentials, :only => [:show, :edit, :update] do
post :sync, on: :member
- resources :lines
+ resources :lines, &deactivable
resources :group_of_lines
resources :companies
resources :networks
diff --git a/lib/link.rb b/lib/link.rb
index 7683a808f..33995c2f7 100644
--- a/lib/link.rb
+++ b/lib/link.rb
@@ -1,10 +1,12 @@
class Link
- attr_reader :content, :href, :method, :data
+ attr_reader :content, :href, :method, :data, :extra_class, :disabled
- def initialize(content: nil, href:, method: nil, data: nil)
+ def initialize(content: nil, href:, method: nil, data: nil, extra_class: nil, disabled: false)
@content = content
@href = href
@method = method
@data = data
+ @extra_class = extra_class
+ @disabled = disabled
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/controllers/stop_areas_controller_spec.rb b/spec/controllers/stop_areas_controller_spec.rb
new file mode 100644
index 000000000..2b5f8c3e2
--- /dev/null
+++ b/spec/controllers/stop_areas_controller_spec.rb
@@ -0,0 +1,38 @@
+RSpec.describe StopAreasController, :type => :controller do
+ login_user
+
+ let(:stop_area_referential) { create :stop_area_referential }
+ let(:stop_area) { create :stop_area, stop_area_referential: stop_area_referential }
+
+ describe 'PUT deactivate' do
+ let(:request){ put :deactivate, id: stop_area.id, stop_area_referential_id: stop_area_referential.id }
+
+ it 'should redirect to 403' do
+ expect(request).to redirect_to "/403"
+ end
+
+ with_permission "stop_areas.change_status" do
+ it 'returns HTTP success' do
+ expect(request).to redirect_to [stop_area_referential, stop_area]
+ expect(stop_area.reload).to be_deactivated
+ end
+ end
+ end
+
+ describe 'PUT activate' do
+ let(:request){ put :activate, id: stop_area.id, stop_area_referential_id: stop_area_referential.id }
+ before(:each){
+ stop_area.deactivate!
+ }
+ it 'should redirect to 403' do
+ expect(request).to redirect_to "/403"
+ end
+
+ with_permission "stop_areas.change_status" do
+ it 'returns HTTP success' do
+ expect(request).to redirect_to [stop_area_referential, stop_area]
+ expect(stop_area.reload).to be_activated
+ end
+ end
+ end
+end
diff --git a/spec/factories/chouette_routes.rb b/spec/factories/chouette_routes.rb
index 4e20059fe..7443d08bc 100644
--- a/spec/factories/chouette_routes.rb
+++ b/spec/factories/chouette_routes.rb
@@ -31,6 +31,13 @@ FactoryGirl.define do
end
end
+
+ trait :with_opposite do
+ after(:create) do |route|
+ opposite = create :route
+ route.opposite_route = opposite
+ end
+ end
end
factory :route_with_after_commit do
diff --git a/spec/factories/chouette_stop_areas.rb b/spec/factories/chouette_stop_areas.rb
index 7f937e361..94517f856 100644
--- a/spec/factories/chouette_stop_areas.rb
+++ b/spec/factories/chouette_stop_areas.rb
@@ -8,5 +8,9 @@ FactoryGirl.define do
longitude {10.0 * rand}
association :stop_area_referential
+
+ trait :deactivated do
+ deleted_at { 1.hour.ago }
+ end
end
end
diff --git a/spec/features/purchase_windows_permission_spec.rb b/spec/features/purchase_windows_permission_spec.rb
index e74fb5c17..9f155a1e8 100644
--- a/spec/features/purchase_windows_permission_spec.rb
+++ b/spec/features/purchase_windows_permission_spec.rb
@@ -4,6 +4,10 @@ require 'spec_helper'
describe "PurchaseWindows", :type => :feature do
login_user
+ before do
+ @user.organisation.update features: %w{purchase_windows}
+ end
+
let(:purchase_window) { create :purchase_window, referential: first_referential}
describe 'permissions' do
diff --git a/spec/support/integration_spec_helper.rb b/spec/support/integration_spec_helper.rb
index 78efb9027..36306559d 100644
--- a/spec/support/integration_spec_helper.rb
+++ b/spec/support/integration_spec_helper.rb
@@ -1,15 +1,20 @@
module IntegrationSpecHelper
- def paginate_collection klass, decorator, page=1
- ModelDecorator.decorate( klass.page(page), with: decorator )
+ def paginate_collection klass, decorator, page=1, context={}
+ collection = klass.page(page)
+ if decorator
+ collection = ModelDecorator.decorate(collection, with: decorator, context: context)
+ end
+ 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
@@ -30,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
diff --git a/spec/views/stop_areas/index.html.slim_spec.rb b/spec/views/stop_areas/index.html.slim_spec.rb
index 8daa5eb4b..520cecc1a 100644
--- a/spec/views/stop_areas/index.html.slim_spec.rb
+++ b/spec/views/stop_areas/index.html.slim_spec.rb
@@ -1,14 +1,15 @@
require 'spec_helper'
describe "/stop_areas/index", :type => :view do
-
- let!(:stop_area_referential) { assign :stop_area_referential, create(:stop_area_referential) }
- let!(:stop_areas) do
+ let(:deactivated_stop_area){ nil }
+ let(:stop_area_referential) { assign :stop_area_referential, create(:stop_area_referential) }
+ let(:stop_areas) do
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) }
before :each do
+ deactivated_stop_area
allow(view).to receive(:link_with_search).and_return("#")
allow(view).to receive(:collection).and_return(stop_areas)
allow(view).to receive(:current_referential).and_return(stop_area_referential)
@@ -16,19 +17,60 @@ describe "/stop_areas/index", :type => :view do
render
end
- it { should have_link_for_each_item(stop_areas, "show", -> (stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) }
+ common_items = ->{
+ it { should have_link_for_each_item(stop_areas, "show", -> (stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) }
+ }
+
+ common_items.call()
it { should have_the_right_number_of_links(stop_areas, 1) }
with_permission "stop_areas.create" do
- it { should have_link_for_each_item(stop_areas, "show", -> (stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) }
+ common_items.call()
it { should_not have_link_for_each_item(stop_areas, "create", -> (stop_area){ view.new_stop_area_referential_stop_area_path(stop_area_referential) }) }
it { should have_the_right_number_of_links(stop_areas, 1) }
end
with_permission "stop_areas.update" do
- it { should have_link_for_each_item(stop_areas, "show", -> (stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) }
+ common_items.call()
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
+ with_permission "stop_areas.change_status" do
+ common_items.call()
+ it { should have_link_for_each_item(stop_areas, "deactivate", -> (stop_area){ view.deactivate_stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) }
+ it { should have_the_right_number_of_links(stop_areas, 2) }
+ end
+
+ with_permission "stop_areas.destroy" do
+ common_items.call()
+ it {
+ should have_link_for_each_item(stop_areas, "destroy", {
+ href: ->(stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area)},
+ method: :delete
+ })
+ }
+ it { should have_the_right_number_of_links(stop_areas, 2) }
+ end
+
+ context "with a deactivated item" do
+ with_permission "stop_areas.change_status" do
+ let(:deactivated_stop_area){ create :stop_area, :deactivated, stop_area_referential: stop_area_referential }
+
+ common_items.call()
+ it "should display an activate link for the deactivated one" do
+ stop_areas.each do |stop_area|
+ if stop_area == deactivated_stop_area
+ href = view.activate_stop_area_referential_stop_area_path(stop_area_referential, stop_area)
+ else
+ href = view.deactivate_stop_area_referential_stop_area_path(stop_area_referential, stop_area)
+ end
+ selector = "tr.#{TableBuilderHelper.item_row_class_name(stop_areas)}-#{stop_area.id} .actions a[href='#{href}']"
+ expect(rendered).to have_selector(selector, count: 1)
+ end
+ end
+ it { should have_the_right_number_of_links(stop_areas, 2) }
+ end
+ end
+
end
diff --git a/spec/views/vehicle_journeys/index.html.slim_spec.rb b/spec/views/vehicle_journeys/index.html.slim_spec.rb
new file mode 100644
index 000000000..7f0a9c5aa
--- /dev/null
+++ b/spec/views/vehicle_journeys/index.html.slim_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe "/vehicle_journeys/index", :type => :view do
+
+ let!(:referential) { assign :referential, create(:referential) }
+ let!(:line) { assign :line, create(:line) }
+ let!(:route) { assign :route, create(:route, line: line) }
+ let!(:vehicle_journeys) do
+ assign :vehicle_journeys, build_paginated_collection(:vehicle_journey, nil, route: route)
+ end
+
+ before :each do
+ allow(view).to receive(:link_with_search).and_return("#")
+ allow(view).to receive(:collection).and_return(vehicle_journeys)
+ allow(view).to receive(:current_referential).and_return(referential)
+ controller.request.path_parameters[:referential_id] = referential.id
+ render
+ end
+
+ context "with an opposite_route" do
+ let!(:route) { assign :route, create(:route, :with_opposite, line: line) }
+
+ it "should have an 'oppposite route timetable' button" do
+ href = view.referential_line_route_vehicle_journeys_path(referential, line, route.opposite_route)
+ oppposite_button_selector = "a[href=\"#{href}\"]"
+
+ expect(view.content_for(:page_header_content)).to have_selector oppposite_button_selector
+ end
+ end
+end