radiant-sheets-extension 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +21 -0
- data/README.md +33 -0
- data/Rakefile +129 -0
- data/app/controllers/admin/scripts_controller.rb +13 -0
- data/app/controllers/admin/sheet_resource_controller.rb +54 -0
- data/app/controllers/admin/styles_controller.rb +13 -0
- data/app/helpers/admin/scripts_helper.rb +5 -0
- data/app/helpers/admin/styles_helper.rb +5 -0
- data/app/models/javascript_page.rb +16 -0
- data/app/models/sheet.rb +93 -0
- data/app/models/stylesheet_page.rb +16 -0
- data/app/views/admin/scripts/edit.html.haml +30 -0
- data/app/views/admin/scripts/index.html.haml +33 -0
- data/app/views/admin/scripts/new.html.haml +30 -0
- data/app/views/admin/sheets/_edit_scripts.html.haml +40 -0
- data/app/views/admin/sheets/_upload_script.html.haml +16 -0
- data/app/views/admin/styles/edit.html.haml +30 -0
- data/app/views/admin/styles/index.html.haml +33 -0
- data/app/views/admin/styles/new.html.haml +30 -0
- data/config/locales/en.yml +17 -0
- data/config/routes.rb +6 -0
- data/cucumber.yml +1 -0
- data/features/admin/managing_javascripts.feature +147 -0
- data/features/admin/managing_stylesheets.feature +108 -0
- data/features/support/env.rb +11 -0
- data/features/support/paths.rb +11 -0
- data/lib/coffee_filter.rb +5 -0
- data/lib/javascript_tags.rb +58 -0
- data/lib/radiant-sheets-extension/version.rb +3 -0
- data/lib/radiant-sheets-extension.rb +2 -0
- data/lib/sass_filter.rb +18 -0
- data/lib/scss_filter.rb +19 -0
- data/lib/stylesheet_tags.rb +61 -0
- data/lib/tasks/sheets_extension_tasks.rake +79 -0
- data/public/images/admin/javascript.png +0 -0
- data/public/images/admin/stylesheet.png +0 -0
- data/radiant-sheets-extension.gemspec +32 -0
- data/sass.html +82 -0
- data/sheets_extension.rb +96 -0
- data/spec/controllers/admin/scripts_controller_spec.rb +123 -0
- data/spec/controllers/admin/styles_controller_spec.rb +124 -0
- data/spec/datasets/javascripts_dataset.rb +15 -0
- data/spec/datasets/stylesheets_dataset.rb +17 -0
- data/spec/helpers/admin/scripts_helper_spec.rb +5 -0
- data/spec/helpers/admin/styles_helper_spec.rb +5 -0
- data/spec/lib/javascript_tags_spec.rb +36 -0
- data/spec/lib/stylesheet_tags_spec.rb +41 -0
- data/spec/models/javascript_page_spec.rb +80 -0
- data/spec/models/page_spec.rb +5 -0
- data/spec/models/stylesheet_page_spec.rb +80 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +36 -0
- metadata +169 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
== MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2010, Jim Gay, Saturn Flyer LLC.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Sheets
|
2
|
+
|
3
|
+
Sheets is a way to manage stylesheets and scripts from your existing page tree. With Sheets, you'll create new types of pages: JavascriptPage and StylesheetPage.
|
4
|
+
|
5
|
+
Pages of these types are Sheets.
|
6
|
+
|
7
|
+
## Features
|
8
|
+
|
9
|
+
The basic features:
|
10
|
+
|
11
|
+
* provide a separate interface for editing CSS and Javascript content
|
12
|
+
* set a longer expire time for Sheet content with `sheet_cache_timeout` (similar to the typical `cache_timeout` set for pages)
|
13
|
+
* hide the JavascriptPage and StylesheetPage nodes from the standard Page index view
|
14
|
+
* provide Radius tags to output content as it is, as a link to content, and as an HTML element containing the content
|
15
|
+
* append a timestamp to sheet content URLs so that the cache need not be cleared with the same frequency for updates to typical pages
|
16
|
+
|
17
|
+
## Differences with other solutions and the benefit of using Sheets
|
18
|
+
|
19
|
+
Some standard site templates provided by Radiant include stylesheet content in a typical page. This requires a custom layout merely to set the content type, and displays content unintended for editing by typical users. This makes for a cluttered page index view and cluttered layout index view.
|
20
|
+
|
21
|
+
A popular solution to these problems is the [SNS extension](http://ext.radiantcms.org/extensions/53-sns). SNS separates the editing interfaces for these types of content, but the problem is that it makes too much of a separation. With SNS, stylesheet and javascript content is stored in a separate table and is generated by models completely unrelated to the Page model. This means that other extensions are *required* to do extra work to provide features and Radius tags to SNS content, and as a result many extensions do not do this work. This situation makes for a confusing introduction to Radiant for new users and developers alike.
|
22
|
+
|
23
|
+
You can get around this SNS limitation by using the [SNS Page Hook extension](http://ext.radiantcms.org/extensions/232-sns-page-hook) but even this solution will lead to unpredictable results because it merely copies modules from the Page model to the TextAsset model and tricks the included methods into believing they are operating on a Page. But this is not a good long-term solution.
|
24
|
+
|
25
|
+
Sheets keeps this content in the same location as all other content: Pages. Doing it this way allows any chosen URL or Page slug to be protected properly with newly created pages. Even more importantly, this allows user and developer expectations about the behavior of Radius tags to make sense. With Sheets, extensions which add Radius tags to the Page model add them to stylesheets and javascripts too; there is no extra work to be done.
|
26
|
+
|
27
|
+
Not only does it do all this, but the standard Page model provides a `headers` method which Sheets overrides to alter the mime-type for the returned content. Sheets uses the built-in ways to serve content, rather than generating yet another way to serve content like SNS.
|
28
|
+
|
29
|
+
## Thanks
|
30
|
+
|
31
|
+
Special thanks goes to Chris Parrish for creating the SNS extension in the first place. And thanks to Dane Harrigan for some early bug checking.
|
32
|
+
|
33
|
+
Built by [Saturn Flyer](http://www.saturnflyer.com)
|
data/Rakefile
ADDED
@@ -0,0 +1,129 @@
|
|
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 'rake/rdoctask'
|
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
|
+
vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
|
25
|
+
$LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
|
26
|
+
|
27
|
+
# Cleanup the RADIANT_ROOT constant so specs will load the environment
|
28
|
+
Object.send(:remove_const, :RADIANT_ROOT)
|
29
|
+
|
30
|
+
extension_root = File.expand_path(File.dirname(__FILE__))
|
31
|
+
|
32
|
+
task :default => [:spec, :cucumber]
|
33
|
+
task :stats => "spec:statsetup"
|
34
|
+
|
35
|
+
desc "Run all specs in spec directory"
|
36
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
37
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
38
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
39
|
+
end
|
40
|
+
|
41
|
+
namespace :spec do
|
42
|
+
desc "Run all specs in spec directory with RCov"
|
43
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
44
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
45
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
46
|
+
t.rcov = true
|
47
|
+
t.rcov_opts = ['--exclude', 'spec', '--rails']
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "Print Specdoc for all specs"
|
51
|
+
Spec::Rake::SpecTask.new(:doc) do |t|
|
52
|
+
t.spec_opts = ["--format", "specdoc", "--dry-run"]
|
53
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
54
|
+
end
|
55
|
+
|
56
|
+
[:models, :controllers, :views, :helpers].each do |sub|
|
57
|
+
desc "Run the specs under spec/#{sub}"
|
58
|
+
Spec::Rake::SpecTask.new(sub) do |t|
|
59
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
60
|
+
t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
desc "Run the Cucumber features"
|
65
|
+
task :integration => 'cucumber:ok'
|
66
|
+
|
67
|
+
# Setup specs for stats
|
68
|
+
task :statsetup do
|
69
|
+
require 'code_statistics'
|
70
|
+
::STATS_DIRECTORIES << %w(Model\ specs spec/models)
|
71
|
+
::STATS_DIRECTORIES << %w(View\ specs spec/views)
|
72
|
+
::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
|
73
|
+
::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
|
74
|
+
::CodeStatistics::TEST_TYPES << "Model specs"
|
75
|
+
::CodeStatistics::TEST_TYPES << "View specs"
|
76
|
+
::CodeStatistics::TEST_TYPES << "Controller specs"
|
77
|
+
::CodeStatistics::TEST_TYPES << "Helper specs"
|
78
|
+
::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
|
79
|
+
end
|
80
|
+
|
81
|
+
namespace :db do
|
82
|
+
namespace :fixtures do
|
83
|
+
desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
|
84
|
+
task :load => :environment do
|
85
|
+
require 'active_record/fixtures'
|
86
|
+
ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
|
87
|
+
(ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
|
88
|
+
Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
namespace :cucumber do
|
96
|
+
Cucumber::Rake::Task.new(:ok, 'Run features that should pass') do |t|
|
97
|
+
t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
|
98
|
+
t.fork = true # You may get faster startup if you set this to false
|
99
|
+
t.profile = 'default'
|
100
|
+
end
|
101
|
+
|
102
|
+
Cucumber::Rake::Task.new(:wip, 'Run features that are being worked on') do |t|
|
103
|
+
t.binary = vendored_cucumber_bin
|
104
|
+
t.fork = true # You may get faster startup if you set this to false
|
105
|
+
t.profile = 'wip'
|
106
|
+
end
|
107
|
+
|
108
|
+
desc 'Run all features'
|
109
|
+
task :all => [:ok, :wip]
|
110
|
+
end
|
111
|
+
|
112
|
+
desc 'Alias for cucumber:ok'
|
113
|
+
task :cucumber => 'cucumber:ok'
|
114
|
+
|
115
|
+
task :features => :cucumber do
|
116
|
+
STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
|
117
|
+
end
|
118
|
+
|
119
|
+
desc 'Generate documentation for the sheets extension.'
|
120
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
121
|
+
rdoc.rdoc_dir = 'rdoc'
|
122
|
+
rdoc.title = 'SheetsExtension'
|
123
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
124
|
+
rdoc.rdoc_files.include('README')
|
125
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
126
|
+
end
|
127
|
+
|
128
|
+
# Load any custom rakefiles for extension
|
129
|
+
Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Admin::ScriptsController < Admin::SheetResourceController
|
2
|
+
model_class JavascriptPage
|
3
|
+
only_allow_access_to :index, :new, :edit, :create, :update, :destroy, :upload,
|
4
|
+
:when => [:designer, :admin],
|
5
|
+
:denied_url => { :controller => 'pages', :action => 'index' },
|
6
|
+
:denied_message => 'You must have developer or administrator privileges to edit javascripts.'
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def edit_model_path
|
11
|
+
edit_admin_script_path(params[:id])
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class Admin::SheetResourceController < Admin::ResourceController
|
2
|
+
paginate_models
|
3
|
+
# only_allow_access_to must be set
|
4
|
+
|
5
|
+
prepend_before_filter :find_root
|
6
|
+
prepend_before_filter :create_root, :only => [:new, :upload]
|
7
|
+
|
8
|
+
def upload
|
9
|
+
if params[:upload].blank? # necessary params are missing
|
10
|
+
render :text => '', :status => :bad_request
|
11
|
+
else
|
12
|
+
@sheet = model_class.create_from_upload!(params[:upload][:upload])
|
13
|
+
response_for :create
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def new
|
18
|
+
self.model = model_class.new_with_defaults
|
19
|
+
response_for :new
|
20
|
+
end
|
21
|
+
|
22
|
+
def create
|
23
|
+
model.parent_id = @root.id
|
24
|
+
model.update_attributes!(params[model_symbol])
|
25
|
+
response_for :create
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def load_models
|
31
|
+
@root.try(:children) || []
|
32
|
+
end
|
33
|
+
|
34
|
+
def find_root
|
35
|
+
@root = model_class.root
|
36
|
+
rescue Page::MissingRootPageError, Sheet::InvalidHomePage => e
|
37
|
+
flash[:error] = t('sheets.root_required', :model => humanized_model_name)
|
38
|
+
redirect_to welcome_path and return false
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_root
|
42
|
+
unless @root
|
43
|
+
s = model_class.new_with_defaults
|
44
|
+
begin
|
45
|
+
s.parent_id = Page.find_by_slug('/').id
|
46
|
+
rescue Page::MissingRootPageError
|
47
|
+
flash[:error] = t('sheets.root_required', :model => humanized_model_name)
|
48
|
+
redirect_to welcome_path and return false
|
49
|
+
end
|
50
|
+
s.slug = model_class == StylesheetPage ? 'css' : 'js'
|
51
|
+
s.save
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Admin::StylesController < Admin::SheetResourceController
|
2
|
+
model_class StylesheetPage
|
3
|
+
only_allow_access_to :index, :new, :edit, :create, :update, :destroy, :upload,
|
4
|
+
:when => [:designer, :admin],
|
5
|
+
:denied_url => { :controller => 'pages', :action => 'index' },
|
6
|
+
:denied_message => 'You must have developer or administrator privileges to edit stylesheets.'
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def edit_model_path
|
11
|
+
edit_admin_style_path(params[:id])
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class JavascriptPage < Page
|
2
|
+
include Sheet::Instance
|
3
|
+
in_menu false
|
4
|
+
|
5
|
+
def headers
|
6
|
+
{'Content-Type' => 'text/javascript'}
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.new_with_defaults(config = Radiant::Config)
|
10
|
+
page = JavascriptPage.new
|
11
|
+
page.parts.concat(self.default_page_parts)
|
12
|
+
page.parent_id = JavascriptPage.root.try(:id)
|
13
|
+
page.status_id = Status[:published].id
|
14
|
+
page
|
15
|
+
end
|
16
|
+
end
|
data/app/models/sheet.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
module Sheet
|
2
|
+
module InvalidHomePage; end
|
3
|
+
module Instance
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval {
|
6
|
+
before_validation :set_title
|
7
|
+
before_validation :set_breadcrumb
|
8
|
+
before_validation :set_published
|
9
|
+
class_inheritable_accessor :sheet_root
|
10
|
+
|
11
|
+
def self.root
|
12
|
+
sheet_root ||= Page.find_by_path('/').children.first(:conditions => {:class_name => self.to_s})
|
13
|
+
rescue NoMethodError => e
|
14
|
+
e.extend Sheet::InvalidHomePage
|
15
|
+
raise e
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.default_page_parts
|
19
|
+
PagePart.new(:name => 'body')
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.create_from_upload!(file)
|
23
|
+
@sheet = self.new_with_defaults
|
24
|
+
@sheet.upload = file
|
25
|
+
@sheet.save!
|
26
|
+
@sheet
|
27
|
+
end
|
28
|
+
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def cache?
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
# so that it is ignored when finding children in radius tags
|
37
|
+
def virtual?
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
41
|
+
def layout
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def find_by_path(path, live = true, clean = true)
|
46
|
+
path = clean_path(path) if clean
|
47
|
+
my_path = self.path
|
48
|
+
if (my_path == path) && (not live or published?)
|
49
|
+
self
|
50
|
+
elsif (path =~ /^#{Regexp.quote(my_path)}([^\/]*)/)
|
51
|
+
slug_child = children.find_by_slug($1)
|
52
|
+
if slug_child
|
53
|
+
return slug_child
|
54
|
+
else
|
55
|
+
super
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
def find_by_url(*args)
|
60
|
+
ActiveSupport::Deprecation.warn("`find_by_url' has been deprecated; use `find_by_path' instead.", caller)
|
61
|
+
find_by_path(*args)
|
62
|
+
end
|
63
|
+
|
64
|
+
def upload=(file)
|
65
|
+
case
|
66
|
+
when file.blank?
|
67
|
+
self.errors.add(:upload, 'not given. Please upload a file.')
|
68
|
+
when !file.kind_of?(ActionController::UploadedFile)
|
69
|
+
self.errors.add(:upload, 'is an unusable format.')
|
70
|
+
when file.size > 262144 # 256k (that's a HUGE script or stylesheet)
|
71
|
+
self.errors.add(:upload, 'file size is larger than 256kB. Please upload a smaller file.')
|
72
|
+
else
|
73
|
+
self.slug = file.original_filename.to_slug().gsub(/-css$/,'.css').gsub(/-js/,'.js')
|
74
|
+
self.part('body').content = file.read
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def set_title
|
81
|
+
self.title = self.slug
|
82
|
+
end
|
83
|
+
|
84
|
+
def set_breadcrumb
|
85
|
+
self.breadcrumb = self.slug
|
86
|
+
end
|
87
|
+
|
88
|
+
def set_published
|
89
|
+
self.published_at = Time.zone.now
|
90
|
+
self.status_id = Status[:published].id
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class StylesheetPage < Page
|
2
|
+
include Sheet::Instance
|
3
|
+
in_menu false
|
4
|
+
|
5
|
+
def headers
|
6
|
+
{'Content-Type' => 'text/css'}
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.new_with_defaults(config = Radiant::Config)
|
10
|
+
page = StylesheetPage.new
|
11
|
+
page.parts.concat(self.default_page_parts)
|
12
|
+
page.parent_id = StylesheetPage.root.try(:id)
|
13
|
+
page.status_id = Status[:published].id
|
14
|
+
page
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
%h1= model.new_record? ? t('new_javascript') : t('edit_javascript')
|
2
|
+
- form_for [:admin, model], :url => (model.new_record? ? admin_scripts_url : admin_script_url(model)) do |f|
|
3
|
+
%p.title
|
4
|
+
= label :sheet_page, :slug, 'Slug'
|
5
|
+
= f.text_field :slug, :class => 'textbox', :maxlength => 255, :id => 'sheet_page_slug'
|
6
|
+
%span.hint= %{#{t('path')}: #{@root.url}<span id="this_slug">#{model.slug}</span>}
|
7
|
+
- f.fields_for :parts do |p|
|
8
|
+
%p.content
|
9
|
+
= p.label :content, 'Body'
|
10
|
+
= p.hidden_field :name, :value => 'body' if model.new_record?
|
11
|
+
= p.text_area :content, :class => 'textarea large', :style => 'width: 100%'
|
12
|
+
%p
|
13
|
+
- if SheetsExtension.javascript_filters.blank?
|
14
|
+
= p.hidden_field :filter_id, :value => ''
|
15
|
+
- else
|
16
|
+
= p.label :filter_id, t('filter'), :for => 'sheet_filter_id'
|
17
|
+
= p.select :filter_id, javascript_filter_options_for_select(p.object.filter_id), {}, :id => 'sheet_filter_id'
|
18
|
+
%span.reference_links
|
19
|
+
= t('reference')
|
20
|
+
- unless SheetsExtension.javascript_filters.blank?
|
21
|
+
%span{:id => "filter_reference_link_body"}
|
22
|
+
= link_to_function t('filter'), "loadFilterReference();"
|
23
|
+
%span{:id => "tag_reference_link_body"}
|
24
|
+
= link_to_function t('available_tags'), "loadTagReference('body');"
|
25
|
+
%p.buttons{:style=>"clear: left"}
|
26
|
+
= save_model_button(model)
|
27
|
+
= save_model_and_continue_editing_button(model)
|
28
|
+
= t('or')
|
29
|
+
= link_to t('cancel'), admin_scripts_url
|
30
|
+
= render 'admin/sheets/edit_scripts'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
= render 'admin/sheets/upload_script'
|
2
|
+
.outset
|
3
|
+
%table.index
|
4
|
+
%thead
|
5
|
+
%tr
|
6
|
+
%th Javascript
|
7
|
+
%th Filter
|
8
|
+
%th Modify
|
9
|
+
%tbody
|
10
|
+
- unless models.blank?
|
11
|
+
- models.each do |javascript|
|
12
|
+
%tr
|
13
|
+
%td.name
|
14
|
+
= image('javascript')
|
15
|
+
= link_to javascript.title, edit_admin_script_path(javascript)
|
16
|
+
%td.filter= javascript.part('body').filter.filter_name
|
17
|
+
%td.actions= link_to(image('minus') + ' ' + t('remove'), admin_script_url(javascript), :class => "action", :method => :delete, :confirm => "Is it OK to delete #{javascript.slug}?")
|
18
|
+
- else
|
19
|
+
%tr
|
20
|
+
%td.empty{:colspan => 2}= t('no_scripts')
|
21
|
+
|
22
|
+
#actions
|
23
|
+
= pagination_for(models)
|
24
|
+
%ul
|
25
|
+
%li= link_to image('plus') + " " + t("new_javascript"), new_admin_script_path, :class => 'action_button'
|
26
|
+
%li
|
27
|
+
= link_to image('upload') + ' ' + t("upload"), '#uploader', :class => 'replace action_button'
|
28
|
+
#uploader.action_button
|
29
|
+
- form_for :upload, :url => upload_admin_scripts_path, :html => { :class => 'button_form', :multipart => true } do |f|
|
30
|
+
%span
|
31
|
+
= f.label :upload, image('upload') + ' ' + t('upload')
|
32
|
+
= f.file_field :upload
|
33
|
+
= f.submit t('create_javascript')
|
@@ -0,0 +1,30 @@
|
|
1
|
+
%h1= model.new_record? ? t('new_javascript') : t('edit_javascript')
|
2
|
+
- form_for [:admin, model], :url => (model.new_record? ? admin_scripts_url : admin_script_url(model)) do |f|
|
3
|
+
%p.title
|
4
|
+
= label :sheet_page, :slug, 'Slug'
|
5
|
+
= f.text_field :slug, :class => 'textbox', :maxlength => 255, :id => 'sheet_page_slug'
|
6
|
+
%span.hint= %{#{t('path')}: #{@root.url}<span id="this_slug">#{model.slug}</span>}
|
7
|
+
- f.fields_for :parts do |p|
|
8
|
+
%p.content
|
9
|
+
= p.label :content, 'Body'
|
10
|
+
= p.hidden_field :name, :value => 'body' if model.new_record?
|
11
|
+
= p.text_area :content, :class => 'textarea large', :style => 'width: 100%'
|
12
|
+
%p
|
13
|
+
- if SheetsExtension.javascript_filters.blank?
|
14
|
+
= p.hidden_field :filter_id, :value => ''
|
15
|
+
- else
|
16
|
+
= p.label :filter_id, t('filter'), :for => 'sheet_filter_id'
|
17
|
+
= p.select :filter_id, javascript_filter_options_for_select(p.object.filter_id), {}, :id => 'sheet_filter_id'
|
18
|
+
%span.reference_links
|
19
|
+
= t('reference')
|
20
|
+
- unless SheetsExtension.javascript_filters.blank?
|
21
|
+
%span{:id => "filter_reference_link_body"}
|
22
|
+
= link_to_function t('filter'), "loadFilterReference();"
|
23
|
+
%span{:id => "tag_reference_link_body"}
|
24
|
+
= link_to_function t('available_tags'), "loadTagReference('body');"
|
25
|
+
%p.buttons{:style=>"clear: left"}
|
26
|
+
= save_model_button(model)
|
27
|
+
= save_model_and_continue_editing_button(model)
|
28
|
+
= t('or')
|
29
|
+
= link_to t('cancel'), admin_scripts_url
|
30
|
+
= render 'admin/sheets/edit_scripts'
|
@@ -0,0 +1,40 @@
|
|
1
|
+
- content_for :page_scripts do
|
2
|
+
:plain
|
3
|
+
Event.addBehavior({
|
4
|
+
'input#sheet_page_slug': function(){
|
5
|
+
var slug = this;
|
6
|
+
var this_slug = $('this_slug');
|
7
|
+
new Form.Element.Observer(slug, 0.15, function() {
|
8
|
+
this_slug.innerHTML = slug.value.toSlug(true);
|
9
|
+
});
|
10
|
+
}
|
11
|
+
});
|
12
|
+
var tagReferenceWindows = {};
|
13
|
+
function loadTagReference(part) {
|
14
|
+
var pageType = '#{model.class_name}';
|
15
|
+
if (!tagReferenceWindows[pageType])
|
16
|
+
tagReferenceWindows[pageType] = new Popup.AjaxWindow("#{admin_reference_path('tags')}?class_name=" + encodeURIComponent(pageType), {reload: false});
|
17
|
+
var window = tagReferenceWindows[pageType];
|
18
|
+
$('tag_reference_link_' + part).highlight();
|
19
|
+
window.show();
|
20
|
+
return false;
|
21
|
+
}
|
22
|
+
|
23
|
+
var lastFilter = 'sheet_filter_id';
|
24
|
+
var filterWindows = {};
|
25
|
+
function loadFilterReference() {
|
26
|
+
var filter = $F("sheet_filter_id");
|
27
|
+
if (filter != "") {
|
28
|
+
if (!filterWindows[filter]) filterWindows[filter] = new Popup.AjaxWindow("#{admin_reference_path('filters')}?filter_name="+encodeURIComponent(filter), {reload: false});
|
29
|
+
var window = filterWindows[filter];
|
30
|
+
if(lastFilter != filter) {
|
31
|
+
window.show();
|
32
|
+
} else {
|
33
|
+
window.toggle();
|
34
|
+
}
|
35
|
+
lastFilter = filter;
|
36
|
+
} else {
|
37
|
+
alert('No documentation for filter.');
|
38
|
+
}
|
39
|
+
return false;
|
40
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
- content_for :page_scripts do
|
2
|
+
:plain
|
3
|
+
document.observe('dom:loaded', function(){
|
4
|
+
$('uploader').down('form.button_form input[type=submit]').hide()
|
5
|
+
$('uploader').hide()
|
6
|
+
})
|
7
|
+
Event.addBehavior({
|
8
|
+
'a.replace:click': function(){
|
9
|
+
var ref = this.readAttribute('href').sub(/\#/,'')
|
10
|
+
$(ref).show();
|
11
|
+
this.hide();
|
12
|
+
},
|
13
|
+
'input[type=file]:change': function(){
|
14
|
+
this.up('form').highlight().down('input[type=submit]').show();
|
15
|
+
}
|
16
|
+
});
|
@@ -0,0 +1,30 @@
|
|
1
|
+
%h1= model.new_record? ? t('new_stylesheet') : t('edit_stylesheet')
|
2
|
+
- form_for [:admin, model], :url => (model.new_record? ? admin_styles_url() : admin_style_url(model)) do |f|
|
3
|
+
%p.title
|
4
|
+
= label :sheet_page, :slug, 'Slug'
|
5
|
+
= f.text_field :slug, :class => 'textbox', :maxlength => 255, :id => "sheet_page_slug"
|
6
|
+
%span.hint= %{Path: #{@root.url}<span id="this_slug">#{model.slug}</span>}
|
7
|
+
- f.fields_for :parts do |p|
|
8
|
+
%p.content
|
9
|
+
= p.label :content, 'Body'
|
10
|
+
= p.hidden_field :name, :value => 'body' if model.new_record?
|
11
|
+
= p.text_area :content, :class => 'textarea large', :style => 'width: 100%'
|
12
|
+
%p
|
13
|
+
- if SheetsExtension.stylesheet_filters.blank?
|
14
|
+
= p.hidden_field :filter_id, :value => ''
|
15
|
+
- else
|
16
|
+
= p.label :filter_id, t('filter'), :for => 'sheet_filter_id'
|
17
|
+
= p.select :filter_id, stylesheet_filter_options_for_select(p.object.filter_id), {}, :id => 'sheet_filter_id'
|
18
|
+
%span.reference_links
|
19
|
+
= t('reference')
|
20
|
+
- unless SheetsExtension.stylesheet_filters.blank?
|
21
|
+
%span{:id => "filter_reference_link_body"}
|
22
|
+
= link_to_function t('filter'), "loadFilterReference();"
|
23
|
+
%span{:id => "tag_reference_link_body"}
|
24
|
+
= link_to_function t('available_tags'), "loadTagReference('body');"
|
25
|
+
%p.buttons{:style=>"clear: left"}
|
26
|
+
= save_model_button(model)
|
27
|
+
= save_model_and_continue_editing_button(model)
|
28
|
+
= t('or')
|
29
|
+
= link_to t('cancel'), admin_styles_url
|
30
|
+
= render 'admin/sheets/edit_scripts'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
= render 'admin/sheets/upload_script'
|
2
|
+
.outset
|
3
|
+
%table.index
|
4
|
+
%thead
|
5
|
+
%tr
|
6
|
+
%th Stylesheet
|
7
|
+
%th Filter
|
8
|
+
%th Modify
|
9
|
+
%tbody
|
10
|
+
- unless models.blank?
|
11
|
+
- models.each do |stylesheet|
|
12
|
+
%tr
|
13
|
+
%td.name
|
14
|
+
= image('stylesheet')
|
15
|
+
= link_to stylesheet.title, edit_admin_style_path(stylesheet)
|
16
|
+
%td.filter= stylesheet.part('body').filter.filter_name
|
17
|
+
%td.actions= link_to(image('minus') + ' ' + t('remove'), admin_style_url(stylesheet), :class => "action", :method => :delete, :confirm => "Is it OK to delete #{stylesheet.slug}?")
|
18
|
+
- else
|
19
|
+
%tr
|
20
|
+
%td.empty{:colspan => 3}= t('no_styles')
|
21
|
+
|
22
|
+
#actions
|
23
|
+
= pagination_for(models)
|
24
|
+
%ul
|
25
|
+
%li= link_to image('plus') + " " + t("new_stylesheet"), new_admin_style_path, :class => 'action_button'
|
26
|
+
%li
|
27
|
+
= link_to image('upload') + ' ' + t("upload"), '#uploader', :class => 'replace action_button'
|
28
|
+
#uploader.action_button
|
29
|
+
- form_for :upload, :url => upload_admin_styles_path, :html => { :class => 'button_form', :multipart => true } do |f|
|
30
|
+
%span
|
31
|
+
= f.label :upload, image('upload') + ' ' + t('upload')
|
32
|
+
= f.file_field :upload
|
33
|
+
= f.submit t('create_stylesheet')
|
@@ -0,0 +1,30 @@
|
|
1
|
+
%h1= model.new_record? ? t('new_stylesheet') : t('edit_stylesheet')
|
2
|
+
- form_for [:admin, model], :url => (model.new_record? ? admin_styles_url() : admin_style_url(model)) do |f|
|
3
|
+
%p.title
|
4
|
+
= label :sheet_page, :slug, 'Slug'
|
5
|
+
= f.text_field :slug, :class => 'textbox', :maxlength => 255, :id => "sheet_page_slug"
|
6
|
+
%span.hint= %{Path: #{@root.url}<span id="this_slug">#{model.slug}</span>}
|
7
|
+
- f.fields_for :parts do |p|
|
8
|
+
%p.content
|
9
|
+
= p.label :content, 'Body'
|
10
|
+
= p.hidden_field :name, :value => 'body' if model.new_record?
|
11
|
+
= p.text_area :content, :class => 'textarea large', :style => 'width: 100%'
|
12
|
+
%p
|
13
|
+
- if SheetsExtension.stylesheet_filters.blank?
|
14
|
+
= p.hidden_field :filter_id, :value => ''
|
15
|
+
- else
|
16
|
+
= p.label :filter_id, t('filter'), :for => 'sheet_filter_id'
|
17
|
+
= p.select :filter_id, stylesheet_filter_options_for_select(p.object.filter_id), {}, :id => 'sheet_filter_id'
|
18
|
+
%span.reference_links
|
19
|
+
= t('reference')
|
20
|
+
- unless SheetsExtension.stylesheet_filters.blank?
|
21
|
+
%span{:id => "filter_reference_link_body"}
|
22
|
+
= link_to_function t('filter'), "loadFilterReference();"
|
23
|
+
%span{:id => "tag_reference_link_body"}
|
24
|
+
= link_to_function t('available_tags'), "loadTagReference('body');"
|
25
|
+
%p.buttons{:style=>"clear: left"}
|
26
|
+
= save_model_button(model)
|
27
|
+
= save_model_and_continue_editing_button(model)
|
28
|
+
= t('or')
|
29
|
+
= link_to t('cancel'), admin_styles_url
|
30
|
+
= render 'admin/sheets/edit_scripts'
|