voluntary_brainstorming 0.0.1 → 0.0.2

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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +3 -2
  3. data/app/assets/javascripts/voluntary_brainstorming/app.js.coffee +8 -0
  4. data/app/assets/javascripts/voluntary_brainstorming/application.js +4 -0
  5. data/app/assets/javascripts/voluntary_brainstorming/components/brainstorming_idea_argument_component.js.coffee +63 -0
  6. data/app/assets/javascripts/voluntary_brainstorming/components/brainstorming_idea_cell_component.js.coffee +34 -0
  7. data/app/assets/javascripts/voluntary_brainstorming/components/brainstorming_idea_vote_component.js.coffee +46 -0
  8. data/app/assets/javascripts/voluntary_brainstorming/controllers/brainstorming_controller.js.coffee +79 -0
  9. data/app/assets/javascripts/voluntary_brainstorming/controllers/user_brainstormings_controller.js.coffee +5 -0
  10. data/app/assets/javascripts/voluntary_brainstorming/mixins/destroy_brainstorming.js.coffee +14 -0
  11. data/app/assets/javascripts/voluntary_brainstorming/mixins/pagination_controller.js.coffee +43 -0
  12. data/app/assets/javascripts/voluntary_brainstorming/models/brainstorming.js.coffee +6 -0
  13. data/app/assets/javascripts/voluntary_brainstorming/models/user.js.coffee +18 -0
  14. data/app/assets/javascripts/voluntary_brainstorming/router.js.coffee +9 -0
  15. data/app/assets/javascripts/voluntary_brainstorming/routes/brainstorming_route.js.coffee +37 -0
  16. data/app/assets/javascripts/voluntary_brainstorming/routes/edit_brainstorming_route.js.coffee +16 -0
  17. data/app/assets/javascripts/voluntary_brainstorming/routes/index_route.js.coffee +4 -0
  18. data/app/assets/javascripts/voluntary_brainstorming/routes/new_brainstorming_route.js.coffee +5 -0
  19. data/app/assets/javascripts/voluntary_brainstorming/routes/user_brainstormings_route.js.coffee +20 -0
  20. data/app/assets/javascripts/voluntary_brainstorming/templates/application.handlebars.erb +20 -0
  21. data/app/assets/javascripts/voluntary_brainstorming/templates/brainstorming.js.handlebars +77 -0
  22. data/app/assets/javascripts/voluntary_brainstorming/templates/brainstorming_form.js.handlebars +18 -0
  23. data/app/assets/javascripts/voluntary_brainstorming/templates/brainstorming_idea_form.js.handlebars +19 -0
  24. data/app/assets/javascripts/voluntary_brainstorming/templates/components/brainstorming-idea-argument.js.handlebars +86 -0
  25. data/app/assets/javascripts/voluntary_brainstorming/templates/components/brainstorming-idea-cell.js.handlebars +7 -0
  26. data/app/assets/javascripts/voluntary_brainstorming/templates/components/brainstorming-idea-vote.js.handlebars +6 -0
  27. data/app/assets/javascripts/voluntary_brainstorming/templates/edit_brainstorming.js.handlebars +3 -0
  28. data/app/assets/javascripts/voluntary_brainstorming/templates/navigation.js.handlebars +28 -0
  29. data/app/assets/javascripts/voluntary_brainstorming/templates/new_brainstorming.js.handlebars +3 -0
  30. data/app/assets/javascripts/voluntary_brainstorming/templates/shared/_pagination.js.handlebars +23 -0
  31. data/app/assets/javascripts/voluntary_brainstorming/templates/user_brainstormings.js.handlebars +33 -0
  32. data/app/assets/stylesheets/voluntary_brainstorming/application.css +13 -0
  33. data/app/controllers/product/brainstorming_controller.rb +16 -0
  34. data/app/controllers/voluntary/api/v1/brainstorming_idea_votes_controller.rb +38 -0
  35. data/app/controllers/voluntary/api/v1/brainstorming_ideas_controller.rb +66 -0
  36. data/app/controllers/voluntary/api/v1/brainstormings_controller.rb +70 -0
  37. data/app/models/brainstorming.rb +18 -0
  38. data/app/models/brainstorming_idea.rb +53 -0
  39. data/app/models/brainstorming_idea_vote.rb +32 -0
  40. data/app/models/product/brainstorming.rb +2 -0
  41. data/app/serializers/brainstorming_idea_serializer.rb +15 -0
  42. data/app/serializers/brainstorming_idea_vote_serializer.rb +11 -0
  43. data/app/serializers/brainstorming_serializer.rb +7 -0
  44. data/app/views/product/brainstorming/index.html.erb +0 -0
  45. data/config/locales/resources/brainstorming/en.yml +26 -0
  46. data/config/locales/resources/brainstorming_idea_votes/en.yml +18 -0
  47. data/config/locales/resources/brainstorming_ideas/en.yml +31 -0
  48. data/config/routes.rb +9 -0
  49. data/db/migrate/20150818181847_add_brainstorming_product.rb +51 -0
  50. data/lib/voluntary_brainstorming.rb +5 -1
  51. data/lib/voluntary_brainstorming/concerns/model/argument/publishes_changes_to_brainstorming.rb +49 -0
  52. data/lib/voluntary_brainstorming/concerns/model/user/has_brainstormings.rb +17 -0
  53. data/lib/voluntary_brainstorming/engine.rb +13 -0
  54. data/lib/voluntary_brainstorming/version.rb +1 -1
  55. metadata +322 -37
  56. data/MIT-LICENSE +0 -20
