milk 0.0.1 → 0.0.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.
Files changed (160) hide show
  1. data/Rakefile +1 -1
  2. data/lib/milk.rb +13 -0
  3. data/lib/milk/application.rb +14 -0
  4. data/lib/milk/component.rb +67 -40
  5. data/lib/milk/field.rb +46 -2
  6. data/lib/milk/fields/component.haml +8 -0
  7. data/lib/milk/fields/component_array.haml +3 -0
  8. data/lib/milk/fields/component_view.haml +2 -0
  9. data/lib/milk/fields/image_chooser.haml +7 -0
  10. data/lib/milk/fields/image_chooser.rb +22 -0
  11. data/lib/milk/fields/markdown_field.haml +1 -0
  12. data/lib/milk/fields/page_chooser.haml +3 -0
  13. data/lib/milk/fields/page_chooser.rb +13 -0
  14. data/lib/milk/fields/sprite_chooser.haml +6 -0
  15. data/lib/milk/fields/sprite_chooser.rb +15 -0
  16. data/lib/milk/fields/text_field.haml +1 -0
  17. data/lib/milk/fields/xhtml.haml +253 -2
  18. data/lib/milk/page.rb +56 -14
  19. metadata +11 -174
  20. data/doc/classes/Milk.html +0 -198
  21. data/doc/classes/Milk.src/M000005.html +0 -17
  22. data/doc/classes/Milk/Application.html +0 -209
  23. data/doc/classes/Milk/Application.src/M000007.html +0 -69
  24. data/doc/classes/Milk/Application.src/M000008.html +0 -38
  25. data/doc/classes/Milk/Component.html +0 -397
  26. data/doc/classes/Milk/Component.src/M000014.html +0 -19
  27. data/doc/classes/Milk/Component.src/M000015.html +0 -16
  28. data/doc/classes/Milk/Component.src/M000016.html +0 -15
  29. data/doc/classes/Milk/Component.src/M000017.html +0 -15
  30. data/doc/classes/Milk/Component.src/M000018.html +0 -15
  31. data/doc/classes/Milk/Component.src/M000019.html +0 -15
  32. data/doc/classes/Milk/Component.src/M000020.html +0 -15
  33. data/doc/classes/Milk/Component.src/M000021.html +0 -15
  34. data/doc/classes/Milk/Component.src/M000022.html +0 -18
  35. data/doc/classes/Milk/Component.src/M000023.html +0 -21
  36. data/doc/classes/Milk/Component.src/M000024.html +0 -15
  37. data/doc/classes/Milk/Component.src/M000025.html +0 -22
  38. data/doc/classes/Milk/ExternalCompilerError.html +0 -117
  39. data/doc/classes/Milk/Field.html +0 -114
  40. data/doc/classes/Milk/Fields.html +0 -173
  41. data/doc/classes/Milk/Fields/ComponentArray.html +0 -114
  42. data/doc/classes/Milk/Fields/ImageChooser.html +0 -114
  43. data/doc/classes/Milk/Fields/MarkdownField.html +0 -114
  44. data/doc/classes/Milk/Fields/PageChooser.html +0 -114
  45. data/doc/classes/Milk/Fields/SpriteChooser.html +0 -114
  46. data/doc/classes/Milk/Fields/TextField.html +0 -114
  47. data/doc/classes/Milk/Haxe.html +0 -208
  48. data/doc/classes/Milk/Haxe.src/M000005.html +0 -40
  49. data/doc/classes/Milk/Haxe.src/M000006.html +0 -15
  50. data/doc/classes/Milk/Page.html +0 -243
  51. data/doc/classes/Milk/Page.src/M000009.html +0 -17
  52. data/doc/classes/Milk/Page.src/M000010.html +0 -17
  53. data/doc/classes/Milk/Page.src/M000011.html +0 -18
  54. data/doc/classes/Milk/Page.src/M000012.html +0 -20
  55. data/doc/classes/Milk/Page.src/M000013.html +0 -21
  56. data/doc/classes/Milk/PageNotFoundError.html +0 -110
  57. data/doc/classes/Object.html +0 -237
  58. data/doc/classes/Object.src/M000001.html +0 -13
  59. data/doc/classes/Object.src/M000002.html +0 -13
  60. data/doc/classes/Object.src/M000003.html +0 -15
  61. data/doc/classes/Object.src/M000004.html +0 -15
  62. data/doc/created.rid +0 -1
  63. data/doc/files/INSTALL.html +0 -106
  64. data/doc/files/LICENSE.html +0 -126
  65. data/doc/files/README.html +0 -100
  66. data/doc/files/Rakefile.html +0 -121
  67. data/doc/files/bin/milk.html +0 -100
  68. data/doc/files/doc/classes/Milk/Application_html.html +0 -302
  69. data/doc/files/doc/classes/Milk/Application_src/M000007_html.html +0 -173
  70. data/doc/files/doc/classes/Milk/Application_src/M000008_html.html +0 -142
  71. data/doc/files/doc/classes/Milk/Component_html.html +0 -477
  72. data/doc/files/doc/classes/Milk/Component_src/M000014_html.html +0 -123
  73. data/doc/files/doc/classes/Milk/Component_src/M000015_html.html +0 -120
  74. data/doc/files/doc/classes/Milk/Component_src/M000016_html.html +0 -119
  75. data/doc/files/doc/classes/Milk/Component_src/M000017_html.html +0 -119
  76. data/doc/files/doc/classes/Milk/Component_src/M000018_html.html +0 -119
  77. data/doc/files/doc/classes/Milk/Component_src/M000019_html.html +0 -119
  78. data/doc/files/doc/classes/Milk/Component_src/M000020_html.html +0 -119
  79. data/doc/files/doc/classes/Milk/Component_src/M000021_html.html +0 -119
  80. data/doc/files/doc/classes/Milk/Component_src/M000022_html.html +0 -122
  81. data/doc/files/doc/classes/Milk/Component_src/M000023_html.html +0 -125
  82. data/doc/files/doc/classes/Milk/Component_src/M000024_html.html +0 -119
  83. data/doc/files/doc/classes/Milk/Component_src/M000025_html.html +0 -126
  84. data/doc/files/doc/classes/Milk/ExternalCompilerError_html.html +0 -214
  85. data/doc/files/doc/classes/Milk/Field_html.html +0 -209
  86. data/doc/files/doc/classes/Milk/Fields/ComponentArray_html.html +0 -209
  87. data/doc/files/doc/classes/Milk/Fields/ImageChooser_html.html +0 -209
  88. data/doc/files/doc/classes/Milk/Fields/MarkdownField_html.html +0 -209
  89. data/doc/files/doc/classes/Milk/Fields/PageChooser_html.html +0 -209
  90. data/doc/files/doc/classes/Milk/Fields/SpriteChooser_html.html +0 -209
  91. data/doc/files/doc/classes/Milk/Fields/TextField_html.html +0 -209
  92. data/doc/files/doc/classes/Milk/Fields_html.html +0 -264
  93. data/doc/files/doc/classes/Milk/Haxe_html.html +0 -298
  94. data/doc/files/doc/classes/Milk/Haxe_src/M000005_html.html +0 -144
  95. data/doc/files/doc/classes/Milk/Haxe_src/M000006_html.html +0 -119
  96. data/doc/files/doc/classes/Milk/PageNotFoundError_html.html +0 -205
  97. data/doc/files/doc/classes/Milk/Page_html.html +0 -330
  98. data/doc/files/doc/classes/Milk/Page_src/M000009_html.html +0 -121
  99. data/doc/files/doc/classes/Milk/Page_src/M000010_html.html +0 -121
  100. data/doc/files/doc/classes/Milk/Page_src/M000011_html.html +0 -122
  101. data/doc/files/doc/classes/Milk/Page_src/M000012_html.html +0 -124
  102. data/doc/files/doc/classes/Milk/Page_src/M000013_html.html +0 -125
  103. data/doc/files/doc/classes/Milk_html.html +0 -321
  104. data/doc/files/doc/classes/Object_html.html +0 -334
  105. data/doc/files/doc/classes/Object_src/M000001_html.html +0 -117
  106. data/doc/files/doc/classes/Object_src/M000002_html.html +0 -117
  107. data/doc/files/doc/classes/Object_src/M000003_html.html +0 -119
  108. data/doc/files/doc/classes/Object_src/M000004_html.html +0 -119
  109. data/doc/files/doc/created_rid.html +0 -97
  110. data/doc/files/doc/files/INSTALL_html.html +0 -206
  111. data/doc/files/doc/files/LICENSE_html.html +0 -226
  112. data/doc/files/doc/files/README_html.html +0 -201
  113. data/doc/files/doc/files/Rakefile_html.html +0 -221
  114. data/doc/files/doc/files/bin/milk_html.html +0 -198
  115. data/doc/files/doc/files/lib/milk/application_rb_html.html +0 -188
  116. data/doc/files/doc/files/lib/milk/component_rb_html.html +0 -188
  117. data/doc/files/doc/files/lib/milk/field_rb_html.html +0 -188
  118. data/doc/files/doc/files/lib/milk/fields/component_array_rb_html.html +0 -188
  119. data/doc/files/doc/files/lib/milk/fields/image_chooser_rb_html.html +0 -188
  120. data/doc/files/doc/files/lib/milk/fields/markdown_field_rb_html.html +0 -188
  121. data/doc/files/doc/files/lib/milk/fields/page_chooser_rb_html.html +0 -188
  122. data/doc/files/doc/files/lib/milk/fields/sprite_chooser_rb_html.html +0 -188
  123. data/doc/files/doc/files/lib/milk/fields/text_field_rb_html.html +0 -188
  124. data/doc/files/doc/files/lib/milk/fields/xhtml_haml_html.html +0 -211
  125. data/doc/files/doc/files/lib/milk/haxe_rb_html.html +0 -188
  126. data/doc/files/doc/files/lib/milk/page_rb_html.html +0 -188
  127. data/doc/files/doc/files/lib/milk/tasks_rb_html.html +0 -202
  128. data/doc/files/doc/files/lib/milk/templates/bzrignore_html.html +0 -197
  129. data/doc/files/doc/files/lib/milk/templates/rackup_html.html +0 -217
  130. data/doc/files/doc/files/lib/milk/templates/rakefile_html.html +0 -198
  131. data/doc/files/doc/files/lib/milk/templates/restart_html.html +0 -197
  132. data/doc/files/doc/files/lib/milk_rb_html.html +0 -197
  133. data/doc/files/doc/fr_class_index_html.html +0 -160
  134. data/doc/files/doc/fr_file_index_html.html +0 -174
  135. data/doc/files/doc/fr_method_index_html.html +0 -178
  136. data/doc/files/doc/index_html.html +0 -128
  137. data/doc/files/doc/rdoc-style_css.html +0 -665
  138. data/doc/files/lib/milk/application_rb.html +0 -90
  139. data/doc/files/lib/milk/component_rb.html +0 -90
  140. data/doc/files/lib/milk/field_rb.html +0 -90
  141. data/doc/files/lib/milk/fields/component_array_rb.html +0 -90
  142. data/doc/files/lib/milk/fields/image_chooser_rb.html +0 -90
  143. data/doc/files/lib/milk/fields/markdown_field_rb.html +0 -90
  144. data/doc/files/lib/milk/fields/page_chooser_rb.html +0 -90
  145. data/doc/files/lib/milk/fields/sprite_chooser_rb.html +0 -90
  146. data/doc/files/lib/milk/fields/text_field_rb.html +0 -90
  147. data/doc/files/lib/milk/fields/xhtml_haml.html +0 -107
  148. data/doc/files/lib/milk/haxe_rb.html +0 -90
  149. data/doc/files/lib/milk/page_rb.html +0 -90
  150. data/doc/files/lib/milk/tasks_rb.html +0 -104
  151. data/doc/files/lib/milk/templates/bzrignore.html +0 -97
  152. data/doc/files/lib/milk/templates/rackup.html +0 -119
  153. data/doc/files/lib/milk/templates/rakefile.html +0 -98
  154. data/doc/files/lib/milk/templates/restart.html +0 -97
  155. data/doc/files/lib/milk_rb.html +0 -97
  156. data/doc/fr_class_index.html +0 -27
  157. data/doc/fr_file_index.html +0 -169
  158. data/doc/fr_method_index.html +0 -33
  159. data/doc/index.html +0 -21
  160. data/doc/rdoc-style.css +0 -299
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ spec = Gem::Specification.new do |s|
5
5
  s.summary = "Milk is a rack based content management system built for ease of use and simplicity. Milk tastes great with and without cookies."
