reativo 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +38 -0
- data/app/controllers/reativo/crud_controller.rb +17 -2
- data/lib/generators/reativo/install_generator.rb +55 -0
- data/lib/generators/reativo/js_generator.rb +78 -0
- data/lib/generators/reativo/op_generator.rb +96 -0
- data/lib/generators/reativo/templates/component/Edit.js +43 -0
- data/lib/generators/reativo/templates/component/Form.js +52 -0
- data/lib/generators/reativo/templates/component/Index.js +51 -0
- data/lib/generators/reativo/templates/component/New.js +37 -0
- data/lib/generators/reativo/templates/component/Show.js +32 -0
- data/lib/generators/reativo/templates/operation/create.erb +3 -4
- data/lib/generators/reativo/templates/operation/destroy.erb +2 -2
- data/lib/generators/reativo/templates/operation/index.erb +2 -1
- data/lib/generators/reativo/templates/operation/update.erb +3 -4
- data/lib/generators/reativo/templates/representer/create.erb +1 -1
- data/lib/generators/reativo/templates/representer/index.erb +1 -1
- data/lib/generators/reativo/templates/representer/module.erb +1 -1
- data/lib/generators/reativo/templates/representer/update.erb +1 -1
- data/lib/generators/reativo/templates/support/store.js +24 -0
- data/lib/generators/reativo/templates/support/theme.js +25 -0
- data/lib/generators/reativo/templates/theme/Baseline.js +10 -0
- data/lib/generators/reativo/templates/theme/Drawer.js +50 -0
- data/lib/generators/reativo/templates/theme/MainBar.js +223 -0
- data/lib/generators/reativo/templates/theme/Menu.js +79 -0
- data/lib/generators/reativo/templates/theme/Snackbar.js +9 -0
- data/lib/generators/reativo/templates/theme/layout.erb +59 -0
- data/lib/generators/reativo/templates/theme/layout.rb +6 -0
- data/lib/reativo/version.rb +1 -1
- metadata +33 -4
- data/lib/generators/reativo/USAGE +0 -23
- data/lib/generators/reativo/reativo_generator.rb +0 -63
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7fbfd0690cbec85de0786d1e7a368d409f79867fd7a644e473949b6da653509
|
4
|
+
data.tar.gz: 27753576e09e0b9b250a47174de9044fd62383e6555af476577bfbc45487b0de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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;
|