Packages

phoenix_kit

1.7.31
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 phoenix_kit_web live modules pages pages.html.heex
Raw

lib/phoenix_kit_web/live/modules/pages/pages.html.heex

<PhoenixKitWeb.Components.LayoutWrapper.app_layout
flash={@flash}
phoenix_kit_current_scope={assigns[:phoenix_kit_current_scope]}
page_title="{@project_title} Pages"
current_path={@url_path}
project_title={@project_title}
current_locale={@current_locale}
>
<div class="container flex flex-col mx-auto px-4 py-6">
<%!-- Header Section --%>
<header class="w-full relative mb-6">
<%!-- Back Button --%>
<.link
navigate={PhoenixKit.Utils.Routes.path("/admin/modules")}
class="btn btn-outline btn-primary btn-sm absolute left-0 top-0"
>
<PhoenixKitWeb.Components.Core.Icons.icon_arrow_left /> Back to Modules
</.link>
<%!-- Title Section --%>
<div class="text-center">
<h1 class="text-4xl font-bold text-base-content mb-3">Pages</h1>
<p class="text-lg text-base-content">File-based content management</p>
</div>
</header>
<%!-- Action Buttons --%>
<div class="flex gap-3 mb-6">
<button
type="button"
class="btn btn-primary"
phx-click="show_new_file_modal"
>
<PhoenixKitWeb.Components.Core.Icons.icon_plus class="w-4 h-4" /> New File
</button>
<button
type="button"
class="btn btn-secondary"
phx-click="show_new_folder_modal"
>
<PhoenixKitWeb.Components.Core.Icons.icon_plus class="w-4 h-4" /> New Folder
</button>
</div>
<%!-- File Tree --%>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<%!-- Breadcrumb Navigation --%>
<div class="flex items-center gap-2 mb-4">
<h2 class="card-title">Files:</h2>
<div class="breadcrumbs text-sm">
<ul>
<li>
<.link
patch={PhoenixKit.Utils.Routes.path("/admin/pages?path=/")}
class="link link-hover"
>
Root
</.link>
</li>
<%= if @current_path != "/" do %>
<%= for {segment, index} <- @current_path |> String.split("/", trim: true) |> Enum.with_index() do %>
<li>
<.link
patch={
PhoenixKit.Utils.Routes.path(
"/admin/pages?path=/" <>
Enum.join(
Enum.take(String.split(@current_path, "/", trim: true), index + 1),
"/"
)
)
}
class="link link-hover"
>
{segment}
</.link>
</li>
<% end %>
<% end %>
</ul>
</div>
</div>
<%= if @items == [] do %>
<div class="text-center text-base-content/60 py-8">
<p>No files or folders yet.</p>
<p class="text-sm">Create your first file or folder to get started.</p>
</div>
<% else %>
<div class="space-y-2">
<%= for item <- @items do %>
<div class="flex items-center gap-3 p-3 hover:bg-base-200 rounded-lg group">
<%= if item.type == :folder do %>
<PhoenixKitWeb.Components.Core.Icons.icon_folder class="w-5 h-5 text-warning flex-shrink-0" />
<div class="flex-1 min-w-0">
<.link
patch={PhoenixKit.Utils.Routes.path("/admin/pages?path=#{item.path}")}
class="link link-hover font-medium"
>
{item.name}/
</.link>
</div>
<% else %>
<PhoenixKitWeb.Components.Core.Icons.icon_document class="w-5 h-5 text-info flex-shrink-0" />
<div class="flex-1 min-w-0">
<div class="flex items-center gap-2">
<.link
navigate={
PhoenixKit.Utils.Routes.path("/admin/pages/view?path=#{item.path}")
}
class="link link-hover font-medium"
>
{item.name}
</.link>
<%!-- Status Badge --%>
<%= if Map.has_key?(item, :metadata) do %>
<.page_status_badge status={item.metadata.status} />
<% end %>
</div>
<%!-- File Info --%>
<div class="flex items-center gap-3 text-xs text-base-content/60 mt-1">
<%= if Map.has_key?(item, :size) do %>
<.file_size bytes={item.size} />
<% end %>
<%= if Map.has_key?(item, :mtime) and item.mtime do %>
<.file_mtime mtime={item.mtime} />
<% end %>
<%= if Map.has_key?(item, :metadata) and item.metadata.author do %>
<span>by {item.metadata.author}</span>
<% end %>
</div>
</div>
<% end %>
<%!-- Action Buttons --%>
<div class="flex gap-1">
<%= if item.type == :file do %>
<%!-- Status Dropdown --%>
<div class="dropdown dropdown-end">
<label tabindex="0" class="btn btn-sm btn-ghost" title="Change Status">
<.page_status_badge status={
if Map.has_key?(item, :metadata),
do: item.metadata.status,
else: "draft"
} />
</label>
<ul
tabindex="0"
class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-40 z-10"
>
<li>
<a
phx-click="change_file_status"
phx-value-path={item.path}
phx-value-status="draft"
>
<.page_status_badge status="draft" /> Draft
</a>
</li>
<li>
<a
phx-click="change_file_status"
phx-value-path={item.path}
phx-value-status="published"
>
<.page_status_badge status="published" /> Published
</a>
</li>
<li>
<a
phx-click="change_file_status"
phx-value-path={item.path}
phx-value-status="archived"
>
<.page_status_badge status="archived" /> Archived
</a>
</li>
</ul>
</div>
<button
type="button"
class="btn btn-sm btn-ghost"
phx-click="duplicate"
phx-value-path={item.path}
title="Duplicate"
>
<PhoenixKitWeb.Components.Core.Icons.icon_duplicate class="w-4 h-4" />
</button>
<.link
class="btn btn-sm btn-ghost"
title="Edit"
phx-click="debug_edit_click"
phx-value-path={item.path}
>
<PhoenixKitWeb.Components.Core.Icons.icon_edit class="w-4 h-4" />
</.link>
<% end %>
<%= if item.type == :file do %>
<button
type="button"
class="btn btn-sm btn-ghost"
phx-click="show_copy_modal"
phx-value-path={item.path}
phx-value-name={item.name}
title="Copy"
>
<PhoenixKitWeb.Components.Core.Icons.icon_copy class="w-4 h-4" />
</button>
<% end %>
<button
type="button"
class="btn btn-sm btn-ghost"
phx-click="show_move_modal"
phx-value-path={item.path}
phx-value-name={item.name}
title="Move"
>
<PhoenixKitWeb.Components.Core.Icons.icon_move class="w-4 h-4" />
</button>
<button
type="button"
class="btn btn-sm btn-error btn-ghost"
phx-click="show_delete_modal"
phx-value-path={item.path}
phx-value-name={item.name}
title="Delete"
>
<PhoenixKitWeb.Components.Core.Icons.icon_trash class="w-4 h-4" />
</button>
</div>
</div>
<% end %>
</div>
<% end %>
</div>
</div>
</div>
<%!-- New File Modal --%>
<%= if @show_new_file_modal do %>
<div class="modal modal-open">
<div class="modal-box" phx-click-away="close_new_file_modal">
<h3 class="font-bold text-lg mb-4">Create New File</h3>
<form phx-change="update_new_item_name" phx-submit="create_file">
<div class="form-control">
<label class="label">
<span class="label-text">File Name</span>
</label>
<input
type="text"
name="name"
class="input input-bordered"
placeholder="example.md"
value={@new_item_name}
autofocus
/>
</div>
</form>
<div class="modal-action">
<button
type="button"
class="btn"
phx-click="close_new_file_modal"
>
Cancel
</button>
<button
type="button"
class="btn btn-primary"
phx-click="create_file"
>
Create
</button>
</div>
</div>
</div>
<% end %>
<%!-- New Folder Modal --%>
<%= if @show_new_folder_modal do %>
<div class="modal modal-open">
<div class="modal-box" phx-click-away="close_new_folder_modal">
<h3 class="font-bold text-lg mb-4">Create New Folder</h3>
<form phx-change="update_new_item_name" phx-submit="create_folder">
<div class="form-control">
<label class="label">
<span class="label-text">Folder Name</span>
</label>
<input
type="text"
name="name"
class="input input-bordered"
placeholder="blog"
value={@new_item_name}
autofocus
/>
</div>
</form>
<div class="modal-action">
<button
type="button"
class="btn"
phx-click="close_new_folder_modal"
>
Cancel
</button>
<button
type="button"
class="btn btn-primary"
phx-click="create_folder"
>
Create
</button>
</div>
</div>
</div>
<% end %>
<%!-- Delete Confirmation Modal --%>
<%= if @show_delete_modal do %>
<div class="modal modal-open">
<div class="modal-box" phx-click-away="close_delete_modal">
<h3 class="font-bold text-lg mb-4">Confirm Delete</h3>
<p class="py-4">
Are you sure you want to delete <strong>{@delete_item_name}</strong>?
</p>
<%= if @delete_item_type == :folder and @delete_item_counts do %>
<div class="alert alert-warning mb-4">
<PhoenixKitWeb.Components.Core.Icons.icon_warning class="w-5 h-5" />
<div>
<p class="font-semibold">This folder contains:</p>
<ul class="list-disc list-inside mt-2">
<%= if @delete_item_counts.files > 0 do %>
<li>
{if @delete_item_counts.files == 1,
do: "1 file",
else: "#{@delete_item_counts.files} files"}
</li>
<% end %>
<%= if @delete_item_counts.folders > 0 do %>
<li>
{if @delete_item_counts.folders == 1,
do: "1 subfolder",
else: "#{@delete_item_counts.folders} subfolders"}
</li>
<% end %>
</ul>
<p class="mt-2 font-semibold">All contents will be permanently deleted!</p>
</div>
</div>
<% end %>
<p class="text-sm text-warning">
This action cannot be undone.
</p>
<div class="modal-action">
<button
type="button"
class="btn"
phx-click="close_delete_modal"
>
Cancel
</button>
<button
type="button"
class="btn btn-error"
phx-click="confirm_delete"
>
Delete
</button>
</div>
</div>
</div>
<% end %>
<%!-- Move Modal --%>
<%= if @show_move_modal do %>
<div class="modal modal-open">
<div class="modal-box" phx-click-away="close_move_modal">
<h3 class="font-bold text-lg mb-4">Move {@move_item_name}</h3>
<form phx-change="update_destination">
<div class="form-control">
<label class="label">
<span class="label-text">Select Destination Folder</span>
</label>
<select
name="destination"
class="select select-bordered"
value={@selected_destination}
>
<%= for folder <- @available_folders do %>
<option value={folder}>
<%= if folder == "/" do %>
Root
<% else %>
{folder}
<% end %>
</option>
<% end %>
</select>
</div>
</form>
<div class="modal-action">
<button
type="button"
class="btn"
phx-click="close_move_modal"
>
Cancel
</button>
<button
type="button"
class="btn btn-primary"
phx-click="confirm_move"
>
Move
</button>
</div>
</div>
</div>
<% end %>
<%!-- Copy Modal --%>
<%= if @show_copy_modal do %>
<div class="modal modal-open">
<div class="modal-box" phx-click-away="close_copy_modal">
<h3 class="font-bold text-lg mb-4">Copy {@copy_item_name}</h3>
<form phx-change="update_copy_destination">
<div class="form-control">
<label class="label">
<span class="label-text">Select Destination Folder</span>
</label>
<select
name="destination"
class="select select-bordered"
value={@copy_destination}
>
<%= for folder <- @available_folders do %>
<option value={folder}>
<%= if folder == "/" do %>
Root
<% else %>
{folder}
<% end %>
</option>
<% end %>
</select>
</div>
</form>
<p class="text-sm text-base-content/60 mt-2">
If a file with the same name exists, a copy will be created with a numbered suffix.
</p>
<div class="modal-action">
<button
type="button"
class="btn"
phx-click="close_copy_modal"
>
Cancel
</button>
<button
type="button"
class="btn btn-primary"
phx-click="confirm_copy"
>
Copy
</button>
</div>
</div>
</div>
<% end %>
</PhoenixKitWeb.Components.LayoutWrapper.app_layout>