tomify 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/tomify/default/object.coffee +3 -0
  3. data/app/assets/javascripts/tomify/dynamic/classes/component.coffee +3 -1
  4. data/app/assets/javascripts/tomify/dynamic/classes/field.coffee +1 -0
  5. data/app/assets/javascripts/tomify/dynamic/classes/form.coffee +7 -6
  6. data/app/assets/javascripts/tomify/dynamic/classes/namespace.coffee +7 -11
  7. data/app/assets/javascripts/tomify/dynamic/classes/store.coffee +2 -1
  8. data/app/assets/javascripts/tomify/dynamic/global.coffee +1 -0
  9. data/app/assets/javascripts/tomify/dynamic/react/components/fields/default.coffee +1 -1
  10. data/app/assets/javascripts/tomify/dynamic/react/components/fields/file.coffee +1 -1
  11. data/app/assets/javascripts/tomify/dynamic/react/components/fields/textarea.coffee +1 -1
  12. data/app/assets/javascripts/tomify/dynamic/react/components/layout/messages.coffee +1 -1
  13. data/app/assets/javascripts/tomify/dynamic/react/components/layout/public_navbar.coffee +3 -2
  14. data/app/assets/javascripts/tomify/dynamic/react/components/public/profile.coffee +26 -0
  15. data/app/assets/javascripts/tomify/dynamic/react/components/public/sessions/show.coffee +0 -2
  16. data/app/assets/javascripts/tomify/dynamic/react/components/public/users/edit.coffee +24 -11
  17. data/app/assets/javascripts/tomify/dynamic/react/components/public/users/new.coffee +1 -1
  18. data/app/assets/javascripts/tomify/dynamic/react/components/public/users/show.coffee +23 -0
  19. data/app/assets/javascripts/tomify/dynamic/react/mixins/follow.coffee +2 -1
  20. data/app/controllers/tomify/api/public/users_controller.rb +9 -3
  21. data/app/controllers/tomify/public/profiles_controller.rb +7 -0
  22. data/config/routes.rb +2 -2
  23. data/lib/tomify/version.rb +1 -1
  24. metadata +5 -3
  25. data/app/controllers/tomify/public/users_controller.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a150d58dedb05af95126801e20124eb12a0d560
4
- data.tar.gz: b52597cf7561633de5a271dd217ddea463787a40
3
+ metadata.gz: 85ed285b35f88cccdcd9e97d65c548def5a31246
4
+ data.tar.gz: 8b6da7d56dbf1e62ffc0cdca368bb76ec8bb7fcf
5
5
  SHA512:
6
- metadata.gz: b5163f01fddc2fd9cbb95ee29a1482d757feb9f24a83faa87dc0bb1f90b8d23aa85b53ae107d14ad06e81e939e68a9592fe763ac743cff180e821fe691e19ba9
7
- data.tar.gz: b3b4bc88c6243f44348b1c5623394c9149da46f0ec2f734665d2df3eb161d88101bda6d95b616945fbd6f8b0f25b1f791640a049130213aa3e498d1ec3d80274
6
+ metadata.gz: b2b4b0a746afbf86c9c6a33387dd10f6c069667c40c7d882985601f3ff0417ae5632ab23d116cecddcfe0e686dff8f3582f5858fab1a9d83f12f33ebcc3a508f
7
+ data.tar.gz: 120be037ee276b3a4903798c5a0f613c2a38d5501e68499b8b1e3a4263eb87596209d988503c4c04c9ca9651588dedc722ddce7310817f0745587f5abe2f425a
@@ -10,3 +10,6 @@
10
10
  path += "#{encodeURIComponent(key)}=#{encodeURIComponent(value)}"
11
11
  path += "&" unless key == last
12
12
  path
13
+
14
+ @ObjectEmpty = (object) ->
15
+ Object.keys(object).length == 0
@@ -3,5 +3,7 @@ class @Component extends Namespace
3
3
  @create: (namespace, component) ->
4
4
  component.displayName ?= namespace
5
5
  component.mixins = @defaultMixins.concat(component.mixins || [])
6
- @namespace namespace, React.createClass(component)
6
+ value = @namespace namespace, React.createClass(component)
7
+ @public namespace
8
+ value
7
9
  @defaultMixins: [WillInitializeMixin, FollowMixin]
@@ -1,6 +1,7 @@
1
1
  class @Field