@@ -0,0 +1,70 @@
1
+ class Voluntary::Api::V1::BrainstormingsController < ActionController::Base
2
+ include Voluntary::V1::BaseController
3
+
4
+ respond_to :json
5
+
6
+ def index
7
+ options = {}
8
+
9
+ user = User.friendly.find params[:user_slug]
10
+ collection = user.brainstormings
11
+ options[:json] = collection.paginate page: params[:page], per_page: 10
12
+
13
+ options[:meta] = {
14
+ pagination: {
15
+ total_pages: options[:json].total_pages, current_page: options[:json].current_page,
16
+ previous_page: options[:json].previous_page, next_page: options[:json].next_page
17
+ }
18
+ }
19
+
20
+ respond_with do |format|
21
+ format.json { render options }
22
+ end
23
+ end
24
+
25
+ def show
26
+ user = User.friendly.find(params[:user_slug])
27
+
28
+ respond_to do |format|
29
+ format.json do
30
+ render json: user.brainstormings.friendly.find(params[:id])
31
+ end
32
+ end
33
+ end
34
+
35
+ def create
36
+ brainstorming = current_user.brainstormings.create params[:brainstorming]
37
+
38
+ respond_to do |format|
39
+ format.json do
40
+ render json: brainstorming.persisted? ? brainstorming : { errors: brainstorming.errors.to_hash }
41
+ end
42
+ end
43
+ end
44
+
45
+ def update
46
+ brainstorming = current_user.brainstormings.friendly.find params[:id]
47
+ brainstorming.update_attributes params[:brainstorming]
48
+
49
+ respond_to do |format|
50
+ format.json do
51
+ render json: brainstorming.valid? ? brainstorming : { errors: brainstorming.errors.to_hash }
52
+ end
53
+ end
54
+ end
55
+
56
+ def destroy
57
+ brainstorming = current_user.brainstormings.friendly.find params[:id]
58
+ brainstorming.destroy
59
+
60
+ respond_to do |format|
61
+ format.json do
62
+ render json: if brainstorming.persisted?
63
+ { error: I18n.t('activerecord.errors.models.brainstorming.attributes.base.deletion_failed') }
64
+ else
65
+ {}
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,18 @@
1
+ class Brainstorming < ActiveRecord::Base
2
+ extend FriendlyId
3
+
4
+ belongs_to :user
5
+
6
+ has_many :ideas, class_name: 'BrainstormingIdea', dependent: :destroy
7
+
8
+ friendly_id :name, use: :scoped, scope: :user
9
+
10
+ attr_accessible :name, :text
11
+
12
+ validates :user_id, presence: true
13
+ validates :name, presence: true, uniqueness: { scope: :user_id }
14
+
15
+ def should_generate_new_friendly_id?
16
+ slug.blank? || name_changed?
17
+ end
18
+ end
@@ -0,0 +1,53 @@
1
+ class BrainstormingIdea < ActiveRecord::Base
2
+ belongs_to :brainstorming
3
+ belongs_to :user
4
+
5
+ has_many :arguments, as: :argumentable, dependent: :destroy
6
+ has_many :votes, class_name: 'BrainstormingIdeaVote', dependent: :destroy, foreign_key: 'idea_id'
7
+
8
+ scope :with_current_user_vote, ->(user_id) do
9
+ select('brainstorming_ideas.*, brainstorming_idea_votes.user_id').joins(
10
+ 'LEFT JOIN brainstorming_idea_votes ON brainstorming_idea_votes.idea_id = brainstorming_ideas.id AND ' +
11
+ "brainstorming_idea_votes.user_id = #{sanitize(user_id)}"
12
+ )
13
+ end
14
+
15
+ validates :brainstorming_id, presence: true
16
+ validates :user_id, presence: true
17
+ validates :name, presence: true, uniqueness: { scope: :brainstorming_id }
18
+
19
+ attr_accessible :brainstorming_id, :name, :text
20
+
21
+ after_create :publish_create
22
+ after_update :publish_update
23
+ after_destroy :publish_destroy
24
+
25
+ private
26
+
27
+ def publish_create
28
+ return if Rails.env.test? || Rails.env.cucumber?
29
+
30
+ MessageBus.publish(
31
+ "/brainstormings/#{brainstorming.slug}",
32
+ { message: "#{I18n.t('brainstorming_ideas.model.publish_create')}: #{name}" }
33
+ )
34
+ end
35
+
36
+ def publish_update
37
+ return if Rails.env.test? || Rails.env.cucumber?
38
+
39
+ MessageBus.publish(
40
+ "/brainstormings/#{brainstorming.slug}",
41
+ { message: "#{I18n.t('brainstorming_ideas.model.publish_update')}: #{name}" }
42
+ )
43
+ end
44
+
45
+ def publish_destroy
46
+ return if Rails.env.test? || Rails.env.cucumber?
47
+
48
+ MessageBus.publish(
49
+ "/brainstormings/#{brainstorming.slug}",
50
+ { message: "#{I18n.t('brainstorming_ideas.model.publish_destroy')}: #{name}" }
51
+ )
52
+ end
53
+ end
@@ -0,0 +1,32 @@
1
+ class BrainstormingIdeaVote < ActiveRecord::Base
2
+ belongs_to :idea, class_name: 'BrainstormingIdea', counter_cache: 'votes_count'
3
+ belongs_to :user
4
+
5
+ validates :idea_id, presence: true
6
+ validates :user_id, presence: true, uniqueness: { scope: :idea_id }
7
+
8
+ attr_accessible :idea_id
9
+
10
+ after_create :publish_create
11
+ after_destroy :publish_destroy
12
+
13
+ private
14
+
15
+ def publish_create
16
+ return if Rails.env.test? || Rails.env.cucumber?
17
+
18
+ MessageBus.publish(
19
+ "/brainstormings/#{idea.brainstorming.slug}",
20
+ { message: "#{I18n.t('brainstorming_idea_votes.model.publish_create')}: +1 #{idea.name} by #{user.name}" }
21
+ )
22
+ end
23
+
24
+ def publish_destroy
25
+ return if Rails.env.test? || Rails.env.cucumber?
26
+
27
+ MessageBus.publish(
28
+ "/brainstormings/#{idea.brainstorming.slug}",
29
+ { message: "#{I18n.t('brainstorming_idea_votes.model.publish_destroy')}: -1 #{idea.name} by #{user.name}" }
30
+ )
31
+ end
32
+ end
@@ -0,0 +1,2 @@
1
+ class Product::Brainstorming < ::Product
2
+ end
@@ -0,0 +1,15 @@
1
+ class BrainstormingIdeaSerializer < ActiveModel::Serializer
2
+ attributes :id, :user_id, :user_slug, :user_name, :name, :text, :arguments, :votes_count
3
+
4
+ def user_slug
5
+ object.user.try(:slug)
6
+ end
7
+
8
+ def user_name
9
+ object.user.try(:name)
10
+ end
11
+
12
+ def arguments
13
+ object.arguments.map{|a| ArgumentSerializer.new(a)}
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ class BrainstormingIdeaVoteSerializer < ActiveModel::Serializer
2
+ attributes :id, :idea_id, :user_id, :user_slug, :user_name
3
+
4
+ def user_slug
5
+ object.user.try(:slug)
6
+ end
7
+
8
+ def user_name
9
+ object.user.try(:name)
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ class BrainstormingSerializer < ActiveModel::Serializer
2
+ attributes :id, :user_id, :user_slug, :name, :slug, :text
3
+
4
+ def user_slug
5
+ object.user.try(:slug)
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ en:
2
+ brainstormings:
3
+ index:
4
+ title: Brainstormings
5
+ your: Your brainstormings
6
+ empty_collection: No brainstormings found.
7
+ new:
8
+ title: New Brainstorming
9
+ edit:
10
+ title: Edit Brainstorming
11
+ save:
12
+ failed: Something went wrong at saving brainstorming
13
+ successful: Successfully saved brainstorming.
14
+
15
+ create:
16
+ title: Create Brainstorming
17
+ update:
18
+ title: Update Brainstorming
19
+
20
+ activerecord:
21
+ errors:
22
+ models:
23
+ brainstorming:
24
+ attributes:
25
+ base:
26
+ deletion_failed: Brainstorming could not be deleted!
@@ -0,0 +1,18 @@
1
+ en:
2
+ brainstorming_idea_votes:
3
+ create:
4
+ failed: Something went wrong at creating vote
5
+ successfully: Successfully voted idea.
6
+ destroy:
7
+ successful: Successfully removed vote.
8
+ model:
9
+ publish_create: A vote for an idea has been created
10
+ publish_destroy: A vote for an idea has been removed
11
+
12
+ activerecord:
13
+ errors:
14
+ models:
15
+ brainstorming_idea_vote:
16
+ attributes:
17
+ base:
18
+ deletion_failed: Vote could not be removed!
@@ -0,0 +1,31 @@
1
+ en:
2
+ brainstorming_ideas:
3
+ index:
4
+ empty_collection: No ideas found.
5
+ new:
6
+ title: New Idea
7
+ save:
8
+ failed: Something went wrong at saving idea
9
+ successful: Successfully saved idea.
10
+ create:
11
+ title: Create Idea
12
+ update:
13
+ title: Update Idea
14
+ destroy:
15
+ failed: Removing idea failed!
16
+ model:
17
+ publish_create: A new idea has been added
18
+ publish_update: An idea has been updated
19
+ publish_destroy: An idea has been removed
20
+
21
+ activerecord:
22
+ errors:
23
+ models:
24
+ brainstorming_idea:
25
+ attributes:
26
+ base:
27
+ deletion_failed: Brainstorming idea could not be deleted!
28
+
29
+ models:
30
+ brainstorming_idea: Brainstorming Idea
31
+ brainstorming_idea_short: Idea
@@ -1,2 +1,11 @@
1
1
  Rails.application.routes.draw do
