manuscript 0.2.3 → 0.3.9pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.gitignore +3 -0
  2. data/Gemfile +23 -0
  3. data/Rakefile +7 -5
  4. data/VERSION +1 -1
  5. data/config.ru +18 -4
  6. data/lib/manuscript.rb +18 -5
  7. data/lib/manuscript/design_manager.rb +87 -0
  8. data/lib/manuscript/keymaster.rb +1 -2
  9. data/lib/manuscript/page.rb +2 -2
  10. data/lib/manuscript/page_manager.rb +1 -0
  11. data/lib/manuscript/settings.rb +30 -0
  12. data/lib/manuscript/settings_manager.rb +17 -0
  13. data/lib/manuscript/template_file.rb +10 -3
  14. data/lib/manuscript/views/_page.haml +8 -0
  15. data/lib/manuscript/views/design.haml +29 -0
  16. data/lib/manuscript/views/edit_template_file.haml +7 -0
  17. data/{views → lib/manuscript/views}/layout.haml +1 -1
  18. data/lib/manuscript/views/menu.haml +16 -0
  19. data/lib/manuscript/views/new_template_file.haml +6 -0
  20. data/{views → lib/manuscript/views}/page.haml +7 -6
  21. data/lib/manuscript/views/pages.haml +7 -0
  22. data/lib/manuscript/views/settings.haml +10 -0
  23. data/{views → lib/manuscript/views}/template.haml +5 -9
  24. data/manuscript.gemspec +35 -23
  25. data/public/css/base.css +82 -14
  26. data/public/css/wmd.css +133 -0
  27. data/public/images/buttonbg.png +0 -0
  28. data/public/images/wmd-buttons.png +0 -0
  29. data/public/js/wmd.min.js +1 -0
  30. data/spec/manuscript/{template_manager_spec.rb → design_manager_spec.rb} +9 -9
  31. data/spec/manuscript/page_manager_spec.rb +2 -2
  32. data/spec/manuscript/settings_manager_spec.rb +21 -0
  33. data/spec/manuscript/settings_spec.rb +19 -0
  34. data/spec/spec_helper.rb +3 -0
  35. metadata +126 -56
  36. data/lib/manuscript/template_file_manager.rb +0 -53
  37. data/lib/manuscript/template_manager.rb +0 -44
  38. data/spec/manuscript/template_file_manager_spec.rb +0 -10
  39. data/views/_page.haml +0 -10
  40. data/views/edit_template_file.haml +0 -9
  41. data/views/menu.haml +0 -16
  42. data/views/new_template_file.haml +0 -7
  43. data/views/pages.haml +0 -6
  44. data/views/template_files.haml +0 -9
  45. data/views/templates.haml +0 -15
data/.gitignore CHANGED
@@ -19,3 +19,6 @@ rdoc
19
19
  pkg
20
20
 
21
21
  ## PROJECT::SPECIFIC
22
+ application.log
23
+ template_files
24
+ *.sqlite3.db
data/Gemfile ADDED
@@ -0,0 +1,23 @@
1
+ source 'http://gemcutter.org'
2
+
3
+
4
+ group :development do
5
+ gem 'sqlite3-ruby'
6
+ end
7
+
8
+ gem 'ruby-openid', :require => 'openid'
9
+ gem 'sinatra'
10
+ gem 'activerecord', :require => 'active_record'
11
+ gem 'rdiscount'
12
+ gem 'liquid'
13
+ gem 'aws-s3', :require => 'aws/s3'
14
+ gem 'paperclip'
15
+ gem 'haml'
16
+ gem 'gatekeeper'
17
+
18
+ group :test do
19
+ gem 'rack-test'
20
+ gem 'shoulda'
21
+ gem 'database_cleaner'
22
+ gem 'rspec'
23
+ end
data/Rakefile CHANGED
@@ -8,11 +8,13 @@ begin
8
8
  gem.name = "manuscript"
9
9
  gem.summary = "A gem for publishing a small Hot Ink authenticated site"
10
10
  gem.description = "A gem for publishing a small Hot Ink authenticated site"
11
- gem.email = "chris@hotink.net"
12
- gem.homepage = "http://github.com/hotink/manuscript"
13
- gem.authors = ["hotink"]
11
+ gem.email = "chrisgdinn@gmail.com"
12
+ gem.homepage = "http://github.com/chrisdinn/manuscript"
13
+ gem.authors = ["Chris Dinn"]
14
+ gem.add_dependency 'ruby-openid'
14
15
  gem.add_dependency 'activerecord', '>= 2.3.5'
