refinerycms-sl-snippets 1.0.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.
Files changed (53) hide show
  1. data/app/assets/javascripts/page-snippet-picker.js +121 -0
  2. data/app/assets/javascripts/part-snippets-select.js +40 -0
  3. data/app/assets/stylesheets/page-snippet-picker.css +82 -0
  4. data/app/controllers/refinery/admin/snippets_controller.rb +38 -0
  5. data/app/controllers/refinery/admin/snippets_page_parts_controller.rb +38 -0
  6. data/app/models/refinery/snippet.rb +62 -0
  7. data/app/models/refinery/snippet_page_part.rb +20 -0
  8. data/app/views/admin/pages/tabs/_snippets_field.html.erb +46 -0
  9. data/app/views/refinery/admin/pages/tabs/_snippets.html.erb +3 -0
  10. data/app/views/refinery/admin/pages/tabs/_snippets_content.html.erb +24 -0
  11. data/app/views/refinery/admin/pages/tabs/_snippets_field.html.erb +55 -0
  12. data/app/views/refinery/admin/pages/tabs/_snippets_list_item.html.erb +20 -0
  13. data/app/views/refinery/admin/snippets/_actions.html.erb +28 -0
  14. data/app/views/refinery/admin/snippets/_form.html.erb +35 -0
  15. data/app/views/refinery/admin/snippets/_locale_picker.html.erb +12 -0
  16. data/app/views/refinery/admin/snippets/_records.html.erb +18 -0
  17. data/app/views/refinery/admin/snippets/_snippet.html.erb +22 -0
  18. data/app/views/refinery/admin/snippets/_snippets.html.erb +2 -0
  19. data/app/views/refinery/admin/snippets/_sortable_list.html.erb +7 -0
  20. data/app/views/refinery/admin/snippets/edit.html.erb +1 -0
  21. data/app/views/refinery/admin/snippets/index.html.erb +10 -0
  22. data/app/views/refinery/admin/snippets/new.html.erb +1 -0
  23. data/app/views/refinery/admin/snippets_page_parts/add.html.erb +1 -0
  24. data/app/views/refinery/admin/snippets_page_parts/remove.html.erb +1 -0
  25. data/config/locales/cs.yml +35 -0
  26. data/config/locales/en.yml +44 -0
  27. data/config/locales/es.yml +44 -0
  28. data/config/locales/nl.yml +22 -0
  29. data/config/routes.rb +18 -0
  30. data/db/migrate/1_create_snippets.rb +22 -0
  31. data/db/migrate/2_translate_snippets.rb +20 -0
  32. data/db/migrate/3_create_snippets_page_parts.rb +22 -0
  33. data/db/migrate/6_remove_position_from_snippets.rb +12 -0
  34. data/db/seeds.rb +6 -0
  35. data/features/manage_snippets.feature +63 -0
  36. data/features/step_definitions/snippet_steps.rb +14 -0
  37. data/features/support/paths.rb +17 -0
  38. data/lib/extensions/application_helper_extensions.rb +39 -0
  39. data/lib/extensions/page_extensions.rb +22 -0
  40. data/lib/gemspec.rb +31 -0
  41. data/lib/generators/refinery/snippets_generator.rb +22 -0
  42. data/lib/refinery/snippets.rb +29 -0
  43. data/lib/refinery/snippets/engine.rb +49 -0
  44. data/lib/refinery/snippets/tabs.rb +22 -0
  45. data/lib/refinery/snippets/version.rb +5 -0
  46. data/lib/refinerycms-snippets.rb +1 -0
  47. data/lib/tasks/snippets.rake +13 -0
  48. data/readme.md +52 -0
  49. data/refinerycms-snippets.gemspec +106 -0
  50. data/spec/helpers/application_helper_spec.rb +43 -0
  51. data/spec/models/page_spec.rb +39 -0
  52. data/spec/models/snippet_spec.rb +91 -0
  53. metadata +133 -0
