diff --git a/Gemfile.lock b/Gemfile.lock index b2aa04fc..9fe60a56 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -97,6 +97,8 @@ GEM coderay (1.1.2) concurrent-ruby (1.0.5) crass (1.0.4) + cypress-on-rails (1.1.1) + rack database_cleaner (1.7.0) devise (4.4.3) bcrypt (~> 3.0) @@ -338,6 +340,7 @@ DEPENDENCIES binda! bullet (>= 5.6, < 6) capybara (>= 2.14, < 3) + cypress-on-rails (~> 1.1) database_cleaner (>= 1.6, < 2) factory_bot_rails (~> 4.8) generator_spec (~> 0.9.4) @@ -356,4 +359,4 @@ DEPENDENCIES yard-activesupport-concern (~> 0.0.1, < 0.1) BUNDLED WITH - 1.16.2 + 1.16.6 diff --git a/app/assets/stylesheets/binda/components/form_item.scss b/app/assets/stylesheets/binda/components/form_item.scss index 9fa46fad..67c012da 100644 --- a/app/assets/stylesheets/binda/components/form_item.scss +++ b/app/assets/stylesheets/binda/components/form_item.scss @@ -8,6 +8,15 @@ padding: 12px; } +.form-item--sixth-size { + display: inline-block; + width: calc(16.6% - 3px); + + .form-group { + border-top: none !important; + } +} + .form-item--half-size { // OLD SOLUTION (nicer, but can't be used with max-height=0 and overflow-y=hidden) // position: relative; diff --git a/app/controllers/binda/boards_controller.rb b/app/controllers/binda/boards_controller.rb index aa77a522..fefe4393 100644 --- a/app/controllers/binda/boards_controller.rb +++ b/app/controllers/binda/boards_controller.rb @@ -18,6 +18,7 @@ def update if @board.update(board_params) redirect_to structure_board_path(@structure.slug, @board.slug), notice: 'Setting was successfully updated.' else + @fields_errors = get_errors(@board) render :edit, flash: { alert: @board.errors } end end @@ -86,5 +87,6 @@ def sort_repeaters_by(repeaters) Repeater.find(id).update_column('position', i+1) end end + end end diff --git a/app/controllers/binda/components_controller.rb b/app/controllers/binda/components_controller.rb index 1c3f9cb2..81d62728 100644 --- a/app/controllers/binda/components_controller.rb +++ b/app/controllers/binda/components_controller.rb @@ -46,6 +46,7 @@ def update if @component.update(component_params) redirect_to structure_component_path(@structure.slug, @component.slug), notice: "#{ @structure.name.capitalize } was successfully updated." else + @fields_errors = get_errors(@component) render :edit, flash: { alert: @component.errors } end end diff --git a/app/controllers/binda/field_groups_controller.rb b/app/controllers/binda/field_groups_controller.rb index 556771c8..265ec450 100644 --- a/app/controllers/binda/field_groups_controller.rb +++ b/app/controllers/binda/field_groups_controller.rb @@ -95,7 +95,7 @@ def set_field_group def field_group_params params.require(:field_group).permit( :name, :slug, :description, :position, :layout, :structure_id, field_settings_attributes: [ - :id, :field_group_id, :field_setting_id, :name, :slug, :description, :field_type, :position, :required, :read_only, :default_text, :ancestry, :default_choice_id, :allow_null, accepted_structure_ids: [], choices: [], choices_attributes: [ + :id, :field_group_id, :field_setting_id, :name, :slug, :description, :field_type, :position, :required, :read_only, :has_preview, :default_text, :ancestry, :default_choice_id, :allow_null, accepted_structure_ids: [], choices: [], choices_attributes: [ :id, :field_setting_id, :label, :value ] ] @@ -105,7 +105,7 @@ def field_group_params def new_params params.require(:field_group).permit( new_field_settings: [ - :id, :field_group_id, :field_setting_id, :name, :slug, :description, :field_type, :position, :required, :read_only, :ancestry, :default_choice_id, :allow_null, choices: [] + :id, :field_group_id, :field_setting_id, :name, :slug, :description, :field_type, :position, :required, :read_only, :has_preview, :ancestry, :default_choice_id, :allow_null, choices: [] ], new_choices: [ :id, :field_setting_id, :label, :value diff --git a/app/controllers/binda/field_settings_controller.rb b/app/controllers/binda/field_settings_controller.rb index 4a2cbff7..20885c46 100644 --- a/app/controllers/binda/field_settings_controller.rb +++ b/app/controllers/binda/field_settings_controller.rb @@ -72,7 +72,7 @@ def set_field_setting # Only allow a trusted parameter "white list" through. def field_setting_params - params.require(:field_setting).permit(:name, :slug, :description, :position, :required, :default_text, :field_group_id, :field_type ) + params.require(:field_setting).permit(:name, :slug, :description, :position, :preview, :required, :default_text, :field_group_id, :field_type ) end end end diff --git a/app/controllers/concerns/binda/fieldable_helpers.rb b/app/controllers/concerns/binda/fieldable_helpers.rb index 324fefb0..cec9f0e9 100644 --- a/app/controllers/concerns/binda/fieldable_helpers.rb +++ b/app/controllers/concerns/binda/fieldable_helpers.rb @@ -1,6 +1,6 @@ module Binda module FieldableHelpers - + extend ActiveSupport::Concern # Only allow a trusted parameter "white list" through. @@ -173,5 +173,28 @@ def return_audio_details asset def bytes_to_megabytes bytes (bytes.to_f / 1.megabyte).round(2) end + + # When a field belonging to a component has a error, this method + # will store the class name and id. Useful to check the status of + # a field on the front end application. + # + # @return {array} Array of objects containing class name and id of the fields with errors + def get_errors(instance) + fields_errors = {} + instance.errors.details.keys.each do |key| + instance.errors.details[key].each do |obj| + obj[:value].each do |obj2| + newKey = "#{obj2.class.name.parameterize}--#{obj2.id.to_s}" # eg: binda-image--33 + fields_errors[newKey] = { + class: obj2.class.name, + id: obj2.id, + message: obj2.errors.full_messages.join('. ') + } + end + end + end + fields_errors + end + end end \ No newline at end of file diff --git a/app/helpers/binda/application_helper.rb b/app/helpers/binda/application_helper.rb index 6a9734e3..ee815e13 100644 --- a/app/helpers/binda/application_helper.rb +++ b/app/helpers/binda/application_helper.rb @@ -19,7 +19,14 @@ def is_devise_controller def get_form_manage_user_url return manage_users_path if action_name == 'new' return manage_user_path if action_name == 'edit' - end + end + + def check_field_errors(instance, attribute) + key = "#{instance.class.name.parameterize}--#{instance.id.to_s}" + unless @fields_errors[key].nil? + instance.errors.add(attribute, @fields_errors[key][:message]); + end + end end end diff --git a/app/models/binda/asset.rb b/app/models/binda/asset.rb index d9f93d9a..45fc07c5 100644 --- a/app/models/binda/asset.rb +++ b/app/models/binda/asset.rb @@ -4,6 +4,6 @@ module Binda class Asset < ApplicationRecord include Fields - + include FieldReadonly end end \ No newline at end of file diff --git a/app/models/binda/audio.rb b/app/models/binda/audio.rb index 62c728ad..7888bfa3 100644 --- a/app/models/binda/audio.rb +++ b/app/models/binda/audio.rb @@ -3,6 +3,5 @@ module Binda class Audio < Asset mount_uploader :audio, AudioUploader - - end + end end \ No newline at end of file diff --git a/app/models/binda/image.rb b/app/models/binda/image.rb index 4d068253..e763b1fb 100644 --- a/app/models/binda/image.rb +++ b/app/models/binda/image.rb @@ -18,7 +18,7 @@ def register_details register_details_of(file) end end - + # Register image details # # This method is used by register_details in a rake task diff --git a/app/models/binda/selection.rb b/app/models/binda/selection.rb index 09d24765..00e9e64e 100644 --- a/app/models/binda/selection.rb +++ b/app/models/binda/selection.rb @@ -134,6 +134,7 @@ class Selection < ApplicationRecord include Fields include FieldUniqueness + include FieldReadonly has_and_belongs_to_many :choices validate :has_choices diff --git a/app/models/binda/text.rb b/app/models/binda/text.rb index dfe8b56d..efa536f3 100644 --- a/app/models/binda/text.rb +++ b/app/models/binda/text.rb @@ -6,9 +6,10 @@ module Binda # this field is represented by a WYSIWYG. But this is just a admin panel convention: the class can infact store # a simple string of text as well. class Text < ApplicationRecord - + include Fields include FieldUniqueness - + include FieldReadonly + end end diff --git a/app/models/concerns/binda/field_readonly.rb b/app/models/concerns/binda/field_readonly.rb new file mode 100644 index 00000000..cdabb981 --- /dev/null +++ b/app/models/concerns/binda/field_readonly.rb @@ -0,0 +1,31 @@ +module Binda + module FieldReadonly + + extend ActiveSupport::Concern + + included do + validate :is_read_only + end + + def is_read_only + field_setting = self.field_setting + if field_setting.read_only? + # check if content is changed + # load previous db instance + db_instance = "Binda::#{field_setting.field_type.classify}".constantize.find_by( + fieldable_id: self.fieldable_id, fieldable_type: self.fieldable_type, field_setting_id: field_setting.id ) + + # check if active record instance you want to save is different + # generate an error if it is + # else do nothing + if self.persisted? && db_instance.attributes != self.attributes + errors.add(:base, I18n.t("binda.readonly_validation", { + arg1: self.class.name, + arg2: self.field_setting.name, + arg3: self.id + })) + end + end + end + end +end \ No newline at end of file diff --git a/app/models/concerns/binda/fieldable_associations.rb b/app/models/concerns/binda/fieldable_associations.rb index d6ea6aec..20fc99ca 100644 --- a/app/models/concerns/binda/fieldable_associations.rb +++ b/app/models/concerns/binda/fieldable_associations.rb @@ -127,9 +127,9 @@ def generate_fields end # If this is a repeater else - self.field_setting.children.each do |field_setting| + self.field_setting.children.each do |field_setting| "Binda::#{field_setting.field_type.classify}".constantize.find_or_create_by!( - fieldable_id: self.id, fieldable_type: self.class.name, field_setting_id: field_setting.id ) + fieldable_id: self.id, fieldable_type: self.class.name, field_setting_id: field_setting.id ) end end end diff --git a/app/models/concerns/binda/fields.rb b/app/models/concerns/binda/fields.rb index 3720ac3e..0c512168 100644 --- a/app/models/concerns/binda/fields.rb +++ b/app/models/concerns/binda/fields.rb @@ -14,8 +14,9 @@ module Fields validates :field_setting, presence: true validates :fieldable_id, presence: true - validates :fieldable_type, presence: true + validates :fieldable_type, presence: true + include ActiveModel::Validations end - end end + diff --git a/app/views/binda/components/edit.html.erb b/app/views/binda/components/edit.html.erb index 8ef372f6..1a51c7ad 100644 --- a/app/views/binda/components/edit.html.erb +++ b/app/views/binda/components/edit.html.erb @@ -3,7 +3,6 @@ <%= @structure.name.humanize.split.map(&:capitalize).join(' ') %> <% end %> - <% content_for :header do %>