6
6
  s.description= File.read(File.join(File.dirname(__FILE__), 'README'))
7
7
  s.requirements << 'none'
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
9
9
  s.author = "Tim Caswell"
10
10
  s.email = "tim@creationix.com"
11
11
  s.homepage = "http://milk.rubyforge.org"
data/lib/milk.rb CHANGED
@@ -20,6 +20,7 @@ module Milk
20
20
  COMPONENTS_DIR = MILK_ROOT + "/design"
21
21
  PAGES_DIR = MILK_ROOT + "/pages"
22
22
  PUBLIC_DIR = MILK_ROOT + "/public"
23
+ FIELDS_DIR = LIB_DIR + "/milk/fields"
23
24
 
24
25
  $LOAD_PATH.unshift(LIB_DIR) unless $LOAD_PATH.include?(LIB_DIR)
25
26
  autoload :Application, "milk/application"
@@ -55,4 +56,16 @@ class Object
55
56
  end
56
57
  end
57
58
 
59
+ # Add ability to get constants from a string name.
60
+ # WARNING: this is akin to eval for security concerns.
61
+ class String
62
+ def constantize
63
+ const = Object
64
+ self.split("::").each do |part|
65
+ const = const.const_get(part)
66
+ end
67
+ const
68
+ end
69
+ end
70
+
58
71
 
