merbiful-release 0.2.1 → 0.2.2

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/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'pathname'
5
5
 
6
6
  PLUGIN = "merbiful-release"
7
7
  NAME = "merbiful-release"
8
- GEM_VERSION = "0.2.1"
8
+ GEM_VERSION = "0.2.2"
9
9
  AUTHOR = "Martin Kihlgren"
10
10
  EMAIL = "martin@wemind.se"
11
11
  HOMEPAGE = ""
@@ -21,6 +21,9 @@ spec = Gem::Specification.new do |s|
21
21
  s.author = AUTHOR
22
22
  s.email = EMAIL
23
23
  s.homepage = HOMEPAGE
24
+ %w(merb-core merb_helpers merb_datamapper merb-action-args merb-assets merb-haml dm-core dm-aggregates dm-migrations dm-timestamps dm-validations).each do |dep|
25
+ s.add_dependency(dep)
26
+ end
24
27
  s.require_path = 'lib'
25
28
  s.autorequire = PLUGIN
26
29
  s.files = %w(Rakefile LICENSE) + Dir.glob("{lib,specs,templates}/**/*")
@@ -1,2 +1,29 @@
1
1
 
2
- require File.join(File.dirname(__FILE__), 'merbiful-release', 'merbiful.rb')
2
+ require 'merb-core'
3
+ require 'merb-action-args'
4
+ require 'merb_helpers'
5
+ require 'merb-assets'
6
+ require 'dm-core'
7
+ require 'dm-validations'
8
+ require 'dm-timestamps'
9
+ require 'dm-aggregates'
10
+ require 'haml'
11
+ require 'forwardable'
12
+ require 'pathname'
13
+ require 'erubis'
14
+ require 'pp'
15
+ require 'digest/sha1'
16
+
17
+ require File.join(File.dirname(__FILE__), 'merbiful-release', 'filters.rb')
18
+ require File.join(File.dirname(__FILE__), 'merbiful-release', 'relative_time.rb')
19
+ require File.join(File.dirname(__FILE__), 'merbiful-release', 'images.rb')
20
+ require File.join(File.dirname(__FILE__), 'merbiful-release', 'controller.rb')
21
+ require File.join(File.dirname(__FILE__), 'merbiful-release', 'body.rb')
22
+ require File.join(File.dirname(__FILE__), 'merbiful-release', 'admin.rb')
23
+ require File.join(File.dirname(__FILE__), 'merbiful-release', 'routes.rb')
24
+ require File.join(File.dirname(__FILE__), 'merbiful-release', 'css.rb')
25
+ require File.join(File.dirname(__FILE__), 'merbiful-release', 'js.rb')
26
+ require File.join(File.dirname(__FILE__), 'merbiful-release', 'page.rb')
27
+ require File.join(File.dirname(__FILE__), 'merbiful-release', 'layout.rb')
28
+ require File.join(File.dirname(__FILE__), 'merbiful-release', 'haml.rb')
29
+ require File.join(File.dirname(__FILE__), 'merbiful-release', 'erubis.rb')
@@ -5,6 +5,31 @@ module Merbiful
5
5
 
6
6
  include RelativeTimeHelpers
7
7
 
8
+ before :authorize!
9
+
10
+ def authorize!
11
+ unless authorized?
12
+ redirect login_url
13
+ throw :halt, "Access denied"
14
+ end
15
+ end
16
+
17
+ def logged_in_user
18
+ nil
19
+ end
20
+
21
+ def login_url
22
+ ""
23
+ end
24
+
25
+ def logout_url
26
+ ""
27
+ end
28
+
29
+ def authorized?
30
+ true
31
+ end
32
+
8
33
  def index
9
34
  render_template_with_layout("index.html.haml")
10
35
  end
@@ -1,10 +1,282 @@
1
1
 
2
2
  module Merbiful
3
3
 
