ende 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/WTFP-LICENSE +13 -0
- data/component.json +31 -0
- data/ende.gemspec +23 -0
- data/lib/assets/.gitkeep +0 -0
- data/lib/assets/javascripts/aura/extensions/devise.js.coffee +110 -0
- data/lib/assets/javascripts/aura/extensions/loader.js.coffee +48 -0
- data/lib/assets/javascripts/aura/extensions/mediator.js +98 -0
- data/lib/assets/javascripts/aura/extensions/models.js.coffee.erb +56 -0
- data/lib/assets/javascripts/aura/extensions/rivets.js.coffee +251 -0
- data/lib/assets/javascripts/aura/extensions/states.js.coffee +62 -0
- data/lib/assets/javascripts/aura/extensions/widget/eventable.js.coffee +66 -0
- data/lib/assets/javascripts/aura/extensions/widget/lifecycleable.js.coffee +75 -0
- data/lib/assets/javascripts/config/initializers/jquery.js.coffee +6 -0
- data/lib/assets/javascripts/config/initializers/load_components.js.coffee +73 -0
- data/lib/assets/javascripts/config/initializers/requirejs.js.coffee +3 -0
- data/lib/assets/javascripts/ende.js.coffee +1 -0
- data/lib/assets/javascripts/widgets/authenticator/main.js.coffee +95 -0
- data/lib/assets/javascripts/widgets/authenticator/presenter.js.coffee +35 -0
- data/lib/assets/javascripts/widgets/authenticator/states/default.html +7 -0
- data/lib/assets/javascripts/widgets/authenticator/states/index.js.coffee +3 -0
- data/lib/assets/javascripts/widgets/authenticator/states/passwords.html +6 -0
- data/lib/assets/javascripts/widgets/list/main.js.coffee +82 -0
- data/lib/assets/javascripts/widgets/list/presenter.js.coffee +34 -0
- data/lib/assets/javascripts/widgets/list/states/default.html +4 -0
- data/lib/assets/javascripts/widgets/list/states/index.js.coffee +2 -0
- data/lib/assets/javascripts/widgets/viewer/main.js.coffee +139 -0
- data/lib/assets/javascripts/widgets/viewer/presenter.js.coffee +54 -0
- data/lib/assets/javascripts/widgets/viewer/states/default.html +6 -0
- data/lib/assets/javascripts/widgets/viewer/states/index.js.coffee +2 -0
- data/lib/assets/stylesheets/application/modules/authenticator.css.styl +7 -0
- data/lib/assets/stylesheets/application/modules/widgets/structure/list.css.styl +9 -0
- data/lib/assets/stylesheets/application/modules/widgets/structure/viewer.css.styl +21 -0
- data/lib/assets/stylesheets/application/modules/widgets/structure/widget.css.styl +5 -0
- data/lib/assets/stylesheets/filter.styl +10 -0
- data/lib/assets/stylesheets/helpers/button.styl +61 -0
- data/lib/assets/stylesheets/helpers/general.styl +36 -0
- data/lib/assets/stylesheets/helpers/index.styl +4 -0
- data/lib/assets/stylesheets/helpers/link.styl +6 -0
- data/lib/assets/stylesheets/helpers/url.styl +5 -0
- data/lib/assets/stylesheets/modules/button.styl +42 -0
- data/lib/assets/stylesheets/sprite.styl +40 -0
- data/lib/assets/stylesheets/ssprites.styl +1 -0
- data/lib/ende/version.rb +3 -0
- data/lib/ende.rb +21 -0
- data/lib/tasks/.gitkeep +0 -0
- data/lib/tasks/component.thor +63 -0
- data/lib/tasks/sprite.thor +62 -0
- data/vendor/assets/javascripts/stampit/stampit.js +392 -0
- metadata +126 -0
@@ -0,0 +1,251 @@
|
|
1
|
+
define 'aura/extensions/rivets', ->
|
2
|
+
|
3
|
+
'use strict';
|
4
|
+
|
5
|
+
extend = require 'segmentio-extend'
|
6
|
+
|
7
|
+
rivets = require 'mikeric-rivets/dist/rivets'
|
8
|
+
|
9
|
+
Rivets = rivets._
|
10
|
+
|
11
|
+
observable_configuration = require 'indefinido-observable/lib/adapters/rivets'
|
12
|
+
|
13
|
+
rivets.configure observable_configuration
|
14
|
+
rivets.configure
|
15
|
+
templateDelimiters: ['{{', '}}']
|
16
|
+
|
17
|
+
# Custom rivets view because we don't want to prefix attributes
|
18
|
+
# Rivets.View
|
19
|
+
# -----------
|
20
|
+
# A collection of bindings built from a set of parent nodes.
|
21
|
+
class Rivets.View
|
22
|
+
# The DOM elements and the model objects for binding are passed into the
|
23
|
+
# constructor along with any local options that should be used throughout the
|
24
|
+
# context of the view and it's bindings.
|
25
|
+
constructor: (@els, @models, @options = {}) ->
|
26
|
+
@els = [@els] unless (@els.jquery || @els instanceof Array)
|
27
|
+
|
28
|
+
for option in ['config', 'binders', 'formatters']
|
29
|
+
@[option] = {}
|
30
|
+
@[option][k] = v for k, v of @options[option] if @options[option]
|
31
|
+
@[option][k] ?= v for k, v of Rivets[option]
|
32
|
+
|
33
|
+
@build()
|
34
|
+
|
35
|
+
# Regular expression used to match binding attributes.
|
36
|
+
bindingRegExp: =>
|
37
|
+
prefix = @config.prefix
|
38
|
+
if prefix then new RegExp("^data-#{prefix}-") else /^data-/
|
39
|
+
|
40
|
+
# Regular expression used to match component nodes.
|
41
|
+
componentRegExp: =>
|
42
|
+
new RegExp "^#{@config.prefix?.toUpperCase() ? 'RV'}-"
|
43
|
+
|
44
|
+
# Parses the DOM tree and builds `Rivets.Binding` instances for every matched
|
45
|
+
# binding declaration.
|
46
|
+
build: =>
|
47
|
+
@bindings = []
|
48
|
+
skipNodes = []
|
49
|
+
bindingRegExp = @bindingRegExp()
|
50
|
+
componentRegExp = @componentRegExp()
|
51
|
+
|
52
|
+
|
53
|
+
buildBinding = (binding, node, type, declaration) =>
|
54
|
+
options = {}
|
55
|
+
|
56
|
+
pipes = (pipe.trim() for pipe in declaration.split '|')
|
57
|
+
context = (ctx.trim() for ctx in pipes.shift().split '<')
|
58
|
+
path = context.shift()
|
59
|
+
splitPath = path.split /\.|:/
|
60
|
+
options.formatters = pipes
|
61
|
+
options.bypass = path.indexOf(':') != -1
|
62
|
+
|
63
|
+
if splitPath[0]
|
64
|
+
key = splitPath.shift()
|
65
|
+
else
|
66
|
+
key = null
|
67
|
+
splitPath.shift()
|
68
|
+
|
69
|
+
keypath = splitPath.join '.'
|
70
|
+
|
71
|
+
if dependencies = context.shift()
|
72
|
+
options.dependencies = dependencies.split /\s+/
|
73
|
+
|
74
|
+
if @models[key]
|
75
|
+
@bindings.push new Rivets[binding] @, node, type, key, keypath, options
|
76
|
+
else
|
77
|
+
console.warn "Model with key '#{key}' not found for binding of type '#{type}' on keypath '#{keypath}'.", @
|
78
|
+
|
79
|
+
parse = (node) =>
|
80
|
+
unless node in skipNodes
|
81
|
+
if node.nodeType is Node.TEXT_NODE
|
82
|
+
parser = Rivets.TextTemplateParser
|
83
|
+
|
84
|
+
if delimiters = @config.templateDelimiters
|
85
|
+
if (tokens = parser.parse(node.data, delimiters)).length
|
86
|
+
unless tokens.length is 1 and tokens[0].type is parser.types.text
|
87
|
+
[startToken, restTokens...] = tokens
|
88
|
+
node.data = startToken.value
|
89
|
+
|
90
|
+
if startToken.type is 0
|
91
|
+
node.data = startToken.value
|
92
|
+
else
|
93
|
+
buildBinding 'TextBinding', node, null, startToken.value
|
94
|
+
|
95
|
+
for token in restTokens
|
96
|
+
text = document.createTextNode token.value
|
97
|
+
node.parentNode.appendChild text
|
98
|
+
|
99
|
+
if token.type is 1
|
100
|
+
buildBinding 'TextBinding', text, null, token.value
|
101
|
+
else if componentRegExp.test node.tagName
|
102
|
+
type = node.tagName.replace(componentRegExp, '').toLowerCase()
|
103
|
+
@bindings.push new Rivets.ComponentBinding @, node, type
|
104
|
+
|
105
|
+
else if node.attributes?
|
106
|
+
for attribute in node.attributes
|
107
|
+
if bindingRegExp.test attribute.name
|
108
|
+
type = attribute.name.replace bindingRegExp, ''
|
109
|
+
unless binder = @binders[type]
|
110
|
+
for identifier, value of @binders
|
111
|
+
if identifier isnt '*' and identifier.indexOf('*') isnt -1
|
112
|
+
regexp = new RegExp "^#{identifier.replace('*', '.+')}$"
|
113
|
+
if regexp.test type
|
114
|
+
binder = value
|
115
|
+
|
116
|
+
binder or= @binders['*']
|
117
|
+
|
118
|
+
if binder.block
|
119
|
+
skipNodes.push n for n in node.childNodes
|
120
|
+
attributes = [attribute]
|
121
|
+
|
122
|
+
for attribute in attributes or node.attributes
|
123
|
+
if bindingRegExp.test attribute.name
|
124
|
+
type = attribute.name.replace bindingRegExp, ''
|
125
|
+
buildBinding 'Binding', node, type, attribute.value
|
126
|
+
|
127
|
+
parse childNode for childNode in node.childNodes
|
128
|
+
|
129
|
+
parse el for el in @els
|
130
|
+
|
131
|
+
return
|
132
|
+
|
133
|
+
# Returns an array of bindings where the supplied function evaluates to true.
|
134
|
+
select: (fn) =>
|
135
|
+
binding for binding in @bindings when fn binding
|
136
|
+
|
137
|
+
# Binds all of the current bindings for this view.
|
138
|
+
bind: =>
|
139
|
+
binding.bind() for binding in @bindings
|
140
|
+
|
141
|
+
# Unbinds all of the current bindings for this view.
|
142
|
+
unbind: =>
|
143
|
+
binding.unbind() for binding in @bindings
|
144
|
+
|
145
|
+
# Syncs up the view with the model by running the routines on all bindings.
|
146
|
+
sync: =>
|
147
|
+
binding.sync() for binding in @bindings
|
148
|
+
|
149
|
+
# Publishes the input values from the view back to the model (reverse sync).
|
150
|
+
publish: =>
|
151
|
+
binding.publish() for binding in @select (b) -> b.binder.publishes
|
152
|
+
|
153
|
+
# Updates the view's models along with any affected bindings.
|
154
|
+
update: (models = {}) =>
|
155
|
+
@models[key] = model for key, model of models
|
156
|
+
binding.update models for binding in @bindings
|
157
|
+
|
158
|
+
|
159
|
+
# Treat backspace, enter and other case
|
160
|
+
rivets.binders.spell ||=
|
161
|
+
publishes: true
|
162
|
+
bind: (el) ->
|
163
|
+
|
164
|
+
@options.publisher ||= (event) =>
|
165
|
+
value = Rivets.Util.getInputValue @el
|
166
|
+
|
167
|
+
# TODO more controllable enter handling
|
168
|
+
return if event.which == 13
|
169
|
+
|
170
|
+
value += String.fromCharCode event.which || event.keyCode || event.charCode
|
171
|
+
|
172
|
+
for formatter in @formatters.slice(0).reverse()
|
173
|
+
args = formatter.split /\s+/
|
174
|
+
id = args.shift()
|
175
|
+
|
176
|
+
if @view.formatters[id]?.publish
|
177
|
+
value = @view.formatters[id].publish value, args...
|
178
|
+
|
179
|
+
@view.config.adapter.publish @model, @keypath, value
|
180
|
+
event.preventDefault()
|
181
|
+
|
182
|
+
if window.jQuery?
|
183
|
+
# TODO Rivets.Util.bindEvent el, 'keypress change', @options.publisher
|
184
|
+
Rivets.Util.bindEvent el, 'keypress', @options.publisher
|
185
|
+
Rivets.Util.bindEvent el, 'change' , @publish
|
186
|
+
else
|
187
|
+
Rivets.Util.bindEvent el, 'keypress', @options.publisher
|
188
|
+
Rivets.Util.bindEvent el, 'change' , @publish
|
189
|
+
|
190
|
+
unbind: (el) ->
|
191
|
+
|
192
|
+
if window.jQuery?
|
193
|
+
# TODO Rivets.Util.unbindEvent el, 'keypress change', @options.publisher
|
194
|
+
Rivets.Util.unbindEvent el, 'keypress', @options.publisher
|
195
|
+
Rivets.Util.unbindEvent el, 'change', @publish
|
196
|
+
else
|
197
|
+
# TODO Rivets.Util.unbindEvent el, 'change' , @options.publisher
|
198
|
+
Rivets.Util.unbindEvent el, 'keypress', @options.publisher
|
199
|
+
Rivets.Util.unbindEvent el, 'change', @publish
|
200
|
+
|
201
|
+
routine: (el, value) ->
|
202
|
+
if window.jQuery?
|
203
|
+
el = jQuery el
|
204
|
+
|
205
|
+
if value?.toString() isnt el.val()?.toString()
|
206
|
+
el.val if value? then value else ''
|
207
|
+
else
|
208
|
+
|
209
|
+
if el.type is 'select-multiple'
|
210
|
+
o.selected = o.value in value for o in el if value?
|
211
|
+
else if value?.toString() isnt el.value?.toString()
|
212
|
+
el.value = if value? then value else ''
|
213
|
+
|
214
|
+
|
215
|
+
|
216
|
+
rivets.formatters.float = (value) ->
|
217
|
+
throw new TypeError "Invalid value passed to float formatter: #{value}" unless value?
|
218
|
+
|
219
|
+
# Blank value and impossible to convert to string
|
220
|
+
(!value || !(value + '')) && (value = 0)
|
221
|
+
|
222
|
+
# Force getter reading on IE
|
223
|
+
value = parseFloat value + ''
|
224
|
+
|
225
|
+
# Handle NaN
|
226
|
+
(isNaN(value)) && (value = 0)
|
227
|
+
|
228
|
+
# Format value
|
229
|
+
value.toFixed(2).toString().replace '.', ','
|
230
|
+
|
231
|
+
rivets.formatters.currency = (value) ->
|
232
|
+
'R$ ' + rivets.formatters.float value
|
233
|
+
|
234
|
+
|
235
|
+
(application) ->
|
236
|
+
|
237
|
+
initialize: (application) ->
|
238
|
+
|
239
|
+
extend application.sandbox,
|
240
|
+
view: rivets
|
241
|
+
|
242
|
+
extend application.core.Widgets.Base.prototype,
|
243
|
+
bind: (presentation, options) ->
|
244
|
+
if presentation.presented
|
245
|
+
presented = presentation.presented
|
246
|
+
delete presentation.presented
|
247
|
+
|
248
|
+
@view = rivets.bind @$el, presentation, options
|
249
|
+
|
250
|
+
presented(@view) if presented?
|
251
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
define 'aura/extensions/states', ['application/states'], (states) ->
|
2
|
+
|
3
|
+
'use strict'
|
4
|
+
|
5
|
+
(application) ->
|
6
|
+
core = application.core
|
7
|
+
logger = application.logger
|
8
|
+
mediator = core.mediator
|
9
|
+
_ = core.util._
|
10
|
+
|
11
|
+
|
12
|
+
state =
|
13
|
+
current: 'default'
|
14
|
+
list: []
|
15
|
+
previous: null
|
16
|
+
change: (transition) ->
|
17
|
+
if state.current != transition.to
|
18
|
+
from = core.state
|
19
|
+
to = if transition.to == 'previous' then state.previous else transition.to
|
20
|
+
state.previous = state.current
|
21
|
+
state.current = to
|
22
|
+
mediator.emit 'state.changed', to: to, from: from
|
23
|
+
else
|
24
|
+
mediator.emit 'state.errored', to: transition.to, message: 'Application already in this state!'
|
25
|
+
changed: (transition) ->
|
26
|
+
core.dom.find('html').addClass(transition.to).removeClass(transition.from)
|
27
|
+
|
28
|
+
# Set default intial state
|
29
|
+
core.dom.find('html').addClass state.current
|
30
|
+
|
31
|
+
# Application flow control
|
32
|
+
flow =
|
33
|
+
|
34
|
+
changed: (transition) ->
|
35
|
+
widget_configurations = states[transition.to]
|
36
|
+
if widget_configurations
|
37
|
+
widgets = []
|
38
|
+
|
39
|
+
for name, options of widget_configurations
|
40
|
+
widgets.push
|
41
|
+
name: options.name || name
|
42
|
+
options: options
|
43
|
+
|
44
|
+
delete options.name
|
45
|
+
|
46
|
+
core.inject(widgets).fail flow.failed
|
47
|
+
|
48
|
+
delete states[transition.to]
|
49
|
+
failed: (exception) ->
|
50
|
+
logger.error "states.flow.failed: Failed autostarting widget #{@} \n Message: #{exception.message}", exception
|
51
|
+
|
52
|
+
|
53
|
+
initialize: (application) ->
|
54
|
+
mediator.on 'state.change' , state.change
|
55
|
+
mediator.on 'state.changed', state.changed
|
56
|
+
|
57
|
+
# TODO load widgets before state.changed, load on state.change
|
58
|
+
mediator.on 'state.changed', flow.changed
|
59
|
+
|
60
|
+
Object.defineProperty core, 'state',
|
61
|
+
set: (to) -> state.change to: to
|
62
|
+
get: -> state.current
|
@@ -0,0 +1,66 @@
|
|
1
|
+
define 'aura/extensions/widget/eventable', ->
|
2
|
+
|
3
|
+
'use strict';
|
4
|
+
|
5
|
+
extend = require 'segmentio-extend'
|
6
|
+
|
7
|
+
extractor = /.*?\$(.*?)@(.*?)\+(.*?)/
|
8
|
+
|
9
|
+
translations = new Map()
|
10
|
+
translations.set 'transition.end',
|
11
|
+
'webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend'
|
12
|
+
|
13
|
+
translations.set 'transition.start',
|
14
|
+
'webkitTransitionStart otransitionstart oTransitionStart msTransitionStart transitionstart'
|
15
|
+
|
16
|
+
translations.set 'animation.end',
|
17
|
+
'webkitAnimationEnd oanimationend oAnimationEnd msAnimationEnd animationend'
|
18
|
+
|
19
|
+
translations.set 'animation.start',
|
20
|
+
'webkitAnimationStart oanimationstart oAnimationStart msAnimationStart animationstart'
|
21
|
+
|
22
|
+
|
23
|
+
create_handler = (widget, event_name) ->
|
24
|
+
(event) ->
|
25
|
+
widget.sandbox.emit "#{widget.name}.#{widget.identifier}.#{event_name}ed", @
|
26
|
+
event.preventDefault()
|
27
|
+
false
|
28
|
+
|
29
|
+
|
30
|
+
(application) ->
|
31
|
+
|
32
|
+
initialize: (application) ->
|
33
|
+
|
34
|
+
extend application.core.Widgets.Base.prototype,
|
35
|
+
# TODO implement rivets compatibility, instead of generic binding events, alter html
|
36
|
+
handles: (event_name, widget_event_name = event_name, selector = @$el) ->
|
37
|
+
unless @name
|
38
|
+
message = "Widget name must be provided in order to use handlers, but this.name is '#{@name}' \n"
|
39
|
+
message = "Also you may have forgotten to set the type of your widget to 'Base'"
|
40
|
+
throw message
|
41
|
+
|
42
|
+
context = @$el unless selector == @$el
|
43
|
+
|
44
|
+
event_name = translations.get(event_name) ? event_name
|
45
|
+
|
46
|
+
@sandbox.dom.find(selector, context).on event_name, create_handler(@, widget_event_name || event_name)
|
47
|
+
|
48
|
+
parent = application.core.Widgets.Base
|
49
|
+
|
50
|
+
# TODO pass this extensions to the identifiable extension
|
51
|
+
eventableize = (options) ->
|
52
|
+
matches = extractor.exec options._ref
|
53
|
+
@name = matches[1]
|
54
|
+
@identifier = options.resource ? matches[2]
|
55
|
+
|
56
|
+
parent.call @, options
|
57
|
+
|
58
|
+
@sandbox.identifier = @identifier
|
59
|
+
|
60
|
+
@
|
61
|
+
|
62
|
+
eventableize.prototype = new parent _ref: ''
|
63
|
+
extend eventableize, parent
|
64
|
+
application.core.Widgets.Base = eventableize
|
65
|
+
|
66
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
define 'aura/extensions/widget/lifecycleable', ->
|
2
|
+
|
3
|
+
'use strict'
|
4
|
+
|
5
|
+
# TODO Remove jquery and use core dependencies
|
6
|
+
jQuery = require 'jquery'
|
7
|
+
|
8
|
+
lifecycleable =
|
9
|
+
injection: (definition) ->
|
10
|
+
options = definition.options
|
11
|
+
|
12
|
+
# TODO check for existing widgets before convert options, and
|
13
|
+
# not only if type is object
|
14
|
+
for subwidget_name, suboptions of options
|
15
|
+
# TODO if isWidget subwidget_name
|
16
|
+
if $.type(suboptions) == 'object'
|
17
|
+
|
18
|
+
for name, suboption of suboptions
|
19
|
+
options["#{subwidget_name}#{@capitalize name}"] = suboption
|
20
|
+
|
21
|
+
# TODO delete options[subwidget_name]
|
22
|
+
|
23
|
+
ref = definition.name.split "@"
|
24
|
+
widgetName = @decamelize ref[0]
|
25
|
+
widgetSource = ref[1] || "default"
|
26
|
+
|
27
|
+
requireContext = require.s.contexts._
|
28
|
+
widgetsPath = @sources[widgetSource] || "widgets"
|
29
|
+
|
30
|
+
# Register the widget a s requirejs package...
|
31
|
+
# TODO: packages are not supported by almond, should we find another way to do this ?
|
32
|
+
options.ref = '__widget__$' + widgetName + "@" + widgetSource
|
33
|
+
options.baseUrl = widgetsPath + "/" + widgetName
|
34
|
+
options.require = options.require || {}
|
35
|
+
options.require.packages = options.require.packages || []
|
36
|
+
options.require.packages.push name: options.ref, location: widgetsPath + "/" + widgetName
|
37
|
+
options.name = widgetName;
|
38
|
+
|
39
|
+
unless options.el
|
40
|
+
options.el = jQuery '<div class="widget"></div>'
|
41
|
+
@root.append options.el
|
42
|
+
|
43
|
+
@find(options.el).attr options.attributes if options.attributes?
|
44
|
+
|
45
|
+
definition
|
46
|
+
|
47
|
+
(application) ->
|
48
|
+
|
49
|
+
initialize: (application) ->
|
50
|
+
core = application.core
|
51
|
+
|
52
|
+
# TODO use indemma inflections module instead
|
53
|
+
core.util.capitalize = (string) ->
|
54
|
+
string.charAt(0).toUpperCase() + string.slice(1);
|
55
|
+
|
56
|
+
|
57
|
+
# Cache usefull methods
|
58
|
+
lifecycleable.sources = application.config.widgets.sources
|
59
|
+
lifecycleable.find = core.dom.find
|
60
|
+
lifecycleable.root = core.dom.find app.startOptions.widgets
|
61
|
+
lifecycleable.decamelize = core.util.decamelize
|
62
|
+
lifecycleable.capitalize = core.util.capitalize
|
63
|
+
|
64
|
+
|
65
|
+
# Add injection functiono for widgets
|
66
|
+
core.inject = (name = options.name, options) ->
|
67
|
+
if jQuery.isArray name
|
68
|
+
widgets = name
|
69
|
+
injections = core.util._.map widgets, lifecycleable.injection, lifecycleable
|
70
|
+
return core.start injections
|
71
|
+
|
72
|
+
else if not name
|
73
|
+
throw new TypeError "app.core.inject: No widget name provided" unless name?
|
74
|
+
|
75
|
+
core.start = lifecycleable.injection options
|
@@ -0,0 +1,73 @@
|
|
1
|
+
#= require require/require
|
2
|
+
#= require build
|
3
|
+
|
4
|
+
root = exports ? this
|
5
|
+
|
6
|
+
# Little object class to merge component require and requirejs require
|
7
|
+
loader =
|
8
|
+
shim: ->
|
9
|
+
# Store loaders functions
|
10
|
+
loader.loaders.component = require
|
11
|
+
loader.loaders.requirejs = requirejs
|
12
|
+
loader.activate.define = root.define
|
13
|
+
|
14
|
+
# Expand require fuction with requirejs configurations
|
15
|
+
# so we can require without great problems
|
16
|
+
loader.require.config = requirejs.config
|
17
|
+
loader.require.s = requirejs.s
|
18
|
+
|
19
|
+
initialize: ->
|
20
|
+
extend = require 'segmentio-extend'
|
21
|
+
extend loader.require, require
|
22
|
+
|
23
|
+
# Override global require for ower one
|
24
|
+
root.require = loader.require
|
25
|
+
root.loader = loader
|
26
|
+
|
27
|
+
# Resource loaders compatibility
|
28
|
+
loaders:
|
29
|
+
requirejs : null
|
30
|
+
component : null
|
31
|
+
discovered: null
|
32
|
+
|
33
|
+
discover: (params...) ->
|
34
|
+
|
35
|
+
if params[0] instanceof Array
|
36
|
+
requirer = 'requirejs'
|
37
|
+
else
|
38
|
+
requirer = 'component'
|
39
|
+
|
40
|
+
@activate (requirer) and requirer
|
41
|
+
|
42
|
+
activate: (requirer) ->
|
43
|
+
switch requirer
|
44
|
+
when 'component'
|
45
|
+
root.define = null
|
46
|
+
when 'requirejs'
|
47
|
+
root.define = @activate.define
|
48
|
+
else
|
49
|
+
false
|
50
|
+
|
51
|
+
@loaders.discovered = @loaders[requirer]
|
52
|
+
|
53
|
+
true
|
54
|
+
|
55
|
+
require: (params...) ->
|
56
|
+
using = loader.discover params...
|
57
|
+
|
58
|
+
try
|
59
|
+
|
60
|
+
module = loader.loaders.discovered.apply @, params
|
61
|
+
|
62
|
+
catch e
|
63
|
+
console.warn 'Failed to load \'', params[0], "' with #{using}: Error: '", e.message, '\'. Trying with requirejs.'
|
64
|
+
loader.activate 'requirejs'
|
65
|
+
module = loader.loaders.discovered.apply @, params unless module
|
66
|
+
|
67
|
+
# Always let requirjs active by default
|
68
|
+
loader.activate 'requirejs'
|
69
|
+
|
70
|
+
module
|
71
|
+
|
72
|
+
loader.shim()
|
73
|
+
loader.initialize()
|
@@ -0,0 +1 @@
|
|
1
|
+
#= require_tree ./config/initializers
|
@@ -0,0 +1,95 @@
|
|
1
|
+
define ['./states/index', './presenter'], (templates, presenter) ->
|
2
|
+
|
3
|
+
# If some extension provides you can use the type defined in there
|
4
|
+
# to extend your widget. Defaults to Base constructor.
|
5
|
+
#
|
6
|
+
# type: 'Base'
|
7
|
+
|
8
|
+
# Default values for the options passed to this widget
|
9
|
+
#
|
10
|
+
# Note: the options are passed thorught the html element data
|
11
|
+
# attributes for this widget: <div data-aura-amount="3"></div>
|
12
|
+
#
|
13
|
+
# options: {}
|
14
|
+
|
15
|
+
|
16
|
+
# Widget initialization method, will be called upon loading, options
|
17
|
+
# are already filled with defaults
|
18
|
+
initialize: (options) ->
|
19
|
+
sandbox = @sandbox
|
20
|
+
sandbox.logger.log "initialized!"
|
21
|
+
|
22
|
+
base =
|
23
|
+
status: null
|
24
|
+
classes: =>
|
25
|
+
"#{@state} #{@status} authenticator"
|
26
|
+
toggle_state: (event) =>
|
27
|
+
@state = if @state == 'default' then 'passwords' else 'default'
|
28
|
+
false
|
29
|
+
|
30
|
+
# Forward the models to the presenter
|
31
|
+
authenticator =
|
32
|
+
message: null
|
33
|
+
email: null
|
34
|
+
password: null
|
35
|
+
# TODO copiar do modacad
|
36
|
+
# button_label: 'Entrar'
|
37
|
+
|
38
|
+
# Authentication state
|
39
|
+
authenticate: (event) ->
|
40
|
+
base.status = "loading" # replace all status
|
41
|
+
sandbox.emit 'user.sign_in', authentication
|
42
|
+
|
43
|
+
# Listeners
|
44
|
+
authenticated: (session) ->
|
45
|
+
base.status = "success"
|
46
|
+
|
47
|
+
unauthorized: ->
|
48
|
+
authentication.message = "Ops... seu e-mail ou senha estão incorretos. Tente mais uma vez!<br><a href='#'>Esqueceu sua senha? Clique aqui.</a>"
|
49
|
+
base.status = "error"
|
50
|
+
|
51
|
+
|
52
|
+
recoverer =
|
53
|
+
email: null
|
54
|
+
message: null
|
55
|
+
|
56
|
+
# TODO copiar do modacad
|
57
|
+
# button_label: 'Entrar'
|
58
|
+
|
59
|
+
# Recovery state
|
60
|
+
recover: (event, models) ->
|
61
|
+
base.status = 'loading'
|
62
|
+
sandbox.emit 'user.recover_password', recovery
|
63
|
+
|
64
|
+
recovered: (password) ->
|
65
|
+
base.status = 'success'
|
66
|
+
|
67
|
+
|
68
|
+
# Bind and unbind events depending on state
|
69
|
+
sandbox.on 'user.signed_in' , authenticator.authenticated
|
70
|
+
sandbox.on 'user.unauthorized' , authenticator.unauthorized
|
71
|
+
sandbox.on 'user.password_recovered' , recoverer.recovered
|
72
|
+
|
73
|
+
|
74
|
+
# Will also initialize sandbox!
|
75
|
+
@$el.attr 'data-class', 'base.classes < base.status'
|
76
|
+
@presentation = presenter authenticator, recoverer, base
|
77
|
+
authentication = @presentation.authenticator
|
78
|
+
recovery = @presentation.recoverer
|
79
|
+
|
80
|
+
# TODO Extract to stateable widget
|
81
|
+
# TODO use observable
|
82
|
+
@observed ||= {}
|
83
|
+
Object.defineProperty @, 'state',
|
84
|
+
get: => @observed.state
|
85
|
+
set: @transition
|
86
|
+
|
87
|
+
@state = 'default'
|
88
|
+
|
89
|
+
|
90
|
+
# TODO Extract to stateable widget
|
91
|
+
# TODO use observable
|
92
|
+
transition: (to) ->
|
93
|
+
@html templates[to]
|
94
|
+
@bind @presentation
|
95
|
+
@observed.state = to
|
@@ -0,0 +1,35 @@
|
|
1
|
+
'use strict'
|
2
|
+
define ->
|
3
|
+
observable = require('observable').mixin
|
4
|
+
|
5
|
+
(authenticator, recoverer, base) ->
|
6
|
+
|
7
|
+
authenticator: observable Object.create null,
|
8
|
+
status:
|
9
|
+
configurable: true
|
10
|
+
get: -> authenticator.status
|
11
|
+
set: (status) -> authenticator.status = status
|
12
|
+
message:
|
13
|
+
configurable: true
|
14
|
+
get: -> authenticator.message
|
15
|
+
set: (message) -> authenticator.message = message
|
16
|
+
classes:
|
17
|
+
configurable: true
|
18
|
+
value: ->
|
19
|
+
"widget authenticator #{authenticator.status}"
|
20
|
+
email:
|
21
|
+
configurable: true
|
22
|
+
set: (email) -> authenticator.email = email
|
23
|
+
get: -> authenticator.email
|
24
|
+
password:
|
25
|
+
configurable: true
|
26
|
+
set: (password) -> authenticator.password = password
|
27
|
+
get: -> authenticator.password
|
28
|
+
authenticate:
|
29
|
+
configurable: true
|
30
|
+
value: authenticator.authenticate
|
31
|
+
|
32
|
+
# TODO split into two presenters
|
33
|
+
recoverer: observable recoverer
|
34
|
+
|
35
|
+
base: observable base
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<div class="message" data-html="authenticator.message"> </div>
|
2
|
+
<input type="email" data-value="authenticator.email" placeholder="Login" />
|
3
|
+
<input type="password" data-value="authenticator.password" placeholder="Password" />
|
4
|
+
<button data-on-click="authenticator.authenticate">
|
5
|
+
Authenticate!
|
6
|
+
</button>
|
7
|
+
<a data-on-click="base.toggle_state">Recuperar Senha</a>
|