Files
sure/app/helpers/settings_helper.rb
Mark Hendriksen a8f5afc351 Add new settings sections and update tests (#278)
* Add new settings sections and update tests

Added 'Recurring', 'LLM Usage', and 'Providers' sections to the settings navigation in SettingsHelper. Updated system tests to include these new sections and added missing entries for 'Billing', 'Self-Hosting', 'Imports', and 'SimpleFin' to ensure test coverage matches the navigation.

* Fix tests

* fix test

* Restrict advanced settings to admin users

Added `admin_user?` and `self_hosted_and_admin?` helper methods. Advanced settings menu items now require admin privileges, and self-hosting settings require both self-hosted and admin status.

* Show admin-only settings links for admin users

Moved admin-specific settings links to be conditionally added only for admin users in the settings system test. This ensures that non-admin users do not see admin-only settings options during tests.

* Update settings_test.rb

* Update settings_test.rb

* Update en.yml

* Update settings_helper.rb

* Update settings_test.rb

* Update settings_test.rb

* Rename 'Recurring Transactions' to 'Recurring' in settings

Revert the label 'Recurring Transactions' to 'Recurring' in the settings navigation, locale file, and related system test to simplify terminology and improve consistency.

* Minor formatting update in settings test

No functional changes; adjusted whitespace in the admin settings links array for consistency.

---------

Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
2025-11-08 13:54:56 +01:00

85 lines
3.1 KiB
Ruby

module SettingsHelper
SETTINGS_ORDER = [
# General section
{ name: "Accounts", path: :accounts_path },
{ name: "Bank Sync", path: :settings_bank_sync_path },
{ name: "Preferences", path: :settings_preferences_path },
{ name: "Profile Info", path: :settings_profile_path },
{ name: "Security", path: :settings_security_path },
{ name: "Billing", path: :settings_billing_path, condition: :not_self_hosted? },
# Transactions section
{ name: "Categories", path: :categories_path },
{ name: "Tags", path: :tags_path },
{ name: "Rules", path: :rules_path },
{ name: "Merchants", path: :family_merchants_path },
{ name: "Recurring", path: :recurring_transactions_path },
# Advanced section
{ name: "AI Prompts", path: :settings_ai_prompts_path, condition: :admin_user? },
{ name: "LLM Usage", path: :settings_llm_usage_path, condition: :admin_user? },
{ name: "API Key", path: :settings_api_key_path, condition: :admin_user? },
{ name: "Self-Hosting", path: :settings_hosting_path, condition: :self_hosted_and_admin? },
{ name: "Providers", path: :settings_providers_path, condition: :admin_user? },
{ name: "Imports", path: :imports_path, condition: :admin_user? },
{ name: "SimpleFin", path: :simplefin_items_path, condition: :admin_user? },
# More section
{ name: "Guides", path: :settings_guides_path },
{ name: "What's new", path: :changelog_path },
{ name: "Feedback", path: :feedback_path }
]
def adjacent_setting(current_path, offset)
visible_settings = SETTINGS_ORDER.select { |setting| setting[:condition].nil? || send(setting[:condition]) }
current_index = visible_settings.index { |setting| send(setting[:path]) == current_path }
return nil unless current_index
adjacent_index = current_index + offset
return nil if adjacent_index < 0 || adjacent_index >= visible_settings.size
adjacent = visible_settings[adjacent_index]
render partial: "settings/settings_nav_link_large", locals: {
path: send(adjacent[:path]),
direction: offset > 0 ? "next" : "previous",
title: adjacent[:name]
}
end
def settings_section(title:, subtitle: nil, &block)
content = capture(&block)
render partial: "settings/section", locals: { title: title, subtitle: subtitle, content: content }
end
def settings_nav_footer
previous_setting = adjacent_setting(request.path, -1)
next_setting = adjacent_setting(request.path, 1)
content_tag :div, class: "hidden md:flex flex-row justify-between gap-4" do
concat(previous_setting)
concat(next_setting)
end
end
def settings_nav_footer_mobile
previous_setting = adjacent_setting(request.path, -1)
next_setting = adjacent_setting(request.path, 1)
content_tag :div, class: "md:hidden flex flex-col gap-4" do
concat(previous_setting)
concat(next_setting)
end
end
private
def not_self_hosted?
!self_hosted?
end
def admin_user?
Current.user&.admin? == true
end
def self_hosted_and_admin?
self_hosted? && admin_user?
end
end