voluntary 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YmQ1ZjZjNDk5MjhjMGExMzNlYmI3NDM0ZGZjOWFkYzJkYWI4YzlkMA==
5
- data.tar.gz: !binary |-
6
- ZjNkMDA4MzU1N2RhZDBhNzMyMjc1ODVhN2M5MjFhZDk3NjY1NGNkNQ==
2
+ SHA1:
3
+ metadata.gz: a771ddeec412e7d388b055acff871018533619c5
4
+ data.tar.gz: c76dc81a5782f89e7309a4391297aa1bced80d89
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- OWJiY2Y1ZGNkODFiMTIxMGJlMjMwY2E3OWNiOGNlOTI0OTI2NTIxODdjNGIw
10
- ZDg4OTM3YWM0N2ZhZWZlYjQ4YTg5MjVmMDlkYzVlZjE0NWZhNGM0N2QwMDI1
11
- ZmNlNzM0NTc2NTdkMWZjZTk4YjZkNWMyNmVmMTA4ZjY4M2U3NjE=
12
- data.tar.gz: !binary |-
13
- ZWJkYzg0ZmRjYTlmYjFmMWNmZDgxZmRkMzcwOTg2ODEwZmVkM2Q3ZDhjZmQ1
14
- ZjE1YzE0ODUzZjVlNDYyZWMyOTQ0Mzk3Y2EwNmVlZjA4NWMyOWJlMDFiOWFl
15
- ZDlhNDY3NTBhMWZlOWI4OTI5NTUyMDdmZDUxNWE5NmJhYWExZDY=
6
+ metadata.gz: 98f5ff05154ed1c5c22dad03918f3648f3935b2e46fbeb8eb877d86afe74196858cf4352460033c6499b42a49d988efb4538ed703b344c1bc4195dab1992b6ff
7
+ data.tar.gz: 996f49f84e99d8b219029c9fbeebd57733eceb89475a640964e98375dc27eb514a383bfcae6ed8b3209372b0d2b5cb8d07ffcd3ff51c23f08d87884a41a64795
@@ -1,5 +1,12 @@
1
1
  ## unreleased ##
2
2
 
3
+ ## 0.3.0 (April 8, 2015) ##
4
+
5
+ * #40 Rails 4.2.1 upgrade.
6
+ * #46 Continuous integration server Travis setup.
7
+ * #77 Workflow product and (user) product area page: consider areas with projects assigned to sub areas deeper than the direct child areas.
8
+ * Removes rails-api gem (temporarily?).
9
+
3
10
  ## 0.2.4 (March 23, 2015) ##
4
11
 
5
12
  * #73 Sticky Footer for Application Layout (Twitter Bootstrap).
@@ -1,35 +1,43 @@
1
- = Voluntary
1
+ # Voluntary [![Build Status](https://travis-ci.org/volontariat/voluntary.svg?branch=master)](https://travis-ci.org/volontariat/voluntary) [![Code Climate](https://codeclimate.com/github/volontariat/voluntary/badges/gpa.svg)](https://codeclimate.com/github/volontariat/voluntary) [![Test Coverage](https://codeclimate.com/github/volontariat/voluntary/badges/coverage.svg)](https://codeclimate.com/github/volontariat/voluntary)
2
2
 
3
3
  This is a gem which turns your rails application into a crowdsourcing platform to run on your intranet or on the internet.
4
4
 
5
5
  Then you can add existing voluntary products like text creation or create your own products.
6
6
 
7
- == Installation
7
+ ## Installation
8
8
 
9
- === New Application
9
+ ### New Application
10
10
 
11
11
  Run this in your console:
12
12
 
13
+ ```bash
13
14
  rvm --create use 1.9.3@your_crowdsourcing_platform_name
14
15
  gem update bundler
15
16
  gem install rails -v 4.0.13 --no-rdoc --no-ri
16
17
  rails new your_crowdsourcing_platform_name
17
18
  cd your_crowdsourcing_platform_name
19
+ ```
18
20
 
19
21
  Add this to your Gemfile:
20
22
 
23
+ ```ruby
21
24
  gem 'voluntary'
25
+ ```
22
26
 
23
27
  Add voluntary products to your Gemfile.
24
28
 
25
29
  Run this in your console:
26
30
 
31
+ ```bash
27
32
  bundle install
33
+ ```
28
34
 
29
35
  Run this in your console (confirm all overwrite questions):
30
36
 
37
+ ```bash
31
38
  rails g voluntary:install
32
39
  rake railties:install:migrations
40
+ ```
33
41
 
34
42
  Remove gem 'sqlite3' from your Gemfile.
35
43
 
@@ -37,9 +45,11 @@ Copy the content of config/database.example.yml into config/database.yml
37
45
 
38
46
  Add this to your application.rb:
39
47
 
