breezy 0.5.5 → 0.5.6

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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/lib/breezy/helpers.rb +1 -1
  3. data/lib/breezy/xhr_headers.rb +9 -0
  4. data/lib/generators/rails/breezy_generator.rb +4 -18
  5. data/lib/generators/rails/scaffold_controller_generator.rb +0 -1
  6. data/lib/generators/rails/templates/edit.js.props +2 -4
  7. data/lib/generators/rails/templates/index.js.props +3 -8
  8. data/lib/generators/rails/templates/new.js.props +1 -3
  9. data/lib/generators/rails/templates/show.js.props +2 -4
  10. data/lib/generators/rails/templates/web/edit.jsx +11 -13
  11. data/lib/generators/rails/templates/web/form.jsx +28 -34
  12. data/lib/generators/rails/templates/web/index.jsx +4 -4
  13. data/lib/generators/rails/templates/web/new.jsx +10 -12
  14. data/lib/generators/rails/templates/web/show.jsx +2 -2
  15. data/lib/install/templates/web/application.js +0 -2
  16. data/lib/install/web.rb +1 -1
  17. metadata +4 -20
  18. data/lib/generators/breezy/view/templates/view.js.breezy +0 -17
  19. data/lib/generators/breezy/view/templates/view.jsx.mobile +0 -21
  20. data/lib/generators/breezy/view/templates/view.jsx.web +0 -24
  21. data/lib/generators/breezy/view/view_generator.rb +0 -68
  22. data/lib/generators/rails/templates/mobile/edit.jsx +0 -76
  23. data/lib/generators/rails/templates/mobile/elements.js +0 -88
  24. data/lib/generators/rails/templates/mobile/form.jsx +0 -34
  25. data/lib/generators/rails/templates/mobile/index.jsx +0 -103
  26. data/lib/generators/rails/templates/mobile/new.jsx +0 -75
  27. data/lib/generators/rails/templates/mobile/show.jsx +0 -32
  28. data/lib/install/mobile.rb +0 -54
  29. data/lib/install/templates/mobile/app.js +0 -77
  30. data/lib/install/templates/mobile/app.json +0 -6
  31. data/lib/install/templates/mobile/babelrc +0 -23
  32. data/lib/install/templates/mobile/package.json +0 -35
  33. data/lib/install/templates/mobile/rn-cli.config.js +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dbe2abbdcd65c8ff1a723ff25f966a3911b62d20
4
- data.tar.gz: 99fcaf756ab0ed0b8e99f2eaf2b5ed3ff98862d8
3
+ metadata.gz: 6c761721a71765c3ed4b56408ee45634044b8227
4
+ data.tar.gz: 4c22efd905a87bc5725fde7aa6aa04073ed4d770
5
5
  SHA512:
6
- metadata.gz: 499d93c621ca6e1cbbad91f1fa44ccd0f82b512c2f09e6ff62bfe60995288c96af8c0847c37999c05569635ec5b25b719fe329eed9a469a225c7adbc291f5f9b
7
- data.tar.gz: 5651fca636aacfc7c1f68dc6f3440c0d39069516dd970317f3c58ab63b6081287cd75184029e2eaa64cac7b0373e9027603c8db57793ffd3d5aaed9505ebc0e0
6
+ metadata.gz: a81fa42b4230d6116136d874dd75b347a81b4f84063c20c8aa16c42d153a22db8102a946b7c27a72854b6ac3b3f6b1bbac79e40738609838757ab66b9fb9bd9f
7
+ data.tar.gz: 33cddac08eed8376c3e04ee7c70bcbeeafc108b1bea5674d1ba3bb5734862cf7be8ccc4144f2a83752caeff85ff51806061766180cfa20a22a5cf3f7820a6e26
@@ -22,7 +22,7 @@ module Breezy
22
22
  end
23
23
 
24
24
  def breezy_filter
25
- filter = request.params[:_bz] || (session && session[:breezy_filter])
25
+ filter = request.params[:_bz]
26
26
 
27
27
  if filter
28
28
  filter.gsub(/[^\da-zA-Z\=\.]+/, '')
@@ -19,6 +19,15 @@ module Breezy
19
19
 
20
20
  if request.xhr? && request.headers["X-BREEZY-REQUEST"]
21
21
  self.status = 200
22
+
23
+ if params['_bz'] && !url.include?('_bz')
24
+ parsed_url = URI.parse(url)
25
+ qry_with_bz = URI.decode_www_form(String(parsed_url.query)) << ["_bz", params['_bz']]
26
+ parsed_url.query = URI.encode_www_form(qry_with_bz)
27
+
28
+ url = parsed_url.to_s
29
+ end
30
+
22
31
  response.headers["X-BREEZY-LOCATION"] = url
23
32
  end
24
33
 
@@ -9,7 +9,6 @@ module Rails
9
9
  source_root File.expand_path('../templates', __FILE__)
10
10
 
11
11
  argument :attributes, type: :array, default: [], banner: 'field:type field:type'
12
- class_option :platform, type: :string, default: 'web', enum: ['web', 'mobile']
13
12
 
14
13
  def create_root_folder
15
14
  path = File.join('app/views', controller_file_path)
@@ -26,21 +25,12 @@ module Rails
26
25
  %w(index show new edit).each do |view|
27
26
  @action_name = view
28
27
  filename = filename_with_jsx_extensions(view)
29
- if options[:platform] == 'mobile'
30
- template 'mobile/' + filename, File.join('app/views', controller_file_path, filename)
31
- else
32
- template 'web/' + filename, File.join('app/views', controller_file_path, filename)
33
- end
28
+ template 'web/' + filename, File.join('app/views', controller_file_path, filename)
34
29
  end
35
30
 
36
31
  js_filename = [plural_table_name, 'form.jsx'].map(&:camelcase).join
37
- if options[:platform] == 'mobile'
38
- template 'mobile/form.jsx', File.join('app/components', js_filename)
39
- template 'mobile/elements.js', File.join('app/components', 'elements.js')
40
- else
41
- template 'web/form.jsx', File.join('app/components', js_filename)
42
- template 'web/base.jsx', File.join('app/components', 'BaseScreen.jsx')
43
- end
32
+ template 'web/form.jsx', File.join('app/components', js_filename)
33
+ template 'web/base.jsx', File.join('app/components', 'BaseScreen.jsx')
44
34
 
