reativo 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +38 -0
  3. data/app/controllers/reativo/crud_controller.rb +17 -2
  4. data/lib/generators/reativo/install_generator.rb +55 -0
  5. data/lib/generators/reativo/js_generator.rb +78 -0
  6. data/lib/generators/reativo/op_generator.rb +96 -0
  7. data/lib/generators/reativo/templates/component/Edit.js +43 -0
  8. data/lib/generators/reativo/templates/component/Form.js +52 -0
  9. data/lib/generators/reativo/templates/component/Index.js +51 -0
  10. data/lib/generators/reativo/templates/component/New.js +37 -0
  11. data/lib/generators/reativo/templates/component/Show.js +32 -0
  12. data/lib/generators/reativo/templates/operation/create.erb +3 -4
  13. data/lib/generators/reativo/templates/operation/destroy.erb +2 -2
  14. data/lib/generators/reativo/templates/operation/index.erb +2 -1
  15. data/lib/generators/reativo/templates/operation/update.erb +3 -4
  16. data/lib/generators/reativo/templates/representer/create.erb +1 -1
  17. data/lib/generators/reativo/templates/representer/index.erb +1 -1
  18. data/lib/generators/reativo/templates/representer/module.erb +1 -1
  19. data/lib/generators/reativo/templates/representer/update.erb +1 -1
  20. data/lib/generators/reativo/templates/support/store.js +24 -0
  21. data/lib/generators/reativo/templates/support/theme.js +25 -0
  22. data/lib/generators/reativo/templates/theme/Baseline.js +10 -0
  23. data/lib/generators/reativo/templates/theme/Drawer.js +50 -0
  24. data/lib/generators/reativo/templates/theme/MainBar.js +223 -0
  25. data/lib/generators/reativo/templates/theme/Menu.js +79 -0
  26. data/lib/generators/reativo/templates/theme/Snackbar.js +9 -0
  27. data/lib/generators/reativo/templates/theme/layout.erb +59 -0
  28. data/lib/generators/reativo/templates/theme/layout.rb +6 -0
  29. data/lib/reativo/version.rb +1 -1
  30. metadata +33 -4
  31. data/lib/generators/reativo/USAGE +0 -23
  32. data/lib/generators/reativo/reativo_generator.rb +0 -63
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6689bddd3533b8b39810df84b4caeb5219398535bad054134cebc4f96bff11c7
4
- data.tar.gz: 26e7e45b8f5ac20e1cd2b2a5bfec1a65230a7894a7b817bc58ec07fbaa2908e4
3
+ metadata.gz: a7fbfd0690cbec85de0786d1e7a368d409f79867fd7a644e473949b6da653509
4
+ data.tar.gz: 27753576e09e0b9b250a47174de9044fd62383e6555af476577bfbc45487b0de
5
5
  SHA512:
6
- metadata.gz: 4f43a74932404fa8b1d7df5ce81c4899317de6d6424db0fa733d9eabe2b1b263aaa6104e44867223944eb2ef9417ae81ce642133625838355533028f8e00d0d9
7
- data.tar.gz: b0f71fd29937827f11f0d114f2a0ac9ffbf64e486a6055c3cf5bf4f7e3e50e8bc1e5ec1a4282c8dee8ca1c4be475bb7ced171b7f5ec0c8faf2a6a4a71cc56acb
6
+ metadata.gz: 2178a719b426401ba734c314138ad4bd25d7e1c53f503be338fc3933b82d01ebce20a9849a0295149653cb622fe6a01bfa7495b844a37f829ddd14c244ba23c5
7
+ data.tar.gz: 6eb8b3804551722735396b12d97d90d066f39bbcb7a3f62d9505e6e3698e0ad2dad75267e8fd568c9cc6daaf32769e3590cdab3c2290cf372a2fa592a590d0da
data/README.md CHANGED
@@ -18,6 +18,15 @@ Add this line to your application's Gemfile:
18
18
  gem 'reativo'
19
19
  ```
20
20
 
21
+ To use our npm package, also run:
22
+
23
+ ```bash
24
+ yarn add reativo
25
+ npm install --save reativo
26
+ ```
27
+
28
+ It has some [peerDependencies](https://github.com/fernandes/reativo/blob/d78b9ab4d88930178fd55267dfed2f32cb2ff2d2/reativo_js/package.json#L17-L31), check this out.
29
+
21
30
  ## Usage
22
31
 
23
32
  The basic usage is include the concern on your controller and set the layout component.
@@ -110,6 +119,35 @@ import { setTheme } from 'reativo'
110
119
  setTheme(theme)
111
120
  ```
112
121
 