48
+ ```ruby
40
49
  config.generators do |g|
41
50
  g.orm :active_record
42
51
  end
52
+ ```
43
53
 
44
54
  Remove public/index.html
45
55
 
@@ -49,14 +59,17 @@ Add a Capfile to your Rails root.
49
59
 
50
60
  Run this in your console:
51
61
 
62
+ ```bash
52
63
  bundle install
53
64
  rake db:create
54
65
  rake db:migrate
55
66
  rake db:seed
56
67
  rails s
68
+ ```
57
69
 
58
- === New Product
59
-
70
+ ### New Product
71
+
72
+ ```bash
60
73
  git clone https://github.com/user/voluntary_product_name.git
61
74
  cd voluntary_product_name
62
75
  rvm --create use --rvmrc 1.9.3@voluntary_product_name # if you use RVM
@@ -85,7 +98,8 @@ Run this in your console:
85
98
  bundle exec rake db:migrate && bundle exec rake db:test:clone_structure
86
99
  # create a class for your new product under app/models/product/product_name.rb like: https://github.com/volontariat/voluntary_scholarship/blob/master/app/models/product/scholarship.rb
87
100
  bundle exec rails s
101
+ ```
88
102
 
89
- = License
103
+ ## License
90
104
 
91
105
  This project uses MIT-LICENSE.
@@ -16,7 +16,7 @@ class CandidaturesController < ApplicationController
16
16
  @candidatures = if @vacancy
17
17
  @vacancy.candidatures.includes(:vacancy, :resource)
18
18
  else
19
- Candidature.includes(:vacancy, :resource).where(resource_type: 'User').all
19
+ Candidature.includes(:vacancy, :resource).where(resource_type: 'User')
20
20
  end
21
21
  end
22
22
 
@@ -5,13 +5,6 @@ module Voluntary
5
5
  #include ActionController::Rendering # enables rendering
6
6
  #include ActionController::MimeResponds # enables serving different content types like :xml or :json
7
7
  #include AbstractController::Callbacks # callbacks for your authentication logic
8
-
9
- after_filter :set_access_control_headers
10
-
11
- def set_access_control_headers
12
- headers['Access-Control-Allow-Origin'] = '*'
13
- headers['Access-Control-Request-Method'] = '*'
14
- end
15
8
  end
16
9
  end
17
10
  end
@@ -79,5 +79,22 @@ module Voluntary
79
79
  def name_with_apostrophe(value)
80
80
  value =~ /s$/i ? "#{value}'" : "#{value}'s"
81
81
  end
82
+
83
+ def event_links_for_resource(current_resource, type)
84
+ return [] unless current_resource.respond_to? :state_events
85
+
86
+ links = []
87
+
88
+ current_resource.state_events.select{|event| can? event, current_resource }.each do |event|
89
+ path = "#{event}_#{type.singularize}_path"
90
+
91
+ next unless respond_to? path
92
+
93
+ path = eval("#{path}(current_resource)")
94
+ links << link_to(t("#{type}.show.events.#{event}"), path, method: :put)
95
+ end
96
+
97
+ links
98
+ end
82
99
  end
83
100
  end
@@ -6,6 +6,17 @@ class Area < ActiveRecord::Base
6
6
  has_and_belongs_to_many :users
7
7
  has_and_belongs_to_many :projects
8
8
 
9
+ scope :with_projects_for_product, ->(product_id) do
10
+ select('DISTINCT(areas.id), areas.*').joins(%Q{
11
+ LEFT JOIN areas areas2 ON areas2.id = areas.id OR areas2.ancestry like CONCAT(areas.id, '/', '%')
12
+ OR areas2.ancestry like CONCAT('%', '/', areas.id)
13
+ OR areas2.ancestry like CONCAT('%', '/', areas.id, '/', '%')
14
+ OR areas2.ancestry = CONCAT(areas.id, '')
15
+ LEFT JOIN areas_projects ON areas_projects.area_id = areas2.id
16
+ LEFT JOIN projects ON projects.id = areas_projects.project_id
17
+ }).where('areas2.id IS NOT NULL AND projects.product_id = ?', product_id)
18
+ end
19
+
9
20
  validates :name, presence: true, uniqueness: true
10
21
 
11
22
  attr_accessible :name, :parent_id
@@ -15,11 +26,13 @@ class Area < ActiveRecord::Base
15
26
  friendly_id :name, :use => :slugged
16
27
 
17
28
  def self.find_by_product_id(product_id)
18
- roots.joins(:projects).merge(Project.for_product_id(product_id))
29
+ #roots.joins(:projects).merge(Project.for_product_id(product_id))
30
+ roots.with_projects_for_product(product_id)
19
31
  end
20
32
 
21
33
  def children_for_product_id(product_id)
