Packages

phoenix_kit

1.7.92
1.7.210 1.7.209 1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib mix tasks phoenix_kit.gen.user.dashboard.ex
Raw

lib/mix/tasks/phoenix_kit.gen.user.dashboard.ex

defmodule Mix.Tasks.PhoenixKit.Gen.User.Dashboard do
@moduledoc """
Igniter task that generates a user dashboard page with tab configuration.
## Usage
mix phoenix_kit.gen.user.dashboard "Example"
## Arguments
- `tab_title` - The display title for the tab (e.g., "Example")
## Options
- `--url` - The URL path for the tab (optional, derived from title if not provided)
- `--category` - The category name (optional, defaults to "General")
- `--icon` - Heroicon name for the tab (optional, defaults to "hero-document")
- `--description` - Brief description for the tab (optional)
- `--category-icon` - Heroicon name for the category (optional, defaults to "hero-folder"). Only used when creating a new category.
- `--index` - Generate as main dashboard index (skips config, for overriding /dashboard)
## Examples
# Simple - uses all defaults
mix phoenix_kit.gen.user.dashboard "Example"
# With custom category
mix phoenix_kit.gen.user.dashboard "Example" --category="Farm Management"
# With custom icon
mix phoenix_kit.gen.user.dashboard "Example" --icon="hero-chart-bar"
# Full control
mix phoenix_kit.gen.user.dashboard "Example" --url="/custom/path" --icon="hero-user"
# Generate as main dashboard index (overrides /dashboard)
mix phoenix_kit.gen.user.dashboard "Dashboard" --url="/dashboard" --index --description="Welcome"
"""
@shortdoc "Generates user dashboard page with tab configuration"
use Igniter.Mix.Task
alias PhoenixKit.Install.IgniterConfig
alias PhoenixKit.Install.IgniterHelpers
@impl Igniter.Mix.Task
def info(_argv, _composing_task) do
%Igniter.Mix.Task.Info{
group: :phoenix_kit,
example: "mix phoenix_kit.gen.user.dashboard \"Example\"",
schema: [
url: :string,
category: :string,
icon: :string,
description: :string,
category_icon: :string,
index: :boolean
],
aliases: [u: :url, c: :category, i: :icon, d: :description, ci: :category_icon]
}
end
@impl Igniter.Mix.Task
def igniter(igniter) do
# Get options and arguments from igniter context
opts = igniter.args.options
argv = igniter.args.argv
case parse_args(argv, opts) do
{:ok, {tab_title, category, url}} ->
igniter
|> create_live_view(tab_title, url, opts)
|> maybe_add_dashboard_tab(category, tab_title, url, opts)
{:error, message} ->
Igniter.add_notice(igniter, """
❌ Error: #{message}
Usage: mix phoenix_kit.gen.user.dashboard <tab_title>
Example: mix phoenix_kit.gen.user.dashboard "Example"
""")
end
end
@impl Mix.Task
def run(argv) do
# Handle --help flag manually
if "--help" in argv or "-h" in argv do
Mix.shell().info("""
Generates a user dashboard page with tab configuration.
Usage:
mix phoenix_kit.gen.user.dashboard "Example"
Arguments:
tab_title - The display title for the tab
Options:
--url - The URL path for the tab (optional, derived from title)
--category - The category name (optional, defaults to "General")
--icon - Heroicon name for the tab (optional, defaults to "hero-document")
--description - Brief description for the tab (optional)
--category-icon - Heroicon name for the category (optional, defaults to "hero-folder")
--index - Generate as main dashboard index (skips config, for overriding /dashboard)
Examples:
# Simple - uses all defaults
mix phoenix_kit.gen.user.dashboard "Example"
# With custom category
mix phoenix_kit.gen.user.dashboard "Example" --category="Farm Management"
# With custom icon
mix phoenix_kit.gen.user.dashboard "Example" --icon="hero-chart-bar"
# Full control
mix phoenix_kit.gen.user.dashboard "Example" --url="/custom/path" --icon="hero-user"
# Generate as main dashboard index (overrides /dashboard)
mix phoenix_kit.gen.user.dashboard "Dashboard" --url="/dashboard" --index --description="Welcome"
Notes:
- Creates a LiveView file for the dashboard page
- Adds tab configuration to config/config.exs under :user_dashboard_categories (unless --index)
- After adding the route, run: mix compile --force
""")
:ok
else
# Delegate to Igniter.Mix.Task for standard execution
super(argv)
end
end
defp parse_args(argv, opts) do
# Filter out option arguments (starting with --) from argv
positional_args = Enum.reject(argv, &String.starts_with?(&1, "--"))
case positional_args do
[tab_title] ->
# Derive URL from tab title if not provided
url = Keyword.get(opts, :url, slugify(tab_title))
category = Keyword.get(opts, :category, "General")
{:ok, {tab_title, category, url}}
[] ->
{:error, "not enough arguments. Expected: <tab_title>"}
_ ->
{:error, "invalid arguments"}
end
end
defp create_live_view(igniter, tab_title, url, opts) do
app_name = IgniterHelpers.get_parent_app_name(igniter)
web_module = IgniterHelpers.get_parent_app_module_web(igniter)
web_module_string =
web_module
|> to_string()
|> String.replace_prefix("Elixir.", "")
page_name = camelize(tab_title)
description = Keyword.get(opts, :description, "Manage your dashboard content")
# Read the EEx template file
template_path =
case :code.priv_dir(:phoenix_kit) do
priv_dir when is_list(priv_dir) or is_binary(priv_dir) ->
Path.join(priv_dir, "templates/user_dashboard_page.ex")
_ ->
"priv/templates/user_dashboard_page.ex"
end
case File.read(template_path) do
{:ok, template_content} ->
# Use string replacement to avoid EEx/HEEX conflicts
rendered_content =
template_content
|> String.replace("<%= @web_module_prefix %>", web_module_string)
|> String.replace("<%= @page_name %>", page_name)
|> String.replace("<%= @page_title %>", tab_title)
|> String.replace("<%= @url %>", url)
|> String.replace("<%= @description %>", description)
# Build the correct path
file_path = build_live_view_file_path(app_name, page_name)
# Use create_new_file to avoid module parsing that might corrupt HEEX syntax
# Also skip formatting to preserve HEEX template syntax
Igniter.create_new_file(igniter, file_path, rendered_content, on_format: :skip)
{:error, reason} ->
igniter
|> Igniter.add_issue({:fatal, "Failed to read template file: #{reason}", []})
end
end
defp add_dashboard_tab(igniter, category, tab_title, url, opts) do
icon = Keyword.get(opts, :icon, "hero-document")
description = Keyword.get(opts, :description)
# Validate inputs
cond do
!String.starts_with?(url, "/") ->
Igniter.add_issue(igniter, {:fatal, "URL must start with '/'", []})
byte_size(tab_title) > 100 ->
Igniter.add_issue(igniter, {:fatal, "Tab title must be less than 100 characters", []})
description && byte_size(description) > 200 ->
Igniter.add_issue(igniter, {:fatal, "Description must be less than 200 characters", []})
true ->
igniter
|> update_dashboard_categories_config(category, tab_title, url, icon, description, opts)
|> print_success_message(category, tab_title, url)
end
end
defp maybe_add_dashboard_tab(igniter, category, tab_title, url, opts) do
is_index = Keyword.get(opts, :index, false)
if is_index do
# Skip adding to config for index pages
print_index_success_message(igniter, tab_title, url)
else
add_dashboard_tab(igniter, category, tab_title, url, opts)
end
end
defp update_dashboard_categories_config(
igniter,
category,
tab_title,
url,
icon,
description,
opts
) do
new_tab = %{
title: tab_title,
url: url,
icon: icon,
description: description
}
# Get category icon from options or use default
category_icon = Keyword.get(opts, :category_icon, "hero-folder")
# Use IgniterConfig to add the tab to the category (creates category if needed)
IgniterConfig.add_to_user_dashboard_category(
igniter,
category,
new_tab,
icon: category_icon
)
end
defp print_success_message(igniter, category, tab_title, url) do
web_module = IgniterHelpers.get_parent_app_module_web(igniter)
web_module_string =
web_module
|> to_string()
|> String.replace_prefix("Elixir.", "")
page_name = camelize(tab_title)
live_view_module = "#{web_module_string}.PhoenixKit.Dashboard.#{page_name}"
Igniter.add_notice(igniter, """
✅ Dashboard page generated!
Page: #{live_view_module}
Tab: #{tab_title}
Category: #{category}
URL: #{url}
📝 Add route:
scope "/" do
pipe_through :browser
live_session :user_dashboard,
on_mount: [
{PhoenixKitWeb.Users.Auth, :phoenix_kit_ensure_authenticated_scope},
{PhoenixKitWeb.Dashboard.ContextProvider, :default}
] do
live "#{url}", #{live_view_module}, :index
end
end
Then: mix compile --force && restart server
""")
end
defp print_index_success_message(igniter, tab_title, url) do
web_module = IgniterHelpers.get_parent_app_module_web(igniter)
web_module_string =
web_module
|> to_string()
|> String.replace_prefix("Elixir.", "")
page_name = camelize(tab_title)
live_view_module = "#{web_module_string}.PhoenixKit.Dashboard.#{page_name}"
Igniter.add_notice(igniter, """
✅ Dashboard index page generated!
Page: #{live_view_module}
URL: #{url}
📝 Add route BEFORE phoenix_kit_routes():
scope "/" do
pipe_through :browser
live_session :user_dashboard,
on_mount: [
{PhoenixKitWeb.Users.Auth, :phoenix_kit_ensure_authenticated_scope},
{PhoenixKitWeb.Dashboard.ContextProvider, :default}
] do
live "#{url}", #{live_view_module}, :index
end
end
import PhoenixKitWeb.Integration
phoenix_kit_routes()
Then: mix compile --force && restart server
""")
end
# Builds the full file path for the LiveView
defp build_live_view_file_path(app_name, page_name) do
# Use the app_name to get the correct web directory name
# E.g., phoenix_kit_parent_project -> phoenix_kit_parent_project_web
web_path =
app_name
|> to_string()
|> Kernel.<>("_web")
|> String.downcase()
# Convert page name to lowercase for the file
file_name = String.downcase(page_name)
# Return the full file path
"lib/#{web_path}/phoenix_kit/dashboard/#{file_name}.ex"
end
# Convert title to URL-safe slug
defp slugify(title) do
title
|> String.downcase()
|> String.replace(~r/[^a-z0-9\s-]/, "")
|> String.replace(~r/\s+/, "-")
|> then(&"/dashboard/#{&1}")
end
defp camelize(string) do
string
|> String.replace(~r/[^a-zA-Z0-9]+/, "_")
|> Macro.camelize()
end
end