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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ea50542043e609312e77f3da4c7d1fef363b3d3b
4
- data.tar.gz: a6daa7a6b46dc31b510fb5c1eaa0887d876b5091
3
+ metadata.gz: 7b9da05cf8c46f15fde699247172243145297a9d
4
+ data.tar.gz: 57698e25090be81d4bdc8488aca81b471a7874b9
5
5
  SHA512:
6
- metadata.gz: 37ba95df0bd821832b80a655f112b2f925062c4042c8007ec7592f91349370d5e974485c79ffc4f32b9790b254655583d8dc9868e2e0e9a6c8de8f36d427fb67
7
- data.tar.gz: 21ec42dd7e39b3e9aac0ad933b38c07d110a1d4562e22738dd2215a35187c2bc3d91ea8ed23773251978047428cc5c280025207641013a39afa6df504b0443b0
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
- ### Instructions
17
+ ### Install
18
18
 
19
- 1. Add to the Gemfile: `gem 'editable_components'`
19
+ - Add to the Gemfile: `gem 'editable_components'`
20
20
 
21
- 2. Copy migrations (Rails 5.x syntax, in Rails 4.x use rake): `rails editable_components:install:migrations`
21
+ - Copy migrations (Rails 5.x syntax, in Rails 4.x use rake): `rails editable_components:install:migrations`
22
22
 
23
- 3. Apply them: `rake db:migrate`
23
+ - Apply them: `rake db:migrate`
24
24
 
25
- 4. Include the concern *Editable* to your model: `include EditableComponents::Concerns::Editable`
25
+ - Include the concern *Editable* to your model: `include EditableComponents::Concerns::Editable`
26
26
 
27
- 5. Add to your application layout (in head, ex. using ERB): `<%= stylesheet_link_tag( EditableComponents::Engine.css ) if EditableComponents::Engine.css %>`
27
+ - Add to your application layout (in head, ex. using ERB): `<%= stylesheet_link_tag( EditableComponents::Engine.css ) if EditableComponents::Engine.css %>`
28
28
 
29
- 6. Add to your application layout (before body closing): `<%= javascript_include_tag( EditableComponents::Engine.js ) if EditableComponents::Engine.js %>`
29
+ - Add to your application layout (before body closing): `<%= javascript_include_tag( EditableComponents::Engine.js ) if EditableComponents::Engine.js %>`
30
30
 
31
- 7. Add your blocks to the views (ex. in show):
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
- 8. Add some sample data (ex. Page model): `Page.first.create_block :text`
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
- cmp.inputs.push( { name: 'ec_cmp[' + el.getAttribute( 'data-ec-type' ) + '][' + el.attributes['data-ec-item'].value + ']', value: el.innerHTML } );
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
- cmp.inputs.push( { name: 'ec_cmp[Block][' + el.attributes['data-ec-block'].value + '][position]', value: last-- } );
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
- cmp.inputs.push( { name: 'ec_cmp[Block][' + sid + '][position]', value: last2-- } );
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
- cmp.inputs.push( { name: 'ec_cmp[Block][0][_add][' + ( cnt++ ) + ']', value: el.getAttribute( 'data-ec-type' ) } );
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
- cmp.inputs.push( { name: 'ec_cmp[Block][' + el.getAttribute( 'data-ec-block' ) + '][_add][' + i + ']', value: el.getAttribute( 'data-ec-container' ) } );
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
- cmp.inputs.push( { name: 'ec_cmp[Block][' + el.attributes['data-ec-block'].value + '][_destroy]', value: '1' } );
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
- cmp.inputs.push( { name: 'ec_cmp[Block][' + el.attributes['data-ec-sub-block'].value + '][_destroy]', value: '1' } );
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._init
129
- self._init = false
130
- if self.name.blank?
131
- names = parent.ec_blocks.map &:name
132
- i = 0
133
- while( ( i += 1 ) < 1000 ) # Search an empty group
134
- unless names.include? "#{block_type}-#{i}"
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( _init: true, block_type: type )
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
@@ -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, _init: true )
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, _init: true ).save
77
+ EditableComponents::Block.new( parent: parent, block_type: t, version: version ).save
78
78
  end
79
79
  end
80
80
  end
@@ -1,3 +1,3 @@
1
1
  module EditableComponents
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.2'
3
3
  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.0
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-01 00:00:00.000000000 Z
11
+ date: 2017-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails