editable_components 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +41 -10
- data/app/assets/javascripts/editable_components/main.js +14 -9
- data/app/models/editable_components/block.rb +32 -38
- data/app/models/editable_components/concerns/editable.rb +1 -1
- data/app/views/editable_components/_admin_toolbar.html.erb +0 -1
- data/db/migrate/20170414173603_create_editable_components_blocks.rb +0 -1
- data/lib/editable_components.rb +2 -2
- data/lib/editable_components/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b9da05cf8c46f15fde699247172243145297a9d
|
4
|
+
data.tar.gz: 57698e25090be81d4bdc8488aca81b471a7874b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7fc23be9b8ebbcd7732652f5f418d0c9091248d2736a1295074596687eb9759d18d6294d2a89f8d97ff69128279d8f7e1d2d12ae609bb3db45c052d1efc8161f
|
7
|
+
data.tar.gz: 53070853e6f5e09fcb0fec4821be5c915aebcd386f2c0b36d2878da239977f82da587e054ba1250a5c03470e66e96dd5c6ac61b33773b942317f74966510a38f
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# EditableComponents for Rails
|
1
|
+
# EditableComponents for Rails [![Gem Version](https://badge.fury.io/rb/editable_components.svg)](https://badge.fury.io/rb/editable_components)
|
2
2
|
|
3
3
|
A Ruby on Rails plugin to manage UI components editable from the front-end.
|
4
4
|
|
@@ -14,21 +14,21 @@ Goals:
|
|
14
14
|
|
15
15
|
![preview](preview.png)
|
16
16
|
|
17
|
-
###
|
17
|
+
### Install
|
18
18
|
|
19
|
-
|
19
|
+
- Add to the Gemfile: `gem 'editable_components'`
|
20
20
|
|
21
|
-
|
21
|
+
- Copy migrations (Rails 5.x syntax, in Rails 4.x use rake): `rails editable_components:install:migrations`
|
22
22
|
|
23
|
-
|
23
|
+
- Apply them: `rake db:migrate`
|
24
24
|
|
25
|
-
|
25
|
+
- Include the concern *Editable* to your model: `include EditableComponents::Concerns::Editable`
|
26
26
|
|
27
|
-
|
27
|
+
- Add to your application layout (in head, ex. using ERB): `<%= stylesheet_link_tag( EditableComponents::Engine.css ) if EditableComponents::Engine.css %>`
|
28
28
|
|
29
|
-
|
29
|
+
- Add to your application layout (before body closing): `<%= javascript_include_tag( EditableComponents::Engine.js ) if EditableComponents::Engine.js %>`
|
30
30
|
|
31
|
-
|
31
|
+
- Add your blocks to the views (ex. in show):
|
32
32
|
```erb
|
33
33
|
<%= render layout: 'editable_components/blocks', locals: { container: @page } do |blocks| %>
|
34
34
|
<% blocks.each do |block| %>
|
@@ -37,7 +37,38 @@ Goals:
|
|
37
37
|
<% end %>
|
38
38
|
```
|
39
39
|
|
40
|
-
|
40
|
+
- Add some sample data (ex. Page model): `Page.first.create_block :text`
|
41
|
+
|
42
|
+
### Config
|
43
|
+
|
44
|
+
Edit the conf file: `config/initializers/editable_components.rb`
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
conf = EditableComponents.config
|
48
|
+
# Adds a new custom block
|
49
|
+
conf[:ec_blocks][:custom] = {
|
50
|
+
name: 'Custom block',
|
51
|
+
items: {
|
52
|
+
int1: :item_integer,
|
53
|
+
int2: :item_integer,
|
54
|
+
a_float: :item_float
|
55
|
+
}
|
56
|
+
}
|
57
|
+
EditableComponents.config( { components: conf[:ec_blocks] } )
|
58
|
+
```
|
59
|
+
|
60
|
+
Create the new view blocks: `app/views/editable_components/_block_custom.html.erb`
|
61
|
+
|
62
|
+
```erb
|
63
|
+
<% if local_assigns[:block] %>
|
64
|
+
<% block = local_assigns[:block] %>
|
65
|
+
<div <%= block.editable %>>
|
66
|
+
1st number: <span class="num1"<%= block.props.integers[0].editable %>><%= block.props.integers[0] %></span>
|
67
|
+
- 2nd number: <span class="num2"<%= block.props.integers[1].editable %>><%= block.props.integers[1] %></span><br/>
|
68
|
+
A float: <span <%= block.props.float.editable %>><%= block.props.float %></span><br/>
|
69
|
+
</div>
|
70
|
+
<% end %>
|
71
|
+
```
|
41
72
|
|
42
73
|
##### Images
|
43
74
|
|
@@ -2,6 +2,13 @@
|
|
2
2
|
var ecMain = (function() {
|
3
3
|
this.editing = false;
|
4
4
|
return {
|
5
|
+
createInput( parent, name, value ) {
|
6
|
+
var el = document.createElement( 'input' );
|
7
|
+
el.setAttribute( 'type', 'hidden' );
|
8
|
+
el.setAttribute( 'name', name );
|
9
|
+
el.setAttribute( 'value', value );
|
10
|
+
parent.appendChild( el );
|
11
|
+
},
|
5
12
|
dlgPreviewClose: function() {
|
6
13
|
Sizzle( '[data-ec-toolbar]' )[0].style.display = 'block';
|
7
14
|
Sizzle( '[data-ec-dlg="preview"]' )[0].style.display = 'none';
|
@@ -228,45 +235,43 @@ var ecVue = new Vue({
|
|
228
235
|
onSubmit: function( event ) {
|
229
236
|
// event.preventDefault();
|
230
237
|
|
231
|
-
var cmp = this;
|
232
|
-
this.inputs = [];
|
233
238
|
// Update items
|
234
239
|
Sizzle( '[data-ec-item]' ).forEach( function( el ) {
|
235
240
|
var input = el.getAttribute( 'data-ec-input' );
|
236
241
|
if( input != 'file' && input != 'file_image' ) {
|
237
|
-
|
242
|
+
ecMain.createInput( Sizzle( '[data-ec-fields]' )[0], 'ec_cmp[' + el.getAttribute( 'data-ec-type' ) + '][' + el.attributes['data-ec-item'].value + ']', el.innerHTML );
|
238
243
|
}
|
239
244
|
});
|
240
245
|
// Update positions
|
241
246
|
var last = Sizzle( '[data-ec-block]' ).length;
|
242
247
|
Sizzle( '[data-ec-block]' ).forEach( function( el ) {
|
243
|
-
|
248
|
+
ecMain.createInput( Sizzle( '[data-ec-fields]' )[0], 'ec_cmp[Block][' + el.attributes['data-ec-block'].value + '][position]', last-- );
|
244
249
|
var last2 = Sizzle( '[data-ec-sub-block]', el ).length;
|
245
250
|
if( last2 ) {
|
246
251
|
Sizzle( '[data-ec-sub-block]', el ).forEach( function( el2 ) {
|
247
252
|
var sid = el2.getAttribute( 'data-ec-sub-block' );
|
248
|
-
|
253
|
+
ecMain.createInput( Sizzle( '[data-ec-fields]' )[0], 'ec_cmp[Block][' + sid + '][position]', last2-- );
|
249
254
|
});
|
250
255
|
}
|
251
256
|
});
|
252
257
|
// New blocks
|
253
258
|
var cnt = 0;
|
254
259
|
Sizzle( '[data-ec-new-block]' ).forEach( function( el ) {
|
255
|
-
|
260
|
+
ecMain.createInput( Sizzle( '[data-ec-fields]' )[0], 'ec_cmp[Block][0][_add][' + ( cnt++ ) + ']', el.getAttribute( 'data-ec-type' ) );
|
256
261
|
});
|
257
262
|
// New sub blocks
|
258
263
|
Sizzle( '[data-ec-block][data-ec-new-blocks]' ).forEach( function( el ) {
|
259
264
|
cnt = parseInt( el.getAttribute( 'data-ec-new-blocks' ) );
|
260
265
|
for( var i = 0; i < cnt; i++ ) {
|
261
|
-
|
266
|
+
ecMain.createInput( Sizzle( '[data-ec-fields]' )[0], 'ec_cmp[Block][' + el.getAttribute( 'data-ec-block' ) + '][_add][' + i + ']', el.getAttribute( 'data-ec-container' ) );
|
262
267
|
}
|
263
268
|
});
|
264
269
|
// Remove blocks
|
265
270
|
Sizzle( '[data-ec-block][data-ec-destroy="1"]' ).forEach( function( el ) {
|
266
|
-
|
271
|
+
ecMain.createInput( Sizzle( '[data-ec-fields]' )[0], 'ec_cmp[Block][' + el.attributes['data-ec-block'].value + '][_destroy]', '1' );
|
267
272
|
});
|
268
273
|
Sizzle( '[data-ec-sub-block][data-ec-destroy="1"]' ).forEach( function( el ) {
|
269
|
-
|
274
|
+
ecMain.createInput( Sizzle( '[data-ec-fields]' )[0], 'ec_cmp[Block][' + el.attributes['data-ec-sub-block'].value + '][_destroy]', '1' );
|
270
275
|
});
|
271
276
|
},
|
272
277
|
removeBlock: function() {
|
@@ -15,6 +15,7 @@ module EditableComponents
|
|
15
15
|
|
16
16
|
# --- hooks -------------------------------------------------------------- #
|
17
17
|
before_create :on_before_create
|
18
|
+
after_create :on_after_create
|
18
19
|
|
19
20
|
# --- scopes ------------------------------------------------------------- #
|
20
21
|
default_scope { order( position: :desc ) }
|
@@ -85,33 +86,6 @@ module EditableComponents
|
|
85
86
|
@_items[name]
|
86
87
|
end
|
87
88
|
|
88
|
-
def init
|
89
|
-
t = block_type.to_sym
|
90
|
-
if Block::block_types.include? t
|
91
|
-
init_items self, EditableComponents.config[:ec_blocks][t][:items]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def init_items( block, items )
|
96
|
-
items.each do |name, type|
|
97
|
-
t = type.to_sym
|
98
|
-
if type.to_s.start_with? 'item_'
|
99
|
-
c = 'EditableComponents::' + ActiveSupport::Inflector.camelize( t )
|
100
|
-
begin
|
101
|
-
model = c.constantize
|
102
|
-
rescue Exception => e
|
103
|
-
Rails.logger.error '[ERROR] EditableComponents - init_items: ' + e.message
|
104
|
-
model = false
|
105
|
-
end
|
106
|
-
block.items << model.new( name: name ).init if model
|
107
|
-
elsif Block::block_types.include? t.to_sym
|
108
|
-
cmp = Block.new( block_type: t, name: name )
|
109
|
-
block.ec_blocks << cmp
|
110
|
-
init_items( cmp, EditableComponents.config[:ec_blocks][t][:items] )
|
111
|
-
end
|
112
|
-
end if items
|
113
|
-
end
|
114
|
-
|
115
89
|
def has_parent?
|
116
90
|
parent.present?
|
117
91
|
end
|
@@ -124,20 +98,22 @@ module EditableComponents
|
|
124
98
|
parent.present? && parent_type == 'EditableComponents::Block'
|
125
99
|
end
|
126
100
|
|
101
|
+
def on_after_create
|
102
|
+
# TODO: validates type before creation!
|
103
|
+
t = self.block_type.to_sym
|
104
|
+
Block::init_items( self, EditableComponents.config[:ec_blocks][t][:items] ) if Block::block_types.include?( t )
|
105
|
+
end
|
106
|
+
|
127
107
|
def on_before_create
|
128
|
-
if self.
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
self.name = "#{block_type}-#{i}"
|
136
|
-
break
|
137
|
-
end
|
108
|
+
if self.name.blank?
|
109
|
+
names = parent.ec_blocks.map &:name
|
110
|
+
i = 0
|
111
|
+
while( ( i += 1 ) < 1000 ) # Search an empty group
|
112
|
+
unless names.include? "#{block_type}-#{i}"
|
113
|
+
self.name = "#{block_type}-#{i}"
|
114
|
+
break
|
138
115
|
end
|
139
116
|
end
|
140
|
-
init
|
141
117
|
end
|
142
118
|
end
|
143
119
|
|
@@ -172,5 +148,23 @@ module EditableComponents
|
|
172
148
|
def self.block_types
|
173
149
|
@@block_types ||= EditableComponents.config[:ec_blocks].keys
|
174
150
|
end
|
151
|
+
|
152
|
+
def self.init_items( block, items )
|
153
|
+
items.each do |name, type|
|
154
|
+
t = type.to_sym
|
155
|
+
if type.to_s.start_with? 'item_'
|
156
|
+
c = 'EditableComponents::' + ActiveSupport::Inflector.camelize( t )
|
157
|
+
begin
|
158
|
+
model = c.constantize
|
159
|
+
rescue Exception => e
|
160
|
+
Rails.logger.error '[ERROR] EditableComponents - init_items: ' + e.message
|
161
|
+
model = false
|
162
|
+
end
|
163
|
+
block.items << model.new( name: name ).init if model
|
164
|
+
elsif Block::block_types.include? t.to_sym
|
165
|
+
block.ec_blocks << ( cmp = Block.new( block_type: t, name: name ) )
|
166
|
+
end
|
167
|
+
end if items
|
168
|
+
end
|
175
169
|
end
|
176
170
|
end
|
@@ -9,7 +9,7 @@ module EditableComponents
|
|
9
9
|
accepts_nested_attributes_for :ec_blocks, allow_destroy: true
|
10
10
|
|
11
11
|
def create_block( type = :text, params = {} )
|
12
|
-
block = Block.new(
|
12
|
+
block = Block.new( block_type: type )
|
13
13
|
block.options = params[:options] if params[:options]
|
14
14
|
block.validations = params[:validations] if params[:validations]
|
15
15
|
ec_blocks << block
|
@@ -85,7 +85,6 @@
|
|
85
85
|
<%= form_for page, url: EditableComponents::Engine::routes.url_helpers.ec_update_path( model, page ), method: :patch, as: :ec_cmp, namespace: 'ec', html: { 'data-ec-form': '', 'data-ec-model': model, 'v-cloak': '', 'v-on:submit': 'onSubmit( $event )' } do |f| %>
|
86
86
|
<input type="hidden" name="version" value="<%= @version.to_i %>"/>
|
87
87
|
<div data-ec-fields></div>
|
88
|
-
<input v-for="input in inputs" type="hidden" v-bind:name="input.name" v-bind:value="input.value"/>
|
89
88
|
<%= button_tag( type: 'submit', class: 'c-button c-button--info', title: 'Save changes', 'data-ec-menu-save': '' ) do %>
|
90
89
|
<i data-ec-icon="icon-floppy-disk"></i> save
|
91
90
|
<% end %>
|
@@ -6,7 +6,6 @@ class CreateEditableComponentsBlocks < ActiveRecord::Migration[5.0]
|
|
6
6
|
t.string :name, null: false, default: ''
|
7
7
|
t.integer :position, null: false, default: 0
|
8
8
|
t.boolean :published, null: false, default: true
|
9
|
-
t.boolean :_init, null: false, default: false
|
10
9
|
t.string :options, null: false, default: '{}'
|
11
10
|
t.string :validations, null: false, default: '{}'
|
12
11
|
t.integer :parent_id
|
data/lib/editable_components.rb
CHANGED
@@ -60,7 +60,7 @@ module EditableComponents
|
|
60
60
|
t = block.block_type.to_sym
|
61
61
|
add.keys.each do
|
62
62
|
if @@config[:ec_blocks][t] && @@config[:ec_blocks][t][:children_type]
|
63
|
-
sub_block = EditableComponents::Block.new( parent: block, block_type: @@config[:ec_blocks][t][:children_type], version: version
|
63
|
+
sub_block = EditableComponents::Block.new( parent: block, block_type: @@config[:ec_blocks][t][:children_type], version: version )
|
64
64
|
sub_block.save
|
65
65
|
# TODO: return errors
|
66
66
|
end
|
@@ -74,7 +74,7 @@ module EditableComponents
|
|
74
74
|
add.each do |index, new_type|
|
75
75
|
t = new_type.to_sym
|
76
76
|
# TODO: check if t is a valid block type
|
77
|
-
EditableComponents::Block.new( parent: parent, block_type: t, version: version
|
77
|
+
EditableComponents::Block.new( parent: parent, block_type: t, version: version ).save
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: editable_components
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mat
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-05-
|
11
|
+
date: 2017-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|