diff --git a/app/components/input/select_component.rb b/app/components/input/select_component.rb index 5e08a37056..7dd36d43f0 100644 --- a/app/components/input/select_component.rb +++ b/app/components/input/select_component.rb @@ -2,7 +2,7 @@ class Input::SelectComponent < Input::InputFieldComponent - def initialize(id: nil, label: '', name:, value: [], selected: '', placeholder: '', error_message: '', helper_text: '', multiple: false, open_to_add_values: false, data: {}, tooltip: nil) + def initialize(id: nil, label: '', name:, value: [], selected: '', placeholder: '', error_message: '', helper_text: '', multiple: false, open_to_add_values: false, required: false, data: {}, tooltip: nil) super(label: label, name: name, value: value, placeholder: placeholder, error_message: error_message, helper_text: helper_text, data: data) @values = value @@ -10,13 +10,15 @@ def initialize(id: nil, label: '', name:, value: [], selected: '', placeholder: @open_to_add_values = open_to_add_values @multiple = multiple @id = id + @required = required end def call render Input::InputFieldComponent.new(name: @name, error_message: @error_message, helper_text: @helper_text, label: @label) do render SelectInputComponent.new(id: @id, name: @name, values: @values, selected: @selected, - placeholder: @placeholder, - multiple: @multiple, open_to_add_values: @open_to_add_values, data: @data) + placeholder: @placeholder, required: @required, + multiple: @multiple, open_to_add_values: @open_to_add_values, + data: @data) end end end diff --git a/app/components/select_input_component.rb b/app/components/select_input_component.rb index 6aee690253..25f905100d 100644 --- a/app/components/select_input_component.rb +++ b/app/components/select_input_component.rb @@ -2,7 +2,7 @@ class SelectInputComponent < ViewComponent::Base - def initialize(id:, name:, values:, selected: nil, multiple: false, open_to_add_values: false, data: {}, placeholder: '') + def initialize(id:, name:, values:, selected: nil, multiple: false, open_to_add_values: false, required: false, data: {}, placeholder: '') super @id = id || '' @name = name @@ -12,10 +12,12 @@ def initialize(id:, name:, values:, selected: nil, multiple: false, open_to_add_ @open_to_add_values = open_to_add_values @placeholder = placeholder @data = data + @required = required end def call - select_input_tag(@id, @name, @values, @selected, multiple: @multiple, open_to_add_values: @open_to_add_values, placeholder: @placeholder) + select_input_tag(@id, @name, @values, @selected, multiple: @multiple, open_to_add_values: @open_to_add_values, + placeholder: @placeholder, required: @required) end private @@ -23,10 +25,12 @@ def call def select_input_tag(id, name, values, selected, options = {}) multiple = options[:multiple] || false open_to_add_values = options[:open_to_add_values] || false + required = options[:required] || false placeholder = options[:placeholder] || '' data = @data.merge({ 'select-input-multiple-value': multiple, - 'select-input-open-add-value': open_to_add_values + 'select-input-open-add-value': open_to_add_values, + 'select-input-required-value': required, }) data[:controller] = "#{data[:controller]} select-input" diff --git a/app/components/select_input_component/select_input_component_controller.js b/app/components/select_input_component/select_input_component_controller.js index 057964c852..1ec8b6499a 100644 --- a/app/components/select_input_component/select_input_component_controller.js +++ b/app/components/select_input_component/select_input_component_controller.js @@ -4,7 +4,8 @@ import {useTomSelect} from "../../javascript/mixins/useTomSelect" export default class extends Controller { static values = { multiple: {type: Boolean, default: false}, - openAdd: {type: Boolean, default: false} + openAdd: {type: Boolean, default: false}, + required: {type: Boolean, default: false} }; @@ -34,10 +35,14 @@ export default class extends Controller { myOptions['create'] = true; } - useTomSelect(this.element, myOptions, this.#triggerChange.bind(this)) + this.select = useTomSelect(this.element, myOptions, this.#triggerChange.bind(this)) } #triggerChange() { - document.dispatchEvent(new Event('change', {target: this.element})) + if (this.requiredValue && !this.multipleValue && this.select.getValue() === ""){ + this.select.setValue(Object.keys(this.select.options)[0]) + } + + document.dispatchEvent(new Event('change', { target: this.element })) } } \ No newline at end of file diff --git a/app/helpers/inputs_helper.rb b/app/helpers/inputs_helper.rb index a48ebf0e71..d756445bf5 100644 --- a/app/helpers/inputs_helper.rb +++ b/app/helpers/inputs_helper.rb @@ -7,12 +7,13 @@ def text_input(name:, value:, label: nil, disabled: false, help: nil, error_mess helper_text: help) end - def select_input(name:, values:, id: nil, label: nil, selected: nil, multiple: false, help: nil, open_to_add: false, data: {}) + def select_input(name:, values:, id: nil, label: nil, selected: nil, multiple: false, help: nil, open_to_add: false, required: false, data: {}) render Input::SelectComponent.new(label: input_label(label, name), id: id || name, name: name, value: values, selected: selected, multiple: multiple, helper_text: help, open_to_add_values: open_to_add, + required: required, data: data) end diff --git a/app/helpers/submission_inputs_helper.rb b/app/helpers/submission_inputs_helper.rb index 3432ac4561..b762d7c460 100644 --- a/app/helpers/submission_inputs_helper.rb +++ b/app/helpers/submission_inputs_helper.rb @@ -3,7 +3,7 @@ module SubmissionInputsHelper class SubmissionMetadataInput include MetadataHelper - def initialize(attribute_key:, attr_metadata: , submission: nil, label: nil) + def initialize(attribute_key:, attr_metadata:, submission: nil, label: nil) @attribute_key = attribute_key @attr_metadata = attr_metadata @submission = submission @@ -13,11 +13,13 @@ def initialize(attribute_key:, attr_metadata: , submission: nil, label: nil) def attr @attribute_key end - alias :attr_key :attr + + alias :attr_key :attr def attr_key @attribute_key end + def name "submission[#{@attribute_key}]" end @@ -54,6 +56,7 @@ def attribute_input(attr_key, long_text: false, label: nil, show_tooltip: true, attr = SubmissionMetadataInput.new(attribute_key: attr_key, submission: @submission, label: label, attr_metadata: attr_metadata(attr_key)) + if attr.type?('Agent') if attr.type?('list') generate_list_agent_input(attr) @@ -71,6 +74,7 @@ def attribute_input(attr_key, long_text: false, label: nil, show_tooltip: true, elsif attr.type?('textarea') generate_textarea_input(attr) elsif enforce_values?(attr) + if attr.type?('list') generate_select_input(attr, multiple: true) elsif attr.type?('boolean') @@ -103,7 +107,6 @@ def attribute_input(attr_key, long_text: false, label: nil, show_tooltip: true, end - def ontology_name_input(ontology = @ontology) text_input(name: 'ontology[name]', value: ontology.name) end @@ -135,8 +138,22 @@ def ontology_categories_input(ontology = @ontology, categories = @categories) end end + def has_ontology_language_input(submission = @submission) + render Layout::RevealComponent.new(init_show: submission.hasOntologyLanguage&.eql?('SKOS'), show_condition: 'SKOS') do |c| + c.button do + attribute_input("hasOntologyLanguage") + end + content_tag(:div, class: "upload-ontology-desc") do + content_tag(:div) do + "SKOS vocabularies submitted to BioPortal must contain a minimum of one concept scheme and top concept assertion. Please + refer to the NCBO wiki for a more #{link_to(ExternalLinkTextComponent.new(text: 'detailed explanation').call, "#seethewiki")} with examples.".html_safe + end + end + end + end + def ontology_groups_input(ontology = @ontology, groups = @groups) - groups ||= LinkedData::Client::Models::Group.all(display_links: false, display_context: false) + groups ||= LinkedData::Client::Models::Group.all(display_links: false, display_context: false) render Input::InputFieldComponent.new(name: '', label: 'Groups') do content_tag(:div, class: 'upload-ontology-chips-container') do @@ -156,7 +173,7 @@ def ontology_visibility_input(ontology = @ontology) render(Layout::RevealComponent.new(init_show: ontology.viewingRestriction&.eql?('private'), show_condition: 'private')) do |c| c.button do - select_input(label: "Visibility", name: "ontology[viewingRestriction]", values: %w[public private], selected: ontology.viewingRestriction ) + select_input(label: "Visibility", name: "ontology[viewingRestriction]", values: %w[public private], selected: ontology.viewingRestriction) end content_tag(:div, class: 'upload-ontology-input-field-container') do select_input(label: "Add or remove accounts that are allowed to see this ontology in #{portal_name}.", name: "ontology[acl]", values: @user_select_list, selected: ontology.acl, multiple: true) @@ -173,7 +190,7 @@ def ontology_view_of_input(ontology = @ontology) end content_tag(:div) do - render partial: "shared/ontology_picker_single", locals: {placeholder: "", field_name: "viewOf", selected: ontology.viewOf} + render partial: "shared/ontology_picker_single", locals: { placeholder: "", field_name: "viewOf", selected: ontology.viewOf } end end end @@ -250,7 +267,7 @@ def generate_agent_input(attr) render Input::InputFieldComponent.new(name: '', label: attr_header_label(attr), error_message: attribute_error(attr.metadata['attribute'])) do render TurboFrameComponent.new(id: "submission_#{attr_key}_#{random_id}") do if agent - render partial: 'agents/agent_show', locals: { agent_id: random_id, + render partial: 'agents/agent_show', locals: { agent_id: random_id, agent: agent, name_prefix: attr.name, parent_id: "submission_#{attr_key}", @@ -266,7 +283,6 @@ def generate_agent_input(attr) end end - def generate_list_agent_input(attr) render Input::InputFieldComponent.new(name: '', error_message: attribute_error(attr.metadata['attribute'])) do render NestedAgentSearchInputComponent.new(label: attr_header_label(attr), @@ -280,7 +296,7 @@ def generate_list_agent_input(attr) def generate_list_date_input(attr, max_date: nil) generate_list_field_input(attr, attr.name, attr_header_label(attr), attr.values) do |value, row_name, id| - date_input(label: '', name: row_name, + date_input(label: '', name: row_name, value: value, max_date: max_date) end @@ -303,13 +319,13 @@ def generate_select_input(attr, multiple: false) label = attr_header_label(attr) metadata_values, select_values = selected_values(attr, enforced_values(attr)) - unless multiple + if !multiple && !attr.required? select_values << ['', ''] - metadata_values = '' if metadata_values.nil? && !attr.required? + metadata_values = '' if metadata_values.nil? end select_input(name: name, label: label, values: select_values, - selected: metadata_values, multiple: multiple, + selected: metadata_values, multiple: multiple, required: attr.required?, open_to_add: open_to_add_metadata?(attr.attr_key)) end @@ -320,7 +336,6 @@ def generate_list_field_input(attr, name, label, values, &block) label end c.template do - binding.pry if @ontology.acronym.nil? block.call('', "#{name}[NEW_RECORD]", attr.attr.to_s + '_' + @ontology.acronym) end @@ -361,7 +376,7 @@ def generate_url_input(attr) end end - def generate_ontology_select_input(name, label , selected, multiple) + def generate_ontology_select_input(name, label, selected, multiple) unless @ontology_acronyms @ontology_acronyms = LinkedData::Client::Models::Ontology.all(include: 'acronym,name', display_links: false, display_context: false, include_views: true) .map { |x| ["#{x.name} (#{x.acronym})", x.id.to_s] } @@ -452,7 +467,7 @@ def attribute_help_text(attr) end unless attr['enforce'].nil? || attr['enforce'].empty? - help_text += render(FieldContainerComponent.new(label: 'Validators', value: attr['enforce'].map do |x| + help_text += render(FieldContainerComponent.new(label: 'Validators', value: attr['enforce'].map do |x| content_tag(:span, x.humanize, class: 'badge badge-primary mx-1') end.join.html_safe)) end diff --git a/app/helpers/submissions_helper.rb b/app/helpers/submissions_helper.rb index 692e912cfa..ba4aa9da03 100644 --- a/app/helpers/submissions_helper.rb +++ b/app/helpers/submissions_helper.rb @@ -192,7 +192,7 @@ def render_submission_inputs(frame_id) if selected_attribute?('hasOntologyLanguage') - output += render partial: 'submissions/submission_format_form' + output += has_ontology_language_input end if selected_attribute?('categories') diff --git a/app/views/submissions/_submission_format_form.html.haml b/app/views/submissions/_submission_format_form.html.haml deleted file mode 100644 index 7c1a85a40c..0000000000 --- a/app/views/submissions/_submission_format_form.html.haml +++ /dev/null @@ -1,71 +0,0 @@ -:javascript - - function ontologyFormatChange(event){ - let selected = event.target.selectedOptions.item(0) - let options = document.querySelectorAll('.format_options') - Array.from(options).forEach( x => $(x).hide()) - switch(selected.value){ - case 'OWL': - jQuery("#owl_options").show() - break - case 'SKOS': - jQuery("#skos_options").show() - break - default: - jQuery("#skos_options").hide() - jQuery("#owl_options").hide() - } - } - -= attribute_form_group_container('hasOntologyLanguage') do - %div{onchange: 'ontologyFormatChange(event)'} - = select_input(label: "Representation language", name: "submission[hasOntologyLanguage]", values: ["OBO", "OWL", "SKOS", "UMLS"], selected: @submission.hasOntologyLanguage) - %div#skos_options.upload-ontology-desc{style: "display:#{skos? ? 'block': 'none'}"} - SKOS vocabularies submitted to BioPortal must contain a minimum of one concept scheme and top concept assertion. - Please refer to the NCBO wiki for a more #{link_to 'detailed explanation', 'https://www.bioontology.org/wiki/index.php/SKOSSupport', target: "_blank" } - with examples. - %div --# - %div#owl_options - %a#collapseOWLOptions{href: "#owl-options-properties", role: "button", data: {toggle: "collapse"}, aria: {expanded: "false", controls: "owl-options"}, - class: "btn btn-outline-primary btn-sm"} Show advanced options - - %div#owl-options-properties.collapse.px-2.py-5.fade - %div - %div - %label Customize default property settings - = attribute_input('prefLabelProperty', label: 'Preferred name') do - - c.help do - Enter a property ID, or leave blank to use the default setting: - = link_to 'http://www.w3.org/2004/02/skos/core#prefLabel', 'http://www.w3.org/2004/02/skos/core#prefLabel', target: "_blank" - - = attribute_input('synonymProperty', label: 'Synonym') do - - c.help do - Enter a property ID, or leave blank to use the default setting: - = link_to 'http://www.w3.org/2004/02/skos/core#altLabel', 'http://www.w3.org/2004/02/skos/core#altLabel', target: "_blank" - - - = attribute_input('definitionProperty', label: 'Definition') do - - c.help do - Enter a property ID, or leave blank to use the default setting: - = link_to 'http://www.w3.org/2004/02/skos/core#definition', 'http://www.w3.org/2004/02/skos/core#definition', target: "_blank" - - - = attribute_input('authorProperty', label: 'Author') do - - c.help do - Enter a property ID, or leave blank to use the default setting: - = link_to 'http://purl.org/dc/elements/1.1/creator', 'http://purl.org/dc/elements/1.1/creator', target: "_blank" - - - %div - %div - %label Identify obsolete classes - = attribute_input('obsoleteProperty', label: 'Obsolete property') do - - c.help do - Optionally enter a property ID that indicates obsolete status for ontology classes - (the property value must be set to "true"). Note that by default, BioPortal checks for existence of the owl:deprecated property. - - = attribute_input('obsoleteParent', label: 'Obsolete branch root') do - - c.help do - Optionally enter a class ID for the root of an obsolete branch. All classes in the branch will be marked as - obsolete, with the exception of the root class.