Module: RoomConfigurationsHelper

Defined in:
app/helpers/room_configurations_helper.rb

Instance Method Summary collapse

Instance Method Details

#display_room_configuration_banner(banner) ⇒ Object



105
106
107
108
109
# File 'app/helpers/room_configurations_helper.rb', line 105

def display_room_configuration_banner(banner)
  return if banner.blank?

  render partial: '/shared/room_configuration_banner', locals: { banner: banner }
end

#get_cable_spacing_optionsObject



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'app/helpers/room_configurations_helper.rb', line 189

def get_cable_spacing_options
  recommended_cable_spacings = HeatingElementProductLineOption.default_cable_spacings(@installation_postal_code, @sub_floor_type, @floor_type)
  cs_opts = []
  if @cable_spacing_options&.any?
    cs_opts = @cable_spacing_options
  elsif @heating_system_product_line && (@heating_system_product_line.heating_system_type_name == 'Slab Heat Cable')
    cs_opts = HeatingElementProductLineOption.shc_cable_spacing_for_select
  elsif @heating_system_product_line && @heating_system_product_line.heating_system_type_name.to_s.index('TempZone') && @heating_system_product_line.heating_system_type_name.to_s.index('Cable')
    cs_opts = HeatingElementProductLineOption.tz_cable_spacing_for_select({ sftid: @sub_floor_type_id, tz_cable_pl_url: @heating_system_product_line.slug_ltree.to_s, is_public: true })
  elsif @heating_system_product_line&.heating_system_type_name&.match(/Snow/i) && @heating_system_product_line.heating_system_type_name.match(/Cable/i)
    cs_opts = HeatingElementProductLineOption.smc_cable_spacing_for_select
  end
  cs_opts = cs_opts.map { |opts| recommended_cable_spacings.include?(opts.last) ? ["#{opts.first}".html_safe, opts.last] : opts }
  Rails.logger.debug cs_opts.inspect
  cs_opts
end

#icon_for_room(rc) ⇒ Object



101
102
103
# File 'app/helpers/room_configurations_helper.rb', line 101

def icon_for_room(rc)
  fa_icon(RoomConfiguration::ROOM_ICON_BY_STATE[rc.state] || RoomConfiguration::FALLBACK_ROOM_ICON)
end

#reusable_layouts_for_select(uploads) ⇒ Object



4
5
6
# File 'app/helpers/room_configurations_helper.rb', line 4

def reusable_layouts_for_select(uploads)
  uploads.map { |u| ["#{u.resource_type} > #{u.resource} > #{u.attachment_name}", u.id] }.sort
end

#room_configuration_command_options(rc) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'app/helpers/room_configurations_helper.rb', line 8

def room_configuration_command_options(rc)
  opts = []
  opts << fa_icon('shuffle', text: rc.human_state_name.titleize)
  if can?(:update, rc) && !rc.complete?
    opts << link_to('Edit', edit_room_configuration_path(rc))
    opts << link_to('Pick Items', pick_items_path(room_configuration_id: rc.id)) unless rc.editing_locked?
  end
  opts << link_to('Edit Name', edit_name_room_configuration_path(rc))

  if rc.draft? && rc.orders.room_not_pickable.empty?
    opts << link_to('Remove all line items', clear_room_configuration_path(rc), data: { turbo_confirm: 'This operation is not reversible, are you sure you want to remove all line items?' }) if rc.line_items.any?
  end

  opts << link_to('Edit installation plans', edit_installation_plans_room_configuration_path(rc)) if can?(:update_installation_plans, rc)

  opts << link_to('Redesign', redesign_room_configuration_path(rc)) if rc.complete?

  opts << link_to('Regenerate plans', regenerate_plans_room_configuration_path(rc)) if rc.has_plans?

  opts << link_to('Edit Relay Pole Assignments', [rc, :element_pole_assignments]) if rc.pole_assignments_possible?

  if rc.floor_type&.is_indoors?
    opts << link_to('Enter Heat Loss Information', enter_heat_loss_info_room_configuration_path(rc))
    opts << link_to('Show Heat Loss Report', show_heat_loss_room_configuration_path(rc)) if rc.last_heat_loss.present?
  end

  opts << link_to('Copy Room', copy_room_configuration_path(rc))

  opts << { class: 'divider' }

  opts << link_to(fa_icon('trash', text: 'Delete'), room_configuration_path(rc), data: { turbo_confirm: 'Are you sure you want to delete this room?', turbo_method: :delete }) if can?(:destroy, rc)

  opts << { class: 'divider' }
  opts += available_events_links(rc, {}, {})

  if rc.complete?
    if rc.installation_plan_image
      if rc.vignette? && can?(:vignette, rc)
        opts << link_to(fa_icon('eye-slash', text: 'Remove Installation Plan Vignette'), un_vignette_room_configuration_path(rc),
                        data: { turbo_confirm: 'Are you sure you want to remove this room from installation plan vignettes? It will no longer appear as an example installation plan vignette.', turbo_method: :put })
      elsif can?(:vignette, rc)
        opts << link_to(fa_icon('eye', text: 'Add Installation Plan Vignette'), vignette_room_configuration_path(rc),
                        data: { turbo_confirm: 'Are you sure you want to add this room to installation plan vignettes? It will appear as an example installation plan vignette on our website.', turbo_method: :put })
      end
    end

    ip_pdf = rc.installation_plan_pdf
    ep_pdf = rc.electrical_plan_pdf

    opts << { class: 'divider' }
    if ip_pdf&.attachment
      opts << link_to(fa_icon('file-pdf', text: 'View Installation Plan'), ip_pdf.attachment.url)
    elsif rc.has_installation_plan_image?
      opts << link_to(fa_icon('file-pdf', text: 'View Installation Plan'), room_configuration_path(rc, format: :pdf))
    end
    opts << if ep_pdf&.attachment
              link_to(fa_icon('file-pdf', text: 'View Electrical Plan'), ep_pdf.attachment.url)
            else
              link_to(fa_icon('file-pdf', text: 'View Electrical Plan'), electrical_plan_room_configuration_path(rc, format: :pdf))
            end
  end

  opts
