luca 0.8.599 → 0.9.0

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 (149) hide show
  1. data/.gitignore +3 -0
  2. data/.rvmrc +1 -0
  3. data/CHANGELOG +51 -2
  4. data/README.md +10 -247
  5. data/ROADMAP +6 -2
  6. data/app.rb +16 -2
  7. data/assets/javascripts/dependencies/bootstrap.min.js +7 -1
  8. data/assets/javascripts/dependencies/codemirror-coffeescript.js +347 -0
  9. data/assets/javascripts/dependencies/codemirror-css.js +124 -0
  10. data/assets/javascripts/dependencies/codemirror-html.js +410 -0
  11. data/assets/javascripts/dependencies/codemirror-javascript.js +361 -0
  12. data/assets/javascripts/dependencies/codemirror-less.js +232 -0
  13. data/assets/javascripts/dependencies/codemirror-vim.js +500 -0
  14. data/assets/javascripts/dependencies/codemirror.js +3076 -0
  15. data/assets/javascripts/dependencies.coffee +0 -1
  16. data/assets/javascripts/luca-ui-base.coffee +10 -3
  17. data/assets/javascripts/luca-ui-bootstrap.js +1 -0
  18. data/assets/javascripts/luca-ui-development-tools.coffee +9 -0
  19. data/assets/javascripts/luca-ui.coffee +6 -1
  20. data/assets/javascripts/sandbox/application.coffee +51 -0
  21. data/assets/javascripts/sandbox/router.coffee +14 -0
  22. data/assets/javascripts/sandbox/templates/main.luca +33 -0
  23. data/assets/javascripts/sandbox/templates/sandbox/navigation.luca +1 -0
  24. data/assets/javascripts/sandbox/templates/sandbox.luca +1 -0
  25. data/assets/javascripts/sandbox/views/top_navigation.coffee +4 -0
  26. data/assets/javascripts/sandbox.coffee +2 -2
  27. data/assets/stylesheets/bootstrap.min.css +395 -297
  28. data/assets/stylesheets/codemirror-blackboard.css +25 -0
  29. data/assets/stylesheets/codemirror-monokai.css +33 -0
  30. data/assets/stylesheets/codemirror.css +126 -0
  31. data/assets/stylesheets/luca-ui-bootstrap.css +0 -1
  32. data/assets/stylesheets/luca-ui-development-tools.css +5 -0
  33. data/assets/stylesheets/sandbox/sandbox.scss +1 -3
  34. data/assets/stylesheets/themes/amelia-bootstrap.css +826 -0
  35. data/assets/stylesheets/themes/slate-bootstrap.css +797 -0
  36. data/assets/stylesheets/themes/superhero-bootstrap.css +830 -0
  37. data/lib/luca/code_browser.rb +55 -0
  38. data/lib/luca/rails/version.rb +1 -1
  39. data/lib/luca/rails.rb +1 -0
  40. data/spec/components/fields/checkbox_array_spec.coffee +46 -0
  41. data/spec/components/form_view_spec.coffee +10 -4
  42. data/spec/containers/card_view_spec.coffee +7 -0
  43. data/spec/core/collection_spec.coffee +58 -4
  44. data/spec/core/container_spec.coffee +6 -6
  45. data/spec/core/view_spec.coffee +93 -7
  46. data/spec/framework_spec.coffee +15 -12
  47. data/src/components/application.coffee +126 -18
  48. data/src/components/base_toolbar.coffee +2 -2
  49. data/src/components/collection_loader_view.coffee +1 -2
  50. data/src/components/collection_view.coffee +77 -0
  51. data/src/components/controller.coffee +1 -4
  52. data/src/components/fields/button_field.coffee +1 -1
  53. data/src/components/fields/checkbox_array.coffee +2 -2
  54. data/src/components/fields/checkbox_field.coffee +3 -1
  55. data/src/components/fields/file_upload_field.coffee +1 -1
  56. data/src/components/fields/hidden_field.coffee +1 -1
  57. data/src/components/fields/select_field.coffee +1 -1
  58. data/src/components/fields/text_area_field.coffee +1 -1
  59. data/src/components/fields/text_field.coffee +10 -6
  60. data/src/components/fields/type_ahead_field.coffee +18 -5
  61. data/src/components/form_button_toolbar.coffee +1 -2
  62. data/src/components/form_view.coffee +44 -62
  63. data/src/components/grid_view.coffee +27 -20
  64. data/src/components/load_mask.coffee +3 -0
  65. data/src/components/nav_bar.coffee +26 -0
  66. data/src/components/record_manager.coffee +1 -3
  67. data/src/components/router.coffee +1 -1
  68. data/src/components/template.coffee +3 -15
  69. data/src/components/toolbar_dialog.coffee +25 -0
  70. data/src/containers/card_view.coffee +22 -23
  71. data/src/containers/column_view.coffee +1 -6
  72. data/src/containers/modal_view.coffee +20 -71
  73. data/src/containers/panel_toolbar.coffee +156 -0
  74. data/src/containers/panel_view.coffee +1 -1
  75. data/src/containers/split_view.coffee +1 -3
  76. data/src/containers/tab_view.coffee +29 -29
  77. data/src/containers/viewport.coffee +38 -3
  78. data/src/core/collection.coffee +80 -48
  79. data/src/core/container.coffee +153 -72
  80. data/src/core/core.coffee +181 -0
  81. data/src/core/field.coffee +4 -2
  82. data/src/core/model.coffee +1 -1
  83. data/src/core/observer.coffee +3 -3
  84. data/src/core/panel.coffee +143 -0
  85. data/src/core/registry.coffee +104 -0
  86. data/src/core/util.coffee +82 -0
  87. data/src/core/view.coffee +158 -85
  88. data/src/framework.coffee +112 -178
  89. data/src/index.coffee +0 -255
  90. data/src/managers/collection_manager.coffee +1 -0
  91. data/src/samples/definition.coffee +49 -0
  92. data/src/stylesheets/base.scss +0 -78
  93. data/src/stylesheets/components/form_view.scss +8 -3
  94. data/src/stylesheets/components/grid_view.scss +3 -7
  95. data/src/stylesheets/components/load_mask.scss +14 -0
  96. data/src/stylesheets/components/toolbar.scss +0 -15
  97. data/src/stylesheets/containers/container.scss +14 -2
  98. data/src/stylesheets/containers/panels.scss +23 -0
  99. data/src/stylesheets/tools/class_browser.scss +32 -0
  100. data/src/stylesheets/tools/code_editor.scss +24 -0
  101. data/src/stylesheets/tools/component_tester.scss +8 -0
  102. data/src/stylesheets/tools/console.scss +26 -0
  103. data/src/templates/components/collection_loader_view.luca +1 -1
  104. data/src/templates/components/form_view.luca +2 -13
  105. data/src/templates/components/grid_view.luca +0 -2
  106. data/src/templates/components/load_mask.luca +3 -0
  107. data/src/templates/components/nav_bar.luca +2 -0
  108. data/src/templates/containers/tab_view.luca +1 -0
  109. data/src/templates/fields/text_field.luca +4 -1
  110. data/src/tools/class_browser.coffee +39 -0
  111. data/src/tools/code_editor.coffee +258 -0
  112. data/src/tools/code_mirror_field.coffee +57 -0
  113. data/src/tools/coffee_script_editor.coffee +60 -0
  114. data/src/tools/collection_inspector.coffee +4 -0
  115. data/src/tools/component_tester.coffee +472 -0
  116. data/src/tools/components/class_browser_detail.coffee +10 -0
  117. data/src/tools/components/class_browser_list.coffee +74 -0
  118. data/src/tools/console.coffee +147 -0
  119. data/src/tools/development_console.coffee +147 -0
  120. data/src/tools/models/components.coffee +63 -0
  121. data/src/tools/templates/component_tester/help.luca +14 -0
  122. data/vendor/assets/javascripts/luca-ui-base.js +1389 -611
  123. data/vendor/assets/javascripts/luca-ui-bootstrap.js +9 -0
  124. data/vendor/assets/javascripts/luca-ui-development-tools.js +18719 -0
  125. data/vendor/assets/javascripts/luca-ui-spec.js +2065 -878
  126. data/vendor/assets/javascripts/luca-ui.js +1759 -852
  127. data/vendor/assets/javascripts/luca-ui.min.js +3 -3
  128. data/vendor/assets/stylesheets/luca-ui-bootstrap.css +494 -440
  129. data/vendor/assets/stylesheets/luca-ui-development-tools.css +224 -0
  130. data/vendor/assets/stylesheets/luca-ui-spec.css +99 -140
  131. data/vendor/assets/stylesheets/luca-ui.css +99 -140
  132. data/views/index.erb +6 -3
  133. metadata +60 -18
  134. data/assets/javascripts/dependencies/jquery-console.js +0 -649
  135. data/assets/javascripts/development-console.coffee +0 -2
  136. data/assets/javascripts/sandbox/sandbox.coffee +0 -16
  137. data/assets/javascripts/sandbox/templates/features/collection_helpers.luca +0 -33
  138. data/assets/javascripts/sandbox/templates/features/form_demo_code.luca +0 -48
  139. data/assets/javascripts/sandbox/templates/features/grid_demo_code.luca +0 -24
  140. data/assets/javascripts/sandbox/templates/features/introduction.luca +0 -11
  141. data/assets/javascripts/sandbox/templates/features/view_helpers.luca +0 -43
  142. data/assets/javascripts/sandbox/templates/navigation.luca +0 -8
  143. data/assets/javascripts/sandbox/views/form_demo.coffee +0 -47
  144. data/assets/javascripts/sandbox/views/grid_demo.coffee +0 -23
  145. data/assets/javascripts/sandbox/views/pages/collection_events_sample.coffee +0 -1
  146. data/assets/javascripts/sandbox/views/pages/pages_controller.coffee +0 -38
  147. data/src/components/collection_inspector.coffee +0 -2
  148. data/src/components/development_console.coffee +0 -59
  149. data/src/stylesheets/components/development_console.scss +0 -47