2
2
  @build: (options) ->
3
3
  props = { name: options.name, type: options.type }
4
+ props.placeholder = options.placeholder || options.name.titleize
4
5
  switch props.type
5
6
  when "checkbox"
6
7
  props.label = options.label
@@ -1,6 +1,6 @@
1
1
  class @Form
2
2
  copy: ->
3
- form = new Form(@layout)
3
+ form = new Form @layout
4
4
  form.fields = (field.copy(form) for field in @fields)
5
5
  form.models = @models
6
6
  form
@@ -28,10 +28,11 @@ class @Form
28
28
  options = $.extend { type: type, name: name, form: @ }, options
29
29
  @fields.push Field.build(options)
30
30
  @models.push options.model if options.model
31
- setComponent: (component) ->
31
+ setComponent: (component, store) ->
32
+ store ?= component.store
32
33
  @component = component
33
- @record = component.store.findOrCreate "Record", {}
34
- @changes = component.store.findOrCreate "Changes", {}
34
+ @record = store.findOrCreate "Record", {}
35
+ @changes = store.findOrCreate "Changes", {}
35
36
  @stores = { record: @record, changes: @changes }
36
37
  component.followModels.push model for model in @models
37
38
  component.followStores.push BuildObject(key, value) for key, value of @stores
@@ -57,10 +58,10 @@ class @Form
57
58
  FieldComponent = Form.Field[field.props.type.capitalize] || Form.Field.Default
58
59
  if @layout == "horizontal"
59
60
  <div key={field.props.name} className="form-group">
60
- <label className="col-sm-2 control-label" htmlFor={field.props.name}>
61
+ <label className="col-sm-3 control-label" htmlFor={field.props.name}>
61
62
  {field.props.name.titleize}
62
63
  </label>
63
- <div className="col-sm-10">
64
+ <div className="col-sm-9">
64
65
  <FieldComponent {...field.props} />
65
66
  </div>
66
67
  </div>
@@ -1,24 +1,20 @@
1
1
  class @Namespace
2
2
  @base: window,
3
3
  @namespace: (namespace, value) ->
4
- unless namespace?.length then throw "Namespace: Requires Keys"
5
- unless value? then throw "Namespace: Requires Value"
6
- keys = namespace.split(".")
7
4
  value.namespace = namespace
5
+ @base[namespace] = value
6
+ @public: (namespace) ->
7
+ keys = namespace.split(".")
8
8
  scope = @base
9
9
  for key in keys when key isnt keys.last
10
10
  scope[key] ?= {}
11
11
  scope = scope[key]
12
- scope[keys.last] = value
13
- value
12
+ scope[keys.last] = @find namespace
14
13
  @create: @namespace
15
14
  @find: (namespace) ->
16
- unless namespace?.length then throw "Namespace: Requires Keys"
17
- scope = @base
18
- scope = (scope ? {})[key] for key in namespace.split(".")
19
- scope
15
+ @base[namespace]
20
16
  @findOrCreate: (namespace, options) ->
21
- @find(namespace, options) || @create(namespace, options)
17
+ @find(namespace) ? @create(namespace, options)
22
18
  findOrCreate: (namespace, options) ->
23
19
  namespace = "#{@namespace}.#{namespace}"
24
- @constructor.find(namespace, options) || @constructor.create(namespace, options)
20
+ @constructor.find(namespace) ? @constructor.create(namespace, options)
@@ -24,7 +24,7 @@ class @Store extends Observer
24
24
  @set(item for item in data when item?)
25
25
  get: (field) ->
26
26
  throw "Store: Invalid Data Type" unless @isDefined()
27
- return @data if @isString() && !field
27
+ return @data if @isBoolean() || @isString()
28
28
  data = $.extend(@data.constructor(), @data)
29
29
  if field then data[field] else data
30
30
  empty: ->
@@ -34,4 +34,5 @@ class @Store extends Observer
34
34
  isDefined: -> @data?
35
35
  isObject: -> @data instanceof Object
36
36
  isArray: -> @data instanceof Array
37
+ isBoolean: -> $.type(@data) == "boolean"
37
38
  isString: -> $.type(@data) == "string"
@@ -16,6 +16,7 @@ env.on "change", ->
16
16
 
17
17
  $ -> Store.find("Env").set(window.env)
18
18
 
19
+ @redirect = (path) -> location.assign path || "/"
19
20
  @message = (message) -> Store.find("Messages").push message
