milk 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
+