radiant-concurrent_draft-extension 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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