diff --git a/app/controllers/admin/custom_field_sections_controller.rb b/app/controllers/admin/custom_field_sections_controller.rb index 3f1e577d..152440f5 100644 --- a/app/controllers/admin/custom_field_sections_controller.rb +++ b/app/controllers/admin/custom_field_sections_controller.rb @@ -51,6 +51,7 @@ def custom_field_section_params custom_fields_attributes: [ :id, :key, + :label, :field_type, :hint, :options, diff --git a/app/controllers/admin/services_controller.rb b/app/controllers/admin/services_controller.rb index c220a16e..194089b6 100644 --- a/app/controllers/admin/services_controller.rb +++ b/app/controllers/admin/services_controller.rb @@ -192,6 +192,7 @@ def service_params ], meta_attributes: [ :id, + :label, :key, :value ] diff --git a/app/controllers/api/v1/custom_fields_controller.rb b/app/controllers/api/v1/custom_fields_controller.rb new file mode 100644 index 00000000..11c83a0f --- /dev/null +++ b/app/controllers/api/v1/custom_fields_controller.rb @@ -0,0 +1,39 @@ +class API::V1::CustomFieldsController < ApplicationController + skip_before_action :authenticate_user! + + def index + render json: json_tree(CustomFieldSection.api_public.includes(:custom_fields)).to_json + end + + private + + def json_tree(custom_field_sections) + custom_field_sections.map do |section| + { + id: section.id, + name: section.name, + hint: section.hint, + custom_fields: section.custom_fields.map do |field| + field_hash = { + id: field.id, + label: field.label, + key: field.key, + hint: field.hint, + field_type: field.field_type + } + field_hash[:options] = process_options(field.options) if field.field_type == 'select' + field_hash + end + } + end + end + + def process_options(options_string) + options_string.split(',').map.with_index(1) do |option, index| + { + value: option.strip, + # key: option.strip.parameterize + } + end + end + end \ No newline at end of file diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb index 74c4cfc4..bd71b817 100644 --- a/app/controllers/services_controller.rb +++ b/app/controllers/services_controller.rb @@ -158,6 +158,7 @@ def service_params meta_attributes: [ :id, :key, + :label, :value ] ) diff --git a/app/models/custom_field.rb b/app/models/custom_field.rb index 6ada0bd0..9190cc05 100644 --- a/app/models/custom_field.rb +++ b/app/models/custom_field.rb @@ -1,5 +1,8 @@ class CustomField < ApplicationRecord - validates :key, presence: true, uniqueness: true + before_validation :slugify_key + + validates :key, uniqueness: true, format: { with: /\A[a-z0-9\-]+\z/, message: "must be lowercase, numbers, and dashes only" } + validates :label, presence: true, uniqueness: true validates_presence_of :field_type belongs_to :custom_field_section, counter_cache: :custom_fields_count @@ -12,4 +15,12 @@ def self.types "Date" ] end + + private + + def slugify_key + self.key = key.to_s.parameterize if key.present? + end + + end diff --git a/app/models/custom_field_section.rb b/app/models/custom_field_section.rb index 00b70f15..ec626193 100644 --- a/app/models/custom_field_section.rb +++ b/app/models/custom_field_section.rb @@ -7,4 +7,6 @@ class CustomFieldSection < ApplicationRecord default_scope { order(sort_order: :asc) } scope :visible_to, -> (current_user){ current_user.admin ? all : where(public: true) } + + scope :api_public, -> { where(api_public: true) } end diff --git a/app/models/service_meta.rb b/app/models/service_meta.rb index ec884597..96175f36 100644 --- a/app/models/service_meta.rb +++ b/app/models/service_meta.rb @@ -1,5 +1,5 @@ class ServiceMeta < ApplicationRecord belongs_to :service - validates :key, presence: true - validates_uniqueness_of :key, scope: :service_id + validates :label, presence: true + validates_uniqueness_of :label, scope: :service_id end diff --git a/app/serializers/service_meta_serializer.rb b/app/serializers/service_meta_serializer.rb index c6f03512..b70b20a0 100644 --- a/app/serializers/service_meta_serializer.rb +++ b/app/serializers/service_meta_serializer.rb @@ -1,5 +1,6 @@ class ServiceMetaSerializer < ActiveModel::Serializer + attribute :label attribute :key attribute :value end \ No newline at end of file diff --git a/app/views/admin/custom_field_sections/_fields.html.erb b/app/views/admin/custom_field_sections/_fields.html.erb index 38f81cd2..701c2d57 100644 --- a/app/views/admin/custom_field_sections/_fields.html.erb +++ b/app/views/admin/custom_field_sections/_fields.html.erb @@ -39,7 +39,7 @@ <ul class="repeater__panels" aria-live="polite"> <%= f.fields_for :custom_fields do |c| %> <li class="repeater__panel" data-custom-fields> - <%= render "admin/custom_field_sections/repeatable-fields", c: c %> + <%= render "admin/custom_field_sections/repeatable-fields", c: c, section: f.object %> </li> <% end %> </ul> diff --git a/app/views/admin/custom_field_sections/_repeatable-fields.html.erb b/app/views/admin/custom_field_sections/_repeatable-fields.html.erb index 0c413a81..efa2d02e 100644 --- a/app/views/admin/custom_field_sections/_repeatable-fields.html.erb +++ b/app/views/admin/custom_field_sections/_repeatable-fields.html.erb @@ -1,7 +1,7 @@ <div class="field-group field-group--two-cols"> <div class="field field--required"> - <%= c.label :key, "Label", class: "field__label" %> - <%= c.text_field :key, class: "field__input" %> + <%= c.label :label, "Label", class: "field__label" %> + <%= c.text_field :label, class: "field__input" %> </div> <div class="field field--required"> @@ -20,6 +20,15 @@ <%= c.text_area :hint, class: "field__input", rows: 1 %> </div> +<% if @section.api_public %> +<div class="field"> + <%= c.label :key, "Key", class: "field__label" %> + <p class="field__hint">This is a unique field used to refer to this field in the API</p> + <%= c.text_field :key, class: "field__input", data: { slugify: true } %> +</div> +<% end %> + + <%= c.hidden_field :_destroy, data: {destroy_field: true} %> <button type="button" class="repeater__closer" data-close="true" title="Remove this field">Remove this field</button> \ No newline at end of file diff --git a/app/views/admin/services/editors/_custom-fields.html.erb b/app/views/admin/services/editors/_custom-fields.html.erb index e7a12746..d1367a83 100644 --- a/app/views/admin/services/editors/_custom-fields.html.erb +++ b/app/views/admin/services/editors/_custom-fields.html.erb @@ -8,20 +8,21 @@ <% end %> <% section.custom_fields.each do |field| %> - <% meta = s.object.meta.find_or_initialize_by(key: field.key) %> + <% meta = s.object.meta.find_or_initialize_by(label: field.label, key: field.key) %> <%= s.fields_for :meta, meta do |c| %> + <%= c.hidden_field :label %> <%= c.hidden_field :key %> <% if field.field_type === "checkbox" %> <div class="field"> <div class="checkbox"> <%= c.check_box :value, {class: "checkbox__input"}, "Yes", "No" %> - <%= c.label :value, field.key, class: "checkbox__label" %> + <%= c.label :value, field.label, class: "checkbox__label" %> </div> </div> <% else %> <div class="field"> - <%= c.label :value, field.key, class: "field__label" %> + <%= c.label :value, field.label, class: "field__label" %> <% if field.hint.present? %> <p class="field__hint"><%= field.hint %></p> <% end %> diff --git a/config/routes.rb b/config/routes.rb index c8bbf451..c50a37ef 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -82,6 +82,7 @@ resources :accessibilities, only: [:index] get "me", to: "me#show" resources :services, only: [:index, :show] + resources :custom_fields, only: [:index] end end diff --git a/db/migrate/20241111163850_add_custom_field_label.rb b/db/migrate/20241111163850_add_custom_field_label.rb new file mode 100644 index 00000000..53b64363 --- /dev/null +++ b/db/migrate/20241111163850_add_custom_field_label.rb @@ -0,0 +1,14 @@ +class AddCustomFieldLabel < ActiveRecord::Migration[6.0] + def change + # Add new label column + add_column :custom_fields, :label, :string + + # Copy data from key to label (only on up migration) + reversible do |dir| + dir.up do + CustomField.reset_column_information + CustomField.update_all('label = key') + end + end + end +end diff --git a/db/migrate/20241111181710_add_service_meta_label.rb b/db/migrate/20241111181710_add_service_meta_label.rb new file mode 100644 index 00000000..7eab7033 --- /dev/null +++ b/db/migrate/20241111181710_add_service_meta_label.rb @@ -0,0 +1,14 @@ +class AddServiceMetaLabel < ActiveRecord::Migration[6.0] + def change + # Add new label column + add_column :service_meta, :label, :string + + # Copy data from key to label (only on up migration) + reversible do |dir| + dir.up do + ServiceMeta.reset_column_information + ServiceMeta.update_all('label = key') + end + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 32ba2452..49336f1a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2024_09_18_091413) do +ActiveRecord::Schema.define(version: 2024_11_11_181710) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" @@ -87,6 +87,7 @@ t.string "hint" t.bigint "custom_field_section_id", null: false t.string "options" + t.string "label" t.index ["custom_field_section_id"], name: "index_custom_fields_on_custom_field_section_id" end @@ -318,6 +319,7 @@ t.string "value" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false + t.string "label" t.index ["service_id"], name: "index_service_meta_on_service_id" end