20
21
  @setting = (name) ->
21
22
  setting = Store.find("Settings").get().find (setting) -> setting.name == name
@@ -1,3 +1,3 @@
1
1
  Component.create "Form.Field.Default",
2
2
  render: ->
3
- <input placeholder={@props.name.titleize} className="form-control" type={@props.type} name={@props.name} id={@props.name} value={@props.value(@props.name)} onChange={@props.onChange.bind(null, @props.name)} />
3
+ <input placeholder={@props.placeholder} className="form-control" type={@props.type} name={@props.name} id={@props.name} value={@props.value(@props.name)} onChange={@props.onChange.bind(null, @props.name)} />
@@ -1,3 +1,3 @@
1
1
  Component.create "Form.Field.File",
2
2
  render: ->
3
- <input placeholder={@props.name.titleize} className="form-control" type="file" name={@props.name} id={@props.name} onChange={@props.onChange.bind(null, @props.name)} />
3
+ <input placeholder={@props.placeholder} className="form-control" type="file" name={@props.name} id={@props.name} onChange={@props.onChange.bind(null, @props.name)} />
@@ -1,3 +1,3 @@
1
1
  Component.create "Form.Field.Textarea",
2
2
  render: ->
3
- <textarea placeholder={@props.name.titleize} className="form-control" type="text" name={@props.name} id={@props.name} value={@props.value(@props.name)} onChange={@props.onChange.bind(null, @props.name)} />
3
+ <textarea placeholder={@props.placeholder} className="form-control" type="text" name={@props.name} id={@props.name} value={@props.value(@props.name)} onChange={@props.onChange.bind(null, @props.name)} />
@@ -11,7 +11,7 @@ Component.create "Layout.Messages",
11
11
  <div>
12
12
  {for message, i in @state.messages
13
13
  <div key={i} className="alert alert-#{message.type} text-center">
14
- {message.text}
14
+ <span dangerouslySetInnerHTML={__html: message.text} />
15
15
  <a className="btn btn-danger btn-xs pull-right" href="#" onClick={@remove.bind(null, i)}><i className="fa fa-close" /></a>
16
16
  </div>
17
17
  }
@@ -7,7 +7,8 @@ Component.create "Layout.PublicNavbar",
7
7
  logout: (e) ->
8
8
  e.preventDefault()
9
9
  Model.find("Public.Session").destroy().then (response) ->
10
- window.location.replace "/" if response.type == "success"
10
+ return redirect response.redirect if response.type == "success"
11
+ message type: response.type, text: response.message
11
12
  link: (page) ->
12
13
  <li key={page.name}>
13
14
  <a href="/#{page.path}">{page.name}</a>
@@ -27,7 +28,7 @@ Component.create "Layout.PublicNavbar",
27
28
  <div id="navbar" className="navbar-collapse collapse">
28
29
  <ul className="nav navbar-nav">
29
30
  {if @state.user.id
30
- @link(name: "Profile", path: "user/edit")
31
+ @link(name: "Profile", path: "profile")
31
32
  else if setting "allow_signup"
32
33
  @link(name: "Login", path: "session")
33
34
  }
@@ -0,0 +1,26 @@
1
+ Component.create "Public.Profile",
2
+ followStores: ["user"]
3
+ componentWillInitialize: ->
4
+ @model = Model.find "Public.User"
5
+ @model.setAction "show", Request.none
6
+ @follow @model.on "show", @modelShow
7
+ @follow @model.on "edit", @modelEdit
8
+ modelShow: ->
9
+ @setState(edit: false)
10
+ modelEdit: ->
11
+ @setState(edit: true)
12
+ edit: (e) ->
13
+ e.preventDefault()
14
+ Model.findOrCreate("Public.User").edit()
15
+ render: ->
16
+ <div className="container-fluid">
17
+ <div className="row text-center">
18
+ <div className="col-md-4 col-md-offset-4">
19
+ {if @state.edit
20
+ <Public.Users.Edit />
21
+ else
22
+ <Public.Users.Show />
23
+ }
24
+ </div>
25
+ </div>
26
+ </div>
@@ -1,6 +1,4 @@
1
1
  Component.create "Public.Sessions.Show",
2
- getInitialState: ->
3
- { forgotPassword: false }
4
2
  componentWillInitialize: ->
