forked from shibao/cannery
improve templates
This commit is contained in:
@ -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>
|
||||
|
Reference in New Issue
Block a user