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.
- data/HELP.rdoc +32 -0
- data/README.textile +52 -0
- data/Rakefile +136 -0
- data/VERSION +1 -0
- data/app/views/admin/_draft_controls.html.haml +85 -0
- data/app/views/admin/_edit_buttons.html.haml +10 -0
- data/app/views/admin/layouts/_edit_content.html.haml +5 -0
- data/app/views/admin/page_parts/_page_part.html.haml +20 -0
- data/app/views/admin/pages/_edit_layout_and_type.html.haml +11 -0
- data/app/views/admin/pages/_published_meta.html.haml +4 -0
- data/app/views/admin/snippets/_edit_content.html.haml +5 -0
- data/app/views/admin/users/_edit_roles.html.haml +26 -0
- data/concurrent_draft_extension.rb +30 -0
- data/config/initializers/radiant_config.rb +3 -0
- data/config/locales/en.yml +11 -0
- data/config/routes.rb +9 -0
- data/db/migrate/001_update_schemata.rb +29 -0
- data/db/migrate/002_create_draft_page_elements.rb +10 -0
- data/db/migrate/003_add_publisher_role.rb +9 -0
- data/lib/concurrent_draft/admin_controller_extensions.rb +52 -0
- data/lib/concurrent_draft/helper_extensions.rb +39 -0
- data/lib/concurrent_draft/model_extensions.rb +77 -0
- data/lib/concurrent_draft/page_extensions.rb +28 -0
- data/lib/concurrent_draft/site_controller_extensions.rb +16 -0
- data/lib/concurrent_draft/tags.rb +56 -0
- data/lib/tasks/concurrent_draft_extension_tasks.rake +46 -0
- data/public/images/admin/cancel.png +0 -0
- data/public/images/admin/clock.png +0 -0
- data/public/images/admin/page_delete.png +0 -0
- data/public/images/admin/page_edit.png +0 -0
- data/public/images/admin/page_refresh.png +0 -0
- data/public/images/admin/tick.png +0 -0
- data/public/javascripts/admin/concurrent_draft.js +72 -0
- data/public/stylesheets/admin/concurrent_draft.css +74 -0
- data/spec/controllers/admin_controller_extensions_spec.rb +184 -0
- data/spec/controllers/site_controller_extensions_spec.rb +31 -0
- data/spec/matchers/concurrent_draft_matcher.rb +11 -0
- data/spec/models/model_extensions_spec.rb +114 -0
- data/spec/models/page_extensions_spec.rb +56 -0
- data/spec/models/tags_spec.rb +43 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +38 -0
- data/test/helpers/caching_test_helper.rb +42 -0
- data/test/helpers/page_part_test_helper.rb +49 -0
- data/test/helpers/page_test_helper.rb +77 -0
- data/vendor/plugins/12_hour_time/CHANGELOG +2 -0
- data/vendor/plugins/12_hour_time/README +16 -0
- data/vendor/plugins/12_hour_time/Rakefile +22 -0
- data/vendor/plugins/12_hour_time/init.rb +1 -0
- data/vendor/plugins/12_hour_time/lib/12_hour_time.rb +78 -0
- data/vendor/plugins/12_hour_time/test/12_hour_time_test.rb +52 -0
- data/vendor/plugins/12_hour_time/test/test_helper.rb +3 -0
- 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
data/spec/spec_helper.rb
ADDED
@@ -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,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
|