editable_components 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +64 -0
  4. data/Rakefile +34 -0
  5. data/app/assets/config/editable_components_manifest.js +2 -0
  6. data/app/assets/fonts/editable_components/icomoon.eot +0 -0
  7. data/app/assets/fonts/editable_components/icomoon.svg +24 -0
  8. data/app/assets/fonts/editable_components/icomoon.ttf +0 -0
  9. data/app/assets/fonts/editable_components/icomoon.woff +0 -0
  10. data/app/assets/javascripts/editable_components/application.js +13 -0
  11. data/app/assets/javascripts/editable_components/dragula/dragula.css +22 -0
  12. data/app/assets/javascripts/editable_components/dragula/dragula.js +908 -0
  13. data/app/assets/javascripts/editable_components/dragula/dragula.min.css +1 -0
  14. data/app/assets/javascripts/editable_components/dragula/dragula.min.js +1 -0
  15. data/app/assets/javascripts/editable_components/dropzone/CONTRIBUTING.md +78 -0
  16. data/app/assets/javascripts/editable_components/dropzone/LICENSE +12 -0
  17. data/app/assets/javascripts/editable_components/dropzone/README.md +134 -0
  18. data/app/assets/javascripts/editable_components/dropzone/basic.css +39 -0
  19. data/app/assets/javascripts/editable_components/dropzone/dropzone-amd-module.js +1782 -0
  20. data/app/assets/javascripts/editable_components/dropzone/dropzone.css +388 -0
  21. data/app/assets/javascripts/editable_components/dropzone/dropzone.js +1767 -0
  22. data/app/assets/javascripts/editable_components/dropzone/min/basic.min.css +1 -0
  23. data/app/assets/javascripts/editable_components/dropzone/min/dropzone-amd-module.min.js +2 -0
  24. data/app/assets/javascripts/editable_components/dropzone/min/dropzone.min.css +1 -0
  25. data/app/assets/javascripts/editable_components/dropzone/min/dropzone.min.js +2 -0
  26. data/app/assets/javascripts/editable_components/main.js +280 -0
  27. data/app/assets/javascripts/editable_components/medium-editor/API.md +520 -0
  28. data/app/assets/javascripts/editable_components/medium-editor/CHANGES.md +1043 -0
  29. data/app/assets/javascripts/editable_components/medium-editor/CODE_OF_CONDUCT.md +13 -0
  30. data/app/assets/javascripts/editable_components/medium-editor/CONTRIBUTING.md +56 -0
  31. data/app/assets/javascripts/editable_components/medium-editor/CUSTOM-EVENTS.md +223 -0
  32. data/app/assets/javascripts/editable_components/medium-editor/LICENSE +36 -0
  33. data/app/assets/javascripts/editable_components/medium-editor/MAINTAINERS.md +33 -0
  34. data/app/assets/javascripts/editable_components/medium-editor/OPTIONS.md +663 -0
  35. data/app/assets/javascripts/editable_components/medium-editor/README.md +725 -0
  36. data/app/assets/javascripts/editable_components/medium-editor/UPGRADE-5.md +146 -0
  37. data/app/assets/javascripts/editable_components/medium-editor/medium-editor.css +230 -0
  38. data/app/assets/javascripts/editable_components/medium-editor/medium-editor.js +7876 -0
  39. data/app/assets/javascripts/editable_components/medium-editor/medium-editor.min.css +1 -0
  40. data/app/assets/javascripts/editable_components/medium-editor/medium-editor.min.js +4 -0
  41. data/app/assets/javascripts/editable_components/medium-editor/themes/beagle.css +78 -0
  42. data/app/assets/javascripts/editable_components/medium-editor/themes/beagle.min.css +1 -0
  43. data/app/assets/javascripts/editable_components/medium-editor/themes/bootstrap.css +67 -0
  44. data/app/assets/javascripts/editable_components/medium-editor/themes/bootstrap.min.css +1 -0
  45. data/app/assets/javascripts/editable_components/medium-editor/themes/default.css +63 -0
  46. data/app/assets/javascripts/editable_components/medium-editor/themes/default.min.css +1 -0
  47. data/app/assets/javascripts/editable_components/medium-editor/themes/flat.css +58 -0
  48. data/app/assets/javascripts/editable_components/medium-editor/themes/flat.min.css +1 -0
  49. data/app/assets/javascripts/editable_components/medium-editor/themes/mani.css +57 -0
  50. data/app/assets/javascripts/editable_components/medium-editor/themes/mani.min.css +1 -0
  51. data/app/assets/javascripts/editable_components/medium-editor/themes/roman.css +58 -0
  52. data/app/assets/javascripts/editable_components/medium-editor/themes/roman.min.css +1 -0
  53. data/app/assets/javascripts/editable_components/medium-editor/themes/tim.css +67 -0
  54. data/app/assets/javascripts/editable_components/medium-editor/themes/tim.min.css +1 -0
  55. data/app/assets/javascripts/editable_components/sizzle/sizzle.js +2272 -0
  56. data/app/assets/javascripts/editable_components/sizzle/sizzle.min.js +3 -0
  57. data/app/assets/javascripts/editable_components/sizzle/sizzle.min.map +1 -0
  58. data/app/assets/javascripts/editable_components/vue/README.md +124 -0
  59. data/app/assets/javascripts/editable_components/vue/vue.common.js +9320 -0
  60. data/app/assets/javascripts/editable_components/vue/vue.common.min.js +7 -0
  61. data/app/assets/javascripts/editable_components/vue/vue.esm.js +9318 -0
  62. data/app/assets/javascripts/editable_components/vue/vue.js +9316 -0
  63. data/app/assets/javascripts/editable_components/vue/vue.min.js +8 -0
  64. data/app/assets/javascripts/editable_components/vue/vue.runtime.common.js +6831 -0
  65. data/app/assets/javascripts/editable_components/vue/vue.runtime.esm.js +6829 -0
  66. data/app/assets/javascripts/editable_components/vue/vue.runtime.js +6827 -0
  67. data/app/assets/javascripts/editable_components/vue/vue.runtime.min.js +7 -0
  68. data/app/assets/stylesheets/editable_components/application.sass +65 -0
  69. data/app/assets/stylesheets/editable_components/blaze/blaze.colors.min.css +1 -0
  70. data/app/assets/stylesheets/editable_components/blaze/blaze.min.css +1 -0
  71. data/app/assets/stylesheets/editable_components/blaze/components.addresses.min.css +1 -0
  72. data/app/assets/stylesheets/editable_components/blaze/components.alerts.min.css +1 -0
  73. data/app/assets/stylesheets/editable_components/blaze/components.avatars.min.css +1 -0
  74. data/app/assets/stylesheets/editable_components/blaze/components.badges.min.css +1 -0
  75. data/app/assets/stylesheets/editable_components/blaze/components.breadcrumbs.min.css +1 -0
  76. data/app/assets/stylesheets/editable_components/blaze/components.bubbles.min.css +1 -0
  77. data/app/assets/stylesheets/editable_components/blaze/components.buttons.min.css +1 -0
  78. data/app/assets/stylesheets/editable_components/blaze/components.calendars.min.css +1 -0
  79. data/app/assets/stylesheets/editable_components/blaze/components.cards.min.css +1 -0
  80. data/app/assets/stylesheets/editable_components/blaze/components.headings.min.css +1 -0
  81. data/app/assets/stylesheets/editable_components/blaze/components.hints.min.css +1 -0
  82. data/app/assets/stylesheets/editable_components/blaze/components.input-groups.min.css +1 -0
  83. data/app/assets/stylesheets/editable_components/blaze/components.inputs.min.css +1 -0
  84. data/app/assets/stylesheets/editable_components/blaze/components.links.min.css +1 -0
  85. data/app/assets/stylesheets/editable_components/blaze/components.lists.min.css +1 -0
  86. data/app/assets/stylesheets/editable_components/blaze/components.navs.min.css +1 -0
  87. data/app/assets/stylesheets/editable_components/blaze/components.overlays.min.css +1 -0
  88. data/app/assets/stylesheets/editable_components/blaze/components.pagination.min.css +1 -0
  89. data/app/assets/stylesheets/editable_components/blaze/components.progress.min.css +1 -0
  90. data/app/assets/stylesheets/editable_components/blaze/components.ranges.min.css +1 -0
  91. data/app/assets/stylesheets/editable_components/blaze/components.tables.min.css +1 -0
  92. data/app/assets/stylesheets/editable_components/blaze/components.tabs.min.css +1 -0
  93. data/app/assets/stylesheets/editable_components/blaze/components.tags.min.css +1 -0
  94. data/app/assets/stylesheets/editable_components/blaze/components.toggles.min.css +1 -0
  95. data/app/assets/stylesheets/editable_components/blaze/components.tooltips.min.css +1 -0
  96. data/app/assets/stylesheets/editable_components/blaze/components.trees.min.css +1 -0
  97. data/app/assets/stylesheets/editable_components/blaze/components.typography.min.css +1 -0
  98. data/app/assets/stylesheets/editable_components/blaze/generics.global.min.css +1 -0
  99. data/app/assets/stylesheets/editable_components/blaze/objects.containers.min.css +1 -0
  100. data/app/assets/stylesheets/editable_components/blaze/objects.drawers.min.css +1 -0
  101. data/app/assets/stylesheets/editable_components/blaze/objects.forms.min.css +1 -0
  102. data/app/assets/stylesheets/editable_components/blaze/objects.grid.min.css +1 -0
  103. data/app/assets/stylesheets/editable_components/blaze/objects.grid.responsive.min.css +1 -0
  104. data/app/assets/stylesheets/editable_components/blaze/objects.images.min.css +1 -0
  105. data/app/assets/stylesheets/editable_components/blaze/objects.media.min.css +1 -0
  106. data/app/assets/stylesheets/editable_components/blaze/objects.modals.min.css +1 -0
  107. data/app/assets/stylesheets/editable_components/blaze/objects.panels.min.css +1 -0
  108. data/app/assets/stylesheets/editable_components/blaze/themes/blaze.example.min.css +1 -0
  109. data/app/assets/stylesheets/editable_components/blaze/utilities.alignment.min.css +1 -0
  110. data/app/assets/stylesheets/editable_components/blaze/utilities.boxing.min.css +1 -0
  111. data/app/assets/stylesheets/editable_components/blaze/utilities.elevation.min.css +1 -0
  112. data/app/assets/stylesheets/editable_components/blaze/utilities.sizes.min.css +1 -0
  113. data/app/assets/stylesheets/editable_components/dragula/dragula.css +22 -0
  114. data/app/assets/stylesheets/editable_components/dragula/dragula.js +908 -0
  115. data/app/assets/stylesheets/editable_components/dragula/dragula.min.css +1 -0
  116. data/app/assets/stylesheets/editable_components/dragula/dragula.min.js +1 -0
  117. data/app/assets/stylesheets/editable_components/main.sass +225 -0
  118. data/app/assets/stylesheets/editable_components/medium-editor/API.md +520 -0
  119. data/app/assets/stylesheets/editable_components/medium-editor/CHANGES.md +1043 -0
  120. data/app/assets/stylesheets/editable_components/medium-editor/CODE_OF_CONDUCT.md +13 -0
  121. data/app/assets/stylesheets/editable_components/medium-editor/CONTRIBUTING.md +56 -0
  122. data/app/assets/stylesheets/editable_components/medium-editor/CUSTOM-EVENTS.md +223 -0
  123. data/app/assets/stylesheets/editable_components/medium-editor/LICENSE +36 -0
  124. data/app/assets/stylesheets/editable_components/medium-editor/MAINTAINERS.md +33 -0
  125. data/app/assets/stylesheets/editable_components/medium-editor/OPTIONS.md +663 -0
  126. data/app/assets/stylesheets/editable_components/medium-editor/README.md +725 -0
  127. data/app/assets/stylesheets/editable_components/medium-editor/UPGRADE-5.md +146 -0
  128. data/app/assets/stylesheets/editable_components/medium-editor/medium-editor.css +230 -0
  129. data/app/assets/stylesheets/editable_components/medium-editor/medium-editor.js +7876 -0
  130. data/app/assets/stylesheets/editable_components/medium-editor/medium-editor.min.css +1 -0
  131. data/app/assets/stylesheets/editable_components/medium-editor/medium-editor.min.js +4 -0
  132. data/app/assets/stylesheets/editable_components/medium-editor/themes/beagle.css +78 -0
  133. data/app/assets/stylesheets/editable_components/medium-editor/themes/beagle.min.css +1 -0
  134. data/app/assets/stylesheets/editable_components/medium-editor/themes/bootstrap.css +67 -0
  135. data/app/assets/stylesheets/editable_components/medium-editor/themes/bootstrap.min.css +1 -0
  136. data/app/assets/stylesheets/editable_components/medium-editor/themes/default.css +63 -0
  137. data/app/assets/stylesheets/editable_components/medium-editor/themes/default.min.css +1 -0
  138. data/app/assets/stylesheets/editable_components/medium-editor/themes/flat.css +58 -0
  139. data/app/assets/stylesheets/editable_components/medium-editor/themes/flat.min.css +1 -0
  140. data/app/assets/stylesheets/editable_components/medium-editor/themes/mani.css +57 -0
  141. data/app/assets/stylesheets/editable_components/medium-editor/themes/mani.min.css +1 -0
  142. data/app/assets/stylesheets/editable_components/medium-editor/themes/roman.css +58 -0
  143. data/app/assets/stylesheets/editable_components/medium-editor/themes/roman.min.css +1 -0
  144. data/app/assets/stylesheets/editable_components/medium-editor/themes/tim.css +67 -0
  145. data/app/assets/stylesheets/editable_components/medium-editor/themes/tim.min.css +1 -0
  146. data/app/controllers/editable_components/blocks_controller.rb +36 -0
  147. data/app/helpers/editable_components/application_helper.rb +4 -0
  148. data/app/jobs/editable_components/application_job.rb +4 -0
  149. data/app/mailers/editable_components/application_mailer.rb +6 -0
  150. data/app/models/editable_components/application_record.rb +5 -0
  151. data/app/models/editable_components/block.rb +176 -0
  152. data/app/models/editable_components/concerns/editable.rb +34 -0
  153. data/app/models/editable_components/item.rb +50 -0
  154. data/app/models/editable_components/item_boolean.rb +23 -0
  155. data/app/models/editable_components/item_datetime.rb +14 -0
  156. data/app/models/editable_components/item_file.rb +46 -0
  157. data/app/models/editable_components/item_float.rb +23 -0
  158. data/app/models/editable_components/item_hash.rb +16 -0
  159. data/app/models/editable_components/item_integer.rb +23 -0
  160. data/app/models/editable_components/item_string.rb +29 -0
  161. data/app/models/editable_components/item_text.rb +19 -0
  162. data/app/views/editable_components/_admin_toolbar.html.erb +105 -0
  163. data/app/views/editable_components/_block.html.erb +6 -0
  164. data/app/views/editable_components/_block_image.html.erb +6 -0
  165. data/app/views/editable_components/_block_multi_text.html.erb +7 -0
  166. data/app/views/editable_components/_block_slide.html.erb +6 -0
  167. data/app/views/editable_components/_block_slider.html.erb +7 -0
  168. data/app/views/editable_components/_block_text.html.erb +5 -0
  169. data/app/views/editable_components/_block_text_with_image.html.erb +12 -0
  170. data/app/views/editable_components/_blocks.html.erb +12 -0
  171. data/config/initializers/editable_components.rb +72 -0
  172. data/config/routes.rb +4 -0
  173. data/db/migrate/20170414173603_create_editable_components_blocks.rb +18 -0
  174. data/db/migrate/20170414173610_create_editable_components_items.rb +11 -0
  175. data/db/migrate/20170414173611_add_items_booleans.rb +5 -0
  176. data/db/migrate/20170414173612_add_items_datetimes.rb +5 -0
  177. data/db/migrate/20170414173613_add_items_files.rb +5 -0
  178. data/db/migrate/20170414173614_add_items_floats.rb +5 -0
  179. data/db/migrate/20170414173615_add_items_hashes.rb +5 -0
  180. data/db/migrate/20170414173616_add_items_integers.rb +5 -0
  181. data/db/migrate/20170414173617_add_items_strings.rb +5 -0
  182. data/db/migrate/20170414173618_add_items_texts.rb +5 -0
  183. data/lib/data/img1.jpg +0 -0
  184. data/lib/editable_components.rb +87 -0
  185. data/lib/editable_components/engine.rb +21 -0
  186. data/lib/editable_components/version.rb +3 -0
  187. data/lib/tasks/editable_components_tasks.rake +4 -0
  188. metadata +264 -0
