feature_box 0.8.1
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.
- data/CHANGELOG.rdoc +1 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +107 -0
- data/app/assets/javascripts/feature_box/application.js +39 -0
- data/app/assets/stylesheets/feature_box/application.css.scss +133 -0
- data/app/assets/stylesheets/feature_box/comments.css.scss +41 -0
- data/app/assets/stylesheets/feature_box/mixins.css.scss +37 -0
- data/app/assets/stylesheets/feature_box/suggestions.css.scss +110 -0
- data/app/controllers/feature_box/application_controller.rb +37 -0
- data/app/controllers/feature_box/categories_controller.rb +43 -0
- data/app/controllers/feature_box/comments_controller.rb +46 -0
- data/app/controllers/feature_box/devise/passwords_controller.rb +4 -0
- data/app/controllers/feature_box/devise/redirects.rb +21 -0
- data/app/controllers/feature_box/devise/registrations_controller.rb +4 -0
- data/app/controllers/feature_box/devise/sessions_controller.rb +4 -0
- data/app/controllers/feature_box/home_controller.rb +8 -0
- data/app/controllers/feature_box/suggestions_controller.rb +161 -0
- data/app/controllers/feature_box/users_controller.rb +32 -0
- data/app/helpers/feature_box/application_helper.rb +40 -0
- data/app/mailers/feature_box/devise/mailer.rb +3 -0
- data/app/models/feature_box/ability.rb +25 -0
- data/app/models/feature_box/category.rb +15 -0
- data/app/models/feature_box/comment.rb +15 -0
- data/app/models/feature_box/suggestion.rb +113 -0
- data/app/models/feature_box/user.rb +61 -0
- data/app/models/feature_box/vote.rb +6 -0
- data/app/views/feature_box/categories/_form.html.haml +14 -0
- data/app/views/feature_box/categories/edit.html.haml +3 -0
- data/app/views/feature_box/categories/index.html.haml +26 -0
- data/app/views/feature_box/categories/new.html.haml +3 -0
- data/app/views/feature_box/comments/_comment.html.haml +9 -0
- data/app/views/feature_box/comments/_new.html.haml +9 -0
- data/app/views/feature_box/comments/edit.html.haml +17 -0
- data/app/views/feature_box/comments/index.html.haml +8 -0
- data/app/views/feature_box/devise/_links.html.haml +9 -0
- data/app/views/feature_box/devise/confirmations/new.html.haml +7 -0
- data/app/views/feature_box/devise/mailer/confirmation_instructions.html.haml +4 -0
- data/app/views/feature_box/devise/mailer/reset_password_instructions.html.haml +6 -0
- data/app/views/feature_box/devise/mailer/unlock_instructions.html.haml +5 -0
- data/app/views/feature_box/devise/passwords/edit.html.haml +7 -0
- data/app/views/feature_box/devise/passwords/new.html.haml +5 -0
- data/app/views/feature_box/devise/registrations/edit.html.haml +16 -0
- data/app/views/feature_box/devise/registrations/new.html.haml +8 -0
- data/app/views/feature_box/devise/sessions/new.html.haml +8 -0
- data/app/views/feature_box/shared/_pages_nav.html.haml +6 -0
- data/app/views/feature_box/suggestions/_form.html.haml +30 -0
- data/app/views/feature_box/suggestions/_order_nav.html.haml +6 -0
- data/app/views/feature_box/suggestions/_search.html.haml +4 -0
- data/app/views/feature_box/suggestions/_suggestion.html.haml +31 -0
- data/app/views/feature_box/suggestions/edit.html.haml +3 -0
- data/app/views/feature_box/suggestions/index.html.haml +27 -0
- data/app/views/feature_box/suggestions/new.html.haml +6 -0
- data/app/views/feature_box/suggestions/show.html.haml +2 -0
- data/app/views/feature_box/users/edit.html.haml +14 -0
- data/app/views/feature_box/users/index.html.haml +24 -0
- data/app/views/layouts/feature_box/application.html.haml +81 -0
- data/config/initializers/devise.rb +3 -0
- data/config/routes.rb +35 -0
- data/db/seeds.rb +11 -0
- data/lib/feature_box.rb +72 -0
- data/lib/feature_box/engine.rb +5 -0
- data/lib/feature_box/helpers.rb +49 -0
- data/lib/feature_box/version.rb +3 -0
- data/lib/generators/feature_box/existing_generator.rb +26 -0
- data/lib/generators/feature_box/generator_base.rb +47 -0
- data/lib/generators/feature_box/initializer_generator.rb +14 -0
- data/lib/generators/feature_box/migrations_generator.rb +25 -0
- data/lib/generators/feature_box/standalone_generator.rb +27 -0
- data/lib/generators/feature_box/templates/initializers/initializer.rb +32 -0
- data/lib/generators/feature_box/templates/initializers/new_devise_initializer.rb +8 -0
- data/lib/generators/feature_box/templates/migrations/00_create_feature_box_suggestions.rb +15 -0
- data/lib/generators/feature_box/templates/migrations/01_create_feature_box_categories.rb +9 -0
- data/lib/generators/feature_box/templates/migrations/02_create_feature_box_comments.rb +13 -0
- data/lib/generators/feature_box/templates/migrations/03_create_feature_box_votes.rb +12 -0
- data/lib/generators/feature_box/templates/migrations/04_create_feature_box_users.rb +10 -0
- data/lib/generators/feature_box/templates/migrations/05_add_devise_to_feature_box_users.rb +50 -0
- data/lib/generators/feature_box/templates/migrations/06_add_type_to_{model_name}.rb +5 -0
- data/lib/generators/feature_box/views_generator.rb +14 -0
- data/lib/tasks/feature_box_tasks.rake +9 -0
- data/test/existing-template/application.html.erb +40 -0
- data/test/existing-template/application_helper.rb +11 -0
- data/test/existing-template/index.html.erb +1 -0
- data/test/run-all-tests.sh +7 -0
- data/test/template.rb +29 -0
- data/vendor/assets/stylesheets/bootstrap.min.css +689 -0
- metadata +250 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module FeatureBox
|
|
2
|
+
|
|
3
|
+
class ApplicationController < ActionController::Base
|
|
4
|
+
|
|
5
|
+
protect_from_forgery
|
|
6
|
+
before_filter :retrieve_vars
|
|
7
|
+
#check_authorization
|
|
8
|
+
|
|
9
|
+
rescue_from CanCan::AccessDenied do |exception|
|
|
10
|
+
redirect_to root_path, :alert => exception.message
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def current_ability
|
|
14
|
+
FeatureBox::Ability.new(current_user)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def pages_helper(&code)
|
|
18
|
+
@current_page = (params[:page]==nil)?0:(params[:page].to_i)
|
|
19
|
+
@current_page = @current_page<1?1:@current_page
|
|
20
|
+
limit = Settings.max_suggestions_on_page
|
|
21
|
+
offset=@current_page*limit-limit
|
|
22
|
+
offset=offset<0?0:offset
|
|
23
|
+
|
|
24
|
+
code.call limit, offset
|
|
25
|
+
|
|
26
|
+
@last_page = (@total / limit.to_f).ceil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def retrieve_vars
|
|
30
|
+
@categories = Array [Category.default] + Category.all
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
include FeatureBox::Helpers
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module FeatureBox
|
|
2
|
+
class CategoriesController < FeatureBox::ApplicationController
|
|
3
|
+
load_and_authorize_resource
|
|
4
|
+
|
|
5
|
+
def index
|
|
6
|
+
pages_helper do |limit,offset|
|
|
7
|
+
@real_categories = Category.limit(limit).offset(offset)
|
|
8
|
+
@total = Category.count
|
|
9
|
+
@offset = offset
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def edit
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def create
|
|
20
|
+
@category.name = params[:category][:name]
|
|
21
|
+
if @category.save
|
|
22
|
+
redirect_to categories_path, notice: 'Category was successfully created.'
|
|
23
|
+
else
|
|
24
|
+
render action: "new"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def update
|
|
29
|
+
@category.name = params[:category][:name]
|
|
30
|
+
if @category.save
|
|
31
|
+
redirect_to categories_path, notice: 'Category was successfully updated.'
|
|
32
|
+
else
|
|
33
|
+
render action: "edit"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def destroy
|
|
38
|
+
@category.destroy
|
|
39
|
+
redirect_to categories_path, notice: 'Category was successfully deleted.'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module FeatureBox
|
|
2
|
+
class CommentsController < FeatureBox::ApplicationController
|
|
3
|
+
|
|
4
|
+
load_and_authorize_resource
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def create
|
|
8
|
+
suggestion =Suggestion.find(params["suggestion_id"])
|
|
9
|
+
@comment.text = params["comment"]["text"]
|
|
10
|
+
@comment.user = current_user
|
|
11
|
+
@comment.suggestion = suggestion
|
|
12
|
+
if @comment.save
|
|
13
|
+
redirect_to suggestion, notice: 'Comment was successfully added.'
|
|
14
|
+
else
|
|
15
|
+
redirect_to suggestion, :flash => {
|
|
16
|
+
#TODO: it can be anything, not only empty comment
|
|
17
|
+
:error => 'Comment cannot be empty'
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def edit
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def show
|
|
26
|
+
redirect_to @comment.suggestion
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def update
|
|
30
|
+
@comment.text = params[:comment][:text]
|
|
31
|
+
if @comment.save
|
|
32
|
+
redirect_to @comment.suggestion, notice: 'Comment was successfully updated.'
|
|
33
|
+
else
|
|
34
|
+
render action: "edit"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def destroy
|
|
39
|
+
@comment.destroy
|
|
40
|
+
redirect_to @comment.suggestion, notice: 'Comment was successfully deleted.'
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module FeatureBox
|
|
2
|
+
module Devise
|
|
3
|
+
module Redirects
|
|
4
|
+
def after_sign_in_path_for resource_or_scope
|
|
5
|
+
feature_box.root_path
|
|
6
|
+
end
|
|
7
|
+
def after_sign_out_path_for resource_or_scope
|
|
8
|
+
feature_box.root_path
|
|
9
|
+
end
|
|
10
|
+
def after_sign_up_path_for resource_or_scope
|
|
11
|
+
feature_box.root_path
|
|
12
|
+
end
|
|
13
|
+
def signed_in_root_path resource_or_scope
|
|
14
|
+
feature_box.root_path
|
|
15
|
+
end
|
|
16
|
+
def self.included m
|
|
17
|
+
m.skip_authorization_check
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
module FeatureBox
|
|
2
|
+
class SuggestionsController < FeatureBox::ApplicationController
|
|
3
|
+
load_and_authorize_resource :except => [:my_suggestions, :my_comments, :my_votes, :search, :create, :vote]
|
|
4
|
+
|
|
5
|
+
def index
|
|
6
|
+
authorize! :read, Suggestion
|
|
7
|
+
|
|
8
|
+
redirect = get_and_validate_params
|
|
9
|
+
if redirect != false
|
|
10
|
+
return redirect
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
pages_helper do |limit, offset|
|
|
14
|
+
@suggestions, @total = Suggestion.find_those_with(
|
|
15
|
+
:category =>@active_category,
|
|
16
|
+
:order_type =>@active_order_type,
|
|
17
|
+
:limit => limit,
|
|
18
|
+
:offset => offset
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
@show_search=true
|
|
23
|
+
@show_nav_bar=true
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def search
|
|
27
|
+
authorize! :read, Suggestion
|
|
28
|
+
q="%"+params[:q].to_s+"%"
|
|
29
|
+
limit=Settings.max_suggestions_on_page;
|
|
30
|
+
@suggestions = Suggestion.where("title LIKE ? OR description LIKE ?",q,q).order("created_at DESC").limit(limit)
|
|
31
|
+
@show_search=true
|
|
32
|
+
render action: "index"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def my_suggestions
|
|
36
|
+
impact_helper :suggestions
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def my_votes
|
|
40
|
+
impact_helper :votes
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def my_comments
|
|
44
|
+
impact_helper :comments
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def vote #json method
|
|
49
|
+
@suggestion = Suggestion.find(params[:id])
|
|
50
|
+
authorize! :create, Vote
|
|
51
|
+
if !user_signed_in?
|
|
52
|
+
{
|
|
53
|
+
:error=>"Sign in to vote"
|
|
54
|
+
}
|
|
55
|
+
elsif can?(:read, @suggestion)
|
|
56
|
+
@suggestion.vote current_user
|
|
57
|
+
votes=@suggestion.user_votes current_user
|
|
58
|
+
render :json => {
|
|
59
|
+
:total_votes=>@suggestion.votes.size,
|
|
60
|
+
:user_votes=>votes,
|
|
61
|
+
:votes_left=>current_user.votes_left
|
|
62
|
+
}
|
|
63
|
+
else
|
|
64
|
+
render :json => {
|
|
65
|
+
:error=>"You are not allowed to vote"
|
|
66
|
+
}
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def show
|
|
72
|
+
@active_category = @suggestion.category
|
|
73
|
+
pages_helper do |limit, offset|
|
|
74
|
+
@comments = @suggestion.comments.order("created_at DESC").limit(limit).offset(offset)
|
|
75
|
+
@total = @suggestion.comments.order("created_at DESC").size
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def new
|
|
80
|
+
if current_user.votes_left<=0 then
|
|
81
|
+
return redirect_to suggestions_listing_path, :flash => {
|
|
82
|
+
:error => 'You need at least one vote to add suggestions'
|
|
83
|
+
}
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def edit
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def create
|
|
91
|
+
@suggestion = Suggestion.new
|
|
92
|
+
authorize! :create, @suggestion
|
|
93
|
+
if current_user.votes_left<=0 then
|
|
94
|
+
return redirect_to suggestions_listing_path, :flash => {
|
|
95
|
+
:error => 'You need at least one vote to add suggestions'
|
|
96
|
+
}
|
|
97
|
+
end
|
|
98
|
+
@suggestion.title = params[:suggestion][:title]
|
|
99
|
+
@suggestion.description = params[:suggestion][:description]
|
|
100
|
+
@suggestion.category_id = params[:suggestion][:category_id]
|
|
101
|
+
if current_user.admin?
|
|
102
|
+
@suggestion.status = params[:suggestion][:status]
|
|
103
|
+
end
|
|
104
|
+
@suggestion.user = current_user
|
|
105
|
+
if @suggestion.save
|
|
106
|
+
redirect_to @suggestion, notice: 'Suggestion was successfully created.'
|
|
107
|
+
else
|
|
108
|
+
render action: "new"
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def update
|
|
113
|
+
@suggestion.title = params[:suggestion][:title]
|
|
114
|
+
@suggestion.description = params[:suggestion][:description]
|
|
115
|
+
@suggestion.category_id = params[:suggestion][:category_id]
|
|
116
|
+
if current_user.admin?
|
|
117
|
+
@suggestion.status = params[:suggestion][:status]
|
|
118
|
+
end
|
|
119
|
+
if @suggestion.save
|
|
120
|
+
redirect_to @suggestion, notice: 'Suggestion was successfully updated.'
|
|
121
|
+
else
|
|
122
|
+
render action: "edit"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def destroy
|
|
127
|
+
@suggestion.destroy
|
|
128
|
+
redirect_to suggestions_listing_url, notice: 'Suggestion was successfully deleted.'
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
private #helper methods
|
|
132
|
+
|
|
133
|
+
# helper for my_votes, my_suggestions, my_comments
|
|
134
|
+
def impact_helper type_of_impact
|
|
135
|
+
authorize! :read_protected, Suggestion
|
|
136
|
+
|
|
137
|
+
pages_helper do |limit, offset|
|
|
138
|
+
@suggestions, @total = Suggestion.find_my type_of_impact, :user => current_user, :limit => limit, :offset => offset
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
@show_nav_bar=true
|
|
142
|
+
render action: "index"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def get_and_validate_params
|
|
146
|
+
|
|
147
|
+
@active_category = Category.find_by_name(params[:category]) || if Category.default.name == params[:category] then Category.default end
|
|
148
|
+
@active_order_type = ["newest","most_popular","in_progress","complete"].include?(params[:order])?(params[:order].to_sym):(nil)
|
|
149
|
+
|
|
150
|
+
if(@active_category == nil && @active_order_type == nil)
|
|
151
|
+
return redirect_to suggestions_listing_path(:category=>Category.default.name, :order=>:newest), :flash => flash
|
|
152
|
+
elsif(@active_category == nil)
|
|
153
|
+
return redirect_to suggestions_listing_path(:category=>Category.default.name), :flash => flash
|
|
154
|
+
elsif(@active_order_type == nil)
|
|
155
|
+
return redirect_to suggestions_listing_path(:order=>:newest), :flash => flash
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
return false
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module FeatureBox
|
|
2
|
+
class UsersController < FeatureBox::ApplicationController
|
|
3
|
+
load_and_authorize_resource
|
|
4
|
+
def index
|
|
5
|
+
pages_helper do |limit,offset|
|
|
6
|
+
@users = User.limit(limit).offset(offset)
|
|
7
|
+
@total = User.count
|
|
8
|
+
@offset = offset
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def edit
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def update
|
|
16
|
+
@user.name = params[:user][:name]
|
|
17
|
+
@user.email = params[:user][:email]
|
|
18
|
+
if @user.save
|
|
19
|
+
redirect_to users_path, notice: 'User info was successfully updated.'
|
|
20
|
+
else
|
|
21
|
+
render action: "edit"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def destroy
|
|
26
|
+
@user.destroy
|
|
27
|
+
redirect_to users_path, notice: 'User was successfully deleted.'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module FeatureBox
|
|
2
|
+
module ApplicationHelper
|
|
3
|
+
|
|
4
|
+
def generate_form_element form, name, element
|
|
5
|
+
if name == nil then
|
|
6
|
+
raw '<div class="control-group"><div class="controls">'+element+'</div></div>'
|
|
7
|
+
else
|
|
8
|
+
raw '<div class="control-group">'+form.label(name, :class=>"control-label")+'<div class="controls">'+element+'</div></div>'
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def multiline text
|
|
13
|
+
raw h(text).gsub(/\n/, '<br/>')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def devise_error_messages_any?
|
|
18
|
+
if respond_to? :resource
|
|
19
|
+
return !resource.errors.empty?
|
|
20
|
+
else
|
|
21
|
+
return false
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def devise_error_messages!
|
|
26
|
+
resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join.html_safe
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def devise_router_name
|
|
30
|
+
if controller.class.name =~ /FeatureBox::Devise/
|
|
31
|
+
feature_box
|
|
32
|
+
else
|
|
33
|
+
self
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
include FeatureBox::Helpers
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module FeatureBox
|
|
2
|
+
class Ability
|
|
3
|
+
|
|
4
|
+
include CanCan::Ability
|
|
5
|
+
|
|
6
|
+
def initialize(user)
|
|
7
|
+
user ||= FeatureBox::User.new # guest user (not logged in)
|
|
8
|
+
if user.admin?
|
|
9
|
+
can :read, :all
|
|
10
|
+
can :read_protected, :all # read_protected is for signed in users only
|
|
11
|
+
can :create, :all
|
|
12
|
+
can :update, :all
|
|
13
|
+
can :destroy, :all
|
|
14
|
+
elsif user.id # registered user
|
|
15
|
+
can :read, [Suggestion, Comment]
|
|
16
|
+
can :read_protected, [Suggestion, Comment]
|
|
17
|
+
can :update, [Suggestion, Comment], :user_id => user.id
|
|
18
|
+
can :destroy, [Suggestion, Comment], :user_id => user.id
|
|
19
|
+
can :create, [Suggestion, Comment, Vote]
|
|
20
|
+
else
|
|
21
|
+
can :read, [Suggestion, Comment]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|