From 4123934ab4fe727487d66e79d0206bd0733a830b Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Fri, 23 Mar 2018 12:24:23 +0100 Subject: [PATCH 1/9] ADD svg uploader --- Gemfile.lock | 32 +++++----- app/models/binda/binda.rb | 7 +++ app/models/binda/svg_image.rb | 7 +++ app/uploaders/binda/svg_uploader.rb | 60 +++++++++++++++++++ db/migrate/20180323112252_add_svg_to_asset.rb | 5 ++ spec/models/binda/svg_image_spec.rb | 7 +++ 6 files changed, 102 insertions(+), 16 deletions(-) create mode 100644 app/models/binda/binda.rb create mode 100644 app/models/binda/svg_image.rb create mode 100644 app/uploaders/binda/svg_uploader.rb create mode 100644 db/migrate/20180323112252_add_svg_to_asset.rb create mode 100644 spec/models/binda/svg_image_spec.rb diff --git a/Gemfile.lock b/Gemfile.lock index 1d5c2717..37849ebb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -74,7 +74,7 @@ GEM sass (~> 3.4) thor (~> 0.19) builder (3.2.3) - bullet (5.7.3) + bullet (5.7.5) activesupport (>= 3.0.0) uniform_notifier (~> 1.11.0) capybara (2.18.0) @@ -88,22 +88,22 @@ GEM activemodel (>= 4.0.0) activesupport (>= 4.0.0) mime-types (>= 1.16) - childprocess (0.8.0) + childprocess (0.9.0) ffi (~> 1.0, >= 1.0.11) coderay (1.1.2) concurrent-ruby (1.0.5) crass (1.0.3) database_cleaner (1.6.2) - devise (4.4.1) + devise (4.4.3) bcrypt (~> 3.0) orm_adapter (~> 0.1) - railties (>= 4.1.0, < 5.2) + railties (>= 4.1.0, < 6.0) responders warden (~> 1.2.3) devise-i18n (1.6.1) devise (>= 4.4) diff-lcs (1.3) - docile (1.1.5) + docile (1.3.0) erubi (1.7.1) ethon (0.11.0) ffi (>= 1.3.0) @@ -161,7 +161,7 @@ GEM rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) ruby_dep (~> 1.2) - loofah (2.2.0) + loofah (2.2.2) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.0) @@ -174,18 +174,18 @@ GEM mini_mime (1.0.0) mini_portile2 (2.3.0) minitest (5.11.3) - mry (0.53.0.0) + mry (0.54.0.0) rubocop (>= 0.41.0) multi_json (1.13.1) multipart-post (2.0.0) net-http-persistent (2.9.4) net-http-pipeline (1.0.1) - nio4r (2.2.0) + nio4r (2.3.0) nokogiri (1.8.2) mini_portile2 (~> 2.3.0) orm_adapter (0.5.0) parallel (1.12.1) - parser (2.5.0.3) + parser (2.5.0.4) ast (~> 2.4.0) pg (0.21.0) powerpack (0.1.1) @@ -215,8 +215,8 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.0.3) - loofah (~> 2.0) + rails-html-sanitizer (1.0.4) + loofah (~> 2.2, >= 2.2.2) railties (5.1.5) actionpack (= 5.1.5) activesupport (= 5.1.5) @@ -224,7 +224,7 @@ GEM rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rainbow (3.0.0) - rake (12.3.0) + rake (12.3.1) rb-fsevent (0.10.3) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) @@ -259,7 +259,7 @@ GEM ruby-progressbar (1.9.0) ruby_dep (1.5.0) rubyzip (1.2.1) - sass (3.5.5) + sass (3.5.6) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) @@ -270,14 +270,14 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - selenium-webdriver (3.10.0) + selenium-webdriver (3.11.0) childprocess (~> 0.5) rubyzip (~> 1.2) simple_form (3.5.1) actionpack (> 4, < 5.2) activemodel (> 4, < 5.2) - simplecov (0.15.1) - docile (~> 1.1.0) + simplecov (0.16.1) + docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) diff --git a/app/models/binda/binda.rb b/app/models/binda/binda.rb new file mode 100644 index 00000000..229de643 --- /dev/null +++ b/app/models/binda/binda.rb @@ -0,0 +1,7 @@ +module Binda + module Binda + def self.table_name_prefix + 'binda_binda_' + end + end +end diff --git a/app/models/binda/svg_image.rb b/app/models/binda/svg_image.rb new file mode 100644 index 00000000..1ef91af7 --- /dev/null +++ b/app/models/binda/svg_image.rb @@ -0,0 +1,7 @@ +module Binda + class SvgImage < Asset + + mount_uploader :svg, SvgUploader + + end +end diff --git a/app/uploaders/binda/svg_uploader.rb b/app/uploaders/binda/svg_uploader.rb new file mode 100644 index 00000000..f6df47dd --- /dev/null +++ b/app/uploaders/binda/svg_uploader.rb @@ -0,0 +1,60 @@ +class SvgUploader < CarrierWave::Uploader::Base + # Include RMagick or MiniMagick support: + # include CarrierWave::RMagick + # include CarrierWave::MiniMagick + + # Choose what kind of storage to use for this uploader: + # storage :file + # storage :fog + + # Override the directory where uploaded files will be stored. + # This is a sensible default for uploaders that are meant to be mounted: + def store_dir + "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" + end + + process :register_details + + def register_details + if file && model + model.content_type = file.content_type if file.content_type + model.file_size = file.size + end + end + + # Provide a default URL as a default if there hasn't been a file uploaded: + # def default_url(*args) + # # For Rails 3.1+ asset pipeline compatibility: + # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) + # + # "/images/fallback/" + [version_name, "default.png"].compact.join('_') + # end + + # Process files as they are uploaded: + # process scale: [200, 300] + # + # def scale(width, height) + # # do something + # end + + # Create different versions of your uploaded files: + # version :thumb do + # process resize_to_fit: [50, 50] + # end + + + # Add a white list of extensions which are allowed to be uploaded. + # For images you might use something like this: + # def extension_whitelist + # %w(jpg jpeg gif png) + # end + def extension_whitelist + %w(svg) + end + + # Override the filename of the uploaded files: + # Avoid using model.id or version_name here, see uploader/store.rb for details. + # def filename + # "something.jpg" if original_filename + # end +end diff --git a/db/migrate/20180323112252_add_svg_to_asset.rb b/db/migrate/20180323112252_add_svg_to_asset.rb new file mode 100644 index 00000000..42ce0ee6 --- /dev/null +++ b/db/migrate/20180323112252_add_svg_to_asset.rb @@ -0,0 +1,5 @@ +class AddSvgToAsset < ActiveRecord::Migration[5.1] + def change + add_column :binda_assets, :svg, :string + end +end diff --git a/spec/models/binda/svg_image_spec.rb b/spec/models/binda/svg_image_spec.rb new file mode 100644 index 00000000..b8e0b1f4 --- /dev/null +++ b/spec/models/binda/svg_image_spec.rb @@ -0,0 +1,7 @@ +require 'rails_helper' + +module Binda + RSpec.describe SvgImage, type: :model do + pending "add some examples to (or delete) #{__FILE__}" + end +end From 83bdb87fc9f647b21deb54464ef3eb71b5199cdd Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Fri, 23 Mar 2018 12:39:55 +0100 Subject: [PATCH 2/9] ADD svg_migration and FIX audio_test --- db/migrate/20180323112252_add_svg_to_asset.rb | 2 +- spec/models/binda/audio_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/db/migrate/20180323112252_add_svg_to_asset.rb b/db/migrate/20180323112252_add_svg_to_asset.rb index 42ce0ee6..dd7b3795 100644 --- a/db/migrate/20180323112252_add_svg_to_asset.rb +++ b/db/migrate/20180323112252_add_svg_to_asset.rb @@ -1,5 +1,5 @@ class AddSvgToAsset < ActiveRecord::Migration[5.1] def change - add_column :binda_assets, :svg, :string + add_column :binda_assets, :svg, :string end end diff --git a/spec/models/binda/audio_spec.rb b/spec/models/binda/audio_spec.rb index 92c7e921..78cf39a2 100644 --- a/spec/models/binda/audio_spec.rb +++ b/spec/models/binda/audio_spec.rb @@ -6,7 +6,7 @@ module Binda include CarrierWave::Test::Matchers before(:context) do - Binda::Audio::AudioUploader.enable_processing = true + Audio::AudioUploader.enable_processing = true end before(:example) do @@ -15,7 +15,7 @@ module Binda end after(:context) do - Binda::Audio::AudioUploader.enable_processing = false + Audio::AudioUploader.enable_processing = false end it "stores content_type and file size" do From 26c22c2ced3d5c19376778e0b1481706321d7a37 Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Fri, 23 Mar 2018 13:48:27 +0100 Subject: [PATCH 3/9] ADD test for svgs --- app/models/binda/field_setting.rb | 14 +- app/models/binda/{svg_image.rb => svg.rb} | 2 +- .../concerns/binda/fieldable_associations.rb | 6 +- app/uploaders/binda/svg_uploader.rb | 120 +++++++++--------- spec/factories/field_settings.rb | 4 + spec/factories/svg.rb | 13 ++ spec/models/binda/svg_image_spec.rb | 7 - spec/models/binda/svg_spec.rb | 30 +++++ spec/support/test-svg.svg | 1 + 9 files changed, 122 insertions(+), 75 deletions(-) rename app/models/binda/{svg_image.rb => svg.rb} (70%) create mode 100644 spec/factories/svg.rb delete mode 100644 spec/models/binda/svg_image_spec.rb create mode 100644 spec/models/binda/svg_spec.rb create mode 100644 spec/support/test-svg.svg diff --git a/app/models/binda/field_setting.rb b/app/models/binda/field_setting.rb index b0c17e95..376849b6 100644 --- a/app/models/binda/field_setting.rb +++ b/app/models/binda/field_setting.rb @@ -6,7 +6,7 @@ class FieldSetting < ApplicationRecord # An array of all classes which represent fields associated to Binda::FieldSetting # This definition must stay on the top of the file def self.get_field_classes - %w( String Text Date Image Video Audio Repeater Radio Selection Checkbox Relation ) + %w( String Text Date Image Video Audio Repeater Radio Selection Checkbox Relation Svg ) end # ASSOCIATIONS @@ -33,6 +33,7 @@ def self.get_field_classes has_many :selections, as: :fieldable has_many :checkboxes, as: :fieldable has_many :relations, as: :fieldable + has_many :svgs, as: :fieldable # The following direct associations are used to securely delete associated fields # Infact via `fieldable` the associated fields might not be deleted @@ -41,15 +42,16 @@ def self.get_field_classes has_many :strings, dependent: :destroy has_many :dates, dependent: :destroy has_many :galleries, dependent: :destroy + has_many :assets, dependent: :destroy + has_many :images, dependent: :destroy + has_many :videos, dependent: :destroy + has_many :audios, dependent: :destroy has_many :repeaters, dependent: :destroy has_many :radios, dependent: :destroy has_many :selections, dependent: :destroy has_many :checkboxes, dependent: :destroy has_many :relations, dependent: :destroy - has_many :assets, dependent: :destroy - has_many :images, dependent: :destroy - has_many :videos, dependent: :destroy - has_many :audios, dependent: :destroy + has_many :svgs, dependent: :destroy # We don't want to run callbacks for choices! # If you run a callback the last choice will throw a error @@ -62,7 +64,7 @@ def self.get_field_classes accepts_nested_attributes_for :accepted_structures, :texts, :strings, :dates, :galleries, :assets, :images, :videos, :audios, :repeaters, :radios, :selections, - :checkboxes, :relations, :choices, allow_destroy: true, reject_if: :is_rejected + :checkboxes, :relations, :svgs, :choices, allow_destroy: true, reject_if: :is_rejected # Sets the validation rules to accept and save an attribute def is_rejected( attributes ) diff --git a/app/models/binda/svg_image.rb b/app/models/binda/svg.rb similarity index 70% rename from app/models/binda/svg_image.rb rename to app/models/binda/svg.rb index 1ef91af7..d18b3746 100644 --- a/app/models/binda/svg_image.rb +++ b/app/models/binda/svg.rb @@ -1,5 +1,5 @@ module Binda - class SvgImage < Asset + class Svg < Asset mount_uploader :svg, SvgUploader diff --git a/app/models/concerns/binda/fieldable_associations.rb b/app/models/concerns/binda/fieldable_associations.rb index 0267b384..d6ea6aec 100644 --- a/app/models/concerns/binda/fieldable_associations.rb +++ b/app/models/concerns/binda/fieldable_associations.rb @@ -29,9 +29,10 @@ module FieldableAssociations has_many :radios, as: :fieldable, dependent: :delete_all has_many :selections, as: :fieldable, dependent: :delete_all has_many :checkboxes, as: :fieldable, dependent: :delete_all + has_many :svgs, as: :fieldable, dependent: :delete_all # Repeaters need destroy_all, not delete_all has_many :repeaters, as: :fieldable, dependent: :destroy - has_many :relations, as: :fieldable, dependent: :destroy + has_many :relations, as: :fieldable, dependent: :destroy has_many :owner_relations, class_name: "RelationLink", @@ -53,7 +54,7 @@ module FieldableAssociations source: :owner - accepts_nested_attributes_for :texts, :strings, :dates, :assets, :images, :videos, :audios, :galleries, :repeaters, :radios, :selections, :checkboxes, :relations, allow_destroy: true + accepts_nested_attributes_for :texts, :strings, :dates, :assets, :images, :videos, :audios, :galleries, :repeaters, :radios, :selections, :checkboxes, :relations, :svgs, allow_destroy: true validates_associated :texts validates_associated :strings @@ -67,6 +68,7 @@ module FieldableAssociations validates_associated :selections validates_associated :checkboxes validates_associated :relations + validates_associated :svgs after_save :generate_fields diff --git a/app/uploaders/binda/svg_uploader.rb b/app/uploaders/binda/svg_uploader.rb index f6df47dd..47a8c8fc 100644 --- a/app/uploaders/binda/svg_uploader.rb +++ b/app/uploaders/binda/svg_uploader.rb @@ -1,60 +1,62 @@ -class SvgUploader < CarrierWave::Uploader::Base - # Include RMagick or MiniMagick support: - # include CarrierWave::RMagick - # include CarrierWave::MiniMagick - - # Choose what kind of storage to use for this uploader: - # storage :file - # storage :fog - - # Override the directory where uploaded files will be stored. - # This is a sensible default for uploaders that are meant to be mounted: - def store_dir - "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" +module Binda + class SvgUploader < CarrierWave::Uploader::Base + # Include RMagick or MiniMagick support: + # include CarrierWave::RMagick + # include CarrierWave::MiniMagick + + # Choose what kind of storage to use for this uploader: + # storage :file + # storage :fog + + # Override the directory where uploaded files will be stored. + # This is a sensible default for uploaders that are meant to be mounted: + def store_dir + "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" + end + + process :register_details + + def register_details + if file && model + model.content_type = file.content_type if file.content_type + model.file_size = file.size + end + end + + # Provide a default URL as a default if there hasn't been a file uploaded: + # def default_url(*args) + # # For Rails 3.1+ asset pipeline compatibility: + # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) + # + # "/images/fallback/" + [version_name, "default.png"].compact.join('_') + # end + + # Process files as they are uploaded: + # process scale: [200, 300] + # + # def scale(width, height) + # # do something + # end + + # Create different versions of your uploaded files: + # version :thumb do + # process resize_to_fit: [50, 50] + # end + + + # Add a white list of extensions which are allowed to be uploaded. + # For images you might use something like this: + # def extension_whitelist + # %w(jpg jpeg gif png) + # end + def extension_whitelist + %w(svg) + end + + # Override the filename of the uploaded files: + # Avoid using model.id or version_name here, see uploader/store.rb for details. + # def filename + # "something.jpg" if original_filename + # end end - - process :register_details - - def register_details - if file && model - model.content_type = file.content_type if file.content_type - model.file_size = file.size - end - end - - # Provide a default URL as a default if there hasn't been a file uploaded: - # def default_url(*args) - # # For Rails 3.1+ asset pipeline compatibility: - # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) - # - # "/images/fallback/" + [version_name, "default.png"].compact.join('_') - # end - - # Process files as they are uploaded: - # process scale: [200, 300] - # - # def scale(width, height) - # # do something - # end - - # Create different versions of your uploaded files: - # version :thumb do - # process resize_to_fit: [50, 50] - # end - - - # Add a white list of extensions which are allowed to be uploaded. - # For images you might use something like this: - # def extension_whitelist - # %w(jpg jpeg gif png) - # end - def extension_whitelist - %w(svg) - end - - # Override the filename of the uploaded files: - # Avoid using model.id or version_name here, see uploader/store.rb for details. - # def filename - # "something.jpg" if original_filename - # end -end +end \ No newline at end of file diff --git a/spec/factories/field_settings.rb b/spec/factories/field_settings.rb index 793184c1..1853f0ee 100644 --- a/spec/factories/field_settings.rb +++ b/spec/factories/field_settings.rb @@ -94,4 +94,8 @@ field_type 'audio' end + factory :svg_setting, parent: :field_setting do + field_type 'svg' + end + end diff --git a/spec/factories/svg.rb b/spec/factories/svg.rb new file mode 100644 index 00000000..cb3112a2 --- /dev/null +++ b/spec/factories/svg.rb @@ -0,0 +1,13 @@ +FactoryBot.define do + + factory :svg, class: Binda::Svg do + association :field_setting, factory: :svg_setting + end + + factory :component_and_svg, class: Binda::Component, parent: :component do + after(:create) do |component| + create(:svg, fieldable_id: component.id, fieldable_type: component.class.name) + end + end + +end \ No newline at end of file diff --git a/spec/models/binda/svg_image_spec.rb b/spec/models/binda/svg_image_spec.rb deleted file mode 100644 index b8e0b1f4..00000000 --- a/spec/models/binda/svg_image_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'rails_helper' - -module Binda - RSpec.describe SvgImage, type: :model do - pending "add some examples to (or delete) #{__FILE__}" - end -end diff --git a/spec/models/binda/svg_spec.rb b/spec/models/binda/svg_spec.rb new file mode 100644 index 00000000..a003ea2d --- /dev/null +++ b/spec/models/binda/svg_spec.rb @@ -0,0 +1,30 @@ +require 'rails_helper' + +module Binda + RSpec.describe Svg, type: :model do + include CarrierWave::Test::Matchers + + before(:context) do + SvgUploader.enable_processing = true + end + + before(:example) do + @component = create(:component) + @svg_setting = create(:svg_setting, field_group_id: @component.structure.field_groups.first.id) + end + + after(:context) do + SvgUploader.enable_processing = false + end + + it "stores content_type and file size" do + svg_name = 'test-svg.svg' + svg_path = ::Binda::Engine.root.join('spec', 'support', svg_name) + svg_record = @component.reload.svgs.first + svg_record.svg = svg_path.open + expect(svg_record.save!).to be_truthy + expect(svg_record.content_type).to eq 'image/svg+xml' + expect(svg_record.file_size).to be_within(400).of(600) # audio is 300kb + end + end +end diff --git a/spec/support/test-svg.svg b/spec/support/test-svg.svg new file mode 100644 index 00000000..0814e472 --- /dev/null +++ b/spec/support/test-svg.svg @@ -0,0 +1 @@ + \ No newline at end of file From 6189d1089a3085658849be0b843b1339d2111829 Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Fri, 23 Mar 2018 17:03:22 +0100 Subject: [PATCH 4/9] ADD svgs to binda for components --- .../binda/components/fileupload.js | 19 ++ .../javascripts/binda/dist/binda.bundle.js | 300 ++++++++++-------- app/controllers/binda/svgs_controller.rb | 71 +++++ .../concerns/binda/fieldable_helpers.rb | 32 +- .../binda/fieldable/_form_item_svg.html.erb | 33 ++ .../binda/fieldable/_form_item_video.html.erb | 17 +- .../binda/fieldable/_form_section.html.erb | 2 +- .../initializers/simple_form__fileupload.rb | 23 +- config/initializers/simple_form_custom.rb | 2 +- config/locales/en.yml | 1 + config/routes.rb | 5 + spec/features/components_edit_spec.rb | 31 ++ 12 files changed, 373 insertions(+), 163 deletions(-) create mode 100644 app/controllers/binda/svgs_controller.rb create mode 100644 app/views/binda/fieldable/_form_item_svg.html.erb diff --git a/app/assets/javascripts/binda/components/fileupload.js b/app/assets/javascripts/binda/components/fileupload.js index 54a8c6ae..cdf59f21 100644 --- a/app/assets/javascripts/binda/components/fileupload.js +++ b/app/assets/javascripts/binda/components/fileupload.js @@ -118,6 +118,8 @@ function updateFileuploadField(data, id) { setup_video_preview(data, id); } else if (data.type == "audio") { setup_audio_preview(data, id); + } else if (data.type == "svg") { + setup_svg_preview(data, id); } else { alert("Something went wrong. No preview has been received."); } @@ -243,3 +245,20 @@ function setup_audio_preview(data, id) { $parent.find(".fileupload--filename").text(data.name); $parent.find(".fileupload--previewlink a").attr("href", data.url); } + +function setup_svg_preview(data, id) { + let $parent = $("#fileupload-" + id); + let $preview = $("#fileupload-" + id + " .fileupload--preview"); + + // Update thumbnail + $preview.css("background-image", `url(${data.thumbnailUrl})`); + + // Remove and add class to trigger css animation + let uploadedClass = "fileupload--preview--uploaded"; + $preview.removeClass(uploadedClass).addClass(uploadedClass); + + // Update details + $parent.find(".fileupload--filesize").text(data.size); + $parent.find(".fileupload--filename").text(data.name); + $parent.find(".fileupload--previewlink a").attr("href", data.url); +} diff --git a/app/assets/javascripts/binda/dist/binda.bundle.js b/app/assets/javascripts/binda/dist/binda.bundle.js index 4f64e8b2..07b9ee99 100644 --- a/app/assets/javascripts/binda/dist/binda.bundle.js +++ b/app/assets/javascripts/binda/dist/binda.bundle.js @@ -33,6 +33,9 @@ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ +/******/ // identity function for calling harmony imports with the correct context +/******/ __webpack_require__.i = function(value) { return value; }; +/******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { @@ -60,7 +63,7 @@ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 2); +/******/ return __webpack_require__(__webpack_require__.s = 11); /******/ }) /************************************************************************/ /******/ ([ @@ -165,7 +168,7 @@ function setupAndAppend(newItem, $list) { var collapsable = $list.find(".form-item--collapsable").get(0); // Update select input for Select2 plugin - Object(__WEBPACK_IMPORTED_MODULE_0__select2__["b" /* setupSelect2 */])($list.find("select")); + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__select2__["b" /* setupSelect2 */])($list.find("select")); setupTinyMCE($list.find("textarea")); @@ -355,66 +358,13 @@ function setupSelect2(target) { /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__components_form_item_collapsable__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__components_form_item_image__ = __webpack_require__(3); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__components_field_setting_choices__ = __webpack_require__(4); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__components_fileupload__ = __webpack_require__(5); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__components_login_shader__ = __webpack_require__(6); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__components_login_form__ = __webpack_require__(7); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__components_sortable__ = __webpack_require__(8); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__components_field_group_editor__ = __webpack_require__(9); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__components_bootstrap__ = __webpack_require__(10); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__components_select2__ = __webpack_require__(1); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__components_radio_toggle__ = __webpack_require__(11); -///- - - - - - - - - - - - - - - - - - - - -/// INDEX OF BINDA'S SCRIPTS -///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -$(document).ready(function () { - if (__WEBPACK_IMPORTED_MODULE_0__components_form_item_collapsable__["a" /* _FormItemCollapsable */].isPresent()) { - __WEBPACK_IMPORTED_MODULE_0__components_form_item_collapsable__["a" /* _FormItemCollapsable */].setEvents(); - } - if (__WEBPACK_IMPORTED_MODULE_1__components_form_item_image__["a" /* _FormItemImage */].isPresent()) { - __WEBPACK_IMPORTED_MODULE_1__components_form_item_image__["a" /* _FormItemImage */].setEvents(); - } - if (__WEBPACK_IMPORTED_MODULE_2__components_field_setting_choices__["a" /* _FieldSettingChoices */].isPresent()) { - __WEBPACK_IMPORTED_MODULE_2__components_field_setting_choices__["a" /* _FieldSettingChoices */].setEvents(); - } - if (__WEBPACK_IMPORTED_MODULE_3__components_fileupload__["a" /* _FileUpload */].isPresent()) { - __WEBPACK_IMPORTED_MODULE_3__components_fileupload__["a" /* _FileUpload */].setEvents(); - } - if (__WEBPACK_IMPORTED_MODULE_5__components_login_form__["a" /* _LoginForm */].isPresent()) { - __WEBPACK_IMPORTED_MODULE_5__components_login_form__["a" /* _LoginForm */].init(); - } - if (__WEBPACK_IMPORTED_MODULE_4__components_login_shader__["a" /* _Shader */].isPresent()) { - __WEBPACK_IMPORTED_MODULE_4__components_login_shader__["a" /* _Shader */].setup(); - __WEBPACK_IMPORTED_MODULE_4__components_login_shader__["a" /* _Shader */].start(); - } - Object(__WEBPACK_IMPORTED_MODULE_10__components_radio_toggle__["a" /* default */])(); - Object(__WEBPACK_IMPORTED_MODULE_6__components_sortable__["a" /* default */])(); - Object(__WEBPACK_IMPORTED_MODULE_7__components_field_group_editor__["a" /* default */])(); - Object(__WEBPACK_IMPORTED_MODULE_8__components_bootstrap__["a" /* default */])(); - Object(__WEBPACK_IMPORTED_MODULE_9__components_select2__["a" /* default */])(); -}); +/** + * BOOSTRAP SCRIPT + */ -// handle event -window.addEventListener("optimizedResize", function () { - if (__WEBPACK_IMPORTED_MODULE_4__components_login_shader__["a" /* _Shader */].isPresent()) { - __WEBPACK_IMPORTED_MODULE_4__components_login_shader__["a" /* _Shader */].resize(); - } +/* harmony default export */ __webpack_exports__["a"] = (function () { + // See https://v4-alpha.getbootstrap.com/components/tooltips/#example-enable-tooltips-everywhere + $('[data-toggle="tooltip"]').tooltip(); }); /***/ }), @@ -422,40 +372,22 @@ window.addEventListener("optimizedResize", function () { /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _FormItemImage; }); -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - /** - * FORM ITEM IMAGE + * FIELD GROUP EDITOR */ -var FormItemImage = function () { - function FormItemImage() { - _classCallCheck(this, FormItemImage); - - this.target = ".form-item--image--uploader"; - } +/* harmony default export */ __webpack_exports__["a"] = (function () { + $(".field_groups-edit #save").on("click", function (event) { + var instanceType = $(this).data("instance-type"); + var entriesNumber = $(this).data("entries-number"); - _createClass(FormItemImage, [{ - key: "isPresent", - value: function isPresent() { - if ($(this.target).length > 0) { - return true; - } else { - return false; - } + // If the current structure have many entries updating the field group + // might be a slow operation, therefore it's good practice to inform the user + if (entriesNumber > 500) { + alert("You have " + entriesNumber + " " + instanceType + ". This operation might take some time to complete. To avoid unexpected behaviour don't leave or refresh the page"); } - }, { - key: "setEvents", - value: function setEvents() {} - }]); - - return FormItemImage; -}(); - -var _FormItemImage = new FormItemImage(); + }); +}); /***/ }), /* 4 */ @@ -501,7 +433,7 @@ var FieldSettingChoices = function () { event.preventDefault(); $(this).closest(".field-setting-choices--choice").remove(); // Update form item editor size - Object(__WEBPACK_IMPORTED_MODULE_0__form_item_collapsable__["d" /* resizeCollapsableStacks */])(); + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__form_item_collapsable__["d" /* resizeCollapsableStacks */])(); }); } }]); @@ -526,7 +458,7 @@ function addChoice(event) { // Append the clone right after choices.prepend(clone); // Update form item editor size - Object(__WEBPACK_IMPORTED_MODULE_0__form_item_collapsable__["d" /* resizeCollapsableStacks */])(); + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__form_item_collapsable__["d" /* resizeCollapsableStacks */])(); } function deleteChoice(event) { @@ -542,7 +474,7 @@ function deleteChoice(event) { }).done(function () { choice.remove(); // Update form item editor size - Object(__WEBPACK_IMPORTED_MODULE_0__form_item_collapsable__["d" /* resizeCollapsableStacks */])(); + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__form_item_collapsable__["d" /* resizeCollapsableStacks */])(); }).fail(function (data) { alert(data.responseJSON.errors); }); @@ -683,6 +615,8 @@ function updateFileuploadField(data, id) { setup_video_preview(data, id); } else if (data.type == "audio") { setup_audio_preview(data, id); + } else if (data.type == "svg") { + setup_svg_preview(data, id); } else { alert("Something went wrong. No preview has been received."); } @@ -780,10 +714,67 @@ function setup_audio_preview(data, id) { $parent.find(".fileupload--previewlink a").attr("href", data.url); } +function setup_svg_preview(data, id) { + var $parent = $("#fileupload-" + id); + var $preview = $("#fileupload-" + id + " .fileupload--preview"); + + // Update thumbnail + $preview.css("background-image", "url(" + data.thumbnailUrl + ")"); + + // Remove and add class to trigger css animation + var uploadedClass = "fileupload--preview--uploaded"; + $preview.removeClass(uploadedClass).addClass(uploadedClass); + + // Update details + $parent.find(".fileupload--filesize").text(data.size); + $parent.find(".fileupload--filename").text(data.name); + $parent.find(".fileupload--previewlink a").attr("href", data.url); +} + /***/ }), /* 6 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _FormItemImage; }); +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/** + * FORM ITEM IMAGE + */ + +var FormItemImage = function () { + function FormItemImage() { + _classCallCheck(this, FormItemImage); + + this.target = ".form-item--image--uploader"; + } + + _createClass(FormItemImage, [{ + key: "isPresent", + value: function isPresent() { + if ($(this.target).length > 0) { + return true; + } else { + return false; + } + } + }, { + key: "setEvents", + value: function setEvents() {} + }]); + + return FormItemImage; +}(); + +var _FormItemImage = new FormItemImage(); + +/***/ }), +/* 7 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _Shader; }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); @@ -998,7 +989,7 @@ function hexToShaderRgb(hex) { })(); /***/ }), -/* 7 */ +/* 8 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -1127,7 +1118,27 @@ var LoginForm = function () { var _LoginForm = new LoginForm(); /***/ }), -/* 8 */ +/* 9 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function () { + $('input[name="login"]').click(function () { + var $radio = $(this); + + // if this was previously checked + if ($radio.data("waschecked") === true) { + $radio.prop("checked", false); + $radio.data("waschecked", false); + } else $radio.data("waschecked", true); + + // remove was checked from other radios + $radio.siblings('input[name="login"]').data("waschecked", false); + }); +}); + +/***/ }), +/* 10 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -1184,7 +1195,7 @@ var sortableOptions = { function setupSortableToggle() { $(".sortable--toggle").each(function () { var id = "#" + $(this).data("sortable-target-id"); - Object(__WEBPACK_IMPORTED_MODULE_0__form_item_collapsable__["b" /* closeCollapsableStacks */])(id); + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__form_item_collapsable__["b" /* closeCollapsableStacks */])(id); }); // Add event to any sortable toggle button $(document).on("click", ".sortable--toggle", toggleSortable); @@ -1196,10 +1207,10 @@ function toggleSortable(event) { if ($(id).hasClass("sortable--disabled")) { $(id).sortable("enable"); - Object(__WEBPACK_IMPORTED_MODULE_0__form_item_collapsable__["b" /* closeCollapsableStacks */])(id); + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__form_item_collapsable__["b" /* closeCollapsableStacks */])(id); } else { $(id).sortable("disable"); - Object(__WEBPACK_IMPORTED_MODULE_0__form_item_collapsable__["c" /* openCollapsableStacks */])(id); + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__form_item_collapsable__["c" /* openCollapsableStacks */])(id); } $(id).toggleClass("sortable--disabled"); @@ -1229,59 +1240,70 @@ function updateSortable() { } /***/ }), -/* 9 */ +/* 11 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -/** - * FIELD GROUP EDITOR - */ +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__components_form_item_collapsable__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__components_form_item_image__ = __webpack_require__(6); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__components_field_setting_choices__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__components_fileupload__ = __webpack_require__(5); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__components_login_shader__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__components_login_form__ = __webpack_require__(8); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__components_sortable__ = __webpack_require__(10); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__components_field_group_editor__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__components_bootstrap__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__components_select2__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__components_radio_toggle__ = __webpack_require__(9); +///- - - - - - - - - - - - - - - - - - - - +/// INDEX OF BINDA'S SCRIPTS +///- - - - - - - - - - - - - - - - - - - - -/* harmony default export */ __webpack_exports__["a"] = (function () { - $(".field_groups-edit #save").on("click", function (event) { - var instanceType = $(this).data("instance-type"); - var entriesNumber = $(this).data("entries-number"); - // If the current structure have many entries updating the field group - // might be a slow operation, therefore it's good practice to inform the user - if (entriesNumber > 500) { - alert("You have " + entriesNumber + " " + instanceType + ". This operation might take some time to complete. To avoid unexpected behaviour don't leave or refresh the page"); - } - }); -}); -/***/ }), -/* 10 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { -"use strict"; -/** - * BOOSTRAP SCRIPT - */ -/* harmony default export */ __webpack_exports__["a"] = (function () { - // See https://v4-alpha.getbootstrap.com/components/tooltips/#example-enable-tooltips-everywhere - $('[data-toggle="tooltip"]').tooltip(); -}); -/***/ }), -/* 11 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { -"use strict"; -/* harmony default export */ __webpack_exports__["a"] = (function () { - $('input[name="login"]').click(function () { - var $radio = $(this); - // if this was previously checked - if ($radio.data("waschecked") === true) { - $radio.prop("checked", false); - $radio.data("waschecked", false); - } else $radio.data("waschecked", true); - // remove was checked from other radios - $radio.siblings('input[name="login"]').data("waschecked", false); - }); + + + + +$(document).ready(function () { + if (__WEBPACK_IMPORTED_MODULE_0__components_form_item_collapsable__["a" /* _FormItemCollapsable */].isPresent()) { + __WEBPACK_IMPORTED_MODULE_0__components_form_item_collapsable__["a" /* _FormItemCollapsable */].setEvents(); + } + if (__WEBPACK_IMPORTED_MODULE_1__components_form_item_image__["a" /* _FormItemImage */].isPresent()) { + __WEBPACK_IMPORTED_MODULE_1__components_form_item_image__["a" /* _FormItemImage */].setEvents(); + } + if (__WEBPACK_IMPORTED_MODULE_2__components_field_setting_choices__["a" /* _FieldSettingChoices */].isPresent()) { + __WEBPACK_IMPORTED_MODULE_2__components_field_setting_choices__["a" /* _FieldSettingChoices */].setEvents(); + } + if (__WEBPACK_IMPORTED_MODULE_3__components_fileupload__["a" /* _FileUpload */].isPresent()) { + __WEBPACK_IMPORTED_MODULE_3__components_fileupload__["a" /* _FileUpload */].setEvents(); + } + if (__WEBPACK_IMPORTED_MODULE_5__components_login_form__["a" /* _LoginForm */].isPresent()) { + __WEBPACK_IMPORTED_MODULE_5__components_login_form__["a" /* _LoginForm */].init(); + } + if (__WEBPACK_IMPORTED_MODULE_4__components_login_shader__["a" /* _Shader */].isPresent()) { + __WEBPACK_IMPORTED_MODULE_4__components_login_shader__["a" /* _Shader */].setup(); + __WEBPACK_IMPORTED_MODULE_4__components_login_shader__["a" /* _Shader */].start(); + } + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_10__components_radio_toggle__["a" /* default */])(); + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_6__components_sortable__["a" /* default */])(); + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_7__components_field_group_editor__["a" /* default */])(); + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_8__components_bootstrap__["a" /* default */])(); + __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_9__components_select2__["a" /* default */])(); +}); + +// handle event +window.addEventListener("optimizedResize", function () { + if (__WEBPACK_IMPORTED_MODULE_4__components_login_shader__["a" /* _Shader */].isPresent()) { + __WEBPACK_IMPORTED_MODULE_4__components_login_shader__["a" /* _Shader */].resize(); + } }); /***/ }) diff --git a/app/controllers/binda/svgs_controller.rb b/app/controllers/binda/svgs_controller.rb new file mode 100644 index 00000000..13dd2bef --- /dev/null +++ b/app/controllers/binda/svgs_controller.rb @@ -0,0 +1,71 @@ +require_dependency "binda/application_controller" + +module Binda + class SvgsController < ApplicationController + before_action :set_svg, only: [:show, :edit, :update, :destroy, :remove_svg] + + # GET /svgs + def index + @svgs = Svg.all + end + + # GET /svgs/1 + def show + end + + # GET /svgs/new + def new + @svg = Svg.new + end + + # GET /svgs/1/edit + def edit + end + + # POST /svgs + def create + @svg = Svg.new(svg_params) + + if @svg.save + redirect_to svg_path( @svg.id ), notice: 'Svg was successfully created.' + else + render :new + end + end + + # PATCH/PUT /svgs/1 + def update + if @svg.update(svg_params) + redirect_to svg_path( @svg.id ), notice: 'Svg was successfully updated.' + else + render :edit + end + end + + # DELETE /svgs/1 + def destroy + @svg.destroy + redirect_to svgs_url, notice: 'Svg was successfully destroyed.' + end + + def remove_svg + @svg.remove_svg! + if @svg.save + head :ok + else + render json: @svg.errors.full_messages, status: 400 + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_svg + @svg = Svg.find(params[:id]) + end + + # Only allow a trusted parameter "white list" through. + def svg_params + params.require(:svg).permit( :svg, :name ) + end + end +end diff --git a/app/controllers/concerns/binda/fieldable_helpers.rb b/app/controllers/concerns/binda/fieldable_helpers.rb index 96a23d75..90109b2d 100644 --- a/app/controllers/concerns/binda/fieldable_helpers.rb +++ b/app/controllers/concerns/binda/fieldable_helpers.rb @@ -9,7 +9,8 @@ def fieldable_params strings_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :content ], images_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :image, :image_cache ], videos_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :video, :video_cache ], - audios_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :audio, :audio_cache ], + audios_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :audio, :audio_cache ], + svgs_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :svg, :svg_cache ], dates_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :date ], galleries_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id ], radios_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :choice_ids ], @@ -21,7 +22,8 @@ def fieldable_params strings_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :content ], images_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :image, :image_cache ], videos_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :video, :video_cache ], - audios_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :audio, :audio_cache ], + audios_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :audio, :audio_cache ], + svgs_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :svg, :svg_cache ], dates_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :date ], galleries_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id ], relations_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, dependent_component_ids: [], dependent_board_ids: [] ], @@ -46,10 +48,12 @@ def upload_params fieldable_type {images_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :image, :image_cache ]}, {videos_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :video, :video_cache ]}, {audios_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :audio, :audio_cache ]}, + {svgs_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :svg, :svg_cache ]}, {repeaters_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, images_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :image, :image_cache ], videos_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :video, :video_cache ], - audios_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :audio, :audio_cache ]]}) + audios_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :audio, :audio_cache ], + svgs_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :svg, :svg_cache ]]}) end # Uploads a details for a fieldable instance (component or board) @@ -68,7 +72,6 @@ def upload_params fieldable_type # } # def upload_details - # Because this is a callback that happens right after the upload # chances are that it's also the latest asset that has been updated. # Therefore get the latest uploaded asset @@ -80,9 +83,12 @@ def upload_details return_video_details(asset) elsif asset.audio.present? return_audio_details(asset) - else + elsif asset.svg.present? + return_svg_details(asset) + else raise "The record Binda::Asset with id=#{asset.id} doesn't have any image, video or audio attached. This might be due to a bug. Please report it in Binda official Github page." end + end @@ -109,6 +115,22 @@ def return_image_details asset } end + # Return svg details + # + # This helper is used internally by the `upload_details` method + # to retrieve and return the necessary details to be displayed on + # the editor. + def return_svg_details asset + # get image dimension + return { + type: 'svg', + name: asset.svg_identifier, + size: "#{bytes_to_megabytes( asset.svg.size )}MB", + url: asset.svg.url, + thumbnailUrl: asset.svg.url + } + end + # Return video details # diff --git a/app/views/binda/fieldable/_form_item_svg.html.erb b/app/views/binda/fieldable/_form_item_svg.html.erb new file mode 100644 index 00000000..21a965db --- /dev/null +++ b/app/views/binda/fieldable/_form_item_svg.html.erb @@ -0,0 +1,33 @@ +
+
+