@@ -35,6 +35,11 @@ module Milk
35
35
  regex = PAGE_PATH_REGEX
36
36
  :delete
37
37
  end
38
+ when req.post?
39
+ if path =~ PAGE_PATH_REGEX
40
+ regex = PAGE_PATH_REGEX
41
+ :preview
42
+ end
38
43
  when req.put?
39
44
  if path =~ PAGE_PATH_REGEX
40
45
  regex = PAGE_PATH_REGEX
@@ -60,6 +65,10 @@ module Milk
60
65
  end
61
66
  end
62
67
 
68
+ if (action == :preview || action == :save)
69
+ page = Milk::Page.json_unserialize(YAML.load(req.body.read))
70
+ end
71
+
63
72
  return action, page_name, page
64
73
  end
65
74
 
@@ -76,6 +85,7 @@ module Milk
76
85
  else
77
86
  html_type = "text/html"
78
87
  end
88
+ html_type = "text/html"
79
89
 
80
90
  case action
81
91
  when :haxe
@@ -86,6 +96,10 @@ module Milk
86
96
  [200, {"Content-Type"=>html_type}, [page.view]]
87
97
  when :edit
88
98
  [200, {"Content-Type"=>html_type}, [page.edit]]
99
+ when :save
100
+ [200, {"Content-Type"=>html_type}, [page.save(page_name)]]
101
+ when :preview
102
+ [200, {"Content-Type"=>html_type}, [page.preview]]
89
103
  else
