spree_grid_faq 0.0.6 → 0.0.7
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/.gitignore +10 -0
- data/.rspec +1 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +226 -0
- data/LICENSE +26 -0
- data/README.md +19 -0
- data/Rakefile +29 -0
- data/Versionfile +6 -0
- data/app/assets/stylesheets/store/spree_grid_faq.css +3 -0
- data/app/controllers/spree/admin/products_decorator.rb +46 -0
- data/app/controllers/spree/admin/questions_controller.rb +25 -0
- data/app/controllers/spree/admin/taxons_decorator.rb +46 -0
- data/app/controllers/spree/questions_controller.rb +28 -0
- data/app/models/spree/product_decorator.rb +3 -0
- data/app/models/spree/question.rb +24 -0
- data/app/models/spree/taxon_decorator.rb +3 -0
- data/app/overrides/grid_faq_admin_tab.rb +4 -0
- data/app/overrides/grid_faq_footer_right.rb +4 -0
- data/app/overrides/grid_faq_product_right_part_wrap.rb +4 -0
- data/app/overrides/grid_faq_taxonomies_sidebar_item.rb +4 -0
- data/app/views/spree/admin/products/_question_product_table.html.erb +23 -0
- data/app/views/spree/admin/products/available_for_question.js.erb +26 -0
- data/app/views/spree/admin/products/remove_for_question.js.erb +1 -0
- data/app/views/spree/admin/products/select_for_question.js.erb +2 -0
- data/app/views/spree/admin/products/selected_for_question.html.erb +40 -0
- data/app/views/spree/admin/questions/_form.html.erb +21 -0
- data/app/views/spree/admin/questions/edit.html.erb +9 -0
- data/app/views/spree/admin/questions/index.html.erb +36 -0
- data/app/views/spree/admin/questions/new.html.erb +7 -0
- data/app/views/spree/admin/shared/_question_tabs.html.erb +24 -0
- data/app/views/spree/admin/taxons/_question_taxon_table.html.erb +23 -0
- data/app/views/spree/admin/taxons/available_for_question.js.erb +26 -0
- data/app/views/spree/admin/taxons/remove_for_question.js.erb +1 -0
- data/app/views/spree/admin/taxons/select_for_question.js.erb +2 -0
- data/app/views/spree/admin/taxons/selected_for_question.html.erb +40 -0
- data/app/views/spree/questions/index.html.haml +14 -0
- data/app/views/spree/questions/index.xml.builder +19 -0
- data/app/views/spree/questions/show.html.haml +15 -0
- data/app/views/spree/shared/_product_faq.html.haml +5 -0
- data/app/views/spree/shared/_taxon_faq.html.erb +10 -0
- data/app/views/spree/shared/_taxon_faq.html.haml +5 -0
- data/config/locales/en.yml +5 -0
- data/config/routes.rb +33 -0
- data/db/migrate/20120526221807_create_spree_questions.rb +12 -0
- data/db/migrate/20120527180748_create_spree_questions_taxons.rb +10 -0
- data/db/migrate/20120527181205_create_spree_products_questions.rb +10 -0
- data/lib/generators/spree_faqs/install/install_generator.rb +24 -0
- data/lib/spree_grid_faq/engine.rb +20 -0
- data/lib/spree_grid_faq/version.rb +3 -0
- data/lib/spree_grid_faq.rb +3 -0
- data/script/rails +7 -0
- data/spec/factories/question_factory.rb +7 -0
- data/spec/requests/questions_spec.rb +57 -0
- data/spec/requests/taxonomies_spec.rb +34 -0
- data/spec/spec_helper.rb +49 -0
- data/spree_grid_faq.gemspec +31 -0
- metadata +74 -18
@@ -0,0 +1,28 @@
|
|
1
|
+
module Spree
|
2
|
+
class QuestionsController < Spree::BaseController
|
3
|
+
|
4
|
+
def index
|
5
|
+
@questions = Question.page(params[:page])
|
6
|
+
raise ActionController::RoutingError.new('No Matching Questions') if not params[:page].nil? and @questions.all.empty?
|
7
|
+
|
8
|
+
@title = 'Frequently Asked Questions'
|
9
|
+
end
|
10
|
+
|
11
|
+
def browse
|
12
|
+
@taxon = Taxon.find_by_permalink!(params[:id])
|
13
|
+
@questions = @taxon.questions.page(params[:page])
|
14
|
+
raise ActionController::RoutingError.new('No Matching Questions') if @questions.all.empty?
|
15
|
+
|
16
|
+
@title = "#{@taxon.name} Frequently Asked Questions"
|
17
|
+
|
18
|
+
render :index
|
19
|
+
end
|
20
|
+
|
21
|
+
def show
|
22
|
+
@question = Question.find_by_slug!(params[:id])
|
23
|
+
|
24
|
+
@title = @question.question
|
25
|
+
@description = @question.description
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Spree
|
2
|
+
class Question < ActiveRecord::Base
|
3
|
+
has_and_belongs_to_many :taxons, :join_table => 'spree_questions_taxons'
|
4
|
+
has_and_belongs_to_many :products, :join_table => 'spree_products_questions'
|
5
|
+
|
6
|
+
attr_accessible :question, :answer, :description
|
7
|
+
|
8
|
+
paginates_per 10
|
9
|
+
|
10
|
+
validates :question, :presence => true, :uniqueness => true
|
11
|
+
validates :slug, :uniqueness => true
|
12
|
+
validates_presence_of :answer
|
13
|
+
|
14
|
+
before_validation do
|
15
|
+
self.slug = question.to_s.to_url(:limit => 64) unless slug
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_param
|
19
|
+
slug
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<table class="index">
|
2
|
+
<thead>
|
3
|
+
<tr data-hook="products_header">
|
4
|
+
<th><%= t(:name) %></th>
|
5
|
+
<th><%= t(:path) %></th>
|
6
|
+
<th></th>
|
7
|
+
</tr>
|
8
|
+
</thead>
|
9
|
+
<tbody>
|
10
|
+
<% products.each do |product| %>
|
11
|
+
<tr id="<%= dom_id(product) %>" data-hook="products_row">
|
12
|
+
<td><%= product.name %></td>
|
13
|
+
<td><%= product_path product %></td>
|
14
|
+
<td class="actions">
|
15
|
+
<%= link_to_delete product, :url => remove_admin_question_product_url(@question, product), :name => icon('delete') + ' ' + t(:remove) %>
|
16
|
+
</td>
|
17
|
+
</tr>
|
18
|
+
<% end %>
|
19
|
+
<% if products.empty? %>
|
20
|
+
<tr data-hook="products_none"><td colspan="3"><%= t(:none) %>.</td></tr>
|
21
|
+
<% end %>
|
22
|
+
</tbody>
|
23
|
+
</table>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<h4><%= t(:available_products) %></h4>
|
2
|
+
<table class="index">
|
3
|
+
<thead>
|
4
|
+
<tr>
|
5
|
+
<th><%= t(:name) %></th>
|
6
|
+
<th><%= t(:path) %></th>
|
7
|
+
<th><%= t(:action) %></th>
|
8
|
+
</tr>
|
9
|
+
</thead>
|
10
|
+
<tbody>
|
11
|
+
<% @products.each do |product| %>
|
12
|
+
<tr id="<%= dom_id(product, :sel) %>">
|
13
|
+
<td><%= product.name %></td>
|
14
|
+
<td><%= product_path product %></td>
|
15
|
+
<td class="actions">
|
16
|
+
<%= link_to icon(:add) + ' ' + t(:select),
|
17
|
+
select_admin_question_product_path(@question, product),
|
18
|
+
:remote => true, :class => 'iconlink' %>
|
19
|
+
</td>
|
20
|
+
</tr>
|
21
|
+
<% end %>
|
22
|
+
<% if @products.empty? %>
|
23
|
+
<tr><td colspan="3"><%= t(:no_match_found) %>.</td></tr>
|
24
|
+
<% end %>
|
25
|
+
</tbody>
|
26
|
+
</table>
|
@@ -0,0 +1 @@
|
|
1
|
+
$("#selected-products").html("<%= escape_javascript(render(:partial => 'question_product_table', :locals => { :products => @products })) %>");
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<%= render :partial => 'spree/admin/shared/question_tabs', :locals => { :current => 'Products' } %>
|
2
|
+
<div id="selected-products" data-hook>
|
3
|
+
<%= render :partial => 'question_product_table', :locals => { :products => @products } %>
|
4
|
+
</div>
|
5
|
+
|
6
|
+
<%= form_tag '#' do %>
|
7
|
+
<%= label_tag nil, t(:search) %>:
|
8
|
+
<input id="searchtext" size="25">
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<%= javascript_tag do %>
|
12
|
+
function search_for_products(){
|
13
|
+
$.ajax({
|
14
|
+
data: {q: $("#searchtext").val() },
|
15
|
+
dataType: 'html',
|
16
|
+
success: function(request){
|
17
|
+
jQuery('#search_hits').html(request);
|
18
|
+
},
|
19
|
+
type: 'POST',
|
20
|
+
url: '<%= available_admin_question_products_url(@question, :format => 'js') %>'
|
21
|
+
});
|
22
|
+
}
|
23
|
+
|
24
|
+
$("#searchtext").keypress(function (e) {
|
25
|
+
if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
|
26
|
+
search_for_products();
|
27
|
+
|
28
|
+
return false;
|
29
|
+
} else {
|
30
|
+
return true;
|
31
|
+
}
|
32
|
+
});
|
33
|
+
|
34
|
+
$("#searchtext").delayedObserver(function() {
|
35
|
+
search_for_products();
|
36
|
+
}, 0.75);
|
37
|
+
<% end %>
|
38
|
+
<br />
|
39
|
+
<div id="search_hits" data-hook></div>
|
40
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<div class="clearfix">
|
2
|
+
<div>
|
3
|
+
<%= f.field_container :question do %>
|
4
|
+
<%= f.label :question %> <span class="required">*</span><br />
|
5
|
+
<%= f.text_field :question, :class => 'fullwidth title' %>
|
6
|
+
<%= f.error_message_on :question %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<%= f.field_container :description do %>
|
10
|
+
<%= f.label :description %> <span class="required">*</span><br />
|
11
|
+
<%= f.text_field :description, :class => 'fullwidth'%>
|
12
|
+
<%= f.error_message_on :description %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<%= f.field_container :answer do %>
|
16
|
+
<%= f.label :answer %> <span class="required">*</span><br />
|
17
|
+
<%= f.text_area :answer, {:class => 'fullwidth'} %>
|
18
|
+
<%= f.error_message_on :answer %>
|
19
|
+
<% end %>
|
20
|
+
</div>
|
21
|
+
</div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<h1><%= t("editing_question") %></h1>
|
2
|
+
<%= render "spree/shared/error_messages", :target => @object %>
|
3
|
+
|
4
|
+
<%= render :partial => 'spree/admin/shared/question_tabs', :locals => { :current => 'Question Details' } %>
|
5
|
+
|
6
|
+
<%= form_for [:admin, @object] do |f| %>
|
7
|
+
<%= render :partial => 'form', :locals => { :f => f } %>
|
8
|
+
<%= render :partial => 'spree/admin/shared/edit_resource_links' %>
|
9
|
+
<% end %>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<div class='toolbar'>
|
2
|
+
<ul class='actions'>
|
3
|
+
<li id="new_product_link">
|
4
|
+
<%= button_link_to t("new_question"), new_object_url, {:icon => 'add'} %>
|
5
|
+
</li>
|
6
|
+
</ul>
|
7
|
+
<br class='clear' />
|
8
|
+
</div>
|
9
|
+
|
10
|
+
<h1><%=t("questions") %></h1>
|
11
|
+
|
12
|
+
<table class="index">
|
13
|
+
<tr>
|
14
|
+
<th><%= Spree::Question.human_attribute_name(:question) %></th>
|
15
|
+
<th><%= Spree::Question.human_attribute_name(:answer) %></th>
|
16
|
+
<th><%= t("action") %></th>
|
17
|
+
</tr>
|
18
|
+
<tbody>
|
19
|
+
<% @questions.each do |question| %>
|
20
|
+
<tr class="<%= cycle('even', 'odd') %>" id="<%= dom_id question %>">
|
21
|
+
<td>
|
22
|
+
<%= question.question %>
|
23
|
+
</td>
|
24
|
+
<td>
|
25
|
+
<%= question.answer %>
|
26
|
+
</td>
|
27
|
+
<td>
|
28
|
+
<%= link_to_edit question %>
|
29
|
+
<%= link_to_delete question %>
|
30
|
+
</td>
|
31
|
+
</tr>
|
32
|
+
<% end %>
|
33
|
+
</tbody>
|
34
|
+
</table>
|
35
|
+
|
36
|
+
<%= paginate @questions %>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<h1><%= t(:editing_question) %></h1>
|
2
|
+
<%= render "spree/shared/error_messages", :target => @question %>
|
3
|
+
|
4
|
+
<%= form_for [:admin, @object] do |f| %>
|
5
|
+
<%= render :partial => 'form', :locals => { :f => f } %>
|
6
|
+
<%= render :partial => 'spree/admin/shared/new_resource_links' %>
|
7
|
+
<% end %>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<h1><%= t(:editing_question) %> “<%= @question.question %>”</h1>
|
2
|
+
|
3
|
+
<% content_for :sidebar do %>
|
4
|
+
|
5
|
+
<h3><%= @question.question %></h3>
|
6
|
+
<br class="clear" />
|
7
|
+
|
8
|
+
<ul class="sidebar question-menu" data-hook="admin_question_tabs">
|
9
|
+
<li<%== ' class="active"' if current == 'Question Details' %>>
|
10
|
+
<%= link_to t(:question_details), edit_admin_question_url(@question) %>
|
11
|
+
</li>
|
12
|
+
|
13
|
+
<li<%== ' class="active"' if current == 'Taxons' %>>
|
14
|
+
<%= link_to t(:taxons), selected_admin_question_taxons_url(@question) %>
|
15
|
+
</li>
|
16
|
+
|
17
|
+
<li<%== ' class="active"' if current == 'Products' %>>
|
18
|
+
<%= link_to t(:products), selected_admin_question_products_url(@question) %>
|
19
|
+
</li>
|
20
|
+
|
21
|
+
</ul>
|
22
|
+
<br class="clear" />
|
23
|
+
|
24
|
+
<% end %>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<table class="index">
|
2
|
+
<thead>
|
3
|
+
<tr data-hook="taxons_header">
|
4
|
+
<th><%= t(:name) %></th>
|
5
|
+
<th><%= t(:path) %></th>
|
6
|
+
<th></th>
|
7
|
+
</tr>
|
8
|
+
</thead>
|
9
|
+
<tbody>
|
10
|
+
<% taxons.each do |taxon| %>
|
11
|
+
<tr id="<%= dom_id(taxon) %>" data-hook="taxons_row">
|
12
|
+
<td><%= taxon.name %></td>
|
13
|
+
<td><%= taxon_path taxon %></td>
|
14
|
+
<td class="actions">
|
15
|
+
<%= link_to_delete taxon, :url => remove_admin_question_taxon_url(@question, taxon), :name => icon('delete') + ' ' + t(:remove) %>
|
16
|
+
</td>
|
17
|
+
</tr>
|
18
|
+
<% end %>
|
19
|
+
<% if taxons.empty? %>
|
20
|
+
<tr data-hook="taxons_none"><td colspan="3"><%= t(:none) %>.</td></tr>
|
21
|
+
<% end %>
|
22
|
+
</tbody>
|
23
|
+
</table>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<h4><%= t(:available_taxons) %></h4>
|
2
|
+
<table class="index">
|
3
|
+
<thead>
|
4
|
+
<tr>
|
5
|
+
<th><%= t(:name) %></th>
|
6
|
+
<th><%= t(:path) %></th>
|
7
|
+
<th><%= t(:action) %></th>
|
8
|
+
</tr>
|
9
|
+
</thead>
|
10
|
+
<tbody>
|
11
|
+
<% @taxons.each do |taxon| %>
|
12
|
+
<tr id="<%= dom_id(taxon, :sel) %>">
|
13
|
+
<td><%= taxon.name %></td>
|
14
|
+
<td><%= taxon_path taxon %></td>
|
15
|
+
<td class="actions">
|
16
|
+
<%= link_to icon(:add) + ' ' + t(:select),
|
17
|
+
select_admin_question_taxon_path(@question, taxon),
|
18
|
+
:remote => true, :class => 'iconlink' %>
|
19
|
+
</td>
|
20
|
+
</tr>
|
21
|
+
<% end %>
|
22
|
+
<% if @taxons.empty? %>
|
23
|
+
<tr><td colspan="3"><%= t(:no_match_found) %>.</td></tr>
|
24
|
+
<% end %>
|
25
|
+
</tbody>
|
26
|
+
</table>
|
@@ -0,0 +1 @@
|
|
1
|
+
$("#selected-taxons").html("<%= escape_javascript(render(:partial => 'question_taxon_table', :locals => { :taxons => @taxons })) %>");
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<%= render :partial => 'spree/admin/shared/question_tabs', :locals => { :current => 'Taxons' } %>
|
2
|
+
<div id="selected-taxons" data-hook>
|
3
|
+
<%= render :partial => 'question_taxon_table', :locals => { :taxons => @taxons } %>
|
4
|
+
</div>
|
5
|
+
|
6
|
+
<%= form_tag '#' do %>
|
7
|
+
<%= label_tag nil, t(:search) %>:
|
8
|
+
<input id="searchtext" size="25">
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<%= javascript_tag do %>
|
12
|
+
function search_for_taxons(){
|
13
|
+
$.ajax({
|
14
|
+
data: {q: $("#searchtext").val() },
|
15
|
+
dataType: 'html',
|
16
|
+
success: function(request){
|
17
|
+
jQuery('#search_hits').html(request);
|
18
|
+
},
|
19
|
+
type: 'POST',
|
20
|
+
url: '<%= available_admin_question_taxons_url(@question, :format => 'js') %>'
|
21
|
+
});
|
22
|
+
}
|
23
|
+
|
24
|
+
$("#searchtext").keypress(function (e) {
|
25
|
+
if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
|
26
|
+
search_for_taxons();
|
27
|
+
|
28
|
+
return false;
|
29
|
+
} else {
|
30
|
+
return true;
|
31
|
+
}
|
32
|
+
});
|
33
|
+
|
34
|
+
$("#searchtext").delayedObserver(function() {
|
35
|
+
search_for_taxons();
|
36
|
+
}, 0.75);
|
37
|
+
<% end %>
|
38
|
+
<br />
|
39
|
+
<div id="search_hits" data-hook></div>
|
40
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
- content_for :sidebar do
|
2
|
+
= render :partial => "spree/shared/taxonomies"
|
3
|
+
- content_for :head do
|
4
|
+
= auto_discovery_link_tag(:rss, spree.questions_path(:format => :xml, :page => nil), {:title => "FAQ Feed" })
|
5
|
+
|
6
|
+
%h1=@title
|
7
|
+
|
8
|
+
#questions_container
|
9
|
+
- @questions.each do |question|
|
10
|
+
= link_to question.question, question
|
11
|
+
%br/
|
12
|
+
= question.description
|
13
|
+
%hr/
|
14
|
+
=paginate @questions
|
@@ -0,0 +1,19 @@
|
|
1
|
+
xml.instruct! :xml, :version => "1.0"
|
2
|
+
xml.rss(:version=>"2.0") do
|
3
|
+
xml.channel do
|
4
|
+
xml.title("#{Spree::Config[:site_name]} FAQ")
|
5
|
+
xml.link(questions_url)
|
6
|
+
xml.description("The latest questions answered by #{Spree::Config[:site_name]}")
|
7
|
+
xml.language('en-us')
|
8
|
+
Spree::Question.order(:created_at).reverse_order.limit(10).each do |question|
|
9
|
+
xml.item do
|
10
|
+
xml.title(question.question)
|
11
|
+
xml.description(question.answer)
|
12
|
+
xml.author('webmaster@alarmgrid.com (AlarmGrid.com)')
|
13
|
+
xml.pubDate(question.created_at.to_s(:rfc822))
|
14
|
+
xml.link(question_url(question))
|
15
|
+
xml.guid(question_url(question))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
%h1=@question.question
|
2
|
+
.answer=@question.answer.html_safe
|
3
|
+
|
4
|
+
- unless @question.products.all.empty?
|
5
|
+
%hr
|
6
|
+
%h2 Related Products
|
7
|
+
%div{:data => {:hook => 'faq_products' } }
|
8
|
+
= render :partial => 'spree/shared/products', :locals => { :products => @question.products }
|
9
|
+
|
10
|
+
- unless @question.taxons.all.empty?
|
11
|
+
%hr
|
12
|
+
%h2 Related Categories
|
13
|
+
%ul
|
14
|
+
- @question.taxons.each do |taxon|
|
15
|
+
%li= link_to taxon.name, seo_url(taxon)
|