+ <%= field_setting.name %> +

+ <% image = ff.object.image.thumb.url if ff.object.image.present? %> +
+ <%= ff.input :svg, + label: " #{t('binda.choose_file_button')}".html_safe, + hint: field_setting.description.nil? ? false : field_setting.description.html_safe, + url: url_for([ff.object, action: :remove_svg]).html_safe, + object: ff.object, + wrapper: false, + input_html: { + 'data-url': url_for([ + @instance.structure, + @instance, + action: :upload, + repeater: { id: "#{field_setting.parent_id}" }]), + 'data-id': ff.object.id + } %> +
+ <%= ff.input :svg_cache, as: :hidden %> + <%= ff.input :field_setting_id, as: :hidden, input_html: { value: field_setting.id } %> + <%= ff.input :id, as: :hidden, input_html: { value: ff.object.id } %> + <%= ff.input :fieldable_id, as: :hidden %> + <%= ff.input :fieldable_type, as: :hidden %> +
+
+
\ No newline at end of file diff --git a/app/views/binda/fieldable/_form_item_video.html.erb b/app/views/binda/fieldable/_form_item_video.html.erb index 5888318c..1732c755 100644 --- a/app/views/binda/fieldable/_form_item_video.html.erb +++ b/app/views/binda/fieldable/_form_item_video.html.erb @@ -7,19 +7,20 @@

