module RocketJobMissionControl module ApplicationHelper STATE_ICON_MAP = { aborted: "fas fa-stop", completed: "fas fa-check", disabled: "fas fa-stop", enabled: "fas fa-check", failed: "fas fa-exclamation-triangle", paused: "fas fa-pause", pending: "fas fa-inbox", queued: "fas fa-inbox", running: "fas fa-play", sleeping: "fas fa-hourglass", scheduled: "fas fa-clock", starting: "fas fa-cogs", stopping: "fas fa-stop", zombie: "fas fa-hourglass" }.freeze def state_icon(state) STATE_ICON_MAP[state.to_sym] + " " + state.to_s end def site_title "Rocket Job Mission Control" end def title @page_title ||= params[:controller].to_s.titleize h(@full_title || [@page_title, site_title].compact.join(" | ")) end def active_page(path) "active" if current_page?(path) end def pretty_print_array_or_hash(arguments) return arguments unless arguments.is_a?(Array) || arguments.is_a?(Hash) json_string_options = {space: " ", indent: " ", array_nl: "
", object_nl: "
"} JSON.generate(arguments, json_string_options).html_safe end # Returns [Array] list of inclusion values for this attribute. # Returns nil when there are no inclusion values for this attribute. def extract_inclusion_values(klass, attribute) values = nil klass.validators_on(attribute).each do |validator| case validator when ActiveModel::Validations::InclusionValidator values = validator.options[:in] end end values end def escape(s) s.dump[1..-2] end def unescape(s) "\"#{s}\"".undump end # Returns the editable field as html for use in editing dynamic fields from a Job class. def editable_field_html(klass, field_name, value, f) # When editing a job the values are of the correct type. # When editing a dirmon entry values are strings. field = klass.fields[field_name.to_s] return unless field&.type placeholder = field.default_val placeholder = nil if placeholder.is_a?(Proc) case field.type.name when "Integer" options = extract_inclusion_values(klass, field_name) f.number_field(field_name, in: options, include_blank: false, value: value, class: "form-control", placeholder: placeholder) when "String", "Symbol", "Mongoid::StringifiedSymbol" options = extract_inclusion_values(klass, field_name) if options f.select(field_name, options, {include_blank: options.include?(nil), selected: value}, {class: "selectize form-control"}) else f.text_area(field_name, value: value ? value : "", class: "form-control", placeholder: placeholder) end when "Boolean", "Mongoid::Boolean" options = extract_inclusion_values(klass, field_name) || [nil, "true", "false"] f.select(field_name, options, {include_blank: options.include?(nil), selected: value}, {class: "selectize form-control"}) when "Hash" "[JSON Hash]\n".html_safe + f.text_field(field_name, value: value ? value.to_json : "", class: "form-control", placeholder: '{"key1":"value1", "key2":"value2", "key3":"value3"}') when "Array" options = value.present? ? Array(value) : [] f.select(field_name, options_for_select(options, options), {include_hidden: true}, {class: "selectize form-control", multiple: true}) else "[#{field.type.name}]".html_safe + f.text_field(field_name, value: value, class: "form-control", placeholder: placeholder) end end # This method creates a link with `data-id` `data-fields` attributes. These attributes are used to create new instances of the nested fields through Javascript. def link_to_add_fields(name, f, association, option) # Takes an object (@job) and creates a new instance of its associated model (:properties) new_object = f.object.send(association).klass.new # Saves the unique ID of the object into a variable. # This is needed to ensure the key of the associated array is unique. This is makes parsing the content in the `data-fields` attribute easier through Javascript. # We could use another method to achive this. id = new_object.object_id # https://api.rubyonrails.org/ fields_for(record_name, record_object = nil, fields_options = {}, &block) # record_name = :addresses # record_object = new_object # fields_options = { child_index: id } # child_index` is used to ensure the key of the associated array is unique, and that it matched the value in the `data-id` attribute. # `person[addresses_attributes][child_index_value][_destroy]` fields = f.fields_for(association, new_object, child_index: id) do |builder| # `association.to_s.singularize + "_fields"` ends up evaluating to `address_fields` # The render function will then look for `views/people/_address_fields.html.erb` # The render function also needs to be passed the value of 'builder', because `views/dirmon_entries/_input_categories.html.erb` needs this to render the form tags. render(association.to_s.singularize + "_fields", f: builder) end # This renders a simple link, but passes information into `data` attributes. # This info can be named anything we want, but in this case we chose `data-id:` and `data-fields:`. # The `id:` is from `new_object.object_id`. # The `fields:` are rendered from the `fields` blocks. # We use `gsub("\n", "")` to remove anywhite space from the rendered partial. # The `id:` value needs to match the value used in `child_index: id`. link_to(name, '#', class: "add_fields btn btn-#{option}", data: { id: id, fields: fields.gsub("\n", "") }) end end end