trusty-snippets-extension 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/README.md +7 -0
  2. data/Rakefile +109 -0
  3. data/app/controllers/admin/snippets_controller.rb +8 -0
  4. data/app/helpers/admin/snippets_helper.rb +3 -0
  5. data/app/models/snippet.rb +23 -0
  6. data/app/models/snippet_finder.rb +24 -0
  7. data/app/models/snippet_tags.rb +80 -0
  8. data/app/views/admin/snippets/_form.html.haml +29 -0
  9. data/app/views/admin/snippets/_popups.html.haml +4 -0
  10. data/app/views/admin/snippets/edit.html.haml +11 -0
  11. data/app/views/admin/snippets/index.html.haml +33 -0
  12. data/app/views/admin/snippets/new.html.haml +9 -0
  13. data/app/views/admin/snippets/remove.html.haml +17 -0
  14. data/config/initializers/radiant_config.rb +3 -0
  15. data/config/locales/en.yml +16 -0
  16. data/config/routes.rb +8 -0
  17. data/cucumber.yml +1 -0
  18. data/features/admin/configuration.feature +9 -0
  19. data/features/admin/pagination.feature +27 -0
  20. data/features/admin/snippets_management.feature +82 -0
  21. data/features/step_definitions/admin/snippet_steps.rb +25 -0
  22. data/features/support/env.rb +11 -0
  23. data/features/support/paths.rb +22 -0
  24. data/lib/snippets/engine.rb +5 -0
  25. data/lib/tasks/snippets_extension_tasks.rake +47 -0
  26. data/lib/trusty-snippets-extension.rb +8 -0
  27. data/snippets_extension.rb +69 -0
  28. data/spec/ci/before_script +22 -0
  29. data/spec/ci/script +2 -0
  30. data/spec/controllers/admin/snippets_controller_spec.rb +110 -0
  31. data/spec/datasets/snippets_dataset.rb +44 -0
  32. data/spec/fixtures/snippet_template.radius +1 -0
  33. data/spec/lib/radiant/admin_ui_spec.rb +33 -0
  34. data/spec/models/page_spec.rb +81 -0
  35. data/spec/models/snippet_finder_spec.rb +20 -0
  36. data/spec/models/snippet_spec.rb +59 -0
  37. data/spec/models/user_action_observer_spec.rb +25 -0
  38. data/spec/snippets_spec_helper.rb +36 -0
  39. data/spec/spec.opts +6 -0
  40. data/trusty-snippets-extension.gemspec +26 -0
  41. metadata +120 -0