15
16
  gem.add_dependency 'rdiscount', '>= 1.3.5'
17
+ gem.add_dependency 'aws-s3'
16
18
  gem.add_dependency 'sinatra', '>= 0.9.4'
17
19
  gem.add_dependency 'haml', '>= 2.2.12'
18
20
  gem.add_dependency 'gatekeeper', '>= 0.1.1'
@@ -54,7 +56,7 @@ end
54
56
 
55
57
  namespace :db do
56
58
  desc "Migrate the database"
57
- task(:migrate => :environment) do
59
+ task :migrate do
58
60
  ActiveRecord::Base.logger = Logger.new(STDOUT)
59
61
  ActiveRecord::Migration.verbose = true
60
62
  ActiveRecord::Migrator.migrate("db/migrate")
@@ -63,5 +65,5 @@ end
63
65
 
64
66
  task :environment do
65
67
  require 'manuscript'
66
- ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => 'manuscript.sqlite3.db'
68
+ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => 'manuscript_test.sqlite3.db'
67
69
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.3
1
+ 0.3.6pre
data/config.ru CHANGED
@@ -1,15 +1,29 @@
1
+ begin
2
+ # Try to require the preresolved locked set of gems.
3
+ require File.expand_path('../.bundle/environment', __FILE__)
4
+ rescue LoadError
5
+ # Fall back on doing an unlocked resolve at runtime.
6
+ require "rubygems"
7
+ require "bundler"
8
+ Bundler.setup :default, :development
9
+ end
10
+
11
+ Bundler.require :default, :development
12
+
1
13
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__),'lib'))
2
14
  require 'manuscript'
3
15
 
16
+ Paperclip::Storage::S3::RAILS_ENV = "development"
17
+
4
18
  ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => 'manuscript.sqlite3.db', :encoding => 'UTF-8'
5
19
 
6
20
  use Rack::Session::Cookie
7
21
  use Rack::Static, :urls => ["/template_files"]
8
22
  use Gatekeeper::Middleware do |sso|
9
- sso.sso_url = "http://hotink.theorem.ca/sso"
23
+ sso.sso_url = "http://digital-achiever.com/sso"
10
24
  end
11
- use Manuscript::Keymaster, :hotink_account_id => 1
25
+ use Manuscript::Keymaster
12
26
  use Manuscript::PageManager
13
- use Manuscript::TemplateManager
14
- use Manuscript::TemplateFileManager
27
+ use Manuscript::DesignManager
28
+ use Manuscript::SettingsManager
15
29
  run Manuscript::Base.new
data/lib/manuscript.rb CHANGED
@@ -6,6 +6,8 @@ require 'gatekeeper/helpers/authentication'
6
6
  require 'sinatra/base'
7
7
  require 'haml'
8
8
  require 'active_record'
9
+ require 'paperclip'
10
+
9
11
  require 'logger'
10
12
 
11
13
  require 'manuscript/base'
@@ -15,13 +17,14 @@ require 'manuscript/page_manager'
15
17
  require 'manuscript/template'
16
18
  require 'manuscript/page_template'
17
19
  require 'manuscript/layout_template'
18
- require 'manuscript/template_manager'
20
+ require 'manuscript/design_manager'
21
+ require 'manuscript/settings_manager'
22
+ require 'manuscript/settings'
19
23
  require 'manuscript/template_file'
20
- require 'manuscript/template_file_manager'
21
24
  require 'manuscript/user'
22
25
 
23
26
 
24
- log = File.new("application.log", "a")
27
+ log = File.new("log/application.log", "a")
25
28
  $stderr.reopen(log)
26
29
  LOGGER = Logger.new($stderr)
27
30
  ActiveRecord::Base.logger = LOGGER
@@ -29,10 +32,20 @@ OpenID::Util.logger = LOGGER
29
32
 
30
33
  module Sinatra
31
34
  class Base
32
- set :views, File.dirname(__FILE__) + "/../views"
35
+ set :views, File.dirname(__FILE__) + "/manuscript/views"
33
36
  set :static, true
34
37
  set :public, File.dirname(__FILE__) + "/../public"
35
- set :raise_errors, false
38
+ set :raise_errors, true
36
39
  set :logging, true
40
+
41
+ helpers do
42
+ def user_email
43
+ if session[:sso]
44
+ return session[:sso][:user_email]
45
+ else
46
+ nil
47
+ end
48
+ end
49
+ end
37
50
  end
38
51
  end