90
104
  [500, {"Content-Type"=>html_type}, [action.to_s]]
91
105
  end
@@ -1,72 +1,99 @@
1
1
  module Milk
2
2
  class Component
3
- @@props = []
4
- @@fields = []
3
+
4
+ @@local_flag = {}
5
5
 
6
- def self.local_properties(*props)
7
- @@props += props
8
- # Dynamically set the yaml dumper to only store local properties
9
- meta_def :to_yaml_properties do
10
- props
6
+ def to_yaml_properties
7
+ if respond_to? :global_properties
8
+ instance_variables.select { |name| !global_properties.member? name }
9
+ else
10
+ instance_variables
11
11
  end
12
12
  end
13
+
14
+ def self.local_properties(*props)
15
+ end
13
16
 
14
17
  def self.global_properties(*props)
15
- @@props += props
16
- # TODO: put hook in save
18
+ globals = props.collect{|name|"@#{name}".to_sym}
19
+ class_def :global_properties do
20
+ globals
21
+ end
17
22
  end
18
23
 
19
- def self.component_array(field, label, com_class)
20
- # TODO: create hooks to add field
21
- end
22
- def self.image_chooser(field, label, alt_field)
23
- # TODO: create hooks to add field
24
+ def name
25
+ self.class.to_s
24
26
  end
25
- def self.markdown_field(field, label)
26
- # TODO: create hooks to add field
27
+
28
+ # All Components start out with default of no fields
29
+ def self.fields
30
+ []
27
31
  end
28
- def self.page_chooser(field, label)
29
- # TODO: create hooks to add field
32
+
33
+ # Assume no defaults
34
+ def self.defaults
35
+ {}
30
36
  end
31
- def self.sprite_chooser(field, label, main_class, sub_classes)
32
- # TODO: create hooks to add field
37
+
38
+ # Metaclass black magic to simulate appending items to a list
39
+ # This works by getting the old result of the fields class method
40
+ # and stores it in a closure, and then redefines the method, but with
41
+ # a new item appended.
42
+ def self.add_field(klass, field, label, options={})
43
+
44
+ # Merge in assumes options
45
+ options[:field] = field
46
+ options[:label] = label
47
+
48
+ # Fill in blanks with defaults
49
+ defaults.each do |k, v|
50
+ options[k] ||= v
51
+ end
52
+
53
+ field = klass.new(options)
54
+
55
+ newfields = self.fields + [field]
56
+ meta_def("fields") do
57
+ newfields
58
+ end
33
59
  end