5
3
  @follow Model.find("Public.Session").on "new", @newSession
6
4
  @follow Model.find("Public.Password").on "new", @newPassword
@@ -26,17 +26,30 @@ Component.create "Public.Users.Edit",
26
26
  else
27
27
  @model.update @form.changes.get()
28
28
  false
29
+ show: (e) ->
30
+ e.preventDefault()
31
+ Model.findOrCreate("Public.User").show()
32
+ destroy: (e) ->
33
+ e.preventDefault()
34
+ Model.find("Public.User").destroy().then (response) ->
35
+ return redirect response.redirect if response.type == "success"
36
+ message type: response.type, text: response.message
37
+ false
29
38
  render: ->
30
- <div className="container-fluid">
31
- <div className="row text-center">
32
- <div className="col-md-4 col-md-offset-4">
33
- <h3>Edit Profile</h3>
34
- <form onSubmit={@submit}>
35
- {@form.render()}
36
- <div className="form-group">
37
- <input type="submit" name="commit" value="Save" className="btn btn-primary" />
38
- </div>
39
- </form>
39
+ <div>
40
+ <h3>Edit Profile</h3>
41
+ <form onSubmit={@submit}>
42
+ {@form.render()}
43
+ <div className="form-group">
44
+ <div className="btn-group">
45
+ <input type="submit" name="commit" value="Save" className="btn btn-primary" />
46
+ <a href="#" onClick={@show} className="btn btn-default">Back</a>
47
+ </div>
48
+ </div>
49
+ <div className="form-group">
50
+ <small>
51
+ <a href="#" onClick={@destroy} data-confirm="Are you sure you want to permanently delete your account?">Delete</a>
52
+ </small>
40
53
  </div>
41
- </div>
54
+ </form>
42
55
  </div>
@@ -14,7 +14,7 @@ Component.create "Public.Users.New",
14
14
  @form = form.setComponent @
15
15
  @follow @model.on "create", @modelCreate
16
16
  modelCreate: (response) ->
17
- return window.location.replace "/" if response.type == "success"
17
+ return redirect response.redirect if response.type == "success"
18
18
  message type: response.type, text: response.message
19
19
  submit: (e) ->
20
20
  e.preventDefault()
@@ -0,0 +1,23 @@
1
+ Component.create "Public.Users.Show",
2
+ followStores: ["user"]
3
+ edit: (e) ->
4
+ e.preventDefault()
5
+ Model.findOrCreate("Public.User").edit()
6
+ render: ->
7
+ <div>
8
+ <h3>Profile</h3>
9
+ <div className="row">
10
+ <div className="col-sm-6 text-right"><b>First Name:</b></div>
11
+ <div className="col-sm-6 text-left">{@state.user.first_name}</div>
12
+ </div>
13
+ <div className="row">
14
+ <div className="col-sm-6 text-right"><b>Last Name:</b></div>
15
+ <div className="col-sm-6 text-left">{@state.user.last_name}</div>
16
+ </div>
17
+ <div className="row">
18
+ <div className="col-sm-6 text-right"><b>Member Since:</b></div>
19
+ <div className="col-sm-6 text-left">{@state.user.created_at.date()}</div>
20
+ </div>
21
+ <br />
22
+ <a href="#" onClick={@edit} className="btn btn-primary">Edit</a>
23
+ </div>
@@ -19,7 +19,7 @@
19
19
  state[key] = store.get()
20
20
  context.setState(state)
21
21
  context.events.push store.on("change", callback)
22
- model.all() for key, model in @models when !model.requested("all")
22
+ model.all() for key, model of @models when !model.requested("all")
23
23
  componentWillUnmount: ->
24
24
  event.off() for event in @events
25
25
  follow: (event) ->
@@ -33,6 +33,7 @@
33
33
  setupModels: ->
34
34
  @models = @convertToHash(@followModels?() || @followModels || [])
35
35
  for key, value of @models when not (value instanceof Store)
36
+ delete @models[key]
36
37
  store = @stores[key.camelize] = @store.findOrCreate value, []
37
38
  model = @models[key.camelize] = Model.findOrCreate(value)
38
39
  context = @
@@ -1,12 +1,11 @@
1
1
  class Tomify::Api::Public::UsersController < Tomify.controllers.public_api
2
2
  before_action :require_user!, only: [:show, :update]