@@ -0,0 +1,87 @@
1
+ module Manuscript
2
+ class DesignManager < Sinatra::Base
3
+ enable :methodoverride
4
+
5
+ get "/admin/design/?" do
6
+ @templates = PageTemplate.all
7
+ @layouts = LayoutTemplate.all
8
+ @template_files = TemplateFile.all
9
+ haml :design
10
+ end
11
+
12
+ get "/admin/design/templates/new" do
13
+ @template = PageTemplate.new
14
+ haml :template
15
+ end
16
+
17
+ get "/admin/design/layouts/new" do
18
+ @template = LayoutTemplate.new
19
+ haml :template
20
+ end
21
+
22
+ post "/admin/design/templates/?" do
23
+ @template = PageTemplate.create(params[:template])
24
+ redirect "/admin/design/templates/#{@template.id}/edit"
25
+ end
26
+
27
+ post "/admin/design/layouts/?" do
28
+ @template = LayoutTemplate.create(params[:template])
29
+ redirect "/admin/design/templates/#{@template.id}/edit"
30
+ end
31
+
32
+ get "/admin/design/templates/:id/edit" do
33
+ @template = Template.find_by_id params[:id]
34
+ halt 404, "Template not found" unless @template
35
+ haml :template
36
+ end
37
+
38
+ put "/admin/design/templates/:id/?" do
39
+ @template = Template.find_by_id params[:id]
40
+ halt 404, "Template not found" unless @template
41
+ @template.update_attributes(params[:template])
42
+ redirect "/admin/design/templates/#{@template.id}/edit"
43
+ end
44
+
45
+ get '/admin/design/template_files/new/?' do
46
+ haml :new_template_file
47
+ end
48
+
49
+ post '/admin/design/template_files' do
50
+ new_file = params[:template_file][:file][:tempfile]
51
+ new_file.original_filename = params[:template_file][:file][:filename]
52
+
53
+ @file = TemplateFile.new
54
+ @file.file = new_file
55
+ @file.save
56
+ redirect '/admin/design#template_files'
57
+ end
58
+
59
+ get '/admin/design/template_files/:id/edit' do
60
+ @file = TemplateFile.find(params[:id])
61
+ haml :edit_template_file
62
+ end
63
+
64
+ put '/admin/design/template_files/:id' do
65
+ new_file = params[:template_file][:file][:tempfile]
66
+ new_file.original_filename = params[:template_file][:file][:filename]
67
+
68
+ @file = TemplateFile.find(params[:id])
69
+ raise Sinatra::NotFound unless @file
70
+ @file.file = new_file
71
+ @file.save
72
+ redirect '/admin/design/#template_files'
73
+ end
74
+
75
+ delete '/admin/design/template_files/:id' do
76
+ @file = TemplateFile.find(params[:id])
77
+ raise Sinatra::NotFound unless @file
78
+ @file.destroy
79
+ redirect '/admin/design/#template_files'
80
+ end
81
+ end
82
+ end
83
+
84
+ # Paperclip expects a Rails-specific ActionController::UploadedFile, so fake it with Tempfile hack
85
+ class Tempfile
86
+ attr_accessor :original_filename
87
+ end
@@ -3,14 +3,13 @@ module Manuscript
3
3
 
4
4
  def initialize(app, options={})
5
5
  @app = app
6
- @hotink_account_id = options[:hotink_account_id] || 1
7
6
  end
8
7
 
9
8
  def call(env)
10
9
  request = Rack::Request.new(env)
11
10
  session = env['rack.session']
12
11
  if env['PATH_INFO']=~/^\/admin/
13
- if (session[:sso] && session[:sso][:user_id]) && (session[:sso][:is_admin?]=='true' || session[:sso]["account_#{@hotink_account_id}_manager"]=='true')
12
+ if (session[:sso] && session[:sso][:user_id])
14
13
  @app.call(env)
15
14
  else
16
15
  [302, {"Location" => "/sso/login?return_to=#{request.url}"}, "Redirecting to SSO server..."]
@@ -9,8 +9,8 @@ module Manuscript
9
9
  validates_uniqueness_of :name
10
10
  validates_format_of :name, :with => /^[-a-zA-Z0-9]+$/
11
11
 
12
- belongs_to :parent, :class_name => "Page"
13
- has_many :child_pages, :class_name => "Page", :foreign_key => "parent_id", :order => :name
12
+ belongs_to :parent, :class_name => "Manuscript::Page"
13
+ has_many :child_pages, :class_name => "Manuscript::Page", :foreign_key => "parent_id", :order => :name
14
14
  named_scope :main_pages, :conditions => { :parent_id => nil }
15
15
 
16
16
  def self.find_by_path(path)