122
+ ### Auto Complete
123
+
124
+ The JS library comes with a material-ui ready to use select using auto complete
125
+
126
+ I'm not sure if a trailblazer operation / macro could help here... thoughts?
127
+
128
+ ```js
129
+ const loadOptions = (inputValue, callback) => {
130
+ axios.get(`/todos.json?q=${inputValue}`)
131
+ .then(function (response) {
132
+ const results = response.data.map(x => {
133
+ return { value: x.id, label: x.title}
134
+ })
135
+ callback(results)
136
+ })
137
+ }
138
+
139
+ const handleChange = (value) => {
140
+ console.log('Auto Compete Selected: ', value)
141
+ }
142
+
143
+ import { SelectAutoComplete } from 'reativo'
144
+
145
+ <SelectAutoComplete
146
+ loadOptions={loadOptions}
147
+ handleChange={this.handleChange}
148
+ />
149
+ ```
150
+
113
151
  ## Generator
114
152
 
115
153
  It comes with a generator for Trailblazer, so, yeah!, you can generate the operations, contracts and representers!
@@ -6,6 +6,10 @@ module Reativo
6
6
  def theme_cell
7
7
  raise Exception.new('Please specify your theme cell here')
8
8
  end
9
+
10
+ def _run_options(options)
11
+ options.merge( "current_user" => self.try(:current_user) )
12
+ end
9
13
 
10
14
  def trb(cell_constant, model, options: {}, rails_options: {})