<%= field_setting.name %>

- - <%= ff.input :video, + <%= ff.input :video, label: " #{t('binda.choose_file_button')}".html_safe, hint: field_setting.description.nil? ? false : field_setting.description.html_safe, url: url_for([ff.object, action: :remove_video]).html_safe, object: ff.object, wrapper: false, - input_html: { - class: 'form-item--video--uploader', - 'data-url': url_for([@instance.structure, @instance, action: :upload]), - 'data-id': ff.object.id, - } %> - + input_html: { + class: 'form-item--video--uploader', + 'data-url': url_for([ + @instance.structure, + @instance, + action: :upload]), + 'data-id': ff.object.id, + } %>
<%= ff.input :video_cache, as: :hidden %> diff --git a/app/views/binda/fieldable/_form_section.html.erb b/app/views/binda/fieldable/_form_section.html.erb index e6fd91ca..8e3c09c5 100644 --- a/app/views/binda/fieldable/_form_section.html.erb +++ b/app/views/binda/fieldable/_form_section.html.erb @@ -1,4 +1,4 @@ -<% if %w(text string date image video audio relation).include? field_setting.field_type %> +<% if %w(text string date image video audio relation svg).include? field_setting.field_type %> <% current = @instance.find_or_create_a_field_by( field_setting.id, field_setting.field_type) %> <%= f.simple_fields_for "#{field_setting.field_type}s_attributes[]", current do |ff| %> <%= render "binda/fieldable/form_item_#{field_setting.field_type}", f: f, ff: ff, field_setting: field_setting %> diff --git a/config/initializers/simple_form__fileupload.rb b/config/initializers/simple_form__fileupload.rb index fb251087..87cc2ff2 100644 --- a/config/initializers/simple_form__fileupload.rb +++ b/config/initializers/simple_form__fileupload.rb @@ -17,6 +17,8 @@ def preview(wrapper_options = nil) html << " fileupload--preview--uploaded" elsif options[:object].audio.present? html << " fileupload--preview--uploaded fileupload--preview--hidden" + elsif options[:object].svg.present? + html << " fileupload--preview--uploaded\" style=\"background-image: url(#{options[:object].svg.url})" end # Add no-preview text @@ -54,7 +56,7 @@ def delete_button(wrapper_options = nil) obj = options[:object] url = options[:url] html = '