@@ -8,6 +8,7 @@ module Manuscript
8
8
  end
9
9
 
10
10
  get "/admin/pages/?" do
11
+ @settings = Settings.new('settings.yml')
11
12
  @pages = Page.main_pages.all
12
13
  haml :pages
13
14
  end
@@ -0,0 +1,30 @@
1
+ module Manuscript
2
+ class Settings
3
+ attr_reader :settings_file_name, :settings
4
+
5
+ def initialize(filename)
6
+ @settings = Hash.new
7
+ @settings_file_name = filename
8
+ settings = YAML::load(File.new(@settings_file_name).read)
9
+ @settings.update(settings) if settings.is_a? Hash
10
+ end
11
+
12
+ def [](key)
13
+ return @settings[key]
14
+ end
15
+
16
+ def []=(key, value)
17
+ @settings[key] = value
18
+ end
19
+
20
+ def to_hash
21
+ return @settings
22
+ end
23
+
24
+ def save
25
+ File.open(@settings_file_name,'w') do |file|
26
+ file << YAML::dump(@settings)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ module Manuscript
2
+ class SettingsManager < Sinatra::Base
3
+
4
+ get '/admin/settings' do
5
+ @settings = Settings.new('settings.yml')
6
+ haml :settings
7
+ end
8
+
9
+ post '/admin/settings' do
10
+ @settings = Settings.new('settings.yml')
11
+ params[:settings].each { |k, v| @settings[k.to_sym] = v }
12
+ @settings.save
13
+ redirect "/admin"
14
+ end
15
+
16
+ end
17
+ end
@@ -1,12 +1,19 @@
1
1
  require 'paperclip'
2
+ require 'yaml'
2
3
 
3
4
  module Manuscript
4
- class TemplateFile < ActiveRecord::Base
5
+ class TemplateFile < ActiveRecord::Base
5
6
  validates_presence_of :file_file_name
7
+ validates_uniqueness_of :file_file_name
8
+
9
+ S3_CREDENTIALS = YAML.load(File.read('config/s3.yml'))
6
10
 
7
11
  has_attached_file :file,
8
- :path => "./template_files/:id/:basename.:extension",
9
- :url => "/template_files/:id/:basename.:extension"
12
+ #:url => "./template_files/:id/:basename.:extension",
13
+ :path => "/template_files/:basename.:extension",
14
+ :storage => :s3,
15
+ :s3_credentials => { :access_key_id => S3_CREDENTIALS["access_key_id"], :secret_access_key => S3_CREDENTIALS["secret_access_key"], :bucket_name => S3_CREDENTIALS["bucket_name"] },
16
+ :bucket => S3_CREDENTIALS["bucket_name"]
10
17
 
11
18
  def url
12
19
  file.url
@@ -0,0 +1,8 @@
1
+ %li
2
+ %a{:href => "/admin/pages/#{page.id}/edit"}
3
+ ="/#{page.name}"
4
+ %a.btn.red.small{:style => "padding:2px 5px 4px 5px;margin:0px 0px 0px 6px;top:-5px;", :onclick => "if(confirm('You are about to delete the page:\\n\\n\"#{page.name}\" \\n\\nThis cannot be undone.\\n\\nClick \\'OK\\' to delete or \\'Cancel\\' to return to the page.\\n')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); { f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);f.submit(); } } return false;", :href => "/admin/pages/#{page.id}" } x
5
+ %a.btn.green.small{:style => "padding:2px 5px 4px 5px;margin:0px;top:-5px;text-decoration:none;", :href => "/admin/pages/new?parent_id=#{page.id}"} + subpage
6
+ %ol.child_pages
7
+ - page.child_pages.each do |child|
8
+ = haml :_page, :locals => { :page => child }, :layout => false
@@ -0,0 +1,29 @@
1
+ %h1 Site design
2
+
3
+ %h2 Templates
4
+ %a.btn.small.green{ :href => "/admin/design/templates/new" } New template
5
+ %ol#templates
6
+ - @templates.each do |template|
7
+ %li
8
+ %a{:href => "/admin/design/templates/#{template.id}/edit"}
9
+ = template.name
10
+
11
+ %hr{ :style => "clear:both; margin-top:10px;"}
12
+ %h2 Layouts
13
+ %a.btn.small.yellow{ :href => "/admin/design/layouts/new" } New layout
14
+ %ol#layouts
15
+ - @layouts.each do |template|
16
+ %li
17
+ %a{:href => "/admin/design/templates/#{template.id}/edit"}
18
+ = template.name
19
+
20
+ %hr{ :style => "clear:both; margin-top:10px;"}
21
+ %h2 Template files
22
+ %a.btn.small.pink{ :href => "/admin/design/template_files/new" } Upload a file
23
+ %ol#template_files
24
+ - @template_files.each do |file|
25
+ %li
26
+ = "#{file.file_file_name} "
27
+ %small
28
+ %a.btn.red.small{:style => "padding:2px 5px 4px 5px;margin:0px 6px 0px 6px;top:-5px;", :onclick => "if(confirm('You are about to delete a template file. Click OK to delete or Cancel to return to the page.')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); { f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);f.submit(); } } return false;", :href => "/admin/design/template_files/#{file.id}" } x
29
+ %a.btn.blue.small{:style => "padding:2px 5px 4px 5px;margin:0px;top:-5px;text-decoration:none;", :href => "/admin/design/template_files/#{file.id}/edit"} edit
@@ -0,0 +1,7 @@
1
+ %h1 Site design
2
+ %h2= "Replace file: #{@file.file_file_name}"
3
+ %form{:method =>:post, :action => "/admin/design/template_files/#{@file.id}", :enctype => "multipart/form-data"}
4
+ %fieldset
5
+ %input{:type => 'file', :name => 'template_file[file]', :id => 'template_file_file', :style => "float:left;"}
6
+ %input{:type => 'hidden', :name => '_method', :value => 'put'}
7
+ %input{ :type => :submit, :class => "btn large green", :value => "Upload", :style => "float:left;" }
@@ -4,7 +4,7 @@
4
4
  %title Manuscript, simple content management
