sferik-merb-admin 0.1.7

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 (104) hide show
  1. data/LICENSE +20 -0
  2. data/README.markdown +55 -0
  3. data/Rakefile +69 -0
  4. data/app/controllers/application.rb +17 -0
  5. data/app/controllers/forms.rb +85 -0
  6. data/app/helpers/application_helper.rb +66 -0
  7. data/app/helpers/forms_helper.rb +112 -0
  8. data/app/views/forms/_big_decimal.html.erb +8 -0
  9. data/app/views/forms/_date.html.erb +8 -0
  10. data/app/views/forms/_date_time.html.erb +8 -0
  11. data/app/views/forms/_float.html.erb +8 -0
  12. data/app/views/forms/_integer.html.erb +12 -0
  13. data/app/views/forms/_string.html.erb +16 -0
  14. data/app/views/forms/_time.html.erb +8 -0
  15. data/app/views/forms/_true_class.html.erb +5 -0
  16. data/app/views/forms/delete.html.erb +12 -0
  17. data/app/views/forms/edit.html.erb +23 -0
  18. data/app/views/forms/index.html.erb +22 -0
  19. data/app/views/forms/list.html.erb +64 -0
  20. data/app/views/forms/new.html.erb +19 -0
  21. data/app/views/layout/_message.html.erb +10 -0
  22. data/app/views/layout/dashboard.html.erb +37 -0
  23. data/app/views/layout/form.html.erb +51 -0
  24. data/app/views/layout/list.html.erb +45 -0
  25. data/lib/merb-admin/merbtasks.rb +103 -0
  26. data/lib/merb-admin/slicetasks.rb +20 -0
  27. data/lib/merb-admin/spectasks.rb +53 -0
  28. data/lib/merb-admin.rb +101 -0
  29. data/public/images/arrow-down.gif +0 -0
  30. data/public/images/arrow-up.gif +0 -0
  31. data/public/images/changelist-bg.gif +0 -0
  32. data/public/images/changelist-bg_rtl.gif +0 -0
  33. data/public/images/chooser-bg.gif +0 -0
  34. data/public/images/chooser_stacked-bg.gif +0 -0
  35. data/public/images/default-bg-reverse.gif +0 -0
  36. data/public/images/default-bg.gif +0 -0
  37. data/public/images/deleted-overlay.gif +0 -0
  38. data/public/images/icon-no.gif +0 -0
  39. data/public/images/icon-unknown.gif +0 -0
  40. data/public/images/icon-yes.gif +0 -0
  41. data/public/images/icon_addlink.gif +0 -0
  42. data/public/images/icon_alert.gif +0 -0
  43. data/public/images/icon_calendar.gif +0 -0
  44. data/public/images/icon_changelink.gif +0 -0
  45. data/public/images/icon_clock.gif +0 -0
  46. data/public/images/icon_deletelink.gif +0 -0
  47. data/public/images/icon_error.gif +0 -0
  48. data/public/images/icon_searchbox.png +0 -0
  49. data/public/images/icon_success.gif +0 -0
  50. data/public/images/inline-delete-8bit.png +0 -0
  51. data/public/images/inline-delete.png +0 -0
  52. data/public/images/inline-restore-8bit.png +0 -0
  53. data/public/images/inline-restore.png +0 -0
  54. data/public/images/inline-splitter-bg.gif +0 -0
  55. data/public/images/nav-bg-grabber.gif +0 -0
  56. data/public/images/nav-bg-reverse.gif +0 -0
  57. data/public/images/nav-bg.gif +0 -0
  58. data/public/images/selector-add.gif +0 -0
  59. data/public/images/selector-addall.gif +0 -0
  60. data/public/images/selector-remove.gif +0 -0
  61. data/public/images/selector-removeall.gif +0 -0
  62. data/public/images/selector-search.gif +0 -0
  63. data/public/images/selector_stacked-add.gif +0 -0
  64. data/public/images/selector_stacked-remove.gif +0 -0
  65. data/public/images/tool-left.gif +0 -0
  66. data/public/images/tool-left_over.gif +0 -0
  67. data/public/images/tool-right.gif +0 -0
  68. data/public/images/tool-right_over.gif +0 -0
  69. data/public/images/tooltag-add.gif +0 -0
  70. data/public/images/tooltag-add_over.gif +0 -0
  71. data/public/images/tooltag-arrowright.gif +0 -0
  72. data/public/images/tooltag-arrowright_over.gif +0 -0
  73. data/public/javascripts/CollapsedFieldsets.js +85 -0
  74. data/public/javascripts/DateTimeShortcuts.js +255 -0
  75. data/public/javascripts/RelatedObjectLookups.js +96 -0
  76. data/public/javascripts/SelectBox.js +111 -0
  77. data/public/javascripts/SelectFilter2.js +113 -0
  78. data/public/javascripts/actions.js +39 -0
  79. data/public/javascripts/calendar.js +143 -0
  80. data/public/javascripts/core.js +176 -0
  81. data/public/javascripts/dateparse.js +233 -0
  82. data/public/javascripts/getElementsBySelector.js +167 -0
  83. data/public/javascripts/i18n.js +33 -0
  84. data/public/javascripts/master.js +0 -0
  85. data/public/javascripts/ordering.js +137 -0
  86. data/public/javascripts/timeparse.js +94 -0
  87. data/public/javascripts/urlify.js +140 -0
  88. data/public/stylesheets/base.css +746 -0
  89. data/public/stylesheets/changelists.css +269 -0
  90. data/public/stylesheets/dashboard.css +24 -0
  91. data/public/stylesheets/forms.css +327 -0
  92. data/public/stylesheets/global.css +142 -0
  93. data/public/stylesheets/ie.css +51 -0
  94. data/public/stylesheets/layout.css +29 -0
  95. data/public/stylesheets/login.css +54 -0
  96. data/public/stylesheets/master.css +2 -0
  97. data/public/stylesheets/null.css +1 -0
  98. data/public/stylesheets/patch-iewin.css +8 -0
  99. data/public/stylesheets/rtl.css +206 -0
  100. data/public/stylesheets/widgets.css +506 -0
  101. data/spec/controller/forms_spec.rb +41 -0
  102. data/spec/merb-admin_spec.rb +5 -0
  103. data/spec/spec_helper.rb +58 -0
  104. metadata +213 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Erik Michaels-Ober
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,55 @@
1
+ # MerbAdmin
2
+
3
+ **MerbAdmin is a merb slice that provides an easy-to-use interface for managing your data.**
4
+
5
+ It currently offers the features listed [here](http://sferik.tadalist.com/lists/1352791/public).
6
+
7
+ ## Get it
8
+
9
+ At the command prompt, type:
10
+
11
+ git clone git://github.com/sferik/merb-admin.git
12
+ cd merb-admin
13
+ sudo rake install
14
+
15
+ ## Install it
16
+
17
+ In your app, add the following dependency to `config/dependencies.rb`:
18
+
19
+ dependency "merb-admin", "0.1.7"
20
+
21
+ Add the following route to `config/router.rb`:
22
+
23
+ slice(:MerbAdmin, :name_prefix => nil, :path_prefix => "", :default_routes => false)
24
+
25
+ Then, run the following rake task:
26
+
27
+ rake slices:merb-admin:install
28
+
29
+ ## Configure it (optional)
30
+
31
+ You can configuring the merb-admin slice in a before_app_loads block:
32
+
33
+ Merb::BootLoader.before_app_loads do
34
+ Merb::Slices::config[:merb_admin][:app_name] = "My App"
35
+ end
36
+
37
+ ## Run it
38
+
39
+ Start the server:
40
+
41
+ merb
42
+
43
+ You should now be able to administer your site at [http://localhost:4000/admin](http://localhost:4000/admin).
44
+
45
+ Please report any problems you encounter to <sferik@gmail.com> or [@sferik](http://twitter.com/home/?status=@sferik%20) on Twitter.
46
+
47
+ ## WARNING
48
+
49
+ MerbAdmin does not implement any authorization scheme. Make sure to apply authorization logic before deploying to production!
50
+
51
+ ## Acknowledgements
52
+
53
+ Many thanks to [Wilson Miner](http://www.wilsonminer.com) for contributing the stylesheets and javascripts from [Django](http://www.djangoproject.com).
54
+
55
+ Also, thanks to [beer](http://www.anchorbrewing.com).
data/Rakefile ADDED
@@ -0,0 +1,69 @@
1
+ require "rubygems"
2
+ require "rake/gempackagetask"
3
+
4
+ require "merb-core"
5
+ require "merb-core/tasks/merb"
6
+
7
+ dependency "dm-core"
8
+ dependency "merb_datamapper"
9
+
10
+ GEM_NAME = "merb-admin"
11
+ AUTHOR = "Erik Michaels-Ober"
12
+ EMAIL = "sferik@gmail.com"
13
+ HOMEPAGE = "http://twitter.com/sferik"
14
+ SUMMARY = "MerbAdmin is a merb slice that provides an easy-to-use interface for managing your data."
15
+ GEM_VERSION = "0.1.7"
16
+
17
+ spec = Gem::Specification.new do |s|
18
+ s.rubyforge_project = "merb"
19
+ s.name = GEM_NAME
20
+ s.version = GEM_VERSION
21
+ s.platform = Gem::Platform::RUBY
22
+ s.has_rdoc = false
23
+ s.extra_rdoc_files = ["README.markdown", "LICENSE"]
24
+ s.summary = SUMMARY
25
+ s.description = s.summary
26
+ s.author = AUTHOR
27
+ s.email = EMAIL
28
+ s.homepage = HOMEPAGE
29
+ s.add_dependency("merb-slices", Merb::VERSION)
30
+ s.add_dependency("merb_datamapper", Merb::VERSION)
31
+ s.add_dependency("dm-core", ">= 0.9.11")
32
+ s.add_dependency("dm-is-paginated", ">= 0.0.1")
33
+ s.require_path = "lib"
34
+ s.files = %w(LICENSE README.markdown Rakefile) + Dir.glob("{lib,spec,app,public,stubs}/**/*")
35
+ s.post_install_message = <<-POST_INSTALL_MESSAGE
36
+ #{"*" * 80}
37
+
38
+ WARNING: MerbAdmin does not implement any authorization scheme.
39
+ Make sure to apply authorization logic before deploying to production!
40
+
41
+ #{"*" * 80}
42
+ POST_INSTALL_MESSAGE
43
+ end
44
+
45
+ Rake::GemPackageTask.new(spec) do |pkg|
46
+ pkg.gem_spec = spec
47
+ end
48
+
49
+ desc "Install the gem"
50
+ task :install do
51
+ Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
52
+ end
53
+
54
+ desc "Uninstall the gem"
55
+ task :uninstall do
56
+ Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
57
+ end
58
+
59
+ desc "Create a gemspec file"
60
+ task :gemspec do
61
+ File.open("#{GEM_NAME}.gemspec", "w") do |file|
62
+ file.puts spec.to_ruby
63
+ end
64
+ end
65
+
66
+ require "spec/rake/spectask"
67
+ require "merb-core/test/tasks/spectasks"
68
+ desc "Default: run spec examples"
69
+ task :default => "spec"
@@ -0,0 +1,17 @@
1
+ class MerbAdmin::Application < Merb::Controller
2
+
3
+ controller_for_slice
4
+
5
+ before :set_model, :exclude => "index"
6
+
7
+ def set_model
8
+ @model_name = params[:model_name].to_s.camel_case.singularize
9
+ begin
10
+ @model = eval(@model_name)
11
+ rescue StandardError
12
+ raise NotFound
13
+ end
14
+ @properties = @model.properties.to_a
15
+ end
16
+
17
+ end
@@ -0,0 +1,85 @@
1
+ class MerbAdmin::Forms < MerbAdmin::Application
2
+ layout :form
3
+
4
+ def index
5
+ @models = DataMapper::Resource.descendants.to_a.sort{|a, b| a.to_s <=> b.to_s}
6
+ # remove DataMapperSessionStore because it's included by default
7
+ @models -= [Merb::DataMapperSessionStore] if Merb.const_defined?(:DataMapperSessionStore)
8
+ render(:layout => "dashboard")
9
+ end
10
+
11
+ def list
12
+ if params[:all]
13
+ @instances = @model.all(:limit => 200).reverse
14
+ else
15
+ # monkey patch pagination
16
+ @model.class_eval("is_paginated") unless @model.respond_to?(:paginated)
17
+ @current_page = (params[:page] || 1).to_i
18
+ @page_count, @instances = @model.paginated(:page => @current_page, :per_page => 100)
19
+ end
20
+ render(:layout => "list")
21
+ end
22
+
23
+ def new
24
+ @instance = @model.new
25
+ render(:layout => "form")
26
+ end
27
+
28
+ def edit(id)
29
+ @instance = @model.get(id)
30
+ raise NotFound unless @instance
31
+ render(:layout => "form")
32
+ end
33
+
34
+ def create
35
+ instance = eval("params[:#{@model_name.snake_case}]")
36
+ @instance = @model.new(instance)
37
+ if @instance.save
38
+ if params[:_continue]
39
+ redirect slice_url(:admin_edit, :model_name => @model_name.snake_case, :id => @instance.id), :message => {:notice => "#{@model_name} was successfully created"}
40
+ elsif params[:_add_another]
41
+ redirect slice_url(:admin_new, :model_name => @model_name.snake_case), :message => {:notice => "#{@model_name} was successfully created"}
42
+ else
43
+ redirect slice_url(:admin_list, :model_name => @model_name.snake_case), :message => {:notice => "#{@model_name} was successfully created"}
44
+ end
45
+ else
46
+ message[:error] = "#{@model_name} failed to be created"
47
+ render(:new, :layout => "form")
48
+ end
49
+ end
50
+
51
+ def update(id)
52
+ instance = eval("params[:#{@model_name.snake_case}]")
53
+ @instance = @model.get(id)
54
+ raise NotFound unless @instance
55
+ if @instance.update_attributes(instance)
56
+ if params[:_continue]
57
+ redirect slice_url(:admin_edit, :model_name => @model_name.snake_case, :id => @instance.id), :message => {:notice => "#{@model_name} was successfully updated"}
58
+ elsif params[:_add_another]
59
+ redirect slice_url(:admin_new, :model_name => @model_name.snake_case), :message => {:notice => "#{@model_name} was successfully updated"}
60
+ else
61
+ redirect slice_url(:admin_list, :model_name => @model_name.snake_case), :message => {:notice => "#{@model_name} was successfully updated"}
62
+ end
63
+ else
64
+ message[:error] = "#{@model_name} failed to be updated"
65
+ render(:edit, :layout => "form")
66
+ end
67
+ end
68
+
69
+ def delete(id)
70
+ @instance = @model.get(id)
71
+ raise NotFound unless @instance
72
+ render(:layout => "form")
73
+ end
74
+
75
+ def destroy(id)
76
+ @instance = @model.get(id)
77
+ raise NotFound unless @instance
78
+ if @instance.destroy
79
+ redirect slice_url(:admin_list, :model_name => @model_name.snake_case), :message => {:notice => "#{@model_name} was successfully destroyed"}
80
+ else
81
+ raise InternalServerError
82
+ end
83
+ end
84
+
85
+ end
@@ -0,0 +1,66 @@
1
+ module Merb
2
+ module MerbAdmin
3
+ module ApplicationHelper
4
+
5
+ # @param *segments<Array[#to_s]> Path segments to append.
6
+ #
7
+ # @return <String>
8
+ # A path relative to the public directory, with added segments.
9
+ def image_path(*segments)
10
+ public_path_for(:image, *segments)
11
+ end
12
+
13
+ # @param *segments<Array[#to_s]> Path segments to append.
14
+ #
15
+ # @return <String>
16
+ # A path relative to the public directory, with added segments.
17
+ def javascript_path(*segments)
18
+ public_path_for(:javascript, *segments)
19
+ end
20
+
21
+ # @param *segments<Array[#to_s]> Path segments to append.
22
+ #
23
+ # @return <String>
24
+ # A path relative to the public directory, with added segments.
25
+ def stylesheet_path(*segments)
26
+ public_path_for(:stylesheet, *segments)
27
+ end
28
+
29
+ # Construct a path relative to the public directory
30
+ #
31
+ # @param <Symbol> The type of component.
32
+ # @param *segments<Array[#to_s]> Path segments to append.
33
+ #
34
+ # @return <String>
35
+ # A path relative to the public directory, with added segments.
36
+ def public_path_for(type, *segments)
37
+ ::MerbAdmin.public_path_for(type, *segments)
38
+ end
39
+
40
+ # Construct an app-level path.
41
+ #
42
+ # @param <Symbol> The type of component.
43
+ # @param *segments<Array[#to_s]> Path segments to append.
44
+ #
45
+ # @return <String>
46
+ # A path within the host application, with added segments.
47
+ def app_path_for(type, *segments)
48
+ ::MerbAdmin.app_path_for(type, *segments)
49
+ end
50
+
51
+ # Construct a slice-level path.
52
+ #
53
+ # @param <Symbol> The type of component.
54
+ # @param *segments<Array[#to_s]> Path segments to append.
55
+ #
56
+ # @return <String>
57
+ # A path within the slice source (Gem), with added segments.
58
+ def slice_path_for(type, *segments)
59
+ ::MerbAdmin.slice_path_for(type, *segments)
60
+ end
61
+
62
+
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,112 @@
1
+ require 'builder'
2
+ module Merb
3
+ module MerbAdmin
4
+ module FormsHelper
5
+ # Given a page count and the current page, we generate a set of pagination
6
+ # links.
7
+ #
8
+ # * We use an inner and outer window into a list of links. For a set of
9
+ # 20 pages with the current page being 10:
10
+ # outer_window:
11
+ # 1 2 ..... 19 20
12
+ # inner_window
13
+ # 5 6 7 8 9 10 11 12 13 14
14
+ #
15
+ # This is totally adjustable, or can be turned off by giving the
16
+ # :inner_window setting a value of nil.
17
+ #
18
+ # * Options
19
+ # :left_cut_label => <em>text_for_cut</em>::
20
+ # Used when the page numbers need to be cut off to prevent the set of
21
+ # pagination links from being too long.
22
+ # Defaults to '&hellip;'
23
+ # :right_cut_label => <em>text_for_cut</em>::
24
+ # Same as :left_cut_label but for the right side of numbers.
25
+ # Defaults to '&hellip;'
26
+ # :outer_window => <em>number_of_pages</em>::
27
+ # Sets the number of pages to include in the outer 'window'
28
+ # Defaults to 2
29
+ # :inner_window => <em>number_of_pages</em>::
30
+ # Sets the number of pags to include in the inner 'window'
31
+ # Defaults to 7
32
+ # :page_param => <em>name_of_page_paramiter</em>
33
+ # Sets the name of the paramiter the paginator uses to return what
34
+ # page is being requested.
35
+ # Defaults to 'page'
36
+ # :url => <em>url_for_links</em>
37
+ # Provides the base url to use in the page navigation links.
38
+ # Defaults to ''
39
+ def paginate(current_page, page_count, options = {})
40
+ options.reverse_merge!({
41
+ :left_cut_label => '&hellip;',
42
+ :right_cut_label => '&hellip;',
43
+ :outer_window => 2,
44
+ :inner_window => 7,
45
+ :page_param => 'page',
46
+ :url => ''
47
+ })
48
+ url = options.delete :url
49
+ url << (url.include?('?') ? '&' : '?') << options[:page_param]
50
+
51
+ pages = {
52
+ :all => (1..page_count).to_a,
53
+ :left => [],
54
+ :center => [],
55
+ :right => []
56
+ }
57
+
58
+ # Only worry about using our 'windows' if the page count is less then
59
+ # our windows combined.
60
+ if options[:inner_window].nil? || ((options[:outer_window] * 2) + options[:inner_window] + 2) >= page_count
61
+ pages[:center] = pages[:all]
62
+ else
63
+ pages[:left] = pages[:all][0, options[:outer_window]]
64
+ pages[:right] = pages[:all][page_count - options[:outer_window], options[:outer_window]]
65
+ pages[:center] = case current_page
66
+ # allow the inner 'window' to shift to right when close to the left edge
67
+ # Ex: 1 2 [3] 4 5 6 7 8 9 ... 20
68
+ when -infinity .. (options[:inner_window] / 2) + 3
69
+ pages[:all][options[:outer_window], options[:inner_window]] +
70
+ [options[:right_cut_label]]
71
+ # allow the inner 'window' to shift left when close to the right edge
72
+ # Ex: 1 2 ... 12 13 14 15 16 [17] 18 19 20
73
+ when (page_count - (options[:inner_window] / 2.0).ceil) - 1 .. infinity
74
+ [options[:left_cut_label]] +
75
+ pages[:all][page_count - options[:inner_window] - options[:outer_window], options[:inner_window]]
76
+ # Display the unshifed window
77
+ # ex: 1 2 ... 5 6 7 [8] 9 10 11 ... 19 20
78
+ else
79
+ [options[:left_cut_label]] +
80
+ pages[:all][current_page - (options[:inner_window] / 2) - 1, options[:inner_window]] +
81
+ [options[:right_cut_label]]
82
+ end
83
+ end
84
+
85
+ b = []
86
+
87
+ [pages[:left], pages[:center], pages[:right]].each do |p|
88
+ p.each do |page_number|
89
+ case page_number
90
+ when String
91
+ b << page_number
92
+ when current_page
93
+ b << Builder::XmlMarkup.new.span(page_number, :class => "this-page")
94
+ when page_count
95
+ b << Builder::XmlMarkup.new.a(page_number, :class => "end", :href => "#{url}=#{page_number}")
96
+ else
97
+ b << Builder::XmlMarkup.new.a(page_number, :href => "#{url}=#{page_number}")
98
+ end
99
+ end
100
+ end
101
+
102
+ b.join(" ")
103
+ end
104
+
105
+ private
106
+
107
+ def infinity
108
+ 1.0 / 0
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,8 @@
1
+ <div class="form-row page">
2
+ <div>
3
+ <%= text_field(property.name, :maxlength => property.length, :label => property.field.capitalize.gsub('_', ' ')) %>
4
+ <p class="help">
5
+ <%= !property.nullable? || property.serial? ? "Required." : "Optional." %>
6
+ </p>
7
+ </div>
8
+ </div>
@@ -0,0 +1,8 @@
1
+ <div class="form-row page">
2
+ <div>
3
+ <%= text_field(property.name, :class => "vDateField", :label => property.field.capitalize.gsub('_', ' '), :value => eval("@instance.#{property.field}").strftime("%Y-%m-%d")) %>
4
+ <p class="help">
5
+ <%= !property.nullable? ? "Required." : "Optional." %>
6
+ </p>
7
+ </div>
8
+ </div>
@@ -0,0 +1,8 @@
1
+ <div class="form-row page">
2
+ <div>
3
+ <%= text_field(property.name, :class => "vDateField", :label => property.field.capitalize.gsub('_', ' '), :value => eval("@instance.#{property.field}").strftime("%Y-%m-%d %H:%M:%S")) %>
4
+ <p class="help">
5
+ <%= !property.nullable? ? "Required." : "Optional." %>
6
+ </p>
7
+ </div>
8
+ </div>
@@ -0,0 +1,8 @@
1
+ <div class="form-row page">
2
+ <div>
3
+ <%= text_field(property.name, :maxlength => property.length, :label => property.field.capitalize.gsub('_', ' ')) %>
4
+ <p class="help">
5
+ <%= !property.nullable? || property.serial? ? "Required." : "Optional." %>
6
+ </p>
7
+ </div>
8
+ </div>
@@ -0,0 +1,12 @@
1
+ <div class="form-row page">
2
+ <div>
3
+ <% if property.type.respond_to?(:flag_map) #Enum or Flag type %>
4
+ <%= select(property.name, :collection => property.type.flag_map.map{|x| [x[1], x[1].to_s.capitalize.gsub('_', ' ')]}.sort{|a, b| a[1] <=> b[1]}, :label => property.field.capitalize.gsub('_', ' ')) %>
5
+ <% else %>
6
+ <%= text_field(property.name, :maxlength => property.length, :label => property.field.capitalize.gsub('_', ' ')) %>
7
+ <% end %>
8
+ <p class="help">
9
+ <%= !property.nullable? || property.serial? ? "Required." : "Optional." %>
10
+ </p>
11
+ </div>
12
+ </div>
@@ -0,0 +1,16 @@
1
+ <div class="form-row page">
2
+ <div>
3
+ <% case property.type.to_s %>
4
+ <% when "DataMapper::Types::Text" %>
5
+ <%= text_area(property.name, :cols => 80, :label => property.field.capitalize.gsub('_', ' ')) %>
6
+ <p class="help">
7
+ <%= property.nullable? ? "Required." : "Optional." %>
8
+ </p>
9
+ <% else %>
10
+ <%= text_field(property.name, :size => [50, property.length].min, :maxlength => property.length, :label => property.field.capitalize.gsub('_', ' ')) %>
11
+ <p class="help">
12
+ <%= !property.nullable? ? "Required." : "Optional." %> <%= property.length %> <%= property.length == 1 ? "character." : "characters or fewer." %>
13
+ </p>
14
+ <% end %>
15
+ </div>
16
+ </div>
@@ -0,0 +1,8 @@
1
+ <div class="form-row page">
2
+ <div>
3
+ <%= text_field(property.name, :class => "vTimeField", :label => property.field.capitalize.gsub('_', ' '), :value => eval("@instance.#{property.field}").strftime("%H:%M:%S")) %>
4
+ <p class="help">
5
+ <%= !property.nullable? ? "Required." : "Optional." %>
6
+ </p>
7
+ </div>
8
+ </div>
@@ -0,0 +1,5 @@
1
+ <div class="form-row page">
2
+ <div>
3
+ <%= check_box(property.name, :label => property.field.capitalize.gsub('_', ' ')) %>
4
+ </div>
5
+ </div>
@@ -0,0 +1,12 @@
1
+ <p>Are you sure you want to delete the <%= @model_name.snake_case.gsub('_', ' ') %>? All of the following related items will be deleted:</p>
2
+ <ul>
3
+ <li>
4
+ <a href="<%= slice_url(:admin_edit, :model_name => @model_name.snake_case, :id => @instance.id) %>"><%= @model_name %></a>
5
+ </li>
6
+ </ul>
7
+ <%= form_for(@instance, :action => slice_url(:admin_destroy, :model_name => @model_name.snake_case, :id => @instance.id), :method => :delete) do %>
8
+ <div>
9
+ <%= submit "Yes, I'm sure" %>
10
+ </div>
11
+ <% end =%>
12
+
@@ -0,0 +1,23 @@
1
+ <div id="content-main">
2
+ <ul class="object-tools">
3
+ <li><a href="<%= "/#{@model_name.snake_case}/#{@instance.id}" %>" target="_blank" class="viewsitelink">View on site</a></li>
4
+ </ul>
5
+ <%= form_for(@instance, :action => slice_url(:admin_update, :model_name => @model_name.snake_case, :id => @instance.id)) do %>
6
+ <div>
7
+ <fieldset class="module aligned">
8
+ <h2><%= @model_name %> info</h2>
9
+ <% @properties.each do |property| %>
10
+ <% next if [:id, :created_at, :created_on, :updated_at, :updated_on].include?(property.name) %>
11
+ <%= partial property.primitive.to_s.snake_case, :property => property -%>
12
+ <% end %>
13
+ </fieldset>
14
+ <div class="submit-row" >
15
+ <%= submit "Save", :class => "default", :name => "_save" %>
16
+ <p class="deletelink-box"><a href="<%= slice_url(:admin_delete, :model_name => @model_name.snake_case, :id => @instance.id) %>" class="deletelink">Delete</a></p>
17
+ <%= submit "Save and add another", :name => "_add_another" %>
18
+ <%= submit "Save and continue editing", :name => "_continue" %>
19
+ </div>
20
+ </div>
21
+ <% end =%>
22
+
23
+ </div>
@@ -0,0 +1,22 @@
1
+ <div id="content-main">
2
+ <div class="module">
3
+ <table summary="Models available in the application.">
4
+ <caption><a href="<%= slice_url(:admin_dashboard) %>" class="section">Models</a></caption>
5
+ <% @models.map{|m| m.to_s}.each do |model_name| %>
6
+ <tr>
7
+ <th scope="row"><a href="<%= slice_url(:admin_list, :model_name => model_name.snake_case) %>"><%=h model_name.pluralize %></a></th>
8
+ <td><a href="<%= slice_url(:admin_new, :model_name => model_name.snake_case) %>" class="addlink">Add</a></td>
9
+ <td><a href="<%= slice_url(:admin_list, :model_name => model_name.snake_case) %>" class="changelink">Edit</a></td>
10
+ </tr>
11
+ <% end %>
12
+ </table>
13
+ </div>
14
+ </div>
15
+ <div id="content-related">
16
+ <div class="module" id="recent-actions-module">
17
+ <h2>Recent Actions</h2>
18
+ <h3>My Actions</h3>
19
+ <p>None available</p>
20
+ </div>
21
+ </div>
22
+ <br class="clear" />
@@ -0,0 +1,64 @@
1
+ <div id="content-main">
2
+ <ul class="object-tools">
3
+ <li>
4
+ <a href="<%= slice_url(:admin_new, :model_name => @model_name.snake_case) %>" class="addlink">Add <%=h @model_name.snake_case.gsub('_', ' ') %></a>
5
+ </li>
6
+ </ul>
7
+ <div class="module filtered" id="changelist">
8
+ <table cellspacing="0">
9
+ <thead>
10
+ <tr>
11
+ <% @properties.each do |property| %>
12
+ <th>
13
+ <%= property.field.capitalize.gsub('_', ' ') %>
14
+ </th>
15
+ <% end %>
16
+ </tr>
17
+ </thead>
18
+ <tbody>
19
+ <% @instances.each_with_index do |instance, index| %>
20
+ <tr class="row<%= index % 2 == 0 ? '1' : '2' %>">
21
+ <% @properties.each do |property| %>
22
+ <td>
23
+ <a href="<%= slice_url(:admin_edit, :model_name => @model_name.snake_case, :id => eval("instance.id")) %>">
24
+ <% case property.primitive.to_s %>
25
+ <% when "TrueClass" %>
26
+ <% if eval("instance.#{property.field}") == true %>
27
+ <img alt="True" src="<%= image_path("icon-yes.gif") %>"/>
28
+ <% else %>
29
+ <img alt="False" src="<%= image_path("icon-no.gif") %>"/>
30
+ <% end %>
31
+ <% when "DateTime" %>
32
+ <%= eval("instance.#{property.field}").strftime("%b. %d, %Y, %I:%M%p") %>
33
+ <% when "Date" %>
34
+ <%= eval("instance.#{property.field}").strftime("%b. %d, %Y") %>
35
+ <% when "Time" %>
36
+ <%= eval("instance.#{property.field}").strftime("%I:%M%p") %>
37
+ <% when "Integer" %>
38
+ <% if property.type.respond_to?(:flag_map) #Enum or Flag type %>
39
+ <%= eval("instance.#{property.field}").to_s.capitalize.gsub('_', ' ') %>
40
+ <% else %>
41
+ <%= eval("instance.#{property.field}") %>
42
+ <% end %>
43
+ <% when "BigDecimal" %>
44
+ <%= eval("instance.#{property.field}") %>
45
+ <% when "Float" %>
46
+ <%= eval("instance.#{property.field}") %>
47
+ <% when "String" %>
48
+ <%= eval("instance.#{property.field}").to_s.truncate(50) %>
49
+ <% end %>
50
+ </a>
51
+ </td>
52
+ <% end %>
53
+ </tr>
54
+ <% end %>
55
+ </tbody>
56
+ </table>
57
+ <p class="paginator">
58
+ <%= paginate(@current_page, @page_count, :url => slice_url(:admin_list, :model_name => @model_name.snake_case)) if @page_count.to_i > 1 %>
59
+ <%= @model.count %> <%= @model.count == 1 ? @model_name.snake_case.gsub('_', ' ') : @model_name.snake_case.gsub('_', ' ').pluralize %>
60
+ <%= "<a href=\"#{slice_url(:admin_list, :model_name => @model_name.snake_case, :all => true)}\" class=\"showall\">Show all</a>" if @page_count.to_i == 2 %>
61
+ </p>
62
+ </div>
63
+ </div>
64
+ <br class="clear" />
@@ -0,0 +1,19 @@
1
+ <div id="content-main">
2
+ <%= form_for(@instance, :action => slice_url(:admin_create, :model_name => @model_name.snake_case)) do %>
3
+ <div>
4
+ <fieldset class="module aligned">
5
+ <h2><%= @model_name %> info</h2>
6
+ <% @properties.each do |property| %>
7
+ <% next if [:id, :created_at, :created_on, :updated_at, :updated_on].include?(property.name) %>
8
+ <%= partial property.primitive.to_s.snake_case, :property => property -%>
9
+ <% end %>
10
+ </fieldset>
11
+ <div class="submit-row" >
12
+ <%= submit "Save", :class => "default", :name => "_save" %>
13
+ <%= submit "Save and add another", :name => "_add_another" %>
14
+ <%= submit "Save and continue editing", :name => "_continue" %>
15
+ </div>
16
+ </div>
17
+ <% end =%>
18
+
19
+ </div>