improve templates
This commit is contained in:
		| @@ -48,11 +48,9 @@ defmodule LokalWeb.Components.InviteCard do | ||||
|         <%= render_slot(@code_actions) %> | ||||
|       </div> | ||||
|  | ||||
|       <%= if @inner_block do %> | ||||
|         <div class="flex space-x-4 justify-center items-center"> | ||||
|           <%= render_slot(@inner_block) %> | ||||
|         </div> | ||||
|       <% end %> | ||||
|       <div :if={@inner_block} class="flex space-x-4 justify-center items-center"> | ||||
|         <%= render_slot(@inner_block) %> | ||||
|       </div> | ||||
|     </div> | ||||
|     """ | ||||
|   end | ||||
|   | ||||
| @@ -33,20 +33,16 @@ | ||||
|       </tr> | ||||
|     </thead> | ||||
|     <tbody> | ||||
|       <%= for values <- @rows do %> | ||||
|         <tr> | ||||
|           <%= for %{key: key} = value <- @columns do %> | ||||
|             <td class={["p-2", value[:class]]}> | ||||
|               <%= case values |> Map.get(key) do %> | ||||
|                 <% {_custom_sort_value, value} -> %> | ||||
|                   <%= value %> | ||||
|                 <% value -> %> | ||||
|                   <%= value %> | ||||
|               <% end %> | ||||
|             </td> | ||||
|       <tr :for={values <- @rows}> | ||||
|         <td :for={%{key: key} = value <- @columns} class={["p-2", value[:class]]}> | ||||
|           <%= case values |> Map.get(key) do %> | ||||
|             <% {_custom_sort_value, value} -> %> | ||||
|               <%= value %> | ||||
|             <% value -> %> | ||||
|               <%= value %> | ||||
|           <% end %> | ||||
|         </tr> | ||||
|       <% end %> | ||||
|         </td> | ||||
|       </tr> | ||||
|     </tbody> | ||||
|   </table> | ||||
| </div> | ||||
|   | ||||
| @@ -53,16 +53,14 @@ defmodule LokalWeb.Components.Topbar do | ||||
|                 <% end %> | ||||
|               </datalist> | ||||
|             </form> | ||||
|             <%= if @current_user.role == :admin do %> | ||||
|               <li class="mx-2 my-1"> | ||||
|                 <.link | ||||
|                   navigate={Routes.invite_index_path(Endpoint, :index)} | ||||
|                   class="text-white text-white hover:underline" | ||||
|                 > | ||||
|                   <%= gettext("Invites") %> | ||||
|                 </.link> | ||||
|               </li> | ||||
|             <% end %> | ||||
|             <li :if={@current_user.role == :admin} class="mx-2 my-1"> | ||||
|               <.link | ||||
|                 navigate={Routes.invite_index_path(Endpoint, :index)} | ||||
|                 class="text-white text-white hover:underline" | ||||
|               > | ||||
|                 <%= gettext("Invites") %> | ||||
|               </.link> | ||||
|             </li> | ||||
|             <li class="mx-2 my-1"> | ||||
|               <.link | ||||
|                 navigate={Routes.user_settings_path(Endpoint, :edit)} | ||||
| @@ -80,27 +78,28 @@ defmodule LokalWeb.Components.Topbar do | ||||
|                 <i class="fas fa-sign-out-alt"></i> | ||||
|               </.link> | ||||
|             </li> | ||||
|             <%= if @current_user.role == :admin and function_exported?(Routes, :live_dashboard_path, 2) do %> | ||||
|               <li class="mx-2 my-1"> | ||||
|                 <.link | ||||
|                   navigate={Routes.live_dashboard_path(Endpoint, :home)} | ||||
|                   class="text-white text-white hover:underline" | ||||
|                 > | ||||
|                   <i class="fas fa-gauge"></i> | ||||
|                 </.link> | ||||
|               </li> | ||||
|             <% end %> | ||||
|             <li | ||||
|               :if={ | ||||
|                 @current_user.role == :admin and function_exported?(Routes, :live_dashboard_path, 2) | ||||
|               } | ||||
|               class="mx-2 my-1" | ||||
|             > | ||||
|               <.link | ||||
|                 navigate={Routes.live_dashboard_path(Endpoint, :home)} | ||||
|                 class="text-white text-white hover:underline" | ||||
|               > | ||||
|                 <i class="fas fa-gauge"></i> | ||||
|               </.link> | ||||
|             </li> | ||||
|           <% else %> | ||||
|             <%= if Accounts.allow_registration?() do %> | ||||
|               <li class="mx-2 my-1"> | ||||
|                 <.link | ||||
|                   navigate={Routes.user_registration_path(Endpoint, :new)} | ||||
|                   class="text-white text-white hover:underline truncate" | ||||
|                 > | ||||
|                   <%= dgettext("actions", "Register") %> | ||||
|                 </.link> | ||||
|               </li> | ||||
|             <% end %> | ||||
|             <li :if={Accounts.allow_registration?()} class="mx-2 my-1"> | ||||
|               <.link | ||||
|                 navigate={Routes.user_registration_path(Endpoint, :new)} | ||||
|                 class="text-white text-white hover:underline truncate" | ||||
|               > | ||||
|                 <%= dgettext("actions", "Register") %> | ||||
|               </.link> | ||||
|             </li> | ||||
|             <li class="mx-2 my-1"> | ||||
|               <.link | ||||
|                 navigate={Routes.user_session_path(Endpoint, :new)} | ||||
|   | ||||
| @@ -10,8 +10,8 @@ defmodule LokalWeb.Components.UserCard do | ||||
|     <div | ||||
|       id={"user-#{@user.id}"} | ||||
|       class="mx-4 my-2 px-8 py-4 flex flex-col justify-center items-center text-center | ||||
|           border border-gray-400 rounded-lg shadow-lg hover:shadow-md | ||||
|           transition-all duration-300 ease-in-out" | ||||
|         border border-gray-400 rounded-lg shadow-lg hover:shadow-md | ||||
|         transition-all duration-300 ease-in-out" | ||||
|     > | ||||
|       <h1 class="px-4 py-2 rounded-lg title text-xl break-all"> | ||||
|         <%= @user.email %> | ||||
| @@ -39,11 +39,9 @@ defmodule LokalWeb.Components.UserCard do | ||||
|         </p> | ||||
|       </h3> | ||||
|  | ||||
|       <%= if @inner_block do %> | ||||
|         <div class="px-4 py-2 flex space-x-4 justify-center items-center"> | ||||
|           <%= render_slot(@inner_block) %> | ||||
|         </div> | ||||
|       <% end %> | ||||
|       <div :if={@inner_block} class="px-4 py-2 flex space-x-4 justify-center items-center"> | ||||
|         <%= render_slot(@inner_block) %> | ||||
|       </div> | ||||
|     </div> | ||||
|     """ | ||||
|   end | ||||
|   | ||||
| @@ -1,43 +1,18 @@ | ||||
| defmodule LokalWeb.HomeLive do | ||||
|   @moduledoc """ | ||||
|   Liveview for the main home page | ||||
|   Liveview for the home page | ||||
|   """ | ||||
|  | ||||
|   use LokalWeb, :live_view | ||||
|   alias Lokal.Accounts | ||||
|   alias LokalWeb.Endpoint | ||||
|  | ||||
|   @version Mix.Project.config()[:version] | ||||
|  | ||||
|   @impl true | ||||
|   def mount(_params, _session, socket) do | ||||
|     {:ok, socket |> assign(page_title: gettext("Home"), query: "", results: %{})} | ||||
|   end | ||||
|  | ||||
|   @impl true | ||||
|   def handle_event("suggest", %{"q" => query}, socket) do | ||||
|     {:noreply, socket |> assign(results: search(query), query: query)} | ||||
|   end | ||||
|  | ||||
|   @impl true | ||||
|   def handle_event("search", %{"q" => query}, socket) do | ||||
|     case search(query) do | ||||
|       %{^query => vsn} -> | ||||
|         {:noreply, socket |> redirect(external: "https://hexdocs.pm/#{query}/#{vsn}")} | ||||
|  | ||||
|       _ -> | ||||
|         {:noreply, | ||||
|          socket | ||||
|          |> put_flash(:error, "No dependencies found matching \"#{query}\"") | ||||
|          |> assign(results: %{}, query: query)} | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   defp search(query) do | ||||
|     if not LokalWeb.Endpoint.config(:code_reloader) do | ||||
|       raise "action disabled when not in development" | ||||
|     end | ||||
|  | ||||
|     for {app, desc, vsn} <- Application.started_applications(), | ||||
|         app = to_string(app), | ||||
|         String.starts_with?(app, query) and not List.starts_with?(desc, ~c"ERTS"), | ||||
|         into: %{}, | ||||
|         do: {app, vsn} | ||||
|     admins = Accounts.list_users_by_role(:admin) | ||||
|     socket = socket |> assign(page_title: gettext("Home"), admins: admins, version: @version) | ||||
|     {:ok, socket} | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -1,9 +1,135 @@ | ||||
| <div class="flex flex-col justify-center items-center text-center space-y-4"> | ||||
|   <h1 class="title text-primary-500 text-2xl"> | ||||
| <div class="mx-auto px-8 sm:px-16 flex flex-col justify-center items-center text-center space-y-4 max-w-3xl"> | ||||
|   <h1 class="title text-primary-600 text-2xl"> | ||||
|     <%= gettext("Welcome to Lokal") %> | ||||
|   </h1> | ||||
|  | ||||
|   <p class="title  text-primary-500 text-lg"> | ||||
|     <%= gettext("Shop from your community") %> | ||||
|   </p> | ||||
|   <h2 class="title text-primary-600 text-lg"> | ||||
|     <%= gettext("Shop from your local community") %> | ||||
|   </h2> | ||||
|  | ||||
|   <hr class="hr" /> | ||||
|  | ||||
|   <ul class="flex flex-col space-y-4 text-center"> | ||||
|     <li class="flex flex-col justify-center items-center | ||||
|       space-y-2"> | ||||
|       <b class="whitespace-nowrap"> | ||||
|         <%= gettext("Easy to Use:") %> | ||||
|       </b> | ||||
|       <p> | ||||
|         <%= gettext("Lokal lets you easily shop from your local community") %> | ||||
|       </p> | ||||
|     </li> | ||||
|     <li class="flex flex-col justify-center items-center space-y-2"> | ||||
|       <b class="whitespace-nowrap"> | ||||
|         <%= gettext("Secure:") %> | ||||
|       </b> | ||||
|       <p> | ||||
|         <%= gettext("Self-host your own instance, or use an instance from someone you trust.") %> | ||||
|         <%= gettext("Your data stays with you, period") %> | ||||
|       </p> | ||||
|     </li> | ||||
|     <li class="flex flex-col justify-center items-center | ||||
|       space-y-2"> | ||||
|       <b class="whitespace-nowrap"> | ||||
|         <%= gettext("Simple:") %> | ||||
|       </b> | ||||
|       <p> | ||||
|         <%= gettext("Access from any internet-capable device") %> | ||||
|       </p> | ||||
|     </li> | ||||
|   </ul> | ||||
|  | ||||
|   <hr class="hr" /> | ||||
|  | ||||
|   <ul class="flex flex-col space-y-2 text-center justify-center"> | ||||
|     <h2 class="title text-primary-600 text-lg"> | ||||
|       <%= gettext("Instance Information") %> | ||||
|     </h2> | ||||
|  | ||||
|     <li class="flex flex-col justify-center space-x-2"> | ||||
|       <b> | ||||
|         <%= gettext("Admins:") %> | ||||
|       </b> | ||||
|       <p> | ||||
|         <%= if @admins |> Enum.empty?() do %> | ||||
|           <.link href={Routes.user_registration_path(Endpoint, :new)} class="hover:underline"> | ||||
|             <%= dgettext("prompts", "Register to setup Lokal") %> | ||||
|           </.link> | ||||
|         <% else %> | ||||
|           <div class="flex flex-wrap justify-center space-x-2"> | ||||
|             <a :for={%{email: email} <- @admins} class="hover:underline" href={"mailto:#{email}"}> | ||||
|               <%= email %> | ||||
|             </a> | ||||
|           </div> | ||||
|         <% end %> | ||||
|       </p> | ||||
|     </li> | ||||
|  | ||||
|     <li class="flex flex-row justify-center space-x-2"> | ||||
|       <b><%= gettext("Registration:") %></b> | ||||
|       <p> | ||||
|         <%= case Application.get_env(:lokal, Lokal.Accounts)[:registration] do | ||||
|           "public" -> gettext("Public Signups") | ||||
|           _ -> gettext("Invite Only") | ||||
|         end %> | ||||
|       </p> | ||||
|     </li> | ||||
|  | ||||
|     <li class="flex flex-row justify-center items-center space-x-2"> | ||||
|       <b><%= gettext("Version:") %></b> | ||||
|       <.link | ||||
|         href="https://gitea.bubbletea.dev/shibao/lokal/src/branch/stable/CHANGELOG.md" | ||||
|         class="flex flex-row justify-center items-center space-x-2 hover:underline" | ||||
|         target="_blank" | ||||
|         rel="noopener noreferrer" | ||||
|       > | ||||
|         <p> | ||||
|           <%= @version %> | ||||
|         </p> | ||||
|         <i class="fas fa-md fa-info-circle"></i> | ||||
|       </.link> | ||||
|     </li> | ||||
|   </ul> | ||||
|  | ||||
|   <hr class="hr" /> | ||||
|  | ||||
|   <ul class="flex flex-col space-y-2 text-center justify-center"> | ||||
|     <h2 class="title text-primary-600 text-lg"> | ||||
|       <%= gettext("Get involved!") %> | ||||
|     </h2> | ||||
|  | ||||
|     <li class="flex flex-col justify-center space-x-2"> | ||||
|       <.link | ||||
|         class="flex flex-row justify-center items-center space-x-2 hover:underline" | ||||
|         href="https://gitea.bubbletea.dev/shibao/lokal" | ||||
|         target="_blank" | ||||
|         rel="noopener noreferrer" | ||||
|       > | ||||
|         <p><%= gettext("View the source code") %></p> | ||||
|         <i class="fas fa-md fa-code"></i> | ||||
|       </.link> | ||||
|     </li> | ||||
|     <li class="flex flex-col justify-center space-x-2"> | ||||
|       <.link | ||||
|         class="flex flex-row justify-center items-center space-x-2 hover:underline" | ||||
|         href="https://weblate.bubbletea.dev/engage/lokal" | ||||
|         target="_blank" | ||||
|         rel="noopener noreferrer" | ||||
|       > | ||||
|         <p><%= gettext("Help translate") %></p> | ||||
|         <i class="fas fa-md fa-language"></i> | ||||
|       </.link> | ||||
|     </li> | ||||
|     <li class="flex flex-col justify-center space-x-2"> | ||||
|       <.link | ||||
|         class="flex flex-row justify-center items-center space-x-2 hover:underline" | ||||
|         href="https://gitea.bubbletea.dev/shibao/lokal/issues/new" | ||||
|         target="_blank" | ||||
|         rel="noopener noreferrer" | ||||
|       > | ||||
|         <p><%= gettext("Report bugs or request features") %></p> | ||||
|         <i class="fas fa-md fa-spider"></i> | ||||
|       </.link> | ||||
|     </li> | ||||
|   </ul> | ||||
| </div> | ||||
|   | ||||
| @@ -11,11 +11,12 @@ | ||||
|     phx-change="validate" | ||||
|     phx-submit="save" | ||||
|   > | ||||
|     <%= if @changeset.action && not @changeset.valid? do %> | ||||
|       <div class="invalid-feedback col-span-3 text-center"> | ||||
|         <%= changeset_errors(@changeset) %> | ||||
|       </div> | ||||
|     <% end %> | ||||
|     <div | ||||
|       :if={@changeset.action && not @changeset.valid?()} | ||||
|       class="invalid-feedback col-span-3 text-center" | ||||
|     > | ||||
|       <%= changeset_errors(@changeset) %> | ||||
|     </div> | ||||
|  | ||||
|     <%= label(f, :name, gettext("Name"), class: "title text-lg text-primary-600") %> | ||||
|     <%= text_input(f, :name, class: "input input-primary col-span-2") %> | ||||
|   | ||||
| @@ -61,7 +61,7 @@ defmodule LokalWeb.InviteLive.Index do | ||||
|       ) do | ||||
|     socket = | ||||
|       Invites.get_invite!(id, current_user) | ||||
|       |> Invites.update_invite(%{"uses_left" => nil}, current_user) | ||||
|       |> Invites.update_invite(%{uses_left: nil}, current_user) | ||||
|       |> case do | ||||
|         {:ok, %{name: invite_name}} -> | ||||
|           prompt = | ||||
| @@ -83,7 +83,7 @@ defmodule LokalWeb.InviteLive.Index do | ||||
|       ) do | ||||
|     socket = | ||||
|       Invites.get_invite!(id, current_user) | ||||
|       |> Invites.update_invite(%{"uses_left" => nil, "disabled_at" => nil}, current_user) | ||||
|       |> Invites.update_invite(%{uses_left: nil, disabled_at: nil}, current_user) | ||||
|       |> case do | ||||
|         {:ok, %{name: invite_name}} -> | ||||
|           prompt = | ||||
| @@ -107,7 +107,7 @@ defmodule LokalWeb.InviteLive.Index do | ||||
|  | ||||
|     socket = | ||||
|       Invites.get_invite!(id, current_user) | ||||
|       |> Invites.update_invite(%{"uses_left" => 0, "disabled_at" => now}, current_user) | ||||
|       |> Invites.update_invite(%{uses_left: 0, disabled_at: now}, current_user) | ||||
|       |> case do | ||||
|         {:ok, %{name: invite_name}} -> | ||||
|           prompt = | ||||
|   | ||||
| @@ -18,69 +18,65 @@ | ||||
|   <% end %> | ||||
|  | ||||
|   <div class="w-full flex flex-row flex-wrap justify-center items-center"> | ||||
|     <%= for invite <- @invites do %> | ||||
|       <.invite_card invite={invite}> | ||||
|         <:code_actions> | ||||
|           <form phx-submit="copy_to_clipboard"> | ||||
|             <button | ||||
|               type="submit" | ||||
|               class="mx-2 my-1 btn btn-primary" | ||||
|               phx-click={JS.dispatch("lokal:clipcopy", to: "#code-#{invite.id}")} | ||||
|             > | ||||
|               <%= dgettext("actions", "Copy to clipboard") %> | ||||
|             </button> | ||||
|           </form> | ||||
|         </:code_actions> | ||||
|         <.link | ||||
|           patch={Routes.invite_index_path(Endpoint, :edit, invite)} | ||||
|           class="text-primary-600 link" | ||||
|           data-qa={"edit-#{invite.id}"} | ||||
|         > | ||||
|           <i class="fa-fw fa-lg fas fa-edit"></i> | ||||
|         </.link> | ||||
|  | ||||
|         <.link | ||||
|           href="#" | ||||
|           class="text-primary-600 link" | ||||
|           phx-click="delete_invite" | ||||
|           phx-value-id={invite.id} | ||||
|           data-confirm={ | ||||
|             dgettext("prompts", "Are you sure you want to delete the invite for %{invite_name}?", | ||||
|               invite_name: invite.name | ||||
|             ) | ||||
|           } | ||||
|           data-qa={"delete-#{invite.id}"} | ||||
|         > | ||||
|           <i class="fa-fw fa-lg fas fa-trash"></i> | ||||
|         </.link> | ||||
|  | ||||
|         <%= if invite.disabled_at |> is_nil() do %> | ||||
|           <a href="#" class="btn btn-primary" phx-click="disable_invite" phx-value-id={invite.id}> | ||||
|             <%= gettext("Disable") %> | ||||
|           </a> | ||||
|         <% else %> | ||||
|           <a href="#" class="btn btn-primary" phx-click="enable_invite" phx-value-id={invite.id}> | ||||
|             <%= gettext("Enable") %> | ||||
|           </a> | ||||
|         <% end %> | ||||
|  | ||||
|         <%= if invite.disabled_at |> is_nil() and not (invite.uses_left |> is_nil()) do %> | ||||
|           <a | ||||
|             href="#" | ||||
|             class="btn btn-primary" | ||||
|             phx-click="set_unlimited" | ||||
|             phx-value-id={invite.id} | ||||
|             data-confirm={ | ||||
|               dgettext("prompts", "Are you sure you want to make %{invite_name} unlimited?", | ||||
|                 invite_name: invite.name | ||||
|               ) | ||||
|             } | ||||
|     <.invite_card :for={invite <- @invites} invite={invite}> | ||||
|       <:code_actions> | ||||
|         <form phx-submit="copy_to_clipboard"> | ||||
|           <button | ||||
|             type="submit" | ||||
|             class="mx-2 my-1 btn btn-primary" | ||||
|             phx-click={JS.dispatch("lokal:clipcopy", to: "#code-#{invite.id}")} | ||||
|           > | ||||
|             <%= gettext("Set Unlimited") %> | ||||
|           </a> | ||||
|         <% end %> | ||||
|       </.invite_card> | ||||
|     <% end %> | ||||
|             <%= dgettext("actions", "Copy to clipboard") %> | ||||
|           </button> | ||||
|         </form> | ||||
|       </:code_actions> | ||||
|       <.link | ||||
|         patch={Routes.invite_index_path(Endpoint, :edit, invite)} | ||||
|         class="text-primary-600 link" | ||||
|         data-qa={"edit-#{invite.id}"} | ||||
|       > | ||||
|         <i class="fa-fw fa-lg fas fa-edit"></i> | ||||
|       </.link> | ||||
|  | ||||
|       <.link | ||||
|         href="#" | ||||
|         class="text-primary-600 link" | ||||
|         phx-click="delete_invite" | ||||
|         phx-value-id={invite.id} | ||||
|         data-confirm={ | ||||
|           dgettext("prompts", "Are you sure you want to delete the invite for %{invite_name}?", | ||||
|             invite_name: invite.name | ||||
|           ) | ||||
|         } | ||||
|         data-qa={"delete-#{invite.id}"} | ||||
|       > | ||||
|         <i class="fa-fw fa-lg fas fa-trash"></i> | ||||
|       </.link> | ||||
|  | ||||
|       <a | ||||
|         href="#" | ||||
|         class="btn btn-primary" | ||||
|         phx-click={if invite.disabled_at, do: "enable_invite", else: "disable_invite"} | ||||
|         phx-value-id={invite.id} | ||||
|       > | ||||
|         <%= if invite.disabled_at, do: gettext("Enable"), else: gettext("Disable") %> | ||||
|       </a> | ||||
|  | ||||
|       <a | ||||
|         :if={invite.disabled_at |> is_nil() and not (invite.uses_left |> is_nil())} | ||||
|         href="#" | ||||
|         class="btn btn-primary" | ||||
|         phx-click="set_unlimited" | ||||
|         phx-value-id={invite.id} | ||||
|         data-confirm={ | ||||
|           dgettext("prompts", "Are you sure you want to make %{invite_name} unlimited?", | ||||
|             invite_name: invite.name | ||||
|           ) | ||||
|         } | ||||
|       > | ||||
|         <%= gettext("Set Unlimited") %> | ||||
|       </a> | ||||
|     </.invite_card> | ||||
|   </div> | ||||
|  | ||||
|   <%= unless @admins |> Enum.empty?() do %> | ||||
| @@ -91,25 +87,23 @@ | ||||
|     </h1> | ||||
|  | ||||
|     <div class="w-full flex flex-row flex-wrap justify-center items-center"> | ||||
|       <%= for admin <- @admins do %> | ||||
|         <.user_card user={admin}> | ||||
|           <.link | ||||
|             href="#" | ||||
|             class="text-primary-600 link" | ||||
|             phx-click="delete_user" | ||||
|             phx-value-id={admin.id} | ||||
|             data-confirm={ | ||||
|               dgettext( | ||||
|                 "prompts", | ||||
|                 "Are you sure you want to delete %{email}? This action is permanent!", | ||||
|                 email: admin.email | ||||
|               ) | ||||
|             } | ||||
|           > | ||||
|             <i class="fa-fw fa-lg fas fa-trash"></i> | ||||
|           </.link> | ||||
|         </.user_card> | ||||
|       <% end %> | ||||
|       <.user_card :for={admin <- @admins} user={admin}> | ||||
|         <.link | ||||
|           href="#" | ||||
|           class="text-primary-600 link" | ||||
|           phx-click="delete_user" | ||||
|           phx-value-id={admin.id} | ||||
|           data-confirm={ | ||||
|             dgettext( | ||||
|               "prompts", | ||||
|               "Are you sure you want to delete %{email}? This action is permanent!", | ||||
|               email: admin.email | ||||
|             ) | ||||
|           } | ||||
|         > | ||||
|           <i class="fa-fw fa-lg fas fa-trash"></i> | ||||
|         </.link> | ||||
|       </.user_card> | ||||
|     </div> | ||||
|   <% end %> | ||||
|  | ||||
| @@ -121,39 +115,35 @@ | ||||
|     </h1> | ||||
|  | ||||
|     <div class="w-full flex flex-row flex-wrap justify-center items-center"> | ||||
|       <%= for user <- @users do %> | ||||
|         <.user_card user={user}> | ||||
|           <.link | ||||
|             href="#" | ||||
|             class="text-primary-600 link" | ||||
|             phx-click="delete_user" | ||||
|             phx-value-id={user.id} | ||||
|             data-confirm={ | ||||
|               dgettext( | ||||
|                 "prompts", | ||||
|                 "Are you sure you want to delete %{email}? This action is permanent!", | ||||
|                 email: user.email | ||||
|               ) | ||||
|             } | ||||
|           > | ||||
|             <i class="fa-fw fa-lg fas fa-trash"></i> | ||||
|           </.link> | ||||
|         </.user_card> | ||||
|       <% end %> | ||||
|       <.user_card :for={user <- @users} user={user}> | ||||
|         <.link | ||||
|           href="#" | ||||
|           class="text-primary-600 link" | ||||
|           phx-click="delete_user" | ||||
|           phx-value-id={user.id} | ||||
|           data-confirm={ | ||||
|             dgettext( | ||||
|               "prompts", | ||||
|               "Are you sure you want to delete %{email}? This action is permanent!", | ||||
|               email: user.email | ||||
|             ) | ||||
|           } | ||||
|         > | ||||
|           <i class="fa-fw fa-lg fas fa-trash"></i> | ||||
|         </.link> | ||||
|       </.user_card> | ||||
|     </div> | ||||
|   <% end %> | ||||
| </div> | ||||
|  | ||||
| <%= if @live_action in [:new, :edit] do %> | ||||
|   <.modal return_to={Routes.invite_index_path(Endpoint, :index)}> | ||||
|     <.live_component | ||||
|       module={LokalWeb.InviteLive.FormComponent} | ||||
|       id={@invite.id || :new} | ||||
|       title={@page_title} | ||||
|       action={@live_action} | ||||
|       invite={@invite} | ||||
|       return_to={Routes.invite_index_path(Endpoint, :index)} | ||||
|       current_user={@current_user} | ||||
|     /> | ||||
|   </.modal> | ||||
| <% end %> | ||||
| <.modal :if={@live_action in [:new, :edit]} return_to={Routes.invite_index_path(Endpoint, :index)}> | ||||
|   <.live_component | ||||
|     module={LokalWeb.InviteLive.FormComponent} | ||||
|     id={@invite.id || :new} | ||||
|     title={@page_title} | ||||
|     action={@live_action} | ||||
|     invite={@invite} | ||||
|     return_to={Routes.invite_index_path(Endpoint, :index)} | ||||
|     current_user={@current_user} | ||||
|   /> | ||||
| </.modal> | ||||
|   | ||||
| @@ -31,10 +31,10 @@ defmodule LokalWeb.LiveHelpers do | ||||
|       id="modal-bg" | ||||
|       patch={@return_to} | ||||
|       class="fade-in fixed z-10 left-0 top-0 | ||||
|          w-full h-full overflow-hidden | ||||
|          p-8 flex flex-col justify-center items-center cursor-auto" | ||||
|         w-full h-full overflow-hidden | ||||
|         p-8 flex flex-col justify-center items-center cursor-auto" | ||||
|       style="background-color: rgba(0,0,0,0.4);" | ||||
|       phx_remove={hide_modal()} | ||||
|       phx-remove={hide_modal()} | ||||
|     > | ||||
|       <span class="hidden"></span> | ||||
|     </.link> | ||||
| @@ -48,18 +48,18 @@ defmodule LokalWeb.LiveHelpers do | ||||
|       <div | ||||
|         id="modal-content" | ||||
|         class="fade-in-scale w-full max-w-3xl relative | ||||
|         pointer-events-auto overflow-hidden | ||||
|         px-8 py-4 sm:py-8 flex flex-col justify-center items-center | ||||
|         flex flex-col justify-start items-center | ||||
|         bg-white border-2 rounded-lg" | ||||
|           pointer-events-auto overflow-hidden | ||||
|           px-8 py-4 sm:py-8 flex flex-col justify-center items-center | ||||
|           flex flex-col justify-start items-center | ||||
|           bg-white border-2 rounded-lg" | ||||
|       > | ||||
|         <.link | ||||
|           id="close" | ||||
|           href={@return_to} | ||||
|           class="absolute top-8 right-10 | ||||
|                       text-gray-500 hover:text-gray-800 | ||||
|                       transition-all duration-500 ease-in-out" | ||||
|           phx_remove={hide_modal()} | ||||
|             text-gray-500 hover:text-gray-800 | ||||
|             transition-all duration-500 ease-in-out" | ||||
|           phx-remove={hide_modal()} | ||||
|         > | ||||
|           <i class="fa-fw fa-lg fas fa-times"></i> | ||||
|         </.link> | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
|     <meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|     <title> | ||||
|       <%= dgettext("errors", "Error") %>| Lokal | ||||
|       <%= dgettext("errors", "Error") %> | <%= gettext("Lokal") %> | ||||
|     </title> | ||||
|     <link rel="stylesheet" href="/css/app.css" /> | ||||
|     <script defer type="text/javascript" src="/js/app.js"> | ||||
|   | ||||
| @@ -3,16 +3,12 @@ | ||||
|     <.topbar current_user={assigns[:current_user]}></.topbar> | ||||
|  | ||||
|     <div class="mx-8 my-2 flex flex-col space-y-4 text-center"> | ||||
|       <%= if get_flash(@conn, :info) do %> | ||||
|         <p class="alert alert-info" role="alert"> | ||||
|           <%= get_flash(@conn, :info) %> | ||||
|         </p> | ||||
|       <% end %> | ||||
|       <%= if get_flash(@conn, :error) do %> | ||||
|         <p class="alert alert-danger" role="alert"> | ||||
|           <%= get_flash(@conn, :error) %> | ||||
|         </p> | ||||
|       <% end %> | ||||
|       <p :if={get_flash(@conn, :info)} class="alert alert-info" role="alert"> | ||||
|         <%= get_flash(@conn, :info) %> | ||||
|       </p> | ||||
|       <p :if={get_flash(@conn, :error)} class="alert alert-danger" role="alert"> | ||||
|         <%= get_flash(@conn, :error) %> | ||||
|       </p> | ||||
|     </div> | ||||
|   </header> | ||||
|  | ||||
|   | ||||
| @@ -3,22 +3,25 @@ | ||||
|     <.topbar current_user={assigns[:current_user]}></.topbar> | ||||
|  | ||||
|     <div class="mx-8 my-2 flex flex-col space-y-4 text-center"> | ||||
|       <%= if @flash && @flash |> Map.has_key?("info") do %> | ||||
|         <p class="alert alert-info" role="alert" phx-click="lv:clear-flash" phx-value-key="info"> | ||||
|           <%= live_flash(@flash, "info") %> | ||||
|         </p> | ||||
|       <% end %> | ||||
|       <p | ||||
|         :if={@flash && @flash |> Map.has_key?("info")} | ||||
|         class="alert alert-info" | ||||
|         role="alert" | ||||
|         phx-click="lv:clear-flash" | ||||
|         phx-value-key="info" | ||||
|       > | ||||
|         <%= live_flash(@flash, "info") %> | ||||
|       </p> | ||||
|  | ||||
|       <%= if @flash && @flash |> Map.has_key?("error") do %> | ||||
|         <p | ||||
|           class="alert alert-danger" | ||||
|           role="alert" | ||||
|           phx-click="lv:clear-flash" | ||||
|           phx-value-key="error" | ||||
|         > | ||||
|           <%= live_flash(@flash, "error") %> | ||||
|         </p> | ||||
|       <% end %> | ||||
|       <p | ||||
|         :if={@flash && @flash |> Map.has_key?("error")} | ||||
|         class="alert alert-danger" | ||||
|         role="alert" | ||||
|         phx-click="lv:clear-flash" | ||||
|         phx-value-key="error" | ||||
|       > | ||||
|         <%= live_flash(@flash, "error") %> | ||||
|       </p> | ||||
|     </div> | ||||
|   </header> | ||||
|  | ||||
|   | ||||
| @@ -20,11 +20,13 @@ | ||||
|   <hr class="hr" /> | ||||
|  | ||||
|   <div class="flex flex-row justify-center items-center space-x-4"> | ||||
|     <%= if Accounts.allow_registration?() do %> | ||||
|       <.link href={Routes.user_registration_path(@conn, :new)} class="btn btn-primary"> | ||||
|         <%= dgettext("actions", "Register") %> | ||||
|       </.link> | ||||
|     <% end %> | ||||
|     <.link | ||||
|       :if={Accounts.allow_registration?()} | ||||
|       href={Routes.user_registration_path(@conn, :new)} | ||||
|       class="btn btn-primary" | ||||
|     > | ||||
|       <%= dgettext("actions", "Register") %> | ||||
|     </.link> | ||||
|     <.link href={Routes.user_session_path(@conn, :new)} class="btn btn-primary"> | ||||
|       <%= dgettext("actions", "Log in") %> | ||||
|     </.link> | ||||
|   | ||||
| @@ -9,13 +9,9 @@ | ||||
|     action={Routes.user_registration_path(@conn, :create)} | ||||
|     class="flex flex-col space-y-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 justify-center items-center" | ||||
|   > | ||||
|     <%= if @changeset.action && not @changeset.valid? do %> | ||||
|       <div class="alert alert-danger col-span-3"> | ||||
|         <p> | ||||
|           <%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %> | ||||
|         </p> | ||||
|       </div> | ||||
|     <% end %> | ||||
|     <p :if={@changeset.action && not @changeset.valid?()} class="alert alert-danger col-span-3"> | ||||
|       <%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %> | ||||
|     </p> | ||||
|  | ||||
|     <%= if @invite do %> | ||||
|       <%= hidden_input(f, :invite_token, value: @invite.token) %> | ||||
|   | ||||
| @@ -9,13 +9,9 @@ | ||||
|     action={Routes.user_reset_password_path(@conn, :update, @token)} | ||||
|     class="flex flex-col space-y-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 justify-center items-center" | ||||
|   > | ||||
|     <%= if @changeset.action && not @changeset.valid? do %> | ||||
|       <div class="alert alert-danger col-span-3"> | ||||
|         <p> | ||||
|           <%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %> | ||||
|         </p> | ||||
|       </div> | ||||
|     <% end %> | ||||
|     <p :if={@changeset.action && not @changeset.valid?()} class="alert alert-danger col-span-3"> | ||||
|       <%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %> | ||||
|     </p> | ||||
|  | ||||
|     <%= label(f, :password, "New password", class: "title text-lg text-primary-600") %> | ||||
|     <%= password_input(f, :password, required: true, class: "input input-primary col-span-2") %> | ||||
| @@ -38,11 +34,13 @@ | ||||
|   <hr class="hr" /> | ||||
|  | ||||
|   <div class="flex flex-row justify-center items-center space-x-4"> | ||||
|     <%= if Accounts.allow_registration?() do %> | ||||
|       <.link href={Routes.user_registration_path(@conn, :new)} class="btn btn-primary"> | ||||
|         <%= dgettext("actions", "Register") %> | ||||
|       </.link> | ||||
|     <% end %> | ||||
|     <.link | ||||
|       :if={Accounts.allow_registration?()} | ||||
|       href={Routes.user_registration_path(@conn, :new)} | ||||
|       class="btn btn-primary" | ||||
|     > | ||||
|       <%= dgettext("actions", "Register") %> | ||||
|     </.link> | ||||
|     <.link href={Routes.user_session_path(@conn, :new)} class="btn btn-primary"> | ||||
|       <%= dgettext("actions", "Log in") %> | ||||
|     </.link> | ||||
|   | ||||
| @@ -20,11 +20,13 @@ | ||||
|   <hr class="hr" /> | ||||
|  | ||||
|   <div class="flex flex-row justify-center items-center space-x-4"> | ||||
|     <%= if Accounts.allow_registration?() do %> | ||||
|       <.link href={Routes.user_registration_path(@conn, :new)} class="btn btn-primary"> | ||||
|         <%= dgettext("actions", "Register") %> | ||||
|       </.link> | ||||
|     <% end %> | ||||
|     <.link | ||||
|       :if={Accounts.allow_registration?()} | ||||
|       href={Routes.user_registration_path(@conn, :new)} | ||||
|       class="btn btn-primary" | ||||
|     > | ||||
|       <%= dgettext("actions", "Register") %> | ||||
|     </.link> | ||||
|     <.link href={Routes.user_session_path(@conn, :new)} class="btn btn-primary"> | ||||
|       <%= dgettext("actions", "Log in") %> | ||||
|     </.link> | ||||
|   | ||||
| @@ -10,13 +10,9 @@ | ||||
|     as="user" | ||||
|     class="flex flex-col space-y-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 justify-center items-center" | ||||
|   > | ||||
|     <%= if @error_message do %> | ||||
|       <div class="alert alert-danger col-span-3"> | ||||
|         <p> | ||||
|           <%= @error_message %> | ||||
|         </p> | ||||
|       </div> | ||||
|     <% end %> | ||||
|     <p :if={@error_message} class="alert alert-danger col-span-3"> | ||||
|       <%= @error_message %> | ||||
|     </p> | ||||
|  | ||||
|     <%= label(f, :email, class: "title text-lg text-primary-600") %> | ||||
|     <%= email_input(f, :email, required: true, class: "input input-primary col-span-2") %> | ||||
| @@ -35,11 +31,13 @@ | ||||
|   <hr class="hr" /> | ||||
|  | ||||
|   <div class="flex flex-row justify-center items-center space-x-4"> | ||||
|     <%= if Accounts.allow_registration?() do %> | ||||
|       <.link href={Routes.user_registration_path(@conn, :new)} class="btn btn-primary"> | ||||
|         <%= dgettext("actions", "Register") %> | ||||
|       </.link> | ||||
|     <% end %> | ||||
|     <.link | ||||
|       :if={Accounts.allow_registration?()} | ||||
|       href={Routes.user_registration_path(@conn, :new)} | ||||
|       class="btn btn-primary" | ||||
|     > | ||||
|       <%= dgettext("actions", "Register") %> | ||||
|     </.link> | ||||
|     <.link href={Routes.user_reset_password_path(@conn, :new)} class="btn btn-primary"> | ||||
|       <%= dgettext("actions", "Forgot your password?") %> | ||||
|     </.link> | ||||
|   | ||||
| @@ -15,13 +15,14 @@ | ||||
|       <%= dgettext("actions", "Change email") %> | ||||
|     </h3> | ||||
|  | ||||
|     <%= if @email_changeset.action && not @email_changeset.valid? do %> | ||||
|       <div class="alert alert-danger col-span-3"> | ||||
|         <p> | ||||
|           <%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %> | ||||
|         </p> | ||||
|       </div> | ||||
|     <% end %> | ||||
|     <div | ||||
|       :if={@email_changeset.action && not @email_changeset.valid?()} | ||||
|       class="alert alert-danger col-span-3" | ||||
|     > | ||||
|       <p> | ||||
|         <%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %> | ||||
|       </p> | ||||
|     </div> | ||||
|  | ||||
|     <%= hidden_input(f, :action, name: "action", value: "update_email") %> | ||||
|  | ||||
| @@ -58,13 +59,14 @@ | ||||
|       <%= dgettext("actions", "Change password") %> | ||||
|     </h3> | ||||
|  | ||||
|     <%= if @password_changeset.action && not @password_changeset.valid? do %> | ||||
|       <div class="alert alert-danger col-span-3"> | ||||
|         <p> | ||||
|           <%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %> | ||||
|         </p> | ||||
|       </div> | ||||
|     <% end %> | ||||
|     <div | ||||
|       :if={@password_changeset.action && not @password_changeset.valid?()} | ||||
|       class="alert alert-danger col-span-3" | ||||
|     > | ||||
|       <p> | ||||
|         <%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %> | ||||
|       </p> | ||||
|     </div> | ||||
|  | ||||
|     <%= hidden_input(f, :action, name: "action", value: "update_password") %> | ||||
|  | ||||
| @@ -113,13 +115,9 @@ | ||||
|       <%= dgettext("actions", "Change Language") %> | ||||
|     </h3> | ||||
|  | ||||
|     <%= if @locale_changeset.action && not @locale_changeset.valid? do %> | ||||
|       <div class="alert alert-danger"> | ||||
|         <p> | ||||
|           <%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %> | ||||
|         </p> | ||||
|       </div> | ||||
|     <% end %> | ||||
|     <p :if={@locale_changeset.action && not @locale_changeset.valid?} class="alert alert-danger"> | ||||
|       <%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %> | ||||
|     </p> | ||||
|  | ||||
|     <%= hidden_input(f, :action, name: "action", value: "update_locale") %> | ||||
|  | ||||
|   | ||||
| @@ -17,11 +17,13 @@ defmodule LokalWeb.ErrorHelpers do | ||||
|     assigns = %{extra_class: extra_class, form: form, field: field} | ||||
|  | ||||
|     ~H""" | ||||
|     <%= for error <- Keyword.get_values(@form.errors, @field) do %> | ||||
|       <span class={["invalid-feedback", @extra_class]} phx-feedback-for={input_name(@form, @field)}> | ||||
|         <%= translate_error(error) %> | ||||
|       </span> | ||||
|     <% end %> | ||||
|     <span | ||||
|       :for={error <- Keyword.get_values(@form.errors, @field)} | ||||
|       class={["invalid-feedback", @extra_class]} | ||||
|       phx-feedback-for={input_name(@form, @field)} | ||||
|     > | ||||
|       <%= translate_error(error) %> | ||||
|     </span> | ||||
|     """ | ||||
|   end | ||||
|  | ||||
|   | ||||
| @@ -7,11 +7,11 @@ defmodule LokalWeb.LayoutView do | ||||
|   # so we instruct Elixir to not warn if the dashboard route is missing. | ||||
|   @compile {:no_warn_undefined, {Routes, :live_dashboard_path, 2}} | ||||
|  | ||||
|   def get_title(conn) do | ||||
|     if conn.assigns |> Map.has_key?(:title) do | ||||
|       "Lokal | #{conn.assigns.title}" | ||||
|     else | ||||
|       "Lokal" | ||||
|     end | ||||
|   def get_title(%{assigns: %{title: title}}) when title not in [nil, ""] do | ||||
|     gettext("Lokal | %{title}", title: title) | ||||
|   end | ||||
|  | ||||
|   def get_title(_conn) do | ||||
|     gettext("Lokal") | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -16,19 +16,18 @@ defmodule LokalWeb.ViewHelpers do | ||||
|  | ||||
|   def datetime(assigns) do | ||||
|     ~H""" | ||||
|     <%= if @datetime do %> | ||||
|       <time | ||||
|         datetime={cast_datetime(@datetime)} | ||||
|         x-data={"{ | ||||
|           datetime: | ||||
|             Intl.DateTimeFormat([], {dateStyle: 'short', timeStyle: 'long'}) | ||||
|               .format(new Date(\"#{cast_datetime(@datetime)}\")) | ||||
|         }"} | ||||
|         x-text="datetime" | ||||
|       > | ||||
|         <%= cast_datetime(@datetime) %> | ||||
|       </time> | ||||
|     <% end %> | ||||
|     <time | ||||
|       :if={@datetime} | ||||
|       datetime={cast_datetime(@datetime)} | ||||
|       x-data={"{ | ||||
|         datetime: | ||||
|           Intl.DateTimeFormat([], {dateStyle: 'short', timeStyle: 'long'}) | ||||
|             .format(new Date(\"#{cast_datetime(@datetime)}\")) | ||||
|       }"} | ||||
|       x-text="datetime" | ||||
|     > | ||||
|       <%= cast_datetime(@datetime) %> | ||||
|     </time> | ||||
|     """ | ||||
|   end | ||||
|  | ||||
| @@ -48,19 +47,18 @@ defmodule LokalWeb.ViewHelpers do | ||||
|  | ||||
|   def date(assigns) do | ||||
|     ~H""" | ||||
|     <%= if @date do %> | ||||
|       <time | ||||
|         datetime={@date |> Date.to_iso8601(:extended)} | ||||
|         x-data={"{ | ||||
|           date: | ||||
|             Intl.DateTimeFormat([], {timeZone: 'Etc/UTC', dateStyle: 'short'}) | ||||
|               .format(new Date(\"#{@date |> Date.to_iso8601(:extended)}\")) | ||||
|         }"} | ||||
|         x-text="date" | ||||
|       > | ||||
|         <%= @date |> Date.to_iso8601(:extended) %> | ||||
|       </time> | ||||
|     <% end %> | ||||
|     <time | ||||
|       :if={@date} | ||||
|       datetime={@date |> Date.to_iso8601(:extended)} | ||||
|       x-data={"{ | ||||
|         date: | ||||
|           Intl.DateTimeFormat([], {timeZone: 'Etc/UTC', dateStyle: 'short'}) | ||||
|             .format(new Date(\"#{@date |> Date.to_iso8601(:extended)}\")) | ||||
|       }"} | ||||
|       x-text="date" | ||||
|     > | ||||
|       <%= @date |> Date.to_iso8601(:extended) %> | ||||
|     </time> | ||||
|     """ | ||||
|   end | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user