Compare commits
No commits in common. "0b27c8f80b71a7baeb63330b57a6cdca9978be05" and "09d3754f922a1ef4a45debc80f3a9b8c87183ab5" have entirely different histories.
0b27c8f80b
...
09d3754f92
@ -2,7 +2,6 @@
|
||||
- Update dependencies
|
||||
- Show topbar on form submit/page refresh
|
||||
- Make loading/reconnection less intrusive
|
||||
- Add QR code for invite link
|
||||
|
||||
# v0.8.0
|
||||
- Add search to catalog, ammo, container, tag and range index pages
|
||||
|
@ -24,7 +24,7 @@ import 'phoenix_html'
|
||||
// Establish Phoenix Socket and LiveView configuration.
|
||||
import { Socket } from 'phoenix'
|
||||
import { LiveSocket } from 'phoenix_live_view'
|
||||
import topbar from 'topbar'
|
||||
import topbar from '../vendor/topbar'
|
||||
import MaintainAttrs from './maintain_attrs'
|
||||
import ShotLogChart from './shot_log_chart'
|
||||
import Alpine from 'alpinejs'
|
||||
|
157
assets/vendor/topbar.js
vendored
Normal file
157
assets/vendor/topbar.js
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
/**
|
||||
* @license MIT
|
||||
* topbar 1.0.0, 2021-01-06
|
||||
* https://buunguyen.github.io/topbar
|
||||
* Copyright (c) 2021 Buu Nguyen
|
||||
*/
|
||||
(function (window, document) {
|
||||
"use strict";
|
||||
|
||||
// https://gist.github.com/paulirish/1579671
|
||||
(function () {
|
||||
var lastTime = 0;
|
||||
var vendors = ["ms", "moz", "webkit", "o"];
|
||||
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
||||
window.requestAnimationFrame =
|
||||
window[vendors[x] + "RequestAnimationFrame"];
|
||||
window.cancelAnimationFrame =
|
||||
window[vendors[x] + "CancelAnimationFrame"] ||
|
||||
window[vendors[x] + "CancelRequestAnimationFrame"];
|
||||
}
|
||||
if (!window.requestAnimationFrame)
|
||||
window.requestAnimationFrame = function (callback, element) {
|
||||
var currTime = new Date().getTime();
|
||||
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
||||
var id = window.setTimeout(function () {
|
||||
callback(currTime + timeToCall);
|
||||
}, timeToCall);
|
||||
lastTime = currTime + timeToCall;
|
||||
return id;
|
||||
};
|
||||
if (!window.cancelAnimationFrame)
|
||||
window.cancelAnimationFrame = function (id) {
|
||||
clearTimeout(id);
|
||||
};
|
||||
})();
|
||||
|
||||
var canvas,
|
||||
progressTimerId,
|
||||
fadeTimerId,
|
||||
currentProgress,
|
||||
showing,
|
||||
addEvent = function (elem, type, handler) {
|
||||
if (elem.addEventListener) elem.addEventListener(type, handler, false);
|
||||
else if (elem.attachEvent) elem.attachEvent("on" + type, handler);
|
||||
else elem["on" + type] = handler;
|
||||
},
|
||||
options = {
|
||||
autoRun: true,
|
||||
barThickness: 3,
|
||||
barColors: {
|
||||
0: "rgba(26, 188, 156, .9)",
|
||||
".25": "rgba(52, 152, 219, .9)",
|
||||
".50": "rgba(241, 196, 15, .9)",
|
||||
".75": "rgba(230, 126, 34, .9)",
|
||||
"1.0": "rgba(211, 84, 0, .9)",
|
||||
},
|
||||
shadowBlur: 10,
|
||||
shadowColor: "rgba(0, 0, 0, .6)",
|
||||
className: null,
|
||||
},
|
||||
repaint = function () {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = options.barThickness * 5; // need space for shadow
|
||||
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.shadowBlur = options.shadowBlur;
|
||||
ctx.shadowColor = options.shadowColor;
|
||||
|
||||
var lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
|
||||
for (var stop in options.barColors)
|
||||
lineGradient.addColorStop(stop, options.barColors[stop]);
|
||||
ctx.lineWidth = options.barThickness;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, options.barThickness / 2);
|
||||
ctx.lineTo(
|
||||
Math.ceil(currentProgress * canvas.width),
|
||||
options.barThickness / 2
|
||||
);
|
||||
ctx.strokeStyle = lineGradient;
|
||||
ctx.stroke();
|
||||
},
|
||||
createCanvas = function () {
|
||||
canvas = document.createElement("canvas");
|
||||
var style = canvas.style;
|
||||
style.position = "fixed";
|
||||
style.top = style.left = style.right = style.margin = style.padding = 0;
|
||||
style.zIndex = 100001;
|
||||
style.display = "none";
|
||||
if (options.className) canvas.classList.add(options.className);
|
||||
document.body.appendChild(canvas);
|
||||
addEvent(window, "resize", repaint);
|
||||
},
|
||||
topbar = {
|
||||
config: function (opts) {
|
||||
for (var key in opts)
|
||||
if (options.hasOwnProperty(key)) options[key] = opts[key];
|
||||
},
|
||||
show: function () {
|
||||
if (showing) return;
|
||||
showing = true;
|
||||
if (fadeTimerId !== null) window.cancelAnimationFrame(fadeTimerId);
|
||||
if (!canvas) createCanvas();
|
||||
canvas.style.opacity = 1;
|
||||
canvas.style.display = "block";
|
||||
topbar.progress(0);
|
||||
if (options.autoRun) {
|
||||
(function loop() {
|
||||
progressTimerId = window.requestAnimationFrame(loop);
|
||||
topbar.progress(
|
||||
"+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2)
|
||||
);
|
||||
})();
|
||||
}
|
||||
},
|
||||
progress: function (to) {
|
||||
if (typeof to === "undefined") return currentProgress;
|
||||
if (typeof to === "string") {
|
||||
to =
|
||||
(to.indexOf("+") >= 0 || to.indexOf("-") >= 0
|
||||
? currentProgress
|
||||
: 0) + parseFloat(to);
|
||||
}
|
||||
currentProgress = to > 1 ? 1 : to;
|
||||
repaint();
|
||||
return currentProgress;
|
||||
},
|
||||
hide: function () {
|
||||
if (!showing) return;
|
||||
showing = false;
|
||||
if (progressTimerId != null) {
|
||||
window.cancelAnimationFrame(progressTimerId);
|
||||
progressTimerId = null;
|
||||
}
|
||||
(function loop() {
|
||||
if (topbar.progress("+.1") >= 1) {
|
||||
canvas.style.opacity -= 0.05;
|
||||
if (canvas.style.opacity <= 0.05) {
|
||||
canvas.style.display = "none";
|
||||
fadeTimerId = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
fadeTimerId = window.requestAnimationFrame(loop);
|
||||
})();
|
||||
},
|
||||
};
|
||||
|
||||
if (typeof module === "object" && typeof module.exports === "object") {
|
||||
module.exports = topbar;
|
||||
} else if (typeof define === "function" && define.amd) {
|
||||
define(function () {
|
||||
return topbar;
|
||||
});
|
||||
} else {
|
||||
this.topbar = topbar;
|
||||
}
|
||||
}.call(this, window, document));
|
@ -15,18 +15,17 @@ end
|
||||
config :cannery, CanneryWeb.ViewHelpers, shibao_mode: System.get_env("SHIBAO_MODE") == "true"
|
||||
|
||||
# Set default locale
|
||||
config :gettext, :default_locale, System.get_env("LOCALE", "en_US")
|
||||
config :gettext, :default_locale, System.get_env("LOCALE") || "en_US"
|
||||
|
||||
maybe_ipv6 = if System.get_env("ECTO_IPV6") == "true", do: [:inet6], else: []
|
||||
|
||||
database_url =
|
||||
if config_env() == :test do
|
||||
System.get_env(
|
||||
"TEST_DATABASE_URL",
|
||||
System.get_env("TEST_DATABASE_URL") ||
|
||||
"ecto://postgres:postgres@localhost/cannery_test#{System.get_env("MIX_TEST_PARTITION")}"
|
||||
)
|
||||
else
|
||||
System.get_env("DATABASE_URL", "ecto://postgres:postgres@cannery-db/cannery")
|
||||
System.get_env("DATABASE_URL") ||
|
||||
"ecto://postgres:postgres@cannery-db/cannery"
|
||||
end
|
||||
|
||||
host =
|
||||
@ -41,7 +40,7 @@ interface =
|
||||
config :cannery, Cannery.Repo,
|
||||
# ssl: true,
|
||||
url: database_url,
|
||||
pool_size: String.to_integer(System.get_env("POOL_SIZE", "10")),
|
||||
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
|
||||
socket_options: maybe_ipv6
|
||||
|
||||
config :cannery, CanneryWeb.Endpoint,
|
||||
@ -50,10 +49,10 @@ config :cannery, CanneryWeb.Endpoint,
|
||||
# See the documentation on https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html
|
||||
# for details about using IPv6 vs IPv4 and loopback vs public addresses.
|
||||
ip: interface,
|
||||
port: String.to_integer(System.get_env("PORT", "4000"))
|
||||
port: String.to_integer(System.get_env("PORT") || "4000")
|
||||
],
|
||||
server: true,
|
||||
registration: System.get_env("REGISTRATION", "invite")
|
||||
registration: System.get_env("REGISTRATION") || "invite"
|
||||
|
||||
if config_env() == :prod do
|
||||
# The secret key base is used to sign/encrypt cookies and other secrets.
|
||||
@ -77,12 +76,12 @@ if config_env() == :prod do
|
||||
config :cannery, Cannery.Mailer,
|
||||
adapter: Swoosh.Adapters.SMTP,
|
||||
relay: System.get_env("SMTP_HOST") || raise("No SMTP_HOST set!"),
|
||||
port: System.get_env("SMTP_PORT", 587),
|
||||
port: System.get_env("SMTP_PORT") || 587,
|
||||
username: System.get_env("SMTP_USERNAME") || raise("No SMTP_USERNAME set!"),
|
||||
password: System.get_env("SMTP_PASSWORD") || raise("No SMTP_PASSWORD set!"),
|
||||
ssl: System.get_env("SMTP_SSL") == "true",
|
||||
email_from: System.get_env("EMAIL_FROM", "no-reply@#{System.get_env("HOST")}"),
|
||||
email_name: System.get_env("EMAIL_NAME", "Cannery")
|
||||
email_from: System.get_env("EMAIL_FROM") || "no-reply@#{System.get_env("HOST")}",
|
||||
email_name: System.get_env("EMAIL_NAME") || "Cannery"
|
||||
|
||||
# ## Using releases
|
||||
#
|
||||
|
@ -55,13 +55,13 @@ defmodule CanneryWeb.Components.AmmoGroupCard do
|
||||
|
||||
<span class="rounded-lg title text-lg">
|
||||
<%= gettext("Purchased on:") %>
|
||||
<.date date={@ammo_group.purchased_on} />
|
||||
<%= @ammo_group.purchased_on |> display_date() %>
|
||||
</span>
|
||||
|
||||
<%= if @ammo_group |> Ammo.get_last_used_shot_group() do %>
|
||||
<span class="rounded-lg title text-lg">
|
||||
<%= gettext("Last used on:") %>
|
||||
<.date date={@ammo_group |> Ammo.get_last_used_shot_group() |> Map.get(:date)} />
|
||||
<%= @ammo_group |> Ammo.get_last_used_shot_group() |> Map.get(:date) |> display_date() %>
|
||||
</span>
|
||||
<% end %>
|
||||
|
||||
|
@ -157,7 +157,7 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do
|
||||
|
||||
{purchased_on,
|
||||
~H"""
|
||||
<.date date={@purchased_on} />
|
||||
<%= @purchased_on |> display_date() %>
|
||||
"""}
|
||||
end
|
||||
|
||||
@ -173,7 +173,7 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do
|
||||
{last_shot_group_date,
|
||||
~H"""
|
||||
<%= if @last_shot_group_date do %>
|
||||
<.date date={@last_shot_group_date} />
|
||||
<%= @last_shot_group_date |> display_date() %>
|
||||
<% else %>
|
||||
<%= gettext("Never used") %>
|
||||
<% end %>
|
||||
|
@ -27,14 +27,8 @@ defmodule CanneryWeb.Components.InviteCard do
|
||||
|
||||
<%= if @invite.disabled_at |> is_nil() do %>
|
||||
<h2 class="title text-md">
|
||||
<%= if @invite.uses_left do %>
|
||||
<%= gettext(
|
||||
"Uses Left: %{uses_left}",
|
||||
uses_left: @invite.uses_left
|
||||
) %>
|
||||
<% else %>
|
||||
<%= gettext("Uses Left: Unlimited") %>
|
||||
<% end %>
|
||||
<%= gettext("Uses Left:") %>
|
||||
<%= @invite.uses_left || "Unlimited" %>
|
||||
</h2>
|
||||
<% else %>
|
||||
<h2 class="title text-md">
|
||||
@ -42,11 +36,6 @@ defmodule CanneryWeb.Components.InviteCard do
|
||||
</h2>
|
||||
<% end %>
|
||||
|
||||
<.qr_code
|
||||
content={Routes.user_registration_url(Endpoint, :new, invite: @invite.token)}
|
||||
filename={@invite.name}
|
||||
/>
|
||||
|
||||
<div class="flex flex-row flex-wrap justify-center items-center">
|
||||
<code
|
||||
id={"code-#{@invite.id}"}
|
||||
|
@ -103,11 +103,7 @@ defmodule CanneryWeb.Components.ShotGroupTableComponent do
|
||||
{ammo_type_name, name_block}
|
||||
end
|
||||
|
||||
defp get_row_value(:date, assigns = %{date: _date}, _extra_data) do
|
||||
~H"""
|
||||
<.date date={@date} />
|
||||
"""
|
||||
end
|
||||
defp get_row_value(:date, %{date: date}, _extra_data), do: date |> display_date()
|
||||
|
||||
defp get_row_value(:actions, shot_group, %{actions: actions}) do
|
||||
assigns = %{actions: actions, shot_group: shot_group}
|
||||
|
@ -4,7 +4,7 @@
|
||||
<tr>
|
||||
<%= for %{key: key, label: label} = column <- @columns do %>
|
||||
<%= if column |> Map.get(:sortable, true) do %>
|
||||
<th class={["p-2", column[:class]]}>
|
||||
<th class={"p-2 #{column[:class]}"}>
|
||||
<span
|
||||
class="cursor-pointer flex justify-center items-center space-x-2"
|
||||
phx-click="sort_by"
|
||||
@ -26,7 +26,7 @@
|
||||
</span>
|
||||
</th>
|
||||
<% else %>
|
||||
<th class={["p-2 cursor-not-allowed", column[:class]]}>
|
||||
<th class={"p-2 cursor-not-allowed #{column[:class]}"}>
|
||||
<%= label %>
|
||||
</th>
|
||||
<% end %>
|
||||
@ -37,7 +37,7 @@
|
||||
<%= for {values, i} <- @rows |> Enum.with_index() do %>
|
||||
<tr class={if i |> Integer.is_even(), do: @row_class, else: @alternate_row_class}>
|
||||
<%= for %{key: key} = value <- @columns do %>
|
||||
<td class={["p-2", value[:class]]}>
|
||||
<td class={"p-2 #{value[:class]}"}>
|
||||
<%= case values |> Map.get(key) do %>
|
||||
<% {_custom_sort_value, value} -> %>
|
||||
<%= value %>
|
||||
|
@ -23,23 +23,16 @@ defmodule CanneryWeb.Components.UserCard do
|
||||
|
||||
<h3 class="px-4 py-2 rounded-lg title text-lg">
|
||||
<p>
|
||||
<%= if @user.confirmed_at do %>
|
||||
<%= gettext(
|
||||
"User was confirmed at%{confirmed_datetime}",
|
||||
confirmed_datetime: ""
|
||||
) %>
|
||||
<.datetime datetime={@user.confirmed_at} />
|
||||
<%= if @user.confirmed_at |> is_nil() do %>
|
||||
Email unconfirmed
|
||||
<% else %>
|
||||
<%= gettext("Email unconfirmed") %>
|
||||
User was confirmed at <%= @user.confirmed_at |> display_datetime() %>
|
||||
<% end %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<%= gettext(
|
||||
"User registered on%{registered_datetime}",
|
||||
registered_datetime: ""
|
||||
) %>
|
||||
<.datetime datetime={@user.inserted_at} />
|
||||
<%= gettext("User registered on") %>
|
||||
<%= @user.inserted_at |> display_datetime() %>
|
||||
</p>
|
||||
</h3>
|
||||
|
||||
|
@ -116,12 +116,7 @@ defmodule CanneryWeb.AmmoGroupLive.Show do
|
||||
value =
|
||||
case key do
|
||||
:date ->
|
||||
assigns = %{date: date}
|
||||
|
||||
{date,
|
||||
~H"""
|
||||
<.date date={@date} />
|
||||
"""}
|
||||
{date, date |> display_date()}
|
||||
|
||||
:actions ->
|
||||
~H"""
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
<span class="rounded-lg title text-lg">
|
||||
<%= gettext("Purchased on:") %>
|
||||
<.date date={@ammo_group.purchased_on} />
|
||||
<%= @ammo_group.purchased_on |> display_date() %>
|
||||
</span>
|
||||
|
||||
<%= if @ammo_group.price_paid do %>
|
||||
|
@ -124,7 +124,7 @@
|
||||
</h3>
|
||||
|
||||
<span class="text-primary-600">
|
||||
<.datetime datetime={@ammo_type.inserted_at} />
|
||||
<%= @ammo_type.inserted_at |> display_datetime() %>
|
||||
</span>
|
||||
|
||||
<%= if @avg_cost_per_round do %>
|
||||
|
@ -11,17 +11,15 @@ defmodule CanneryWeb.Router do
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
plug :fetch_current_user
|
||||
plug :put_user_locale
|
||||
plug :put_user_locale, default: Application.compile_env(:gettext, :default_locale, "en_US")
|
||||
end
|
||||
|
||||
defp put_user_locale(%{assigns: %{current_user: %{locale: locale}}} = conn, _opts) do
|
||||
default = Application.fetch_env!(:gettext, :default_locale)
|
||||
defp put_user_locale(%{assigns: %{current_user: %{locale: locale}}} = conn, default: default) do
|
||||
Gettext.put_locale(locale || default)
|
||||
conn |> put_session(:locale, locale || default)
|
||||
end
|
||||
|
||||
defp put_user_locale(conn, _opts) do
|
||||
default = Application.fetch_env!(:gettext, :default_locale)
|
||||
defp put_user_locale(conn, default: default) do
|
||||
Gettext.put_locale(default)
|
||||
conn |> put_session(:locale, default)
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
<main class="pb-8 min-w-full">
|
||||
<main class="mb-8 min-w-full">
|
||||
<header>
|
||||
<.topbar current_user={assigns[:current_user]}></.topbar>
|
||||
|
||||
|
@ -10,8 +10,8 @@
|
||||
type="image/jpg"
|
||||
href={Routes.static_path(@conn, "/images/cannery.svg")}
|
||||
/>
|
||||
<.live_title suffix={" | #{gettext("Cannery")}"}>
|
||||
<%= assigns[:page_title] || gettext("Cannery") %>
|
||||
<.live_title suffix=" | Cannery">
|
||||
<%= assigns[:page_title] || "Cannery" %>
|
||||
</.live_title>
|
||||
<link phx-track-static rel="stylesheet" href={Routes.static_path(@conn, "/css/app.css")} />
|
||||
<script
|
||||
@ -23,7 +23,7 @@
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body class="m-0 p-0 w-full h-full subpixel-antialiased">
|
||||
<body class="m-0 p-0 w-full h-full bg-white">
|
||||
<%= @inner_content %>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -18,7 +18,7 @@ defmodule CanneryWeb.ErrorHelpers do
|
||||
|
||||
~H"""
|
||||
<%= for error <- Keyword.get_values(@form.errors, @field) do %>
|
||||
<span class={["invalid-feedback", @extra_class]} phx-feedback-for={input_name(@form, @field)}>
|
||||
<span class={"invalid-feedback #{@extra_class}"} phx-feedback-for={input_name(@form, @field)}>
|
||||
<%= translate_error(error) %>
|
||||
</span>
|
||||
<% end %>
|
||||
|
@ -5,62 +5,64 @@ defmodule CanneryWeb.ViewHelpers do
|
||||
:view`
|
||||
"""
|
||||
|
||||
use Phoenix.Component
|
||||
import Phoenix.Component
|
||||
|
||||
@id_length 16
|
||||
|
||||
@doc """
|
||||
Phoenix.Component for a <time> element that renders the naivedatetime in the
|
||||
user's local timezone with Alpine.js
|
||||
Returns a <time> element that renders the naivedatetime in the user's local
|
||||
timezone with Alpine.js
|
||||
"""
|
||||
@spec display_datetime(NaiveDateTime.t() | nil) :: Phoenix.LiveView.Rendered.t()
|
||||
def display_datetime(nil), do: ""
|
||||
|
||||
attr :datetime, :any, required: true, doc: "A `DateTime` struct or nil"
|
||||
def display_datetime(datetime) do
|
||||
assigns = %{
|
||||
id: :crypto.strong_rand_bytes(@id_length) |> Base.url_encode64(),
|
||||
datetime: datetime |> DateTime.from_naive!("Etc/UTC") |> DateTime.to_iso8601(:extended)
|
||||
}
|
||||
|
||||
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 %>
|
||||
"""
|
||||
end
|
||||
|
||||
@spec cast_datetime(NaiveDateTime.t() | nil) :: String.t()
|
||||
defp cast_datetime(%NaiveDateTime{} = datetime) do
|
||||
datetime |> DateTime.from_naive!("Etc/UTC") |> DateTime.to_iso8601(:extended)
|
||||
end
|
||||
|
||||
defp cast_datetime(_datetime), do: ""
|
||||
|
||||
@doc """
|
||||
Phoenix.Component for a <date> element that renders the Date in the user's
|
||||
local timezone with Alpine.js
|
||||
"""
|
||||
|
||||
attr :date, :any, required: true, doc: "A `Date` struct or nil"
|
||||
|
||||
def date(assigns) do
|
||||
~H"""
|
||||
<%= if @date do %>
|
||||
<time
|
||||
datetime={@date |> Date.to_iso8601(:extended)}
|
||||
id={@id}
|
||||
datetime={@datetime}
|
||||
x-data={"{
|
||||
date:
|
||||
Intl.DateTimeFormat([], {timeZone: 'Etc/UTC', dateStyle: 'short'})
|
||||
.format(new Date(\"#{@date |> Date.to_iso8601(:extended)}\"))
|
||||
Intl.DateTimeFormat([], {dateStyle: 'short', timeStyle: 'long'})
|
||||
.format(new Date(\"#{@datetime}\"))
|
||||
}"}
|
||||
x-text="date"
|
||||
>
|
||||
<%= @date |> Date.to_iso8601(:extended) %>
|
||||
<%= @datetime %>
|
||||
</time>
|
||||
"""
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns a <date> element that renders the Date in the user's local
|
||||
timezone with Alpine.js
|
||||
"""
|
||||
@spec display_date(Date.t() | nil) :: Phoenix.LiveView.Rendered.t()
|
||||
def display_date(nil), do: ""
|
||||
|
||||
def display_date(date) do
|
||||
assigns = %{
|
||||
id: :crypto.strong_rand_bytes(@id_length) |> Base.url_encode64(),
|
||||
date: date |> Date.to_iso8601(:extended)
|
||||
}
|
||||
|
||||
~H"""
|
||||
<time
|
||||
id={@id}
|
||||
datetime={@date}
|
||||
x-data={"{
|
||||
date:
|
||||
Intl.DateTimeFormat([], {timeZone: 'Etc/UTC', dateStyle: 'short'}).format(new Date(\"#{@date}\"))
|
||||
}"}
|
||||
x-text="date"
|
||||
>
|
||||
<%= @date %>
|
||||
</time>
|
||||
<% end %>
|
||||
"""
|
||||
end
|
||||
|
||||
@ -68,44 +70,12 @@ defmodule CanneryWeb.ViewHelpers do
|
||||
Displays emoji as text emoji if SHIBAO_MODE is set to true :)
|
||||
"""
|
||||
@spec display_emoji(String.t()) :: String.t()
|
||||
def display_emoji("😔") do
|
||||
if Application.get_env(:cannery, CanneryWeb.ViewHelpers)[:shibao_mode], do: "q_q", else: "😔"
|
||||
end
|
||||
def display_emoji("😔"),
|
||||
do:
|
||||
if(Application.get_env(:cannery, CanneryWeb.ViewHelpers)[:shibao_mode], do: "q_q", else: "😔")
|
||||
|
||||
def display_emoji(other_emoji), do: other_emoji
|
||||
|
||||
@doc """
|
||||
Displays content in a QR code as a base64 encoded PNG
|
||||
"""
|
||||
@spec qr_code_image(String.t()) :: String.t()
|
||||
@spec qr_code_image(String.t(), width :: non_neg_integer()) :: String.t()
|
||||
def qr_code_image(content, width \\ 384) do
|
||||
img_data =
|
||||
content
|
||||
|> EQRCode.encode()
|
||||
|> EQRCode.png(width: width)
|
||||
|> Base.encode64()
|
||||
|
||||
"data:image/png;base64," <> img_data
|
||||
end
|
||||
|
||||
@doc """
|
||||
Creates a downloadable QR Code element
|
||||
"""
|
||||
|
||||
attr :content, :string, required: true
|
||||
attr :filename, :string, default: "qrcode", doc: "filename without .png extension"
|
||||
attr :image_class, :string, default: "w-64 h-max"
|
||||
attr :width, :integer, default: 384, doc: "width of png to generate"
|
||||
|
||||
def qr_code(assigns) do
|
||||
~H"""
|
||||
<a href={qr_code_image(@content)} download={@filename <> ".png"}>
|
||||
<img class={@image_class} alt={@filename} src={qr_code_image(@content)} />
|
||||
</a>
|
||||
"""
|
||||
end
|
||||
|
||||
@doc """
|
||||
Get a random color in `#ffffff` hex format
|
||||
|
||||
|
1
mix.exs
1
mix.exs
@ -70,7 +70,6 @@ defmodule Cannery.MixProject do
|
||||
{:jason, "~> 1.2"},
|
||||
{:plug_cowboy, "~> 2.5"},
|
||||
{:ecto_psql_extras, "~> 0.6"},
|
||||
{:eqrcode, "~> 0.1.10"},
|
||||
{:credo, "~> 1.5", only: [:dev, :test], runtime: false},
|
||||
{:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false}
|
||||
]
|
||||
|
1
mix.lock
1
mix.lock
@ -16,7 +16,6 @@
|
||||
"ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.10", "e14d400930f401ca9f541b3349212634e44027d7f919bbb71224d7ac0d0e8acd", [:mix], [{:ecto_sql, "~> 3.4", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.15.7 or ~> 0.16.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "505e8cd81e4f17c090be0f99e92b1b3f0fd915f98e76965130b8ccfb891e7088"},
|
||||
"ecto_sql": {:hex, :ecto_sql, "3.9.2", "34227501abe92dba10d9c3495ab6770e75e79b836d114c41108a4bf2ce200ad5", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1eb5eeb4358fdbcd42eac11c1fbd87e3affd7904e639d77903c1358b2abd3f70"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.7.3", "c37fdae1b52d2cc51069713a58c2314877c1ad40800a57efb213f77b078a460d", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "24ada3e3996adbed1fa024ca14995ef2ba3d0d17b678b0f3f2b1f66e6ce2b274"},
|
||||
"eqrcode": {:hex, :eqrcode, "0.1.10", "6294fece9d68ad64eef1c3c92cf111cfd6469f4fbf230a2d4cc905a682178f3f", [:mix], [], "hexpm", "da30e373c36a0fd37ab6f58664b16029919896d6c45a68a95cc4d713e81076f1"},
|
||||
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.29.1", "b1c652fa5f92ee9cf15c75271168027f92039b3877094290a75abcaac82a9f77", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "b7745fa6374a36daf484e2a2012274950e084815b936b1319aeebcf7809574f6"},
|
||||
"expo": {:hex, :expo, "0.3.0", "13127c1d5f653b2927f2616a4c9ace5ae372efd67c7c2693b87fd0fdc30c6feb", [:mix], [], "hexpm", "fb3cd4bf012a77bc1608915497dae2ff684a06f0fa633c7afa90c4d72b881823"},
|
||||
|
@ -194,7 +194,7 @@ msgstr "Brandmunition"
|
||||
msgid "Instance Information"
|
||||
msgstr "Instanzinformationen"
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:41
|
||||
#: lib/cannery_web/components/invite_card.ex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Invite Disabled"
|
||||
msgstr "Einladung deaktiviert"
|
||||
@ -441,6 +441,11 @@ msgstr "Art:"
|
||||
msgid "Users"
|
||||
msgstr "Benutzer"
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses Left:"
|
||||
msgstr "Verbleibende Nutzung:"
|
||||
|
||||
#: lib/cannery_web/live/invite_live/form_component.html.heex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses left"
|
||||
@ -729,6 +734,11 @@ msgstr "Kopien"
|
||||
msgid "Added on:"
|
||||
msgstr "Hinzugefügt am:"
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User registered on"
|
||||
msgstr "Benutzer registriert am"
|
||||
|
||||
#: lib/cannery_web/templates/user_registration/new.html.heex:37
|
||||
#: lib/cannery_web/templates/user_settings/edit.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
@ -1136,34 +1146,3 @@ msgstr ""
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/templates/layout/root.html.heex:13
|
||||
#: lib/cannery_web/templates/layout/root.html.heex:14
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Cannery"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Email unconfirmed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:38
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "User registered on%{registered_datetime}"
|
||||
msgstr "Benutzer registriert am"
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User was confirmed at%{confirmed_datetime}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:31
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Uses Left: %{uses_left}"
|
||||
msgstr "Verbleibende Nutzung:"
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:36
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Uses Left: Unlimited"
|
||||
msgstr "Verbleibende Nutzung:"
|
||||
|
@ -208,7 +208,7 @@ msgstr "Schüsse erfolgreich dokumentiert"
|
||||
msgid "Are you sure you want to unstage this ammo?"
|
||||
msgstr "Sind sie sicher, dass Sie diese Munition demarkieren möchten?"
|
||||
|
||||
#: lib/cannery_web/live/ammo_group_live/show.ex:142
|
||||
#: lib/cannery_web/live/ammo_group_live/show.ex:137
|
||||
#: lib/cannery_web/live/range_live/index.html.heex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Are you sure you want to delete this shot record?"
|
||||
|
@ -179,7 +179,7 @@ msgstr ""
|
||||
msgid "Instance Information"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:41
|
||||
#: lib/cannery_web/components/invite_card.ex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Invite Disabled"
|
||||
msgstr ""
|
||||
@ -424,6 +424,11 @@ msgstr ""
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses Left:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/live/invite_live/form_component.html.heex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses left"
|
||||
@ -712,6 +717,11 @@ msgstr ""
|
||||
msgid "Added on:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User registered on"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/templates/user_registration/new.html.heex:37
|
||||
#: lib/cannery_web/templates/user_settings/edit.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
@ -1119,34 +1129,3 @@ msgstr ""
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/templates/layout/root.html.heex:13
|
||||
#: lib/cannery_web/templates/layout/root.html.heex:14
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Cannery"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Email unconfirmed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User registered on%{registered_datetime}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User was confirmed at%{confirmed_datetime}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:31
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses Left: %{uses_left}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:36
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses Left: Unlimited"
|
||||
msgstr ""
|
||||
|
@ -179,7 +179,7 @@ msgstr ""
|
||||
msgid "Instance Information"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:41
|
||||
#: lib/cannery_web/components/invite_card.ex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Invite Disabled"
|
||||
msgstr ""
|
||||
@ -424,6 +424,11 @@ msgstr ""
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses Left:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/live/invite_live/form_component.html.heex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses left"
|
||||
@ -712,6 +717,11 @@ msgstr ""
|
||||
msgid "Added on:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User registered on"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/templates/user_registration/new.html.heex:37
|
||||
#: lib/cannery_web/templates/user_settings/edit.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
@ -1119,34 +1129,3 @@ msgstr ""
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/templates/layout/root.html.heex:13
|
||||
#: lib/cannery_web/templates/layout/root.html.heex:14
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Cannery"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Email unconfirmed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:38
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "User registered on%{registered_datetime}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User was confirmed at%{confirmed_datetime}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:31
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Uses Left: %{uses_left}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:36
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Uses Left: Unlimited"
|
||||
msgstr ""
|
||||
|
@ -187,7 +187,7 @@ msgstr ""
|
||||
msgid "Are you sure you want to unstage this ammo?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/live/ammo_group_live/show.ex:142
|
||||
#: lib/cannery_web/live/ammo_group_live/show.ex:137
|
||||
#: lib/cannery_web/live/range_live/index.html.heex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Are you sure you want to delete this shot record?"
|
||||
|
@ -194,7 +194,7 @@ msgstr "Incendiaria"
|
||||
msgid "Instance Information"
|
||||
msgstr "Información de Instancia"
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:41
|
||||
#: lib/cannery_web/components/invite_card.ex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Invite Disabled"
|
||||
msgstr "Invitación Desactivada"
|
||||
@ -442,6 +442,11 @@ msgstr "Tipo:"
|
||||
msgid "Users"
|
||||
msgstr "Usuarios"
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses Left:"
|
||||
msgstr "Usos Restantes:"
|
||||
|
||||
#: lib/cannery_web/live/invite_live/form_component.html.heex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses left"
|
||||
@ -730,6 +735,11 @@ msgstr "Copias"
|
||||
msgid "Added on:"
|
||||
msgstr "Añadido en:"
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User registered on"
|
||||
msgstr "Usuario registrado en"
|
||||
|
||||
#: lib/cannery_web/templates/user_registration/new.html.heex:37
|
||||
#: lib/cannery_web/templates/user_settings/edit.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
@ -1138,34 +1148,3 @@ msgstr ""
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/templates/layout/root.html.heex:13
|
||||
#: lib/cannery_web/templates/layout/root.html.heex:14
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Cannery"
|
||||
msgstr "Logo de cannery"
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Email unconfirmed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:38
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "User registered on%{registered_datetime}"
|
||||
msgstr "Usuario registrado en"
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User was confirmed at%{confirmed_datetime}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:31
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Uses Left: %{uses_left}"
|
||||
msgstr "Usos Restantes:"
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:36
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Uses Left: Unlimited"
|
||||
msgstr "Usos Restantes:"
|
||||
|
@ -207,7 +207,7 @@ msgstr "Tiros registrados exitosamente"
|
||||
msgid "Are you sure you want to unstage this ammo?"
|
||||
msgstr "Está seguro que desea desmontar esta munición?"
|
||||
|
||||
#: lib/cannery_web/live/ammo_group_live/show.ex:142
|
||||
#: lib/cannery_web/live/ammo_group_live/show.ex:137
|
||||
#: lib/cannery_web/live/range_live/index.html.heex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Are you sure you want to delete this shot record?"
|
||||
|
@ -194,7 +194,7 @@ msgstr "Incendiaire"
|
||||
msgid "Instance Information"
|
||||
msgstr "Information de l’instance"
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:41
|
||||
#: lib/cannery_web/components/invite_card.ex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Invite Disabled"
|
||||
msgstr "Invitation désactivée"
|
||||
@ -443,6 +443,11 @@ msgstr "Type :"
|
||||
msgid "Users"
|
||||
msgstr "Utilisateurs"
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses Left:"
|
||||
msgstr "Utilisations restantes :"
|
||||
|
||||
#: lib/cannery_web/live/invite_live/form_component.html.heex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses left"
|
||||
@ -731,6 +736,11 @@ msgstr "Exemplaires"
|
||||
msgid "Added on:"
|
||||
msgstr "Ajouté le :"
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User registered on"
|
||||
msgstr "Utilisateur·ice enregistré·e le"
|
||||
|
||||
#: lib/cannery_web/templates/user_registration/new.html.heex:37
|
||||
#: lib/cannery_web/templates/user_settings/edit.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
@ -1139,34 +1149,3 @@ msgstr ""
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/templates/layout/root.html.heex:13
|
||||
#: lib/cannery_web/templates/layout/root.html.heex:14
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Cannery"
|
||||
msgstr "Logo de Cannery"
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Email unconfirmed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:38
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "User registered on%{registered_datetime}"
|
||||
msgstr "Utilisateur·ice enregistré·e le"
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User was confirmed at%{confirmed_datetime}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:31
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Uses Left: %{uses_left}"
|
||||
msgstr "Utilisations restantes :"
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:36
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Uses Left: Unlimited"
|
||||
msgstr "Utilisations restantes :"
|
||||
|
@ -209,7 +209,7 @@ msgstr "Tirs enregistré avec succès"
|
||||
msgid "Are you sure you want to unstage this ammo?"
|
||||
msgstr "Êtes-vous certain·e de vouloir désélectionner cette munition ?"
|
||||
|
||||
#: lib/cannery_web/live/ammo_group_live/show.ex:142
|
||||
#: lib/cannery_web/live/ammo_group_live/show.ex:137
|
||||
#: lib/cannery_web/live/range_live/index.html.heex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Are you sure you want to delete this shot record?"
|
||||
|
@ -190,7 +190,7 @@ msgstr ""
|
||||
msgid "Instance Information"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:41
|
||||
#: lib/cannery_web/components/invite_card.ex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Invite Disabled"
|
||||
msgstr ""
|
||||
@ -435,6 +435,11 @@ msgstr ""
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses Left:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/live/invite_live/form_component.html.heex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uses left"
|
||||
@ -723,6 +728,11 @@ msgstr ""
|
||||
msgid "Added on:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User registered on"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/templates/user_registration/new.html.heex:37
|
||||
#: lib/cannery_web/templates/user_settings/edit.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
@ -1130,34 +1140,3 @@ msgstr ""
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/templates/layout/root.html.heex:13
|
||||
#: lib/cannery_web/templates/layout/root.html.heex:14
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Cannery"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Email unconfirmed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:38
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "User registered on%{registered_datetime}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/user_card.ex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User was confirmed at%{confirmed_datetime}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:31
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Uses Left: %{uses_left}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/components/invite_card.ex:36
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Uses Left: Unlimited"
|
||||
msgstr ""
|
||||
|
@ -198,7 +198,7 @@ msgstr ""
|
||||
msgid "Are you sure you want to unstage this ammo?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/live/ammo_group_live/show.ex:142
|
||||
#: lib/cannery_web/live/ammo_group_live/show.ex:137
|
||||
#: lib/cannery_web/live/range_live/index.html.heex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Are you sure you want to delete this shot record?"
|
||||
|
@ -187,7 +187,7 @@ msgstr ""
|
||||
msgid "Are you sure you want to unstage this ammo?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/cannery_web/live/ammo_group_live/show.ex:142
|
||||
#: lib/cannery_web/live/ammo_group_live/show.ex:137
|
||||
#: lib/cannery_web/live/range_live/index.html.heex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Are you sure you want to delete this shot record?"
|
||||
|
Loading…
Reference in New Issue
Block a user