4
- class Controller < Merb::Controller
4
+ class Admin < Merb::Controller
5
+
6
+ include RelativeTimeHelpers
7
+
8
+ def index
9
+ render_template_with_layout("index.html.haml")
10
+ end
11
+
12
+ def layouts
13
+ @form_layout = Layout.get(params[:layout_id])
14
+ if request.post?
15
+ @form_layout.update_attributes(params[:layout])
16
+ if @form_layout.valid?
17
+ @form_layout.save
18
+ @form_version = Layout::Version.new(params[:version].merge(:layout => @form_layout))
19
+ if @form_version.valid?
20
+ @form_version.save
21
+ redirect url(:merbiful_admin, :action => "layouts", :layout_id => @form_layout.id)
22
+ end
23
+ end
24
+ else
25
+ if @form_layout
26
+ @form_version = Layout::Version.get(params[:version_id])
27
+ @form_version = @form_layout.latest unless @form_version
28
+ end
29
+ end
30
+ render_template_with_layout("layouts.html.haml")
31
+ end
32
+
33
+ def js
34
+ @form_js = Js.get(params[:js_id])
35
+ if request.post?
36
+ params[:js][:cached] = !!params[:js][:cached]
37
+ @form_js.update_attributes(params[:js])
38
+ if @form_js.valid?
39
+ @form_js.save
40
+ @form_version = Js::Version.new(params[:version].merge(:js => @form_js))
41
+ if @form_version.valid?
42
+ @form_version.save
43
+ redirect url(:merbiful_admin, :action => "js", :js_id => @form_js.id)
44
+ end
45
+ end
46
+ else
47
+ if @form_js
48
+ @form_version = Js::Version.get(params[:version_id])
49
+ @form_version = @form_js.latest unless @form_version
50
+ end
51
+ end
52
+ render_template_with_layout("js.html.haml")
53
+ end
54
+
55
+ def images
56
+ if request.post?
57
+ end
58
+ render_template_with_layout("images.html.haml")
59
+ end
60
+
61
+ def css
62
+ @form_css = Css.get(params[:css_id])
63
+ if request.post?
64
+ params[:css][:cached] = !!params[:css][:cached]
65
+ @form_css.update_attributes(params[:css])
66
+ if @form_css.valid?
67
+ @form_css.save
68
+ @form_version = Css::Version.new(params[:version].merge(:css => @form_css))
69
+ if @form_version.valid?
70
+ @form_version.save
71
+ redirect url(:merbiful_admin, :action => "css", :css_id => @form_css.id)
72
+ end
73
+ end
74
+ else
75
+ if @form_css
76
+ @form_version = Css::Version.get(params[:version_id])
77
+ @form_version = @form_css.latest unless @form_version
78
+ end
79
+ end
80
+ render_template_with_layout("css.html.haml")
81
+ end
82
+
83
+ def pages
84
+ if Page.count == 0
85
+ new_root = Page.create(:path => "/")
86
+ new_root_version = Page::Version.create(:page => new_root, :body => "Here be Dagon")
87
+ end
88
+ @form_page = Page.get(params[:page_id])
89
+ if request.post?
90
+ params[:page][:cached] = !!params[:page][:cached]
91
+ @form_page.update_attributes(params[:page])
92
+ if @form_page.valid?
93
+ @form_page.save
94
+ version_csses = params[:version].delete(:css)
95
+ version_jses = params[:version].delete(:js)
96
+ @form_version = Page::Version.new(params[:version].merge(:page => @form_page))
97
+ version_csses.each do |css|
98
+ @form_version.add_css(Css.get(css))
99
+ end if version_csses
100
+ version_jses.each do |js|
101
+ @form_version.add_js(Js.get(js))
102
+ end if version_jses
103
+ if @form_version.valid?
104
+ @form_version.save
105
+ redirect url(:merbiful_admin, :action => "pages", :page_id => @form_page.id)
106
+ end
107
+ end
108
+ else
109
+ if @form_page
110
+ @form_version = Page::Version.get(params[:version_id])
111
+ @form_version = @form_page.latest unless @form_version
112
+ end
113
+ end
114
+ render_with_layout(Page.all(:parent_id => nil).collect do |page|
115
+ "<ul class='root'>\n#{render_page(page)}\n</ul>"
116
+ end.join("\n"))
117
+ end
118
+
119
+ def render_css
120
+ read_template("admin.css")
121
+ end
122
+
123
+ def destroy_page
124
+ page = Page.get(params[:page_id])
125
+ page.destroy
126
+ redirect url(:merbiful_admin, :action => "pages")
127
+ end
128
+
129
+ def upload_image
130
+ path = Pathname.new(File.join(Merb.root, "public", "images", File.basename(params[:image][:filename])))
131
+ raise "H4xx0r" unless path.to_s.index(Pathname.new(Merb.root).expand_path.to_s) == 0
132
+ Pathname.new(params[:image][:tempfile].path).rename(path)
133
+ redirect url(:merbiful_admin, :action => "images")
134
+ end
135
+
136
+ def delete_image
137
+ path = Pathname.new(File.join(Merb.root, "public", params[:path])).expand_path
138
+ raise "H4xx0r" unless path.to_s.index(Pathname.new(Merb.root).expand_path.to_s) == 0
139
+ path.unlink
140
+ redirect url(:merbiful_admin, :action => "images")
141
+ end
142
+
143
+ def destroy_layout
144
+ layout = Layout.get(params[:layout_id])
145
+ layout.destroy
146
+ redirect url(:merbiful_admin, :action => "layouts")
147
+ end
148
+
149
+ def destroy_css
150
+ css = Css.get(params[:css_id])
151
+ css.destroy
152
+ redirect url(:merbiful_admin, :action => "css")
153
+ end
154
+
155
+ def destroy_js
156
+ js = Js.get(params[:js_id])
157
+ js.destroy
158
+ redirect url(:merbiful_admin, :action => "js")
159
+ end
160
+
161
+ def create_page
162
+ parent = Page.get(params[:parent_id])
163
+ new_page = Page.create(:parent => parent, :path => next_path(parent.path))
164
+ new_page_version = Page::Version.create(:page => new_page)
165
+ redirect url(:merbiful_admin, :action => "pages", :page_id => new_page.id)
166
+ end
167
+
168
+ def create_css
169
+ new_css = Css.create(:name => next_name(Css))
170
+ new_css_version = Css::Version.create(:css => new_css)
171
+ redirect url(:merbiful_admin, :action => 'css', :css_id => new_css.id)
172
+ end
173
+
174
+ def create_js
175
+ new_js = Js.create(:name => next_name(Js))
176
+ new_js_version = Js::Version.create(:js => new_js)
177
+ redirect url(:merbiful_admin, :action => 'js', :js_id => new_js.id)
178
+ end
179
+
180
+ def create_layout
181
+ new_layout = Layout.create(:name => next_name(Layout))
182
+ new_layout_version = Layout::Version.create(:layout => new_layout)
183
+ redirect url(:merbiful_admin, :action => 'layouts', :layout_id => new_layout.id)
184
+ end
185
+
186
+ def move_page_up
187
+ page = Page.get(params[:page_id])
188
+ page.position -= 1
189
+ page.save
190
+ redirect url(:merbiful_admin, :action => "pages")
191
+ end
192
+
193
+ def move_page_down
194
+ page = Page.get(params[:page_id])
195
+ page.position += 1
196
+ page.save
197
+ redirect url(:merbiful_admin, :action => "pages")
198
+ end
199
+
200
+ private
201
+
202
+ def confirm(message)
203
+ "return confirm('#{message}');"
204
+ end
205
+
206
+ def text_area_rows
207
+ 20
208
+ end
209
+
210
+ def next_path(parent_path)
211
+ index = 0
212
+ while Page.first(:path => File.join(parent_path, index.to_s))
213
+ index += 1
214
+ end
215
+ return File.join(parent_path, index.to_s)
216
+ end
217
+
218
+ def next_name(klass)
219
+ index = 0
220
+ while klass.first(:name => index.to_s)
221
+ index += 1
222
+ end
223
+ return index.to_s
224
+ end
225
+
226
+ def errors(obj, meth)
227
+ return ""
228
+ if obj.errors.on(meth)
229
+ obj.errors.on(meth).join(", ")
230
+ else
231
+ ""
232
+ end
233
+ end
234
+
235
+ def render_children(page, ind = "")
236
+ rval = []
237
+ rval << "<ul class='children'>"
238
+ page.children(:order => [:position, :id]).each do |child|
239
+ rval << render_page(child, ind + " ")
240
+ end
241
+ rval << "</ul>"
242
+ return rval.collect do |line| ind + line end.join("\n")
243
+ end
5
244
 