@@ -0,0 +1,121 @@
1
+ $(document).ready(function (cms) {
2
+ cms = cms || {};
3
+ cms.plugin = cms.plugin || {};
4
+
5
+ /**
6
+ * Class for handling everything between page and snippets
7
+ */
8
+ cms.plugin.PageSnippet = {
9
+ processing: false,
10
+ content_holder: [], // html wrapper for all stuff
11
+ add_snippet: [], // add snippet anchor
12
+ remove_snippet: [],
13
+
14
+ spinner_on: function () {
15
+ this.processing = true;
16
+ this.content_holder.css({opacity: 0.5});
17
+ },
18
+
19
+ spinner_off: function () {
20
+ this.content_holder.css({opacity: 1});
21
+ this.processing = false;
22
+ },
23
+
24
+ update: function (html) {
25
+ this.clear();
26
+ this.content_holder.html(html);
27
+ this.bind();
28
+ this.spinner_off();
29
+ },
30
+
31
+ add: function (elm) {
32
+ var that = this,
33
+ add_url = $(elm).attr('href');
34
+
35
+ if (!this.processing) {
36
+ this.spinner_on();
37
+ var partId = $('#part-snippets-select').val();
38
+ $.ajax({
39
+ url: add_url,
40
+ type: 'GET',
41
+ dataType: 'html',
42
+ error: function (response) { alert(response); },
43
+ complete: function (e) {
44
+ // console.log(e);
45
+ },
46
+ success: function (response) {
47
+ that.update(response);
48
+ cms.plugin.PartSnippetsSelect.init();
49
+ $('#part-snippets-select').val(partId).change();
50
+ }
51
+ });
52
+ }
53
+ },
54
+
55
+ remove: function (elm) {
56
+ var that = this,
57
+ remove_url = $(elm).attr('href');
58
+
59
+ if (!this.processing) {
60
+ this.spinner_on();
61
+ var partId = $('#part-snippets-select').val();
62
+ // console.log('remove start');
63
+ $.ajax({
64
+ url: remove_url,
65
+ dataType: 'html',
66
+ error: function (response) {
67
+ alert(response);
68
+ },
69
+ complete: function (e) {
70
+ // console.log(e);
71
+ },
72
+ success: function (response) {
73
+ that.update(response);
74
+ cms.plugin.PartSnippetsSelect.init();
75
+ $('#part-snippets-select').val(partId).change();
76
+ }
77
+ });
78
+ }
79
+ },
80
+
81
+ /**
82
+ * Remove event handlers and other smells
83
+ */
84
+ clear: function () {
85
+ // console.log('start clear');
86
+ this.content_holder.find('a').unbind('click');
87
+ this.content_holder.find('a').unbind('mouseout');
88
+ this.content_holder.find('a').unbind('mouseover');
89
+ },
90
+
91
+ /**
92
+ * Bind event handlers and other smells ;-)
93
+ */
94
+ bind: function () {
95
+ var that = this;
96
+ this.add_snippet = this.content_holder.find('a.add-snippet');
97
+ this.remove_snippet = this.content_holder.find('a.remove-snippet');
98
+
99
+ this.add_snippet.click(function (e) {
100
+ e.preventDefault();
101
+ that.add(this);
102
+ return false;
103
+ });
104
+
105
+ this.remove_snippet.click(function (e) {
106
+ e.preventDefault();
107
+ that.remove(this);
108
+ return false;
109
+ });
110
+ },
111
+
112
+ init: function () {
113
+ this.content_holder = $('#page_snippet_picker');
114
+ if (this.content_holder.length > 0) {
115
+ this.bind();
116
+ }
117
+ }
118
+ }
119
+
120
+ cms.plugin.PageSnippet.init();
121
+ });
@@ -0,0 +1,40 @@
1
+ $(document).ready(function (cms) {
2
+ cms = cms || {};
3
+ cms.plugin = cms.plugin || {};
4
+
5
+ /**
6
+ * Generates a drop-down box for changing the displayed page part
7
+ * in the snippets tab in the edit page interface.
8
+ */
9
+ cms.plugin.PartSnippetsSelect = {
10
+
11
+ init: function() {
12
+ $('#part-snippets-menu').html(this.generateWidget());
13
+ this.changeVisiblePart();
14
+ $('#part-snippets-select').change(this.changeVisiblePart);
15
+ },
16
+
17
+ /**
18
+ * Writes the html code for the drop-down box.
19
+ */
20
+ generateWidget: function() {
21
+ select = '<select id="part-snippets-select">';
22
+ $('#part-snippets-menu a').each(function(i,e) {
23
+ select += '<option value="'+$(e).attr('href').split('#',2)[1]+'">'
24
+ select += e.text
25
+ select += '</option>'
26
+ });
27
+ select += '</select>';
28
+ return select;
29
+ },
30
+
31
+ changeVisiblePart: function() {
32
+ $('.part-snippets').css('display', 'none');
33
+ $('#'+$('#part-snippets-select').val()).css('display', 'block');
34
+ },
35
+
36
+ }
37
+
38
+ cms.plugin.PartSnippetsSelect.init();
39
+
40
+ });
@@ -0,0 +1,82 @@
1
+ /*
2
+ Document : page-snippet-picker.css
3
+ Created on : May 16, 2011, 4:41:03 AM
4
+ Author : keram
5
+ Description:
6
+ Styles for snippets administrations
7
+ */
8
+
9
+ a.add-snippet,
10
+ span.add-snippet {
11
+ background-repeat: no-repeat;
12
+ background-position: left center;
13
+ border: none;
14
+ padding-left: 20px;
15
+ }
16
+
17
+ span.add-snippet {
18
+ float: right;
19
+ color: lightGray;
20
+ margin: 3px;
21
+ }
22
+
23
+ .part-snippets ul {
24
+ background: #fff;
25
+ padding: 10px;
26
+ padding-bottom: 0px;
27
+ margin-bottom: 5px;
28
+ }
29
+
30
+ .active-snippets ul {
31
+ margin-bottom: 15px;
32
+ }
33
+
34
+ .inactive-snippets ul {
35
+ background: #fcfcfc;
36
+ }
37
+
38
+ .msg {
39
+ margin: 5px 5px 10px;
40
+ padding: 20px;
41
+ }
42
+
43
+ .msg.alert {
44
+ color: #f66;
45
+ background: #fff;
46
+ }
47
+
48
+ .part-snippets {
49
+ margin-bottom: 5ex;
50
+ }
51
+
52
+ .part-snippets:last-child {
53
+ margin-bottom: 0;
54
+ }
55
+
56
+ #page_snippet_picker div.actions {
57
+ display: inline;
58
+ }
59
+
60
+ #page_snippet_picker span.title {
61
+ line-height: 30px;
62
+ }
63
+
64
+ #part-snippets-menu, .part-snippets {
65
+ margin: 1ex;
66
+ }
67
+
68
+ #part-snippets-menu li {
69
+ display: inline;
70
+ }
71
+
72
+ #part-snippets-select {
73
+ font-weight: bold;
74
+ width: 21%;
75
+ font-size: 16px;
76
+ line-height: 20px;
77
+ }
78
+
79
+ .part-snippets .block {
80
+ border-top: solid 1px #99998B;
81
+ padding-top: 1ex;
82
+ }
@@ -0,0 +1,38 @@
1
+ module ::Refinery
2
+ module Admin
3
+ class SnippetsController < ::Refinery::AdminController
4
+
5
+ crudify :'refinery/snippet', :xhr_paging => true
6
+
7
+ def create
8
+ if (@snippet = Refinery::Snippet.create(params[:snippet])).valid?
9
+ (request.xhr? ? flash.now : flash).notice = t(
10
+ 'refinery.crudify.created',
11
+ :what => "#{@snippet.title}"
12
+ )
13
+
14
+ unless request.xhr?
15
+ redirect_to (params[:continue_editing] =~ /1/ ? refinery.edit_admin_snippet_path(@snippet) : refinery.admin_snippets_url)
16
+ else
17
+ response = Hash.new
18
+ response['redirect'] = refinery.edit_admin_snippet_path(@snippet) if params[:continue_editing]
19
+ render :json => response
20
+ end
21
+
22
+ else
23
+ unless request.xhr?
24
+ render :action => 'new'
25
+ else
26
+ html_snippets = Hash.new
27
+ html_snippets['flash_container'] = render_to_string(:partial => "/shared/admin/error_messages",
28
+ :locals => {
29
+ :object => @snippet,
30
+ :include_object_name => true
31
+ })
32
+ render :json => {'snippets' => html_snippets}
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ module ::Refinery
2
+ module Admin
3
+ class SnippetsPagePartsController < ::Refinery::AdminController
4
+
5
+ def add
6
+ @page = Refinery::Page.find(params[:id])
7
+ @part = Refinery::PagePart.find(params[:part_id])
8
+ @snippet = Refinery::Snippet.find(params[:snippet_id])
9
+ before_body = params[:before_body] == 'true' ? true : false
10
+
11
+ sp = Refinery::SnippetPagePart.new(:page_part => @part, :snippet => @snippet, :before_body => before_body)
12
+
13
+ if sp.save
14
+ flash[:notice] = "Snippet #{@snippet.title} was successfully added."
15
+ end
16
+
17
+ render :layout => false if request.xhr?
18
+ end
19
+
20
+ def remove
21
+ @page = Refinery::Page.find(params[:id])
22
+ @part = Refinery::PagePart.find(params[:part_id])
23
+ @snippet = Refinery::Snippet.find(params[:snippet_id])
24
+ before_body = params[:before_body] == 'true' ? true : false
25
+
26
+ sp = Refinery::SnippetPagePart.where(:page_part_id => @part, :snippet_id => @snippet, :before_body => before_body)
27
+
28
+ removed = sp.first.destroy() unless sp.empty?
29
+
30
+ if removed
31
+ flash[:notice] = "Snippet #{@snippet.title} was successfully removed."
32
+ end
33
+
34
+ render :layout => false if request.xhr?
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,62 @@
1
+ module Refinery
2
+ class Snippet < ActiveRecord::Base
3
+
4
+ TEMPLATES_DIR = "app/views/shared/snippets"
5
+
6
+ attr_protected :id
7
+
8
+ acts_as_indexed :fields => [:title, :body]
9
+
10
+ validates :title, :presence => true, :uniqueness => true
11
+
12
+ translates :body
13
+
14
+ has_many :snippet_page_parts, :dependent => :destroy
15
+ has_many :page_parts, :through => :snippet_page_parts
16
+
17
+ scope :for_page, lambda{ |page|
18
+ raise RuntimeError.new("Couldn't find Snippet for a nil Page") if page.blank?
19
+ joins(:page_parts => :page).where(:refinery_pages => {:id => page.id})
20
+ }
21
+
22
+ scope :before, where(:snippets_page_parts => {:before_body => true})
23
+ scope :after, where(:snippets_page_parts => {:before_body => false})
24
+
25
+ # rejects any snippet that has not been translated to the current
26
+ # locale.
27
+ scope :translated, lambda {
28
+ pages = Arel::Table.new(Refinery::Snippet.table_name)
29
+ translations = Arel::Table.new(Refinery::Snippet.translations_table_name)
30
+
31
+ includes(:translations).where(
32
+ translations[:locale].eq(Globalize.locale)).where(pages[:id].eq(translations[:snippet_id]))
33
+ }
34
+
35
+ def pages
36
+ Refinery::Page.for_snippet(self)
37
+ end
38
+
39
+ def before?(part)
40
+ part.snippets.before.include? self
41
+ end
42
+
43
+ def after?(part)
44
+ part.snippets.after.include? self
45
+ end
46
+
47
+ def template_filename
48
+ filename = self.title.strip.gsub(/[^A-Za-z0-9]/,'_').squeeze('_').downcase
49
+ filename = "_#{filename}" unless filename.start_with?('_')
50
+ "#{filename}.html.erb"
51
+ end
52
+
53
+ def template_path
54
+ File.join(TEMPLATES_DIR, template_filename)
55
+ end
56
+
57
+ def template?
58
+ File.file? template_path
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,20 @@
1
+ module Refinery
2
+ class SnippetPagePart < ActiveRecord::Base
3
+
4
+ self.table_name = 'snippets_page_parts'
5
+
6
+ attr_protected :id
7
+
8
+ delegate :title, :to => :snippet
9
+
10
+ belongs_to :snippet, :foreign_key => :snippet_id
11
+ belongs_to :page_part, :foreign_key => :page_part_id
12
+
13
+ validates_uniqueness_of :snippet_id, :scope => [:page_part_id, :before_body]
14
+
15
+ before_save do |snippet_page_part|
16
+ snippet_page_part.position = (Refinery::SnippetPagePart.where('page_part_id = ?', snippet_page_part.page_part_id).maximum(:position) || -1) + 1
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,46 @@
1
+ <div id="<%= "part-#{part.id}" %>" class="part-snippets">
2
+ <div class="active-snippets block">
3
+ <% if part.snippets.before.any? %>
4
+ <h3><%= t('.before_body') %></h3>
5
+ <ul>
6
+ <%= render :partial => '/admin/pages/tabs/snippets_list_item', :collection => part.snippets.before, :as => :snippet, :locals => {:part => part, :before_body => true} %>
7
+ </ul>
8
+ <% end %>
9
+ <% if part.snippets.after.any? %>
10
+ <h3><%= t('.after_body') %></h3>
11
+ <ul>
12
+ <%= render :partial => '/admin/pages/tabs/snippets_list_item', :collection => part.snippets.after, :as => :snippet, :locals => {:part => part, :before_body => false} %>
13
+ </ul>
14
+ <% end %>
15
+ </div>
16
+ <div class="inactive-snippets block">
17
+ <% inactive_snippets = Snippet.all %>
18
+ <% if inactive_snippets.length > 0 %>
19
+ <h3><%= t('.inactive') %></h3>
20
+ <ul>
21
+ <% inactive_snippets.each do |snippet| %>
22
+ <li class='clearfix record <%= cycle('on', 'on-hover') %>' >
23
+ <span class="title"><%= snippet.title %></span>
24
+ <div class="actions">
25
+ <% unless snippet.after?(part) %>
26
+ <%= link_to t('.add_after_body'), {:controller => 'snippets_page_parts', :action => 'add', :id => @page.id, :snippet_id => snippet.id, :part_id => part.id}, :class => 'add_icon add-snippet' %>
27
+ <% else %>
28
+ <span class="add_icon add-snippet"><%= t('.add_after_body') %></span>
29
+ <% end %>
30
+ <% unless snippet.before?(part) %>
31
+ <%= link_to t('.add_before_body'), {:controller => 'snippets_page_parts', :action => 'add', :id => @page.id, :snippet_id => snippet.id, :part_id => part.id, :before_body => 'true'}, :class => 'add_icon add-snippet' %>
32
+ <% else %>
33
+ <span class="add_icon add-snippet"><%= t('.add_before_body') %></span>
34
+ <% end %>
35
+ </div>
36
+ </li>
37
+ <% end %>
38
+ </ul>
39
+ <% end %>
40
+ </div>
41
+ </div>
42
+
43
+
44
+
45
+
46
+