22
- children.joins(:projects).merge(Project.for_product_id(product_id))
34
+ #children.joins(:projects).merge(Project.for_product_id(product_id))
35
+ children.with_projects_for_product(product_id)
23
36
  end
24
37
 
25
38
  def products
@@ -10,7 +10,10 @@ module Likeable
10
10
  has_many :dislikers, class_name: 'User', through: :dislikes, source: :user
11
11
 
12
12
  scope :liked_by, ->(user_id) do
13
- positive_likes_string = if ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
13
+ positive_likes_string = if (
14
+ defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) &&
15
+ ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
16
+ )
14
17
  "likes.positive = 't'"
15
18
  else
16
19
  'likes.positive = 1'
@@ -99,6 +99,6 @@ class Product
99
99
  end
100
100
 
101
101
  def set_klass_name
102
- update_attribute(:_type, get_klass_name)
102
+ self._type = get_klass_name
103
103
  end
104
104
  end
@@ -8,7 +8,7 @@ module Product::ProjectManagement
8
8
  module ClassMethods
9
9
  def stories(id, user)
10
10
  collection = if id == 'no-name'
11
- Story.exists(_type: false)
11
+ Story.where(_type: 'Story')
12
12
  else
13
13
  product = Product.find(id)
14
14
 
@@ -2,7 +2,7 @@ class Role < ActiveRecord::Base
2
2
  has_many :users, through: :user_roles
3
3
  has_many :projects, through: :project_users
4
4
 
5
- scope :public, -> { where(public: true) }
5
+ scope :is_public, -> { where(public: true) }
6
6
 
7
7
  attr_accessible :name, :public
8
8
  end
@@ -8,6 +8,8 @@ module StateMachines::Candidature
8
8
  const_set 'STATES', [:new, :accepted, :denied]
9
9
  const_set 'EVENTS', [:accept, :deny, :quit]
10
10
 
11
+ after_initialize :set_initial_state
12
+
11
13
  state_machine :state, initial: :new do
12
14
  event :accept do
13
15
  transition [:new, :denied] => :accepted
@@ -50,6 +52,10 @@ module StateMachines::Candidature
50
52
  errors[:state] << I18n.t('activerecord.errors.models.vacancy.attributes.limit.reached')
51
53
  end
52
54
  end
55
+
56
+ def set_initial_state
57
+ self.state ||= :new
58
+ end
53
59
  end
54
60
  end
55
61
 
@@ -8,8 +8,16 @@ module StateMachines::Page
8
8
  const_set 'STATES', [:active]
9
9
  const_set 'EVENTS', []
10
10
 
11
+ after_initialize :set_initial_state
12
+
11
13
  state_machine :state, initial: :active do
12
14
  end
15
+
16
+ private
17
+
18
+ def set_initial_state
19
+ self.state ||= :active
20
+ end
13
21
  end
14
22
  end
15
23
 
@@ -10,6 +10,8 @@ module StateMachines::Story
10
10
  const_set 'STATES', [:new, :tasks_defined, :active, :completed, :closed]
11
11
  const_set 'EVENTS', [:initialization, :setup_tasks, :activate, :complete]
12
12
 
13
+ after_initialize :set_initial_state
14
+
13
15
  state_machine :state, initial: :new do
14
16
  event :initialization do
15
17
  transition :new => :initialized
@@ -44,6 +46,10 @@ module StateMachines::Story
44
46
 
45
47
  private
46
48
 
49
+ def set_initial_state
50
+ self.state ||= :new
51
+ end
52
+
47
53
  def presence_of_tasks
48
54
  self.tasks.delete_if{|t| t.name.blank? && t.text.blank? }
49
55
 
@@ -10,6 +10,8 @@ module StateMachines::Task
10
10
  const_set 'STATES', [:new, :assigned, :under_supervision, :completed]
11
11
  const_set 'EVENTS', [:assign, :cancel, :review, :follow_up, :complete]
12
12
 
13
+ after_initialize :set_initial_state
14
+
13
15
  state_machine :state, initial: :new do
14
16
  event :assign do
15
17
  transition :new => :assigned
@@ -74,6 +76,12 @@ module StateMachines::Task
74
76
  end
75
77
  end
76
78
  end
79
+
80
+ private
81
+
82
+ def set_initial_state
83
+ self.state ||= :new
84
+ end
77
85
  end
78
86
  end
79
87
  end
@@ -8,6 +8,8 @@ module StateMachines::Vacancy
8
8
  const_set 'STATES', [:open, :recommended, :denied, :closed]
9
9
  const_set 'EVENTS', [:accept_recommendation, :deny_recommendation, :close, :reopen]
10
10
 
11
+ after_initialize :set_initial_state
12
+
11
13
  state_machine :state, initial: :new do
12
14
  event :recommend do
13
15
  transition :new => :recommended
