manuscript 0.2.3 → 0.3.9pre

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 (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
+