data/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # Snippets
2
+
3
+ Use Snippets as reusable bits of content.
4
+
5
+ This extension was pulled from the original core.
6
+
7
+ Created by Radiant CMS Development Team.
data/Rakefile ADDED
@@ -0,0 +1,109 @@
1
+ # Determine where the RSpec plugin is by loading the boot
2
+ unless defined? RADIANT_ROOT
3
+ ENV["RAILS_ENV"] = "test"
4
+ case
5
+ when ENV["RADIANT_ENV_FILE"]
6
+ require File.dirname(ENV["RADIANT_ENV_FILE"]) + "/boot"
7
+ when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
8
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
9
+ else
10
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
11
+ end
12
+ end
13
+
14
+ require 'rake'
15
+ require 'rdoc/task'
16
+ require 'rake/testtask'
17
+
18
+ rspec_base = File.expand_path(RADIANT_ROOT + '/vendor/plugins/rspec/lib')
19
+ $LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
20
+ require 'spec/rake/spectask'
21
+ require 'cucumber'
22
+ require 'cucumber/rake/task'
23
+
24
+ # Cleanup the RADIANT_ROOT constant so specs will load the environment
25
+ Object.send(:remove_const, :RADIANT_ROOT)
26
+
27
+ extension_root = File.expand_path(File.dirname(__FILE__))
28
+
29
+ task :default => [:spec, :features]
30
+ task :stats => "spec:statsetup"
31
+
32
+ desc "Run all specs in spec directory"
33
+ Spec::Rake::SpecTask.new(:spec) do |t|
34
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
35
+ t.spec_files = FileList['spec/**/*_spec.rb']
36
+ end
37
+
38
+ task :features => 'spec:integration'
39
+
40
+ namespace :spec do
41
+ desc "Run all specs in spec directory with RCov"
42
+ Spec::Rake::SpecTask.new(:rcov) do |t|
43
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
44
+ t.spec_files = FileList['spec/**/*_spec.rb']
45
+ t.rcov = true
46
+ t.rcov_opts = ['--exclude', 'spec', '--rails']
47
+ end
48
+
49
+ desc "Print Specdoc for all specs"
50
+ Spec::Rake::SpecTask.new(:doc) do |t|
51
+ t.spec_opts = ["--format", "specdoc", "--dry-run"]
52
+ t.spec_files = FileList['spec/**/*_spec.rb']
53
+ end
54
+
55
+ [:models, :controllers, :views, :helpers].each do |sub|
56
+ desc "Run the specs under spec/#{sub}"
57
+ Spec::Rake::SpecTask.new(sub) do |t|
58
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
59
+ t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
60
+ end
61
+ end
62
+
63
+ desc "Run the Cucumber features"
64
+ Cucumber::Rake::Task.new(:integration) do |t|
65
+ t.fork = true
66
+ t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'pretty')]
67
+ # t.feature_pattern = "#{extension_root}/features/**/*.feature"
68
+ t.profile = "default"
69
+ end
70
+
71
+ # Setup specs for stats
72
+ task :statsetup do
73
+ require 'code_statistics'
74
+ ::STATS_DIRECTORIES << %w(Model\ specs spec/models)
75
+ ::STATS_DIRECTORIES << %w(View\ specs spec/views)
76
+ ::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
77
+ ::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
78
+ ::CodeStatistics::TEST_TYPES << "Model specs"
79
+ ::CodeStatistics::TEST_TYPES << "View specs"
80
+ ::CodeStatistics::TEST_TYPES << "Controller specs"
81
+ ::CodeStatistics::TEST_TYPES << "Helper specs"
82
+ ::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
83
+ end
84
+
85
+ namespace :db do
86
+ namespace :fixtures do
87
+ desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
88
+ task :load => :environment do
89
+ require 'active_record/fixtures'
90
+ ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
91
+ (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
92
+ Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ desc 'Generate documentation for the snippets extension.'
100
+ RDoc::Task.new(:rdoc) do |rdoc|
101
+ rdoc.rdoc_dir = 'rdoc'
102
+ rdoc.title = 'SnippetsExtension'
103
+ rdoc.options << '--line-numbers' << '--inline-source'
104
+ rdoc.rdoc_files.include('README')
105
+ rdoc.rdoc_files.include('lib/**/*.rb')
106
+ end
107
+
108
+ # Load any custom rakefiles for extension
109
+ Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
@@ -0,0 +1,8 @@
1
+ class Admin::SnippetsController < Admin::ResourceController
2
+ paginate_models
3
+ only_allow_access_to :index, :show, :new, :create, :edit, :update, :remove, :destroy,
4
+ :when => [:designer, :admin],
5
+ :denied_url => { :controller => 'admin/pages', :action => 'index' },
6
+ :denied_message => 'You must have designer privileges to perform this action.'
7
+
8
+ end
@@ -0,0 +1,3 @@
1
+ module Admin::SnippetsHelper
2
+
3
+ end
@@ -0,0 +1,23 @@
1
+ class Snippet < ActiveRecord::Base
2
+
3
+ # Default Order
4
+ default_scope :order => 'name'
5
+
6
+ # Associations
7
+ belongs_to :created_by, :class_name => 'User'
8
+ belongs_to :updated_by, :class_name => 'User'
9
+
10
+ # Validations
11
+ validates_presence_of :name
12
+ validates_length_of :name, :maximum => 100
13
+ validates_length_of :filter_id, :maximum => 25, :allow_nil => true
14
+ validates_format_of :name, :with => %r{^\S*$}
15
+ validates_uniqueness_of :name
16
+
17
+ object_id_attr :filter, TextFilter
18
+
19
+ def after_initialize
20
+ self.filter_id ||= TrustyCms::Config['defaults.snippet.filter'] if new_record?
21
+ end
22
+
23
+ end
@@ -0,0 +1,24 @@
1
+ class SnippetFinder
2
+ class << self
3
+ def find(id)
4
+ find_map('find',id)
5
+ end
6
+
7
+ def find_by_name(name)
8
+ find_map('find_by_name', name)
9
+ end
10
+
11
+ def finder_types
12
+ [SnippetFile, Snippet]
13
+ end
14
+
15
+ private
16
+
17
+ def find_map(meth, *args)
18
+ finder_types.find{|type|
19
+ found = type.send(meth, *args)
20
+ return found if found
21
+ }
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,80 @@
1
+ module SnippetTags
2
+ include TrustyCms::Taggable
3
+
4
+ class TagError < StandardError; end
5
+
6
+ desc %{
7
+ Renders the snippet specified in the @name@ attribute within the context of a page.
8
+
9
+ *Usage:*
10
+
11
+ <pre><code><r:snippet name="snippet_name" /></code></pre>
12
+
13
+ When used as a double tag, the part in between both tags may be used within the
14
+ snippet itself, being substituted in place of @<r:yield/>@.
15
+
16
+ *Usage:*
17
+
18
+ <pre><code><r:snippet name="snippet_name">Lorem ipsum dolor...</r:snippet></code></pre>
19
+ }
20
+ tag 'snippet' do |tag|
21
+ required_attr(tag, 'name')
22
+ name = tag['name']
23
+
24
+ snippet = snippet_cache(name.strip)
25
+
26
+ if snippet
27
+ tag.locals.yield = tag.expand if tag.double?
28
+ tag.globals.page.render_snippet(snippet)
29
+ else
30
+ raise TagError.new("snippet '#{name}' not found")
31
+ end
32
+ end
33
+
34
+ def snippet_cache(name)
35
+ @snippet_cache ||= {}
36
+
37
+ snippet = @snippet_cache[name]
38
+ unless snippet
39
+ snippet = SnippetFinder.find_by_name(name)
40
+ @snippet_cache[name] = snippet
41
+ end
42
+ snippet
43
+ end
44
+ private :snippet_cache
45
+
46
+ desc %{
47
+ Used within a snippet as a placeholder for substitution of child content, when
48
+ the snippet is called as a double tag.
49
+
50
+ *Usage (within a snippet):*
51
+
52
+ <pre><code>
53
+ <div id="outer">
54
+ <p>before</p>
55
+ <r:yield/>
56
+ <p>after</p>
57
+ </div>
58
+ </code></pre>
59
+
60
+ If the above snippet was named "yielding", you could call it from any Page,
61
+ Layout or Snippet as follows:
62
+
63
+ <pre><code><r:snippet name="yielding">Content within</r:snippet></code></pre>
64
+
65
+ Which would output the following:
66
+
67
+ <pre><code>
68
+ <div id="outer">
69
+ <p>before</p>
70
+ Content within
71
+ <p>after</p>
72
+ </div>
73
+ </code></pre>
74
+
75
+ When called in the context of a Page or a Layout, @<r:yield/>@ outputs nothing.
76
+ }
77
+ tag 'yield' do |tag|
78
+ tag.locals.yield
79
+ end
80
+ end
@@ -0,0 +1,29 @@
1
+ = form_for [:admin, @snippet], :html => {'data-onsubmit_status' => onsubmit_status(@snippet)} do |f|
2
+ = f.hidden_field :lock_version
3
+ = render_region :form_top, :locals => {:f => f}
4
+ .form_area
5
+ - render_region :form, :locals => {:f => f} do |form|
6
+ - form.edit_title do
7
+ %p.title
8
+ = f.label :name, t('name')
9
+ = f.text_field :name, :class => 'textbox activate', :maxlength => 100
10
+ - form.edit_content do
11
+ %p.content
12
+ = f.label :content, t('body')
13
+ ~ f.text_area :content, :class => "textarea large", :style => "width: 100%"
14
+ - form.edit_filter do
15
+ .set
16
+ %p
17
+ %span.reference_links
18
+ == #{t('reference')}:
19
+ %span{:id => "tag_reference_link"}
20
+ = link_to t('available_tags'), admin_reference_url(:tags), id: 'tag_reference'
21
+ - render_region :form_bottom, :locals => {:f => f} do |form_bottom|
22
+ - form_bottom.edit_buttons do
23
+ .buttons{:style=>"clear: left"}
24
+ = save_model_button(@snippet)
25
+ = save_model_and_continue_editing_button(@snippet)
26
+ = t('or')
27
+ = link_to t('cancel'), admin_snippets_url
28
+ - form_bottom.edit_timestamp do
29
+ = updated_stamp @snippet
@@ -0,0 +1,4 @@
1
+ - content_for :popups do
2
+ #popup_window
3
+ .outer
4
+ .content
@@ -0,0 +1,11 @@
1
+ - @page_title = @snippet.name + ' ' + t('snippet') + ' - ' + default_page_title
2
+
3
+ - render_region :main do |main|
4
+ - main.edit_header do
5
+ %h1= t('edit_snippet')
6
+ - main.edit_form do
7
+ = render :partial => 'form'
8
+ - main.edit_popups do
9
+ = render :partial => "popups"
10
+
11
+ - content_for 'page_scripts'
@@ -0,0 +1,33 @@
1
+ - @page_title = t('snippets') + ' - ' + default_page_title
2
+
3
+ .outset
4
+ = render_region :top
5
+ %table.index#snippets
6
+ %thead
7
+ %tr
8
+ - render_region :thead do |thead|
9
+ - thead.title_header do
10
+ %th.name= t('snippet')
11
+ - thead.actions_header do
12
+ %th.actions{:style=>"width:9em"}= t('modify')
13
+ %tbody
14
+ - if @snippets.any?
15
+ - @snippets.each do |snippet|
16
+ %tr[snippet]
17
+ - render_region :tbody, :locals => {:snippet => snippet} do |tbody|
18
+ - tbody.title_cell do
19
+ %td.name
20
+ = link_to image('snippet', :alt => '') + ' ' + snippet.name, edit_admin_snippet_url(snippet)
21
+ - tbody.actions_cell do
22
+ %td.actions
23
+ = link_to image('minus') + ' ' + t('remove'), remove_admin_snippet_url(snippet), :class => "action"
24
+ - else
25
+ %tr
26
+ %td.empty{:colspan => admin.snippet.index.tbody.length}= t('no_snippets')
27
+
28
+ - render_region :bottom do |bottom|
29
+ - bottom.new_button do
30
+ #actions
31
+ = pagination_for(@snippets)
32
+ %ul
33
+ %li= link_to image('plus') + " " + t('new_snippet'), new_admin_snippet_url, :class => 'action_button'
@@ -0,0 +1,9 @@
1
+ - render_region :main do |main|
2
+ - main.edit_header do
3
+ %h1= t('new_snippet')
4
+ - main.edit_form do
5
+ = render :partial => 'form'
6
+ - main.edit_popups do
7
+ = render :partial => "popups"
8
+
9
+ - content_for 'page_scripts'
@@ -0,0 +1,17 @@
1
+ %h1= t('remove_snippet')
2
+
3
+ %p
4
+ = t('text.snippets.remove_warning')
5
+
6
+ %table.index#snippets
7
+ %tbody
8
+ %tr.node.level_1
9
+ %td.snippet
10
+ = image('snippet', :alt => "")
11
+ %span.title= @snippet.name
12
+
13
+ = form_for [:admin, @snippet], :html => {:method => :delete, 'data-onsubmit_status'=>"Removing snippet&#8230;"} do
14
+ .buttons
15
+ %input.button{:type=>"submit", :value => t('delete_snippet')}/
16
+ = t('or')
17
+ = link_to t('cancel'), admin_snippets_url
@@ -0,0 +1,3 @@
1
+ if TrustyCms.config_definitions['defaults.snippet.filter'].nil?
2
+ TrustyCms.config.define 'defaults.snippet.filter', :select_from => lambda { TextFilter.descendants.map { |s| s.filter_name }.sort }, :allow_blank => true
3
+ end
@@ -0,0 +1,16 @@
1
+ ---
2
+ en:
3
+ snippet: 'Snippet'
4
+ snippets: 'Snippets'
5
+ config:
6
+ defaults:
7
+ snippet:
8
+ filter: "snippet filter"
9
+ delete_snippet: 'Delete Snippet'
10
+ edit_snippet: 'Edit Snippet'
11
+ new_snippet: 'New Snippet'
12
+ no_snippets: 'No Snippets'
13
+ remove_snippet: 'Remove Snippet'
14
+ text:
15
+ snippets:
16
+ remove_warning: 'Are you sure you want to <strong class="warning">permanently remove</strong> the following snippet?'
data/config/routes.rb ADDED
@@ -0,0 +1,8 @@
1
+ TrustyCms::Application.routes.draw do
2
+ namespace :admin do
3
+
4
+ resources :snippets do
5
+ get :remove, on: :member
6
+ end
7
+ end
8
+ end
data/cucumber.yml ADDED
@@ -0,0 +1 @@
1
+ default: --format progress features --tags ~@proposed,~@in_progress
@@ -0,0 +1,9 @@
1
+ Feature: Rich configuration
2
+ In order to control site delivery
3
+ an administrator
4
+ wants to change the configuration of the site
5
+
6
+ Scenario: Reviewing configuration
7
+ Given I am logged in as "admin"
8
+ And I go to the "configuration" admin page
9
+ Then I should see "Snippet Filter"
@@ -0,0 +1,27 @@
1
+ Feature: Paginating admin views
2
+ In order to reduce load time and page bulk
3
+ a content editor
4
+ wants longer resource lists to be paginated
5
+
6
+ Background:
7
+ Given There are many snippets
8
+ And I am logged in as "designer"
9
+ And I go to the "snippets" admin page
10
+
11
+ Scenario: More snippets than we want to show on one page
12
+ Then I should see "first"
13
+ And I should not see "snippet_50"
14
+ And I should see page 1 of the results
15
+ And I should see pagination controls
16
+ And I should see a depagination link
17
+
18
+ When I follow "2" within "div.pagination"
19
+ Then I should see page 2 of the results
20
+ And I should see "snippet_50"
21
+
22
+ When I follow "show all"
23
+ # Then I should mention the request parameters
24
+ Then I should see all the snippets
25
+ And I should not see pagination controls
26
+ And I should not see a depagination link
27
+