2
+ get '/products/brainstorming' => 'product/brainstorming#index'
3
+
4
+ namespace :voluntary, path: 'api', module: 'voluntary/api', defaults: {format: 'json'} do
5
+ namespace :v1 do
6
+ resources :brainstormings, only: [:index, :create, :show, :update, :destroy]
7
+ resources :brainstorming_ideas, only: [:index, :create, :update, :destroy]
8
+ resources :brainstorming_idea_votes, only: [:index, :create, :destroy]
9
+ end
10
+ end
2
11
  end
@@ -0,0 +1,51 @@
1
+ class AddBrainstormingProduct < ActiveRecord::Migration
2
+ def up
3
+ if Product::Brainstorming.first
4
+ else
5
+ Product::Brainstorming.create(name: 'Brainstorming', text: 'Dummy')
6
+ end
7
+
8
+ create_table :brainstormings, force: true do |t|
9
+ t.integer :user_id
10
+ t.string :name
11
+ t.string :slug
12
+ t.text :text
13
+ t.timestamps
14
+ end
15
+
16
+ add_index :brainstormings, :user_id
17
+ add_index :brainstormings, [:slug, :user_id], unique: true
18
+
19
+ create_table :brainstorming_ideas, force: true do |t|
20
+ t.integer :brainstorming_id
21
+ t.integer :user_id
22
+ t.string :name
23
+ t.text :text
24
+ t.integer :votes_count, default: 0
25
+ t.timestamps
26
+ end
27
+
28
+ add_index :brainstorming_ideas, :user_id
29
+ add_index :brainstorming_ideas, [:brainstorming_id, :name], unique: true
30
+
31
+ create_table :brainstorming_idea_votes, force: true do |t|
32
+ t.integer :idea_id
33
+ t.integer :user_id
34
+ t.timestamps
35
+ end
36
+
37
+ add_index :brainstorming_idea_votes, :idea_id
38
+ add_index :brainstorming_idea_votes, :user_id
39
+ add_index :brainstorming_idea_votes, [:idea_id, :user_id], unique: true
40
+ end
41
+
42
+ def down
43
+ if product = Product::Brainstorming.first
44
+ product.destroy
45
+ end
46
+
47
+ drop_table :brainstormings
48
+ drop_table :brainstorming_ideas
49
+ drop_table :brainstorming_idea_votes
50
+ end
51
+ end
@@ -1,4 +1,8 @@
1
- require "voluntary_brainstorming/engine"
1
+ require 'voluntary'
2
+
3
+ require 'message_bus'
4
+
5
+ require 'voluntary_brainstorming/engine'
2
6
 
