fron 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ee70da4161fdf883ebd912c124c53c5a8bb8ada5
4
+ data.tar.gz: ab1e9096d251fc25a772e8b9fcf9798b1b8deda4
5
+ SHA512:
6
+ metadata.gz: cdddc4a004ae3e9160e82fa001db6f41199038d72e47426a4953ce40dbf2f681c0ba2dacd4f9fd31e66a8140c372590fadbe6004a0049b4f5ad1fd51b3592698
7
+ data.tar.gz: d265e541022bfb84a9299c6b9ca24386738ba932f5679cfe37fe5b3bd959734aa2bf20f39ec3930cb101619a61d36dc754c84fa77a40daf5bea375b932fa3d07
@@ -0,0 +1,7 @@
1
+ # Application
2
+
3
+ * [Configuration]()
4
+ * [Controllers]()
5
+ * [Routers]()
6
+ * [Components]()
7
+ * [DOM]()
@@ -0,0 +1,29 @@
1
+ # Configuration
2
+ Application configuration utility.
3
+
4
+ ## Title
5
+ The layout of the application can be set with the 'title' DSL.
6
+
7
+ ## Layout
8
+ The layout of the application can be set with the 'layout' DSL.
9
+
10
+ This DSL takes a block and runs it in the context of the main application component, with the injection poin for controllers as the argument.
11
+
12
+ ## Routes
13
+ For using routes see the [routing documentation]().
14
+
15
+ ## Example
16
+ ```ruby
17
+ class TestApplication < Application
18
+ config.title = 'Test Application'
19
+
20
+ config.layout do |main|
21
+ component :header, 'header'
22
+ self << main
23
+ end
24
+
25
+ config.routes do
26
+ map SiteController
27
+ end
28
+ end
29
+ ```
@@ -0,0 +1,35 @@
1
+ # Controllers
2
+ Controllers are responsible for parts of the application, it handles state / view changes for itself only.
3
+
4
+ ## Base Component
5
+ The base component can be specified with the `base` DSL method.
6
+
7
+ The base component is the "page" wthich is injected into the document when a route matches this controller. It is accessible with the `@base` attribute. It must be a subclass of `Component`.
8
+
9
+ ## Global Events
10
+ A controller can listen on Global Events with the `on` DSL.
11
+
12
+ The first argument is the event to listen to and the second argument is the method to run when the event triggered. Globa Events can be trigger like so:
13
+ ```ruby
14
+ Eventable.trigger 'load'
15
+ ```
16
+
17
+ ## Routes
18
+ For using routes see the [routing documentation]().
19
+
20
+ ## Example
21
+ ```ruby
22
+ class TestController < Controller
23
+ base BaseComponent
24
+
25
+ on :load, :loaded
26
+
27
+ def loaded
28
+
29
+ end
30
+
31
+ def test
32
+ puts @base
33
+ end
34
+ end
35
+ ```
@@ -0,0 +1,63 @@
1
+ # Routing
2
+ There are two leves of routing:
3
+
4
+ * Application level: This defines which controller is responsibe for specified paths
5
+ * Controller level: This defines which actions / sub controllers on the controller are called for specified paths
6
+
7
+ ## Applications Routes
8
+ Routes are defined in the Application Configuration with the `routes` DSL method.
9
+
10
+ You can define controllers for specific paths, for example the following `map 'users/', UserController` will delegate all paths under the `users/` to the `UserController`. The controller only recieves the portion of the path which remains after the matched path.
11
+
12
+ ## Controller Routes
13
+ Routes are defined with the `route` DSL method.
14
+
15
+ The first argument is the path, the second argument is the action / sub controller to be called. The path can contain parameter identifiers such as `:name`. These will be passed along to the action as a hash in the first parameter.
16
+
17
+ ## Before Filters
18
+ Before filters can be added to the controllers actions with the `beforeFilter` DSL method.
19
+
20
+ The first argument is the action to be called, the second argument is an array of methods which before the action should be called.
21
+
22
+ ## Example
23
+ ```ruby
24
+ class TestApplication < Application
25
+ config.routes do
26
+ # Both 'users/new' and 'users/10' will be
27
+ # handled by an instance of UserController
28
+ map 'users/', UserController
29
+
30
+ # Anything else will be handled by
31
+ # an instance of IndexController
32
+ map IndexController
33
+ end
34
+ end
35
+
36
+ class CommentsController < Controller
37
+ ...
38
+ end
39
+
40
+ class UserController < Controller
41
+ # users/new -> UserController#authorize -> UserController#new
42
+ route 'new', :new
43
+ # users/10/comments -> CommentsController with params[:id] = 10
44
+ route ':id/comments/', CommentsController
45
+ # users/10 -> UserController#authorize -> USerController#user with params[:id] = 10
46
+ route ':id', :user
47
+
48
+ beforeFilter :authorize, [:new,:user]
49
+
50
+ def new
51
+ ...
52
+ end
53
+
54
+ def user(params)
55
+ puts params[:id]
56
+ ...
57
+ end
58
+
59
+ def authorize
60
+ ...
61
+ end
62
+ end
63
+ ```
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/fron/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'fron'
6
+ s.version = Fron::VERSION
7
+ s.author = 'Gusztav Szikszai'
8
+ s.email = 'gusztav.szikszai@digitalnatives.hu'
9
+ s.homepage = ''
10
+ s.summary = 'Frontend Application Framework'
11
+ s.description = 'Frontend Application Framework that uses Opal'
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.require_paths = ['lib']
17
+
18
+ s.add_runtime_dependency 'opal', ['~> 0.6.2']
19
+ s.add_development_dependency 'opal-rspec', '~> 0.3.0.beta3'
20
+ end
@@ -0,0 +1,4 @@
1
+ require 'opal'
2
+ require 'fron/version'
3
+
4
+ Opal.append_path File.expand_path('../../opal', __FILE__).untaint
@@ -0,0 +1,3 @@
1
+ module Fron
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,5 @@
1
+ require 'opal'
2
+ require './fron/dom'
3
+ require './fron/request'
4
+ require './fron/storage'
5
+ require './fron/core'
@@ -0,0 +1,17 @@
1
+ class Hash
2
+ def to_query_string
3
+ r = []
4
+ each do |key,value|
5
+ r << `encodeURIComponent(#{key})+"="+encodeURIComponent(#{value})`
6
+ end
7
+ r.join "&"
8
+ end
9
+
10
+ def to_form_data
11
+ r = `new FormData()`
12
+ each do |key,value|
13
+ `r.append(#{key},#{value})`
14
+ end
15
+ r
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ require './core/logger'
2
+ require './core/component'
3
+ require './core/adapters/rails'
4
+ require './core/adapters/local-storage'
5
+ require './core/configuration'
6
+ require './core/eventable'
7
+ require './core/model'
8
+ require './core/router'
9
+ require './core/controller'
10
+ require './core/application'
@@ -0,0 +1,41 @@
1
+ require 'json'
2
+ require 'securerandom'
3
+
4
+ module Fron
5
+ module Adapters
6
+ class LocalAdapter
7
+ def initialize(options)
8
+ @options = options
9
+ end
10
+
11
+ def all(&block)
12
+ block.call LocalStorage.all
13
+ end
14
+
15
+ def get(id, &block)
16
+ block.call LocalStorage.get id
17
+ end
18
+
19
+ def set(id, data, &block)
20
+ id = SecureRandom.uuid unless id
21
+ data[:id] = id
22
+ unless (errors = validate data)
23
+ LocalStorage.set id, data
24
+ block.call nil
25
+ else
26
+ block.call errors
27
+ end
28
+ end
29
+
30
+ def validate(data)
31
+ errors = {}
32
+ @options[:fields].map do |field|
33
+ next unless data[field] == ""
34
+ errors[field] = ["can't be blank"]
35
+ valid = false
36
+ end
37
+ errors.keys.length == 0 ? nil : errors
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,48 @@
1
+ module Fron
2
+ module Adapters
3
+ class RailsAdapter
4
+
5
+ def initialize(options)
6
+ @options = options
7
+ @request = Request.new
8
+ end
9
+
10
+ def all(&block)
11
+ setUrl nil
12
+ @request.get { |response| block.call response.json }
13
+ end
14
+
15
+ def get(id,&block)
16
+ setUrl id
17
+ @request.get { |response| block.call response.json }
18
+ end
19
+
20
+ def set(id,data,&block)
21
+ setUrl id
22
+ method = id ? 'put' : 'post'
23
+ @request.send(method,transform(data)) do |response|
24
+ block.call case response.status
25
+ when 201, 204
26
+ nil
27
+ when 422
28
+ response.json
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def setUrl(id)
36
+ base = @options[:endpoint] + "/" + @options[:resources]
37
+ base += id ? "/" + id.to_s : ".json"
38
+ @request.url = base
39
+ end
40
+
41
+ def transform(data)
42
+ newdata = data.dup
43
+ newdata.keys.each{ |key| newdata["#{@options[:resource]}[#{key}]"] = newdata.delete key}
44
+ newdata
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,39 @@
1
+ module Fron
2
+ class Application
3
+ class << self
4
+ def config
5
+ @configuration ||= Configuration.new
6
+ end
7
+ end
8
+
9
+ def initialize
10
+ @routeMap = []
11
+ DOM::Document.title = config.title
12
+ instance_eval &config.routeBlock
13
+ @router = Router.new @routeMap, config
14
+
15
+ DOM::Window.on 'load' do
16
+ config.stylesheets.map do |sheet|
17
+ link = DOM::Element.new("link[rel=stylesheet][type=text/css][href=#{sheet}]")
18
+ link.on 'load' do
19
+ config.logger.info "External stylesheet loaded: #{sheet}"
20
+ end
21
+ DOM::Document.head << link
22
+ end
23
+ end
24
+ config.logger.info "Initialized Applicationation!"
25
+ config.logger.info "Inserting application to DOM!"
26
+ DOM::Document.body << config.app
27
+ end
28
+
29
+ private
30
+
31
+ def map(*args)
32
+ @routeMap << Router.map(*args)
33
+ end
34
+
35
+ def config
36
+ self.class.config
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,81 @@
1
+ module Fron
2
+ class Component < DOM::Element
3
+ attr_reader :model
4
+
5
+ class << self
6
+ attr_accessor :events
7
+ attr_accessor :tagname
8
+ attr_accessor :components
9
+
10
+ def tag(tag)
11
+ @tagname = tag
12
+ end
13
+
14
+ def on(*args)
15
+ @events ||= []
16
+ @events << args
17
+ end
18
+
19
+ def component(*args,&block)
20
+ attr_reader args[0]
21
+ @components ||= []
22
+ @components << ( args << block )
23
+ end
24
+
25
+ def delegate(method,target)
26
+ define_method(method) do
27
+ instance_variable_get("@#{target}").send(method)
28
+ end
29
+
30
+ define_method(method+"=") do |value|
31
+ instance_variable_get("@#{target}").send(method+"=",value)
32
+ end
33
+ end
34
+ end
35
+
36
+ def initialize(*args)
37
+ case args.length
38
+ when 1
39
+ @model = args[0]
40
+ when 2
41
+ tag, @model = args
42
+ end
43
+
44
+ super tag || self.class.tagname || self.class.name.split("::").last
45
+
46
+ applyEvents
47
+ createComponents
48
+
49
+ return if !respond_to?(:render) || !@model
50
+ @model.on 'change' do render end
51
+ render
52
+ end
53
+
54
+ def component(name,comp,&block)
55
+ c = comp.is_a?(Class) ? comp.new(@model) : Component.new(comp, @model)
56
+ c.instance_eval(&block) if block
57
+ self << c
58
+ self.instance_variable_set "@#{name}", c
59
+ end
60
+
61
+ private
62
+
63
+ def createComponents
64
+ return unless self.class.components
65
+ self.class.components.each do |args|
66
+ component args[0], args[1], &args[2]
67
+ end
68
+ end
69
+
70
+ def applyEvents
71
+ return unless self.class.events
72
+ self.class.events.each do |args|
73
+ if args.length == 3
74
+ delegate(args[0], args[1]) { |e| self.method(args[2]).call e }
75
+ else
76
+ on(args[0]) { |e| self.method(args[1]).call e }
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,26 @@
1
+ module Fron
2
+ class Configuration
3
+ class App < Component
4
+ end
5
+ class Yield < Component
6
+ end
7
+
8
+ attr_accessor :title, :stylesheets, :logger
9
+ attr_reader :routeBlock, :main, :app
10
+
11
+ def initialize
12
+ @main = Yield.new
13
+ @app = App.new
14
+
15
+ DOM::Document.body.empty
16
+ end
17
+
18
+ def routes(&block)
19
+ @routeBlock = block
20
+ end
21
+
22
+ def layout(&block)
23
+ @app.instance_exec @main, &block
24
+ end
25
+ end
26
+ end