45
35
  %w(index show new edit).each do |view|
46
36
  append_mapping(view)
@@ -50,11 +40,7 @@ module Rails
50
40
 
51
41
  protected
52
42
  def append_mapping(action)
53
- if options[:platform] == 'mobile'
54
- app_js = 'App.js'
55
- else
56
- app_js = 'app/javascript/packs/application.js'
57
- end
43
+ app_js = 'app/javascript/packs/application.js'
58
44
 
59
45
  base_parts = class_path + [file_name]
60
46
  destination = File.join("views", base_parts)
@@ -5,7 +5,6 @@ module Rails
5
5
  module Generators
6
6
  class ScaffoldControllerGenerator
7
7
  source_paths << File.expand_path('../templates', __FILE__)
8
- class_option :platform, type: :string, desc:'Indicates to generate React web or native components', default: 'web', enum: ['web', 'mobile']
9
8
 
10
9
  hook_for :breezy, type: :boolean, default: true
11
10
  end
@@ -12,7 +12,5 @@ json.attributes_for_form do
12
12
  <%- end -%>
13
13
  end
14
14
 
15
- json.meta do
16
- json.show_path <%=singular_table_name%>_path(@<%=singular_table_name%>)
17
- json.index_path <%= plural_table_name %>_path
18
- end
15
+ json.post_path <%= singular_table_name%>_path(@<%=singular_table_name%>)
16
+ json.posts_path <%= plural_table_name %>_path
@@ -3,11 +3,8 @@ json.<%= plural_table_name %> do
3
3
  <%- attributes_list_with_timestamps.each do |attr| -%>
4
4
  json.<%=attr%> <%= singular_table_name %>.<%=attr%>
5
5
  <%- end -%>
6
- json.meta do
7
- json.edit_path edit_<%=singular_table_name%>_path(<%=singular_table_name%>)
8
- json.show_path <%=singular_table_name%>_path(<%=singular_table_name%>)
9
- json.delete_path <%=singular_table_name%>_path(<%=singular_table_name%>)
10
- end
6
+ json.edit_post_path edit_<%=singular_table_name%>_path(<%=singular_table_name%>)
7
+ json.post_path <%=singular_table_name%>_path(<%=singular_table_name%>)
11
8
  end
12
9
  end
13
10
 
@@ -15,6 +12,4 @@ if notice
15
12
  json.notice notice
16
13
  end
17
14
 
18
- json.meta do
19
- json.new_path new_<%= singular_table_name %>_path
20
- end
15
+ json.new_post_path new_<%= singular_table_name %>_path
@@ -2,6 +2,4 @@ if @<%= singular_table_name %>.errors.any?
2
2
  json.errors @<%= singular_table_name %>.errors.to_h
3
3
  end
4
4
 
5
- json.meta do
6
- json.index_path <%= plural_table_name %>_path
7
- end
5
+ json.<%= plural_table_name %>_path <%= plural_table_name %>_path
@@ -6,7 +6,5 @@ if notice
6
6
  json.notice notice
7
7
  end
8
8
 
9
- json.meta do
10
- json.index_path <%= plural_table_name %>_path
11
- json.edit_path edit_<%= singular_table_name %>_path(@<%= singular_table_name %>)
12
- end
9
+ json.<%= plural_table_name %>_path <%= plural_table_name %>_path
10
+ json.edit_<%= singular_table_name %>_path edit_<%= singular_table_name %>_path(@<%= singular_table_name %>)
@@ -1,26 +1,24 @@
1
1
  import React from 'react'
2
2
  import {mapStateToProps, mapDispatchToProps} from '@jho406/breezy'
3
- import {delInPage} from '@jho406/breezy/dist/action_creators'
4
3
  import {connect} from 'react-redux'
5
4
  import BaseScreen from 'components/BaseScreen'
6
- import {SubmissionError} from 'redux-form'
7
5
  import <%= plural_table_name.camelize %>Form from 'components/<%= plural_table_name.camelize %>Form'
8
6
 
