Use label_fn and value_fn
This commit is contained in:
@@ -7,12 +7,16 @@ defmodule MusicLibraryWeb.ChartComponents do
|
|||||||
## Examples
|
## Examples
|
||||||
<.vertical_bar_chart
|
<.vertical_bar_chart
|
||||||
data={[{"Artist 1", 5}, {"Artist 2", 3}]}
|
data={[{"Artist 1", 5}, {"Artist 2", 3}]}
|
||||||
|
label_fn={&elem(&1, 0)}
|
||||||
|
value_fn={&elem(&1, 1)}
|
||||||
width={400}
|
width={400}
|
||||||
height={300}
|
height={300}
|
||||||
bar_color="rgb(79, 70, 229)"
|
bar_color="rgb(79, 70, 229)"
|
||||||
/>
|
/>
|
||||||
"""
|
"""
|
||||||
attr :data, :list, required: true, doc: "List of {label, value} tuples"
|
attr :data, :list, required: true
|
||||||
|
attr :label_fn, :any, required: true
|
||||||
|
attr :value_fn, :any, required: true
|
||||||
attr :width, :integer, default: 400
|
attr :width, :integer, default: 400
|
||||||
attr :height, :integer, default: 300
|
attr :height, :integer, default: 300
|
||||||
attr :bar_color, :string, default: "rgb(79, 70, 229)"
|
attr :bar_color, :string, default: "rgb(79, 70, 229)"
|
||||||
@@ -23,7 +27,7 @@ defmodule MusicLibraryWeb.ChartComponents do
|
|||||||
assigns =
|
assigns =
|
||||||
assigns
|
assigns
|
||||||
|> assign(:padding, 40)
|
|> assign(:padding, 40)
|
||||||
|> assign(:max_value, max_value(assigns.data))
|
|> assign(:max_value, max_value(assigns.data, assigns.value_fn))
|
||||||
# Account for labels
|
# Account for labels
|
||||||
|> assign(:chart_width, assigns.width - 150)
|
|> assign(:chart_width, assigns.width - 150)
|
||||||
# Account for bottom padding
|
# Account for bottom padding
|
||||||
@@ -54,8 +58,8 @@ defmodule MusicLibraryWeb.ChartComponents do
|
|||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%!-- Bars and labels --%>
|
<%!-- Bars and labels --%>
|
||||||
<%= for {{label, value}, index} <- Enum.with_index(@data) do %>
|
<%= for {datum, index} <- Enum.with_index(@data) do %>
|
||||||
<% bar_width = @chart_width * value / @max_value %>
|
<% bar_width = @chart_width * @value_fn.(datum) / @max_value %>
|
||||||
<% y = @padding / 2 + index * (@bar_height + 4) %>
|
<% y = @padding / 2 + index * (@bar_height + 4) %>
|
||||||
|
|
||||||
<%!-- Label --%>
|
<%!-- Label --%>
|
||||||
@@ -64,9 +68,9 @@ defmodule MusicLibraryWeb.ChartComponents do
|
|||||||
y={y + @bar_height / 2 + 4}
|
y={y + @bar_height / 2 + 4}
|
||||||
text-anchor="end"
|
text-anchor="end"
|
||||||
class={["text-xs fill-zinc-500 dark:fill-zinc-400", @label_click && "cursor-pointer"]}
|
class={["text-xs fill-zinc-500 dark:fill-zinc-400", @label_click && "cursor-pointer"]}
|
||||||
phx-click={@label_click && @label_click.(label)}
|
phx-click={@label_click && @label_click.(datum)}
|
||||||
>
|
>
|
||||||
{truncate_label(label, 20)}
|
{truncate_label(@label_fn.(datum), 20)}
|
||||||
</text>
|
</text>
|
||||||
|
|
||||||
<%!-- Bar --%>
|
<%!-- Bar --%>
|
||||||
@@ -78,7 +82,7 @@ defmodule MusicLibraryWeb.ChartComponents do
|
|||||||
fill={@bar_color}
|
fill={@bar_color}
|
||||||
class="opacity-80 hover:opacity-100 transition-opacity"
|
class="opacity-80 hover:opacity-100 transition-opacity"
|
||||||
>
|
>
|
||||||
<title>{label}: {value}</title>
|
<title>{@label_fn.(datum)}: {@value_fn.(datum)}</title>
|
||||||
</rect>
|
</rect>
|
||||||
|
|
||||||
<%!-- Value label --%>
|
<%!-- Value label --%>
|
||||||
@@ -87,16 +91,16 @@ defmodule MusicLibraryWeb.ChartComponents do
|
|||||||
y={y + @bar_height / 2 + 4}
|
y={y + @bar_height / 2 + 4}
|
||||||
class="text-xs fill-zinc-500 dark:fill-zinc-400"
|
class="text-xs fill-zinc-500 dark:fill-zinc-400"
|
||||||
>
|
>
|
||||||
{value}
|
{@value_fn.(datum)}
|
||||||
</text>
|
</text>
|
||||||
<% end %>
|
<% end %>
|
||||||
</svg>
|
</svg>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
defp max_value(data) do
|
defp max_value(data, value_fn) do
|
||||||
{_, max} = Enum.max_by(data, fn {_, value} -> value end)
|
max = Enum.max_by(data, value_fn)
|
||||||
max
|
value_fn.(max)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp calculate_bar_height(data, available_height) do
|
defp calculate_bar_height(data, available_height) do
|
||||||
|
|||||||
@@ -79,8 +79,12 @@
|
|||||||
width={600}
|
width={600}
|
||||||
height={35 * length(@records_by_artist)}
|
height={35 * length(@records_by_artist)}
|
||||||
bar_color="rgb(79, 70, 229)"
|
bar_color="rgb(79, 70, 229)"
|
||||||
|
label_fn={fn {artist, _count} -> artist end}
|
||||||
|
value_fn={fn {_artist, count} -> count end}
|
||||||
label_click={
|
label_click={
|
||||||
fn label -> JS.navigate(~p"/collection?#{%{query: ~s(artist:"#{label}")}}") end
|
fn {artist, _count} ->
|
||||||
|
JS.navigate(~p"/collection?#{%{query: ~s(artist:"#{artist}")}}")
|
||||||
|
end
|
||||||
}
|
}
|
||||||
class="w-full"
|
class="w-full"
|
||||||
/>
|
/>
|
||||||
@@ -97,8 +101,10 @@
|
|||||||
width={600}
|
width={600}
|
||||||
height={35 * length(@records_by_genre)}
|
height={35 * length(@records_by_genre)}
|
||||||
bar_color="rgb(244, 63, 94)"
|
bar_color="rgb(244, 63, 94)"
|
||||||
|
label_fn={fn {genre, _count} -> genre end}
|
||||||
|
value_fn={fn {_genre, count} -> count end}
|
||||||
label_click={
|
label_click={
|
||||||
fn label -> JS.navigate(~p"/collection?#{%{query: ~s(genre:"#{label}")}}") end
|
fn {genre, _count} -> JS.navigate(~p"/collection?#{%{query: ~s(genre:"#{genre}")}}") end
|
||||||
}
|
}
|
||||||
class="w-full"
|
class="w-full"
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user