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 +5 -13
- data/CHANGELOG.md +7 -0
- data/{README.rdoc → README.md} +20 -6
- data/app/controllers/candidatures_controller.rb +1 -1
- data/app/controllers/voluntary/api/v1/base_controller.rb +0 -7
- data/app/helpers/voluntary/application_helper.rb +17 -0
- data/app/models/area.rb +15 -2
- data/app/models/concerns/likeable.rb +4 -1
- data/app/models/product.rb +1 -1
- data/app/models/product/project_management.rb +1 -1
- data/app/models/role.rb +1 -1
- data/app/models/state_machines/candidature.rb +6 -0
- data/app/models/state_machines/page.rb +8 -0
- data/app/models/state_machines/story.rb +6 -0
- data/app/models/state_machines/task.rb +8 -0
- data/app/models/state_machines/vacancy.rb +8 -0
- data/app/models/story.rb +2 -0
- data/app/views/products/index.html.erb +5 -4
- data/app/views/shared/resource/_actions.html.erb +4 -3
- data/app/views/shared/resource/_event_elements.html.erb +2 -4
- data/app/views/users/preferences.html.erb +1 -1
- data/app/views/workflow/user/product/areas/show.html.erb +18 -1
- data/config/initializers/cookies_serializer.rb +1 -0
- data/config/initializers/state_machine_patch_for_rails_4_1_support.rb +8 -0
- data/lib/voluntary.rb +3 -9
- data/lib/voluntary/engine.rb +7 -0
- data/lib/voluntary/test/rspec_helpers/factories.rb +1 -1
- data/lib/voluntary/version.rb +1 -1
- data/lib/wizard.rb +2 -2
- metadata +203 -285
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZjNkMDA4MzU1N2RhZDBhNzMyMjc1ODVhN2M5MjFhZDk3NjY1NGNkNQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a771ddeec412e7d388b055acff871018533619c5
|
4
|
+
data.tar.gz: c76dc81a5782f89e7309a4391297aa1bced80d89
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
ZDg4OTM3YWM0N2ZhZWZlYjQ4YTg5MjVmMDlkYzVlZjE0NWZhNGM0N2QwMDI1
|
11
|
-
ZmNlNzM0NTc2NTdkMWZjZTk4YjZkNWMyNmVmMTA4ZjY4M2U3NjE=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
ZWJkYzg0ZmRjYTlmYjFmMWNmZDgxZmRkMzcwOTg2ODEwZmVkM2Q3ZDhjZmQ1
|
14
|
-
ZjE1YzE0ODUzZjVlNDYyZWMyOTQ0Mzk3Y2EwNmVlZjA4NWMyOWJlMDFiOWFl
|
15
|
-
ZDlhNDY3NTBhMWZlOWI4OTI5NTUyMDdmZDUxNWE5NmJhYWExZDY=
|
6
|
+
metadata.gz: 98f5ff05154ed1c5c22dad03918f3648f3935b2e46fbeb8eb877d86afe74196858cf4352460033c6499b42a49d988efb4538ed703b344c1bc4195dab1992b6ff
|
7
|
+
data.tar.gz: 996f49f84e99d8b219029c9fbeebd57733eceb89475a640964e98375dc27eb514a383bfcae6ed8b3209372b0d2b5cb8d07ffcd3ff51c23f08d87884a41a64795
|
data/CHANGELOG.md
CHANGED
@@ -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).
|
data/{README.rdoc → README.md}
RENAMED
@@ -1,35 +1,43 @@
|
|
1
|
-
=
|
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
|
-
|
7
|
+
## Installation
|
8
8
|
|
9
|
-
|
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
|
-
|
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
|
-
|
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')
|
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
|
data/app/models/area.rb
CHANGED
@@ -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
|
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'
|
data/app/models/product.rb
CHANGED
data/app/models/role.rb
CHANGED
@@ -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
|
|
data/app/models/story.rb
CHANGED
@@ -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
|
-
<%
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
-
<%
|
25
|
-
|
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
|
-
<%
|
2
|
-
<% resource.state_events.select{|event| can? event, resource }.each do |event| %>
|
1
|
+
<% links.each do |link| %>
|
3
2
|
<li>
|
4
|
-
<%=
|
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.
|
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
|
-
|
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
|