voluntary 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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