@@ -0,0 +1,39 @@
1
+ # The Class Browser takes a map of your application's source code and the
2
+ # classes it defines and allows you to view and even edit the source code
3
+ # for a given class in the browser.
4
+
5
+ # We do this by combining the functionality of a Luca CollectionList View
6
+ # which inspects the Luca component registry, and a CodeMirror Editor instance
7
+ # which compiles coffeescript and evaluates it on the fly. The Luca Framework
8
+ # is capable of updating all of the application components with the changes
9
+ # you make to their code.
10
+ _.def("Luca.tools.ClassBrowser").extends("Luca.containers.SplitView").with
11
+
12
+ name: "class_browser"
13
+
14
+ className: "luca-class-browser row"
15
+
16
+ layout:["span3","span9"]
17
+ # Composite views can be made up by specifying a list of components
18
+ # either as a collection of object configurations, or as a list
19
+ # of names corresponding to component types. The various types of
20
+ # Luca containers will handle rendering these components and arranging
21
+ # them visually
22
+ components:["class_browser_list","class_browser_detail"]
23
+
24
+ # The container is responsible for handling communication between components.
25
+ # We provide a nice API for this via the @componentEvents property.
26
+ componentEvents:
27
+ "class_browser_list component:loaded" : "loadSourceCode"
28
+
29
+ bottomToolbar:
30
+ buttons:[
31
+ label: "Add New"
32
+ icon: "plus"
33
+ color: "primary"
34
+ white: true
35
+ align: 'right'
36
+ ]
37
+
38
+ loadSourceCode: (model, response)->
39
+ Luca("class_browser_detail").loadComponent( model )
@@ -0,0 +1,258 @@
1
+ BuffersModel = Luca.Model.extend
2
+ defaults:
3
+ _current: "default"
4
+ _namespace: "default"
5
+ _compiled: []
6
+
7
+ initialize: (@attributes={})->
8
+ Luca.Model::initialize.apply(@, arguments)
9
+ @fetch(silent:true)
10
+
11
+ requireCompilation: ()->
12
+ @get("_compiled")
13
+
14
+ bufferKeys: ()->
15
+ return @bufferNames if @bufferNames?
16
+
17
+ for key, value of @attributes when !key.match(/_/)
18
+ key
19
+
20
+ namespacedBuffer: (key)->
21
+ "#{ @get('_namespace') }:#{ key }"
22
+
23
+ bufferValues: ()->
24
+ _( @attributes ).pick( @bufferKeys() )
25
+
26
+ fetch: (options={})->
27
+ options.silent ||= true
28
+
29
+ _( @bufferKeys() ).each (key)=>
30
+ value = localStorage?.getItem( @namespacedBuffer(key) )
31
+ @set(key, value, silent: options.silent is true) if value?
32
+
33
+ @
34
+
35
+ persist: ()->
36
+ _( @bufferKeys() ).each (key)=>
37
+ value = @get(key)
38
+ localStorage?.setItem( @namespacedBuffer(key), value)
39
+
40
+ @
41
+
42
+ currentContent: ()->
43
+ current = @get("_current")
44
+ @get(current)
45
+
46
+ compilers =
47
+ coffeescript: (code)->
48
+ CoffeeScript.compile code, bare: true
49
+ default: (code)->
50
+ code
51
+
52
+ _.def("Luca.tools.CodeEditor").extends("Luca.components.Panel").with
53
+ name: "code_editor"
54
+
55
+ id: "editor_container"
56
+
57
+ autoBindEventHandlers: true
58
+
59
+ bodyClassName: "codemirror-wrapper"
60
+
61
+ defaultValue: ''
62
+
63
+ compilationEnabled: false
64
+
65
+ bufferNamespace: "luca:code"
66
+
67
+ namespace: (set, options={})->
68
+ if set?
69
+ @bufferNamespace = set
70
+ @buffers?.set("_namespace", set, silent: (options.silent is true) )
71
+
72
+ @bufferNamespace
73
+
74
+ initialize: (@options)->
75
+ @_super("initialize", @, arguments)
76
+
77
+ _.bindAll @, "onCompiledCodeChange", "onBufferChange", "onEditorChange", "stripTabs"
78
+
79
+ @mode ||= "coffeescript"
80
+ @theme ||= "monokai"
81
+ @keyMap ||= "vim"
82
+ @lineWrapping ||= true
83
+
84
+ @compiler = compilers[@mode] || compilers.default
85
+
86
+ @setupBuffers()
87
+
88
+ setWrap: (@lineWrapping)->
89
+ @editor.setOption("lineWrapping", @lineWrapping)
90
+
91
+ setMode: (@mode)->
92
+ @editor.setOption("mode", @mode)
93
+ @
94
+
95
+ setKeyMap: (@keyMap)->
96
+ @editor.setOption("keyMap", @keyMap)
97
+ @
98
+
99
+ setTheme: (@theme)->
100
+ @editor.setOption("theme",@theme)
101
+ @
102
+
103
+ setupBuffers: ()->
104
+ attributes = _.extend(@currentBuffers || {},_compiled:@compiledBuffers,_namespace:@namespace())
105
+ @buffers = new BuffersModel(attributes)
106
+
107
+ editor = @
108
+
109
+ _( @buffers.bufferKeys() ).each (key)=>
110
+ @buffers.bind "change:#{ key }", ()=>
111
+ @onBufferChange.apply(@, arguments)
112
+
113
+ _( @buffers.requireCompilation() ).each (key)=>
114
+ @buffers.bind "change:compiled_#{ key }", @onCompiledCodeChange
115
+
116
+ # handle switching of the buffers. when the editor
117
+ # is told to switch buffers, we will get the current content
118
+ # in that buffer, and update the code mirror instance
119
+ @buffers.bind "change:_current", (model,value)=>
120
+ editor.trigger "buffer:change"
121
+ editor.editor.setValue( @buffers.currentContent() || "" )
122
+
123
+ @monitorChanges = true
124
+
125
+ currentBuffer: ()->
126
+ @buffers.get("_current")
127
+
128
+ loadBuffer: (bufferName, autoSave=true)->
129
+ @saveBuffer() if autoSave
130
+ @buffers.set("_current", bufferName)
131
+
132
+ saveBuffer: ()->
133
+ localStorage.setItem( @buffers.namespacedBuffer( @currentBuffer() ), @editor.getValue())
134
+ @buffers.set( @currentBuffer(), @editor.getValue() )
135
+
136
+ getBuffer: (buffer, compiled=false)->
137
+ buffer ||= @currentBuffer()
138
+ code = @buffers.get( buffer )
139
+
140
+ return code unless compiled is true
141
+
142
+ compiledCode = @buffers.get("compiled_#{ buffer }")
143
+
144
+ if _.string.isBlank(compiledCode)
145
+ compiledCode = @compileCode(code, buffer)
146
+
147
+ return compiledCode
148
+
149
+ editorOptions: ()->
150
+ mode: @mode
151
+ theme: @theme
152
+ keyMap: @keyMap
153
+ lineNumbers: true
154
+ gutter: true
155
+ autofocus: true
156
+ onChange: @onEditorChange
157
+ onKeyEvent: @stripTabs
158
+ passDelay: 50
159
+ autoClearEmptyLines: true
160
+ smartIndent: false
161
+ tabSize: 2
162
+ electricChars: false
163
+
164
+
165
+ beforeRender: ()->
166
+ Luca.components.Panel::beforeRender?.apply(@, arguments)
167
+
168
+ styles =
169
+ "min-height": @minHeight
170
+ background:'#272822'
171
+ color:'#f8f8f2'
172
+
173
+ @$bodyEl().css(styles)
174
+
175
+ @$html "<textarea></textarea>"
176
+
177
+ afterRender: ()->
178
+ _.defer ()=>
179
+ @editor = window.CodeMirror.fromTextArea( @$('textarea')[0], @editorOptions())
180
+ @restore()
181
+ @enableTabStripping = true
182
+
183
+ save: ()->
184
+ @saveBuffer()
185
+
186
+ restore: ()->
187
+ @editor.setValue("")
188
+ @editor.refresh()
189
+
190
+ replaceTabWithSpace: ()->
191
+
192
+ stripTabs: (editor, keyEvent)->
193
+ if keyEvent?.keyCode is 9
194
+ coords = @editor.cursorCoords()
195
+ cleansed = @getValue().replace(/\t/g,' ')
196
+ @setValue(cleansed)
197
+ @editor.setCursor( coords )
198
+
199
+ false
200
+
201
+ onEditorChange: ()->
202
+ if @monitorChanges
203
+ @save()
204
+
205
+ onBufferChange: (model, newValue, changes)->
206
+ previous = model.previousAttributes()
207
+
208
+ _( @buffers.bufferKeys() ).each (key)=>
209
+ if previous[key] isnt @buffers.get(key)
210
+
211
+ if _( @buffers.requireCompilation() ).include(key)
212
+ result = @compileCode( @buffers.get(key), key )
213
+ if result.success is true
214
+ @buffers.persist(key)
215
+ @buffers.set("compiled_#{ key }", result.compiled, silent: true)
216
+ else
217
+ @trigger "code:change:#{ key }", @buffers.get(key)
218
+ @buffers.persist(key)
219
+
220
+ @buffers.change()
221
+
222
+ onCompiledCodeChange: (model, newValue, changes)->
223
+ changedBuffers = _( model.changedAttributes() ).keys()
224
+ @trigger "code:change", changedBuffers
225
+ for changed in changedBuffers
226
+ @trigger "code:change:#{ changed }", changed
227
+
228
+ compileCode: (code, buffer)->
229
+ buffer ||= @currentBuffer()
230
+ code ||= @getBuffer(buffer, false)
231
+
232
+ compiled = ""
233
+
234
+ result =
235
+ success: true
236
+ compiled: ""
237
+
238
+ try
239
+ compiled = @compiler.call(@, code)
240
+ @trigger "compile:success", code, compiled
241
+ result.compiled = compiled
242
+ catch error
243
+ @trigger "compile:error", error, code
244
+ result.success = false
245
+ result.compiled = @buffers.get("compiled_#{ buffer }")
246
+
247
+ result
248
+
249
+ getCompiledCode: (buffer)->
250
+ buffer = @getBuffer(buffer)
251
+ _.string.strip( @compileCode(buffer) )
252
+
253
+ getValue: ()->
254
+ @editor.getValue()
255
+
256
+ setValue: (value)->
257
+ value = value.replace(/\t/g, ' ')
258
+ @editor.setValue( value )
@@ -0,0 +1,57 @@
1
+ defaultOptions =
2
+ readOnly: false
3
+ lineNumbers: true
4
+ gutter: true
5
+ autofocus: false
6
+ passDelay: 50
7
+ autoClearEmptyLines: true
8
+ smartIndent: false
9
+ tabSize: 2
10
+ electricChars: false
11
+
12
+ Luca.define("Luca.tools.CodeMirrorField").extends("Luca.components.Panel").with
13
+ bodyClassName: "codemirror-wrapper"
14
+ preProcessors: []
15
+ postProcessors: []
16
+
17
+ codemirrorOptions: ()->
18
+ options = _.clone( defaultOptions )
19
+
20
+ customOptions =
21
+ mode: @mode || "coffeescript"
22
+ theme: @theme || "monokai"
23
+ keyMap: @keyMap || "basic"
24
+ lineNumbers: if @lineNumbers? then @lineNumbers else defaultOptions.lineNumbers
25
+ readOnly: if @readOnly? then @readOnly else defaultOptions.readOnly
26
+ gutter: if @gutter? then @gutter else defaultOptions.gutter
27
+ lineWrapping: @lineWrapping is true
28
+ onChange: ()=>
29
+ @trigger "editor:change", @
30
+ @onEditorChange?.call(@)
31
+
32
+ customOptions.onKeyEvent = _.bind(@onKeyEvent,@) if @onKeyEvent?
33
+
34
+ _.extend(options, customOptions)
35
+
36
+ getCodeMirror: ()->
37
+ @instance
38
+
39
+ getValue: (processed=true)->
40
+ value = @getCodeMirror().getValue()
41
+
42
+ setValue: (value="", processed=true)->
43
+ @getCodeMirror().setValue( value )
44
+
45
+ afterRender: ()->
46
+ @instance = CodeMirror( @$bodyEl()[0], @codemirrorOptions() )
47
+ @setMaxHeight()
48
+ @setHeight()
49
+
50
+ setMaxHeight: (maxHeight=undefined, grow=true)->
51
+ maxHeight ||= @maxHeight
52
+ return unless maxHeight?
53
+ @$('.CodeMirror-scroll').css('max-height', maxHeight)
54
+ @$('.CodeMirror-scroll').css('height', maxHeight) if grow is true
55
+
56
+ setHeight: (height=undefined)->
57
+ @$('.CodeMirror-scroll').css('height', height) if height?
@@ -0,0 +1,60 @@
1
+ _.def("Luca.tools.CoffeeEditor").extends("Luca.tools.CodeMirrorField").with
2
+ name : "coffeescript_editor"
3
+
4
+ compileOptions:
5
+ bare: true
6
+
7
+ hooks:[
8
+ "editor:change"
9
+ ]
10
+
11
+ initialize: (@options)->
12
+ Luca.tools.CodeMirrorField::initialize.apply(@, arguments)
13
+
14
+ _.bindAll(@, "editorChange")
15
+
16
+ editor = @
17
+
18
+ @state = new Luca.Model
19
+ currentMode: "coffeescript"
20
+ coffeescript:""
21
+ javascript:""
22
+
23
+ @state.bind "change:coffeescript", (model)->
24
+ editor.trigger("change:coffeescript")
25
+ code = model.get("coffeescript")
26
+
27
+ editor.compile code, (compiled)->
28
+ model.set('javascript',compiled)
29
+
30
+ @state.bind "change:javascript", (model)->
31
+ editor.onJavascriptChange?.call(editor, model.get('javascript') )
32
+
33
+ compile: (code, callback)->
34
+ response = {}
35
+ code ||= @getValue()
36
+
37
+ try
38
+ compiled = CoffeeScript.compile(code, @compileOptions)
39
+ callback?.call(@, compiled)
40
+ response =
41
+ success: true
42
+ compiled: compiled
43
+ catch error
44
+ @trigger("compile:error", error, code)
45
+
46
+ response =
47
+ success: false
48
+ compiled: ''
49
+ message: error.message
50
+
51
+ currentMode: ()->
52
+ @state.get("currentMode")
53
+
54
+ fixTabs: ()->
55
+ value = @getValue(false)
56
+ debugger
57
+
58
+ editorChange: ()->
59
+ @fixTabs()
60
+ @state.set( @currentMode(), @getValue() )
@@ -0,0 +1,4 @@
1
+ _.def("Luca.tools.CollectionInspector").extends("Luca.View").with
2
+ name: "collection_inspector"
3
+
4
+ className: "collection-inspector"