5
5
  %link{ :rel=>'stylesheet', :href=>'/css/base.css', :type=>'text/css', :media=>'screen' }
6
6
  %body
7
- = haml(:menu, :layout => false)
8
7
  #page_container
8
+ = haml(:menu, :layout => false)
9
9
  = yield
10
10
 
@@ -0,0 +1,16 @@
1
+ %ol.menu
2
+ - if request.path_info =~ /^\/admin\/pages/
3
+ %li.current
4
+ %a{:href => "/admin/pages"} Pages
5
+ - else
6
+ %li
7
+ %a{:href => "/admin/pages"} Pages
8
+ - if request.path_info =~ /^\/admin\/design/
9
+ %li.current
10
+ %a{:href => "/admin/design"} Design
11
+ - else
12
+ %li
13
+ %a{:href => "/admin/design"} Design
14
+ %li{:style => "float: right; font-size: 12px;padding-left: 35px; margin-top:2px;" }
15
+ = user_email
16
+ %a{:href => "/sso/logout", :style => "margin-left: 7px; font-size: 12px;" } Sign out
@@ -0,0 +1,6 @@
1
+ %h1 Site design
2
+ %h2 Upload template file
3
+ %form{:method =>:post, :action => "/admin/design/template_files", :enctype => "multipart/form-data"}
4
+ %fieldset
5
+ %input{:type => 'file', :name => 'template_file[file]', :id => 'template_file_file', :style => "float:left;"}
6
+ %input{ :type => :submit, :class => "btn large green", :value => "Upload", :style => "float:left;" }
@@ -1,11 +1,9 @@
1
- %p
2
- %a{ :href => "/admin/pages" } &laquo back
1
+ %h1 Edit page
3
2
  %form{:method =>:post, 'accept-charset' => "utf-8", :action => "/admin/pages/#{@page.id unless @page.new_record? }"}
4
3
  - unless @page.new_record?
5
4
  %input{ :type => :hidden, :name => "_method", :value => :put }
6
5
  %fieldset
7
- %legend Edit page
8
- %input{ :type => :submit }
6
+ %input{ :type => :submit, :class => "btn large blue", :value => "Save" }
9
7
  %label
10
8
  = "Page url:&nbsp;&nbsp;<strong>#{@page.parent_url}/</strong>"
11
9
  %input{:type => :text, :name => "page[name]", :value => "#{@page.name}"}
@@ -22,6 +20,9 @@
22
20
  = template.name
23
21
  - unless @page.parent_id.nil?
24
22
  %input{:type => :hidden, :name => "page[parent_id]", :value => "#{@page.parent_id}"}
25
- %label{:for => "page_contents" }
23
+ %label{:for => "wmd-input" }
26
24
  Contents
27
- %textarea{:name => "page[contents]", :id => "page_contents"}= @page.contents
25
+ #wmd-button-bar
26
+ %textarea{:name => "page[contents]", :id => "wmd-input"}= @page.contents
27
+ <script src="/js/wmd.min.js" type="text/javascript"></script>
28
+