34
- def self.text_field(field, label)
35
- # TODO: create hooks to add field
60
+
61
+ def self.method_missing(method, *args)
62
+ raise "Missing '#{method}' method" unless File.file? FIELDS_DIR+"/#{method}.rb"
63
+ klass = eval("Fields::" + method.to_s.gsub(/(^|_)(.)/) { $2.upcase })
64
+ add_field(klass, *args)
36
65
  end
37
66
 
38
- def initilize(*props)
39
- props.each_pair do |key, value|
40
- raise "Undefined property \"" + key.to_s + "\"" unless @@props.member? key
41
- self.instance_variable_set(key, value)
42
- end
67
+ def save_settings
43
68
  end
44
69
 
45
70
  def load_settings
46
- name = self.class.to_s.gsub(/([a-z])([A-Z])/) { "#{$1}_#{$2}" }.downcase
47
- yml_file = Milk::PAGES_DIR + "/global/" + name + ".yml"
71
+ # Only load once
72
+ return unless @system_name.nil?
73
+
74
+ @system_name = self.class.to_s.gsub(/([a-z])([A-Z])/) { "#{$1}_#{$2}" }.downcase
75
+ yml_file = Milk::PAGES_DIR + "/global/" + @system_name + ".yml"
48
76
  if File.file? yml_file
49
- YAML.load_file(yml_file)
50
- else
51
- {}
77
+ YAML.load_file(yml_file).each_pair do |key, value|
78
+ self.instance_eval("@#{key} ||= value")
79
+ end
52
80
  end
53
81
  end
54
82
 
55
- def edit
56
- self.inspect
83
+ def edit(prefix)
84
+ @prefix = prefix
85
+ haml_file = FIELDS_DIR + "/component.haml"
86
+ ::Haml::Engine.new(File.read(haml_file), :filename => haml_file).render(self)
57
87
  end
58
88
 
59
89
  def view
60
- globals = load_settings
61
- globals.each_pair do |key, value|
62
- self.instance_variable_set(('@' + key).to_sym, value)
63
- end unless globals.nil?
64
- name = self.class.to_s.gsub(/([a-z])([A-Z])/) { "#{$1}_#{$2}" }.downcase
65
- haml_file = Milk::COMPONENTS_DIR + "/" + name + ".haml"
90
+ load_settings
91
+ haml_file = Milk::COMPONENTS_DIR + "/" + @system_name + ".haml"
66
92
  raise "Missing template \"" + haml_file + "\"" unless File.file? haml_file
67
93
  ::Haml::Engine.new(File.read(haml_file), :filename => haml_file).render(self)
68
94
  end
69
95
 
96
+
70
97
  end
71
98
  end
72
99
 
data/lib/milk/field.rb CHANGED
@@ -1,10 +1,53 @@
1
1
  module Milk
2
+
3
+ # A field is a data type for part of a component. This way components can be
4
+ # quickly built without coding any logic. The fields take care of the heavy
5
+ # work.
2
6
  class Field
7
+
8
+ attr_reader :field
9
+
10
+ # Store the field configurations
11
+ def initialize(props)
12
+ props.each do |key, value|
13
+ self.instance_variable_set('@' + key.to_s, value)
14
+ end
15
+ end
16
+
17
+ # This is the name shown to the user for the field.
18
+ def name
19
+ @label || self.class.to_s.rpartition('::').last
20
+ end
21
+
22
+ def form_field
23
+ @prefix
24
+ end
25
+
26
+ def value
27
+ @component.instance_variable_get('@' + @field.to_s)
28
+ end
29
+
30
+ # This is called to render the html for a field's form
31
+ def render(component, prefix)
32
+ @component = component
33
+ @prefix = prefix
34
+
35
+ name = self.class.to_s.rpartition('::').last.gsub(/([a-z])([A-Z])/) { "#{$1}_#{$2}" }.downcase
36
+ haml_file = "#{FIELDS_DIR}/#{name}.haml"
37
+ if File.file?(haml_file)
38
+ ::Haml::Engine.new(File.read(haml_file), :filename => haml_file).render(self)
39
+ else
40
+ "#{self.class} Not Implemented"
41
+ end
42
+ end
43
+
3
44
  end
4
45
 
46
+ # This module is a namespace for all the subclasses of Milk::Field
47
+ # Is sets up autoloading for the fields classes
5
48
  module Fields
6
- # Autoload the fields of the user space app into the root namespace for easy use
7
- Dir.glob(Milk::LIB_DIR + "/milk/fields/*.rb").each do |c|
49
+
50
+ Dir.glob(Milk::FIELDS_DIR + "/*.rb").each do |c|
8
51
  name = c.split('/').last.gsub(/(.*)\.rb/) { $1 }