6
- def display(what)
7
- render what.inspect
245
+ def render_page(page, ind = "")
246
+ rval = []
247
+ rval << "<li class='page'>"
248
+ rval << "<ul class='page_info info'>"
249
+ rval << "<a href='#{url(:merbiful_admin, :action => 'pages', :page_id => page.id)}'>"
250
+ rval << "<li class='page_path'>#{page.path}</li>"
251
+ rval << "<li class='page_title'>#{page.title || "untitled"}</li>"
252
+ rval << "<li class='page_version'>ver##{page.latest.id} (#{time_ago_in_words(page.latest.created_at)} ago)</li>"
253
+ rval << "</a>"
254
+ rval << "<li class='up'><a href='#{url(:merbiful_admin, :action => 'move_page_up', :page_id => page.id)}'>&uarr;</a></li>"
255
+ rval << "<li class='down'><a href='#{url(:merbiful_admin, :action => 'move_page_down', :page_id => page.id)}'>&darr;</a></li>"
256
+ rval << "<li class='remove'><a href='#{url(:merbiful_admin, :action => 'destroy_page', :page_id => page.id)}' onclick=\"#{confirm("Are you absolutely certain that you want to destroy the page at #{page.path}? All versions will be irreversibly destroyed.")}\">-</a></li>" unless page.parent_id.nil?
257
+ rval << "<li class='append'><a href='#{url(:merbiful_admin, :action => 'create_page', :parent_id => page.id)}'>+</a></li>"
258
+ rval << "</ul>"
259
+ rval << render_template_without_layout("page_form.html.haml") if params[:page_id].to_s == page.id.to_s
260
+ rval << render_children(page, ind) unless page.children.empty?
261
+ rval << "</li>"
262
+ return rval.collect do |line| ind + line end.join("\n")
263
+ end
264
+
265
+ def read_template(template)
266
+ Pathname.new(__FILE__).parent.parent.parent.join("templates").join(template).read
267
+ end
268
+
269
+ def render_with_layout(text)
270
+ throw_content :for_layout, text
271
+ ::Haml::Engine.new(read_template("admin_layout.html.haml")).render(self)
272
+ end
273
+
274
+ def render_template_with_layout(template)
275
+ render_with_layout(::Haml::Engine.new(read_template(template)).render(self))
276
+ end
277
+
278
+ def render_template_without_layout(template)
279
+ ::Haml::Engine.new(read_template(template)).render(self)
8
280
  end