@@ -33,6 +35,12 @@ module StateMachines::Vacancy
33
35
  transition [:denied, :closed] => :open
34
36
  end
35
37
  end
38
+
39
+ private
40
+
41
+ def set_initial_state
42
+ self.state ||= :new
43
+ end
36
44
  end
37
45
  end
38
46
 
@@ -15,6 +15,8 @@ class Story
15
15
 
16
16
  accepts_nested_attributes_for :tasks, allow_destroy: true, reject_if: ->(t) { t['name'].blank? && t['text'].blank? }
17
17
 
18
+ # see https://github.com/mongoid/mongoid/issues/2222
19
+ field(:_type, default: ->{ self.class.name }, type: String)
18
20
  field :project_id, type: Integer
19
21
  field :offeror_id, type: Integer
20
22
  field :name, type: String
@@ -37,10 +37,11 @@
37
37
  <% if can? :edit, product %>
38
38
  <li><%= link_to t('general.edit'), eval("edit_product_path(product)") %></li>
39
39
  <% end %>
40
- <% if product.respond_to? :state_events %>
41
- <li class="divider"></li>
42
- <% end %>
43
- <%= render 'shared/resource/event_elements', resource: product, type: 'products' %>
40
+ <% links = event_links_for_resource(product, 'products') %>
41
+ <% if links.any? %>
42
+ <li class="divider"></li>
43
+ <%= render 'shared/resource/event_elements', links: links %>
44
+ <% end %>
44
45
  </ul>
45
46
  </div>
46
47
  <% end %>
@@ -21,10 +21,11 @@
21
21
  <% if can? :edit, resource %>
22
22
  <li><%= link_to t('general.edit'), eval("edit_#{(namespace.present? ? namespace.to_s + '_' : '')}#{type.gsub('/', '_').singularize}_path(resource)") %></li>
23
23
  <% end %>
24
- <% if resource.respond_to? :state_events %>
25
- <li class="divider"></li>
24
+ <% links = event_links_for_resource(resource, type) %>
25
+ <% if links.any? %>
26
+ <li class="divider"></li>
27
+ <%= render 'shared/resource/event_elements', links: links %>
26
28
  <% end %>
27
- <%= render 'shared/resource/event_elements', resource: resource, type: type %>
28
29
  </ul>
29
30
  </div>
30
31
  <% end %>
@@ -1,7 +1,5 @@
1
- <% if resource.respond_to? :state_events %>
2
- <% resource.state_events.select{|event| can? event, resource }.each do |event| %>
1
+ <% links.each do |link| %>
3
2
  <li>
4
- <%= link_to t("#{type}.show.events.#{event}"), eval("#{event}_#{type.singularize}_path(resource)"), method: :put %>
3
+ <%= raw link %>
5
4
  </li>
6
- <% end %>
7
5
  <% end %>
@@ -2,7 +2,7 @@
2
2
 
3
3
  <%= simple_form_for(current_user, url: preferences_user_path(current_user), html: { class: 'form-horizontal block-form' }) do |f| %>
4
4
  <div class="form-inputs">
5
- <%= f.input :main_role_id, collection: Role.public %>
5
+ <%= f.input :main_role_id, collection: Role.is_public %>
6
6
  </div>
7
7
 
8
8
  <div class="form-actions">
@@ -1,4 +1,21 @@
1
- <h3><%= params[:product_id] == 'no-name' ? 'No Name' : @product.name %></h3>
1
+ <% content_for :breadcrumbs do %>
2
+ <% product_key = nil %>
3
+ <% Voluntary::Navigation::Base.products.each{|s,k| product_key = k if s == params[:product_id] } %>
4
+ <%= raw(
5
+ (
6
+ [
7
+ link_to(t('workflow.index.title'), workflow_path),
8
+ link_to(t('workflow.user.index.title'), workflow_user_index_path),
9
+ link_to(t(product_key), product_workflow_user_index_path(params[:product_id]))
10
+ ] +
11
+ (@area.ancestors + [@area]).map do |a|
12
+ link_to(a.name, product_area_workflow_user_index_path(params[:product_id], a))
13
+ end
14
+ ).join(' > ')
15
+ ) %>
16
+ <% end %>
17
+
18
+ <h3><%= @area.name %></h3>
2
19
 
3
20
  <%= render 'shared/collection/table',
4
21
  type: 'areas', collection: @areas, columns: {
@@ -0,0 +1 @@
1
+ Rails.application.config.action_dispatch.cookies_serializer = :json
@@ -0,0 +1,8 @@
1
+ # from https://github.com/pluginaweek/state_machine/issues/251#issuecomment-31598775
2
+ module StateMachine
3
+ module Integrations
4
+ module ActiveModel
5
+ public :around_validation
6
+ end
7
+ end
8
+ end