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