3
- before_action :set_record, only: [:show, :update]
3
+ before_action :set_record, only: [:show, :update, :destroy]
4
4
  before_action :not_found, only: :create, unless: "setting(:allow_signup)"
5
5
 
6
6
  def create
7
7
  session[:current_user_id] = Tomify.models.user.create!(record_params).id
8
- flash[:success] = "Welcome #{current_user.name}!"
9
- render json: { type: :success, message: "Welcome #{current_user.name}!" }
8
+ render json: { type: :success }, success: "Welcome #{current_user.name}!"
10
9
  rescue ActiveRecord::RecordInvalid => e
11
10
  render json: { type: :warning, message: e.record.errors.full_messages.join(", ") }
12
11
  end
@@ -18,6 +17,13 @@ class Tomify::Api::Public::UsersController < Tomify.controllers.public_api
18
17
  render json: { type: :warning, message: e.record.errors.full_messages.join(", ") }
19
18
  end
20
19
 
20
+ def destroy
21
+ flash[:danger] = "Goodbye #{current_user.name}"
22
+ find_record
23
+ destroy_record
24
+ render json: { type: :success }
25
+ end
26
+
21
27
  private
22
28
  def set_record
23
29
  @record = current_user
@@ -0,0 +1,7 @@
1
+ class Tomify::Public::ProfilesController < Tomify.controllers.public
2
+ before_action :require_user!
3
+
4
+ def show
5
+ render component: "Public.Profile"
6
+ end
7
+ end
data/config/routes.rb CHANGED
@@ -3,7 +3,7 @@ Rails.application.routes.draw do
3
3
  root "public/pages#root"
4
4
 
5
5
  scope module: :public do
6
- resource :user, only: :edit
6
+ resource :profile, only: :show
7
7
  resource :session, only: :show
8
8
  end
9
9
 
@@ -27,7 +27,7 @@ Rails.application.routes.draw do
27
27
  end
28
28
 
29
29
  namespace :public do
30
- resource :user, only: [:create, :show, :update]
30
+ resource :user, only: [:create, :show, :update, :destroy]
31
31
  resource :session, only: [:create, :destroy]
32
32
  resource :password, only: :create
33
33
  end
@@ -1,3 +1,3 @@
1
1
  module Tomify
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tomify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Prats
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-03 00:00:00.000000000 Z
11
+ date: 2017-04-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -288,10 +288,12 @@ files:
288
288
  - app/assets/javascripts/tomify/dynamic/react/components/new.coffee
289
289
  - app/assets/javascripts/tomify/dynamic/react/components/pagination.coffee
290
290
  - app/assets/javascripts/tomify/dynamic/react/components/public/passwords/new.coffee
291
+ - app/assets/javascripts/tomify/dynamic/react/components/public/profile.coffee
291
292
  - app/assets/javascripts/tomify/dynamic/react/components/public/sessions/new.coffee
292
293
  - app/assets/javascripts/tomify/dynamic/react/components/public/sessions/show.coffee
293
294
  - app/assets/javascripts/tomify/dynamic/react/components/public/users/edit.coffee
294
295
  - app/assets/javascripts/tomify/dynamic/react/components/public/users/new.coffee
296
+ - app/assets/javascripts/tomify/dynamic/react/components/public/users/show.coffee
295
297
  - app/assets/javascripts/tomify/dynamic/react/mixins/follow.coffee
296
298
  - app/assets/javascripts/tomify/dynamic/react/mixins/will-initialize.coffee
297
299
  - app/assets/javascripts/tomify/dynamic/react/mount.coffee
@@ -331,8 +333,8 @@ files:
331
333
  - app/controllers/tomify/concerns/default/react_helper.rb
332
334
  - app/controllers/tomify/public/controller.rb
333
335
  - app/controllers/tomify/public/pages_controller.rb
336
+ - app/controllers/tomify/public/profiles_controller.rb
334
337
  - app/controllers/tomify/public/sessions_controller.rb
335
- - app/controllers/tomify/public/users_controller.rb
336
338
  - app/controllers/tomify_controller.rb
337
339
  - app/helpers/tomify/carrierwave_helper.rb
338
340
  - app/helpers/tomify/email_helper.rb
@@ -1,7 +0,0 @@
1
- class Tomify::Public::UsersController < Tomify.controllers.public
2
- before_action :require_user!
3
-
4
- def edit
5
- render component: "Public.Users.Edit"
6
- end
7
- end