radiant-concurrent_draft-extension 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/HELP.rdoc +32 -0
  2. data/README.textile +52 -0
  3. data/Rakefile +136 -0
  4. data/VERSION +1 -0
  5. data/app/views/admin/_draft_controls.html.haml +85 -0
  6. data/app/views/admin/_edit_buttons.html.haml +10 -0
  7. data/app/views/admin/layouts/_edit_content.html.haml +5 -0
  8. data/app/views/admin/page_parts/_page_part.html.haml +20 -0
  9. data/app/views/admin/pages/_edit_layout_and_type.html.haml +11 -0
  10. data/app/views/admin/pages/_published_meta.html.haml +4 -0
  11. data/app/views/admin/snippets/_edit_content.html.haml +5 -0
  12. data/app/views/admin/users/_edit_roles.html.haml +26 -0
  13. data/concurrent_draft_extension.rb +30 -0
  14. data/config/initializers/radiant_config.rb +3 -0
  15. data/config/locales/en.yml +11 -0
  16. data/config/routes.rb +9 -0
  17. data/db/migrate/001_update_schemata.rb +29 -0
  18. data/db/migrate/002_create_draft_page_elements.rb +10 -0
  19. data/db/migrate/003_add_publisher_role.rb +9 -0
  20. data/lib/concurrent_draft/admin_controller_extensions.rb +52 -0
  21. data/lib/concurrent_draft/helper_extensions.rb +39 -0
  22. data/lib/concurrent_draft/model_extensions.rb +77 -0
  23. data/lib/concurrent_draft/page_extensions.rb +28 -0
  24. data/lib/concurrent_draft/site_controller_extensions.rb +16 -0
  25. data/lib/concurrent_draft/tags.rb +56 -0
  26. data/lib/tasks/concurrent_draft_extension_tasks.rake +46 -0
  27. data/public/images/admin/cancel.png +0 -0
  28. data/public/images/admin/clock.png +0 -0
  29. data/public/images/admin/page_delete.png +0 -0
  30. data/public/images/admin/page_edit.png +0 -0
  31. data/public/images/admin/page_refresh.png +0 -0
  32. data/public/images/admin/tick.png +0 -0
  33. data/public/javascripts/admin/concurrent_draft.js +72 -0
  34. data/public/stylesheets/admin/concurrent_draft.css +74 -0
  35. data/spec/controllers/admin_controller_extensions_spec.rb +184 -0
  36. data/spec/controllers/site_controller_extensions_spec.rb +31 -0
  37. data/spec/matchers/concurrent_draft_matcher.rb +11 -0
  38. data/spec/models/model_extensions_spec.rb +114 -0
  39. data/spec/models/page_extensions_spec.rb +56 -0
  40. data/spec/models/tags_spec.rb +43 -0
  41. data/spec/spec.opts +6 -0
  42. data/spec/spec_helper.rb +38 -0
  43. data/test/helpers/caching_test_helper.rb +42 -0
  44. data/test/helpers/page_part_test_helper.rb +49 -0
  45. data/test/helpers/page_test_helper.rb +77 -0
  46. data/vendor/plugins/12_hour_time/CHANGELOG +2 -0
  47. data/vendor/plugins/12_hour_time/README +16 -0
  48. data/vendor/plugins/12_hour_time/Rakefile +22 -0
  49. data/vendor/plugins/12_hour_time/init.rb +1 -0
  50. data/vendor/plugins/12_hour_time/lib/12_hour_time.rb +78 -0
  51. data/vendor/plugins/12_hour_time/test/12_hour_time_test.rb +52 -0
  52. data/vendor/plugins/12_hour_time/test/test_helper.rb +3 -0
  53. metadata +143 -0
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe "ConcurrentDraft::Tags" do
4
+ dataset :pages, :snippets
5
+ describe '<r:content>' do
6
+ before :each do
7
+ @page = pages(:home)
8
+ @page.part(:body).update_attribute('draft_content', 'Draft body.')
9
+ end
10
+
11
+ it "should render the published content on the live site" do
12
+ @page.should render('<r:content />').as("Hello world!")
13
+ end
14
+
15
+ it "should render the draft content on the dev site" do
16
+ @page.should render('<r:content />').as("Draft body.").on('dev.host')
17
+ end
18
+ end
19
+
20
+ describe "<r:snippet>" do
21
+ before :each do
22
+ @snippet = snippets(:first)
23
+ @snippet.update_attribute(:draft_content, 'Draft content.')
24
+ @page = pages(:home)
25
+ end
26
+
27
+ it "should render published snippet content on the live site" do
28
+ @page.should render('<r:snippet name="first" />').as('test')
29
+ end
30
+
31
+ it "should render draft snippet content on the dev site" do
32
+ @page.should render('<r:snippet name="first" />').as('Draft content.').on('dev.host')
33
+ end
34
+
35
+ it "should promote the draft body if it is scheduled" do
36
+ @snippet.update_attribute(:draft_promotion_scheduled_at, 1.second.from_now)
37
+ sleep 2
38
+ @page.should render('<r:snippet name="first" />').as('Draft content.')
39
+ @snippet.reload
40
+ @snippet.should be_has_draft_promoted
41
+ end
42
+ end
43
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,6 @@
1
+ --colour
2
+ --format
3
+ progress
4
+ --loadby
5
+ mtime
6
+ --reverse
@@ -0,0 +1,38 @@
1
+ unless defined? RADIANT_ROOT
2
+ ENV["RAILS_ENV"] = "test"
3
+ case
4
+ when ENV["RADIANT_ENV_FILE"]
5
+ require ENV["RADIANT_ENV_FILE"]
6
+ when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
7
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../../")}/config/environment"
8
+ else
9
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../")}/config/environment"
10
+ end
11
+ end
12
+ require "#{RADIANT_ROOT}/spec/spec_helper"
13
+
14
+ Dataset::Resolver.default << (File.dirname(__FILE__) + "/datasets")
15
+ if File.directory?(File.dirname(__FILE__) + "/scenarios")
16
+ Scenario.load_paths.unshift File.dirname(__FILE__) + "/scenarios"
17
+ end
18
+ if File.directory?(File.dirname(__FILE__) + "/matchers")
19
+ Dir[File.dirname(__FILE__) + "/matchers/*.rb"].each {|file| require file }
20
+ end
21
+
22
+ Spec::Runner.configure do |config|
23
+ # config.use_transactional_fixtures = true
24
+ # config.use_instantiated_fixtures = false
25
+ # config.fixture_path = RAILS_ROOT + '/spec/fixtures'
26
+
27
+ # You can declare fixtures for each behaviour like this:
28
+ # describe "...." do
29
+ # fixtures :table_a, :table_b
30
+ #
31
+ # Alternatively, if you prefer to declare them only once, you can
32
+ # do so here, like so ...
33
+ #
34
+ # config.global_fixtures = :table_a, :table_b
35
+ #
36
+ # If you declare global fixtures, be aware that they will be declared
37
+ # for all of your examples, even those that don't use them.
38
+ end
@@ -0,0 +1,42 @@
1
+ class FakeResponseCache
2
+ attr_accessor :expired_path, :expired_paths
3
+
4
+ def initialize
5
+ @expired_paths = []
6
+ @cached_responses = {}
7
+ end
8
+
9
+ def clear
10
+ @cached_responses.clear
11
+ @cleared = true
12
+ end
13
+
14
+ def cache_response(path, response)
15
+ @cached_responses[path] = response
16
+ response
17
+ end
18
+
19
+ def update_response(path, response)
20
+ if r = @cached_response[path]
21
+ response.headers.merge!(r.headers)
22
+ response.body = r.body
23
+ end
24
+ response
25
+ end
26
+
27
+ def expire_response(path)
28
+ @expired_paths << path
29
+ @expired_path = path
30
+ end
31
+
32
+ def response_cached?(path)
33
+ @cached_responses.keys.include?(path)
34
+ end
35
+
36
+ def cleared?
37
+ !!@cleared
38
+ end
39
+ end
40
+
41
+ module CachingTestHelper
42
+ end
@@ -0,0 +1,49 @@
1
+ module PagePartTestHelper
2
+ VALID_PAGE_PART_PARAMS = {
3
+ :name => 'custom',
4
+ :content => 'Some simple content.',
5
+ :page_id => '1'
6
+ }
7
+
8
+ def part_params(options = {})
9
+ params = VALID_PAGE_PART_PARAMS.dup
10
+ params.delete(:page_id)
11
+ params.merge!(:name => @part_name) if @part_name
12
+ params.merge!(options)
13
+ params
14
+ end
15
+
16
+ def destroy_test_part(title = @part_name)
17
+ while part = get_test_part(title) do
18
+ part.destroy
19
+ end
20
+ end
21
+
22
+ def get_test_part(name = @part_name)
23
+ PagePart.find_by_name(name)
24
+ end
25
+
26
+ def create_test_part(name = @part_name)
27
+ params = part_params
28
+ params.merge!(:name => name)
29
+ part = PagePart.new(params)
30
+ if part.save
31
+ part
32
+ else
33
+ raise "part <#{part.inspect}> could not be saved"
34
+ end
35
+ end
36
+
37
+ # must be included after PageTestHelper to work
38
+ def create_test_page(options = {})
39
+ no_part = options.delete(:no_part)
40
+ page = super(options)
41
+ unless no_part
42
+ part = PagePart.new part_params(:name => 'body', :content => 'test')
43
+ page.parts << part
44
+ page.save
45
+ part.save
46
+ end
47
+ page
48
+ end
49
+ end
@@ -0,0 +1,77 @@
1
+ class NoCachePage < Page
2
+ description 'Turns caching off for testing.'
3
+
4
+ def cache?
5
+ false
6
+ end
7
+ end
8
+
9
+ class CustomFileNotFoundPage < FileNotFoundPage
10
+ end
11
+
12
+ class TestPage < Page
13
+ description 'this is just a test page'
14
+
15
+ tag 'test1' do
16
+ 'Hello world!'
17
+ end
18
+
19
+ tag 'test2' do
20
+ 'Another test.'
21
+ end
22
+
23
+ def headers
24
+ {
25
+ 'cool' => 'beans',
26
+ 'request' => @request.inspect[20..30],
27
+ 'response' => @response.inspect[20..31]
28
+ }
29
+ end
30
+
31
+ end
32
+
33
+ class VirtualPage < Page
34
+ def virtual?
35
+ true
36
+ end
37
+ end
38
+
39
+ module PageTestHelper
40
+
41
+ VALID_PAGE_PARAMS = {
42
+ :title => 'New Page',
43
+ :slug => 'page',
44
+ :breadcrumb => 'New Page',
45
+ :status_id => '1',
46
+ :parent_id => nil
47
+ }
48
+
49
+ def page_params(options = {})
50
+ params = VALID_PAGE_PARAMS.dup
51
+ params.merge!(:title => @page_title) if @page_title
52
+ params.merge!(:status_id => '5')
53
+ params.merge!(options)
54
+ end
55
+
56
+ def destroy_test_page(title = @page_title)
57
+ while page = get_test_page(title) do
58
+ page.destroy
59
+ end
60
+ end
61
+
62
+ def get_test_page(title = @page_title)
63
+ Page.find_by_title(title)
64
+ end
65
+
66
+ def create_test_page(options = {})
67
+ options[:title] ||= @page_title
68
+ klass = options.delete(:class_name) || Page
69
+ klass = Kernel.eval(klass) if klass.kind_of? String
70
+ page = klass.new page_params(options)
71
+ if page.save
72
+ page
73
+ else
74
+ raise "page <#{page.inspect}> could not be saved"
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,2 @@
1
+ Fri Dec 28 16:40:43 PST 2007
2
+ - Fixed handling of 00:00 and added test
@@ -0,0 +1,16 @@
1
+ 12-HOUR TIME PLUGIN
2
+
3
+ Not all of us are adept at those exotic, 24-hour clocks. So for the rest of us,
4
+ here's a simple plugin that tacks on an AM/PM selector to the DateHelper
5
+ methods. It also handles the backend, so things are properly stored in 24-hour
6
+ format.
7
+
8
+ USAGE:
9
+
10
+ <%= time_select 'event', 'time', {:twelve_hour => true} %>
11
+
12
+ Authors: Nick Muerdter (original code)
13
+ Maurice Aubrey <maurice.aubrey+12hour@gmail.com>
14
+
15
+ Homepage:
16
+ http://code.google.com/p/rails-twelve-hour-time-plugin/
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the 12_hour_time plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the 12_hour_time plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = '12-Hour Time'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
@@ -0,0 +1 @@
1
+ require "12_hour_time"
@@ -0,0 +1,78 @@
1
+ class ActiveRecord::Base
2
+ def instantiate_time_object_with_ampm(name, values)
3
+ if values.last < 0
4
+ ampm = values.pop
5
+ if ampm == ActionView::Helpers::DateTimeSelector::AM and values[3] == 12
6
+ values[3] = 0
7
+ elsif ampm == ActionView::Helpers::DateTimeSelector::PM and values[3] != 12
8
+ values[3] += 12
9
+ end
10
+ end
11
+
12
+ instantiate_time_object_without_ampm(name, values)
13
+ end
14
+
15
+ alias_method_chain :instantiate_time_object, :ampm
16
+ end
17
+
18
+ module ActionView::Helpers
19
+ class DateTimeSelector
20
+ POSITION = {
21
+ :year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5,
22
+ :second => 6, :ampm => 7
23
+ }
24
+ # XXX would like to do this, but it's frozen
25
+ # POSITION[:ampm] = 7
26
+
27
+ # We give them negative values so can differentiate between normal
28
+ # date/time values. The way the multi param stuff works, from what I
29
+ # can see, results in a variable number of fields (if you tell it to
30
+ # include seconds, for example). So we expect the AM/PM field, if
31
+ # present, to be last and have a negative value.
32
+ AM = -1
33
+ PM = -2
34
+
35
+ def select_hour_with_ampm
36
+ unless @options[:twelve_hour]
37
+ return select_hour_without_ampm
38
+ end
39
+
40
+ if @options[:use_hidden] || @options[:discard_hour]
41
+ build_hidden(:hour, hour12)
42
+ else
43
+ build_options_and_select(:hour, hour12, :start => 1, :end => 12)
44
+ end
45
+ end
46
+
47
+ alias_method_chain :select_hour, :ampm
48
+
49
+ def select_ampm
50
+ selected = hour < 12 ? AM : PM
51
+
52
+ # XXX i18n?
53
+ label = { AM => 'AM', PM => 'PM' }
54
+ ampm_options = []
55
+ [AM, PM].each do |meridiem|
56
+ option = { :value => meridiem }
57
+ option[:selected] = "selected" if selected == meridiem
58
+ ampm_options << content_tag(:option, label[meridiem], option) + "\n"
59
+ end
60
+ build_select(:ampm, ampm_options.join)
61
+ end
62
+
63
+ private
64
+
65
+ def build_selects_from_types_with_ampm(order)
66
+ order += [:ampm] if @options[:twelve_hour] and !order.include?(:ampm)
67
+ build_selects_from_types_without_ampm(order)
68
+ end
69
+
70
+ alias_method_chain :build_selects_from_types, :ampm
71
+
72
+ def hour12
73
+ h12 = hour % 12
74
+ h12 = 12 if h12 == 0
75
+ return h12
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,52 @@
1
+ # Todo: use assert_seelect? Only avail in edge?
2
+ # http://nubyonrails.com/articles/test-your-helpers
3
+
4
+ require File.join(File.dirname(__FILE__), 'test_helper')
5
+
6
+ class String
7
+ def nstrip
8
+ self.gsub(/\n+/, '')
9
+ end
10
+
11
+ def nstrip!
12
+ self.gsub!(/\n+/, '')
13
+ end
14
+ end
15
+
16
+ class TwelveHourTimeTest < Test::Unit::TestCase
17
+ include ActionView::Helpers::TagHelper
18
+ include ActionView::Helpers::FormTagHelper
19
+ include ActionView::Helpers::FormOptionsHelper
20
+ include ActionView::Helpers::DateHelper
21
+
22
+ def test_24_to_12_hour
23
+ assert_equal(12, _12_hour(0), "12 AM")
24
+ assert_equal(1, _12_hour(1), "1 AM")
25
+ assert_equal(12, _12_hour(12), "12 PM")
26
+ assert_equal(1, _12_hour(13), "1 PM")
27
+ assert_equal(12, _12_hour(24), "12 AM")
28
+ end
29
+
30
+ def test_select_hour_12
31
+ time = Time.parse '2005-07-27 15:03:34'
32
+
33
+ options = options_for_select((1..12).to_a.map { |h| "%02d" % h }, "03")
34
+ expected = select_tag 'date[hour]', options, :id => 'date_hour'
35
+ actual = select_hour time, :twelve_hour => true
36
+ assert_equal(expected.nstrip, actual.nstrip, "12 hour select")
37
+ end
38
+
39
+ def test_select_hour_24
40
+ time = Time.parse '2005-07-27 15:03:34'
41
+
42
+ options = options_for_select((0..23).to_a.map { |h| "%02d" % h }, "15")
43
+ expected = select_tag 'date[hour]', options, :id => 'date_hour'
44
+ expected.nstrip!
45
+
46
+ actual = select_hour time, :twelve_hour => false
47
+ assert_equal(expected, actual.nstrip, "24 hour select, explicit")
48
+
49
+ actual = select_hour time
50
+ assert_equal(expected, actual.nstrip, "24 hour select, default")
51
+ end
52
+ end