Module: HrLite::ApplicationHelper

Defined in:
app/helpers/hr_lite/application_helper.rb

Constant Summary collapse

[
  { label: "Home",       path: :root_path,           match: [ "/" ] },
  { label: "Attendance", path: :attendance_path,     match: [ "/attendance", "/regularization_requests" ] },
  { label: "Leaves",     path: :leave_requests_path, match: [ "/leave_requests", "/leave_balances", "/comp_off_requests" ] },
  { label: "Team",       path: :team_path,           match: [ "/team" ] },
  { label: "Calendar",   path: :calendar_path,       match: [ "/calendar", "/holidays" ] },
  # After Calendar deliberately: the phone tab bar shows the first four
  # and this screen is empty for everybody who is not an approver, so it
  # belongs in "More" rather than displacing something everybody uses.
  # Employee tier all the same — holding an approval IS the authorisation,
  # so a manager and a stand-in covering for one reach the same screen.
  { label: "Approvals",  path: :approvals_path,      match: [ "/approvals" ] },
  { label: "Expenses",   path: :expenses_path,       match: [ "/expenses" ] },
  { label: "Benefits",   path: :benefits_path,       match: [ "/benefits" ] },
  { label: "Policies",   path: :policies_path,       match: [ "/policies" ] },
  { label: "Ask HR",     path: :hr_requests_path,    match: [ "/hr_requests" ] },
  { label: "Org",        path: :org_path,            match: [ "/org" ] },
  { label: "Kudos",      path: :kudos_path,          match: [ "/kudos" ] },
  { label: "Slips",      path: :salary_slips_path,   match: [ "/salary_slips" ] },
  { label: "Career",     path: :career_path,         match: [ "/career", "/appraisals", "/profile" ] }
].freeze
ADMIN_NAV_ITEMS =
[
  { label: "Overview",        path: :admin_overview_path,        match: [ "/admin/overview" ] },
  { label: "Team attendance", path: :admin_attendances_path,     match: [ "/admin/attendances" ] },
  { label: "Approvals",       path: :admin_leave_requests_path,  match: [ "/admin/leave_requests", "/admin/leave_balances", "/admin/comp_off_requests", "/admin/regularization_requests" ] },
  { label: "Reports",         path: :admin_reports_path,         match: [ "/admin/reports" ] }
].freeze
LEADERSHIP_NAV_ITEMS =
[
  { label: "Employees", path: :admin_employees_path,        match: [ "/admin/employees" ] },
  { label: "Settings",  path: :admin_leave_types_path,      match: [ "/admin/leave_types", "/admin/office_locations", "/admin/holidays", "/admin/setting" ] },
  { label: "Audit",     path: :admin_audit_logs_path,       match: [ "/admin/audit_logs" ] }
].freeze
SUPERADMIN_NAV_ITEMS =

Money screens, plus role management: granting somebody payroll is the same act as holding it, so it sits with the pay rather than with the other governing screens.

[
  { label: "Payroll", path: :admin_payroll_runs_path, match: [ "/admin/payroll_runs", "/admin/salary_slips" ] },
  { label: "Roles",   path: :admin_roles_path,        match: [ "/admin/roles" ] },
  { label: "Rates",   path: :admin_statutory_rate_cards_path, match: [ "/admin/statutory_rate_cards" ] }
].freeze
APPROVAL_PATHS =

Where an approval row actually leads. Each subject type has its own decision screen; the inbox only gathers them.

{
  "HrLite::LeaveRequest" => :admin_leave_request_path,
  "HrLite::CompOffRequest" => :admin_comp_off_request_path,
  "HrLite::RegularizationRequest" => :admin_regularization_request_path
}.freeze

Instance Method Summary collapse

Instance Method Details

#hr_lite_route?(helper_name) ⇒ Boolean

Returns:

  • (Boolean)


52
53
54
# File 'app/helpers/hr_lite/application_helper.rb', line 52

def hr_lite_route?(helper_name)
  hr_lite.respond_to?(helper_name)
end

#hrl_amount_in_words(amount) ⇒ Object

Indian-system amount in words for the slip footer. Delegates to the PORO so host-rendered templates (config.render_pdf) work too.



111
112
113
# File 'app/helpers/hr_lite/application_helper.rb', line 111

def hrl_amount_in_words(amount)
  HrLite::AmountInWords.words(amount)
end

#hrl_approval_path(approval) ⇒ Object



93
94
95
96
97
98
# File 'app/helpers/hr_lite/application_helper.rb', line 93