9
52
  class_name = name.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
10
53
  path = c.gsub(/(.*)\.rb/) { $1 }
@@ -12,5 +55,6 @@ module Milk
12
55
  end
13
56
 
14
57
  end
58
+
15
59
  end
16
60
 
@@ -0,0 +1,8 @@
1
+ %h3
2
+ %a{:href => "#"}&= name
3
+ %div
4
+ %input{:type=>"hidden", :name=>"#{@prefix}:class", :value=>self.class.to_s}
5
+ -self.class.fields.each do |field|
6
+ .field
7
+ %h4= field.name
8
+ .field-content= field.render(self, "#{@prefix}:#{field.field}")
@@ -0,0 +1,3 @@
1
+ .sub-fields
2
+ - value.each_with_index do |item, i|
3
+ = item.edit("#{@prefix}:#{i}")
@@ -0,0 +1,2 @@
1
+ %div{:class=>"component com_#{index}"}
2
+ = yield
@@ -0,0 +1,7 @@
1
+ %select{:name=>form_field}
2
+ - images.each do |img|
3
+ %option{:value=>img[:url], :selected=>value==img[:url], :title=>"#{img[:size]} bytes"}&= img[:filename]
4
+ %br
5
+ Alt:
6
+ %input{:name=>alt_form_field, :value=>alt_value}
7
+
@@ -1,4 +1,26 @@
1
1
  module Milk::Fields
2
2
  class ImageChooser < Milk::Field
3
+ @@images = []
4
+ IMAGE_DIR = Milk::PUBLIC_DIR + "/images"
5
+ Dir.glob(IMAGE_DIR + "/*").each do |img|
6
+ @@images << {
7
+ size: File.size(img),
8
+ url: img.sub(Milk::PUBLIC_DIR, ''),
9
+ filename: img.rpartition('/').last
10
+ }
11
+ end
12
+
13
+ def images
14
+ @@images
15
+ end
16
+
17
+ def alt_form_field
18
+ @prefix.rpartition(':').first + ":#{@alt_field}"
19
+ end
20
+
21
+ def alt_value
22
+ @component.instance_variable_get('@' + @alt_field.to_s)
23
+ end
24
+
3
25
  end
4
26
  end
@@ -0,0 +1 @@
1
+ %textarea.markdown{:class=>"ui-widget ui-corner-all", :name => form_field}&= value
@@ -0,0 +1,3 @@
1
+ %select{:name=>form_field}
2
+ - pages.each do |page|
3
+ %option{:value=>page[:url], :selected=>value==page[:url], :title=>page[:file]}&= page[:name]
@@ -1,4 +1,17 @@
1
1
  module Milk::Fields
2
2
  class PageChooser < Milk::Field
3
+ @@pages = []
4
+ Dir.glob(Milk::PAGES_DIR + "/*.yml").each do |page|
5
+ pagename = File.basename(page, '.yml').rpartition('/').last.gsub('.','/')
6
+ @@pages << {
7
+ file: page,
8
+ name: pagename,
9
+ url: "/"+pagename
10
+ }
11
+ end
12
+
13
+ def pages
14
+ @@pages
15
+ end
3
16
  end
4
17
  end
@@ -0,0 +1,6 @@
1
+ .sprite-select
2
+ %input{:type=>"hidden", :name=>form_field, :value=>value}
3
+ - @sprites.each do |sprite|
4
+ %div{:class => "ui-state-default ui-corner-all sprite-option" + ((value == sprite[:name]) ? " ui-state-highlight" : "")}
5
+ %span{:class => sprite[:css_class], :title => sprite[:name]}
6
+ %br.clear
@@ -1,4 +1,19 @@
1
1
  module Milk::Fields
2
2
  class SpriteChooser < Milk::Field
3
+
4
+ def initialize(*args)
5
+ super(*args)
6
+ @sprites = []
7
+ open(Milk::COMPONENTS_DIR+"/sprites.sass") do |sass|
8
+ sass.each do |line|
9
+ if match = @icon_classes.match(line)
10
+ @sprites << {
11
+ css_class: @main_class + " " + match[1],
12
+ name: match[2]
13
+ }
14
+ end
15
+ end
16
+ end
17
+ end
3
18
  end
4
19
  end
@@ -0,0 +1 @@
1
+ %input{:class=>"ui-widget ui-widget-content ui-corner-all", :type =>"text", :name=>form_field, :value=>value}
@@ -2,9 +2,260 @@
2
2
  !!! 1.1