' html << "#{t 'binda.filename'}: " html << '' html << File.basename(obj.image.path).to_s if obj.image.present? html << File.basename(obj.video.path).to_s if obj.video.present? html << File.basename(obj.audio.path).to_s if obj.audio.present? + html << File.basename(obj.svg.path).to_s if obj.svg.present? html << '

' html << '

' html << "#{t 'binda.filesize'}: " html << '' html << bytes_to_megabytes(obj.file_size).to_s unless obj.file_size.blank? html << 'MB

' - html << '

' - html << "#{t 'binda.filedimension'}: " - html << '' - html << obj.file_width.round.to_s unless obj.file_width.blank? - html << ' x ' - html << obj.file_height.round.to_s unless obj.file_height.blank? - html << ' px

' + html << '

' unless obj.svg.present? + html << "#{t 'binda.filedimension'}: " unless obj.svg.present? + html << '' unless obj.svg.present? + html << obj.file_width.round.to_s unless obj.file_width.blank? unless obj.svg.present? + html << ' x ' unless obj.svg.present? + html << obj.file_height.round.to_s unless obj.file_height.blank? || obj.svg.present? + html << ' px

' unless obj.svg.present? html << '
' html << '' diff --git a/config/initializers/simple_form_custom.rb b/config/initializers/simple_form_custom.rb index 3124b1ec..3e93c273 100644 --- a/config/initializers/simple_form_custom.rb +++ b/config/initializers/simple_form_custom.rb @@ -119,7 +119,7 @@ b.optional :maxlength b.optional :readonly - b.use :preview + b.use :preview b.wrapper tag: 'div', class: 'fileupload--dashboard' do |bb| bb.use :label, class: 'control-label b-btn b-btn-primary', wrap_with: { tag: 'div', class: 'control-label-wrap' } bb.use :delete_button diff --git a/config/locales/en.yml b/config/locales/en.yml index 46fd4344..58908cf7 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -59,6 +59,7 @@ en: filedimension: Dimension filevideolink: Preview video fileaudiolink: Preview audio + filesvglink: Preview svg select_placeholder: Select a option new_item_in_repeater: New %{arg1} item null_is_not_allowed: You need to select at least one choice diff --git a/config/routes.rb b/config/routes.rb index 9dd6a978..fd2c70d6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -85,6 +85,11 @@ delete 'remove_image' end end + resources :svgs do + member do + delete 'remove_svg' + end + end resources :repeaters end diff --git a/spec/features/components_edit_spec.rb b/spec/features/components_edit_spec.rb index 79c91f1b..b9a54653 100644 --- a/spec/features/components_edit_spec.rb +++ b/spec/features/components_edit_spec.rb @@ -196,6 +196,37 @@ Binda::Audio::AudioUploader.enable_processing = false end + + it "allows to upload a file to the svg field and store it" do + Binda::SvgUploader.enable_processing = true + # Create an image field setting on which will work + svg_setting = create(:svg_setting, field_group_id: @structure.field_groups.first.id) + # Refresh the page so the image field appear on the editor + visit @path + expect(@component.svgs.first.svg.present?).not_to be_truthy + field_id = "component_svgs_attributes_#{@component.svgs.where(field_setting_id: svg_setting.id ).first.id}_svg" + svg_name = 'test-svg.svg' + svg_path = ::Binda::Engine.root.join('spec', 'support', svg_name) + page.execute_script("document.getElementById('#{field_id}').style.zIndex = '1'") + page.execute_script("document.getElementById('#{field_id}').style.opacity = '1'") + page.attach_file(field_id, svg_path) + wait_for_ajax + sleep 1 # wait for animation to complete + @component.reload + svg = @component.svgs.first + within "#fileupload-#{svg.id}" do + expect(page).to have_content svg_name + expect(page).to have_content (svg.file_size.to_f / 1.megabyte).round(2) + end + visit @path + expect( File.basename( svg.svg.path ) ).to eq svg_name + within "#fileupload-#{audio.id}" do + expect(page).to have_content svg_name + expect(page).to have_content (svg.file_size.to_f / 1.megabyte).round(2) + end + Binda::SvgUploader.enable_processing = false + end + it "allows to upload a file to the video field and store it" do Binda::Video::VideoUploader.enable_processing = true # Create an image field setting on which will work From 0fb5a1ed95a8d5e1a04d3b68b399389069bb9099 Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Mon, 26 Mar 2018 10:14:38 +0200 Subject: [PATCH 5/9] ADD board tst for svgs --- spec/features/boards_edit_spec.rb | 29 +++++++++++++++++++++++++++ spec/features/components_edit_spec.rb | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/spec/features/boards_edit_spec.rb b/spec/features/boards_edit_spec.rb index 391f0781..ff4ead62 100644 --- a/spec/features/boards_edit_spec.rb +++ b/spec/features/boards_edit_spec.rb @@ -139,6 +139,35 @@ Binda::Image::ImageUploader.enable_processing = false end + it "allows to add an svg to an svg field and store it" do + Binda::SvgUploader.enable_processing = true + # Create an image field setting on which will work + svg_setting = create(:svg_setting, field_group_id: @structure.field_groups.first.id) + # Refresh the page so the image field appear on the editor + visit @path + expect(@board.svgs.first.svg.present?).not_to be_truthy + field_id = "board_svgs_attributes_#{@board.svgs.where(field_setting_id: svg_setting.id ).first.id}_svg" + svg_name = 'test-svg.svg' + svg_path = ::Binda::Engine.root.join('spec', 'support', svg_name) + page.execute_script("document.getElementById('#{field_id}').style.zIndex = '1'") + page.execute_script("document.getElementById('#{field_id}').style.opacity = '1'") + page.attach_file(field_id, svg_path) + wait_for_ajax + sleep 1 # wait for animation to complete + @board.reload + svg = @board.svgs.first + within "#fileupload-#{svg.id}" do + expect(page).to have_content svg_name + end + + visit @path + expect( File.basename( svg.svg.path ) ).to eq svg_name + within "#fileupload-#{svg.id}" do + expect( page ).to have_content svg_name + end + Binda::SvgUploader.enable_processing = false + end + it "allows to add an image to an image field in a repeater" do skip "not implemeted yet" end diff --git a/spec/features/components_edit_spec.rb b/spec/features/components_edit_spec.rb index b9a54653..189cd15f 100644 --- a/spec/features/components_edit_spec.rb +++ b/spec/features/components_edit_spec.rb @@ -220,7 +220,7 @@ end visit @path expect( File.basename( svg.svg.path ) ).to eq svg_name - within "#fileupload-#{audio.id}" do + within "#fileupload-#{svg.id}" do expect(page).to have_content svg_name expect(page).to have_content (svg.file_size.to_f / 1.megabyte).round(2) end From 35209df77bd60253fcac2009989fd7bf425dae5f Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Mon, 26 Mar 2018 10:23:47 +0200 Subject: [PATCH 6/9] ADD svg helpers --- .../binda/fieldable_association_helpers.rb | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/app/models/concerns/binda/fieldable_association_helpers.rb b/app/models/concerns/binda/fieldable_association_helpers.rb index d309aca2..b937f952 100644 --- a/app/models/concerns/binda/fieldable_association_helpers.rb +++ b/app/models/concerns/binda/fieldable_association_helpers.rb @@ -292,6 +292,56 @@ def get_audio_info(field_slug, info) end end + # Check if the field has an attached audio + # + # @param field_slug [string] The slug of the field setting + # @return [boolean] + def has_svg(field_slug) + obj = self.svgs.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + # Alternative query + # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first + raise ArgumentError, "There isn't any svg associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + return obj.svg.present? + end + + # Get the svg url based on the size provided, + # default is Carrierwave default (usually the real size) + # + # @param field_slug [string] The slug of the field setting + # @param size [string] The size. It can be 'thumb' 200x200 cropped, + # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank + # @return [string] The url of the svg + def get_svg_url(field_slug) + get_svg_info( field_slug, 'url' ) + end + + # Get the svg path based on the size provided, + # default is Carrierwave default (usually the real size) + # + # @param field_slug [string] The slug of the field setting + # @param size [string] The size. It can be 'thumb' 200x200 cropped, + # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank + # @return [string] The url of the svg + def get_svg_path(field_slug) + get_svg_info( field_slug, 'path' ) + end + + # Get the object related to that field setting + # + # @param field_slug [string] The slug of the field setting + # @param info [string] String of the info to be retrieved + # @return [string] The info requested if present + # @return [boolean] Returns false if no info is found or if image isn't found + def get_svg_info(field_slug, info) + obj = self.svgs.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + # Alternative query + # obj = svg.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first + raise ArgumentError, "There isn't any svg associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + if obj.svg.present? + obj.svg.send(info) + end + end + # Check if the field has an attached date # # @param field_slug [string] The slug of the field setting From 097d5918a306f4c20da3c060fa3170b39a7987da Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Mon, 26 Mar 2018 10:33:13 +0200 Subject: [PATCH 7/9] ADD missing helpers, modify readme --- README.md | 7 +++++++ .../binda/fieldable_association_helpers.rb | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/README.md b/README.md index 66d24694..6df7bb2d 100644 --- a/README.md +++ b/README.md @@ -364,6 +364,7 @@ Here below a list of field types available and their use: | string | Store a string. No formatting options available. | [source](http://www.rubydoc.info/gems/binda/Binda/String) | | text | Store a text. TinyMCE let's you format the text as you like. | [source](http://www.rubydoc.info/gems/binda/Binda/Text) | | image | Store image. | [source](http://www.rubydoc.info/gems/binda/Binda/Image) | +| svg | Store svg. | [source](http://www.rubydoc.info/gems/binda/Binda/Svg) | | video | Store video. | [source](http://www.rubydoc.info/gems/binda/Binda/Video) | | audio | Store audio. | [source](http://www.rubydoc.info/gems/binda/Binda/Audio) | | date | Store a date. | [source](http://www.rubydoc.info/gems/binda/Binda/Date) | @@ -440,6 +441,12 @@ You can retrieve field content from a instance of `Binda::Component`, `Binda::Bo |`get_image_size`| Returns the image size in MB. | [source](http://www.rubydoc.info/gems/binda/Binda/FieldableAssociationHelpers:get_image_size) | |`get_image_dimension`| Returns a hash { width: xxx, height: xxx } with image dimension. | [source](http://www.rubydoc.info/gems/binda/Binda/FieldableAssociationHelpers:get_image_dimension) | |`get_image_mime_type`| Returns the mime type of the image. | [source](http://www.rubydoc.info/gems/binda/Binda/FieldableAssociationHelpers:get_image_mime_type) | +|`has_svg`| Returns `true/false`.| [source](http://www.rubydoc.info/gems/binda/Binda/FieldableAssociationHelpers:has_svg) | +|`get_svg_url`| Returns the url of the svg. | [source](http://www.rubydoc.info/gems/binda/Binda/FieldableAssociationHelpers:get_svg_url) | +|`get_svg_path`| Returns the path of the svg. | [source](http://www.rubydoc.info/gems/binda/Binda/FieldableAssociationHelpers:get_svg_path) | +|`get_svg_size`| Returns the svg size in MB. | [source](http://www.rubydoc.info/gems/binda/Binda/FieldableAssociationHelpers:get_svg_size) | +|`get_svg_mime_type`| Returns the mime type of the svg. | [source](http://www.rubydoc.info/gems/binda/Binda/FieldableAssociationHelpers:get_svg_mime_type) | + |`has_video`| Returns `true/false`.| [source](http://www.rubydoc.info/gems/binda/Binda/FieldableAssociationHelpers:has_video) | |`get_video_url`| Returns the url of the video. | [source](http://www.rubydoc.info/gems/binda/Binda/FieldableAssociationHelpers:get_video_url) | |`get_video_path`| Returns the path of the video. | [source](http://www.rubydoc.info/gems/binda/Binda/FieldableAssociationHelpers:get_video_path) | diff --git a/app/models/concerns/binda/fieldable_association_helpers.rb b/app/models/concerns/binda/fieldable_association_helpers.rb index b937f952..597a8bb8 100644 --- a/app/models/concerns/binda/fieldable_association_helpers.rb +++ b/app/models/concerns/binda/fieldable_association_helpers.rb @@ -342,6 +342,20 @@ def get_svg_info(field_slug, info) end end + def get_svg_size(field_slug) + obj = self.svgs.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + return bytes_to_megabytes(obj.file_size) + end + + # Get svg type + # + # @param field_slug [string] The slug of the field setting + # @return [string] with svg type + def get_svg_mime_type(field_slug) + obj = self.svgs.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + return obj.content_type + end + # Check if the field has an attached date # # @param field_slug [string] The slug of the field setting From 0aaf32de60a2cb865718ac8b53f06134f8f78ed0 Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Mon, 26 Mar 2018 10:34:06 +0200 Subject: [PATCH 8/9] UPDATE dependencies --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 37849ebb..a183bd0d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -185,7 +185,7 @@ GEM mini_portile2 (~> 2.3.0) orm_adapter (0.5.0) parallel (1.12.1) - parser (2.5.0.4) + parser (2.5.0.5) ast (~> 2.4.0) pg (0.21.0) powerpack (0.1.1) From 86fd603df808c6a5941533f17fa501232bec311c Mon Sep 17 00:00:00 2001 From: marco panzeri Date: Mon, 26 Mar 2018 12:02:34 +0200 Subject: [PATCH 9/9] FIX all broken tests --- .../concerns/binda/fieldable_helpers.rb | 40 +- .../binda/fieldable_association_helpers.rb | 528 +----------------- .../fieldable_audio_helpers.rb | 55 ++ .../fieldable_date_helpers.rb | 30 + .../fieldable_image_helpers.rb | 95 ++++ .../fieldable_relation_helpers.rb | 68 +++ .../fieldable_repeater_helpers.rb | 32 ++ .../fieldable_selection_helpers.rb | 60 ++ .../fieldable_string_helpers.rb | 56 ++ .../fieldable_svg_helpers.rb | 74 +++ .../fieldable_text_helpers.rb | 59 ++ .../fieldable_video_helpers.rb | 56 ++ .../binda/boards_controller_spec.rb | 2 +- .../binda/components_controller_spec.rb | 2 +- .../generators/binda/setup_generator_spec.rb | 26 +- spec/models/binda/field_setting_spec.rb | 6 +- spec/models/binda/image_spec.rb | 4 +- spec/models/binda/selection_spec.rb | 4 +- 18 files changed, 640 insertions(+), 557 deletions(-) create mode 100644 app/models/concerns/binda/fieldable_association_helpers/fieldable_audio_helpers.rb create mode 100644 app/models/concerns/binda/fieldable_association_helpers/fieldable_date_helpers.rb create mode 100644 app/models/concerns/binda/fieldable_association_helpers/fieldable_image_helpers.rb create mode 100644 app/models/concerns/binda/fieldable_association_helpers/fieldable_relation_helpers.rb create mode 100644 app/models/concerns/binda/fieldable_association_helpers/fieldable_repeater_helpers.rb create mode 100644 app/models/concerns/binda/fieldable_association_helpers/fieldable_selection_helpers.rb create mode 100644 app/models/concerns/binda/fieldable_association_helpers/fieldable_string_helpers.rb create mode 100644 app/models/concerns/binda/fieldable_association_helpers/fieldable_svg_helpers.rb create mode 100644 app/models/concerns/binda/fieldable_association_helpers/fieldable_text_helpers.rb create mode 100644 app/models/concerns/binda/fieldable_association_helpers/fieldable_video_helpers.rb diff --git a/app/controllers/concerns/binda/fieldable_helpers.rb b/app/controllers/concerns/binda/fieldable_helpers.rb index 90109b2d..324fefb0 100644 --- a/app/controllers/concerns/binda/fieldable_helpers.rb +++ b/app/controllers/concerns/binda/fieldable_helpers.rb @@ -4,8 +4,9 @@ module FieldableHelpers extend ActiveSupport::Concern # Only allow a trusted parameter "white list" through. - def fieldable_params - [ texts_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :content ], + def fieldable_params + [ + texts_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :content ], strings_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :content ], images_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :image, :image_cache ], videos_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :video, :video_cache ], @@ -17,21 +18,26 @@ def fieldable_params selections_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :choice_ids ], checkboxes_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, choice_ids: [] ], relations_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, dependent_component_ids: [], dependent_board_ids: [] ], - repeaters_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :field_group_id, - texts_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :content ], - strings_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :content ], - images_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :image, :image_cache ], - videos_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :video, :video_cache ], - audios_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :audio, :audio_cache ], - svgs_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :svg, :svg_cache ], - dates_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :date ], - galleries_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id ], - relations_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, dependent_component_ids: [], dependent_board_ids: [] ], - repeaters_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :field_group_id ], - radios_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :choice_ids ], - selections_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :choice_ids ], - checkboxes_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, choice_ids: [] ] - ]] + repeaters_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :field_group_id, *nested_fieldable_params ] + ] + end + + def nested_fieldable_params + [ + texts_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :content ], + strings_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :content ], + images_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :image, :image_cache ], + videos_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :video, :video_cache ], + audios_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :audio, :audio_cache ], + svgs_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :svg, :svg_cache ], + dates_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :date ], + galleries_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id ], + relations_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, dependent_component_ids: [], dependent_board_ids: [] ], + repeaters_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :field_group_id ], + radios_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :choice_ids ], + selections_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, :choice_ids ], + checkboxes_attributes: [ :id, :field_setting_id, :fieldable_type, :fieldable_id, choice_ids: [] ] + ] end # Uploads parameters. diff --git a/app/models/concerns/binda/fieldable_association_helpers.rb b/app/models/concerns/binda/fieldable_association_helpers.rb index 597a8bb8..e9001377 100644 --- a/app/models/concerns/binda/fieldable_association_helpers.rb +++ b/app/models/concerns/binda/fieldable_association_helpers.rb @@ -3,524 +3,16 @@ module FieldableAssociationHelpers extend ActiveSupport::Concern - # Get the object related to that field setting - # If the object doesn't exists yet it will return nil - # - # @param field_slug [string] The slug of the field setting - # @return [string] Returns the content of the text - # @return [error] Raise an error if no record is found - def get_text(field_slug) - obj = Text - .includes(:field_setting) - .where(fieldable_id: self.id, fieldable_type: self.class.name) - .where(binda_field_settings: { slug: field_slug }) - .where.not(binda_field_settings: { field_type: "string" }) - .first - unless obj.nil? - # to_s ensures the returned object is class String - obj.content.to_s - else - check_text_error field_slug - end - end + include FieldableTextHelpers + include FieldableStringHelpers + include FieldableImageHelpers + include FieldableVideoHelpers + include FieldableAudioHelpers + include FieldableSvgHelpers + include FieldableRelationHelpers + include FieldableSelectionHelpers + include FieldableRepeaterHelpers + include FieldableDateHelpers - # Check why get_text doesn't return a value - # This method isn't supposed to be used by anything other than get_text method - def check_text_error(field_slug) - you_mean_string = !self.strings.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) && t.type == 'Binda::String' }.nil? - if you_mean_string - raise ArgumentError, "This slug (#{field_slug}) is associated to a string not a text. Use get_string() instead on instance (#{self.class.name} ##{self.id}).", caller - else - raise ArgumentError, "There isn't any text associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller - end - end - - # Get the object related to that field setting - # - # @param field_slug [string] The slug of the field setting - # @return [boolean] - def has_text(field_slug) - obj = Text - .includes(:field_setting) - .where(fieldable_id: self.id, fieldable_type: self.class.name) - .where(binda_field_settings: { slug: field_slug }) - .where.not(binda_field_settings: { field_type: "string" }) - .first - raise ArgumentError, "There isn't any text associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - if obj.present? - return !obj.content.nil? - else - return false - end - end - - # Get the object related to that field setting - # If the object doesn't exists yet it will return nil - # - # @param field_slug [string] The slug of the field setting - # @return [string] Returns the content of the string - # @return [error] Raise an error if no record is found - def get_string(field_slug) - obj = Text - .includes(:field_setting) - .where(fieldable_id: self.id, fieldable_type: self.class.name) - .where(binda_field_settings: { slug: field_slug, field_type: "string" }) - .first - unless obj.nil? - # to_s ensures the returned object is class String - obj.content.to_s - else - check_string_error field_slug - end - end - - # Check why get_string doesn't return a value - # This method isn't supposed to be used by anything other than get_string method - def check_string_error(field_slug) - you_mean_text = !self.strings.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) && t.type == 'Binda::Text' }.nil? - if you_mean_text - raise ArgumentError, "This slug (#{field_slug}) is associated to a text not a string. Use get_text() instead on instance (#{self.class.name} ##{self.id}).", caller - else - raise ArgumentError, "There isn't any string associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller - end - end - - # Get the object related to that field setting - # - # @param field_slug [string] The slug of the field setting - # @return [boolean] - def has_string(field_slug) - obj = Text - .includes(:field_setting) - .where(fieldable_id: self.id, fieldable_type: self.class.name) - .where(binda_field_settings: { slug: field_slug, field_type: "string" }) - .first - raise ArgumentError, "There isn't any string associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - if obj.present? - return !obj.content.nil? - else - return false - end - end - - # Check if the field has an attached image - # - # @param field_slug [string] The slug of the field setting - # @return [boolean] - def has_image(field_slug) - obj = self.images.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - # Alternative query - # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first - raise ArgumentError, "There isn't any image associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - return obj.image.present? - end - - # Get the image url based on the size provided, - # default is Carrierwave default (usually the real size) - # - # @param field_slug [string] The slug of the field setting - # @param size [string] The size. It can be 'thumb' 200x200 cropped, - # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank - # @return [string] The url of the image - def get_image_url(field_slug, size = '') - get_image_info( field_slug, size, 'url' ) - end - - # Get the image path based on the size provided, - # default is Carrierwave default (usually the real size) - # - # @param field_slug [string] The slug of the field setting - # @param size [string] The size. It can be 'thumb' 200x200 cropped, - # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank - # @return [string] The url of the image - def get_image_path(field_slug, size = '') - get_image_info( field_slug, size, 'path' ) - end - - # Get the object related to that field setting - # - # @param field_slug [string] The slug of the field setting - # @param size [string] The size. It can be 'thumb' 200x200 cropped, - # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank - # @param info [string] String of the info to be retrieved - # @return [string] The info requested if present - # @return [boolean] Returns false if no info is found or if image isn't found - def get_image_info(field_slug, size, info) - obj = self.images.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - # Alternative query - # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first - raise ArgumentError, "There isn't any image associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - if obj.image.present? && obj.image.respond_to?(size) && %w[thumb].include?(size) - obj.image.send(size).send(info) - elsif obj.image.present? - obj.image.send(info) - else - raise "Looks like the image you are looking for isn't present. See field setting with slug=\"#{field_slug}\" on component with id=\"self.id\"" - end - end - - # Get image size - # - # @param field_slug [string] The slug of the field setting - # @return [float] with image type - def get_image_size(field_slug) - obj = self.images.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - return bytes_to_megabytes(obj.file_size) - end - - # Convert bytes to megabites - def bytes_to_megabytes bytes - (bytes.to_f / 1.megabyte).round(2) - end - - # Get image type - # - # @param field_slug [string] The slug of the field setting - # @return [string] with image type - def get_image_mime_type(field_slug) - obj = self.images.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - return obj.content_type - end - - # Get image dimension - # - # @param field_slug [string] The slug of the field setting - # @return [hash] with width and height as floats - def get_image_dimension(field_slug) - obj = self.images.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - return { width: obj.file_width, height: obj.file_height } - end - - # Check if the field has an attached video - # - # @param field_slug [string] The slug of the field setting - # @return [boolean] - def has_video(field_slug) - obj = self.videos.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - # Alternative query - # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first - raise ArgumentError, "There isn't any video associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - return obj.video.present? - end - - # Get the video url based on the size provided, - # default is Carrierwave default (usually the real size) - # - # @param field_slug [string] The slug of the field setting - # @param size [string] The size. It can be 'thumb' 200x200 cropped, - # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank - # @return [string] The url of the video - def get_video_url(field_slug) - get_video_info( field_slug, 'url' ) - end - - # Get the video path based on the size provided, - # default is Carrierwave default (usually the real size) - # - # @param field_slug [string] The slug of the field setting - # @param size [string] The size. It can be 'thumb' 200x200 cropped, - # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank - # @return [string] The url of the video - def get_video_path(field_slug) - get_video_info( field_slug, 'path' ) - end - - # Get the object related to that field setting - # - # @param field_slug [string] The slug of the field setting - # @param info [string] String of the info to be retrieved - # @return [string] The info requested if present - # @return [boolean] Returns false if no info is found or if image isn't found - def get_video_info(field_slug, info) - obj = self.videos.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - # Alternative query - # obj = video.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first - raise ArgumentError, "There isn't any video associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - if obj.video.present? - obj.video.send(info) - end - end - - - # Check if the field has an attached audio - # - # @param field_slug [string] The slug of the field setting - # @return [boolean] - def has_audio(field_slug) - obj = self.audios.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - # Alternative query - # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first - raise ArgumentError, "There isn't any audio associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - return obj.audio.present? - end - - # Get the audio url based on the size provided, - # default is Carrierwave default (usually the real size) - # - # @param field_slug [string] The slug of the field setting - # @param size [string] The size. It can be 'thumb' 200x200 cropped, - # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank - # @return [string] The url of the audio - def get_audio_url(field_slug) - get_audio_info( field_slug, 'url' ) - end - - # Get the audio path based on the size provided, - # default is Carrierwave default (usually the real size) - # - # @param field_slug [string] The slug of the field setting - # @param size [string] The size. It can be 'thumb' 200x200 cropped, - # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank - # @return [string] The url of the audio - def get_audio_path(field_slug) - get_audio_info( field_slug, 'path' ) - end - - # Get the object related to that field setting - # - # @param field_slug [string] The slug of the field setting - # @param info [string] String of the info to be retrieved - # @return [string] The info requested if present - # @return [boolean] Returns false if no info is found or if image isn't found - def get_audio_info(field_slug, info) - obj = self.audios.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - # Alternative query - # obj = audio.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first - raise ArgumentError, "There isn't any audio associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - if obj.audio.present? - obj.audio.send(info) - end - end - - # Check if the field has an attached audio - # - # @param field_slug [string] The slug of the field setting - # @return [boolean] - def has_svg(field_slug) - obj = self.svgs.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - # Alternative query - # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first - raise ArgumentError, "There isn't any svg associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - return obj.svg.present? - end - - # Get the svg url based on the size provided, - # default is Carrierwave default (usually the real size) - # - # @param field_slug [string] The slug of the field setting - # @param size [string] The size. It can be 'thumb' 200x200 cropped, - # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank - # @return [string] The url of the svg - def get_svg_url(field_slug) - get_svg_info( field_slug, 'url' ) - end - - # Get the svg path based on the size provided, - # default is Carrierwave default (usually the real size) - # - # @param field_slug [string] The slug of the field setting - # @param size [string] The size. It can be 'thumb' 200x200 cropped, - # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank - # @return [string] The url of the svg - def get_svg_path(field_slug) - get_svg_info( field_slug, 'path' ) - end - - # Get the object related to that field setting - # - # @param field_slug [string] The slug of the field setting - # @param info [string] String of the info to be retrieved - # @return [string] The info requested if present - # @return [boolean] Returns false if no info is found or if image isn't found - def get_svg_info(field_slug, info) - obj = self.svgs.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - # Alternative query - # obj = svg.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first - raise ArgumentError, "There isn't any svg associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - if obj.svg.present? - obj.svg.send(info) - end - end - - def get_svg_size(field_slug) - obj = self.svgs.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - return bytes_to_megabytes(obj.file_size) - end - - # Get svg type - # - # @param field_slug [string] The slug of the field setting - # @return [string] with svg type - def get_svg_mime_type(field_slug) - obj = self.svgs.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - return obj.content_type - end - - # Check if the field has an attached date - # - # @param field_slug [string] The slug of the field setting - # @return [datetime] The date - # @return [boolean] Reutrn false if nothing is found - def has_date(field_slug) - obj = self.dates.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - raise ArgumentError, "There isn't any date associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - if obj.present? - return !obj.date.nil? - else - return false - end - end - - # Get the object related to that field setting - # - # @param field_slug [string] The slug of the field setting - # @return [boolean] - def get_date(field_slug) - obj = self.dates.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - raise ArgumentError, "There isn't any date associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - obj.date - end - - # Check if exists any repeater with that slug - # - # @param field_slug [string] The slug of the field setting - # @return [boolean] - def has_repeaters(field_slug) - obj = self.repeaters.find_all{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - raise ArgumentError, "There isn't any repeater associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - return obj.present? - end - def has_repeater(field_slug) - has_repeaters(field_slug) - end - - # Get the all repeater instances sorted by position - # - # @param field_slug [string] The slug of the field setting - # @return [array] An array of repeater items which have all sorts of fields attached - def get_repeaters(field_slug) - obj = self.repeaters.find_all{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - raise ArgumentError, "There isn't any repeater associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - obj.sort_by(&:position) - end - def get_repeater(field_slug) - get_repeaters(field_slug) - end - - # Get the radio choice - # - # If by mistake the Radio instance has many choices associated, - # only the first one will be retrieved. - # - # @param field_slug [string] The slug of the field setting - # @return [hash] A hash of containing the label and value of the selected choice. `{ label: 'the label', value: 'the value'}` - def get_radio_choice(field_slug) - field_setting = FieldSetting.find_by(slug:field_slug) - obj = self.radios.find{ |t| t.field_setting_id == field_setting.id } - raise ArgumentError, "There isn't any radio associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - raise "There isn't any choice available for the current radio (#{field_slug}) on instance (#{self.class.name} ##{self.id})." unless obj.choices.any? - return { label: obj.choices.first.label, value: obj.choices.first.value } - end - - # Get the select choices - # - # @param field_slug [string] The slug of the field setting - # @return [hash] A hash of containing the label and value of the selected choice. `{ label: 'the label', 'value': 'the value'}` - def get_selection_choice(field_slug) - field_setting = FieldSetting.find_by(slug:field_slug) - obj = self.selections.find{ |t| t.field_setting_id == field_setting.id } - raise ArgumentError, "There isn't any selection associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - raise "There isn't any choice available for the current selection (#{field_slug}) on instance (#{self.class.name} ##{self.id})." unless field_setting.choices.any? - return { label: obj.choices.first.label, value: obj.choices.first.value } - end - - # Get the select choices - # - # @param field_slug [string] The slug of the field setting - # @return [array] An array of hashes of containing label and value of the selected choices. `{ label: 'the label', 'value': 'the value'}` - def get_selection_choices(field_slug) - field_setting = FieldSetting.find_by(slug:field_slug) - obj = self.selections.find{ |t| t.field_setting_id == field_setting.id } - raise ArgumentError, "There isn't any selection associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - raise "There isn't any choice available for the current selection (#{field_slug}) on instance (#{self.class.name} ##{self.id})." unless field_setting.choices.any? - return obj.choices.map{|choice| { label: choice.label, value: choice.value }} - end - - # Get the checkbox choice - # - # @param field_slug [string] The slug of the field setting - # @return [array] An array of labels and values of the selected choices. `[{ label: '1st label', value: '1st-value'}, { label: '2nd label', value: '2nd-value'}]` - def get_checkbox_choices(field_slug) - field_setting = FieldSetting.find_by(slug:field_slug) - obj = self.checkboxes.find{ |t| t.field_setting_id == field_setting.id } - raise ArgumentError, "There isn't any checkbox associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - raise "There isn't any choice available for the current checkbox (#{field_slug}) on instance (#{self.class.name} ##{self.id})." unless field_setting.choices.any? - obj_array = [] - obj.choices.order('label').each do |o| - obj_array << { label: o.label, value: o.value } - end - return obj_array - end - - # Check if has related components - # - # @param field_slug [string] The slug of the field setting - # @return [boolean] - def has_related_components(field_slug) - obj = self.relations.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - raise ArgumentError, "There isn't any related field associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - return obj.dependent_relations.any? - end - - # Alias for has_related_components - def has_dependent_components(field_slug) - has_related_components(field_slug) - end - - # Get related components - # - # @param field_slug [string] The slug of the field setting - # @return [array] An array of components - def get_related_components(field_slug) - obj = self.relations.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - raise ArgumentError, "There isn't any related field associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - return obj.dependent_relations.map{|relation| relation.dependent} - end - - # Alias for get_related_components - def get_dependent_components(field_slug) - get_related_components(field_slug) - end - - # Get all components which owns a relation where the current instance is a dependent - # - # @param field_slug [string] The slug of the field setting of the relation - # @return [array] An array of components and/or boards - def get_owner_components(field_slug) - # obj = self.owner_relations.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - obj = Relation.where(field_setting_id: B.get_field_settings(field_slug)).includes(dependent_relations: :dependent).where(binda_relation_links: {dependent_type: self.class.name}) - raise ArgumentError, "There isn't any relation associated to the current slug (#{field_slug}) where the current instance (#{self.class.name} ##{self.id}) is a dependent.", caller if obj.nil? - return obj - end - - # Check if has related boards - # - # @param field_slug [string] The slug of the field setting - # @return [boolean] - def has_related_boards(field_slug) - obj = self.relations.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } - raise ArgumentError, "There isn't any related field associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - return obj.dependent_relations.any? - end - - # Get related boards - # - # @param field_slug [string] The slug of the field setting - # @return [array] An array of boards - def get_related_boards(field_slug) - obj = self.relations.find{ |t| t.field_setting_idid == FieldSetting.get_id( field_slug ) } - raise ArgumentError, "There isn't any related field associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? - return obj.dependent_relations.map{|relation| relation.dependent} - end end end \ No newline at end of file diff --git a/app/models/concerns/binda/fieldable_association_helpers/fieldable_audio_helpers.rb b/app/models/concerns/binda/fieldable_association_helpers/fieldable_audio_helpers.rb new file mode 100644 index 00000000..dc20f0c0 --- /dev/null +++ b/app/models/concerns/binda/fieldable_association_helpers/fieldable_audio_helpers.rb @@ -0,0 +1,55 @@ +module Binda + module FieldableAssociationHelpers + module FieldableAudioHelpers + # Check if the field has an attached audio + # + # @param field_slug [string] The slug of the field setting + # @return [boolean] + def has_audio(field_slug) + obj = self.audios.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + # Alternative query + # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first + raise ArgumentError, "There isn't any audio associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + return obj.audio.present? + end + + # Get the audio url based on the size provided, + # default is Carrierwave default (usually the real size) + # + # @param field_slug [string] The slug of the field setting + # @param size [string] The size. It can be 'thumb' 200x200 cropped, + # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank + # @return [string] The url of the audio + def get_audio_url(field_slug) + get_audio_info( field_slug, 'url' ) + end + + # Get the audio path based on the size provided, + # default is Carrierwave default (usually the real size) + # + # @param field_slug [string] The slug of the field setting + # @param size [string] The size. It can be 'thumb' 200x200 cropped, + # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank + # @return [string] The url of the audio + def get_audio_path(field_slug) + get_audio_info( field_slug, 'path' ) + end + + # Get the object related to that field setting + # + # @param field_slug [string] The slug of the field setting + # @param info [string] String of the info to be retrieved + # @return [string] The info requested if present + # @return [boolean] Returns false if no info is found or if image isn't found + def get_audio_info(field_slug, info) + obj = self.audios.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + # Alternative query + # obj = audio.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first + raise ArgumentError, "There isn't any audio associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + if obj.audio.present? + obj.audio.send(info) + end + end + end + end +end \ No newline at end of file diff --git a/app/models/concerns/binda/fieldable_association_helpers/fieldable_date_helpers.rb b/app/models/concerns/binda/fieldable_association_helpers/fieldable_date_helpers.rb new file mode 100644 index 00000000..4eb9528d --- /dev/null +++ b/app/models/concerns/binda/fieldable_association_helpers/fieldable_date_helpers.rb @@ -0,0 +1,30 @@ +module Binda + module FieldableAssociationHelpers + module FieldableDateHelpers + # Check if the field has an attached date + # + # @param field_slug [string] The slug of the field setting + # @return [datetime] The date + # @return [boolean] Reutrn false if nothing is found + def has_date(field_slug) + obj = self.dates.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + raise ArgumentError, "There isn't any date associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + if obj.present? + return !obj.date.nil? + else + return false + end + end + + # Get the object related to that field setting + # + # @param field_slug [string] The slug of the field setting + # @return [boolean] + def get_date(field_slug) + obj = self.dates.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + raise ArgumentError, "There isn't any date associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + obj.date + end + end + end +end \ No newline at end of file diff --git a/app/models/concerns/binda/fieldable_association_helpers/fieldable_image_helpers.rb b/app/models/concerns/binda/fieldable_association_helpers/fieldable_image_helpers.rb new file mode 100644 index 00000000..03e587ee --- /dev/null +++ b/app/models/concerns/binda/fieldable_association_helpers/fieldable_image_helpers.rb @@ -0,0 +1,95 @@ +module Binda + module FieldableAssociationHelpers + module FieldableImageHelpers + + # Check if the field has an attached image + # + # @param field_slug [string] The slug of the field setting + # @return [boolean] + def has_image(field_slug) + obj = self.images.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + # Alternative query + # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first + raise ArgumentError, "There isn't any image associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + return obj.image.present? + end + + # Get the image url based on the size provided, + # default is Carrierwave default (usually the real size) + # + # @param field_slug [string] The slug of the field setting + # @param size [string] The size. It can be 'thumb' 200x200 cropped, + # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank + # @return [string] The url of the image + def get_image_url(field_slug, size = '') + get_image_info( field_slug, size, 'url' ) + end + + # Get the image path based on the size provided, + # default is Carrierwave default (usually the real size) + # + # @param field_slug [string] The slug of the field setting + # @param size [string] The size. It can be 'thumb' 200x200 cropped, + # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank + # @return [string] The url of the image + def get_image_path(field_slug, size = '') + get_image_info( field_slug, size, 'path' ) + end + + # Get the object related to that field setting + # + # @param field_slug [string] The slug of the field setting + # @param size [string] The size. It can be 'thumb' 200x200 cropped, + # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank + # @param info [string] String of the info to be retrieved + # @return [string] The info requested if present + # @return [boolean] Returns false if no info is found or if image isn't found + def get_image_info(field_slug, size, info) + obj = self.images.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + # Alternative query + # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first + raise ArgumentError, "There isn't any image associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + if obj.image.present? && obj.image.respond_to?(size) && %w[thumb].include?(size) + obj.image.send(size).send(info) + elsif obj.image.present? + obj.image.send(info) + else + raise "Looks like the image you are looking for isn't present. See field setting with slug=\"#{field_slug}\" on component with id=\"self.id\"" + end + end + + # Get image size + # + # @param field_slug [string] The slug of the field setting + # @return [float] with image type + def get_image_size(field_slug) + obj = self.images.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + return bytes_to_megabytes(obj.file_size) + end + + # Get image type + # + # @param field_slug [string] The slug of the field setting + # @return [string] with image type + def get_image_mime_type(field_slug) + obj = self.images.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + return obj.content_type + end + + # Get image dimension + # + # @param field_slug [string] The slug of the field setting + # @return [hash] with width and height as floats + def get_image_dimension(field_slug) + obj = self.images.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + return { width: obj.file_width, height: obj.file_height } + end + + # Convert bytes to megabites + def bytes_to_megabytes bytes + (bytes.to_f / 1.megabyte).round(2) + end + + end + end +end \ No newline at end of file diff --git a/app/models/concerns/binda/fieldable_association_helpers/fieldable_relation_helpers.rb b/app/models/concerns/binda/fieldable_association_helpers/fieldable_relation_helpers.rb new file mode 100644 index 00000000..c9e355ca --- /dev/null +++ b/app/models/concerns/binda/fieldable_association_helpers/fieldable_relation_helpers.rb @@ -0,0 +1,68 @@ +module Binda + module FieldableAssociationHelpers + module FieldableRelationHelpers + + # Check if has related components + # + # @param field_slug [string] The slug of the field setting + # @return [boolean] + def has_related_components(field_slug) + obj = self.relations.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + raise ArgumentError, "There isn't any related field associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + return obj.dependent_relations.any? + end + + # Alias for has_related_components + def has_dependent_components(field_slug) + has_related_components(field_slug) + end + + # Get related components + # + # @param field_slug [string] The slug of the field setting + # @return [array] An array of components + def get_related_components(field_slug) + obj = self.relations.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + raise ArgumentError, "There isn't any related field associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + return obj.dependent_relations.map{|relation| relation.dependent} + end + + # Alias for get_related_components + def get_dependent_components(field_slug) + get_related_components(field_slug) + end + + # Get all components which owns a relation where the current instance is a dependent + # + # @param field_slug [string] The slug of the field setting of the relation + # @return [array] An array of components and/or boards + def get_owner_components(field_slug) + # obj = self.owner_relations.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + obj = Relation.where(field_setting_id: B.get_field_settings(field_slug)).includes(dependent_relations: :dependent).where(binda_relation_links: {dependent_type: self.class.name}) + raise ArgumentError, "There isn't any relation associated to the current slug (#{field_slug}) where the current instance (#{self.class.name} ##{self.id}) is a dependent.", caller if obj.nil? + return obj + end + + # Check if has related boards + # + # @param field_slug [string] The slug of the field setting + # @return [boolean] + def has_related_boards(field_slug) + obj = self.relations.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + raise ArgumentError, "There isn't any related field associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + return obj.dependent_relations.any? + end + + # Get related boards + # + # @param field_slug [string] The slug of the field setting + # @return [array] An array of boards + def get_related_boards(field_slug) + obj = self.relations.find{ |t| t.field_setting_idid == FieldSetting.get_id( field_slug ) } + raise ArgumentError, "There isn't any related field associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + return obj.dependent_relations.map{|relation| relation.dependent} + end + + end + end +end \ No newline at end of file diff --git a/app/models/concerns/binda/fieldable_association_helpers/fieldable_repeater_helpers.rb b/app/models/concerns/binda/fieldable_association_helpers/fieldable_repeater_helpers.rb new file mode 100644 index 00000000..916fd775 --- /dev/null +++ b/app/models/concerns/binda/fieldable_association_helpers/fieldable_repeater_helpers.rb @@ -0,0 +1,32 @@ +module Binda + module FieldableAssociationHelpers + module FieldableRepeaterHelpers + # Check if exists any repeater with that slug + # + # @param field_slug [string] The slug of the field setting + # @return [boolean] + def has_repeaters(field_slug) + obj = self.repeaters.find_all{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + raise ArgumentError, "There isn't any repeater associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + return obj.present? + end + def has_repeater(field_slug) + has_repeaters(field_slug) + end + + # Get the all repeater instances sorted by position + # + # @param field_slug [string] The slug of the field setting + # @return [array] An array of repeater items which have all sorts of fields attached + def get_repeaters(field_slug) + obj = self.repeaters.find_all{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + raise ArgumentError, "There isn't any repeater associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + obj.sort_by(&:position) + end + def get_repeater(field_slug) + get_repeaters(field_slug) + end + + end + end +end \ No newline at end of file diff --git a/app/models/concerns/binda/fieldable_association_helpers/fieldable_selection_helpers.rb b/app/models/concerns/binda/fieldable_association_helpers/fieldable_selection_helpers.rb new file mode 100644 index 00000000..9794b638 --- /dev/null +++ b/app/models/concerns/binda/fieldable_association_helpers/fieldable_selection_helpers.rb @@ -0,0 +1,60 @@ +module Binda + module FieldableAssociationHelpers + module FieldableSelectionHelpers + # Get the radio choice + # + # If by mistake the Radio instance has many choices associated, + # only the first one will be retrieved. + # + # @param field_slug [string] The slug of the field setting + # @return [hash] A hash of containing the label and value of the selected choice. `{ label: 'the label', value: 'the value'}` + def get_radio_choice(field_slug) + field_setting = FieldSetting.find_by(slug:field_slug) + obj = self.radios.find{ |t| t.field_setting_id == field_setting.id } + raise ArgumentError, "There isn't any radio associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + raise "There isn't any choice available for the current radio (#{field_slug}) on instance (#{self.class.name} ##{self.id})." unless obj.choices.any? + return { label: obj.choices.first.label, value: obj.choices.first.value } + end + + # Get the select choices + # + # @param field_slug [string] The slug of the field setting + # @return [hash] A hash of containing the label and value of the selected choice. `{ label: 'the label', 'value': 'the value'}` + def get_selection_choice(field_slug) + field_setting = FieldSetting.find_by(slug:field_slug) + obj = self.selections.find{ |t| t.field_setting_id == field_setting.id } + raise ArgumentError, "There isn't any selection associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + raise "There isn't any choice available for the current selection (#{field_slug}) on instance (#{self.class.name} ##{self.id})." unless field_setting.choices.any? + return { label: obj.choices.first.label, value: obj.choices.first.value } + end + + # Get the select choices + # + # @param field_slug [string] The slug of the field setting + # @return [array] An array of hashes of containing label and value of the selected choices. `{ label: 'the label', 'value': 'the value'}` + def get_selection_choices(field_slug) + field_setting = FieldSetting.find_by(slug:field_slug) + obj = self.selections.find{ |t| t.field_setting_id == field_setting.id } + raise ArgumentError, "There isn't any selection associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + raise "There isn't any choice available for the current selection (#{field_slug}) on instance (#{self.class.name} ##{self.id})." unless field_setting.choices.any? + return obj.choices.map{|choice| { label: choice.label, value: choice.value }} + end + + # Get the checkbox choice + # + # @param field_slug [string] The slug of the field setting + # @return [array] An array of labels and values of the selected choices. `[{ label: '1st label', value: '1st-value'}, { label: '2nd label', value: '2nd-value'}]` + def get_checkbox_choices(field_slug) + field_setting = FieldSetting.find_by(slug:field_slug) + obj = self.checkboxes.find{ |t| t.field_setting_id == field_setting.id } + raise ArgumentError, "There isn't any checkbox associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + raise "There isn't any choice available for the current checkbox (#{field_slug}) on instance (#{self.class.name} ##{self.id})." unless field_setting.choices.any? + obj_array = [] + obj.choices.order('label').each do |o| + obj_array << { label: o.label, value: o.value } + end + return obj_array + end + end + end +end \ No newline at end of file diff --git a/app/models/concerns/binda/fieldable_association_helpers/fieldable_string_helpers.rb b/app/models/concerns/binda/fieldable_association_helpers/fieldable_string_helpers.rb new file mode 100644 index 00000000..cab481c3 --- /dev/null +++ b/app/models/concerns/binda/fieldable_association_helpers/fieldable_string_helpers.rb @@ -0,0 +1,56 @@ +module Binda + module FieldableAssociationHelpers + module FieldableStringHelpers + + # Get the object related to that field setting + # If the object doesn't exists yet it will return nil + # + # @param field_slug [string] The slug of the field setting + # @return [string] Returns the content of the string + # @return [error] Raise an error if no record is found + def get_string(field_slug) + obj = Text + .includes(:field_setting) + .where(fieldable_id: self.id, fieldable_type: self.class.name) + .where(binda_field_settings: { slug: field_slug, field_type: "string" }) + .first + unless obj.nil? + # to_s ensures the returned object is class String + obj.content.to_s + else + check_string_error field_slug + end + end + + # Check why get_string doesn't return a value + # This method isn't supposed to be used by anything other than get_string method + def check_string_error(field_slug) + you_mean_text = !self.strings.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) && t.type == 'Binda::Text' }.nil? + if you_mean_text + raise ArgumentError, "This slug (#{field_slug}) is associated to a text not a string. Use get_text() instead on instance (#{self.class.name} ##{self.id}).", caller + else + raise ArgumentError, "There isn't any string associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller + end + end + + # Get the object related to that field setting + # + # @param field_slug [string] The slug of the field setting + # @return [boolean] + def has_string(field_slug) + obj = Text + .includes(:field_setting) + .where(fieldable_id: self.id, fieldable_type: self.class.name) + .where(binda_field_settings: { slug: field_slug, field_type: "string" }) + .first + raise ArgumentError, "There isn't any string associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + if obj.present? + return !obj.content.nil? + else + return false + end + end + + end + end +end \ No newline at end of file diff --git a/app/models/concerns/binda/fieldable_association_helpers/fieldable_svg_helpers.rb b/app/models/concerns/binda/fieldable_association_helpers/fieldable_svg_helpers.rb new file mode 100644 index 00000000..7db22b45 --- /dev/null +++ b/app/models/concerns/binda/fieldable_association_helpers/fieldable_svg_helpers.rb @@ -0,0 +1,74 @@ +module Binda + module FieldableAssociationHelpers + module FieldableSvgHelpers + # Check if the field has an attached audio + # + # @param field_slug [string] The slug of the field setting + # @return [boolean] + def has_svg(field_slug) + obj = self.svgs.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + # Alternative query + # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first + raise ArgumentError, "There isn't any svg associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + return obj.svg.present? + end + + # Get the svg url based on the size provided, + # default is Carrierwave default (usually the real size) + # + # @param field_slug [string] The slug of the field setting + # @param size [string] The size. It can be 'thumb' 200x200 cropped, + # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank + # @return [string] The url of the svg + def get_svg_url(field_slug) + get_svg_info( field_slug, 'url' ) + end + + # Get the svg path based on the size provided, + # default is Carrierwave default (usually the real size) + # + # @param field_slug [string] The slug of the field setting + # @param size [string] The size. It can be 'thumb' 200x200 cropped, + # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank + # @return [string] The url of the svg + def get_svg_path(field_slug) + get_svg_info( field_slug, 'path' ) + end + + # Get the object related to that field setting + # + # @param field_slug [string] The slug of the field setting + # @param info [string] String of the info to be retrieved + # @return [string] The info requested if present + # @return [boolean] Returns false if no info is found or if image isn't found + def get_svg_info(field_slug, info) + obj = self.svgs.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + # Alternative query + # obj = svg.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first + raise ArgumentError, "There isn't any svg associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + if obj.svg.present? + obj.svg.send(info) + end + end + + def get_svg_size(field_slug) + obj = self.svgs.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + return bytes_to_megabytes(obj.file_size) + end + + # Get svg type + # + # @param field_slug [string] The slug of the field setting + # @return [string] with svg type + def get_svg_mime_type(field_slug) + obj = self.svgs.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + return obj.content_type + end + + # Convert bytes to megabites + def bytes_to_megabytes bytes + (bytes.to_f / 1.megabyte).round(2) + end + end + end +end \ No newline at end of file diff --git a/app/models/concerns/binda/fieldable_association_helpers/fieldable_text_helpers.rb b/app/models/concerns/binda/fieldable_association_helpers/fieldable_text_helpers.rb new file mode 100644 index 00000000..aaa6ce22 --- /dev/null +++ b/app/models/concerns/binda/fieldable_association_helpers/fieldable_text_helpers.rb @@ -0,0 +1,59 @@ +module Binda + module FieldableAssociationHelpers + module FieldableTextHelpers + + extend ActiveSupport::Concern + # Get the object related to that field setting + # If the object doesn't exists yet it will return nil + # + # @param field_slug [string] The slug of the field setting + # @return [string] Returns the content of the text + # @return [error] Raise an error if no record is found + def get_text(field_slug) + obj = Text + .includes(:field_setting) + .where(fieldable_id: self.id, fieldable_type: self.class.name) + .where(binda_field_settings: { slug: field_slug }) + .where.not(binda_field_settings: { field_type: "string" }) + .first + unless obj.nil? + # to_s ensures the returned object is class String + obj.content.to_s + else + check_text_error field_slug + end + end + + # Check why get_text doesn't return a value + # This method isn't supposed to be used by anything other than get_text method + def check_text_error(field_slug) + you_mean_string = !self.strings.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) && t.type == 'Binda::String' }.nil? + if you_mean_string + raise ArgumentError, "This slug (#{field_slug}) is associated to a string not a text. Use get_string() instead on instance (#{self.class.name} ##{self.id}).", caller + else + raise ArgumentError, "There isn't any text associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller + end + end + + # Get the object related to that field setting + # + # @param field_slug [string] The slug of the field setting + # @return [boolean] + def has_text(field_slug) + obj = Text + .includes(:field_setting) + .where(fieldable_id: self.id, fieldable_type: self.class.name) + .where(binda_field_settings: { slug: field_slug }) + .where.not(binda_field_settings: { field_type: "string" }) + .first + raise ArgumentError, "There isn't any text associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + if obj.present? + return !obj.content.nil? + else + return false + end + end + + end + end +end \ No newline at end of file diff --git a/app/models/concerns/binda/fieldable_association_helpers/fieldable_video_helpers.rb b/app/models/concerns/binda/fieldable_association_helpers/fieldable_video_helpers.rb new file mode 100644 index 00000000..7ff76382 --- /dev/null +++ b/app/models/concerns/binda/fieldable_association_helpers/fieldable_video_helpers.rb @@ -0,0 +1,56 @@ +module Binda + module FieldableAssociationHelpers + module FieldableVideoHelpers + + # Check if the field has an attached video + # + # @param field_slug [string] The slug of the field setting + # @return [boolean] + def has_video(field_slug) + obj = self.videos.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + # Alternative query + # obj = Image.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first + raise ArgumentError, "There isn't any video associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + return obj.video.present? + end + + # Get the video url based on the size provided, + # default is Carrierwave default (usually the real size) + # + # @param field_slug [string] The slug of the field setting + # @param size [string] The size. It can be 'thumb' 200x200 cropped, + # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank + # @return [string] The url of the video + def get_video_url(field_slug) + get_video_info( field_slug, 'url' ) + end + + # Get the video path based on the size provided, + # default is Carrierwave default (usually the real size) + # + # @param field_slug [string] The slug of the field setting + # @param size [string] The size. It can be 'thumb' 200x200 cropped, + # 'medium' 700x700 max size, 'large' 1400x1400 max size, or blank + # @return [string] The url of the video + def get_video_path(field_slug) + get_video_info( field_slug, 'path' ) + end + + # Get the object related to that field setting + # + # @param field_slug [string] The slug of the field setting + # @param info [string] String of the info to be retrieved + # @return [string] The info requested if present + # @return [boolean] Returns false if no info is found or if image isn't found + def get_video_info(field_slug, info) + obj = self.videos.find{ |t| t.field_setting_id == FieldSetting.get_id( field_slug ) } + # Alternative query + # obj = video.where(field_setting_id: FieldSetting.get_id( field_slug ), fieldable_id: self.id, fieldable_type: self.class.to_s ).first + raise ArgumentError, "There isn't any video associated to the current slug (#{field_slug}) on instance (#{self.class.name} ##{self.id}).", caller if obj.nil? + if obj.video.present? + obj.video.send(info) + end + end + end + end +end diff --git a/spec/controllers/binda/boards_controller_spec.rb b/spec/controllers/binda/boards_controller_spec.rb index 3ef8d359..48ccf021 100644 --- a/spec/controllers/binda/boards_controller_spec.rb +++ b/spec/controllers/binda/boards_controller_spec.rb @@ -63,7 +63,7 @@ module Binda it "create a new repeater with correct position" do @board.reload # apparently this is needed as the variable isn't updated to reflect the real record state initial_repeaters_length = @board.repeaters.length - repeater_setting = Binda::FieldSetting + repeater_setting = FieldSetting .includes(:field_group) .where( binda_field_groups: { structure_id: @structure.id }, diff --git a/spec/controllers/binda/components_controller_spec.rb b/spec/controllers/binda/components_controller_spec.rb index bd2b9e2e..727b7591 100644 --- a/spec/controllers/binda/components_controller_spec.rb +++ b/spec/controllers/binda/components_controller_spec.rb @@ -69,7 +69,7 @@ module Binda it "creates a new repeater with correct position" do initial_repeaters_length = @component.repeaters.length - repeater_setting = Binda::FieldSetting + repeater_setting = FieldSetting .includes(:field_group) .where( binda_field_groups: { structure_id: @structure.id }, diff --git a/spec/lib/generators/binda/setup_generator_spec.rb b/spec/lib/generators/binda/setup_generator_spec.rb index 680bd545..8c9cda53 100644 --- a/spec/lib/generators/binda/setup_generator_spec.rb +++ b/spec/lib/generators/binda/setup_generator_spec.rb @@ -34,9 +34,9 @@ module Binda end it "creates one maintenance mode field" do - maintenance_mode_array = Binda::Radio + maintenance_mode_array = Radio .where( - field_setting_id: Binda::FieldSetting.where( + field_setting_id: FieldSetting.where( slug: 'maintenance-mode' ).ids ) @@ -44,9 +44,9 @@ module Binda end it "assigns one choice to the maintenance mode field" do - maintenance_mode = Binda::Radio + maintenance_mode = Radio .where( - field_setting_id: Binda::FieldSetting.where( + field_setting_id: FieldSetting.where( slug: 'maintenance-mode' ).ids ).first @@ -54,9 +54,9 @@ module Binda end it "set maintenance mode as disabled" do - maintenance_mode_choice = Binda::Radio + maintenance_mode_choice = Radio .where( - field_setting_id: Binda::FieldSetting.where( + field_setting_id: FieldSetting.where( slug: 'maintenance-mode' ) .ids @@ -69,13 +69,13 @@ module Binda end it "sets a dashboard structure" do - expect(Binda::Structure.all.any?).to be true - expect(Binda::Structure.where(slug: 'dashboard').length).to eq 1 + expect(Structure.all.any?).to be true + expect(Structure.where(slug: 'dashboard').length).to eq 1 end it "sets website name" do - dashboard = Binda::Board.where(slug: 'dashboard').first - website_name = Binda::String + dashboard = Board.where(slug: 'dashboard').first + website_name = String .includes(:field_setting) .where( binda_texts: { fieldable_id: dashboard.id, fieldable_type: dashboard.class.name}, @@ -86,8 +86,8 @@ module Binda end it "sets website description" do - dashboard = Binda::Board.where(slug: 'dashboard').first - website_desc = Binda::Text + dashboard = Board.where(slug: 'dashboard').first + website_desc = Text .includes(:field_setting) .where( binda_texts: { fieldable_id: dashboard.id, fieldable_type: dashboard.class.name}, @@ -114,7 +114,7 @@ module Binda end it "can create a default user" do - expect(Binda::User.where(email: 'new@admin.com').present?).to be true + expect(User.where(email: 'new@admin.com').present?).to be true end end end diff --git a/spec/models/binda/field_setting_spec.rb b/spec/models/binda/field_setting_spec.rb index d4e2d44a..7e5617f1 100644 --- a/spec/models/binda/field_setting_spec.rb +++ b/spec/models/binda/field_setting_spec.rb @@ -156,7 +156,7 @@ module Binda component = @radio_setting.structure.components.create(name:'my component') # Get directly that radio - radio = Binda::Radio.where( + radio = Radio.where( field_setting_id: @radio_setting.id, fieldable_id: component.id, fieldable_type: component.class.name @@ -193,7 +193,7 @@ module Binda # Get directly that radio expect{ - Binda::Radio.where( + Radio.where( field_setting_id: @radio_setting.id, fieldable_id: board.id, fieldable_type: board.class.name @@ -238,7 +238,7 @@ module Binda end it "generates a error if field group isn't specified" do - expect{Binda::FieldSetting.create!(name: 'foo', field_type: 'text')}.to raise_error ActiveRecord::RecordInvalid + expect{FieldSetting.create!(name: 'foo', field_type: 'text')}.to raise_error ActiveRecord::RecordInvalid end # test method Binda::FieldSetting.remove_orphan_fields diff --git a/spec/models/binda/image_spec.rb b/spec/models/binda/image_spec.rb index f34a62d9..9fafd375 100644 --- a/spec/models/binda/image_spec.rb +++ b/spec/models/binda/image_spec.rb @@ -6,7 +6,7 @@ module Binda include CarrierWave::Test::Matchers before(:context) do - Binda::Image::ImageUploader.enable_processing = true + Image::ImageUploader.enable_processing = true end before(:example) do @@ -15,7 +15,7 @@ module Binda end after(:context) do - Binda::Image::ImageUploader.enable_processing = false + Image::ImageUploader.enable_processing = false end it "stores height and width" do diff --git a/spec/models/binda/selection_spec.rb b/spec/models/binda/selection_spec.rb index 2664a09d..243c74f7 100644 --- a/spec/models/binda/selection_spec.rb +++ b/spec/models/binda/selection_spec.rb @@ -51,7 +51,7 @@ module Binda # At this point we have an situation: # selection it's now required to have a choice, but it has none. # Let's fix it! - expect{Binda::Selection.add_default_choice_to_all_selections_with_no_choices}.not_to raise_error + expect{Selection.add_default_choice_to_all_selections_with_no_choices}.not_to raise_error @selection.reload expect(@selection.choices.empty?).to be false @@ -68,7 +68,7 @@ module Binda # At this point we have an situation: # selection it's now required to have a choice, but it has none. # Let's fix it! - expect{Binda::Selection.add_default_choice_to_all_selections_with_no_choices}.to raise_error RuntimeError + expect{Selection.add_default_choice_to_all_selections_with_no_choices}.to raise_error RuntimeError # but the above cannot work as there are no choices at all! end