@@ -0,0 +1 @@
1
+ .medium-toolbar-arrow-under:after{border-color:#2f1e07 transparent transparent;top:60px}.medium-toolbar-arrow-over:before{border-color:transparent transparent #2f1e07}.medium-editor-toolbar{background-color:#2f1e07;border:1px solid #5b3a0e;border-radius:6px}.medium-editor-toolbar li button{background-color:transparent;border:none;border-right:1px solid #5b3a0e;box-sizing:border-box;color:#ffedd5;height:60px;min-width:60px;-webkit-transition:background-color .2s ease-in,color .2s ease-in;transition:background-color .2s ease-in,color .2s ease-in}.medium-editor-toolbar li .medium-editor-button-active,.medium-editor-toolbar li button:hover{background-color:#030200;color:#ffedd5}.medium-editor-toolbar li .medium-editor-button-first{border-bottom-left-radius:6px;border-top-left-radius:6px}.medium-editor-toolbar li .medium-editor-button-last{border-bottom-right-radius:6px;border-right:none;border-top-right-radius:6px}.medium-editor-toolbar-form{background:#2f1e07;border-radius:6px;color:#ffedd5}.medium-editor-toolbar-form .medium-editor-toolbar-input{background:#2f1e07;color:#ffedd5;height:60px}.medium-editor-toolbar-form .medium-editor-toolbar-input::-webkit-input-placeholder{color:#ffedd5;color:rgba(255,237,213,.8)}.medium-editor-toolbar-form .medium-editor-toolbar-input:-moz-placeholder{color:#ffedd5;color:rgba(255,237,213,.8)}.medium-editor-toolbar-form .medium-editor-toolbar-input::-moz-placeholder{color:#ffedd5;color:rgba(255,237,213,.8)}.medium-editor-toolbar-form .medium-editor-toolbar-input:-ms-input-placeholder{color:#ffedd5;color:rgba(255,237,213,.8)}.medium-editor-toolbar-form a{color:#ffedd5}.medium-editor-toolbar-anchor-preview{background:#2f1e07;border-radius:6px;color:#ffedd5}.medium-editor-placeholder:after{color:#5b3a0e}
@@ -0,0 +1,36 @@
1
+ module EditableComponents
2
+ class BlocksController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+
5
+ def publish
6
+ model = params[:container].camelcase.constantize rescue nil
7
+ if model && model.ancestors.include?( EditableComponents::Concerns::Editable )
8
+ container = model.find params[:container_id]
9
+ ver = EditableComponents.publish( container, params[:version] )
10
+ respond_to do |format|
11
+ # format.html { redirect_to page_path( @page, version: ver ), notice: "Version: #{ver}" }
12
+ format.html { redirect_back fallback_location: '/', notice: "Version: #{ver}" }
13
+ format.json { render json: { status: :ok }, status: :ok } # , location: container
14
+ end
15
+ end
16
+ # TODO: set errors if not a valid model
17
+ end
18
+
19
+ def update
20
+ model = params[:container].camelcase.constantize rescue nil
21
+ if model && model.ancestors.include?( EditableComponents::Concerns::Editable )
22
+ container = model.find params[:container_id]
23
+ respond_to do |format|
24
+ if EditableComponents.update( container, params )
25
+ format.html { redirect_back fallback_location: '/', notice: 'Saved.' }
26
+ format.json { render json: { status: :ok }, status: :ok } # , location: container
27
+ else
28
+ format.html { redirect_back fallback_location: '/', notice: container.errors.messages[:base].join( ' - ' ) }
29
+ format.json { render json: container.errors, status: :unprocessable_entity }
30
+ end
31
+ end
32
+ end
33
+ # TODO: set errors if not a valid model
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,4 @@
1
+ module EditableComponents
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module EditableComponents
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module EditableComponents
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module EditableComponents
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,176 @@
1
+ module EditableComponents
2
+ class Block < ApplicationRecord
3
+ EMPTY_DATA = OpenStruct.new( { data: '' } )
4
+
5
+ # --- fields options ----------------------------------------------------- #
6
+ serialize :options, JSON
7
+ serialize :validations, JSON
8
+
9
+ # --- relations ---------------------------------------------------------- #
10
+ belongs_to :parent, polymorphic: true
11
+ has_many :ec_blocks, as: :parent, foreign_key: 'parent_id', class_name: 'Block'
12
+ has_many :items
13
+ accepts_nested_attributes_for :ec_blocks, allow_destroy: true
14
+ accepts_nested_attributes_for :items
15
+
16
+ # --- hooks -------------------------------------------------------------- #
17
+ before_create :on_before_create
18
+
19
+ # --- scopes ------------------------------------------------------------- #
20
+ default_scope { order( position: :desc ) }
21
+ scope :published, -> { where( published: true ) unless EditableComponents::Engine.edit_mode }
22
+ scope :with_nested, -> { includes( :items, ec_blocks: :items ) }
23
+
24
+ # --- validations -------------------------------------------------------- #
25
+ validates_presence_of :block_type, :position
26
+
27
+ # --- misc --------------------------------------------------------------- #
28
+ amoeba do
29
+ enable
30
+ # customize( lambda { |original_obj, new_obj|
31
+ # original_obj.unit_pictures.each{|p| new_obj.unit_pictures.new(:data => File.open(p.data.file.path))}
32
+ # })
33
+ end
34
+
35
+ # after_validation :on_after_validation
36
+ #
37
+ # field :block_type, type: String, default: 'text'
38
+ # field :name, type: String, default: ''
39
+ # field :position, type: Integer, default: 0
40
+ # field :published, type: Mongoid::Boolean, default: true
41
+ # field :_init, type: Mongoid::Boolean, default: false
42
+ #
43
+ # embedded_in :parent, polymorphic: true
44
+ #
45
+ # embeds_many :ec_blocks, cascade_callbacks: true, order: :position.desc, class_name: 'EditableComponents::Block'
46
+ # embeds_many :items, cascade_callbacks: true, class_name: 'EditableComponents::Item'
47
+ #
48
+ # accepts_nested_attributes_for :ec_blocks, allow_destroy: true
49
+ # accepts_nested_attributes_for :items
50
+ #
51
+ # # scope :published, -> { where( published: true ) unless ApplicationController.edit_mode }
52
+
53
+ def attr_id
54
+ "#{self.class.to_s.split('::').last}-#{self.id}"
55
+ end
56
+
57
+ def children_type
58
+ EditableComponents.config[:ec_blocks][block_type.to_sym][:children_type]
59
+ end
60
+
61
+ def editable
62
+ Engine.edit_mode ? (
63
+ is_sub_block? ?
64
+ {
65
+ 'data-ec-sub-block': self.id,
66
+ 'data-ec-ct': self.block_type,
67
+ 'data-ec-position': self.position,
68
+ 'data-ec-pub': self.published
69
+ } :
70
+ {
71
+ 'data-ec-block': self.id,
72
+ 'data-ec-container': self.children_type,
73
+ 'data-ec-ct': self.block_type,
74
+ 'data-ec-pub': self.published
75
+ }
76
+ ).map { |k, v| "#{k}=\"#{v}\"" }.join( ' ' ).html_safe : ''
77
+ end
78
+
79
+ # Returns an item by name
80
+ def get( name )
81
+ unless @_items
82
+ @_items = {}
83
+ items.each { |item| @_items[item.name] = item }
84
+ end
85
+ @_items[name]
86
+ end
87
+
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
+ def has_parent?
116
+ parent.present?
117
+ end
118
+
119
+ def has_children?
120
+ ec_blocks.exists?
121
+ end
122
+
123
+ def is_sub_block?
124
+ parent.present? && parent_type == 'EditableComponents::Block'
125
+ end
126
+
127
+ 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
138
+ end
139
+ end
140
+ init
141
+ end
142
+ end
143
+
144
+ def props
145
+ pieces = {}
146
+
147
+ Item::item_types.each do |type|
148
+ pieces[type.pluralize.to_sym] = []
149
+ end
150
+ items.each do |item| # TODO: improve me
151
+ pieces[item.class.type_name.pluralize.to_sym].push item
152
+ end
153
+ Item::item_types.each do |type|
154
+ pieces[type.to_sym] = pieces[type.pluralize.to_sym].any? ? pieces[type.pluralize.to_sym].first : nil # EMPTY_DATA - empty Item per sti class?
155
+ end
156
+
157
+ # pieces = {
158
+ # images: items.select { |item| item.type == ItemImage.to_s },
159
+ # integers: items.select { |item| item.type == ItemInteger.to_s },
160
+ # strings: items.select { |item| item.type == ItemString.to_s },
161
+ # texts: items.select { |item| item.type == ItemText.to_s },
162
+ # }
163
+
164
+ # pieces[:image] = pieces[:images].any? ? pieces[:images].first : EMPTY_DATA
165
+ # pieces[:integers] = pieces[:integers].any? ? pieces[:integers].first : EMPTY_DATA
166
+ # pieces[:string] = pieces[:strings].any? ? pieces[:strings].first : EMPTY_DATA
167
+ # pieces[:text] = pieces[:texts].any? ? pieces[:texts].first : EMPTY_DATA
168
+
169
+ OpenStruct.new( pieces )
170
+ end
171
+
172
+ def self.block_types
173
+ @@block_types ||= EditableComponents.config[:ec_blocks].keys
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,34 @@
1
+ module EditableComponents
2
+ module Concerns
3
+ module Editable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ # embeds_many :ec_blocks, as: :parent, cascade_callbacks: true, order: :position.desc, class_name: 'EditableComponents::Block'
8
+ has_many :ec_blocks, as: :parent, foreign_key: 'parent_id', class_name: Block.to_s
9
+ accepts_nested_attributes_for :ec_blocks, allow_destroy: true
10
+
11
+ def create_block( type = :text, params = {} )
12
+ block = Block.new( _init: true, block_type: type )
13
+ block.options = params[:options] if params[:options]
14
+ block.validations = params[:validations] if params[:validations]
15
+ ec_blocks << block
16
+ block
17
+ end
18
+
19
+ def current_blocks( version = 0 )
20
+ return @current_blocks if @current_blocks
21
+ version = 0 unless EditableComponents::Engine.edit_mode # no admin = only current version
22
+ @current_blocks = ec_blocks.where( version: version.to_i ).with_nested.published
23
+ end
24
+
25
+ def get_block( name, version = 0 )
26
+ current_blocks( version ).each do |block|
27
+ return block if block.name == name
28
+ end
29
+ nil
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,50 @@
1
+ module EditableComponents
2
+ class Item < ApplicationRecord
3
+ # field :data, type: String
4
+
5
+ # embedded_in :ec_blocks
6
+
7
+ belongs_to :block
8
+
9
+ def attr_id
10
+ "#{self.class_name}-#{self.id}"
11
+ end
12
+
13
+ def class_name
14
+ self.class.to_s.split('::').last
15
+ end
16
+
17
+ def editable
18
+ Engine.edit_mode ? " data-ec-item=\"#{self.id}\" data-ec-input=\"#{self.opt_input}\" data-ec-type=\"#{self.class_name}\"".html_safe : ''
19
+ end
20
+
21
+ def opt_input
22
+ if self.block.options[self.name] && self.block.options[self.name]['input']
23
+ self.block.options[self.name]['input'].to_s
24
+ elsif config[:input]
25
+ config[:input].to_s
26
+ else
27
+ ''
28
+ end
29
+ end
30
+
31
+ def to_s
32
+ self.data
33
+ end
34
+
35
+ def update_data( value )
36
+ self.data = value
37
+ self.save
38
+ end
39
+
40
+ def self.item_types
41
+ @@item_types ||= EditableComponents.config[:items].keys.map &:to_s
42
+ end
43
+
44
+ protected
45
+
46
+ def config
47
+ @config ||= EditableComponents.config[:items][self.class::type_name.to_sym] ? EditableComponents.config[:items][self.class::type_name.to_sym] : {}
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,23 @@
1
+ module EditableComponents
2
+ class ItemBoolean < Item
3
+ alias_attribute :data, :data_boolean
4
+
5
+ def init
6
+ self.data = 0
7
+ self
8
+ end
9
+
10
+ def update_data( value )
11
+ self.data = ( value == 'true' ) ? 1 : 0
12
+ self.save
13
+ end
14
+
15
+ def to_s
16
+ self.data > 0 ? 'true' : 'false'
17
+ end
18
+
19
+ def self.type_name
20
+ 'boolean'
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ module EditableComponents
2
+ class ItemDatetime < Item
3
+ alias_attribute :data, :data_datetime
4
+
5
+ def init
6
+ self.data = Time.now
7
+ self
8
+ end
9
+
10
+ def self.type_name
11
+ 'datetime'
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,46 @@
1
+ module EditableComponents
2
+ class ItemFile < Item
3
+ # has_attached_file :data_string
4
+ # validates_attachment_content_type :data_string, content_type: ['image/jpg', 'image/jpeg', 'image/png', 'image/gif']
5
+
6
+ # include Mongoid::Paperclip
7
+ # has_mongoid_attached_file :data
8
+ # validates_attachment_content_type :data, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
9
+
10
+ mount_uploader :data_file, ::FileUploader
11
+
12
+ alias_attribute :data, :data_file
13
+
14
+ def editable
15
+ Engine.edit_mode ? { 'data-ec-item': self.id, 'data-ec-input': self.opt_input, 'data-ec-type': self.class_name, 'data-ec-block': self.block_id } : {}
16
+ end
17
+
18
+ def init
19
+ self.data_file = File.open( EditableComponents::Engine.root.join( 'lib', 'data', 'img1.jpg' ) )
20
+ self
21
+ end
22
+
23
+ def self.type_name
24
+ 'file'
25
+ end
26
+
27
+ # before_validation :on_before_validation
28
+ #
29
+ # def on_before_validation
30
+ # self.data = File.open( 'rails/editable_components_test/public/img/img1.jpg' )
31
+ # # binding.pry
32
+ # end
33
+
34
+ # before_save :on_before_save
35
+ # before_validation :on_before_validation
36
+ # before_create :on_before_create
37
+ # before_update :on_before_update
38
+ # before_upsert :on_before_upsert
39
+ #
40
+ # def on_before_save; p '>>> before_save'; end
41
+ # def on_before_validation; p '>>> before_validation'; end
42
+ # def on_before_create; p '>>> before_create'; end
43
+ # def on_before_update; p '>>> before_update'; end
44
+ # def on_before_upsert; p '>>> before_upsert'; end
45
+ end
46
+ end
@@ -0,0 +1,23 @@
1
+ module EditableComponents
2
+ class ItemFloat < Item
3
+ alias_attribute :data, :data_float
4
+
5
+ def init
6
+ self.data = 0
7
+ self
8
+ end
9
+
10
+ def update_data( value )
11
+ self.data = value.to_f
12
+ self.save
13
+ end
14
+
15
+ def to_s
16
+ self.data.to_s
17
+ end
18
+
19
+ def self.type_name
20
+ 'float'
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ module EditableComponents
2
+ class ItemHash < Item
3
+ alias_attribute :data, :data_hash
4
+
5
+ serialize :data_hash, JSON
6
+
7
+ def init
8
+ self.data = {}
9
+ self
10
+ end
11
+
12
+ def self.type_name
13
+ 'hash'
14
+ end
15
+ end
16
+ end