refinerycms-sl-snippets 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/app/assets/javascripts/page-snippet-picker.js +121 -0
- data/app/assets/javascripts/part-snippets-select.js +40 -0
- data/app/assets/stylesheets/page-snippet-picker.css +82 -0
- data/app/controllers/refinery/admin/snippets_controller.rb +38 -0
- data/app/controllers/refinery/admin/snippets_page_parts_controller.rb +38 -0
- data/app/models/refinery/snippet.rb +62 -0
- data/app/models/refinery/snippet_page_part.rb +20 -0
- data/app/views/admin/pages/tabs/_snippets_field.html.erb +46 -0
- data/app/views/refinery/admin/pages/tabs/_snippets.html.erb +3 -0
- data/app/views/refinery/admin/pages/tabs/_snippets_content.html.erb +24 -0
- data/app/views/refinery/admin/pages/tabs/_snippets_field.html.erb +55 -0
- data/app/views/refinery/admin/pages/tabs/_snippets_list_item.html.erb +20 -0
- data/app/views/refinery/admin/snippets/_actions.html.erb +28 -0
- data/app/views/refinery/admin/snippets/_form.html.erb +35 -0
- data/app/views/refinery/admin/snippets/_locale_picker.html.erb +12 -0
- data/app/views/refinery/admin/snippets/_records.html.erb +18 -0
- data/app/views/refinery/admin/snippets/_snippet.html.erb +22 -0
- data/app/views/refinery/admin/snippets/_snippets.html.erb +2 -0
- data/app/views/refinery/admin/snippets/_sortable_list.html.erb +7 -0
- data/app/views/refinery/admin/snippets/edit.html.erb +1 -0
- data/app/views/refinery/admin/snippets/index.html.erb +10 -0
- data/app/views/refinery/admin/snippets/new.html.erb +1 -0
- data/app/views/refinery/admin/snippets_page_parts/add.html.erb +1 -0
- data/app/views/refinery/admin/snippets_page_parts/remove.html.erb +1 -0
- data/config/locales/cs.yml +35 -0
- data/config/locales/en.yml +44 -0
- data/config/locales/es.yml +44 -0
- data/config/locales/nl.yml +22 -0
- data/config/routes.rb +18 -0
- data/db/migrate/1_create_snippets.rb +22 -0
- data/db/migrate/2_translate_snippets.rb +20 -0
- data/db/migrate/3_create_snippets_page_parts.rb +22 -0
- data/db/migrate/6_remove_position_from_snippets.rb +12 -0
- data/db/seeds.rb +6 -0
- data/features/manage_snippets.feature +63 -0
- data/features/step_definitions/snippet_steps.rb +14 -0
- data/features/support/paths.rb +17 -0
- data/lib/extensions/application_helper_extensions.rb +39 -0
- data/lib/extensions/page_extensions.rb +22 -0
- data/lib/gemspec.rb +31 -0
- data/lib/generators/refinery/snippets_generator.rb +22 -0
- data/lib/refinery/snippets.rb +29 -0
- data/lib/refinery/snippets/engine.rb +49 -0
- data/lib/refinery/snippets/tabs.rb +22 -0
- data/lib/refinery/snippets/version.rb +5 -0
- data/lib/refinerycms-snippets.rb +1 -0
- data/lib/tasks/snippets.rake +13 -0
- data/readme.md +52 -0
- data/refinerycms-snippets.gemspec +106 -0
- data/spec/helpers/application_helper_spec.rb +43 -0
- data/spec/models/page_spec.rb +39 -0
- data/spec/models/snippet_spec.rb +91 -0
- 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
|
+
|