def hrl_approval_path(approval)
  helper = APPROVAL_PATHS[approval.subject_type]
  return nil unless helper && hr_lite_route?(helper)

  hr_lite.public_send(helper, approval.subject_id)
end

#hrl_duration(seconds) ⇒ Object



115
116
117
118
119
120
# File 'app/helpers/hr_lite/application_helper.rb', line 115

def hrl_duration(seconds)
  return "\u2014" if seconds.nil?

  total = seconds.to_i
  format("%dh %02dm", total / 3600, (total % 3600) / 60)
end

#hrl_money(amount) ⇒ Object

Delegates to the PORO so the host-rendered slip PDF formats identically.



105
106
107
# File 'app/helpers/hr_lite/application_helper.rb', line 105

def hrl_money(amount)
  HrLite::Money.format(amount)
end

#hrl_nav_items(items) ⇒ Object

Only items whose routes exist yet (the nav grows with each phase).



48
49
50
# File 'app/helpers/hr_lite/application_helper.rb', line 48

def hrl_nav_items(items)
  items.select { |item| hr_lite_route?(item[:path]) }
end


56
57
58
59
60
61
62
# File 'app/helpers/hr_lite/application_helper.rb', line 56

def hrl_nav_link(item)
  href = hr_lite.public_send(item[:path])
  active = item[:match].any? do |prefix|
    prefix == "/" ? request.path == href : request.path.start_with?("#{hr_lite.root_path.chomp('/')}#{prefix}")
  end
  link_to item[:label], href, class: "hrl-nav__link #{'hrl-nav__link--active' if active}"
end

#hrl_paginationObject



100
101
102
# File 'app/helpers/hr_lite/application_helper.rb', line 100

def hrl_pagination
  render "hr_lite/shared/pagination"
end

#hrl_request_status_badge(status) ⇒ Object

Status pill for a request lifecycle string — one colour map for every list and show screen.



147
148
149
150
151
# File 'app/helpers/hr_lite/application_helper.rb', line 147

def hrl_request_status_badge(status)
  css = { "approved" => "hrl-badge--ok", "rejected" => "hrl-badge--bad",
          "cancelled" => "hrl-badge--muted" }[status]
  (:span, status.humanize, class: "hrl-badge #{css}")
end

#hrl_team_status(row) ⇒ Object

Status badge for a TeamDay row — punch times over vague labels.



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'app/helpers/hr_lite/application_helper.rb', line 123

def hrl_team_status(row)
  case row.kind
  when :holiday then hrl_status_badge("Holiday", "hrl-badge--muted", worked_hint(row))
  when :weekend then hrl_status_badge("Weekend", "hrl-badge--muted", worked_hint(row))
  when :leave then hrl_status_badge("On leave (#{row.leave.leave_type.code})", "hrl-badge--warn")
  when :half_day_leave then hrl_status_badge("Half-day leave (#{row.leave.leave_type.code})", "hrl-badge--warn", worked_hint(row))
  when :upcoming then hrl_status_badge("\u2014", "hrl-badge--muted")
  when :absent
    label = row.date_today? ? "Not in yet" : "Absent"
    hrl_status_badge(label, "hrl-badge--bad")
  else # :present / :half_day punch
    record = row.record
    if record.check_out_at
      hrl_status_badge("Done #{record.check_in_at.strftime('%H:%M')}\u2013#{record.check_out_at.strftime('%H:%M')}", "hrl-badge--ok")
    elsif row.date_today?
      hrl_status_badge("In since #{record.check_in_at.strftime('%H:%M')}", "hrl-badge--ok")
    else
      hrl_status_badge("In #{record.check_in_at.strftime('%H:%M')}, no check-out", "hrl-badge--warn")
    end
  end
end

#render_kudo_message(kudo) ⇒ Object

Mention-marker-aware, XSS-safe kudos message rendering. Every literal chunk is escaped; only markers whose id has a mention row become highlighted chips (with the CURRENT display name — stale-name safe).



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'app/helpers/hr_lite/application_helper.rb', line 67

def render_kudo_message(kudo)
  mentioned = kudo.kudo_mentions.index_by(&:user_id)
  out = +""
  rest = kudo.message.to_s
  while (m = HrLite::MentionParser::MARKER.match(rest))
    out << ERB::Util.html_escape(m.pre_match)
    mention = mentioned[m[2].to_i]
    if mention
      out << %(<span class="hrl-mention">@#{ERB::Util.html_escape(HrLite.display_name(mention.user))}</span>)
    else
      out << ERB::Util.html_escape("@#{m[1]}")
    end
    rest = m.post_match
  end
  out << ERB::Util.html_escape(rest)
  out.html_safe
end