11
15
  render(
@@ -60,8 +64,11 @@ module Reativo
60
64
  end
61
65
 
62
66
  def new
67
+ run new_op
68
+
69
+ decorated_model = result_model ? result_model.extend(result['representer.render.class']) : nil
63
70
  respond_to do |format|
64
- format.html { component(new_compo) }
71
+ format.html { component(new_compo, model: decorated_model ? decorated_model.to_hash : nil) }
65
72
  end
66
73
  end
67
74
 
@@ -142,12 +149,16 @@ module Reativo
142
149
  action_op('create')
143
150
  end
144
151
 
152
+ def new_op
153
+ present_op("create")
154
+ end
155
+
145
156
  def new_compo
146
157
  action_compo('new')
147
158
  end
148
159
 
149
160
  def edit_op
150
- action_op("edit")
161
+ present_op("update")
151
162
  end
152
163
 
153
164
  def edit_compo
@@ -165,6 +176,10 @@ module Reativo
165
176
  def action_op(action)
166
177
  "#{collection_name}::Operation::#{action.camelize}".constantize
167
178
  end
179
+
180
+ def present_op(action)
181
+ "#{collection_name}::Operation::#{action.camelize}::Present".constantize
182
+ end
168
183
 
169
184
  def action_compo(action)
170
185
  "#{collection_name.underscore}/#{action.camelize}"
@@ -0,0 +1,55 @@
1
+ module Reativo
2
+ class InstallGenerator < Rails::Generators::Base
3
+ source_root File.expand_path('templates', __dir__)
4
+
5
+ desc <<-DESC.strip_heredoc
6
+ Description:
7
+ Reativo install, make it running, fast!
8
+
9
+ Example:
10
+ rails g reativo:install
11
+
12
+ This will create:
13
+ - theme cell and layout
14
+ - theme js components (Baseline, Drawer, MainBar, Menu, Snackbar)
15
+ - support files (theme and store example)
16
+
17
+ Also appends the initial setup to `application` pack
18
+
19
+ DESC
20
+
21
+ def install
22
+ append_to_file 'app/javascript/packs/application.js' do <<~'RUBY'
23
+ import store from '../store'
24
+ window.store = store
25
+
26
+ import theme from '../theme'
27
+
28
+ import { setTheme } from 'reativo'
29
+ setTheme(theme)
30
+ RUBY
31
+ end
32
+
33
+ template "theme/layout.rb", 'app/concepts/theme/cell/layout.rb'
34
+ copy_file "theme/layout.erb", 'app/concepts/theme/view/layout.erb'
35
+
36
+ copy_component("Baseline")
37
+ copy_component("Drawer")
38
+ copy_component("MainBar")
39
+ copy_component("Menu")
40
+ copy_component("Snackbar")
41
+
42
+ copy_support("theme")
43
+ copy_support("store")
44
+ end
45
+
46
+ private
47
+ def copy_component(name)
48
+ copy_file "theme/#{name}.js", "app/javascript/components/theme/#{name}.js"
49
+ end
50
+
51
+ def copy_support(name)
52
+ copy_file "support/#{name}.js", "app/javascript/#{name}/index.js"
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,78 @@
1
+ module Reativo
2
+ class JsGenerator < Rails::Generators::NamedBase
3
+ source_root File.expand_path('templates', __dir__)
4
+ argument :model_name, required: true
5
+ class_option :actions, type: :array, default: []
6
+ class_option :properties, type: :array, default: [], aliases: ['--props']
7
+
8
+ desc <<-DESC.strip_heredoc
9
+ Description:
10
+ Generate the JS files for a crud
11
+
12
+ Example:
13
+ If you don't specify some actions, default is create for all
14
+
15
+ rails g reativo Admin::Todos Todo --properties title completed
16
+
17
+ This will create:
18
+ app/javascript/components/admin/todos/Index.js
19
+ app/javascript/components/admin/todos/New.js
20
+ app/javascript/components/admin/todos/Show.js
21
+ app/javascript/components/admin/todos/Edit.js
22
+ app/javascript/components/admin/todos/Form.js
23
+
24
+ Example:
25
+ rails g reativo:js Admin::Todos --properties title completed --actions index
26
+
27
+ This will create:
28
+ app/javascript/components/admin/todos/Index.js
29
+ DESC
30
+
31
+ def generate_operations
32
+ needs_form = false
33
+ actions = options['actions'].empty? ? ['index', 'new', 'show', 'edit'] : options['actions']
34
+
35
+ actions.each do |action|
36
+ template "component/#{action.capitalize}.js", component_path(action)
37
+ if needs_form?(action)
38
+ needs_form = true
39
+ end
40
+ end
41
+
42
+ if needs_form
43
+ template "component/Form.js", component_path("Form")
44
+ end
45
+ end
46
+
47
+ private
48
+ def needs_form?(action)
49
+ return true if action == "new"
50
+ return true if action == "edit"
51
+ false
52
+ end
53
+
54
+ def component_path(action)
55
+ "app/javascript/components/#{class_name.underscore}/#{action.capitalize}.js"
56
+ end
57
+
58
+ def collection_path
59
+ class_name.underscore
60
+ end
61
+
62
+ def element_path
63
+ class_name.singularize.underscore
64
+ end
65
+
66
+ def model_name_singular
67
+ model_name.demodulize.singularize
68
+ end
69
+
70
+ def model_name_plural
71
+ model_name.demodulize.pluralize
72
+ end
73
+
74
+ def js_properties
75
+ options[:properties].join(", ")
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,96 @@
1
+ module Reativo
2
+ class OpGenerator < Rails::Generators::NamedBase
3
+ MAP = {
4
+ index: { operation: true, contract: false, representer: true},
5
+ create: { operation: true, contract: true, representer: true},
6
+ show: { operation: true, contract: false, representer: false},
7
+ update: { operation: true, contract: true, representer: true},
8
+ destroy: { operation: true, contract: false, representer: false},
9
+ }
10
+
11
+ source_root File.expand_path('templates', __dir__)
12
+ argument :model_name, required: true
13
+ class_option :view_model, type: :boolean, default: false, aliases: ['-v']
14
+ class_option :crud, type: :boolean, default: false, aliases: ['-c']
15
+ class_option :actions, type: :array, default: []
16
+ class_option :properties, type: :array, default: [], aliases: ['--props']
17
+
18
+ desc <<-DESC.strip_heredoc
19
+ Description:
20
+ Trailblazer generator for my trailblazer workflow
21
+
22
+ Example:
23
+ rails g reativo:op Admin::Todos Todo --properties title completed --crud --view_model
24
+
25
+ This will create:
26
+ app/concepts/admin/todos/{operation, representer}/index.rb
27
+ app/concepts/admin/todos/{contract, operation, representer}/create.rb
28
+ app/concepts/admin/todos/{operation}/show.rb
29
+ app/concepts/admin/todos/{contract, operation, representer}/update.rb
30
+ app/concepts/admin/todos/{operation}/destroy.rb
31
+ app/concepts/admin/todos/representer/todo_module.rb # the model representation
32
+
33
+ Example 2:
34
+ If you don't wanna create for all actions, you can specify
35
+
36
+ rails g reativo:op Admin::Todos Todo --properties title completed --actions index create --view_model
37
+
38
+ This will create:
39
+ app/concepts/admin/todos/{operation, representer}/index.rb
40
+ app/concepts/admin/todos/{contract, operation, representer}/create.rb
41
+ app/concepts/admin/todos/representer/todo_module.rb
42
+
43
+ DESC
44
+
45
+ def generate_operations
46
+ representer_module = false
47
+ actions = options['actions'] || []
48
+
49
+ actions = ['index', 'create', 'show', 'update', 'destroy'] if options[:crud]
50
+
51
+ actions.each do |action|
52
+ template "operation/#{action}.erb", concept_path("operation", action) if has_operation?(action)
53
+ template "contract/#{action}.erb", concept_path("contract", action) if has_contract?(action)
54
+ if has_representer?(action)
55
+ template "representer/#{action}.erb", concept_path("representer", action)
56
+ representer_module = true
57
+ end
58
+ end
59
+
60
+ if representer_module
61
+ template "representer/module.erb", concept_path("representer", "#{representer_path(model_name)}_module")
62
+ end
63
+ end
64
+
65
+ private
66
+ def property_attribute(property)
67
+ return "property :#{property}"
68
+ end
69
+
70
+ def properties_symbols(include_id:)
71
+ args = options[:properties].dup
72
+ args.prepend(:id) if include_id
73
+ args.map { |x| ":#{x}" }.join(", ")
74
+ end
75
+
76
+ def concept_path(operation, action)
77
+ "app/concepts/#{class_name.underscore}/#{operation}/#{action}.rb"
78
+ end
79
+
80
+ def has_operation?(action)
81
+ MAP.dig(action.to_sym, :operation) || false
82
+ end
83
+
84
+ def has_contract?(action)
85
+ MAP.dig(action.to_sym, :contract) || false
86
+ end
87
+
88
+ def has_representer?(action)
89
+ MAP.dig(action.to_sym, :representer) || false
90
+ end
91
+
92
+ def representer_path(model_name)
93
+ model_name.demodulize.underscore
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,43 @@
1
+ import { hot } from 'react-hot-loader/root'
2
+ import React from 'react'
3
+
4
+ import {
5
+ Typography,
6
+ Button,
7
+ } from '@material-ui/core'
8
+ import Form from './Form'
9
+ import { Form as FinalForm } from 'react-final-form'
10
+ import { validate } from './Form'
11
+ import { RailsForm } from 'reativo'
12
+ import { wrapper } from "reativo"
13
+
14
+ function Edit({model}) {
15
+ <%- unless js_properties.empty? -%>
16
+ const { <%= js_properties %> } = model
17
+ <%- end -%>
18
+ return (
19
+ <div style={{ padding: 16, margin: 'auto', maxWidth: 600 }}>
20
+ <Typography variant="h4" align="center" component="h1" gutterBottom>
21
+ Edit <%= model_name_singular %>
22
+ </Typography>
23
+ <RailsForm
24
+ component={FinalForm}
25
+ action='update'
26
+ url={`/<%= collection_path %>/${model.id}`}
27
+ successUrl={`/<%= collection_path %>/${model.id}`}
28
+ validate={validate}
29
+ <%- unless js_properties.empty? -%>
30
+ initialValues={{ <%= js_properties %> }}
31
+ <%- end -%>
32
+ render={(props) => (
33
+ <Form {...props} />
34
+ )}
35
+ />
36
+ <Button variant="contained" color="secondary" href="/<%= collection_path %>">
37
+ Back to <%= model_name_plural %>
38
+ </Button>
39
+ </div>
40
+ );
41
+ }
42
+
43
+ export default hot(wrapper(Edit))
@@ -0,0 +1,52 @@
1
+ import React from 'react'
2
+
3
+ import { Field } from 'react-final-form'
4
+ import { TextField } from 'final-form-material-ui'
5
+ import {
6
+ Paper,
7
+ Grid,
8
+ Button,
9
+ } from '@material-ui/core';
10
+
11
+ export const validate = values => {
12
+ // const errors = {};
13
+ // if (!values.name) {
14
+ // errors.name = 'Required';
15
+ // }
16
+ // return errors;
17
+ };
18
+
19
+ function Form({ handleSubmit, reset, submitting, pristine, values }) {
20
+ return (
21
+ <form onSubmit={handleSubmit}>
22
+ <Paper style={{ padding: 16 }}>
23
+ <Grid container alignItems="flex-start" spacing={8}>
24
+ <%- options[:properties].each do |prop| -%>
25
+ <Grid item xs={12}>
26
+ <Field
27
+ fullWidth
28
+ name="<%= prop %>"
29
+ component={TextField}
30
+ type="text"
31
+ label="<%= prop.humanize %>"
32
+ />
33
+ </Grid>
34
+ <%- end -%>
35
+ <Grid item style={{ marginTop: 16 }}>
36
+ <Button
37
+ variant="contained"
38
+ color="primary"
39
+ type="submit"
40
+ disabled={submitting}
41
+ onClick={(e) => handleSubmit(e)}
42
+ >
43
+ Submit
44
+ </Button>
45
+ </Grid>
46
+ </Grid>
47
+ </Paper>
48
+ </form>
49
+ );
50
+ }
51
+
52
+ export default Form;