9
281
 
10
282
  end
@@ -2,14 +2,35 @@
2
2
  module Merbiful
3
3
 
4
4
  module Body
5
- def to_html(controller)
6
- if self.filter.nil?
7
- self.body
8
- else
9
- filter_class = Merbiful.const_get(self.filter.to_sym)
10
- filter_class.new.render(self.body, controller)
5
+
6
+ def render(controller, caches = {})
7
+ rval = if self.filter.blank?
8
+ self.body
9
+ else
10
+ filter_class = Merbiful.const_get(self.filter.to_sym)
11
+ filter_class.new.render(self.body, controller)
12
+ end
13
+ unless Merb.environment == "development"
14
+ caches.each do |destination, to_cache|
15
+ if to_cache
16
+ path = Pathname.new(File.join(Merb.root, "public", destination))
17
+ Merb.logger.info("Flushing to #{path.inspect}")
18
+ path.parent.mkpath
19
+ path.open("w") do |out|
20
+ out.write(rval)
21
+ end
22
+ end
23
+ end
11
24
  end
25
+ return rval
26
+ end
27
+
28
+ def clear_cache(target)
29
+ return if target == "/"
30
+ path = Pathname.new(File.join(Merb.root, "public", target))
31
+ path.unlink if path.exist?
12
32
  end
33
+
13
34
  end
14
35
 
15
36
  end
@@ -17,23 +17,34 @@ module Merbiful
17
17
  property :updated_at, DateTime
18
18
 
19
19
  has n, :css_nesses, :class_name => "Merbiful::Css::Ness"
20
- has n, :page_versions, :through => :css_nesses, :class_name => "Merbiful::Page::Version"
20
+ has n, :page_versions, :through => :css_nesses, :class_name => "Merbiful::Page::Version", :child_key => [:css_id]
21
21
  has n, :css_versions, :class_name => "Merbiful::Css::Version"
22
22
 
23
+ before :destroy do
24
+ css_nesses.destroy!
25
+ css_versions.destroy!
26
+ end
27
+
23
28
  def latest
24
- css_versions.first(:order => [:id.desc])
29
+ css_versions.first(:css_id => self.id, :order => [:id.desc])
25
30
  end
26
31
 
27
- def_delegators :latest, :render
32
+ def_delegators :latest, :render, :body, :filter
33
+
34
+ def path
35
+ "/stylesheets/#{latest.id}"
36
+ end
28
37
 
29
38
  class Ness
30
39
  include DataMapper::Resource
31
40
  include DataMapper::Validate
32
41
 
33
42
  property :id, Serial
43
+ property :page_version_id, Integer
44
+ property :css_id, Integer
34
45
 
35
- belongs_to :css, :class_name => "Merbiful::Css"
36
- belongs_to :page_version, :class_name => "Merbiful::Page::Version"
46
+ belongs_to :css, :class_name => "Merbiful::Css", :child_key => [:css_id]
47
+ belongs_to :page_version, :class_name => "Merbiful::Page::Version", :child_key => [:page_version_id]
37
48
  end
38
49
 
39
50
  class Version
@@ -54,6 +65,10 @@ module Merbiful
54
65
 
55
66
  belongs_to :css, :class_name => "Merbiful::Css"
56
67
 
68
+ before :save do
69
+ clear_cache(css.path) if css.latest
70
+ end
71
+
57
72
  end
58
73
 
59
74
  end