mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-23 07:09:39 +02:00
New Settings Menu, Routes and Controllers Organization (#641)
* Add new settings routes and controllers * Add new settings view, restructure controllers and routes * Fix lint errors
This commit is contained in:
parent
39d57a167e
commit
9bda7efc3f
52 changed files with 771 additions and 203 deletions
|
@ -2,6 +2,18 @@ class AccountsController < ApplicationController
|
||||||
include Filterable
|
include Filterable
|
||||||
before_action :set_account, only: %i[ show update destroy sync ]
|
before_action :set_account, only: %i[ show update destroy sync ]
|
||||||
|
|
||||||
|
def index
|
||||||
|
@accounts = Current.family.accounts
|
||||||
|
end
|
||||||
|
|
||||||
|
def summary
|
||||||
|
snapshot = Current.family.snapshot(@period)
|
||||||
|
@net_worth_series = snapshot[:net_worth_series]
|
||||||
|
@asset_series = snapshot[:asset_series]
|
||||||
|
@liability_series = snapshot[:liability_series]
|
||||||
|
@account_groups = Current.family.accounts.by_group(period: @period, currency: Current.family.currency)
|
||||||
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@account = Account.new(
|
@account = Account.new(
|
||||||
balance: nil,
|
balance: nil,
|
||||||
|
|
|
@ -8,4 +8,13 @@ class PagesController < ApplicationController
|
||||||
@liability_series = snapshot[:liability_series]
|
@liability_series = snapshot[:liability_series]
|
||||||
@account_groups = Current.family.accounts.by_group(period: @period, currency: Current.family.currency)
|
@account_groups = Current.family.accounts.by_group(period: @period, currency: Current.family.currency)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def changelog
|
||||||
|
end
|
||||||
|
|
||||||
|
def feedback
|
||||||
|
end
|
||||||
|
|
||||||
|
def invites
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
7
app/controllers/settings/billings_controller.rb
Normal file
7
app/controllers/settings/billings_controller.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
class Settings::BillingsController < ApplicationController
|
||||||
|
def edit
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
end
|
||||||
|
end
|
46
app/controllers/settings/hostings_controller.rb
Normal file
46
app/controllers/settings/hostings_controller.rb
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
class Settings::HostingsController < ApplicationController
|
||||||
|
before_action :verify_hosting_mode
|
||||||
|
|
||||||
|
def show
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
if all_updates_valid?
|
||||||
|
hosting_params.keys.each do |key|
|
||||||
|
Setting.send("#{key}=", hosting_params[key].strip)
|
||||||
|
end
|
||||||
|
|
||||||
|
redirect_to settings_hosting_path, notice: t(".success")
|
||||||
|
else
|
||||||
|
flash.now[:error] = @errors.first.message
|
||||||
|
render :edit, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def all_updates_valid?
|
||||||
|
@errors = ActiveModel::Errors.new(Setting)
|
||||||
|
hosting_params.keys.each do |key|
|
||||||
|
setting = Setting.new(var: key)
|
||||||
|
setting.value = hosting_params[key].strip
|
||||||
|
|
||||||
|
unless setting.valid?
|
||||||
|
@errors.merge!(setting.errors)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if hosting_params[:upgrades_mode] == "auto" && hosting_params[:render_deploy_hook].blank?
|
||||||
|
@errors.add(:render_deploy_hook, t("settings.hostings.update.render_deploy_hook_error"))
|
||||||
|
end
|
||||||
|
|
||||||
|
@errors.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def hosting_params
|
||||||
|
params.require(:setting).permit(:render_deploy_hook, :upgrades_mode, :upgrades_target)
|
||||||
|
end
|
||||||
|
|
||||||
|
def verify_hosting_mode
|
||||||
|
head :not_found unless self_hosted?
|
||||||
|
end
|
||||||
|
end
|
7
app/controllers/settings/notifications_controller.rb
Normal file
7
app/controllers/settings/notifications_controller.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
class Settings::NotificationsController < ApplicationController
|
||||||
|
def edit
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
end
|
||||||
|
end
|
7
app/controllers/settings/preferences_controller.rb
Normal file
7
app/controllers/settings/preferences_controller.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
class Settings::PreferencesController < ApplicationController
|
||||||
|
def edit
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,5 @@
|
||||||
class SettingsController < ApplicationController
|
class Settings::ProfilesController < ApplicationController
|
||||||
def edit
|
def show
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
7
app/controllers/settings/securities_controller.rb
Normal file
7
app/controllers/settings/securities_controller.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
class Settings::SecuritiesController < ApplicationController
|
||||||
|
def edit
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,46 +0,0 @@
|
||||||
class Settings::SelfHostingController < ApplicationController
|
|
||||||
before_action :verify_self_hosting_enabled
|
|
||||||
|
|
||||||
def edit
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
|
||||||
if all_updates_valid?
|
|
||||||
self_hosting_params.keys.each do |key|
|
|
||||||
Setting.send("#{key}=", self_hosting_params[key].strip)
|
|
||||||
end
|
|
||||||
|
|
||||||
redirect_to edit_settings_self_hosting_path, notice: t(".success")
|
|
||||||
else
|
|
||||||
flash.now[:error] = @errors.first.message
|
|
||||||
render :edit, status: :unprocessable_entity
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def all_updates_valid?
|
|
||||||
@errors = ActiveModel::Errors.new(Setting)
|
|
||||||
self_hosting_params.keys.each do |key|
|
|
||||||
setting = Setting.new(var: key)
|
|
||||||
setting.value = self_hosting_params[key].strip
|
|
||||||
|
|
||||||
unless setting.valid?
|
|
||||||
@errors.merge!(setting.errors)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if self_hosting_params[:upgrades_mode] == "auto" && self_hosting_params[:render_deploy_hook].blank?
|
|
||||||
@errors.add(:render_deploy_hook, t("settings.self_hosting.update.render_deploy_hook_error"))
|
|
||||||
end
|
|
||||||
|
|
||||||
@errors.empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
def self_hosting_params
|
|
||||||
params.require(:setting).permit(:render_deploy_hook, :upgrades_mode, :upgrades_target)
|
|
||||||
end
|
|
||||||
|
|
||||||
def verify_self_hosting_enabled
|
|
||||||
head :not_found unless self_hosted?
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,6 +1,9 @@
|
||||||
class Transactions::CategoriesController < ApplicationController
|
class Transactions::CategoriesController < ApplicationController
|
||||||
before_action :set_category, only: [ :update, :destroy ]
|
before_action :set_category, only: [ :update, :destroy ]
|
||||||
|
|
||||||
|
def index
|
||||||
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
if Current.family.transaction_categories.create(category_params)
|
if Current.family.transaction_categories.create(category_params)
|
||||||
redirect_to transactions_path, notice: t(".success")
|
redirect_to transactions_path, notice: t(".success")
|
||||||
|
|
4
app/controllers/transactions/merchants_controller.rb
Normal file
4
app/controllers/transactions/merchants_controller.rb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
class Transactions::MerchantsController < ApplicationController
|
||||||
|
def index
|
||||||
|
end
|
||||||
|
end
|
4
app/controllers/transactions/rules_controller.rb
Normal file
4
app/controllers/transactions/rules_controller.rb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
class Transactions::RulesController < ApplicationController
|
||||||
|
def index
|
||||||
|
end
|
||||||
|
end
|
|
@ -38,21 +38,16 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def sidebar_link_to(name, path, options = {})
|
def sidebar_link_to(name, path, options = {})
|
||||||
base_class_names = [ "block", "border", "border-transparent", "rounded-xl", "-ml-2", "p-2", "text-sm", "font-medium", "text-gray-500", "flex", "items-center" ]
|
is_current = current_page?(path) || (request.path.start_with?(path) && path != "/")
|
||||||
hover_class_names = [ "hover:bg-white", "hover:border-alpha-black-50", "hover:text-gray-900", "hover:shadow-xs" ]
|
|
||||||
current_page_class_names = [ "bg-white", "border-alpha-black-50", "text-gray-900", "shadow-xs" ]
|
|
||||||
|
|
||||||
link_class_names = if current_page?(path) || (request.path.start_with?(path) && path != "/")
|
classes = [
|
||||||
base_class_names.delete("border-transparent")
|
"flex items-center gap-2 px-3 py-2 rounded-xl border text-sm font-medium text-gray-500",
|
||||||
base_class_names + hover_class_names + current_page_class_names
|
(is_current ? "bg-white text-gray-900 shadow-xs border-alpha-black-50" : "hover:bg-gray-100 border-transparent")
|
||||||
else
|
].compact.join(" ")
|
||||||
base_class_names + hover_class_names
|
|
||||||
end
|
|
||||||
|
|
||||||
merged_options = options.reverse_merge(class: link_class_names.join(" ")).except(:icon)
|
link_to path, **options.merge(class: classes), aria: { current: ("page" if current_page?(path)) } do
|
||||||
|
concat(lucide_icon(options[:icon], class: "w-5 h-5")) if options[:icon]
|
||||||
link_to path, merged_options do
|
concat(name)
|
||||||
lucide_icon(options[:icon], class: "w-5 h-5 mr-2") + name
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
2
app/helpers/settings/hosting_helper.rb
Normal file
2
app/helpers/settings/hosting_helper.rb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
module Settings::HostingHelper
|
||||||
|
end
|
|
@ -1,2 +0,0 @@
|
||||||
module Settings::SelfHostingHelper
|
|
||||||
end
|
|
9
app/helpers/settings_helper.rb
Normal file
9
app/helpers/settings_helper.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
module SettingsHelper
|
||||||
|
def next_setting(title, path)
|
||||||
|
render partial: "settings/nav_link_large", locals: { path: path, direction: "next", title: title }
|
||||||
|
end
|
||||||
|
|
||||||
|
def previous_setting(title, path)
|
||||||
|
render partial: "settings/nav_link_large", locals: { path: path, direction: "previous", title: title }
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,13 +1,17 @@
|
||||||
import { Controller } from "@hotwired/stimulus"
|
import { Controller } from "@hotwired/stimulus";
|
||||||
import { install, uninstall } from "@github/hotkey"
|
import { install, uninstall } from "@github/hotkey";
|
||||||
|
|
||||||
// Connects to data-controller="hotkey"
|
// Connects to data-controller="hotkey"
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
connect() {
|
connect() {
|
||||||
install(this.element)
|
install(this.element);
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect() {
|
disconnect() {
|
||||||
uninstall(this.element)
|
uninstall(this.element);
|
||||||
|
}
|
||||||
|
|
||||||
|
navigateBack(event) {
|
||||||
|
window.history.back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,17 +38,17 @@ export default {
|
||||||
900: "rgba(255, 255, 255, 0.7)",
|
900: "rgba(255, 255, 255, 0.7)",
|
||||||
},
|
},
|
||||||
"alpha-black": {
|
"alpha-black": {
|
||||||
25: "rgba(20, 20, 20, 0.03)",
|
25: "rgba(11, 11, 11, 0.03)",
|
||||||
50: "rgba(20, 20, 20, 0.05)",
|
50: "rgba(11, 11, 11, 0.05)",
|
||||||
100: "rgba(20, 20, 20, 0.08)",
|
100: "rgba(11, 11, 11, 0.08)",
|
||||||
200: "rgba(20, 20, 20, 0.1)",
|
200: "rgba(11, 11, 11, 0.1)",
|
||||||
300: "rgba(20, 20, 20, 0.15)",
|
300: "rgba(11, 11, 11, 0.15)",
|
||||||
400: "rgba(20, 20, 20, 0.2)",
|
400: "rgba(11, 11, 11, 0.2)",
|
||||||
500: "rgba(20, 20, 20, 0.3)",
|
500: "rgba(11, 11, 11, 0.3)",
|
||||||
600: "rgba(20, 20, 20, 0.4)",
|
600: "rgba(11, 11, 11, 0.4)",
|
||||||
700: "rgba(20, 20, 20, 0.5)",
|
700: "rgba(11, 11, 11, 0.5)",
|
||||||
800: "rgba(20, 20, 20, 0.6)",
|
800: "rgba(11, 11, 11, 0.6)",
|
||||||
900: "rgba(20, 20, 20, 0.7)",
|
900: "rgba(11, 11, 11, 0.7)",
|
||||||
},
|
},
|
||||||
red: {
|
red: {
|
||||||
25: "#FFFBFB",
|
25: "#FFFBFB",
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<%= render "settings/nav" %>
|
||||||
|
<% end %>
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<h1 class="text-xl font-medium text-gray-900">Accounts</h1>
|
<h1 class="text-xl font-medium text-gray-900">Accounts</h1>
|
||||||
|
@ -6,7 +9,7 @@
|
||||||
<span><%= t(".new_account") %></span>
|
<span><%= t(".new_account") %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% if Current.family.accounts.empty? %>
|
<% if @accounts.empty? %>
|
||||||
<div class="flex justify-center items-center h-[800px] text-sm">
|
<div class="flex justify-center items-center h-[800px] text-sm">
|
||||||
<div class="text-center flex flex-col items-center max-w-[300px]">
|
<div class="text-center flex flex-col items-center max-w-[300px]">
|
||||||
<p class="text-gray-900 mb-1 font-medium">No accounts yet</p>
|
<p class="text-gray-900 mb-1 font-medium">No accounts yet</p>
|
||||||
|
@ -19,8 +22,8 @@
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div>
|
<div>
|
||||||
<% Current.family.accounts.by_provider.each do |item| %>
|
<% @accounts.by_provider.each do |item| %>
|
||||||
<details class="bg-white group p-4 border border-alpha-black-25 shadow-xs rounded-xl">
|
<details open class="bg-white group p-4 border border-alpha-black-25 shadow-xs rounded-xl">
|
||||||
<summary class="flex items-center gap-2">
|
<summary class="flex items-center gap-2">
|
||||||
<%= lucide_icon("chevron-down", class: "hidden group-open:block w-5 h-5 text-gray-500") %>
|
<%= lucide_icon("chevron-down", class: "hidden group-open:block w-5 h-5 text-gray-500") %>
|
||||||
<%= lucide_icon("chevron-right", class: "group-open:hidden w-5 h-5 text-gray-500") %>
|
<%= lucide_icon("chevron-right", class: "group-open:hidden w-5 h-5 text-gray-500") %>
|
||||||
|
@ -54,4 +57,12 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<div class="flex justify-between gap-4">
|
||||||
|
<% if self_hosted? %>
|
||||||
|
<%= previous_setting("Self Hosting", settings_hosting_path) %>
|
||||||
|
<% else %>
|
||||||
|
<%= previous_setting("Billing", settings_billing_path) %>
|
||||||
|
<% end %>
|
||||||
|
<%= next_setting("Categories", transactions_categories_path) %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
76
app/views/accounts/summary.html.erb
Normal file
76
app/views/accounts/summary.html.erb
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<div class="space-y-4">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h1 class="text-xl font-medium text-gray-900">Accounts</h1>
|
||||||
|
<%= link_to new_account_path, class: "flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2", data: { turbo_frame: "modal" } do %>
|
||||||
|
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||||
|
<span><%= t(".new") %></span>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<div class="bg-white rounded-xl shadow-xs border border-alpha-black-100 flex divide-x divide-gray-200">
|
||||||
|
<div class="w-1/2 p-4 flex items-stretch justify-between">
|
||||||
|
<div class="space-y-2 grow">
|
||||||
|
<%= render partial: "shared/balance_heading", locals: {
|
||||||
|
label: "Assets",
|
||||||
|
period: @period,
|
||||||
|
balance: Current.family.assets,
|
||||||
|
trend: @asset_series.trend
|
||||||
|
} %>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-controller="trendline"
|
||||||
|
id="assetsTrendline"
|
||||||
|
class="h-full w-2/5"
|
||||||
|
data-trendline-series-value="<%= @asset_series.to_json %>"
|
||||||
|
data-trendline-classification-value="asset"></div>
|
||||||
|
</div>
|
||||||
|
<div class="w-1/2 p-4 flex items-stretch justify-between">
|
||||||
|
<div class="space-y-2 grow">
|
||||||
|
<%= render partial: "shared/balance_heading", locals: {
|
||||||
|
label: "Liabilities",
|
||||||
|
period: @period,
|
||||||
|
size: "md",
|
||||||
|
balance: Current.family.liabilities,
|
||||||
|
trend: @liability_series.trend
|
||||||
|
} %>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-controller="trendline"
|
||||||
|
id="liabilitiesTrendline"
|
||||||
|
class="h-full w-2/5"
|
||||||
|
data-trendline-series-value="<%= @liability_series.to_json %>"
|
||||||
|
data-trendline-classification-value="liability"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 bg-white rounded-xl shadow-xs border border-alpha-black-25 space-y-4">
|
||||||
|
<div class="flex justify-between items-center mb-5">
|
||||||
|
<h2 class="text-lg font-medium text-gray-900">Assets</h2>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<%= link_to new_account_path, class: "flex items-center gap-1 p-2 text-gray-900 text-sm font-medium bg-gray-50 rounded-lg hover:bg-gray-100", data: { turbo_frame: "modal" } do %>
|
||||||
|
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-500") %>
|
||||||
|
<p><%= t(".new") %></p>
|
||||||
|
<% end %>
|
||||||
|
<%= form_with url: summary_accounts_path, method: :get, class: "flex items-center gap-4", data: { controller: "auto-submit-form" } do %>
|
||||||
|
<%= render partial: "shared/period_select", locals: { value: @period.name } %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%= render partial: "pages/account_percentages_bar", locals: { account_groups: @account_groups[:assets].children } %>
|
||||||
|
<%= render partial: "pages/account_percentages_table", locals: { account_groups: @account_groups[:assets].children } %>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 bg-white rounded-xl shadow-xs border border-alpha-black-25 space-y-4">
|
||||||
|
<div class="flex justify-between items-center mb-5">
|
||||||
|
<h2 class="text-lg font-medium text-gray-900">Liabilities</h2>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<%= link_to new_account_path, class: "flex items-center gap-1 p-2 text-gray-900 text-sm font-medium bg-gray-50 rounded-lg hover:bg-gray-100", data: { turbo_frame: "modal" } do %>
|
||||||
|
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-500") %>
|
||||||
|
<p><%= t(".new") %></p>
|
||||||
|
<% end %>
|
||||||
|
<%= form_with url: summary_accounts_path, method: :get, class: "flex items-center gap-4", data: { controller: "auto-submit-form" } do %>
|
||||||
|
<%= render partial: "shared/period_select", locals: { value: @period.name } %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%= render partial: "pages/account_percentages_bar", locals: { account_groups: @account_groups[:liabilities].children } %>
|
||||||
|
<%= render partial: "pages/account_percentages_table", locals: { account_groups: @account_groups[:liabilities].children } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
88
app/views/layouts/_sidebar.html.erb
Normal file
88
app/views/layouts/_sidebar.html.erb
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<%= link_to root_path do %>
|
||||||
|
<%= image_tag "logo.svg", alt: "Maybe", class: "h-[22px]" %>
|
||||||
|
<% end %>
|
||||||
|
<div id="user-menu" data-controller="menu">
|
||||||
|
<button data-menu-target="button">
|
||||||
|
<div class="text-white w-9 h-9 bg-gray-400 rounded-full flex items-center justify-center text-lg uppercase"><%= Current.user.email.first %></div>
|
||||||
|
</button>
|
||||||
|
<div data-menu-target="content" class="hidden absolute w-[240px] z-10 top-10 left-[255px] top-[72px] bg-white rounded-sm shadow-xs border border-alpha-black-25">
|
||||||
|
<div class="p-3 flex items-center gap-3">
|
||||||
|
<div class="text-white shrink-0 w-9 h-9 bg-gray-400 rounded-full flex items-center justify-center text-lg uppercase"><%= Current.user.email.first %></div>
|
||||||
|
<div>
|
||||||
|
<span class="text-gray-900 font-medium text-sm"><%= Current.user.first_name %> <%= Current.user.last_name %></span>
|
||||||
|
<span class="text-gray-500 text-sm"><%= Current.user.email %></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="border-t border-b border-alpha-black-100 p-1">
|
||||||
|
<%= link_to settings_profile_path, class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||||
|
<%= lucide_icon("settings", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||||
|
<span class="text-gray-900 text-sm">Settings</span>
|
||||||
|
<% end %>
|
||||||
|
<div class="flex justify-between items-center gap-2">
|
||||||
|
<div class="flex items-center gap-2 rounded-lg px-3 py-2">
|
||||||
|
<%= lucide_icon("app-window", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||||
|
<div>
|
||||||
|
<span class="text-gray-900 text-sm">Demo mode</span>
|
||||||
|
<span class="text-gray-500 text-xs block">Coming soon...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%# TODO: This will be a form toggle when implemented %>
|
||||||
|
<div class="relative inline-block cursor-not-allowed" title="Coming soon...">
|
||||||
|
<label class="cursor-not-allowed block bg-gray-100 w-9 h-5 rounded-full after:content-[''] after:block after:absolute after:top-0.5 after:left-0.5 after:bg-white after:w-4 after:h-4 after:rounded-full after:transition-transform after:duration-300 after:ease-in-out peer-checked:bg-green-600 peer-checked:after:translate-x-4"></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="border-t border-b border-alpha-black-100 p-1">
|
||||||
|
<%= link_to changelog_path, class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||||
|
<%= lucide_icon("box", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||||
|
<span class="text-gray-900 text-sm">Changelog</span>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to feedback_path, class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||||
|
<%= lucide_icon("megaphone", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||||
|
<span class="text-gray-900 text-sm">Feedback</span>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to "https://link.maybe.co/discord", class: "flex gap-2 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||||
|
<%= lucide_icon("message-square-more", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||||
|
<span class="text-gray-900 text-sm">Contact</span>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<div class="p-1">
|
||||||
|
<%= button_to session_path, method: :delete, class: "w-full text-red-400 flex gap-1 items-center hover:bg-gray-50 rounded-lg px-3 py-2" do %>
|
||||||
|
<%= lucide_icon("log-out", class: "w-5 h-5 shrink-0") %>
|
||||||
|
<span class="text-sm">Logout</span>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<nav>
|
||||||
|
<ul class="mt-6 space-y-1">
|
||||||
|
<li>
|
||||||
|
<%= sidebar_link_to t(".dashboard"), root_path, icon: "layout-grid" %>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<%= sidebar_link_to t(".accounts"), summary_accounts_path, icon: "layers" %>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<%= sidebar_link_to t(".transactions"), transactions_path, icon: "credit-card" %>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<div class="flex flex-col mt-6">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<%= link_to accounts_path, class: "text-xs uppercase text-gray-500 font-bold tracking-wide" do %>
|
||||||
|
<%= t(".accounts") %>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to new_account_path, class: "block hover:bg-gray-100 p-2 text-sm font-semibold text-gray-900 flex items-center rounded", title: t(".new_account"), data: { turbo_frame: "modal" } do %>
|
||||||
|
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-500") %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<%= link_to new_account_path, class: "flex items-center gap-4 px-2 py-3 mb-1 text-gray-500 text-sm font-medium rounded-[10px] hover:bg-gray-100", data: { turbo_frame: "modal" } do %>
|
||||||
|
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||||
|
<p><%= t(".new_account") %></p>
|
||||||
|
<% end %>
|
||||||
|
<% account_groups.each do |group| %>
|
||||||
|
<%= render "accounts/account_list", group: group %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
|
@ -25,73 +25,28 @@
|
||||||
<body class="h-full">
|
<body class="h-full">
|
||||||
<div id="notification-tray" class="fixed z-50 space-y-1 top-6 right-6"></div>
|
<div id="notification-tray" class="fixed z-50 space-y-1 top-6 right-6"></div>
|
||||||
<%= safe_join(flash.map { |type, message| notification(message, type: type) }) %>
|
<%= safe_join(flash.map { |type, message| notification(message, type: type) }) %>
|
||||||
<div class="flex">
|
<div class="flex h-full">
|
||||||
<div class="flex-col p-5 min-w-80">
|
<div class="p-6 w-80 shrink-0 h-full overflow-y-auto">
|
||||||
<div class="flex items-center justify-between">
|
<% if content_for?(:sidebar) %>
|
||||||
<%= link_to root_path do %>
|
<%= yield :sidebar %>
|
||||||
<%= image_tag "logo.svg", alt: "Maybe", class: "h-[22px]" %>
|
<% else %>
|
||||||
<% end %>
|
<%= render "layouts/sidebar" %>
|
||||||
<div class="relative" data-controller="menu">
|
<% end %>
|
||||||
<button data-menu-target="button">
|
|
||||||
<div class="text-white w-9 h-9 bg-gray-400 rounded-full flex items-center justify-center text-lg uppercase"><%= Current.user.email.first %></div>
|
|
||||||
</button>
|
|
||||||
<div
|
|
||||||
data-menu-target="content"
|
|
||||||
class="hidden absolute min-w-[200px] z-10 top-10 right-0 bg-white p-1 rounded-sm shadow-xs border border-alpha-black-25 w-fit">
|
|
||||||
<%= link_to edit_settings_path, class: "flex gap-1 items-center hover:bg-gray-50 rounded-md p-2" do %>
|
|
||||||
<%= lucide_icon("pencil-line", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
|
||||||
<span class="text-gray-900 text-sm">General Settings</span>
|
|
||||||
<% end %>
|
|
||||||
<% if self_hosted? %>
|
|
||||||
<%= link_to edit_settings_self_hosting_path, class: "flex gap-1 items-center hover:bg-gray-50 rounded-md p-2" do %>
|
|
||||||
<%= lucide_icon("pencil-line", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
|
||||||
<span class="text-gray-900 text-sm">Self Host Settings</span>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
<%= button_to session_path, method: :delete, class: "w-full text-gray-900 flex gap-1 items-center hover:bg-gray-50 rounded-md p-2" do %>
|
|
||||||
<%= lucide_icon("log-out", class: "w-5 h-5 shrink-0") %>
|
|
||||||
<span class="text-sm">Logout</span>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<nav>
|
|
||||||
<ul class="mt-6 space-y-1">
|
|
||||||
<li>
|
|
||||||
<%= sidebar_link_to t(".dashboard"), root_path, icon: "layout-grid" %>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<%= sidebar_link_to t(".accounts"), accounts_path, icon: "layers" %>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<%= sidebar_link_to t(".transactions"), transactions_path, icon: "credit-card" %>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
<div class="flex flex-col mt-6">
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<%= link_to accounts_path, class: "text-xs uppercase text-gray-500 font-bold tracking-wide" do %>
|
|
||||||
<%= t(".accounts") %>
|
|
||||||
<% end %>
|
|
||||||
<%= link_to new_account_path, class: "block hover:bg-gray-100 p-2 text-sm font-semibold text-gray-900 flex items-center rounded", title: t(".new_account"), data: { turbo_frame: "modal" } do %>
|
|
||||||
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-500") %>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<%= link_to new_account_path, class: "flex items-center gap-4 px-2 py-3 mb-1 text-gray-500 text-sm font-medium rounded-[10px] hover:bg-gray-100", data: { turbo_frame: "modal" } do %>
|
|
||||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
|
||||||
<p><%= t(".new_account") %></p>
|
|
||||||
<% end %>
|
|
||||||
<% account_groups.each do |group| %>
|
|
||||||
<%= render "accounts/account_list", group: group %>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<main class="flex-grow px-20 py-6">
|
<main class="grow px-20 py-6 h-full overflow-y-auto">
|
||||||
<%= yield %>
|
<%= yield %>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
<%= turbo_frame_tag "modal" %>
|
<%= turbo_frame_tag "modal" %>
|
||||||
<%= render "shared/custom_confirm_modal" %>
|
<%= render "shared/custom_confirm_modal" %>
|
||||||
<%= render "shared/upgrade_notification" %>
|
<%= render "shared/upgrade_notification" %>
|
||||||
|
<% if self_hosted? %>
|
||||||
|
<div class="flex items-center py-0.5 px-0.5 gap-1 fixed bottom-2 right-2 shadow-xs border border-alpha-black-50 rounded-md bg-white">
|
||||||
|
<p class="text-xs text-gray-500 pl-2">Self-hosted Maybe: <%= Maybe.version.to_release_tag %></p>
|
||||||
|
<%= link_to settings_hosting_path, class: "flex gap-1 items-center hover:bg-gray-50 rounded-md p-2" do %>
|
||||||
|
<%= lucide_icon("settings", class: "w-4 h-4 text-gray-500 shrink-0") %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -15,6 +15,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-white border border-alpha-black-25 shadow-xs rounded-lg divide-y divide-alpha-black-50">
|
<div class="bg-white border border-alpha-black-25 shadow-xs rounded-lg divide-y divide-alpha-black-50">
|
||||||
<%= render partial: "account_group_disclosure", collection: account_groups, as: :accountable_group %>
|
<%= render partial: "pages/account_group_disclosure", collection: account_groups, as: :accountable_group %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
15
app/views/pages/changelog.html.erb
Normal file
15
app/views/pages/changelog.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<%= render "settings/nav" %>
|
||||||
|
<% end %>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h1 class="text-gray-900 text-xl font-medium mb-4">What's New</h1>
|
||||||
|
<div class="bg-white shadow-xs border border-alpha-black-25 rounded-xl p-4">
|
||||||
|
<div class="flex justify-center items-center py-20">
|
||||||
|
<p class="text-gray-500">Changelog coming soon...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between gap-4">
|
||||||
|
<%= previous_setting("Rules", transactions_rules_path) %>
|
||||||
|
<%= next_setting("Feedback", feedback_path) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
15
app/views/pages/feedback.html.erb
Normal file
15
app/views/pages/feedback.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<%= render "settings/nav" %>
|
||||||
|
<% end %>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h1 class="text-gray-900 text-xl font-medium mb-4">Feedback</h1>
|
||||||
|
<div class="bg-white shadow-xs border border-alpha-black-25 rounded-xl p-4">
|
||||||
|
<div class="flex justify-center items-center py-20">
|
||||||
|
<p class="text-gray-500">Feedback coming soon...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between gap-4">
|
||||||
|
<%= previous_setting("What's New", changelog_path) %>
|
||||||
|
<%= next_setting("Invite friends", invites_path) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
14
app/views/pages/invites.html.erb
Normal file
14
app/views/pages/invites.html.erb
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<%= render "settings/nav" %>
|
||||||
|
<% end %>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h1 class="text-gray-900 text-xl font-medium mb-4">Invite friends</h1>
|
||||||
|
<div class="bg-white shadow-xs border border-alpha-black-25 rounded-xl p-4">
|
||||||
|
<div class="flex justify-center items-center py-20">
|
||||||
|
<p class="text-gray-500">Invite friends coming soon...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between gap-4">
|
||||||
|
<%= previous_setting("Feedback", feedback_path) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
56
app/views/settings/_nav.html.erb
Normal file
56
app/views/settings/_nav.html.erb
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<div class="flex items-center gap-1 mb-6">
|
||||||
|
<%= link_to root_path, class: "flex items-center gap-1 text-gray-900 font-medium text-sm" do %>
|
||||||
|
<%= lucide_icon "chevron-left", class: "w-5 h-5 text-gray-500" %>
|
||||||
|
<span>Back</span>
|
||||||
|
<% end %>
|
||||||
|
<span data-controller="hotkey" data-hotkey="Escape" data-action="hotkey#navigateBack" class="uppercase bg-gray-100 rounded-sm px-1 py-0.5 text-xs text-gray-500 shadow-sm ml-1">
|
||||||
|
esc
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<nav class="space-y-4">
|
||||||
|
<section class="space-y-2">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<h3 class="uppercase text-gray-500 font-medium text-xs">General</h3>
|
||||||
|
<div class="h-px bg-alpha-black-100 w-full"></div>
|
||||||
|
</div>
|
||||||
|
<ul class="space-y-1">
|
||||||
|
<li>
|
||||||
|
<%= sidebar_link_to t(".profile_label"), settings_profile_path, icon: "circle-user" %>
|
||||||
|
<%= sidebar_link_to t(".preferences_label"), settings_preferences_path, icon: "bolt" %>
|
||||||
|
<%= sidebar_link_to t(".notifications_label"), settings_notifications_path, icon: "bell-dot" %>
|
||||||
|
<%= sidebar_link_to t(".security_label"), settings_security_path, icon: "shield-check" %>
|
||||||
|
<%= sidebar_link_to t(".billing_label"), settings_billing_path, icon: "circle-dollar-sign" %>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section class="space-y-2">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<h3 class="uppercase text-gray-500 font-medium text-xs">Setup</h3>
|
||||||
|
<div class="h-px bg-alpha-black-100 w-full"></div>
|
||||||
|
</div>
|
||||||
|
<ul class="space-y-1">
|
||||||
|
<li>
|
||||||
|
<% if self_hosted? %>
|
||||||
|
<%= sidebar_link_to t(".self_hosting_label"), settings_hosting_path, icon: "database" %>
|
||||||
|
<% end %>
|
||||||
|
<%= sidebar_link_to t(".accounts_label"), accounts_path, icon: "layers" %>
|
||||||
|
<%= sidebar_link_to t(".categories_label"), transactions_categories_path, icon: "tags" %>
|
||||||
|
<%= sidebar_link_to t(".merchants_label"), transactions_merchants_path, icon: "store" %>
|
||||||
|
<%= sidebar_link_to t(".rules_label"), transactions_rules_path, icon: "list-checks" %>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section class="space-y-2">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<h3 class="uppercase text-gray-500 font-medium text-xs">More</h3>
|
||||||
|
<div class="h-px bg-alpha-black-100 w-full"></div>
|
||||||
|
</div>
|
||||||
|
<ul class="space-y-1">
|
||||||
|
<li>
|
||||||
|
<%= sidebar_link_to t(".whats_new_label"), changelog_path, icon: "box" %>
|
||||||
|
<%= sidebar_link_to t(".feedback_label"), feedback_path, icon: "megaphone" %>
|
||||||
|
<%= sidebar_link_to t(".invite_label"), invites_path, icon: "gift" %>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</nav>
|
17
app/views/settings/_nav_link_large.html.erb
Normal file
17
app/views/settings/_nav_link_large.html.erb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<%# locals: path, direction, title %>
|
||||||
|
<%= link_to path, class: "w-full bg-white hover:bg-gray-50 rounded-xl border border-alpha-black-25 shadow-xs p-4 flex items-center justify-between" do %>
|
||||||
|
<% if direction == 'previous' %>
|
||||||
|
<div class="w-5 h-5 text-gray-500">
|
||||||
|
<%= lucide_icon("arrow-left") %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<div class="<%= "flex-grow" if direction == "next" %> <%= "text-right" if direction == "previous" %>">
|
||||||
|
<span class="block text-sm text-gray-500"><%= t(".#{direction}") %></span>
|
||||||
|
<span class="block text-sm font-medium text-gray-900"><%= title %></span>
|
||||||
|
</div>
|
||||||
|
<% if direction == 'next' %>
|
||||||
|
<div class="w-5 h-5 text-gray-500">
|
||||||
|
<%= lucide_icon("arrow-right") %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
19
app/views/settings/billings/show.html.erb
Normal file
19
app/views/settings/billings/show.html.erb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<%= render "settings/nav" %>
|
||||||
|
<% end %>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h1 class="text-gray-900 text-xl font-medium mb-4">Billing</h1>
|
||||||
|
<div class="bg-white shadow-xs border border-alpha-black-25 rounded-xl p-4">
|
||||||
|
<div class="flex justify-center items-center py-20">
|
||||||
|
<p class="text-gray-500">Billing settings coming soon...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between gap-4">
|
||||||
|
<%= previous_setting("Security", settings_security_path) %>
|
||||||
|
<% if self_hosted? %>
|
||||||
|
<%= next_setting("Self Hosting", settings_hosting_path) %>
|
||||||
|
<% else %>
|
||||||
|
<%= next_setting("Accounts", accounts_path) %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,17 +0,0 @@
|
||||||
<h1 class="text-3xl font-semibold font-display">Update settings</h1>
|
|
||||||
<%= form_with model: Current.user, url: settings_path, html: { class: "space-y-4" } do |form| %>
|
|
||||||
<%= form.fields_for :family_attributes do |family_fields| %>
|
|
||||||
<%= family_fields.text_field :name, placeholder: "Family name", value: Current.family.name, label: "Family name" %>
|
|
||||||
<%= family_fields.select :currency, options_for_select(Money::Currency.popular.map { |currency| ["#{currency.iso_code} (#{currency.name})", currency.iso_code] }, selected: Current.family.currency), { label: "Currency" } %>
|
|
||||||
<% end %>
|
|
||||||
<%= form.text_field :first_name, placeholder: "First name", value: Current.user.first_name, label: true %>
|
|
||||||
<%= form.text_field :last_name, placeholder: "Last name", value: Current.user.last_name, label: true %>
|
|
||||||
<%= form.email_field :email, placeholder: "Email", value: Current.user.email, label: true %>
|
|
||||||
<%= form.password_field :password, label: true %>
|
|
||||||
<%= form.password_field :password_confirmation, label: true %>
|
|
||||||
<div class="fixed right-5 bottom-5">
|
|
||||||
<button type="submit" class="flex items-center justify-center w-12 h-12 mb-2 bg-black rounded-full shrink-0 grow-0 hover:bg-gray-600">
|
|
||||||
<%= inline_svg_tag("icn-check.svg", class: "text-white fill-current") %>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
|
@ -1,11 +1,14 @@
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<%= render "settings/nav" %>
|
||||||
|
<% end %>
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<h1 class="text-3xl font-semibold font-display">Edit Self Hosting Settings</h1>
|
<h1 class="text-3xl font-semibold font-display">Self Hosting</h1>
|
||||||
<hr>
|
<hr>
|
||||||
<%= form_with model: Setting.new, url: settings_self_hosting_path, method: :patch, local: true, html: { class: "space-y-4" } do |form| %>
|
<%= form_with model: Setting.new, url: settings_hosting_path, method: :patch, local: true, html: { class: "space-y-4" } do |form| %>
|
||||||
<section class="space-y-3">
|
<section class="space-y-3">
|
||||||
<h2 class="text-2xl font-semibold">Render Deploy Hook</h2>
|
<h2 class="text-2xl font-semibold">Render Deploy Hook</h2>
|
||||||
<p class="text-gray-500">You must fill this in so your app can trigger upgrades when Maybe releases upgrades. Learn more about deploy hooks and how they work in the <%= link_to "Render documentation", "https://docs.render.com/docs/deploy-hooks", target: "_blank", rel: "noopener noreferrer", class: "text-blue-500 hover:underline" %>.</p>
|
<p class="text-gray-500">You must fill this in so your app can trigger upgrades when Maybe releases upgrades. Learn more about deploy hooks and how they work in the <%= link_to "Render documentation", "https://docs.render.com/docs/deploy-hooks", target: "_blank", rel: "noopener noreferrer", class: "text-blue-500 hover:underline" %>.</p>
|
||||||
<%= form.text_field :render_deploy_hook, label: "Render Deploy Hook", placeholder: "https://api.render.com/deploy/srv-xyz...", value: Setting.render_deploy_hook %>
|
<%= form.url_field :render_deploy_hook, label: "Render Deploy Hook", placeholder: "https://api.render.com/deploy/srv-xyz...", value: Setting.render_deploy_hook %>
|
||||||
</section>
|
</section>
|
||||||
<section class="space-y-3">
|
<section class="space-y-3">
|
||||||
<h2 class="text-2xl font-semibold">Auto Upgrades Setting</h2>
|
<h2 class="text-2xl font-semibold">Auto Upgrades Setting</h2>
|
||||||
|
@ -37,4 +40,8 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<div class="flex justify-between gap-4">
|
||||||
|
<%= previous_setting("Billing", settings_billing_path) %>
|
||||||
|
<%= next_setting("Accounts", accounts_path) %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
15
app/views/settings/notifications/show.html.erb
Normal file
15
app/views/settings/notifications/show.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<%= render "settings/nav" %>
|
||||||
|
<% end %>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h1 class="text-gray-900 text-xl font-medium mb-4">Notifications</h1>
|
||||||
|
<div class="bg-white shadow-xs border border-alpha-black-25 rounded-xl p-4">
|
||||||
|
<div class="flex justify-center items-center py-20">
|
||||||
|
<p class="text-gray-500">Notifications coming soon...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between gap-4">
|
||||||
|
<%= previous_setting("Preferences", settings_preferences_path) %>
|
||||||
|
<%= next_setting("Security", settings_security_path) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
15
app/views/settings/preferences/show.html.erb
Normal file
15
app/views/settings/preferences/show.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<%= render "settings/nav" %>
|
||||||
|
<% end %>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h1 class="text-gray-900 text-xl font-medium mb-4">Preferences</h1>
|
||||||
|
<div class="bg-white shadow-xs border border-alpha-black-25 rounded-xl p-4">
|
||||||
|
<div class="flex justify-center items-center py-20">
|
||||||
|
<p class="text-gray-500">Preferences coming soon...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between gap-4">
|
||||||
|
<%= previous_setting("Account", settings_profile_path) %>
|
||||||
|
<%= next_setting("Notifications", settings_notifications_path) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
25
app/views/settings/profiles/show.html.erb
Normal file
25
app/views/settings/profiles/show.html.erb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<%= render "settings/nav" %>
|
||||||
|
<% end %>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h1 class="text-gray-900 text-xl font-medium mb-4">Account</h1>
|
||||||
|
<%= form_with model: Current.user, url: settings_profile_path, html: { class: "space-y-4" } do |form| %>
|
||||||
|
<%= form.fields_for :family_attributes do |family_fields| %>
|
||||||
|
<%= family_fields.text_field :name, placeholder: "Family name", value: Current.family.name, label: "Family name" %>
|
||||||
|
<%= family_fields.select :currency, options_for_select(Money::Currency.popular.map { |currency| ["#{currency.iso_code} (#{currency.name})", currency.iso_code] }, selected: Current.family.currency), { label: "Currency" } %>
|
||||||
|
<% end %>
|
||||||
|
<%= form.text_field :first_name, placeholder: "First name", value: Current.user.first_name, label: true %>
|
||||||
|
<%= form.text_field :last_name, placeholder: "Last name", value: Current.user.last_name, label: true %>
|
||||||
|
<%= form.email_field :email, placeholder: "Email", value: Current.user.email, label: true %>
|
||||||
|
<%= form.password_field :password, label: true %>
|
||||||
|
<%= form.password_field :password_confirmation, label: true %>
|
||||||
|
<div class="fixed right-5 bottom-5">
|
||||||
|
<button type="submit" class="flex items-center justify-center w-12 h-12 mb-2 bg-black rounded-full shrink-0 grow-0 hover:bg-gray-600">
|
||||||
|
<%= inline_svg_tag("icn-check.svg", class: "text-white fill-current") %>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<div class="flex gap-4">
|
||||||
|
<%= next_setting("Preferences", settings_preferences_path) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
15
app/views/settings/securities/show.html.erb
Normal file
15
app/views/settings/securities/show.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<%= render "settings/nav" %>
|
||||||
|
<% end %>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h1 class="text-gray-900 text-xl font-medium mb-4">Security</h1>
|
||||||
|
<div class="bg-white shadow-xs border border-alpha-black-25 rounded-xl p-4">
|
||||||
|
<div class="flex justify-center items-center py-20">
|
||||||
|
<p class="text-gray-500">Security settings coming soon...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between gap-4">
|
||||||
|
<%= previous_setting("Notifications", settings_notifications_path) %>
|
||||||
|
<%= next_setting("Billing", settings_billing_path) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
15
app/views/transactions/categories/index.html.erb
Normal file
15
app/views/transactions/categories/index.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<%= render "settings/nav" %>
|
||||||
|
<% end %>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h1 class="text-gray-900 text-xl font-medium mb-4">Categories</h1>
|
||||||
|
<div class="bg-white shadow-xs border border-alpha-black-25 rounded-xl p-4">
|
||||||
|
<div class="flex justify-center items-center py-20">
|
||||||
|
<p class="text-gray-500">Transaction categories coming soon...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between gap-4">
|
||||||
|
<%= previous_setting("Accounts", accounts_path) %>
|
||||||
|
<%= next_setting("Merchants", transactions_merchants_path) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
15
app/views/transactions/merchants/index.html.erb
Normal file
15
app/views/transactions/merchants/index.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<%= render "settings/nav" %>
|
||||||
|
<% end %>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h1 class="text-gray-900 text-xl font-medium mb-4">Merchants</h1>
|
||||||
|
<div class="bg-white shadow-xs border border-alpha-black-25 rounded-xl p-4">
|
||||||
|
<div class="flex justify-center items-center py-20">
|
||||||
|
<p class="text-gray-500">Manage transaction merchants coming soon...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between gap-4">
|
||||||
|
<%= previous_setting("Categories", transactions_categories_path) %>
|
||||||
|
<%= next_setting("Rules", transactions_rules_path) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
15
app/views/transactions/rules/index.html.erb
Normal file
15
app/views/transactions/rules/index.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<%= render "settings/nav" %>
|
||||||
|
<% end %>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h1 class="text-gray-900 text-xl font-medium mb-4">Rules</h1>
|
||||||
|
<div class="bg-white shadow-xs border border-alpha-black-25 rounded-xl p-4">
|
||||||
|
<div class="flex justify-center items-center py-20">
|
||||||
|
<p class="text-gray-500">Transaction rules coming soon...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between gap-4">
|
||||||
|
<%= previous_setting("Merchants", transactions_merchants_path) %>
|
||||||
|
<%= next_setting("What's New", changelog_path) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -16,6 +16,8 @@ en:
|
||||||
placeholder: Example account name
|
placeholder: Example account name
|
||||||
select_accountable_type: What would you like to add?
|
select_accountable_type: What would you like to add?
|
||||||
title: Add an account
|
title: Add an account
|
||||||
|
summary:
|
||||||
|
new: New account
|
||||||
sync:
|
sync:
|
||||||
success: Account sync started
|
success: Account sync started
|
||||||
update:
|
update:
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
---
|
---
|
||||||
en:
|
en:
|
||||||
layouts:
|
layouts:
|
||||||
application:
|
|
||||||
accounts: Accounts
|
|
||||||
dashboard: Dashboard
|
|
||||||
new_account: New account
|
|
||||||
transactions: Transactions
|
|
||||||
auth:
|
auth:
|
||||||
or: or
|
or: or
|
||||||
privacy_policy: Privacy Policy
|
privacy_policy: Privacy Policy
|
||||||
|
@ -13,3 +8,8 @@ en:
|
||||||
sign_up: create an account
|
sign_up: create an account
|
||||||
terms_of_service: Terms of Service
|
terms_of_service: Terms of Service
|
||||||
your_account: Your account
|
your_account: Your account
|
||||||
|
sidebar:
|
||||||
|
accounts: Accounts
|
||||||
|
dashboard: Dashboard
|
||||||
|
new_account: New account
|
||||||
|
transactions: Transactions
|
||||||
|
|
|
@ -1,8 +1,25 @@
|
||||||
---
|
---
|
||||||
en:
|
en:
|
||||||
settings:
|
settings:
|
||||||
self_hosting:
|
hostings:
|
||||||
update:
|
update:
|
||||||
render_deploy_hook_error: Render deploy hook must be provided to enable auto
|
render_deploy_hook_error: Render deploy hook must be provided to enable auto
|
||||||
upgrades
|
upgrades
|
||||||
success: Settings updated successfully.
|
success: Settings updated successfully.
|
||||||
|
nav:
|
||||||
|
accounts_label: Accounts
|
||||||
|
billing_label: Billing
|
||||||
|
categories_label: Categories
|
||||||
|
feedback_label: Feedback
|
||||||
|
invite_label: Invite friends
|
||||||
|
merchants_label: Merchants
|
||||||
|
notifications_label: Notifications
|
||||||
|
preferences_label: Preferences
|
||||||
|
profile_label: Account
|
||||||
|
rules_label: Rules
|
||||||
|
security_label: Security
|
||||||
|
self_hosting_label: Self Hosting
|
||||||
|
whats_new_label: What's New
|
||||||
|
nav_link_large:
|
||||||
|
next: Next
|
||||||
|
previous: Back
|
||||||
|
|
|
@ -1,24 +1,39 @@
|
||||||
Rails.application.routes.draw do
|
Rails.application.routes.draw do
|
||||||
mount GoodJob::Engine => "jobs"
|
mount GoodJob::Engine => "jobs"
|
||||||
|
|
||||||
|
get "changelog" => "pages#changelog", as: :changelog
|
||||||
|
get "feedback" => "pages#feedback", as: :feedback
|
||||||
|
get "invites" => "pages#invites", as: :invites
|
||||||
|
|
||||||
resource :registration
|
resource :registration
|
||||||
resource :session
|
resource :session
|
||||||
resource :password_reset
|
resource :password_reset
|
||||||
resource :password
|
resource :password
|
||||||
|
|
||||||
resource :settings, only: %i[edit update] do
|
namespace :settings do
|
||||||
resource :self_hosting, only: %i[edit update], controller: "settings/self_hosting"
|
resource :profile, only: %i[show update]
|
||||||
|
resource :preferences, only: %i[show update]
|
||||||
|
resource :notifications, only: %i[show update]
|
||||||
|
resource :billing, only: %i[show update]
|
||||||
|
resource :hosting, only: %i[show update]
|
||||||
|
resource :security, only: %i[show update]
|
||||||
|
end
|
||||||
|
|
||||||
|
namespace :transactions do
|
||||||
|
resources :categories
|
||||||
|
|
||||||
|
# TODO: These are *placeholders*
|
||||||
|
# Uncomment `only` and add the necessary actions as they are implemented.
|
||||||
|
resources :rules, only: [ :index ]
|
||||||
|
resources :merchants, only: [ :index ]
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :transactions do
|
resources :transactions do
|
||||||
match "search" => "transactions#search", on: :collection, via: [ :get, :post ], as: :search
|
match "search" => "transactions#search", on: :collection, via: [ :get, :post ], as: :search
|
||||||
end
|
end
|
||||||
|
|
||||||
namespace :transactions do
|
|
||||||
resources :categories
|
|
||||||
end
|
|
||||||
|
|
||||||
resources :accounts, shallow: true do
|
resources :accounts, shallow: true do
|
||||||
|
get :summary, on: :collection
|
||||||
post :sync, on: :member
|
post :sync, on: :member
|
||||||
resources :valuations
|
resources :valuations
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,9 +12,10 @@ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
|
||||||
fill_in "Password", with: "password"
|
fill_in "Password", with: "password"
|
||||||
click_button "Log in"
|
click_button "Log in"
|
||||||
end
|
end
|
||||||
assert_text "Dashboard", wait: 5
|
end
|
||||||
find('[data-controller="menu"]').click
|
|
||||||
|
def sign_out
|
||||||
|
find("#user-menu").click
|
||||||
click_button "Logout"
|
click_button "Logout"
|
||||||
assert_text "Sign in to your account"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
0
test/controllers/settings/billings_controller_test.rb
Normal file
0
test/controllers/settings/billings_controller_test.rb
Normal file
|
@ -1,6 +1,6 @@
|
||||||
require "test_helper"
|
require "test_helper"
|
||||||
|
|
||||||
class Settings::SelfHostingControllerTest < ActionDispatch::IntegrationTest
|
class Settings::HostingsControllerTest < ActionDispatch::IntegrationTest
|
||||||
setup do
|
setup do
|
||||||
ENV["SELF_HOSTING_ENABLED"] = "true"
|
ENV["SELF_HOSTING_ENABLED"] = "true"
|
||||||
sign_in users(:family_admin)
|
sign_in users(:family_admin)
|
||||||
|
@ -9,14 +9,14 @@ class Settings::SelfHostingControllerTest < ActionDispatch::IntegrationTest
|
||||||
test "cannot edit when self hosting is disabled" do
|
test "cannot edit when self hosting is disabled" do
|
||||||
ENV["SELF_HOSTING_ENABLED"] = "false"
|
ENV["SELF_HOSTING_ENABLED"] = "false"
|
||||||
|
|
||||||
get edit_settings_self_hosting_url
|
get settings_hosting_url
|
||||||
assert :not_found
|
assert :not_found
|
||||||
|
|
||||||
patch settings_self_hosting_url, params: { setting: { render_deploy_hook: "https://example.com" } }
|
patch settings_hosting_url, params: { setting: { render_deploy_hook: "https://example.com" } }
|
||||||
assert :not_found
|
assert :not_found
|
||||||
end
|
end
|
||||||
test "should get edit when self hosting is enabled" do
|
test "should get edit when self hosting is enabled" do
|
||||||
get edit_settings_self_hosting_url
|
get settings_hosting_url
|
||||||
assert_response :success
|
assert_response :success
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ class Settings::SelfHostingControllerTest < ActionDispatch::IntegrationTest
|
||||||
NEW_RENDER_DEPLOY_HOOK = "https://api.render.com/deploy/srv-abc123"
|
NEW_RENDER_DEPLOY_HOOK = "https://api.render.com/deploy/srv-abc123"
|
||||||
assert_nil Setting.render_deploy_hook
|
assert_nil Setting.render_deploy_hook
|
||||||
|
|
||||||
patch settings_self_hosting_url, params: { setting: { render_deploy_hook: NEW_RENDER_DEPLOY_HOOK } }
|
patch settings_hosting_url, params: { setting: { render_deploy_hook: NEW_RENDER_DEPLOY_HOOK } }
|
||||||
|
|
||||||
assert_equal NEW_RENDER_DEPLOY_HOOK, Setting.render_deploy_hook
|
assert_equal NEW_RENDER_DEPLOY_HOOK, Setting.render_deploy_hook
|
||||||
end
|
end
|
11
test/controllers/settings/notifications_controller_test.rb
Normal file
11
test/controllers/settings/notifications_controller_test.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class Settings::NotificationsControllerTest < ActionDispatch::IntegrationTest
|
||||||
|
setup do
|
||||||
|
sign_in users(:family_admin)
|
||||||
|
end
|
||||||
|
test "get" do
|
||||||
|
get settings_notifications_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
end
|
11
test/controllers/settings/preferences_controller_test.rb
Normal file
11
test/controllers/settings/preferences_controller_test.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class Settings::PreferencesControllerTest < ActionDispatch::IntegrationTest
|
||||||
|
setup do
|
||||||
|
sign_in users(:family_admin)
|
||||||
|
end
|
||||||
|
test "get" do
|
||||||
|
get settings_preferences_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
end
|
11
test/controllers/settings/profiles_controller_test.rb
Normal file
11
test/controllers/settings/profiles_controller_test.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class Settings::ProfilesControllerTest < ActionDispatch::IntegrationTest
|
||||||
|
setup do
|
||||||
|
sign_in @user = users(:family_admin)
|
||||||
|
end
|
||||||
|
test "get" do
|
||||||
|
get settings_profile_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
end
|
11
test/controllers/settings/securities_controller_test.rb
Normal file
11
test/controllers/settings/securities_controller_test.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class Settings::SecuritiesControllerTest < ActionDispatch::IntegrationTest
|
||||||
|
setup do
|
||||||
|
sign_in users(:family_admin)
|
||||||
|
end
|
||||||
|
test "get" do
|
||||||
|
get settings_security_url
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,20 +0,0 @@
|
||||||
require "application_system_test_case"
|
|
||||||
|
|
||||||
class AccountsTest < ApplicationSystemTestCase
|
|
||||||
setup do
|
|
||||||
sign_in @user = users(:family_admin)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "should create account" do
|
|
||||||
skip("Disabling this test for now, UI is changing to quickly to do systems testing")
|
|
||||||
|
|
||||||
click_on "New account"
|
|
||||||
click_on "Credit Card"
|
|
||||||
within "form" do
|
|
||||||
fill_in "Name", with: "VISA"
|
|
||||||
fill_in "Balance", with: "1000"
|
|
||||||
click_on "Submit"
|
|
||||||
end
|
|
||||||
assert_text "$1,000"
|
|
||||||
end
|
|
||||||
end
|
|
66
test/system/settings_test.rb
Normal file
66
test/system/settings_test.rb
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
require "application_system_test_case"
|
||||||
|
|
||||||
|
class SettingsTest < ApplicationSystemTestCase
|
||||||
|
setup do
|
||||||
|
sign_in @user = users(:family_admin)
|
||||||
|
|
||||||
|
@settings_links = [
|
||||||
|
[ "Account", "Account", settings_profile_path ],
|
||||||
|
[ "Preferences", "Preferences", settings_preferences_path ],
|
||||||
|
[ "Notifications", "Notifications", settings_notifications_path ],
|
||||||
|
[ "Security", "Security", settings_security_path ],
|
||||||
|
[ "Billing", "Billing", settings_billing_path ],
|
||||||
|
[ "Accounts", "Accounts", accounts_path ],
|
||||||
|
[ "Categories", "Categories", transactions_categories_path ],
|
||||||
|
[ "Merchants", "Merchants", transactions_merchants_path ],
|
||||||
|
[ "Rules", "Rules", transactions_rules_path ],
|
||||||
|
[ "What's New", "What's New", changelog_path ],
|
||||||
|
[ "Feedback", "Feedback", feedback_path ],
|
||||||
|
[ "Invite friends", "Invite friends", invites_path ]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "can access settings from sidebar" do
|
||||||
|
open_settings_from_sidebar
|
||||||
|
assert_selector "h1", text: "Account"
|
||||||
|
assert_current_path settings_profile_path
|
||||||
|
end
|
||||||
|
|
||||||
|
test "all settings views and links are accessible" do
|
||||||
|
open_settings_from_sidebar
|
||||||
|
|
||||||
|
@settings_links.each_with_index do |(link_text, header_text, path), index|
|
||||||
|
next_setting_path = @settings_links[index + 1][2] if index < @settings_links.size - 1
|
||||||
|
prev_setting_path = @settings_links[index - 1][2] if index > 0
|
||||||
|
|
||||||
|
find_link(link_text, exact: true).click
|
||||||
|
|
||||||
|
assert_selector "h1", text: header_text
|
||||||
|
assert_current_path path
|
||||||
|
assert_link "Next", href: next_setting_path if next_setting_path.present?
|
||||||
|
assert_link "Back", href: prev_setting_path if prev_setting_path.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
# Conditional nav items don't show by default
|
||||||
|
assert_no_text "Self Hosting"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "can see conditional nav items" do
|
||||||
|
ENV["SELF_HOSTING_ENABLED"] = "true"
|
||||||
|
|
||||||
|
open_settings_from_sidebar
|
||||||
|
|
||||||
|
click_link "Self Hosting"
|
||||||
|
assert_selector "h1", text: "Self Hosting"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "clicking back or hitting escape key takes user back page they opened settings from" do
|
||||||
|
# TODO: Implement test for back navigation and escape key functionality.
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def open_settings_from_sidebar
|
||||||
|
find("#user-menu").click
|
||||||
|
click_link "Settings"
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,3 +1,7 @@
|
||||||
|
# Require individual test files to enable these as needed
|
||||||
|
ENV["SELF_HOSTING_ENABLED"] = "false"
|
||||||
|
ENV["UPGRADES_ENABLED"] = "false"
|
||||||
|
|
||||||
ENV["RAILS_ENV"] ||= "test"
|
ENV["RAILS_ENV"] ||= "test"
|
||||||
require_relative "../config/environment"
|
require_relative "../config/environment"
|
||||||
require "rails/test_help"
|
require "rails/test_help"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue