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.
Files changed (57) hide show
  1. data/.gitignore +10 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +9 -0
  4. data/Gemfile.lock +226 -0
  5. data/LICENSE +26 -0
  6. data/README.md +19 -0
  7. data/Rakefile +29 -0
  8. data/Versionfile +6 -0
  9. data/app/assets/stylesheets/store/spree_grid_faq.css +3 -0
  10. data/app/controllers/spree/admin/products_decorator.rb +46 -0
  11. data/app/controllers/spree/admin/questions_controller.rb +25 -0
  12. data/app/controllers/spree/admin/taxons_decorator.rb +46 -0
  13. data/app/controllers/spree/questions_controller.rb +28 -0
  14. data/app/models/spree/product_decorator.rb +3 -0
  15. data/app/models/spree/question.rb +24 -0
  16. data/app/models/spree/taxon_decorator.rb +3 -0
  17. data/app/overrides/grid_faq_admin_tab.rb +4 -0
  18. data/app/overrides/grid_faq_footer_right.rb +4 -0
  19. data/app/overrides/grid_faq_product_right_part_wrap.rb +4 -0
  20. data/app/overrides/grid_faq_taxonomies_sidebar_item.rb +4 -0
  21. data/app/views/spree/admin/products/_question_product_table.html.erb +23 -0
  22. data/app/views/spree/admin/products/available_for_question.js.erb +26 -0
  23. data/app/views/spree/admin/products/remove_for_question.js.erb +1 -0
  24. data/app/views/spree/admin/products/select_for_question.js.erb +2 -0
  25. data/app/views/spree/admin/products/selected_for_question.html.erb +40 -0
  26. data/app/views/spree/admin/questions/_form.html.erb +21 -0
  27. data/app/views/spree/admin/questions/edit.html.erb +9 -0
  28. data/app/views/spree/admin/questions/index.html.erb +36 -0
  29. data/app/views/spree/admin/questions/new.html.erb +7 -0
  30. data/app/views/spree/admin/shared/_question_tabs.html.erb +24 -0
  31. data/app/views/spree/admin/taxons/_question_taxon_table.html.erb +23 -0
  32. data/app/views/spree/admin/taxons/available_for_question.js.erb +26 -0
  33. data/app/views/spree/admin/taxons/remove_for_question.js.erb +1 -0
  34. data/app/views/spree/admin/taxons/select_for_question.js.erb +2 -0
  35. data/app/views/spree/admin/taxons/selected_for_question.html.erb +40 -0
  36. data/app/views/spree/questions/index.html.haml +14 -0
  37. data/app/views/spree/questions/index.xml.builder +19 -0
  38. data/app/views/spree/questions/show.html.haml +15 -0
  39. data/app/views/spree/shared/_product_faq.html.haml +5 -0
  40. data/app/views/spree/shared/_taxon_faq.html.erb +10 -0
  41. data/app/views/spree/shared/_taxon_faq.html.haml +5 -0
  42. data/config/locales/en.yml +5 -0
  43. data/config/routes.rb +33 -0
  44. data/db/migrate/20120526221807_create_spree_questions.rb +12 -0
  45. data/db/migrate/20120527180748_create_spree_questions_taxons.rb +10 -0
  46. data/db/migrate/20120527181205_create_spree_products_questions.rb +10 -0
  47. data/lib/generators/spree_faqs/install/install_generator.rb +24 -0
  48. data/lib/spree_grid_faq/engine.rb +20 -0
  49. data/lib/spree_grid_faq/version.rb +3 -0
  50. data/lib/spree_grid_faq.rb +3 -0
  51. data/script/rails +7 -0
  52. data/spec/factories/question_factory.rb +7 -0
  53. data/spec/requests/questions_spec.rb +57 -0
  54. data/spec/requests/taxonomies_spec.rb +34 -0
  55. data/spec/spec_helper.rb +49 -0
  56. data/spree_grid_faq.gemspec +31 -0
  57. 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,3 @@
1
+ Spree::Product.class_eval do
2
+ has_and_belongs_to_many :questions, :join_table => 'spree_products_questions'
3
+ 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,3 @@
1
+ Spree::Taxon.class_eval do
2
+ has_and_belongs_to_many :questions, :join_table => 'spree_questions_taxons'
3
+ end
@@ -0,0 +1,4 @@
1
+ Deface::Override.new(:virtual_path => "spree/layouts/admin",
2
+ :name => "grid_faq_admin_tab",
3
+ :insert_bottom => "[data-hook='admin_tabs']",
4
+ :text => "<%= tab(:questions, :taxons) %>")
@@ -0,0 +1,4 @@
1
+ Deface::Override.new(:virtual_path => "spree/layouts/spree_application",
2
+ :name => "grid_faq_footer_right",
3
+ :insert_bottom => "#footer-right[data-hook]",
4
+ :text => "<%= link_to 'FAQ', questions_url %>")
@@ -0,0 +1,4 @@
1
+ Deface::Override.new(:virtual_path => "spree/products/show",
2
+ :name => "grid_faq_product_right_part_wrap",
3
+ :insert_bottom => "[data-hook='product_right_part_wrap']",
4
+ :partial => "spree/shared/product_faq")
@@ -0,0 +1,4 @@
1
+ Deface::Override.new(:virtual_path => "spree/shared/_taxonomies",
2
+ :name => "grid_faq_taxonomies_sidebar_item",
3
+ :insert_bottom => "#taxonomies[class='sidebar-item']",
4
+ :partial => "spree/shared/taxon_faq")
@@ -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,2 @@
1
+ $("#selected-products").html("<%= escape_javascript(render(:partial => 'question_product_table', :locals => { :products => @products })) %>");
2
+ $("#<%= dom_id @product, :sel %>").hide();
@@ -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 %> &nbsp;
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) %> &ldquo;<%= @question.question %>&rdquo;</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,2 @@
1
+ $("#selected-taxons").html("<%= escape_javascript(render(:partial => 'question_taxon_table', :locals => { :taxons => @taxons })) %>");
2
+ $("#<%= dom_id @taxon, :sel %>").hide();
@@ -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)