voluntary 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +1 -1
- data/app/assets/javascripts/voluntary/lib/jquery.cookie.js +139 -0
- data/app/assets/javascripts/voluntary/lib/jquery.toggle_text.js.coffee +27 -0
- data/app/controllers/concerns/voluntary/v1/base_controller.rb +8 -0
- data/app/controllers/stories_controller.rb +10 -5
- data/app/controllers/voluntary/api/v1/arguments_controller.rb +4 -0
- data/app/controllers/voluntary/api/v1/stories_controller.rb +90 -0
- data/app/models/area.rb +6 -0
- data/app/models/argument.rb +41 -1
- data/app/models/concerns/likeable.rb +3 -2
- data/app/models/organization.rb +6 -0
- data/app/models/profession.rb +6 -0
- data/app/models/project.rb +4 -0
- data/app/models/result.rb +4 -4
- data/app/models/state_machines/story.rb +12 -2
- data/app/models/story.rb +6 -0
- data/app/models/task.rb +7 -6
- data/app/models/user.rb +4 -0
- data/app/models/wikidata.rb +20 -16
- data/app/serializers/story_serializer.rb +3 -0
- data/app/serializers/task_serializer.rb +3 -0
- data/app/views/workflow/user/index.html.erb +2 -2
- data/app/views/workflow/user/stories/_next_task.html.erb +1 -0
- data/app/views/workflow/user/stories/index.html.erb +5 -1
- data/config/locales/resources/argument/en.yml +2 -0
- data/config/locales/resources/story/en.yml +12 -0
- data/config/locales/resources/thing/en.yml +7 -0
- data/config/routes/api.rb +11 -2
- data/lib/voluntary.rb +1 -0
- data/lib/voluntary/navigation.rb +4 -0
- data/lib/voluntary/version.rb +1 -1
- metadata +23 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e0d6d9bf2a37688124de536d7859f1830abf3c6
|
4
|
+
data.tar.gz: 94f456e0b313a7d306724a1612e0bedea268d0f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e2b60e9b3b05d5f3c0bd8733b96908fd3cc687db7c03999dcd36c69834030e595c7ec77cfa961ebc93ff739830e53d228e67f74931e19732a3cd53d195eff74
|
7
|
+
data.tar.gz: d5affd0cc24ceb1af706ce02afaedaf1e9441509f033b6f884ee1b3516b93fe91f6409f4692b4241726e2d1f9180e4458eebe2ea3f7dac545ced13e0a6033b74
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -89,7 +89,7 @@ Run this in your console:
|
|
89
89
|
bundle exec rake db:create:all && bundle exec rails g voluntary:product_dummy # confirm all overwrite questions except of Gemfile
|
90
90
|
cd ..
|
91
91
|
# add gitignore file from voluntary: https://github.com/volontariat/voluntary/blob/master/.gitignore
|
92
|
-
rails g migration add_product_name_product
|
92
|
+
bundle exec rails g migration add_product_name_product
|
93
93
|
# fill migration file with template: https://github.com/volontariat/voluntary_scholarship/blob/master/db/migrate/20140306201232_add_scholarship_product.rb
|
94
94
|
cd dummy
|
95
95
|
bundle exec rake railties:install:migrations
|
@@ -0,0 +1,139 @@
|
|
1
|
+
/*!
|
2
|
+
* JavaScript Cookie v2.0.3
|
3
|
+
* https://github.com/js-cookie/js-cookie
|
4
|
+
*
|
5
|
+
* Copyright 2006, 2015 Klaus Hartl & Fagner Brack
|
6
|
+
* Released under the MIT license
|
7
|
+
*/
|
8
|
+
(function (factory) {
|
9
|
+
if (typeof define === 'function' && define.amd) {
|
10
|
+
define(factory);
|
11
|
+
} else if (typeof exports === 'object') {
|
12
|
+
module.exports = factory();
|
13
|
+
} else {
|
14
|
+
var _OldCookies = window.Cookies;
|
15
|
+
var api = window.Cookies = factory();
|
16
|
+
api.noConflict = function () {
|
17
|
+
window.Cookies = _OldCookies;
|
18
|
+
return api;
|
19
|
+
};
|
20
|
+
}
|
21
|
+
}(function () {
|
22
|
+
function extend () {
|
23
|
+
var i = 0;
|
24
|
+
var result = {};
|
25
|
+
for (; i < arguments.length; i++) {
|
26
|
+
var attributes = arguments[ i ];
|
27
|
+
for (var key in attributes) {
|
28
|
+
result[key] = attributes[key];
|
29
|
+
}
|
30
|
+
}
|
31
|
+
return result;
|
32
|
+
}
|
33
|
+
|
34
|
+
function init (converter) {
|
35
|
+
function api (key, value, attributes) {
|
36
|
+
var result;
|
37
|
+
|
38
|
+
// Write
|
39
|
+
|
40
|
+
if (arguments.length > 1) {
|
41
|
+
attributes = extend({
|
42
|
+
path: '/'
|
43
|
+
}, api.defaults, attributes);
|
44
|
+
|
45
|
+
if (typeof attributes.expires === 'number') {
|
46
|
+
var expires = new Date();
|
47
|
+
expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
|
48
|
+
attributes.expires = expires;
|
49
|
+
}
|
50
|
+
|
51
|
+
try {
|
52
|
+
result = JSON.stringify(value);
|
53
|
+
if (/^[\{\[]/.test(result)) {
|
54
|
+
value = result;
|
55
|
+
}
|
56
|
+
} catch (e) {}
|
57
|
+
|
58
|
+
value = encodeURIComponent(String(value));
|
59
|
+
value = value.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
|
60
|
+
|
61
|
+
key = encodeURIComponent(String(key));
|
62
|
+
key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
|
63
|
+
key = key.replace(/[\(\)]/g, escape);
|
64
|
+
|
65
|
+
return (document.cookie = [
|
66
|
+
key, '=', value,
|
67
|
+
attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE
|
68
|
+
attributes.path && '; path=' + attributes.path,
|
69
|
+
attributes.domain && '; domain=' + attributes.domain,
|
70
|
+
attributes.secure ? '; secure' : ''
|
71
|
+
].join(''));
|
72
|
+
}
|
73
|
+
|
74
|
+
// Read
|
75
|
+
|
76
|
+
if (!key) {
|
77
|
+
result = {};
|
78
|
+
}
|
79
|
+
|
80
|
+
// To prevent the for loop in the first place assign an empty array
|
81
|
+
// in case there are no cookies at all. Also prevents odd result when
|
82
|
+
// calling "get()"
|
83
|
+
var cookies = document.cookie ? document.cookie.split('; ') : [];
|
84
|
+
var rdecode = /(%[0-9A-Z]{2})+/g;
|
85
|
+
var i = 0;
|
86
|
+
|
87
|
+
for (; i < cookies.length; i++) {
|
88
|
+
var parts = cookies[i].split('=');
|
89
|
+
var name = parts[0].replace(rdecode, decodeURIComponent);
|
90
|
+
var cookie = parts.slice(1).join('=');
|
91
|
+
|
92
|
+
if (cookie.charAt(0) === '"') {
|
93
|
+
cookie = cookie.slice(1, -1);
|
94
|
+
}
|
95
|
+
|
96
|
+
try {
|
97
|
+
cookie = converter && converter(cookie, name) || cookie.replace(rdecode, decodeURIComponent);
|
98
|
+
|
99
|
+
if (this.json) {
|
100
|
+
try {
|
101
|
+
cookie = JSON.parse(cookie);
|
102
|
+
} catch (e) {}
|
103
|
+
}
|
104
|
+
|
105
|
+
if (key === name) {
|
106
|
+
result = cookie;
|
107
|
+
break;
|
108
|
+
}
|
109
|
+
|
110
|
+
if (!key) {
|
111
|
+
result[name] = cookie;
|
112
|
+
}
|
113
|
+
} catch (e) {}
|
114
|
+
}
|
115
|
+
|
116
|
+
return result;
|
117
|
+
}
|
118
|
+
|
119
|
+
api.get = api.set = api;
|
120
|
+
api.getJSON = function () {
|
121
|
+
return api.apply({
|
122
|
+
json: true
|
123
|
+
}, [].slice.call(arguments));
|
124
|
+
};
|
125
|
+
api.defaults = {};
|
126
|
+
|
127
|
+
api.remove = function (key, attributes) {
|
128
|
+
api(key, '', extend(attributes, {
|
129
|
+
expires: -1
|
130
|
+
}));
|
131
|
+
};
|
132
|
+
|
133
|
+
api.withConverter = init;
|
134
|
+
|
135
|
+
return api;
|
136
|
+
}
|
137
|
+
|
138
|
+
return init();
|
139
|
+
}));
|
@@ -0,0 +1,27 @@
|
|
1
|
+
@toggleText = ->
|
2
|
+
showChar = 255
|
3
|
+
ellipsesText = '...'
|
4
|
+
moreText = 'Show more >'
|
5
|
+
lessText = 'Show less'
|
6
|
+
|
7
|
+
$('.more').each ->
|
8
|
+
content = $(this).html()
|
9
|
+
|
10
|
+
if content.length > showChar
|
11
|
+
c = content.substr(0, showChar)
|
12
|
+
h = content.substr(showChar, content.length - showChar)
|
13
|
+
html = c + '<span class="more_ellipses">' + ellipsesText + ' </span><span style="display:none;">' + h + '</span> <a href="" class="more_link" style="display:block;">' + moreText + '</a>'
|
14
|
+
$(this).html html
|
15
|
+
|
16
|
+
$('.more_link').click ->
|
17
|
+
if $(this).hasClass('less')
|
18
|
+
$(this).removeClass 'less'
|
19
|
+
$(this).html moreText
|
20
|
+
else
|
21
|
+
$(this).addClass 'less'
|
22
|
+
$(this).html lessText
|
23
|
+
|
24
|
+
$(this).siblings('.more_ellipses').toggle()
|
25
|
+
$(this).prev().toggle()
|
26
|
+
|
27
|
+
false
|
@@ -26,6 +26,14 @@ module Voluntary
|
|
26
26
|
|
27
27
|
protected
|
28
28
|
|
29
|
+
def product_serializer(class_name, record)
|
30
|
+
begin
|
31
|
+
"#{record.product.class.name.gsub('Product::', '')}#{class_name}Serializer".constantize.new(record)
|
32
|
+
rescue NameError
|
33
|
+
"#{class_name}Serializer".constantize.new(record)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
29
37
|
def application_navigation
|
30
38
|
:main
|
31
39
|
end
|
@@ -18,6 +18,7 @@ class StoriesController < ApplicationController
|
|
18
18
|
|
19
19
|
def show
|
20
20
|
@comments = @story.comments
|
21
|
+
@twitter_sidenav_level = 5
|
21
22
|
end
|
22
23
|
|
23
24
|
def new
|
@@ -33,10 +34,7 @@ class StoriesController < ApplicationController
|
|
33
34
|
end
|
34
35
|
|
35
36
|
def edit
|
36
|
-
|
37
|
-
#@story.tasks << @story.tasks.new
|
38
|
-
#@story.tasks.first.errors.clear
|
39
|
-
#end
|
37
|
+
@twitter_sidenav_level = 5
|
40
38
|
|
41
39
|
render_wizard
|
42
40
|
end
|
@@ -90,6 +88,13 @@ class StoriesController < ApplicationController
|
|
90
88
|
@presenter = Resources::General::Wizards::StoryPresenter.new(
|
91
89
|
self.view_context, resource: resource
|
92
90
|
)
|
93
|
-
|
91
|
+
|
92
|
+
begin
|
93
|
+
raise NotImplementedError if @project.product_id.blank?
|
94
|
+
|
95
|
+
render "products/types/#{@project.product.class.name.split('Product::').last.tableize.singularize}/wizard"
|
96
|
+
rescue NotImplementedError, ActionView::MissingTemplate
|
97
|
+
render 'general/wizard'
|
98
|
+
end
|
94
99
|
end
|
95
100
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
class Voluntary::Api::V1::StoriesController < ActionController::Base
|
2
|
+
include Voluntary::V1::BaseController
|
3
|
+
|
4
|
+
respond_to :json
|
5
|
+
|
6
|
+
def show
|
7
|
+
story = Story.find(params[:id])
|
8
|
+
|
9
|
+
respond_to do |format|
|
10
|
+
format.json do
|
11
|
+
render json: product_serializer('Story', story)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def create
|
17
|
+
project = Project.find(params[:story][:project_id])
|
18
|
+
story = project.story_class.new({ project_id: project.id }.merge(params[:story] || {}))
|
19
|
+
|
20
|
+
authorize! :create, story
|
21
|
+
|
22
|
+
story.save
|
23
|
+
|
24
|
+
respond_to do |format|
|
25
|
+
format.json do
|
26
|
+
render json: story.persisted? ? product_serializer('Story', story) : { errors: story.errors.to_hash }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def update
|
32
|
+
story = Story.find params[:id]
|
33
|
+
|
34
|
+
authorize! :update, story
|
35
|
+
|
36
|
+
story.update_attributes params[:story]
|
37
|
+
|
38
|
+
respond_to do |format|
|
39
|
+
format.json do
|
40
|
+
render json: story.valid? ? product_serializer('Story', story) : { errors: story.errors.to_hash }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def activate
|
46
|
+
story = Story.find params[:id]
|
47
|
+
|
48
|
+
authorize! :update, story
|
49
|
+
|
50
|
+
story.activate
|
51
|
+
|
52
|
+
respond_to do |format|
|
53
|
+
format.json do
|
54
|
+
render json: story.errors.empty? && story.valid? ? product_serializer('Story', story) : { errors: story.errors.to_hash }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def deactivate
|
60
|
+
story = Story.find params[:id]
|
61
|
+
|
62
|
+
authorize! :update, story
|
63
|
+
|
64
|
+
story.deactivate
|
65
|
+
|
66
|
+
respond_to do |format|
|
67
|
+
format.json do
|
68
|
+
render json: story.errors.empty? && story.valid? ? product_serializer('Story', story) : { errors: story.errors.to_hash }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def destroy
|
74
|
+
story = current_user.stories.friendly.find params[:id]
|
75
|
+
|
76
|
+
authorize! :destroy, story
|
77
|
+
|
78
|
+
story.destroy
|
79
|
+
|
80
|
+
respond_to do |format|
|
81
|
+
format.json do
|
82
|
+
render json: if story.persisted?
|
83
|
+
{ error: I18n.t('activerecord.errors.models.story.attributes.base.deletion_failed') }
|
84
|
+
else
|
85
|
+
{}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/app/models/area.rb
CHANGED
data/app/models/argument.rb
CHANGED
@@ -27,7 +27,7 @@ class Argument < ActiveRecord::Base
|
|
27
27
|
|
28
28
|
attr_accessible :topic_id, :argumentable_type, :argumentable_id, :vote, :value
|
29
29
|
|
30
|
-
attr_accessor :positive
|
30
|
+
attr_accessor :vote, :positive
|
31
31
|
|
32
32
|
def self.create_with_topic(user_id, attributes)
|
33
33
|
topic = ArgumentTopic.find_or_create_by_name attributes[:topic_name]
|
@@ -55,4 +55,44 @@ class Argument < ActiveRecord::Base
|
|
55
55
|
{ errors: { topic: topic.errors.to_hash } }
|
56
56
|
end
|
57
57
|
end
|
58
|
+
|
59
|
+
def self.matrix(argumentables)
|
60
|
+
arguments = []
|
61
|
+
|
62
|
+
argumentables.each do |index, argumentable|
|
63
|
+
arguments += Argument.where(
|
64
|
+
argumentable_type: argumentable['type'], argumentable_id: argumentable['id']
|
65
|
+
).includes(:topic).to_a
|
66
|
+
end
|
67
|
+
|
68
|
+
arguments_by_name = {}
|
69
|
+
|
70
|
+
arguments.each do |argument|
|
71
|
+
arguments_by_name[argument.topic.name] ||= []
|
72
|
+
arguments_by_name[argument.topic.name] << argument
|
73
|
+
end
|
74
|
+
|
75
|
+
json = { argumentables: [], matrix: [] }
|
76
|
+
|
77
|
+
argumentables.keys.map(&:to_i).sort.each do |argumentable_index|
|
78
|
+
argumentable = argumentables[argumentable_index.to_s]
|
79
|
+
argumentable = argumentable['type'].constantize.find(argumentable['id'])
|
80
|
+
|
81
|
+
json[:argumentables] << { id: argumentable.id, slug: argumentable.try(:slug), name: argumentable.name }
|
82
|
+
end
|
83
|
+
|
84
|
+
arguments_by_name.keys.sort.each do |topic_name|
|
85
|
+
item = { topic_name: topic_name, values: [] }
|
86
|
+
arguments = arguments_by_name[topic_name]
|
87
|
+
|
88
|
+
argumentables.keys.map(&:to_i).sort.each do |argumentable_index|
|
89
|
+
argumentable = argumentables[argumentable_index.to_s]
|
90
|
+
item[:values] << arguments.select{|a| a.argumentable_type == argumentable['type'] && a.argumentable_id == argumentable['id'].to_i }.first.try(:value)
|
91
|
+
end
|
92
|
+
|
93
|
+
json[:matrix] << item
|
94
|
+
end
|
95
|
+
|
96
|
+
json
|
97
|
+
end
|
58
98
|
end
|
@@ -4,9 +4,10 @@ module Likeable
|
|
4
4
|
included do
|
5
5
|
belongs_to :target, polymorphic: true
|
6
6
|
|
7
|
-
has_many :
|
7
|
+
has_many :likes_or_dislikes, class_name: 'Like', dependent: :delete_all, as: :target
|
8
|
+
has_many :likes, -> { where(positive: true) }, as: :target
|
8
9
|
has_many :likers, class_name: 'User', through: :likes, source: :user
|
9
|
-
has_many :dislikes, -> { where(positive: false) }, class_name: 'Like',
|
10
|
+
has_many :dislikes, -> { where(positive: false) }, class_name: 'Like', as: :target
|
10
11
|
has_many :dislikers, class_name: 'User', through: :dislikes, source: :user
|
11
12
|
|
12
13
|
scope :liked_by, ->(user_id) do
|
data/app/models/organization.rb
CHANGED
data/app/models/profession.rb
CHANGED
data/app/models/project.rb
CHANGED
data/app/models/result.rb
CHANGED
@@ -23,7 +23,7 @@ class Result
|
|
23
23
|
|
24
24
|
validates :task_id, presence: true
|
25
25
|
validates :story_id, presence: true
|
26
|
-
validates :offeror_id, presence: true
|
26
|
+
validates :offeror_id, presence: true, if: 'task_id.present? && (task rescue nil) && task.story.with_offeror'
|
27
27
|
validates :text, presence: true
|
28
28
|
|
29
29
|
after_initialize :cache_associations
|
@@ -48,13 +48,13 @@ class Result
|
|
48
48
|
|
49
49
|
def cache_associations
|
50
50
|
self.story_id = task.story_id if task_id.present? && (task rescue nil)
|
51
|
-
self.offeror_id = task.offeror_id if task_id.present? && (task rescue nil)
|
51
|
+
self.offeror_id = task.offeror_id if task_id.present? && (task rescue nil) && task.story.with_offeror
|
52
52
|
end
|
53
53
|
|
54
54
|
def cache_product_association
|
55
55
|
self.product_id = task.product_id if task_id.present? && (task rescue nil)
|
56
56
|
end
|
57
57
|
|
58
|
-
def set_tasks_result_association; task.update_attribute(:result_id, id); end
|
59
|
-
def unset_tasks_result_association; task.update_attribute(:result_id, nil); end
|
58
|
+
def set_tasks_result_association; task.update_attribute(:result_id, id) unless task.respond_to?(:results); end
|
59
|
+
def unset_tasks_result_association; task.update_attribute(:result_id, nil) unless task.respond_to?(:results); end
|
60
60
|
end
|
@@ -26,8 +26,16 @@ module StateMachines::Story
|
|
26
26
|
validate :presence_of_tasks
|
27
27
|
end
|
28
28
|
|
29
|
+
state :active do
|
30
|
+
validate :presence_of_tasks
|
31
|
+
end
|
32
|
+
|
29
33
|
event :activate do
|
30
|
-
transition [:tasks_defined, :completed] => :active
|
34
|
+
transition [:new, :tasks_defined, :completed] => :active
|
35
|
+
end
|
36
|
+
|
37
|
+
event :deactivate do
|
38
|
+
transition :active => :tasks_defined
|
31
39
|
end
|
32
40
|
|
33
41
|
event :complete do
|
@@ -51,7 +59,9 @@ module StateMachines::Story
|
|
51
59
|
end
|
52
60
|
|
53
61
|
def presence_of_tasks
|
54
|
-
self.tasks.delete_if
|
62
|
+
self.tasks.delete_if do |t|
|
63
|
+
t.name.blank? && (t.class.name == 'Task' && t.text.blank?)
|
64
|
+
end
|
55
65
|
|
56
66
|
if tasks.select{|t| !t.valid?}.any?
|
57
67
|
errors[:base] << I18n.t(
|
data/app/models/story.rb
CHANGED
data/app/models/task.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
class Task
|
2
2
|
include Mongoid::Document
|
3
3
|
include Mongoid::Timestamps
|
4
|
-
include Mongoid::Slug
|
5
4
|
#include Mongoid::History::Trackable
|
6
5
|
include ActiveModel::MassAssignmentSecurity
|
7
6
|
|
@@ -21,8 +20,6 @@ class Task
|
|
21
20
|
field :text, type: String
|
22
21
|
field :state, type: String
|
23
22
|
field :unassigned_user_ids, type: Array
|
24
|
-
|
25
|
-
slug :name, reserve: ['new', 'edit', 'next']
|
26
23
|
|
27
24
|
attr_accessible :story, :story_id, :name, :text, :result_attributes
|
28
25
|
|
@@ -33,7 +30,7 @@ class Task
|
|
33
30
|
scope :incomplete, -> { ne(state: 'completed') }
|
34
31
|
|
35
32
|
validates :story_id, presence: true
|
36
|
-
validates :offeror_id, presence: true
|
33
|
+
validates :offeror_id, presence: true, if: 'story_id.present? && (story rescue nil) && story.with_offeror'
|
37
34
|
validates :text, presence: true, if: ->(t) { t.class.name == 'Task' }
|
38
35
|
validate :name_valid?
|
39
36
|
|
@@ -124,11 +121,15 @@ class Task
|
|
124
121
|
private
|
125
122
|
|
126
123
|
def destroy_result
|
127
|
-
|
124
|
+
if respond_to? :results
|
125
|
+
results.map(&:destroy)
|
126
|
+
else
|
127
|
+
result.try(:destroy)
|
128
|
+
end
|
128
129
|
end
|
129
130
|
|
130
131
|
def cache_associations
|
131
|
-
self.offeror_id = story.offeror_id if story_id.present? && (story rescue nil)
|
132
|
+
self.offeror_id = story.offeror_id if story_id.present? && (story rescue nil) && story.with_offeror
|
132
133
|
end
|
133
134
|
|
134
135
|
def cache_product_association
|
data/app/models/user.rb
CHANGED
data/app/models/wikidata.rb
CHANGED
@@ -1,20 +1,24 @@
|
|
1
1
|
class Wikidata
|
2
2
|
def self.search(term, known_things)
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
3
|
+
begin
|
4
|
+
JSON.parse(
|
5
|
+
HTTParty.get(
|
6
|
+
"https://www.wikidata.org/w/api.php?action=wbsearchentities&search=" +
|
7
|
+
"#{URI.encode(term, /\W/)}&format=json&language=en&type=item&continue=0",
|
8
|
+
verify: false
|
9
|
+
).body
|
10
|
+
)['search'].map do |item|
|
11
|
+
description = if item['description'].to_s.present? &&
|
12
|
+
item['description'] != 'Wikimedia disambiguation page'
|
13
|
+
" (#{item['description']})"
|
14
|
+
else
|
15
|
+
''
|
16
|
+
end
|
17
|
+
|
18
|
+
"#{item['label']}#{description}"
|
19
|
+
end.uniq.select{|i| known_things.select{|t| t[:name] == i }.none? }.map{|item| { name: item } }
|
20
|
+
rescue SocketError => e
|
21
|
+
[]
|
22
|
+
end
|
19
23
|
end
|
20
24
|
end
|
@@ -19,10 +19,10 @@
|
|
19
19
|
</ul>
|
20
20
|
<div class="tab-content">
|
21
21
|
<div role="tabpanel" class="tab-pane active" id="stories" style="padding-top:15px;">
|
22
|
-
|
22
|
+
<%= image_tag 'voluntary/spinner.gif' %>
|
23
23
|
</div>
|
24
24
|
<div role="tabpanel" class="tab-pane" id="assigned_tasks" style="padding-top:15px;">
|
25
|
-
|
25
|
+
<%= image_tag 'voluntary/spinner.gif' %>
|
26
26
|
</div>
|
27
27
|
</div>
|
28
28
|
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= link_to t('workflow.user.next_task'), next_task_workflow_user_index_path(story) %>
|
@@ -19,7 +19,11 @@
|
|
19
19
|
-
|
20
20
|
<% end %>
|
21
21
|
</td>
|
22
|
-
<td
|
22
|
+
<td>
|
23
|
+
<%= render_product_specific_partial_if_available(
|
24
|
+
story.project, 'workflow/user/stories/next_task', { story: story }
|
25
|
+
) %>
|
26
|
+
</td>
|
23
27
|
</tr>
|
24
28
|
<% end %>
|
25
29
|
</tbody>
|
@@ -7,6 +7,13 @@ en:
|
|
7
7
|
|
8
8
|
new:
|
9
9
|
title: New Story
|
10
|
+
|
11
|
+
create:
|
12
|
+
title: Create Story
|
13
|
+
|
14
|
+
save:
|
15
|
+
failed: Something went wrong at saving story
|
16
|
+
successful: Successfully saved story.
|
10
17
|
|
11
18
|
show:
|
12
19
|
states:
|
@@ -15,6 +22,9 @@ en:
|
|
15
22
|
|
16
23
|
edit:
|
17
24
|
title: Edit Story
|
25
|
+
|
26
|
+
update:
|
27
|
+
title: Update Story
|
18
28
|
|
19
29
|
steps:
|
20
30
|
initialization:
|
@@ -26,6 +36,8 @@ en:
|
|
26
36
|
update: Update Tasks
|
27
37
|
activate:
|
28
38
|
title: Activate
|
39
|
+
deactivate:
|
40
|
+
title: Deactivate
|
29
41
|
|
30
42
|
activerecord:
|
31
43
|
attributes:
|
@@ -1,4 +1,11 @@
|
|
1
1
|
en:
|
2
|
+
things:
|
3
|
+
show:
|
4
|
+
limit_of_comparison_list: Limit of 4 items in thing comparison list reached!
|
5
|
+
add_to_comparison_list: Add to comparison list
|
6
|
+
remove_from_comparison_list: Remove from comparison list
|
7
|
+
comparison_list: Comparison List
|
8
|
+
|
2
9
|
activerecord:
|
3
10
|
errors:
|
4
11
|
models:
|
data/config/routes/api.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
namespace :voluntary, path: 'api', module: 'voluntary/api', defaults: {format: 'json'} do
|
2
2
|
namespace :v1 do
|
3
|
-
resources :stories, only: [] do
|
3
|
+
resources :stories, only: [:create, :show, :update, :destroy] do
|
4
4
|
resources :tasks, only: [:index, :create]
|
5
|
+
|
6
|
+
member do
|
7
|
+
put :activate
|
8
|
+
put :deactivate
|
9
|
+
end
|
5
10
|
end
|
6
11
|
|
7
12
|
resources :argument_topics, only: [] do
|
@@ -10,7 +15,11 @@ namespace :voluntary, path: 'api', module: 'voluntary/api', defaults: {format: '
|
|
10
15
|
end
|
11
16
|
end
|
12
17
|
|
13
|
-
resources :arguments
|
18
|
+
resources :arguments do
|
19
|
+
collection do
|
20
|
+
get :matrix
|
21
|
+
end
|
22
|
+
end
|
14
23
|
|
15
24
|
get '/things/:left_thing_name/vs/:right_thing_name/arguments', to: 'things/arguments#comparison'
|
16
25
|
|
data/lib/voluntary.rb
CHANGED
data/lib/voluntary/navigation.rb
CHANGED
@@ -210,6 +210,10 @@ module Voluntary
|
|
210
210
|
comments.item(:edit, I18n.t('general.edit'), edit_comment_path(@comment))
|
211
211
|
end
|
212
212
|
end
|
213
|
+
|
214
|
+
if options[:stories_after_resource_has_many]
|
215
|
+
instance_exec story, {}, &options[:stories_after_resource_has_many]
|
216
|
+
end
|
213
217
|
end
|
214
218
|
end
|
215
219
|
end
|
data/lib/voluntary/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: voluntary
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mathias Gawlista
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -444,6 +444,20 @@ dependencies:
|
|
444
444
|
- - "~>"
|
445
445
|
- !ruby/object:Gem::Version
|
446
446
|
version: 1.0.0
|
447
|
+
- !ruby/object:Gem::Dependency
|
448
|
+
name: mongoid_orderable
|
449
|
+
requirement: !ruby/object:Gem::Requirement
|
450
|
+
requirements:
|
451
|
+
- - "~>"
|
452
|
+
- !ruby/object:Gem::Version
|
453
|
+
version: 4.1.1
|
454
|
+
type: :runtime
|
455
|
+
prerelease: false
|
456
|
+
version_requirements: !ruby/object:Gem::Requirement
|
457
|
+
requirements:
|
458
|
+
- - "~>"
|
459
|
+
- !ruby/object:Gem::Version
|
460
|
+
version: 4.1.1
|
447
461
|
- !ruby/object:Gem::Dependency
|
448
462
|
name: mongoid_slug
|
449
463
|
requirement: !ruby/object:Gem::Requirement
|
@@ -1130,7 +1144,7 @@ dependencies:
|
|
1130
1144
|
- - "~>"
|
1131
1145
|
- !ruby/object:Gem::Version
|
1132
1146
|
version: 2.2.0
|
1133
|
-
description: "#Crowdsourcing management system for #RubyOnRails: http://bit.ly/voluntary-0-
|
1147
|
+
description: "#Crowdsourcing management system for #RubyOnRails: http://bit.ly/voluntary-0-6-0"
|
1134
1148
|
email:
|
1135
1149
|
- gawlista@gmail.com
|
1136
1150
|
executables: []
|
@@ -1146,7 +1160,9 @@ files:
|
|
1146
1160
|
- app/assets/javascripts/voluntary/base.js.coffee
|
1147
1161
|
- app/assets/javascripts/voluntary/functions.js
|
1148
1162
|
- app/assets/javascripts/voluntary/lib/jquery-competitive_list.js
|
1163
|
+
- app/assets/javascripts/voluntary/lib/jquery.cookie.js
|
1149
1164
|
- app/assets/javascripts/voluntary/lib/jquery.multisortable.js
|
1165
|
+
- app/assets/javascripts/voluntary/lib/jquery.toggle_text.js.coffee
|
1150
1166
|
- app/assets/javascripts/voluntary/lib/moment.js
|
1151
1167
|
- app/assets/javascripts/voluntary/lib/sugar.js
|
1152
1168
|
- app/assets/javascripts/voluntary/likes/list.js.coffee
|
@@ -1176,6 +1192,7 @@ files:
|
|
1176
1192
|
- app/controllers/voluntary/api/v1/arguments_controller.rb
|
1177
1193
|
- app/controllers/voluntary/api/v1/base_controller.rb
|
1178
1194
|
- app/controllers/voluntary/api/v1/organizations_controller.rb
|
1195
|
+
- app/controllers/voluntary/api/v1/stories_controller.rb
|
1179
1196
|
- app/controllers/voluntary/api/v1/tasks_controller.rb
|
1180
1197
|
- app/controllers/voluntary/api/v1/things/arguments_controller.rb
|
1181
1198
|
- app/controllers/voluntary/api/v1/users_controller.rb
|
@@ -1248,6 +1265,8 @@ files:
|
|
1248
1265
|
- app/serializers/argument_serializer.rb
|
1249
1266
|
- app/serializers/basic_user_serializer.rb
|
1250
1267
|
- app/serializers/current_user_serializer.rb
|
1268
|
+
- app/serializers/story_serializer.rb
|
1269
|
+
- app/serializers/task_serializer.rb
|
1251
1270
|
- app/serializers/user_serializer.rb
|
1252
1271
|
- app/views/areas/_form.html.erb
|
1253
1272
|
- app/views/areas/edit.html.erb
|
@@ -1339,6 +1358,7 @@ files:
|
|
1339
1358
|
- app/views/workflow/user/index.html.erb
|
1340
1359
|
- app/views/workflow/user/product/areas/show.html.erb
|
1341
1360
|
- app/views/workflow/user/projects/show.html.erb
|
1361
|
+
- app/views/workflow/user/stories/_next_task.html.erb
|
1342
1362
|
- app/views/workflow/user/stories/index.html.erb
|
1343
1363
|
- app/views/workflow/user/tasks/assigned.html.erb
|
1344
1364
|
- config/initializers/1_initialize_app_config.rb
|