end

#room_configuration_tab_optionsObject



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'app/helpers/room_configurations_helper.rb', line 111

def room_configuration_tab_options
  tabs = {}

  # Main tab (always present) — engineering/material alerts are rendered inline below line items
  tabs[:main] = { title: 'Line Items & Room Info', remote_href: tab_main_room_configuration_path(@room_configuration) }

  # Standard tabs
  tabs[:activities] = { remote_href: room_configuration_activities_path(@room_configuration, selected_activity: params[:selected_activity]), counter: @room_configuration.activities.open_activities.size }
  tabs[:attachments] = { counter: @room_configuration.uploads.size, remote_href: room_configuration_uploads_path(@room_configuration) }
  tabs[:tickets] = {
    remote_href: tab_tickets_room_configuration_path(@room_configuration),
    title: 'Tickets',
    counter_html: tech_counter_badge(@room_configuration.support_cases)
  }
  tabs[:revision] = { remote_href: tab_revision_room_configuration_path(@room_configuration) }
  tabs[:quotes] = {
    remote_href: room_configuration_quotes_path(@room_configuration),
    counter: @room_configuration.quotes.size
  }
  tabs[:orders] = {
    counter: @room_configuration.orders.size,
    remote_href: room_configuration_orders_path(@room_configuration)
  }

  tabs
end

#room_install_plan_image(room_configuration, size = nil) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'app/helpers/room_configurations_helper.rb', line 77

def room_install_plan_image(room_configuration, size = nil)
  return unless (f = room_configuration.installation_plan_image)
  return unless f.attachment

  if f.is_image?
    size ||= '456x304>'
    image_url = f.attachment.thumb(size, format: 'png', frame: '0').url
    if image_url
      link_to image_tag(image_url),
              f.attachment.url,
              class: 'thumbnail img-responsive',
              data: {
                type: 'image',
                fancybox: 'room-config-helper',
                src: f.attachment.url
              }
    else
      link_to fa_icon('image', title: 'No Thumbnail', class: 'fa-2x'), upload_path(f)
    end
  else
    link_to fa_icon('image', title: 'No Thumbnail', class: 'fa-2x'), upload_path(f)
  end
end

#room_layout_image(rc, size = nil) ⇒ Object



73
74
75
# File 'app/helpers/room_configurations_helper.rb', line 73

def room_layout_image(rc, size = nil)
  render Crm::RoomLayoutPreviewComponent.new(room_configuration: rc, size: size || '92x61>')
end

#with_cascade_options(html_options, flag: nil, extra_actions: []) ⇒ Object

Wire an input into the room-configuration-form Stimulus controller's
cascading-options submit. Adds (without clobbering existing actions/data)
a change->room-configuration-form#submitOptions action and an optional
flag action param naming the hidden *_changed input the controller
should set to '1' before the next side-channel form submission.

Pass extra_actions: for inputs that need additional behaviors on the
same change event (e.g. heating-system also drives the alternate/cable
visibility toggle).



147
148
149
150
151
152
153
154
# File 'app/helpers/room_configurations_helper.rb', line 147

def with_cascade_options(html_options, flag: nil, extra_actions: [])
  opts = with_data_actions(html_options, 'change->room-configuration-form#submitOptions', *Array(extra_actions))
  return opts unless flag

  data = opts[:data].dup
  data['room-configuration-form-flag-param'] = flag
  opts.merge(data: data)
end

#with_data_actions(html_options, *new_actions) ⇒ Object

Append Stimulus action descriptors to an html_options hash without
clobbering an existing data[:action] / data['action'] (callers in the
wild use either key style). Returns a new hash with a normalized,
symbol-keyed :data containing the merged :action string.



160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'app/helpers/room_configurations_helper.rb', line 160

def with_data_actions(html_options, *new_actions)
  return html_options if new_actions.empty?

  opts = html_options.dup
  data = (opts[:data] || opts['data'] || {}).dup
  opts.delete('data')

  existing_action = data.delete(:action) || data.delete('action')
  data[:action] = [existing_action, *new_actions].compact.map(&:to_s).reject(&:empty?).join(' ')

  opts[:data] = data
  opts
end

#with_tom_select(html_options, placeholder: I18n.t('helpers.tom_select.placeholder', default: 'Please Select')) ⇒ Object

Augment a select_tag html_options hash so the rendered <select> is
wrapped by the tom-select Stimulus controller and picks up Bootstrap's
form-select styling. Preserves any existing classes, data attributes,
and controllers (so it composes with with_cascade_options).



178
179
180
181
182
183
184
185
186
187
# File 'app/helpers/room_configurations_helper.rb', line 178

def with_tom_select(html_options, placeholder: I18n.t('helpers.tom_select.placeholder', default: 'Please Select'))
  opts = html_options.dup
  opts[:class] = (Array(opts[:class]) + ['form-select']).compact.uniq.join(' ')
  data = (opts[:data] || {}).dup
  existing_controller = data[:controller] || data['controller']
  data[:controller] = [existing_controller, 'tom-select'].compact.uniq.join(' ')
  data['tom-select-placeholder-value'] ||= placeholder
  opts[:data] = data
  opts
end