3
3
  %html{:xmlns =>"http://www.w3.org/1999/xhtml"}
4
4
  %head
5
+ %title&= "Editing \"#{@pagename}\""
6
+ %style{:type=>"text/css"}
7
+ :sass
8
+ body, html
9
+ :border 0
10
+ :margin 0
11
+ :padding 0
12
+ body.busy
13
+ :cursor busy
14
+ div.component
15
+ border: 2px solid transparent
16
+ &:hover
17
+ border-color: #08f
18
+ #framework-logo
19
+ :position absolute
20
+ :bottom 0
21
+ :right 20px
22
+ :opacity 0.3
23
+ :background transparent url(http://static.creationix.com/milk-logo.png)
24
+ :width 139px
25
+ :height 69px
26
+ #admin-title
27
+ :position absolute
28
+ :margin 0
29
+ :top 5px
30
+ :left 10px
31
+ :line-height 1em
32
+ :font-size 20px
33
+ :font-family monaco,monospace
34
+
35
+ #toolbar
36
+ :position absolute
37
+ :left 0
38
+ :bottom 0
39
+ :right 0
40
+ :padding 3px
41
+ .toolitem
42
+ :cursor pointer
43
+ :line-height 1em
44
+ :padding 2px 5px 2px 2px
45
+ .ui-icon
46
+ :float left
47
+ :line-height 1em
48
+ #frame
49
+ :position absolute
50
+ :top 0px
51
+ :left 0px
52
+ :right 0px
53
+ :bottom 0px
54
+ #left
55
+ :position absolute
56
+ :top 0px
57
+ :left 0px
58
+ :width 400px
59
+ :bottom 0px
60
+ #divider
61
+ :position absolute
62
+ :top 0px
63
+ :left 400px
64
+ :width 5px
65
+ :bottom 0px
66
+ :background-color #555
67
+
68
+ #fields
69
+ :position absolute
70
+ :top 0px
71
+ :bottom 35px
72
+ :overflow auto
73
+ :left 0px
74
+ :right 0
75
+ .ui-accordion-content
76
+ :padding 10px
77
+ h4
78
+ :margin 0
79
+ .field-content
80
+ :margin-bottom 10px
81
+ input
82
+ :width 95%
83
+ :padding 2px
84
+ textarea
85
+ :width 100%
86
+ :min-height 380px
87
+ .sprite-select
88
+ .sprite-option
89
+ :padding 5px
90
+ :margin 2px
91
+ :float left
92
+ :cursor pointer
93
+
94
+ #preview
95
+ :position absolute
96
+ :top 0px
97
+ :left 405px
98
+ :right 0
99
+ :width auto
100
+ :bottom 0px
101
+ :overflow auto
102
+
103
+
5
104
  %link{ :rel => "shortcut icon", :href => "/favicon.ico", :type => "image/x-icon"}/
6
105
  %link{ :href => "http://static.creationix.com/skins/ui-lightness/jquery-ui-1.7.1.custom.css", :media => "screen", :rel => "stylesheet", :type => "text/css" }/
7
- %title&= "Edit #{@pagename}"
106
+ %link{ :href => "/style/style.css", :media => "screen", :rel => "stylesheet", :type => "text/css" }/
8
107
  %script{:src=>"http://static.creationix.com/scripts/jquery-1.3.2.min.js", :type=>"text/javascript"}
108
+ %script{:src=>"http://static.creationix.com/scripts/jquery.json-1.3.min.js", :type=>"text/javascript"}
9
109
  %script{:src=>"http://static.creationix.com/scripts/jquery-ui-1.7.1.custom.min.js", :type=>"text/javascript"}
10
- %body= yield
110
+ %body
111
+ #frame
112
+ #left
113
+ %form#fields{:method => "post", :action => "/"+@pagename}
114
+ %h3
115
+ %a{:href => "#"} Page Settings
116
+ %div
117
+ %input{:type=>"hidden", :name=>"class", :value=>self.class.to_s}
118
+ -to_yaml_properties.each do |name|
119
+ - next if name == :@components
120
+ - fieldname = name.to_s.sub('@','')
121
+ .field
122
+ %h4= fieldname.capitalize + ":"
123
+ .field-content
124
+ %input{:type=>"text", :name=>fieldname, :value=>instance_variable_get(name)}
125
+ -@components.each_with_index do |component, i|
126
+ = component.edit("components:#{i}")
127
+ #toolbar{:class=>'ui-widget ui-widget-header'}
128
+ %button#save_button.toolitem{:title=>'Save changes and go to live page.'}
129
+ %span{:class=>'ui-icon ui-icon-disk'}
130
+ Save
131
+ %button#cancel_button.toolitem{:title=>'Cancel changes and go to live page.'}
132
+ %span{:class=>'ui-icon ui-icon-cancel'}
133
+ Cancel
134
+ #preview{:class => "ui-widget ui-helper-reset ui-widget-content"}
135
+ = preview
136
+ #divider
137
+ #framework-logo
138
+
139
+ :javascript
140
+ function on_click_sprite(e)
141
+ {
142
+ // Look up some useful variables
143
+ var current = e.currentTarget;
144
+ var sprite_select = $(current.parentNode);
145
+ var peers = $(".sprite-option", sprite_select);
146
+ var hidden_input = $('input', sprite_select)[0];
147
+ var inner_span = $('span', current)[0];
148
+
149
+ // Set the value on the hidden input
150
+ hidden_input.value = inner_span.title;
151
+
152
+ // Move the highlight
153
+ peers.removeClass('ui-state-highlight');
154
+ $(current).addClass('ui-state-highlight');
155
+ update_preview(50);
156
+ }
157
+
158
+ function jsonify(form)
159
+ {
160
+ var data = {}
161
+ $("input, textarea, select", form).each(function (i, field){
162
+ var parts = field.name.split(':');
163
+ var root = data;
164
+ var part = parts[0];
165
+ var numeric_regexp = /[0-9]+/;
166
+ for(i=0;i<parts.length-1;i++)
167
+ {
168
+ if (!root[part])
169
+ {
170
+ if (numeric_regexp.test(part))
171
+ root[part]={};
172
+ else
173
+ root[part]=[];
174
+ }
175
+ root = root[part];
176
+ part = parts[i + 1];
177
+ }
178
+ root[part] = field.value;
179
+ });
180
+ return $.toJSON(data);
181
+ }
182
+
183
+ function do_update_preview()
184
+ {
185
+ var preview = $("#preview");
186
+ $("body").addClass("busy")
187
+ $.ajax({
188
+ type: "POST",
189
+ url: $("form")[0].action,
190
+ contentType: "application/json",
191
+ data: jsonify($("form")[0]),
192
+ success: function(msg){
193
+ preview.html(msg);
194
+ $("body").removeClass("busy")
195
+ }
196
+ });
197
+ }
198
+
199
+ function update_preview(timeout)
200
+ {
201
+ clearTimeout(window.preview_timeout);
202
+ window.preview_timeout = setTimeout(do_update_preview, timeout);
203
+ }
204
+
205
+
206
+ $(function() {
207
+ $("#left").resizable({handles: "e", resize: function(event, ui) {
208
+ $("#divider").css("left", ui.size.width);
209
+ $("#preview").css("left", ui.size.width+5);
210
+ }});
211
+ $(".sub-fields").accordion({
212
+ collapsible: true,
213
+ autoHeight: false,
214
+ active: false
215
+ });
216
+ var sections = $("#fields").accordion({
217
+ autoHeight: false
218
+ });
219
+
220
+ $(".sprite-option").click(on_click_sprite);
221
+ $(".toolitem, .sprite-option")
222
+ .addClass("ui-state-default ui-corner-all")
223
+ .hover(
224
+ function() { $(this).addClass('ui-state-hover'); },
225
+ function() { $(this).removeClass('ui-state-hover'); }
226
+ );
227
+ $("#fields select, #fields input, #fields textarea").change(function(){
228
+ update_preview(100);
229
+ });
230
+ $("#fields select, #fields input, #fields textarea").keyup(function(){
231
+ update_preview(1000);
232
+ });
233
+ $("#save_button").click(function(){
234
+ $.ajax({
235
+ type: "PUT",
236
+ url: $("form")[0].action,
237
+ contentType: "application/json",
238
+ data: jsonify($("form")[0]),
239
+ success: function(msg){
240
+ window.location = $("form")[0].action;
241
+ }
242
+ });
243
+ });
244
+
245
+ $("#cancel_button").click(function(){
246
+ window.location = $("form")[0].action;
247
+ });
248
+
249
+ $(".component").click(function(evt){
250
+ evt.stopPropagation();
251
+ evt.preventDefault();
252
+ var index = this.className.split("_")[1];
253
+ console.log(index);
254
+ console.log(sections);
255
+ sections.accordion('activate', parseInt(index)+1);
256
+ });
257
+
258
+
259
+ });
260
+
261
+