editable_components 0.1.0 → 0.1.2

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.
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