Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure Consistent Category Colors #1722

8 changes: 7 additions & 1 deletion app/javascript/controllers/color_avatar_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Controller } from "@hotwired/stimulus";
// Connects to data-controller="color-avatar"
// Used by the transaction merchant form to show a preview of what the avatar will look like
export default class extends Controller {
static targets = ["name", "avatar"];
static targets = ["name", "avatar", "selection"];

connect() {
this.nameTarget.addEventListener("input", this.handleNameChange);
Expand All @@ -25,4 +25,10 @@ export default class extends Controller {
this.avatarTarget.style.borderColor = `color-mix(in srgb, ${color} 10%, white)`;
this.avatarTarget.style.color = color;
}

handleParentChange(e) {
const parent = e.currentTarget.value;
const visibility = typeof parent === "string" && parent !== "" ? "hidden" : "visible"
this.selectionTarget.style.visibility = visibility
}
}
8 changes: 8 additions & 0 deletions app/models/category.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class Category < ApplicationRecord
validate :category_level_limit
validate :nested_category_matches_parent_classification

before_create :inherit_color_from_parent

scope :alphabetically, -> { order(:name) }
scope :roots, -> { where(parent_id: nil) }
scope :incomes, -> { where(classification: "income") }
Expand Down Expand Up @@ -85,6 +87,12 @@ def default_categories
end
end

def inherit_color_from_parent
if subcategory?
self.color = parent.color
end
end

def replace_and_destroy!(replacement)
transaction do
transactions.update_all category_id: replacement&.id
Expand Down
5 changes: 3 additions & 2 deletions app/views/categories/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<%= render partial: "shared/color_avatar", locals: { name: category.name, color: category.color } %>
</div>

<div class="flex gap-2 items-center justify-center">
<div class="flex gap-2 items-center justify-center" data-color-avatar-target="selection">
<% Category::COLORS.each do |color| %>
<label class="relative">
<%= f.radio_button :color, color, class: "sr-only peer", data: { action: "change->color-avatar#handleColorChange" } %>
Expand All @@ -21,6 +21,7 @@
<% end %>

<div class="flex flex-wrap gap-2 justify-center mb-4">

<% Category.icon_codes.each do |icon| %>
<label class="relative">
<%= f.radio_button :lucide_icon, icon, class: "sr-only peer" %>
Expand All @@ -35,7 +36,7 @@
<%= f.select :classification, [["Income", "income"], ["Expense", "expense"]], { label: "Classification" }, required: true %>
<%= f.text_field :name, placeholder: t(".placeholder"), required: true, autofocus: true, label: "Name", data: { color_avatar_target: "name" } %>
<% unless category.parent? %>
<%= f.select :parent_id, categories.pluck(:name, :id), { include_blank: "(unassigned)", label: "Parent category (optional)" }, disabled: category.parent? %>
<%= f.select :parent_id, categories.pluck(:name, :id), { include_blank: "(unassigned)", label: "Parent category (optional)" }, disabled: category.parent?, data: { action: "change->color-avatar#handleParentChange" } %>
<% end %>
</div>
</section>
Expand Down
2 changes: 1 addition & 1 deletion test/models/category_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def setup
category = categories(:subcategory)

error = assert_raises(ActiveRecord::RecordInvalid) do
category.subcategories.create!(name: "Invalid category", color: "#000", family: @family)
category.subcategories.create!(name: "Invalid category", family: @family)
end

assert_equal "Validation failed: Parent can't have more than 2 levels of subcategories", error.message
Expand Down