voluntary 0.5.2 → 0.6.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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 04ce673bd23bdfc0a764e2e6e94a05721b54518d
4
- data.tar.gz: e7a3f174f5cdd4a83f37434bb639373079af5ae3
3
+ metadata.gz: 9e0d6d9bf2a37688124de536d7859f1830abf3c6
4
+ data.tar.gz: 94f456e0b313a7d306724a1612e0bedea268d0f6
5
5
  SHA512:
6
- metadata.gz: ecfb127f78f437007cf0d312bfe883698ac532fec3d6d04b38fd8315d587353996798504e731fcb92050429ac7282fa28bd293c6552223b88f7faba6550e2cb1
7
- data.tar.gz: 7401b9fd9770e8a18c3d001465545ec7aac84d1bc60a5316dc7d01f7e9e04128eed017e1ada63859070e653d07b21aa678c55095cf75af3763d9d81e7e806388
6
+ metadata.gz: 7e2b60e9b3b05d5f3c0bd8733b96908fd3cc687db7c03999dcd36c69834030e595c7ec77cfa961ebc93ff739830e53d228e67f74931e19732a3cd53d195eff74
7
+ data.tar.gz: d5affd0cc24ceb1af706ce02afaedaf1e9441509f033b6f884ee1b3516b93fe91f6409f4692b4241726e2d1f9180e4458eebe2ea3f7dac545ced13e0a6033b74
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## unreleased ##
2
2
 
3
+ ## 0.6.0 (October 1, 2015) ##
4
+
5
+ * [#93](https://github.com/volontariat/voluntary/issues/93) Core customizations for survey product.
6
+
3
7
  ## 0.5.2 (September 2, 2015) ##
4
8
 
5
9
  * Adds moment.js.
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 + '&nbsp;</span><span style="display:none;">' + h + '</span>&nbsp;&nbsp;<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
- #if @story.tasks.none?
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
- render 'general/wizard'
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
@@ -27,6 +27,10 @@ module Voluntary
27
27
  end
28
28
  end
29
29
 
30
+ def matrix
31
+ render json: Argument.matrix(params[:argumentables]), root: false
32
+ end
33
+
30
34
  def create
31
35
  raise CanCan::AccessDenied if current_user.blank?
32
36
 
@@ -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
@@ -36,4 +36,10 @@ class Area < ActiveRecord::Base
36
36
 
37
37
  def products
38
38
  end
39
+
40
+ private
41
+
42
+ def should_generate_new_friendly_id?
43
+ slug.blank? || name_changed?
44
+ end
39
45
  end
@@ -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 :likes, -> { where(positive: true) }, dependent: :delete_all, as: :target
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', dependent: :delete_all, as: :target
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
@@ -17,4 +17,10 @@ class Organization < ActiveRecord::Base
17
17
  friendly_id :name, :use => :slugged
18
18
 
19
19
  PARENT_TYPES = ['user']
20
+
21
+ private
22
+
23
+ def should_generate_new_friendly_id?
24
+ slug.blank? || name_changed?
25
+ end
20
26
  end
@@ -10,4 +10,10 @@ class Profession < ActiveRecord::Base
10
10
  extend FriendlyId
11
11
 
12
12
  friendly_id :name, :use => :slugged
13
+
14
+ private
15
+
16
+ def should_generate_new_friendly_id?
17
+ slug.blank? || name_changed?
18
+ end
13
19
  end
@@ -74,4 +74,8 @@ class Project < ActiveRecord::Base
74
74
  def destroy_non_active_records
75
75
  stories.destroy_all
76
76
  end
77
+
78
+ def should_generate_new_friendly_id?
79
+ slug.blank? || name_changed?
80
+ end
77
81
  end
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{|t| t.name.blank? && t.text.blank? }
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
@@ -77,6 +77,12 @@ class Story
77
77
  task
78
78
  end
79
79
 
80
+ protected
81
+
82
+ def with_offeror
83
+ true
84
+ end
85
+
80
86
  private
81
87
 
82
88
  def import_tasks_from_file
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
- result.try(:destroy)
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
@@ -113,4 +113,8 @@ class User < ActiveRecord::Base
113
113
  self.api_key = SecureRandom.uuid.tr('-', '')
114
114
  end while User.where(api_key: api_key).any?
115
115
  end
116
+
117
+ def should_generate_new_friendly_id?
118
+ slug.blank? || name_changed?
119
+ end
116
120
  end
@@ -1,20 +1,24 @@
1
1
  class Wikidata
2
2
  def self.search(term, known_things)
3
- JSON.parse(
4
- HTTParty.get(
5
- "https://www.wikidata.org/w/api.php?action=wbsearchentities&search=" +
6
- "#{URI.encode(term, /\W/)}&format=json&language=en&type=item&continue=0",
7
- verify: false
8
- ).body
9
- )['search'].map do |item|
10
- description = if item['description'].to_s.present? &&
11
- item['description'] != 'Wikimedia disambiguation page'
12
- " (#{item['description']})"
13
- else
14
- ''
15
- end
16
-
17
- "#{item['label']}#{description}"
18
- end.uniq.select{|i| known_things.select{|t| t[:name] == i }.none? }.map{|item| { name: item } }
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
@@ -0,0 +1,3 @@
1
+ class StorySerializer < ActiveModel::Serializer
2
+ attributes :id, :name, :text, :product_id, :state
3
+ end
@@ -0,0 +1,3 @@
1
+ class TaskSerializer < ActiveModel::Serializer
2
+ attributes :id, :name, :text, :offeror_id, :author_id, :user_id
3
+ 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
- Stories
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
- Tasks
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><%= link_to t('workflow.user.next_task'), next_task_workflow_user_index_path(story) %></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>
@@ -2,6 +2,8 @@ en:
2
2
  arguments:
3
3
  index:
4
4
  title: Arguments
5
+ matrix:
6
+ title: Arguments Matrix
5
7
  new:
6
8
  title: New Argument
7
9
  save:
@@ -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
@@ -60,6 +60,7 @@ require 'bitmask_attributes'
60
60
  require 'csv'
61
61
  require 'httparty'
62
62
  require 'active_model/serializer'
63
+ require 'mongoid_orderable'
63
64
 
64
65
  require 'voluntary/navigation'
65
66
 
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Voluntary
2
- VERSION = '0.5.2'
2
+ VERSION = '0.6.0'
3
3
  end
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.5.2
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-09-02 00:00:00.000000000 Z
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-5-2"
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