From 94c0e9eed5281e93307424db2d50923fcf2c3b78 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Tue, 13 Aug 2024 15:30:30 -0700 Subject: [PATCH 01/30] Mock up collapsible panel helpers --- app/helpers/content_helper.rb | 34 +++++++++++++++++++++++++++++----- app/helpers/link_helper.rb | 6 +++++- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/app/helpers/content_helper.rb b/app/helpers/content_helper.rb index 40049b853d..cf63f18e95 100644 --- a/app/helpers/content_helper.rb +++ b/app/helpers/content_helper.rb @@ -153,11 +153,10 @@ def panel_block(**args, &block) **args.except(:class, :inner_class, :inner_id, :heading, :heading_links) ) do concat(heading) - if content.present? - concat(tag.div(class: class_names("panel-body", args[:inner_class]), - id: args[:inner_id]) do - concat(content) - end) + if args[:collapse].present? + concat(panel_collapse_body(args, content)) + else + concat(panel_block_body(args, content)) end concat(footer) end @@ -170,6 +169,8 @@ def panel_block_heading(args) els = [args[:heading]] if args[:heading_links].present? els << tag.span(args[:heading_links], class: "float-right") + elsif args[:collapse].present? + els << panel_collapse_trigger(args) end els.safe_join end @@ -179,6 +180,29 @@ def panel_block_heading(args) end end + def panel_body(args, content) + return "" if content.blank? + + tag.div(class: class_names("panel-body", args[:inner_class]), + id: args[:inner_id]) do + concat(content) + end + end + + def panel_collapse_trigger(args) + link_to(link_icon(:chevron_down), "##{args[:collapse]}", + class: "panel-collapse-trigger", + role: "button", data: { toggle: "collapse" }, + aria: { expanded: "false", controls: args } ) + end + + def panel_collapse_body(args, content) + tag.div(class: class_names("panel-collapse collapse", args[:collapsed]), + id: args[:collapse]) do + concat(panel_body(args, content)) + end + end + def panel_block_footer(args) if args[:footer] tag.div(class: "panel-footer") do diff --git a/app/helpers/link_helper.rb b/app/helpers/link_helper.rb index 8048896771..3ca7578549 100644 --- a/app/helpers/link_helper.rb +++ b/app/helpers/link_helper.rb @@ -181,7 +181,11 @@ def link_icon(type, **args) print: "print", globe: "globe", find_on_map: "screenshot", - apply: "check" + apply: "check", + chevron_down: "chevron-down", + chevron_up: "chevron-up", + chevron_left: "chevron-left", + chevron_right: "chevron-right" }.freeze # button to destroy object From 8f42c58e81749c6b54549f47370c2014ceab6efd Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Tue, 13 Aug 2024 15:38:25 -0700 Subject: [PATCH 02/30] panel_collapse_trigger --- app/helpers/content_helper.rb | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/app/helpers/content_helper.rb b/app/helpers/content_helper.rb index cf63f18e95..0150e1c7c5 100644 --- a/app/helpers/content_helper.rb +++ b/app/helpers/content_helper.rb @@ -180,6 +180,19 @@ def panel_block_heading(args) end end + def panel_collapse_trigger(args) + icon_link_to( + :OPEN.l, + "##{args[:collapse]}", + icon: link_icon(:chevron_down), + active_icon: link_icon(:chevron_up), + active_content: :CLOSE.l, + class: "panel-collapse-trigger", + role: "button", data: { toggle: "collapse" }, + aria: { expanded: args[:collapsed], controls: args } + ) + end + def panel_body(args, content) return "" if content.blank? @@ -189,13 +202,6 @@ def panel_body(args, content) end end - def panel_collapse_trigger(args) - link_to(link_icon(:chevron_down), "##{args[:collapse]}", - class: "panel-collapse-trigger", - role: "button", data: { toggle: "collapse" }, - aria: { expanded: "false", controls: args } ) - end - def panel_collapse_body(args, content) tag.div(class: class_names("panel-collapse collapse", args[:collapsed]), id: args[:collapse]) do From 71a7d5a7309eb3c11b32b3266490a0aeb21b7f6c Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Tue, 13 Aug 2024 15:48:37 -0700 Subject: [PATCH 03/30] Update args[:collapse_show] --- app/helpers/content_helper.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/helpers/content_helper.rb b/app/helpers/content_helper.rb index 0150e1c7c5..3ffce86243 100644 --- a/app/helpers/content_helper.rb +++ b/app/helpers/content_helper.rb @@ -180,6 +180,7 @@ def panel_block_heading(args) end end + # NOTE: args[:collapse_show] should be a boolean def panel_collapse_trigger(args) icon_link_to( :OPEN.l, @@ -189,7 +190,7 @@ def panel_collapse_trigger(args) active_content: :CLOSE.l, class: "panel-collapse-trigger", role: "button", data: { toggle: "collapse" }, - aria: { expanded: args[:collapsed], controls: args } + aria: { expanded: args[:collapse_show], controls: args } ) end @@ -203,7 +204,9 @@ def panel_body(args, content) end def panel_collapse_body(args, content) - tag.div(class: class_names("panel-collapse collapse", args[:collapsed]), + open = args[:collapse_show] ? "in" : "" + + tag.div(class: class_names("panel-collapse collapse", open), id: args[:collapse]) do concat(panel_body(args, content)) end From 32068f49af17a63d2b3e84f180ddab6bc05f504d Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Tue, 13 Aug 2024 15:50:01 -0700 Subject: [PATCH 04/30] Update content_helper.rb --- app/helpers/content_helper.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/helpers/content_helper.rb b/app/helpers/content_helper.rb index 3ffce86243..267bebcc8b 100644 --- a/app/helpers/content_helper.rb +++ b/app/helpers/content_helper.rb @@ -143,6 +143,8 @@ def collapse_info_trigger(id, **args) aria: { expanded: "false", controls: id }) end + # For a collapsing panel_block, pass an HTML id for args[:collapse] and + # args[:collapse_show] to show it open by default. def panel_block(**args, &block) heading = panel_block_heading(args) footer = panel_block_footer(args) From b8cfe335c76f19d77f1b6c1008ed6aff3959f1b5 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Wed, 14 Aug 2024 11:55:48 -0700 Subject: [PATCH 05/30] panel_inner_args --- app/helpers/content_helper.rb | 8 +++++++- app/views/controllers/observations/form/_record_step.erb | 6 ------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/helpers/content_helper.rb b/app/helpers/content_helper.rb index 267bebcc8b..2914e6002d 100644 --- a/app/helpers/content_helper.rb +++ b/app/helpers/content_helper.rb @@ -152,7 +152,7 @@ def panel_block(**args, &block) tag.div( class: class_names("panel panel-default", args[:class]), - **args.except(:class, :inner_class, :inner_id, :heading, :heading_links) + **args.except(*panel_inner_args) ) do concat(heading) if args[:collapse].present? @@ -164,6 +164,12 @@ def panel_block(**args, &block) end end + # Args passed to panel components that are not applied to the outer div. + def panel_inner_args + [:class, :inner_class, :inner_id, :heading, :heading_links, :collapse, + :collapse_show, :footer].freeze + end + def panel_block_heading(args) if args[:heading] tag.div(class: "panel-heading") do diff --git a/app/views/controllers/observations/form/_record_step.erb b/app/views/controllers/observations/form/_record_step.erb index a49bdf2488..de45d202df 100644 --- a/app/views/controllers/observations/form/_record_step.erb +++ b/app/views/controllers/observations/form/_record_step.erb @@ -16,11 +16,5 @@ <%= render(partial: "observations/form/details", locals: { f:, button_name:, location:, logging_optional: }) %> - <%= tag.div(class: "panel-body mt-4") do - tag.div(class: "text-center", id: "step-nav-1") do - tab_link(:NEXT.l, id: "identify", button: true) - end - end %> - <% end %> <% end %> From c567ed6bf7218f77b26a4de20e52ff48ae206d4e Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Wed, 14 Aug 2024 18:40:44 -0700 Subject: [PATCH 06/30] Refactor content_helper panel_helper --- app/helpers/content_helper.rb | 249 -------------------------------- app/helpers/panel_helper.rb | 257 ++++++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+), 249 deletions(-) create mode 100644 app/helpers/panel_helper.rb diff --git a/app/helpers/content_helper.rb b/app/helpers/content_helper.rb index 2914e6002d..2f89fc7254 100644 --- a/app/helpers/content_helper.rb +++ b/app/helpers/content_helper.rb @@ -76,253 +76,4 @@ def content_tag_unless(condition, name, content_or_options_with_block = nil, content_tag_if(!condition, name, content_or_options_with_block, options, escape, &block) end - - # Wrap an html object in '' tag. This has the effect of - # giving it context help (mouse-over popup) in most modern browsers. - # - # <%= help_tooltip(label, title: "Click here to do something.") %> - # - def help_tooltip(label, **args) - args[:data] ||= {} - tag.span(label, title: args[:title], - class: class_names("context-help", args[:class]), - data: { toggle: "tooltip" }.merge(args[:data])) - end - - # make a help-note styled element, like a div, p, or span - def help_note(element = :span, string = "") - content_tag(element, string, class: "help-note mr-3") - end - - # make a help-block styled element, like a div, p - def help_block(element = :div, string = "", **args, &block) - content = block ? capture(&block) : string - html_options = { - class: class_names("help-block", args[:class]) - }.deep_merge(args.except(:class)) - - content_tag(element, html_options) { content } - end - - # draw a help block with an arrow - def help_block_with_arrow(direction = nil, **args, &block) - div_class = "well well-sm help-block position-relative" - div_class += " mt-3" if direction == "up" - - tag.div(class: div_class, id: args[:id]) do - concat(capture(&block).to_s) - if direction - arrow_class = "arrow-#{direction}" - arrow_class += " hidden-xs" unless args[:mobile] - concat(tag.div("", class: arrow_class)) - end - end - end - - def collapse_help_block(direction = nil, string = nil, **args, &block) - div_class = "well well-sm help-block position-relative" - div_class += " mt-3" if direction == "up" - content = block ? capture(&block) : string - - tag.div(class: "collapse", id: args[:id]) do - tag.div(class: div_class) do - concat(content) - if direction - arrow_class = "arrow-#{direction}" - arrow_class += " hidden-xs" unless args[:mobile] - concat(tag.div("", class: arrow_class)) - end - end - end - end - - def collapse_info_trigger(id, **args) - link_to(link_icon(:question), "##{id}", - class: class_names("info-collapse-trigger", args[:class]), - role: "button", data: { toggle: "collapse" }, - aria: { expanded: "false", controls: id }) - end - - # For a collapsing panel_block, pass an HTML id for args[:collapse] and - # args[:collapse_show] to show it open by default. - def panel_block(**args, &block) - heading = panel_block_heading(args) - footer = panel_block_footer(args) - content = capture(&block).to_s - - tag.div( - class: class_names("panel panel-default", args[:class]), - **args.except(*panel_inner_args) - ) do - concat(heading) - if args[:collapse].present? - concat(panel_collapse_body(args, content)) - else - concat(panel_block_body(args, content)) - end - concat(footer) - end - end - - # Args passed to panel components that are not applied to the outer div. - def panel_inner_args - [:class, :inner_class, :inner_id, :heading, :heading_links, :collapse, - :collapse_show, :footer].freeze - end - - def panel_block_heading(args) - if args[:heading] - tag.div(class: "panel-heading") do - tag.h4(class: "panel-title") do - els = [args[:heading]] - if args[:heading_links].present? - els << tag.span(args[:heading_links], class: "float-right") - elsif args[:collapse].present? - els << panel_collapse_trigger(args) - end - els.safe_join - end - end - else - "" - end - end - - # NOTE: args[:collapse_show] should be a boolean - def panel_collapse_trigger(args) - icon_link_to( - :OPEN.l, - "##{args[:collapse]}", - icon: link_icon(:chevron_down), - active_icon: link_icon(:chevron_up), - active_content: :CLOSE.l, - class: "panel-collapse-trigger", - role: "button", data: { toggle: "collapse" }, - aria: { expanded: args[:collapse_show], controls: args } - ) - end - - def panel_body(args, content) - return "" if content.blank? - - tag.div(class: class_names("panel-body", args[:inner_class]), - id: args[:inner_id]) do - concat(content) - end - end - - def panel_collapse_body(args, content) - open = args[:collapse_show] ? "in" : "" - - tag.div(class: class_names("panel-collapse collapse", open), - id: args[:collapse]) do - concat(panel_body(args, content)) - end - end - - def panel_block_footer(args) - if args[:footer] - tag.div(class: "panel-footer") do - args[:footer] - end - else - "" - end - end - - def alert_block(level = :warning, string = "") - content_tag(:div, string, class: "alert alert-#{level}") - end - - # Create a div for notes. - # - # <%= notes_panel(html) %> - # - # <% notes_panel() do %> - # Render stuff in here. Note lack of "=" in line above. - # <% end %> - # - def notes_panel(msg = nil, &block) - msg = capture(&block) if block - result = tag.div(msg, class: "panel-body") - wrapper = tag.div(result, class: "panel panel-default dotted-border") - if block - concat(wrapper) - else - wrapper - end - end - - # Bootstrap tablist - def tab_nav(**args, &block) - if args[:tabs] - content = capture do - args[:tabs].each do |tab| - concat(tab_item(tab[:name], id: tab[:id], active: tab[:active])) - end - end - elsif block - content = capture(&block).to_s - else - content = "" - end - style = args[:style] || "pills" - - tag.ul( - role: "tablist", - class: class_names("nav nav-#{style}", args[:class]), - **args.except(:class, :style) - ) do - content - end - end - - # Bootstrap "tab" item in ul/li tablist - def tab_item(name, **args) - active = args[:active] ? "active" : nil - disabled = args[:disabled] ? "disabled" : nil - - tag.li( - role: "presentation", - class: class_names(active, disabled, args[:class]) - ) do - tab_link(name, **args.except(:active, :disabled, :class)) - end - end - - # Bootstrap tab - just the link. Use for independent tab (e.g. button). - def tab_link(name, **args) - classes = args[:button] ? "btn btn-default" : "nav-link" - - link_to( - name, "##{args[:id]}-tab-pane", - role: "tab", id: "#{args[:id]}-tab", class: classes, - data: { toggle: "tab" }, aria: { controls: "#{args[:id]}-tab-pane" } - ) - end - - # Bootstrap tabpanel wrapper - def tab_content(**args, &block) - content = capture(&block).to_s - - tag.div(class: class_names("tab-content", args[:class]), - **args.except(:class)) do - content - end - end - - # Bootstrap tabpanel - def tab_panel(**args, &block) - content = capture(&block).to_s - active = args[:active] ? "in active" : nil - - tag.div( - role: "tabpanel", id: "#{args[:id]}-tab-pane", - class: class_names("tab-pane fade", active, args[:class]), - aria: { labelledby: "#{args[:id]}-tab" }, - **args.except(:class, :id) - ) do - content - end - end end diff --git a/app/helpers/panel_helper.rb b/app/helpers/panel_helper.rb new file mode 100644 index 0000000000..57da222360 --- /dev/null +++ b/app/helpers/panel_helper.rb @@ -0,0 +1,257 @@ +# frozen_string_literal: true + +# helpers for bootstrap panels +module PanelHelper + # For a collapsing panel_block, pass an HTML id for args[:collapse] and + # args[:collapse_show] to show it open by default. + def panel_block(**args, &block) + heading = panel_block_heading(args) + footer = panel_block_footer(args) + content = capture(&block).to_s + + tag.div( + class: class_names("panel panel-default", args[:class]), + **args.except(*panel_inner_args) + ) do + concat(heading) + if args[:collapse].present? + concat(panel_collapse_body(args, content)) + else + concat(panel_block_body(args, content)) + end + concat(footer) + end + end + + # Args passed to panel components that are not applied to the outer div. + def panel_inner_args + [:class, :inner_class, :inner_id, :heading, :heading_links, :collapse, + :open, :footer].freeze + end + + def panel_block_heading(args) + if args[:heading] + tag.div(class: "panel-heading") do + tag.h4(class: "panel-title") do + els = [args[:heading]] + if args[:heading_links].present? + els << tag.span(args[:heading_links], class: "float-right") + elsif args[:collapse].present? + els << panel_collapse_trigger(args) + end + els.safe_join + end + end + else + "" + end + end + + # NOTE: args[:collapse_show] should be a boolean + def panel_collapse_trigger(args) + icon_link_to( + :OPEN.l, + "##{args[:collapse]}", + icon: link_icon(:chevron_down), + active_icon: link_icon(:chevron_up), + active_content: :CLOSE.l, + class: "panel-collapse-trigger", + role: "button", data: { toggle: "collapse" }, + aria: { expanded: args[:open], controls: args } + ) + end + + def panel_body(args, content) + return "" if content.blank? + + tag.div(class: class_names("panel-body", args[:inner_class]), + id: args[:inner_id]) do + concat(content) + end + end + + def panel_collapse_body(args, content) + open = args[:open] ? "in" : "" + + tag.div(class: class_names("panel-collapse collapse", open), + id: args[:collapse]) do + concat(panel_body(args, content)) + end + end + + def panel_block_footer(args) + if args[:footer] + tag.div(class: "panel-footer") do + args[:footer] + end + else + "" + end + end + + def alert_block(level = :warning, string = "") + content_tag(:div, string, class: "alert alert-#{level}") + end + + # Create a div for notes. + # + # <%= notes_panel(html) %> + # + # <% notes_panel() do %> + # Render stuff in here. Note lack of "=" in line above. + # <% end %> + # + def notes_panel(msg = nil, &block) + msg = capture(&block) if block + result = tag.div(msg, class: "panel-body") + wrapper = tag.div(result, class: "panel panel-default dotted-border") + if block + concat(wrapper) + else + wrapper + end + end + + # Help tooltip, note, block. + # + # Help tooltip is a span with a title attribute. This has the effect of + # giving it context help (mouse-over popup) in most modern browsers. + # + # <%= help_tooltip(label, title: "Click here to do something.") %> + # + def help_tooltip(label, **args) + args[:data] ||= {} + tag.span(label, title: args[:title], + class: class_names("context-help", args[:class]), + data: { toggle: "tooltip" }.merge(args[:data])) + end + + # make a help-note styled element, like a div, p, or span + def help_note(element = :span, string = "") + content_tag(element, string, class: "help-note mr-3") + end + + # make a help-block styled element, like a div, p + def help_block(element = :div, string = "", **args, &block) + content = block ? capture(&block) : string + html_options = { + class: class_names("help-block", args[:class]) + }.deep_merge(args.except(:class)) + + content_tag(element, html_options) { content } + end + + # draw a help block with an arrow + def help_block_with_arrow(direction = nil, **args, &block) + div_class = "well well-sm help-block position-relative" + div_class += " mt-3" if direction == "up" + + tag.div(class: div_class, id: args[:id]) do + concat(capture(&block).to_s) + if direction + arrow_class = "arrow-#{direction}" + arrow_class += " hidden-xs" unless args[:mobile] + concat(tag.div("", class: arrow_class)) + end + end + end + + def collapse_help_block(direction = nil, string = nil, **args, &block) + div_class = "well well-sm help-block position-relative" + div_class += " mt-3" if direction == "up" + content = block ? capture(&block) : string + + tag.div(class: "collapse", id: args[:id]) do + tag.div(class: div_class) do + concat(content) + if direction + arrow_class = "arrow-#{direction}" + arrow_class += " hidden-xs" unless args[:mobile] + concat(tag.div("", class: arrow_class)) + end + end + end + end + + def collapse_info_trigger(id, **args) + link_to(link_icon(:question), "##{id}", + class: class_names("info-collapse-trigger", args[:class]), + role: "button", data: { toggle: "collapse" }, + aria: { expanded: "false", controls: id }) + end + + # BOOTSTRAP TABBED CONTENT + # + # Bootstrap tablist + def tab_nav(**args, &block) + if args[:tabs] + content = capture do + args[:tabs].each do |tab| + concat(tab_item(tab[:name], id: tab[:id], active: tab[:active])) + end + end + elsif block + content = capture(&block).to_s + else + content = "" + end + style = args[:style] || "pills" + + tag.ul( + role: "tablist", + class: class_names("nav nav-#{style}", args[:class]), + **args.except(:class, :style) + ) do + content + end + end + + # Bootstrap "tab" item in ul/li tablist + def tab_item(name, **args) + active = args[:active] ? "active" : nil + disabled = args[:disabled] ? "disabled" : nil + + tag.li( + role: "presentation", + class: class_names(active, disabled, args[:class]) + ) do + tab_link(name, **args.except(:active, :disabled, :class)) + end + end + + # Bootstrap tab - just the link. Use for independent tab (e.g. button). + def tab_link(name, **args) + classes = args[:button] ? "btn btn-default" : "nav-link" + + link_to( + name, "##{args[:id]}-tab-pane", + role: "tab", id: "#{args[:id]}-tab", class: classes, + data: { toggle: "tab" }, aria: { controls: "#{args[:id]}-tab-pane" } + ) + end + + # Bootstrap tabpanel wrapper + def tab_content(**args, &block) + content = capture(&block).to_s + + tag.div(class: class_names("tab-content", args[:class]), + **args.except(:class)) do + content + end + end + + # Bootstrap tabpanel + def tab_panel(**args, &block) + content = capture(&block).to_s + active = args[:active] ? "in active" : nil + + tag.div( + role: "tabpanel", id: "#{args[:id]}-tab-pane", + class: class_names("tab-pane fade", active, args[:class]), + aria: { labelledby: "#{args[:id]}-tab" }, + **args.except(:class, :id) + ) do + content + end + end +end From cc49bfa28176d1e01625c8a25d4764145a0b8ce3 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Wed, 14 Aug 2024 18:41:02 -0700 Subject: [PATCH 07/30] Refactor obs form with panel helper --- .../controllers/observations/_form.html.erb | 87 +++++++++++++++++-- .../observations/form/_identify_step.erb | 4 +- .../observations/form/_projects.html.erb | 4 +- .../observations/form/_species_lists.html.erb | 4 +- 4 files changed, 87 insertions(+), 12 deletions(-) diff --git a/app/views/controllers/observations/_form.html.erb b/app/views/controllers/observations/_form.html.erb index 2c959fd666..6b2f79fc3b 100644 --- a/app/views/controllers/observations/_form.html.erb +++ b/app/views/controllers/observations/_form.html.erb @@ -32,7 +32,21 @@ data = { form_images_target: "form", exif_used: create ? false : true } -projects_lists = @projects.any? || @lists.any? +naming_locals = if include_naming + { + f: f, + action: action, + button_name: button_name, + show_reasons: false, + unfocused: true, + name_help: :form_naming_name_help_leave_blank.t + } + else + {} + end +show_projects = @projects.any? || @error_checked_projects.any? || + @suspect_checked_projects.any? +show_lists = @lists.any? %> <%= form_with( @@ -46,12 +60,12 @@ projects_lists = @projects.any? || @lists.any? data: ) do |f| %> - <%= if @field_code - tag.p("#{:form_observations_field_code.t} #{@field_code}") - end %> - <%= hidden_field_tag(:field_code, @field_code) %> + <% if @field_code %> + <%= tag.p("#{:form_observations_field_code.t} #{@field_code}") %> + <%= hidden_field_tag(:field_code, @field_code) %> + <% end %> - <%= tab_content do %> + <%# tab_content do %> <%= render(partial: "observations/form/record_step", locals: { f:, button_name:, location: @location, logging_optional: }) %> @@ -63,6 +77,67 @@ projects_lists = @projects.any? || @lists.any? <%= render(partial: "observations/form/add_to_step", locals: { f:, button_name: }) %> <% end %> + <%# end %> + + <%= panel_block( + heading: "#{:IMAGES.l} + #{:show_observation_details.l}", + id: "observation_images_details" + ) do %> + <%= render(partial: "observations/form/images", locals: { f: }) %> + + <%= render(partial: "observations/form/details", + locals: { f:, button_name:, location:, logging_optional: }) %> + <% end %> + + <%= panel_block( + heading: :IDENTIFICATION.l, + id: "observation_identification", + collapse: "observation_identification_inner", + open: false + ) do + render(partial: "observations/namings/fields", locals: naming_locals) + end %> + + <%= panel_block( + heading: :SPECIMEN.l, + id: "observation_specimen", + collapse: "observation_specimen_inner", + open: false + ) do + render(partial: "observations/form/specimen_section", + locals: { f:, action: }) + end %> + + <%= panel_block( + heading: :NOTES.l, + id: "observation_notes", + collapse: "observation_notes_inner", + open: false + ) do + render(partial: "shared/notes_fields", + locals: { form: f, fields: @observation.form_notes_parts(@user) }) + end %> + + <% if show_projects %> + <%= panel_block( + heading: :PROJECTS.l, + id: "observation_projects", + collapse: "observation_projects_inner", + open: false + ) do + render(partial: "observations/form/projects", locals: { button_name: }) + end %> + <% end %> + + <% if show_lists %> + <%= panel_block( + heading: :SPECIES_LISTS.l, + id: "observation_lists", + collapse: "observation_lists_inner", + open: false + ) do + render(partial: "observations/form/species_lists") + end %> <% end %> <% end %> diff --git a/app/views/controllers/observations/form/_identify_step.erb b/app/views/controllers/observations/form/_identify_step.erb index 0f8f794740..239d0c5dd6 100644 --- a/app/views/controllers/observations/form/_identify_step.erb +++ b/app/views/controllers/observations/form/_identify_step.erb @@ -22,8 +22,8 @@ <% end %> <%= tag.div(class: "col-xs-12 col-lg-6") do %> <%= render(partial: "shared/notes_fields", - locals: { form: f, - fields: @observation.form_notes_parts(@user) }) %> + locals: { form: f, + fields: @observation.form_notes_parts(@user) }) %> <% end %> <% end %> diff --git a/app/views/controllers/observations/form/_projects.html.erb b/app/views/controllers/observations/form/_projects.html.erb index 63a002ba13..3aa8931b18 100644 --- a/app/views/controllers/observations/form/_projects.html.erb +++ b/app/views/controllers/observations/form/_projects.html.erb @@ -20,7 +20,7 @@ if @suspect_checked_projects.any? end %> -<%= tag.div(id: "observation_projects") do %> +<%# tag.div(id: "observation_projects") do %> <%= fields_for(:project) do |f_p| %> <% if error_messages.present? || suspect_messages.present? %> @@ -71,5 +71,5 @@ end <% end %> <% end %> -<% end %> +<%# end %> diff --git a/app/views/controllers/observations/form/_species_lists.html.erb b/app/views/controllers/observations/form/_species_lists.html.erb index 1172d3fc85..16e147d639 100644 --- a/app/views/controllers/observations/form/_species_lists.html.erb +++ b/app/views/controllers/observations/form/_species_lists.html.erb @@ -1,6 +1,6 @@ <%# species_list section of create_observation form %> -<%= tag.div(id: "observation_projects") do %> +<%# tag.div(id: "observation_lists") do %> <%= fields_for(:list) do |f_l| %> <%= tag.div do @@ -23,4 +23,4 @@ <% end %> <% end %> -<% end %> +<%# end %> From 85b60bda2d35dad00ab7a078e1355cb9738b9711 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Wed, 14 Aug 2024 22:40:17 -0700 Subject: [PATCH 08/30] Update panel_helper.rb Enable args[:content] --- app/helpers/panel_helper.rb | 60 ++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/app/helpers/panel_helper.rb b/app/helpers/panel_helper.rb index 57da222360..878eb85be5 100644 --- a/app/helpers/panel_helper.rb +++ b/app/helpers/panel_helper.rb @@ -4,20 +4,26 @@ module PanelHelper # For a collapsing panel_block, pass an HTML id for args[:collapse] and # args[:collapse_show] to show it open by default. + # Pass args[:panel_bodies] to create multiple panel bodies, or args[:content] + # to pass preformatted content instead of building `panel-body` here. def panel_block(**args, &block) - heading = panel_block_heading(args) - footer = panel_block_footer(args) - content = capture(&block).to_s + heading = panel_heading(args) + footer = panel_footer(args) + content = block ? capture(&block).to_s : "" tag.div( class: class_names("panel panel-default", args[:class]), **args.except(*panel_inner_args) ) do concat(heading) - if args[:collapse].present? + if args[:panel_bodies].present? + concat(panel_bodies(args)) + elsif args[:content].present? + concat(args[:content]) + elsif args[:collapse].present? concat(panel_collapse_body(args, content)) else - concat(panel_block_body(args, content)) + concat(panel_body(args, content)) end concat(footer) end @@ -25,35 +31,34 @@ def panel_block(**args, &block) # Args passed to panel components that are not applied to the outer div. def panel_inner_args - [:class, :inner_class, :inner_id, :heading, :heading_links, :collapse, - :open, :footer].freeze + [:class, :inner_class, :inner_id, :heading, :heading_links, :panel_bodies, + :collapse, :open, :footer].freeze end - def panel_block_heading(args) - if args[:heading] - tag.div(class: "panel-heading") do - tag.h4(class: "panel-title") do - els = [args[:heading]] - if args[:heading_links].present? - els << tag.span(args[:heading_links], class: "float-right") - elsif args[:collapse].present? - els << panel_collapse_trigger(args) - end - els.safe_join + def panel_heading(args) + return "" unless args[:heading] + + tag.div(class: "panel-heading") do + tag.h4(class: "panel-title") do + els = [args[:heading]] + if args[:heading_links].present? + els << tag.span(args[:heading_links], class: "float-right") + elsif args[:collapse].present? + els << tag.span(panel_collapse_trigger(args), class: "float-right") end + els.safe_join end - else - "" end end - # NOTE: args[:collapse_show] should be a boolean + # The caret icon that toggles the panel collapse. + # NOTE: args[:open] should be a boolean def panel_collapse_trigger(args) icon_link_to( :OPEN.l, "##{args[:collapse]}", - icon: link_icon(:chevron_down), - active_icon: link_icon(:chevron_up), + icon: :chevron_down, + active_icon: :chevron_up, active_content: :CLOSE.l, class: "panel-collapse-trigger", role: "button", data: { toggle: "collapse" }, @@ -70,6 +75,13 @@ def panel_body(args, content) end end + # Some panels need multiple panel bodies. + def panel_bodies(args) + args[:panel_bodies].map do |body| + panel_body(args, body) + end.safe_join + end + def panel_collapse_body(args, content) open = args[:open] ? "in" : "" @@ -79,7 +91,7 @@ def panel_collapse_body(args, content) end end - def panel_block_footer(args) + def panel_footer(args) if args[:footer] tag.div(class: "panel-footer") do args[:footer] From b0b73e8255372eba622ce5906525c976efb94853 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Wed, 14 Aug 2024 22:40:44 -0700 Subject: [PATCH 09/30] Rename panel_block_heading panel_heading --- app/views/controllers/field_slips/_obs_thumbnail.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/controllers/field_slips/_obs_thumbnail.erb b/app/views/controllers/field_slips/_obs_thumbnail.erb index 92683315e8..1f0ff94f4a 100644 --- a/app/views/controllers/field_slips/_obs_thumbnail.erb +++ b/app/views/controllers/field_slips/_obs_thumbnail.erb @@ -1,5 +1,5 @@ <%= tag.div(class: "panel panel-default") do - concat(panel_block_heading( + concat(panel_heading( heading: submit_button(form: form, button: button) )) concat(tag.div(class: "thumbnail-container") do From d418554cebd2fb0b2010e57179b970b8e8e58ff9 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Wed, 14 Aug 2024 22:40:59 -0700 Subject: [PATCH 10/30] Redesign form --- .../controllers/observations/_form.html.erb | 63 +++-------- .../observations/form/_details.html.erb | 101 ++++++++++-------- .../observations/form/_identify_specimen.erb | 29 +++++ .../observations/form/_identify_step.erb | 38 ------- .../observations/form/_images.html.erb | 14 ++- .../observations/form/_record_step.erb | 6 ++ .../observations/namings/_fields.erb | 15 ++- 7 files changed, 120 insertions(+), 146 deletions(-) create mode 100644 app/views/controllers/observations/form/_identify_specimen.erb delete mode 100644 app/views/controllers/observations/form/_identify_step.erb diff --git a/app/views/controllers/observations/_form.html.erb b/app/views/controllers/observations/_form.html.erb index 6b2f79fc3b..0c4667eef6 100644 --- a/app/views/controllers/observations/_form.html.erb +++ b/app/views/controllers/observations/_form.html.erb @@ -32,18 +32,6 @@ data = { form_images_target: "form", exif_used: create ? false : true } -naming_locals = if include_naming - { - f: f, - action: action, - button_name: button_name, - show_reasons: false, - unfocused: true, - name_help: :form_naming_name_help_leave_blank.t - } - else - {} - end show_projects = @projects.any? || @error_checked_projects.any? || @suspect_checked_projects.any? show_lists = @lists.any? @@ -65,48 +53,19 @@ show_lists = @lists.any? <%= hidden_field_tag(:field_code, @field_code) %> <% end %> - <%# tab_content do %> - <%= render(partial: "observations/form/record_step", - locals: { f:, button_name:, location: @location, - logging_optional: }) %> - - <%= render(partial: "observations/form/identify_step", - locals: { f:, action:, button_name:, include_naming: }) %> - - <% if projects_lists %> - <%= render(partial: "observations/form/add_to_step", - locals: { f:, button_name: }) %> - <% end %> - <%# end %> - + <% content = [ + render(partial: "observations/form/images", locals: { f: }), + render(partial: "observations/form/details", + locals: { f:, button_name:, location: @location, logging_optional:, + action:, include_naming: }), + ].safe_join %> <%= panel_block( heading: "#{:IMAGES.l} + #{:show_observation_details.l}", - id: "observation_images_details" - ) do %> - <%= render(partial: "observations/form/images", locals: { f: }) %> + id: "observation_images_details", content: + ) %> - <%= render(partial: "observations/form/details", - locals: { f:, button_name:, location:, logging_optional: }) %> - <% end %> - - <%= panel_block( - heading: :IDENTIFICATION.l, - id: "observation_identification", - collapse: "observation_identification_inner", - open: false - ) do - render(partial: "observations/namings/fields", locals: naming_locals) - end %> - - <%= panel_block( - heading: :SPECIMEN.l, - id: "observation_specimen", - collapse: "observation_specimen_inner", - open: false - ) do - render(partial: "observations/form/specimen_section", - locals: { f:, action: }) - end %> + <%= render(partial: "observations/form/identify_specimen", + locals: { f:, action:, button_name:, include_naming: }) %> <%= panel_block( heading: :NOTES.l, @@ -118,6 +77,8 @@ show_lists = @lists.any? locals: { form: f, fields: @observation.form_notes_parts(@user) }) end %> + <%= submit_button(form: f, button: button_name, center: true) %> + <% if show_projects %> <%= panel_block( heading: :PROJECTS.l, diff --git a/app/views/controllers/observations/form/_details.html.erb b/app/views/controllers/observations/form/_details.html.erb index 9471ea8834..dcee14f00d 100644 --- a/app/views/controllers/observations/form/_details.html.erb +++ b/app/views/controllers/observations/form/_details.html.erb @@ -1,13 +1,25 @@ -<%# locals: (f:, button_name:, location:, logging_optional:) -%> +<%# locals: (f:, action:, button_name:, location:, logging_optional:, include_naming: false) -%> <%# When and Where (location) section of create_observation form - including location autocomplete, map, lat/long/alt %> + including location autocomplete, map, lat/long/alt, naming %> <% t_s = { lat: { abbr: :LAT.l, full: :LATITUDE.l, addon: "º" }, lng: { abbr: :LNG.l, full: :LONGITUDE.l, addon: "º" }, alt: { abbr: :ALT.l, full: :ALTITUDE.l, addon: "m" } } +naming_locals = if include_naming + { + f: f, + action: action, + button_name: button_name, + show_reasons: false, + unfocused: true, + name_help: :form_naming_name_help_leave_blank.t + } + else + {} + end %> <%= tag.div(class: "panel-body border-top", id: "observation_details") do %> @@ -21,44 +33,13 @@ t_s = { <%= tag.div(id: "observation_where") do %> - <%= tag.p do - [tag.strong("#{:WHERE_GROUP.l}:"), - collapse_info_trigger("geolocation_help")].safe_join(" ") - end %> - - - <%= tag.div(class: "row no-gutters", - id: "observation_lat_lng_alt") do %> - <% [:lat, :lng, :alt].each do |key| %> - <%= tag.div(class: "col-xs-4") do - text_field_with_label( - form: f, field: key, class: "mb-0", addon: t_s[key][:addon], - label: [ - tag.span("#{t_s[key][:full]}:", class: "d-none d-sm-inline"), - tag.span("#{t_s[key][:abbr]}:", class: "d-inline d-sm-none") - ].safe_join, - data: { map_target: "#{key}Input", action: "map#bufferInputs" } - ) - end %> - <% end %> - <% end %> - - <%= collapse_help_block(nil, id: "geolocation_help") do %> - <%= tag.p(:form_observations_click_point.l) %> - <%= tag.p(:form_observations_lat_long_help.t) %> - <% end %> - - <%= check_box_with_label(form: f, field: :gps_hidden, - label: :form_observations_gps_hidden.l) %> - - <%= render(partial: "shared/form_location_feedback", locals: { button: button_name } ) %> <%= autocompleter_field( - form: f, field: :place_name, type: :location, + form: f, field: :place_name, type: :location, class: "mb-0", label: [tag.span("#{:WHERE.l}:", class: "unconstrained-label"), tag.span("#{:form_observations_locality_contains.l}:", class: "constrained-label"), @@ -85,25 +66,58 @@ t_s = { } ) %> - <%= render(partial: "locations/form/bounds_hidden_fields", - locals: { location: @location, target_controller: :map }) %> - - <%= check_box_with_label( form: f, field: :is_collection_location, label: :form_observations_is_collection_location.l, - help: :form_observations_is_collection_location_help.t + help: :form_observations_is_collection_location_help.t, + class: "ml-5 mb-5" ) %> + <%= render(partial: "locations/form/bounds_hidden_fields", + locals: { location: @location, target_controller: :map }) %> + + + + <%= tag.p do + [tag.strong("#{:GEOLOCATION.l}:"), + collapse_info_trigger("geolocation_help")].safe_join(" ") + end %> + + <%= tag.div(class: "row no-gutters", + id: "observation_lat_lng_alt") do %> + <% [:lat, :lng, :alt].each do |key| %> + <%= tag.div(class: "col-xs-4") do + text_field_with_label( + form: f, field: key, class: "mb-0", addon: t_s[key][:addon], + label: [ + tag.span("#{t_s[key][:full]}:", class: "d-none d-sm-inline"), + tag.span("#{t_s[key][:abbr]}:", class: "d-inline d-sm-none") + ].safe_join, + data: { map_target: "#{key}Input", action: "map#bufferInputs" } + ) + end %> + <% end %> + <% end %> + + <%= collapse_help_block(nil, id: "geolocation_help") do %> + <%= tag.p(:form_observations_click_point.l) %> + <%= tag.p(:form_observations_lat_long_help.t) %> + <% end %> + + <%= check_box_with_label( + form: f, field: :gps_hidden, label: :form_observations_gps_hidden.l, + class: "ml-5 mb-5" + ) %> + + <% if logging_optional %> <%= check_box_with_label( form: f, field: :log_change, checked: "checked", label: :form_observations_log_change.t ) %> <% end %> - <% end %> <% end %> @@ -111,12 +125,11 @@ t_s = { <%= tag.div(class: "col-xs-12 col-md-6", id: "observation_geolocation") do %> <%= render( - partial: "shared/form_location_map", - locals: { id: "observation_form_map", map_type: "observation" } - ) %> + partial: "shared/form_location_map", + locals: { id: "observation_form_map", map_type: "observation" } + ) %> <% end %> - <% end %> <% end %> diff --git a/app/views/controllers/observations/form/_identify_specimen.erb b/app/views/controllers/observations/form/_identify_specimen.erb new file mode 100644 index 0000000000..d02630e453 --- /dev/null +++ b/app/views/controllers/observations/form/_identify_specimen.erb @@ -0,0 +1,29 @@ +<%# locals: (f:, action:, button_name:, include_naming:) -%> + +<%= panel_block( + id: "observation_identification", + heading: "#{:IDENTIFICATION.l} + #{:SPECIMEN.l}", + collapse: "observation_specimen_inner", + open: false +) do %> + <%= tag.div(class: "row mt-3") do %> + <%= tag.div(class: "col-xs-12 col-lg-6") do %> + <% if include_naming + naming_locals = { + f: f, + action: action, + button_name: button_name, + show_reasons: false, + unfocused: true, + name_help: :form_naming_name_help_leave_blank.t + } %> + <%= render(partial: "observations/namings/fields", + locals: naming_locals) %> + <% end %> + <% end %> + <%= tag.div(class: "col-xs-12 col-lg-6") do %> + <%= render(partial: "observations/form/specimen_section", + locals: { f:, action: }) %> + <% end %> + <% end %> +<% end %> diff --git a/app/views/controllers/observations/form/_identify_step.erb b/app/views/controllers/observations/form/_identify_step.erb deleted file mode 100644 index 239d0c5dd6..0000000000 --- a/app/views/controllers/observations/form/_identify_step.erb +++ /dev/null @@ -1,38 +0,0 @@ -<%# locals: (f:, action:, button_name:, include_naming:) -%> - -<%= tab_panel(id: "identify") do %> - <%= panel_block(id: "observation_identification", - heading: "#{:IDENTIFICATION.l} + #{:NOTES.l}") do %> - <%= tag.div(class: "row mt-3") do %> - <%= tag.div(class: "col-xs-12 col-lg-6") do %> - <% if include_naming - naming_locals = { - f: f, - action: action, - button_name: button_name, - show_reasons: false, - unfocused: true, - name_help: :form_naming_name_help_leave_blank.t - } %> - <%= render(partial: "observations/namings/fields", - locals: naming_locals) %> - <% end %> - <%= render(partial: "observations/form/specimen_section", - locals: { f:, action: }) %> - <% end %> - <%= tag.div(class: "col-xs-12 col-lg-6") do %> - <%= render(partial: "shared/notes_fields", - locals: { form: f, - fields: @observation.form_notes_parts(@user) }) %> - <% end %> - <% end %> - - <%= tag.div(class: "row mt-5 text-center", id: "step-nav-2") do - [ - tab_link(:BACK.l, id: "record", button: true), - tab_link(:NEXT.l, id: "add_to", button: true), - submit_button(form: f, button: button_name) - ].safe_join(" ") - end %> - <% end %> -<% end %> diff --git a/app/views/controllers/observations/form/_images.html.erb b/app/views/controllers/observations/form/_images.html.erb index ed2b3db2d1..e7676c021a 100644 --- a/app/views/controllers/observations/form/_images.html.erb +++ b/app/views/controllers/observations/form/_images.html.erb @@ -12,13 +12,6 @@ i.e. not observation[good_image_ids]. It's a top-level field. --%> <%= tag.div(id: "observation_images") do %> - <%= hidden_field_tag(:good_image_ids, - @good_images.map { |img| img.id }.join(" "), - data: { form_images_target: "goodImageIds" }) %> - - <%= f.hidden_field(:thumb_image_id, - data: { form_images_target: "thumbImageId" }) %> - <%= tag.div(class: "panel-body border-bottom") do [ tag.h4(:IMAGES.l, class: "panel-title d-inline-block mr-4"), @@ -32,7 +25,12 @@ i.e. not observation[good_image_ids]. It's a top-level field. --%> data: { action: "change->form-images#addSelectedFiles" } ) ].safe_join - end + end, + hidden_field_tag(:good_image_ids, + @good_images.map { |img| img.id }.join(" "), + data: { form_images_target: "goodImageIds" }), + f.hidden_field(:thumb_image_id, + data: { form_images_target: "thumbImageId" }) ].safe_join end %> diff --git a/app/views/controllers/observations/form/_record_step.erb b/app/views/controllers/observations/form/_record_step.erb index de45d202df..a49bdf2488 100644 --- a/app/views/controllers/observations/form/_record_step.erb +++ b/app/views/controllers/observations/form/_record_step.erb @@ -16,5 +16,11 @@ <%= render(partial: "observations/form/details", locals: { f:, button_name:, location:, logging_optional: }) %> + <%= tag.div(class: "panel-body mt-4") do + tag.div(class: "text-center", id: "step-nav-1") do + tab_link(:NEXT.l, id: "identify", button: true) + end + end %> + <% end %> <% end %> diff --git a/app/views/controllers/observations/namings/_fields.erb b/app/views/controllers/observations/namings/_fields.erb index 3c1ac6ee3c..86a4aa711b 100644 --- a/app/views/controllers/observations/namings/_fields.erb +++ b/app/views/controllers/observations/namings/_fields.erb @@ -23,14 +23,19 @@ confidences = options_for_select(menu, @vote&.value) select_opts = { include_blank: ["new", "create"].include?(action_name) } context ||= "blank" name_help ||= :form_naming_name_help.t +feedback = if @given_name.present? + tag.div do + render(partial: "shared/form_name_feedback", + locals: feedback_locals) + end + else + "" + end %> <%= [ - tag.div do - render(partial: "shared/form_name_feedback", - locals: feedback_locals) if @given_name.present? - end, + feedback, fields_for(:naming) do |f_n| [ autocompleter_field( @@ -49,5 +54,5 @@ name_help ||= :form_naming_name_help.t ].safe_join end, hidden_field_tag(:context, context) -].safe_join +].compact.safe_join %> From 58273165623ce70dcf380796af219689201f57ab Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Wed, 14 Aug 2024 22:42:30 -0700 Subject: [PATCH 11/30] Update _details.html.erb --- .../controllers/observations/form/_details.html.erb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/views/controllers/observations/form/_details.html.erb b/app/views/controllers/observations/form/_details.html.erb index dcee14f00d..37d1201fc6 100644 --- a/app/views/controllers/observations/form/_details.html.erb +++ b/app/views/controllers/observations/form/_details.html.erb @@ -101,15 +101,15 @@ naming_locals = if include_naming <% end %> <% end %> - <%= collapse_help_block(nil, id: "geolocation_help") do %> - <%= tag.p(:form_observations_click_point.l) %> - <%= tag.p(:form_observations_lat_long_help.t) %> - <% end %> - <%= check_box_with_label( form: f, field: :gps_hidden, label: :form_observations_gps_hidden.l, class: "ml-5 mb-5" ) %> + + <%= collapse_help_block(nil, id: "geolocation_help") do %> + <%= tag.p(:form_observations_click_point.l) %> + <%= tag.p(:form_observations_lat_long_help.t) %> + <% end %> <% if logging_optional %> From 4f6356c0070d140d3ddcc4805d94d2d0e7dd2c37 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Wed, 14 Aug 2024 22:53:21 -0700 Subject: [PATCH 12/30] Open naming panel if there are messages --- .../controllers/observations/form/_identify_specimen.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/controllers/observations/form/_identify_specimen.erb b/app/views/controllers/observations/form/_identify_specimen.erb index d02630e453..2eb1567948 100644 --- a/app/views/controllers/observations/form/_identify_specimen.erb +++ b/app/views/controllers/observations/form/_identify_specimen.erb @@ -4,7 +4,7 @@ id: "observation_identification", heading: "#{:IDENTIFICATION.l} + #{:SPECIMEN.l}", collapse: "observation_specimen_inner", - open: false + open: @given_name.present? ) do %> <%= tag.div(class: "row mt-3") do %> <%= tag.div(class: "col-xs-12 col-lg-6") do %> @@ -18,7 +18,7 @@ name_help: :form_naming_name_help_leave_blank.t } %> <%= render(partial: "observations/namings/fields", - locals: naming_locals) %> + locals: naming_locals) %> <% end %> <% end %> <%= tag.div(class: "col-xs-12 col-lg-6") do %> From 7f735eeb0623a51591698b6735f5869b23f2bc4c Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Wed, 14 Aug 2024 22:56:30 -0700 Subject: [PATCH 13/30] Update _identify_specimen.erb --- .../controllers/observations/form/_identify_specimen.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/controllers/observations/form/_identify_specimen.erb b/app/views/controllers/observations/form/_identify_specimen.erb index 2eb1567948..5f85f69bb7 100644 --- a/app/views/controllers/observations/form/_identify_specimen.erb +++ b/app/views/controllers/observations/form/_identify_specimen.erb @@ -7,7 +7,7 @@ open: @given_name.present? ) do %> <%= tag.div(class: "row mt-3") do %> - <%= tag.div(class: "col-xs-12 col-lg-6") do %> + <%= tag.div(class: "col-xs-12 col-md-6") do %> <% if include_naming naming_locals = { f: f, @@ -21,7 +21,7 @@ locals: naming_locals) %> <% end %> <% end %> - <%= tag.div(class: "col-xs-12 col-lg-6") do %> + <%= tag.div(class: "col-xs-12 col-md-6") do %> <%= render(partial: "observations/form/specimen_section", locals: { f:, action: }) %> <% end %> From 3fb46821f410baa5e7e04a4e3750fad5cc565f32 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Thu, 15 Aug 2024 13:56:43 -0700 Subject: [PATCH 14/30] Remove steps, simplify locals, panel formatted_content --- app/helpers/panel_helper.rb | 4 +- .../controllers/observations/_form.html.erb | 56 +++++++++++++------ .../observations/form/_add_to_step.erb | 30 ---------- .../observations/form/_details.html.erb | 12 ---- .../observations/form/_identify_specimen.erb | 29 ---------- .../observations/form/_record_step.erb | 26 --------- .../form/_specimen_section.html.erb | 4 +- .../_collection_number.html.erb | 0 .../{ => specimen}/_herbarium_record.html.erb | 0 .../observations/namings/_fields.erb | 17 +++--- .../observations/namings/_form.erb | 16 ++++-- .../observations/namings/edit.html.erb | 3 +- .../observations/namings/new.html.erb | 3 +- .../shared/_form_name_feedback.erb | 15 ++--- 14 files changed, 66 insertions(+), 149 deletions(-) delete mode 100644 app/views/controllers/observations/form/_add_to_step.erb delete mode 100644 app/views/controllers/observations/form/_identify_specimen.erb delete mode 100644 app/views/controllers/observations/form/_record_step.erb rename app/views/controllers/observations/form/{ => specimen}/_collection_number.html.erb (100%) rename app/views/controllers/observations/form/{ => specimen}/_herbarium_record.html.erb (100%) diff --git a/app/helpers/panel_helper.rb b/app/helpers/panel_helper.rb index 878eb85be5..1279184a6f 100644 --- a/app/helpers/panel_helper.rb +++ b/app/helpers/panel_helper.rb @@ -18,8 +18,8 @@ def panel_block(**args, &block) concat(heading) if args[:panel_bodies].present? concat(panel_bodies(args)) - elsif args[:content].present? - concat(args[:content]) + elsif args[:formatted_content].present? + concat(content) elsif args[:collapse].present? concat(panel_collapse_body(args, content)) else diff --git a/app/views/controllers/observations/_form.html.erb b/app/views/controllers/observations/_form.html.erb index 0c4667eef6..ff938ab77e 100644 --- a/app/views/controllers/observations/_form.html.erb +++ b/app/views/controllers/observations/_form.html.erb @@ -3,9 +3,19 @@ create = (action == :create) method = create ? :post : :patch button_name = create ? :CREATE.l : :SAVE_EDITS.l -include_naming = create ? true : false has_specimen = create ? false : @observation.herbarium_records.length > 0 logging_optional = create ? false : true +naming_locals = { + create:, + button_name:, + show_reasons: false, + unfocused: true, + name_help: :form_naming_name_help_leave_blank.t +} +naming_locals = {} unless create +show_projects = @projects.any? || @error_checked_projects.any? || + @suspect_checked_projects.any? +show_lists = @lists.any? # Data for the form-images Stimulus controller. # Controller element is the form, so image dropzone can cover the whole form. @@ -20,7 +30,7 @@ image_upload_localization = { something_went_wrong: :form_observations_upload_error.t }.to_json # Outlets are how the stimulus controllers call each others' methods. -data = { +form_element_data = { controller: "form-images form-exif map", map_autocompleter_outlet: "#observation_location_autocompleter", map_open: false, @@ -32,9 +42,6 @@ data = { form_images_target: "form", exif_used: create ? false : true } -show_projects = @projects.any? || @error_checked_projects.any? || - @suspect_checked_projects.any? -show_lists = @lists.any? %> <%= form_with( @@ -45,7 +52,7 @@ show_lists = @lists.any? method:, multipart: true, id: "observation_form", - data: + data: form_element_data ) do |f| %> <% if @field_code %> @@ -53,19 +60,34 @@ show_lists = @lists.any? <%= hidden_field_tag(:field_code, @field_code) %> <% end %> - <% content = [ - render(partial: "observations/form/images", locals: { f: }), - render(partial: "observations/form/details", - locals: { f:, button_name:, location: @location, logging_optional:, - action:, include_naming: }), - ].safe_join %> <%= panel_block( heading: "#{:IMAGES.l} + #{:show_observation_details.l}", - id: "observation_images_details", content: - ) %> + id: "observation_images_details", formatted_content: true + ) do + concat(render(partial: "observations/form/images", locals: { f: })) + concat(render(partial: "observations/form/details", + locals: { f:, action:, button_name:, location: @location, + logging_optional: })) + end %> + + <%= panel_block( + id: "observation_identification", + heading: "#{:IDENTIFICATION.l} + #{:SPECIMEN.l}", + collapse: "observation_specimen_inner", + open: true # @given_name.present? + ) do + tag.div(class: "row mt-3") do + concat(tag.div(class: "col-xs-12 col-md-6") do + render(partial: "observations/namings/fields", locals: naming_locals) + end) + concat(tag.div(class: "col-xs-12 col-md-6") do + render(partial: "observations/form/specimen_section", + locals: { f:, action: }) + end) + end + end %> - <%= render(partial: "observations/form/identify_specimen", - locals: { f:, action:, button_name:, include_naming: }) %> + <%= submit_button(form: f, button: button_name, center: true) %> <%= panel_block( heading: :NOTES.l, @@ -77,8 +99,6 @@ show_lists = @lists.any? locals: { form: f, fields: @observation.form_notes_parts(@user) }) end %> - <%= submit_button(form: f, button: button_name, center: true) %> - <% if show_projects %> <%= panel_block( heading: :PROJECTS.l, diff --git a/app/views/controllers/observations/form/_add_to_step.erb b/app/views/controllers/observations/form/_add_to_step.erb deleted file mode 100644 index 47f2d195d8..0000000000 --- a/app/views/controllers/observations/form/_add_to_step.erb +++ /dev/null @@ -1,30 +0,0 @@ -<%# locals: (f:, button_name:) -%> -<%# Add to Project and List section of create_observation form %> - -<%= tab_panel(id: "add_to") do %> - <%= panel_block(id: "observation_projects_and_lists", - heading: "#{:PROJECTS.l} + #{:SPECIES_LISTS.l}") do %> - - <%= tag.div(class: "row mt-3") do %> - <% if @projects.any? %> - <%= tag.div(class: "col-xs-12 col-sm-6") do - render(partial: "observations/form/projects", - locals: { button_name: }) - end %> - <% end %> - <% if @lists.any? %> - <%= tag.div(class: "col-xs-12 col-sm-6") do - render(partial: "observations/form/species_lists") - end %> - <% end %> - <% end %> - - <%= tag.div(class: "row mt-5 text-center", id: "step-nav-3") do - [ - tab_link(:BACK.l, id: "identify", button: true), - submit_button(form: f, button: button_name) - ].safe_join(" ") - end %> - <% end %> -<% end %> - diff --git a/app/views/controllers/observations/form/_details.html.erb b/app/views/controllers/observations/form/_details.html.erb index 37d1201fc6..40876c228f 100644 --- a/app/views/controllers/observations/form/_details.html.erb +++ b/app/views/controllers/observations/form/_details.html.erb @@ -8,18 +8,6 @@ t_s = { lng: { abbr: :LNG.l, full: :LONGITUDE.l, addon: "º" }, alt: { abbr: :ALT.l, full: :ALTITUDE.l, addon: "m" } } -naming_locals = if include_naming - { - f: f, - action: action, - button_name: button_name, - show_reasons: false, - unfocused: true, - name_help: :form_naming_name_help_leave_blank.t - } - else - {} - end %> <%= tag.div(class: "panel-body border-top", id: "observation_details") do %> diff --git a/app/views/controllers/observations/form/_identify_specimen.erb b/app/views/controllers/observations/form/_identify_specimen.erb deleted file mode 100644 index 5f85f69bb7..0000000000 --- a/app/views/controllers/observations/form/_identify_specimen.erb +++ /dev/null @@ -1,29 +0,0 @@ -<%# locals: (f:, action:, button_name:, include_naming:) -%> - -<%= panel_block( - id: "observation_identification", - heading: "#{:IDENTIFICATION.l} + #{:SPECIMEN.l}", - collapse: "observation_specimen_inner", - open: @given_name.present? -) do %> - <%= tag.div(class: "row mt-3") do %> - <%= tag.div(class: "col-xs-12 col-md-6") do %> - <% if include_naming - naming_locals = { - f: f, - action: action, - button_name: button_name, - show_reasons: false, - unfocused: true, - name_help: :form_naming_name_help_leave_blank.t - } %> - <%= render(partial: "observations/namings/fields", - locals: naming_locals) %> - <% end %> - <% end %> - <%= tag.div(class: "col-xs-12 col-md-6") do %> - <%= render(partial: "observations/form/specimen_section", - locals: { f:, action: }) %> - <% end %> - <% end %> -<% end %> diff --git a/app/views/controllers/observations/form/_record_step.erb b/app/views/controllers/observations/form/_record_step.erb deleted file mode 100644 index a49bdf2488..0000000000 --- a/app/views/controllers/observations/form/_record_step.erb +++ /dev/null @@ -1,26 +0,0 @@ -<%# locals: (f:, button_name:, location:, logging_optional:) -%> -<%# NOTE: not using panel_block helper, because it has three panel-body divs %> - -<%= tab_panel(id: "record", active: true) do %> - <%= tag.div( - id: "observation_images_details", class: "panel panel-default" - ) do %> - - <%= tag.div(class: "panel-heading") do - tag.h4("#{:IMAGES.l} + #{:show_observation_details.l}", - class: "panel-title") - end %> - - <%= render(partial: "observations/form/images", locals: { f: f }) %> - - <%= render(partial: "observations/form/details", - locals: { f:, button_name:, location:, logging_optional: }) %> - - <%= tag.div(class: "panel-body mt-4") do - tag.div(class: "text-center", id: "step-nav-1") do - tab_link(:NEXT.l, id: "identify", button: true) - end - end %> - - <% end %> -<% end %> diff --git a/app/views/controllers/observations/form/_specimen_section.html.erb b/app/views/controllers/observations/form/_specimen_section.html.erb index 4fae2a6b43..4ef974a6e9 100644 --- a/app/views/controllers/observations/form/_specimen_section.html.erb +++ b/app/views/controllers/observations/form/_specimen_section.html.erb @@ -29,8 +29,8 @@ herbarium_record. Fields hidden unless box checked. %> <%= tag.div(id: "specimen_fields", class: ("hidden" if !@observation.specimen), data: { specimen_target: "fields" }) do %> - <%= render(partial: "observations/form/collection_number") %> - <%= render(partial: "observations/form/herbarium_record") %> + <%= render(partial: "observations/form/specimen/collection_number") %> + <%= render(partial: "observations/form/specimen/herbarium_record") %> <% end %> <% end %> diff --git a/app/views/controllers/observations/form/_collection_number.html.erb b/app/views/controllers/observations/form/specimen/_collection_number.html.erb similarity index 100% rename from app/views/controllers/observations/form/_collection_number.html.erb rename to app/views/controllers/observations/form/specimen/_collection_number.html.erb diff --git a/app/views/controllers/observations/form/_herbarium_record.html.erb b/app/views/controllers/observations/form/specimen/_herbarium_record.html.erb similarity index 100% rename from app/views/controllers/observations/form/_herbarium_record.html.erb rename to app/views/controllers/observations/form/specimen/_herbarium_record.html.erb diff --git a/app/views/controllers/observations/namings/_fields.erb b/app/views/controllers/observations/namings/_fields.erb index 86a4aa711b..1bb677d2a5 100644 --- a/app/views/controllers/observations/namings/_fields.erb +++ b/app/views/controllers/observations/namings/_fields.erb @@ -1,18 +1,17 @@ +<%# locals: (create:, button_name:, show_reasons:, unfocused: false, name_help: :form_naming_name_help.t, context: "blank" ) -%> + <% # This is included by obs form, naming new/edit form + lightbox identifier - -unfocused ||= false -focus_on_name = !unfocused && (button_name != :CREATE.l || @given_name.empty?) -focus_on_vote = !unfocused && (button_name == :CREATE.l && @given_name.present?) +focus_on_name = !unfocused && (!create || @given_name.empty?) +focus_on_vote = !unfocused && (create && @given_name.present?) feedback_locals = { - f: f, button_name: button_name, given_name: @given_name, + names: @names, valid_names: @valid_names, suggest_corrections: @suggest_corrections, - parent_deprecated: @parent_deprecated, - names: @names + parent_deprecated: @parent_deprecated } menu = unless @vote&.value&.nonzero? Vote.opinion_menu @@ -20,9 +19,7 @@ menu = unless @vote&.value&.nonzero? Vote.confidence_menu end confidences = options_for_select(menu, @vote&.value) -select_opts = { include_blank: ["new", "create"].include?(action_name) } -context ||= "blank" -name_help ||= :form_naming_name_help.t +select_opts = { include_blank: create } feedback = if @given_name.present? tag.div do render(partial: "shared/form_name_feedback", diff --git a/app/views/controllers/observations/namings/_form.erb b/app/views/controllers/observations/namings/_form.erb index 05a89d8eb0..9e4ce63469 100644 --- a/app/views/controllers/observations/namings/_form.erb +++ b/app/views/controllers/observations/namings/_form.erb @@ -1,9 +1,12 @@ +<%# locals: (local:, show_reasons: true, form_locals: {}) -%> + <% # Fields must be separate because they're included in the obs form too. # HTML ID's may seem overly precise, but there may be more than one of # these forms open on a page if modal. IDs must be unique. case action_name when "new", "create" + create = true button_name = :CREATE.l method = :post id = "obs_#{@observation.id}_naming_form" @@ -11,6 +14,7 @@ when "new", "create" approved_name: @given_name, q: get_query_param) when "edit", "update" + create = false button_name = :SAVE_EDITS.l method = :patch id = "obs_#{@observation.id}_naming_#{@naming.id}_form" @@ -20,6 +24,7 @@ when "edit", "update" q: get_query_param) end +# `local` true means do not send via Turbo. form_args = { model: @naming, url: url, method: method, id: id } if local_assigns[:local] == true form_args = form_args.merge({ local: true }) @@ -27,16 +32,15 @@ else form_args = form_args.deep_merge({ data: { turbo: true } }) end -# Note: the form needs local_assigns[:form_locals]. -# I can't find where show_reasons is ever false - AN 20230801 -form_locals = local_assigns[:form_locals] || {} +# `naming_locals`: modal forms can accept a `form_locals` local. The controller +# may send `context` (i.e. where the form appears), which defaults to "blank". +# `show_reasons` is false on the obs form, true on the naming form. +naming_locals = { create:, button_name:, show_reasons: }.merge(form_locals) %> <%= form_with(**form_args) do |f| %> + <%= render(partial: "observations/namings/fields", locals: naming_locals) %> <%= submit_button(form: f, button: button_name, center: true) %> - <%= render(partial: "observations/namings/fields", - locals: { f: f, button_name: button_name }.merge(form_locals)) %> - <% end # form %> diff --git a/app/views/controllers/observations/namings/edit.html.erb b/app/views/controllers/observations/namings/edit.html.erb index 715ab3e8c9..e8a752b14c 100644 --- a/app/views/controllers/observations/namings/edit.html.erb +++ b/app/views/controllers/observations/namings/edit.html.erb @@ -13,8 +13,7 @@ add_tab_set(naming_form_edit_tabs(obs: @observation))
<%= render(partial: "observations/namings/form", - locals: { action: :update, show_reasons: true, - local: true }) %> + locals: { show_reasons: true, local: true }) %>
diff --git a/app/views/controllers/observations/namings/new.html.erb b/app/views/controllers/observations/namings/new.html.erb index c4ff406d8d..161f4aa7cf 100644 --- a/app/views/controllers/observations/namings/new.html.erb +++ b/app/views/controllers/observations/namings/new.html.erb @@ -13,8 +13,7 @@ add_tab_set(naming_form_new_tabs(obs: @observation))
<%= render(partial: "observations/namings/form", - locals: { action: :create, show_reasons: true, - local: true }) %> + locals: { show_reasons: true, local: true }) %>
diff --git a/app/views/controllers/shared/_form_name_feedback.erb b/app/views/controllers/shared/_form_name_feedback.erb index 5ae008500f..be83f5e852 100644 --- a/app/views/controllers/shared/_form_name_feedback.erb +++ b/app/views/controllers/shared/_form_name_feedback.erb @@ -1,6 +1,8 @@ +<%# locals: (given_name:, button_name:, names:, valid_names:, suggest_corrections:, parent_deprecated:) -%> + <%# -Handling deprecated, new & multiple Names -Used by Name and Naming create and edit pages +Feedback if the user entered deprecated, new or multiple Names +Used by Observation, Name and Naming create and edit pages Does two things: Describes the issue - Deprecated, Parent Deprecated, or Not Recognized Adds Help how to proceed - depends on issue and the button @@ -12,18 +14,11 @@ names - Name(s) corresponding to given_name valid_names - Name(s) that are valid synonyms suggest_corrections - t/f whether to suggest correction(s) parent_deprecated - t/f - -TODO: -Differentiate warning (valid_names) from error (!valid_names) -A conditional to watch is `if @params[:given_name].present?`. -Also, views/observations/namings/fields is doing too much work, -the multiple local_assigns for this partial should be set upstream. %> <%= +##### Warnings ##### if valid_names - ##### Warnings ##### - tag.div(class: "alert alert-warning", id: "name_messages") do concat(tag.div do if suggest_corrections || names.blank? From dfe99dd100abfb6750cbb61aa7cafa1b2f2d36d5 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Thu, 15 Aug 2024 15:13:11 -0700 Subject: [PATCH 15/30] Camera info - show no geolocation message --- .../observations/form/images/_camera_info.erb | 29 ++++++++++--------- config/locales/en.txt | 1 + 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/app/views/controllers/observations/form/images/_camera_info.erb b/app/views/controllers/observations/form/images/_camera_info.erb index a2e108c974..9bd29d6959 100644 --- a/app/views/controllers/observations/form/images/_camera_info.erb +++ b/app/views/controllers/observations/form/images/_camera_info.erb @@ -1,24 +1,27 @@ <%# locals: (img_id: "", lat: "", lng: "", alt: "", date: "", file_name: "", file_size: "") -%> +<% +if lat.present? + geolocation = [ + tag.strong("#{:LAT.l}: ") + tag.span(lat, class: "exif_lat"), + tag.strong("#{:LNG.l}: ") + tag.span(lng, class: "exif_lng"), + tag.strong("#{:ALT.l}: ") + tag.span(alt, class: "exif_alt") + " m" + ].safe_join(", ") +else + geolocation = tag.span("#{:image_no_geolocation.l}") +end +%> + <%= -tag.div(class: "well well-sm position-relative", - id: "camera_info_#{img_id}") do +tag.div(class: "well well-sm position-relative", id: "camera_info_#{img_id}") do [ label_tag("camera_info_#{img_id}", :image_camera_info.l), tag.div(class: "form-group") do [ tag.div do - [ - tag.strong("#{:DATE.l}: "), # :form_images_camera_date.t - carousel_exif_to_image_date_button(date: date) - ].safe_join - end, - tag.div do - [ - tag.strong("#{:LAT.l}: ") + tag.span(lat, class: "exif_lat"), - tag.strong("#{:LNG.l}: ") + tag.span(lng, class: "exif_lng"), - tag.strong("#{:ALT.l}: ") + tag.span(alt, class: "exif_alt") + " m" - ].safe_join(", ") + [tag.strong("#{:DATE.l}: "), # :form_images_camera_date.t + carousel_exif_to_image_date_button(date: date)].safe_join end, + tag.div(geolocation), carousel_transfer_exif_button(has_exif: date.present? || lat.present?) ].safe_join end, diff --git a/config/locales/en.txt b/config/locales/en.txt index b0cdd0b90a..fc7438f47c 100644 --- a/config/locales/en.txt +++ b/config/locales/en.txt @@ -1741,6 +1741,7 @@ image_exif_copied: Info copied image_use_exif: Use this info image_camera_info: Camera info + image_no_geolocation: No geolocation found image_file_name: File name image_file_size: File size From d08728f639340a72ba8f647f656c1f02ba4886ae Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Thu, 15 Aug 2024 15:13:52 -0700 Subject: [PATCH 16/30] deprecate form, remove f arg from form name feedback call --- app/views/controllers/names/synonyms/deprecate/new.html.erb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/controllers/names/synonyms/deprecate/new.html.erb b/app/views/controllers/names/synonyms/deprecate/new.html.erb index 86c7ea9f9e..ff1bb067f3 100644 --- a/app/views/controllers/names/synonyms/deprecate/new.html.erb +++ b/app/views/controllers/names/synonyms/deprecate/new.html.erb @@ -9,10 +9,10 @@ action = { controller: "/names/synonyms/deprecate", action: :create, feedback_locals = { button_name: :SUBMIT.l, given_name: @given_name, + names: @names, valid_names: @valid_names, suggest_corrections: @suggest_corrections, - parent_deprecated: @parent_deprecated, - names: @names + parent_deprecated: @parent_deprecated } deprecate_comments_help = capture do @@ -26,7 +26,7 @@ end <%= submit_button(form: f, button: :SUBMIT.l, center: true) %> <%= render(partial: "shared/form_name_feedback", - locals: feedback_locals.merge({ f: f })) if @given_name.present? %> + locals: feedback_locals) if @given_name.present? %> <%= autocompleter_field( form: f, field: :proposed_name, type: :name, From a786258bb21e05987b5b47c1c91c9c7a868b29d7 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Thu, 15 Aug 2024 17:16:12 -0700 Subject: [PATCH 17/30] fix locals, naming form only if create --- app/views/controllers/observations/_form.html.erb | 3 +-- app/views/controllers/observations/namings/_fields.erb | 2 +- app/views/controllers/observations/namings/_form.erb | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/views/controllers/observations/_form.html.erb b/app/views/controllers/observations/_form.html.erb index ff938ab77e..d9579831e2 100644 --- a/app/views/controllers/observations/_form.html.erb +++ b/app/views/controllers/observations/_form.html.erb @@ -12,7 +12,6 @@ naming_locals = { unfocused: true, name_help: :form_naming_name_help_leave_blank.t } -naming_locals = {} unless create show_projects = @projects.any? || @error_checked_projects.any? || @suspect_checked_projects.any? show_lists = @lists.any? @@ -79,7 +78,7 @@ form_element_data = { tag.div(class: "row mt-3") do concat(tag.div(class: "col-xs-12 col-md-6") do render(partial: "observations/namings/fields", locals: naming_locals) - end) + end) if create concat(tag.div(class: "col-xs-12 col-md-6") do render(partial: "observations/form/specimen_section", locals: { f:, action: }) diff --git a/app/views/controllers/observations/namings/_fields.erb b/app/views/controllers/observations/namings/_fields.erb index 1bb677d2a5..ebd3233b17 100644 --- a/app/views/controllers/observations/namings/_fields.erb +++ b/app/views/controllers/observations/namings/_fields.erb @@ -1,4 +1,4 @@ -<%# locals: (create:, button_name:, show_reasons:, unfocused: false, name_help: :form_naming_name_help.t, context: "blank" ) -%> +<%# locals: (create:, button_name:, show_reasons: false, unfocused: false, name_help: :form_naming_name_help.t, context: "blank" ) -%> <% # This is included by obs form, naming new/edit form + lightbox identifier diff --git a/app/views/controllers/observations/namings/_form.erb b/app/views/controllers/observations/namings/_form.erb index 9e4ce63469..2cd54b4afb 100644 --- a/app/views/controllers/observations/namings/_form.erb +++ b/app/views/controllers/observations/namings/_form.erb @@ -26,7 +26,7 @@ end # `local` true means do not send via Turbo. form_args = { model: @naming, url: url, method: method, id: id } -if local_assigns[:local] == true +if local form_args = form_args.merge({ local: true }) else form_args = form_args.deep_merge({ data: { turbo: true } }) From cb14a80b87a00e2817eb646833fc0a18511be932 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Fri, 16 Aug 2024 00:16:15 -0700 Subject: [PATCH 18/30] panel show/hide css --- app/assets/stylesheets/Admin.scss | 2 +- app/assets/stylesheets/Agaricus.scss | 2 +- app/assets/stylesheets/Amanita.scss | 2 +- app/assets/stylesheets/BlackOnWhite.scss | 2 +- app/assets/stylesheets/Cantharellaceae.scss | 2 +- app/assets/stylesheets/Hygrocybe.scss | 2 +- app/assets/stylesheets/Sudo.scss | 2 +- app/assets/stylesheets/mo/_icons.scss | 6 ++- app/helpers/panel_helper.rb | 52 ++++++++++++------- .../controllers/shared/_notes_fields.html.erb | 3 +- 10 files changed, 45 insertions(+), 30 deletions(-) diff --git a/app/assets/stylesheets/Admin.scss b/app/assets/stylesheets/Admin.scss index ee2d668f7d..aef9b29a8d 100644 --- a/app/assets/stylesheets/Admin.scss +++ b/app/assets/stylesheets/Admin.scss @@ -9,7 +9,7 @@ $LOGO_BG_COLOR: yellow; $LOGO_HOVER_FG_COLOR: purple; $LOGO_HOVER_BG_COLOR: yellow; -$LEFT_BAR_BORDER_COLOR: #545454; // gray +$LEFT_BAR_BORDER_COLOR: #535454; // gray $LEFT_BAR_BORDER_RADIUS: 0px; $LEFT_BAR_HEADER_FG_COLOR: black; $LEFT_BAR_HEADER_BG_COLOR: yellow; diff --git a/app/assets/stylesheets/Agaricus.scss b/app/assets/stylesheets/Agaricus.scss index 3658b0575d..de32becc3c 100644 --- a/app/assets/stylesheets/Agaricus.scss +++ b/app/assets/stylesheets/Agaricus.scss @@ -1,7 +1,7 @@ @import "defaults"; $augustus_cap: #ECCF95; -$brasiliensis_gills_1: #A06362; // #A06463 +$brasiliensis_gills_1: #BF6362; // #A06463 $brasiliensis_gills_2: #743931; $campestris_cap: #F6F0F2; $cupreobrunneus_gills: #3B2821; diff --git a/app/assets/stylesheets/Amanita.scss b/app/assets/stylesheets/Amanita.scss index b790f04f51..8439d52e28 100644 --- a/app/assets/stylesheets/Amanita.scss +++ b/app/assets/stylesheets/Amanita.scss @@ -13,7 +13,7 @@ $calyptroderma_middle_cap: #c18346; $muscaria_background: #cc2616; $muscaria_foreground: #fff8c6; $velosa_background: #dd9d5f; -$velosa_light_veil: #fce9d3; // faebd4 +$velosa_light_veil: #f9e9d3; // faebd4 $velosa_dark_veil: #f4d5a6; $novinupta_background: #d1afa5; $pachycolea_background: #383138; diff --git a/app/assets/stylesheets/BlackOnWhite.scss b/app/assets/stylesheets/BlackOnWhite.scss index 8a5fe17a1d..beb7ee2336 100644 --- a/app/assets/stylesheets/BlackOnWhite.scss +++ b/app/assets/stylesheets/BlackOnWhite.scss @@ -4,7 +4,7 @@ $LOGO_BORDER_COLOR: #DDDDDD; $LEFT_BAR_BORDER_COLOR: #DDDDDD; -$TOP_BAR_BORDER_COLOR: #D9DaDa; +$TOP_BAR_BORDER_COLOR: #D9D9Da; $LIST_BORDER_COLOR: #DDDDDD; $BUTTON_HOVER_BORDER_COLOR: #CCCCCC; $BUTTON_BG_COLOR: #CCCCCC; diff --git a/app/assets/stylesheets/Cantharellaceae.scss b/app/assets/stylesheets/Cantharellaceae.scss index c8547a05a9..5fc8c120c1 100644 --- a/app/assets/stylesheets/Cantharellaceae.scss +++ b/app/assets/stylesheets/Cantharellaceae.scss @@ -11,7 +11,7 @@ $tubaeformis_hymenium: #c2914c; $tubaeformis_bright_stipe: #ffb230; $tubaeformis_dark_stipe: #4b2e0c; $tubaeformis_light_stipe: #e5bb67; -$cornucopioides_dark_hymenium: #12120c; // image 465 #10110b +$cornucopioides_dark_hymenium: #12120d; // image 465 #10110b $cornucopioides_light_hymenium: #9b9690; $cornucopioides_dark_cap: #4f4337; $cornucopioides_light_cap: #826c57; diff --git a/app/assets/stylesheets/Hygrocybe.scss b/app/assets/stylesheets/Hygrocybe.scss index da30be5b27..6546aca668 100644 --- a/app/assets/stylesheets/Hygrocybe.scss +++ b/app/assets/stylesheets/Hygrocybe.scss @@ -1,6 +1,6 @@ @import "defaults"; -$conica_stain: #34352d; // #37372f +$conica_stain: #34342d; // #37372f $conica_cap_red: #a31404; $conica_cap_orange: #dd6226; $conica_cap_yellow: #ffbf01; diff --git a/app/assets/stylesheets/Sudo.scss b/app/assets/stylesheets/Sudo.scss index 03adfe837c..06ffc4e641 100644 --- a/app/assets/stylesheets/Sudo.scss +++ b/app/assets/stylesheets/Sudo.scss @@ -1,6 +1,6 @@ @import "defaults"; -$BODY_BG_COLOR: #DE7300; // #DD7700 +$BODY_BG_COLOR: #DE7200; // #DD7700 $LOGO_BORDER_COLOR: black; $LOGO_BORDER_WIDTH: 2px; // vs 1px in default diff --git a/app/assets/stylesheets/mo/_icons.scss b/app/assets/stylesheets/mo/_icons.scss index 82c0b4ddc6..6e96d3a9ee 100644 --- a/app/assets/stylesheets/mo/_icons.scss +++ b/app/assets/stylesheets/mo/_icons.scss @@ -99,11 +99,13 @@ } // This is for the stateful icon_link_to helper -.icon-link { +.icon-link, +.panel-collapse-trigger { .active-icon, .active-label { display: none; } - &.active { + &.active, + &.collapsed { .link-icon:not(.active-icon), .sr-only:not(.active-label) { display: none; diff --git a/app/helpers/panel_helper.rb b/app/helpers/panel_helper.rb index 1279184a6f..d487936f4e 100644 --- a/app/helpers/panel_helper.rb +++ b/app/helpers/panel_helper.rb @@ -39,31 +39,43 @@ def panel_heading(args) return "" unless args[:heading] tag.div(class: "panel-heading") do - tag.h4(class: "panel-title") do - els = [args[:heading]] - if args[:heading_links].present? - els << tag.span(args[:heading_links], class: "float-right") - elsif args[:collapse].present? - els << tag.span(panel_collapse_trigger(args), class: "float-right") - end - els.safe_join + if args[:collapse].present? + panel_heading_collapse_elements(args) + else + panel_heading_elements(args) end end end - # The caret icon that toggles the panel collapse. + def panel_heading_elements(args) + els = [args[:heading]] + if args[:heading_links].present? + els << tag.span(args[:heading_links], class: "float-right") + end + + tag.h4(class: "panel-title") { els.safe_join } + end + + # The whole heading is a link that toggles the panel collapse. # NOTE: args[:open] should be a boolean - def panel_collapse_trigger(args) - icon_link_to( - :OPEN.l, - "##{args[:collapse]}", - icon: :chevron_down, - active_icon: :chevron_up, - active_content: :CLOSE.l, - class: "panel-collapse-trigger", - role: "button", data: { toggle: "collapse" }, - aria: { expanded: args[:open], controls: args } - ) + def panel_heading_collapse_elements(args) + tag.h4(class: "panel-title") do + link_to( + "##{args[:collapse]}", + class: "panel-collapse-trigger", + role: "button", data: { toggle: "collapse" }, + aria: { expanded: args[:open], controls: args[:collapse] } + ) do + [args[:heading], + tag.span(panel_collapse_icons, class: "float-right")].safe_join + end + end + end + + # The caret icon that indicates toggling the panel open/collapsed. + def panel_collapse_icons + [link_icon(:chevron_down, title: :OPEN.l, class: "active-icon"), + link_icon(:chevron_up, title: :CLOSE.l)].safe_join end def panel_body(args, content) diff --git a/app/views/controllers/shared/_notes_fields.html.erb b/app/views/controllers/shared/_notes_fields.html.erb index baeeb2d1df..88592fef63 100644 --- a/app/views/controllers/shared/_notes_fields.html.erb +++ b/app/views/controllers/shared/_notes_fields.html.erb @@ -1,6 +1,7 @@ -<%# Notes section of any form %> +<%# locals: (form:, fields:) -%> <% +# Notes section of any form # Users may have custom notes "parts". This prints a single large textarea and # textile help block if there's only one notes part. Otherwise, it prints # smaller textareas and a general textile help link. From 959cdefaa5363f94b22ed504c1ce3f5e86c38faa Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Fri, 16 Aug 2024 00:16:43 -0700 Subject: [PATCH 19/30] checkbox-collapse controller --- .../checkbox-collapse_controller.js | 46 ++++++++++++ .../controllers/specimen_controller.js | 30 -------- .../controllers/observations/_form.html.erb | 13 ++-- .../observations/form/_details.html.erb | 71 +++++++++++-------- .../form/_specimen_section.html.erb | 10 +-- .../controllers/shared/_form_location_map.erb | 3 +- 6 files changed, 102 insertions(+), 71 deletions(-) create mode 100644 app/javascript/controllers/checkbox-collapse_controller.js delete mode 100644 app/javascript/controllers/specimen_controller.js diff --git a/app/javascript/controllers/checkbox-collapse_controller.js b/app/javascript/controllers/checkbox-collapse_controller.js new file mode 100644 index 0000000000..d7152d5142 --- /dev/null +++ b/app/javascript/controllers/checkbox-collapse_controller.js @@ -0,0 +1,46 @@ +import { Controller } from "@hotwired/stimulus" + +// Connects to data-controller="checkbox-collapse" +export default class extends Controller { + static targets = ["checkbox", "fields"] + + connect() { + this.element.dataset.stimulus = "checkbox-collapse-connected"; + + this.checked = this.element.dataset.checked + if (this.hasFieldsTarget && this.checked) { + this.hideShowFields() + } + } + + // Only show if user prefers + hideShowFields() { + if (this.checkboxTarget.checked) { + this.fieldsTarget.classList.remove("hidden") + this.hideFields() + } else { + this.showFields() + } + } + + // Programmatically show or hide fields. To keep the checkbox in sync, + // it also checks or unchecks the checkbox, in case called directly. + hideFields() { + $(this.fieldsTarget).hide() + this.uncheckCheckbox() + } + + showFields() { + $(this.fieldsTarget).show() + this.checkCheckbox() + } + + // This checks "specimen" anyway if people add a CN or HR. + checkCheckbox() { + this.checkboxTarget.setAttribute("checked", true) + } + + uncheckCheckbox() { + this.checkboxTarget.removeAttribute("checked") + } +} diff --git a/app/javascript/controllers/specimen_controller.js b/app/javascript/controllers/specimen_controller.js deleted file mode 100644 index 51dde8d910..0000000000 --- a/app/javascript/controllers/specimen_controller.js +++ /dev/null @@ -1,30 +0,0 @@ -import { Controller } from "@hotwired/stimulus" - -// Connects to data-controller="specimen" -export default class extends Controller { - static targets = ["checkbox", "fields"] - - connect() { - this.element.dataset.stimulus = "connected"; - - this.showPref = this.element.dataset.userPref - if (this.hasFieldsTarget && this.showPref) { - this.hideShowFields() - } - } - - // Only show if user prefers - hideShowFields() { - if (this.checkboxTarget.checked) { - this.fieldsTarget.classList.remove("hidden") - $(this.fieldsTarget).show() - } else { - $(this.fieldsTarget).hide() - } - } - - // This checks "specimen" anyway if people add a CN or HR. - checkCheckbox() { - this.checkboxTarget.setAttribute("checked", true) - } -} diff --git a/app/views/controllers/observations/_form.html.erb b/app/views/controllers/observations/_form.html.erb index d9579831e2..02220909e7 100644 --- a/app/views/controllers/observations/_form.html.erb +++ b/app/views/controllers/observations/_form.html.erb @@ -1,5 +1,5 @@ -<%# locals: (action:) -%> <% +# Declaring permitted locals in a magic comment doesn't work here (?) create = (action == :create) method = create ? :post : :patch button_name = create ? :CREATE.l : :SAVE_EDITS.l @@ -12,6 +12,8 @@ naming_locals = { unfocused: true, name_help: :form_naming_name_help_leave_blank.t } +show_notes = @observation.notes.present? +notes_fields = @observation.form_notes_parts(@user) show_projects = @projects.any? || @error_checked_projects.any? || @suspect_checked_projects.any? show_lists = @lists.any? @@ -35,6 +37,7 @@ form_element_data = { map_open: false, form_exif_autocompleter_outlet: "#observation_location_autocompleter", form_exif_map_outlet: "#observation_form", + form_exif_checkbox_collapse_outlet: "#observation_details", action: "map:reenableBtns@window->form-exif#reenableButtons", upload_max_size: max_size, localization: image_upload_localization, @@ -92,10 +95,10 @@ form_element_data = { heading: :NOTES.l, id: "observation_notes", collapse: "observation_notes_inner", - open: false + open: notes_fields.length > 1 ) do render(partial: "shared/notes_fields", - locals: { form: f, fields: @observation.form_notes_parts(@user) }) + locals: { form: f, fields: notes_fields }) end %> <% if show_projects %> @@ -103,7 +106,7 @@ form_element_data = { heading: :PROJECTS.l, id: "observation_projects", collapse: "observation_projects_inner", - open: false + open: @project_checks.any? ) do render(partial: "observations/form/projects", locals: { button_name: }) end %> @@ -114,7 +117,7 @@ form_element_data = { heading: :SPECIES_LISTS.l, id: "observation_lists", collapse: "observation_lists_inner", - open: false + open: @list_checks.any? ) do render(partial: "observations/form/species_lists") end %> diff --git a/app/views/controllers/observations/form/_details.html.erb b/app/views/controllers/observations/form/_details.html.erb index 40876c228f..ce09d35b6d 100644 --- a/app/views/controllers/observations/form/_details.html.erb +++ b/app/views/controllers/observations/form/_details.html.erb @@ -10,7 +10,8 @@ t_s = { } %> -<%= tag.div(class: "panel-body border-top", id: "observation_details") do %> +<%= tag.div(class: "panel-body border-top", id: "observation_details", + data: { controller: "checkbox-collapse" }) do %> <%= tag.div(class: "row mt-3") do %> <%= tag.div(class: "col-xs-12 col-md-6") do %> @@ -54,6 +55,10 @@ t_s = { } ) %> + <%= render(partial: "locations/form/bounds_hidden_fields", + locals: { location: @location, target_controller: :map }) %> + + <%= check_box_with_label( form: f, field: :is_collection_location, @@ -63,40 +68,46 @@ t_s = { ) %> - <%= render(partial: "locations/form/bounds_hidden_fields", - locals: { location: @location, target_controller: :map }) %> - - - <%= tag.p do - [tag.strong("#{:GEOLOCATION.l}:"), - collapse_info_trigger("geolocation_help")].safe_join(" ") - end %> - - <%= tag.div(class: "row no-gutters", - id: "observation_lat_lng_alt") do %> - <% [:lat, :lng, :alt].each do |key| %> - <%= tag.div(class: "col-xs-4") do - text_field_with_label( - form: f, field: key, class: "mb-0", addon: t_s[key][:addon], - label: [ - tag.span("#{t_s[key][:full]}:", class: "d-none d-sm-inline"), - tag.span("#{t_s[key][:abbr]}:", class: "d-inline d-sm-none") - ].safe_join, - data: { map_target: "#{key}Input", action: "map#bufferInputs" } - ) - end %> - <% end %> - <% end %> - <%= check_box_with_label( - form: f, field: :gps_hidden, label: :form_observations_gps_hidden.l, - class: "ml-5 mb-5" + form: f, field: :has_geolocation, # field is ignored + label: "#{:GEOLOCATION.l}:", + help: :form_observations_lat_long_help.t, + data: { checkbox_collapse_target: "checkbox", + action: "change->checkbox-collapse#hideShowFields" } ) %> - <%= collapse_help_block(nil, id: "geolocation_help") do %> + <%= tag.div(class: "hidden", + data: { checkbox_collapse_target: "fields" }) do %> + <%= tag.p(:form_observations_click_point.l) %> - <%= tag.p(:form_observations_lat_long_help.t) %> + + <%= tag.div(class: "row no-gutters", + id: "observation_lat_lng_alt") do %> + <% [:lat, :lng, :alt].each do |key| %> + <%= tag.div(class: "col-xs-4") do + text_field_with_label( + form: f, field: key, class: "mb-0", addon: t_s[key][:addon], + label: [ + tag.span("#{t_s[key][:full]}:", + class: "d-none d-sm-inline"), + tag.span("#{t_s[key][:abbr]}:", + class: "d-inline d-sm-none") + ].safe_join, + data: { map_target: "#{key}Input", + action: "map#bufferInputs" } + ) + end %> + <% end %> + <% end %> + + <%= check_box_with_label( + form: f, field: :gps_hidden, label: :form_observations_gps_hidden.l, + class: "ml-5 mb-5" + ) %> + + <%# collapse_help_block(nil, id: "geolocation_help") do %> + <%# tag.p(:form_observations_lat_long_help.t) %> <% end %> diff --git a/app/views/controllers/observations/form/_specimen_section.html.erb b/app/views/controllers/observations/form/_specimen_section.html.erb index 4ef974a6e9..b8733b34f7 100644 --- a/app/views/controllers/observations/form/_specimen_section.html.erb +++ b/app/views/controllers/observations/form/_specimen_section.html.erb @@ -4,16 +4,16 @@ herbarium_record. Fields hidden unless box checked. %> <%= tag.div(id: "observation_specimen_section", - data: { controller: "specimen", - user_pref: (!@user.try(&:hide_specimen_stuff?)) }) do %> + data: { controller: "checkbox-collapse", + checked: (!@user.try(&:hide_specimen_stuff?)) }) do %> <%= tag.div(class: "mt-3") do %> <%= check_box_with_label( form: f, field: :specimen, label: :form_observations_specimen_available.t, help: :form_observations_specimen_available_help.t, - data: { specimen_target: "checkbox", - action: "change->specimen#hideShowFields" } + data: { checkbox_collapse_target: "checkbox", + action: "change->checkbox-collapse#hideShowFields" } ) %> <% if action == :update %> @@ -28,7 +28,7 @@ herbarium_record. Fields hidden unless box checked. %> <%= tag.div(id: "specimen_fields", class: ("hidden" if !@observation.specimen), - data: { specimen_target: "fields" }) do %> + data: { checkbox_collapse_target: "fields" }) do %> <%= render(partial: "observations/form/specimen/collection_number") %> <%= render(partial: "observations/form/specimen/herbarium_record") %> <% end %> diff --git a/app/views/controllers/shared/_form_location_map.erb b/app/views/controllers/shared/_form_location_map.erb index 0fb5a0a0e4..44addb8671 100644 --- a/app/views/controllers/shared/_form_location_map.erb +++ b/app/views/controllers/shared/_form_location_map.erb @@ -22,7 +22,8 @@ on an ancestor element that also contains the inputs tag.span(:form_observations_hide_map.l, class: "map-hide mx-2") ].safe_join, name: "map_toggle", class: "map-toggle", - data: { map_target: "toggleMapBtn", action: "map#toggleMap", + data: { map_target: "toggleMapBtn", + action: "map#toggleMap checkbox-collapse#showFields", toggle: "collapse", target: "##{id}" }, aria: { expanded: "false", controls: id } ) %> From 369e610e9f54c0d23a5c62ae47b27cc194869fe9 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Fri, 16 Aug 2024 00:29:07 -0700 Subject: [PATCH 20/30] hopefully fix checkboxes --- .../controllers/checkbox-collapse_controller.js | 13 +++++++------ .../controllers/observations/form/_details.html.erb | 2 +- .../observations/form/_specimen_section.html.erb | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app/javascript/controllers/checkbox-collapse_controller.js b/app/javascript/controllers/checkbox-collapse_controller.js index d7152d5142..4ca368b53d 100644 --- a/app/javascript/controllers/checkbox-collapse_controller.js +++ b/app/javascript/controllers/checkbox-collapse_controller.js @@ -7,19 +7,19 @@ export default class extends Controller { connect() { this.element.dataset.stimulus = "checkbox-collapse-connected"; - this.checked = this.element.dataset.checked - if (this.hasFieldsTarget && this.checked) { - this.hideShowFields() + this.showPref = this.element.dataset.userPref + if (this.hasFieldsTarget && this.showPref) { + this.fieldsTarget.style.display = "none" + this.fieldsTarget.classList.remove("hidden") } } // Only show if user prefers hideShowFields() { if (this.checkboxTarget.checked) { - this.fieldsTarget.classList.remove("hidden") - this.hideFields() + $(this.fieldsTarget).show() } else { - this.showFields() + $(this.fieldsTarget).hide() } } @@ -31,6 +31,7 @@ export default class extends Controller { } showFields() { + this.fieldsTarget.classList.remove("hidden") $(this.fieldsTarget).show() this.checkCheckbox() } diff --git a/app/views/controllers/observations/form/_details.html.erb b/app/views/controllers/observations/form/_details.html.erb index ce09d35b6d..63a28e80eb 100644 --- a/app/views/controllers/observations/form/_details.html.erb +++ b/app/views/controllers/observations/form/_details.html.erb @@ -11,7 +11,7 @@ t_s = { %> <%= tag.div(class: "panel-body border-top", id: "observation_details", - data: { controller: "checkbox-collapse" }) do %> + data: { controller: "checkbox-collapse", user_pref: true }) do %> <%= tag.div(class: "row mt-3") do %> <%= tag.div(class: "col-xs-12 col-md-6") do %> diff --git a/app/views/controllers/observations/form/_specimen_section.html.erb b/app/views/controllers/observations/form/_specimen_section.html.erb index b8733b34f7..ea58eb8264 100644 --- a/app/views/controllers/observations/form/_specimen_section.html.erb +++ b/app/views/controllers/observations/form/_specimen_section.html.erb @@ -5,7 +5,7 @@ herbarium_record. Fields hidden unless box checked. %> <%= tag.div(id: "observation_specimen_section", data: { controller: "checkbox-collapse", - checked: (!@user.try(&:hide_specimen_stuff?)) }) do %> + user_pref: (!@user.try(&:hide_specimen_stuff?)) }) do %> <%= tag.div(class: "mt-3") do %> <%= check_box_with_label( From 1b18363645ec622f4d1215c69ec7cfc070a0b7ae Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Fri, 16 Aug 2024 13:26:19 -0700 Subject: [PATCH 21/30] Simplify checkbox controller --- app/javascript/controllers/checkbox-collapse_controller.js | 6 ------ app/views/controllers/observations/form/_details.html.erb | 6 +++--- .../observations/form/_specimen_section.html.erb | 5 ++--- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/app/javascript/controllers/checkbox-collapse_controller.js b/app/javascript/controllers/checkbox-collapse_controller.js index 4ca368b53d..afd0250912 100644 --- a/app/javascript/controllers/checkbox-collapse_controller.js +++ b/app/javascript/controllers/checkbox-collapse_controller.js @@ -6,12 +6,6 @@ export default class extends Controller { connect() { this.element.dataset.stimulus = "checkbox-collapse-connected"; - - this.showPref = this.element.dataset.userPref - if (this.hasFieldsTarget && this.showPref) { - this.fieldsTarget.style.display = "none" - this.fieldsTarget.classList.remove("hidden") - } } // Only show if user prefers diff --git a/app/views/controllers/observations/form/_details.html.erb b/app/views/controllers/observations/form/_details.html.erb index 63a28e80eb..15d4b2e584 100644 --- a/app/views/controllers/observations/form/_details.html.erb +++ b/app/views/controllers/observations/form/_details.html.erb @@ -77,7 +77,8 @@ t_s = { action: "change->checkbox-collapse#hideShowFields" } ) %> - <%= tag.div(class: "hidden", + <%= tag.div(id: "observation_geolocation", + style: ("display: none;" unless @observation.lat), data: { checkbox_collapse_target: "fields" }) do %> <%= tag.p(:form_observations_click_point.l) %> @@ -121,8 +122,7 @@ t_s = { <% end %> - <%= tag.div(class: "col-xs-12 col-md-6", - id: "observation_geolocation") do %> + <%= tag.div(class: "col-xs-12 col-md-6") do %> <%= render( partial: "shared/form_location_map", locals: { id: "observation_form_map", map_type: "observation" } diff --git a/app/views/controllers/observations/form/_specimen_section.html.erb b/app/views/controllers/observations/form/_specimen_section.html.erb index ea58eb8264..362fcd9ad8 100644 --- a/app/views/controllers/observations/form/_specimen_section.html.erb +++ b/app/views/controllers/observations/form/_specimen_section.html.erb @@ -4,8 +4,7 @@ herbarium_record. Fields hidden unless box checked. %> <%= tag.div(id: "observation_specimen_section", - data: { controller: "checkbox-collapse", - user_pref: (!@user.try(&:hide_specimen_stuff?)) }) do %> + data: { controller: "checkbox-collapse" }) do %> <%= tag.div(class: "mt-3") do %> <%= check_box_with_label( @@ -27,7 +26,7 @@ herbarium_record. Fields hidden unless box checked. %> <% if action == :create %> <%= tag.div(id: "specimen_fields", - class: ("hidden" if !@observation.specimen), + style: ("display: none;" unless @observation.specimen), data: { checkbox_collapse_target: "fields" }) do %> <%= render(partial: "observations/form/specimen/collection_number") %> <%= render(partial: "observations/form/specimen/herbarium_record") %> From d6ebdf7530651b83d65bf7c803636289455c600d Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Fri, 16 Aug 2024 13:26:28 -0700 Subject: [PATCH 22/30] Fix checkbox help --- app/helpers/forms_helper.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/helpers/forms_helper.rb b/app/helpers/forms_helper.rb index e3eda3da22..2897affb36 100644 --- a/app/helpers/forms_helper.rb +++ b/app/helpers/forms_helper.rb @@ -92,14 +92,14 @@ def check_box_with_label(**args) wrap_class = form_group_wrap_class(args, "checkbox") tag.div(class: wrap_class) do - args[:form].label(args[:field]) do + concat(args[:form].label(args[:field]) do concat(args[:form].check_box(args[:field], opts)) concat(args[:label]) if args[:between].present? concat(tag.div(class: "d-inline-block ml-3") { args[:between] }) end - concat(args[:append]) if args[:append].present? - end + end) + concat(args[:append]) if args[:append].present? end end @@ -126,14 +126,14 @@ def radio_with_label(**args) wrap_class = form_group_wrap_class(args, "radio") tag.div(class: wrap_class) do - args[:form].label("#{args[:field]}_#{args[:value]}") do + concat(args[:form].label("#{args[:field]}_#{args[:value]}") do concat(args[:form].radio_button(args[:field], args[:value], opts)) concat(args[:label]) if args[:between].present? concat(tag.div(class: "d-inline-block ml-3") { args[:between] }) end - concat(args[:append]) if args[:append].present? - end + end) + concat(args[:append]) if args[:append].present? end end From 5d0e910e47c2d31d11bba340c8c2d4871ce2e514 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Fri, 16 Aug 2024 13:49:24 -0700 Subject: [PATCH 23/30] Fix image w geolocation showing/hiding geoloc fields --- .../controllers/form-exif_controller.js | 21 ++++++++++++++----- .../observations/form/_details.html.erb | 2 +- .../observations/form/images/_camera_info.erb | 10 ++++----- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/app/javascript/controllers/form-exif_controller.js b/app/javascript/controllers/form-exif_controller.js index 34c073ac5c..6f4e4cff5f 100644 --- a/app/javascript/controllers/form-exif_controller.js +++ b/app/javascript/controllers/form-exif_controller.js @@ -14,10 +14,10 @@ const internalConfig = { // Connects to data-controller="form-exif" export default class extends Controller { static targets = ["carousel", "item", "useExifBtn"] - static outlets = ["autocompleter", "map"] + static outlets = ["autocompleter", "map", "checkbox-collapse"] connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "form-exif-connected"; Object.assign(this, internalConfig); Object.assign(this.localized_text, @@ -68,25 +68,32 @@ export default class extends Controller { } populateExifGPS(itemElement, exif_data) { - const _exif_lat = itemElement.querySelector(".exif_lat"), + const _exif_gps = itemElement.querySelector(".exif_gps"), + _exif_no_gps = itemElement.querySelector(".exif_no_gps"), + _exif_lat = itemElement.querySelector(".exif_lat"), _exif_lng = itemElement.querySelector(".exif_lng"), _exif_alt = itemElement.querySelector(".exif_alt"), _use_exif_button = itemElement.querySelector('.use_exif_btn'); // Geocode Logic // check if there is geodata on the image - if (exif_data.GPSLatitude && exif_data.GPSLongitude) { + if (exif_data.GPSLatitude && exif_data.GPSLatitude.description && + exif_data.GPSLongitude && exif_data.GPSLongitude.description) { const latLngAlt = this.getLatLngEXIF(exif_data), { lat, lng, alt } = latLngAlt; // Set item's data-geocode attribute so we can have a record itemElement.dataset.geocode = JSON.stringify(latLngAlt); - // These are not inputs, they're spans so we can't set the value + // These are spans, not inputs — set innerText, not value _exif_lat.innerText = lat == null ? lat : lat.toFixed(4); _exif_lng.innerText = lng == null ? lng : lng.toFixed(4); _exif_alt.innerText = alt == null ? alt : alt.toFixed(0); _use_exif_button.classList.remove('d-none'); + } else { + // Show the "no GPS" message + _exif_gps.classList.add("d-none"); + _exif_no_gps.classList.remove("d-none"); } } @@ -185,6 +192,10 @@ export default class extends Controller { } // disables the button, even when called programmatically this.selectExifButton(element); + // show the geolocation fields + if (this.hasCheckboxCollapseOutlet) { + this.checkboxCollapseOutlet.showFields(); + } } // Disables this button but enables others, kind of like a radio. Happens on diff --git a/app/views/controllers/observations/form/_details.html.erb b/app/views/controllers/observations/form/_details.html.erb index 15d4b2e584..6bafe82150 100644 --- a/app/views/controllers/observations/form/_details.html.erb +++ b/app/views/controllers/observations/form/_details.html.erb @@ -11,7 +11,7 @@ t_s = { %> <%= tag.div(class: "panel-body border-top", id: "observation_details", - data: { controller: "checkbox-collapse", user_pref: true }) do %> + data: { controller: "checkbox-collapse" }) do %> <%= tag.div(class: "row mt-3") do %> <%= tag.div(class: "col-xs-12 col-md-6") do %> diff --git a/app/views/controllers/observations/form/images/_camera_info.erb b/app/views/controllers/observations/form/images/_camera_info.erb index 9bd29d6959..1d5e322454 100644 --- a/app/views/controllers/observations/form/images/_camera_info.erb +++ b/app/views/controllers/observations/form/images/_camera_info.erb @@ -1,14 +1,14 @@ <%# locals: (img_id: "", lat: "", lng: "", alt: "", date: "", file_name: "", file_size: "") -%> <% -if lat.present? - geolocation = [ +# on new form, lat will not be present until form-exif reads it from the image +gps = tag.span(class: "exif_gps") do + [ tag.strong("#{:LAT.l}: ") + tag.span(lat, class: "exif_lat"), tag.strong("#{:LNG.l}: ") + tag.span(lng, class: "exif_lng"), tag.strong("#{:ALT.l}: ") + tag.span(alt, class: "exif_alt") + " m" ].safe_join(", ") -else - geolocation = tag.span("#{:image_no_geolocation.l}") end +no_gps = tag.span("#{:image_no_geolocation.l}", class: "exif_no_gps d-none") %> <%= @@ -21,7 +21,7 @@ tag.div(class: "well well-sm position-relative", id: "camera_info_#{img_id}") do [tag.strong("#{:DATE.l}: "), # :form_images_camera_date.t carousel_exif_to_image_date_button(date: date)].safe_join end, - tag.div(geolocation), + tag.div { [gps, no_gps].safe_join }, carousel_transfer_exif_button(has_exif: date.present? || lat.present?) ].safe_join end, From 7243d6df3c59206cc959c5ee3ee19c97a0eeb1c9 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Fri, 16 Aug 2024 14:48:22 -0700 Subject: [PATCH 24/30] Refactor autocompleter wrap for dropdown, append --- app/helpers/autocompleter_helper.rb | 28 ++++++-------- .../controllers/autocompleter_controller.js | 18 ++++++++- .../observations/namings/_fields.erb | 38 +++++++++---------- 3 files changed, 46 insertions(+), 38 deletions(-) diff --git a/app/helpers/autocompleter_helper.rb b/app/helpers/autocompleter_helper.rb index aeb7cddca1..98c5e5e205 100644 --- a/app/helpers/autocompleter_helper.rb +++ b/app/helpers/autocompleter_helper.rb @@ -21,15 +21,19 @@ def autocompleter_field(**args) data: { autocompleter_target: "input" } }.deep_merge(args.except(*autocompleter_outer_args)) ac_args[:class] = class_names("dropdown", args[:class]) - ac_args[:wrap_data] = autocompleter_wrap_data(args) + # doing our own wrap here, because dropdown is position-absolute + ac_args[:wrap_data] = { autocompleter_target: "wrap"} ac_args[:label_after] = autocompleter_label_after(args) ac_args[:label_end] = autocompleter_label_end(args) - ac_args[:append] = autocompleter_append(args) + ac_args[:append] = autocompleter_dropdown - if args[:textarea] == true - text_area_with_label(**ac_args) - else - text_field_with_label(**ac_args) + tag.div(data: autocompleter_wrap_data(args)) do + if args[:textarea] == true + concat(text_area_with_label(**ac_args)) + else + concat(text_field_with_label(**ac_args)) + end + concat(args[:append]) end end @@ -37,7 +41,7 @@ def autocompleter_field(**args) def autocompleter_outer_args [:wrap_data, :type, :separator, :textarea, :hidden_value, :hidden_data, :create_text, :keep_text, :edit_text, :find_text, :create, :create_path, - :map_outlet, :geocode_outlet] + :map_outlet, :geocode_outlet].freeze end def autocompleter_wrap_data(args) @@ -45,8 +49,7 @@ def autocompleter_wrap_data(args) controller: :autocompleter, type: args[:type], separator: args[:separator], autocompleter_map_outlet: args[:map_outlet], - autocompleter_geocode_outlet: args[:geocode_outlet], - autocompleter_target: "wrap" + autocompleter_geocode_outlet: args[:geocode_outlet] }.deep_merge(args[:wrap_data] || {}) end @@ -68,13 +71,6 @@ def autocompleter_label_end(args) end end - def autocompleter_append(args) - capture do - concat(autocompleter_dropdown) - concat(args[:append]) - end - end - def autocompleter_has_id_indicator link_icon(:check, title: :autocompleter_has_id.l, class: "ml-3 px-2 text-success has-id-indicator", diff --git a/app/javascript/controllers/autocompleter_controller.js b/app/javascript/controllers/autocompleter_controller.js index 8402522114..669fb8e468 100644 --- a/app/javascript/controllers/autocompleter_controller.js +++ b/app/javascript/controllers/autocompleter_controller.js @@ -149,7 +149,7 @@ export default class extends Controller { // The select target is not the element, but a element is its target. static targets = ["input", "select", "pulldown", "list", "hidden", "wrap", - "createBtn", "hasIdIndicator", "keepBtn", "mapWrap"] + "createBtn", "hasIdIndicator", "keepBtn", "mapWrap", "collapseFields"] static outlets = ["map"] initialize() { @@ -174,7 +174,7 @@ export default class extends Controller { } connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "autocompleter-connected"; // Figure out a few browser-dependent dimensions. this.getScrollBarWidth; @@ -1008,12 +1008,14 @@ export default class extends Controller { if (hidden_id && hidden_id !== NaN && hidden_id != 0) { this.wrapTarget.classList.add('has-id'); this.wrapTarget.classList.remove('offer-create'); + this.cssUncollapseFields() } else { this.wrapTarget.classList.remove('has-id'); if (this.inputTarget.value && !this.wrapTarget.classList.contains('create')) { this.wrapTarget.classList.add('offer-create'); } + this.cssCollapseFields() } // On forms where a map may not be relevant, we also show/hide the map. // Only show if we're in "create" mode. @@ -1026,6 +1028,18 @@ export default class extends Controller { } } + cssCollapseFields() { + if (!this.hasCollapseFieldsTarget) return; + + this.collapseFieldsTarget.classList.add('d-none'); + } + + cssUncollapseFields() { + if (!this.hasCollapseFieldsTarget) return; + + this.collapseFieldsTarget.classList.remove('d-none'); + } + storeCurrentHiddenData() { this.verbose("autocompleter:storeCurrentHiddenData()"); this.stored_id = parseInt(this.hiddenTarget.value); // value is a string diff --git a/app/views/controllers/observations/namings/_fields.erb b/app/views/controllers/observations/namings/_fields.erb index ebd3233b17..599c3e2b9f 100644 --- a/app/views/controllers/observations/namings/_fields.erb +++ b/app/views/controllers/observations/namings/_fields.erb @@ -20,25 +20,18 @@ menu = unless @vote&.value&.nonzero? end confidences = options_for_select(menu, @vote&.value) select_opts = { include_blank: create } -feedback = if @given_name.present? - tag.div do - render(partial: "shared/form_name_feedback", - locals: feedback_locals) - end - else - "" - end %> -<%= -[ - feedback, - fields_for(:naming) do |f_n| +<% if @given_name.present? %> + <%= tag.div do + render(partial: "shared/form_name_feedback", locals: feedback_locals) + end %> +<% end %> + +<%= fields_for(:naming) do |f_n| %> + <% vote_reasons = tag.div(data: { autocompleter_target: "collapseFields" }, + class: "d-none") do [ - autocompleter_field( - form: f_n, field: :name, type: :name, label: "#{:WHAT.t}:", - value: @given_name, autofocus: focus_on_name, help: name_help - ), f_n.fields_for(:vote) do |f_v| select_with_label(form: f_v, field: :value, options: confidences, select_opts: select_opts, @@ -49,7 +42,12 @@ feedback = if @given_name.present? naming_form_reasons_fields(f_r, @reasons) end ].safe_join - end, - hidden_field_tag(:context, context) -].compact.safe_join -%> + end %> + <%= autocompleter_field( + form: f_n, field: :name, type: :name, label: "#{:WHAT.t}:", + value: @given_name, autofocus: focus_on_name, help: name_help, + append: vote_reasons + ) %> +<% end %> + +<%= hidden_field_tag(:context, context) %> From 40db1871d597150f7ea15ddd7aeb1fb8bceaba53 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Fri, 16 Aug 2024 17:59:50 -0700 Subject: [PATCH 25/30] Eliminate checkbox-collapse, use native bootstrap collapse --- .../checkbox-collapse_controller.js | 41 ------------------- .../controllers/form-exif_controller.js | 13 ++++-- app/javascript/controllers/map_controller.js | 2 +- .../controllers/observations/_form.html.erb | 1 - .../observations/form/_details.html.erb | 12 +++--- .../form/_specimen_section.html.erb | 14 +++---- .../controllers/shared/_form_location_map.erb | 2 +- 7 files changed, 24 insertions(+), 61 deletions(-) delete mode 100644 app/javascript/controllers/checkbox-collapse_controller.js diff --git a/app/javascript/controllers/checkbox-collapse_controller.js b/app/javascript/controllers/checkbox-collapse_controller.js deleted file mode 100644 index afd0250912..0000000000 --- a/app/javascript/controllers/checkbox-collapse_controller.js +++ /dev/null @@ -1,41 +0,0 @@ -import { Controller } from "@hotwired/stimulus" - -// Connects to data-controller="checkbox-collapse" -export default class extends Controller { - static targets = ["checkbox", "fields"] - - connect() { - this.element.dataset.stimulus = "checkbox-collapse-connected"; - } - - // Only show if user prefers - hideShowFields() { - if (this.checkboxTarget.checked) { - $(this.fieldsTarget).show() - } else { - $(this.fieldsTarget).hide() - } - } - - // Programmatically show or hide fields. To keep the checkbox in sync, - // it also checks or unchecks the checkbox, in case called directly. - hideFields() { - $(this.fieldsTarget).hide() - this.uncheckCheckbox() - } - - showFields() { - this.fieldsTarget.classList.remove("hidden") - $(this.fieldsTarget).show() - this.checkCheckbox() - } - - // This checks "specimen" anyway if people add a CN or HR. - checkCheckbox() { - this.checkboxTarget.setAttribute("checked", true) - } - - uncheckCheckbox() { - this.checkboxTarget.removeAttribute("checked") - } -} diff --git a/app/javascript/controllers/form-exif_controller.js b/app/javascript/controllers/form-exif_controller.js index 6f4e4cff5f..d966c80f9d 100644 --- a/app/javascript/controllers/form-exif_controller.js +++ b/app/javascript/controllers/form-exif_controller.js @@ -13,8 +13,8 @@ const internalConfig = { // (formerly "observation_images" section of the form) // Connects to data-controller="form-exif" export default class extends Controller { - static targets = ["carousel", "item", "useExifBtn"] - static outlets = ["autocompleter", "map", "checkbox-collapse"] + static targets = ["carousel", "item", "useExifBtn", "collapseFields"] + static outlets = ["autocompleter", "map"] connect() { this.element.dataset.stimulus = "form-exif-connected"; @@ -193,8 +193,13 @@ export default class extends Controller { // disables the button, even when called programmatically this.selectExifButton(element); // show the geolocation fields - if (this.hasCheckboxCollapseOutlet) { - this.checkboxCollapseOutlet.showFields(); + this.showFields(); + } + + // show the geolocation fields + showFields() { + if (this.hasCollapseFieldsTarget) { + $(this.collapseFieldsTarget).collapse('show'); } } diff --git a/app/javascript/controllers/map_controller.js b/app/javascript/controllers/map_controller.js index 2a115b765b..207085ba67 100644 --- a/app/javascript/controllers/map_controller.js +++ b/app/javascript/controllers/map_controller.js @@ -15,7 +15,7 @@ export default class extends GeocodeController { "autocompleter"] connect() { - this.element.dataset.stimulus = "connected" + this.element.dataset.stimulus = "map-connected" this.map_type = this.mapDivTarget.dataset.mapType this.editable = (this.mapDivTarget.dataset.editable === "true") this.opened = this.element.dataset.mapOpen === "true" diff --git a/app/views/controllers/observations/_form.html.erb b/app/views/controllers/observations/_form.html.erb index 02220909e7..7291e9dc23 100644 --- a/app/views/controllers/observations/_form.html.erb +++ b/app/views/controllers/observations/_form.html.erb @@ -37,7 +37,6 @@ form_element_data = { map_open: false, form_exif_autocompleter_outlet: "#observation_location_autocompleter", form_exif_map_outlet: "#observation_form", - form_exif_checkbox_collapse_outlet: "#observation_details", action: "map:reenableBtns@window->form-exif#reenableButtons", upload_max_size: max_size, localization: image_upload_localization, diff --git a/app/views/controllers/observations/form/_details.html.erb b/app/views/controllers/observations/form/_details.html.erb index 6bafe82150..eaac83ae5d 100644 --- a/app/views/controllers/observations/form/_details.html.erb +++ b/app/views/controllers/observations/form/_details.html.erb @@ -10,8 +10,7 @@ t_s = { } %> -<%= tag.div(class: "panel-body border-top", id: "observation_details", - data: { controller: "checkbox-collapse" }) do %> +<%= tag.div(class: "panel-body border-top", id: "observation_details") do %> <%= tag.div(class: "row mt-3") do %> <%= tag.div(class: "col-xs-12 col-md-6") do %> @@ -73,13 +72,14 @@ t_s = { form: f, field: :has_geolocation, # field is ignored label: "#{:GEOLOCATION.l}:", help: :form_observations_lat_long_help.t, - data: { checkbox_collapse_target: "checkbox", - action: "change->checkbox-collapse#hideShowFields" } + data: { toggle: "collapse", target: "#observation_geolocation" }, + aria: { controls: "observation_geolocation", + expanded: @observation.lat } ) %> <%= tag.div(id: "observation_geolocation", - style: ("display: none;" unless @observation.lat), - data: { checkbox_collapse_target: "fields" }) do %> + class: class_names("collapse", ("in" if @observation.lat)), + data: { form_exif_target: "collapseFields" }) do %> <%= tag.p(:form_observations_click_point.l) %> diff --git a/app/views/controllers/observations/form/_specimen_section.html.erb b/app/views/controllers/observations/form/_specimen_section.html.erb index 362fcd9ad8..ae96a32c6d 100644 --- a/app/views/controllers/observations/form/_specimen_section.html.erb +++ b/app/views/controllers/observations/form/_specimen_section.html.erb @@ -3,16 +3,15 @@ <%# Specimen section of create_observation form, for collection_number and herbarium_record. Fields hidden unless box checked. %> -<%= tag.div(id: "observation_specimen_section", - data: { controller: "checkbox-collapse" }) do %> +<%= tag.div(id: "observation_specimen_section") do %> <%= tag.div(class: "mt-3") do %> <%= check_box_with_label( form: f, field: :specimen, label: :form_observations_specimen_available.t, help: :form_observations_specimen_available_help.t, - data: { checkbox_collapse_target: "checkbox", - action: "change->checkbox-collapse#hideShowFields" } + data: { toggle: "collapse", target: "#specimen_fields" }, + aria: { controls: "specimen_fields", expanded: @observation.specimen } ) %> <% if action == :update %> @@ -25,9 +24,10 @@ herbarium_record. Fields hidden unless box checked. %> <% if action == :create %> - <%= tag.div(id: "specimen_fields", - style: ("display: none;" unless @observation.specimen), - data: { checkbox_collapse_target: "fields" }) do %> + <%= tag.div( + id: "specimen_fields", + class: class_names("collapse", ("in" if @observation.specimen)) + ) do %> <%= render(partial: "observations/form/specimen/collection_number") %> <%= render(partial: "observations/form/specimen/herbarium_record") %> <% end %> diff --git a/app/views/controllers/shared/_form_location_map.erb b/app/views/controllers/shared/_form_location_map.erb index 44addb8671..1831402983 100644 --- a/app/views/controllers/shared/_form_location_map.erb +++ b/app/views/controllers/shared/_form_location_map.erb @@ -23,7 +23,7 @@ on an ancestor element that also contains the inputs ].safe_join, name: "map_toggle", class: "map-toggle", data: { map_target: "toggleMapBtn", - action: "map#toggleMap checkbox-collapse#showFields", + action: "map#toggleMap form-exif#showFields", toggle: "collapse", target: "##{id}" }, aria: { expanded: "false", controls: id } ) %> From dadf76b2e670f25c4735baf4e4cb58c72be2f3f6 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Fri, 16 Aug 2024 20:45:06 -0700 Subject: [PATCH 26/30] Update autocompleter collapseFields to use bootstrap collapse --- .../controllers/autocompleter_controller.js | 11 +++++++---- .../controllers/observations/namings/_fields.erb | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/javascript/controllers/autocompleter_controller.js b/app/javascript/controllers/autocompleter_controller.js index 669fb8e468..4dd0b242b8 100644 --- a/app/javascript/controllers/autocompleter_controller.js +++ b/app/javascript/controllers/autocompleter_controller.js @@ -479,6 +479,11 @@ export default class extends Controller { const old_val = this.old_value; const new_val = this.inputTarget.value; // this.debug("ourChange(" + this.inputTarget.value + ")"); + if (new_val.length > 0) { + this.cssUncollapseFields(); + } else { + this.cssCollapseFields(); + } if (new_val != old_val) { this.old_value = new_val; if (do_refresh) { @@ -1008,14 +1013,12 @@ export default class extends Controller { if (hidden_id && hidden_id !== NaN && hidden_id != 0) { this.wrapTarget.classList.add('has-id'); this.wrapTarget.classList.remove('offer-create'); - this.cssUncollapseFields() } else { this.wrapTarget.classList.remove('has-id'); if (this.inputTarget.value && !this.wrapTarget.classList.contains('create')) { this.wrapTarget.classList.add('offer-create'); } - this.cssCollapseFields() } // On forms where a map may not be relevant, we also show/hide the map. // Only show if we're in "create" mode. @@ -1031,13 +1034,13 @@ export default class extends Controller { cssCollapseFields() { if (!this.hasCollapseFieldsTarget) return; - this.collapseFieldsTarget.classList.add('d-none'); + $(this.collapseFieldsTarget).collapse('hide'); } cssUncollapseFields() { if (!this.hasCollapseFieldsTarget) return; - this.collapseFieldsTarget.classList.remove('d-none'); + $(this.collapseFieldsTarget).collapse('show'); } storeCurrentHiddenData() { diff --git a/app/views/controllers/observations/namings/_fields.erb b/app/views/controllers/observations/namings/_fields.erb index 599c3e2b9f..bc1b156e10 100644 --- a/app/views/controllers/observations/namings/_fields.erb +++ b/app/views/controllers/observations/namings/_fields.erb @@ -30,7 +30,7 @@ select_opts = { include_blank: create } <%= fields_for(:naming) do |f_n| %> <% vote_reasons = tag.div(data: { autocompleter_target: "collapseFields" }, - class: "d-none") do + class: ("collapse" if context == "blank")) do [ f_n.fields_for(:vote) do |f_v| select_with_label(form: f_v, field: :value, From 7f52379695892b9f73ebf63ad1a428a6b2b13fef Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Sat, 17 Aug 2024 01:26:27 -0700 Subject: [PATCH 27/30] Panel helper changes Images + Details collapsible Fix carets display refactor formatted content --- app/helpers/panel_helper.rb | 25 ++++++++++--------- .../controllers/observations/_form.html.erb | 22 +++++++--------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/app/helpers/panel_helper.rb b/app/helpers/panel_helper.rb index d487936f4e..5f265b4bc2 100644 --- a/app/helpers/panel_helper.rb +++ b/app/helpers/panel_helper.rb @@ -18,8 +18,6 @@ def panel_block(**args, &block) concat(heading) if args[:panel_bodies].present? concat(panel_bodies(args)) - elsif args[:formatted_content].present? - concat(content) elsif args[:collapse].present? concat(panel_collapse_body(args, content)) else @@ -59,10 +57,12 @@ def panel_heading_elements(args) # The whole heading is a link that toggles the panel collapse. # NOTE: args[:open] should be a boolean def panel_heading_collapse_elements(args) + collapsed = args[:open] ? "" : "collapsed" + tag.h4(class: "panel-title") do link_to( "##{args[:collapse]}", - class: "panel-collapse-trigger", + class: class_names("panel-collapse-trigger", collapsed), role: "button", data: { toggle: "collapse" }, aria: { expanded: args[:open], controls: args[:collapse] } ) do @@ -78,15 +78,6 @@ def panel_collapse_icons link_icon(:chevron_up, title: :CLOSE.l)].safe_join end - def panel_body(args, content) - return "" if content.blank? - - tag.div(class: class_names("panel-body", args[:inner_class]), - id: args[:inner_id]) do - concat(content) - end - end - # Some panels need multiple panel bodies. def panel_bodies(args) args[:panel_bodies].map do |body| @@ -103,6 +94,16 @@ def panel_collapse_body(args, content) end end + def panel_body(args, content) + return "" if content.blank? + return content if args[:formatted_content] + + tag.div(class: class_names("panel-body", args[:inner_class]), + id: args[:inner_id]) do + concat(content) + end + end + def panel_footer(args) if args[:footer] tag.div(class: "panel-footer") do diff --git a/app/views/controllers/observations/_form.html.erb b/app/views/controllers/observations/_form.html.erb index 7291e9dc23..207b1e22a2 100644 --- a/app/views/controllers/observations/_form.html.erb +++ b/app/views/controllers/observations/_form.html.erb @@ -12,8 +12,8 @@ naming_locals = { unfocused: true, name_help: :form_naming_name_help_leave_blank.t } -show_notes = @observation.notes.present? notes_fields = @observation.form_notes_parts(@user) +open_notes = notes_fields.length > 1 || !create # @observation.notes.present? show_projects = @projects.any? || @error_checked_projects.any? || @suspect_checked_projects.any? show_lists = @lists.any? @@ -63,7 +63,8 @@ form_element_data = { <%= panel_block( heading: "#{:IMAGES.l} + #{:show_observation_details.l}", - id: "observation_images_details", formatted_content: true + id: "observation_images_details", formatted_content: true, + collapse: "observation_images_details_inner", open: true ) do concat(render(partial: "observations/form/images", locals: { f: })) concat(render(partial: "observations/form/details", @@ -72,10 +73,9 @@ form_element_data = { end %> <%= panel_block( - id: "observation_identification", heading: "#{:IDENTIFICATION.l} + #{:SPECIMEN.l}", - collapse: "observation_specimen_inner", - open: true # @given_name.present? + id: "observation_naming_specimen", # @given_name.present? + collapse: "observation_naming_specimen_inner", open: true ) do tag.div(class: "row mt-3") do concat(tag.div(class: "col-xs-12 col-md-6") do @@ -91,10 +91,8 @@ form_element_data = { <%= submit_button(form: f, button: button_name, center: true) %> <%= panel_block( - heading: :NOTES.l, - id: "observation_notes", - collapse: "observation_notes_inner", - open: notes_fields.length > 1 + heading: :NOTES.l, id: "observation_notes", + collapse: "observation_notes_inner", open: open_notes ) do render(partial: "shared/notes_fields", locals: { form: f, fields: notes_fields }) @@ -102,8 +100,7 @@ form_element_data = { <% if show_projects %> <%= panel_block( - heading: :PROJECTS.l, - id: "observation_projects", + heading: :PROJECTS.l, id: "observation_projects", collapse: "observation_projects_inner", open: @project_checks.any? ) do @@ -113,8 +110,7 @@ form_element_data = { <% if show_lists %> <%= panel_block( - heading: :SPECIES_LISTS.l, - id: "observation_lists", + heading: :SPECIES_LISTS.l, id: "observation_lists", collapse: "observation_lists_inner", open: @list_checks.any? ) do From fdcaa4d6e23739c8bb188c709fdf3895a21c5d92 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Sat, 17 Aug 2024 01:36:59 -0700 Subject: [PATCH 28/30] conditions for open/closed --- app/views/controllers/observations/_form.html.erb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/controllers/observations/_form.html.erb b/app/views/controllers/observations/_form.html.erb index 207b1e22a2..25be05f0d8 100644 --- a/app/views/controllers/observations/_form.html.erb +++ b/app/views/controllers/observations/_form.html.erb @@ -13,7 +13,7 @@ naming_locals = { name_help: :form_naming_name_help_leave_blank.t } notes_fields = @observation.form_notes_parts(@user) -open_notes = notes_fields.length > 1 || !create # @observation.notes.present? +notes_open = (create && notes_fields.length > 1) || @observation.notes.present? show_projects = @projects.any? || @error_checked_projects.any? || @suspect_checked_projects.any? show_lists = @lists.any? @@ -75,7 +75,7 @@ form_element_data = { <%= panel_block( heading: "#{:IDENTIFICATION.l} + #{:SPECIMEN.l}", id: "observation_naming_specimen", # @given_name.present? - collapse: "observation_naming_specimen_inner", open: true + collapse: "observation_naming_specimen_inner", open: create ) do tag.div(class: "row mt-3") do concat(tag.div(class: "col-xs-12 col-md-6") do @@ -92,7 +92,7 @@ form_element_data = { <%= panel_block( heading: :NOTES.l, id: "observation_notes", - collapse: "observation_notes_inner", open: open_notes + collapse: "observation_notes_inner", open: notes_open ) do render(partial: "shared/notes_fields", locals: { form: f, fields: notes_fields }) From b112cc3563389e492672433099d07020b1541e70 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Sat, 17 Aug 2024 13:09:43 -0700 Subject: [PATCH 29/30] identify stimulus controllers on connect --- app/javascript/controllers/advanced-search_controller.js | 2 +- app/javascript/controllers/banner_controller.js | 2 +- app/javascript/controllers/donate_controller.js | 2 +- app/javascript/controllers/field-slip-job_controller.js | 2 +- app/javascript/controllers/file-input_controller.js | 2 +- app/javascript/controllers/form-images_controller.js | 2 +- app/javascript/controllers/geocode_controller.js | 2 +- app/javascript/controllers/lazyload_controller.js | 2 +- app/javascript/controllers/lightgallery_controller.js | 2 +- app/javascript/controllers/links_controller.js | 2 +- app/javascript/controllers/matrix-table_controller.js | 2 +- app/javascript/controllers/modal-toggle_controller.js | 3 ++- app/javascript/controllers/modal_controller.js | 2 +- app/javascript/controllers/name-list_controller.js | 2 +- app/javascript/controllers/name-panels_controller.js | 2 +- app/javascript/controllers/naming-reason_controller.js | 5 ++--- app/javascript/controllers/naming-vote_controller.js | 4 +++- app/javascript/controllers/nav-active_controller.js | 2 +- app/javascript/controllers/nav_controller.js | 2 +- app/javascript/controllers/reviewed-toggle_controller.js | 2 +- app/javascript/controllers/section-update_controller.js | 2 +- app/javascript/controllers/suggestions_controller.js | 2 +- app/javascript/controllers/thumbnail-map_controller.js | 2 +- app/javascript/controllers/translation_controller.js | 2 +- app/javascript/controllers/year-input_controller.js | 2 +- 25 files changed, 29 insertions(+), 27 deletions(-) diff --git a/app/javascript/controllers/advanced-search_controller.js b/app/javascript/controllers/advanced-search_controller.js index 74354491ff..88b73f7bbd 100644 --- a/app/javascript/controllers/advanced-search_controller.js +++ b/app/javascript/controllers/advanced-search_controller.js @@ -5,7 +5,7 @@ export default class extends Controller { static targets = ["searchModel", "filter"] connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "advanced-search-connected"; this.disableUnusedFilters(); } diff --git a/app/javascript/controllers/banner_controller.js b/app/javascript/controllers/banner_controller.js index 4c4dfe27ea..7ac360d090 100644 --- a/app/javascript/controllers/banner_controller.js +++ b/app/javascript/controllers/banner_controller.js @@ -3,7 +3,7 @@ import { Controller } from "@hotwired/stimulus" // Connects to data-controller="banner" export default class extends Controller { connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "banner-connected"; } setCookie({ params: { time } }) { diff --git a/app/javascript/controllers/donate_controller.js b/app/javascript/controllers/donate_controller.js index a82d330456..992de05b2e 100644 --- a/app/javascript/controllers/donate_controller.js +++ b/app/javascript/controllers/donate_controller.js @@ -5,7 +5,7 @@ export default class extends Controller { static targets = ['otherCheck', 'otherAmount'] connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "donate-connected"; } checkOther() { diff --git a/app/javascript/controllers/field-slip-job_controller.js b/app/javascript/controllers/field-slip-job_controller.js index f65fbac72b..f111256fd2 100644 --- a/app/javascript/controllers/field-slip-job_controller.js +++ b/app/javascript/controllers/field-slip-job_controller.js @@ -16,7 +16,7 @@ export default class extends Controller { connect() { // Just a "sanity check" convention, so you can tell "is this thing on?" - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "field-slip-job-connected"; this.status_id = this.element.dataset.status this.start_timer_sending_requests() diff --git a/app/javascript/controllers/file-input_controller.js b/app/javascript/controllers/file-input_controller.js index 4ecdfd356f..7a3c3d3b02 100644 --- a/app/javascript/controllers/file-input_controller.js +++ b/app/javascript/controllers/file-input_controller.js @@ -5,7 +5,7 @@ export default class extends Controller { static targets = ['input', 'name'] connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "file-input-connected"; this.max_size = Number(this.inputTarget.dataset.maxUploadSize); this.error_msg = this.inputTarget.dataset.maxUploadMsg; this.old_callback = this.inputTarget.onchange; diff --git a/app/javascript/controllers/form-images_controller.js b/app/javascript/controllers/form-images_controller.js index b08c398756..83a520ece1 100644 --- a/app/javascript/controllers/form-images_controller.js +++ b/app/javascript/controllers/form-images_controller.js @@ -54,7 +54,7 @@ export default class extends Controller { } connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "form-images-connected"; Object.assign(this, internalConfig); Object.assign(this.localized_text, diff --git a/app/javascript/controllers/geocode_controller.js b/app/javascript/controllers/geocode_controller.js index 1284151180..892b06ee9c 100644 --- a/app/javascript/controllers/geocode_controller.js +++ b/app/javascript/controllers/geocode_controller.js @@ -13,7 +13,7 @@ export default class extends Controller { static outlets = ["autocompleter"] connect() { - this.element.dataset.stimulus = "connected" + this.element.dataset.stimulus = "geocode-connected" // These private vars are for keeping track of user inputs to a form // that should update the form after a timeout. diff --git a/app/javascript/controllers/lazyload_controller.js b/app/javascript/controllers/lazyload_controller.js index b1904eb2fa..bc417a64f5 100644 --- a/app/javascript/controllers/lazyload_controller.js +++ b/app/javascript/controllers/lazyload_controller.js @@ -3,7 +3,7 @@ import { Controller } from "@hotwired/stimulus" // Connects to data-controller="lazyload" export default class extends Controller { connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "lazyload-connected"; if (window.lazyLoadInstance != undefined) window.lazyLoadInstance.update(); diff --git a/app/javascript/controllers/lightgallery_controller.js b/app/javascript/controllers/lightgallery_controller.js index 4e4fda18ce..ca522def36 100644 --- a/app/javascript/controllers/lightgallery_controller.js +++ b/app/javascript/controllers/lightgallery_controller.js @@ -5,7 +5,7 @@ import lgZoom from 'lightgallery/plugins/zoom' // Connects to data-controller="lightgallery", currently "#content" export default class extends Controller { connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "lightgallery-connected"; lightGallery(this.element, { selector: '.theater-btn', diff --git a/app/javascript/controllers/links_controller.js b/app/javascript/controllers/links_controller.js index 4a775a7eb3..c57e95a9b8 100644 --- a/app/javascript/controllers/links_controller.js +++ b/app/javascript/controllers/links_controller.js @@ -3,7 +3,7 @@ import { Controller } from "@hotwired/stimulus" // Connects to data-controller="links" export default class extends Controller { connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "links-connected"; } disable(e) { diff --git a/app/javascript/controllers/matrix-table_controller.js b/app/javascript/controllers/matrix-table_controller.js index 44e3090305..3ab0fac1ee 100644 --- a/app/javascript/controllers/matrix-table_controller.js +++ b/app/javascript/controllers/matrix-table_controller.js @@ -3,7 +3,7 @@ import { Controller } from "@hotwired/stimulus" // Connects to data-controller="matrix-table" export default class extends Controller { connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "matrix-table-connected"; this.matrixBoxes = document.querySelectorAll('.matrix-box') this.boxes = document.querySelectorAll('.matrix-box .panel-sizing') diff --git a/app/javascript/controllers/modal-toggle_controller.js b/app/javascript/controllers/modal-toggle_controller.js index 9290da4a0c..a3ed06b854 100644 --- a/app/javascript/controllers/modal-toggle_controller.js +++ b/app/javascript/controllers/modal-toggle_controller.js @@ -7,10 +7,11 @@ import { get } from "@rails/request.js" // For example, you can start entering a collection number, close the modal, // open a herbarium record form, close it and go back to the collection number // and find the form form as you left it, or vice versa, until you submit. +// Connects to data-controller="modal-toggle" export default class extends Controller { connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "modal-toggle-connected"; this.modalSelector = this.element.dataset.modal this.destination = this.element.getAttribute("href") } diff --git a/app/javascript/controllers/modal_controller.js b/app/javascript/controllers/modal_controller.js index 0740c84292..ea0738fa44 100644 --- a/app/javascript/controllers/modal_controller.js +++ b/app/javascript/controllers/modal_controller.js @@ -7,7 +7,7 @@ export default class extends Controller { connect() { // console.log("Hello Modal " + this.element.id); - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "modal-connected"; } // Modal is only removed in the event that the page section updates. diff --git a/app/javascript/controllers/name-list_controller.js b/app/javascript/controllers/name-list_controller.js index 96738b2c18..609d9a747b 100644 --- a/app/javascript/controllers/name-list_controller.js +++ b/app/javascript/controllers/name-list_controller.js @@ -43,7 +43,7 @@ export default class extends Controller { } connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "name-list-connected"; // These are the div elements for each column. this.DIVS = { diff --git a/app/javascript/controllers/name-panels_controller.js b/app/javascript/controllers/name-panels_controller.js index e6863dfe3b..dfe89a1dbd 100644 --- a/app/javascript/controllers/name-panels_controller.js +++ b/app/javascript/controllers/name-panels_controller.js @@ -7,7 +7,7 @@ export default class extends Controller { static targets = ['classification', 'lifeform'] connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "name-panels-connected"; this.equalizePanelHeights() } diff --git a/app/javascript/controllers/naming-reason_controller.js b/app/javascript/controllers/naming-reason_controller.js index ae878ec301..7431894fba 100644 --- a/app/javascript/controllers/naming-reason_controller.js +++ b/app/javascript/controllers/naming-reason_controller.js @@ -1,8 +1,6 @@ import { Controller } from "@hotwired/stimulus" import { delegate, abnegate } from 'jquery-events-to-dom-events' -// Connects to data-controller="naming-reason" - // https://github.com/leastbad/jquery-events-to-dom-events // We use a Stimulus action that listens to `$shown.bs.collapse` on the div // (note the `$`). This depends on using `delegate` from the imported library @@ -11,11 +9,12 @@ import { delegate, abnegate } from 'jquery-events-to-dom-events' // // If moving to BS 5, can remove. +// Connects to data-controller="naming-reason" export default class extends Controller { static targets = ['collapse', 'input'] connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "naming-reason-connected"; this.delegate = delegate('shown.bs.collapse') } diff --git a/app/javascript/controllers/naming-vote_controller.js b/app/javascript/controllers/naming-vote_controller.js index aeb3123c50..ce4ae2e74f 100644 --- a/app/javascript/controllers/naming-vote_controller.js +++ b/app/javascript/controllers/naming-vote_controller.js @@ -2,6 +2,8 @@ import { Controller } from "@hotwired/stimulus" // Controller deals with naming vote select bindings ** per select. ** // the controller is on the
+ +// Connects to data-controller="naming-vote" export default class extends Controller { static targets = ["select", "submit"] @@ -11,7 +13,7 @@ export default class extends Controller { connect() { // console.log("Hello Modal"); - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "naming-vote-connected"; // The localized text is for the modal progress caption. Object.assign(this.localized_text, JSON.parse(this.element.dataset.localization)); diff --git a/app/javascript/controllers/nav-active_controller.js b/app/javascript/controllers/nav-active_controller.js index 4ff0ebda5f..26780431e2 100644 --- a/app/javascript/controllers/nav-active_controller.js +++ b/app/javascript/controllers/nav-active_controller.js @@ -6,7 +6,7 @@ export default class extends Controller { static targets = ['link'] connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "nav-active-connected"; this.pickActive(); } diff --git a/app/javascript/controllers/nav_controller.js b/app/javascript/controllers/nav_controller.js index 61766e685a..18dd41718d 100644 --- a/app/javascript/controllers/nav_controller.js +++ b/app/javascript/controllers/nav_controller.js @@ -5,7 +5,7 @@ export default class extends Controller { static targets = ['hamburger', 'search', 'container', 'offcanvas', 'topNav'] connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "nav-connected"; } // HAMBURGER HELPER action to toggle offcanvas left nav diff --git a/app/javascript/controllers/reviewed-toggle_controller.js b/app/javascript/controllers/reviewed-toggle_controller.js index 2805c4cdf3..b0e3eb4afc 100644 --- a/app/javascript/controllers/reviewed-toggle_controller.js +++ b/app/javascript/controllers/reviewed-toggle_controller.js @@ -6,7 +6,7 @@ export default class extends Controller { static targets = ['toggle'] connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "reviewed-toggle-connected"; } // https://stackoverflow.com/questions/68624668/how-can-i-submit-a-form-on-input-change-with-turbo-streams diff --git a/app/javascript/controllers/section-update_controller.js b/app/javascript/controllers/section-update_controller.js index 38519e5cf7..f8a5f4b80b 100644 --- a/app/javascript/controllers/section-update_controller.js +++ b/app/javascript/controllers/section-update_controller.js @@ -6,7 +6,7 @@ export default class extends Controller { // this is a handler for page elements that get updated // on successful form submit, so it "cleans up" connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "section-update-connected"; // Note: this is simpler than adding an action on every frame. hides modal this.element.addEventListener("turbo:frame-render", this.updated()); diff --git a/app/javascript/controllers/suggestions_controller.js b/app/javascript/controllers/suggestions_controller.js index f68a978ca1..6838e3dba2 100644 --- a/app/javascript/controllers/suggestions_controller.js +++ b/app/javascript/controllers/suggestions_controller.js @@ -10,7 +10,7 @@ export default class extends Controller { } connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "suggestions-connected"; this.progressModal = document.getElementById("mo_ajax_progress") this.progressCaption = document.getElementById("mo_ajax_progress_caption") diff --git a/app/javascript/controllers/thumbnail-map_controller.js b/app/javascript/controllers/thumbnail-map_controller.js index 508f5d6dc7..b9d7c0dc57 100644 --- a/app/javascript/controllers/thumbnail-map_controller.js +++ b/app/javascript/controllers/thumbnail-map_controller.js @@ -5,7 +5,7 @@ export default class extends Controller { static targets = ["mapContainer", "map", "globe"] connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "thumbnail-map-connected"; this.map_url = this.element.dataset.mapUrl this.coords = JSON.parse(this.element.dataset.coordinates) diff --git a/app/javascript/controllers/translation_controller.js b/app/javascript/controllers/translation_controller.js index 4c646fcee4..9615c72d60 100644 --- a/app/javascript/controllers/translation_controller.js +++ b/app/javascript/controllers/translation_controller.js @@ -8,7 +8,7 @@ export default class extends Controller { ] connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "translate-connected"; this.LOCALE = this.element.dataset.locale; this.CONFIRM_STRING = this.element.dataset.confirmString; diff --git a/app/javascript/controllers/year-input_controller.js b/app/javascript/controllers/year-input_controller.js index 4ed344bce5..b320ea2258 100644 --- a/app/javascript/controllers/year-input_controller.js +++ b/app/javascript/controllers/year-input_controller.js @@ -3,7 +3,7 @@ import { Controller } from "@hotwired/stimulus" // Connects to data-controller="year-input" export default class extends Controller { connect() { - this.element.dataset.stimulus = "connected"; + this.element.dataset.stimulus = "year-input-connected"; this.id = this.element.getAttribute("id"); // console.log(this.id) From 1148614eff14253aadf670eb21a003c0305232b9 Mon Sep 17 00:00:00 2001 From: andrew nimmo Date: Sat, 17 Aug 2024 13:38:23 -0700 Subject: [PATCH 30/30] Fix application of autocompleter outlet ID --- app/helpers/autocompleter_helper.rb | 21 +++++++++++-------- app/helpers/forms_helper.rb | 2 +- .../observations/form/_details.html.erb | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/app/helpers/autocompleter_helper.rb b/app/helpers/autocompleter_helper.rb index 98c5e5e205..309c480701 100644 --- a/app/helpers/autocompleter_helper.rb +++ b/app/helpers/autocompleter_helper.rb @@ -21,13 +21,14 @@ def autocompleter_field(**args) data: { autocompleter_target: "input" } }.deep_merge(args.except(*autocompleter_outer_args)) ac_args[:class] = class_names("dropdown", args[:class]) - # doing our own wrap here, because dropdown is position-absolute - ac_args[:wrap_data] = { autocompleter_target: "wrap"} + # inner form-group wrap, because dropdown is position-absolute + ac_args[:wrap_data] = { autocompleter_target: "wrap" } ac_args[:label_after] = autocompleter_label_after(args) ac_args[:label_end] = autocompleter_label_end(args) ac_args[:append] = autocompleter_dropdown - tag.div(data: autocompleter_wrap_data(args)) do + tag.div(id: args[:controller_id], + data: autocompleter_controller_data(args)) do if args[:textarea] == true concat(text_area_with_label(**ac_args)) else @@ -39,18 +40,20 @@ def autocompleter_field(**args) # Any arg not on this list gets sent to the text field/area. def autocompleter_outer_args - [:wrap_data, :type, :separator, :textarea, :hidden_value, :hidden_data, - :create_text, :keep_text, :edit_text, :find_text, :create, :create_path, - :map_outlet, :geocode_outlet].freeze + [:controller_data, :controller_id, :type, :separator, :textarea, + :hidden_value, :hidden_data, :create_text, :keep_text, :edit_text, + :find_text, :create, :create_path, :map_outlet, :geocode_outlet].freeze end - def autocompleter_wrap_data(args) + # This data goes on the outer div (controller element), not the input field. + def autocompleter_controller_data(args) { - controller: :autocompleter, type: args[:type], + controller: :autocompleter, + type: args[:type], separator: args[:separator], autocompleter_map_outlet: args[:map_outlet], autocompleter_geocode_outlet: args[:geocode_outlet] - }.deep_merge(args[:wrap_data] || {}) + }.deep_merge(args[:outer_data] || {}) end def autocompleter_label_after(args) diff --git a/app/helpers/forms_helper.rb b/app/helpers/forms_helper.rb index 2897affb36..a55be8171d 100644 --- a/app/helpers/forms_helper.rb +++ b/app/helpers/forms_helper.rb @@ -164,7 +164,7 @@ def text_field_with_label(**args) label_opts = field_label_opts(args) label_opts[:class] = class_names(label_opts[:class], args[:label_class]) - tag.div(class: wrap_class, data: wrap_data, id: args[:wrap_id]) do + tag.div(class: wrap_class, data: wrap_data) do concat(text_label_row(args, label_opts)) if args[:addon].present? # text addon, not interactive concat(tag.div(class: "input-group") do diff --git a/app/views/controllers/observations/form/_details.html.erb b/app/views/controllers/observations/form/_details.html.erb index eaac83ae5d..8d5733b808 100644 --- a/app/views/controllers/observations/form/_details.html.erb +++ b/app/views/controllers/observations/form/_details.html.erb @@ -45,7 +45,7 @@ t_s = { # find_text: :form_locations_find_on_map.l, # Be precise about which map controller to connect to: map_outlet: "#observation_form", - wrap_id: "observation_location_autocompleter", + controller_id: "observation_location_autocompleter", # Action ok because there's only one form-exif controller on the page, # and it should only affect this autocompleter: data: {