3
7
  module VoluntaryBrainstorming
4
8
  end
@@ -0,0 +1,49 @@
1
+ module VoluntaryBrainstorming
2
+ module Concerns
3
+ module Model
4
+ module Argument
5
+ module PublishesChangesToBrainstorming
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ after_create :publish_create_to_brainstorming
10
+ after_update :publish_update_to_brainstorming
11
+ before_destroy :publish_destroy_to_brainstorming
12
+
13
+ private
14
+
15
+ def publish_create_to_brainstorming
16
+ return if Rails.env.test? || Rails.env.cucumber?
17
+ return unless argumentable_type == 'BrainstormingIdea'
18
+
19
+ MessageBus.publish(
20
+ "/brainstormings/#{argumentable.brainstorming.slug}",
21
+ { message: "#{I18n.t('arguments.model.publish_create_to_brainstorming')}: #{topic.name}" }
22
+ )
23
+ end
24
+
25
+ def publish_update_to_brainstorming
26
+ return if Rails.env.test? || Rails.env.cucumber?
27
+ return unless argumentable_type == 'BrainstormingIdea'
28
+
29
+ MessageBus.publish(
30
+ "/brainstormings/#{argumentable.brainstorming.slug}",
31
+ { message: "#{I18n.t('arguments.model.publish_update_to_brainstorming')}: #{topic.name}" }
32
+ )
33
+ end
34
+
35
+ def publish_destroy_to_brainstorming
36
+ return if Rails.env.test? || Rails.env.cucumber?
37
+ return unless argumentable_type == 'BrainstormingIdea'
38
+
39
+ MessageBus.publish(
40
+ "/brainstormings/#{argumentable.brainstorming.slug}",
41
+ { message: "#{I18n.t('arguments.model.publish_destroy_to_brainstorming')}: #{topic.name}" }
42
+ )
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,17 @@
1
+ module VoluntaryBrainstorming
2
+ module Concerns
3
+ module Model
4
+ module User
5
+ module HasBrainstormings
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ has_many :brainstormings
10
+ has_many :brainstorming_ideas
11
+ has_many :brainstorming_idea_votes
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end