diff --git a/app/components/maglev/content/builder.rb b/app/components/maglev/content/builder.rb index b32366ce..842a9bbb 100644 --- a/app/components/maglev/content/builder.rb +++ b/app/components/maglev/content/builder.rb @@ -3,26 +3,19 @@ module Maglev module Content module Builder - TYPES = { - text: Maglev::Content::Text, - image: Maglev::Content::Image, - link: Maglev::Content::Link, - checkbox: Maglev::Content::Checkbox, - color: Maglev::Content::Color, - select: Maglev::Content::Select, - collection_item: Maglev::Content::CollectionItem, - icon: Maglev::Content::Icon - }.freeze - def build(scope, content, setting) - klass = TYPES[setting.type.to_sym] + klass = find_klass(setting.type.to_sym) raise "[Maglev] Unknown setting type: #{setting.type}" unless klass klass.new(scope, content, setting) end - module_function :build + def find_klass(type) + Maglev::Content.const_get(type.to_s.camelize) + end + + module_function :build, :find_klass end end end diff --git a/app/javascript/editor/components/dynamic-form/dynamic-input.vue b/app/javascript/editor/components/dynamic-form/dynamic-input.vue deleted file mode 100644 index 21473573..00000000 --- a/app/javascript/editor/components/dynamic-form/dynamic-input.vue +++ /dev/null @@ -1,120 +0,0 @@ - - - diff --git a/app/javascript/editor/components/dynamic-form/dynamic-input/checkbox.vue b/app/javascript/editor/components/dynamic-form/dynamic-input/checkbox.vue new file mode 100644 index 00000000..ddaf9775 --- /dev/null +++ b/app/javascript/editor/components/dynamic-form/dynamic-input/checkbox.vue @@ -0,0 +1,16 @@ + + + diff --git a/app/javascript/editor/components/dynamic-form/dynamic-input/collection-item.vue b/app/javascript/editor/components/dynamic-form/dynamic-input/collection-item.vue new file mode 100644 index 00000000..21b2e00b --- /dev/null +++ b/app/javascript/editor/components/dynamic-form/dynamic-input/collection-item.vue @@ -0,0 +1,16 @@ + + + diff --git a/app/javascript/editor/components/dynamic-form/dynamic-input/color.vue b/app/javascript/editor/components/dynamic-form/dynamic-input/color.vue new file mode 100644 index 00000000..7af83af9 --- /dev/null +++ b/app/javascript/editor/components/dynamic-form/dynamic-input/color.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/javascript/editor/components/dynamic-form/dynamic-input/dictionnary.js b/app/javascript/editor/components/dynamic-form/dynamic-input/dictionnary.js new file mode 100644 index 00000000..451b059b --- /dev/null +++ b/app/javascript/editor/components/dynamic-form/dynamic-input/dictionnary.js @@ -0,0 +1,41 @@ +import DynamicInputMixin from '@/mixins/dynamic-input' + +import TextInput from './text' +import ImageInput from './image' +import ColorInput from './color' +import LinkInput from './link' +import CheckboxInput from './checkbox' +import SelectInput from './select' +import IconInput from './icon' +import CollectionItemInput from './collection-item' + +let registeredInputs = {} + +// key names must be "underscored" (since they're coming from the Rails API) +const CORE_INPUTS = { + text: TextInput, + image: ImageInput, + color: ColorInput, + link: LinkInput, + checkbox: CheckboxInput, + select: SelectInput, + icon: IconInput, + collection_item: CollectionItemInput, +} + +export const register = (type, component) => { + registeredInputs[type] = component +} + +export const get = (type) => { + const component = registeredInputs[type] || CORE_INPUTS[type] + + if (!component) { + console.log(`[Maglev] we couldn't find a component for the "${type}" type`) + } + + return component +} + +window.registerMaglevSetting = register +window.maglevSettingMixin = DynamicInputMixin diff --git a/app/javascript/editor/components/dynamic-form/dynamic-input/icon.vue b/app/javascript/editor/components/dynamic-form/dynamic-input/icon.vue new file mode 100644 index 00000000..5763a178 --- /dev/null +++ b/app/javascript/editor/components/dynamic-form/dynamic-input/icon.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/javascript/editor/components/dynamic-form/dynamic-input/image.vue b/app/javascript/editor/components/dynamic-form/dynamic-input/image.vue new file mode 100644 index 00000000..93b91b2f --- /dev/null +++ b/app/javascript/editor/components/dynamic-form/dynamic-input/image.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/javascript/editor/components/dynamic-form/dynamic-input/index.vue b/app/javascript/editor/components/dynamic-form/dynamic-input/index.vue new file mode 100644 index 00000000..b59d10db --- /dev/null +++ b/app/javascript/editor/components/dynamic-form/dynamic-input/index.vue @@ -0,0 +1,37 @@ + + + diff --git a/app/javascript/editor/components/dynamic-form/dynamic-input/link.vue b/app/javascript/editor/components/dynamic-form/dynamic-input/link.vue new file mode 100644 index 00000000..b0ec82ab --- /dev/null +++ b/app/javascript/editor/components/dynamic-form/dynamic-input/link.vue @@ -0,0 +1,23 @@ + + + diff --git a/app/javascript/editor/components/dynamic-form/dynamic-input/select.vue b/app/javascript/editor/components/dynamic-form/dynamic-input/select.vue new file mode 100644 index 00000000..ef69ea8e --- /dev/null +++ b/app/javascript/editor/components/dynamic-form/dynamic-input/select.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/javascript/editor/components/dynamic-form/dynamic-input/text.vue b/app/javascript/editor/components/dynamic-form/dynamic-input/text.vue new file mode 100644 index 00000000..abfaac03 --- /dev/null +++ b/app/javascript/editor/components/dynamic-form/dynamic-input/text.vue @@ -0,0 +1,54 @@ + + + diff --git a/app/javascript/editor/mixins/dynamic-input.js b/app/javascript/editor/mixins/dynamic-input.js new file mode 100644 index 00000000..a3c90d33 --- /dev/null +++ b/app/javascript/editor/mixins/dynamic-input.js @@ -0,0 +1,23 @@ +export default { + props: { + setting: { type: Object, default: () => ({ type: 'text' }) }, + value: { required: true }, + isFocused: { type: Boolean, default: false }, + options: { type: Object }, + }, + computed: { + inputValue: { + get() { + return this.value + }, + set(value) { + this.$emit('change', { + settingId: this.setting.id, + settingType: this.setting.type, + settingOptions: this.setting.options, + value, + }) + }, + }, + }, +} diff --git a/app/models/maglev/section/setting.rb b/app/models/maglev/section/setting.rb index c367554a..b441b441 100644 --- a/app/models/maglev/section/setting.rb +++ b/app/models/maglev/section/setting.rb @@ -2,6 +2,8 @@ # rubocop:disable Style/ClassAndModuleChildren class Maglev::Section::Setting + DEFAULT_TYPES = %w[text image checkbox link color select collection_item icon].freeze + ## concerns ## include ActiveModel::Model @@ -10,17 +12,18 @@ class Maglev::Section::Setting ## validations ## validates :id, :label, :type, :default, 'maglev/presence': true - validates :type, inclusion: { in: %w[text image checkbox link color select collection_item icon] } + validates :type, inclusion: { in: DEFAULT_TYPES + Maglev.config.custom_setting_types } ## methods ## # NOTE: any modification to that method must be reflected to the JS editor def build_default_content(custom_default = nil) default = custom_default || self.default - case type.to_sym - when :image then build_default_image_content(default) - when :link then build_default_link_content(default) - when :checkbox then build_default_checkbox_content(default) + + default_method_name = :"build_default_#{type}_content" + + if respond_to?(default_method_name) + public_send(default_method_name, default) else default || label end diff --git a/lib/maglev.rb b/lib/maglev.rb index 1653b188..47f278d4 100644 --- a/lib/maglev.rb +++ b/lib/maglev.rb @@ -39,6 +39,7 @@ def config c.admin_password = nil c.static_pages = [] c.reserved_paths = [] + c.custom_setting_types = [] end end # rubocop:enable Metrics/MethodLength, Metrics/AbcSize diff --git a/lib/maglev/config.rb b/lib/maglev/config.rb index 3b968c5c..6467e8ad 100644 --- a/lib/maglev/config.rb +++ b/lib/maglev/config.rb @@ -3,6 +3,6 @@ module Maglev Config = Struct.new(:primary_color, :title, :favicon, :logo, :back_action, :uploader, :services, :collections, :is_authenticated, :ui_locale, :default_site_locales, - :static_pages, :reserved_paths, + :static_pages, :reserved_paths, :custom_setting_types, :admin_username, :admin_password) end