9
7
  class <%= plural_table_name.camelize %>Edit extends BaseScreen {
10
- handleSubmit = (body) => {
8
+ formRef = React.createRef()
9
+
10
+ handleSubmit = (values, {setSubmitting}) => {
11
11
  this.props.delInPage({pageKey: this.props.pageKey, keypath: 'errors'})
12
12
 
13
13
  const options = {
14
14
  method:'PUT',
15
- body: JSON.stringify(body),
15
+ body: JSON.stringify(values),
16
16
  }
17
- const path = '/<%= plural_table_name %>/' + this.props.id
18
17
 
19
- this.visit(path, options).then( rsp => {
18
+ this.visit(this.props.<%= singular_table_name %>, options).then( rsp => {
19
+ setSubmitting(false)
20
20
  if (this.props.errors) {
21
- throw new SubmissionError({
22
- ...this.props.errors
23
- })
21
+ this.formRef.current.setErrors(this.props.errors)
24
22
  }
25
23
  })
26
24
  }
@@ -29,12 +27,12 @@ class <%= plural_table_name.camelize %>Edit extends BaseScreen {
29
27
  return (
30
28
  <div>
31
29
  <<%= plural_table_name.camelize %>Form
32
- error={this.props.error}
33
30
  onSubmit={this.handleSubmit}
34
31
  initialValues={this.props.attributes_for_form}
32
+ ref={this.formRef}
35
33
  />
36
- <a onClick={ e => this.visit(this.props.meta.show_path)}>Show</a>
37
- <a onClick={ e => this.visit(this.props.meta.index_path)}>Back</a>
34
+ <a onClick={ e => this.visit(this.props.post_path)}>Show</a>
35
+ <a onClick={ e => this.visit(this.props.posts_path)}>Back</a>
38
36
  </div>
39
37
  )
40
38
  }
@@ -42,7 +40,7 @@ class <%= plural_table_name.camelize %>Edit extends BaseScreen {
42
40
 
43
41
  export default connect(
44
42
  mapStateToProps,
45
- {...mapDispatchToProps, delInPage}
43
+ mapDispatchToProps
46
44
  )(<%= plural_table_name.camelize %>Edit)
47
45
 
48
46
 
@@ -1,37 +1,31 @@
1
1
  import React from 'react'
2
- import { Field, reduxForm, stopSubmit, touch} from 'redux-form'
2
+ import { Formik, Form, Field } from 'formik';
3
3
 
4
- const RenderField = ({ input, label, type, meta: { touched, error } }) => (
5
- <div>
6
- <label>{label}</label>
7
- <div>
8
- <input {...input} placeholder={label} type={type} />
9
- {touched && error && <span>{error}</span>}
10
- </div>
11
- </div>
12
- )
13
-
14
- const SimpleForm = props => {
15
- const { error, handleSubmit, initialValue } = props
16
-
17
- return (
18
- <form onSubmit={handleSubmit}>
19
- <%- attributes_list.select{|attr| attr != :id }.each do |attr| -%>
20
- <label><%=attr.to_s.humanize%></label>
21
- <Field
22
- name="<%=attr.to_s.camelize(:lower)%>"
23
- component={RenderField}
24
- type="text"
25
- />
26
- <%- end -%>
27
- <button type="submit">
28
- Submit
29
- </button>
30
- </form>
31
- )
32
- }
33
-
34
- export default reduxForm({
35
- form: '<%=plural_table_name%>_form' // a unique identifier for this form
36
- })(SimpleForm)
4
+ export default React.forwardRef(
5
+ ({initialValues = {
6
+ <%- attributes_list.select{|attr| attr != :id }.each do |attr| -%>
7
+ <%=attr.to_s%>:'',
8
+ <%- end -%>
9
+ }, onSubmit}, ref) => {
10
+ return (
11
+ <Formik
12
+ initialValues={initialValues}
13
+ onSubmit={onSubmit}
14
+ ref={ref}
15
+ >
16
+ {({ errors, touched, isSubmitting }) => (
17
+ <Form>
18
+ <%- attributes_list.select{|attr| attr != :id }.each do |attr| -%>
19
+ <Field type="text" name="<%=attr.to_s%>" />
20
+ {errors.<%=attr.to_s%> && touched.<%=attr.to_s%> && errors.<%=attr.to_s%>}
21
+ <%- end -%>
37
22
 
23
+ <button type="submit" disabled={isSubmitting}>
24
+ Submit
25
+ </button>
26
+ </Form>
27
+ )}
28
+ </Formik>
29
+ )
30
+ }
31
+ )
@@ -15,9 +15,9 @@ class <%= plural_table_name.camelize %>Index extends BaseScreen {
15
15
  <%- attributes_list.select{|attr| attr != :id }.each do |attr| -%>
16
16
  <td>{<%=singular_table_name%>.<%=attr%>}</td>
17
17
  <%- end -%>
18
- <td><a onClick={ e => this.visit(<%=singular_table_name%>.meta.show_path)}>Show</a></td>
19
- <td><a onClick={ e => this.visit(<%=singular_table_name%>.meta.edit_path)}>Edit</a></td>
20
- <td><a onClick={ e => this.visit(<%=singular_table_name%>.meta.delete_path, {method: 'DELETE'})}>Delete</a></td>
18
+ <td><a onClick={ e => this.visit(<%=singular_table_name%>.post_path)}>Show</a></td>
19
+ <td><a onClick={ e => this.visit(<%=singular_table_name%>.edit_post_path)}>Edit</a></td>
20
+ <td><a onClick={ e => this.visit(<%=singular_table_name%>.post_path, {method: 'DELETE'})}>Delete</a></td>
21
21
  </tr>
22
22
  )
23
23
  })
@@ -43,7 +43,7 @@ class <%= plural_table_name.camelize %>Index extends BaseScreen {
43
43
  </tbody>
44
44
  </table>
45
45
  <br />
46
- <a onClick={ e => this.visit(this.props.meta.new_path)}>New <%= singular_table_name.capitalize %></a>
46
+ <a onClick={ e => this.visit(this.props.new_post_path)}>New <%= singular_table_name.capitalize %></a>
47
47
  </div>
48
48
  )
49
49
  }
@@ -1,38 +1,36 @@
1
1
  import React from 'react'
2
2
  import {mapStateToProps, mapDispatchToProps} from '@jho406/breezy'
3
- import {delInPage} from '@jho406/breezy/dist/action_creators'
4
3
  import {connect} from 'react-redux'
5
4
  import BaseScreen from 'components/BaseScreen'
6
- import {SubmissionError} from 'redux-form'
7
5
  import <%= plural_table_name.camelize %>Form from 'components/<%= plural_table_name.camelize %>Form'
8
6
 
9
7
  class <%= plural_table_name.camelize %>New extends BaseScreen {
10
- handleSubmit = (body) => {
8
+ formRef = React.createRef()
9
+
10
+ handleSubmit = (values, {setSubmitting}) => {
11
11
  this.props.delInPage({pageKey: this.props.pageKey, keypath: 'errors'})
12
12
 
13
13
  const options = {
14
14
  method:'POST',
15
- body: JSON.stringify(body),
15
+ body: JSON.stringify(values),
16
16
  }
17
17
 
18
- this.visit('/<%= plural_table_name %>', options).then( rsp => {
18
+ this.visit(this.props.<%= plural_table_name %>_path, options).then( rsp => {
19
+ setSubmitting(false)
19
20
  if (this.props.errors) {
20
- throw new SubmissionError({
21
- ...this.props.errors
22
- })
21
+ this.formRef.current.setErrors(this.props.errors)
23
22
  }
24
23
  })
25
-
26
24
  }
27
25
 
28
26
  render () {
29
27
  return (
30
28
  <div>
31
29
  <<%= plural_table_name.camelize %>Form
32
- error={this.props.error}
33
30
  onSubmit={this.handleSubmit}
31
+ ref={this.formRef}
34
32
  />
35
- <a onClick={ e => this.visit(this.props.meta.index_path)}>Back</a>
33
+ <a onClick={ e => this.visit(this.props.<%= plural_table_name %>_path)}>Back</a>
36
34
  </div>
37
35
  )
38
36
  }
@@ -40,6 +38,6 @@ class <%= plural_table_name.camelize %>New extends BaseScreen {
40
38
 
41
39
  export default connect(
42
40
  mapStateToProps,
43
- {...mapDispatchToProps, delInPage}
41
+ mapDispatchToProps
44
42
  )(<%= plural_table_name.camelize %>New)
45
43
 
@@ -14,8 +14,8 @@ class <%= plural_table_name.camelize %>Show extends BaseScreen {
14
14
  {this.props.<%=attr%>}
15
15
  </p>
16
16
  <%- end -%>
17
- <a onClick={ e => this.visit(this.props.meta.edit_path)}>Edit</a>
18
- <a onClick={ e => this.visit(this.props.meta.index_path)}>Back</a>
17
+ <a onClick={ e => this.visit(this.props.edit_<%= singular_table_name %>_path)}>Edit</a>
18
+ <a onClick={ e => this.visit(this.props.<%= plural_table_name %>_path )}>Back</a>
19
19
  </div>
20
20
  )
21
21
  }
@@ -4,7 +4,6 @@ import thunk from 'redux-thunk'
4
4
  import { Provider } from 'react-redux'
5
5
  import { render } from 'react-dom'
6
6
  import createHistory from 'history/createBrowserHistory'
7
- import { reducer as formReducer } from 'redux-form'
8
7
  import Breezy from '@jho406/breezy'
9
8
 
10
9
  // This mapping can be auto populate through
@@ -29,7 +28,6 @@ const {reducer, initialState, Nav, connect} = Breezy.start({
29
28
  const store = createStore(
30
29
  combineReducers({
31
30
  ...reducer,
32
- form: formReducer
33
31
  }),
34
32
  initialState,
35
33
  applyMiddleware(thunk)
@@ -85,7 +85,7 @@ say "Adding required member methods to ApplicationRecord"
85
85
  add_member_methods
86
86
 
87
87
  say "Installing React, Redux, and Breezy"
88
- run "yarn add react-redux redux react react-dom babel-preset-react prop-types redux-form @jho406/breezy --save"
88
+ run "yarn add react-redux redux react react-dom babel-preset-react prop-types formik @jho406/breezy --save"
89
89
  run "yarn add babel-plugin-module-resolver --save-dev"
90
90
 
91
91
  say "Updating webpack paths to include .jsx file extension"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: breezy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.5
4
+ version: 0.5.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johny Ho
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-06 00:00:00.000000000 Z
11
+ date: 2018-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 0.5.5
33
+ version: 0.5.6
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 0.5.5
40
+ version: 0.5.6
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: webpacker
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -164,21 +164,11 @@ files:
164
164
  - lib/breezy/x_domain_blocker.rb
165
165
  - lib/breezy/xhr_headers.rb
166
166
  - lib/breezy/xhr_url_for.rb
167
- - lib/generators/breezy/view/templates/view.js.breezy
168
- - lib/generators/breezy/view/templates/view.jsx.mobile
169
- - lib/generators/breezy/view/templates/view.jsx.web
170
- - lib/generators/breezy/view/view_generator.rb
171
167
  - lib/generators/rails/breezy_generator.rb
172
168
  - lib/generators/rails/scaffold_controller_generator.rb
173
169
  - lib/generators/rails/templates/controller.rb.tt
174
170
  - lib/generators/rails/templates/edit.js.props
175
171
  - lib/generators/rails/templates/index.js.props
176
- - lib/generators/rails/templates/mobile/edit.jsx
177
- - lib/generators/rails/templates/mobile/elements.js
178
- - lib/generators/rails/templates/mobile/form.jsx
179
- - lib/generators/rails/templates/mobile/index.jsx
180
- - lib/generators/rails/templates/mobile/new.jsx
181
- - lib/generators/rails/templates/mobile/show.jsx
182
172
  - lib/generators/rails/templates/new.js.props
183
173
  - lib/generators/rails/templates/show.js.props
184
174
  - lib/generators/rails/templates/web/base.jsx
@@ -187,12 +177,6 @@ files:
187
177
  - lib/generators/rails/templates/web/index.jsx
188
178
  - lib/generators/rails/templates/web/new.jsx
189
179
  - lib/generators/rails/templates/web/show.jsx
190
- - lib/install/mobile.rb
191
- - lib/install/templates/mobile/app.js
192
- - lib/install/templates/mobile/app.json
193
- - lib/install/templates/mobile/babelrc
194
- - lib/install/templates/mobile/package.json
195
- - lib/install/templates/mobile/rn-cli.config.js
196
180
  - lib/install/templates/web/application.js
197
181
  - lib/install/templates/web/babelrc
198
182
  - lib/install/templates/web/initializer.rb
@@ -1,17 +0,0 @@
1
- # Example:
2
- #
3
- # json.notice notice
4
- #
5
- # json.posts do
6
- # json.array! @posts do |post|
7
- # json.id post.id
8
- # json.title post.title
9
- # json.body post.body
10
- #
11
- # json.show_url post_path(post)
12
- # json.edit_url edit_post_path(post)
13
- # json.delete_url post_path(post)
14
- # end
15
- # end
16
- #
17
- json.greetings 'Change me'
@@ -1,21 +0,0 @@
1
- import React from 'react'
2
- import {mapStateToProps, mapDispatchToProps} from '@jho406/breezy'
3
- import { connect } from 'react-redux'
4
- import {View, Text} from 'react-native'
5
-
6
- class <%= @js_filename %> extends React.Component {
7
- render () {
8
- return (
9
- <View>
10
- <Text>
11
- {this.props.greetings}
12
- </Text>
13
- </View>
14
- )
15
- }
16
- }
17
-
18
- export default connect(
19
- mapStateToProps,
20
- mapDispatchToProps
21
- )(<%= @js_filename %>)
@@ -1,24 +0,0 @@
1
- import React from 'react'
2
- import {mapStateToProps, mapDispatchToProps, withBrowserBehavior} from '@jho406/breezy'
3
- import { connect } from 'react-redux'
4
-
5
- class <%= @js_filename %> extends React.Component {
6
- constructor (props) {
7
- super(props)
8
- const {visit, remote} = withBrowserBehavior(props.visit, props.remote)
9
- this.visit = visit.bind(this)
10
- this.remote = remote.bind(this)
11
- }
12
-
13
- render () {
14
- return (
15
- <div> {this.props.greetings}
16
- </div>
17
- )
18
- }
19
- }
20
-
21
- export default connect(
22
- mapStateToProps,
23
- mapDispatchToProps
24
- )(<%= @js_filename %>)
@@ -1,68 +0,0 @@
1
- module Breezy
2
- module Generators
3
- class ViewGenerator < ::Rails::Generators::NamedBase
4
- desc <<-DESC
5
- Description:
6
- Creates a content view and jsx view.
7
- DESC
8
- class_option :target,
9
- aliases: '-t',
10
- type: :string,
11
- default: 'web',
12
- desc: 'Specify target platform',
13
- enum: ['web', 'mobile']
14
-
15
- argument :actions, type: :array, default: [], banner: "action action"
16
-
17
- def self.source_root
18
- @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
19
- end
20
-
21
- def copy_view_files
22
- base_parts = class_path + [file_name]
23
- destination = File.join("app/views", base_parts)
24
-
25
-
26
- actions.each do |action|
27
- @action = action
28
- @js_filename = (base_parts + [action]).map(&:camelcase).join
29
- @content_path = File.join(destination, "#{@action}.js.props")
30
-
31
- if options[:target] == 'mobile'
32
- @view_ext = 'jsx.mobile'
33
- else
34
- @view_ext = 'jsx.web' #todo fix me
35
- end
36
-
37
- @view_path = File.join(destination, "#{@action}.jsx")
38
-
39
- template "view.#{@view_ext}", @view_path
40
- template 'view.js.breezy', @content_path
41
- end
42
- end
43
-
44
- def append_mapping
45
- if options[:platform] == 'mobile'
46
- app_js = 'App.js'
47
- else
48
- app_js = 'app/javascript/packs/application.js'
49
- end
50
-
51
- base_parts = class_path + [file_name]
52
- destination = File.join("views", base_parts)
53
-
54
- actions.each do |action|
55
- @js_filename = (base_parts + [action]).map(&:camelcase).join
56
-
57
- inject_into_file app_js, after: "from '@jho406/breezy'" do
58
- "\nimport #{@js_filename} from '#{destination}/#{action}'"
59
- end
60
-
61
- inject_into_file app_js, after: 'const mapping = {' do
62
- "\n #{@js_filename},"
63
- end
64
- end
65
- end
66
- end
67
- end
68
- end
@@ -1,76 +0,0 @@
1
- import React from 'react'
2
- import {submit} from 'redux-form'
3
- import {Header} from 'react-native-elements'
4
- import {SubmissionError} from 'redux-form'
5
- import {View} from 'react-native'
6
- import {connect} from 'react-redux'
7
- import {delInPage} from '@jho406/breezy/dist/action_creators'
8
- import {mapStateToProps, mapDispatchToProps} from '@jho406/breezy'
9
- import <%= plural_table_name.camelize %>Form from 'components/<%= plural_table_name.camelize %>Form'
10
- import {Container, BarSaveAndGoBack, BarCancel} from 'components/elements'
11
-
12
- class <%= plural_table_name.camelize %>Edit extends React.Component {
13
- constructor (props) {
14
- super(props)
15
- this.submit = this.submit.bind(this)
16
- this.remoteSubmit = this.remoteSubmit.bind(this)
17
- }
18
-
19
- submit (body) {
20
- const options = {
21
- method: 'PATCH',
22
- body: JSON.stringify(body),
23
- contentType: 'application/json'
24
- }
25
-
26
- this.props.delInPage({pageKey: this.props.pageKey, keypath: 'errors'})
27
- return this.props.visit('/<%= plural_table_name %>/' + this.props.id, options).then((rsp) => {
28
- if (this.props.errors) {
29
- throw new SubmissionError({
30
- ...this.props.errors
31
- })
32
- }
33
- if (rsp.canNavigate) {
34
- return this.props.navigation.goBack()
35
- } else {
36
- // There can only ve one visit at a time, if `canNavigate`
37
- // is false, then this request is being ignored for a more
38
- // recent visit. Do Nothing.
39
- return
40
- }
41
-
42
- }).catch((err) => {
43
- if (err instanceof SubmissionError) {
44
- throw err
45
- } else {
46
- //handle other errors here
47
- }
48
- })
49
- }
50
-
51
- remoteSubmit () {
52
- this.props.remoteSubmit('<%=plural_table_name%>_form')
53
- }
54
-
55
- render () {
56
- const headerOptions = {
57
- leftComponent: (<BarSaveAndGoBack onPress={this.remoteSubmit} />),
58
- rightComponent: (<BarCancel onPress={e => this.props.navigation.goBack()} />)
59
- }
60
- return (
61
- <View>
62
- <Header {...headerOptions}/>
63
- <Container>
64
- <<%= plural_table_name.camelize %>Form error={this.props.error} onSubmit={this.submit} initialValues={this.props.attributes_for_form}/>
65
- </Container>
66
- </View>
67
- )
68
- }
69
- }
70
-
71
- export default connect(
72
- mapStateToProps,
73
- {...mapDispatchToProps, remoteSubmit: submit, delInPage}
74
- )(<%= plural_table_name.camelize %>Edit)
75
-
76
-
@@ -1,88 +0,0 @@
1
- import React from 'react'
2
- import {View, Text, ScrollView, TouchableOpacity, Alert} from 'react-native'
3
- import {Header, Card, ListItem, Icon, Button} from 'react-native-elements'
4
-
5
- export function Container(props) {
6
- return <ScrollView contentContainerStyle={{paddingBottom: 100, flexDirection: 'column'}}>
7
- {props.children}
8
- </ScrollView>
9
- }
10
-
11
- export function BarSaveAndGoBack({onPress}) {
12
- return (
13
- <TouchableOpacity onPress={onPress} style={{flex: 1, flexDirection: 'row', alignItems: 'flex-end'}}>
14
- <Icon
15
- name='chevron-left'
16
- color='#fff'
17
- size={18}
18
- underlayColor='rgba(0, 0, 0, 0)'
19
- />
20
- <Text style={{color: '#fff'}}>SAVE AND GO BACK</Text>
21
- </TouchableOpacity>
22
- )
23
- }
24
-
25
- export function BarGoBack({onPress}) {
26
- return (
27
- <TouchableOpacity onPress={onPress} style={{flex: 1, flexDirection: 'row', alignItems: 'flex-end'}}>
28
- <Icon
29
- name='chevron-left'
30
- color='#fff'
31
- size={18}
32
- underlayColor='rgba(0, 0, 0, 0)'
33
- />
34
- <Text style={{color: '#fff'}}>BACK</Text>
35
- </TouchableOpacity>
36
- )
37
- }
38
-
39
- export function BarCancel({onPress}) {
40
- return (
41
- <TouchableOpacity onPress={onPress} style={{flex: 1, flexDirection: 'row', alignItems: 'flex-end'}}>
42
- <Text style={{color: '#fff'}}>CANCEL</Text>
43
- </TouchableOpacity>
44
- )
45
- }
46
-
47
- export function BarNew ({onPress}) {
48
- return (
49
- <TouchableOpacity
50
- onPress={onPress}
51
- style={{flex: 1, flexDirection: 'row', alignItems: 'flex-end'}}>
52
- <Icon
53
- name='note-add'
54
- color='#fff'
55
- size={18}
56
- underlayColor='rgba(0, 0, 0, 0)'
57
- />
58
- <Text style={{color: '#fff'}}>NEW</Text>
59
- </TouchableOpacity>
60
- )
61
- }
62
-
63
- export function IconDelete({onPress}) {
64
- return <Icon
65
- raised
66
- name='close'
67
- color='#f50'
68
- size={13}
69
- onPress={onPress}/>
70
- }
71
- export function IconEdit({onPress}) {
72
- return <Icon
73
- raised
74
- name='mode-edit'
75
- color='#f50'
76
- size={13}
77
- onPress={onPress}/>
78
-
79
- }
80
- export function IconShow({onPress}) {
81
- return <Icon
82
- raised
83
- name='more-horiz'
84
- color='#f50'
85
- size={13}
86
- onPress={onPress}/>
87
- }
88
-
@@ -1,34 +0,0 @@
1
- import React from 'react'
2
- import { Field, reduxForm, stopSubmit, touch} from 'redux-form'
3
- import {View, Text} from 'react-native'
4
- import { FormLabel, FormInput, FormValidationMessage } from 'react-native-elements'
5
-
6
- const RenderField = ({ input, label, type, meta: { touched, error } }) => {
7
- return (
8
- <View>
9
- <FormLabel><Text>{label}</Text></FormLabel>
10
- <FormInput onChangeText={input.onChange} value={input.value} placeholder={`Please enter ${label}`}/>
11
- {touched && error && <FormValidationMessage><Text>{error}</Text></FormValidationMessage>}
12
- </View>
13
- )
14
- }
15
- const SimpleForm = props => {
16
- const { error, handleSubmit, initialValue } = props
17
-
18
- return (
19
- <View><% attributes_list.select{|attr| attr != :id }.each do |attr| %>
20
- <Field
21
- name="<%=attr.to_s.camelize(:lower)%>"
22
- label="<%=attr.to_s.humanize%>"
23
- component={RenderField}
24
- type="text"
25
- />
26
- <%end%></View>
27
- )
28
- }
29
-
30
- export default reduxForm({
31
- form: '<%=plural_table_name%>_form' // a unique identifier for this form
32
- })(SimpleForm)
33
-
34
-
@@ -1,103 +0,0 @@
1
- import React from 'react'
2
- import {mapDispatchToProps, mapStateToProps} from '@jho406/breezy'
3
- import {connect} from 'react-redux'
4
- import {View, Text, TouchableOpacity, Alert} from 'react-native'
5
- import {Header, Card} from 'react-native-elements'
6
- import DropdownAlert from 'react-native-dropdownalert';
7
- import {Container, IconDelete, IconEdit, IconShow, BarNew} from 'components/elements'
8
-
9
- class <%= plural_table_name.camelize %>Index extends React.Component {
10
- static defaultProps = {
11
- <%= plural_table_name %>: []
12
- }
13
-
14
- constructor (props) {
15
- super(props)
16
- this.handleClick = this.handleClick.bind(this)
17
- this.handleDeleteClick = this.handleDeleteClick.bind(this)
18
- }
19
-
20
- handleDeleteClick(path) {
21
- const method = 'DELETE'
22
-
23
- Alert.alert(
24
- 'Wait!',
25
- 'Are you sure you want to delete this <%=singular_table_name%>?',
26
- [
27
- {
28
- text: 'Delete',
29
- onPress: e => {this.props.visit(path, {method})},
30
- style: 'destructive'
31
- },
32
- { text: 'Cancel', style: 'cancel' },
33
- ],
34
- { cancelable: false }
35
- )
36
- }
37
-
38
- handleClick(path, method='GET') {
39
- const nav = this.props.navigation
40
- this.props.visit(path, {method}).then((rsp)=>{
41
- if (rsp.canNavigate) {
42
- return nav.navigate(rsp.screen, {pageKey: rsp.pageKey})
43
- } else {
44
- // There can only be one visit at a time, if `canNavigate`
45
- // is false, then this request is being ignored for a more
46
- // recent visit. Do Nothing.
47
- return
48
- }
49
- })
50
- }
51
-
52
- showNotice (message) {
53
- if (message) {
54
- setImmediate(() => {
55
- this.dropdown.alertWithType('success', 'Success', message);
56
- })
57
-
58
- return <DropdownAlert ref={ref => this.dropdown = ref} translucent={true}/>
59
- } else {
60
- return null
61
- }
62
- }
63
-
64
- render () {
65
- const headerOptions = {
66
- centerComponent: { text: 'POSTS', style: { color: '#fff' } },
67
- rightComponent: (<BarNew
68
- onPress={e => this.handleClick('/<%=plural_table_name%>/new')}
69
- />)
70
- }
71
-
72
- return (
73
- <View>
74
- <Header {...headerOptions}/>
75
- <Container>
76
- {this.props.<%=plural_table_name%>.map((<%=singular_table_name%>) => {
77
- const {show_path, edit_path, delete_path} = <%=singular_table_name%>.meta
78
- return (
79
- <Card key={<%=singular_table_name%>.id}>
80
- <TouchableOpacity>
81
- <% attributes_list.select{|attr| attr != :id }.each do |attr| %><Text style={{marginBottom: 10}}>{<%=singular_table_name%>.<%=attr%>}</Text>
82
- <% end %>
83
- </TouchableOpacity>
84
- <View style={{flex: 1, justifyContent: 'flex-end', flexDirection: 'row'}}>
85
- <IconDelete onPress={e => this.handleDeleteClick(delete_path)}/>
86
- <IconEdit onPress={e => this.handleClick(edit_path)}/>
87
- <IconShow onPress={e => this.handleClick(show_path)}/>
88
- </View>
89
- </Card>
90
- )
91
- })}
92
- </Container>
93
- {this.showNotice(this.props.notice)}
94
- </View>
95
- )
96
- }
97
- }
98
-
99
- export default connect(
100
- mapStateToProps,
101
- mapDispatchToProps
102
- )(<%= plural_table_name.camelize %>Index)
103
-
@@ -1,75 +0,0 @@
1
- import React from 'react'
2
- import {submit} from 'redux-form'
3
- import {Header} from 'react-native-elements'
4
- import {SubmissionError} from 'redux-form'
5
- import {View} from 'react-native'
6
- import {connect} from 'react-redux'
7
- import {delInPage} from '@jho406/breezy/dist/action_creators'
8
- import {mapStateToProps, mapDispatchToProps} from '@jho406/breezy'
9
- import <%= plural_table_name.camelize %>Form from 'components/<%= plural_table_name.camelize %>Form'
10
- import {Container, BarSaveAndGoBack, BarCancel} from 'components/elements'
11
-
12
- class <%= plural_table_name.camelize %>New extends React.Component {
13
- constructor (props) {
14
- super(props)
15
- this.submit = this.submit.bind(this)
16
- this.remoteSubmit = this.remoteSubmit.bind(this)
17
- }
18
-
19
- submit (body) {
20
- const options = {
21
- method: 'POST',
22
- body: JSON.stringify(body),
23
- contentType: 'application/json'
24
- }
25
-
26
- this.props.delInPage({pageKey: this.props.pageKey, keypath: 'errors'})
27
- return this.props.visit('/<%= plural_table_name %>', options).then((rsp) => {
28
- if (this.props.errors) {
29
- throw new SubmissionError({
30
- ...this.props.errors
31
- })
32
- }
33
- if (rsp.canNavigate) {
34
- return this.props.navigation.goBack()
35
- } else {
36
- // There can only ve one visit at a time, if `canNavigate`
37
- // is false, then this request is being ignored for a more
38
- // recent visit. Do Nothing.
39
- return
40
- }
41
- }).catch((err) => {
42
- if (err instanceof SubmissionError) {
43
- throw err
44
- } else {
45
- //handle other errors here
46
- }
47
- })
48
- }
49
-
50
- remoteSubmit () {
51
- this.props.remoteSubmit('<%=plural_table_name%>_form')
52
- }
53
-
54
- render () {
55
- const headerOptions = {
56
- leftComponent: (<BarSaveAndGoBack onPress={this.remoteSubmit} />),
57
- rightComponent: (<BarCancel onPress={e => this.props.navigation.goBack()} />)
58
- }
59
-
60
- return (
61
- <View>
62
- <Header {...headerOptions}/>
63
- <Container>
64
- <<%= plural_table_name.camelize %>Form error={this.props.error} onSubmit={this.submit}/>
65
- </Container>
66
- </View>
67
- )
68
- }
69
- }
70
-
71
- export default connect(
72
- mapStateToProps,
73
- {...mapDispatchToProps, remoteSubmit: submit, delInPage}
74
- )(<%= plural_table_name.camelize %>New)
75
-
@@ -1,32 +0,0 @@
1
- import React from 'react'
2
- import {mapStateToProps, mapDispatchToProps} from '@jho406/breezy'
3
- import {connect} from 'react-redux'
4
- import {Text, View} from 'react-native'
5
- import {Header, Card} from 'react-native-elements'
6
- import {Container, BarGoBack} from 'components/elements'
7
-
8
- class <%= plural_table_name.camelize %>Show extends React.Component {
9
- render() {
10
- const headerOptions = {
11
- leftComponent: (<BarGoBack onPress={ e => this.props.navigation.goBack()} />)
12
- }
13
-
14
- return (
15
- <View>
16
- <Header {...headerOptions}/>
17
- <Container>
18
- <Card><% attributes_list_with_timestamps.select{|attr| attr != :id }.each do |attr| %>
19
- <Text style={{fontWeight: 'bold'}}><%=attr%></Text>
20
- <Text>{this.props.<%=attr%>}</Text><% end %>
21
- </Card>
22
- </Container>
23
- </View>
24
- )
25
- }
26
- }
27
-
28
- export default connect(
29
- mapStateToProps,
30
- mapDispatchToProps
31
- )(<%= plural_table_name.camelize %>Show)
32
-
@@ -1,54 +0,0 @@
1
- babelrc = Rails.root.join(".babelrc")
2
-
3
- if File.exist?(babelrc)
4
- react_babelrc = JSON.parse(File.read(babelrc))
5
- react_babelrc["presets"] ||= []
6
- react_babelrc["plugins"] ||= []
7
-
8
- if !react_babelrc["presets"].include?("react")
9
- react_babelrc["presets"].push("react")
10
- say "Copying react preset to your .babelrc file"
11
-
12
- File.open(babelrc, "w") do |f|
13
- f.puts JSON.pretty_generate(react_babelrc)
14
- end
15
- end
16
-
17
- if !react_babelrc["plugins"].any?{|plugin| Array(plugin).include?("module-resolver")}
18
- react_babelrc["plugins"].push(["module-resolver", {
19
- "root": ["./app"],
20
- "alias": {
21
- "views": "./app/views",
22
- "components": "./app/components",
23
- "javascripts": "./app/javascripts"
24
- }
25
- }])
26
-
27
- say "Copying module-resolver preset to your .babelrc file"
28
-
29
- File.open(babelrc, "w") do |f|
30
- f.puts JSON.pretty_generate(react_babelrc)
31
- end
32
- end
33
-
34
- else
35
- say "Copying .babelrc to app root"
36
- copy_file "#{__dir__}/templates/mobile/babelrc", Rails.root.join(".babelrc")
37
- end
38
-
39
- say "Copying application.js file to app root"
40
- copy_file "#{__dir__}/templates/mobile/app.js", Rails.root.join("App.js")
41
-
42
- say "Copying rn-cli.config.js file to app root"
43
- copy_file "#{__dir__}/templates/mobile/rn-cli.config.js", Rails.root.join("rn-cli.config.js")
44
-
45
- say "Copying app.json expo file to app root"
46
- copy_file "#{__dir__}/templates/mobile/app.json", Rails.root.join("app.json")
47
-
48
- say "Copying package.json expo file to app root"
49
- copy_file "#{__dir__}/templates/mobile/package.json", Rails.root.join("package.json")
50
-
51
- say "Installing all breezy dependencies"
52
- run "yarn"
53
-
54
- say "Rails Breezy and ReactNative! 🎉", :green
@@ -1,77 +0,0 @@
1
- import React from 'react'
2
- import {combineReducers, createStore, applyMiddleware} from 'redux'
3
- import thunk from 'redux-thunk'
4
- import { Provider } from 'react-redux'
5
- import Breezy from '@jho406/breezy'
6
- import {visit} from '@jho406/breezy/dist/action_creators'
7
- import { StackNavigator } from 'react-navigation'
8
- import { reducer as formReducer } from 'redux-form'
9
-
10
- //Change the below when you have your first screen
11
- const baseUrl = 'http://localhost:3000'
12
- const initialPath = '/example'
13
- const initialPage = {
14
- data: {},
15
- screen: 'ExampleScreen'
16
- }
17
-
18
- // Remove me when you have your first screen
19
- import {View, Text} from 'react-native'
20
- class ExampleScreen extends React.Component {
21
- render() {
22
- return (
23
- <View style={{paddingTop: 50}}>
24
- <Text>Looks like you're up and running!</Text>
25
- <Text>Next create your rails routes and controllers as usual</Text>
26
- <Text>Then run the view generators `rails g breezy:view Post index -t mobile`</Text>
27
- <Text>When ready, remove this ExampleScreen from App.js</Text>
28
- </View>
29
- )
30
- }
31
- }
32
-
33
- // This mapping can be auto populate through
34
- // Breezy generators, for example:
35
- // Run `rails g breezy:view Post index --mobile`
36
- const mapping = {
37
- ExampleScreen, //Remove me when you have your first screen
38
- }
39
-
40
- const navMapping = Object.entries(mapping).reduce((memo, [key, value])=> {
41
- return {[key]: {screen: value}, ...memo}
42
- }, {})
43
-
44
- const {reducer, initialState, connect} = Breezy.start({
45
- initialPage,
46
- baseUrl
47
- })
48
-
49
- const store = createStore(
50
- combineReducers({
51
- ...reducer,
52
- form: formReducer
53
- }),
54
- initialState,
55
- applyMiddleware(thunk)
56
- )
57
-
58
- connect(store)
59
- store.dispatch({type: 'BREEZY_SET_BASE_URL', baseUrl})
60
-
61
- // Uncomment below if you need to fetch on the initial screen
62
- // store.dispatch(visit(initialPath))
63
- window.store = store
64
- const Nav = StackNavigator(navMapping, {
65
- initialRouteName: initialPage.screen,
66
- initialRouteParams: {pageKey: initialPath},
67
- headerMode: 'none',
68
- })
69
-
70
- export default class extends React.Component {
71
- render() {
72
- return <Provider store={store}>
73
- <Nav pageKey={initialPath}/>
74
- </Provider>
75
- }
76
- }
77
-
@@ -1,6 +0,0 @@
1
- {
2
- "expo": {
3
- "sdkVersion": "22.0.0"
4
- }
5
- }
6
-
@@ -1,23 +0,0 @@
1
- {
2
- "presets": ["babel-preset-expo"],
3
- "env": {
4
- "development": {
5
- "plugins": ["transform-react-jsx-source"]
6
- }
7
- },
8
- "plugins": [
9
- [
10
- "module-resolver",
11
- {
12
- "root": [
13
- "./app"
14
- ],
15
- "alias": {
16
- "views": "./app/views",
17
- "components": "./app/components",
18
- "javascripts": "./app/javascripts"
19
- }
20
- }
21
- ]
22
- ]
23
- }
@@ -1,35 +0,0 @@
1
- {
2
- "name": "myapp",
3
- "version": "0.1.0",
4
- "private": true,
5
- "devDependencies": {
6
- "jest-expo": "^22.0.0",
7
- "react-native-scripts": "1.7.0",
8
- "react-test-renderer": "16.0.0-beta.5"
9
- },
10
- "main": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
11
- "scripts": {
12
- "start": "react-native-scripts start",
13
- "eject": "react-native-scripts eject",
14
- "android": "react-native-scripts android",
15
- "ios": "react-native-scripts ios",
16
- "test": "node node_modules/jest/bin/jest.js --watch"
17
- },
18
- "jest": {
19
- "preset": "jest-expo"
20
- },
21
- "dependencies": {
22
- "@jho406/breezy": "0.3.2",
23
- "expo": "^22.0.2",
24
- "react": "16.0.0-beta.5",
25
- "react-native": "^0.49.5",
26
- "react-native-dropdownalert": "3.1.2",
27
- "react-native-elements": "^0.19.0",
28
- "react-navigation": "^1.0.0-beta.19",
29
- "react-redux": "^5.0.6",
30
- "redux": "^3.7.2",
31
- "redux-form": "^7.2.0",
32
- "redux-thunk": "^2.2.0"
33
- }
34
- }
35
-
@@ -1,4 +0,0 @@
1
- module.exports = {
2
- getSourceExts: () => [ 'jsx' ],
3
- }
4
-